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:
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?
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 AS
clause 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();
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.