Skip to content

Commit

Permalink
remote_execution ssh_user management
Browse files Browse the repository at this point in the history
Especially useful if you have...
* Hosts that were built before you discovered/enabled remote execution
* You rebuild your foreman proxy server and the ssh keys are regenerated
  • Loading branch information
alexjfisher committed Jan 29, 2019
1 parent 32727ce commit d806a47
Show file tree
Hide file tree
Showing 6 changed files with 177 additions and 0 deletions.
4 changes: 4 additions & 0 deletions .fixtures.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,13 @@ fixtures:
mysql: 'https://github.com/puppetlabs/puppetlabs-mysql'
puppet: 'https://github.com/theforeman/puppet-puppet'
stdlib: 'https://github.com/puppetlabs/puppetlabs-stdlib'
sudo: 'https://github.com/saz/puppet-sudo'
systemd: 'https://github.com/camptocamp/puppet-systemd'
tftp: 'https://github.com/theforeman/puppet-tftp'
xinetd: 'https://github.com/puppetlabs/puppetlabs-xinetd'
yumrepo_core:
repo: "https://github.com/puppetlabs/puppetlabs-yumrepo_core"
puppet_version: ">= 6.0.0"
sshkeys_core:
repo: "https://github.com/puppetlabs/puppetlabs-sshkeys_core"
puppet_version: ">= 6.0.0"
17 changes: 17 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,23 @@ The powerdns plugin can optionally manage the database. If that's used, then
the puppetlabs-mysql module must be added to the modulepath, otherwise it's not
required.

### Remote Execution User Management

This module can also be used to manage the ssh user on
[Foreman Remote Execution](https://github.com/theforeman/foreman_remote_execution)
clients.

```puppet
include foreman_proxy::plugin::remote_execution::ssh_user
```

The class will make use of the `remote_execution_*` host parameters available
in the ENC data provided by Foreman.

It will manage the user, (by default `foreman_ssh`), install/update the ssh
keys and manage the sudo rules (using [saz\sudo](https://forge.puppet.com/saz/sudo)
if available in your environment).

## Contributing

* Fork the project
Expand Down
78 changes: 78 additions & 0 deletions manifests/plugin/remote_execution/ssh_user.pp
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
# This class replicates the functionality of the remote_execution_ssh_keys community templates snippet
#
# === Parameters:
#
# $manage_user:: Whether to manage the ssh user. Defaults to the host's Foreman ENC parameter `remote_execution_create_user`.
#
# $ssh_user:: The ssh user name. Defaults to the host's Foreman ENC parameter `remote_execution_ssh_user`.
#
# $effective_user_method:: Method to switch from ssh user to effective user. Defaults to the host's Foreman ENC parameter `remote_execution_effective_user_method`.
#
# $ssh_keys:: An array of public keys to put in ~/.ssh/authorized_keys. Defaults to the host's Foreman ENC parameter `remote_execution_ssh_keys`.
#
class foreman_proxy::plugin::remote_execution::ssh_user (
Boolean $manage_user = $foreman_proxy::plugin::remote_execution::ssh_user::params::remote_execution_create_user,
String[1] $ssh_user = $foreman_proxy::plugin::remote_execution::ssh_user::params::remote_execution_ssh_user,
Enum['sudo', 'su'] $effective_user_method = $foreman_proxy::plugin::remote_execution::ssh_user::params::remote_execution_effective_user_method,
Array[String[1]] $ssh_keys = $foreman_proxy::plugin::remote_execution::ssh_user::params::remote_execution_ssh_keys,
) inherits foreman_proxy::plugin::remote_execution::ssh_user::params {

# Manage the user
if $manage_user and $ssh_user != 'root'{
user { $ssh_user:
ensure => present,
home => "/home/${ssh_user}",
managehome => true,
expiry => absent,
password_max_age => -1, # password never expires
password => '!!',
purge_ssh_keys => true,
}
}

# Manage the user's keys
$ssh_keys.each |String $ssh_key| {
$key_array = split($ssh_key, ' ')
$key_type = $key_array[0]
$key = $key_array[1]
$key_name = $key_array[2]

ssh_authorized_key { $key_name:
ensure => present,
user => $ssh_user,
type => $key_type,
key => $key,
}
}

# Manage the sudo configuration
if $ssh_user != 'root' and $effective_user_method == 'sudo' {

$content = "${ssh_user} ALL = (root) NOPASSWD : ALL\nDefaults:${ssh_user} !requiretty\n"

# saz/sudo is a very popular module
# If it's in the environment, go ahead and use it
if extlib::has_module('saz/sudo') {
sudo::conf { $ssh_user:
content => $content,
}
# Clean up file created by the provisioning template
# Most of the time this is probably not necessary as saz/sudo defaults to purging unmanaged files in /etc/sudoers.d
file { "/etc/sudoers.d/${ssh_user}":
ensure => absent,
}
} else {
if $facts['os']['family'] =~ /(Redhat|Debian)/ {
file { "/etc/sudoers.d/${ssh_user}": # This file name matches the provisioning snippet
ensure => file,
owner => 'root',
group => 'root',
mode => '0440',
content => $content,
}
} else {
warning("Support for managing sudoers in foreman_proxy::plugin::remote_execution::ssh_user without saz/sudo isn't implemented for ${facts['os']['family']}")
}
}
}
}
31 changes: 31 additions & 0 deletions manifests/plugin/remote_execution/ssh_user/params.pp
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Remote Execution SSH user default parameters
class foreman_proxy::plugin::remote_execution::ssh_user::params {

if defined('$::remote_execution_create_user') {
$remote_execution_create_user = str2bool($::remote_execution_create_user)
} else {
$remote_execution_create_user = false
}

if defined('$::remote_execution_ssh_user') {
$remote_execution_ssh_user = $::remote_execution_ssh_user
} else {
$remote_execution_ssh_user = 'root'
}

if defined('$::remote_execution_effective_user_method') {
$remote_execution_effective_user_method = $::remote_execution_effective_user_method
} else {
$remote_execution_effective_user_method = 'sudo'
}

if defined('$::remote_execution_ssh_keys') {
if ($::remote_execution_ssh_keys =~ Array) {
$remote_execution_ssh_keys = $::remote_execution_ssh_keys
} else {
$remote_execution_ssh_keys = []
}
} else {
$remote_execution_ssh_keys = []
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
require 'spec_helper'

describe 'foreman_proxy::plugin::remote_execution::ssh_user' do
context 'when Foreman ENC is providing topscope variables' do
let :facts do
on_supported_os['redhat-7-x86_64'].merge(
remote_execution_create_user: 'true',
remote_execution_ssh_user: 'foreman_ssh',
remote_execution_effective_user_method: 'sudo',
remote_execution_ssh_keys: [
'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC2f3qnCl0FBVTERe+mh+vKgBr/Cttei/V6Txpt4NVMABb802rce8ARZb/lMlWlA98J7a20hZ3Q4kOJxtJvRTty7TPRi1C5fDlTIUtmjWEoRp+ZgXb6BuBU/pYGx9HRgym9jleqvdcZq5ek59xxuu/KHHRc6Y+UBzfQVcVdMgy3hi13oN/nXN+JBuCHZ6s3IdvlhZ1Xir5qqMVdcg2l5ARnUlEyZ7UPvB2LkNiEHjRcr8z8yVdCASUygzcj8lD1uZl4YzuzbSXFD4reqgXcP2EskWqhXiloPoXUNPFH28nfzAndQ3kAYz0cTKSU/gNxCaYhwU5sFnvULWxkMQy062x3 foreman-proxy@foreman-proxy1.example.com',
'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC2f3qnCl0FBVTERe+mh+vKgBr/Cttei/V6Txpt4NVMABb802rce8ARZb/lMlWlA98J7a20hZ3Q4kOJxtJvRTty7TPRi1C5fDlTIUtmjWEoRp+ZgXb6BuBU/pYGx9HRgym9jleqvdcZq5ek59xxuu/KHHRc6Y+UBzfQVcVdMgy3hi13oN/nXN+JBuCHZ6s3IdvlhZ1Xir5qqMVdcg2l5ARnUlEyZ7UPvB2LkNiEHjRcr8z8yVdCASUygzcj8lD1uZl4YzuzbSXFD4reqgXcP2EskWqhXiloPoXUNPFH28nfzAndQ3kAYz0cTKSU/gNxCaYhwU5sFnvULWxkMQy062x3 foreman-proxy@foreman-proxy2.example.com'
]
)
end

it { is_expected.to contain_class('foreman_proxy::plugin::remote_execution::ssh_user') }
it { is_expected.to contain_user('foreman_ssh').with_home('/home/foreman_ssh') }

describe 'ssh keys' do
it { is_expected.to have_ssh_authorized_key_resource_count(2) }
it { is_expected.to contain_ssh_authorized_key('foreman-proxy@foreman-proxy1.example.com').with(
ensure: 'present',
user: 'foreman_ssh',
type: 'ssh-rsa',
key: 'AAAAB3NzaC1yc2EAAAADAQABAAABAQC2f3qnCl0FBVTERe+mh+vKgBr/Cttei/V6Txpt4NVMABb802rce8ARZb/lMlWlA98J7a20hZ3Q4kOJxtJvRTty7TPRi1C5fDlTIUtmjWEoRp+ZgXb6BuBU/pYGx9HRgym9jleqvdcZq5ek59xxuu/KHHRc6Y+UBzfQVcVdMgy3hi13oN/nXN+JBuCHZ6s3IdvlhZ1Xir5qqMVdcg2l5ARnUlEyZ7UPvB2LkNiEHjRcr8z8yVdCASUygzcj8lD1uZl4YzuzbSXFD4reqgXcP2EskWqhXiloPoXUNPFH28nfzAndQ3kAYz0cTKSU/gNxCaYhwU5sFnvULWxkMQy062x3',
)}
end

describe 'sudo config' do
it { is_expected.to contain_sudo__conf('foreman_ssh').with_content("foreman_ssh ALL = (root) NOPASSWD : ALL\nDefaults:foreman_ssh !requiretty\n") }
it { is_expected.to contain_file('/etc/sudoers.d/foreman_ssh').with_ensure('absent') }
end
end

context 'when Foreman ENC is NOT providing topscope variables' do
let :facts do
on_supported_os['redhat-7-x86_64']
end
it { is_expected.to contain_class('foreman_proxy::plugin::remote_execution::ssh_user') }
it { is_expected.not_to contain_user('foreman_ssh') }
it { is_expected.to have_ssh_authorized_key_resource_count(0) }
it { is_expected.not_to contain_sudo__conf('foreman_ssh') }
it { is_expected.not_to contain_file('/etc/sudoers.d/foreman_ssh') }
end
end
1 change: 1 addition & 0 deletions spec/spec_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
# Original fact sources:
add_custom_fact :puppet_environmentpath, '/etc/puppetlabs/code/environments' # puppetlabs-stdlib
add_custom_fact :root_home, '/root' # puppetlabs-stdlib
add_custom_fact :sudoversion, '1.8.23' # saz-sudo

# Workaround for no method in rspec-puppet to pass undef through :params
class Undef
Expand Down

0 comments on commit d806a47

Please sign in to comment.