2012-02-13 4 views
1

Je veux faire quelque chose qui est conceptuellement simple mais qui semble beaucoup plus complexe en réalité.Comment créer un déclencheur Oracle qui accorde des autorisations

Fondamentalement, chaque fois qu'une nouvelle table est créée pour un couple d'utilisateurs dans notre base de données, je veux accorder des autorisations de sélection à un rôle. Fondamentalement ceci:

grant select on TABLENAME to READROLE;

Jusqu'à présent, mon déclencheur ressemble à ceci:

CREATE OR REPLACE TRIGGER osmm_grant_on_creation

CREATE APRÈS ON OSMM.SCHEMA

BEGIN

//grant goes here 

FIN

Le problème est, je ne peux pas comprendre comment joindre les deux ensemble en obtenant le nom de la nouvelle table et son référencement par le déclenchement de la subvention. Des suggestions? Merci.

+3

Des suggestions? Bien sûr: ne faites pas ça. Les autorisations accordées font partie de notre configuration de base de données. En tant que tels, ils doivent être scriptés et conservés dans un référentiel de contrôle de source, à côté du DDL pour créer la table. – APC

+0

@APC - Pourquoi je ne voudrais pas faire ça?Je ne suis pas un administrateur de bases de données et j'ai une connaissance limitée d'Oracle. J'ai donc peur que votre réponse n'ait aucun sens. Existe-t-il un autre moyen d'accorder automatiquement des autorisations select à un rôle pour une nouvelle table? Parce que le faire manuellement est une corvée que nous aimerions éviter. Les déclencheurs semblaient être une solution évidente, mais s'il y a un «meilleur» moyen, je suis ouvert à cela. –

+0

Les déclencheurs sont la seule façon d'accorder automatiquement des permissions sur des objets, à la demande, et ce n'est pas facile (comme le montre la réponse de Justin). C'est difficile car il est inhabituel de devoir accorder les mêmes autorisations sur toutes les tables d'un schéma à quelqu'un d'autre (rôle ou utilisateur). Il est plus commun d'accorder une variété de privilèges sur un sous-ensemble de tables, souvent à des comptes différents. C'est une logique difficile à mettre en place. L'approche la plus courante (autre que le codage cut'n'paste) consiste à utiliser des métadonnées pour générer des scripts. – APC

Répondre

12

Il est probablement plus complexe que vous pensez même. L'instruction GRANT est DDL, ce qui signifie qu'elle émet des validations implicites, ce qui signifie que vous ne pouvez pas la placer directement dans un trigger. Votre déclencheur doit soumettre un travail qui s'est déroulé dans une session distincte après que la transaction de déclenchement a été validée, ce qui ferait effectivement l'attribution. Et cela signifie que vous devez utiliser l'ancien package pour planifier le travail, car le DBMS_SCHEDULER plus moderne commet implicitement.

Étant donné que vous ne devez pas créer de tables à la volée dans Oracle en premier lieu, l'emplacement approprié pour ce type de subvention est dans les scripts de construction que vous exécutez pour créer la table en premier lieu. S'appuyer sur des déclencheurs pour faire des choses comme des subventions a tendance à rendre plus difficile la réalisation de builds correctement car exécuter exactement le même script dans deux environnements différents peut générer deux résultats différents à cause des différences dans le trigger.

Si vous êtes déterminé à aller dans cette voie, cependant, vous voudrez probablement quelque chose comme

Une procédure qui accorde le privilège

CREATE OR REPLACE PROCEDURE grant_select_to_readrole(p_table_name IN VARCHAR2) 
AS 
BEGIN 
    EXECUTE IMMEDIATE 'grant select on ' || p_table_name || ' to readrole'; 
END; 

Et un déclencheur qui soumet un travail qui appelle cette procédure

CREATE OR REPLACE TRIGGER osmm_grant_on_creation 
    AFTER CREATE ON OSMM.SCHEMA 
AS 
    l_jobno PLS_INTEGER; 
BEGIN 
    dbms_job.submit(l_jobno, 
        'BEGIN grant_select_to_readrole(''' || ora_dict_obj_name || '''); END;', 
        sysdate + interval '10' second); 
END; 

Si vous deviez essayer d'émettre dans le déclencheur DDL au niveau du schéma lui-même, vous obtiendrez une erreur

SQL> ed 
Wrote file afiedt.buf 

    1 create or replace trigger after_create_on_scott 
    2 after create on schema 
    3 declare 
    4 begin 
    5 execute immediate 'grant select on scott.emp to hr'; 
    6* end; 
SQL>/

Trigger created. 

SQL> create table foo(col1 number); 
create table foo(col1 number) 
* 
ERROR at line 1: 
ORA-00604: error occurred at recursive SQL level 1 
ORA-30511: invalid DDL operation in system triggers 
ORA-06512: at line 3 
+1

+1 pour dire «ne fais pas ça» puis -1 pour leur montrer comment résoudre les problèmes. – APC

+1

@APC - J'ai malheureusement fait quelque chose comme ça pour faire face à une application empaquetée qui engendrerait périodiquement de nouvelles tables, auquel cas un déclencheur était une solution raisonnable (étant donné que le remplacement du système était un non-démarreur). Mais il devrait être reconnu comme un hack massif. –

+0

Selon les informations que j'ai trouvées, certains DDL sont autorisés dans les triggers au niveau du schéma (ce qui n'est pas clair). – Allan

0

vous avez besoin probabply faire quelque chose comme:

CREATE OR REPLACE TRIGGER osmm_grant_on_creation 

AFTER CREATE ON OSMM.SCHEMA 
DECLARE 
new_obj_name varchar2(30); 
BEGIN 
SELECT ora_dict_obj_name 
INTO new_obj_name 
FROM dual 
WHERE ora_dict_obj_type = 'TABLE'; 

execute immediate 'grant select on ' || new_obj_name || ' to READROLE'; 
END 

mais je ne peux pas vérifier si cela fonctionne

+0

Comme écrit, je crois que cela déclencherait une erreur si l'objet créé est autre chose qu'une table, puisqu'il essaierait d'exécuter 'select select on sur READROLE'. – Allan

Questions connexes