使用客户管理的 Wallet 进行外部调用

当自治 AI 数据库需要通过 HTTP/HTTPS 访问互联网上的数据时,可以使用 UTL_HTTP 程序包。通过 UTL_HTTP 程序包,可以直接从 SQL 和 PL/SQL 进行 HTTP 标注。

如果您要调用 HTTPS 端点,则必须配置 Oracle Wallet 。自治 AI 数据库需要一个 wallet,其中包含您的数据库将连接到的任何 HTTPS 端点的可信根证书和中间证书。UTL_HTTP 软件包使用此 wallet 建立安全的 SSL/TLS 连接。您可以使用 orapki 实用程序创建和管理 wallet。

注:普通 HTTP(非 HTTPS)请求不需要 Oracle Wallet。

以下各节介绍了如何配置和使用客户管理的 wallet,以通过自治 AI 数据库上的 UTL_HTTP 程序包进行出站 HTTPS 调用。

使用客户管理的 Wallet 和外部调用时的先决条件

开始之前,确保您具有:

准备客户管理的钱包

在此步骤中,您将先在工作站上创建并验证 wallet,然后再将其上载到自治 AI 数据库。

获取或创建客户管理的钱包

使用 orapki 的示例:

-- Create an SSL Wallet and load the Root CERTs using orapki utility
$ORACLE_HOME/bin/orapki wallet create -wallet /u01/web/wallet -pwd ********
$ORACLE_HOME/bin/orapki wallet add -wallet /u01/web/wallet -trusted_cert -cert MyWebServer.cer -pwd ********
-- Store the credentials in the SSL Wallet using mkstore utility
$ORACLE_HOME/bin/mkstore -wrl /u01/web/wallet -createCredential secret-from-the-wallet 'example@oracle.com'
********Enter wallet password: ********

验证 Wallet

$ORACLE_HOME/bin/orapki wallet display -wallet /u01/web/wallet

您应看到列出的所有导入的证书。

上载 Wallet

客户管理的 wallet 准备就绪(包括任何必需的自签名/root/中间证书)后,将 wallet 文件上载到 Oracle Cloud Infrastructure (OCI) 对象存储中的位置。

将客户管理的 wallet 与 UTL_HTTP 一起使用

本部分介绍如何从对象存储下载 wallet,允许通过网络访问 HTTPS 端点,然后使用 UTL_HTTP 程序包进行 HTTPS 调用。

  1. 创建用于对象存储访问的身份证明:

     BEGIN
     DBMS_CLOUD.CREATE_CREDENTIAL(credential_name => 'DEF_CRED_NAME',
     username => 'user1@example.com',
     password => 'password'
     );
     END;
     /
    

    usernamepassword 提供的值取决于您使用的云对象存储服务。这将创建用于访问客户管理的 wallet 所在的云对象存储的身份证明。

  2. 为 wallet 创建(或重用)目录对象:

    使用现有目录,或者为 wallet 文件创建新目录。例如:

     CREATE DIRECTORY wallet_dir AS 'directory_path_of_your_choice';
    

    有关创建目录的信息,请参见 Create Directory in Autonomous AI Database

  3. 获取绝对目录路径:

    调用 UTL_HTTP.SET_WALLET 时将需要绝对目录路径。

     SELECT DIRECTORY_NAME, DIRECTORY_PATH FROM DBA_DIRECTORIES WHERE DIRECTORY_NAME = '<wallet_dir>';
    
  4. 将 wallet 文件从对象存储下载到目录中:

    使用 DBMS_CLOUD.GET_OBJECT 将 wallet 文件复制到目录中。例如:

     BEGIN
     DBMS_CLOUD.GET_OBJECT(
     credential_name => 'DEF_CRED_NAME',
     object_uri => 'https://objectstorage.us-phoenix-1.oraclecloud.com/n/namespace-string/b/bucketname/o/cwallet.sso',
     directory_name => 'WALLET_DIR');
     END;
     /
    

    在此示例中,namespace-string 是 Oracle Cloud Infrastructure 对象存储名称空间,bucketname 是存储桶名称。有关详细信息,请参阅了解对象存储名称空间

  5. 允许对 HTTPS 端点的出站网络访问 (ACL):

    必须允许数据库用户/方案通过网络访问目标主机。

      BEGIN
       DBMS_NETWORK_ACL_ADMIN.APPEND_HOST_ACE(
           host => 'api.example.com',
           ace  => xs$ace_type(
           privilege_list => xs$name_list('CONNECT','HTTP','RESOLVE'),
           principal_name => 'ADMIN',
           principal_type => xs_acl.ptype_db
       )
     );
     END;
     /
    

    在 Exadata Cloud@Customer 部署上,您还需要设置代理,如下所示:

     BEGIN
       UTL_HTTP.SET_PROXY('www-proxy.us.oracle.com:80', 'oracle.com');
     END;
     /
    
  6. 使用 UTL_HTTP 进行 HTTPS 调用:

    简单 GET 请求:

     DECLARE
     l_http_req UTL_HTTP.req;
     l_http_resp UTL_HTTP.resp;
     l_response VARCHAR2(32767);
    
     BEGIN
        utl_http.set_wallet('file:<absolute_directory_path_from_step_3>');
        l_http_req := UTL_HTTP.BEGIN_REQUEST('https://api.example.com/status');
        l_http_resp := UTL_HTTP.GET_RESPONSE(l_http_req);
        LOOP UTL_HTTP.READ_LINE(l_http_resp, l_response, TRUE);
            DBMS_OUTPUT.PUT_LINE(l_response);
        END LOOP;
        UTL_HTTP.END_RESPONSE(l_http_resp);
     END;
     /
    

    带有 JSON 有效负载的 POST 请求:

     DECLARE
       l_req UTL_HTTP.req;
       l_resp UTL_HTTP.resp;
       l_line VARCHAR2(32767);
     BEGIN
       utl_http.set_wallet('file:<absolute_directory_path_from_step_3>');
       l_req := UTL_HTTP.BEGIN_REQUEST( url => 'https://api.example.com/data', method => 'POST' );
       UTL_HTTP.SET_HEADER(l_req, 'Content-Type', 'application/json');
       UTL_HTTP.WRITE_TEXT(l_req, '{"key":"value"}');
       l_resp := UTL_HTTP.GET_RESPONSE(l_req);
       LOOP UTL_HTTP.READ_LINE(l_resp, l_line, TRUE);
         DBMS_OUTPUT.PUT_LINE(l_line);
       END LOOP;
       UTL_HTTP.END_RESPONSE(l_resp);
      END;
      /
    

常见错误的故障排除:

证书链错误

错误:ORA-29024: Certificate validation failure

Wallet 路径错误

ORA-28759: Failure to open file

握手故障

ORA-24263 / ORA-29005

将客户管理的 Wallet 用于调度程序电子邮件通知 (SMTP)

本节说明如何将调度程序电子邮件通知配置为通过 TLS (STARTTLS) 将 SMTP 服务器与客户管理的 wallet 一起使用。

在开始之前,请确保您已准备好客户管理的 wallet(在本地创建、验证并上载到对象存储)。有关详细信息,请参阅“准备客户管理的 Wallet”。

要将客户管理的 wallet 与调度程序电子邮件服务器一起使用,请执行以下操作:

  1. 创建用于对象存储访问的身份证明:

    可以使用 DBMS_CLOUD.CREATE_CREDENTIAL 创建用于访问云对象存储的身份证明。

     BEGIN
       DBMS_CLOUD.CREATE_CREDENTIAL(
         credential_name => 'DEF_CRED_NAME',
         username => 'user1@example.com',
         password => 'password'
     );
     END;
     /
    

    usernamepassword 提供的值取决于您使用的云对象存储服务。这将创建用于访问客户管理的 wallet 所在的云对象存储的身份证明。

  2. 为 wallet 创建(或重用)目录对象:

    使用现有目录,或者为 wallet 文件创建新目录。例如:

     CREATE DIRECTORY wallet_dir AS 'directory_path_of_your_choice';
    

    有关创建目录的信息,请参见 Create Directory in Autonomous AI Database

  3. 获取绝对目录路径:

    调用 UTL_HTTP.SET_WALLET 时将需要绝对目录路径。

     SELECT DIRECTORY_NAME, DIRECTORY_PATH FROM DBA_DIRECTORIES WHERE DIRECTORY_NAME = '<wallet_dir>';
    
  4. 将 wallet 文件从对象存储下载到目录中:

    使用 DBMS_CLOUD.GET_OBJECT 将 wallet 文件复制到目录中。例如:

     BEGIN
       DBMS_CLOUD.GET_OBJECT(
         credential_name => 'DEF_CRED_NAME',
         object_uri => 'https://objectstorage.us-phoenix-1.oraclecloud.com/n/namespace-string/b/bucketname/o/cwallet.sso',
         directory_name => 'WALLET_DIR');
     END;
     /
    

    在此示例中,namespace-string 是 Oracle Cloud Infrastructure 对象存储名称空间,bucketname 是存储桶名称。有关详细信息,请参阅了解对象存储名称空间

  5. 配置调度程序电子邮件 (SMTP + STARTTLS):

    运行命令以设置调度程序,以便为调度程序作业通知发送 SMTP 电子邮件:

     EXEC DBMS_CLOUD.CREATE_CREDENTIAL('EMAIL_CRED', '<user_ocid>', '<password>');
     GRANT EXECUTE ON admin.EMAIL_CRED TO sys;
     EXEC DBMS_SCHEDULER.SET_SCHEDULER_ATTRIBUTE(
           'EMAIL_SERVER',
           'smtp.email.us-ashburn-1.oci.oraclecloud.com:587'
     );
     EXEC DBMS_SCHEDULER.SET_SCHEDULER_ATTRIBUTE(
             'EMAIL_SERVER_CREDENTIAL',
             'EMAIL_CRED'
     );
     EXEC DBMS_SCHEDULER.SET_SCHEDULER_ATTRIBUTE(
             'EMAIL_SERVER_ENCRYPTION',
             'STARTTLS'
     );
    

    这些命令执行以下操作:

    • 设置调度程序 SMTP 端点 (EMAIL_SERVER)

    • EMAIL_CRED 中存储 SMTP 登录详细信息并将调度程序指向它

    • 使用 STARTTLS 启用 TLS 加密

    有关详细信息,请参阅 SET_SCHEDULER_ATTRIBUTE 过程

  6. 为 wallet 密码创建身份证明:

    创建身份证明以存储客户管理的 wallet 的密码。

     BEGIN
       DBMS_CLOUD.CREATE_CREDENTIAL(
         credential_name => 'WALLET_CRED',
         username        => 'any_user',
         password        => 'password'
       );
     END;
     /
    

    这将创建您在下一步中使用的身份证明,以提供客户管理的 wallet 的密码。

  7. 告诉调度程序 Wallet 的位置以及如何解锁它:

    设置调度程序 wallet 目录和 wallet 身份证明。

     BEGIN
       DBMS_SCHEDULER.SET_SCHEDULER_ATTRIBUTE(
         'EMAIL_SERVER_WALLET_DIRECTORY',
         'WALLET_DIR'
       );
    
       DBMS_SCHEDULER.SET_SCHEDULER_ATTRIBUTE(
         'EMAIL_SERVER_WALLET_CREDENTIAL',
         'ADMIN.WALLET_CRED'
       );
     END;
     /
    
  8. 验证调度程序电子邮件配置:

    查询 DBA_SCHEDULER_GLOBAL_ATTRIBUTE 视图以验证您在前面步骤中设置的值。

     SELECT attribute_name, value
     FROM DBA_SCHEDULER_GLOBAL_ATTRIBUTE
     WHERE attribute_name LIKE 'EMAIL_SERVER%' ORDER BY 1, 2;
    
     ATTRIBUTE_NAME                 VALUE
    
     ------------------------------ -----------------------------------------------
     EMAIL_SERVER                   smtp.email.us-ashburn-1.oci.oraclecloud.com:587
     EMAIL_SERVER_CREDENTIAL        "ADMIN"."EMAIL_CRED"
     EMAIL_SERVER_ENCRYPTION        STARTTLS
     EMAIL_SERVER_WALLET_CREDENTIAL "ADMIN"."WALLET_CRED"
     EMAIL_SERVER_WALLET_DIRECTORY  "WALLET_DIR"
    

引用

有用的 orapki 命令:

orapki wallet display -wallet <path> orapki wallet add -wallet <path>
-trusted_cert -cert <cert-file> orapki wallet create -wallet <path> -auto_login

wallet 目录结构样例:

cmw_wallet/
- ewallet.p12
- cwallet.sso