Emitir certificados que certifiquen la identidad de terceros

En este instructivo, se muestra cómo puedes emitir certificados que den fe de una identidad de terceros con la reflexión de identidad y los grupos de identidad de carga de trabajo.

Puedes usar la reflexión de identidad para crear certificados que coincidan con la identidad verificada de un solicitante de certificados. Con la reflexión de identidad, puedes limitar a un solicitante de certificados sin privilegios para que solo solicite certificados con un nombre alternativo del sujeto (SAN) que corresponda a la identidad en sus credenciales.

Objetivos

En este instructivo, se proporciona información sobre cómo puedes usar CA Service con grupos de identidades para cargas de trabajo para federar una identidad de terceros y obtener un certificado que acredite esta identidad.

Antes de comenzar

Antes de comenzar, asegúrate de comprender los siguientes conceptos:

  • Grupos de identidades para cargas de trabajo: Los grupos de identidades para cargas de trabajo te permiten administrar proveedores de identidad externos. Para obtener más información, consulta Administra grupos y proveedores de identidades para cargas de trabajo.
  • Federación de identidades para cargas de trabajo: La federación de identidades para cargas de trabajo aprovecha los grupos de identidades para cargas de trabajo para otorgar a las identidades de terceros acceso a los servicios de Google Cloud. Para obtener más información, consulta Federación de identidades para cargas de trabajo.
  • Servicio de tokens de seguridad (STS): El servicio de tokens de seguridad te permite intercambiar credenciales de terceros por tokens de origen (Google Cloud). Para obtener más información, consulta Servicio de tokens de seguridad.
  • Reflejo de identidad: La función de reflejo de identidad permite que la identidad verificada de un solicitante de certificado se incluya en el certificado solicitado. Para obtener más información, consulta Reflexión de identidad.

Asegúrate de tener los siguientes roles de IAM:

  • Para administrar autoridades certificadoras (AC) y grupos de AC, y solicitar certificados, debes tener el rol de Administrador de operaciones de CA Service (privateca.caManager). Para obtener más información sobre los roles de IAM para el servicio de CA, consulta Control de acceso con IAM.
  • Para administrar grupos y proveedores de identidades para cargas de trabajo, debes tener el rol de administrador de grupos de identidades para cargas de trabajo (iam.workloadIdentityPoolAdmin).
  • Para crear una cuenta de servicio, debes tener el rol de administrador de cuentas de servicio (iam.serviceAccountAdmin).

Para obtener información sobre cómo otorgar roles de IAM, consulta Administra el acceso a proyectos, carpetas y organizaciones. Puedes otorgar los roles de IAM requeridos a una Cuenta de Google, una cuenta de servicio, un Grupo de Google, una cuenta de Google Workspace o un dominio de Cloud Identity.

Configura un proveedor y un grupo de identidades para cargas de trabajo

En este instructivo, se explica cómo puedes usar un proveedor de Google OpenID Connect (OIDC) combinado con una cuenta de servicio para actuar como una identidad de terceros. El proveedor de OIDC de Cuentas de Google actúa como un proveedor de identidad (IDP) externo, y la cuenta de servicio es una muestra de identidad externa que afirma este IDP. Google Cloud

Los grupos de identidades para cargas de trabajo admiten una variedad de proveedores de identidad, incluidos Microsoft Azure/Active Directory local, AWS y proveedores de identidad basados en SAML.

Para configurar un proveedor y un grupo de identidades para cargas de trabajo, haz lo siguiente: 1. Para representar un conjunto de identidades federadas de confianza, crea un grupo de identidades para cargas de trabajo:

```
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. Crea un proveedor de grupos de identidades para cargas de trabajo para tu proveedor de identidad externo:

    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"
    

    Reemplaza lo siguiente:

    • PROVIDER_ID: Es el identificador único del proveedor de identidades que deseas crear en el grupo de identidades para cargas de trabajo.

    Puedes personalizar las siguientes marcas para tu caso de uso:

    • attribute-mapping: Esta marca establece la asignación entre los derechos de terceros y el derecho principal de Google, google.subject. google.subject es una asignación obligatoria que puedes establecer en cualquier combinación de reclamos o reclamos individuales con una expresión CEL. Para obtener más información, consulta Define una condición y la asignación de atributos.
    • issuer-uri: En el caso de los proveedores de OIDC, esta marca es un extremo accesible de forma pública al que Google se comunica para verificar los tokens de terceros. Para obtener más información, consulta Cómo preparar un proveedor de identidad externo.

    Si deseas obtener más información para configurar un proveedor de identidades para cargas de trabajo, consulta Configura la federación de identidades para cargas de trabajo.

Crea un grupo de CA y una CA emisora

En esta sección, se explica cómo crear un grupo de CA y agregarle una CA raíz. Puedes usar este grupo de CA para emitir certificados que reflejen la identidad. Si deseas usar un grupo de CA y una CA existentes, puedes omitir esta sección.

En lugar de una CA raíz, también puedes crear una CA subordinada. Crear una AC raíz ayuda a acortar el procedimiento.

  1. Crea un grupo de CA en el nivel de DevOps:

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

    Reemplaza lo siguiente:

    • CA_POOL_ID: Es el ID del grupo de AC de CA Service que emite certificados.
    • LOCATION: Es la ubicación del grupo de AC.

    Para obtener más información sobre cómo crear grupos de CA, consulta Crea un grupo de CA.

  2. Crea una CA raíz:

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

    Reemplaza lo siguiente:

    • CA_ID: Es el ID de la autoridad certificadora que emite los certificados.
    • CA_POOL_ID: Es el ID del grupo de AC de CA Service que emite certificados.
    • LOCATION: Es la ubicación del grupo de AC.

    Para obtener más información sobre cómo crear una AC raíz, consulta Crea una AC raíz.

  3. Habilita las identidades federadas desde el grupo de identidades para cargas de trabajo para emitir certificados desde el grupo de AC. La reflexión de identidad requiere el rol de IAM de Solicitante de certificados de cargas de trabajo del Servicio de CA (roles/privateca.workloadCertificateRequester) para los solicitantes de CreateCertificate.

    Puedes representar las principales del grupo de identidades para cargas de trabajo en varias granularidades, desde un solo sujeto hasta todas las identidades del grupo en todos los proveedores. Para obtener más información, consulta los principales o conjuntos de principales disponibles (usa la pestaña de Google Cloud CLI) que mejor se adapten a tu caso de uso.

    gcloud privateca pools add-iam-policy-binding CA_POOL_ID \
        --location LOCATION \
        --role "roles/privateca.workloadCertificateRequester" \
        --member "group:PROJECT_ID.svc.id.goog:/allAuthenticatedUsers/"
    

    Reemplaza lo siguiente:

    • LOCATION: Es la ubicación del grupo de CA.
    • PROJECT_ID: Es el ID del proyecto Google Cloud en el que creaste el grupo de identidades para cargas de trabajo.

Crea una cuenta de servicio que represente una identidad de terceros

En el siguiente procedimiento, se supone que una cuenta de servicio representa a un tercero. En esta sección, se muestra cómo puedes usar el extremo de IAM GenerateIdToken para recuperar una identidad de terceros en forma de un token de OIDC. Según tu caso de uso, es posible que necesites seguir diferentes pasos para obtener el token de identidad de terceros que elijas.

gcloud iam service-accounts create SERVICE_ACCOUNT

Reemplaza lo siguiente:

  • SERVICE_ACCOUNT: Es el ID de la cuenta de servicio que representa la identidad de terceros.

Emitir un certificado que certifique la identidad de un tercero

Antes de comenzar, asegúrate de tener el rol de IAM de Creador de tokens de cuenta de servicio (roles/iam.serviceAccountTokenCreator). Necesitas este rol de IAM para llamar a la API de GenerateIdToken.

Para obtener un certificado que certifique la identidad de un tercero, haz lo siguiente:

  1. Obtén un token de identidad de terceros de tu proveedor de identidad externo.

    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'])"`
    

    Reemplaza lo siguiente:

    • PROJECT_ID: Es el ID del proyecto en el que deseas crear recursos. Google Cloud

    Bibliotecas cliente

    .

    Para acceder al token de terceros de forma programática, puedes obtener un token de una credencial basada en un archivo o en una URL. Para obtener más información, consulta Autentica mediante bibliotecas cliente, gcloud CLI o Terraform. En este instructivo, seguimos un flujo de trabajo de credenciales de fuente de archivo.

    Carga tu credencial en una ruta que pueda leer el solicitante del certificado:

    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
    

    Reemplaza lo siguiente:

    • PROJECT_ID: ID del proyecto en el que deseas crear recursos.
  2. Intercambia tu token de terceros por un token de OAuth federado con el extremo token de 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'])"`
    

    Bibliotecas cliente

    1. Crea un archivo de configuración de credenciales llamado oidc_token.txt que el código de solicitud de certificado pueda leer para realizar un intercambio de tokens.
    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. Lee el archivo oidc_token.txt para configurar el mecanismo de autorización en la biblioteca 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. Realiza una solicitud al servicio de CA con el modo de solicitud de asunto REFLECTED_SPIFFE:

    curl

    1. Opcional: Si no tienes una CSR, crea una ejecutando el siguiente comando.

      export TUTORIAL_CSR=$(openssl req -newkey rsa:2048 -nodes -subj / -keyout tutorial_do_not_use.key)
      
    2. Solicita un certificado con la CSR, una vida útil y un modo de solicitud de sujeto reflejado:

      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"}'
      

    Bibliotecas cliente

    Para reenviar el token de origen a CA Service, debes crear un cliente con credenciales. Luego, puedes usar este cliente con credenciales para realizar solicitudes de certificados:

    1. Inicia un cliente de CA Service con credenciales:

      python

      caServiceClient = privateca_v1.CertificateAuthorityServiceClient(credentials=scoped_credentials)
      
    2. Solicita un certificado.

      Python

      Para autenticarte en CA Service, configura las credenciales predeterminadas de la aplicación. Si deseas obtener más información, consulta Configura la autenticación para un entorno de desarrollo 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. Verifica el certificado. Tu certificado debe tener un asunto que contenga un solo URI SAN. El SAN que certifica una identidad tiene el siguiente formato:

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

      Reemplaza lo siguiente:

      • IDENTITY_POOL_ID: Es el identificador único del grupo de identidades para cargas de trabajo.
      • PROJECT_NUMBER: Es el número del proyecto en el que creaste el grupo de identidades para cargas de trabajo.

Limpia

Para evitar que se generen cargos en tu cuenta de Google Cloud por los recursos del servicio de CA que creaste siguiendo este documento, realiza las siguientes operaciones con Google Cloud CLI:

  1. Borra la CA que creaste.

    1. Inhabilita la CA:

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

      Reemplaza lo siguiente:

      • CA_ID: Es el identificador único de la CA.
      • CA_POOL_ID: Es el identificador único del grupo de AC.
      • LOCATION: Es la ubicación del grupo de CA.
    2. Borra la CA:

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

      Reemplaza lo siguiente:

      • CA_ID: Es el identificador único de la CA.
      • CA_POOL_ID: Es el identificador único del grupo de AC.
      • LOCATION: Es la ubicación del grupo de CA.
  2. Borra el grupo de CA que creaste.

    gcloud privateca pools delete CA_POOL_ID --location LOCATION
    

    Reemplaza lo siguiente:

    • CA_POOL_ID: Es el identificador único del grupo de AC.
    • LOCATION: Es la ubicación del grupo de CA.

    Para obtener más información sobre el comando gcloud privateca pools delete, consulta gcloud privateca pools delete.

  3. Borra el grupo de identidades para cargas de trabajo que creaste:

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

    Reemplaza lo siguiente:

    • IDENTITY_POOL_ID: Es el identificador único del grupo de identidades para cargas de trabajo.
  4. Borra la cuenta de servicio que creaste:

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

    Reemplaza lo siguiente:

    • SERVICE_ACCOUNT: Es el identificador único del grupo de identidades para cargas de trabajo.
    • PROJECT_ID: Es el proyecto propietario de la cuenta de servicio.

El rol de IAM Solicitante de certificados de cargas de trabajo del servicio de CA (privateca.workloadCertificateRequester) restringe el asunto del certificado emitido solo a la identidad del solicitante. Asegúrate de que a los usuarios o las cargas de trabajo que usan la función de reflexión de identidad solo se les otorgue el rol de IAM Solicitante de certificados de cargas de trabajo del servicio de CA (privateca.workloadCertificateRequester). Para cumplir con el principio de privilegio mínimo, puedes evitar otorgar el rol de IAM de Solicitante de certificados del servicio de AC (privateca.certificateRequester).

¿Qué sigue?