2010-01-20 18 views
6

Podobne do this question, chciałbym wiedzieć, jak wygenerować wszystkie instrukcje GRANT wydane dla wszystkich ról w zestawie schematów i listę ról, których nazwy kończą się na "PROXY". Chcę odtworzyć oświadczenia takie jak:Regenerowanie GRANT dla ról na schematach

GRANT SELECT ON TABLE_NAME TO ROLE_NAME; 
GRANT EXECUTE ON PACKAGE_NAME TO ROLE_NAME; 

Celem jest pomoc w migracji z rozwojowej bazy danych do testowej bazy danych (Oracle 11g). Istnieją narzędzia, które próbują to zrobić automatycznie, ale często zawodzą.

Wszelkie pomysły?

+0

Myślę, że musisz to zrobić na własnej skórze. Przeprowadź pętlę przez "All_TAB_PRIVS" i wygeneruj ten skrypt. Jednak ciekawe pytanie. Chciałbym wiedzieć, czy to możliwe. – Guru

Odpowiedz

7

Ten skrypt generuje listę wszystkich tabel przywilejów przyznanych ról ...

select 'grant '||privilege||' on '||owner||'.'||table_name||' to '||grantee 
     ||case when grantable = 'YES' then ' with grant option' else null end 
     ||';' 
from dba_tab_privs 
where owner in ('A', 'B') 
and grantee in (select role from dba_roles) 
order by grantee, owner 
/

pamiętać, że nie ograniczają rolę Beneficjenta, ponieważ twoje pytanie jest niejasne w tej kwestii. Może być konieczne dodanie filtru do sub_query pod numerem dba_roles. Jeśli masz role przyznane innych ról będzie chciał odebrać ci się zbyt ...

select 'grant '||granted_role||' to '||grantee 
     ||case when admin_option = 'YES' then ' with admin option' else null end 
     ||';' 
from dba_role_privs 
where grantee in (select role from dba_roles) 
order by grantee, granted_role 
/

Aby uzyskać listę ról ...

select 'create role '||role ||';' 
from dba_roles 
where role like '%PROXY' 
/

Zauważ, że te skrypty nie generują przyznaje uprawnienia systemowe. Również życie jest nieco bardziej skomplikowana, jeśli używasz obiektów katalogu, ponieważ to wymaga dodatkowego słowo klucz ...

select 'grant '||privilege||' on '||owner||'.'||table_name||' to '||grantee 
     ||case when grantable = 'YES' then ' with grant option' else null end 
     ||';' 
from dba_tab_privs 
where owner in ('A', 'B') 
and grantee in (select role from dba_roles) 
and table_name not in (select directory_name from dba_directories) 
union all 
select 'grant '||privilege||' on directory '||table_name||' to '||grantee 
     ||case when grantable = 'YES' then ' with grant option' else null end 
     ||';' 
from dba_tab_privs 
where grantee in (select role from dba_roles) 
and table_name in (select directory_name from dba_directories) 
/

edit

W 9i Oracle wprowadziła pakiet DBMS_METADATA który owija się wiele z nich rodzaje zapytań w prostym API PL/SQL. Na przykład, to połączenie zostanie prorduces CLOB ze wszystkich przywilejów obiektowych przyznane ...

select dbms_metadata.get_granted_ddl('OBJECT_GRANT', 'A') from dual 
/

To jest oczywiście dużo prostsze niż walcowanie nasz własny.

1

Można zrobić to z jakiegoś kodu PL/SQL:

TYPE obj_name_type is TABLE OF ALL_OBJECTS%OBJECT_NAME INDEX BY BINARY_INTEGER; 
object_names obj_name_type; 
i INTEGER; 
BEGIN 
    SELECT object_name BULK COLLECT INTO object_names FROM ALL_OBJECTS WHERE OWNER = 'whatever' AND object_type = 'PROCEDURE'; 
    FOR i IN 1 .. object_names.last LOOP 
     EXECUTE IMMEDIATE 'GRANT EXECUTE ON ' object_names(i) ' TO ' role_name 
    END LOOP; 
END; 

Można uczynić go bardziej ogólny mapować typy uprawnień do typów obiektów lub co-ma-ty, ale to podstawowa idea.

Należy użyć EXECUTE IMMEDIATE, ponieważ nie można statycznie wykonywać kodu DDL w kodzie proceduralnym.

+0

Pozwoliłoby to po prostu przyznać prawa do wszystkich procedur twojego właściciela. Jak rozumiem, chodzi o uzyskanie prawdziwych grantów i udostępnienie skryptu do odtworzenia ich na innym schemacie. –

+0

Po prostu pokazałem ogólny pomysł. Możesz dostosować zapytanie SELECT, aby uzyskać właściwą listę. – Dan

+0

Dlaczego nie używać PL/SQL? Wydaje się, że jest to dobre narzędzie do tego celu. – Dan

0

ten spełnia nasze potrzeby:

SELECT 
    'GRANT ' || p.privilege || ' ON ' || p.table_name || ' TO ' || 
    p.grantee || ';' AS generated_grant 
FROM 
    dba_tab_privs p 
WHERE 
    p.grantor IN ('SCHEMA_NAME_01', 'SCHEMA_NAME_02') AND 
    p.grantee IN (
    SELECT DISTINCT 
     granted_role 
    FROM 
     dba_role_privs 
    WHERE 
     grantee LIKE '%PROXY' AND 
     granted_role NOT IN ('CONNECT','AQ_ADMINISTRATOR_ROLE','RESOURCE') 
) AND 
    p.table_name NOT LIKE 'BIN%' AND 
    p.table_name NOT LIKE '%$%' 
ORDER BY 
    p.table_name, p.grantee, p.privilege; 
+0

Niestety, to nie działa. Nie obejmuje właściciela obiektu w skrypcie, co ma znaczenie, gdy obsługujemy wiele schematów. Ponadto 'grantor' jest kontem, które wystawiło oryginalne oświadczenie' grant ... 'nie będące właścicielem schematu. – APC

+0

Wystarczająco fair. Chciałem tylko wskazać potencjalne obszary, które mogą powodować problemy dla przyszłych poszukiwaczy, którzy przychodzą do tego wątku poprzez wynik wyszukiwania. – APC

0

Chciałem rozwiązać problem bardzo podobny do tego. Jedyną różnicą jest to, że chciałem narzędzie bardziej ogólne, a także agnostyczne DBMS. Chciałem móc zastosować to narzędzie w środowiskach produkcyjnych, a niektóre z docelowych baz danych nie były Oracle.

to, co wymyśliłem, to funkcja Powershell, która wykonuje zastępowanie parametrów i generuje powtarzający się skrypt zawierający sekwencję instrukcji GRANT. Dane wyjściowe wyglądają jak dwa wejścia do mojego narzędzia, pliku szablonu i pliku CSV.Plik szablon wygląda tak:

grant $privs 
    on $table 
    to $user; 

a plik CSV wygląda tak:

privs,table,user 
ALL,Employees,DBA 
READ,Employees,Analyst 
"READ, WRITE", Employees, Application 
ALL,Departments,DBA 
READ,Departments,"Analyst, Application" 

Narzędzie ekspansja wygląda następująco:

<# This function is a table driven template tool. 
    It's a refinement of an earlier attempt. 

    It generates output from a template and 
    a driver table. The template file contains plain 
    text and embedded variables. The driver table 
    (in a csv file) has one column for each variable, 
    and one row for each expansion to be generated. 

    5/13/2015 

#> 

function Expand-csv { 
    [CmdletBinding()] 
    Param(
     [Parameter(Mandatory=$true)] 
     [string] $driver, 
     [Parameter(Mandatory=$true)] 
     [string] $template 
    ) 
    Process 
    { 
     $OFS = "`r`n" 
     $list = Import-Csv $driver 
     [string]$pattern = Get-Content $template 

     foreach ($item in $list) { 
     foreach ($key in $item.psobject.properties) { 
      Set-variable -name $key.name -value $key.value 
      } 
     $ExecutionContext.InvokeCommand.ExpandString($pattern) 
     } 
    } 
} 

Wreszcie, wezwanie próbki do narzędzie wygląda następująco:

Expand-csv demo.csv demo.tem > demo.sql 

Należy zauważyć, że specyfikacja pliku csv pojawia się jako pierwsza, a specyfikacja pliku szablonu ma drugie miejsce. Należy zauważyć, że "parametry formalne" użyte w pliku szablonu wyglądają jak zmienne Powershell. Tak właśnie są. Należy pamiętać, że nazwy używane w szablonie odpowiadają nazwom, które pojawiają się w nagłówku pliku csv.

Rzeczywiście użyłem prekursora tego narzędzia z różnymi dialektami SQL, a także z językami docelowymi innymi niż SQL. Używałem go nawet do generowania powtarzającego się skryptu Powershell, który nie tylko przywołuje inny skrypt .ps1, w kółko, z różnymi rzeczywistymi parametrami.

To nie jest najbardziej eleganckie narzędzie na świecie, ale służy mi dobrze.