Provisionamento de usuários e concessão automatizada de privilégios no Oracle Database

Introdução
Em ambientes corporativos é comum a necessidade de provisionar múltiplos usuários com as mesmas permissões dentro do banco de dados.
Realizar a concessão manual de privilégios em centenas ou milhares de objetos pode ser um processo demorado, sujeito a erros e difícil de auditar.
Neste artigo apresento uma abordagem estruturada para:
• Criar usuários no Oracle Database
• Centralizar privilégios em uma ROLE
• Automatizar a concessão de privilégios em tabelas e objetos PL/SQL
• Executar um dry-run para validação antes de aplicar os GRANTs
• Registrar todas as operações em log
Essa abordagem é especialmente útil em ambientes com grande volume de objetos, onde a manutenção manual se torna inviável.
1. Criando uma ROLE para centralizar os privilégios
A primeira boa prática é evitar conceder privilégios diretamente aos usuários.
Em vez disso, criamos uma ROLE que centraliza os privilégios.
CREATE ROLE app_dml_role;
2. Criação dos usuários no banco de dados
Agora criamos os usuários que terão acesso ao banco.
CREATE USER user_1 IDENTIFIED BY "aDo04j28L"
DEFAULT TABLESPACE USERS
TEMPORARY TABLESPACE TEMP
QUOTA UNLIMITED ON USERS;
CREATE USER user_2 IDENTIFIED BY "8178R2uxW"
DEFAULT TABLESPACE USERS
TEMPORARY TABLESPACE TEMP
QUOTA UNLIMITED ON USERS;
CREATE USER user_3 IDENTIFIED BY "O7F7xI0Y5"
DEFAULT TABLESPACE USERS
TEMPORARY TABLESPACE TEMP
QUOTA UNLIMITED ON USERS;
CREATE USER user_4 IDENTIFIED BY "CRF1190Kh"
DEFAULT TABLESPACE USERS
TEMPORARY TABLESPACE TEMP
QUOTA UNLIMITED ON USERS;
CREATE USER user_5 IDENTIFIED BY "N8cHd9q1A"
DEFAULT TABLESPACE USERS
TEMPORARY TABLESPACE TEMP
QUOTA UNLIMITED ON USERS;
3. Concedendo privilégio de conexão
Todos os usuários precisam do privilégio básico de conexão.
GRANT CREATE SESSION TO user_1;
GRANT CREATE SESSION TO user_2;
GRANT CREATE SESSION TO user_3;
GRANT CREATE SESSION TO user_4;
GRANT CREATE SESSION TO user_5;
4. Associando a ROLE aos usuários
Agora vinculamos os usuários à role criada anteriormente.
GRANT app_dml_role TO user_1;
GRANT app_dml_role TO user_2;
GRANT app_dml_role TO user_3;
GRANT app_dml_role TO user_4;
GRANT app_dml_role TO user_5;
5. Tabela de log das operações
Antes de executar os GRANTs, criamos uma tabela para registrar todas as operações realizadas.
CREATE TABLE sec_grant_log (
log_id NUMBER GENERATED ALWAYS AS IDENTITY,
log_ts TIMESTAMP DEFAULT SYSTIMESTAMP,
role_name VARCHAR2(128),
owner_name VARCHAR2(128),
obj_type VARCHAR2(30),
obj_name VARCHAR2(128),
stmt CLOB,
status VARCHAR2(10),
err_msg VARCHAR2(4000)
);
6. Package para execução automatizada dos GRANTs
Specification
CREATE OR REPLACE PACKAGE sec_grant_mgr AS
PROCEDURE grant_role_for_owners(
p_role IN VARCHAR2,
p_owners IN SYS.ODCIVARCHAR2LIST,
p_dry_run IN BOOLEAN DEFAULT FALSE
);
END sec_grant_mgr;
/
Package Body
CREATE OR REPLACE PACKAGE BODY sec_grant_mgr AS
PROCEDURE log_stmt(
p_role VARCHAR2,
p_owner VARCHAR2,
p_type VARCHAR2,
p_name VARCHAR2,
p_stmt CLOB,
p_status VARCHAR2,
p_err VARCHAR2
) IS
BEGIN
INSERT INTO sec_grant_log(role_name, owner_name, obj_type, obj_name, stmt, status, err_msg)
VALUES (UPPER(p_role), UPPER(p_owner), p_type, p_name, p_stmt, p_status, p_err);
END;
PROCEDURE exec_sql(
p_role VARCHAR2,
p_owner VARCHAR2,
p_type VARCHAR2,
p_name VARCHAR2,
p_sql CLOB,
p_dry_run BOOLEAN
) IS
BEGIN
IF NOT p_dry_run THEN
EXECUTE IMMEDIATE p_sql;
END IF;
log_stmt(p_role, p_owner, p_type, p_name, p_sql, 'OK', NULL);
EXCEPTION
WHEN OTHERS THEN
log_stmt(p_role, p_owner, p_type, p_name, p_sql, 'ERROR', SQLERRM);
END;
PROCEDURE grant_role_for_owners(
p_role IN VARCHAR2,
p_owners IN SYS.ODCIVARCHAR2LIST,
p_dry_run IN BOOLEAN DEFAULT FALSE
) IS
BEGIN
FOR t IN (
SELECT owner, table_name
FROM dba_tables
WHERE owner IN (SELECT UPPER(column_value) FROM TABLE(p_owners))
) LOOP
exec_sql(
p_role, t.owner, 'TABLE', t.table_name,
'GRANT SELECT, INSERT, UPDATE, DELETE ON ' || t.owner || '.' || t.table_name || ' TO ' || p_role,
p_dry_run
);
END LOOP;
FOR o IN (
SELECT owner, object_name, object_type
FROM dba_objects
WHERE owner IN (SELECT UPPER(column_value) FROM TABLE(p_owners))
AND object_type IN ('PROCEDURE','FUNCTION','PACKAGE')
) LOOP
exec_sql(
p_role, o.owner, o.object_type, o.object_name,
'GRANT EXECUTE ON ' || o.owner || '.' || o.object_name || ' TO ' || p_role,
p_dry_run
);
END LOOP;
COMMIT;
END;
END sec_grant_mgr;
/
7. Executando um DRY-RUN
Antes de aplicar os GRANTs efetivamente, podemos simular a execução.
SQL
BEGIN
sec_grant_mgr.grant_role_for_owners(
p_role => 'APP_DML_ROLE',
p_owners => SYS.ODCIVARCHAR2LIST('RM'),
p_dry_run => TRUE
);
END;
/
8. Validando os resultados da simulação
SELECT status, obj_type, COUNT(*) qtd
FROM sec_grant_log
WHERE role_name = 'APP_DML_ROLE'
GROUP BY status, obj_type
ORDER BY status, obj_type;
STATUS OBJ_TYPE QTD
---------- ------------------------------ ----------
OK FUNCTION 45
OK PROCEDURE 53
OK TABLE 8544
SELECT stmt
FROM sec_grant_log
WHERE role_name = 'APP_DML_ROLE'
AND status = 'OK'
ORDER BY log_id;
9. Validando os grants gerados e armazenados na tabela, após simulação.
SELECT stmt
FROM sec_grant_log
WHERE role_name = 'APP_DML_ROLE'
AND status = 'OK'
ORDER BY log_id;
STMT
--------------------------------------------------------------------------------
GRANT EXECUTE ON RM.VERIFICAGLOSAGG TO APP_DML_ROLE
GRANT EXECUTE ON RM.SP_AJUSTACLIENTEDUPLICADO TO APP_DML_ROLE
GRANT EXECUTE ON RM.P_AUDITLOG TO APP_DML_ROLE
GRANT EXECUTE ON RM.P_AUDITGETDIF TO APP_DML_ROLE
GRANT EXECUTE ON RM.SAUGETGRUPOGASTOTISS TO APP_DML_ROLE
9. Limpando o log antes da execução real, para garantir que não haja duplicidade.
TRUNCATE TABLE sec_grant_log;
10. Executando os GRANTs efetivamente
BEGIN
sec_grant_mgr.grant_role_for_owners(
p_role => 'APP_DML_ROLE',
p_owners => SYS.ODCIVARCHAR2LIST('RM'),
p_dry_run => FALSE
);
END;
/
11. Validando os privilégios que foram concedidos aos usuários efetivamente.
SELECT owner, table_name, privilege, grantee
FROM dba_tab_privs
WHERE grantee = 'APP_DML_ROLE'
AND owner = 'RM';
OWNER TABLE_NAME PRIVILEGE GRANTEE
---------- ---------------------------------------- --------------- ---------------
RM P_AUDITGETDIF EXECUTE APP_DML_ROLE
RM SAUGETGRUPOGASTOTISS EXECUTE APP_DML_ROLE
Conclusão
Essa abordagem traz várias vantagens para ambientes Oracle:
• Centralização de permissões via ROLE
• Provisionamento consistente de usuários
• Automação de GRANTs em milhares de objetos
• Execução segura via dry-run
• Auditoria completa das operações
Esse tipo de automação é extremamente útil em ambientes corporativos com grande volume de objetos e múltiplos usuários de aplicação.
Fique à vontade em alterar a procedure e incluir outros grants necessários como DDL ou DCL.





