Introdução
Wallet é um recurso do Oracle Database que permite armazenar chaves de criptografia, certificados digitais e credenciais de acesso de banco de dados ou outros serviços que o banco de dados precisa se autenticar.
Server-Wallet
É importante considerar que uma wallet pode ser usada com o propósito de “Server-Wallet” ou “Client-Wallet”. Uma “Server-Wallet” é aquela usada pela instância do banco de dados para funcionalidades como Transparent Data Encryption (TDE), Transport Layer Security (TLS), Enterprise User Security (EUS), entre outras.
Client-Wallet
Uma Client-Wallet é aquela onde criamos credenciais para nos conectarmos no banco de dados, ou incluímos certificados do Oracle Client que precisa se autenticar a um servidor de banco de dados usando TLS. A autenticação no banco de dados usando uma senha armazenada nesse tipo de wallet é chamada de Secure External Password Store (SEPS).
Em resumo, uma alteração errônea na Server-Wallet pode afetar a disponibilidade de alguma funcionalidade mencionada acima, enquanto a mesma alteração errônea em uma Client-Wallet afeta apenas o client ou script que depende dessa wallet.
Server-Wallet vs Client-Wallet
O que diferencia uma Server-Wallet de uma Client-Wallet não é o fato dela estar localizada no servidor ou do lado do cliente, mas sim a diferença de propósito mencionada anteriormente. Ou seja, pode existir wallet do tipo “Client” criada dentro do servidor de banco de dados, utilizada para autenticação segura de rotinas administrativas.
Por esse motivo, é importante ter ciência das diferenças e optar por criar uma Wallet isolada sempre que o propósito de uso for “Client-Wallet”. Neste post eu demonstro como configurar e usar uma wallet para armazenar a senha de usuários e como utilizá-la em diferentes ferramentas do Oracle, como SQL*PLUS, RMAN, Data Pump, DGMGRL, DBCA e DBSAT.
As ferramentas e casos de uso desse tipo de Wallet não se limitam aos que serão demonstrados abaixo, mas tentei trazer os exemplos mais comuns do dia a dia.
Caso de uso
Para demonstrar o isso dessa funcionalidade, para este post vou criar a estrutura abaixo:
| Propósito | Diretório |
|---|---|
| Armazenar os scripts shell / SQL | /home/oracle/dba/scripts |
| Armazenar os arquivos tnsnames.ora e sqlnet.ora | /home/oracle/dba/tns |
| Armazenar os arquivos da wallet | /home/oracle/dba/wallet |
Para essa estrutura funcionar, os scripts precisarão ser executados com a variável de ambiente TNS_ADMIN apontando para o diretório “/home/oracle/dba/tns”. É dessa maneira que conseguimos direcionar os utilitários para uma wallet dedicada, sem depender do sqlnet.ora usado pela instância do banco de dados. Os scripts usarão um sqlnet.ora exclusivo com o parâmetro WALLET_LOCATION apontando para o diretório “/home/oracle/dba/wallet”.
Criando a wallet
1) Crie o diretório da wallet
mkdir -p /home/oracle/dba/wallet chmod 700 /home/oracle/dba/wallet
2) Crie a wallet, informe uma senha administrativa para ter acesso e modificar essa wallet:
cd /home/oracle/dba/wallet mkstore -wrl . -create
[oracle@lab01 wallet]$ mkstore -wrl . -create
Oracle Secret Store Tool Release 19.0.0.0.0 - Production
Version 19.4.0.0.0
Copyright (c) 2004, 2024, Oracle and/or its affiliates. All rights reserved.
Enter password:
Enter password again:
3) Adicione uma credencial com o seguinte comando:
mkstore -wrl . -createCredential <TNS ALIAS> <USERNAME>
Exemplo 1 – Uma entrada para o usuário SYSTEM
mkstore -wrl . -createCredential PDBEX_DATAPUMP system
Note que será solicitado para informar a senha do usuário system 2x, e no final será solicitado a senha da wallet que está sendo modificada:

Nota: PDBEX_DATAPUMP é o alias que iremos criar no arquivo tnsnames.ora
Exemplo 2 – Uma entrada para o usuário SYS no CDB root:
mkstore -wrl . -createCredential CDB1_RMAN sys
Exemplo 3 – Uma entrada para o usuário REC_USER para o catalogo RMAN:
mkstore -wrl . -createCredential RMAN_CATALOG rec_user
4) Opcional – Liste o conteúdo da wallet para confirmar que as entradas foram criadas com sucesso:
mkstore -wrl . -listCredential
DICA: Uma wallet suporta apenas uma combinação de usuário e senha por String de conexão. Se você precisa de mais de um usuário e senha para o mesmo banco de dados, crie entradas com ALIAS diferentes no TNSNAME.ORA para o mesmo banco de dados.
Configurando o SQLNET.ORA
Crie o diretório tns:
mkdir -p /home/oracle/dba/tns
Crie o arquivo sqlnet.ora:
cd /home/oracle/dba/tns vi sqlnet.ora
Adicione as duas linhas abaixo:
WALLET_LOCATION = (SOURCE = (METHOD = FILE) (METHOD_DATA = (DIRECTORY = /home/oracle/dba/wallet)))
SQLNET.WALLET_OVERRIDE=TRUE
Configurando o tnsnames.ora
Crie o arquivo tnsnames.ora no mesmo diretório do sqlnet.ora:
cd /home/oracle/dba/tns vi tnsnames.ora
Adicione as entradas para os bancos de dados que deseja se conectar, onde o ALIAS deve corresponder ao que foi configurado na wallet.
Neste exemplo, estou usando CDB1_RMAN, PDBEX_DATAPUMP e RMAN_CATALOG:
PDBEX_DATAPUMP =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = lab01.dibiei.com)(PORT = 1521))
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = PDBEX)
)
)
CDB1_RMAN =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = lab01.dibiei.com)(PORT = 1521))
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = CDB1)
)
)
RMAN_CATALOG =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = emcc.dibiei.com)(PORT = 1521))
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = RMAN_CATALOG)
)
)
Testando em modo Ad-hoc
Para testar a configuração, exportamos a variável de ambiente TNS_ADMIN nesta seção:
export TNS_ADMIN=/home/oracle/dba/tns
ATENÇÃO: Não adicione ou modifique essa variável no arquivo .bash_profile ou similar para o usuário “oracle” no servidor de banco dados, isso pode afetar o próximo startup da instância.
Uma forma de validar que a variável está apontando para o diretório desejado é observando a informação apresentada em “Used parameter files” no resultado do tnsping:
[oracle@lab01 scripts]$ tnsping cdb1_rman
...
Used parameter files:
/home/oracle/dba/tns/sqlnet.ora
...
Para conectar nos utilitários usando a credencial armazenada na wallet, basta usar a sintaxe “/@<ALIAS>” onde normalmente teria o usuário e senha.
Por exemplo:
| Tipo de Conexão | Com Senha | Com Wallet (SEPS) |
|---|---|---|
| TNS | username/password@ALIAS | /@ALIAS |
| EZCONNECT | username/password@//host:port/service_name | /@host:port/service_name |
Exemplos
a) Testando com SQL*PLUS
Note que apesar de ter usado nomes sugestivos ao criar os apelidos de conexões na wallet e no tnsnames.ora, no fundo não existe nenhuma amarração ou restrição com esses nomes, trata-se apenas de uma padronização pra facilitar a manutenção no ambiente.
Por exemplo, podemos usar as mesmas entradas no SQLPLUS:
sqlplus /@CDB1_RMAN
Assim como:
sqlplus /@PDBEX_DATAPUMP
Ou com o comando Connect dentro do SQLPLUS:
sqlplus /nolog connect /@PDBEX_DATAPUMP
No primeiro exemplo, o resultado seria uma conexão aberta no CDB root da instância CDB1 com o usuário “SYS”. Já no segundo exemplo, o resultado seria uma sessão aberta no PDB “PDBEX” com o usuário “SYSTEM”.
Se você trabalha com SQLcl, funciona da mesma maneira.
b) Testando com Data Pump:
Abaixo o exemplo de como ficaria no expdp e impdp:
expdp /@PDBEX_DATAPUMP directory=EXP_DIR schemas=HR ... impdp /@PDBEX_DATAPUMP directory=EXP_DIR schemas=HR ...
Se preferir, também pode explicitar o parâmetro userid:
expdp userid=/@PDBEX_DATAPUMP directory=EXP_DIR schemas=HR ... impdp userid=/@PDBEX_DATAPUMP directory=EXP_DIR schemas=HR ...
c) Testando com RMAN
No RMAN, podemos usar essa sintaxe para as opções TARGET, AUXILIARY e CATALOG.
Exemplo com target em linha:
rman target /@CDB1_RMAN
Ou dentro do RMAN:
RMAN> connect target /@CDB1_RMAN
Você pode usar essa sintaxe para o Target e Auxiliary, desde que o arquivo tnsnames.ora e a wallet tenham as entradas correspondentes.
Por exemplo, conectando no Primary e Standby, assumindo que as entradas são CDB1_PRIMARY e CDB1_STANDBY:
rman target @/CDB1_PRIMARY auxiliary @/CDB1_STANDBY
Ou dentro do RMAN:
connect target /@CDB1_PRIMARY connect auxiliary /@CDB1_STANDBY
d) Exemplo com DGMGRL (Data Guard Broker)
Você também pode conectar no utilitário Data Guard Broker usando a mesma abordagem, como no exemplo abaixo:
dgmgrl /@CDB1_RMAN
Ou:
DGMGRL> connect /@CDB1_RMAN Connected to "CDB1" Connected as SYSDBA.
e) Exemplo com DBSAT
O DBSAT (Database Security Assessment Tool) é uma ferramenta de segurança da Oracle usada para identificar vulnerabilidades no banco de dados. Durante a etapa inicial de coleta de dados ou descoberta de dados sensíveis, a ferramenta requer autenticação com o banco de dados.
Podemos usar a mesma abordagem vista em outras ferramentas, conforme exemplo abaixo:
Collector
./dbsat collect /@PDBSEC1_DBSAT collect_PDBSEC1
Discovery
Se estiver rodando o processo de Discovery, o arquivo de configuração teria um configuração similar a essa na seção “Database”:
[Database]
TNS_ADMIN = /home/oracle/dba/tns
NET_SERVICE_NAME = PDBSEC1_DBSAT
WALLET_LOCATION = /home/oracle/dba/wallet
E o exemplo abaixo deveria funcionar sem solicitar senha do banco de dados:
./dbsat discover -c Discover/conf/PDBSEC1_dbsat.config PDBSEC1_discover
f) Exemplo com DBCA
Quando utilizamos o DBCA para criar ou modificar o database, ele solicita a senha de usuários administrativos para modificar a configuração atual, ou a senha que deve ser usada para novos usuários quando estamos criando um CDB ou PDB.
Para permitir uma execução em modo silent sem passar a senha em texto aberto na linha de comando, o DBCA suporta a opção -useWalletForDBCredentials
1) Crie as entradas na wallet que correspondem a cada usuário que o DBCA pode solicitar.
Note que não é necessário incluir todas, e que a sintaxe é diferente dos primeiros exemplos:
mkstore -wrl ~/dba/wallet -createEntry oracle.dbsecurity.sysPassword mkstore -wrl ~/dba/wallet -createEntry oracle.dbsecurity.systemPassword mkstore -wrl ~/dba/wallet -createEntry oracle.dbsecurity.pdbAdminPassword
2) O DBCA pode ser executado com uma sintaxe similar ao exemplo abaixo:
dbca -silent -useWalletForDBCredentials true -dbCredentialsWalletLocation ~/dba/wallet
Exemplo criando um novo PDB:
[oracle@lab01 ~]$ dbca -silent -useWalletForDBCredentials true -dbCredentialsWalletLocation ~/dba/wallet -createPluggableDatabase -sourceDB CDBTST -pdbName PDBTST4
Prepare for db operation
13% complete
Creating Pluggable Database
15% complete
19% complete
23% complete
31% complete
53% complete
Completing Pluggable Database Creation
60% complete
Executing Post Configuration Actions
100% complete
Pluggable database "PDBTST4" plugged successfully.
OBS: Para o DBCA não há necessidade de usar uma wallet configurada no arquivo sqlnet.ora, basta informar o caminho da wallet na linha de comando.
Exemplo com EZCONNECT
Caso não queira usar uma entrada dentro do tnsnames.ora, também é possível usar a sintaxe do EZCONNECT com a wallet, conforme exemplo abaixo:
1) Adicione uma entrada na wallet com a sintaxe abaixo:
mkstore -wrl . -createCredential lab01:1521/PDBEX system
2) Use a mesma string de conexão na hora de se conectar, exemplos:
sqlplus /@lab01:1521/PDBEX
Exemplo de Como Usar em Script
Para usar em scripts, o que você precisa é basicamente adaptar os seus scripts existentes usando a sintaxe de conexão com a wallet, e garantir que o script está usando a variável de ambiente customizada. Nestes exemplos, adicionei a variável TNS_ADMIN em cada script.
a) Exemplo SQL*PLUS
Script
#!/bin/bash
source /home/oracle/.bash_profile
export TNS_ADMIN=/home/oracle/dba/tns
sqlplus -s /nolog << EOF
connect /@PDBEX_DATAPUMP ;
exec dbms_stats.gather_table_stats('HR','LOCATIONS');
EOF
Execução
[oracle@lab01 scripts]$ ./gather_stats.sh
PL/SQL procedure successfully completed.
b) Exemplo Data Pump
Script:
#!/bin/bash source /home/oracle/.bash_profile export TNS_ADMIN=/home/oracle/dba/tns expdp /@PDBEX_DATAPUMP \ directory=EXP_DIR \ tables=hr.locations \ dumpfile=example.dmp \ logfile=example.log
Execução:
[oracle@lab01 scripts]$ ./export_hr.sh
Export: Release 19.0.0.0.0 - Production on Fri Sep 13 19:42:57 2024
Version 19.24.0.0.0
Copyright (c) 1982, 2019, Oracle and/or its affiliates. All rights reserved.
Connected to: Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production
FLASHBACK automatically enabled to preserve database integrity.
Starting "SYSTEM"."SYS_EXPORT_SCHEMA_01": /********@PDBEX_DATAPUMP
Processing object type SCHEMA_EXPORT/TABLE/TABLE_DATA
Processing object type SCHEMA_EXPORT/TABLE/INDEX/STATISTICS/INDEX_STATISTICS
Processing object type SCHEMA_EXPORT/TABLE/STATISTICS/TABLE_STATISTICS
Processing object type SCHEMA_EXPORT/DEFAULT_ROLE
Processing object type SCHEMA_EXPORT/PRE_SCHEMA/PROCACT_SCHEMA
Processing object type SCHEMA_EXPORT/TABLE/TABLE
Processing object type SCHEMA_EXPORT/TABLE/COMMENT
Processing object type SCHEMA_EXPORT/TABLE/INDEX/INDEX
Master table "SYSTEM"."SYS_EXPORT_SCHEMA_01" successfully loaded/unloaded
******************************************************************************
Dump file set for SYSTEM.SYS_EXPORT_SCHEMA_01 is:
/u01/app/oracle/admin/CDB1/dpdump/1E818A046F905718E0630E01A8C0E0A6/expdat.dmp
Job "SYSTEM"."SYS_EXPORT_SCHEMA_01" successfully completed at Fri Sep 13 19:43:39 2024 elapsed 0 00:00:41
c) Exemplo RMAN
Script – Note que neste exemplo estou fazendo uma conexão no RMAN Catalog usando a mesma abordagem:
#!/bin/bash
source /home/oracle/.bash_profile
export TNS_ADMIN=/home/oracle/dba/tns
export NLS_DATE_FORMAT="DD/MM/YYYY HH24:MI:SS"
rman <<EOF
connect target /@CDB1_RMAN;
connect catalog /@RMAN_CATALOG;
run {
allocate channel c1 device type disk;
backup as compressed backupset
tablespace PDBEX:TBS_BANK
format '/home/oracle/backup/rman/CDB1_%U.bkp';
}
EOF
Execução
[oracle@lab01 scripts]$ ./backup_tbs.sh
Recovery Manager: Release 19.0.0.0.0 - Production on Fri Sep 13 19:57:49 2024
Version 19.24.0.0.0
Copyright (c) 1982, 2019, Oracle and/or its affiliates. All rights reserved.
RMAN>
connected to target database: CDB1 (DBID=1147586932)
RMAN>
connected to recovery catalog database
RMAN> 2> 3> 4> 5> 6>
allocated channel: c1
channel c1: SID=156 device type=DISK
Starting backup at 13/09/2024 19:57:52
channel c1: starting compressed full datafile backup set
channel c1: specifying datafile(s) in backup set
input datafile file number=00019 name=+DATA/CDB1/1E818A046F905718E0630E01A8C0E0A6/DATAFILE/tbs_bank.296.1179243785
channel c1: starting piece 1 at 13/09/2024 19:57:52
channel c1: finished piece 1 at 13/09/2024 19:57:53
piece handle=/home/oracle/backup/rman/CDB1_0u34ulm0_30_1_1.bkp tag=TAG20240913T195752 comment=NONE
channel c1: backup set complete, elapsed time: 00:00:01
Finished backup at 13/09/2024 19:57:53
Starting Control File and SPFILE Autobackup at 13/09/2024 19:57:53
piece handle=+DATA/CDB1/AUTOBACKUP/2024_09_13/s_1179604674.275.1179604675 comment=NONE
Finished Control File and SPFILE Autobackup at 13/09/2024 19:57:55
released channel: c1
RMAN>
Recovery Manager complete.
Outros casos de uso
Em um ambiente RAC, você pode criar essa estrutura em um ACFS para simplificar a gestão dos scripts, wallet e tnsnames usado no scripts, considerando que pode ser necessário executar o mesmo script em diferentes nodes do Cluster. Por exemplo, essa estrutura poderia ser criada dentro de “/acfs01/dba”.
Uma dica é que essa estrutura pode ser facilmente portada para outro ambiente apenas copiando a estrutura de diretório para um servidor diferente (similar a wallet do Autonomous Database). Para este caso, uma forma de torná-lo mais portável é ter um arquivo de variáveis de ambiente na pasta raiz da estrutura, contendo uma variável TNS_ADMIN e uma WALLET_DIR.
Conclusão
Este post demonstrou como usar uma wallet em um servidor de banco de dados como propósito de “Client-Wallet”, evitando assim uma falha de segurança que é deixar senhas expostas em scripts no servidor, mas sem correr o risco estar realizando alterações na wallet principal do servidor, mitigando o risco de causar uma indisponibilidade por uma alteração incorreta na wallet usada por features como Transparente Data Encryption (TDE).
Como recomendação final, sempre que possível use wallet para autenticação em scripts, e quando usar, sempre opte por uma configuração isolada com a demonstrada neste post.
Pingback: ORACLE SECURE EXTERNAL PASSWORD STORE – Blog DBA Focus