É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 de l'identité et des pools d'identités de charge de travail.

Vous pouvez utiliser la réflexion sur l'identité pour créer des certificats correspondant à l'identité validée d'un demandeur de certificat. Grâce à la réflexion d'identité, vous pouvez limiter un demandeur de certificat non privilégié à ce qu'il ne demande que des certificats ayant un autre nom d'objet (SAN, Subject Alternative Name) correspondant à l'identité de ses identifiants.

Objectifs

Ce tutoriel explique comment utiliser CA Service avec des pools d'identités 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 que vous comprenez 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 les fournisseurs d'identité tiers. Pour en savoir plus, consultez la page Gérer les pools et les fournisseurs d'identités de charge de travail.
  • Fédération d'identité de charge de travail: la fédération d'identité de charge de travail exploite des pools d'identités de charge de travail pour permettre aux identités tierces d'accéder aux services Google Cloud. Pour en savoir plus, consultez la page Fédération d'identité de charge de travail.
  • Security Token Service (STS): il vous permet d'échanger des identifiants tiers contre des jetons propriétaires (Google Cloud). Pour en savoir plus, consultez la page Service de jetons de sécurité.
  • Réflexion sur l'identité: la fonctionnalité de réflexion sur l'identité permet à l'identité validée d'un demandeur de certificat d'accéder au certificat demandé. Pour en savoir plus, consultez la section Réflexion sur l'identité.

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

  • Pour gérer les autorités de certification et les pools d'autorités de certification, et demander des certificats, vous devez disposer du rôle "Gestionnaire des opérations du service d'autorités de certification" (privateca.caManager). Pour en savoir plus sur les rôles IAM pour Certificate Authority Service, consultez la page Contrôle des accès avec IAM.
  • Pour gérer les pools et les fournisseurs d'identités de charge de travail, vous devez disposer du rôle Administrateur de pool d'identités de charge de travail (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 déclaré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 approuvé d'identités fédéré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 pool 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 indicateurs suivants en fonction de votre cas d'utilisation:

    • attribute-mapping: cette option définit le mappage entre les revendications tierces et la revendication principale de 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 la section Définir un mappage d'attributs et une condition.
    • issuer-uri: pour les fournisseurs OIDC, cet indicateur est un point de terminaison accessible publiquement auquel Google contacte pour vérifier les jetons tiers. Pour en savoir plus, consultez la page Préparer un fournisseur d'identité externe.

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

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

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 associés à une 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 dans le 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 émet des 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 la page 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 émet des 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. Autorisez les identités fédérées à partir du pool d'identités de charge de travail à émettre des certificats à partir du pool d'autorités de certification. La réflexion sur l'identité nécessite le rôle IAM roles/privateca.workloadCertificateRequester (Demandeur de certificat de charge de travail du service CA) pour les demandeurs de CreateCertificate.

    Vous pouvez représenter les comptes principaux du pool d'identités de charge de travail selon différents niveaux de précision, allant d'un seul sujet à toutes les identités du pool pour tous les fournisseurs. Pour en savoir plus, consultez la liste des comptes principaux disponibles (dans 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 du projet dans lequel vous avez créé le pool d'identités de charge de travail.

Créer un compte de service qui représente 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 qui représente 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. Procurez-vous 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'un identifiant provenant d'un fichier ou d'une URL. Pour en savoir plus, consultez la page S'authentifier à l'aide de bibliothèques clientes, de gcloud CLI ou de Terraform. Dans ce tutoriel, nous suivons un workflow d'identifiant de source de fichier.

    Chargez vos identifiants dans un chemin d'accès 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 STS token:

    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 d'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 à CA Service avec le mode de requête d'objet REFLECTED_SPIFFE:

    curl

    1. Facultatif: si vous n'avez pas de requête de signature de certificat, 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 vie et un mode de requête d'objet reflété:

      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 CA, vous devez créer un client avec identifiants. Vous pouvez ensuite utiliser ce client avec identifiants pour effectuer des requêtes de certificat:

    1. Démarrez un client de service CA authentifié:

      python

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

      Python

      Pour vous authentifier auprès du service CA, 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. Votre certificat doit avoir un objet contenant un seul URI SAN. Le SAN attestant 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 à la suite de ce document soient facturées sur votre compte Google Cloud, effectuez les opérations suivantes à l'aide de la 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 plus d'informations sur la commande gcloud privateca pools delete, consultez la page 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 auquel appartient le compte de service.

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

Étapes suivantes