mariadbpuppethieraeyaml

Using MySQL Puppet module and Hiera eyaml for storing encrypted user passwords


I am running the Puppet Server (v8) on a host and configured the Puppet agent (v8) on another host, all running on Rocky 8. I have installed the MySQL module from Puppet Forge.

How do I define an encrypted user password without overwriting the hiera.yaml and common.yaml in the MySQL module directory?

My Puppet folder structure on the server is:

etc/
├─ puppetlabs/
│  ├─ code/
│  │  ├─ environments/
│  │  │  ├─ production/
│  │  │  │  ├─ data/
│  │  │  │  │  ├─ common.yaml
│  │  │  │  ├─ modules/
│  │  │  │  ├─ manifests/
│  │  │  │  │  ├─ site.pp
│  │  │  │  ├─ hiera.yaml
│  │  ├─ modules/
│  │  │  ├─ mysql/
│  │  │  │  ├─ data/
│  │  │  │  │  ├─ common.yaml
│  │  │  │  ├─ manifest/
│  │  │  │  │  ├─ server.pp
│  │  │  │  ├─ hiera.yaml
│  │  │  │  ├─ and more...

I'm looking to encrypt the root password for MySQL using eyaml installed on the Puppet Server. I have run the following to generate the keys and encrypt the password:

eyaml createkeys
eyaml encrypt -l 'my_mysql_password' -s 'mypassword' 

The above generated an encrypted key in the format ENC[PKCS7,...==].

My production environment hiera.yaml is: /etc/puppetlabs/code/environments/production/hiera.yaml

---
version: 5
defaults:
  datadir: data
  data_hash: yaml_data
hierarchy:
  - name: "Per-node data (yaml version)"
    path: "nodes/%{::trusted.certname}.yaml"
  - name: "Other YAML hierarchy levels"
    paths:
      - "common.yaml"
  - name: 'common'
    lookup_key: eyaml_lookup_key
    paths:
      - "common.yaml"
    options:
      pkcs7_private_key: /etc/puppetlabs/puppet/keys/private_key.pkcs7.pem
      pkcs7_public_key:  /etc/puppetlabs/puppet/keys/public_key.pkcs7.pem

My production environment common.yaml is: /etc/puppetlabs/code/environments/production/data/common.yaml

---
mysql::server::root_password: >
  ENC[PKCS7,...==]

My production manifest contains: /etc/puppetlabs/code/environments/production/manifests/site.pp

class { 'mysql::server':
        package_name            => 'mariadb-server',
        root_password           => lookup('mysql::server::root_password'),
        remove_default_accounts => true,
        restart                 => true,
        override_options => {
          mysqld => {
            'max_connections' => '500',
          },
        }
      }

Solution

  • My Puppet folder structure on the server is: [...]

    That's a little unusual. When I install modules with the puppet module command, they ordinarily go into the default environment's module space, but your puppetlabs-mysql went into the global module space. I think that should still be ok, though.

    How do I define an encrypted user password without overwriting the hiera.yaml and common.yaml in the MySQL module directory?

    You are right to avoid modifying the files inside the module itself. They belong to the module. Instead, customize properties of your modules by modifying a data file in your global or environment Hiera hierarchy. For example, /etc/puppetlabs/code/environments/production/data/common.yaml.

    I see that you have in fact done that, and I presume that you ask the question because it's not working for you as you expect. I can't confirm whether you have eyaml itself installed and configured properly, but being able to use the eyaml command as you describe seems to say so.

    The main issue I see is in your production-environment Hiera configuration: you have configured two different hierarchy levels based on the same common.yaml data file. That means that lookups using the default first-found strategy will always be served by the first-listed of those two, which uses the default YAML back-end. In your case, then, you'll get the ciphertext of the password instead of the corresponding decrypted text.

    You have two viable options here:

    1. move the encrypted data to a separate file, and reconfigure Hiera accordingly. Maybe something like this:

      ---
      version: 5
      defaults:
        datadir: data
        data_hash: yaml_data
      hierarchy:
        - name: "Per-node data (yaml version)"
          path: "nodes/%{::trusted.certname}.yaml"
        - name: "Common data"
          paths:
            - "common.yaml"
        - name: 'Encrypted common data'
          lookup_key: eyaml_lookup_key
          paths:
            - "secure.eyaml"
          options:
            pkcs7_private_key: /etc/puppetlabs/puppet/keys/private_key.pkcs7.pem
            pkcs7_public_key:  /etc/puppetlabs/puppet/keys/public_key.pkcs7.pem
      

      That supposes that the eyaml data will go in file /etc/puppetlabs/code/environments/production/data/secure.eyaml, leaving the common.yaml file for less sensitive data.

      OR

    2. Eyaml supports mixing encrypted and non-encrypted data, so you can set up a single, eyaml, level for the common data:

      ---
      version: 5
      defaults:
        datadir: data
        data_hash: yaml_data
      hierarchy:
        - name: "Per-node data (yaml version)"
          path: "nodes/%{::trusted.certname}.yaml"
        - name: 'Common data'
          lookup_key: eyaml_lookup_key
          paths:
            - "common.yaml"
          options:
            pkcs7_private_key: /etc/puppetlabs/puppet/keys/private_key.pkcs7.pem
            pkcs7_public_key:  /etc/puppetlabs/puppet/keys/public_key.pkcs7.pem
      

    Additional notes: