puppet-prod/site/profiles/manifests/ssh/sign.pp
Ben Vincent b468f67103 feat: sign ssh host keys
- manage python script/venv to sign ssh host certificates
- add approle_id to puppetmaster eyaml files
- add class to sign ssh-rsa host keys
- add facts to check if the current principals match the desired principals
2024-06-01 22:51:42 +10:00

85 lines
2.3 KiB
Puppet

# profiles::ssh::sign
class profiles::ssh::sign (
Optional[Array[Stdlib::Host]] $principals = [],
){
# validate and prepare additional alt_names, if any
$default_principals = [
$::facts['networking']['hostname'],
$::facts['networking']['fqdn'],
$::facts['networking']['ip'],
]
$effective_principals = $principals ? {
[] => $default_principals,
default => concat($default_principals, $principals),
}
# path for the principals file
$principals_file = '/etc/ssh/host_principals'
# alt_names_file contents
$principals_file_content = $effective_principals
# manage the alt names file
file { $principals_file:
ensure => file,
owner => 'root',
group => 'root',
mode => '0644',
content => join($principals_file_content, "\n"),
}
# compare the sorted arrays of principals from disk (fact) vs what is intended (this run)
$principals_match = sort($::facts['sshd_host_principals']) == sort($principals_file_content)
# only renew signed certificate if doesnt exist or the principals have changed
if ! $::facts['sshd_host_cert_exists'] or ! $principals_match {
$common_name = $::facts['networking']['fqdn']
$valid_hours = '87600h'
# prepare alt_names and ip_sans arguments conditionally
$principals_string = $effective_principals.empty() ? {
true => '',
default => join($effective_principals, ','),
}
# sshsignhost arguments
$cmd = '/usr/local/bin/sshsignhost'
$principals_arg = '--valid_principals'
$ttl_arg = '--ttl'
$public_key_arg = '--public_key'
# call the script with generate(), capturing json output
$json_output = generate(
$cmd,
$principals_arg,
$principals_string,
$ttl_arg,
$valid_hours,
$public_key_arg,
"${facts['ssh']['rsa']['type']} ${facts['ssh']['rsa']['key']}",
'--json'
)
$signed_data = parsejson($json_output)
# manage the signed hostkey file
file { '/etc/ssh/ssh_host_rsa_key-cert.pem':
ensure => file,
content => $signed_data['signed_key'],
owner => 'root',
group => 'root',
mode => '0644',
}
}else{
# manage the signed hostkey file
file { '/etc/ssh/ssh_host_rsa_key-cert.pem':
ensure => file,
owner => 'root',
group => 'root',
mode => '0644',
}
}
}