Puppet-moduulien ja manifestien uudelleenkäytettävyyden vuoksi on suositeltavaa pitää data niistä erillään. Tämä tapahtuu käyttämällä hieraa. Moduulit voivat esimerkiksi tuottaa erilaisia asetuksia käyttämällä hieran perusteella organisaatiohin tai sijainteihin määriteltyä dataa

Hieraan tallennetaan tyypillisesti myös sellaista yksityistä dataa mikä pitää olla suojattua, ja minkä ei haluta joutuvan ulkopuolisten saataville. Tyypillisesti data tallennetaan muun koodin ohella versionhallintajärjestelmään, joka voi olla organisaation rajojen ulkopuolella. Tällöin on käytettävä hieran encryptionta.

Aiemmin yleisesti käytetty hieran salauksen menetelmä oli hiera-gpg. Hiera-gpg:n avulla salattiin koko tiedosto. Hiera-eyaml parantaa tilannetta sallimalla hieratiedoston sisällä haluttujen datalohkojen salaamisen, mikä parantaa käytettävyyttä.

Hiera-yaml pitää ensin asentaa:

$ sudo gem install hiera-eyaml
Puppet-palvelimella asennus tapahtuu seuraavasti:
$ sudo puppetserver gem install hiera-eyaml

Hiera-eyaml käyttää asymmetristä enkryptointia, oletuksena PKCS#7:ää. Sen käyttöön tarvitaan siis avainpari. Julkisella avaimella voidaan purkaa salattujen datalohkojen encryption ja yksityisellä avaimella salata. Avainpari luodaan komennolla:

$ eyaml createkeys

Avainpari luodaan sen hetkisen hakemiston keys-alihakemistoon. Luodut avaimet tulee suojata ja säilyttää huolellisesti. Salauksen tuottamiseen riittää että julkinen avain on käytettävissä. Salatun lohkon muokkaamiseen tarvitaan sekä julkinen että yksityinen avain. Henkilö, joka lisää tai muokkaa hiera-tiedostojen sisältöä tarvitsee siis molemmat avaimet. Avaimet tulee suojata vastaavasti kuten palvelimellakin, eli omistajaksi määritetään käyttäjä ja tiedostoille vain lukuoikeus käyttäjälle itselleen. Sopiva sijainti on esimerkiksi kotihakemiston keys-alihakemisto.

Puppetserver tarvitsee salauksen purkamiseen ja arvojen lukemiseen sekä julkisen että yksityisen avaimen. Puppetserverillä sopiva sijainti avaimille on esim.:

/etc/puppetlabs/puppet/eyaml
Luodaan siis tämä hakemisto ja säädetään sen oikeudet minimiin.
$ mkdir /etc/puppetlabs/puppet/eyaml
 $ chown -R puppet:puppet /etc/puppetlabs/puppet/eyaml
 $ chmod -R 0500 /etc/puppetlabs/puppet/eyaml
 $ chmod 0400 /etc/puppetlabs/puppet/eyaml/*.pem
Tarkistetaan että tiedostojen omistajat ja oikeudet ovat halutunlaiset:
$ ls -lha /etc/puppetlabs/puppet/eyaml

Omistajana tulee siis olla puppet, ryhmäomistajana puppet, ja lukuoikeus vain puppet-tunnukselle.

Jos käyttäjä haluaa muokata omalle koneellaan olemassaolevan hiera-tiedoston arvoja, tyypillisesti hallintarepon kopiossa, tarvitaan molemmat avaimet. Avaimet tulee siirtää omalle koneelle asianmukaisella turvallisella protokollalla, esim. scp:llä. Muokkaamisen helpottamiseksi on hyödyllistä luoda kotihakemistoon uusi hakemisto .eyaml, ja sinne konfigurointitiedosto config.yaml, jossa määritetään mistä avaimet löytyvät:

---
 pkscs7_public_key: '/Users/tunnus/keys/public_key.pkcs7.pem'
 pkcs7_private_key: '/Users/tunnus/keys/private_key.pkcs7.pem'

Kun avaimet ovat palvelimella paikoillaan, voidaan määrittää hieran konfigurointitiedosto käyttämään näitä avaimia. Uudessa hiera-versiossa 5 on itsenäiset hierarkian määritykset jokaiselle environmentille ja moduulille. Hiera.yaml voidaan siis sijoittaa hallintarepoon ja sen haaroihin, ja viitata näissä edellä luotuihin avaimiin palvelimella. Oletetaan että yksityiselle avaimelle on annettu nimi private_key.pkcs7.pem ja julkiselle avaimelle public_key.pkcs7.pem.

---
 version: 5
 defaults:
 datadir: data
 data_hash: yaml_data
 
 hierarchy:
 - name: "Secret data"
 lookup_key: eyaml_lookup_key
 paths:
 - "secrets.eyaml"
 options:
 pkcs7_private_key: /etc/puppetlabs/puppet/eyaml/private_key.pkcs7.pem
 pkcs7_public_key: /etc/puppetlabs/puppet/eyaml/public_key.pkcs7.pem
 
 - name: "Per-node data"
 path: ”nodes/%{trusted.certname}.yaml"
 - name: "Common data"
 path: "common.yaml"
*nix-tyyppisissä käyttöjärjestelmissä voidaan luoda ympäristömuuttuja EDITOR joka määrittää käyttäjän haluaman oletusmuokkaimen. Ympäristömuuttuja voidaan laittaa esim. bash-käyttäjän kuoren alustustiedostoon ~/.bashrc. Tai se voidaan antaa suoraan komentorivillä:
$ export EDITOR=emacs
Kun ympäristömuuttuja on olemassa, voidaan hierassa määritettyä eyaml-muotoisen tiedoston datalohkoja muokata seuraavasti
$ eyaml edit secrets.eyaml

Eyaml avaa tällöin tiedoston ohjeen kera. Salattavaksi haluttu arvo laitetaan tällöin hakasulkeiden väliin muotoon DEC::PKCS7[]!

#| This is eyaml edit mode. This text (lines starting with #| at the top of the
 #| file) will be removed when you save and exit.
 #| - To edit encrypted values, change the content of the DEC(<num>)::PKCS7[]!
 #| block.
 #| WARNING: DO NOT change the number in the parentheses.
 #| - To add a new encrypted value copy and paste a new block from the
 #| appropriate example below. Note that:
 #| * the text to encrypt goes in the square brackets
 #| * ensure you include the exclamation mark when you copy and paste
 #| * you must not include a number when adding a new block
 #| e.g. DEC::PKCS7[]!
 ---
 # This value will not be encrypted
 plaintextvalue: plaintext
 # This value will be encrypted
 encryptedvalue: DEC::PKCS7[encrypted]!

Jos nyt katsotaan tiedostoa, voidaan todentaa että edellä määritetty arvo on salattu:

$ cat secrets.eyaml
 ---
 # This value will not be encrypted
 plaintextvalue: plaintext
 # This value will be encrypted
 encryptedvalue: ENC[PKCS7,MIIBeQYJKoZIhvcNAQcDoIIBajCCAWYCAQAxggEhMIIBHQIBADAFMAACAQEwDQYJKoZIhvcNAQEBBQAEggEAK/YGRbR2qbgpxHxrCic6ywXG6x0w0hZksNQqJPBYTq2FDyDO7H9L0XlVmnSP+wpjEleDGBJqUEyxgucYICvub5QaHQukBJ7/5ZeQ3grGIBOQkvEZVONWjNtdA+MkiIrc/erasgWYaU8lVJZ73RC6VzJQHYdphCsxue10kTAQw1uBKZOCbc9qHlhIwJuNERfUZBsfMpWgmnExph3kBsVlQ4FPTurkX2Kp0wEQlDVKm5llv4juq3dQLhDS4NkxmdopX/8jWP8+TMQB7vfW5kgS2U08vlm9QKgukO6GMeDrn/1Y66KnbokfGh4eJF7L94A1EYpKQx5eja+ITkvGarvCSTA8BgkqhkiG9w0BBwEwHQYJYIZIAWUDBAEqBBBn5gfCNVVsnRmQgIhE23pZgBAHsuh7FqP+XQMbJCQlREMN]

Linkkejä:

Artikkelisarjan muut osat:

Mikäli muutosten tekeminen Puppet-koodiin ja Hieraan suoraan puppetmasterilla tuntuu liian kevyeltä ja helpolta, voi Puppet-työnkulusta tehdä asteittain vaikeammaksi oman sietokyvyn mukaan lisäämällä palettiin lisää komponentteja. Esimerkiksi ns. control repon ja r10k:n käyttö Puppetin environmentien ylläpitoon lisää heti useita vaiheita aiemmin yksinkertaiseen työnkulkuun. Toki tällä saavutetaan myös ihan oikeita etuja, joista lisää tuonnempana.

Control repo - tästä lähtien osin suomennettuna "hallintarepo" - on käytännössä Git repository, jonka jokaisesta haarasta (branch) luodaan (tai ainakin voidaan luoda) dynaamisesti Puppet masterille vastaava Puppet-environment. Hallintarepon oletushaaran nimi, "production", on tästä syystä sama, kuin Puppet agenttien oletuksena käyttämä environment. Hallintarepon haaroissa on pitkälti sama sisältö kuin tavanomaisessa /etc/puppetlabs/code/environments/production -kansiossakin olisi:

$ ls control-repo
 data
 environment.conf
 hiera.yaml
 Puppetfile
 README.md
 site
 site.pp

Puppetfileä käsiteltiin jo aiemmassa artikkelista, jossa luotiin Puppet-koodiin pohjautuvia Kafo-installereja. Tiivistetysti Puppetfile sisältää viittaukset niihin Puppet-moduuleihin, jotka environmentin moduulikansiossa halutaan olevan:

# Forgen osoite
 forge "https://forgeapi.puppetlabs.com"
 
 # Moduuli Puppet Forgesta
 mod 'puppetlabs/stdlib'
 
 # Moduuli Gitistä
 mod 'puppet-mymodule',
 :git => 'git@gitlab.com:myorg/puppet-mymodule.git'

Tiedosto site.pp on näinä aikoina usein äärimmäisen pelkistetty, koska sitä tulee usein käytettyä lähinnä luokkien lataamiseen Hieran "classes"-listasta:

# Oletusarvo [] estää Puppet-ajojen epäonnistumisen siinä
 # tapauksessa, että jollakin koneella ei ole classes-listassa yhtään
 # luokkaa.
 lookup('classes', {merge => unique, default_value => []}).include

Tiedosto environment.conf on sekin varsin pelkistetty:

# Environmentin manifesti (ks. yllä)
 manifest = site.pp
 
 # Puppet-moduulien latauspolku. Alla käytetään globaaleja,
 # environmentien ulkopuolisia moduuleja kansiosta
 # /etc/puppetlabs/code/modules, sitten etsitään environmentin
 # moduulikansiosta, sitten environmentin site-kansiosta.
 # Site-kansion moduulien tiedostojen oletetaan olevan suoraan
 # hallintarepossa, ts. niihin ei viitata Puppetfilessä.
 modulepath = $basemodulepath:modules:site
 
 # Varmistetaan, että noodit käyttävät aina tuoreinta koodia. Suurella
 # noodimäärällä tämän parametrin arvoa voi joutua miettimään
 # uudelleen. 
 environment_timeout = 0

Tiedosto hiera.yaml on environment-kohtainen Hieran-asetustiedosto. Aiemmista versioista poiketen versio 5 hiera.yaml:ista sallii kolmitasoisen hierarkian, johon kuuluu globaali taso, environment-kohtainen taso ja moduulikohtainen taso. Viimeksi mainittu vaikuttaa suunnitellun vaihtoehdoksi hieman ikääntyneelle params.pp -patternille. Näillä seikoilla ei ole hallintarepon kannalta muuta merkitystä kuin se, että hallintarepon jokaisessa haarassa on hiera.yaml-tiedosto - esimerkiksi tällainen:

---
 version: 5
 defaults:
 datadir: data
 data_hash: yaml_data
 
 hierarchy:
 - name: "Per-node data"
 path: "nodes/%{trusted.certname}.yaml"
 - name: "Common data"
 path: "common.yaml"

Kansio site sisältää hallintarepossa suoraan ylläpidettävät Puppet-moduulit, kuten yllä site.pp:n kommenteissa mainittiinkin. Näin säästytään Puppetfilen ja erillisten moduulirepojen ylläpidolta.

Kansio data sisältää Hieran hierarkian, eli yllä olevaa hiera.yml-tiedostoa käytettäessä tiedoston common.yaml sekä kansion nodes, jossa on noodeille niiden omat yaml-tiedostot.

Artikkelisarjan muut osat:

Toisinaan Puppet-koodissa on tarve tehdä haku Hierasta, mutta se ei toimi odotetulla tavalla. Näissä tapauksissa auttaa "puppet lookup"-komento:

$ puppet lookup --node www.domain.com --explain bacula::filedaemon::backup_files
 Data Binding "hiera"
 Found key: "bacula::filedaemon::backup_files" value: [
 "/etc",
 "/var/lib/puppet/ssl",
 "/var/backups/local"
 ]

Erikoista kyllä, tämä komento löytää ainoastaan ne Hieran hierarkian tasot, jotka perustuvat faktoihin:

---
 :backends:
 - yaml
 :hierarchy:
 - "nodes/%{::trusted.certname}"
 - "roles/%{::role}"
 - "lsbdistcodename/%{::lsbdistcodename}"
 - "osfamily/%{::osfamily}"
 - "kernel/%{::kernel}"
 - common
 
 :yaml:
 :datadir:

Yllä muuttuja role ei siis ole fakta, vaan se on oikeastaan parametri tai käytänne, joka määritetään noodin yaml-tiedostossa:

role: webserver

Nämä yaml-tiedostoissa määritetyt roolit muunnetaan globaaliksi muuttujiksi tiedostossa /etc/puppetlabs/code/environments/production/manifests/site.pp:

# Save server role defined in the node's yaml into a top-scope
 # variable. These top-scope variables are then used in the Hiera
 # hierarchy to configure a node according to it's role.
 $role = hiera('role', undef)

Kun edellä mainitulla "puppet lookup"-komennolla yritetään löytää arvo parametrille, joka on määritelty ainoastaan valitun noodin roolissa, ei sitä löydy. Tämä ongelma voidaan kuitenkin kiertää kankeahkosti luomalla faktatiedosto, esim. facts.yaml ja määrittämällä noodin rooli siinä:

role: 'webserver'

Tämän jälkeen tehdään puppet lookup --facts -parametrin kera:

$ puppet lookup --node www.domain.com --explain bacula::filedaemon::backup_files --facts facts.yaml

Tämä komento etsii myös roolin mukaisesta yaml-tiedostosta. Tämä on erittäin kätevää etenkin, jos halutaan nähdä kaikki noodille määritetyt luokat ja käytössä on edellä mainittu roolien toteutus:

$ puppet lookup --node www.domain.com --explain classes --facts facts.yaml --merge unique

Lisätietoja "puppet lookup"-komennon käytöstä löytyy täältä.

Samuli Seppänen

Jotkin Puppet ENC:t (External Node Classifier), hyvänä esimerkkinä Foreman, eivät tue määriteltyjen resurssien (Defined Resource Types) käyttöä suoraan, vaan kaikki konfiguraatiot pitää sisällyttää Puppet-luokkiin.

Myös Hieran kanssa määritellyt resurssit ovat hieman ongelmallisia, koska ne pitää erikseen luoda create_resources funktiolla. Eräs ratkaisu on määrittää kaikki create_resources -funktiot site.pp-tiedostossa (sovellettu täältä):

create_resources('mysqldump::backup',hiera('mysqldump_backups', {}))

Tämän lähestymistavan ongelma on se, että uudet määritellyt resurssit pitää muistaa lisätä site.pp-tiedostoon.

Yksinkertaisempi ja myös Foremanin kanssa toimiva ratkaisu on luoda määritellyt resurssit suoraan Puppet-moduulin pääluokasta (sovellettu täältä):

class mysqldump
 (
 $backups = {}
 )
 {
 create_resources('mysqldump::backup', $backups)
 }

Yllä mysqldump-luokalla on hash-tyyppinen parameteri $backups, jossa määritetyt mysqldump::backup -resurssit luodaan create_resources -funktiolla. Aaltosulkeet parametrin oletusarvona mahdollistavat parametrin $backups määrittelemättä jättämisen ja kertovat Puppetille, että kyseessä on nimenomaan hash-tyyppinen parametri. Noodin yaml-tiedostossa $backups -parametri määriteltäisiin tähän tapaan:

---
 classes:
 - mysqldump
 
 mysqldump::backups:
 eka:
 databases:
 - 'eka'
 toka:
 databases:
 - 'toka'

Tämä ratkaisu toimii tietenkin toimii vain, jos noodille on lisätty hash-parametrin sisältävä luokka (yllä mysqldump). Luokkien lisääminen Hierasta onnistuu vain, jos site.pp -tiedostossa on seuraava rivi:

hiera_include('classes')
menucross-circle