Nota

Gestisci le API REST di Oracle Cloud Infrastructure a livello di programmazione utilizzando Shell e codice Java

Introduzione

Oracle Cloud Infrastructure (OCI) fornisce ai clienti un'infrastruttura cloud per ospitare le loro applicazioni mission critical nel cloud. OCI offre anche ai clienti i modi per accedere ai servizi OCI tramite la console o tramite le API. Per la connessione tramite le API, i clienti possono utilizzare gli SDK in base al linguaggio di programmazione scelto, ad esempio Java, Python o Ruby. Sono tuttavia pochi i casi in cui il cliente non può utilizzare SDK e non può utilizzare alcun linguaggio di programmazione, ma desidera invece connettersi tramite API direttamente da uno strumento, un database o un'applicazione di terze parti in cui non può installare SDK. Ecco perché l'uso delle API REST è utile. I clienti possono sfruttare le API REST fornite da OCI per quasi tutti i servizi e utilizzarle direttamente nei propri strumenti semplicemente aggiornando gli endpoint e occupandosi dell'autorizzazione e dell'autenticazione.

Oggi, ogni organizzazione vuole sfruttare la potenza delle API REST nelle proprie applicazioni e creare un'offerta innovativa per i propri clienti senza la necessità di installare e gestire alcun SDK.

In questo tutorial, discuteremo e capiremo come OCI può aiutare le organizzazioni di tutto il mondo a sfruttare la potenza delle API REST con OCI. In questa esercitazione verrà illustrato un esempio di API REST basate su script shell e codice Java.

Obiettivi

Prerequisiti

Task 1: impostare le chiavi API di Oracle Cloud Infrastructure

  1. Eseguire il login alla tenancy OCI con l'account di servizio o l'utente amministratore e andare alle impostazioni utente.

    Apri impostazioni utente

    Oppure

    Andare all'utente dalla console IAM OCI. Assicurarsi che l'utente disponga di tutti gli accessi necessari per creare e aggiornare l'infrastruttura su OCI.

  2. Passare alla sezione Risorse, fare clic su Chiavi API e su Aggiungi chiave API. Selezionare questa opzione per scaricare le nuove chiavi pubbliche e private, caricare la chiave pubblica o incollare la chiave pubblica.

    Aggiungi chiave API

  3. Salvare le chiavi in una posizione comoda e salvare il file di configurazione come mostrato nella pagina seguente. Durante la connessione alla tenancy mediante le API REST, saranno necessari questo file di configurazione e questa chiave privata.

    Salva file di configurazione

    Nota:

    • Per connettersi all'area geografica e alla tenancy OCI, sarà necessario lo stesso configuration parameters. Sostituirete i parametri nel codice Java e negli script shell di conseguenza mentre ci immergiamo più a fondo nell'esercitazione.

    • Per chiamare i servizi OCI dalle istanze di OCI Compute, OCI offre un modo più sicuro utilizzando i principal delle istanze. Evita di utilizzare le chiavi API degli utenti come best practice. Per ulteriori informazioni, vedere Chiamata di servizi da un'istanza.

Task 2: creare ed eseguire uno script shell per caricare o inserire un file binario da OCI Object Storage utilizzando le API REST

  1. Passare al file system e creare un file shell. In questo esempio, file denominato PUT_OBJECT_REST_API.sh.

  2. Aprire il file con l'editor scelto e incollare il codice seguente nel file della 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. Ora abbiamo tutto il codice incollato nel file shell, lavoriamo per aggiornare i valori richiesti e capire le loro funzionalità.

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

    Tutti questi valori sono responsabili di stabilire una connessione sicura con la tenancy OCI. Recuperare questi valori dal file di configurazione.

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

    Questo è l'endpoint rest_api e host, prepararlo in base alle proprie esigenze in quanto ciò cambierà per ogni servizio. L'esempio mostrato qui è l'endpoint per il servizio di storage degli oggetti OCI per l'area ashburn.

    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"
    

    Qui abbiamo creato le intestazioni per l'API REST insieme al tipo di contenuto e ad altri parametri obbligatori. Si noti che qui sono disponibili definizioni per method_type, data e intestazione host in quanto per la chiamata successiva è necessario impostare un'intestazione dettagliata.

    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" ...
    

    Infine, stiamo creando la stringa di firma, quindi effettuando la chiamata API REST utilizzando curl. Si noti che OCI ha bisogno che le chiamate API siano firmate ed è per questo che lo stiamo facendo qui.

  4. Dopo aver aggiornato i valori in base alla configurazione, esegui lo script della shell, dovresti vedere lo script che esegue tutte le operazioni valide e il file viene sottoposto a PUSH nello storage degli oggetti OCI.

    Nota:

    • Assicurarsi di aver aggiornato l'autorizzazione di esecuzione del file shell modificandola in 755 o gestirla personalmente.

    • Puoi anche farlo su Windows utilizzando powershell, o utilizzare lo stesso script su Windows installando un WSL (Windows Subsystem for Linux) come Ubuntu ed eseguirlo da Ubuntu WSL su Windows. Per ulteriori informazioni, vedere Sottosistema Windows per Linux.

Task 3: creare ed eseguire il codice Java per caricare o inserire un file binario dallo storage degli oggetti OCI utilizzando le API REST

  1. Passare al file system e creare un file java. In questo esempio, file denominato PUT_OBJECT_REST_API.java.

  2. Aprire il file con l'editor scelto e incollare il codice seguente nel file della 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. Ora abbiamo tutto il codice incollato nel file java, lavoriamo per aggiornare i valori richiesti e capire le loro funzionalità.

    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
    

    Tutti questi valori sono responsabili di stabilire una connessione sicura con la tenancy OCI. Recuperare questi valori dal file di configurazione.

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

    Si tratta dell'endpoint rest_api e dell'host, prepararlo in base alle proprie esigenze in quanto ciò cambierà per ogni servizio. L'esempio mostrato qui è l'endpoint per il servizio di storage degli oggetti OCI per l'area ashburn.

    private static HttpRequest buildRequest
    

    Le intestazioni per l'API REST sono state create insieme al tipo di contenuto e ad altri parametri obbligatori. Si noti che qui abbiamo definizioni per method_type, data e intestazioni host come per la chiamata post abbiamo bisogno di una serie di intestazioni dettagliate.

    private static String signRequest
    

    Infine, stiamo creando la stringa di firma e quindi effettuando la chiamata all'API REST. Si noti che OCI ha bisogno che le chiamate API siano firmate ed è per questo che lo stiamo facendo qui.

  4. Dopo aver aggiornato i valori in base alla configurazione, esegui il codice java, dovresti vedere lo script che esegue tutte le operazioni valide e il file viene sottoposto a push nello storage degli oggetti OCI.

    Nota: assicurarsi di avere installato Java con tutti i package richiesti in base alle esigenze del codice.

Conferme

Altre risorse di apprendimento

Esplora altri laboratori su docs.oracle.com/learn o accedi a più contenuti gratuiti sulla formazione su Oracle Learning YouTube channel. Inoltre, visita education.oracle.com/learning-explorer per diventare un Oracle Learning Explorer.

Per la documentazione del prodotto, visita l'Oracle Help Center.