Neste artigo iremos verificar como realizar a validação de uma allowlist em um ambiente de homologação e posteriormente importa-la em produção, evitando a necessidade de repetir todo o processo de captura da aplicação em cada um dos ambientes.
Para esta atividade será
utilizado o DBMS_SQL_FIREWALL.EXPORT_ALLOW_LIST e IMPORT_ALLOW_LIST, incluindo
validação antes do bloqueio e os cuidados com políticas já existentes.
Sobre os exemplos: este é
um procedimento de referência baseado na documentação do Oracle AI Database
26ai e executado em um ambiente de teste.
1. Cenário e pré-requisitos
|
Item |
Exemplo |
|
Origem |
ORA26AIHMG_PDB1, com treinamento e
allowlist já revisados |
|
Destino |
ORA26AI_PDB1, aberto para
leitura e escrita |
|
Usuário protegido |
FW_DEMO_APP nos dois ambientes |
O exemplo pressupõe nomes de
schemas, objetos e usuários coerentes entre os ambientes.
2. O que a exportação transporta — e o que não transporta
A API exporta a allowlist de um
usuário em JSON, por meio de um CLOB. O conteúdo inclui SQLs permitidos,
contextos e configurações da política, além dos SQL logs referenciados pelas
entradas permitidas. Isso não equivale a exportar o histórico de captura ou de
violações. Para transportar o conjunto de metadados de todos os usuários,
existe a integração com Data Pump; ela tem outro escopo e não é a escolha deste
exemplo.
Atenção para a existência de
allowlist no destino (produção):
- Sem allowlist no destino: a importação cria
uma política com as configurações presentes no JSON, inclusive seu estado
de ativação.
- Com allowlist no destino: SQLs e contextos
são mesclados; as configurações existentes permanecem. A importação não
remove automaticamente entradas antigas.
3. Revisar a baseline em homologação
Onde executar: conectado ao PDB de homologação (ORA26AIHMG_PDB1), com a conta administrativa de SQL Firewall. A captura e a geração inicial da allowlist devem ter sido concluídas previamente.
SELECT SYS_CONTEXT('USERENV', 'CON_NAME') AS container_atual
FROM dual;
SELECT username, status, top_level_only, enforce, block
FROM dba_sql_firewall_allow_lists
WHERE username = 'FW_DEMO_APP';
SELECT username, COUNT(*) AS quantidade_sqls
FROM dba_sql_firewall_allowed_sql
WHERE username = 'FW_DEMO_APP'
GROUP BY username;
SELECT * FROM dba_sql_firewall_allowed_ip_addr
WHERE username = 'FW_DEMO_APP';
SELECT * FROM dba_sql_firewall_allowed_os_user
WHERE username = 'FW_DEMO_APP';
SELECT * FROM dba_sql_firewall_allowed_os_prog
WHERE username = 'FW_DEMO_APP';
A contagem serve como conferência inicial; duas políticas com o mesmo número de SQLs podem permitir ações diferentes. Revise as assinaturas e os objetos acessados, além da quantidade. Verifique se o treinamento incluiu fluxos de fechamento, integrações, relatórios e exceções legítimas da aplicação.
IP, usuário do sistema operacional e nome do programa podem diferir entre homologação e produção.
4. Preparar os contextos e desabilitar a política de origem para transporte
Impacto: desabilitar uma allowlist interrompe sua aplicação para aquele usuário. Faça esta etapa somente na política de homologação destinada à promoção, após combinar a janela com os responsáveis. Não desabilite o SQL Firewall globalmente.
-- Executar somente em FW_DEMO_APPe somente se STATUS = ENABLED.
-- Se a allowlist ja estiver DISABLED, apenas confira o estado.
SQL> show con_name;
CON_NAME
------------------------------
ORA26AIHMG_PDB1
SQL>
SQL> BEGIN
DBMS_SQL_FIREWALL.DISABLE_ALLOW_LIST(
username => 'FW_DEMO_APP'
);
END;
/ 2 3 4 5 6
PL/SQL procedure successfully completed.
SQL> set lines 210
SQL> SELECT username, status, top_level_only, enforce, block
FROM dba_sql_firewall_allow_lists
WHERE username = 'FW_DEMO_APP';
USERNAME STATUS TOP_LEVEL_ONLY ENFORCE BLOCK
---------------- -------- -------------- --------------- --------------
FW_DEMO_APP DISABLED Y ENFORCE_ALL Y
Resultado esperado: a linha de FW_DEMO_APP apresenta STATUS = DISABLED. Registre os valores anteriores para restaurar a proteção da homologação depois de exportar.
Caso necessário , segue o exemplo de ajuste de IP na política desabilitada. Os endereços abaixo são ilustrativos: substitua pelos endpoints efetivamente observados pelo banco e aprovados para produção.
BEGIN
DBMS_SQL_FIREWALL.ADD_ALLOWED_CONTEXT(
username => 'FW_DEMO_APP',
context_type => DBMS_SQL_FIREWALL.IP_ADDRESS,
value => '192.0.2.20'
);
DBMS_SQL_FIREWALL.DELETE_ALLOWED_CONTEXT(
username => 'FW_DEMO_APP',
context_type => DBMS_SQL_FIREWALL.IP_ADDRESS,
value => '192.0.2.10'
);
END;
/
5. Exportar o CLOB para um arquivo JSON
Para transportar o CLOB sem depender de formatação de tela ou de limites de DBMS_OUTPUT, usarei o Python com o driver python-oracledb. O programa pode rodar em uma estação administrativa com acesso aos serviços dos PDBs; não precisa rodar no servidor do banco como realizado neste exemplo.
python -m pip install oracledb
[root@oracle26ai ~]# python -m venv ~/venvs/fw-demo
[root@oracle26ai ~]# source ~/venvs/fw-demo/bin/activate
(fw-demo) [root@oracle26ai ~]#
(fw-demo) [root@oracle26ai ~]# python -m pip install --upgrade oracledb
Collecting oracledb
Downloading https://files.pythonhosted.org/packages/e7/c4/00b05440b001a224423076e7b051d42acc6b1af1f40841ad65d3b3acdede/oracledb-1.4.2.tar.gz (495kB)
100% |████████████████████████████████| 501kB 2.6MB/s
Complete output from command python setup.py egg_info:
running egg_info
creating pip-egg-info/oracledb.egg-info
writing pip-egg-info/oracledb.egg-info/PKG-INFO
writing dependency_links to pip-egg-info/oracledb.egg-info/dependency_links.txt
writing requirements to pip-egg-info/oracledb.egg-info/requires.txt
writing top-level names to pip-egg-info/oracledb.egg-info/top_level.txt
writing manifest file 'pip-egg-info/oracledb.egg-info/SOURCES.txt'
/tmp/pip-build-rniwo58j/oracledb/src/oracledb/__init__.py:39: UserWarning: Python 3.6 is no longer supported by the Python core team. Therefore, support for it is deprecated in python-oracledb and will be removed in a future release
warnings.warn(message)
Traceback (most recent call last):
File "<string>", line 1, in <module>
File "/tmp/pip-build-rniwo58j/oracledb/setup.py", line 95, in <module>
extra_compile_args=extra_compile_args)
File "/root/venvs/fw-demo/lib64/python3.6/site-packages/setuptools/__init__.py", line 129, in setup
return distutils.core.setup(**attrs)
File "/usr/lib64/python3.6/distutils/core.py", line 148, in setup
dist.run_commands()
File "/usr/lib64/python3.6/distutils/dist.py", line 955, in run_commands
self.run_command(cmd)
File "/usr/lib64/python3.6/distutils/dist.py", line 974, in run_command
cmd_obj.run()
File "/root/venvs/fw-demo/lib64/python3.6/site-packages/setuptools/command/egg_info.py", line 278, in run
self.find_sources()
File "/root/venvs/fw-demo/lib64/python3.6/site-packages/setuptools/command/egg_info.py", line 293, in find_sources
mm.run()
File "/root/venvs/fw-demo/lib64/python3.6/site-packages/setuptools/command/egg_info.py", line 524, in run
self.add_defaults()
File "/root/venvs/fw-demo/lib64/python3.6/site-packages/setuptools/command/egg_info.py", line 560, in add_defaults
sdist.add_defaults(self)
File "/root/venvs/fw-demo/lib64/python3.6/site-packages/setuptools/command/py36compat.py", line 36, in add_defaults
self._add_defaults_ext()
File "/root/venvs/fw-demo/lib64/python3.6/site-packages/setuptools/command/py36compat.py", line 119, in _add_defaults_ext
build_ext = self.get_finalized_command('build_ext')
File "/usr/lib64/python3.6/distutils/cmd.py", line 298, in get_finalized_command
cmd_obj = self.distribution.get_command_obj(command, create)
File "/usr/lib64/python3.6/distutils/dist.py", line 846, in get_command_obj
klass = self.get_command_class(command)
File "/root/venvs/fw-demo/lib64/python3.6/site-packages/setuptools/dist.py", line 635, in get_command_class
self.cmdclass[command] = cmdclass = ep.load()
File "/root/venvs/fw-demo/lib64/python3.6/site-packages/pkg_resources/__init__.py", line 2318, in load
return self.resolve()
File "/root/venvs/fw-demo/lib64/python3.6/site-packages/pkg_resources/__init__.py", line 2324, in resolve
module = __import__(self.module_name, fromlist=['__name__'], level=0)
File "/root/venvs/fw-demo/lib64/python3.6/site-packages/setuptools/command/build_ext.py", line 17, in <module>
from Cython.Distutils.build_ext import build_ext as _build_ext
File "/tmp/pip-build-rniwo58j/oracledb/.eggs/cython-3.3.0-py3.6.egg/Cython/__init__.py", line 3, in <module>
from .Shadow import __version__
File "/tmp/pip-build-rniwo58j/oracledb/.eggs/cython-3.3.0-py3.6.egg/Cython/Shadow.py", line 2
from __future__ import annotations
^
SyntaxError: future feature annotations is not defined
----------------------------------------
Command "python setup.py egg_info" failed with error code 1 in /tmp/pip-build-rniwo58j/oracledb/
You are using pip version 9.0.3, however version 26.2.2 is available.
You should consider upgrading via the 'pip install --upgrade pip' command.
(fw-demo) [root@oracle26ai ~]# pip install --upgrade pip
Collecting pip
Downloading https://files.pythonhosted.org/packages/a4/6d/6463d49a933f547439d6b5b98b46af8742cc03ae83543e4d7688c2420f8b/pip-21.3.1-py3-none-any.whl (1.7MB)
100% |████████████████████████████████| 1.7MB 850kB/s
Installing collected packages: pip
Found existing installation: pip 9.0.3
Uninstalling pip-9.0.3:
Successfully uninstalled pip-9.0.3
Successfully installed pip-21.3.1
You are using pip version 21.3.1, however version 26.2.2 is available.
You should consider upgrading via the 'pip install --upgrade pip' command.
(fw-demo) [root@oracle26ai ~]# pip install --upgrade pip
Requirement already satisfied: pip in ./venvs/fw-demo/lib/python3.6/site-packages (21.3.1)
(fw-demo) [root@oracle26ai ~]#
(fw-demo) [root@oracle26ai ~]# python -c "import oracledb; print(oracledb.__version__)"
Traceback (most recent call last):
File "<string>", line 1, in <module>
ModuleNotFoundError: No module named 'oracledb'
(fw-demo) [root@oracle26ai ~]#
(fw-demo) [root@oracle26ai ~]# python -m pip install --upgrade oracledb
Collecting oracledb
Downloading oracledb-1.4.2-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (7.8 MB)
|████████████████████████████████| 7.8 MB 33.4 MB/s
Collecting cryptography>=3.2.1
Downloading cryptography-40.0.2-cp36-abi3-manylinux_2_28_x86_64.whl (3.7 MB)
|████████████████████████████████| 3.7 MB 43.6 MB/s
Collecting cffi>=1.12
Downloading cffi-1.15.1-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl (402 kB)
|████████████████████████████████| 402 kB 46.2 MB/s
Collecting pycparser
Downloading pycparser-2.21-py2.py3-none-any.whl (118 kB)
|████████████████████████████████| 118 kB 83.3 MB/s
Installing collected packages: pycparser, cffi, cryptography, oracledb
Successfully installed cffi-1.15.1 cryptography-40.0.2 oracledb-1.4.2 pycparser-2.21
(fw-demo) [root@oracle26ai ~]# python -c "import oracledb; print(oracledb.__version__)"
/root/venvs/fw-demo/lib64/python3.6/site-packages/oracledb/__init__.py:39: UserWarning: Python 3.6 is no longer supported by the Python core team. Therefore, support for it is deprecated in python-oracledb and will be removed in a future release
warnings.warn(message)
/root/venvs/fw-demo/lib64/python3.6/site-packages/oracledb/connection.py:45: CryptographyDeprecationWarning: Python 3.6 is no longer supported by the Python core team. Therefore, support for it is deprecated in cryptography. The next release of cryptography will remove support for Python 3.6.
from . import base_impl, thick_impl, thin_impl
1.4.2
(fw-demo) [root@oracle26ai ~]#
Sobre a execução acima: foi criado e ativado um ambiente virtual Python chamado fw-demo, pois a configuração do pip exigia esse isolamento para permitir a instalação de bibliotecas. Isso mantém as dependências do teste separadas das utilizadas pelo sistema operacional.
Em seguida, foi verificada a disponibilidade do oracledb, driver necessário para conectar o Python ao Oracle Database e executar as operações do teste com SQL Firewall. A verificação mostrou que o driver ainda não estava instalado nesse ambiente, sendo necessário instalá-lo para prosseguir.
Concluída a criação e ativação do ambiente virtual python. Connect com o usuário oracle e salve o script abaixo exportar_allowlist.py. O script exige que a política esteja desabilitada e não sobrescreve um arquivo existente.
[oracle@oracle26ai ~]$
[oracle@oracle26ai ~]$ cat exportar_allowlist.py
from getpass import getpass
from hashlib import sha256
from pathlib import Path
import json
import oracledb
oracledb.init_oracle_client()
print("Modo Thick ativo:", not oracledb.is_thin_mode())
arquivo = Path("FW_DEMO_APP_release_001.json")
dsn = input("DSN do PDB de HOMOLOGACAO: ").strip()
usuario = input("Conta administrativa: ").strip()
senha = getpass("Senha: ")
with oracledb.connect(user=usuario, password=senha, dsn=dsn,mode=oracledb.AUTH_MODE_SYSDBA) as conn:
with conn.cursor() as cur:
cur.execute("""
SELECT status FROM dba_sql_firewall_allow_lists
WHERE username = :usuario
""", usuario="FW_DEMO_APP")
estado = cur.fetchone()
if estado is None or estado[0] != "DISABLED":
raise RuntimeError("Origem deve possuir allowlist DISABLED")
payload = cur.var(oracledb.DB_TYPE_CLOB)
payload.setvalue(0, conn.createlob(oracledb.DB_TYPE_CLOB))
cur.execute("""
BEGIN
DBMS_SQL_FIREWALL.EXPORT_ALLOW_LIST(
username => :usuario, allow_list => :payload);
END;
""", usuario="FW_DEMO_APP", payload=payload)
texto = payload.getvalue().read()
json.loads(texto) # Valida a sintaxe, sem reescrever o JSON.
dados = texto.encode("utf-8")
with arquivo.open("xb") as saida:
saida.write(dados)
print("Arquivo:", arquivo)
print("SHA-256:", sha256(dados).hexdigest())
[oracle@oracle26ai ~]$
Execute com python exportar_allowlist.py. Registre o hash, a versão da aplicação, o PDB de origem, a data da revisão e a aprovação da mudança em um manifesto separado. O JSON pode conter informações sensíveis sobre SQL e infraestrutura: mantenha-o em repositório privado e transporte-o por canal autorizado.
[oracle@oracle26ai ~]$ [oracle@oracle26ai ~]$ python exportar_allowlist.py Modo Thick ativo: True DSN do PDB de HOMOLOGACAO: oracle26ai:1521/ora26aihmg_pdb1.publicsubnet.vcn01.oraclevcn.com Conta administrativa: sys Senha: Arquivo: FW_DEMO_APP_release_001.json SHA-256: cf0199f3c51f0b8740f432daa5237001f5749917d0112a4a59cc688c9df09f81 [oracle@oracle26ai ~]$ [oracle@oracle26ai ~]$
Após exportar, restaure na homologação os contextos e o estado de aplicação que eram necessários ao ambiente. A política de transporte não deve deixar a homologação desprotegida por esquecimento.
6. Importar no PDB de produção, sem ativação automática
Para importar a allowlist no pdb de produção, utilize o script abaixo importar_allowlist.py. Este processo interrompe a operação se encontrar allowlist ou captura para FW_DEMO_APP (Destino possui politica/captura para FW_DEMO_APP; revisar antes de importar); esse caso exige o tratamento da seção sobre políticas existentes.
[oracle@oracle26ai ~]$
[oracle@oracle26ai ~]$ cat importar_allowlist.py
from getpass import getpass
from hashlib import sha256
from pathlib import Path
import json
import oracledb
# Ativa o modo Thick antes de abrir qualquer conexão.
oracledb.init_oracle_client()
print("Modo Thick ativo:", not oracledb.is_thin_mode())
usuario_alvo = "FW_DEMO_APP"
arquivo = Path("FW_DEMO_APP_release_001.json")
# Valida o arquivo antes de conectar ao destino.
dados = arquivo.read_bytes()
hash_calculado = sha256(dados).hexdigest()
esperado = input("SHA-256 do manifesto aprovado: ").strip().lower()
if hash_calculado != esperado:
raise RuntimeError("Hash diferente do manifesto")
texto = dados.decode("utf-8")
json.loads(texto) # Valida a sintaxe sem reescrever o JSON.
print("Arquivo validado:", arquivo)
print("SHA-256:", hash_calculado)
dsn = input("DSN do PDB de PRODUCAO: ").strip()
usuario = input("Conta administrativa (somente o nome): ").strip()
senha = getpass("Senha: ")
with oracledb.connect(
user=usuario,
password=senha,
dsn=dsn,
mode=oracledb.AUTH_MODE_SYSDBA
) as conn:
with conn.cursor() as cur:
# Exibe o container efetivo da conexão.
cur.execute("""
SELECT SYS_CONTEXT('USERENV', 'CON_NAME')
FROM dual
""")
container = cur.fetchone()[0]
print("Container de destino:", container)
if container in ("CDB$ROOT", "PDB$SEED"):
raise RuntimeError(
"Conecte diretamente ao PDB de destino"
)
# Confirma que o usuário existe no destino.
cur.execute("""
SELECT COUNT(*)
FROM dba_users
WHERE username = :usuario
""", usuario=usuario_alvo)
if cur.fetchone()[0] == 0:
raise RuntimeError(
"Usuario {} nao existe no PDB de destino".format(
usuario_alvo
)
)
# Impede importação sobre política ou captura existente.
# Os nomes das views são fixos; o usuário utiliza bind.
for view in (
"dba_sql_firewall_allow_lists",
"dba_sql_firewall_captures"
):
cur.execute(
"SELECT COUNT(*) FROM {} "
"WHERE username = :usuario".format(view),
usuario=usuario_alvo
)
if cur.fetchone()[0]:
raise RuntimeError(
"Destino possui registro em {} para {}; "
"importacao interrompida".format(
view, usuario_alvo
)
)
# Cria e preenche o CLOB temporário.
# Não chamar close(): não houve open() explícito.
payload = conn.createlob(oracledb.DB_TYPE_CLOB)
payload.write(texto)
cur.execute("""
BEGIN
DBMS_SQL_FIREWALL.IMPORT_ALLOW_LIST(
username => :usuario,
allow_list => :payload
);
END;
""", usuario=usuario_alvo, payload=payload)
conn.commit()
# Confirma a presença e o estado da lista importada.
cur.execute("""
SELECT username, status, enforce, block
FROM dba_sql_firewall_allow_lists
WHERE username = :usuario
""", usuario=usuario_alvo)
resultado = cur.fetchone()
if resultado is None:
raise RuntimeError(
"Allowlist nao encontrada apos a importacao"
)
cur.execute("""
SELECT COUNT(*)
FROM dba_sql_firewall_allowed_sql
WHERE username = :usuario
""", usuario=usuario_alvo)
quantidade_sql = cur.fetchone()[0]
print("Importacao concluida.")
print("Container:", container)
print("Usuario:", resultado[0])
print("Status:", resultado[1])
print("Enforce:", resultado[2])
print("Block:", resultado[3])
print("Quantidade de SQLs permitidos:", quantidade_sql)
[oracle@oracle26ai ~]$
Execute com python importar_allowlist.py.
[oracle@oracle26ai ~]$ python importar_allowlist.py Modo Thick ativo: True SHA-256 do manifesto aprovado: cf0199f3c51f0b8740f432daa5237001f5749917d0112a4a59cc688c9df09f81 Arquivo validado: FW_DEMO_APP_release_001.json SHA-256: cf0199f3c51f0b8740f432daa5237001f5749917d0112a4a59cc688c9df09f81 DSN do PDB de PRODUCAO: oracle26ai:1521/ora26ai_pdb1.publicsubnet.vcn01.oraclevcn.com Conta administrativa (somente o nome): sys Senha: Container de destino: ORA26AI_PDB1 Importacao concluida. Container: ORA26AI_PDB1 Usuario: FW_DEMO_APP Status: DISABLED Enforce: ENFORCE_ALL Block: Y Quantidade de SQLs permitidos: 3 [oracle@oracle26ai ~]$
7. Conferir a política antes de ativar
Repita no destino as consultas da etapa 3. Compare SQL_SIGNATURE, CURRENT_USER, TOP_LEVEL e objetos acessados; confira os contextos e TOP_LEVEL_ONLY. Verifique também a situação global do recurso:
SELECT * FROM dba_sql_firewall_status;SELECT username, sql_signature, current_user, top_level,accessed_objectsFROM dba_sql_firewall_allowed_sqlWHERE username = 'FW_DEMO_APP'ORDER BY sql_signature;
Se o SQL Firewall global estiver desabilitado, sua ativação exige avaliar as demais políticas do container: DBMS_SQL_FIREWALL.ENABLE pode iniciar configurações já marcadas como habilitadas. Não trate essa operação global como parte automática da promoção de um único usuário.
8. Ativar em observação e testar a aplicação
Com o recurso global já habilitado e a política revisada, aplique a allowlist inicialmente sem bloqueio. Esse modo registra divergências, mas não impede a execução apenas por violação do SQL Firewall.
BEGIN
DBMS_SQL_FIREWALL.ENABLE_ALLOW_LIST(
username => 'FW_DEMO_APP',
enforce => DBMS_SQL_FIREWALL.ENFORCE_ALL,
block => FALSE
);
END;
/
SQL> BEGIN
DBMS_SQL_FIREWALL.ENABLE_ALLOW_LIST(
username => 'FW_DEMO_APP',
enforce => DBMS_SQL_FIREWALL.ENFORCE_ALL,
block => FALSE
);
END;
/ 2 3 4 5 6 7 8
PL/SQL procedure successfully completed.
SQL>
Abra novas conexões usando o caminho real da aplicação. Teste inicialização do pool, transações, consultas, relatórios, integrações e rotinas previstas para a versão. Lembrando que uma execução rápida da tela inicial não cobre processos de fechamento e cargas periódicas.
SELECT occurred_at, cause, firewall_action,
ip_address, client_program, os_user, sql_text
FROM dba_sql_firewall_violations
WHERE username = 'FW_DEMO_APP'
AND occurred_at >= SYSTIMESTAMP - INTERVAL '1' HOUR
ORDER BY occurred_at DESC;
9. Habilitar bloqueio após aprovação
BEGIN
DBMS_SQL_FIREWALL.UPDATE_ALLOW_LIST_ENFORCEMENT(
username => 'APP_USER',
enforce => DBMS_SQL_FIREWALL.ENFORCE_ALL,
block => TRUE
);
END;
/
SELECT username, status, enforce, block
FROM dba_sql_firewall_allow_lists
WHERE username = 'APP_USER';
Resultado esperado: ENABLED, ENFORCE_ALL e BLOCK = Y. Um SQL de teste previamente definido, sintaticamente válido e com privilégios suficientes, mas fora da política, deve ser bloqueado com ORA-47605. Os fluxos autorizados devem continuar funcionando. Execute os testes negativos primeiro em laboratório, com operações sem efeito destrutivo.
10. E quando produção já possui uma allowlist?
Nesse cenário, a importação é uma atualização por mesclagem. Não reutilize o procedimento de primeira importação sem revisar o resultado efetivo.
- Exporte uma baseline da política de produção, preservando SQLs, contextos e configurações; guarde também uma relação consultável das entradas. Para esse backup, não desabilite a proteção apenas para reutilizar o script de transporte deste artigo.
- Reproduza a baseline de produção em um ambiente de validação e aplique o novo artefato sobre ela. Confira o resultado da união, inclusive SQLs e endpoints antigos que continuarão permitidos.
- Compare TOP_LEVEL_ONLY e a presença de capturas. Resolva diferenças e conflitos antes da mudança.
- Revise os acréscimos e as remoções pretendidas separadamente: importar uma lista menor não revoga as entradas ausentes nela.
- Defina explicitamente a estratégia de teste. O estado ENABLED/BLOCK do destino permanece; não suponha que o modo de observação da origem será aplicado.
Para uma política de destino já ativa em bloqueio, os novos SQLs podem passar a ser autorizados assim que forem mesclados. Trate isso como mudança de segurança e mantenha o escopo aprovado.
11. Retorno operacional e reversão da política
Se houver bloqueio indevido, um retorno operacional possível, mediante aprovação, é voltar apenas o usuário afetado ao modo sem bloqueio:
BEGIN
DBMS_SQL_FIREWALL.UPDATE_ALLOW_LIST_ENFORCEMENT(
username => 'APP_USER',
enforce => DBMS_SQL_FIREWALL.ENFORCE_ALL,
block => FALSE
);
END;
/
Esse comando reduz a proteção do usuário e não desfaz a importação. Deve ser temporário e acompanhado de monitoramento.
Reimportar o JSON anterior também não remove os SQLs e contextos adicionados por uma mesclagem. Para restaurar exatamente a baseline, planeje a remoção das entradas específicas pelas APIs de manutenção ou a reconstrução da política em janela controlada. Uma reconstrução envolve desabilitar e excluir a allowlist antes da restauração, criando um intervalo sem enforcement; por isso, não deve ser automatizada como um rollback genérico.
Referências
- Oracle SQL Firewall User’s Guide — 26ai
- DBMS_SQL_FIREWALL: exportação, importação e aplicação de políticas
- SQL Firewall e Oracle Data Pump
- DBA_SQL_FIREWALL_ALLOW_LISTS
- DBA_SQL_FIREWALL_VIOLATIONS
- python-oracledb: Connection e CLOB temporário
- LamimDBA: fundamentos do SQL Firewall
- LamimDBA: manutenção da allowlist após mudanças da aplicação

Comentários
Postar um comentário