Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
91 changes: 91 additions & 0 deletions spec/acceptance/client_config_user_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
# frozen_string_literal: true

require 'spec_helper_acceptance'

describe 'ssh::client::config::user' do
context 'with per-user ssh config' do
before(:context) do
on(default, 'useradd -m testuser || true')
end

after(:context) do
on(default, 'userdel -r testuser || true')
end

it_behaves_like 'an idempotent resource' do
let(:manifest) do
<<~PP
class { 'ssh':
storeconfigs_enabled => false,
users_client_options => {
'testuser' => {
'options' => {
'Host *.example.com' => {
'User' => 'deploy',
'IdentityFile' => '~/.ssh/deploy_key',
},
'ServerAliveInterval' => '60',
},
},
},
}
PP
end
end

describe file('/home/testuser/.ssh') do
it { is_expected.to be_directory }
it { is_expected.to be_owned_by 'testuser' }
it { is_expected.to be_mode '700' }
end

describe file('/home/testuser/.ssh/config') do
it { is_expected.to be_file }
it { is_expected.to be_owned_by 'testuser' }
it { is_expected.to be_mode '600' }
its(:content) { is_expected.to match(%r{Host \*\.example\.com}) }
its(:content) { is_expected.to match(%r{User deploy}) }
its(:content) { is_expected.to match(%r{IdentityFile ~/.ssh/deploy_key}) }
its(:content) { is_expected.to match(%r{ServerAliveInterval\s+60}) }
end

# Verify OpenSSH can parse the per-user config
describe command('ssh -G -F /home/testuser/.ssh/config example.org') do
its(:exit_status) { is_expected.to eq 0 }
end
end

context 'with manage_user_ssh_dir set to false' do
before(:context) do
on(default, 'useradd -m testuser2 || true')
on(default, 'mkdir -p /home/testuser2/.ssh && chown testuser2 /home/testuser2/.ssh')
end

after(:context) do
on(default, 'userdel -r testuser2 || true')
end

it_behaves_like 'an idempotent resource' do
let(:manifest) do
<<~PP
class { 'ssh':
storeconfigs_enabled => false,
users_client_options => {
'testuser2' => {
'manage_user_ssh_dir' => false,
'options' => {
'ServerAliveInterval' => '30',
},
},
},
}
PP
end
end

describe file('/home/testuser2/.ssh/config') do
it { is_expected.to be_file }
its(:content) { is_expected.to match(%r{ServerAliveInterval\s+30}) }
end
end
end
105 changes: 105 additions & 0 deletions spec/acceptance/client_config_validation_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
# frozen_string_literal: true

require 'spec_helper_acceptance'

describe 'ssh client config validation' do
context 'with custom client_options' do
it_behaves_like 'an idempotent resource' do
let(:manifest) do
<<~PP
class { 'ssh':
storeconfigs_enabled => false,
client_options => {
'ServerAliveInterval' => '60',
'ServerAliveCountMax' => '3',
'StrictHostKeyChecking' => 'ask',
},
}
PP
end
end

describe file('/etc/ssh/ssh_config') do
it { is_expected.to be_file }
it { is_expected.to be_owned_by 'root' }
it { is_expected.to be_mode '644' }
its(:content) { is_expected.to match(%r{ServerAliveInterval 60}) }
its(:content) { is_expected.to match(%r{ServerAliveCountMax 3}) }
its(:content) { is_expected.to match(%r{StrictHostKeyChecking ask}) }
end

# Verify OpenSSH can parse the generated config
describe command('ssh -G -F /etc/ssh/ssh_config example.org') do
its(:exit_status) { is_expected.to eq 0 }
its(:stdout) { is_expected.to match(%r{serveraliveinterval 60}) }
its(:stdout) { is_expected.to match(%r{serveralivecountmax 3}) }
end
end

context 'with client_options and client_match_block combined' do
it_behaves_like 'an idempotent resource' do
let(:manifest) do
<<~PP
class { 'ssh':
storeconfigs_enabled => false,
client_options => {
'ForwardAgent' => 'no',
},
client_match_block => {
'bastion.example.com' => {
'type' => 'host',
'options' => {
'ForwardAgent' => 'yes',
'ProxyJump' => 'none',
},
},
},
}
PP
end
end

describe file('/etc/ssh/ssh_config') do
its(:content) { is_expected.to match(%r{ForwardAgent no}) }
its(:content) { is_expected.to match(%r{Match host bastion\.example\.com}) }
its(:content) { is_expected.to match(%r{ForwardAgent yes}) }
its(:content) { is_expected.to match(%r{ProxyJump none}) }
end

# Verify the generated config is parseable for both regular and matched hosts
%w[example.org bastion.example.com].each do |host|
describe command("ssh -G -F /etc/ssh/ssh_config #{host}") do
its(:exit_status) { is_expected.to eq 0 }
end
end
end

context 'with Host wildcard blocks in default options' do
it_behaves_like 'an idempotent resource' do
let(:manifest) do
<<~PP
class { 'ssh':
storeconfigs_enabled => false,
client_options => {
'Host *.internal.example.com' => {
'User' => 'deploy',
'IdentityFile' => '~/.ssh/deploy_key',
'StrictHostKeyChecking' => 'no',
},
},
}
PP
end
end

describe file('/etc/ssh/ssh_config') do
its(:content) { is_expected.to match(%r{Host \*\.internal\.example\.com}) }
its(:content) { is_expected.to match(%r{User deploy}) }
its(:content) { is_expected.to match(%r{IdentityFile ~/.ssh/deploy_key}) }
end

describe command('ssh -G -F /etc/ssh/ssh_config example.org') do
its(:exit_status) { is_expected.to eq 0 }
end
end
end
61 changes: 61 additions & 0 deletions spec/acceptance/server_config_file_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# frozen_string_literal: true

require 'spec_helper_acceptance'

describe 'ssh server config_file and include_dir' do
service_name = case fact('os.family')
when 'Debian'
'ssh'
else
'sshd'
end

context 'with include_dir and a config_file' do
it_behaves_like 'an idempotent resource' do
let(:manifest) do
<<~PP
class { 'ssh::server':
storeconfigs_enabled => false,
include_dir => '/etc/ssh/sshd_config.d',
options => {
'PermitRootLogin' => 'yes',
},
config_files => {
'hardening' => {
'options' => {
'MaxAuthTries' => '3',
'MaxSessions' => '5',
},
},
},
}
PP
end
end

describe file('/etc/ssh/sshd_config.d') do
it { is_expected.to be_directory }
it { is_expected.to be_owned_by 'root' }
it { is_expected.to be_mode '700' }
end

describe file('/etc/ssh/sshd_config.d/hardening.conf') do
it { is_expected.to be_file }
it { is_expected.to be_owned_by 'root' }
its(:content) { is_expected.to match(%r{MaxAuthTries 3}) }
its(:content) { is_expected.to match(%r{MaxSessions 5}) }
end

describe file('/etc/ssh/sshd_config') do
its(:content) { is_expected.to match(%r{Include /etc/ssh/sshd_config\.d/\*\.conf}) }
end

describe command('sshd -t') do
its(:exit_status) { is_expected.to eq 0 }
end

describe service(service_name) do
it { is_expected.to be_running }
end
end
end
62 changes: 62 additions & 0 deletions spec/acceptance/server_config_setting_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# frozen_string_literal: true

require 'spec_helper_acceptance'

describe 'ssh::server::config::setting' do
service_name = case fact('os.family')
when 'Debian'
'ssh'
else
'sshd'
end

context 'with a string value' do
it_behaves_like 'an idempotent resource' do
let(:manifest) do
<<~PP
include ssh

ssh::server::config::setting { 'allow_groups':
key => 'AllowGroups',
value => 'root sshusers',
}
PP
end
end

describe file('/etc/ssh/sshd_config') do
its(:content) { is_expected.to match(%r{AllowGroups root sshusers}) }
end

describe command('sshd -t') do
its(:exit_status) { is_expected.to eq 0 }
end

describe service(service_name) do
it { is_expected.to be_running }
end
end

context 'with a boolean value' do
it_behaves_like 'an idempotent resource' do
let(:manifest) do
<<~PP
include ssh

ssh::server::config::setting { 'permit_empty_passwords':
key => 'PermitEmptyPasswords',
value => false,
}
PP
end
end

describe file('/etc/ssh/sshd_config') do
its(:content) { is_expected.to match(%r{PermitEmptyPasswords no}) }
end

describe command('sshd -t') do
its(:exit_status) { is_expected.to eq 0 }
end
end
end
Loading
Loading