Amazon RDS Oracle 지갑의 CA 인증서 번들을 사용하여 SSL/TLS 엔드포인트에 연결하려면 어떻게 해야 하나요?

9분 분량
0

Oracle 지갑이 있는 Oracle DB 인스턴스에 대해 Amazon Relational Database Service(Amazon RDS)에서 외부 SSL/TLS 엔드포인트와 안전하게 통신하고 싶습니다.

해결 방법

참고: AWS Command Line Interface(AWS CLI) 명령 실행 시 오류가 발생하는 경우, AWS CLI 오류 문제 해결을 참고하세요. 또한 최신 AWS CLI 버전을 사용하고 있는지 확인하세요.

대상 SSL/TLS 엔드포인트 루트 및 중간 인증서를 다운로드합니다.

  1. 웹 브라우저에서 액세스하려는 URL (웹 서비스의 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 지갑을 만듭니다. Oracle 클라이언트 소프트웨어를 설치할 때 orapki 유틸리티를 사용할 수 있습니다. Oracle JDeveloper Studio 에디션에도 orapki 유틸리티가 포함되어 있습니다. 소스 데이터베이스 환경에서 지갑을 생성해야 합니다.

  2. 지갑을 만들 때 선택할 수 있는 몇 가지 매개 변수가 있습니다. 예를 들어 auto_login_only를 사용하여 비밀번호 없이도 열 수 있는 자동 로그인 지갑(cwallet.sso)을 만들 수 있습니다.

  3. 지갑을 만들려는 디렉토리로 이동합니다. 그런 다음 로컬 워크스테이션의 명령줄에서 다음 명령을 실행합니다.

    cd /app/client/wallet>
    orapki wallet create -wallet . -auto_login_only
  4. 두 개의 인증서를 지갑에 추가합니다.

    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. URL_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. 웹 서비스 호스트 DNS 이름 확인을 확인합니다.

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

    Oracle 지갑을 사용하여 원격 웹 서비스 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;
    /

    HTTPS를 사용하여 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. 웹 서비스 호스트 DNS 이름 확인을 확인합니다.

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

    Oracle 지갑을 사용하여 원격 웹 서비스 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: 파일을 열지 못했습니다.

참조하는 지갑이 지정한 위치에 있지 않은 경우 이 오류가 발생합니다. 디렉터리를 나열하여 지갑 파일의 위치를 확인하세요.

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

ORA-28768: 잘못된 매직 넘버

S3 버킷과 그 콘텐츠가 AWS Key Management Service(AWS KMS)로 암호화된 경우 이 오류가 표시됩니다. 버킷 객체의 암호화를 제거하세요.

ORA-12535: 버킷 개체의 암호화를 제거하세요.

인스턴스가 사설 서브넷에 있기 때문에 이 오류가 발생할 수 있습니다. 또는 라우트 테이블에 인터넷으로 나가는 경로가 없습니다.