如何使用 Amazon RDS Oracle 钱包中的 CA 证书包连接到 SSL/TLS 端点?
我想从我的 Amazon Relational Database Service(Amazon RDS)安全地与外部 SSL/TLS 端点进行通信,以获得具有 Oracle 钱包的Oracle 数据库实例。
解决方案
**注意:**如果在运行 AWS 命令行界面(AWS CLI)命令时收到错误,请参阅 Troubleshoot AWS CLI errors。此外,确保您使用的是最新版本的 AWS CLI。
下载目标 SSL/TLS 端点根证书和中间证书
-
在 Web 浏览器中,打开要访问的 URL(Web 服务的 SSL/TLS 端点)。
-
若要在浏览器的地址栏中查看证书详细信息,请选择挂锁符号。或者,在本地工作站的命令行上运行类似于以下内容的命令:
**注意:**将 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
-
下载证书提供商中列出的相关根证书和中间证书。在此示例中,堆栈跟踪表明您需要证书 Amazon Root CA 1 和 Amazon RSA 2048 M01。从 Amazon Trust Services 存储库下载证书。
-
如果证书不能以 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 端点根证书与中间证书
-
使用 orapki 实用程序来创建 Oracle 钱包。当您安装 Oracle 客户端软件时,orapki 实用程序可用。Oracle JDeveloper Studio 版本还包括 orapki 实用程序。必须在源数据库环境中创建钱包。
-
创建钱包时,有几个参数可供选择。例如,使用 auto_login_only 来创建不需要密码即可打开的自动登录钱包(cwallet.sso)。
-
导航到要在其中创建钱包的目录。然后,在本地工作站的命令行上运行下面的命令:
cd /app/client/wallet> orapki wallet create -wallet . -auto_login_only
-
向钱包添加两个证书:
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
-
验证钱包内容,然后确认您已添加证书:
>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 存储桶的名称。
配置数据库用户和权限
-
使用 SQL*Plus 作为主要用户来连接到 RDS for Oracle 数据库实例。
-
向您希望能够使用 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 数据库用户的名称。
-
为钱包创建一个目录:
**注意:**最好将每个钱包存储在自己的目录中。
SQL> exec rdsadmin.rdsadmin_util.create_directory('WALLET');
将钱包从 S3 存储桶下载到 RDS 数据库实例
**注意:**可以在有或没有 Amazon S3 集成的情况下完成此步骤。
使用 Amazon S3 集成
-
使用 Amazon S3 集成将钱包从 S3 存储桶下载到数据库实例。
-
要从 S3 存储桶下载钱包文件,请在连接到数据库实例的 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
-
要查看结果,请使用上一步中的 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.
-
验证钱包是否已下载到数据库实例:
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
-
设置 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.
-
验证 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 集成
-
要允许 Oracle 的 ACL 上的出站流量,请在连接到数据库实例的 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.
-
在连接到数据库实例的 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;
-
要生成预签名 URL,请使用 AWS CLI 运行下面的命令。默认情况下,预签名 URL 的有效期为一小时。
>aws s3 presign s3://wallet4321/cwallet.sso https://wallet4321.s3.amazonaws.com/cwallet.sso?AWSAccessKeyId=AKIAJWTPIJJA4FAQURFA&Signature=u8ysKQyp4O6ws3Qy5qZak8PfmLE%3D&Expires=1588199836
-
要从 S3 存储桶下载钱包,请在连接到数据库实例的 SQL*Plus 会话中运行 s3_download_presigned_url 过程。在运行 s3_download_presigned_url 过程之前,更新下面的输入参数:
p_s3 url - 输入您生成的预签名 URL
p_local_filename - 输入钱包文件的名称
p_local_directory - 输入您在数据库实例上创建的用于存储钱包的目录的名称
p_wallet_directory - 输入 S3_SSL_WALLET。数据库实例使用此目录来存储包含 Amazon S3 Web 服务证书的钱包。
请参阅下面使用 HTTP 访问 S3 Web 服务的示例命令。在运行该命令之前,请将预签名 URL 中的 https 替换为 http:
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 Web 服务的示例命令。
**注意:**要使用 HTTPS,必须将 Amazon S3 Web 服务钱包存储在数据库实例目录 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; /
-
验证钱包是否已下载到 RDS for 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
-
设置 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.
-
验证 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:无法打开文件
如果所引用的钱包不在指定的位置,则会收到此错误。请列出目录以确认钱包文件的位置:
SQL> select directory_name, directory_path from dba_directories where directory_name = 'WALLET'; DIRECTORY_NAME DIRECTORY_PATH -------------------------------------------------------------------------------- WALLET /rdsdbdata/userdirs/01
ORA-28768:错误的幻数
如果使用 AWS Key Management Service(AWS KMS)对 S3 存储桶及其内容进行加密,则会收到此错误。移除存储桶对象上的加密。
ORA-12535: TNS:操作超时
由于实例位于私有子网中,您可能会收到此错误。或者,路由表没有通往互联网的路由。
相关内容
- AWS 官方已更新 1 年前
- AWS 官方已更新 1 年前
- AWS 官方已更新 2 年前
- AWS 官方已更新 10 个月前