AWS re:Postを使用することにより、以下に同意したことになります AWS re:Post 利用規約

Amazon RDS Oracle ウォレットの CA 証明書バンドルを使用して SSL/TLS エンドポイントに接続するにはどうすればよいですか?

所要時間8分
0

Oracle ウォレットを使用して Oracle DB インスタンスの Amazon Relational Database Service (Amazon RDS) から外部の SSL/TLS エンドポイントと安全に通信したいと考えています。

解決策

**注:**AWS コマンドラインインターフェイス (AWS CLI) コマンドの実行中にエラーが発生した場合は、「AWS CLI エラーのトラブルシューティング」を参照してください。また、AWS CLI の最新バージョンを使用しているようにしてください。

ターゲット SSL/TLS エンドポイントのルート証明書と中間証明書をダウンロードする

  1. ウェブブラウザで、アクセスしたい URL (Web サービスの SSL/TLS エンドポイント) を開きます。

  2. ブラウザのアドレスバーに証明書の詳細を表示するには、南京錠マークを選択します。または、ローカルワークステーションのコマンドラインで次のようなコマンドを実行します。

    注: status.aws.amazon.com は、アクセスする URL に置き換えてください。

    $ 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. 証明書プロバイダーから、一覧表示された関連するルート証明書と中間証明書をダウンロードします。この例では、スタックトレースで、Amazon Root CA 1Amazon RSA 2048 M01 の証明書が必要であることが示されています。Amazon Trust Services リポジトリから証明書をダウンロードします。

  4. 証明書を pem 形式でダウンロードできない場合は、DER/CRT 形式で証明書をダウンロードします。ダウンロードした証明書を PEM 形式に変換するには、ローカルワークステーションのコマンドラインで次のようなコマンドを実行します。

    $ 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"

Oracle ウォレットを作成してから、SSL/TLS エンドポイントのルート証明書と中間証明書をロードする

  1. orapki ユーティリティを使用して Oracle ウォレットを作成します。orapki ユーティリティは、Oracle クライアントソフトウェアをインストールするときに使用できます。Oracle JDeveloper Studio エディションには orapki ユーティリティも含まれています。ソースデータベース環境でウォレットを作成する必要があります。

  2. ウォレットの作成時に、いくつか選択できるパラメーターがあります。例えば、auto_login_only を使用すると、開くためにパスワードを必要としない自動ログインウォレット (cwallet.sso) を作成できます。

  3. ウォレットを作成するディレクトリに移動します。その後、ローカルワークステーションのコマンドラインで次のコマンドを実行します。

    cd /app/client/wallet>
    orapki wallet create -wallet . -auto_login_only
  4. 次の 2 つの証明書をウォレットに追加します。

    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. ウォレットの内容を確認し、証明書を追加したことを確認します。

    >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

S3 バケットにウォレットをアップロードする

新しい Amazon Simple Storage Service (Amazon S3) バケットを作成するか、既存のバケットを使用してウォレットをアップロードします。AWS CLI を使用する場合は、Oracle ウォレットを作成したクライアントマシンで次のコマンドを実行します。または、Amazon S3 コンソールからウォレットをアップロードします。

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

注: wallet4321 は、該当する S3 バケットの名前に置き換えてください。

データベースユーザーと権限の設定

  1. SQL\ *Plus をプライマリユーザーとして使用して RDS for Oracle DB インスタンスに接続します。

  2. 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.

    注: app_user は、UTL_HTTP コマンドを実行できるようにする RDS データベースユーザーの名前に置き換えてください。

  3. ウォレット用のディレクトリを作成します。

    注: 各ウォレットを独自のディレクトリに保存するのがベストプラクティスです。

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

S3 バケットから RDS DB インスタンスにウォレットをダウンロードする

注: このステップは、Amazon S3 統合の有無にかかわらず完了できます。

**Amazon S3 統合を使用する **

  1. Amazon S3 統合を使用して、S3 バケットから DB インスタンスにウォレットをダウンロードします。

  2. S3 バケットからウォレットファイルをダウンロードするには、DB インスタンスに接続されている SQL*Plus セッションで次のコマンドを実行します。

    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. 結果を表示するには、前のステップの task-id を使用してタスクの出力ファイルを表示します。

    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. ウォレットが DB インスタンスにダウンロードされたことを確認します。

    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. 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. Web サービスホストの DNS 名前解決を確認します。

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

    Oracle ウォレットを使用してリモート Web サービス URL を参照します。

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

**S3 統合なし **

  1. Oracle の ACL でアウトバウンドトラフィックを許可するには、DB インスタンスに接続されている SQL*Plus セッションで次のコマンドを実行します。

    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. DB インスタンスに接続されている SQL*Plus セッションで次のプロシージャを作成します。

    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. 署名付き URL を生成するには、AWS CLI を使用して次のコマンドを実行します。署名付き URL は、デフォルトで 1 時間有効です。

    >aws s3 presign s3://wallet4321/cwallet.sso
    
    https://wallet4321.s3.amazonaws.com/cwallet.sso?AWSAccessKeyId=AKIAJWTPIJJA4FAQURFA&Signature=u8ysKQyp4O6ws3Qy5qZak8PfmLE%3D&Expires=1588199836
  4. S3 バケットからウォレットをダウンロードするには、DB インスタンスに接続されている SQL*Plus セッションで s3_download_presigned_url プロシージャを実行します。s3_download_presigned_url プロシージャを実行する前に、次の入力パラメータを更新します。

    p_s3 url - 生成した署名付き URL を入力します

    p_local_filename - ウォレットファイルの名前を入力します

    p_local_directory - ウォレットを保存するために DB インスタンスに作成したディレクトリの名前を入力します

    p_wallet_directory - S3_SSL_WALLET と入力します。DB インスタンスは、このディレクトリを使用して Amazon S3 ウェブサービス証明書を含んでいるウォレットを保存します。

    次のコマンドの例では、HTTP を使用して S3 ウェブサービスにアクセスします。コマンドを実行する前に、署名付き URL の httpshttp に置き換えてください。

    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;
    /

    次のコマンドの例では、HTTP を使用して Amazon S3 ウェブサービスにアクセスします。

    注: HTTPS を使用するには、Amazon S3 ウェブサービスウォレットを DB インスタンスディレクトリ 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. ウォレットが RDS for Oracle DB インスタンスにダウンロードされたことを確認します。

    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. 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. Web サービスホストの DNS 名前解決を確認します。

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

    Oracle ウォレットを使用してリモート Web サービス URL を参照します。

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

よくあるエラー

ORA-28759: failure to open file

このエラーが表示されるのは、参照しているウォレットが指定した場所にない場合です。ディレクトリをリストして、ウォレットファイルの場所を確認してください。

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

ORA-28768: bad magic number

このエラーが表示されるのは、S3 バケットとそのコンテンツが AWS Key Management Service (AWS KMS) で暗号化されている場合です。バケットオブジェクトの暗号化を解除してください。

ORA-12535: TNS: operation timed out

このエラーが表示される原因としては、インスタンスがプライベートサブネットにあることや、ルートテーブルにインターネットへのルートがないことが考えられます。

コメントはありません