Nota:
- Questa esercitazione richiede l'accesso a Oracle Cloud. Per iscriversi a un account gratuito, consulta Inizia a utilizzare Oracle Cloud Infrastructure Free Tier.
- Utilizza valori di esempio per le credenziali, la tenancy e i compartimenti di Oracle Cloud Infrastructure. Al termine del laboratorio, sostituisci questi valori con quelli specifici del tuo ambiente cloud.
Utilizza Oracle Cloud API Gateway per creare un servizio di download sicuro dello storage degli oggetti con autenticazione della funzione
Introduzione
Lo storage degli oggetti Oracle Cloud è un modo molto economico ed efficace per memorizzare file di grandi o piccole dimensioni. Lo storage degli oggetti consente di utilizzare un'architettura basata sugli eventi, avvicinandosi all'esecuzione dei processi in tempo reale. Puoi configurare gli eventi nello storage degli oggetti per attivare gli eventi e puoi anche creare servizi REST in modo sicuro, rapido e conveniente per scrivere o leggere i file dallo storage degli oggetti.
Se ti interessa vedere come implementare un'architettura basata sugli eventi, consulta Elaborare file di grandi dimensioni in Autonomous Database e Kafka con Oracle Cloud Infrastructure Data Flow.
Architettura
Integrazione di Oracle API Gateway
In questa esercitazione verrà illustrato come configurare Oracle API Gateway per implementare un servizio REST tramite una funzione che consenta, in modo flessibile, di autenticare un token JWT tramite un provider di identità esterno o la stessa Oracle Cloud Infrastructure (OCI) (Oracle Identity Cloud Service). Indipendentemente dal processo, puoi convalidare il token JWT (poiché un attributo può far parte del nome file), utilizza i servizi OCI tramite il relativo SDK e altri processi personalizzabili.
Obiettivi
- Esponi un servizio REST API per scaricare un file dallo storage degli oggetti in modo sicuro
- Usare il gateway API OCI che esegue l'autenticazione con le funzioni OCI
- Restituisci un collegamento preautenticato con un tempo limite di 60 secondi per il download
- Configurare un'impostazione di osservabilità per monitorare la scrittura e la lettura del file
Prerequisiti
-
Bucket di storage degli oggetti OCI creato e configurato con criteri necessari per scrivere e leggere i file. Consulta la sezione relativa alla sicurezza dello storage degli oggetti.
-
Un tenant Oracle Cloud operativo: puoi creare un account Oracle Cloud gratuito con 300,00 dollari americani per un mese per provare questa esercitazione. Consulta la sezione relativa alla creazione di un account Oracle Cloud gratuito.
-
Oracle Cloud Command Line Interface (OCI CLI)) installata sul computer locale: si tratta del collegamento per installare l'interfaccia CLI OCI.
-
Funzioni OCI e criteri configurati per lo sviluppo. Questo esempio viene implementato in Python. Per ulteriori informazioni, vedere Functions QuickStart Guides.
-
Un'istanza del gateway API OCI creata ed esposta a Internet. Consulta la sezione relativa alla creazione del primo gateway API in Oracle Cloud.
-
Accedere a Oracle Identity Cloud Service.
Task 1: configurazione di un'applicazione in Oracle Identity Cloud Service
È possibile configurare qualsiasi provider di identità esterno API REST in modo che funzioni con JWT come Auth0 e Oracle Identity Cloud Service.
In questa esercitazione, lavoreremo con Oracle Identity Cloud Service e chiameremo l'autenticazione all'interno della funzione.
-
Creare un'applicazione in Oracle Identity Cloud Service, in questo esempio denominata my-client-app.
-
Selezionare le opzioni Credenziali client e Dichiarazione JWT.
-
Per i dettagli di configurazione, consulta la sezione relativa alla protezione delle API con il gateway API utilizzando Oracle Identity Cloud Service/IAM JWT con ambiti e richieste.
Nota: questo esempio di autenticazione riflette solo una situazione ipotetica per identificare l'utente e altre informazioni sul bucket. Ciò potrebbe non riflettere il modo migliore per autenticare e autorizzare un'applicazione e si consiglia di essere valutato in base agli standard dell'azienda.
-
Salvare e attivare l'applicazione. È possibile utilizzare clientID e secretID nella sezione successiva.
Task 2: rivedere il codice
Codice Python utilizzato in una distribuzione di gateway API per autorizzare un collegamento preautenticato per scaricare un file nello storage degli oggetti.
È possibile scaricare il codice Python da qui: Python fn Project.
python
import io
import json
import logging
import datetime
import jwt
import requests
import base64
import oci
from datetime import timedelta
from fdk import response
from py_zipkin import Encoding #import Zipkin package
from py_zipkin.zipkin import zipkin_span #import Zipkin package
from transport import http_transport #import Zipkin transport
@zipkin_span(service_name='Status: Load File', span_name='statusGetFile')
def auth(ctx, data: io.BytesIO = None):
auth_token = "invalid"
token = "invalid"
apiKey = "invalid"
expiresAt = (datetime.datetime.utcnow() + timedelta(seconds=60)).replace(tzinfo=datetime.timezone.utc).astimezone().replace(microsecond=0).isoformat()
config = oci.config.from_file("config")
object_storage = oci.object_storage.ObjectStorageClient(config)
namespace = object_storage.get_namespace().data
try:
auth_token = json.loads(data.getvalue())
secretID = auth_token.get("secretID")
clientID = auth_token.get("clientID")
details = oci.object_storage.models.CreatePreauthenticatedRequestDetails(name="data", access_type="AnyObjectReadWrite", bucket_listing_action="ListObjects", time_expires=expiresAt)
preauth = object_storage.create_preauthenticated_request(namespace_name=namespace, bucket_name="data", create_preauthenticated_request_details=details)
preauthstr = str(preauth.data)
auth = clientID + ":" + secretID
auth_bytes = auth.encode("ascii")
auth_base64_bytes = base64.b64encode(auth_bytes)
auth_base64_message = auth_base64_bytes.decode("ascii")
headers = {"Authorization": "Basic " + auth_base64_message, "Content-Type": "application/x-www-form-urlencoded"}
scope = "cihxxxxxxxxxxxxxxxxxowu.apigateway.us-ashburn-1.oci.customer-oci.com/super-scope"
grant_type = "client_credentials"
body = {"scope": scope, "grant_type": grant_type}
url_post = "https://Oracle Identity Cloud Service-4fxxxxxxxxxxxxxxxxxxxxxx9.identity.oraclecloud.com/oauth2/v1/token"
post_response = requests.post(url_post, headers=headers, data=body)
jwtTokenDecoded = jwt.decode(post_response.json()['access_token'], options={"verify_signature": False})
return response.Response(
ctx,
status_code=200,
response_data=json.dumps({"active": True, "principal": "foo", "scope": "bar", "clientId": "1234", "expiresAt": expiresAt, "context": {"username": "wally", "token":
post_response.json()['access_token'], "jwtTokenDecoded": jwtTokenDecoded, "objectID": preauthstr}})
)
except (Exception, ValueError) as ex:
logging.getLogger().info('error parsing json payload: ' + str(ex))
pass
return response.Response(
ctx,
status_code=401,
response_data=json.dumps({"active": False, "wwwAuthenticate": "API-key"})
)
@zipkin_span(service_name='Status: Load File', span_name='statusGetFile')
def handler(ctx, data: io.BytesIO = None):
with zipkin_span(
service_name="Status: Load File", #You can change it as you need
span_name="statusGetFile", #You can change it as you need
transport_handler=http_transport, #zipkin transport, will use it to upload trace data to OCI APM
encoding = Encoding.V2_JSON,
binary_annotations = {"status":"Load File", "objectID":json.loads(data.getvalue()).get("objectID")}, #Custom tag
sample_rate=100 # this is optional and can be used to set custom sample rates
):
return auth(ctx, data)
Analizziamo il codice nelle parti per capire come:
- Seguire i processi nell'osservabilità OCI
- Configurare un collegamento preautenticato per scaricare un file nello storage degli oggetti
- Eseguire l'autenticazione con un provider di identità e ottenere un token JWT
- Decodifica un token JWT e utilizza le informazioni nel processo
- Restituisce uno stato di operazione riuscita o non riuscita nella distribuzione del gateway API
Questa parte del codice salva una posizione di stato in Osservabilità OCI. Utilizza la struttura Zipkin per pubblicare in OCI APM Observability
python
@zipkin_span(service_name='Status: Load File', span_name='statusGetFile')
def handler(ctx, data: io.BytesIO = None):
with zipkin_span(
service_name="Status: Load File", #You can change it as you need
span_name="statusGetFile", #You can change it as you need
transport_handler=http_transport, #zipkin transport, will use it to upload trace data to OCI APM
encoding = Encoding.V2_JSON,
binary_annotations = {"status":"Load File", "objectID":json.loads(data.getvalue()).get("objectID")}, #Custom tag
sample_rate=100 # this is optional and can be used to set custom sample rates
):
Si tratta della vista console APM OCI relativa al codice ed è possibile trovare i file con query quali:
**ServiceName** = 'Status: Load File' and **objectID** = '50 - DR-HA OIC.pdf'
Il codice successivo stabilisce una data e un'ora di scadenza per il file Storage degli oggetti. Verrà generata una preautenticazione e l'attributo expiresAt verrà utilizzato per questo obiettivo. timedelta aggiunge 60 secondi dall'ora corrente per lo scaricamento del file.
python
expiresAt = (datetime.datetime.utcnow() + timedelta(seconds=60)).replace(tzinfo=datetime.timezone.utc).astimezone().replace(microsecond=0).isoformat()
A questo punto, è necessario inizializzare il framework dello storage degli oggetti OCI in base alle credenziali salvate nell'installazione CLI OCI. La configurazione dell'interfaccia CLI OCI utilizza il file ~/.oci/config e il file del certificato .pem. È possibile installare l'interfaccia CLI OCI a livello locale e configurare un utente per accedere allo storage degli oggetti (consultare la documentazione OCI per installare l'interfaccia CLI OCI e i criteri dello storage degli oggetti nella sezione Collegamenti correlati), quindi copiare questi 2 file in questo progetto fn.
python
config = oci.config.from_file("config")
object_storage = oci.object_storage.ObjectStorageClient(config)
namespace = object_storage.get_namespace().data
Il passo successivo deriva dai valori dei parametri Corpo: secretID, clientID e objectID.
#secretID = the Oracle Identity Cloud Service secretID from the application created to validate the JWT Token
#clientID = the Oracle Identity Cloud Service clientID from the application created to validate the JWT Token
#objectID = the file name in the Object Storage
python
try:
auth_token = json.loads(data.getvalue())
secretID = auth_token.get("secretID")
clientID = auth_token.get("clientID")
objectID = auth_token.get("objectID")
L'SDK OCI può supportare lo storage degli oggetti per molti servizi, ad esempio in lettura e/o scrittura di un file, elencare il contenuto di un bucket e di altri. Ad esempio, puoi consentire al consumer di elencare tutti i contenuti di un bucket con un URL preautenticato che verrà generato in questa parte del codice. La variabile bucket_name contiene il nome del bucket nello storage degli oggetti creato in precedenza e time_expires rappresenta la data e l'ora di scadenza in cui scaricare il file.
python
details = oci.object_storage.models.CreatePreauthenticatedRequestDetails(name="data", access_type="AnyObjectReadWrite", bucket_listing_action="ListObjects", time_expires=expiresAt)
preauth = object_storage.create_preauthenticated_request(namespace_name=namespace, bucket_name="data", create_preauthenticated_request_details=details)
preauthstr = str(preauth.data)
Questa parte del codice chiama Oracle Identity Cloud Service per convalidare clientID e secretID per ottenere il token JWT. Un JWT può essere decodificato in una stringa JSON, in questo caso senza firma, ma è possibile verificare facilmente la firma con un certificato.
python
auth = clientID + ":" + secretID
auth_bytes = auth.encode("ascii")
auth_base64_bytes = base64.b64encode(auth_bytes)
auth_base64_message = auth_base64_bytes.decode("ascii")
headers = {"Authorization": "Basic " + auth_base64_message, "Content-Type": "application/x-www-form-urlencoded"}
scope = "xxxxxxxxxxxxxxxxxxxx.apigateway.us-ashburn-1.oci.customer-oci.com/super-scope"
grant_type = "client_credentials"
body = {"scope": scope, "grant_type": grant_type}
url_post = "https://Oracle Identity Cloud Service-xxxxxxxxxxxxxxxxxxxxxxx.identity.oraclecloud.com/oauth2/v1/token"
post_response = requests.post(url_post, headers=headers, data=body)
jwtTokenDecoded = jwt.decode(post_response.json()['access_token'], options={"verify_signature": False})
Questa è la parte finale, in cui verranno restituiti tutti i dati con il codice 200. Puoi restituire tutte le informazioni necessarie alla tua applicazione e questa parte del codice convalida l'autenticazione, con conseguente codice 200 (autorizzato/successo) o 401 (non autorizzato).
python
return response.Response(
ctx,
status_code=200,
response_data=json.dumps({"active": True, "principal": "foo", "scope": "bar", "clientId": "1234", "expiresAt": expiresAt, "context": {"username": "wally", "token": post_response.json()['access_token'], "jwtTokenDecoded": jwtTokenDecoded, "objectID": preauthstr}})
)
except (Exception, ValueError) as ex:
logging.getLogger().info('error parsing json payload: ' + str(ex))
pass
return response.Response(
ctx,
status_code=401,
response_data=json.dumps({"active": False, "wwwAuthenticate": "API-key"})
)
Task 3: configurare il gateway API OCI per l'autenticazione con fn
Il gateway API OCI può distribuire un'interfaccia API come funzione OCI. Come visto in precedenza, il codice utilizza il corpo contenente le informazioni clientID, secretID e objectID passate dalla configurazione del gateway API. È possibile configurare la distribuzione:
Dopo aver salvato la distribuzione, è possibile ottenere l'endpoint REST qui. Ricorda che l'endpoint completo per il servizio API REST di storage degli oggetti è questo endpoint più il "/" alla fine (hai dichiarato / come percorso in precedenza).
Task 4: eseguire il test della distribuzione del gateway API
È possibile eseguire il test dell'applicazione con CURL o in Postman:
bash
curl --location 'https://xxxxxxxxxxxxxxxxxxx.apigateway.us-ashburn-1.oci.customer-oci.com/dummyauthorizer/' \
--header 'Content-Type: text/plain' \
--data '{"clientID": "e3exxxxxxxxxxxxxxxxxc2f", "secretID": "8exxxxxxx-fa5e-xxcf-8xxxc-xxxxxxxxxxx87", "objectID": "any-file.txt"}'
Nota: l'attributo
objectID
viene utilizzato qui solo per illustrare l'osservabilità e come visualizzare lo stato in Trace Explorer nella console OCI.
Se tutto va bene, potete vedere il codice di successo 200:
Verrà generato un URL per lo storage degli oggetti preautenticato e sarà possibile scaricare il file per i prossimi 60 secondi. È possibile scaricare il file seguendo l'esempio qui:
https://objectstorage.us-ashburn-1.oraclecloud.com + [access_uri]
or
https://objectstorage.us-ashburn-1.oraclecloud.com/p/eL5C0R0luN_cTNn-vUF7_Dx_z2N4w7IXemKr5y61cSRxZZPRXcR2Yj1dNCaJBDK8/n/idavixsf5sbx/b/data/o/calico.yaml
Puoi scaricare, caricare o visualizzare i file bucket con questa riga di comando:
- TO UPLOAD A FILE: `curl https://objectstorage.us-ashburn-1.oraclecloud.com/p/HoPudIF45Bj6J5-Qy3J1D9dOplLuKtECRFhvOTkKAtBjJXkOTDx0Pt8gXbOOEoRx/n/idavixsf5sbx/b/data/o/ --upload-file func.py`
- TO DOWNLOAD A FILE: `curl https://objectstorage.us-ashburn-1.oraclecloud.com/p/3ZyXd6PchrTFrp1oxmedamSG1ojwQa3BxPUyonAA-q1mf3QAe5STpDrt89eYITPf/n/idavixsf5sbx/b/data/o/func.py`
- TO LIST BUCKET: `curl https://objectstorage.us-ashburn-1.oraclecloud.com/p/ODVRMB71kD0SHWuoY4ojVd93nmIiy8u0zrxA56T7FBaohAgA7k8KOLAIlhxjcveE/n/idavixsf5sbx/b/data/o/``
Task 5: Configura dashboard osservabilità
In sostanza, ogni risorsa OCI può mostrare le metriche in un dashboard e molti eventi in queste risorse possono attivare un'azione. In questa demo, puoi configurare un dashboard per mostrare il numero di file scritti o letti nello storage degli oggetti:
È possibile configurare la query del dashboard come indicato di seguito.
- File bucket = ObjectCount[1d].groupby(resourceID).count()
- Scritture bucket = PutRequests[5m].grouping().count()
- Letture bucket = GetRequests[5m].grouping().count()
Collegamenti correlati
- Installare l'interfaccia CLI OCI
- Sicurezza dello storage degli oggetti
- Creazione del primo gateway API in Oracle Cloud
- Funzioni QuickStart Guide
- Esempi di Oracle Functions
- Passaggio di token alle funzioni del responsabile autorizzazioni per aggiungere autenticazione e autorizzazione alle distribuzioni API
- Crea un token JWT in Java per Oracle Identity Cloud Service
- Metriche dello storage degli oggetti
- Riferimento MQL (Monitoring Query Language)
- Proteggi le API con il gateway API utilizzando Oracle Identity Cloud Service/IAM JWT con ambiti e richieste di rimborso
- Elabora file di grandi dimensioni in Autonomous Database e Kafka con Oracle Cloud Infrastructure Data Flow
- Storage degli oggetti - Limiti e uso dei caricamenti multiparte
Conferme
- Autore - Cristiano Hoshikawa (Oracle LAD A-Team Solution Engineer)
Altre risorse di apprendimento
Esplora altri laboratori su docs.oracle.com/learn o accedi a contenuti di formazione gratuiti sul canale YouTube di Oracle Learning. Inoltre, visitare education.oracle.com/learning-explorer per diventare Explorer di Oracle Learning.
Per la documentazione sul prodotto, visitare il sito Oracle Help Center.
Use Oracle Cloud API Gateway to create a secure Object Storage download service with function authentication
F84019-01
July 2023
Copyright © 2023, Oracle and/or its affiliates.