É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és de charge de travail.

Vous pouvez utiliser la réflexion d'identité pour créer des certificats qui correspondent à 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é à ne demander que des certificats avec un autre nom de l'objet (SAN) 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 qui atteste 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 page 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 exploite les pools d'identités de charge de travail pour permettre aux identités tierces d'accéder aux Google Cloud services. Pour en savoir plus, consultez la page 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 de première partie (Google Cloud). Pour en savoir plus, consultez la page Security Token Service.
  • Réflexion d'identité : la fonctionnalité de réflexion d'identité permet à l'identité validée d'un demandeur de certificat de passer au certificat demandé. Pour en savoir plus, consultez la page Réflexion d'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 pour demander des certificats, vous devez disposer du rôle Gestionnaire d'opérations CA Service (privateca.caManager). Pour en savoir plus sur les rôles IAM pour CA Service, consultez la page Contrôle des accès avec IAM.
  • Pour gérer les pools d'identités de charge de travail et leurs fournisseurs, 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 plus d'informations sur l'attribution de rôles IAM, consultez la page Gérer l'accès aux projets, aux dossiers et aux organisations. Vous pouvez accorder 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 de comptes Google agit en tant que fournisseur d'identité tiers (IdP), et le Google Cloud compte de service est un exemple d'identité tierce affirmée par cet IdP.

Les pools d'identités de charge de travail sont compatibles avec différents 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"
    

    Remplacez les éléments suivants :

    • IDENTITY_POOL_ID : identifiant unique du nouveau pool d'identités de charge de travail
  2. 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: cette option 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 CEL CEL. Pour en savoir plus, consultez la page Définir un mappage et une condition d'attributs.
    • issuer-uri: pour les fournisseurs OIDC, cette option est un point de terminaison accessible au public que 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 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 CA Service 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 des certificats
    • CA_POOL_ID : ID du pool d'autorités de certification CA Service 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 page 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 d'identité nécessite le rôle IAM Demandeur de certificat de charge de travail de CA Service (roles/privateca.workloadCertificateRequester) pour les demandeurs de CreateCertificate.

    Vous pouvez représenter les comptes principaux du pool d'identités de charge de travail avec différents niveaux de granularité, allant d'un seul sujet à toutes les identités du pool entre les fournisseurs. Pour en savoir plus, consultez les comptes principaux ou les ensembles de comptes 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 :

    • CA_POOL_ID : ID du pool d'autorités de certification CA Service qui émet des certificats
    • LOCATION : emplacement du pool d'autorités de certification
    • PROJECT_NUMBER : numéro du projet dans lequel vous avez créé le pool d'identités de charge de travail
    • IDENTITY_POOL_ID : identifiant unique du nouveau 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 GenerateIdToken point de terminaison IAM 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é tierce 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 d'identité OpenID Connect du compte de service (roles/iam.serviceAccountOpenIdTokenCreator). 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é tierce 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 : Google Cloud ID du projet 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 basé sur un fichier ou d'un identifiant basé sur une URL. Pour en savoir plus, consultez la page S'authentifier à l'aide de bibliothèques clientes, de la gcloud CLI, ou de Terraform. Dans ce tutoriel, nous suivons un workflow d'identifiants basés sur un fichier.

    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 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 REFLECTED_SPIFFE mode de requête de sujet :

    curl

    1. Facultatif : si vous ne disposez pas d'une 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 de sujet 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 de première partie à CA Service, vous devez créer un client avec identifiants. Vous pouvez ensuite utiliser ce client avec identifiants pour effectuer des demandes de certificat :

    1. Lancez un client CA Service avec identifiants :

      python

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

      Python

      Pour vous authentifier auprès de CA Service, configurez le service 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 sujet contenant 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

Libérer de l'espace

Pour éviter que les ressources CA Service que vous avez créées en suivant ce document ne soient facturées sur votre Google Cloud compte, effectuez les opérations suivantes à l'aide de 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 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 propriétaire du compte de service

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

Étape suivante