Criar uma autoridade certificadora subordinada

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

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

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 precisa ser assinada pela CA externa.

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 CA subordinada, é preciso solicitar as permissões necessárias e preparar o ambiente.

Solicitar papéis do IAM

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

Preparar o ambiente

Criar uma Sub CA gerenciada

Para uma sub-CA gerenciada, o signatário do certificado de CA é outra CA (CA raiz) criada no CA Service.

Para criar uma sub-CA 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. Especifique como uma duração em horas (por exemplo, 1000h). Unidades como dias (d) ou anos (y) não são aceitas.
    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 que o certificado de CA expire.
    ORGANIZATIONS Organizações que serão usadas no certificado.
    ORGANIZATIONAL_UNITS Unidades organizacionais a serem usadas no certificado.
    COUNTRIES Países que serão usados no certificado.
    LOCALITIES Cidades que serão usadas no certificado.
    PROVINCES Estado ou províncias a serem usados no certificado.
    STREET_ADDRESSES Endereços que serão usados no certificado.
    POSTAL_CODES Códigos postais a serem usados no certificado.
    EXTENDED_KEY_USAGE O uso de chave estendido para o certificado. Se fornecido, 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 desse 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 é executada no modo ACME e gera o URL do servidor ACME. Em seguida, use o cliente e o protocolo ACME para gerenciar certificados.
  2. Aplique o recurso personalizado à 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 de API Management.

  3. Verifique a prontidão da CA subordinada. 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 sub-CA de uma CA externa

Essa Sub CA é compatível com a assinatura de certificados de folha com CAs 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. Especifique como uma duração em horas (por exemplo, 1000h). Unidades como dias (d) ou anos (y) não são aceitas.
    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 que o certificado de CA expire.
    ORGANIZATION Organização que será usada no certificado.
    ORGANIZATIONAL_UNITS Unidades organizacionais a serem usadas no certificado.
    COUNTRIES Países que serão usados no certificado.
    LOCALITIES Cidades que serão usadas no certificado.
    PROVINCES Estado ou províncias a serem usados no certificado.
    STREET_ADDRESSES Endereços que serão usados no certificado.
    POSTAL_CODES Códigos postais a serem usados no certificado.
    EXTENDED_KEY_USAGE O uso de chave estendido para o certificado. Se fornecido, 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 desse 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 é executada no modo ACME e gera o URL do servidor ACME. Em seguida, use o cliente e o protocolo ACME para gerenciar certificados.
  2. Aplique o recurso personalizado à instância do Distributed Cloud:

    kubectl apply -f subca-external.yaml --kubeconfig MANAGEMENT_API_SERVER_KUBECONFIG
    
  3. Uma CSR para a sub-CA é gerada no servidor de API Management do GDC. Você precisa baixar a CSR e assiná-la. Depois de assinado, é possível fazer upload do certificado assinado no servidor de API Management do GDC.

  4. Reúna as solicitações de assinatura de certificado (CSR) do 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, é necessário 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, consiga o certificado de CA raiz do cliente e armazene-o no arquivo ca.crt no diretório atual.

  8. Verifique o nome comum (CN) do certificado de CA:

    openssl x509 -noout -subject -in sub_ca.crt
    

    Se a configuração exigir extensões de nome alternativo do sujeito (SAN, na sigla em inglês), verifique as extensões de SAN no certificado:

    openssl x509 -text -noout -in sub_ca.crt | grep -A 1 "Subject Alternative Name"
    
  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 ao seguinte:

    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 a prontidão da sub-CA BYO. Normalmente, leva cerca de 40 minutos para que a CA fique 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 do Distributed Cloud com isolamento físico, 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