web-dev-qa-db-fra.com

SQL Server - Comment accorder l'autorisation SELECT sur View qui accède aux données dans les schémas de différents propriétaires?

J'ai besoin d'aide pour résoudre un problème concernant les autorisations dans ma base de données.

Voici le scénario:

1 base de données

4 schémas:

  • schéma A; propriétaire dbo
  • schemaB; propriétaire ownerX
  • schemaC; propriétaire ownerX
  • schemaD; propriétaire ownerX

Dans schemaD j'ai une vue nommée viewABC, qui obtient les informations des tables et des vues allouées sur les schémas schemaA, schemaB e schemaC.

Un utilisateur serX a SELECT permission pour viewABC.

Avec la commande suivante, j'accorde l'autorisation:

GRANT SELECT ON schemaD.viewABC TO userX;

Lorsque serX essayez d'exécuter un SELECT contre la vue, de cette façon:

SELECT * FROM schemaD.viewABC;

Nous obtenons l'erreur:

L'autorisation SELECT a été refusée sur l'objet 'tableA', la base de données 'MyDatabase', le schéma 'schemaA'.

Je comprends que l'erreur se produit car tableA est sur un schéma différent, avec un propriétaire différent (dbo à la place ownerX), et SQLServer applique userX autorisations pour accorder ou refuser l'accès. Une fois serX n'a ​​pas d'accès explicite à tableA l'exécution de la requête renvoie une erreur.

Comment résoudre ce problème sans accorder l'autorisation SELECT sur tableA pour userX?

6
Emerson JS

Sur la base d'une des suggestions que Dan Guzman m'a données dans votre réponse, et après avoir lu ceci question j'ai trouvé une solution de contournement pour mon problème.

Apparemment, il n'y a aucun moyen, dans le scénario décrit, d'accorder à userX SELECT permission dans le viewABC sans octroi également l'autorisation SELECT sur tableA .

La solution que j'ai trouvée était la suivante:

  • dans schemaD J'ai créé un fonction table qui renvoie le même jeu d'enregistrements viewABC - malgré ownerX n'est pas propriétaire de schemaA , il a SELECT permission sur tableA

  • le EXECUTE ASclause a été utilisé pour garantir que toute exécution de la fonction utilisera les autorisations ownerX - dans ce contexte, peu importe l'autorisation que userX a sur tableA

  • à userX a obtenu la permission SELECT dans la fonction créée - pas EXECUTE permission, car la fonction retourne une table


L'exemple de code de la fonction table :

CREATE FUNCTION schemaD.udfABC ()
RETURNS @tabABC TABLE (
  fieldA INT NOT NULL, fieldB INT NOT NULL, fieldC INT NOT NULL
)
WITH EXECUTE AS OWNER
AS
BEGIN
  INSERT INTO @tabABC (fieldA, fieldB, fieldC)
    SELECT a.fieldA, b.fieldB, c.fieldC
      FROM schemaA.tableA a
     INNER JOIN schemaB.tableB b ON a.id = b.idA
     INNER JOIN schemaC.tableC c ON b.id = c.idB;

  RETURN;  
END

Octroi de l'autorisation SELECT:

GRANT SELECT ON schemaD.udfABC TO userX;

Maintenant userX peut utiliser cette commande pour obtenir des données:

SELECT * FROM schemaD.udfABC();
6
Emerson JS

Je ne peux pas penser à un moyen d'éviter d'accorder des autorisations SELECT en raison de la chaîne de propriété rompue dans les objets sous-jacents de la vue. Une solution consiste à remplacer le propriétaire de TableA par ownerX afin que la chaîne de propriété des vues ne soit pas interrompue:

ALTER AUTHORIZATION ON OBJECT::dbo.tableA TO ownerX;

Notez que cela donnera au propriétaire X CONTROL des autorisations sur dbo.tableA. Si cela n'est pas acceptable, vous devrez utiliser un module à la place (par exemple, une fonction table) et le signer avec un certificat basé sur un utilisateur disposant des autorisations d'objet SELECT nécessaires.

4
Dan Guzman