Integra Cloud Run e la federazione delle identità per i carichi di lavoro


Questo tutorial descrive come utilizzare la federazione delle identità per i carichi di lavoro per autenticare i carichi di lavoro in esecuzione al di fuori di Google Cloud, in modo che possano accedere ai microservizi ospitati da Cloud Run. Questo tutorial è destinato agli amministratori che vogliono integrare la federazione delle identità per i carichi di lavoro con il proprio provider di identità (IdP) esistente. La federazione delle identità per i carichi di lavoro consente di connettere i carichi di lavoro esterni ai carichi di lavoro eseguiti in Google Cloud. Cloud Run ti consente di eseguire microservizi containerizzati stateless.

Questo tutorial fornisce istruzioni su come configurare Jenkins come carico di lavoro esterno, Keycloak come IdP, Cloud Run e federazione delle identità per i carichi di lavoro. Quando completi questo tutorial, puoi vedere in che modo la federazione delle identità per i carichi di lavoro ti consente di autenticare la tua applicazione Jenkins con Google Cloud utilizzando l'autenticazione OpenID Connect.

Autenticazione dei carichi di lavoro esterni mediante chiavi degli account di servizio

Se il tuo carico di lavoro viene eseguito al di fuori di Google Cloud, devi autenticare in modo sicuro il carico di lavoro in modo che possa interagire con il microservizio ospitato da Cloud Run. Tradizionalmente, potresti utilizzare uno strumento come Librerie client Cloud per autenticare e passare una chiave dell'account di servizio al fine di eseguire l'autenticazione con un carico di lavoro esterno. Le librerie client di Cloud utilizzano una libreria denominata ADC (ApplicationDefault Credentials) per trovare automaticamente le credenziali dell'account di servizio. Questa libreria imposta una variabile di ambiente denominata GOOGLE_APPLICATION_CREDENTIALS. ADC utilizza la chiave dell'account di servizio o il file di configurazione a cui punta la variabile per autenticare automaticamente il tuo account.

Tuttavia, questo approccio presenta i seguenti rischi per la sicurezza:

  • Per impostazione predefinita, una chiave dell'account di servizio non include una data di scadenza. Se il tuo codice viene divulgato, puoi esporre tutte le autorizzazioni associate alla chiave.
  • Poiché le chiavi dell'account di servizio sono statiche, devi creare una strategia per gestirle e ruotarle.

Anche se la creazione di una chiave dell'account di servizio è un processo abbastanza semplice, potresti sacrificare la sicurezza per la semplicità.

Autenticazione dei carichi di lavoro esterni tramite la federazione delle identità per i carichi di lavoro

La federazione delle identità per i carichi di lavoro risolve i rischi per la sicurezza derivanti dalla creazione e dal download di chiavi statiche degli account di servizio. La federazione delle identità per i carichi di lavoro consente di autenticare i carichi di lavoro all'esterno di Google Cloud senza utilizzare una chiave statica dell'account di servizio. Qualsiasi carico di lavoro esterno che deve utilizzare servizi in Google Cloud può trarre vantaggio da questa funzionalità.

La federazione delle identità per i carichi di lavoro consente di utilizzare il tuo IdP per eseguire l'autenticazione direttamente con Google Cloud. Per l'autenticazione, utilizza OpenID Connect. Cloud Run accetta i token OpenID Connect dal tuo IdP per l'autenticazione.

Il processo di autenticazione quando si utilizza la federazione delle identità per i carichi di lavoro è il seguente:

  1. La libreria di autenticazione (AUTHN) invia una richiesta di token web JSON (JWT) all'IdP.
  2. L'IdP firma i token JWT (JSON Web Token). La libreria AUTHN legge questi dati da una variabile.
  3. La libreria invia un comando POST al servizio token di sicurezza che include il token firmato.
  4. Il servizio token di sicurezza esamina il provider di pool di identificazione dei carichi di lavoro che hai configurato per creare un attendibilità e verifica l'identità della credenziale.
  5. Il servizio token di sicurezza restituisce un token federato.
  6. La libreria invia il token a IAM.
  7. IAM scambia il token con un token OpenID Connect di un account di servizio. Per ulteriori informazioni, consulta Generazione di token ID OpenID Connect.
  8. La libreria fornisce il token OpenID Connect a Jenkins.
  9. Jenkins utilizza questo token per l'autenticazione con Cloud Run.

Il seguente diagramma illustra il flusso di autenticazione:

Flusso di autenticazione.

Obiettivi

  • Configura Jenkins come carico di lavoro esterno.
  • Configura Keycloak come IdP compatibile con OpenID Connect.
  • Collega Jenkins a Keycloak.
  • Installa le librerie client di Cloud per ottenere il token JWT da Keycloak a Google Cloud.
  • Connetti Google Cloud a Keycloak e Jenkins.
  • Recupera il JWT per l'utente autenticato da Keycloak.

Anche se questo tutorial utilizza Keycloak, puoi utilizzare qualsiasi provider di identità che supporti OpenID Connect, come GitLab, Okta o OneLogin.

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 dei progetti.

    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. Configurare un microservizio su Cloud Run. Per saperne di più, consulta la guida rapida: deployment di un container in Cloud Run.

Configura Jenkins

Completa queste attività in un ambiente non Google Cloud, ad esempio nel tuo ambiente on-premise o su un altro cloud.

Se hai già un provider di identità che supporta OpenID Connect e un carico di lavoro esterno, puoi saltare questo passaggio e consultare la sezione Installazione delle librerie client di Cloud.

Per simulare un carico di lavoro esterno, puoi utilizzare una VM in cui è installato Jenkins. Puoi eseguire Jenkins come immagine Docker o installarlo direttamente sul tuo server. I passaggi seguenti mostrano come installarlo direttamente sul server.

  1. Apri una riga di comando su una VM di tua scelta.
  2. Installa Java:

    $ sudo apt update
    $ sudo apt install openjdk-11-jre
    $ java -version
    
  3. Installa Jenkins:

    curl -fsSL https://pkg.jenkins.io/debian-stable/jenkins.io.key | sudo tee \
    /usr/share/keyrings/jenkins-keyring.asc > /dev/null
    echo deb [signed-by=/usr/share/keyrings/jenkins-keyring.asc] \
    https://pkg.jenkins.io/debian-stable binary/ | sudo tee \
    /etc/apt/sources.list.d/jenkins.list > /dev/null
    sudo apt-get update
    sudo apt-get install jenkins
    
  4. Verifica di poter accedere al server Jenkins sulla porta 8080. Se utilizzi una VM protetta da un firewall, assicurati che siano aperte le porte appropriate.

  5. Ottieni la password di amministratore e configura Jenkins. Per le istruzioni, consulta la sezione Configurazione guidata post-installazione.

  6. Completa le seguenti azioni per configurare SSL:

    1. Se hai un provider di dominio, puoi utilizzare la sua autorità di certificazione (CA) per richiedere un certificato firmato. In alternativa, puoi ottenere un certificato firmato gratuito che dura 90 giorni su zerossl.com.
    2. Scarica il file ZIP del certificato e trasferiscilo al server su cui è in esecuzione Jenkins:

      scp -i CERTFILE.pem -r CERTFILE.zip VM_FQDN:/home/USERNAME
      

      Sostituisci quanto segue:

      • CERTFILE con il nome del file del certificato che include la chiave pubblica.
      • VM_FQDN con il nome di dominio completo del tuo server esterno a Google Cloud.
      • USERNAME con il tuo nome utente.
    3. Rinomina i file e genera un file .pkcs12 che Jenkins può utilizzare:

      openssl rsa -in KEYFILE.com.key -out KEYFILE.com.key

      Sostituisci KEYFILE con il nome del file del certificato.

  7. Aggiorna il file /etc/sysconfig/jenkins:

    1. Apri il file in un editor di testo:

      vi /etc/sysconfig/jenkins
      
    2. Imposta JENKINS_PORT su -1.

    3. Imposta JENKINS_HTTPS_PORT su 8443.

    4. Alla fine del file, aggiungi i seguenti argomenti:

      JENKINS_ARGS="--httpsCertificate=/var/lib/jenkins/.ssl/CERTFILE.crt --httpsPrivateKeys=/var/lib/jenkins/.ssl/KEYFILE.pkcs1.key"

      Sostituisci quanto segue:

      • CERTFILE con il nome del file del certificato in formato .crt.
      • KEYFILE con il nome file della chiave PKCS.
  8. Riavvia il server Jenkins.

  9. Verifica che la porta 8443 sia aperta sul firewall e che tu possa accedere a Jenkins sulla porta 8443.

  10. Installa il plug-in Jenkins di cui hai bisogno per integrare Keycloak con Jenkins. Puoi scegliere una delle seguenti opzioni:

    Per installare il plug-in:

    1. Nella dashboard di Jenkins, vai a Manage Jenkins > Gestisci plug-in.
    2. Seleziona Available e cerca il plug-in che preferisci. Il seguente screenshot mostra il Gestore plug-in con la scheda Disponibile selezionata.

      Gestore dei plug-in di Jenkins.

    3. Installa il plug-in.

Configura keycloak

In questo tutorial, Keycloak gestisce gli utenti, i gruppi e i ruoli. Keycloak utilizza le realms per gestire gli utenti.

  1. Sulla VM in esecuzione all'esterno di Google Cloud, installa il server Keycloak. Per questo tutorial, ti consigliamo di installare Keycloak da un container Docker.

  2. Apri la console di amministrazione di Keycloak.

  3. Vai alle Impostazioni di Realm.

  4. Nella scheda Generale, verifica che i campi siano impostati come segue:

    • Attivata: ON
    • Accesso gestito dall'utente: OFF
    • Endpoint: Configurazione endpoint OpenID e Metadati del provider di identità SAML 2.0

    Il seguente screenshot mostra i campi che devi configurare.

    Impostazioni generali keycloak.

  5. Crea un client in modo da avere un'entità che possa richiedere Keycloak per autenticare un utente. Spesso i client sono applicazioni e servizi che usano Keycloak per fornire una soluzione Single Sign-On (SSO).

    1. Nella Console di amministrazione Keycloak, fai clic su Client > Crea.
    2. Inserisci quanto segue:

      • ID client: jenkins
      • Protocollo client: openid-connect
      • URL radice: http://JENKINS_IP_ADDRESS:8080, dove JENKINS_IP_ADDRESS è l'indirizzo IP del tuo server Jenkins.

      Il seguente screenshot mostra i campi che devi configurare.

      Aggiunta di un client Keycloak.

    3. Fai clic su Salva.

  6. Nella scheda Installazione, verifica che il formato del token sia Keycloak OIDC JSON. Crea una copia di questo token perché ti servirà per completare la configurazione di Jenkins.

  7. Per creare un gruppo di test:

    1. Nella Console di amministrazione Keycloak, fai clic su Gruppi > Nuovo.
    2. Inserisci un nome per il gruppo e fai clic su Salva.
    3. Crea un altro gruppo di test. Puoi assegnare ruoli ai gruppi, ma questo tutorial non li richiede.
  8. Per creare un utente di test da aggiungere al gruppo:

    1. Nella Console di amministrazione Keycloak, fai clic su Gestisci utente > Aggiungi utenti.
    2. Inserisci le informazioni utente e fai clic su Salva.

      Il seguente screenshot mostra informazioni di esempio per un account utente.

      Aggiunta di un utente tramite keycloak.

    3. Fai clic sulla scheda Credenziali e verifica che l'opzione Temporanee sia impostata su Off.

    4. Reimposta la password.

      Utilizzerai questo account in un secondo momento nel JWT per l'autenticazione.

      Lo screenshot seguente mostra la scheda Credenziali con i campi che devi configurare.

      Modifica password del keycloak.

    5. Fai clic sulla scheda Gruppi e seleziona uno dei gruppi che hai creato in precedenza.

    6. Fai clic su Partecipa.

    7. Ripeti questo passaggio per creare altri utenti di test.

Configura la configurazione di Jenkins per OpenID Connect

Questa sezione descrive come configurare il plug-in OpenID Connect per Jenkins.

  1. Sul server Jenkins, vai a Manage Jenkins > Configure Global Security.
  2. In Security Realm, seleziona Keycloak Authentication Plugin. Fai clic su Salva.

  3. Fai clic su Configura sistema.

  4. Nelle impostazioni Global Keycloak, copia il codice JSON di installazione di Keycloak creato in Configura Keycloak. Se devi recuperare nuovamente i dati JSON, completa quanto segue:

    1. Nella Console di amministrazione Keycloak, vai a Client.

    2. Fai clic sul nome del cliente.

    3. Nella scheda Installazione, fai clic su Opzione formato e seleziona JSON OIDC Keycloak.

    Di seguito è riportato un esempio di JSON Keycloak:

    {
        "realm":"master"
        "auth-server-url":"AUTHSERVERURL"
        "ssl-required":"none"
        "resource":"jenkins"
        "public-client":true
        "confidential-port":0
    }
    

    AUTHSERVERURL è l'URL del server di autenticazione.

  5. Per salvare la configurazione OIDC, fai clic su Salva.

Jenkins ora può reindirizzare a Keycloak per ottenere informazioni sugli utenti.

Installazione delle librerie client di Cloud

Per inviare un JWT da Keycloak a Google Cloud, devi installare le librerie client di Cloud sul server Jenkins. Questo tutorial usa Python per interagire con Google Cloud usando l'SDK.

  1. Installa Python sul server Jenkins. I seguenti passaggi mostrano come installare python3:

    sudo apt update
    sudo apt install software-properties-common
    sudo add-apt-repository ppa:deadsnakes/ppa
    sudo apt update
    sudo apt install python3.8
    
  2. Installa pip3 per scaricare e importare le librerie client di Cloud:

    pip3 –version
    sudo apt update
    sudo apt install python3-pip
    pip3 –version
    
  3. Installa le librerie client di Cloud per Python utilizzando pip3:

    pip3 install –upgrade google-api-python-client google-auth-httplib2 google-auth-oauthlib
    

    Ad esempio:

    pip3 install --upgrade google-api-python-client google-auth-httplib2 google-auth-oauthlib
    Collecting google-api-python-client
        Downloading google_api_python_client-2.42.0-py2.py3-none-any.whl (8.3 MB)
            USERNAME | 8.3 MB 19.9 MB/s
    Collecting google-auth-httplib2
        Downloading google_auth_httplib2-0.1.0-py2.py3-none-any.whl (9.3 MB)
    Collecting google-auth-oauthlib
    Downloading google_auth_oauthlib-0.5.1-py2.py3-non-any.whl (19 KB)
    

    Sostituisci USERNAME con il tuo nome utente.

  4. Installa Google Cloud CLI sul tuo server Jenkins. Per le istruzioni, consulta la Guida rapida: installazione di gcloud CLI.

Configura il tuo ambiente Google Cloud

Questa sezione descrive i passaggi da completare per garantire che l'ambiente Google Cloud che ospita il container serverless possa connettersi con Jenkins e Keycloak.

  1. In Google Cloud, crea un account di servizio in modo che il microservizio su Cloud Run possa accedere alle autorizzazioni associate. Ad esempio, per creare un account di servizio utilizzando gcloud CLI, esegui queste operazioni:

    gcloud iam service-accounts create cloudrun-oidc \
      –-description="cloud run oidc sa"  \
      –-display-name="cloudrun-oidc"
    

    Per impostazione predefinita, Cloud Run crea un account di servizio predefinito per te. Tuttavia, l'utilizzo dell'account di servizio predefinito non è una best practice per la sicurezza perché l'account ha un ampio set di autorizzazioni. Consigliamo quindi di creare un account di servizio separato per il microservizio. Per istruzioni sulla creazione di un account di servizio per Cloud Run, consulta Creazione e gestione degli account di servizio.

  2. Crea un pool di identità per i carichi di lavoro. Per creare un pool utilizzando gcloud CLI, esegui questo comando:

    gcloud iam workload-identity-pools create cloudrun-oidc-pool \
      --location="global" \
      —-description="cloudrun-oidc" \
      —-display-name="cloudrun-oidc"
    
  3. Crea un provider del pool di identità per i carichi di lavoro per OpenID Connect:

    gcloud iam workload-identity-pools providers create-oidc cloud-run-provider \
      --workload-identity-pool="cloudrun-oidc-pool" \
      --issuer-uri="VAR_LINK_TO_ENDPOINT" \
      --location="global" \
      --attribute-mapping ="google.subject=assertion.sub,attribute.isadmin-assertion.isadmin,attribute.aud=assertion.aud" \
      --attribute-condition="attribute.isadmin=='true'"
    

    Sostituisci VAR_LINK_TO_ENDPOINT con una variabile che contiene il link all'endpoint OIDC Keycloak. Per trovare questo link, nella finestra Realm della console di amministrazione KeyCloud, fai clic sulla scheda General (Generale). L'endpoint deve essere HTTPS, il che significa che devi configurare il server Keycloak con HTTPS.

recupera il JWT per l'utente autenticato da Keycloak

  1. Sulla VM che esegue Keycloak, scarica il token in un file di testo. Ad esempio, su Linux, esegui questo comando:

    curl -L -X POST 'https://IP_FOR_KEYCLOAK:8080/auth/realms/master/protocol/openid-connect/token' -H 'Content-Type: application/x-www-form-urlencoded' \
      --data-urlencode 'client_id=jenks' \
      --data-urlencode 'grant_type=password' \
      --data-urlencode 'client_secret=CLIENT_SECRET \
      --data-urlencode 'scope=openid' \
      --data-urlencode 'username=USERNAME' \
      --data-urlencode 'password=PASSWORD' | grep access_token | cut -c18-1490 > token.txt
    

    Sostituisci quanto segue:

    • IP_FOR_KEYCLOAK con l'indirizzo IP del server Keycloak.
    • CLIENT_SECRET con il client secret Keycloak.
    • USERNAME con un utente Keycloak.
    • PASSWORD con la password per l'utente Keycloak.

    Questo comando include l'ID client, il client secret, il nome utente e la password. Come best practice per la sicurezza, consigliamo di utilizzare le variabili di ambiente per mascherare questi valori anziché la riga di comando. Il comando di esempio reindirizza le credenziali a un file denominato token.txt.

    Se vuoi, per automatizzare questo passaggio puoi creare uno script bash.

  2. Convalida il token all'indirizzo jwt.io.

  3. Sulla VM, crea il tuo file delle credenziali:

    gcloud iam workload-identity-pools create-cred config \
    projects/$PROJECT_NUMBER/locations/global/workloadIdentityPools/cloudrun-oidc-pool/providers/cloud-run/provider \
      --output-file=sts-creds.json \
      --credential-source-file=token.txt
    

    Per ulteriori informazioni, consulta gcloud iam workload-identity-pools create-cred-config.

    Il file di output dovrebbe avere il seguente aspetto:

    {
        "type": "external_account",
        "audience": "//iam.google.apis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/cloudrun-oidc-pool/subject/USER_EMAIL",
        "subject_token_type": "urn:ietf:params:oauth:token-type:jwt",
        "token_url": "https://sts.googleapis.com/v1/token",
        "credential_source": {
            "file" "token.txt" }
    }
    

    PROJECT_NUMBER è il numero del progetto.

  4. Nella VM, imposta il file sts.creds.json come variabile per ADC:

    export GOOGLE_APPLICATION_CREDENTIALS=/Users/USERNAME/sts-creds.json
    

    Sostituisci USERNAME con il tuo nome utente UNIX.

    Prima del lancio della federazione delle identità per i carichi di lavoro, questo valore era la chiave dell'account di servizio. Con la federazione delle identità per i carichi di lavoro, questo valore corrisponde al file delle credenziali appena creato.

  5. Crea un'associazione di ruoli per consentire all'utente di impersonare l'account di servizio:

    gcloud iam service-accounts add-iam-policy-binding SERVICE_ACCOUNT \
        --role roles/iam.workloadIdentityUser \
        --member "principal://iam.googleapis.com/projects/$PROJECT_NUMBER/locations/global/workloadIdentityPools/cloudrun-oidc-pool/subject/USER_EMAIL
    

    Sostituisci quanto segue:

  6. Consenti all'account di servizio di accedere al servizio Cloud Run:

    gcloud run services add-iam-policy-binding SERVICE_NAME
      --member-"serviceAccount:SERVICE_ACCOUNT" \
      --role="roles/run.invoker"
    

    Sostituisci quanto segue:

    • SERVICE_NAME con il nome del microservizio in esecuzione su Cloud Run.

    • SERVICE_ACCOUNT con l'indirizzo email dell'account di servizio per Cloud Run.

    Per ulteriori informazioni, consulta gcloud run services add-iam-policy-binding.

  7. Genera un token ID:

    #!/usr/bin/python
    from google.auth import credentials
    from google.cloud import  iam_credentials_v1
    
    import google.auth
    import google.oauth2.credentials
    
    from google.auth.transport.requests import AuthorizedSession, Request
    
    url = "https://WORKLOAD_FQDN"
    aud = "https://WORKLOAD_FQDN"
    service_account = 'SERVICE_ACCOUNT'
    
    name = "projects/-/serviceAccounts/{}".format(service_account)
    id_token = client.generate_id_token(name=name,audience=aud, include_email=True)
    
    print(id_token.token)
    
    creds = google.oauth2.credentials.Credentials(id_token.token)
    authed_session = AuthorizedSession(creds)
    r = authed_session.get(url)
    print(r.status_code)
    print(r.text)
    

    Sostituisci quanto segue:

    • WORKLOAD_FQDN con il nome di dominio completo per il carico di lavoro.

    • SERVICE_ACCOUNT con l'indirizzo email dell'account di servizio per Cloud Run.

Il token che utilizzi può chiamare l'API Identity and Access Management, che ti fornirà il nuovo JWT necessario per richiamare il servizio Cloud Run.

Puoi utilizzare il token all'interno di una pipeline Jenkins per richiamare il container serverless che stai eseguendo in Cloud Run. Tuttavia, questi passaggi non rientrano nell'ambito di questo tutorial.

Esegui la pulizia

Per evitare che al tuo account Google Cloud vengano addebitati costi relativi alle risorse utilizzate in questo tutorial, puoi eliminare il tuo progetto.

Elimina il progetto

  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.

Passaggi successivi