Configurer l'accès basé sur les certificats pour la fédération d'identité de charge de travail

Ce document explique comment configurer l'accès basé sur les certificats pour la fédération d'identité de charge de travail à l'aide de certificats X.509.

L'accès basé sur un certificat utilise le protocole TLS mutuel (mTLS) pour authentifier le client et le serveur lors d'un handshake TLS. Dans ce processus, une liaison mTLS intègre des règles basées sur le contexte de transport et utilise l'état du certificat du client dans la session TLS pour prendre des décisions d'autorisation.

Pour la fédération d'identité de charge de travail X.509, une liaison mTLS garantit que l'intégralité du flux d'authentification est liée de manière sécurisée à une charge de travail de confiance. Cela réduit le risque de vol d'identifiants, car le système lie l'authentification à un point de terminaison spécifique et de confiance.

Présentation de la configuration de l'accès basé sur un certificat pour la fédération d'identité de charge de travail

Voici un aperçu général du processus de configuration de l'accès basé sur un certificat pour la fédération d'identité de charge de travail :

  1. Établissez la fédération d'identité de charge de travail en configurant la confiance avec l'ancre de confiance des certificats X.509.

  2. Créez un niveau d'accès pour l'accès basé sur des certificats.

  3. Ajoutez le niveau d'accès à une règle d'accès contextuel qui applique la liaison mTLS.

Avant de commencer

Vérifiez que vous disposez des éléments suivants :

Créer un niveau d'accès pour les certificats

  1. Créez un niveau d'accès mTLS. Le niveau d'accès mTLS valide les certificats lors de la détermination de l'accès aux ressources.

    Console

    Dans Access Context Manager, créez un niveau d'accès personnalisé et saisissez l'expression suivante dans le champ Expression CEL : request.auth.matchesMtlsTokens(origin) == true.

    gcloud

    Pour créer un niveau d'accès personnalisé, exécutez la commande suivante :

    gcloud access-context-manager levels create ACCESS_LEVEL_NAME \
        --title=TITLE \
        --custom-level-spec=FILE \
        --description=DESCRIPTION \
        --policy=POLICY_NAME

    Remplacez les éléments suivants :

    • ACCESS_LEVEL_NAME : nom du niveau d'accès.
    • TITLE : titre du niveau d'accès.
    • FILE : fichier YAML avec le contenu suivant : expression: "request.auth.matchesMtlsTokens(origin) == true".
    • DESCRIPTION : description du niveau d'accès.
    • POLICY_NAME : nom de la règle d'accès.
  2. Exportez le niveau d'accès que vous avez créé vers une variable d'environnement à utiliser lors des étapes suivantes :

      export ACCESS_LEVEL_ID=ACCESS_LEVEL_ID
      

    Remplacez ACCESS_LEVEL_ID par le nom du niveau d'accès (par exemple, accessPolicies/12345/accessLevels/acl_1).

Créer une liaison d'accès contextuel pour un pool d'identités de charge de travail

  1. Définissez les variables d'environnement suivantes :

    export ORG_ID=ORG_ID
    export CALLER_PROJECT_ID=CALLER_PROJECT_ID
    export FEDERATED_PRINCIPAL=FEDERATED_PRINCIPAL
    

    Remplacez les éléments suivants :

    • ORG_ID : ID de votre organisation.
    • CALLER_PROJECT_ID : ID du projet à utiliser pour appeler les API.
    • FEDERATED_PRINCIPAL : nom du compte principal d'identité dans le pool d'identités de charge de travail qui respecte la règle d'accès contextuel. Vous pouvez utiliser l'une des options suivantes :

      • Une seule identité : principal://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/subject/SUBJECT_ATTRIBUTE_VALUE
      • Toutes les identités d'un pool : principalSet://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/*

    gcloud

    gcloud alpha access-context-manager cloud-bindings create \
    --organization=ORG_ID \
    --federated-principal=FEDERATED_PRINCIPAL \
    --level=ACCESS_LEVEL_ID \
    --dry-run-level=DRY_RUN_ACCESS_LEVEL_ID
    

    Remplacez les éléments suivants :

    • ACCESS_LEVEL_ID : nom du niveau d'accès.
    • DRY_RUN_ACCESS_LEVEL_ID : nom du niveau d'accès dry run. Nous vous recommandons d'activer d'abord une liaison de stratégie dry run pour comprendre l'impact potentiel sur le trafic existant.

    curl

    1. Créez un fichier JSON avec la liaison d'accès contextuel :

      Vous ne pouvez fournir qu'un seul niveau d'accès dans une requête, même si le champ est répété. Vous pouvez utiliser les types de comptes principaux fédérés suivants :

      • Identité unique : principal://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/subject/SUBJECT_ATTRIBUTE_VALUE
      • Toutes les identités d'un pool : principalSet://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/*
      cat <<EOF > request.json
      {
        "principal": {
          "federatedPrincipal": "${FEDERATED_PRINCIPAL:?}"
        },
        "accessLevels": ["${ACCESS_LEVEL_ID:?}"]
      }
      EOF
      
    2. Utilisez curl pour envoyer la requête HTTP suivante :

      curl -H "X-Goog-User-Project: ${CALLER_PROJECT_ID:?}" -X POST \
         -H "Authorization: Bearer $(gcloud auth print-access-token)" \
         -H "Content-Type: application/json; charset=utf-8" \
         -d @request.json \
       "https://accesscontextmanager.googleapis.com/v1alpha/organizations/${ORG_ID:?}/gcpUserAccessBindings"
      

Autoriser l'accès à l'aide des bibliothèques clientes Cloud de Confiance by S3NS

Pour autoriser les charges de travail de la fédération d'identité de charge de travail à l'aide des bibliothèques clientesCloud de Confiance , procédez comme suit :

  1. Créez un fichier d'Identifiants par défaut de l'application (ADC) configuré pour l'authentification par fédération d'identité de charge de travail :

    gcloud iam workload-identity-pools create-cred-config IDENTITY_POOL_ID \
    --credential-cert-path WORKLOAD_CERTIFICATE_PATH \
    --credential-cert-private-key-path WORKLOAD_KEY_PATH \
    --output-file ADC_FILE_OUTPUT_PATH
    

    Remplacez les éléments suivants :

    • IDENTITY_POOL_ID : ID de votre pool d'identités de charge de travail.
    • WORKLOAD_CERTIFICATE_PATH : chemin d'accès au fichier de certificat de votre charge de travail.
    • WORKLOAD_KEY_PATH : chemin d'accès au fichier de clé privée de votre charge de travail.
    • ADC_FILE_OUTPUT_PATH : chemin de sortie du fichier ADC.

    Cette commande génère également un fichier de configuration de certificat dans le répertoire de configuration par défaut de gcloud CLI. Le fichier de configuration du certificat accepte l'authentification initiale et établit des liaisons mTLS pour les requêtes ultérieures adressées aux ressources Cloud de Confiance .

  2. Définissez une variable d'environnement pointant vers le fichier ADC pour que les bibliothèques clientes Google puissent détecter vos identifiants :

    export GOOGLE_APPLICATION_CREDENTIALS=ADC_FILE_OUTPUT_PATH
    

    Cette étape est facultative si vous omettez l'argument --output-file lorsque vous générez le fichier ADC. Si vous omettez l'argument, la gcloud CLI crée et lit le fichier ADC à partir du répertoire de configuration par défaut de la gcloud CLI.

  3. Cette fonctionnalité est compatible avec les bibliothèques clientes en Go, Python et Java. Vous devez définir la variable d'environnement pour activer mTLS pour Python et Java.

  4. Pour établir et tester rapidement l'accès mTLS aux API Cloud de Confiance , vous pouvez utiliser les exemples de code suivants :

    Go

    1. Utilisez l'exemple suivant pour créer un fichier Go, tel que golang_test.go :

      package golang_test
      
      import (
           "io"
           "log"
           "testing"
      
           "cloud.google.com/go/auth/credentials"
           "cloud.google.com/go/auth/httptransport"
      )
      
      func TestGoExample(t *testing.T) {
      
           scopes := []string{
                   "https://www.googleapis.com/auth/pubsub", // Scope for Pub/Sub access
                   // Add other scopes as needed
           }
      
           dopts := credentials.DetectOptions{
                   Scopes: scopes,
           }
      
           // Create httptransport.Options with the scopes
           opts := &httptransport.Options{
                   DetectOpts: &dopts,
           }
           hc, err := httptransport.NewClient(opts)
           if err != nil {
                   t.Fatalf("NewHTTPClient: %v", err)
           }
      
           resp, err := hc.Get("https://pubsub.mtls.googleapis.com/v1/projects/PROJECT_ID/topics")
           if err != nil {
                   t.Fatalf("Get: %v", err)
           }
           t.Logf("Status: %s", resp.Status)
      
           t.Cleanup(func() {
                  resp.Body.Close()
           })
      
           b, err := io.ReadAll(resp.Body)
           if err != nil {
                  t.Fatal(err)
           }
           log.Println(string(b))
      }
      

      Remplacez PROJECT_ID par l'ID de votre projetCloud de Confiance .

    2. Pour exécuter un test sur une VM Compute Engine, utilisez la commande suivante :

    go mod init example.com
    go mod tidy
    go test -v golang_test.go --count=1
    

    Python

    1. Utilisez l'exemple suivant pour créer un fichier de test, tel que python_test.py :

      import google.auth
      import google.auth.transport.requests
      import requests
      
      def test_python_example():
      # Define the required scopes for your application
      scopes = [
         "https://www.googleapis.com/auth/pubsub",  # Scope for Pub/Sub access
         # Add other scopes as needed
      ]
      
      # Obtain Application Default Credentials (ADC) with the specified scopes
      credentials, _ = google.auth.default(scopes=scopes)
      
      # Create an authorized HTTP session using the ADC credentials
      authed_session = google.auth.transport.requests.AuthorizedSession(credentials)
      
      try:
       # Make a GET request to the Pub/Sub API endpoint
       response = authed_session.get(
           "https://pubsub.mtls.googleapis.com/v1/projects/PROJECT_ID/topics"
       )
      
       # Check if the request was successful
       response.raise_for_status()  # Raise an exception for error statuses
      
       # Log the response status and content
       print(f"Status: {response.status_code}")
       print(response.text)
      
      except requests.exceptions.RequestException as e:
       print(f"Error making the request: {e}")
      
      if __name__ == "__main__":
      test_python_example()
      

      Remplacez PROJECT_ID par l'ID de votre projetCloud de Confiance .

    2. Pour exécuter un test sur une VM Compute Engine, procédez comme suit :

      1. Configurez un environnement virtuel Python.
      2. Installez les bibliothèques requises :

        pip install google-auth google-auth-httplib2 requests
        
      3. Exécutez le test :

        python3 python_test.py
        

Autoriser à l'aide de requêtes HTTP simples

Pour autoriser les charges de travail de la fédération d'identité de charge de travail à l'aide de requêtes HTTP simples, procédez comme suit :

  1. Obtenez un jeton d'accès lié à un certificat auprès du service de jetons de sécurité Cloud de Confiance via un handshake mTLS standard.

  2. Appelez les services Cloud de Confiance avec le jeton d'accès que vous avez obtenu auprès de Security Token Service. Cet exemple interroge Cloud Storage :

    curl --key WORKLOAD_KEY_PATH --cert WORKLOAD_CERTIFICATE_PATH \
     -X GET "https://storage.mtls.googleapis.com/RESOURCE_PATH" \
     -H "Authorization: Bearer $ACCESS_TOKEN"
    
  3. La liaison mTLS applique l'utilisation de mTLS. Exécutez la commande suivante pour vérifier qu'une connexion non mTLS échoue avec une erreur d'autorisation :

    curl -X GET "https://storage.googleapis.com/RESOURCE_PATH" \
     -H "Authorization: Bearer $ACCESS_TOKEN"
    

Lister la liaison de stratégie

Pour lister la liaison de stratégie pour la fédération d'identité de charge de travail, exécutez la commande suivante :

gcloud

La commande suivante liste des liaisons spécifiques au sein d'une organisation donnée, en filtrant celles qui s'appliquent aux comptes principaux fédérés :

gcloud alpha access-context-manager cloud-bindings list \
--organization=ORG_ID \
--filter='principal:federatedPrincipal'

curl

curl -H "X-Goog-User-Project: ${CALLER_PROJECT_ID:?}" -X GET \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
"https://accesscontextmanager.googleapis.com/v1alpha/organizations/${ORG_ID:?}/gcpUserAccessBindings?filter=principal%3Afederated_principal"

Mettre à jour une liaison de stratégie

Pour mettre à jour une liaison de stratégie, procédez comme suit :

gcloud

gcloud alpha access-context-manager cloud-bindings update \
--binding=BINDING_ID \
--organization=ORG_ID \
--level=NEW_ACCESS_LEVEL_ID

curl

Ajoutez le nouveau niveau d'accès au fichier request.json et exécutez la commande suivante :

curl -H "X-Goog-User-Project: ${CALLER_PROJECT_ID:?}" -X PATCH \
 -H "Authorization: Bearer $(gcloud auth print-access-token)" \
 -H "Content-Type: application/json; charset=utf-8" \
 -d @request.json \
"https://accesscontextmanager.googleapis.com/v1alpha/organizations/${ORG_ID:?}/gcpUserAccessBindings/${BINDING_ID:?}?updateMask=access_levels"

Supprimer une liaison de stratégie

Pour supprimer une liaison de stratégie, exécutez la commande suivante :

gcloud

gcloud alpha access-context-manager cloud-bindings delete \
--binding=BINDING_ID \
--organization=ORG_ID

curl

curl -H "X-Goog-User-Project: ${CALLER_PROJECT_ID:?}" -X DELETE \
   -H "Authorization: Bearer $(gcloud auth print-access-token)" \
"https://accesscontextmanager.googleapis.com/v1alpha/organizations/${ORG_ID:?}/gcpUserAccessBindings/${BINDING_ID:?}"

Étapes suivantes