Configurazione di un proxy Pub/Sub per i client mobile su GKE


Questo tutorial mostra come pubblicare messaggi da app mobile o lato client in Pub/Sub utilizzando un proxy che gestisce la logica di autenticazione e autorizzazione anziché le credenziali lato client.

Sebbene sia possibile autenticare i messaggi provenienti dal client in Pub/Sub utilizzando Identity and Access Management (IAM), queste credenziali di lunga durata non scadono mai. Nelle app lato client, queste credenziali possono essere rilevate tramite tecniche quali la decompilazione delle app e il reverse engineering.

Puoi invece trasferire la logica di autenticazione e autorizzazione a un proxy che esegue le seguenti attività:

  • Autentica le richieste in entrata per convalidare l'utente.
  • Inoltra le richieste a Pub/Sub insieme alle autorizzazioni IAM appropriate.

Questo tutorial mostra come implementare un proxy Pub/Sub su Google Kubernetes Engine (GKE). Questo tutorial è destinato agli sviluppatori di applicazioni e agli architetti di sistema che definiscono e implementano la progettazione per applicazioni mobile o lato client. Si presume che tu comprenda i concetti fondamentali di Kubernetes e abbia familiarità con Cloud Endpoints.

Flusso di richiesta per questo tutorial

Per comprendere in che modo Pub/Sub si inserisce in una pipeline di flusso, considera l'analisi di un flusso di clic. In questo caso d'uso, ti consigliamo di comprendere in che modo gli utenti interagiscono con la tua app mobile. Per ottenere queste informazioni, acquisisci l'attività utente in tempo reale. Il seguente diagramma mostra il flusso di dati.

Il proxy Pub/Sub riceve i messaggi dal client prima che i dati vengano aggregati.

I dati acquisiti dall'app vengono inviati a Pub/Sub tramite un proxy. Pub/Sub può avere sottoscrittori a valle, come Dataflow o Dataproc, che aggregano i dati in modo da poter eseguire analisi significative.

Il seguente diagramma mostra una visualizzazione dettagliata del flusso di richieste seguito da questo tutorial.

Come interagiscono i componenti della pipeline in una richiesta utente.

Le sezioni successive spiegano come interagiscono i vari componenti di questo diagramma.

Autenticazione degli utenti

Le app mobile possono utilizzare diversi metodi per autenticare gli utenti. Il flusso di autenticazione è specifico per la tua app. Questo tutorial mostra una di queste soluzioni per l'autenticazione degli utenti. Un'implementazione di questa soluzione accompagna questo tutorial.

Richieste dall'app client al proxy Pub/Sub

Il backend dell'app genera un token di autenticazione di breve durata che il client archivia localmente (ad esempio, utilizzando il sistema dell'archivio chiavi Android o i servizi portachiavi iOS). Questo tutorial utilizza i token ID OIDC (OpenID Connect) per autenticare l'app client. Google emette e firma il token ID OIDC.

L'app lato client invia una richiesta al proxy Pub/Sub utilizzando il token ID OIDC. Il proxy Pub/Sub convalida il token e inoltra la richiesta a Pub/Sub insieme alle credenziali IAM appropriate.

Pubblicazione di messaggi

Dopo l'autenticazione dell'app client, il proxy Pub/Sub invia una richiesta di pubblicazione a Pub/Sub. Utilizzando IAM, Pub/Sub aiuta a garantire che il chiamante (il proxy Pub/Sub) disponga delle autorizzazioni appropriate per inviare le richieste di pubblicazione. In questo tutorial, il proxy Pub/Sub utilizza l'account di servizio predefinito di Compute Engine per eseguire l'autenticazione con Pub/Sub. L'account di servizio predefinito di Compute Engine dispone del ruolo IAM Editor (roles/editor), che fornisce l'accesso publisher al proxy Pub/Sub.

Obiettivi

  • Crea un cluster GKE per eseguire un proxy Pub/Sub.
  • Creare un argomento Pub/Sub.
  • Esegui il deployment del proxy Pub/Sub.
  • Configura gli endpoint per autenticare le richieste al proxy Pub/Sub.
  • Verifica che i messaggi siano pubblicati in Pub/Sub.

Costi

In questo documento vengono utilizzati i seguenti componenti fatturabili di Google Cloud:

Per generare una stima dei costi in base all'utilizzo previsto, utilizza il Calcolatore prezzi. I nuovi utenti di Google Cloud possono essere idonei a una prova senza costi aggiuntivi.

Una volta completate le attività descritte in questo documento, puoi evitare la fatturazione continua eliminando le risorse che hai creato. Per ulteriori informazioni, consulta la pagina Pulizia.

Prima di iniziare

  1. Nella console Google Cloud, vai alla pagina del selettore progetto.

    Vai al selettore progetti

  2. Seleziona o crea un progetto Google Cloud.

  3. Assicurati che la fatturazione sia attivata per il tuo progetto Google Cloud.

  4. Nella console Google Cloud, attiva Cloud Shell.

    Attiva Cloud Shell

    Nella parte inferiore della console Google Cloud viene avviata una sessione di Cloud Shell che mostra un prompt della riga di comando. Cloud Shell è un ambiente shell con Google Cloud CLI già installato e con valori già impostati per il progetto attuale. L'inizializzazione della sessione può richiedere alcuni secondi.

  5. Definisci le variabili di ambiente necessarie per questo tutorial:
        export PROJECT=$(gcloud config get-value project)
        export REGION=us-central1
        export ZONE=${REGION}-b
        export CLUSTER=pubsub-proxy
        export TOPIC=proxy-test
        export SERVICE_ACCOUNT=publish-test
        export ENDPOINTS_SERVICE="pubtest.endpoints.${PROJECT}.cloud.goog"
        export GENERATE_TOKEN="https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts"
  6. Abilita le API per Cloud Build, Compute Engine, Google Kubernetes Engine, Artifact Analysis, Container Registry, Endpoints, Service Management, Service Control e Pub/Sub:
        gcloud services enable \
            cloudbuild.googleapis.com \
            compute.googleapis.com \
            container.googleapis.com \
            containeranalysis.googleapis.com \
            containerregistry.googleapis.com \
            endpoints.googleapis.com \
            servicemanagement.googleapis.com \
            servicecontrol.googleapis.com \
            pubsub.googleapis.com

Creazione di un argomento Pub/Sub

  • In Cloud Shell, crea un argomento Pub/Sub in cui pubblicare messaggi:

    gcloud pubsub topics create $TOPIC
    

Crea un cluster GKE

  1. In Cloud Shell, crea un cluster GKE:

    gcloud container clusters create $CLUSTER \
        --zone $ZONE \
        --scopes "https://www.googleapis.com/auth/cloud-platform"
    
  2. Recupera le credenziali per il cluster in esecuzione:

    gcloud container clusters get-credentials $CLUSTER \
        --zone $ZONE \
        --project $PROJECT
    

Creazione di un'immagine container in corso…

  1. In Cloud Shell, clona il repository di codice:

    git clone https://github.com/GoogleCloudPlatform/solutions-pubsub-proxy-rest
    
  2. Utilizza Cloud Build per creare un'immagine container dall'origine, quindi salvala in Container Registry:

    cd solutions-pubsub-proxy-rest && \
        gcloud builds submit --tag gcr.io/$PROJECT/pubsub-proxy:v1
    

Creazione di un indirizzo IP esterno statico

  1. In Cloud Shell, crea un indirizzo IP esterno statico che viene successivamente assegnato al bilanciatore del carico del proxy Pub/Sub:

    gcloud compute addresses create service-ip --region $REGION
    
  2. Archivia l'indirizzo IP statico in una variabile di ambiente, PROXY_IP:

    PROXY_IP=$(gcloud compute addresses describe service-ip \
        --region $REGION --format='value(address)')
    

Deployment di endpoint

Il proxy Pub/Sub utilizza gli endpoint per autenticare le richieste degli utenti. Endpoints utilizza Extensible Service Proxy (ESP) per fornire funzionalità di gestione delle API come autenticazione, monitoring, tracciamento e gestione del ciclo di vita delle API. Questo tutorial utilizza Endpoints solo per autenticare le richieste in entrata al proxy Pub/Sub.

In questo tutorial, eseguirai il deployment di ESP come sidecar con il proxy Pub/Sub. ESP intercetta e autentica le richieste in entrata prima di inoltrarle al proxy Pub/Sub.

  1. In Cloud Shell, sostituisci il segnaposto [PROJECT_ID] con l'ID del tuo progetto Google Cloud nel file openapi.yaml:

    sed -i -e "s/\[PROJECT_ID\]/$PROJECT/g" openapi.yaml
    
  2. Nel file manifest OpenAPI, sostituisci il segnaposto [IP_ADDRESS] con il valore di PROXY_IP:

    sed -i -e "s/\[IP_ADDRESS\]/$PROXY_IP/g" openapi.yaml
    
  3. Esegui il deployment della definizione del servizio OpenAPI su Endpoints:

    gcloud endpoints services deploy openapi.yaml
    

    Il comando precedente crea quanto segue:

    • Un servizio gestito con il nome specificato nel campo host del file openapi.yaml (pubtest.endpoints.project-id.cloud.goog), dove project-id è l'ID del progetto Google Cloud.
    • Un record A DNS che utilizza il nome del servizio e la mappatura dell'indirizzo IP del bilanciatore del carico proxy Pub/Sub definita nell'estensione x-google-endpoints del file openapi.yaml.

    Durante il deployment, viene visualizzato un avviso che puoi ignorare perché questo tutorial utilizza i token ID OIDC per l'autenticazione anziché le chiavi API.

    WARNING: openapi.yaml: Operation 'post' in path '/publish': Operation does
    not require an API key; callers may invoke the method without specifying an
    associated API-consuming project. To enable API key all the
    SecurityRequirement Objects
    (https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#security-requirement-object)
    inside security definition must reference at least one SecurityDefinition
    of type : 'apiKey'.
    
  4. Verifica che il deployment del servizio sia stato eseguito correttamente:

    gcloud endpoints services describe ${ENDPOINTS_SERVICE}
    

    L'output è simile al seguente:

    [...]
    producerProjectId: project-id
    serviceConfig:
      documentation:
        summary: Pub/Sub proxy exposed as an Endpoint API
    [...]
      name: pubtest.endpoints.project-id.cloud.goog
      title: PubSub Proxy
      usage: {}
    serviceName: pubtest.endpoints.project-id.cloud.goog
    

    Nell'output:

    • project-id: l'ID del tuo progetto Google Cloud.

Deployment di un proxy

  1. In Cloud Shell, genera un certificato SSL autofirmato per consentire le connessioni HTTPS al proxy.

    openssl req -x509 -nodes -days 365 \
        -newkey rsa:2048 -keyout ./nginx.key \
        -out ./nginx.crt \
        -subj "/CN=${ENDPOINTS_SERVICE}"
    
  2. Crea un secret Kubernetes utilizzando il certificato SSL e la chiave privata:

    kubectl create secret generic nginx-ssl \
        --from-file=./nginx.crt \
        --from-file=./nginx.key
    
  3. Sostituisci il segnaposto [PROJECT_ID] nel file manifest di deployment con il tuo ID progetto Google Cloud:

    sed -i -e "s/\[PROJECT_ID\]/$PROJECT/g" kube/deployment.yaml
    
  4. Sostituisci il segnaposto [IP_ADDRESS] nel file manifest del servizio con il valore PROXY_IP:

    sed -i -e "s/\[IP_ADDRESS\]/$PROXY_IP/g" kube/service.yaml
    
  5. Esegui il deployment del proxy:

    kubectl apply -f kube/
    
  6. Verifica che il deployment sia riuscito:

    kubectl rollout status deployment/pubsub-proxy
    

    L'output è simile al seguente:

    [...]
    deployment "pubsub-proxy" successfully rolled out
    
  7. Assicurati che due container (proxy EP e Pub/Sub) siano in esecuzione nel pod:

    kubectl get pods $(kubectl get pod \
        -l app=pubsub-proxy \
        -o jsonpath="{.items[0].metadata.name}") \
        -o jsonpath={.spec.containers[*].name}
    

    L'output è simile al seguente:

    esp  pubsub-proxy
    
  8. Controlla che il valore di EXTERNAL-IP passi da <pending> all'indirizzo IP esterno statico che hai creato in precedenza:

    kubectl get svc pubsub-proxy -w
    

    L'output è simile al seguente:

    NAME          TYPE          CLUSTER-IP    EXTERNAL-IP   PORT(S)        AGE
    pubsub-proxy  LoadBalancer  10.7.247.212  <pending>     443:31104/TCP  6m32s
    pubsub-proxy  LoadBalancer  10.7.247.212  <PROXY_IP>    443:31104/TCP  6m5s
    

    Per interrompere la visione, premi CTRL+C.

    Una volta eseguito il deployment del proxy Pub/Sub, il proxy viene esposto all'indirizzo https://${ENDPOINTS_SERVICE}/publish. La propagazione della nuova configurazione DNS potrebbe richiedere alcuni minuti.

  9. Verifica la configurazione DNS:

    watch nslookup ${ENDPOINTS_SERVICE}
    

    L'output è simile al seguente:

    Server:   169.254.169.254
    Address:  169.254.169.254#53
    
    Non-authoritative answer:
    Name: pubtest.endpoints.project-id.cloud.goog
    Address: gke-load-balancer-ip
    

    Nell'output:

    • gke-load-balancer-ip: l'indirizzo IP del bilanciatore del carico GKE (IP proxy).

    Per interrompere la visione, premi CTRL+C.

Se uno dei passaggi precedenti genera un errore, consulta la procedura per la risoluzione dei problemi.

Generazione di un token di autenticazione

La seguente procedura per la generazione di un token di autenticazione è da intendersi come esempio. Per il tuo ambiente di produzione, hai bisogno di un modo per consentire agli utenti di generare i propri token di autenticazione. Ad esempio, puoi trovare un codice campione per ottenere un token ID OIDC in modo programmatico nella documentazione di Identity-Aware Proxy.

Per generare un token di autenticazione:

  1. Crea un account di servizio Google Cloud per cui generare un token ID OIDC:

    gcloud iam service-accounts create \
        $SERVICE_ACCOUNT \
        --display-name $SERVICE_ACCOUNT
    
  2. Ottieni l'identità email dell'account di servizio:

    SA_EMAIL=${SERVICE_ACCOUNT}@${PROJECT}.iam.gserviceaccount.com
    
  3. Concedi il ruolo IAM Creatore token account di servizio (roles/iam.serviceAccountTokenCreator) per l'account di servizio:

    gcloud iam service-accounts add-iam-policy-binding $SA_EMAIL \
        --member user:$(gcloud config get-value account) \
        --role roles/iam.serviceAccountTokenCreator
    
  4. Utilizzando l'API IAM credenziali, genera un token ID OIDC.

    TOKEN=$(curl -s ${GENERATE_TOKEN}/${SA_EMAIL}:generateIdToken \
        -H "Content-Type: application/json" \
        -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
        -d '{"audience": "'${ENDPOINTS_SERVICE}'", "includeEmail": "true"}' | jq -r ".token")
    

    Il nome del servizio Endpoints è specificato nel campo audience. L'attestazione audience identifica il destinatario a cui è destinato il token.

  5. Verifica che il token sia stato creato correttamente:

    echo $TOKEN
    

    Il token web JSON (JWT) è simile al seguente:

    eyJhbGciOiJSUzI1NiIsImtpZCI6IjY4NjQyODlm[...].eyJhdWQiOiJwdWJ0ZXN0LmVuZHBvaW50cy52aXR
    hbC1vY3RhZ29uLTEwOTYxMi5jbG91ZC5nb[...].SjBI4TZjZAlYo6lFKkrvfAcVUp_AJzFKoSsjNbmD_n[...]
    

Chiamata a Pub/Sub tramite proxy

  1. In Cloud Shell, pubblica un messaggio di prova:

    curl -i -k -X POST https://${ENDPOINTS_SERVICE}/publish \
        -H "Authorization: Bearer $TOKEN" \
        -H "Content-Type: application/json" \
        -d '{"topic": "'$TOPIC'", "messages": [ {"attributes": {"key1": "value1", "key2" : "value2"}, "data": "test data"}]}'
    

    L'output è simile al seguente:

    HTTP/2 200
    server: nginx
    date: Sun, 02 Jun 2019 03:53:46 GMT
    ...
    
  2. Controlla se il messaggio è stato pubblicato correttamente nell'argomento Pub/Sub:

    kubectl logs -f --tail=5 deployment/pubsub-proxy -c pubsub-proxy
    

    I log di deployment del proxy Pub/Sub mostrano il messaggio Successfully published:

    2019-06-02 03:49:39.723:INFO:oejs.Server:main: Started @2554ms
    Jun 02, 2019 3:53:44 AM com.google.pubsub.proxy.publish.PublishMessage
    getPublisher
    INFO: Creating new publisher for: proxy-test
    Jun 02, 2019 3:53:47 AM
    com.google.pubsub.proxy.publish.PublishMessage$1 onSuccess
    INFO: Successfully published: 569006136173844
    

Risoluzione dei problemi

  1. In Cloud Shell, controlla lo stato di entrambi i container nel pod proxy Pub/Sub:

    kubectl describe pods $(kubectl get pod -l app=pubsub-proxy \
        -o jsonpath="{.items[0].metadata.name}")
    

    Nell'output del log, lo stato dei container è Running:

    [...]
    Containers:
      esp:
    [...]
      State:  Running
        Started:  Fri, 21 Jun 2019 16:41:30 +0530
      Ready:  True
      Restart Count:  0
    [...]
      pubsub-proxy:
        State:  Running
          Started:  Fri, 21 Jun 2019 16:41:42 +0530
        Ready:  True
        Restart Count:  0
    [...]
    
  2. (Facoltativo) Controlla i log del container per verificare se sono presenti altri errori. Ad esempio, per controllare i log del proxy Pub/Sub, esegui questo comando:

    kubectl logs -f --tail=10 deployment/pubsub-proxy -c pubsub-proxy
    

Per assistenza con la risoluzione dei problemi, consulta i seguenti documenti:

Esegui la pulizia

Per evitare che al tuo account Google Cloud vengano addebitati costi relativi alle risorse utilizzate in questo tutorial, puoi eliminare il progetto Google Cloud che hai creato per questo tutorial o le risorse associate a questo tutorial.

Elimina il progetto Google Cloud

Il modo più semplice per eliminare la fatturazione è eliminare il progetto che hai creato per il tutorial.

  1. Nella console Google Cloud, vai alla pagina Gestisci risorse.

    Vai a Gestisci risorse

  2. Nell'elenco dei progetti, seleziona il progetto che vuoi eliminare, quindi fai clic su Elimina.
  3. Nella finestra di dialogo, digita l'ID del progetto e fai clic su Chiudi per eliminare il progetto.

Elimina le risorse

Se vuoi mantenere il progetto Google Cloud che hai utilizzato in questo tutorial, elimina le singole risorse:

  1. In Cloud Shell, elimina il cluster GKE:

    gcloud container clusters delete $CLUSTER --zone $ZONE --async
    
  2. Elimina il codice scaricato, gli artefatti e altre dipendenze:

    cd .. && rm -rf solutions-pubsub-proxy-rest
    
  3. Elimina l'immagine in Container Registry:

    gcloud container images list-tags \
        gcr.io/$PROJECT/pubsub-proxy \
        --format 'value(digest)' | \
        xargs -I {} gcloud container images delete \
        --force-delete-tags --quiet \
        gcr.io/${PROJECT}/pubsub-proxy@sha256:{}
    
  4. Elimina l'argomento Pub/Sub:

    gcloud pubsub topics delete $TOPIC
    
  5. Elimina l'account di servizio:

    gcloud iam service-accounts delete $SA_EMAIL
    
  6. Elimina endpoint:

    gcloud endpoints services delete ${ENDPOINTS_SERVICE}
    
  7. Elimina l'indirizzo IP statico:

    gcloud compute addresses delete service-ip --region $REGION
    

Passaggi successivi