Émettre des certificats attestant d'une identité tierce

Ce tutoriel explique comment émettre des certificats attestant d'une identité tierce à l'aide de la réflexion d'identité et des pools d'identité de charge de travail.

Vous pouvez utiliser la réflexion d'identité pour créer des certificats correspondant à l'identité validée d'un demandeur de certificat. À l'aide de la réflexion d'identité, vous pouvez limiter un demandeur de certificat non privilégié à ne demander que des certificats avec un autre nom d'objet (SAN) correspondant à l'identité dans ses identifiants.

Objectifs

Ce tutoriel explique comment utiliser le service de certification avec des pools d'identité de charge de travail pour fédérer une identité tierce et obtenir un certificat attestant de cette identité.

Avant de commencer

Avant de commencer, assurez-vous de bien comprendre les concepts suivants:

  • Pools d'identités de charge de travail: les pools d'identités de charge de travail vous permettent de gérer des fournisseurs d'identité tiers. Pour en savoir plus, consultez la section Gérer les pools d'identités de charge de travail et leurs fournisseurs.
  • Fédération d'identité de charge de travail: la fédération d'identité de charge de travail s'appuie sur des pools d'identité de charge de travail pour accorder aux identités tierces l'accès aux services Google Cloud. Pour en savoir plus, consultez la section Fédération d'identité de charge de travail.
  • Security Token Service (STS): le service de jetons de sécurité vous permet d'échanger des identifiants tiers contre des jetons propriétaires (Google Cloud). Pour en savoir plus, consultez Security Token Service.
  • Reflet d'identité: la fonctionnalité de reflet d'identité permet de transmettre l'identité validée d'un demandeur de certificat au certificat demandé. Pour en savoir plus, consultez la section Réflexion de l'identité.

Assurez-vous de disposer des rôles IAM suivants:

  • Pour gérer les autorités de certification (CA) et les pools d'autorités de certification, et demander des certificats, vous devez disposer du rôle Administrateur des opérations du service CA (privateca.caManager). Pour en savoir plus sur les rôles IAM pour le service CA, consultez la page Contrôle des accès avec IAM.
  • Pour gérer les pools et fournisseurs d'identités de charge de travail, vous devez disposer du rôle Administrateur de pools Workload Identity (iam.workloadIdentityPoolAdmin).
  • Pour créer un compte de service, vous devez disposer du rôle Administrateur de compte de service (iam.serviceAccountAdmin).

Pour en savoir plus sur l'attribution de rôles IAM, consultez la page Gérer l'accès aux projets, aux dossiers et aux organisations. Vous pouvez attribuer les rôles IAM requis à un compte Google, un compte de service, un groupe Google, un compte Google Workspace ou un domaine Cloud Identity.

Configurer un pool d'identités de charge de travail et un fournisseur

Ce tutoriel explique comment utiliser un fournisseur Google OpenID Connect (OIDC) associé à un compte de service pour agir en tant qu'identité tierce. Le fournisseur OIDC des comptes Google agit en tant que fournisseur d'identité tiers (IdP), et le compte de service Google Cloud est un exemple d'identité tierce affirmée par cet IDP.

Les pools d'identités de charge de travail sont compatibles avec divers fournisseurs d'identité, y compris Microsoft Azure/Active Directory sur site, AWS et les fournisseurs d'identité basés sur SAML.

Pour configurer un pool d'identités de charge de travail et un fournisseur, procédez comme suit : 1. Pour représenter un ensemble d'identités fédérées approuvées, créez un pool d'identités de charge de travail:

```
gcloud iam workload-identity-pools create IDENTITY_POOL_ID --location global --display-name "tutorial-wip"
```

Replace the following:

- <var>IDENTITY_POOL_ID</var>: The unique identifier of the new workload
  identity pool.
  1. Créez un fournisseur de pools d'identités de charge de travail pour votre fournisseur d'identité tiers:

    gcloud iam workload-identity-pools providers create-oidc PROVIDER_ID --location global --workload-identity-pool IDENTITY_POOL_ID --display-name "tutorial-oidc" --attribute-mapping "google.subject=assertion.sub" --issuer-uri="https://accounts.google.com"
    

    Remplacez les éléments suivants :

    • PROVIDER_ID: identifiant unique du fournisseur d'identité que vous souhaitez créer dans le pool d'identités de charge de travail.

    Vous pouvez personnaliser les options suivantes en fonction de votre cas d'utilisation:

    • attribute-mapping: cet indicateur définit le mappage entre les revendications tierces et la revendication principale Google, google.subject. google.subject est un mappage obligatoire que vous pouvez définir sur n'importe quelle revendication ou combinaison de revendications à l'aide d'une expression CEL. Pour en savoir plus, consultez Définir un mappage et une condition d'attribut.
    • issuer-uri: pour les fournisseurs OIDC, cet indicateur est un point de terminaison accessible au public que Google contacte pour valider les jetons tiers. Pour en savoir plus, consultez la section Préparer un fournisseur d'identité externe.

    Pour en savoir plus sur la configuration d'un fournisseur d'identités de charge de travail, consultez la section Configurer la fédération d'identité de charge de travail.

Créer un pool d'autorités de certification et une autorité d'émission

Cette section explique comment créer un pool d'autorités de certification et y ajouter une autorité de certification racine. Vous pouvez utiliser ce pool d'autorités de certification pour émettre des certificats reflétant l'identité. Si vous souhaitez utiliser un pool d'autorités de certification et une autorité de certification existants, vous pouvez ignorer cette section.

Au lieu d'une autorité de certification racine, vous pouvez également choisir de créer une autorité de certification subordonnée. La création d'une autorité de certification racine permet de raccourcir la procédure.

  1. Créez un pool d'autorités de certification au niveau DevOps:

    gcloud privateca pools create CA_POOL_ID --location LOCATION --tier devops
    

    Remplacez les éléments suivants :

    • CA_POOL_ID : ID du pool d'autorités de certification du service CA qui délivre les certificats.
    • LOCATION : emplacement du pool d'autorités de certification.

    Pour en savoir plus sur la création de pools d'autorités de certification, consultez Créer un pool d'autorités de certification.

  2. Créez une autorité de certification racine :

    gcloud privateca roots create CA_ID --pool CA_POOL_ID  --location LOCATION --subject "CN=test,O=test-org"
    

    Remplacez les éléments suivants :

    • CA_ID : ID de l'autorité de certification qui émet les certificats.
    • CA_POOL_ID : ID du pool d'autorités de certification du service CA qui délivre les certificats.
    • LOCATION : emplacement du pool d'autorités de certification.

    Pour en savoir plus sur la création d'une autorité de certification racine, consultez la section Créer une autorité de certification racine.

  3. Activez les identités fédérées à partir du pool d'identités de charge de travail pour émettre des certificats à partir du pool d'autorités de certification. La réflexion d'identité nécessite le rôle IAM Demandeur de certificat de charge de travail du service CA (roles/privateca.workloadCertificateRequester) pour les demandeurs de CreateCertificate.

    Vous pouvez représenter les principaux de pool d'identités de charge de travail avec différentes précisions, allant d'un seul sujet à toutes les identités du pool entre les fournisseurs. Pour en savoir plus, consultez les principals ou ensembles de principaux disponibles (utilisez l'onglet Google Cloud CLI) qui correspondent le mieux à votre cas d'utilisation.

    gcloud privateca pools add-iam-policy-binding CA_POOL_ID --location LOCATION --role roles/privateca.workloadCertificateRequester --member "principalSet://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/IDENTITY_POOL_ID/*"
    

    Remplacez les éléments suivants :

    • PROJECT_NUMBER : numéro de projet du projet dans lequel vous avez créé le pool d'identités de charge de travail.

Créer un compte de service représentant une identité tierce

La procédure suivante suppose qu'un compte de service représente un tiers. Cette section explique comment utiliser le point de terminaison IAM GenerateIdToken pour récupérer une identité tierce sous la forme d'un jeton OIDC. Selon votre cas d'utilisation, vous devrez peut-être suivre différentes étapes pour obtenir le jeton d'identité tiers de votre choix.

gcloud iam service-accounts create SERVICE_ACCOUNT

Remplacez les éléments suivants :

  • SERVICE_ACCOUNT : ID du compte de service représentant l'identité tierce.

Émettre un certificat attestant d'une identité tierce

Avant de commencer, assurez-vous de disposer du rôle IAM "Créateur de jetons du compte de service" (roles/iam.serviceAccountTokenCreator). Vous avez besoin de ce rôle IAM pour appeler l'API GenerateIdToken.

Pour obtenir un certificat attestant d'une identité tierce, procédez comme suit:

  1. Obtenez un jeton d'identité tiers auprès de votre fournisseur d'identité tiers.

    curl

    export ID_TOKEN=`curl -d '{"audience":"//iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/IDENTITY_POOL_ID/providers/PROVIDER_ID"}' -H 'Content-Type: application/json' -H "Authorization: Bearer $(gcloud auth print-access-token)" https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/SERVICE_ACCOUNT@PROJECT_ID.iam.gserviceaccount.com:generateIdToken | python3 -c "import sys;import json;print(json.load(sys.stdin)['token'])"`
    

    Remplacez les éléments suivants :

    • PROJECT_ID : ID du projet Google Cloud dans lequel vous souhaitez créer des ressources.

    Bibliothèques clientes

    .

    Pour accéder au jeton tiers de manière programmatique, vous pouvez obtenir un jeton à partir d'identifiants issus d'un fichier ou d'une URL. Pour en savoir plus, consultez S'authentifier à l'aide de bibliothèques clientes, de la gcloud CLI ou de Terraform. Dans ce tutoriel, nous suivons un workflow d'authentification de source de fichiers.

    Chargez vos identifiants dans un chemin lisible par votre demandeur de certificat:

    curl -d '{"audience":"//iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/IDENTITY_POOL_ID/providers/PROVIDER_ID"}' -H 'Content-Type: application/json' -H "Authorization: Bearer $(gcloud auth print-access-token)" https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/SERVICE_ACCOUNT@PROJECT_ID.iam.gserviceaccount.com:generateIdToken | python3 -c "import sys;import json;       print(json.load(sys.stdin)['token']) > /tmp/oidc_token.txt
    

    Remplacez les éléments suivants :

    • PROJECT_ID: ID du projet dans lequel vous souhaitez créer des ressources.
  2. Échangez votre jeton tiers contre un jeton OAuth fédéré à l'aide du point de terminaison token du STS:

    curl

    export STS_TOKEN=`curl -L -X POST 'https://sts.googleapis.com/v1/token' -H 'Content-Type: application/json' \
    -d '{
        "grant_type": "urn:ietf:params:oauth:grant-type:token-exchange",
        "audience": "//iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/IDENTITY_POOL_ID/providers/PROVIDER_ID",
        "requested_token_type": "urn:ietf:params:oauth:token-type:access_token",
        "scope": "https://www.googleapis.com/auth/cloud-platform",
        "subject_token": "'$ID_TOKEN'",
        "subject_token_type": "urn:ietf:params:oauth:token-type:jwt"
    }' | python3 -c "import sys;import json; print(json.load(sys.stdin)['access_token'])"`
    

    Bibliothèques clientes

    1. Créez un fichier de configuration des identifiants nommé oidc_token.txt que le code de demande de certificat peut lire pour effectuer un échange de jetons.
    gcloud iam workload-identity-pools create-cred-config projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/IDENTITY_POOL_ID --output-file=/tmp/cred_config.json --credential-source-file=/tmp/oidc_token.txt
    
    1. Lisez le fichier oidc_token.txt pour définir le mécanisme d'autorisation dans la bibliothèque cliente:

    python

    import json
    
    from google.auth import identity_pool
    
    with open('/tmp/cred_config.json', 'r') as f:
      json_config_info = json.loads(f.read())
    credentials = identity_pool.Credentials.from_info(json_config_info)
    scoped_credentials = credentials.with_scopes(
        ['https://www.googleapis.com/auth/cloud-platform'])
    
  3. Envoyez une requête au service CA avec le mode de requête d'objet REFLECTED_SPIFFE:

    curl

    1. Facultatif: Si vous ne disposez pas d'une CSR, créez-en une en exécutant la commande suivante.

      export TUTORIAL_CSR=$(openssl req -newkey rsa:2048 -nodes -subj / -keyout tutorial_do_not_use.key)
      
    2. Demandez un certificat avec la requête de signature de certificat, une durée de validité et un mode de requête d'objet réfléchi:

      curl -H "Authorization: Bearer $(echo $STS_TOKEN)" https://privateca.googleapis.com/v1/projects/PROJECT_NUMBER/locations/LOCATION/caPools/CA_POOL_ID/certificates\?alt\=json  -X POST -H "Content-Type: application/json" -H 'Accept: application/json' --data '{"lifetime": "100s", "pemCsr": "'$TUTORIAL_CSR'", "subjectMode": "REFLECTED_SPIFFE"}'
      

    Bibliothèques clientes

    Pour transférer le jeton propriétaire au service d'autorité de certification, vous devez créer un client authentifié. Vous pouvez ensuite utiliser ce client authentifié pour effectuer des demandes de certificat:

    1. Lancez un client du service d'autorité de certification authentifié:

      python

      caServiceClient = privateca_v1.CertificateAuthorityServiceClient(credentials=scoped_credentials)
      
    2. Demandez un certificat.

      Python

      Pour vous authentifier auprès du service d'autorité de certification, configurez les Identifiants par défaut de l'application. Pour en savoir plus, consultez Configurer l'authentification pour un environnement de développement local.

      import google.cloud.security.privateca_v1 as privateca_v1
      from google.protobuf import duration_pb2
      
      
      def create_certificate(
          project_id: str,
          location: str,
          ca_pool_name: str,
          ca_name: str,
          certificate_name: str,
          common_name: str,
          domain_name: str,
          certificate_lifetime: int,
          public_key_bytes: bytes,
      ) -> None:
          """
          Create a Certificate which is issued by the Certificate Authority present in the CA Pool.
          The key used to sign the certificate is created by the Cloud KMS.
      
          Args:
              project_id: project ID or project number of the Cloud project you want to use.
              location: location you want to use. For a list of locations, see: https://cloud.google.com/certificate-authority-service/docs/locations.
              ca_pool_name: set a unique name for the CA pool.
              ca_name: the name of the certificate authority which issues the certificate.
              certificate_name: set a unique name for the certificate.
              common_name: a title for your certificate.
              domain_name: fully qualified domain name for your certificate.
              certificate_lifetime: the validity of the certificate in seconds.
              public_key_bytes: public key used in signing the certificates.
          """
      
          caServiceClient = privateca_v1.CertificateAuthorityServiceClient()
      
          # The public key used to sign the certificate can be generated using any crypto library/framework.
          # Also you can use Cloud KMS to retrieve an already created public key.
          # For more info, see: https://cloud.google.com/kms/docs/retrieve-public-key.
      
          # Set the Public Key and its format.
          public_key = privateca_v1.PublicKey(
              key=public_key_bytes,
              format_=privateca_v1.PublicKey.KeyFormat.PEM,
          )
      
          subject_config = privateca_v1.CertificateConfig.SubjectConfig(
              subject=privateca_v1.Subject(common_name=common_name),
              subject_alt_name=privateca_v1.SubjectAltNames(dns_names=[domain_name]),
          )
      
          # Set the X.509 fields required for the certificate.
          x509_parameters = privateca_v1.X509Parameters(
              key_usage=privateca_v1.KeyUsage(
                  base_key_usage=privateca_v1.KeyUsage.KeyUsageOptions(
                      digital_signature=True,
                      key_encipherment=True,
                  ),
                  extended_key_usage=privateca_v1.KeyUsage.ExtendedKeyUsageOptions(
                      server_auth=True,
                      client_auth=True,
                  ),
              ),
          )
      
          # Create certificate.
          certificate = privateca_v1.Certificate(
              config=privateca_v1.CertificateConfig(
                  public_key=public_key,
                  subject_config=subject_config,
                  x509_config=x509_parameters,
              ),
              lifetime=duration_pb2.Duration(seconds=certificate_lifetime),
          )
      
          # Create the Certificate Request.
          request = privateca_v1.CreateCertificateRequest(
              parent=caServiceClient.ca_pool_path(project_id, location, ca_pool_name),
              certificate_id=certificate_name,
              certificate=certificate,
              issuing_certificate_authority_id=ca_name,
          )
          result = caServiceClient.create_certificate(request=request)
      
          print("Certificate creation result:", result)
      
      

    3. Vérifiez le certificat. L'objet de votre certificat doit contenir un seul SAN URI. Le SAN qui atteste d'une identité est au format suivant:

      spiffe://IDENTITY_POOL_ID.PROJECT_NUMBER.global.workload.id.goog/subject/<oidc_subject_number>
      

      Remplacez :

      • IDENTITY_POOL_ID: identifiant unique du pool d'identités de charge de travail.
      • PROJECT_NUMBER : numéro du projet dans lequel vous avez créé le pool d'identités de charge de travail.

Effectuer un nettoyage

Pour éviter que les ressources du service d'autorité de certification que vous avez créées en suivant ce document soient facturées sur votre compte Google Cloud, effectuez les opérations suivantes à l'aide du Google Cloud CLI:

  1. Supprimez l'autorité de certification que vous avez créée.

    1. Désactivez l'autorité de certification:

      gcloud privateca roots disable CA_ID --pool CA_POOL_ID  --location LOCATION
      

      Remplacez :

      • CA_ID: identifiant unique de l'autorité de certification.
      • CA_POOL_ID: identifiant unique du pool d'autorités de certification.
      • LOCATION: emplacement du pool d'autorités de certification.
    2. Supprimez l'autorité de certification:

      gcloud privateca roots delete CA_ID --pool CA_POOL_ID  --location LOCATION --ignore-active-certificates
      

      Remplacez :

      • CA_ID: identifiant unique de l'autorité de certification.
      • CA_POOL_ID: identifiant unique du pool d'autorités de certification.
      • LOCATION: emplacement du pool d'autorités de certification.
  2. Supprimez le pool d'autorités de certification que vous avez créé.

    gcloud privateca pools delete CA_POOL_ID --location LOCATION
    

    Remplacez :

    • CA_POOL_ID: identifiant unique du pool d'autorités de certification.
    • LOCATION: emplacement du pool d'autorités de certification.

    Pour en savoir plus sur la commande gcloud privateca pools delete, consultez gcloud privateca pools delete.

  3. Supprimez le pool d'identités de charge de travail que vous avez créé:

    gcloud iam workload-identity-pools delete IDENTITY_POOL_ID --location global
    

    Remplacez :

    • IDENTITY_POOL_ID: identifiant unique du pool d'identités de charge de travail.
  4. Supprimez le compte de service que vous avez créé:

    gcloud iam service-accounts delete SERVICE_ACCOUNT@PROJECT_ID.iam.gserviceaccount.com
    

    Remplacez :

    • SERVICE_ACCOUNT: identifiant unique du pool d'identités de charge de travail.
    • PROJECT_ID: projet propriétaire du compte de service.

Le rôle IAM Demandeur de certificat de charge de travail du service CA (privateca.workloadCertificateRequester) limite le sujet du certificat émis à l'identité du demandeur uniquement. Assurez-vous que les utilisateurs ou les charges de travail qui utilisent la fonctionnalité de réflexion d'identité ne reçoivent que le rôle IAM "Demandeur de certificat de charge de travail du service CA" (privateca.workloadCertificateRequester). Pour respecter le principe du moindre privilège, vous pouvez éviter d'attribuer le rôle IAM Demandeur de certificat de service CA (privateca.certificateRequester).

Étape suivante