Renovação Automática de Certificados

Playbook de Ansible para configuração de Certbot

Playbook
Pode transferir o zip através do link seguinte: Pacote cliente ACME FCCN - certbot - v1.2.2

O repositório com a com o código fonte do Playbook encontra-se disponível no Github.


1. Protocolo ACME

O protocolo Automated Certificate Management Environment (ACME) é um protocolo de gestão de certificados SSL desenvolvido para simplificar e automatizar a emissão, renovação e revogação desses certificados. O seu objetivo principal é tornar o processo seguro, eficiente e, acima de tudo, automática. Criado pela Internet Security Research Group (ISRG), o protocolo ACME visa tornar-se numa ferramenta essencial na vida dos administradores de sistemas, garantindo que os certificados SSL estejam sempre atualizados.

1.1. Funcionamento do ACME

O protocolo ACME opera através da troca de um conjunto de mensagens criptográficas entre um cliente ACME e uma Autoridade de Certificação (CA). A CA, por sua vez, é responsável por verificar a identidade do cliente e emitir ou renovar o certificado SSL. As interações entre o servidor e a CA são baseadas em desafios (challenges) criptográficos, garantindo a autenticidade do pedido.

1.1.1. Etapas do ACME

  1. Pedido de certificado: o cliente ACME envia para a CA o pedido de um certificado.
  2. Validação da propriedade do domínio (desafios de validação): a CA responde com o envio de um conjunto de desafios (challenges). Para responder aos desafios, o cliente ACME terá de provar que controla cada subject name que pediu no certificado desejado. Os desafios podem ser feitos via DNS ou HTTP.
  3. Emissão do certificado: Após a validação dos desafios de forma bem sucedida, o cliente ACME envia para a CA um certificate signing request (CSR). A CA verifica se o cliente controla a chave privada associada a esse CSR, e em caso afirmativo emite o certificado para o cliente.
CAs e credenciais EAB
Algumas CAs, como é o caso da HARICA, implementam a extensão ao protocolo ACME de External Account Bindings (EAB), que é uma forma de associar o conceito de contas ACME criadas no portal da HARICA, com domínios já registados no portal (que podem ou não já ter sido validados através de Domain Control Validation DCV).

Durante o processo ACME a CA da HARICA permite a utilização de credenciais EAB. Após serem fornecidas as credenciais EAB a um cliente ACME (e.g., Certbot), existem 2 possibilidades:
  1. Domínio já está validado no portal da HARICA e utilização de credenciais EAB: neste caso não são submetidos os desafios mencionados na etapa 2. O domínio pedido do certificado é dado como válido e procede-se imediatamente para a emissão do certificado.
  2. Domínio não está pré-validado no portal da HARICA: a emissão de certificados SSL segue o protocolo ACME tradicional, sendo necessário validar o controlo de propriedade sobre o Domínio (via DNS ou HTTP). É importante salientar, que mesmo não estando pré-validado, o domínio tem de estar registado no portal da HARICA. Domínios validados durante o processo ACME não passam a estar validados no portal da HARICA.

Em resumo, a utilização de credenciais EAB proporciona dois grandes benefícios:
  • nível adicional de segurança, pois reduz a possibilidade de entidades externas com acesso ao URL ACME de uma instituição consigam criar certificados em nome dessa instituição.
  • obtenção de certificados mais simples e flexível, pois reduz a necessidade de efetuar a validação com a CA da propriedade do domínio do certificado no momento do seu pedido.

2.2. Vantagens da automação com ACME

  1. Eficiência operacional: A automatização elimina a necessidade de intervenção manual repetitiva. Isso não apenas economiza tempo, mas também reduz o risco associado a falhas humanas, garantindo uma gestão eficaz dos certificados SSL.

  2. Segurança: A automação proporcionada pelo ACME e pelo cliente ACME reduz significativamente a probabilidade de erro humano. A renovação automática garante que os certificados SSL estejam sempre atualizados, fortalecendo a segurança do tráfego web.

  3. Conformidade: A automação facilita a conformidade com prazos de renovação, uma vez que os certificados são renovados automaticamente antes da sua expiração. Isso é crucial para garantir que os sites permaneçam em conformidade com as políticas de segurança e regulamentações.

  4. Facilidade de implementação: Os clientes ACME são projetados para serem fáceis de implementar e configurar. Isso torna a adoção do ACME e a automação da gestão de certificados SSL acessíveis a uma ampla gama de utilizadores, desde administradores de sistemas experientes até responsáveis por pequenos websites.

1.2. Desafios da automação com ACME

  1. Atualização tecnológica: Para tirar pleno partido do protocolo ACME, os servidores web (ou outras aplicações que requeiram certificados SSL) devem suportar e estar configurados para utilizar este protocolo, nomeadamente através da utilização de clientes ACME. Isso pode exigir atualizações tecnológicas, sendo crucial garantir que os sistemas estejam atualizados.

  2. Monitorização contínua: Embora a automação simplifique a gestão de certificados SSL, é essencial implementar uma monitorização contínua para garantir que tudo funcione de acordo com o esperado. Alertas automáticos podem/devem ser configurados para notificar os administradores sobre potenciais problemas.

  3. Segurança da chave privada: Uma vez que os clientes ACME lidam com chaves privadas, é crucial implementar práticas de segurança robustas para proteger essas informações sensíveis. Isso inclui a utilização de métodos de armazenamento seguro e a aplicação de políticas de acesso rigorosas. Em infraestruturas que necessitem que os certificados/chaves privadas sejam propagados para servidores diferentes de onde foram gerados, deve também ser garantida a segurança da informação durante o seu trânsito.

2. Clientes ACME

Um cliente ACME corresponde uma implementação específica do protocolo ACME que corre num servidor. Pode ou não correr junto da aplicação que irá servir o certificado SSL (por exemplo, servidor Web). Tal como referido anteriormente, o cliente ACME age como um intermediário entre o servidor e a CA, facilitando a comunicação e automatizando as etapas necessárias para a emissão e renovação de certificados SSL.

2.1 Funcionalidades dos clientes ACME

  1. Renovação automática de certificados: Uma das características mais cruciais do clientes ACME é a capacidade de renovar automaticamente os certificados antes destes expirarem. Não requerem intervenção manual, reduzindo os riscos associados a certificados expirados.

  2. Verificação de propriedade do domínio: Os clientes ACME executam os desafios criptográficos necessários para provar que o servidor tem controlo sobre o domínio para o qual está a solicitar o certificado. Este processo garante a autenticidade do pedido.

  3. Gestão automática de chaves públicas e privadas: Os clientes ACME lidam automaticamente com a geração de chaves públicas e privadas, garantindo que as informações sensíveis permaneçam seguras.

  4. Integração com servidores web: Vários clientes ACME (por exemplo, certbot) são projetados para funcionar de maneira integrada com uma variedade de servidores web populares, como Apache e Nginx, entre outros, simplificando a sua implementação e configuração.

2.2. Exemplos de clientes ACME

Existem diversos clientes ACME disponíveis online, muitos dos quais se encontram resumidos nesta lista disponível no Github.

HARICA
Para conseguirem comunicar com a HARICA o cliente ACME tem de suportar a utilização de credenciais EAB.

Especificamente, para sistema operativo Linux, os clientes mais frequentemente recomendados são:

Para sistemas Windows, alguns exemplos de clientes:

2.3. Certbot

Tal como referido anteriormente, o certbot é o cliente ACME mais usado para sistemas Linux. É uma ferramenta de linha de comandos, grátis e open-source, e é mantida pela Electronic Frontier Foundation (EFF). As principais características do certbot são:

  • Grátis e Open-source
  • Fácil de instalar
  • Automaticamente renova certificados quando faltarem 30 dias para a sua data de expiração.

Na Secção 3 é fornecido um playbook de Ansible que pode ser usado para instalar a ferramenta certbot.

Uma vez instalado, o certbot pode ser facilmente executado para pedir certificados através da linha de comandos, por exemplo:

shell> sudo certbot certonly -m <contact_email> --server <certificate_acme_directory>  --domain <certificate_domains_list> --eab-kid <acme_mac_id> --eab-hmac-key=<acme_mac_key> --standalone

onde devem ser substituídos os seguintes valores:

  • <contact_email>: email de contacto (e.g., joao.guerreiro@fccn.pt)
  • <certificate_domains_list>: lista separada por vírgulas dos domínios a pedir no certificado (e.g., 'teste1.eduroam.pt, teste2.eduroam.pt')
  • <certificate_acme_directory>: URL da directory ACME da conta fornecido pelo Administrador de Certificados da Instituição.
  • <acme_mac_id>: credencial EAB Key ID fornecida pelo Administrador de Certificados da Instituição.
  • <acme_mac_key>: credencial EAB HMAC Key fornecida pelo Administrador de Certificados da Instituição.

Para mais informações, por favor ver a Documentação Oficial.


3. Pacote de ACME FCCN

Como forma de promover a adopção da utilização do protocolo ACME na comunidade RCTS, a FCCN disponibiliza um pacote de Ansible que permite instalar e configurar um cliente de ACME para servidores Linux, especificamente o cliente certbot. O resto desta Secção encontra-se dividida em 2 sub-secções, consoante os destinatários da mesma, nomeadamente:

3.1. Gestão de Contas ACME - Administrador de Certificados da Instituição

Antes de executar o playbook de Ansible

Um elemento essencial para a utilização do processo de gestão automática de certificados é a existência de contas ACME, neste caso junto da CA da HARICA. A gestão destas contas, nomeadamente a sua criação, alteração ou remoção é da responsabilidade do Administrador de Certificados da Instituição.

Assim, e para a utilização do procedimento implementado no playbook, é necessário que sejam criadas/configuradas contas ACME no Portal da HARICA.

3.1.1. Criação de conta ACME

Pré-requisitos
A criação de uma conta ACME é associada a um (ou múltiplos) domínio. Desta forma, é um pré-requisito para a criação de contas ACME que os domínios a associar já tenham sido previamente validados na plataforma da Sectigo (via DCV).

Os passos a proceder para a criação de uma conta ACME são os seguintes:

  1. No menu de Enterprise Admin, carregar na tab de ACME e carregar no botão para criar uma nova Conta.

harica_acme_1.png

  1. Aqui pode-se escolher a Organização sobre a qual se pretende criar a conta ACME. Seleccionar o tipo de validação dos certificados (OV ou DV). É necessário introduzido um nome amigável paraa conta, de preferência algo que permita identificar facilmente a conta ACME que irá ser criada, aceitar os Termos e Condições da HARICA e criar no botão de Criar.

harica_acme_2.png

  1. Depois de criada a conta, ficam disponíveis nesta as credenciais EAB e o URL do endpoint que são necessários configurar nos Clientes ACME.

harica_acme_3.png

  1. Após a sua criação, uma conta ACME ainda não tem nenhum domínio associado. Ao navegar-se para a Tab de Domínios, é possível associar que domínios para os quais essa conta ACME poderá emitir certificados. Apenas podem ser seleccionados domínios já pré-validados no site da HARICA. Existem duas opções: 1) associar todos os domínios da organização, ou 2) associar domínios específicos. É possível adicionar regras de Allow e de Deny, sendo que em caso de conflitos, as regras de Deny explícito tomam precedência. harica_acme_4.png harica_acme_5.png

3.1.2. Passagem das credenciais ao utilizador final

Uma vez criada a conta ACME, as credenciais obtidas podem ser passadas ao utilizador final que as irá utilizar nos seus sistemas.

Segurança das credenciais
Uma vez que estas credenciais permitem a criação de qualquer certificado dentro do(s) domínio(s) associado(s), recomenda-se que esta passagem seja feita da forma mais segura possível.

Por exemplo, pode ser utilizada encriptação dos emails através da utilização de certificados pessoais.


3.2. Playbook de Ansible - Administrador de Sistemas dos serviços da Instituição

3.2.0. Pré-requisitos

As secções seguintes assumem a existência de um ambiente Linux com os seguintes requisitos:

  • Ansible instalado.
  • Pacote de ACME FCCN (.zip) mais recente já localizado no servidor.
Clique aqui para ver pré-requisitos num servidor Debian (testado em Debian 11 e 12).
shell> sudo apt install -y ansible unzip
shell> wget --no-check-certificate https://certificados.fccn.pt/assets/acme/certbot_playbook_<current_version>.zip
shell> unzip certbot_playbook_<current_version>.zip -d certbot_ansible
shell> cd certbot_ansible
Clique aqui para ver pré-requisitos num servidor CentOS (testado em CentOS Stream 9).
shell> sudo yum install wget unzip
shell> sudo dnf install ansible-core
shell> ansible-galaxy collection install community.general ansible.posix
shell> sudo dnf install epel-release
shell> sudo dnf upgrade
shell> wget --no-check-certificate https://certificados.fccn.pt/assets/acme/certbot_playbook_<current_version>.zip
shell> unzip certbot_playbook_<current_version>.zip -d certbot_ansible
shell> cd certbot_ansible

3.2.1. Inventário - Credenciais ACME

O cliente de ACME (certbot) necessita de credenciais EAB associadas a uma conta ACME (hmac_id e hmac_key) e do endpoint a utilizar (server), pelo que antes da execução do pacote de Ansible devem ser pedidas as credenciais ACME.

Depois de seguido o procedimento detalhado na Secção anterior, as credenciais recebidas devem ser colocadas num ficheiro YAML, por exemplo defaults/credentials.yml, que deve ser construído seguindo a sintaxe exemplificada em defaults/template.yml:

Clique aqui para ver exemplo do ficheiro defaults/template.yml.
contact_email: <contact_fccn> #exemplo: joao.guerreiro@fccn.pt

acme_accounts:
  - name: <serviço> #exemplo: "CIENCIA ID"
    ca: acme-v02.harica.gr
    server: https://acme-v02.harica.gr/acme/<directory_id>/directory
    mac_id: <credencial_eab_hmac_id>
    mac_key: <credencial_eab_hmac_key>

O pacote permite a existência de diferentes conjuntos de credenciais (por exemplo, associados a diferentes serviços/domínios), podendo ser colocados no ficheiro credentials.yml numa lista. Cada conjunto de credenciais deve estar associado a um nome (por exemplo, eduroam, rctsaai, etc.) que será fornecido no momento de execução do pacote para escolha das credenciais a utilizar.

Embora opcional, é recomendável que as credenciais ACME sejam encriptadas utilizando o Ansible Vault.

3.2.2. Utilizar o Ansible Vault

Para facilitar a segurança e visibilidade das credenciais ACME, o pacote de Ansible vem com um ficheiro defaults/secrets.yml, que pode ser utilizado de acordo com as recomendações oficiais Ansible.

Nomeadamente:

  • Colocar as credenciais encriptadas em variáveis no ficheiro defaults/secrets.yml.
  • No ficheiro de credenciais (e.g., defaults/credentials.yml) as variáveis com as credenciais que serão usadas pelo playbook deverão apontar para as variáveis encriptadas no ficheiro defaults/secrets.yml.
3.2.2.1. Encriptar as credenciais

Para tal, as credenciais ACME podem ser encriptadas pelo Ansible Vault, através dos seguintes comando:

shell> ansible-vault encrypt_string --ask-vault-pass '<Key ID>' --name 'vault_<service>_mac_id'
shell> ansible-vault encrypt_string --ask-vault-pass '<HMAC Key>' --name 'vault_<service>_mac_key'

onde <Key ID> e <HMAC Key> devem ser substituídos pelas credenciais ACME recebidas, e <service> por um nome que identifique o serviço. Ao executar cada um destes comandos, vai ser pedida uma password que passará a corresponder à password do Ansible Vault deste inventário. Para tal, deve ser usada a mesma password em todas as encriptações/desencriptações deste projecto/playbook.

O comando irá fornecer fornecer o bloco de texto que deve ser copiado integralmente para o ficheiro defaults\secrets.yml.

Clique aqui para ver um exemplo do output do commando ansible-vault encrypt.
vault_eduroam_mac_id: !vault |
      $ANSIBLE_VAULT;1.1;AES256
      62313365396662343061393464336163383764373764613633653634306231386433626436623361
      6134333665353966363534333632666535333761666131620a663537646436643839616531643561
      63396265333966386166373632626539326166353965363262633030333630313338646335303630
      3438626666666137650a353638643435666633633964366338633066623234616432373231333331
      6564
Clique aqui para ver um exemplo do ficheiro defaults/secrets.yml preenchido.
---
vault_eduroam_mac_id: !vault |
                      $ANSIBLE_VAULT;1.1;AES256
                      39396466383037323236346163383033326236363234613062653862323864383464373165643031
                      3666653933336134356239356535366530613837363963370a626139306336306435363565613937
                      66663062303333643363383762373833383632623663313330643435656330326235333731666638
                      6338643530333832620a653130663762633134386137656236383961666437383534323731316135
                      34356439353038333737663265633334336265613765316435313237313762306535
vault_eduroam_mac_key: !vault |
                       $ANSIBLE_VAULT;1.1;AES256
                       61396563393339636639383362326563396363653438313831653565356635383734633861376534
                       3661316165643935393338303238643062323366323232380a633164346137303263306566643333
                       62323834396530663830663635643661636366383965346235363934653266666337393234356632
                       3034663632393031300a306563333236666439313934663435633766646338306134353035396634
                       36643839626135646539653333383366306433313265376665653262656135343532366430333164
                       65663664313032366338343135653137353138323161396666646664306338343364353333616363
                       62616630633863323038323764393535623938643265326236323933313631333730643131633061
                       65636332323037323563363464613139396138326339616337343030383736323531623233393530
                       6262
3.2.2.2. Utilizar as variáveis encriptadas no Inventário

Por fim, é necessário que as variáveis de credenciais utilizadas dentro do playbook de Ansible referenciem as variáveis encriptadas que foram criadas, utilizando sintaxe jinja2. Para tal, basta alterar o ficheiro de inventário previamente criado com base no defaults/template.yml (por exemplo, defaults/credentials.yml), de acordo com o exemplo seguinte:

---
contact_email: joao.guerreiro@fccn.pt

acme_accounts:
    - name: "eduroam"
      ca: "acme-v02.harica.gr"
      server: "https://acme-v02.harica.gr/acme/XXXXXXXXXXXXX/directory"
      mac_id: "{{ vault_eduroam_mac_id }}"
      mac_key: "{{ vault_eduroam_mac_key }}"

É importante que o nome das variáveis correspondam exactamente aos que estão definidos no ficheiro defaults/secrets.yml. Desta forma as variáveis das credenciais vão utilizar os valores encriptados.

3.2.3. Executar o playbook

O pacote fornecido consiste num playbook de Ansible que irá efetuar sempre as seguintes etapas:

  1. Instalar o certbot (caso não esteja já instalado)
  2. Registar o certbot como cliente de ACME na entidade certificadora da Sectigo com as credenciais ACME fornecidas (caso não esteja já registado)
  3. Pedir o(s) certificado(s) desejados

O playbook de Ansible permite que sejam fornecidos 7 argumentos:

option_acme_account_name
  • Obrigatório.
  • Nome das credenciais ACME a utilizar. Deve corresponder a um valor existente no ficheirodefaults/credentials.yml.
  • Exemplo: option_acme_account_name='eduroam'
option_common_names_list
  • Obrigatório.
  • lista de common-names, separados por vírgulas. Para cada common-name será gerado um (ou vários, dependendo do valor de option_multi_domain) certificado(s) SSL do tipo OV.
  • Exemplo: option_common_names_list='teste1.eduroam.pt,teste2.eduroam.pt'
option_credentials_file
  • Opcional (default: 'defaults/template.yml').
  • Caminho para o ficheiro com as credenciais ACME.
  • Exemplo: option_credentials_file='defaults/credentials.yml'
option_multi_domain
  • Opcional (default: 'single-domain').
  • Valores permitidos:
    • single-domain
    • multi-domain
  • Permite selecionar se se pretende um certificado single-domain por cada common-name ou um único certificado multi-domain com todos os common-names fornecidos.
  • Exemplo: option_multi_domain='single-domain'
option_post_hook
  • Opcional (default: '').
  • Permite definir uma ação (comando, script, etc.) a executar sempre que existe uma nova versão de um certificado. Um exemplo pode ser reiniciar o servidor web (e.g., apache, nginx, etc.) após renovação de certificados.
  • Exemplo: option_post_hook='service apache2 reload'
option_webserver
  • Opcional (default: 'standalone').
  • Permite definir o servidor web a ser usado para comunicar com a CA.
  • Exemplo: option_webserver='standalone'
option_encryption_algorithm
  • Opcional (default: 'ecdsa').
  • Permite definir o algoritmo de encriptação usado.
  • Exemplo: option_encryption_algorithm='ecdsa'
option_concatenate_certs
  • Opcional (default: 'False').
  • Permite gerar, para além dos ficheiros habituais, um ficheiro que agrega o certificado gerado e a chave privada. Util para algumas aplicações, como por exemplo Haproxy.
  • Exemplo: option_concatenate_certs='False'

Uma vez clonado o repositório, e devidamente configurado o ficheiro defaults/credentials.yml, o playbook de Ansible pode ser executado de uma de duas formas:

  1. Localmente.
  2. Remotamente com inventário de Ansible devidamente configurado.

A execução local pode ser feita com o seguinte comando:

shell> ansible-playbook playbook_acme_ssl.yml --extra-vars "option_acme_account_name='eduroam' option_common_names_list='teste1.eduroam.pt,teste2.eduroam.pt' option_credentials_file='defaults/credentials.yml' option_multi_domain='single-domain' option_post_hook='service apache2 reload'"
Ansible Vault
Caso esteja a ser utilizado um inventário encriptado pelo Ansible Vault tem de ser passada ao playbook a password do vault, o que pode ser feito acrescentando a flag --ask-vault-pass.

Em caso de utilização de Ansible Vault, o comando anterior deve ser substituído pelo seguinte comando:

shell> ansible-playbook playbook_acme_ssl.yml --ask-vault-pass --extra-vars "option_acme_account_name='eduroam' option_common_names_list='teste1.eduroam.pt,teste2.eduroam.pt' option_credentials_file='defaults/credentials.yml' option_multi_domain='single-domain' option_post_hook='service apache2 reload'"

3.2.3 Estado Final

Após execução do pacote, deverá ser criada a directoria /etc/letsencrypt/ com a seguinte estrutura:


/etc/letsencrypt/
├── accounts/
│   └── acme-v02.harica.gr/
│       └── acme/
│           └── e2b2669d-33bd-3308-8dc7-c0fba5d5b507/
├── archive/
│   ├── teste1.eduroam.pt/
│   │   ├── cert1.pem*
│   │   ├── chain1.pem*
│   │   ├── fullchain1.pem*
│   │   └── privkey1.pem*
│   └── teste2.eduroam.pt/
│       ├── cert1.pem*
│       ├── chain1.pem*
│       ├── fullchain1.pem*
│       └── privkey1.pem*
├── live/
│   ├── teste1.eduroam.pt/
│   │   ├── cert.pem -> ../../archive/teste1.eduroam.pt/cert1.pem*
│   │   ├── chain.pem -> ../../archive/teste1.eduroam.pt/chain1.pem*
│   │   ├── fullchain.pem -> ../../archive/teste1.eduroam.pt/fullchain1.pem*
│   │   ├── privkey.pem -> ../../archive/teste1.eduroam.pt/privkey1.pem*
│   │   └── README*
│   ├── teste2.eduroam.pt/
│   │   ├── cert.pem -> ../../archive/teste2.eduroam.pt/cert1.pem*
│   │   ├── chain.pem -> ../../archive/teste2.ciencia-id.pt/chain1.pem*
│   │   ├── fullchain.pem -> ../../archive/teste2.ciencia-id.pt/fullchain1.pem*
│   │   ├── privkey.pem -> ../../archive/teste2.ciencia-id.pt/privkey1.pem*
│   │   └── README*
│   └── README*
├── options-ssl-apache.conf*
├── renewal/
│   ├── teste1.ciencia-id.pt.conf*
│   └── teste2.ciencia-id.pt.conf*
└── renewal-hooks/
    ├── deploy/
    ├── post/
    └�