TDE (Part I)

 TDE : Transparent Data Encryption, est une fonctionnalité incluse dans l’option OAS : Oracle Advanced Security.

 

TDE permet de crypter (chiffrer en français), les données au niveau stockage. Cela signifie que sur disque la donnée est chiffrée (non lisible) : elle est chiffrée dans les datafiles, les redologs et dans le backup. Et évidement elle est lisible si nous passons par une connexion à la base de données et que nous sommes autorisés à la lire (grant)

TDE protège donc du vol physique des données : vol des fichiers (copie, édition…), vol des backups, vol des disques dur mais ne protège pas la donnée au niveau des connexions oracle.

 TDE permet de chiffrer par colonne ou bien par tablespace.

 

Nous allons voir dans cet article comment l’implémenter, quelles sont les restrictions que TDE impose et aussi les impacts sur un crash de base. Dans un second article nous compléterons par l’impact sur les performances,  la gestion des rekey (changement de clef) les  restaurations, et comment se débarrasser du cryptage..

 

 

L’article n’a pas la prétention d’être exhaustif. Il est là pour vous donner un premier contact avec TDE. Toutes les subtilités ne seront pas décrites… parce que cela serait trop long et laborieux… et aussi parce que je ne les connais pas toutes. Et je rajoute il s’applique à la version 11gR2.

Toutes les commandes ci-dessous peuvent être faites « à la lettre» ,  comme dans un TP ; l’environnement provient du l’article : testbed : 11gR2 RAC ASM.

 

Portefeuille et clef

Pour commencer le cryptage il faut générer une clef de chiffrage (master key) que l’on stockera dans un wallet (un portefeuille). Le wallet peut être soit un fichier, stocké sur l’OS (le moins secure) ou bien le wallet peut être un HSM (Hardware Security Module). Ici nous verrons uniquement le cas du wallet sur OS… pas les moyens d’avoir un HSM !

Pour configurer le wallet rien de plus simple, il suffit  d’éditer le sqlnet.ora et de générer la clef. Pour cela :

$ cd $ORACLE_BASE
$ mkdir wallet
$ chmod 700 wallet
$ vi $ORACLE_HOME/network/admin/sqlnet.ora

Rajouter la ligne:

ENCRYPTION_WALLET_LOCATION = (SOURCE =(METHOD = FILE) (METHOD_DATA =(DIRECTORY =/oracle/oraBase/wallet)))

Comme nous sommes en RAC, et que nous sommes en wallet sur fichier, il va falloir penser à synchroniser la clef sur les 2 nœuds manuellement. Un HSM réseau aurait permis de ne pas se soucier de la synchronisation.

Il est conseillé pour générer la clef d’éteindre une instance :

$ srvctl stop instance -d ARKONA -i ARKONA2

Puis pour générer la clef:

$ export ORACLE_SID=ARKONA1
$ sqlplus / as sysdba
$ ALTER SYSTEM SET ENCRYPTION KEY IDENTIFIED BY "MotDePasse";

MotDePasse est ici le mot de passe qui ouvre le wallet. Après la commande « Alter system », le wallet est généré dans $ORACLE_HOME/wallet.

Ce wallet doit être recopié manuellement sur le deuxième nœud :

$ scp ewallet.p12 racdb2:/oracle/oraBase/wallet
$ ssh racdb2 chmod 600 ewallet.p12

Le portefeuille (wallet) est créée, nous pouvons le visualiser dans $ORACLE_BASE/wallet, il se nomme ewallet.p12. Je ne sais pas pourquoi cela s’appelle un wallet, un keychain aurait semblé plus logique, non ?

 

TDE en action 

Une fois la clef générée, nous pouvons créer des tablespaces cryptés ou bien des colonnes cryptées.

Commençons par le tablespace.

Un tablespace crypté signifie que les datafiles qui le composent sont cryptés. Donc tous les objets qui seront contenus dans les datafiles (tables ou index) seront cryptés dans les datafiles, donc cryptés sur disques.

Plusieurs algorithmes de chiffrages peuvent être utilisés indépendamment de la master key, ainsi que la « longueur » de chiffrage.

Nous allons créer un tablespace USERS_CRYPT chiffré en AES en 256bits sur notre base ARKONA en RAC :

SQL> create tablespace USERS_CRYPT datafile '+DATA1' size 32m autoextend on next 32M maxsize 1G encryption using 'AES256' default storage(encrypt);

Bon, pour l’instant il n’y a rien dedans, alors mettons y une table et mettons aussi une table identique dans un tablespace non crypté, avec une ligne dans chacune :

SQL> CREATE TABLE crypt (
  id    NUMBER(10),  data  VARCHAR2(50)) tablespace USERS_CRYPT;

SQL> INSERT INTO crypt (id, data) VALUES (1, 'TOP SECRET!');

SQL> CREATE TABLE pas_crypt (
  id    NUMBER(10),  data  VARCHAR2(50)
) tablespace USERS;  -- si USERS n existe pas créez le petit.

SQL> INSERT INTO pas_crypt (id, data) VALUES (1, 'PAS SECRET!');
SQL> commit;

SQL> ALTER SYSTEM FLUSH BUFFER_CACHE;
SQL> ALTER SYSTEM ARCHIVELOG CURRENT;

Pour vérifier que les données sont bien chiffrées dans la table crypt, comme nous sommes sous ASM, copions les 2 datafiles dans un filesystem avec le user grid:

$ export ORACLE_SID=+ASM1
$ asmcmd -p
ASMCMD [+DATA1/ARKONA/DATAFILE] > cp USERS.264.806278525 /home/grid
copying +DATA1/ARKONA/DATAFILE/USERS.264.806278525 -> /home/grid/USERS.264.806278525
ASMCMD [+DATA1/ARKONA/DATAFILE] > cp USERS_CRYPT.268.828999975 /home/grid
copying +DATA1/ARKONA/DATAFILE/USERS_CRYPT.268.828999975 -> /home/grid/USERS_CRYPT.268.828999975

Les 2 datafiles étant petit, un petit vi pour les éditer suffira

$ vi /home/grid/USERS.264.806278525

Si nous cherchons la chaîne de caractère « SECRET » nous trouvons :

^B^KPAS SECRET!^A^F<96

Alors que si nous faisons la même opération avec le datafile chiffré USERS_CRYPT.268.828999975 nous ne trouvons rien.

Un petit grep fait aussi l’affaire :

$ grep SECRET /home/grid/USERS_CRYPT.268.828999975
$ grep SECRET USERS.264.806278525
Binary file USERS.264.806278525 matches

Vous pouvez faire aussi le test avec un backup RMAN, vous trouverez "PAS SECRET" dans les fichiers de backup mais pas "TOP SECRET".

TDE protège donc comme dit dans l’intro du vol de fichier ou de media.

Si le fichier ewallet.p12 est volé alors les fichiers ou media peuvent être déchiffrés mais il y aura le mot de passe à casser. C’est pour cela qu’il faut mettre un vrai mot de passe.

 Mais si la clef est stocké dans un HSM alors on peut considérer que la clef est bien protégé car il faudrait voler le HSM, le serveur de base de données et en plus avoir le badge opérateur qui peut lire la clef.

 

Restriction(s) ?

En 11gR2, il y a peu de limitation imposé par le chiffrage par tablespace. Les limitations sont :

-          Les BFILE ne peuvent être chiffrés (ils ne sont pas dans la base)

-          L’ « antique » export/import n’est pas supporté, il faut passer par data pump.

En revanche le chiffrage par colonne impose beaucoup plus de restriction. Avant d’en faire la liste, un petit exemple de restriction qui introduit la notion de « sel » Wink

Nous créeons une table avec une colonne chiffrée dans un tablespace non chiffré :

SQL> CREATE TABLE col_crypt (
  id    NUMBER(10),  data  VARCHAR2(50),  data_crypt  VARCHAR2(50) ENCRYPT
) tablespace USERS;

SQL>INSERT INTO col_crypt (id, data,data_crypt) VALUES (1, 'COL PAS SECRET!','COL TOP SECRET');
SQL> commit;

Bon très bien jusque-là pas de soucis. Créons maintenant un simple index (B-tree) sur la colonne chiffrée :

SQL> create index col_crypt_data_idx on col_crypt(data_crypt);
create index col_crypt_data_idx on col_crypt(data_crypt)
                                             *
ERROR at line 1:
ORA-28338: Column(s) cannot be both indexed and encrypted with salt

Oui et non, nous ne pouvons pas créer d’index sur une colonne chiffrée avec l’option SALT. SALT est l’option par défaut quand on ne précise pas, comme nous l’avons fait lors de la création de la table.  Si nous avion mis NO SALT comme ci-dessous, nous aurions pu créer l’index.

SQL> drop table col_cryp;
SQL> CREATE TABLE col_crypt (
  id    NUMBER(10),  data  VARCHAR2(50),  data_crypt  VARCHAR2(50) ENCRYPT NO SALT
) tablespace USERS;

SQL>INSERT INTO col_crypt (id, data,data_crypt) VALUES (1, 'COL PAS SECRET!','COL TOP SECRET');
SQL> commit;
SQL> create index col_crypt_data_idx on col_crypt(data_crypt);

 

Reste à comprendre SALT. Une colonne SALT est une colonne qui avant d’être chiffrée par TDE, est « salée » c'est-à-dire qu’une chaîne de caractère aléatoire est inséré dans la donnée. Cela va renforcer la difficulté à déchiffrer (dans le sens hacker) la colonne. Et donc évidement avec NO SALT il n’y a pas ce mécanisme de mis en place.

Et pour les autres index que les B-tree ? Il faut aussi qu’il n’y ait pas de sel ? Et bien non, même sans sel cela ne marchera pas. Si la colonne est chiffrée, aucun index possible différent du traditionnel B-Tree.

Dans les autres restrictions:

Autre restriction non négligeable, une colonne chiffrée ne peut être référencé dans une autre table.

La taille maximum de certain datatype sont diminués comme dans le tableau ci-dessous :

Data Type Maximum Size

CHAR 1932 bytes

VARCHAR2 3932 bytes

NVARCHAR2 1966 bytes

NCHAR 966 bytes

 

Dernier exemple de restriction, le »index range scan » n’est pas possible avec une colonne chiffrée, l’optimiseur choissira donc éventuellement un « index fast full scan » ou autre.

Il y a quelques autres restrictions mais les principales sont là.

 

Un petit tableau pour résumer tout cela:

 

Chiffrage pas colonne

Chiffrage par tablespace

 

SALT

NO SALT

index B-TREE

NON

OUI

OUI

Autres index

NON

NON

OUI

Pas de changement de taille max sur les datatypes

NON

NON

OUI

Colonne chiffrée référençable

NON

NON

OUI

Lecture “index range scan“ possible

NON

NON

OUI

BFILE chiffré

NON

NON

NO

 

Stop/Start & Crash

Nous avons vu qu’il faut ouvrir le portefeuille avec le mot de passe pour lire la clef et donc avoir accès aux données cryptées. Nous pouvons très bien avoir une base ouverte même avec le wallet fermé, cela n’empêche pas son bon fonctionnement. Mais que ce passe-t-il si la donnée cryptée se trouve uniquement dans le redolog courant et que la base crash ? A la ré-ouverture de la base il va bien falloir relire la donnée sinon il sera impossible d’ouvrir la base ? Testons :

 

$ srvctl start instance -d ARKONA -i ARKONA1
$ sqlplus system/xxx
SQL> INSERT INTO crypt (id, data) VALUES (1, 'TOP SECRET!');
SQL> commit;
SQL> conn / as sysdba
SQL> shutdown abort
SQL> exit

$ srvctl start database -d ARKONA

PRCR-1079 : Failed to start resource ora.arkona.db
CRS-5017: The resource action "ora.arkona.db start" encountered the following error:
ORA-28365: wallet is not open
. For details refer to "(:CLSN00107:)" in "/oracle/11.2.0.3/grid/log/racdb1/agent/crsd/oraagent_oracle/oraagent_oracle.log".

CRS-2674: Start of 'ora.arkona.db' on 'racdb1' failed
CRS-2632: There are no more servers to try to place resource 'ora.arkona.db' on that would satisfy its placement policy
CRS-5017: The resource action "ora.arkona.db start" encountered the following error:
ORA-28365: wallet is not open
. For details refer to "(:CLSN00107:)" in "/oracle/11.2.0.3/grid/log/racdb2/agent/crsd/oraagent_oracle/oraagent_oracle.log".

CRS-2674: Start of 'ora.arkona.db' on 'racdb2' failed

Mince! Pourquoi! Comme souvent, une indication apparait dans l’alert.log:

This instance was first to open
Beginning crash recovery of 1 threads
Started redo scan
Completed redo scan
read 87 KB redo, 81 data blocks need recovery
Started redo application at
Thread 1: logseq 85, block 3
Recovery of Online Redo Log: Thread 1 Group 1 Seq 85 Reading mem 0
  Mem# 0: +DATA1/arkona/onlinelog/group_1.257.806278453
  Mem# 1: +DATA2/arkona/onlinelog/group_1.257.806278455
kcbztek_get_tbskey: decrypting encrypted key for tablespace 0 without opening the wallet
Abort recovery for domain 0
Aborting crash recovery due to error 28365
Errors in file /oracle/oraBase/diag/rdbms/arkona/ARKONA1/trace/ARKONA1_ora_8376.trc:
ORA-28365: wallet is not open
Abort recovery for domain 0
Errors in file /oracle/oraBase/diag/rdbms/arkona/ARKONA1/trace/ARKONA1_ora_8376.trc:
ORA-28365: wallet is not open

L’instance, comme après chaque crash, a besoin de faire un « auto recover » et donc de rejouer les dernières  transactions, mais dans notre cas certaines données sont cryptées dans les redologs. Oui mais pour pouvoir les lire (les données), il faut pouvoir lire la clef et donc avoir ouvert le wallet ce qui signifie que la base doit être au moins en mount pour pouvoir passer la commande « alter system set wallet open » . Ensuite la base pourra faire son « auto recover » juste avant le « open » :

SQL> startup mount
SQL> ALTER SYSTEM SET WALLET OPEN IDENTIFIED BY "MotDePasse";
SQL> alter database open;

Donc en cas de crash du serveur par exemple, au reboot la base ne redémarrera pas. Il faudra dans notre cas une intervention manuelle. Je dis bien dans notre cas, car il est possible de mettre le wallet en auto-open (moyen niveau sécurité) ou bien de configurer le wallet dans le cluster (apparemment possible à partir de la 12c mais pas sur notre banc en 11g)…

Et les perfs ?

 

réponse ici : TDE (Part II) : Performance et Volumétrie

 

Key Rekey Rerekey patati

 

réponse ici : TDE (Part III) : Les clefs du chiffrages

 

Restauration

 

Ben cela sera dans un futur article

 

Jeter son portefeuille

 

réponse ici : TDE (Part III) : Les clefs du chiffrages

 

Ajouter un Commentaire


Code de sécurité
Rafraîchir