附註:

使用 Shell 和 Java Code 以程式設計方式管理 Oracle Cloud Infrastructure REST API

簡介

Oracle Cloud Infrastructure (OCI) 為客戶提供雲端基礎架構,以便在雲端代管其關鍵任務應用程式。OCI 還為客戶提供透過主控台或透過 API 存取 OCI 服務的方法。為了透過 API 進行連線,客戶可以根據自己選擇的程式設計語言 (例如 Java、Python 或 Ruby) 使用 SDK。但在少數情況下,客戶無法使用 SDK,也無法使用任何程式設計語言,而是想要直接從他們無法安裝 SDK 的工具、資料庫或第三方應用程式透過 API 進行連線。以下是 REST API 的使用方式。客戶可以將 OCI 提供的 REST API 用於幾乎所有服務,並直接在工具中使用這些服務,只需更新端點並處理授權和驗證。

如今,每個組織都希望在其應用程式中運用 REST API 的強大功能,並為其客戶建立創新的產品,而無需安裝和管理任何 SDK。

在本教學課程中,我們將討論並瞭解 OCI 如何協助全球各地的組織運用 OCI 的 REST API 強大功能。在本教學課程中,我們將根據 Shell 命令檔和 Java 程式碼示範 REST API 的範例。

目標

必要條件

作業 1:設定 Oracle Cloud Infrastructure API 金鑰

  1. 使用服務帳戶或管理員使用者登入 OCI 租用戶,並前往使用者設定值

    開啟使用者設定值

    從 OCI IAM 主控台前往使用者。確定使用者具備在 OCI 上建立及更新基礎架構的所有必要存取權。

  2. 前往資源區段,按一下 API 金鑰新增 API 金鑰。選取即可下載新的公用金鑰和私密金鑰、上傳您的公開金鑰或貼上您的公開金鑰。

    新增 API 金鑰

  3. 將金鑰儲存在方便的位置,並依照下列頁面所示儲存配置檔案。使用 REST API 連線至您的租用戶時,將需要使用此組態檔和私密金鑰。

    儲存組態檔

    注意:

    • 您需要相同的 configuration parameters 才能連線至 OCI 區域和租用戶。您將取代 Java 程式碼和 Shell 命令檔中的參數,因為我們深入教學課程。

    • 若要從 OCI Compute 執行處理呼叫 OCI 服務,OCI 能夠以更安全的方式使用執行處理主體。避免使用使用者 API 金鑰作為最佳做法。如需詳細資訊,請參閱從執行處理呼叫服務

作業 2:建立並執行 Shell 命令檔,使用 REST API 從 OCI 物件儲存上傳或放置二進位檔案

  1. 前往檔案系統並建立 Shell 檔案。在此範例中,檔案名稱為 PUT_OBJECT_REST_API.sh

  2. 以您選擇的編輯器開啟檔案,並將下列程式碼貼到 Shell 檔案中。

    • PUT_OBJECT_REST_API.sh:

      #!/bin/bash
      
      ########################## Fill these in with your values ##########################
      #OCID of the tenancy calls are being made in to
      tenancy_ocid="ocid1.tenancy.oc1..aaaaaaaackopa"
      
      # namespace of the tenancy
      namespace="ocitenancyname"
      
      # OCID of the user making the rest call
      user_ocid="ocid1.user.oc1..aaaaaaaafelqsoffcjh"
      
      # path to the private PEM format key for this user
      privateKeyPath="/home/lovelesh/.oci/oci_api_key.pem"
      
      # fingerprint of the private key for this user
      fingerprint="72:d4:6c:f8:89"
      
      #bucket name for uplaod/ put
      bucket="ocibucketname"
      
      #file name for upload/ put
      object="test_pdf.pdf"
      
      # The REST api you want to call, with any required paramters.
      rest_api="/n/$namespace/b/$bucket/o/$object"
      
      # The host you want to make the call against
      host="objectstorage.us-ashburn-1.oraclecloud.com"
      
      # the file containing the data you want to POST to the rest endpoint
      body="/home/lovelesh/.oci/test_pdf.pdf"
      ####################################################################################
      
      # extra headers required for a POST/PUT request
      method="put"
      content_type="application/octet-stream"
      body_arg=(--data-binary @${body})
      content_sha256="$(openssl dgst -binary -sha256 < $body | openssl enc -e -base64)";
      content_sha256_header="x-content-sha256: $content_sha256"
      content_length="$(wc -c < $body | xargs)";
      content_length_header="content-length: $content_length"
      headers="(request-target) date host"
      # add on the extra fields required for a POST/PUT
      headers=$headers" x-content-sha256 content-type content-length"
      content_type_header="content-type: $content_type";
      
      date=`date -u "+%a, %d %h %Y %H:%M:%S GMT"`
      date_header="date: $date"
      host_header="host: $host"
      request_target="(request-target): $method $rest_api"
      
      # note the order of items. The order in the signing_string matches the order in the headers, including the extra POST fields
      signing_string="$request_target\n$date_header\n$host_header"
      # add on the extra fields required for a POST/PUT
      signing_string="$signing_string\n$content_sha256_header\n$content_type_header\n$content_length_header"
      
      
      
      signature=`printf '%b' "$signing_string" | openssl dgst -sha256 -sign $privateKeyPath | openssl enc -e -base64 | tr -d '\n'`
      
      set -x
      curl -v -X $(echo $method | tr [:lower:] [:upper:]) --data-binary "@$body" -sS https://$host$rest_api -H "date: $date" -H "x-content-sha256: $content_sha256" -H "content-type: $content_type" -H "content-length: $content_length" -H "Authorization: Signature version=\"1\",keyId=\"$tenancy_ocid/$user_ocid/$fingerprint\",algorithm=\"rsa-sha256\",headers=\"$headers\",signature=\"$signature\""
      
  3. 現在我們已經將所有程式碼貼到 shell 檔案中,讓我們努力更新所需的值並瞭解其功能。

    tenancy_ocid="ocid1.tenancy.oc1..aaaaaaaackopa"
    ...
    fingerprint="72:d4:6c:f8:89"
    

    所有這些值都負責與您的 OCI 租用戶進行安全連線。從組態檔取得這些值。

    rest_api="/n/$namespace/b/$bucket/o/$object"
    host="objectstorage.us-ashburn-1.oraclecloud.com"
    

    這是 rest_apihost 端點,依照您的需求做好準備,因為這將會對每個服務和每個服務進行變更。此處顯示的範例是 ashburn 區域 OCI 物件儲存體服務的端點。

    headers=$headers" x-content-sha256 content-type content-length"
    content_type_header="content-type: $content_type";
    date=`date -u "+%a, %d %h %Y %H:%M:%S GMT"`
    date_header="date: $date"
    host_header="host: $host"
    request_target="(request-target): $method $rest_api"
    

    我們已在此建立 REST API 標頭,以及內容類型和其他必要參數。請注意,這裡有 method_typedate 以及 host headers 的定義,我們需要設定詳細的標頭。

    signing_string="$signing_string\n$content_sha256_header\n$content_type_header\n$content_length_header"
    curl -v -X $(echo $method | tr [:lower:] [:upper:]) --data-binary "@$body" ...
    

    最後,我們正在建立簽署字串,然後使用 Curl 進行 REST API 呼叫。請注意,OCI 需要簽署 API 呼叫,這也是我們在此進行 API 呼叫的原因。

  4. 依照您的組態更新值之後,請執行 Shell 命令檔,您應該會看到執行全部正常的命令檔,並將檔案推送至 OCI Object Storage。

    注意:

    • 請將 Shell 檔案權限變更為 755 或自行管理,以確定您已更新可執行的 Shell 檔案權限。

    • 同樣地,您也可以使用 powershell 在 Windows 上執行此操作,或藉由安裝 WSL (Windows Subsystem for Linux) (例如 Ubuntu) 在 Windows 上使用相同的程序檔,然後在 Windows 上從 Ubuntu WSL 執行。如需詳細資訊,請參閱 Windows Subsystem for Linux

作業 3:建立並執行 Java 程式碼以使用 REST API 從 OCI 物件儲存上傳或放置二進位檔案

  1. 移至檔案系統並建立 java 檔案。在此範例中,檔案名稱為 PUT_OBJECT_REST_API.java

  2. 以您選擇的編輯器開啟檔案,並將下列程式碼貼到 Shell 檔案中。

    • PUT_OBJECT_REST_API.java:

      import java.io.IOException;
      import java.net.URI;
      import java.net.http.HttpClient;
      import java.net.http.HttpRequest;
      import java.net.http.HttpResponse;
      import java.nio.file.Files;
      import java.nio.file.Paths;
      import java.security.KeyFactory;
      import java.security.NoSuchAlgorithmException;
      import java.security.PrivateKey;
      import java.security.Signature;
      import java.security.spec.InvalidKeySpecException;
      import java.security.spec.PKCS8EncodedKeySpec;
      import java.time.ZoneOffset;
      import java.time.ZonedDateTime;
      import java.time.format.DateTimeFormatter;
      import java.util.Base64;
      
      // NOTE - Feel free to remove logging as needed. Currently logs the signing string, host, date, and response. 
      
      public class PUT_OBJECT_REST_API {
      
          private static final String apiKeyFilePath = "C:\\Users\\User1\\Folder\\privatekey.pem"
          private static final String tenancyId = "ocid1.tenancy.oc1..aaaaaaaackopa27emaz4uteg4q7"; // OCI Tenancy ID
          private static final String userId = "ocid1.user.oc1..aaaaaaaafelqsoffcjq"; // OCI User ID
          private static final String keyFingerprint = "72:d4:6c:f8:89:74:aa"; // OCI fingerprint
          private static final String region = "us-ashburn-1"; // OCI Region
          private static final String namespace = "ocitenancyname"; // OCI bucket namespace
          private static final String bucketName = "ocibucketname"; // OCI bucket NAME
      
          public static void main(String[] args) {
              try {
                  String filePath = "D:\\file\\location\\test_pdf.pdf"; //args.length > 0 ? args[0] : ""; // File to upload (path)
                  PrivateKey privateKey = loadPrivateKey(apiKeyFilePath);
                  String fileName = Paths.get(filePath).getFileName().toString();
                  String targetUri = "https://objectstorage." + region + ".oraclecloud.com/n/" + namespace + "/b/" + bucketName + "/o/" + fileName;
                  HttpRequest request = buildRequest(targetUri, filePath, privateKey);
                  HttpClient client = HttpClient.newHttpClient();
                  HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
      
                  System.out.println("Response status code: " + response.statusCode());
                  System.out.println("Response body: " + response.body());
              } catch (Exception e) {
                  e.printStackTrace();
              }
          }
      
          private static PrivateKey loadPrivateKey(String filePath) throws IOException, NoSuchAlgorithmException, InvalidKeySpecException {
              String key = new String(Files.readAllBytes(Paths.get(filePath)))
                  .replace("-----BEGIN PRIVATE KEY-----", "")
                  .replace("-----END PRIVATE KEY-----", "")
                  .replaceAll("\\s+", ""); // Remove all whitespace
      
              byte[] decodedKey = Base64.getDecoder().decode(key);
              PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(decodedKey);
              KeyFactory kf = KeyFactory.getInstance("RSA");
              return kf.generatePrivate(spec);
          }
      
          private static HttpRequest buildRequest(String targetUri, String filePath, PrivateKey privateKey) throws Exception {
              String method = "put";
              String path = "/n/" + namespace + "/b/" + bucketName + "/o/" + Paths.get(filePath).getFileName();
              String host = "objectstorage." + region + ".oraclecloud.com";
              String date = DateTimeFormatter.RFC_1123_DATE_TIME.format(ZonedDateTime.now(ZoneOffset.UTC));
              byte[] fileContent = Files.readAllBytes(Paths.get(filePath)); // Read file content as byte array
      
              String signingString = "(request-target): " + method.toLowerCase() + " " + path + "\n" +
                                  "host: " + host + "\n" +
                                  "date: " + date;
              System.out.println("Signing String: \n" + signingString);
      
              String signature = signRequest(privateKey, signingString);
              String authorizationHeader = "Signature version=\"1\",headers=\"(request-target) host date\",keyId=\"" +
                  tenancyId + "/" + userId + "/" + keyFingerprint + "\",algorithm=\"rsa-sha256\",signature=\"" + signature + "\"";
      
              return HttpRequest.newBuilder()
                      .uri(URI.create(targetUri))
                      .header("Content-Type", "application/octet-stream")
                      .header("date", date)
                      .header("Authorization", authorizationHeader)
                      .PUT(HttpRequest.BodyPublishers.ofByteArray(fileContent))
                      .build();
          }
      
          private static String signRequest(PrivateKey privateKey, String dataToSign) throws Exception {
              Signature signatureInstance = Signature.getInstance("SHA256withRSA");
              signatureInstance.initSign(privateKey);
              signatureInstance.update(dataToSign.getBytes());
              byte[] signature = signatureInstance.sign();
              return Base64.getEncoder().encodeToString(signature);
          }
      }
      
  3. 現在我們把所有貼到 java 檔案中的程式碼,讓我們努力更新必要的值並瞭解其功能。

    private static final String apiKeyFilePath = "C:\\Users\\User1\\Folder\\privatekey.pem"
    private static final String tenancyId = "ocid1.tenancy.oc1..aaaaaaaackopa27emaz4uteg4q7"; // OCI Tenancy ID
    private static final String userId = "ocid1.user.oc1..aaaaaaaafelqsoffcjq"; // OCI User ID
    private static final String keyFingerprint = "72:d4:6c:f8:89:74:aa"; // OCI fingerprint
    private static final String region = "us-ashburn-1"; // OCI Region
    private static final String namespace = "ocitenancyname"; // OCI bucket namespace
    private static final String bucketName = "ocibucketname"; // OCI bucket NAME
    

    所有這些值都負責與您的 OCI 租用戶進行安全連線。從組態檔取得這些值。

    String targetUri = "https://objectstorage." + region + ".oraclecloud.com/n/" + namespace + "/b/" + bucketName + "/o/" + fileName;
    HttpRequest request = buildRequest(targetUri, filePath, privateKey);
    

    這是 rest_api 和主機端點,依照您的需求做好準備,因為這會針對每個服務和每個服務進行變更。此處顯示的範例是 ashburn 區域 OCI 物件儲存體服務的端點。

    private static HttpRequest buildRequest
    

    我們已建立 REST API 標頭,以及內容類型和其他必要參數。請注意,這裡有 method_type、日期及主機標頭的定義 (針對後續呼叫),我們需要詳細的標頭集。

    private static String signRequest
    

    最後,我們正在建立簽署字串,然後進行 REST API 呼叫。請注意,OCI 需要簽署 API 呼叫,這也是我們在此進行 API 呼叫的原因。

  4. 依照您的組態更新值之後,請執行 java 程式碼,您應該會看到所有正常執行的命令檔,並將檔案推送至 OCI Object Storage。

    注意:請確定已安裝 Java 與程式碼所需的所有必要套裝程式。

認可

其他學習資源

瀏覽 docs.oracle.com/learn 的其他實驗室,或前往 Oracle Learning YouTube 頻道存取更多免費學習內容。此外,請造訪 education.oracle.com/learning-explorer 以成為 Oracle Learning Explorer。

如需產品文件,請造訪 Oracle Help Center