Oracle External Secure Password Store, OCI et JDBC Thin

Les bases de données Oracle offrent un mécanisme simple pour stocker les identifiants et mots de passe des utilisateurs dans un wallet sur le client. Ce mécanisme appelé External Secure Password Store est disponible avec les versions 10g et 11g Enterprise Edition.

Si la solution est largement moins évoluée que de mettre en œuvre une PKI, comme présenté dans l’article « JDBC thin » sans mot de passe ou Comment intégrer Oracle dans une PKI via SSL, elle offre également de nombreux avantages :

  • Il n’est pas nécessaire d’utiliser une licence Advanced Security Option (ASO). Les bases de données Enterprise Edition suffisent
  • Il ne faut effectuer aucun changement sur les serveurs de bases de données.
  • La mise en œuvre est d’une simplicité redoutable. Elle est compatible avec les clients OCI et JDBC
  • Cela permet facilement de supprimer les mots de passe des scripts ou autres fichiers de configuration des applications.

Côté sécurité, comme dans le cas d’un certificat, se faire voler (ou copier) un wallet reste problématique. S’il possède la clé du wallet, un « voleur » peut en découvrir le contenu. Pire : s’il arrive à subtiliser d’une version ayant auto login actif (aka SSO Wallet), il pourra se faire passer pour un utilisateur technique ou physique sans en connaître le contenu. Sécuriser le wallet est donc essentiel. Mais c’est déjà une autre histoire…

Cet article illustre, à travers un exemple, comment utiliser un Secure External Password Store en OCI et JDBC Thin.

Créer un wallet

La première étape consiste à créer un wallet à l’endroit qui vous convient. On pourra, par exemple, utiliser Oracle Wallet Manager (owm), mkstore ou orapki. Vous noterez qu’il n’est pas nécessaire, en général, d’être sur la même machine que celle sur laquelle vous utiliserez le fichier pour cette création. La création d’un wallet avec mkstore s’effectue comme ceci :

mkstore -wrl /home/oracle -create
Oracle Secret Store Tool : Version 11.2.0.3.0 - Production
Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved.

Enter password:
Enter password again:

Cette commande est équivalente à la commande ci-dessous :

orapki wallet create -wallet /home/oracle -auto_login
Oracle PKI Tool : Version 11.2.0.3.0 - Production
Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved.

Enter password:
Enter password again:

Notes:

  • Pour que le client puisse le connecter au serveur avec un External Secure Password Store, il faut que l’option du wallet « autologin » soit activée. Cette option crée un fichier cwallet.sso. Le client utilise alors ce fichier, qui doit être sécurisé par les droits systèmes, pour se connecter sans mot de passe à la base de données. L’utilisation du seul fichier ewallet.p12 au format PKCS #12 ne suffit donc pas. C’est pour cette raison que la commande mkstore est équivalente à la commande orapki avec le paramètre -auto_login.
  • L’avantage de orapki [...] -auto_login ou mkstore est que vous pouvez générer le fichier sur l’importe quel machine et envoyer uniquement cwallet.sso pour permettre la connexion d’un client. L’inconvénient, vous l’aurez compris, est que le seul fichier suffit à se connecter depuis l’importe quel serveur. Oracle 11.2 offre la possibilité de chiffrer le fichier en fonction d’éléments qui dépendent du serveur. Il faut alors utiliser orapki [...] -auto_login_local pour assurer que le fichier ne puisse pas être utilisé sur une autre machine que celle sur laquelle il a été généré. Ce type de fichier fonctionne comme External Secure Password Store également. Il serait intéressant de voir comment ça fonctionne avec des machines virtuelles car, après tout, on peut également les « voler »
  • N’utilisez pas orapki [...] -auto_login_only ! Si le fichier cwallet.sso généré fonctionne comme External Secure Password Store, accéder au mot de passe de ce type de store est aussi simple que de lancer mkstore -wrl $ORACLE_HOME/network/admin -viewEntry oracle.security.client.password1

Associer un utilisateur et un mot de passe à une chaîne de connexion

L’étape suivante consiste à utiliser mkstore pour stocker un nom d’utilisateur et un mot de passe en association avec une chaîne de connexion.

La chaîne de connexion peut avoir la forme que vous voulez : ce peut être un alias tnsnames, un descripteur EZCONNECT ou même une description complète avec tous les mots clés et parenthèses nécessaires. L’utilisation d’un External Secure Password Store n’influe pas sur la résolution de la connexion. En revanche, il faut que la chaîne de connexion corresponde exactement à la clé stockée dans le wallet. La chaîne ne peut donc pas correspondre au contenu des variables TWO_TASK ou LOCALE. Par ailleurs, si vous voulez vous connecter avec des utilisateurs différents, il faut et il suffit d’utiliser des chaînes de connexion différentes.

Il n’est pas possible d’utiliser owm ou orapki pour cette opération; seul mkstore permet de gérer les informations de connexion. Dans notre cas, nous utiliserons une chaîne de connexion EZCONNECT compatible avec les 2 syntaxes OCI et JDBC Thin :

mkstore -wrl . -createCredential pink:1521/WHITE system
Oracle Secret Store Tool : Version 11.2.0.3.0 - Production
Copyright (c) 2004, 2011, 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


mkstore -wrl . -listCredential
Oracle Secret Store Tool : Version 11.2.0.3.0 - Production
Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved.

Enter wallet password:

List credential (index: connect_string username)
1: pink:1521/WHITE system

Pour visualiser les clés, en plus de mkstore, vous pouvez utiliser owm :

Avec orapki ou avec les classes Java fournies dans oraclepki.jar:

export JAVA_HOME=/usr/lib/jvm/java-6-sun-1.6.0.26
export PATH=$JAVA_HOME/bin:$PATH
export CLASSPATH=.
export CLASSPATH=$CLASSPATH:$ORACLE_HOME/jdbc/lib/ojdbc6.jar
export CLASSPATH=$CLASSPATH:$ORACLE_HOME/jlib/oraclepki.jar
export CLASSPATH=$CLASSPATH:$ORACLE_HOME/jlib/osdt_cert.jar
export CLASSPATH=$CLASSPATH:$ORACLE_HOME/jlib/osdt_core.jar
export CLASSPATH=$CLASSPATH:$ORACLE_HOME/jlib/ojpse.jar

java oracle.security.pki.textui.OraclePKITextUI wallet display -wallet cwallet.sso

Oracle PKI Tool : Version 11.2.0.3.0 - Production
Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved.

Requested Certificates:
User Certificates:
Oracle Secret Store entries:
oracle.security.client.connect_string1
oracle.security.client.password1
oracle.security.client.username1
Trusted Certificates:
Subject: OU=Class 1 Public Primary Certification Authority,O=VeriSign, Inc.,C=US
Subject: OU=Class 3 Public Primary Certification Authority,O=VeriSign, Inc.,C=US
Subject: OU=Class 2 Public Primary Certification Authority,O=VeriSign, Inc.,C=US
Subject: OU=Secure Server Certification Authority,O=RSA Data Security, Inc.,C=US
Subject: CN=GTE CyberTrust Global Root,OU=GTE CyberTrust Solutions, Inc.,O=GTE Corporation,C=US

Notes Importantes :
Il est possible d’afficher le contenu du mot de passe à l’aide du fichier PKCS #12 et du mot de passe du Wallet ; pour ce faire utilisez la commande ci-dessous :

mkstore -wrl /home/oracle -viewEntry oracle.security.client.password1
Oracle Secret Store Tool : Version 11.2.0.3.0 - Production
Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved.

Enter wallet password:
oracle.security.client.password1 = manager

Dans le cas d’un fichier cwallet.sso créé avec l’option -auto_login_only, il n’y a même pas besoin de mot de passe ! Il est donc très risqué d’utiliser cette option pour une autre raison que pour des tests.

Configurer un client OCI pour utiliser un External Secure Password Store

Pour configurer un client OCI, il suffit d’utiliser le paramètre WALLET_LOCATION dans le fichier sqlnet.ora. Voici un exemple de configuration :

cat sqlnet.ora 

DIRECTORY_PATH=(EZCONNECT, TNSNAMES)
WALLET_LOCATION =
(SOURCE =
(METHOD = FILE)
(METHOD_DATA =
(DIRECTORY = /u01/app/oracle/product/11.2.0/db_1/network/admin)
)
)

SQLNET.WALLET_OVERRIDE = TRUE

La mise en oeuvre de la connexion est alors aussi simple que ce qui suit :

sqlplus /@pink:1521/white

SQL*Plus: Release 11.2.0.3.0 Production on Wed Apr 4 19:43:46 2012

Copyright (c) 1982, 2011, Oracle. All rights reserved.


Connected to:
Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - 64bit Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options


SQL> select user from dual;

USER
------------------------------
SYSTEM

External Secure Password Store et JDBC Thin

Pour utiliser un External Secure Password Store avec JDBC Thin, il suffit de remplir les conditions suivantes :

  • Ajouter les bibliothèques de chiffrement et de gestion du wallet d’Oracle dans le CLASSPATH
  • Utiliser la syntaxe comme "jdbc:oracle:thin:/@[...]" dans la chaîne de connexion, en n’oubliant pas le slash « / » devant le @.
  • Indiquer la position du wallet et/ou les paramètres correspondant au paramètre WALLET_LOCATION du fichier sqlnet.ora dans la propriété Java oracle.net.wallet_location. Cela peut être fait dans le programme ou dans la configuration de la machine virtuelle Java

Voici un exemple simple de mise en oeuvre d’un programme se connectant à la base de données via  un External Secure Password Store :

export JAVA_HOME=/usr/java/jdk1.7.0_03
export PATH=$JAVA_HOME/bin:$PATH
export CLASSPATH=.
export CLASSPATH=$CLASSPATH:$ORACLE_HOME/jdbc/lib/ojdbc6.jar
export CLASSPATH=$CLASSPATH:$ORACLE_HOME/jlib/oraclepki.jar
export CLASSPATH=$CLASSPATH:$ORACLE_HOME/jlib/osdt_cert.jar
export CLASSPATH=$CLASSPATH:$ORACLE_HOME/jlib/osdt_core.jar
export CLASSPATH=$CLASSPATH:$ORACLE_HOME/jlib/ojpse.jar

cat OracleAuthExternalStore.java
import java.sql.SQLException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;

public class OracleAuthExternalStore {
public static void main(String[] args)
throws SQLException {
DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver());
String url = "jdbc:oracle:thin:/@pink:1521/WHITE";
Connection conn = DriverManager.getConnection(url);
Statement stmt = conn.createStatement();
ResultSet rset = stmt.executeQuery("select user from dual");

while (rset.next())
System.out.println(rset.getString(1));

rset.close();
stmt.close();
conn.close();
}

javac OracleAuthExternalStore.java

java -Doracle.net.wallet_location=$ORACLE_HOME/network/admin
OracleAuthExternalStore

SYSTEM

Continuer…

Pour continuer, quelques lectures plus qu’utiles :