ノート:

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を活用し、エンドポイントを更新して認可と認証を処理するだけで、ツールで直接使用できます。

現在、すべての組織は、SDKをインストールおよび管理することなく、アプリケーションでREST APIの機能を活用し、顧客向けの革新的な製品を作成することを望んでいます。

このチュートリアルでは、OCIが世界中の組織がOCIでREST APIのパワーを活用するのにどのように役立つかについて説明し、理解します。このチュートリアルでは、シェル・スクリプトおよびJavaコードに基づくREST APIの例を示します。

目的

前提条件

タスク1: Oracle Cloud Infrastructure APIキーの設定

  1. サービス・アカウントまたは管理ユーザーでOCIテナンシにログインし、「ユーザー設定」に移動します。

    ユーザー設定を開く

    または

    OCI IAMコンソールからユーザーに移動します。OCIでインフラストラクチャを作成および更新するために必要なすべてのアクセス権をユーザーに付与します。

  2. 「リソース」セクションに移動し、「APIキー」および「APIキーの追加」をクリックします。新しい公開鍵と秘密鍵をダウンロードするか、公開鍵をアップロードするか、公開鍵を貼り付けるかを選択します。

    APIキーの追加

  3. キーを便利な場所に保存し、次のページに示すように構成ファイルを保存します。REST APIを使用してテナンシに接続する場合、この構成ファイルおよび秘密キーが必要になります。

    構成ファイルの保存

    ノート:

    • OCIリージョンおよびテナンシに接続するには、同じconfiguration parametersが必要です。チュートリアルの詳細は、Javaコードおよびシェル・スクリプトのパラメータを適宜置き換えます。

    • OCIコンピュート・インスタンスからOCIサービスを呼び出すために、OCIはインスタンス・プリンシパルを使用するより安全な方法を提供します。ベスト・プラクティスとしてユーザーAPIキーを使用しないでください。詳細は、インスタンスからのサービスのコールを参照してください。

タスク2: REST APIを使用したOCIオブジェクト・ストレージからのバイナリ・ファイルのアップロードまたは配置のためのシェル・スクリプトの作成および実行

  1. ファイルシステムに移動し、シェルファイルを作成します。この例では、PUT_OBJECT_REST_API.shという名前のファイルです。

  2. 任意のエディタでファイルを開き、次のコードをシェルファイルに貼り付けます。

    • 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. これで、すべてのコードをシェルファイルに貼り付けました。必要な値を更新し、その機能を理解しましょう。

    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_apiおよび hostエンドポイントで、各サービスで変更されるため、要件に従って準備します。ここに示す例は、アッシュバーン・リージョンのOCI Object Storage Serviceのエンドポイントです。

    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コールに署名する必要があることに注意してください。そのため、ここではこれを行っています。

  4. 構成に従って値を更新した後、シェル・スクリプトを実行すると、スクリプトが正常に実行され、ファイルがOCIオブジェクト・ストレージにプッシュされます。

    ノート:

    • 755に変更してシェルファイルアクセス権を実行可能ファイルに更新したことを確認するか、自分で管理してください。

    • Windowsでも同様に、UbuntuのようなWSL(Windows Subsystem for Linux)をインストールし、Windows上のUbuntu WSLからそれを実行して、同じスクリプトをWindowsでも使用できます。詳細は、Windows Subsystem for Linuxを参照してください。

タスク3: REST APIを使用したOCIオブジェクト・ストレージからのバイナリ・ファイルのアップロードまたは配置のためのJavaコードの作成および実行

  1. ファイル・システムに移動し、javaファイルを作成します。この例では、PUT_OBJECT_REST_API.javaという名前のファイルです。

  2. 任意のエディタでファイルを開き、次のコードをシェルファイルに貼り付けます。

    • 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およびホスト・エンドポイントで、各サービスで変更されるため、要件に従って準備します。ここに示す例は、アッシュバーン・リージョンのOCI Object Storage Serviceのエンドポイントです。

    private static HttpRequest buildRequest
    

    REST APIのヘッダーと、コンテンツ・タイプおよびその他の必須パラメータが作成されました。ここでは、method_type、日付およびホスト・ヘッダーの定義があります。ポスト・コールについては、詳細なヘッダー・セットが必要です。

    private static String signRequest
    

    最後に、署名文字列を作成し、REST APIコールを実行します。OCIはAPIコールに署名する必要があることに注意してください。そのため、ここではAPIコールを行います。

  4. 構成に従って値を更新した後、javaコードを実行すると、スクリプトがすべて正常に実行され、ファイルがOCIオブジェクト・ストレージにプッシュされます。

    ノート:コードに必要なすべての必須パッケージを含むJavaがインストールされていることを確認します。

承認

その他の学習リソース

docs.oracle.com/learnの他のラボを確認するか、Oracle Learning YouTubeチャネルで無料のラーニング・コンテンツにアクセスしてください。また、education.oracle.com/learning-explorerにアクセスしてOracle Learning Explorerになります。

製品ドキュメントは、Oracle Help Centerを参照してください。