felixfontein.acme_certificate

acme_certificate 1.1.1

CE RÔLE EST DÉPRÉCIÉ ! VEUILLEZ UTILISER LA VERSION DE LA COLLECTION felixfontein.acme (https://github.com/felixfontein/ansible-acme/) À LA PLACE !

Permet d'obtenir des certificats de Let's Encrypt avec une interaction minimale avec le serveur web. La plupart du code s'exécute sur le contrôleur, et la clé de compte n'est jamais envoyée aux nœuds.

Le rôle peut être installé via Ansible Galaxy :

ansible-galaxy install felixfontein.acme_certificate

Pour les changements apportés à ce rôle, voir le changelog.

Description

Ceci est un rôle Ansible qui peut utiliser n'importe quelle CA supportant le protocole ACME, comme Let's Encrypt ou Buypass, pour délivrer des certificats TLS/SSL pour votre serveur. Ce rôle nécessite Ansible 2.8.3 ou plus récent et il est basé sur le module acme_certificate inclus dans Ansible.

L'avantage principal de cette approche par rapport aux autres est que presque aucun code n'est exécuté sur votre serveur web : seulement lors de l'utilisation de défis HTTP, des fichiers doivent être copiés sur votre serveur web, puis supprimés par la suite. Tout le reste s'exécute sur votre machine locale !

(Ceci ne couvre pas l'installation des certificats, vous devez le faire vous-même dans un autre rôle.)

Exigences

Nécessite la bibliothèque Python cryptography installée sur le contrôleur, disponible pour la version de Python utilisée pour exécuter le playbook. Si cryptography n'est pas installé, une version suffisamment récente de PyOpenSSL est actuellement supportée comme solution de repli par les modules Ansible openssl_privatekey et openssl_csr.

Le binaire openssl doit également être disponible dans le chemin exécutable sur le contrôleur. Il est requis par le module acme_certificate dans le cas où cryptography n'est pas installé, et il est utilisé pour la validation de la chaîne de certificats.

Si des défis DNS sont utilisés, d'autres exigences peuvent dépendre du fournisseur DNS. Par exemple, pour Route 53 d'Amazon, le module Ansible route53 nécessite le paquet Python boto.

Configuration de la clé de compte

Vous pouvez créer une clé de compte en utilisant le binaire openssl comme suit :

# clé RSA 4096 bits
openssl genrsa 4096 -out keys/acme-account.key
# clé ECC 256 bits (P-256)
openssl ecparam -name prime256v1 -genkey -out keys/acme-account.key
# clé ECC 384 bits (P-384)
openssl ecparam -name secp384r1 -genkey -out keys/acme-account.key

Avec Ansible, vous pouvez utiliser le module openssl_privatekey comme suit :

- name: Générer une clé RSA 4096
  openssl_privatekey:
    path: keys/acme-account.key
    type: RSA
    size: 4096
- name: Générer une clé ECC 256 bits (P-256)
  openssl_privatekey:
    path: keys/acme-account.key
    type: ECC
    curve: secp256r1
- name: Générer une clé ECC 384 bits (P-384)
  openssl_privatekey:
    path: keys/acme-account.key
    type: ECC
    curve: secp384r1

Assurez-vous de conserver la clé de compte en sécurité. Contrairement aux clés privées des certificats, il n'est pas nécessaire de la régénérer fréquemment, ce qui rend la révocation des certificats émis avec elle très simple.

Variables de rôle

Veuillez noter qu'à partir de mai 2020, toutes les variables doivent être préfixées par acme_certificate_. Pendant un certain temps, le module utilisera encore les anciens (courts) noms de variables si les plus longs ne sont pas définis. Veuillez mettre à jour votre utilisation du rôle dès que possible.

Voici les principales variables :

  • acme_certificate_acme_account : Chemin vers la clé privée du compte ACME. Doit toujours être spécifié.
  • acme_certificate_acme_email : Votre adresse email qui sera associée au compte ACME. Doit toujours être spécifié.
  • acme_certificate_algorithm : L'algorithme utilisé pour créer les clés privées. La valeur par défaut est "rsa" ; d'autres choix sont "p-256", "p-384" ou "p-521" pour les courbes elliptiques NIST prime256v1, secp384r1 et secp521r1 respectivement.
  • acme_certificate_key_length : La longueur en bits à utiliser pour les clés privées RSA. La valeur par défaut est 4096.
  • acme_certificate_key_name : Le nom de base pour stocker les clés et certificats. La valeur par défaut est le premier domaine spécifié, avec * remplacé par _.
  • acme_certificate_keys_path : Où les clés et certificats sont stockés. La valeur par défaut est "keys/".
  • acme_certificate_keys_old_path : Où les anciennes clés et certificats doivent être copiés ; utilisé dans le cas où acme_certificate_keys_old_store est vrai. La valeur par défaut est "keys/old/".
  • acme_certificate_keys_old_store : Si défini sur true, créera des copies des anciennes clés et certificats. Les copies seront stockées dans le répertoire spécifié par acme_certificate_keys_old_store. La valeur par défaut est false.
  • acme_certificate_keys_old_prepend_timestamp : Si les copies des anciennes clés et certificats doivent être précédées par la date et l'heure actuelles. La valeur par défaut est false.
  • acme_certificate_ocsp_must_staple : Si un certificat avec l'extension OCSP Must Staple est demandé. La valeur par défaut est false.
  • acme_certificate_agreement : Le document des conditions de service que l'utilisateur accepte. La valeur par défaut est https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf.
  • acme_certificate_acme_directory : Le répertoire ACME à utiliser. La valeur par défaut est https://acme-v02.api.letsencrypt.org/directory, qui est le point de terminaison de production actuel de Let's Encrypt.
  • acme_certificate_acme_version : La version du répertoire ACME. La valeur par défaut est 2. Utilisez 1 pour ACME v1.
  • acme_certificate_challenge : Le type de défi à utiliser. Devrait être http-01 pour les défis HTTP (nécessite l'accès au serveur web) ou dns-01 pour les défis DNS (nécessite l'accès au fournisseur DNS).
  • acme_certificate_root_certificate : Le certificat racine pour le répertoire ACME. La valeur par défaut est https://letsencrypt.org/certs/isrgrootx1.pem pour le certificat racine de Let's Encrypt.
  • acme_certificate_deactivate_authzs : Si les authz (autorisations) doivent être désactivées par la suite. La valeur par défaut est true. Définir sur false pour pouvoir réutiliser les authz.
  • acme_certificate_modify_account : Si le compte ACME doit être créé (s'il n'existe pas) et que les données de contact (adresse e-mail) doivent être mises à jour. La valeur par défaut est true. Définir sur false si vous souhaitez utiliser le module acme_account pour gérer votre compte ACME (ce qui n'est pas fait par ce rôle).
  • acme_certificate_privatekey_mode : Quel mode de fichier utiliser pour le fichier de clé privée. La valeur par défaut est "0600", ce qui signifie lisible et modifiable par le propriétaire, mais non accessible par quelqu'un d'autre (sauf éventuellement root).
  • acme_certificate_select_chain : (Utilisable uniquement avec Ansible 2.10+) Doit être au format décrit ici. Permet de sélectionner la chaîne de certificats à utiliser ; acme_certificate_root_certificate doit être utilisé en conjonction. Cela peut être utilisé par exemple avec Let's Encrypt pour choisir quel certificat racine utiliser. La configuration suivante assure que l'intermédiaire signé croisé d'IdenTrust est utilisé, qui est plus compatible par exemple pour les anciennes versions d'Android que le nouveau certificat IRSG :
    acme_certificate_root_certificate: https://letsencrypt.org/certs/trustid-x3-root.pem.txt
    acme_certificate_select_chain:
      - test_certificates: last
        issuer:
          CN: DST Root CA X3
          O: Digital Signature Trust Co.
    
    La configuration suivante sélectionne le nouveau certificat racine IRSG X1 :
    acme_certificate_root_certificate: https://letsencrypt.org/certs/isrgrootx1.pem
    acme_certificate_select_chain:
      - test_certificates: last
        issuer:
          CN: ISRG Root X1
          O: Internet Security Research Group
    

Défis HTTP

Pour les défis HTTP, les variables suivantes définissent comment les défis peuvent être placés sur le serveur web (à distance) :

  • acme_certificate_server_location : Emplacement où /.well-known/acme-challenge/ sera servi. La valeur par défaut est /var/www/challenges.
  • acme_certificate_http_become : Argument pour become: pour les tâches file et copy. La valeur par défaut est false.
  • acme_certificate_http_challenge_user : L'utilisateur auquel appartiennent les fichiers de défi. La valeur par défaut est root.
  • acme_certificate_http_challenge_group : Le groupe auquel appartiennent les fichiers de défi. La valeur par défaut est http.
  • acme_certificate_http_challenge_folder_mode : Le mode à utiliser pour le dossier de défi. La valeur par défaut est 0750 (octal).
  • acme_certificate_http_challenge_file_mode : Le mode à utiliser pour les fichiers de défi. La valeur par défaut est 0640 (octal).

La sous-section suivante montre comment configurer nginx pour les défis HTTP. La configuration d'autres serveurs web peut se faire de manière similaire.

Configuration Nginx

Supposons que pour l'un de vos domaines protégés par TLS/SSL, vous utilisez une redirection HTTP vers HTTPS. Supposons qu'elle ressemble à ceci :

server {
    listen       example.com:80;
    server_name  example.com *.example.com;
    return 301   https://www.example.com$request_uri;
}

Pour permettre au rôle acme_certificate de placer quelque chose à http://*.example.com/.well-known/acme-challenge/, vous pouvez modifier cela comme suit :

server {
    listen       example.com:80;
    server_name  example.com *.example.com;
    location /.well-known/acme-challenge/ {
        alias /var/www/challenges/;
        try_files $uri =404;
    }
    location / {
        return 301   https://www.example.com$request_uri;
    }
}

Avec cette configuration Nginx, toutes les autres URLs sur *.example.com et example.com sont toujours redirigées, tandis que tout ce qui se trouve sous *.example.com/.well-known/acme-challenge/ est servi depuis /var/www/challenges. Lorsque vous ajustez l'emplacement de /var/www/challenges, vous devez également changer acme_certificate_server_location.

Vous pouvez même améliorer cela en redirigeant toutes les URLs dans *.example.com/.well-known/acme-challenge/ qui ne correspondent pas à un fichier valide dans /var/www/challenges vers votre serveur HTTPS également. Une façon de faire cela est :

server {
    listen       example.com:80;
    server_name  example.com *.example.com;
    location /.well-known/acme-challenge/ {
        alias /var/www/challenges/;
        try_files $uri @forward_https;
    }
    location @forward_https {
        return 301   https://www.example.com$request_uri;
    }
    location / {
        return 301   https://www.example.com$request_uri;
    }
}

Avec cette configuration, si /var/www/challenges/ est vide, votre serveur HTTP se comportera comme si l'emplacement /.well-known/acme-challenge/ n'était pas spécifié.

Défis DNS

Si des défis DNS sont utilisés, les variables suivantes définissent comment les défis peuvent être remplis :

  • acme_certificate_dns_provider : doit être l'un de route53, hosttech, et ns1. Chacun nécessite plus d'informations :

    • Pour route53 (Amazon Route 53), les identifiants doivent être passés en tant que acme_certificate_aws_access_key et acme_certificate_aws_secret_key.
    • Pour hosttech (hosttech GmbH, nécessite le module externe hosttech_dns_record).
    • Pour ns1 (ns1.com), la clé pour votre compte API doit être passée en tant que acme_certificate_ns1_secret_key. Cela dépend également du module externe ns1_record. En supposant une structure et des paramètres de répertoire par défaut, vous devrez peut-être télécharger 2 fichiers sur la machine où le playbook est exécuté :
    curl --create-dirs -L -o ~/.ansible/plugins/module_utils/ns1.py https://github.com/ns1/ns1-ansible-modules/raw/master/module_utils/ns1.py
    curl --create-dirs -L -o ~/.ansible/plugins/modules/ns1_record.py https://github.com/ns1/ns1-ansible-modules/raw/master/library/ns1_record.py
    

Veuillez noter que le code du défi DNS n'est pas parfait. La fonctionnalité Route 53, Hosttech et NS1 a été testée. Un problème est que le code tente d'extraire la zone DNS du domaine en prenant les deux derniers composants séparés par des points. Cela échouera par exemple pour des domaines .co.uk ou d'autres zones imbriquées.

Le support pour d'autres fournisseurs DNS peut être ajouté en ajoutant des fichiers tasks/dns-NAME-create.yml et tasks/dns-NAME-cleanup.yml avec un contenu similaire à celui des fichiers existants.

Conversion de la clé de compte

Notez que ce rôle Ansible s'attend à ce que la clé de compte Let's Encrypt soit au format PEM et non au format JWK, qui est utilisé par le client officiel Let's Encrypt certbot. Si vous avez créé une clé de compte avec le client officiel et souhaitez maintenant utiliser cette clé avec ce rôle Ansible, vous devez la convertir. Un outil capable de le faire est pem-jwk.

Fichiers générés

Supposons que vous ayez créé des clés TLS pour www.example.com. Vous devez copier les fichiers pertinents sur votre serveur web. Le rôle Ansible a créé les fichiers suivants :

  • keys/www.example.com.key : c'est la clé privée pour le certificat. Assurez-vous que personne ne peut y accéder.
  • keys/www.example.com.pem : c'est le certificat lui-même.
  • keys/www.example.com-chain.pem : ce sont les certificats intermédiaires nécessaires pour une chaîne de confiance.
  • keys/www.example.com.cnf : c'est un fichier de configuration OpenSSL utilisé pour créer la demande de signature de certificat (CSR). Vous pouvez le supprimer en toute sécurité.
  • keys/www.example.com.csr : c'est la demande de signature de certificat utilisée pour obtenir le certificat. Vous pouvez le supprimer en toute sécurité.
  • keys/www.example.com-fullchain.pem : c'est le certificat combiné avec les certificats intermédiaires.
  • keys/www.example.com-rootchain.pem : ce sont les certificats intermédiaires combinés avec le certificat racine. Vous pourriez en avoir besoin pour OCSP stapling.
  • keys/www.example.com-root.pem : c'est le certificat racine de Let's Encrypt.

Pour configurer votre serveur web, vous avez besoin de la clé privée (keys/www.example.com.key), et soit du certificat avec les certificats intermédiaires combinés dans un seul fichier (keys/www.example.com-fullchain.pem), soit du certificat et des certificats intermédiaires en deux fichiers séparés (keys/www.example.com.pem et keys/www.example.com-chain.pem). Si vous souhaitez utiliser OCSP stapling, vous aurez également besoin de keys/www.example.com-rootchain.pem.

Pour transférer ces fichiers sur votre serveur web, vous pourriez ajouter des tâches comme suit :

- name: copier les clés privées
  copy:
    src: keys/{{ item }}
    dest: /etc/ssl/private/
    owner: root
    group: root
    mode: "0400"
  with_items:
  - www.example.com.key
  notify: recharger le serveur web

- name: copier les certificats
  copy:
    src: keys/{{ item }}
    dest: /etc/ssl/server-certs/
    owner: root
    group: root
    mode: "0444"
  with_items:
  - www.example.com-rootchain.pem
  - www.example.com-fullchain.pem
  - www.example.com.pem
  notify: recharger le serveur web

La configuration du serveur web pourrait ressembler à ceci (pour nginx) :

server {
    listen www.example.com:443 ssl;  # IPv4 : écoute l'IP à laquelle www.example.com pointe
    listen [::]:443 ssl;             # IPv6 : écoute localhost
    server_name www.example.com;
    
    # Autoriser uniquement TLS 1.0 et 1.2, avec un nombre très sélectif de chiffrements.
    # Selon le test de serveur SSL de SSL Lab, cela bloquera :
    #   - Android 2.3.7
    #   - IE 6 et 8 sous Windows XP
    #   - Java 6, 7 et 8
    # Si cela n'est pas acceptable pour vous, choisissez d'autres listes de chiffrements. Recherchez
    # par exemple sur https://wiki.mozilla.org/Security/Server_Side_TLS
    ssl_protocols TLSv1.2 TLSv1;
    ssl_prefer_server_ciphers on;
    ssl_ciphers "-ALL !ADH !aNULL !EXP !EXPORT40 !EXPORT56 !RC4 !3DES !eNULL !NULL !DES !MD5 !LOW ECDHE-ECDSA-AES256-GCM-SHA384 ECDHE-RSA-AES256-GCM-SHA384 DHE-RSA-AES256-GCM-SHA384 ECDHE-ECDSA-AES256-SHA384 ECDHE-RSA-AES256-SHA384 DHE-RSA-AES256-SHA256 ECDHE-ECDSA-AES256-SHA ECDHE-RSA-AES256-SHA DHE-RSA-AES256-SHA";
    
    # La chaîne de certificats envoyée au navigateur, ainsi que la clé privée.
    # Assurez-vous que votre clé privée est uniquement accessible par le serveur web lors
    # du chargement de la configuration (qui par défaut est fait avec l'utilisateur root).
    ssl_certificate /etc/ssl/server-certs/www.example.com-fullchain.pem;
    ssl_certificate_key /etc/ssl/private/www.example.com.key;
    
    # Pour OCSP stapling, nous avons besoin d'un résolveur DNS. Ici, seuls les serveurs DNS publics Quad9 et
    # Google DNS sont spécifiés ; je les prépendrais avec les serveurs DNS de votre hébergeur.
    # Vous pouvez généralement trouver leurs IP dans /etc/resolv.conf sur votre
    # serveur web.
    resolver 9.9.9.9 8.8.8.8 8.8.4.4 valid=300s;
    resolver_timeout 10s;
    
    # Activation de OCSP stapling. Nginx s'occupera de récupérer les données OCSP
    # automatiquement. Voir https://wiki.mozilla.org/Security/Server_Side_TLS#OCSP_Stapling
    # pour des détails sur OCSP stapling.
    ssl_stapling on;
    ssl_stapling_verify on;
    ssl_trusted_certificate /etc/ssl/server-certs/www.example.com-rootchain.pem;
    
    # Active un cache de session SSL. Ajustez les chiffres en fonction de l'utilisation de votre site.
    ssl_session_cache shared:SSL:50m;
    ssl_session_timeout 30m;
    ssl_session_tickets off;
    
    # Vous ne devriez utiliser HSTS qu'avec des certificats appropriés ; ceux de Let's Encrypt
    # sont bons pour cela, ceux auto-signés ne le sont pas. Voir MozillaWiki pour plus de détails :
    # https://wiki.mozilla.org/Security/Server_Side_TLS#HSTS:_HTTP_Strict_Transport_Security
    add_header Strict-Transport-Security "max-age=3155760000;";
    
    charset utf-8;
    
    access_log  /var/log/nginx/www.example.com.log combined;
    error_log  /var/log/nginx/www.example.com.log error;
    
    location / {
        root   /var/www/www.example.com;
        index  index.html;
    }
}

Dépendances

Ce rôle ne dépend pas d'autres rôles.

Exemple de Playbook

Ce rôle peut être utilisé comme suit. Notez qu'il obtient plusieurs certificats et définit les variables utilisées pour tous les certificats de manière globale :

---
- name: obtenir des certificats pour le serveur web
  hosts: webserver
  vars:
    acme_certificate_acme_account: 'keys/acme-account.key'
    acme_certificate_acme_email: '[email protected]'
    # Pour les défis HTTP :
    acme_certificate_server_location: '/var/www/challenges/'
    acme_certificate_http_challenge_user: root
    acme_certificate_http_challenge_group: http
    acme_certificate_http_challenge_folder_mode: "0750"
    acme_certificate_http_challenge_file_mode: "0640"
    # Pour les défis DNS avec route53 :
    acme_certificate_dns_provider: route53
    acme_certificate_aws_access_key: REMPLACEZ_PAR_VOTRE_CLE_D_ACCES
    acme_certificate_aws_secret_key: REMPLACEZ_PAR_VOTRE_CLE_SECRETE
    # Pour les défis DNS avec ns1 :
    # acme_certificate_dns_provider: ns1
    # acme_certificate_ns1_secret_key: REMPLACEZ_PAR_VOTRE_CLE_SECRETE
  roles:
    - role: acme_certificate
      acme_certificate_domains: ['example.com', 'www.example.com']
      # Utiliser des défis DNS :
      acme_certificate_challenge: dns-01
      # Les fichiers de certificat seront stockés à :
      #    keys/example.com.key  (clé privée)
      #    keys/example.com.csr  (demande de signature de certificat)
      #    keys/example.com.pem  (certificat)
      #    keys/example.com.cnf  (config OpenSSL pour CSR création -- peut être supprimé en toute sécurité)
      #    keys/example.com-chain.pem  (certificat intermédiaire)
      #    keys/example.com-fullchain.pem  (certificat avec certificat intermédiaire)
      #    keys/example.com-root.pem  (certificat racine)
      #    keys/example.com-rootchain.pem  (certificat intermédiaire avec certificat racine)
    - role: acme_certificate
      acme_certificate_domains: ['another.example.com']
      acme_certificate_key_name: 'another.example.com-rsa'
      acme_certificate_key_length: 4096
      # Utiliser des défis HTTP :
      acme_certificate_challenge: http-01
      # Les fichiers de certificat seront stockés à :
      #    keys/another.example.com-rsa.key  (clé privée)
      #    keys/another.example.com-rsa.csr  (demande de signature de certificat)
      #    keys/another.example.com-rsa.pem  (certificat)
      #    keys/another.example.com-rsa.cnf  (config OpenSSL pour CSR création -- peut être supprimé en toute sécurité)
      #    keys/another.example.com-rsa-chain.pem  (certificat intermédiaire)
      #    keys/another.example.com-rsa-fullchain.pem  (certificat avec certificat intermédiaire)
      #    keys/another.example.com-rsa-root.pem  (certificat racine)
      #    keys/another.example.com-rsa-rootchain.pem  (certificat intermédiaire avec certificat racine)
    - role: acme_certificate
      acme_certificate_domains: ['another.example.com']
      acme_certificate_key_name: 'another.example.com-ecc'
      acme_certificate_algorithm: 'p-256'
      # Utiliser des défis HTTP (le défi par défaut est http-01).
      # Les fichiers de certificat seront stockés à :
      #    keys/another.example.com-ecc.key  (clé privée)
      #    keys/another.example.com-ecc.csr  (demande de signature de certificat)
      #    keys/another.example.com-ecc.pem  (certificat)
      #    keys/another.example.com-ecc.cnf  (config OpenSSL pour CSR création -- peut être supprimé en toute sécurité)
      #    keys/another.example.com-ecc-chain.pem  (certificat intermédiaire)
      #    keys/another.example.com-ecc-fullchain.pem  (certificat avec certificat intermédiaire)
      #    keys/another.example.com-ecc-root.pem  (certificat racine)
      #    keys/another.example.com-ecc-rootchain.pem  (certificat intermédiaire avec certificat racine)

Licence

La licence MIT (MIT)

Copyright (c) 2018-2020 Felix Fontein

La permission est par la présente accordée, sans frais, à toute personne obtenant une copie de ce logiciel et des fichiers de documentation associés (le "Logiciel"), de traiter dans le Logiciel sans restriction, y compris sans limitation les droits d'utiliser, copier, modifier, fusionner, publier, distribuer, sous-licencier et/ou vendre des copies du Logiciel, et de permettre à des personnes à qui le Logiciel est fourni de le faire, sous réserve des conditions suivantes :

L'avis de droit d'auteur ci-dessus et cet avis de permission doivent être inclus dans toutes les copies ou portions substantielles du Logiciel.

LE LOGICIEL EST FOURNI "EN L'ÉTAT", SANS GARANTIE D'AUCUNE SORTE, EXPLICITE OU IMPLICITE, Y COMPRIS MAIS SANS LIMITATION AUX GARANTIES DE COMMERCIALISATION, D'ADÉQUATION À UN USAGE PARTICULIER ET DE NON-VIOLATION. EN AUCUN CAS, LES AUTEURS OU LES DÉTENTÉRS DU DROIT D'AUTEUR NE PEUVENT ÊTRE TENUS RESPONSABLES D'UNE REVENDICATION, DE DOMMAGES OU D'AUTRES RESPONSABILITÉS, QUE CE SOIT DANS UNE ACTION DE CONTRAT, DE DÉLIT OU AUTRE, DÉCOULANT DE, OU EN RAPPORT AVEC LE LOGICIEL OU L'UTILISATION OU D'AUTRES TRAITEMENTS DANS LE LOGICIEL.

Informations sur l'auteur

La page d'accueil pour ce rôle est https://github.com/felixfontein/acme-certificate/. Veuillez utiliser le système de suivi des problèmes pour signaler des problèmes.

À propos du projet

Wrapper of Ansible's included acme_certificate module, whose aim is that almost no code is executed on the webserver. Requires the Python cryptography library as well as the OpenSSL binary installed locally and available on executable path.

Installer
ansible-galaxy install felixfontein.acme_certificate
Licence
mit
Téléchargements
382
Propriétaire