Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Support for Extra Configuration Options #173

Merged
merged 1 commit into from
Apr 10, 2017
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
21 changes: 21 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ override['ssh-hardening']['ssh']['server']['listen_to'] = node['ipaddress']
* `['ssh-hardening']['ssh']['client']['remote_hosts']` - `[]` - one or more hosts, to which ssh-client can connect to.
* `['ssh-hardening']['ssh']['client']['password_authentication']` - `false`. Set to `true` if password authentication should be enabled.
* `['ssh-hardening']['ssh']['client']['roaming']` - `false`. Set to `true` if experimental client roaming should be enabled. This is known to cause potential issues with secrets being disclosed to malicious servers and defaults to being disabled.
* `['ssh-hardening']['ssh']['client']['extras']` - `{}`. Add extra configuration options, see [below](#extra-configuration-options) for details
* `['ssh-hardening']['ssh']['server']['host_key_files']` - `nil` to calculate best hostkey configuration based on server version, otherwise specify an array with file paths (e.g. `/etc/ssh/ssh_host_rsa_key`)
* `['ssh-hardening']['ssh']['server']['dh_min_prime_size']` - `2048` - Minimal acceptable prime length in bits in `/etc/ssh/moduli`. Primes below this number will get removed. (See [this](https://entropux.net/article/openssh-moduli/) for more information and background)
* `['ssh-hardening']['ssh']['server']['dh_build_primes']` - `false` - If own primes should be built. This rebuild happens only once and takes a lot of time (~ 1.5 - 2h on the modern hardware for 4096 length).
Expand Down Expand Up @@ -76,6 +77,8 @@ override['ssh-hardening']['ssh']['server']['listen_to'] = node['ipaddress']
* `['ssh-hardening']['ssh']['server']['sftp']['group']` - `sftponly`. Sets the `Match Group` option of SFTP to allow SFTP only for dedicated users
* `['ssh-hardening']['ssh']['server']['sftp']['chroot']` - `/home/%u`. Sets the directory where the SFTP user should be chrooted

* `['ssh-hardening']['ssh']['server']['extras']` - `{}`. Add extra configuration options, see [below](#extra-configuration-options) for details


## Usage

Expand Down Expand Up @@ -124,6 +127,24 @@ Configure attributes:

This will enable the SFTP Server and chroot every user in the `sftpusers` group to the `/home/sftp/%u` directory.

## Extra Configuration Options
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bdwyertech cool, thanks for adding this to the docs. Can you please add something like

....
* `['ssh-hardening']['ssh']['server']['extras']` - `{}`. Add extra configuration options, see [below](#extra-configuration-options) for details
....
* `['ssh-hardening']['ssh']['client']['extras']` - `{}`. Add extra configuration options, see [below](#extra-configuration-options) for details

to the attribute documentation above?

Can you do me a favor and cleanup a commit history by squashing the commits?

Then we can merge it :-)

Extra configuration options can be appended to the client or server configuration files. This can be used to override statically set values, or add configuration options not otherwise available via attributes.

The syntax is as follows:
```
# => Extra Server Configuration
default['ssh-hardening']['ssh']['server']['extras'].tap do |extra|
extra['#Some Comment'] = 'Heres the Comment'
extra['AuthenticationMethods'] = 'publickey,keyboard-interactive'
end

# => Extra Client Configuration
default['ssh-hardening']['ssh']['client']['extras'].tap do |extra|
extra['PermitLocalCommand'] = 'no'
extra['Tunnel'] = 'no'
end
```

## Local Testing

For local testing you can use vagrant and Virtualbox of VMWare to run tests locally. You will have to install Virtualbox and Vagrant on your system. See [Vagrant Downloads](http://downloads.vagrantup.com/) for a vagrant package suitable for your system. For all our tests we use `test-kitchen`. If you are not familiar with `test-kitchen` please have a look at [their guide](http://kitchen.ci/docs/getting-started). We are writing our test with [InSpec](https://github.com/chef/inspec).
Expand Down
108 changes: 59 additions & 49 deletions attributes/default.rb
Original file line number Diff line number Diff line change
Expand Up @@ -52,55 +52,65 @@
default['ssh-hardening']['ssh']['ports'] = [22]

# ssh client
default['ssh-hardening']['ssh']['client']['mac'] = nil # nil = calculate best combination for client
default['ssh-hardening']['ssh']['client']['kex'] = nil # nil = calculate best combination for client
default['ssh-hardening']['ssh']['client']['cipher'] = nil # nil = calculate best combination for client
default['ssh-hardening']['ssh']['client']['cbc_required'] = false
default['ssh-hardening']['ssh']['client']['weak_hmac'] = false
default['ssh-hardening']['ssh']['client']['weak_kex'] = false
default['ssh-hardening']['ssh']['client']['remote_hosts'] = []
default['ssh-hardening']['ssh']['client']['password_authentication'] = false # ssh
# http://undeadly.org/cgi?action=article&sid=20160114142733
default['ssh-hardening']['ssh']['client']['roaming'] = false
default['ssh-hardening']['ssh']['client']['send_env'] = ['LANG', 'LC_*', 'LANGUAGE']
default['ssh-hardening']['ssh']['client'].tap do |client|
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

.tap is a cool idea and improvement :-)

client['mac'] = nil # nil = calculate best combination for client
client['kex'] = nil # nil = calculate best combination for client
client['cipher'] = nil # nil = calculate best combination for client
client['cbc_required'] = false
client['weak_hmac'] = false
client['weak_kex'] = false
client['remote_hosts'] = []
client['password_authentication'] = false # ssh
# http://undeadly.org/cgi?action=article&sid=20160114142733
client['roaming'] = false
client['send_env'] = ['LANG', 'LC_*', 'LANGUAGE']

# extra client configuration options
client['extras'] = {}
end

# sshd
default['ssh-hardening']['ssh']['server']['kex'] = nil # nil = calculate best combination for server version
default['ssh-hardening']['ssh']['server']['cipher'] = nil # nil = calculate best combination for server version
default['ssh-hardening']['ssh']['server']['mac'] = nil # nil = calculate best combination for server version
default['ssh-hardening']['ssh']['server']['cbc_required'] = false
default['ssh-hardening']['ssh']['server']['weak_hmac'] = false
default['ssh-hardening']['ssh']['server']['weak_kex'] = false
default['ssh-hardening']['ssh']['server']['dh_min_prime_size'] = 2048
default['ssh-hardening']['ssh']['server']['dh_build_primes'] = false
default['ssh-hardening']['ssh']['server']['dh_build_primes_size'] = 4096
default['ssh-hardening']['ssh']['server']['host_key_files'] = nil
default['ssh-hardening']['ssh']['server']['client_alive_interval'] = 600 # 10min
default['ssh-hardening']['ssh']['server']['client_alive_count'] = 3 # ~> 3 x interval
default['ssh-hardening']['ssh']['server']['allow_root_with_key'] = false
default['ssh-hardening']['ssh']['server']['allow_tcp_forwarding'] = false
default['ssh-hardening']['ssh']['server']['allow_agent_forwarding'] = false
default['ssh-hardening']['ssh']['server']['allow_x11_forwarding'] = false
default['ssh-hardening']['ssh']['server']['use_pam'] = true
default['ssh-hardening']['ssh']['server']['challenge_response_authentication'] = false
default['ssh-hardening']['ssh']['server']['deny_users'] = []
default['ssh-hardening']['ssh']['server']['allow_users'] = []
default['ssh-hardening']['ssh']['server']['deny_groups'] = []
default['ssh-hardening']['ssh']['server']['allow_groups'] = []
default['ssh-hardening']['ssh']['server']['print_motd'] = false
default['ssh-hardening']['ssh']['server']['print_last_log'] = false
default['ssh-hardening']['ssh']['server']['banner'] = nil # set this to nil to disable banner or provide a path like '/etc/issue.net'
default['ssh-hardening']['ssh']['server']['os_banner'] = false # (Debian OS family)
default['ssh-hardening']['ssh']['server']['use_dns'] = nil # set this to nil to let us use the default OpenSSH in case it's not set by the user
default['ssh-hardening']['ssh']['server']['use_privilege_separation'] = nil # set this to nil to let us detect the attribute based on the node platform
default['ssh-hardening']['ssh']['server']['login_grace_time'] = '30s'
default['ssh-hardening']['ssh']['server']['max_auth_tries'] = 2
default['ssh-hardening']['ssh']['server']['max_sessions'] = 10
default['ssh-hardening']['ssh']['server']['password_authentication'] = false
default['ssh-hardening']['ssh']['server']['log_level'] = 'verbose'
default['ssh-hardening']['ssh']['server']['accept_env'] = ['LANG', 'LC_*', 'LANGUAGE']
default['ssh-hardening']['ssh']['server'].tap do |server| # rubocop: disable BlockLength
server['kex'] = nil # nil = calculate best combination for server version
server['cipher'] = nil # nil = calculate best combination for server version
server['mac'] = nil # nil = calculate best combination for server version
server['cbc_required'] = false
server['weak_hmac'] = false
server['weak_kex'] = false
server['dh_min_prime_size'] = 2048
server['dh_build_primes'] = false
server['dh_build_primes_size'] = 4096
server['host_key_files'] = nil
server['client_alive_interval'] = 600 # 10min
server['client_alive_count'] = 3 # ~> 3 x interval
server['allow_root_with_key'] = false
server['allow_tcp_forwarding'] = false
server['allow_agent_forwarding'] = false
server['allow_x11_forwarding'] = false
server['use_pam'] = true
server['challenge_response_authentication'] = false
server['deny_users'] = []
server['allow_users'] = []
server['deny_groups'] = []
server['allow_groups'] = []
server['print_motd'] = false
server['print_last_log'] = false
server['banner'] = nil # set this to nil to disable banner or provide a path like '/etc/issue.net'
server['os_banner'] = false # (Debian OS family)
server['use_dns'] = nil # set this to nil to let us use the default OpenSSH in case it's not set by the user
server['use_privilege_separation'] = nil # set this to nil to let us detect the attribute based on the node platform
server['login_grace_time'] = '30s'
server['max_auth_tries'] = 2
server['max_sessions'] = 10
server['password_authentication'] = false
server['log_level'] = 'verbose'
server['accept_env'] = ['LANG', 'LC_*', 'LANGUAGE']

# sshd sftp options
default['ssh-hardening']['ssh']['server']['sftp']['enable'] = false
default['ssh-hardening']['ssh']['server']['sftp']['group'] = 'sftponly'
default['ssh-hardening']['ssh']['server']['sftp']['chroot'] = '/home/%u'
# extra server configuration options
server['extras'] = {}

# sshd sftp options
server['sftp']['enable'] = false
server['sftp']['group'] = 'sftponly'
server['sftp']['chroot'] = '/home/%u'
end
27 changes: 27 additions & 0 deletions spec/recipes/client_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,33 @@
end
end

describe 'extra configuration values' do
context 'without custom extra config value' do
cached(:chef_run) do
ChefSpec::ServerRunner.new.converge(described_recipe)
end

it 'does not have any extra config options' do
expect(chef_run).to render_file('/etc/ssh/ssh_config')
expect(chef_run).not_to render_file('/etc/ssh/ssh_config').
with_content(/^# Extra Configuration Options/)
end
end

context 'with custom extra config value' do
cached(:chef_run) do
ChefSpec::ServerRunner.new do |node|
node.normal['ssh-hardening']['ssh']['client']['extras']['#ExtraConfig'] = 'Value'
end.converge(described_recipe)
end

it 'uses the extra config attributes' do
expect(chef_run).to render_file('/etc/ssh/ssh_config').with_content(/^# Extra Configuration Options/)
expect(chef_run).to render_file('/etc/ssh/ssh_config').with_content(/^#ExtraConfig Value/)
end
end
end

context 'chef-solo' do
cached(:chef_run) do
ChefSpec::SoloRunner.new.converge(described_recipe)
Expand Down
27 changes: 27 additions & 0 deletions spec/recipes/server_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -403,6 +403,33 @@
end
end

describe 'extra configuration values' do
context 'without custom extra config value' do
cached(:chef_run) do
ChefSpec::ServerRunner.new.converge(described_recipe)
end

it 'does not have any extra config options' do
expect(chef_run).to render_file('/etc/ssh/sshd_config')
expect(chef_run).not_to render_file('/etc/ssh/sshd_config').
with_content(/^# Extra Configuration Options/)
end
end

context 'with custom extra config value' do
cached(:chef_run) do
ChefSpec::ServerRunner.new do |node|
node.normal['ssh-hardening']['ssh']['server']['extras']['#ExtraConfig'] = 'Value'
end.converge(described_recipe)
end

it 'uses the extra config attributes' do
expect(chef_run).to render_file('/etc/ssh/sshd_config').with_content(/^# Extra Configuration Options/)
expect(chef_run).to render_file('/etc/ssh/sshd_config').with_content(/^#ExtraConfig Value/)
end
end
end

it 'disables the challenge response authentication' do
expect(chef_run).to render_file('/etc/ssh/sshd_config').
with_content(/ChallengeResponseAuthentication no/)
Expand Down
7 changes: 7 additions & 0 deletions templates/default/openssh.conf.erb
Original file line number Diff line number Diff line change
Expand Up @@ -117,3 +117,10 @@ UseRoaming <%= @node['ssh-hardening']['ssh']['client']['roaming'] ? 'yes' : 'no'
# Send locale environment variables
SendEnv <%= @node['ssh-hardening']['ssh']['client']['send_env'].join(' ') %>
<% end %>

<%- unless @node['ssh-hardening']['ssh']['client']['extras'].empty? %>
# Extra Configuration Options
<%- @node['ssh-hardening']['ssh']['client']['extras'].each do |key, value| %>
<%= key %> <%= value %>
<% end -%>
<% end -%>
7 changes: 7 additions & 0 deletions templates/default/opensshd.conf.erb
Original file line number Diff line number Diff line change
Expand Up @@ -229,3 +229,10 @@ X11Forwarding no
#PermitRootLogin no
#X11Forwarding no
<% end %>

<%- unless @node['ssh-hardening']['ssh']['server']['extras'].empty? %>
# Extra Configuration Options
<%- @node['ssh-hardening']['ssh']['server']['extras'].each do |key, value| %>
<%= key %> <%= value %>
<% end -%>
<% end -%>