Version information
This version is compatible with:
- Puppet Enterprise 2023.8.x, 2023.7.x, 2023.6.x, 2023.5.x, 2023.4.x, 2023.3.x, 2023.2.x, 2023.1.x, 2023.0.x, 2021.7.x, 2021.6.x, 2021.5.x, 2021.4.x, 2021.3.x, 2021.2.x, 2021.1.x, 2021.0.x, 2019.8.x, 2019.7.x, 2019.5.x, 2019.4.x, 2019.3.x, 2019.2.x, 2019.1.x, 2019.0.x
- Puppet >= 6.0.0 < 9.0.0
- CentOS, OracleLinux, RedHat, Scientific, Debian, Ubuntu, Fedora, SLES, Gentoo
Start using this module
Add this module to your Puppetfile:
mod 'jcpunk-secrets', '1.2.4'
Learn more about managing modules with a PuppetfileDocumentation
secrets
Table of Contents
- Description
- Setup - The basics of getting started with secrets
- Usage - Configuration options and additional functionality
- Limitations - OS compatibility, etc.
Description
This class will deploy 'secrets' from outside the puppet tree onto your nodes.
It is targeted specifically at items like SSL certificates, ssh host keys, and kerberos keytabs. These are items that often have heavily restricted access.
These are items that you might not be able to store with your manifests.
Setup
Setup Requirements
Ultimately this module simply looks for ${secret_store}/$trusted['hostname'].$trusted['domain']/<path>
on your puppet server and pushes it out to the the node.
You can setup an encrypted git repo to store things.
If your secrets are in a repo, you can use the puppetlabs-vcsrepo type to check them out.
Beginning with secrets
For the most basic configuration you can create a secret store with the following commands:
mkdir -p /etc/puppetlabs/secrets
mkdir -p /etc/puppetlabs/secrets/myhostname.example.com/etc/
cat /etc/krb5.keytab > /etc/puppetlabs/secrets/myhostname.example.com/etc/krb5.keytab
Then import the following class:
class {'secrets':
install => {'/etc/krb5.keytab'}
}
or:
class {'secrets':
install => {'/etc/krb5.keytab' => { group => 'kerberos'}
}
hiera is similar:
secrets::load:
/etc/krb5.keytab:
group: kerberos
notify_services:
- sshd
Shared secrets
I don't like the idea of letting a host fetch secrets from a non-host specific directory. But for shared secrets (like the HTTPS cert for a load balanced cluser) there needs to be some sort of plan.
My suggestion, is to use symbolic links to a directory containing the shared secrets. This keeps the secrets in one place but also makes clear restrictions on which hosts can access things.
├── hostA.example.com
│ └── example -> ../my_shared_secrets/lbhost.example.com/example
├── hostB.example.com
│ └── example -> ../my_shared_secrets/lbhost.example.com/example
└── my_shared_secrets
└── lbhost.example.com
└── example
Usage
Some secrets may not be present on all nodes. For example, ssh added
ssh_host_ed25519_key
to newer releases. You may elect to make a secret
optional by setting mandatory=false
. This feature exists so that you can
list off every secret you are managing, but only enforce them on applicable
nodes.
The most fancy version I can think of looks like:
class {'secrets':
install => {'/etc/ssh/ssh_host_rsa_key' => {
owner => 'root',
group => 'root',
mode => '0400',
mandatory => true,
secret_store => '/my/private/directory',
notify_services => [ 'sshd', ],
},
'/etc/ssh/ssh_host_rsa_key.pub' => {
owner => 'root',
group => 'root',
mode => '0444',
mandatory => true,
secret_store => '/my/private/directory',
notify_services => [ 'sshd', ],
},
'/etc/ssh/ssh_host_ed25519_key' => {
owner => 'root',
group => 'root',
mode => '0400',
mandatory => false,
secret_store => '/my/other/directory',
notify_services => [ 'sshd', ],
},
'/etc/ssh/etc/ssh/ssh_host_ed25519_key.pub' => {
owner => 'root',
mode => '0444',
mandatory => false,
secret_store => '/my/other/directory',
notify_services => [ 'sshd', ],
},
'/etc/pki/tls/${::domain}.ca' => {
owner => 'root',
mode => '0444',
mandatory => false,
notify_services => [ 'httpd', ],
},
'/etc/pki/tls/${::fqdn}.crt' => {
owner => 'root',
mode => '0444',
mandatory => false,
notify_services => [ 'httpd', ],
},
'/etc/pki/tls/${::hostname}.key' => {
owner => 'root',
group => 'root',
mode => undef,
mandatory => false,
notify_services => [ 'httpd', ],
posix_acl => { 'action' => 'set',
'permission' => ['group:wheel:r--', ],},
},
defaults => {'group' => 'wheel' },
}
In this example we check out two repos and deploy our RSA keys to everyone, and our ED25519 to anyone who has them stored.
If the RSA keys are missing the catalog produces an error, if the ED25519 keys are missing, the report includes a notice that nothing happend.
Any file without the group set directly will default to wheel
.
Once done, it will restart the sshd service,
though if Service['sshd']
doesn't exist, your catalog will crash.
It will also deploy public/private keys where the filename is
determined from the system trusted hostname facts and tell Service['httpd']
.
The key used for Service['httpd']
will have a POSIX ACL set to let the
wheel
group also read the file.
The literal strings ${::domain}
, ${::fqdn}
, ${::hostname}
,
${::networking[domain]}
, ${::networking[fqdn]}
, ${::networking[hostname]}
${::networking.domain}
, ${::networking.fqdn}
, ${::networking.hostname}
will be converted to the values of $::trusted[domain]
, $::trusted[hostname]
,
$::trusted[hostname].$::trusted[domain]
if they are not converted automatically by
your parameter source to an explicit value.
Limitations
This class tries to only act as a secure file deployment method.
The use of the $::trusted
facts is by choice to ensure a client cannot swipe
someone else's secrets.
Reference
Table of Contents
Classes
secrets
: Manage secrets on a given host
Defined types
secrets::load
: This type will provide the actual file requested
Classes
secrets
This class will fetch secrets from the puppet server that follow a specific layout.
Examples
class {'secrets':
install => { '/etc/krb5.keytab' => {
'owner' => 'root',
'group' => 'root',
'mode' => '0400',
'mandatory' => 'true',
'secretbase' => '/my/secrets/repo/on/server',
'posix_acl' => { 'action' => 'set',
'permission' => ['group:wheel:r--', ],},
'selrange' => 's0',
'seluser' => 'system_u',
'selrole' => 'object_r',
'seltype' => 'krb5_keytab_t', },
}
}
Parameters
The following parameters are available in the secrets
class:
install
Data type: Hash
Secrets to install on the system
defaults
Data type: Hash
Passed as a list of defaults to the installed secrets
Defined types
secrets::load
Find the secret on the system and make the relevant Files
Examples
secrets::load { '/etc/krb5.keytab':
owner => 'root',
group => 'root',
mode => '0400',
mandatory => 'true',
secretbase => '/my/secrets/repo/on/server',
posix_acl => { 'action' => 'set',
'permission' => ['group:wheel:r--', ],},
selrange => 's0',
seluser => 'system_u',
selrole => 'object_r',
seltype => 'krb5_keytab_t',
}
Parameters
The following parameters are available in the secrets::load
defined type:
mandatory
notify_services
posix_acl
secretbase
path
owner
group
mode
selinux_ignore_defaults
selrange
seluser
selrole
seltype
mandatory
Data type: Boolean
Should the catalog crash if this secret doesn't exist
Default value: true
notify_services
Data type: Array
Service titles to try and notify if this changes.
Default value: []
posix_acl
Data type: Hash
Set these posix acls (see posix_acl resource)
Default value: {}
secretbase
Data type: Stdlib::Absolutepath
The directory to use as the base to start the secret search
Default value: '/etc/puppetlabs/secrets/'
path
Data type: Stdlib::Absolutepath
Passed directly to the file
resource
Default value: $title
owner
Data type: Variant[String,Integer]
Passed directly to the file
resource
Default value: 'root'
group
Data type: Variant[String,Integer]
Passed directly to the file
resource
Default value: 'root'
mode
Data type: String
Passed directly to the file
resource
Default value: '0400'
selinux_ignore_defaults
Data type: Boolean
Passed directly to the file
resource
Default value: false
selrange
Data type: Optional[String]
Passed directly to the file
resource
Default value: undef
seluser
Data type: Optional[String]
Passed directly to the file
resource
Default value: undef
selrole
Data type: Optional[String]
Passed directly to the file
resource
Default value: undef
seltype
Data type: Optional[String]
Passed directly to the file
resource
Default value: undef
Changelog
All notable changes to this project will be documented in this file.
Release 1.2.4
Features
- Note puppet8 support
Release 1.2.3
Features
- Note stdlib 9.x.x support
Release 1.2.2
Features
- Support facter dotted notation
Release 1.2.1
Features
- Support non-legacy fact name swaps
Release 1.2.0
Features
- Switched to the
binary_file
function wrapper for json serialization
Release 1.1.1
Features
- Switched from 'puppet master' to 'puppet server'
Release 1.1.0
Features
- Using a resource collector for notifications now
Bugfixes
- Filenames with
/./
in them now have that removed.
Release 1.0.4
Bugfixes
- Missed a notify from 1.0.2
Release 1.0.3
Bugfixes
- File accepts an Integer, so we should too
Release 1.0.2
Bugfixes
- drop client notices on non-mandatory secrets. They were counting as "changed" resources
Release 1.0.1
Bugfixes
- Fix defaults from data/common.yaml
Release 1.0.0
Features
- Move secrets under /etc/puppetlabs/ by default
Bugfixes
- Fix typos in documentation
Known Issues
Release 0.3.1
Features
Move to PDK
Bugfixes
Known Issues
Dependencies
- puppetlabs-stdlib (>= 6.0.0 < 10.0.0)
- puppet-posix_acl (>= 1.0.0 < 2.1.0)