Background
Almost every DBA writes and uses various custom scripts to monitor and backup their Oracle databases. However, finding the optimal and most secure way to connect to the database is often not prioritized.
The short summary is that having your script put the username/password (credentials) in any sort of variables or command arguments is the “bad way”. Using an “Oracle External Password Store” (SEPS) or Oracle Wallet is the “better way”. Yet this technology which has been around since Oracle 10gR2 and which does not require the Advanced Security Option is often not used.
Common Mistakes
Many DBAs will store credentials in their actual scripts. Sometimes obfuscating the actual password through some custom mechanism or script. For example, the following is a simplified version of an RMAN backup script found at a client site:
#!/bin/bash export DB_USER=backup_user export DB_PASS=`~/.secure_pwd_extractor` $ORACLE_HOME/bin/rman << EOF connect target $DB_USER/$DB_PASS shutdown immediate startup mount backup database; alter database open; EOF
The client thought that it was somewhat secure as the actual password wasn’t used as a command line argument to RMAN and was stored in a Linux “hidden file” (starts with a period), which was protected by properly setting OS permissions. However, it dynamically extracted the password from a plain text file (based on the DB_USER environment variable). Another key problem was the fact that the environment variable was exported and hence was part of the environmental profile under which the database was started.
The exported environment variables in this case can be a little bit of a security risk in a couple of ways:
First of all, the complete operating environment including the exported environment variables under which the database is running are recorded by the listener when service is registered. Hence, they are visible in a listener “services” command with “set displaymode verbose“:
Secondly, they may be recorded in OS process files. For example, the pmon process’ operating environment or even the RMAN process’ while running:
But most significantly the credentials can be extracted by anyone with access to the script file and/or the underlying credentials file.
A Better Approach
A better way to store database credentials for monitoring or backup scripts is to use a “Secure External Password Store” (SEPS) which relies on having the necessary credentials securely stored in an Oracle Wallet file.
Typically a DBA might create their own plain text password listing file for use by scripts and batch jobs. Usually with three columns: 1) DB_NAME; 2) DB_USERNAME; 3) DB_PASSWORD. The Oracle Wallet is structured exactly the same way except:
- The file is protected with 3DES encryption.
- The DB_NAME is really an OracleNET Service Name meaning you can have multiple aliases for the same database.
- The passwords are never exposed.
- A separate Wallet password is required to manipulate the file’s contents.
- Control on whether the Oracle Wallet file is tied to the local machine or whether it can be copied to and used on other machines.
The advantages of this approach include:
- No clear text password in any scripts or files.
- No possible exposure of passwords by the listener or process operating environments.
- Control on whether the Oracle Wallet file can be copied and used on another machine.
The last point is actually a complex one. A Wallet can be created as an “auto_login” wallet (done by default). To secure it to only work on the local server, it can be changed to “auto_login_local“. However, there are various issues, limitations, and 12c bugs with the additional functionality that Oracle provides. A separate article goes into this in detail.
Setup
Setting up a “Secure External Password Store” and Oracle Wallet is actually quite quick and easy:
1) Adjust the sqlnet.ora file to point to an Oracle Wallet location. For example, add the following to the sqlnet.ora file (assuming that the specified directory exists):
WALLET_LOCATION = (SOURCE = (METHOD = FILE) (METHOD_DATA = (DIRECTORY = /u01/app/oracle/wallet) ) ) SQLNET.WALLET_OVERRIDE = TRUE
2) Create the Oracle Wallet files and add a credential. Two files will actually be created in the specified directory:
- ewallet.p12 – the actual password protected Wallet file.
- cwallet.sso – an additional file for auto-login credentials.
This can be done as either two separate commands or all in a single command:
$ mkstore -wrl "/u01/app/oracle/wallet" -create Oracle Secret Store Tool : Version 12.1.0.2 Copyright (c) 2004, 2014, Oracle and/or its affiliates. All rights reserved. Enter password: Enter password again: $ mkstore -wrl "/u01/app/oracle/wallet" -createCredential ORCL scott Oracle Secret Store Tool : Version 12.1.0.2 Copyright (c) 2004, 2014, Oracle and/or its affiliates. All rights reserved. Your secret/Password is missing in the command line Enter your secret/Password: Re-enter your secret/Password: Enter wallet password: Create credential oracle.security.client.connect_string1
Or as a single command:
$ mkstore -wrl "/u01/app/oracle/wallet" -create -createCredential ORCL scott Oracle Secret Store Tool : Version 12.1.0.2 Copyright (c) 2004, 2014, Oracle and/or its affiliates. All rights reserved. Enter password: Enter password again: Your secret/Password is missing in the command line Enter your secret/Password: Re-enter your secret/Password: Create credential oracle.security.client.connect_string1 $
Notice that the Wallet is secured by a password. And then the SCOTT credentials are stored within the Wallet. The Wallet password is required to manipulate contents – not for scripts to access the stored credentials.
The first parameter after the “-createCredential” argument is an OracleNET Service Name. Just like with any database connection, here we can specify an OracleNET Service Name (from the tnsnames.ora file), or a full connection string, or an EZconnect string.
Hence, we could add a second and third connection to the same database as:
$ mkstore -wrl "/u01/app/oracle/wallet" -createCredential localhost:1521/ORCL monitoring_user Oracle Secret Store Tool : Version 12.1.0.2 Copyright (c) 2004, 2014, Oracle and/or its affiliates. All rights reserved. Your secret/Password is missing in the command line Enter your secret/Password: Re-enter your secret/Password: Enter wallet password: Create credential oracle.security.client.connect_string2 $ mkstore -wrl "/u01/app/oracle/wallet" -createCredential 127.0.0.1:1521/ORCL batch_reporting Oracle Secret Store Tool : Version 12.1.0.2 Copyright (c) 2004, 2014, Oracle and/or its affiliates. All rights reserved. Your secret/Password is missing in the command line Enter your secret/Password: Re-enter your secret/Password: Enter wallet password: Create credential oracle.security.client.connect_string3 $
And to list the contents of the Oracle Wallet:
$ mkstore -wrl "/u01/app/oracle/wallet" -listCredential Oracle Secret Store Tool : Version 12.1.0.2 Copyright (c) 2004, 2014, Oracle and/or its affiliates. All rights reserved. Enter wallet password: List credential (index: connect_string username) 3: 127.0.0.1:1521/ORCL batch_reporting 2: localhost:1521/ORCL monitoring_user 1: ORCL scott $
Now any of the three can be used (from the same OS account: “oracle”) depending on which OracleNET Service Name is referenced:
$ sqlplus /@ORCL SQL*Plus: Release 12.1.0.2.0 Production on Wed Jan 13 08:59:12 2016 Copyright (c) 1982, 2014, Oracle. All rights reserved. Last Successful login time: Wed Jan 13 2016 08:56:56 -07:00 Connected to: Oracle Database 12c Enterprise Edition Release 12.1.0.2.0 - 64bit Production With the Partitioning, OLAP, Advanced Analytics and Real Application Testing options SQL> show user USER is "SCOTT" SQL>
$ sqlplus /@localhost:1521/ORCL SQL*Plus: Release 12.1.0.2.0 Production on Wed Jan 13 08:59:41 2016 Copyright (c) 1982, 2014, Oracle. All rights reserved. Last Successful login time: Wed Jan 13 2016 08:57:25 -07:00 Connected to: Oracle Database 12c Enterprise Edition Release 12.1.0.2.0 - 64bit Production With the Partitioning, OLAP, Advanced Analytics and Real Application Testing options SQL> show user USER is "MONITORING_USER" SQL>
$ sqlplus /@127.0.0.1:1521/ORCL SQL*Plus: Release 12.1.0.2.0 Production on Wed Jan 13 09:00:14 2016 Copyright (c) 1982, 2014, Oracle. All rights reserved. Last Successful login time: Wed Jan 13 2016 08:43:44 -07:00 Connected to: Oracle Database 12c Enterprise Edition Release 12.1.0.2.0 - 64bit Production With the Partitioning, OLAP, Advanced Analytics and Real Application Testing options SQL> show user USER is "BATCH_REPORTING" SQL>
$ sqlplus / as sysdba SQL*Plus: Release 12.1.0.2.0 Production on Wed Jan 13 09:01:12 2016 Copyright (c) 1982, 2014, Oracle. All rights reserved. Connected to: Oracle Database 12c Enterprise Edition Release 12.1.0.2.0 - 64bit Production With the Partitioning, OLAP, Advanced Analytics and Real Application Testing options SQL> show user USER is "SYS" SQL>
However, one might challenge the fact that the Oracle Wallet file itself that must be secured just as a plain text password file would need to be and that the risks of either being obtained by a “bad actor” are the same. That being said, there are still some benefits of the SEPS method:
- Passwords are never maintained in plain text in scripts or (hidden) password files.
- No risk of password exposure at the operating system process list.
- No risk of password exposure in operating system process environmental files.
- No risk of exposure from any bad actor with access to the script.
- No risk of password exposure in OS backups maintained by sysadmins or backup vendors (though the files themselves may still be usable).
Regardless, using the SEPS and Oracle Wallet shouldn’t make anything less secure. One could argue that security and risk is equal, but definitely not worse.
However they are a few operational disadvantages:
- The OracleNET Service Name forms the primary key of the entries in the Wallet and hence must be unique. So if another user credential is required for the same DB, an OracleNET alias will be required (as trying to add another user using the same OracleNET Service Name will generate the “Credential already exists” error based on the OracleNET Service Name not being unique).
- Doesn’t work after connecting to SQLPLUS using the “CONNECT” command.
- Scripts are now dependent on listener availability for establishing a TNS connection instead of a BEQ. Though a workaround may be to connect directly to a DISPATCHER port.
Advantages Over OS Authentication
Using a SEPS and an Oracle Wallet may seem functionally similar to just using “OS Authentication”. However it does pose a few differences or advantages.
Most DBAs operate and implement scripts under the “Oracle software owner” account which is typically called “oracle” on Unix or Linux systems. And hence most are able to connect to the database using a SYSDBA connection. So one solution would be to use a dedicated OS user account specifically for monitoring or database backup scripts. And then rely on OS authentication for database connections. However this is often not done. And if running scripts from a remote server or centralized monitoring server then the REMOTE_OS_AUTHENT=TRUE parameter would have to be set which poses other security risks.
Instead, using a SEPS allows for non-OS authenticated connections to a dedicated and minimally privileged database account even from the software owner (Oracle) account locally, or from any other account remotely.
Other Questions
Q: Do I need to re-create my Wallet file as part of a 12c upgrade?
A: NO.
Q: Do I need to backup the Wallet files?
A: Absolutely. Just back them up as you would other Oracle environmental files, such as the sqlnet.ora. Otherwise they’ll need to be re-created.
Q: Is SEPS compatible with “Proxy Authenticated Connections”?
A: YES. See Proxy Authenticated Database connections.
Q: Can the Wallet be used with RMAN?
A: YES. It definitely can and should be used by RMAN scripts.
Q: Can the Wallet be used with JDBC thin or ODBC connections?
A: YES to both. See MOS documents 1441745.1 and 1430666.1 for further details.
Q: Are SEPS and Wallet connections compatible with the CDB architecture and PDBs?
A: Of course. PDBs connect through Oracle Services and OracleNET Service Names.
Q: Can we tell from within the database whether a connected session referenced an Oracle Wallet and used SEPS?
A: NO. There doesn’t seem to be any indication from within the database. As far as the DB is concerned, it just seems to be a password authenticated connection. A SQLNET trace shows that the Wallet files are accessed but doesn’t transpose that information into any DB metric or SYS_CONTEXT USERENV data.
Preventing the Secure Password Store Wallet File from Being Moved to Another Host
Oracle suggests that we can add additional security by tying the Oracle Wallet file to a specific host. See MOS document 1114599.1. However, this poses some restrictions and bugs with 12.1.0.2 specifically. As this discussion is complex, this follow-up article has been created.
A good workaround (and a key point from the follow-up article) is to simply use an EZconnect connection in the Oracle Wallet file and to specify localhost or 127.0.0.1.
Summarizing Best Practices
- Continue to properly secure the directory and file permissions of the Wallet files as you would a plain text password file. Further, why not make the entire wallet directory a hidden directory starting with a period. Remember that If the wallet file can be copied to another server then potentially the credentials within it can continue to be used. See the follow-up article for suggested techniques for securing access further.
- Have scripts connect to the database using dedicated purpose based user accounts with minimal privileges (don’t use SYS or SYSTEM).
- Use OracleNET Service Name aliases (not duplicate entries, but aliases to an existing entry) in the tnsnames.ora file to allow multiple credentials for the same database.
- For additional security add Wallet entries based on EZconnect strings using localhost or 127.0.0.1 instead of relying on OracleNET Service Names from the tnsnames.ora file.
Discover more about our expertise in the world of Oracle.
5 Comments. Leave new
Hi Simon,
I am trying to do the same but getiing a ERROR:
ORA-01017: invalid username/password; logon denied
1. Created directory – /home/app/tns
2. Created 2 files in it as sqlnet.ora and tnsnames.ora.
3. In sqlnet.ora it shows as :
# sqlnet.ora Network Configuration File: /oraclient/product/12.1.0.2.0/client/network/admin/sqlnet.ora
# Generated by Oracle configuration tools.
NAMES.DIRECTORY_PATH= (TNSNAMES, EZCONNECT)
WALLET_LOCATION =
(SOURCE =
(METHOD = FILE)
(METHOD_DATA =
(DIRECTORY = /home/app/appstore)
)
)
SQLNET.WALLET_OVERRIDE = TRUE
SSL_CLIENT_AUTHENTICATION = FALSE
SSL_VERSION = 0
4. In tnsnames.ora :
connect_db =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = Dbhost)(PORT = 61901))
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = service_name_io2)
)
)
5. export TNS_ADMIN=/home/app/tns.
6.
mkdir -p /home/app/appstore
mkstore -wrl /home/app/appstore -create
mkstore -wrl /home/app/appstore -createCredential connect_db username password.
7. Chmod 777 to all files.
8. tnsping connect_db
Used TNSNAMES adapter to resolve the alias
Attempting to contact : …………………………..
OK (20 msec).
But when trying to connect as
9. sqlplus /@connect_db
failing with below error:
SQL*Plus: Release 12.1.0.2.0 Production on Fri Jan 18 18:08:14 2019
Copyright (c) 1982, 2014, Oracle. All rights reserved.
ERROR:
ORA-01017: invalid username/password; logon denied
Checked client and server both are in 12.1.0.2.0
Note, the SYSBACKUP privilege does not work when using a wallet.
You will need to explicitly grant the SYSDBA privilege to the user in order for the wallet entry to work. This was tested on an Oracle 19c database
Seems to work fine for me as SYSBACKUP on 19c.
Setup:
SQL> select username, sysdba, sysbackup from v$pwfile_users where username = 'C##SIMON';
USERNAME SYSDBA SYSBACKUP
------------------------ ---------- ----------
C##SIMON FALSE TRUE
SQL>
Wallet contents:
$ mkstore -wrl "/u01/app/oracle/wallet" -listCredential
Oracle Secret Store Tool Release 19.0.0.0.0 - Production
Version 19.4.0.0.0
Copyright (c) 2004, 2020, Oracle and/or its affiliates. All rights reserved.
Enter wallet password:
List credential (index: connect_string username)
1: ORCL c##simon
RMAN connection:
$ rman
Recovery Manager: Release 19.0.0.0.0 - Production on Tue Mar 9 11:00:12 2021
Version 19.10.0.0.0
Copyright (c) 1982, 2019, Oracle and/or its affiliates. All rights reserved.
RMAN> connect target "/@ORCL as sysbackup"
connected to target database: ORCL (DBID=1593919861)
RMAN>
Verification:
SQL> select username, program, process from v$session where username is not null;
USERNAME PROGRAM PROCESS
------------------------ ------------------------------------------------ ------------------------
SYS [email protected] (OFSD) 1696_1698
SYS [email protected] (TNS V1-V3) 2814
SYSBACKUP [email protected] (TNS V1-V3) 3150
SYSBACKUP [email protected] (TNS V1-V3) 3150
SQL> !ps -ef |grep [3]150
oracle 3150 1762 1 11:00 pts/0 00:00:00 rman
SQL>
Looks good to me?
Hi Simon.
I’m looking for ideas on how to script this with SYSBACKUP, as the backup command is about 35 lines and built on the fly from another script. Piping the connection first and then passing the parameter command fails as it runs the cmdfile first before connecting
[[email protected] scripts]$ echo “connect target ‘/@DBATEST_RMANBKP as sysbackup’;” | rman cmdfile=rman.cmd
Recovery Manager: Release 19.0.0.0.0 – Production on Fri Feb 18 16:33:00 2022
Version 19.3.0.0.0
Copyright (c) 1982, 2019, Oracle and/or its affiliates. All rights reserved.
RMAN> show all;
2>
using target database control file instead of recovery catalog
RMAN-00571: ===========================================================
RMAN-00569: =============== ERROR MESSAGE STACK FOLLOWS ===============
RMAN-00571: ===========================================================
RMAN-03002: failure of show command at 02/18/2022 16:33:00
RMAN-06171: not connected to target database
Recovery Manager complete.
Hi Simon, found out how to do it :)
[[email protected] scripts]$ rman target ‘”/@DBATEST_RMANBKP as sysbackup”‘ cmdfile=rman.cmd
Recovery Manager: Release 19.0.0.0.0 – Production on Fri Feb 18 17:26:24 2022
Version 19.3.0.0.0
Copyright (c) 1982, 2019, Oracle and/or its affiliates. All rights reserved.
connected to target database: DBTEST (DBID=1479858209)
RMAN> show all;
2>
using target database control file instead of recovery catalog
RMAN configuration parameters for database with db_unique_name DBTEST are:
CONFIGURE RETENTION POLICY TO REDUNDANCY 1; # default
CONFIGURE BACKUP OPTIMIZATION OFF; # default
CONFIGURE DEFAULT DEVICE TYPE TO DISK; # default
CONFIGURE CONTROLFILE AUTOBACKUP ON; # default
CONFIGURE CONTROLFILE AUTOBACKUP FORMAT FOR DEVICE TYPE DISK TO ‘%F’; # default
CONFIGURE DEVICE TYPE DISK PARALLELISM 1 BACKUP TYPE TO BACKUPSET; # default
CONFIGURE DATAFILE BACKUP COPIES FOR DEVICE TYPE DISK TO 1; # default
CONFIGURE ARCHIVELOG BACKUP COPIES FOR DEVICE TYPE DISK TO 1; # default
CONFIGURE MAXSETSIZE TO UNLIMITED; # default
CONFIGURE ENCRYPTION FOR DATABASE OFF; # default
CONFIGURE ENCRYPTION ALGORITHM ‘AES128’; # default
CONFIGURE COMPRESSION ALGORITHM ‘BASIC’ AS OF RELEASE ‘DEFAULT’ OPTIMIZE FOR LOAD TRUE ; # default
CONFIGURE RMAN OUTPUT TO KEEP FOR 7 DAYS; # default
CONFIGURE ARCHIVELOG DELETION POLICY TO NONE; # default
CONFIGURE SNAPSHOT CONTROLFILE NAME TO ‘/u01/app/oracle/product/19.0.0.0/dbhome_1/dbs/snapcf_DBTEST.f’; # default
Recovery Manager complete.