Comment me connecter à un point de terminaison SSL/TLS à l’aide du bundle de certificats CA dans un portefeuille Oracle Amazon RDS ?

Lecture de 12 minute(s)
0

Je souhaite communiquer en toute sécurité avec des points de terminaison SSL/TLS externes depuis mon Amazon Relational Database Service (Amazon RDS) pour une instance de base de données Oracle dotée d'un portefeuille Oracle.

Résolution

Remarque : si des erreurs surviennent lorsque vous exécutez des commandes de l’interface de la ligne de commande AWS (AWS CLI), consultez la page Résoudre les erreurs liées à AWS CLI. Vérifiez également que vous utilisez bien la version la plus récente de l’AWS CLI.

Téléchargez les certificats racine et intermédiaire du point de terminaison SSL/TLS cible

  1. Dans votre navigateur Web, ouvrez l’URL (point de terminaison SSL/TLS du service Web) à laquelle vous souhaitez accéder.

  2. Pour afficher les détails du certificat dans la barre d’adresse de votre navigateur, cliquez sur le symbole du cadenas. Vous pouvez également exécuter une commande similaire à la suivante sur la ligne de commande de votre poste de travail local :

    Remarque : Remplacez status.aws.amazon.com par l'URL à laquelle vous souhaitez accéder.

    $ openssl s_client -connect status.aws.amazon.com:443
    CONNECTED(00000003)
    depth=2 C = US, O = Amazon, CN = Amazon Root CA 1
    verify return:1
    depth=1 C = US, O = Amazon, CN = Amazon RSA 2048 M01
    verify return:1
    depth=0 CN = status.aws.amazon.com
    verify return:1
    ---
    Certificate chain
     0 s:CN = status.aws.amazon.com
       i:C = US, O = Amazon, CN = Amazon RSA 2048 M01
     1 s:C = US, O = Amazon, CN = Amazon RSA 2048 M01
       i:C = US, O = Amazon, CN = Amazon Root CA 1
     2 s:C = US, O = Amazon, CN = Amazon Root CA 1
       i:C = US, ST = Arizona, L = Scottsdale, O = "Starfield Technologies, Inc.", CN = Starfield Services Root Certificate Authority - G2
     3 s:C = US, ST = Arizona, L = Scottsdale, O = "Starfield Technologies, Inc.", CN = Starfield Services Root Certificate Authority - G2
       i:C = US, O = "Starfield Technologies, Inc.", OU = Starfield Class 2 Certification Authority
  3. Téléchargez les certificats racine et intermédiaires correspondants répertoriés auprès du fournisseur de certificats. Dans cet exemple, le stack trace indique que vous avez besoin des certificats Amazon Root CA 1 et Amazon RSA 2048 M01. Téléchargez les certificats depuis le référentiel Amazon Trust Services.

  4. Si le certificat n’est pas disponible au format pem, téléchargez-le au format DER/CRT. Pour convertir le certificat téléchargé au format pem, exécutez des commandes similaires aux suivantes sur la ligne de commande de votre poste de travail local :

    $ openssl x509 -inform der -in "Amazon Root CA 1.der" -outform pem -out "Amazon Root CA 1.pem"
    $ openssl x509 -inform der -in "Amazon RSA 2048 M01.der" -outform pem -out "Amazon RSA 2048 M01.pem"

Créez le portefeuille Oracle, puis chargez les certificats racine et intermédiaire du point de terminaison SSL/TLS

  1. Utilisez l'utilitaire orapki pour créer un portefeuille Oracle. L'utilitaire orapki est disponible lorsque vous installez le logiciel client Oracle. L'édition Oracle JDeveloper Studio inclut également l’utilitaire orapki. Vous devez créer le portefeuille dans l’environnement de base de données source.

  2. Vous pouvez choisir parmi plusieurs paramètres lorsque vous créez le portefeuille. Par exemple, utilisez auto_login_only pour créer un portefeuille à connexion automatique (cwallet.sso) qui n’a pas besoin de mot de passe pour s’ouvrir.

  3. Accédez au répertoire dans lequel vous souhaitez créer le portefeuille. Exécutez ensuite la commande suivante sur la ligne de commande de votre poste de travail local :

    cd /app/client/wallet>
    orapki wallet create -wallet . -auto_login_only
  4. Ajoutez les deux certificats au portefeuille :

    orapki wallet add -wallet . -trusted_cert -cert "Amazon Root CA 1.pem" -auto_login_only
    orapki wallet add -wallet . -trusted_cert -cert "Amazon RSA 2048 M01.pem" -auto_login_only
  5. Vérifiez le contenu du portefeuille, puis confirmez que vous avez ajouté les certificats :

    >ls -ltrh cwallet.sso
    -rw------- 1 oracle oinstall 2.3K Aug 13 11:39 cwallet.sso
    
    >orapki wallet display -wallet .Oracle PKI Tool Release 19.0.0.0.0 - Production
    Version 19.3.0.0.0
    Copyright (c) 2004, 2019, Oracle and/or its affiliates. All rights reserved.
    
    Requested Certificates:
    User Certificates:
    Trusted Certificates:
    Subject:        CN=Amazon RSA 2048 M01,O=Amazon,C=US
    Subject:        CN=Amazon Root CA 1,O=Amazon,C=US

Téléchargez le portefeuille dans un compartiment S3

Créez un nouveau compartiment Amazon Simple Storage Service (Amazon S3) ou utilisez un compartiment existant, puis chargez le portefeuille. Si vous utilisez l’interface de ligne de commande AWS, exécutez la commande suivante sur la machine cliente sur laquelle vous avez créé le portefeuille Oracle. Vous pouvez également charger le portefeuille depuis la console Amazon S3.

aws s3 cp cwallet.sso s3://wallet4321/

Remarque : Remplacez wallet4321 par le nom de votre compartiment S3.

Configurer l’utilisateur et les autorisations de la base de données

  1. Utilisez SQL*Plus en tant qu’utilisateur principal pour vous connecter à l'instance de base de données RDS pour Oracle.

  2. Accordez les privilèges nécessaires à l’utilisateur de la base de données pour lequel vous souhaitez pouvoir utiliser le package UTL_HTTP :

    SQL> define user='
    ';
    SQL>  BEGIN rdsadmin.rdsadmin_util.grant_sys_object('DBA_DIRECTORIES', UPPER('&user')); END;
      2  /
    old   1:  BEGIN rdsadmin.rdsadmin_util.grant_sys_object('DBA_DIRECTORIES', UPPER('&user')); END;
    new   1:  BEGIN rdsadmin.rdsadmin_util.grant_sys_object('DBA_DIRECTORIES', UPPER('app_user')); END;
    
    PL/SQL procedure successfully completed.
    
    SQL> BEGIN rdsadmin.rdsadmin_util.grant_sys_object('UTL_HTTP', UPPER('&user')); END;
      2  /
    old   1: BEGIN rdsadmin.rdsadmin_util.grant_sys_object('UTL_HTTP', UPPER('&user')); END;
    new   1: BEGIN rdsadmin.rdsadmin_util.grant_sys_object('UTL_HTTP', UPPER('app_user')); END;
    
    PL/SQL procedure successfully completed.
    
    SQL> BEGIN rdsadmin.rdsadmin_util.grant_sys_object('UTL_FILE', UPPER('&user')); END;
      2  /
    old   1: BEGIN rdsadmin.rdsadmin_util.grant_sys_object('UTL_FILE', UPPER('&user')); END;
    new   1: BEGIN rdsadmin.rdsadmin_util.grant_sys_object('UTL_FILE', UPPER('app_user')); END;
    
    PL/SQL procedure successfully completed.

    Remarque : Remplacez app_user par le nom de l'utilisateur de la base de données RDS pour lequel vous souhaitez pouvoir exécuter les commandes UTL_HTTP.

  3. Créez un répertoire pour le portefeuille :

    Remarque : il est recommandé de stocker chaque portefeuille dans son propre répertoire.

    SQL> exec rdsadmin.rdsadmin_util.create_directory('WALLET');

Téléchargez le portefeuille depuis le compartiment S3 vers l’instance de base de données RDS

Remarque : vous pouvez effectuer cette étape avec ou sans l’intégration Amazon S3.

Utiliser l’intégration Amazon S3

  1. Utilisez l'intégration Amazon S3 pour télécharger le portefeuille depuis un compartiment S3 vers votre instance de base de données.

  2. Pour télécharger le fichier de portefeuille depuis le compartiment S3, exécutez la commande suivante dans la session SQL*Plus connectée à votre instance de base de données.

    SQL> SELECT rdsadmin.rdsadmin_s3_tasks.download_from_s3(
              p_bucket_name    =>  'wallet4321',
              p_s3_prefix => 'cwallet.sso',
              p_directory_name =>  'WALLET')
              AS TASK_ID FROM DUAL;   
    OUTPUT
    1691935899410-1902
  3. Pour afficher les résultats, utilisez le task-id de l’étape précédente pour afficher le fichier de sortie de la tâche.

    SQL> SELECT text FROM table(rdsadmin.rds_file_util.read_text_file('BDUMP','dbtask-1691935899410-1902.log'));
    OUTPUT
    2023-08-13 14:11:39.497 UTC [INFO ] This task is about to list the Amazon S3 objects for AWS Region us-east-1, bucket name wallet4321, and prefix cwallet.sso.
    2023-08-13 14:11:39.552 UTC [INFO ] The task successfully listed the Amazon S3 objects for AWS Region us-east-1, bucket name wallet4321, and prefix cwallet.sso.
    2023-08-13 14:11:39.568 UTC [INFO ] This task is about to download the Amazon S3 object or objects in /rdsdbdata/userdirs/01 from bucket name wallet4321 and key cwallet.sso.
    2023-08-13 14:11:39.719 UTC [INFO ] The task successfully downloaded the Amazon S3 object or objects from bucket name wallet4321 with key cwallet.sso to the location /rdsdbdata/userdirs/01.
    2023-08-13 14:11:39.720 UTC [INFO ] The task finished successfully.
  4. Vérifiez que le portefeuille a été téléchargé sur votre instance de base de données :

    SQL> select * from table (rdsadmin.rds_file_util.listdir(p_directory => 'WALLET'));
    FILENAME            TYPE         FILESIZE MTIME               
    ------------------- ---------- ---------- --------------------
    01/                 directory        4096 13-AUG-2023 14:11:39
    cwallet.sso         file             2349 13-AUG-2023 14:11:39
  5. Définissez le chemin du portefeuille pour les transactions UTL_HTTP :

    SQL>  DECLAREl_wallet_path all_directories.directory_path%type;
    BEGIN
    select directory_path into l_wallet_path from all_directories
    where upper(directory_name)='WALLET';
    utl_http.set_wallet('file:/' || l_wallet_path);
    END;
    /
    PL/SQL procedure successfully completed.
  6. Vérifiez la résolution du nom DNS de l'hôte du service Web :

    SQL> SELECT UTL\_INADDR.GET\_HOST\_ADDRESS(host => 'status.aws.amazon.com') FROM DUAL

    Utilisez le portefeuille Oracle pour parcourir l’URL du service Web distant :

    SQL> SELECT utl_http.request('https://status.aws.amazon.com/robots.txt') AS ROBOTS_TXT FROM DUAL;
    ROBOTS_TXT
    --------------------------------------------------------------------------------
    {"message":"Not Found"}

Sans intégration S3

  1. Pour autoriser le trafic sortant sur l’ACL d’Oracle, exécutez la commande suivante dans la session SQL*Plus connectée à votre instance de base de données :

    SQL> define user='app_user';
    SQL> BEGIN DBMS_NETWORK_ACL_ADMIN.CREATE_ACL
         ( acl => 's3.xml', description => 'AWS S3 ACL', principal => UPPER('&user'), is_grant => TRUE, privilege => 'connect');
         COMMIT;
         END;
         /
    old   3: ( acl => 's3.xml', description => 'AWS S3 ACL', principal => UPPER('&user'), is_grant => TRUE, privilege => 'connect');
    new   3: ( acl => 's3.xml', description => 'AWS S3 ACL', principal => UPPER('app_user'), is_grant => TRUE, privilege => 'connect');
    
    PL/SQL procedure successfully completed.
    
    SQL> BEGIN DBMS_NETWORK_ACL_ADMIN.ASSIGN_ACL ( acl => 's3.xml', host => '*.amazonaws.com');
         COMMIT;
         END;
         /
    PL/SQL procedure successfully completed.
  2. Créez la procédure suivante dans la session SQL*Plus connectée à votre instance de base de données :

    SQL> CREATE OR REPLACE PROCEDURE s3_download_presigned_url (
            p_s3_url IN VARCHAR2,
            p_local_filename IN VARCHAR2,
            p_local_directory IN VARCHAR2,
            p_wallet_directory IN VARCHAR2 DEFAULT NULL
        ) AS
    -- Local variables
        l_req utl_http.req;
        l_wallet_path VARCHAR2(4000);
        l_fh utl_file.file_type;
        l_resp utl_http.resp;
        l_data raw(32767);
        l_file_size NUMBER;
        l_file_exists BOOLEAN;
        l_block_size BINARY_INTEGER;
        l_http_status NUMBER;
    -- User-defined exceptions
        e_https_requires_wallet EXCEPTION;
        e_wallet_dir_invalid EXCEPTION;
        e_http_exception EXCEPTION;
    BEGIN
        -- Validate input
        IF (regexp_like(p_s3_url, '^https:', 'i') AND
            p_wallet_directory IS NULL) THEN
            raise e_https_requires_wallet;
        END IF;
        -- Use wallet, if specified
        IF (p_wallet_directory IS NOT NULL) THEN
            BEGIN
                       SELECT directory_path INTO l_wallet_path
                       FROM dba_directories
                       WHERE upper(directory_name)= upper(p_wallet_directory);
                       utl_http.set_wallet('file:' || l_wallet_path);
            EXCEPTION
                WHEN NO_DATA_FOUND
                    THEN raise e_wallet_dir_invalid;
            END;
        END IF;
    
        -- Do HTTP request
        BEGIN
            l_req := utl_http.begin_request(p_s3_url, 'GET', 'HTTP/1.1');
                    l_fh := utl_file.fopen(p_local_directory, p_local_filename, 'wb', 32767);
            l_resp := utl_http.get_response(l_req);
            -- If we get HTTP error code, write that instead
            l_http_status := l_resp.status_code;
            IF (l_http_status != 200) THEN
                dbms_output.put_line('WARNING: HTTP response '
                    || l_http_status
                    || ' - ' || l_resp.reason_phrase
                    || '. Details in ' || p_local_filename
                );
            END IF;
    
            -- Loop over response and write to file
            BEGIN
                LOOP
                    utl_http.read_raw(l_resp, l_data, 32766);
                    utl_file.put_raw(l_fh, l_data, true);
                END LOOP;
            EXCEPTION
                WHEN utl_http.end_of_body THEN
    
                    utl_http.end_response(l_resp);
            END;
    
            -- Get file attributes to see what we did
            utl_file.fgetattr(
                location => p_local_directory,
                filename => p_local_filename,
                fexists => l_file_exists,
                file_length => l_file_size,
                block_size => l_block_size
            );
    
            utl_file.fclose(l_fh);
            dbms_output.put_line('wrote ' || l_file_size || ' bytes');
            EXCEPTION
                WHEN OTHERS THEN
                    utl_http.end_response(l_resp);
                    utl_file.fclose(l_fh);
                    dbms_output.put_line(dbms_utility.format_error_stack());
                    dbms_output.put_line(dbms_utility.format_error_backtrace());
                    raise;
        END;
    EXCEPTION
    
        WHEN e_https_requires_wallet THEN
            dbms_output.put_line('ERROR: HTTPS requires a valid wallet location');
        WHEN e_wallet_dir_invalid THEN
            dbms_output.put_line('ERROR: wallet directory not found');
        WHEN others THEN
            raise;
    END s3_download_presigned_url;
  3. Pour générer une URL présignée, utilisez l’interface de ligne de commande AWS pour exécuter la commande suivante. L’URL présignée est valide pendant une heure, par défaut.

    >aws s3 presign s3://wallet4321/cwallet.sso
    
    https://wallet4321.s3.amazonaws.com/cwallet.sso?AWSAccessKeyId=AKIAJWTPIJJA4FAQURFA&Signature=u8ysKQyp4O6ws3Qy5qZak8PfmLE%3D&Expires=1588199836
  4. Pour télécharger le portefeuille depuis le compartiment S3, exécutez la procédure s3_download_presigned_url dans la session SQL*Plus connectée à votre instance de base de données. Mettez à jour les paramètres d’entrée suivants avant d’exécuter la procédure s3_download_presigned_url :

    p_s3 url - Entrez l'URL présignée que vous avez générée

    p_local_filename - Entrez le nom du fichier du portefeuille

    p_local_directory - Entrez le nom du répertoire que vous avez créé sur votre instance de base de données pour stocker le portefeuille

    p_wallet_directory - Entez S3_SSL_WALLET . L’instance de base de données utilise ce répertoire pour stocker le portefeuille contenant les certificats de service Web Amazon S3.

    Consultez l’exemple de commande suivant qui utilise HTTP pour accéder au service Web S3. Remplacez https par http dans l’URL présignée avant d’exécuter la commande :

    SQL> SET SERVEROUTPUT ON;
    SQL> set define #;
    SQL> BEGIN s3_download_presigned_url(
     p_s3_url=> 'http://wallet4321.s3.amazonaws.com/cwallet.sso?AWSAccessKeyId=AKIAJWTPIJJA4FAQURFA&Signature=u8ysKQyp4O6ws3Qy5qZak8PfmLE%3D&Expires=1588199836',
     p_local_filename => 'cwallet.sso',
     p_local_directory => 'WALLET'
    );
    END;
    /

    Consultez l’exemple de commande suivant qui utilise le protocole HTTPS pour accéder au service Web Amazon S3.

    Remarque : pour utiliser le protocole HTTPS, vous devez stocker le portefeuille du service Web Amazon S3 dans le répertoire de l'instance de base de données S3_SSL_WALLET.

    SQL> exec rdsadmin.rdsadmin_util.create_directory('S3_SSL_WALLET');
    SQL> SET SERVEROUTPUT ON;
    SQL> set define #;
    SQL> BEGIN s3_download_presigned_url(
          p_s3_url=> 'https://wallet4321.s3.amazonaws.com/cwallet.sso?AWSAccessKeyId=AKIAJWTPIJJA4FAQURFA&Signature=u8ysKQyp4O6ws3Qy5qZak8PfmLE%3D&Expires=1588199836',
          p_local_filename => 'cwallet.sso',
          p_local_directory => 'WALLET',
          p_wallet_directory => 'S3_SSL_WALLET'
         );
         END;
        /
  5. Vérifiez que le portefeuille a été téléchargé sur l’instance de base de données RDS pour Oracle :

    SQL> select * from table (rdsadmin.rds_file_util.listdir(p_directory => 'WALLET'));
    FILENAME            TYPE         FILESIZE MTIME               
    ------------------- ---------- ---------- --------------------
    01/                 directory        4096 13-AUG-2023 15:15:39
    cwallet.sso         file             2349 13-AUG-2023 15:15:39
  6. Définissez le chemin du portefeuille pour les transactions url_http :

    SQL>  DECLARE
    l_wallet_path all_directories.directory_path%type;
    BEGIN
    select directory_path into l_wallet_path from all_directories
    where upper(directory_name)='WALLET';
    utl_http.set_wallet('file:/' || l_wallet_path);
    END;
    /
    PL/SQL procedure successfully completed.
  7. Vérifiez la résolution du nom DNS de l'hôte du service Web :

    SQL> SELECT UTL_INADDR.GET_HOST_ADDRESS(host => 'status.aws.amazon.com') FROM DUAL

    Utilisez le portefeuille Oracle pour parcourir l’URL du service Web distant :

    SQL> SELECT utl_http.request('https://status.aws.amazon.com/robots.txt') AS ROBOTS_TXT FROM DUAL;ROBOTS_TXT
    --------------------------------------------------------------------------------
    User-agent: *
    Allow: /

Erreurs courantes

ORA-28759 : échec de l’ouverture du fichier

Cette erreur s’affiche si le portefeuille auquel vous faites référence ne se trouve pas à l’emplacement que vous avez indiqué. Listez les répertoires pour confirmer l’emplacement du fichier portefeuille :

SQL> select directory_name, directory_path from dba_directories where directory_name = 'WALLET';
DIRECTORY_NAME               DIRECTORY_PATH
--------------------------------------------------------------------------------
WALLET                       /rdsdbdata/userdirs/01

ORA-28768 : mauvais numéro magique

Cette erreur s’affiche si le compartiment S3 et son contenu sont chiffrés avec AWS Key Management Service (AWS KMS). Supprimez le chiffrement des objets du compartiment.

ORA-12535 : TNS : l’opération a expiré

Cette erreur peut s’afficher car l'instance se trouve dans un sous-réseau privé. Ou bien, la table de routage ne propose aucune route vers Internet.