Criar uma autoridade certificadora subordinada

Neste documento, descrevemos as etapas para criar uma autoridade certificadora subordinada (Sub AC).

As sub-CAs são responsáveis por emitir certificados diretamente para entidades finais, como usuários, computadores e dispositivos. Elas são assinadas criptograficamente por uma CA principal, geralmente a CA raiz. Os sistemas que confiam na CA raiz confiam automaticamente nas sub-CAs e nos certificados emitidos por elas.

O signatário do certificado de CA pode ser outra CA criada no CA Service, por exemplo, uma CA raiz, ou uma CA externa. Com CAs externas, o CA Service gera uma solicitação de assinatura de certificado (CSR, na sigla em inglês) que a CA externa precisa assinar.

Este documento é destinado a públicos-alvo do grupo de operadores de aplicativos, como desenvolvedores de aplicativos ou cientistas de dados, que gerenciam ciclos de vida de certificados no projeto. Para mais informações, consulte Públicos-alvo da documentação do GDC com isolamento físico.

Antes de começar

Antes de criar uma subautoridade certificadora, solicite as permissões necessárias e prepare seu ambiente.

Solicitar papéis do IAM

Para criar, atualizar e excluir recursos do Certificate Authority Service, entre em contato com o administrador do IAM da organização e peça o papel Administrador do serviço de autoridade certificadora (certificate-authority-service-admin) no namespace do projeto da autoridade certificadora.

Preparar o ambiente

Criar uma subautoridade de certificação gerenciada

Para uma subautoridade de certificação gerenciada, o signatário do certificado de CA é outra AC (raiz) criada no serviço de AC.

Para criar uma subautoridade de certificação gerenciada, aplique um recurso personalizado à sua instância do Distributed Cloud Appliance.

  1. Crie um recurso CertificateAuthority e salve-o como um arquivo YAML chamado subca.yaml:

    apiVersion: pki.security.gdc.goog/v1
    kind: CertificateAuthority
    metadata:
      Name: SUB_CA_NAME
      namespace: USER_PROJECT_NAMESPACE
    spec:
      caProfile:
        commonName: COMMON_NAME
        duration: DURATION
        renewBefore: RENEW_BEFORE
        organizations:
        - ORGANIZATIONS
        organizationalUnits:
        - ORGANIZATIONAL_UNITS
        countries:
        - COUNTRIES
        localities:
        - LOCALITIES
        provinces:
        - PROVINCES
        streetAddresses:
        - STREET_ADDRESSES
        postalCodes:
        - POSTAL_CODES
      caCertificate:
        managedSubCA:
          certificateAuthorityRef:
            name: ROOT_CA_NAME
            namespace: USER_PROJECT_NAMESPACE
      certificateProfile:
        keyUsage:
          - digitalSignature
          - keyCertSign
          - crlSign
        extendedKeyUsage:
          - EXTENDED_KEY_USAGE
      secretConfig:
        secretName: SECRET_NAME
        privateKeyConfig:
          algorithm: KEY_ALGORITHM
          size: KEY_SIZE
      acme:
        enabled: ACME_ENABLED
    

    Substitua as seguintes variáveis:

    Variável Descrição
    SUB_CA_NAME O nome da CA subordinada.
    USER_PROJECT_NAMESPACE O nome do namespace em que o projeto do usuário está localizado.
    COMMON_NAME O nome comum do certificado de CA.
    DURATION O ciclo de vida solicitado do certificado de CA.
    ROOT_CA_NAME O nome da CA raiz.
    SECRET_NAME O nome do secret do Kubernetes que contém a chave privada e o certificado de CA assinado.

    As variáveis a seguir são valores opcionais:

    Variável Descrição
    RENEW_BEFORE O tempo de rotação antes da expiração do certificado de CA.
    ORGANIZATIONS Organizações a serem usadas no certificado.
    ORGANIZATIONAL_UNITS Unidades organizacionais a serem usadas no certificado.
    COUNTRIES Países a serem usados no certificado.
    LOCALITIES Cidades a serem usadas no certificado.
    PROVINCES Estado ou províncias a serem usadas no certificado.
    STREET_ADDRESSES Endereços de rua a serem usados no certificado.
    POSTAL_CODES Códigos postais a serem usados no certificado.
    EXTENDED_KEY_USAGE O uso estendido da chave para o certificado. Se fornecidos, os valores permitidos são serverAuth e clientAuth.
    KEY_ALGORITHYM O algoritmo de chave privada usado para este certificado. Os valores permitidos são RSA, Ed25519 ou ECDSA. Se o tamanho não for fornecido, o padrão será 256 para ECDSA e 2048 para RSA. O tamanho da chave é ignorado para Ed25519.
    KEY_SIZE O tamanho, em bits, da chave privada para este certificado depende do algoritmo. O RSA permite 2048, 3072, 4096 ou 8192 (padrão 2048). O ECDSA permite 256, 384 ou 521 (padrão 256). O Ed25519 ignora o tamanho.
    ACME_ENABLED Se definido como true, a CA será executada no modo ACME e vai gerar o URL do servidor ACME. Em seguida, você poderá usar o cliente e o protocolo ACME para gerenciar certificados.
  2. Aplique o recurso personalizado à sua instância do Distributed Cloud:

    kubectl apply -f subca.yaml --kubeconfig MANAGEMENT_API_SERVER_KUBECONFIG
    

    Substitua MANAGEMENT_API_SERVER_KUBECONFIG pelo caminho para o arquivo kubeconfig do servidor da API Management.

  3. Verifique se a subautoridade de certificação está pronta. Leva cerca de 40 minutos para que a CA fique pronta:

    kubectl --kubeconfig MANAGEMENT_API_SERVER_KUBECONFIG -n USER_PROJECT_NAMESPACE get certificateauthority.pki.security.gdc.goog/SUB_CA_NAME -ojson | jq -r ' 
    .status.conditions[] | select( .type as $id | "Ready" | index($id))'
    

    A saída será assim:

    {
      "lastTransitionTime": "2025-01-24T17:09:29Z",
      "message": "CA reconciled",
      "observedGeneration": 2,
      "reason": "Ready",
      "status": "True",
      "type": "Ready"
    }
    

Criar uma AC subordinada de uma AC externa

Essa subautoridade de certificação é compatível com a assinatura de certificados de folha com ACs externas ou gerenciadas pelo usuário. Ele gera uma CSR para os usuários assinarem.

  1. Crie um recurso CertificateAuthority e salve-o como um arquivo YAML chamado subca-external.yaml:

    apiVersion: pki.security.gdc.goog/v1
    kind: CertificateAuthority
    metadata:
      Name: SUB_CA_NAME
      namespace: USER_PROJECT_NAMESPACE
    spec:
      caProfile:
        commonName: COMMON_NAME
        duration: DURATION
        renewBefore: RENEW_BEFORE
        organizations:
        - ORGANIZATION
        organizationalUnits:
        - ORGANIZATIONAL_UNITS
        countries:
        - COUNTRIES
        localities:
        - LOCALITIES
        provinces:
        - PROVINCES
        streetAddresses:
        - STREET_ADDRESSES
        postalCodes:
        - POSTAL_CODES
      caCertificate:
        externalCA: {}
      certificateProfile:
        keyUsage:
          - digitalSignature
          - keyCertSign
          - crlSign
        extendedKeyUsage:
          - EXTENDED_KEY_USAGE
      secretConfig:
        secretName: SECRET_NAME
        privateKeyConfig:
          algorithm: KEY_ALGORITHM
          size: KEY_SIZE
      acme:
        enabled: ACME_ENABLED
    

    Substitua as seguintes variáveis:

    Variável Descrição
    SUB_CA_NAME O nome da subCA.
    USER_PROJECT_NAMESPACE O ID do projeto em que você quer importar a imagem.
    COMMON_NAME O nome comum do certificado de CA.
    DURATION O ciclo de vida solicitado do certificado de CA
    SECRET_NAME O nome do secret do Kubernetes que contém a chave privada e o certificado de CA assinado.

    As variáveis a seguir são valores opcionais:

    Variável Descrição
    RENEW_BEFORE O tempo de rotação antes da expiração do certificado de CA.
    ORGANIZATION Organização a ser usada no certificado.
    ORGANIZATIONAL_UNITS Unidades organizacionais a serem usadas no certificado.
    COUNTRIES Países a serem usados no certificado.
    LOCALITIES Cidades a serem usadas no certificado.
    PROVINCES Estado ou províncias a serem usadas no certificado.
    STREET_ADDRESSES Endereços de rua a serem usados no certificado.
    POSTAL_CODES Códigos postais a serem usados no certificado.
    EXTENDED_KEY_USAGE O uso estendido da chave para o certificado. Se fornecidos, os valores permitidos são serverAuth e clientAuth.
    KEY_ALGORITHYM O algoritmo de chave privada usado para este certificado. Os valores permitidos são RSA, Ed25519 ou ECDSA. Se o tamanho não for fornecido, o padrão será 256 para ECDSA e 2048 para RSA. O tamanho da chave é ignorado para Ed25519.
    KEY_SIZE O tamanho, em bits, da chave privada para este certificado depende do algoritmo. RSA permite 2048, 3072, 4096 ou 8192 (padrão 2048). ECDSA permite 256, 384 ou 521 (padrão 256). Ed25519 ignora o tamanho.
    ACME_ENABLED Se definido como true, a CA será executada no modo ACME e vai gerar o URL do servidor ACME. Em seguida, você poderá usar o cliente e o protocolo ACME para gerenciar certificados.
  2. Aplique o recurso personalizado à sua instância do Distributed Cloud:

    kubectl apply -f subca-external.yaml --kubeconfig MANAGEMENT_API_SERVER_KUBECONFIG
    
  3. Uma CSR para a subautoridade certificadora é gerada no servidor da API GDC Management. Faça o download e assine a CSR. Depois de assinado, faça upload do certificado assinado no servidor da API GDC Management.

  4. Reúna as solicitações de assinatura de certificado (CSR) do seu ambiente do Distributed Cloud:

    kubectl get certificateauthorities SUB_CA_NAME -n USER_PROJECT_NAMESPACE -ojson | jq -j '"echo ", .status.externalCA.csr, " | base64 -d > ","sub_ca.csr\n"' | bash
    

    O comando gera um arquivo CSR chamado sub_ca.csr no diretório atual. Esse arquivo contém uma CSR para um certificado de CA X.509.

  5. Use a CA raiz do cliente para solicitar certificados de CA assinados para o arquivo sub_ca.csr.

  6. Para uma solicitação de assinatura de certificado aprovada, você precisa receber um certificado de CA assinado pela CA raiz do cliente. Armazene o certificado no arquivo sub_ca.crt no diretório atual.

  7. Se aplicável, obtenha o certificado de CA raiz do cliente e armazene-o no arquivo ca.crt no diretório atual.

  8. Verifique as extensões de nome alternativo do assunto (SAN) no certificado:

    openssl x509 -text -noout -in sub_ca.crt | grep -A 1 "Subject Alternative Name"
    

    Se o certificado de CA tiver um nome comum (CN) em vez de um SAN, verifique o CN no certificado:

    openssl x509 -text -noout -in sub_ca.crt | grep -A 1 "Subject: CN"
    
  9. Gere o spec para corrigir o recurso CertificateAuthority:

    echo "spec:
      caCertificate:
        externalCA:
          signedCertificate:
            certificate: $(base64 -w0 SUB_CA_NAME.crt)
            ca: $(base64 -w0 ca.crt)" > patch.txt
    

    O conteúdo do arquivo patch.txt é semelhante a este:

    spec:
      caCertificate:
        externalCA:
          signedCertificate:
            certificate: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURSekNDQ…
            ca: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURRVENDQ…
    
  10. Edite o campo spec do recurso CertificateAuthority:

    kubectl patch certificateauthority SUB_CA_NAME -n USER_PROJECT_NAMESPACE--patch-file patch.txt --type='merge'
    
  11. Verifique se a subautoridade de certificação (subCA) do tipo "traga sua própria" (BYO, na sigla em inglês) está pronta. Normalmente, leva cerca de 40 minutos para a CA ficar pronta:

    kubectl -n USER_PROJECT_NAMESPACE get certificateauthority.pki.security.gdc.goog/SUB_CA_NAME -ojson | jq -r ' .status.conditions[] | select( .type as $id | "Ready" | index($id))'
    

    A saída será assim:

    {
      "lastTransitionTime": "2024-04-30T22:10:50Z",
      "message": "Certificate authority is ready for use",
      "observedGeneration": 3,
      "reason": "Ready",
      "status": "True",
      "type": "Ready"
    }
    
  12. Verifique a data de validade dos certificados de CA assinados:

    kubectl -n USER_PROJECT_NAMESPACE get secret SECRET_NAME -ojson | jq -j '"echo ", .metadata.name, " $(echo ", .data["tls.crt"], "| base64 -d | openssl x509 -enddate -noout)\n"' | bash
    

Listar CAs

Para listar todos os recursos do Certificate Authority Service na sua instância isolada do Distributed Cloud, faça o seguinte:

Use o parâmetro certificateauthorities para listar todos os recursos CertificateAuthority:

   kubectl --kubeconfig MANAGEMENT_API_SERVER_KUBECONFIG -n USER_PROJECT_NAMESPACE get certificateauthorities

A saída será assim:

   NAMESPACE    NAME              READY   REASON   AGE
   foo          root-ca           True    Ready    7h24m
   foo          sub-ca            True    Ready    7h24m