Integre o Cloud Run e a federação de identidade da carga de trabalho


Este tutorial descreve como usar a Workload Identity Federation para autenticar cargas de trabalho executadas fora do Google Cloud , de modo que possam aceder a microsserviços alojados pelo Cloud Run. Este tutorial destina-se a administradores que pretendem integrar a federação de identidade da carga de trabalho com o respetivo fornecedor de identidade (IdP) existente. A federação de identidades da carga de trabalho permite-lhe ligar cargas de trabalho externas a cargas de trabalho executadas no Google Cloud. O Cloud Run permite-lhe executar microserviços contentorizados sem estado.

Este tutorial fornece instruções sobre como configurar o Jenkins como a sua carga de trabalho externa, o Keycloak como o seu IdP, o Cloud Run e a Workload Identity Federation. Quando concluir este tutorial, pode ver como a Workload Identity Federation lhe permite autenticar a sua aplicação Jenkins com o Google Cloud usando a autenticação OpenID Connect. Google Cloud

Autenticação de cargas de trabalho externas através da Workload Identity Federation

A federação de identidades da carga de trabalho permite-lhe autenticar cargas de trabalho fora do Google Cloud sem usar uma chave de conta de serviço estática. Qualquer carga de trabalho externa que precise de consumir serviços emGoogle Cloud pode beneficiar desta funcionalidade.

A Workload Identity Federation permite-lhe usar o seu IdP para fazer a autenticação diretamente com o Google Cloud. Para autenticar, usa o OpenID Connect. O Cloud Run aceita tokens OpenID Connect do seu IdP para autenticação.

O processo de autenticação quando usa a Workload Identity Federation é o seguinte:

  1. A sua biblioteca de autenticação (AUTHN) envia um pedido de token da Web JSON (JWT) para o IdP.
  2. O seu IdP assina os símbolos da Web JSON (JWT). A biblioteca AUTHN lê estes dados a partir de uma variável.
  3. A biblioteca envia um comando POST para o Serviço de tokens de segurança que inclui o token assinado.
  4. O serviço de tokens de segurança analisa o fornecedor do Workload Identity Pool que configurou para criar confiança e valida a identidade na credencial.
  5. O serviço de tokens de segurança envia de volta um token de acesso federado.
  6. A biblioteca envia a chave de acesso federado para o IAM.
  7. O IAM troca o token de acesso federado por um token de ID. Para mais informações, consulte o artigo Crie um token de ID do OpenID Connect (OIDC).
  8. A biblioteca fornece o token de ID ao Jenkins.
  9. O Jenkins usa este token para fazer a autenticação no Cloud Run.

O diagrama seguinte demonstra o fluxo de autenticação:

Fluxo de autenticação.

Objetivos

  • Configure o Jenkins como a carga de trabalho externa.
  • Configure o Keycloak como o IdP compatível com o OpenID Connect.
  • Associe o Jenkins ao Keycloak.
  • Instale as bibliotecas cliente da nuvem para obter o token JWT do Keycloak para Google Cloud.
  • Associe Google Cloud ao Keycloak e ao Jenkins.
  • Obtenha o JWT para o utilizador autenticado a partir do Keycloak.

Embora este tutorial use o Keycloak, pode usar qualquer fornecedor de identidade que suporte o OpenID Connect, como o GitLab, o Okta ou o OneLogin.

Custos

Neste documento, usa os seguintes componentes faturáveis do Google Cloud:

Para gerar uma estimativa de custos com base na sua utilização projetada, use a calculadora de preços.

Os novos Google Cloud utilizadores podem ser elegíveis para uma avaliação gratuita.

Quando terminar as tarefas descritas neste documento, pode evitar a faturação contínua eliminando os recursos que criou. Para mais informações, consulte o artigo Limpe.

Antes de começar

  1. In the Google Cloud console, go to the project selector page.

    Go to project selector

  2. Select or create a Google Cloud project.

  3. Verify that billing is enabled for your Google Cloud project.

  4. Configure um microsserviço no Cloud Run. Para mais informações, consulte o artigo Início rápido: implemente um contentor no Cloud Run.

Configure o Jenkins

Conclua estas tarefas num ambiente que não seja oGoogle Cloud , como o seu ambiente no local ou noutra nuvem.

Se já tiver um fornecedor de identidade que suporte o OpenID Connect e uma carga de trabalho externa, pode ignorar este passo e aceder a Instalar bibliotecas de cliente da nuvem.

Para simular uma carga de trabalho externa, pode usar uma VM com o Jenkins instalado na mesma. Pode executar o Jenkins como uma imagem do Docker ou instalá-lo diretamente no seu servidor. Os passos seguintes demonstram como instalá-lo diretamente no servidor.

  1. Numa VM à sua escolha, abra uma linha de comandos.
  2. Instale o Java:

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

    curl -fsSL https://pkg.jenkins.io/debian-stable/jenkins.io-2023.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. Confirme se consegue aceder ao seu servidor Jenkins na porta 8080. Se estiver a usar uma VM que se encontra atrás de uma firewall, certifique-se de que as portas adequadas estão abertas.

  5. Obtenha a palavra-passe de administrador e configure o Jenkins. Para ver instruções, consulte o artigo Assistente de configuração pós-instalação.

  6. Conclua as seguintes ações para configurar o SSL:

    1. Se tiver um fornecedor de domínio, pode usar a respetiva autoridade de certificação (AC) para pedir um certificado assinado. Em alternativa, pode obter um certificado assinado gratuito com uma validade de 90 dias em zerossl.com.
    2. Transfira o ficheiro ZIP do certificado e transfira-o para o servidor que está a executar o Jenkins:

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

      Substitua o seguinte:

      • CERTFILE com o nome do ficheiro do certificado que inclui a sua chave pública.
      • VM_FQDN com o FQDN do seu servidor fora de Google Cloud.
      • USERNAME com o seu nome de utilizador.
    3. Mude o nome dos ficheiros e gere um ficheiro .pkcs12 que o Jenkins possa usar:

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

      Substitua KEYFILE pelo nome do ficheiro de certificado.

  7. Atualize o ficheiro /etc/sysconfig/jenkins:

    1. Abra o ficheiro num editor de texto:

      vi /etc/sysconfig/jenkins
      
    2. Defina JENKINS_PORT como -1.

    3. Defina JENKINS_HTTPS_PORT como 8443.

    4. Na parte inferior do ficheiro, adicione os seguintes argumentos:

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

      Substitua o seguinte:

      • CERTFILE com o nome de ficheiro do certificado no formato .crt.
      • KEYFILE com o nome do ficheiro da chave PKCS.
  8. Reinicie o servidor do Jenkins.

  9. Verifique se tem a porta 8443 aberta na firewall e aceda ao Jenkins na porta 8443.

  10. Instale um plug-in do Jenkins necessário para integrar o Keycloak com o Jenkins. Pode escolher uma das seguintes opções:

    Para instalar o plug-in, faça o seguinte:

    1. No painel de controlo do Jenkins, aceda a Manage Jenkins > Manage Plugins.
    2. Selecione Disponível e pesquise o plugin que quer. A captura de ecrã seguinte mostra o Gestor de plug-ins com o separador Disponível selecionado.

      Gestor de plug-ins do Jenkins.

    3. Instale o plug-in.

Configure o Keycloak

Neste tutorial, o Keycloak gere os utilizadores, os grupos e as funções. O Keycloak usa domínios para gerir utilizadores.

  1. Na VM que está a ser executada fora do Google Cloud, instale o servidor Keycloak. Para este tutorial, recomendamos que instale o Keycloak a partir de um contentor do Docker.

  2. Abra a consola de administração do Keycloak.

  3. Aceda às definições do domínio.

  4. No separador Geral, verifique se os campos estão definidos da seguinte forma:

    • Ativado: ATIVADO
    • Acesso gerido pelo utilizador: DESATIVADO
    • Pontos finais: configuração do ponto final do OpenID e metadados do fornecedor de identidade SAML 2.0

    A captura de ecrã seguinte mostra os campos que tem de configurar.

    Definições gerais do Keycloak.

  5. Crie um cliente para ter uma entidade que possa pedir ao Keycloak para autenticar um utilizador. Muitas vezes, os clientes são aplicações e serviços que usam o Keycloak para fornecer uma solução de início de sessão único (SSO).

    1. Na consola de administração do Keycloak, clique em Clientes > Criar.
    2. Introduza os seguintes dados:

      • ID do cliente: jenkins
      • Protocolo do cliente: openid-connect
      • URL raiz: http://JENKINS_IP_ADDRESS:8080, onde JENKINS_IP_ADDRESS é o endereço IP do seu servidor Jenkins.

      A captura de ecrã seguinte mostra os campos que tem de configurar.

      Keycloak add client.

    3. Clique em Guardar.

  6. No separador Instalação, verifique se o formato do token é Keycloak OIDC JSON. Faça uma cópia deste token, pois vai precisar dele para concluir a configuração do Jenkins.

  7. Para criar um grupo de teste, faça o seguinte:

    1. Na consola de administração do Keycloak, clique em Groups > New.
    2. Introduza um nome para o grupo e clique em Guardar.
    3. Crie mais um grupo de teste. Pode atribuir funções aos seus grupos, mas este tutorial não as requer.
  8. Para criar um utilizador de teste para adicionar ao grupo, faça o seguinte:

    1. Na consola do administrador do Keycloak, clique em Gerir utilizador > Adicionar utilizadores.
    2. Preencha as informações do utilizador e clique em Guardar.

      A captura de ecrã seguinte mostra informações de exemplo para uma conta de utilizador.

      Keycloak add user.

    3. Clique no separador Credenciais e verifique se a opção Temporário está definida como Desativado.

    4. Reponha a palavra-passe.

      Vai usar esta conta mais tarde no JWT para autenticação.

      A captura de ecrã seguinte mostra o separador Credenciais com os campos que tem de configurar.

      Alteração da palavra-passe do Keycloak.

    5. Clique no separador Grupos e selecione um dos grupos que criou anteriormente.

    6. Clique em Participar.

    7. Repita este passo para criar mais utilizadores de teste.

Configure o Jenkins para a configuração do OpenID Connect

Esta secção descreve como configurar o plug-in OpenID Connect para o Jenkins.

  1. No servidor Jenkins, aceda a Manage Jenkins > Configure Global Security.
  2. Em Security Realm, selecione Keycloak Authentication Plugin. Clique em Guardar.

  3. Clique em Configurar sistema.

  4. Nas definições Global Keycloak, copie o JSON de instalação do Keycloak que criou em Configure o Keycloak. Se precisar de obter novamente os dados JSON, conclua o seguinte:

    1. Na consola do administrador do Keycloak, aceda a Clientes.

    2. Clique no nome do cliente.

    3. No separador Instalação, clique em Opção de formato e selecione JSON OIDC do Keycloak.

    Segue-se um exemplo de JSON do Keycloak:

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

    O AUTHSERVERURL é o URL do seu servidor de autenticação.

  5. Para guardar a configuração do OIDC, clique em Guardar.

O Jenkins pode agora redirecionar para o Keycloak para obter informações do utilizador.

Instale as bibliotecas de cliente do Google Cloud

Para enviar um JWT do Keycloak para o Google Cloud, tem de instalar as bibliotecas cliente da Google Cloud no servidor do Jenkins. Este tutorial usa o Python para interagir com o Google Cloud usando o SDK.

  1. No servidor do Jenkins, instale o Python. Os passos seguintes mostram como instalar o Python 3:

    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. Instale o pip3 para poder transferir e importar as bibliotecas cliente do Google Cloud:

    pip3 –version
    sudo apt update
    sudo apt install python3-pip
    pip3 –version
    
  3. Instale as bibliotecas cliente da Google Cloud para Python com o pip3:

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

    Por exemplo:

    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)
    

    Substitua USERNAME pelo seu nome de utilizador.

  4. Instale a Google Cloud CLI no seu servidor Jenkins. Para ver instruções, consulte o Início rápido: instale a CLI gcloud.

Configure o seu Google Cloud ambiente

Esta secção descreve os passos que tem de concluir para garantir que o seu Google Cloud ambiente que aloja o contentor sem servidor consegue estabelecer ligação com o Jenkins e o Keycloak.

  1. No Google Cloud, crie uma conta de serviço para que o microsserviço no Cloud Run possa aceder às autorizações anexadas à mesma. Por exemplo, para criar uma conta de serviço através da CLI gcloud, faça o seguinte:

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

    Por predefinição, o Cloud Run cria uma conta de serviço predefinida para si. No entanto, a utilização da conta de serviço predefinida não é uma prática recomendada de segurança, uma vez que a conta tem um conjunto alargado de autorizações. Por conseguinte, recomendamos que crie uma conta de serviço separada para o seu microsserviço. Para ver instruções sobre como criar uma conta de serviço para o Cloud Run, consulte o artigo Criar e gerir contas de serviço.

  2. Crie um Workload Identity Pool. Para criar um conjunto com a CLI gcloud, execute o seguinte comando:

    gcloud iam workload-identity-pools create cloudrun-oidc-pool \
      --location="global" \
      —-description="cloudrun-oidc" \
      —-display-name="cloudrun-oidc"
    
  3. Crie um fornecedor do Workload Identity Pool para o 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'"
    

    Substitua VAR_LINK_TO_ENDPOINT por uma variável que contenha o link para o ponto final OIDC do Keycloak. Para encontrar este link, na Consola do administrador do KeyCloud, na janela Realm, clique no separador Geral. O ponto final tem de ser HTTPS, o que significa que tem de configurar o seu servidor Keycloak com HTTPS.

Obtenha o JWT do utilizador autenticado a partir do Keycloak

  1. Na VM que executa o Keycloak, transfira o token para um ficheiro de texto. Por exemplo, no Linux, execute o seguinte:

    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
    

    Substitua o seguinte:

    • IP_FOR_KEYCLOAK com o endereço IP do servidor Keycloak.
    • CLIENT_SECRET com o segredo do cliente do Keycloak.
    • USERNAME com um utilizador do Keycloak.
    • PASSWORD com a palavra-passe do utilizador do Keycloak.

    Este comando inclui o ID de cliente, o segredo do cliente, o nome de utilizador e a palavra-passe. Como prática recomendada de segurança, recomendamos que use variáveis de ambiente para ocultar estes valores em vez de usar a linha de comandos. O comando de exemplo redireciona as credenciais para um ficheiro denominado token.txt.

    Opcionalmente, para automatizar este passo, pode criar um script bash.

  2. Valide o seu token em jwt.io.

  3. Na VM, crie o ficheiro de credenciais:

    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
    

    Para mais informações, consulte o artigo gcloud iam workload-identity-pools create-cred-config.

    O ficheiro de saída deve ter o seguinte aspeto:

    {
        "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 é o número do seu projeto.

  4. Na VM, defina o ficheiro sts.creds.json como uma variável para o ADC:

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

    Substitua USERNAME pelo seu nome de utilizador do UNIX.

    Antes do lançamento da Workload Identity Federation, este valor era a chave da conta de serviço. Com a Workload Identity Federation, este valor é o ficheiro de credenciais criado recentemente.

  5. Crie uma associação de funções para o utilizador usar a identidade da conta de serviço:

    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
    

    Substitua o seguinte:

  6. Permita que a conta de serviço aceda ao serviço do Cloud Run:

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

    Substitua o seguinte:

    • SERVICE_NAME com o nome do microsserviço em execução no Cloud Run.

    • SERVICE_ACCOUNT com o endereço de email da conta de serviço do Cloud Run.

    Para mais informações, consulte o artigo gcloud run services add-iam-policy-binding.

  7. Gere um token de 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'
    
    client = iam_credentials_v1.IAMCredentialsClient()
    
    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)
    

    Substitua o seguinte:

    • WORKLOAD_FQDN com o FQDN da sua carga de trabalho.

    • SERVICE_ACCOUNT com o endereço de email da conta de serviço do Cloud Run.

O token que usa pode chamar a API Identity and Access Management, que lhe dá o novo JWT de que precisa para invocar o seu serviço do Cloud Run.

Pode usar o seu token num pipeline do Jenkins para invocar o contentor sem servidor que está a executar no Cloud Run. No entanto, estes passos estão fora do âmbito deste tutorial.

Limpar

Para evitar incorrer em custos na sua Google Cloud conta pelos recursos usados neste tutorial, pode eliminar o seu projeto.

Elimine o projeto

  1. In the Google Cloud console, go to the Manage resources page.

    Go to Manage resources

  2. In the project list, select the project that you want to delete, and then click Delete.
  3. In the dialog, type the project ID, and then click Shut down to delete the project.

O que se segue?