Comment ajouter automatiquement de nouvelles gouttelettes à votre système de gestion de la configuration

introduction

À l'aide du service de métadonnées DigitalOcean, les administrateurs peuvent fournir des instructions permettant aux nouveaux serveurs de se configurer automatiquement. Bien que cela soit utile, de nombreuses organisations aiment gérer toute la configuration de leur infrastructure dans un outil de gestion de la configuration tel que Chef ou Puppet.

Dans ce guide, nous montrerons comment amorcer un serveur DigitalOcean à l'aide du service de métadonnées et de CloudInit pour se connecter à un déploiement de gestion de configuration existant. La configuration réelle du serveur peut ensuite être gérée par le service de gestion de configuration. Nous montrerons comment amorcer les nœuds Chef et Puppet.

Conditions préalables

Pour compléter ce guide, vous devez connaître le service de métadonnées de DigitalOcean. Vous pouvez en savoir plus sur la manière de saisir et de récupérer des informations à partir du service de métadonnées dansthis guide.

Ce guide tirera parti d'un type de script appelécloud-config qui est utilisé au premier démarrage par le service CloudInit sur votre Droplet afin d'effectuer la configuration de première exécution. Vous devez vous familiariser avec les scriptscloud-config, leur syntaxe et leur comportement afin de mieux comprendre comment modifier les scripts présentés dans ce guide. Vous pouvez trouver une introduction aux scripts de configuration cloudhere. Pour un exemple plus pratique (avec une discussion sur les limites du format), vous pouvez lire notre guide sur l'exécution de certaines tâches de base à l'aide de cloud-confighere.

Utilisation de scripts Cloud-Config pour amorcer un nœud Chef

En utilisant le service de métadonnées DigitalOcean, vous pouvez facilement connecter vos nouveaux serveurs à une infrastructure existante contrôlée par Chef avec les scriptscloud-config.

Pour ajouter votre nouveau serveur à ce système, vous devez déjà avoir configuré un serveur Chef que votre nouveau serveur peut contacter pour recevoir des instructions de configuration. Si vous avez besoin d'aide pour déployer un serveur Chef et un poste de travail de gestion, vous pouvez suivrethis guide pour commencer.

Plan général

Lorsqu'un nouveau serveur est mis en ligne, il doit être placé sous le contrôle du serveur Chef. En règle générale, cela peut être accompli en se connectant au nouveau serveur avec la commande de gestionknife et en utilisant la sous-commandebootstrap. Cela permettrait de se connecter au nouveau serveur, d'installer le client Chef et les informations d'identification de validation permettant au nouveau nœud de se connecter au serveur Chef. Ensuite, le client Chef se connecte au serveur, se valide, reçoit les nouvelles informations d'identification du client, extrait sa configuration du serveur et effectue les actions nécessaires pour se mettre à l'état souhaité.

Dans ce guide, nous utiliserons un scriptcloud-config pour remplacer l'étape de démarrage manuel, permettant au nouveau nœud de se connecter automatiquement au serveur Chef, de se valider, de recevoir les informations d'identification du client et d'exécuter une première exécution du client Chef. Le serveur le fera automatiquement au premier démarrage sans aucune assistance manuelle de l'administrateur.

Collecte des données nécessaires à partir du fichier de configuration de couteau

Pour que notre scriptcloud-config démarre correctement, il aura besoin d'accéder aux informations d'identification généralement disponibles pour la commandeknife. Plus précisément, nous avons besoin des informations suivantes:

  • Le nom de validation du chef

  • La clé de validation

  • L'URL où le serveur Chef peut être atteint

Toutes ces informations sont disponibles, au format correct, dans le fichier de configuration deknife sur le poste de travail utilisé pour gérer l'infrastructure Chef. À l'intérieur du référentiel Chef, il doit y avoir un répertoire caché appelé.chef qui contient ce fichier.

En supposant que votre dépôt Chef se trouve dans votre répertoire personnel sur le poste de travail et s'appellechef-repo, vous pouvez afficher le contenu du fichier en tapant:

cat ~/chef-repo/.chef/knife.rb

Les informations dont vous avez besoin sont mises en évidence ci-dessous:

current_dir = File.dirname(__FILE__)
log_level                :info
log_location             STDOUT
node_name                "jellingwood"
client_key               "#{current_dir}/jellingwood.pem"
validation_client_name   "digitalocean-validator"
validation_key           "#{current_dir}/digitalocean-validator.pem"
chef_server_url          "https://your_server.com/organizations/digitalocean"
syntax_check_cache_path  "#{ENV['HOME']}/.chef/syntaxcache"
cookbook_path            ["#{current_dir}/../cookbooks"]

Le nom de validation et l'URL du serveur Chef peuvent être extraits directement tels quels du fichier. Copiez ces valeurs afin de pouvoir les utiliser dans le fichiercloud-config.

Levalidation_key pointe vers l'emplacement où la clé réelle est conservée. Dans l'exemple ci-dessus, cela indique qu'il se trouve dans le même répertoire que le fichierknife.rb et s'appelledigitalocean-validator.pem. Ce sera probablement différent pour votre configuration.

Nous avons besoin du contenu de ce fichier, alors utilisez à nouveau la commandecat. Modifiez la commande pour qu'elle pointe vers l'emplacement indiqué pour votre clé de validation:

cat ~/chef-repo/.chef/digitalocean-validator.pem

Vous verrez une clé privée RSA:

-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEA3O60HT5pwEo6xUwcZ8WtExBUhoL3bTjlsvHVXg1JVmBUES+f
V9jLu2N00uSZEDZneCIQyHLBXnqD/UNvWEPNvPzt1ecXzmw2BytB7lPDW4/F/8tJ
vAVrKqC7B04VFGmcFY2zC8gf8BWmX8CNRDQooM7UO5OWe/H6GDGPPRIITerO3GrU

. . .

sWyRAoGBAKNc/ZUM8ljRV0UJxQ9nbdozXRZjtUaNgXMNiw+oP2HYYdHrlkKnGHYJ
Js63rvjpq8pocjE8YI+2H0v4/4uWqW8GEBfrWbLMzGsYPnRyiHR5+hgjCUU50RB3
eFoNbURwLYcq2Z/IAQZpDpJWpofz3OVMpMXtei1cIflrAAd2wtWO
-----END RSA PRIVATE KEY-----

Copiez l'intégralité de la clé de validation afin de pouvoir l'utiliser momentanément dans le scriptcloud-config.

Installation de base du client Cloud-Config Chef

Une fois que vous avez les données ci-dessus, vous pouvez créer le script. La configuration de Chef peut être effectuée via un modulecloud-config dédié appeléchef. Lescloud-config doivent contenir du YAML valide et doivent avoir#cloud-config comme première ligne du script.

En commençant, votre script ressemblera à ceci:

#cloud-config
chef:

La documentation decloud-config prétend pouvoir installer le client Chef soit à partir d'un gem Ruby, d'un package, soit en utilisant la méthode d'installation traditionnelle «omnibus». Cependant, dans la pratique, les méthodes de type gem et package ont tendance à échouer, nous allons donc utiliser la méthode «omnibus». Bien que cela ne soit généralement pas nécessaire, nous allons également répertorier explicitement l'emplacement du programme d'installation omnibus.

Nous mettronsforce_install à «faux». Ainsi, si pour une raison quelconque le client Chef est déjà installé sur l'image (par exemple, si vous déployez à partir d'un instantané), le client ne sera pas réinstallé. Jusqu'ici, notre script ressemble à ceci:

#cloud-config
chef:
  install_type: "omnibus"
  omnibus_url: "https://www.opscode.com/chef/install.sh"
  force_install: false

Ensuite, nous avons la possibilité de sélectionner un nom pour le nouveau serveur dans l'infrastructure Chef en utilisant la directivenode_name. Si vous ne le définissez pas, Chef utilisera le nom d’hôte du serveur, ce qui est donc facultatif. Toutefois, cela doit être unique dans votre environnement Chef.

Ensuite, nous pouvons ajouter toutes les informations de connexion que nous avons extraites de notre poste de travail Chef. Nous allons définir l'optionserver_url à l'emplacement du serveur Chef exactement comme il était dans le fichierknife.rb. Il en va de même pour l'optionvalidation_name.

Pour la clé de validation, nous utiliserons le symbole du tube YAML (|) pour saisir l'intégralité de la clé de validation que nous avons trouvée sur le poste de travail:

#cloud-config
chef:
  install_type: "omnibus"
  omnibus_url: "https://www.opscode.com/chef/install.sh"
  force_install: false
  node_name: "new_node"
  server_url: "https://your_server.com/organizations/digitalocean"
  validation_name: "digitalocean-validator"
  validation_key: |
    -----BEGIN RSA PRIVATE KEY-----
    MIIEowIBAAKCAQEA3O60HT5pwEo6xUwcZ8WtExBUhoL3bTjlsvHVXg1JVmBUES+f
    V9jLu2N00uSZEDZneCIQyHLBXnqD/UNvWEPNvPzt1ecXzmw2BytB7lPDW4/F/8tJ
    vAVrKqC7B04VFGmcFY2zC8gf8BWmX8CNRDQooM7UO5OWe/H6GDGPPRIITerO3GrU

    . . .

    sWyRAoGBAKNc/ZUM8ljRV0UJxQ9nbdozXRZjtUaNgXMNiw+oP2HYYdHrlkKnGHYJ
    Js63rvjpq8pocjE8YI+2H0v4/4uWqW8GEBfrWbLMzGsYPnRyiHR5+hgjCUU50RB3
    eFoNbURwLYcq2Z/IAQZpDpJWpofz3OVMpMXtei1cIflrAAd2wtWO
    -----END RSA PRIVATE KEY-----

À ce stade, votre script dispose de toutes les authentifications nécessaires pour se connecter à votre serveur Chef et créer les informations d'identification du client.

Configuration de l'environnement Chef, de la liste d'exécution et des attributs

Bien que les détails ci-dessus fournissent suffisamment d’informations au client pour se connecter au serveur Chef, nous n’avons fourni au noeud aucune information sur la manière de se configurer lui-même. Nous pouvons également fournir ces informations dans le scriptcloud-config.

Pour spécifier l'environnement dans lequel le nouveau nœud doit être placé, utilisez l'optionenvironment. Si ce n'est pas défini, l'environnement_default sera défini, qui est la valeur par défaut générique pour les nœuds Chef qui n'ont pas reçu un autre environnement.

chef:
  environment: "staging"

Nosrun_list peuvent être spécifiés comme une simple liste d'éléments que le client doit appliquer dans l'ordre. Ceux-ci peuvent être des recettes ou des rôles.

chef:
  run_list:
    - "recipe[lamp]"
    - "role[backend-web]"

Vous pouvez spécifier les attributs initiaux du nouveau nœud en utilisant une hiérarchieinitial_attributes. Cela définira les attributs initiaux qui affecteront la façon dont lerun_list est appliqué:

chef:
  initial_attributes:
    lamp:
      apache:
        port: 80
      mysql:
        username: webclient
        pass: $#fjeaiop34S

Lorsqu'il est connecté au scriptcloud-config précédent, cela peut ressembler à ceci:

#cloud-config
chef:
  install_type: "omnibus"
  omnibus_url: "https://www.opscode.com/chef/install.sh"
  force_install: false
  node_name: "new_node"
  server_url: "https://your_server.com/organizations/digitalocean"
  validation_name: "digitalocean-validator"
  validation_key: |
    -----BEGIN RSA PRIVATE KEY-----
    MIIEowIBAAKCAQEA3O60HT5pwEo6xUwcZ8WtExBUhoL3bTjlsvHVXg1JVmBUES+f
    V9jLu2N00uSZEDZneCIQyHLBXnqD/UNvWEPNvPzt1ecXzmw2BytB7lPDW4/F/8tJ
    vAVrKqC7B04VFGmcFY2zC8gf8BWmX8CNRDQooM7UO5OWe/H6GDGPPRIITerO3GrU

    . . .

    sWyRAoGBAKNc/ZUM8ljRV0UJxQ9nbdozXRZjtUaNgXMNiw+oP2HYYdHrlkKnGHYJ
    Js63rvjpq8pocjE8YI+2H0v4/4uWqW8GEBfrWbLMzGsYPnRyiHR5+hgjCUU50RB3
    eFoNbURwLYcq2Z/IAQZpDpJWpofz3OVMpMXtei1cIflrAAd2wtWO
    -----END RSA PRIVATE KEY-----
  environment: "staging"
  run_list:
    - "recipe[lamp]"
    - "role[backend-web]"
  initial_attributes:
    lamp:
      apache:
        port: 80
      mysql:
        username: webclient
        pass: $#fjeaiop34S

Redirection de la sortie et configuration de l'exécution du client Chef

Le script ci-dessus contient toutes les informations nécessaires dans la sectionchef:. Cependant, il y a quelques autres choses que nous devrions faire en utilisant d'autres modulescloud-config.

Tout d’abord, nous devons spécifier que nous souhaitons rediriger la sortie de chaque commande et sous-commande dans le journal de sortie du processus CloudInit. Il se trouve par défaut à/var/log/cloud-init-output.log. Nous pouvons le faire avec le moduleoutput comme ceci:

output: {all: '| tee -a /var/log/cloud-init-output.log'}

Nous souhaitons également configurer le client Chef pour qu'il s'exécute réellement une fois qu'il a été installé et configuré. Au moment d'écrire ces lignes, la méthode d'installation omnibus ne le fait pas automatiquement.

Nous pouvons forcer ce comportement en attendant que l'exécutablechef-client soit installé sur le serveur avant d'appeler la commande. En utilisant une simple bouclebash, nous vérifierons l'existence de ce fichier toutes les cinq secondes. Quand il est trouvé, nous exécuteronschef-client afin d'implémenter la configuration initiale que nous avons spécifiée.

Le moduleruncmd peut être utilisé pour émettre des commandes arbitraires. C'est l'emplacement idéal pour notre bouclebash:

runcmd:
  - while [ ! -e /usr/bin/chef-client ]; do sleep 5; done; chef-client

De plus, vous pouvez éventuellement ajouter une autre directivecloud-config pour acheminer par null le point de terminaison des métadonnées après le premier démarrage. Ceci est utile car nous mettons une clé privée dans nos données utilisateur. Sans le routage nul du point de terminaison de métadonnées, celui-ci serait accessible à tout utilisateur du serveur. Implémentez ceci en ajoutant:

disable_ec2_metadata: true

En les combinant avec le script que nous avons construit jusqu'à présent, nous pouvons obtenir le script complet nécessaire pour amorcer notre nœud et le connecter à notre infrastructure Chef:

#cloud-config
chef:
  install_type: "omnibus"
  omnibus_url: "https://www.opscode.com/chef/install.sh"
  force_install: false
  node_name: "new_node"
  server_url: "https://your_server.com/organizations/digitalocean"
  validation_name: "digitalocean-validator"
  validation_key: |
    -----BEGIN RSA PRIVATE KEY-----
    MIIEowIBAAKCAQEA3O60HT5pwEo6xUwcZ8WtExBUhoL3bTjlsvHVXg1JVmBUES+f
    V9jLu2N00uSZEDZneCIQyHLBXnqD/UNvWEPNvPzt1ecXzmw2BytB7lPDW4/F/8tJ
    vAVrKqC7B04VFGmcFY2zC8gf8BWmX8CNRDQooM7UO5OWe/H6GDGPPRIITerO3GrU

    . . .

    sWyRAoGBAKNc/ZUM8ljRV0UJxQ9nbdozXRZjtUaNgXMNiw+oP2HYYdHrlkKnGHYJ
    Js63rvjpq8pocjE8YI+2H0v4/4uWqW8GEBfrWbLMzGsYPnRyiHR5+hgjCUU50RB3
    eFoNbURwLYcq2Z/IAQZpDpJWpofz3OVMpMXtei1cIflrAAd2wtWO
    -----END RSA PRIVATE KEY-----
  environment: "staging"
  run_list:
    - "recipe[lamp]"
    - "role[backend-web]"
  initial_attributes:
    lamp:
      apache:
        port: 80
      mysql:
        username: webclient
        pass: $#fjeaiop34S
output: {all: '| tee -a /var/log/cloud-init-output.log'}
runcmd:
  - while [ ! -e /usr/bin/chef-client ]; do sleep 5; done; chef-client
disable_ec2_metadata: true

Le script ci-dessus peut être modifié si nécessaire pour chaque nouveau serveur de votre infrastructure.

Utilisation de scripts Cloud-Config pour amorcer un nœud de marionnette

Si votre infrastructure repose sur Puppet pour la gestion de la configuration, vous pouvez utiliser le modulepuppet à la place. À l'instar de l'exemple de Chef, l'amorçage d'un nœud Puppet implique l'utilisation decloud-config pour attacher le nouveau serveur à l'infrastructure de gestion de configuration existante.

Avant de commencer, vous devez avoir un serveur maître Puppet configuré pour votre infrastructure. Si vous avez besoin d'aide pour installer et exécuter un serveur Puppet, consultezthis guide.

Plan général

Lorsqu'un nouveau serveur Puppet est mis en ligne, un agent Puppet est installé afin qu'il puisse communiquer avec le serveur maître Puppet. Cet agent est responsable de la réception et de l'application des informations qui dictent l'état souhaité du noeud. Pour ce faire, l'agent se connecte au maître, télécharge des données sur lui-même, extrait le catalogue en cours décrivant son état souhaité et effectue les actions nécessaires pour atteindre cet état.

Avant que cela ne se produise cependant, lors de sa première exécution, l'agent doit s'inscrire auprès du serveur maître. Il crée une demande de signature de certificat et l'envoie au maître pour signature. En règle générale, l'agent se reconnecte périodiquement au maître jusqu'à la signature du certificat, mais vous pouvez configurer votre Marionnette pour qu'il signe automatiquement les demandes entrantes présentant certaines caractéristiques, si cela convient à votre environnement (nous en parlerons plus tard).

En utilisant notre scriptcloud-config, nous allons configurer notre nouveau serveur avec les informations dont il a besoin pour se connecter au maître pour la première fois. À ce stade, il peut récupérer les détails de la configuration du serveur maître Puppet sous la forme d'un catalogue.

Rassembler les données nécessaires du maître des marionnettes

La première chose que nous devons faire avant de construire notre fichiercloud-config est de rassembler les données de notre serveur maître Puppet dont nous aurons besoin pour nous connecter. Nous n'avons besoin que de quelques informations.

Tout d’abord, vous devez obtenir le nom de domaine complet (FQDN) du serveur maître de Puppet. Vous pouvez le faire en tapant:

hostname -f

Dans la plupart des cas, il devrait retourner quelque chose comme ceci:

puppet.example.com

Vous pouvez également vérifier votre fichier de configuration maître Puppet pour voir si l'optiondns_alt_names est définie:

cat /etc/puppet/puppet.conf
. . .

dns_alt_names = puppet,puppet.example.com

. . .

Si les certificats SSL de votre maître de marionnettes ont été générés après avoir défini ces options, elles peuvent également être utilisables.

L’autre élément à collecter est le certificat de l’autorité de certification du maître de marionnettes. Cela peut être trouvé dans/var/lib/puppet/ssl/certs/ca.pem ou/var/lib/puppet/ssl/ca/ca_crt.pem:

sudo cat /var/lib/puppet/ssl/certs/ca.pem

Les résultats ressembleront à ceci:

-----BEGIN CERTIFICATE-----
MIIFXjCCA0agAwIBAgIBATANBgkqhkiG9w0BAQsFADAcMRowGAYDVQQDDBFQdXBw
ZXQgQ0E6IHB1cHBldDAeFw8xNTAyMTkxOTA0MzVaFw0yMDAyMTkxOTA0MzVaMBwx
GjAYBgNVBAMMEVB1cHBldCBDQTogcHVwcGV0MIICIjANBgkqhkiG9w0BAQEFAAOC

. . .

arsjZT5/CtIhtP33Jl3mCp7U2F6bsk4/GDGRaAsFXjJHvBbL93NzgpkZ7elf0zUP
rOcSGrDrUuzuJk8lEAtrZr/IfAgfKKXPqbyYF95V1qN3OMY+aTcrK20XTydKVWSe
l5UfYGY3S9UJFrSn9aBsZzN+10HXPkaFKo7HxpztlYyJNI8UVSatcRF4aYYqt9KR
UClnR+2WxK5v7ix0CVd4/KpYH/6YivvyTwxrhjF2AksZKg==
-----END CERTIFICATE-----

Copiez le certificat dans son intégralité. Nous allons l'inclure dans notre fichiercloud-config afin que nos nouveaux serveurs puissent vérifier qu'ils se connectent au bon maître Puppet.

Une fois que vous avez ces informations, vous pouvez commencer à créer le fichiercloud-config afin que le nouveau serveur puisse se connecter à l'infrastructure Puppet existante.

Installation de base des nœuds de marionnettes Cloud-Config

La configuration decloud-config pour les nouveaux nœuds Puppet est assez simple. Toutes les configurations spécifiques à Puppet se trouvent dans la sectionpuppet: du fichier. Comme pour chaque fichiercloud-config, la toute première ligne doit contenir#cloud-config seule:

#cloud-config
puppet:

En dessous, il n'y a que deux sous-sections. Le premier est la toucheca_cert. Ceci utilisera le caractère de pipe pour démarrer un bloc de texte YAML afin que le certificat de l'autorité de certification puisse être donné dans son intégralité en tant que bloc en retrait:

#cloud-config
puppet:
  ca_cert: |
    -----BEGIN CERTIFICATE-----
    MIIFXjCCA0agAwIBAgIBATANBgkqhkiG9w0BAQsFADAcMRowGAYDVQQDDBFQdXBw
    ZXQgQ0E6IHB1cHBldDAeFw8xNTAyMTkxOTA0MzVaFw0yMDAyMTkxOTA0MzVaMBwx
    GjAYBgNVBAMMEVB1cHBldCBDQTogcHVwcGV0MIICIjANBgkqhkiG9w0BAQEFAAOC

    . . .

    arsjZT5/CtIhtP33Jl3mCp7U2F6bsk4/GDGRaAsFXjJHvBbL93NzgpkZ7elf0zUP
    rOcSGrDrUuzuJk8lEAtrZr/IfAgfKKXPqbyYF95V1qN3OMY+aTcrK20XTydKVWSe
    l5UfYGY3S9UJFrSn9aBsZzN+10HXPkaFKo7HxpztlYyJNI8UVSatcRF4aYYqt9KR
    UClnR+2WxK5v7ix0CVd4/KpYH/6YivvyTwxrhjF2AksZKg==
    -----END CERTIFICATE-----

Assurez-vous d'inclure le certificat complet avec les marques de début et de fin et de l'indenter de manière appropriée.

La deuxième section sous le parapluiepuppet: est la sectionconf:. Ceci est utilisé pour spécifier des paires clé-valeur qui seront ajoutées à un fichier génériquepuppet.conf. Les paires clé-valeur doivent être placées sous les en-têtes de section comme elles le seraient dans le fichierpuppet.conf.

Par exemple, à tout le moins, le nouveau serveur devra connaître l'adresse du serveur maître de Puppet. Dans le fichierpuppet.conf, ceci se trouve sous la section[agent], comme ceci:

. . .

[agent]
server = puppet.example.com

. . .

Pour le spécifier dans la syntaxecloud-config, vous ajouteriez ceci à ce que nous avons jusqu'à présent:

#cloud-config
puppet:
  ca_cert: |
    -----BEGIN CERTIFICATE-----
    MIIFXjCCA0agAwIBAgIBATANBgkqhkiG9w0BAQsFADAcMRowGAYDVQQDDBFQdXBw
    ZXQgQ0E6IHB1cHBldDAeFw8xNTAyMTkxOTA0MzVaFw0yMDAyMTkxOTA0MzVaMBwx
    GjAYBgNVBAMMEVB1cHBldCBDQTogcHVwcGV0MIICIjANBgkqhkiG9w0BAQEFAAOC

    . . .

    arsjZT5/CtIhtP33Jl3mCp7U2F6bsk4/GDGRaAsFXjJHvBbL93NzgpkZ7elf0zUP
    rOcSGrDrUuzuJk8lEAtrZr/IfAgfKKXPqbyYF95V1qN3OMY+aTcrK20XTydKVWSe
    l5UfYGY3S9UJFrSn9aBsZzN+10HXPkaFKo7HxpztlYyJNI8UVSatcRF4aYYqt9KR
    UClnR+2WxK5v7ix0CVd4/KpYH/6YivvyTwxrhjF2AksZKg==
    -----END CERTIFICATE-----
  conf:
    agent:
      server: "puppet.example.com"

Notez que la sectionconf: est en ligne avec la sectionca_cert et non un élément enfant. C'est le minimum nécessaire pour se connecter au maître de marionnettes. Tous les éléments de configuration supplémentaires trouvés danspuppet.conf peuvent être ajoutés de la même manière en créant d'abord un niveau pour le nom de la section, puis en définissant la paire clé-valeur.

Après cela, nous devrions rediriger toutes les sorties futures vers le fichiercloud-init-output.log et ajouter une ligneruncmd comparable à celle que nous avons ajoutée pour la configuration de Chef. Cela attendra que l'agent Puppet soit installé, puis l'activer et le redémarrer. Nous pouvons également effectuer un routage nul du point de terminaison des métadonnées après la première analyse, comme nous l'avons fait dans la section Chef. Ces lignes directivescloud-config doivent être placées en dehors de toute autre section du module:

. . .

  conf:
    agent:
      server: "puppet.example.com"
output: {all: '| tee -a /var/log/cloud-init-output.log'}
runcmd:
  - while [ ! -e /usr/bin/puppet ]; do sleep 5; done; puppet agent --enable; service puppet restart
disable_ec2_metadata: true

Avec ces informations, le nouveau serveur peut se connecter au serveur maître Puppet, puis générer une demande de signature de certificat client à transférer au maître. Par défaut, les certificats clients doivent être signés manuellement sur le maître de marionnettes. Une fois cette opération effectuée, lors du prochain intervalle de mise à jour de l'agent Puppet (toutes les 30 minutes par défaut), le nœud extraira sa configuration du maître Puppet. Nous montrerons un peu plus tard comment mettre en œuvre un mécanisme de signature automatique relativement sécurisé pour éviter ce délai.

Définir le nom de certification du nœud

L’une des valeurs qui peuvent être placées dans le fichierpuppet.conf du nouveau serveur est un cas unique. Dans le fichiercloud-config, l'optioncertname peut remplacer des valeurs de l'environnement si certaines variables sont données. Les variables suivantes sont reconnues:

  • %i: l'ID d'instance du serveur. Cela sera extrait dehttp://169.254.169.254/metadata/v1/id lors de la création du serveur. Il correspond à l'ID de gouttelette utilisé pour identifier de manière unique les droplets.

  • %f: le FQDN du serveur.

Dans cet esprit, un paramètrecertname commun ressemblerait à ceci:

#cloud-config
puppet:

. . .

  conf:
    agent:
      server: "puppet.example.com"
      certname: "%i.%f"

Cela produirait uncertname avec un modèle similaire à celui-ci:

   |-Droplet ID
   |
   |            |-Fully Qualified Domain Name
   |            |
|-----||-------------------|
123456.testnode.example.com

Avoir l'ID Droplet dans le cadre descertname peut être utile pour configurer la signature automatique sécurisée de Puppet comme nous le verrons dans la section suivante.

Implémenter la signature automatique du certificat de marionnette

Si vous souhaitez implémenter un système de signature automatique de certificats pour éviter l'intervention d'un administrateur, vous avez le choix entre plusieurs options. Vous devez d'abord configurer ceci sur votre serveur maître Puppet.

Dans le fichierpuppet.conf sur le serveur maître Puppet, vous pouvez définir l'optionautosign sous la section[master] du fichier. Cela peut prendre quelques valeurs différentes:

  • true: Cela indiquera au serveur maître Puppet de signer chaque demande de certificat qui arrive, sans effectuer aucune vérification. Ceci est extrêmement dangereux dans un environnement réel, car tout hôte peut faire signer un CSR et accéder à votre infrastructure.

  • <whitelist_filename>: la deuxième option consiste à spécifier un fichier qui fonctionnera comme une liste blanche d'hôtes ou des expressions régulières d'hôte. Le maître des marionnettes vérifiera les demandes de signature de certificat par rapport à cette liste pour voir si le certificat doit être signé. Ceci n’est à nouveau pas recommandé car les noms de certificats peuvent être usurpés facilement.

  • <policy_executable>: la troisième option consiste à spécifier un script ou un exécutable pouvant être exécuté pour déterminer si la demande de signature de certificat doit être signée. Puppet transmettra le certname sous forme d'argument et l'intégralité de la CSR via une entrée standard. Si un état de sortie de 0 est renvoyé, le certificat est signé. Si un autre statut est donné, le certificat seranot signé.

La signature automatique basée sur des stratégies est le moyen le plus sûr d'implémenter la signature automatique de clé car elle vous permet d'être arbitrairement complexe dans la distinction des demandes légitimes et non légitimes.

Pour illustrer la signature automatique basée sur des règles, vous pouvez ajouter la variablecertname à votrecloud-config qui inclut la variable d'ID d'instance%i. Nous utiliserons%i.%f pour qu'il inclue également le nom d'hôte sélectionné:

#cloud-config
puppet:
  conf:
    agent:
      server: "puppet.example.com"
      certname: "%i.%f"
  ca_cert: |

   . . .

Voscloud-config complets peuvent maintenant ressembler à ceci:

#cloud-config
puppet:
  conf:
    agent:
      server: "puppet.example.com"
      certname: "%i.%f"
  ca_cert: |
    -----BEGIN CERTIFICATE-----
    MIIFXjCCA0agAwIBAgIBATANBgkqhkiG9w0BAQsFADAcMRowGAYDVQQDDBFQdXBw
    ZXQgQ0E6IHB1cHBldDAeFw8xNTAyMTkxOTA0MzVaFw0yMDAyMTkxOTA0MzVaMBwx
    GjAYBgNVBAMMEVB1cHBldCBDQTogcHVwcGV0MIICIjANBgkqhkiG9w0BAQEFAAOC

    . . .

    arsjZT5/CtIhtP33Jl3mCp7U2F6bsk4/GDGRaAsFXjJHvBbL93NzgpkZ7elf0zUP
    rOcSGrDrUuzuJk8lEAtrZr/IfAgfKKXPqbyYF95V1qN3OMY+aTcrK20XTydKVWSe
    l5UfYGY3S9UJFrSn9aBsZzN+10HXPkaFKo7HxpztlYyJNI8UVSatcRF4aYYqt9KR
    UClnR+2WxK5v7ix0CVd4/KpYH/6YivvyTwxrhjF2AksZKg==
    -----END CERTIFICATE-----
output: {all: '| tee -a /var/log/cloud-init-output.log'}
runcmd:
  - while [ ! -e /usr/bin/puppet ]; do sleep 5; done; puppet agent --enable; service puppet restart
disable_ec2_metadata: true

Sur le serveur maître de Puppet, nous devrons configurer un script de validation. Comme Ruby est déjà installé pour Puppet, nous pouvons créer un script Ruby simple.

Comme nous utilisons le format%i.%f pour lescertname, nous pouvons vérifier si la première partie descertname (la partie avant le premier point) correspond à un identifiant de gouttelette valide pour notre compte . C’est une simple vérification qui, dans la pratique, ne fait pas beaucoup plus que le fichier de la liste blanche. Cependant, vous pouvez adapter cette idée pour qu'elle soit beaucoup plus complexe si vous le souhaitez.

Pour ce faire, nous aurons besoin d’un jeton d’accès personnel dans la section «Applications et API» du panneau de configuration de DigitalOcean. Vous devrez également installer l’une des bibliothèques DigitalOcean Ruby. Ci-dessous, nous allons vous montrer quelques scripts simplifiés qui utilisent les clients DigitalOcean RubyBarge etDropletKit.

Si vous souhaitez utiliser le client Barge, installez la gemme sur votre maître de marionnettes en tapant:

sudo gem install barge

Le script suivant peut être utilisé pour vérifier si la première partie descertname dans la demande de signature de certificat correspond à un ID de droplet valide:

#!/usr/bin/env ruby

require 'barge'

TOKEN = 'YOUR_DIGITALOCEAN_API_TOKEN'

droplet_ids = []
certname = ARGV[0]
id_string = certname.slice(0...(certname.index('.')))
id_to_check = id_string.to_i

client = Barge::Client.new(access_token: TOKEN)
droplets = client.droplet.all

droplets.droplets.each do |droplet|
        droplet_ids << droplet.id
end

Kernel.exit(droplet_ids.include?(id_to_check))

Si vous souhaitez plutôt utiliser DropletKit, le client officiel de DigitalOcean Ruby, vous pouvez installer la gem en tapant:

sudo gem install droplet_kit

Notez que la gemme DropletKit n’est valable que pour Ruby 2.0 et les versions ultérieures. Cela n’est donc peut-être pas possible avec la version de Ruby fournie avec Puppet.

Le script de DropletKit peut être adapté comme ceci:

#!/usr/bin/env ruby

require 'droplet_kit'

TOKEN = 'YOUR_DIGITALOCEAN_API_TOKEN'

droplet_ids = []
certname = ARGV[0]
id_string = certname.slice(0...(certname.index('.')))
id_to_check = id_string.to_i

client = DropletKit::Client.new(access_token: TOKEN)
droplets = client.droplets.all

droplets.each do |droplet|
        droplet_ids << droplet.id
end

Kernel.exit(droplet_ids.include?(id_to_check))

Vous pouvez placer le script qui correspond au gem que vous avez installé dans un fichier appelé/etc/puppet/validate.rb et le marquer comme exécutable en tapant:

sudo chmod +x /etc/puppet/validate.rb

Vous pouvez ensuite ajouter ce qui suit à votre fichierpuppet.conf (situé à/etc/puppet/puppet.conf si vous utilisez Open Source Puppet):

. . .

[master]
autosign = /etc/puppet/validate.rb

. . .

Redémarrez le service Apache pour implémenter la nouvelle stratégie de signature:

sudo service apache2 restart

Désormais, lorsque les demandes de signature de certificat sont reçues par votre maître Puppet, celui-ci vérifie si la première partie du nom du certificat correspond à un nom Droplet valide dans votre compte. Ceci est un exemple approximatif de la manière dont vous pouvez valider des demandes à l'aide d'un exécutable.

Conclusion

En exploitant les scriptscloud-config, vous pouvez facilement amorcer vos nouveaux serveurs et les transmettre à vos systèmes de gestion de configuration existants. Cela vous permet de contrôler immédiatement votre infrastructure via vos outils existants avant d'effectuer des modifications importantes en dehors de la portée de votre solution de gestion.