Updated Ansible roles

This commit is contained in:
Oleg Lavrovsky 2018-12-17 13:50:15 +01:00
parent 3b81fa38ae
commit 8a2933414b
133 changed files with 2949 additions and 897 deletions

View File

@ -86,7 +86,15 @@ Now access the admin panel with the user account you created earlier: http://loc
We use [Ansible](https://www.ansible.com) and [Docker Compose](https://docs.docker.com/compose/reference/overview/) for automated deployment.
To use Docker Compose to deploy the site, copy `ansible/roles/web/templates/docker-compose.j2` to `/docker-compose.yml` and fill in all `{{ variables }}`. This is done automatically in Ansible.
To use Docker Compose to manually deploy the site, copy `ansible/roles/web/templates/docker-compose.j2` to `/docker-compose.yml` and fill in all `{{ variables }}`. This can also be done automatically in Ansible.
Install or update the following roles from [Ansible Galaxy](https://docs.ansible.com/ansible/latest/reference_appendices/galaxy.html) to use our scripts:
```
ansible-galaxy install \
dev-sec.nginx-hardening dev-sec.ssh-hardening dev-sec.os-hardening \
geerlingguy.nodejs geerlingguy.certbot
```
To do production deployments, you need to obtain SSH and vault keys from your system administrator (who has followed the Ansible guide to set up a vault..), and place these in a `.keys` folder. To deploy a site:

View File

@ -1,4 +1,4 @@
[defaults]
retry_files_enabled = False
roles_path = ansible/roles
roles_path = ansible/roles:~/.ansible/roles
vault_password_file = .keys/ansible.vault

View File

@ -0,0 +1,40 @@
---
name: Bug report
about: Create a report to help us improve
---
**Describe the bug**
A clear and concise description of what the bug is.
**Expected behavior**
A clear and concise description of what you expected to happen.
**Actual behavior**
<!--- Paste verbatim command output between quotes -->
```paste below
```
**Example Playbook**
<!--- Paste an example playbook that can be used to reproduce the problem between quotes -->
```paste below
```
**OS / Environment**
<!--- Provide all relevant information below, e.g. target OS versions, network device firmware, etc. -->
**Ansible Version**
<!--- Paste verbatim output from "ansible --version" between quotes -->
```paste below
```
**Role Version**
<!--- Paste version of the role between quotes -->
```paste below
```
**Additional context**
Add any other context about the problem here.

View File

@ -0,0 +1,17 @@
---
name: Feature request
about: Suggest an idea for this project
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.

View File

@ -0,0 +1 @@
unreleased=false

View File

@ -1,13 +1,3 @@
README.pdf
README.html
shared_test_repo/
test/integration
.kitchen
coverage
Vagrantfile.erb
Gemfile.lock
Berksfile.lock
ansible.cfg
hosts
Gemfile.lock

View File

@ -1,18 +1,28 @@
---
driver:
name: vagrant
driver_config:
http_proxy: <%= ENV['http_proxy'] || nil %>
https_proxy: <%= ENV['https_proxy'] || nil %>
vagrantfiles:
- kitchen_vagrant_block.rb
provisioner:
name: ansible_playbook
test_repo_uri: https://github.com/hardening-io/tests-ssh-hardening.git
hosts: all
require_ansible_repo: false
require_ansible_omnibus: true
require_chef_for_busser: false
require_ruby_for_busser: false
ansible_verbose: true
roles_path: ../ansible-ssh-hardening/
roles_path: ../ansible-nginx-hardening/
requirements_path: requirements.yml
playbook: default.yml
http_proxy: <%= ENV['http_proxy'] || nil %>
https_proxy: <%= ENV['https_proxy'] || nil %>
transport:
max_ssh_sessions: 5
platforms:
- name: ubuntu-12.04
@ -23,6 +33,10 @@ platforms:
driver_config:
box: opscode-ubuntu-14.04
box_url: https://opscode-vm-bento.s3.amazonaws.com/vagrant/virtualbox/opscode_ubuntu-14.04_chef-provisionerless.box
- name: ubuntu-16.04
driver_config:
box: opscode-ubuntu-16.04
box_url: https://opscode-vm-bento.s3.amazonaws.com/vagrant/virtualbox/opscode_ubuntu-16.04_chef-provisionerless.box
- name: centos-6.4
driver_config:
box: opscode-centos-6.4
@ -31,6 +45,12 @@ platforms:
driver_config:
box: opscode-centos-6.5
box_url: https://opscode-vm-bento.s3.amazonaws.com/vagrant/virtualbox/opscode_centos-6.5_chef-provisionerless.box
- name: centos-6.8
driver_config:
box: bento/centos-6.8
- name: centos-7
driver_config:
box: bento/centos-7.2
- name: oracle-6.4
driver_config:
box: oracle-6.4
@ -39,14 +59,9 @@ platforms:
driver_config:
box: oracle-6.5
box_url: https://storage.us2.oraclecloud.com/v1/istoilis-istoilis/vagrant/oel65-64.box
- name: debian-6
- name: oracle-7
driver_config:
box: debian-6
box_url: https://opscode-vm-bento.s3.amazonaws.com/vagrant/virtualbox/opscode_debian-6.0.10_chef-provisionerless.box
- name: debian-7
driver_config:
box: debian-7
box_url: https://opscode-vm-bento.s3.amazonaws.com/vagrant/virtualbox/opscode_debian-7.8_chef-provisionerless.box
box: boxcutter/ol72
- name: debian-8
driver_config:
box: debian-8
@ -56,10 +71,7 @@ verifier:
name: inspec
sudo: true
inspec_tests:
- https://github.com/dev-sec/tests-ssh-hardening
- https://github.com/dev-sec/nginx-baseline/
suites:
- name: nginx-ansible_1.9
provisioner:
ansible_version: 1.9.4
- name: nginx-ansible_latest
- name: nginx

View File

@ -2,6 +2,9 @@
driver:
name: docker
use_sudo: false
privileged: true
http_proxy: <%= ENV['http_proxy'] || nil %>
https_proxy: <%= ENV['https_proxy'] || nil %>
transport:
max_ssh_sessions: 5
@ -10,51 +13,104 @@ provisioner:
name: ansible_playbook
hosts: all
require_ansible_repo: false
require_ansible_omnibus: true
require_chef_for_busser: false
require_ruby_for_busser: false
ansible_verbose: true
ansible_diff: true
requirements_path: requirements.yml
roles_path: ../ansible-nginx-hardening/
playbook: default.yml
http_proxy: <%= ENV['http_proxy'] || nil %>
https_proxy: <%= ENV['https_proxy'] || nil %>
playbook: tests/test.yml
requirements_path: requirements.yml
galaxy_ignore_certs: true
platforms:
- name: ubuntu-12.04
- name: centos6-ansible-latest
driver:
image: ubuntu:12.04
- name: ubuntu-14.04
image: rndmh3ro/docker-centos6-ansible:latest
platform: centos
- name: centos7-ansible-latest
driver:
image: ubuntu:14.04
- name: ubuntu-16.04
image: rndmh3ro/docker-centos7-ansible:latest
platform: centos
run_command: /sbin/init
provision_command:
- sed -i 's/UsePAM yes/UsePAM no/g' /etc/ssh/sshd_config
- systemctl enable sshd.service
- name: oracle6-ansible-latest
driver:
image: ubuntu:16.04
- name: centos-6.7
image: rndmh3ro/docker-oracle6-ansible:latest
platform: centos
- name: oracle7-ansible-latest
driver:
image: centos:6.7
- name: centos-6.8
image: rndmh3ro/docker-oracle7-ansible:latest
run_command: /sbin/init
platform: centos
provision_command:
- sed -i 's/UsePAM yes/UsePAM no/g' /etc/ssh/sshd_config
- systemctl enable sshd.service
- name: ubuntu1404-ansible-latest
driver:
image: centos:6.8
- name: centos-7
image: rndmh3ro/docker-ubuntu1404-ansible:latest
platform: ubuntu
- name: ubuntu1604-ansible-latest
driver:
image: centos:7
privileged: true
run_command: /usr/sbin/init
- name: debian-7
image: rndmh3ro/docker-ubuntu1604-ansible:latest
platform: ubuntu
run_command: /sbin/init
provision_command:
- systemctl enable ssh.service
- name: ubuntu1804-ansible-latest
driver:
image: debian:7
- name: debian-8
image: rndmh3ro/docker-ubuntu1804-ansible:latest
platform: ubuntu
run_command: /sbin/init
provision_command:
- systemctl enable ssh.service
- name: debian8-ansible-latest
driver:
image: debian:8
image: rndmh3ro/docker-debian8-ansible:latest
platform: debian
- name: debian9-ansible-latest
driver:
image: rndmh3ro/docker-debian9-ansible:latest
platform: debian
run_command: /sbin/init
provision_command:
- apt install -y systemd-sysv
- systemctl enable ssh.service
- name: amazon-ansible-latest
driver:
image: rndmh3ro/docker-amazon-ansible:latest
platform: centos
run_command: /sbin/init
provision_command:
- sed -i 's/UsePAM yes/UsePAM no/g' /etc/ssh/sshd_config
- systemctl enable sshd.service
verifier:
name: inspec
sudo: true
inspec_tests:
- https://github.com/dev-sec/tests-nginx-hardening
- ../nginx-baseline
#- https://github.com/dev-sec/nginx-baseline
controls:
- nginx-01
- nginx-02
- nginx-03
- nginx-04
- nginx-05
- nginx-06
- nginx-07
- nginx-08
- nginx-09
- nginx-10
- nginx-12
- nginx-13
- nginx-14
- nginx-15
- nginx-17
suites:
- name: nginx-ansible_1.9
provisioner:
ansible_version: 1.9.4
- name: nginx-ansible_latest
- name: nginx

View File

@ -1,23 +1,72 @@
---
notifications:
webhooks: https://galaxy.ansible.com/api/v1/notifications/
language: python
python: "2.7"
services: docker
env:
- ANSIBLE_VERSION=latest
- ANSIBLE_VERSION=1.9.4
- distro: centos6
version: latest
init: /sbin/init
- distro: centos7
init: /lib/systemd/systemd
run_opts: "--privileged --volume=/sys/fs/cgroup:/sys/fs/cgroup:ro"
version: latest
- distro: oracle6
version: latest
init: /sbin/init
# - distro: oracle7
# init: /usr/lib/systemd/systemd
# run_opts: "--privileged --volume=/sys/fs/cgroup:/sys/fs/cgroup:ro"
# version: latest
- distro: ubuntu1404
version: latest
init: /sbin/init
- distro: ubuntu1604
version: latest
init: /lib/systemd/systemd
run_opts: "--privileged --volume=/sys/fs/cgroup:/sys/fs/cgroup:ro"
- distro: ubuntu1804
version: latest
init: /lib/systemd/systemd
run_opts: "--privileged --volume=/sys/fs/cgroup:/sys/fs/cgroup:ro"
- distro: debian8
version: latest
init: /sbin/init
run_opts: "--privileged --volume=/sys/fs/cgroup:/sys/fs/cgroup:ro"
- distro: debian9
version: latest
init: /lib/systemd/systemd
run_opts: "--privileged --volume=/sys/fs/cgroup:/sys/fs/cgroup:ro"
# - distro: amazon
# init: /lib/systemd/systemd
# version: latest
# run_opts: "--privileged --volume=/sys/fs/cgroup:/sys/fs/cgroup:ro"
before_install:
- sudo apt-get update -qq
- sudo apt-get install -qq python-apt python-pycurl
install:
- if [ "$ANSIBLE_VERSION" = "latest" ]; then pip install ansible; else pip install ansible==$ANSIBLE_VERSION; fi
- echo -e 'localhost ansible_connection=local' > spec/inventory
- echo -e '[defaults]\nroles_path = ../\nhostfile = ./spec/inventory' > ansible.cfg
# Pull container
- 'docker pull rndmh3ro/docker-${distro}-ansible:${version}'
script:
- ansible-galaxy install -r requirements.yml
- ansible-playbook --syntax-check spec/travis.yml
- ansible-playbook --sudo -v --diff spec/travis.yml
- ansible-playbook --sudo -v --diff spec/travis.yml --extra-vars "nginx_remove_default_site=false"
- container_id=$(mktemp)
# Run container in detached state.
- 'docker run --detach --volume="${PWD}":/etc/ansible/roles/ansible-nginx-hardening:ro ${run_opts} rndmh3ro/docker-${distro}-ansible:${version} "${init}" > "${container_id}"'
# Install ansible galaxy requirements
- 'docker exec "$(cat ${container_id})" ansible-galaxy -c install -r /etc/ansible/roles/ansible-nginx-hardening/requirements.yml -p /etc/ansible/roles/'
# Test role.
- 'docker exec "$(cat ${container_id})" ansible-playbook /etc/ansible/roles/ansible-nginx-hardening/tests/test.yml -vv'
# Verify role
#- 'inspec exec https://github.com/dev-sec/nginx-baseline/ -t docker://$(cat ${container_id}) --controls=nginx-01 nginx-02 nginx-03 nginx-04 nginx-05 nginx-06 nginx-07 nginx-08 nginx-09 nginx-10 nginx-12 nginx-13 nginx-14 nginx-15 nginx-17 --no-distinct-exit'
- 'inspec exec https://github.com/dev-sec/nginx-baseline/ -t docker://$(cat ${container_id}) --controls=nginx-01 nginx-02 nginx-03 nginx-05 nginx-06 nginx-07 nginx-08 nginx-09 nginx-10 nginx-12 nginx-13 nginx-15 nginx-17 --no-distinct-exit'
notifications:
webhooks: https://galaxy.ansible.com/api/v1/notifications/

View File

@ -1,5 +1,32 @@
# Change Log
## [2.0.0](https://github.com/dev-sec/ansible-nginx-hardening/tree/2.0.0) (2018-09-08)
[Full Changelog](https://github.com/dev-sec/ansible-nginx-hardening/compare/1.0.2...2.0.0)
**Implemented enhancements:**
- Update readme to include baselines [\#10](https://github.com/dev-sec/ansible-nginx-hardening/issues/10)
- Update testing, remove useless params, style update [\#18](https://github.com/dev-sec/ansible-nginx-hardening/pull/18) ([rndmh3ro](https://github.com/rndmh3ro))
- Update README.md [\#14](https://github.com/dev-sec/ansible-nginx-hardening/pull/14) ([vishesh92](https://github.com/vishesh92))
- Add comment filter to {{ansible\_managed}} string [\#12](https://github.com/dev-sec/ansible-nginx-hardening/pull/12) ([fazlearefin](https://github.com/fazlearefin))
- use new Docker images [\#8](https://github.com/dev-sec/ansible-nginx-hardening/pull/8) ([rndmh3ro](https://github.com/rndmh3ro))
**Fixed bugs:**
- Running kitchen verify asks for 'roots' password [\#11](https://github.com/dev-sec/ansible-nginx-hardening/issues/11)
- Fix duplicate ssl\_prefer\_server\_ciphers error [\#16](https://github.com/dev-sec/ansible-nginx-hardening/pull/16) ([oakey-b1](https://github.com/oakey-b1))
## [1.0.2](https://github.com/dev-sec/ansible-nginx-hardening/tree/1.0.2) (2016-10-24)
[Full Changelog](https://github.com/dev-sec/ansible-nginx-hardening/compare/1.0.1...1.0.2)
**Fixed bugs:**
- Syntax Error while loading YAML in defaults/main.yml [\#6](https://github.com/dev-sec/ansible-nginx-hardening/issues/6)
**Merged pull requests:**
- remove tabs. fix \#6 [\#7](https://github.com/dev-sec/ansible-nginx-hardening/pull/7) ([rndmh3ro](https://github.com/rndmh3ro))
## [1.0.1](https://github.com/dev-sec/ansible-nginx-hardening/tree/1.0.1) (2016-09-23)
[Full Changelog](https://github.com/dev-sec/ansible-nginx-hardening/compare/1.0.0...1.0.1)
@ -20,4 +47,4 @@
## [1.0.0](https://github.com/dev-sec/ansible-nginx-hardening/tree/1.0.0) (2016-08-11)
\* *This Change Log was automatically generated by [github_changelog_generator](https://github.com/skywinder/Github-Changelog-Generator)*
\* *This Change Log was automatically generated by [github_changelog_generator](https://github.com/skywinder/Github-Changelog-Generator)*

View File

@ -2,25 +2,6 @@
source 'https://rubygems.org'
if Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.2.2')
gem 'rack', '< 2.0'
gem 'ruby_dep', '< 1.4.0'
gem 'listen', '< 3.0.0'
end
group :test do
gem 'rake'
gem 'foodcritic', '~> 4.0'
gem 'thor-foodcritic'
gem 'coveralls', require: false
end
group :development do
gem 'guard'
gem 'guard-rspec'
gem 'guard-kitchen'
end
group :integration do
gem 'test-kitchen', '~> 1.0'
gem 'kitchen-ansible'
@ -32,10 +13,10 @@ group :integration do
gem 'kitchen-docker'
end
group :openstack do
gem 'kitchen-openstack'
end
group :tools do
gem 'github_changelog_generator', '~> 1'
end
gem 'kitchen-dokken'
gem 'rb-readline'

View File

@ -6,17 +6,17 @@
## Description
This role provides secure nginx configuration.
This role provides secure nginx configuration. It is intended to be compliant with the [DevSec Nginx Baseline](https://github.com/dev-sec/nginx-baseline).
It works with the following nginx-roles, including, but not limited to:
* [geerlinggux.nginx](https://galaxy.ansible.com/geerlingguy/nginx/)
* [geerlingguy.nginx](https://galaxy.ansible.com/geerlingguy/nginx/)
* [jdauphant.nginx](https://galaxy.ansible.com/jdauphant/nginx/)
* [franklinkim.nginx](https://galaxy.ansible.com/franklinkim/nginx/)
**NOTE: This role does not work with nginx 1.0.15 or older! Please use the latest version from the official nginx repositories!**
## Requirements
* Ansible
* Ansible >= 2.5
## Role Variables
@ -35,10 +35,10 @@ It works with the following nginx-roles, including, but not limited to:
| [nginx_limit_conn_zone][] | `$binary_remote_addr zone=default:10m` | Sets parameters for a shared memory zone that will keep states for various keys. |
| [nginx_limit_conn][] | `default 5` | Sets the shared memory zone and the maximum allowed number of connections for a given key value. |
| [nginx_add_header][] | `[ "X-Frame-Options SAMEORIGIN", "X-Content-Type-Options nosniff", "X-XSS-Protection \"1; mode=block\"" ]` |Adds the specified field to a response header provided that the response code equals 200, 201, 204, 206, 301, 302, 303, 304, or 307. |
| [nginx_ssl_protocols][] | `TLSv1 TLSv1.1 TLSv1.2` | Specifies the SSL protocol which should be used. |
| [nginx_ssl_protocols][] | `TLSv1.2` | Specifies the SSL protocol which should be used. |
| [nginx_ssl_ciphers][] | *see defaults.yml* | Specifies the TLS ciphers which should be used. |
| [nginx_ssl_prefer_server_ciphers][] | `on` | Specifies that server ciphers should be preferred over client ciphers when using the TLS protocols. Set to false to disable it. |
| [nginx_dh-size][] | `2048` | Specifies the length of DH parameters for EDH ciphers. |
| [nginx_dh_size][] | `2048` | Specifies the length of DH parameters for EDH ciphers. |
## Example Playbook
@ -96,7 +96,7 @@ See [contributor guideline](CONTRIBUTING.md).
## License and Author
* Author:: Sebastian Gumprich <sebastian.gumprich@38.de>
* Author:: Sebastian Gumprich
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -130,4 +130,4 @@ limitations under the License.
[nginx_ssl_protocols]: http://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_protocols
[nginx_ssl_ciphers]: http://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_ciphers
[nginx_ssl_prefer_server_ciphers]: http://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_prefer_server_ciphers
[nginx_dh-size]: http://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_dhparam
[nginx_dh_size]: http://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_dhparam

View File

@ -0,0 +1,14 @@
# config file for ansible -- http://ansible.com/
# ==============================================
# nearly all parameters can be overridden in ansible-playbook
# or with command line flags. ansible will read ANSIBLE_CONFIG,
# ansible.cfg in the current working directory, .ansible.cfg in
# the home directory or /etc/ansible/ansible.cfg, whichever it
# finds first
[defaults]
ansible_managed = Ansible managed: {file} modified on %Y-%m-%d by {uid} on {host}
role_path = /vagrant
scp_if_ssh = True

View File

@ -1,6 +0,0 @@
---
- name: wrapper playbook for kitchen testing "ansible-nginx-hardening" with custom settings
hosts: localhost
roles:
- geerlingguy.nginx
- ansible-nginx-hardening

View File

@ -17,10 +17,13 @@ nginx_add_header: [
# disable content-type sniffing
"X-Content-Type-Options nosniff",
# XSS filter
"X-XSS-Protection \"1; mode=block\"" ]
"X-XSS-Protection \"1; mode=block\"",
"Strict-Transport-Security max-age=15768000",
"Content-Security-Policy \"script-src 'self'; object-src 'self'\"" ]
nginx_ssl_protocols: "TLSv1 TLSv1.1 TLSv1.2"
nginx_ssl_ciphers: "ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA"
nginx_set_cookie_flag: "* HttpOnly secure"
nginx_ssl_prefer_server_ciphers: "on"
nginx_dh_param: "{{nginx_root_dir}}/dh{{nginx_dh_size}}.pem"
nginx_ssl_protocols: "TLSv1.2"
nginx_ssl_ciphers: "ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256"
nginx_ssl_session_tickets: "off"
nginx_dh_size: "2048"

View File

@ -1,2 +1,4 @@
- name: reload nginx
service: name={{ nginx_service_name }} state=reloaded
- name: restart nginx
service:
name: "nginx"
state: restarted

View File

@ -0,0 +1,15 @@
# This is a Vagrant block to allow proxy settings to be carried into Kitchen
# You need this for all of yum/apt etc. to work!
unless ENV['http_proxy'].empty? || Vagrant.has_plugin?("vagrant-proxyconf")
raise "Missing required plugin 'vagrant-proxyconf' to support HTTP(S) proxies, run `vagrant plugin install vagrant-proxyconf`"
end
Vagrant.configure(2) do |config|
config.proxy.http = "#{ENV['http_proxy']}"
config.proxy.https = "#{ENV['https_proxy']}"
config.proxy.no_proxy = "localhost,127.0.0.1"
# You may have vagrant-vbguest plugin installed to keep your images up to date
# - but will probably have VBoxAddition build issues with the foreign boxes listed in .kitchen.vagrant.yml
config.vbguest.auto_update = false
end

View File

@ -1 +1 @@
{install_date: 'Sun Apr 23 07:59:34 2017', version: 1.0.2}
{install_date: 'Mon Dec 17 12:48:14 2018', version: 2.1.0}

View File

@ -4,7 +4,7 @@ galaxy_info:
description: 'This Ansible role provides secure nginx configurations. http://dev-sec.io/'
company: Hardening Framework Team
license: Apache License 2.0
min_ansible_version: '1.9'
min_ansible_version: '2.5'
platforms:
- name: EL
versions:
@ -15,10 +15,12 @@ galaxy_info:
- precise
- trusty
- xenial
- bionic
- name: Debian
versions:
- wheezy
- jessie
- stretch
galaxy_tags:
- system
- security

View File

@ -1 +1,2 @@
- src: nginxinc.nginx
- src: geerlingguy.nginx

View File

@ -1,4 +0,0 @@
- hosts: localhost
roles:
- geerlingguy.nginx
- ansible-nginx-hardening

View File

@ -1,35 +1,80 @@
---
- name: add the OS specific variables
include_vars: "{{ ansible_os_family }}.yml"
- name: config should not be worldwide read- or writeable
file: path="/etc/nginx" mode="o-rw" owner="root" group="root" recurse=yes
file:
path: "/etc/nginx"
mode: "o-rw"
owner: "root"
group: "root"
recurse: yes
- name: create additional configuration
template: src="hardening.conf.j2" dest="{{nginx_config_conf_dir}}/90.hardening.conf" owner="root" group="root"
notify: reload nginx
template:
src: "hardening.conf.j2"
dest: "/etc/nginx/conf.d/90.hardening.conf"
owner: "root"
group: "root"
notify: restart nginx
- name: change configuration in main nginx.conf
lineinfile: dest="/etc/nginx/nginx.conf" regexp="^\s*server_tokens" line="server_tokens {{nginx_server_tokens}};" insertafter="http {"
notify: reload nginx
lineinfile:
dest: "/etc/nginx/nginx.conf"
regexp: '^\s*server_tokens'
line: " server_tokens {{ nginx_server_tokens }};"
insertafter: "http {"
notify: restart nginx
- name: change ssl_protocols in main nginx.conf
lineinfile:
dest: "/etc/nginx/nginx.conf"
regexp: '^\s*ssl_protocols'
line: " ssl_protocols {{ nginx_ssl_protocols }};"
insertafter: "http {"
notify: restart nginx
- name: change ssl_prefer_server_ciphers in main nginx.conf
lineinfile:
dest: "/etc/nginx/nginx.conf"
regexp: '^\s*ssl_prefer_server_ciphers'
line: " ssl_prefer_server_ciphers {{ nginx_ssl_prefer_server_ciphers }};"
insertafter: "http {"
notify: restart nginx
- name: change client_max_body_size in main nginx.conf
lineinfile: dest="/etc/nginx/nginx.conf" regexp="^\s*client_max_body_size" line="client_max_body_size {{nginx_client_max_body_size}};" insertafter="http {"
notify: reload nginx
lineinfile:
dest: "/etc/nginx/nginx.conf"
regexp: '^\s*client_max_body_size'
line: " client_max_body_size {{ nginx_client_max_body_size }};"
insertafter: "http {"
notify: restart nginx
- name: change client_body_buffer_size in main nginx.conf
lineinfile: dest="/etc/nginx/nginx.conf" regexp="^\s*client_body_buffer_size" line="client_body_buffer_size {{nginx_client_body_buffer_size}};" insertafter="http {"
notify: reload nginx
lineinfile:
dest: "/etc/nginx/nginx.conf"
regexp: '^\s*client_body_buffer_size'
line: " client_body_buffer_size {{ nginx_client_body_buffer_size }};"
insertafter: "http {"
notify: restart nginx
- name: change keepalive_timeout in main nginx.conf
lineinfile: dest="/etc/nginx/nginx.conf" regexp="^\s*keepalive_timeout" line="keepalive_timeout {{nginx_keepalive_timeout}};" insertafter="http {"
notify: reload nginx
lineinfile:
dest: "/etc/nginx/nginx.conf"
regexp: '^\s*keepalive_timeout'
line: " keepalive_timeout {{ nginx_keepalive_timeout }};"
insertafter: "http {"
notify: restart nginx
- name: remove default.conf
file: path="{{nginx_default_conf}}" state=absent
file:
path: "{{ item }}"
state: absent
when: nginx_remove_default_site
notify: reload nginx
notify: restart nginx
loop:
- "/etc/nginx/conf.d/default.conf"
- "/etc/nginx/sites-enabled/default"
- name: generate dh group
command: openssl dhparam -out {{nginx_dh_param}} {{nginx_dh_size}} creates={{nginx_dh_param}}
notify: reload nginx
command: "openssl dhparam -out /etc/nginx/dh{{ nginx_dh_size }}.pem {{ nginx_dh_size }}"
args:
creates: "/etc/nginx/dh{{ nginx_dh_size }}.pem"
notify: restart nginx

View File

@ -1,17 +1,16 @@
# {{ansible_managed}}
# {{ ansible_managed|comment }}
# Additional configuration for Nginx.
client_header_buffer_size {{nginx_client_header_buffer_size}};
large_client_header_buffers {{nginx_large_client_header_buffers}};
client_body_timeout {{nginx_client_body_timeout}};
client_header_timeout {{nginx_client_header_timeout}};
send_timeout {{nginx_send_timeout}};
limit_conn_zone {{nginx_limit_conn_zone}};
limit_conn {{nginx_limit_conn}};
ssl_protocols {{nginx_ssl_protocols}};
ssl_ciphers {{nginx_ssl_ciphers}};
ssl_dhparam {{nginx_dh_param}};
ssl_prefer_server_ciphers {{nginx_ssl_prefer_server_ciphers}};
client_header_buffer_size {{ nginx_client_header_buffer_size }};
large_client_header_buffers {{ nginx_large_client_header_buffers }};
client_body_timeout {{ nginx_client_body_timeout }};
client_header_timeout {{ nginx_client_header_timeout }};
send_timeout {{ nginx_send_timeout }};
limit_conn_zone {{ nginx_limit_conn_zone }};
limit_conn {{ nginx_limit_conn }};
ssl_ciphers '{{ nginx_ssl_ciphers }}';
ssl_session_tickets {{ nginx_ssl_session_tickets }};
ssl_dhparam /etc/nginx/dh{{ nginx_dh_size }}.pem;
{% for header in nginx_add_header %}
add_header {{header}};
add_header {{ header }};
{% endfor %}

View File

@ -0,0 +1,25 @@
---
- name: wrapper playbook for kitchen testing "ansible-nginx-hardening" with custom settings
hosts: localhost
vars:
- nginx_ppa_use: true
- nginx_ppa_version: stable
pre_tasks:
- apt_repository:
repo: "deb http://ftp.debian.org/debian jessie-backports main"
state: present
when: ansible_distribution == 'Debian' and ansible_distribution_major_version == '8'
- set_fact:
nginx_default_release: "jessie-backports"
when: ansible_distribution == 'Debian' and ansible_distribution_major_version == '8'
- package: name="{{item}}" state=installed
with_items:
- "systemd"
ignore_errors: true
- apt: name="{{item}}" state=installed update_cache=true
with_items:
- "systemd"
ignore_errors: true
roles:
- geerlingguy.nginx
- ansible-nginx-hardening

View File

@ -1,4 +0,0 @@
nginx_root_dir: '/etc/nginx'
nginx_config_conf_dir: '/etc/nginx/conf.d'
nginx_default_conf: '/etc/nginx/sites-enabled/default'
nginx_service_name: 'nginx'

View File

@ -1,4 +0,0 @@
nginx_root_dir: '/etc/nginx'
nginx_config_conf_dir: '/etc/nginx/conf.d'
nginx_default_conf: '/etc/nginx/conf.d/default.conf'
nginx_service_name: 'nginx'

View File

@ -1,4 +0,0 @@
nginx_root_dir: '/etc/nginx'
nginx_config_conf_dir: '/etc/nginx/conf.d'
nginx_default_conf: '/etc/nginx/conf.d/default.conf'
nginx_service_name: 'nginx'

View File

@ -0,0 +1,35 @@
# These files are text and should be normalized (Convert crlf => lf)
*.php text eol=lf
*.css text eol=lf
*.js text eol=lf
*.htm text eol=lf
*.html text eol=lf
*.xml text eol=lf
*.txt text eol=lf
*.ini text eol=lf
*.inc text eol=lf
.htaccess text eol=lf
*.pp text eol=lf
*.yml text eol=lf
*.yaml text eol=lf
*.sh text eol=lf
# These files are binary and should be left untouched
# (binary is a macro for -text -diff)
*.png binary
*.jpg binary
*.jpeg binary
*.gif binary
*.ico binary
*.mov binary
*.mp4 binary
*.mp3 binary
*.flv binary
*.fla binary
*.swf binary
*.gz binary
*.zip binary
*.7z binary
*.ttf binary
*.rpm binary

View File

@ -0,0 +1,40 @@
---
name: Bug report
about: Create a report to help us improve
---
**Describe the bug**
A clear and concise description of what the bug is.
**Expected behavior**
A clear and concise description of what you expected to happen.
**Actual behavior**
<!--- Paste verbatim command output between quotes -->
```paste below
```
**Example Playbook**
<!--- Paste an example playbook that can be used to reproduce the problem between quotes -->
```paste below
```
**OS / Environment**
<!--- Provide all relevant information below, e.g. target OS versions, network device firmware, etc. -->
**Ansible Version**
<!--- Paste verbatim output from "ansible --version" between quotes -->
```paste below
```
**Role Version**
<!--- Paste version of the role between quotes -->
```paste below
```
**Additional context**
Add any other context about the problem here.

View File

@ -0,0 +1,17 @@
---
name: Feature request
about: Suggest an idea for this project
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.

View File

@ -24,51 +24,39 @@ transport:
max_ssh_sessions: 5
platforms:
- name: ubuntu-12.04
driver_config:
box: opscode-ubuntu-12.04
box_url: https://opscode-vm-bento.s3.amazonaws.com/vagrant/virtualbox/opscode_ubuntu-12.04_chef-provisionerless.box
- name: ubuntu-14.04
- name: ubuntu14.04
driver_config:
box: opscode-ubuntu-14.04
box_url: https://opscode-vm-bento.s3.amazonaws.com/vagrant/virtualbox/opscode_ubuntu-14.04_chef-provisionerless.box
- name: ubuntu-16.04
- name: ubuntu16.04
driver_config:
box: opscode-ubuntu-16.04
box_url: https://opscode-vm-bento.s3.amazonaws.com/vagrant/virtualbox/opscode_ubuntu-16.04_chef-provisionerless.box
- name: centos-6.4
- name: ubuntu18.04
driver_config:
box: opscode-centos-6.4
box_url: https://opscode-vm.s3.amazonaws.com/vagrant/opscode_centos-6.4_provisionerless.box
- name: centos-6.5
box: ubuntu/bionic64
- name: centos6
driver_config:
box: opscode-centos-6.5
box_url: https://opscode-vm-bento.s3.amazonaws.com/vagrant/virtualbox/opscode_centos-6.5_chef-provisionerless.box
- name: centos-6.8
box: bento/centos-6.9
- name: centos7
driver_config:
box: bento/centos-6.8
- name: centos-7
driver_config:
box: bento/centos-7.2
- name: oracle-6.4
driver_config:
box: oracle-6.4
box_url: https://storage.us2.oraclecloud.com/v1/istoilis-istoilis/vagrant/oel64-64.box
- name: oracle-6.5
box: bento/centos-7.3
- name: oracle6
driver_config:
box: oracle-6.5
box_url: https://storage.us2.oraclecloud.com/v1/istoilis-istoilis/vagrant/oel65-64.box
- name: oracle-7
- name: oracle7
driver_config:
box: boxcutter/ol72
- name: debian-7
- name: debian7
driver_config:
box: debian-7
box_url: https://opscode-vm-bento.s3.amazonaws.com/vagrant/virtualbox/opscode_debian-7.8_chef-provisionerless.box
- name: debian-8
box: bento/debian-7.11
- name: debian8
driver_config:
box: debian-8
box_url: https://opscode-vm-bento.s3.amazonaws.com/vagrant/virtualbox/opscode_debian-8.1_chef-provisionerless.box
box: bento/debian-8.8
- name: debian9
driver_config:
box: bento/debian-9.0
verifier:
name: inspec

View File

@ -21,9 +21,7 @@ provisioner:
roles_path: ../ansible-os-hardening/
http_proxy: <%= ENV['http_proxy'] || nil %>
https_proxy: <%= ENV['https_proxy'] || nil %>
playbook: default.yml
ansible_extra_flags:
- "--skip-tags=sysctl"
playbook: tests/test.yml
platforms:
- name: centos6-ansible-latest
@ -34,6 +32,10 @@ platforms:
driver:
image: rndmh3ro/docker-centos7-ansible:latest
platform: centos
run_command: /sbin/init
provision_command:
- sed -i 's/UsePAM yes/UsePAM no/g' /etc/ssh/sshd_config
- systemctl enable sshd.service
- name: oracle6-ansible-latest
driver:
image: rndmh3ro/docker-oracle6-ansible:latest
@ -41,11 +43,11 @@ platforms:
- name: oracle7-ansible-latest
driver:
image: rndmh3ro/docker-oracle7-ansible:latest
run_command: /sbin/init
platform: centos
- name: ubuntu1204-ansible-latest
driver:
image: rndmh3ro/docker-ubuntu1204-ansible:latest
platform: ubuntu
provision_command:
- sed -i 's/UsePAM yes/UsePAM no/g' /etc/ssh/sshd_config
- systemctl enable sshd.service
- name: ubuntu1404-ansible-latest
driver:
image: rndmh3ro/docker-ubuntu1404-ansible:latest
@ -54,6 +56,16 @@ platforms:
driver:
image: rndmh3ro/docker-ubuntu1604-ansible:latest
platform: ubuntu
run_command: /sbin/init
provision_command:
- systemctl enable ssh.service
- name: ubuntu1804-ansible-latest
driver:
image: rndmh3ro/docker-ubuntu1804-ansible:latest
platform: ubuntu
run_command: /sbin/init
provision_command:
- systemctl enable ssh.service
- name: debian7-ansible-latest
driver:
image: rndmh3ro/docker-debian7-ansible:latest
@ -66,6 +78,18 @@ platforms:
driver:
image: rndmh3ro/docker-debian9-ansible:latest
platform: debian
run_command: /sbin/init
provision_command:
- apt install -y systemd-sysv
- systemctl enable ssh.service
- name: amazon-ansible-latest
driver:
image: rndmh3ro/docker-amazon-ansible:latest
platform: centos
run_command: /sbin/init
provision_command:
- sed -i 's/UsePAM yes/UsePAM no/g' /etc/ssh/sshd_config
- systemctl enable sshd.service
verifier:
name: inspec

View File

@ -7,7 +7,7 @@ env:
init: /sbin/init
- distro: centos7
init: /usr/lib/systemd/systemd
init: /lib/systemd/systemd
run_opts: "--privileged --volume=/sys/fs/cgroup:/sys/fs/cgroup:ro"
version: latest
@ -15,23 +15,24 @@ env:
version: latest
init: /sbin/init
- distro: oracle7
init: /usr/lib/systemd/systemd
run_opts: "--privileged --volume=/sys/fs/cgroup:/sys/fs/cgroup:ro"
# - distro: oracle7
# init: /lib/systemd/systemd
# run_opts: "--privileged --volume=/sys/fs/cgroup:/sys/fs/cgroup:ro"
# version: latest
- distro: ubuntu1404
version: latest
init: /sbin/init
- distro: ubuntu1604
version: latest
init: /lib/systemd/systemd
run_opts: "--privileged --volume=/sys/fs/cgroup:/sys/fs/cgroup:ro"
- distro: ubuntu1404
- distro: ubuntu1804
version: latest
init: /sbin/init
- distro: ubuntu1204
version: latest
init: /sbin/init
init: /lib/systemd/systemd
run_opts: "--privileged --volume=/sys/fs/cgroup:/sys/fs/cgroup:ro"
- distro: debian7
version: latest
@ -40,12 +41,18 @@ env:
- distro: debian8
version: latest
init: /sbin/init
run_opts: "--privileged --volume=/sys/fs/cgroup:/sys/fs/cgroup:ro"
- distro: debian9
version: latest
init: /lib/systemd/systemd
run_opts: "--privileged --volume=/sys/fs/cgroup:/sys/fs/cgroup:ro"
- distro: amazon
init: /lib/systemd/systemd
version: latest
run_opts: "--privileged --volume=/sys/fs/cgroup:/sys/fs/cgroup:ro"
before_install:
# Pull container
- 'docker pull rndmh3ro/docker-${distro}-ansible:${version}'
@ -55,11 +62,11 @@ script:
# Run container in detached state.
- 'docker run --detach --volume="${PWD}":/etc/ansible/roles/ansible-os-hardening:ro ${run_opts} rndmh3ro/docker-${distro}-ansible:${version} "${init}" > "${container_id}"'
# Test role.
- 'docker exec "$(cat ${container_id})" ansible-playbook /etc/ansible/roles/ansible-os-hardening/default.yml --skip-tags "sysctl"'
# Test role.
- 'docker exec "$(cat ${container_id})" ansible-playbook /etc/ansible/roles/ansible-os-hardening/tests/test.yml --diff --skip-tags "sysctl"'
# Verify role
- 'inspec exec https://github.com/dev-sec/linux-baseline/ -t docker://$(cat ${container_id}) --controls=os-01 os-02 os-03 os-04 os-05 os-06 os-07 package-01 package-02 package-03 package-04 package-05 package-06'
# Verify role
- 'inspec exec https://github.com/dev-sec/linux-baseline/ -t docker://$(cat ${container_id}) --controls=os-01 os-02 os-03 os-04 os-05 os-05b os-06 os-07 os-09 os-10 os-11 package-01 package-02 package-03 package-05 package-06 package-08 package-09 --no-distinct-exit'
notifications:
webhooks: https://galaxy.ansible.com/api/v1/notifications/

View File

@ -1,5 +1,143 @@
# Change Log
## [5.0.0](https://github.com/dev-sec/ansible-os-hardening/tree/5.0.0) (2018-09-02)
[Full Changelog](https://github.com/dev-sec/ansible-os-hardening/compare/4.3.0...5.0.0)
**Implemented enhancements:**
- Warning about "include" for tasks for ansible-playbook 2.4.0 \(devel f0a5854e39\) [\#131](https://github.com/dev-sec/ansible-os-hardening/issues/131)
- fix problems with efi and vfat [\#190](https://github.com/dev-sec/ansible-os-hardening/pull/190) ([rndmh3ro](https://github.com/rndmh3ro))
- added os\_hardening\_enabled flag [\#186](https://github.com/dev-sec/ansible-os-hardening/pull/186) ([jcheroske](https://github.com/jcheroske))
- add amazon run opts to travis [\#183](https://github.com/dev-sec/ansible-os-hardening/pull/183) ([rndmh3ro](https://github.com/rndmh3ro))
- use package instead of yum and apt [\#180](https://github.com/dev-sec/ansible-os-hardening/pull/180) ([rndmh3ro](https://github.com/rndmh3ro))
- add oracle7 to travis [\#178](https://github.com/dev-sec/ansible-os-hardening/pull/178) ([rndmh3ro](https://github.com/rndmh3ro))
- fix wrong permissions passwdqc \#170 [\#176](https://github.com/dev-sec/ansible-os-hardening/pull/176) ([rndmh3ro](https://github.com/rndmh3ro))
- ipv4 forwarding comment is inconsistent with example [\#174](https://github.com/dev-sec/ansible-os-hardening/pull/174) ([carchrae](https://github.com/carchrae))
- Rename pam\_passwdqd.j2 to pam\_passwdqc.j2 [\#172](https://github.com/dev-sec/ansible-os-hardening/pull/172) ([martinbydefault](https://github.com/martinbydefault))
- Use package state 'present' since 'installed' is deprecated [\#168](https://github.com/dev-sec/ansible-os-hardening/pull/168) ([Normo](https://github.com/Normo))
- Update syntax to Ansible 2.4 [\#161](https://github.com/dev-sec/ansible-os-hardening/pull/161) ([thomasjpfan](https://github.com/thomasjpfan))
- add amazon linux testing [\#160](https://github.com/dev-sec/ansible-os-hardening/pull/160) ([rndmh3ro](https://github.com/rndmh3ro))
- Add support for Amazon Linux [\#158](https://github.com/dev-sec/ansible-os-hardening/pull/158) ([woneill](https://github.com/woneill))
- install and configure auditd - fix inspec package-08 [\#144](https://github.com/dev-sec/ansible-os-hardening/pull/144) ([rndmh3ro](https://github.com/rndmh3ro))
- Remove deprecated include for static tasks and use instead import\_tasks fix \#131 [\#132](https://github.com/dev-sec/ansible-os-hardening/pull/132) ([HelioCampos](https://github.com/HelioCampos))
**Fixed bugs:**
- minimize\_access: maximum recursion depth exceeded on Ansible 2.5 [\#171](https://github.com/dev-sec/ansible-os-hardening/issues/171)
- wrong permissions passwdqc [\#170](https://github.com/dev-sec/ansible-os-hardening/issues/170)
- Update deprecated `include` statements [\#166](https://github.com/dev-sec/ansible-os-hardening/issues/166)
- Strongly recommend against disabling vfat by default [\#162](https://github.com/dev-sec/ansible-os-hardening/issues/162)
- System completely unresponsive after role execution [\#145](https://github.com/dev-sec/ansible-os-hardening/issues/145)
- do not install passwdqc on amazon linux [\#189](https://github.com/dev-sec/ansible-os-hardening/pull/189) ([rndmh3ro](https://github.com/rndmh3ro))
- add back run opts for debian 8 in travis [\#184](https://github.com/dev-sec/ansible-os-hardening/pull/184) ([rndmh3ro](https://github.com/rndmh3ro))
- Fix core dump config file creation when core dumps are disabled [\#182](https://github.com/dev-sec/ansible-os-hardening/pull/182) ([Normo](https://github.com/Normo))
- change minimize access method [\#181](https://github.com/dev-sec/ansible-os-hardening/pull/181) ([rndmh3ro](https://github.com/rndmh3ro))
## [4.3.0](https://github.com/dev-sec/ansible-os-hardening/tree/4.3.0) (2018-01-03)
[Full Changelog](https://github.com/dev-sec/ansible-os-hardening/compare/4.3.1...4.3.0)
**Implemented enhancements:**
- Update some RH settings in this role [\#155](https://github.com/dev-sec/ansible-os-hardening/issues/155)
- Removal of core dump hardening configuration if core dumps are allowed [\#129](https://github.com/dev-sec/ansible-os-hardening/issues/129)
- Don't create home for system accounts [\#156](https://github.com/dev-sec/ansible-os-hardening/pull/156) ([oakey-b1](https://github.com/oakey-b1))
- Prevent disabling of filesystems via whitelist [\#153](https://github.com/dev-sec/ansible-os-hardening/pull/153) ([manuelprinz](https://github.com/manuelprinz))
- Add kernel hardening settings from Ubuntu /etc/sysctl.d [\#150](https://github.com/dev-sec/ansible-os-hardening/pull/150) ([kravietz](https://github.com/kravietz))
- Removal of core dump hardening configuration if core dumps are allowed [\#146](https://github.com/dev-sec/ansible-os-hardening/pull/146) ([martinbydefault](https://github.com/martinbydefault))
- add missing sysctl parameter [\#143](https://github.com/dev-sec/ansible-os-hardening/pull/143) ([rndmh3ro](https://github.com/rndmh3ro))
- update readme [\#139](https://github.com/dev-sec/ansible-os-hardening/pull/139) ([rndmh3ro](https://github.com/rndmh3ro))
**Fixed bugs:**
- bug in ufw.j2 template [\#151](https://github.com/dev-sec/ansible-os-hardening/issues/151)
- replace single ticks with double ticks. fix \#151 [\#152](https://github.com/dev-sec/ansible-os-hardening/pull/152) ([rndmh3ro](https://github.com/rndmh3ro))
- fixed tag [\#149](https://github.com/dev-sec/ansible-os-hardening/pull/149) ([martinbydefault](https://github.com/martinbydefault))
**Closed issues:**
- ansible hardening fails on ubuntu 16.04 with msg": "ERROR! 'sysctl\_rhel\_config' is undefined [\#147](https://github.com/dev-sec/ansible-os-hardening/issues/147)
- Enhancement: Test with TestInfra and Molecule [\#128](https://github.com/dev-sec/ansible-os-hardening/issues/128)
**Merged pull requests:**
- move defaults to os-specific vars [\#157](https://github.com/dev-sec/ansible-os-hardening/pull/157) ([rndmh3ro](https://github.com/rndmh3ro))
## [4.3.1](https://github.com/dev-sec/ansible-os-hardening/tree/4.3.1) (2017-09-13)
[Full Changelog](https://github.com/dev-sec/ansible-os-hardening/compare/4.2.0...4.3.1)
**Fixed bugs:**
- os\_security\_kernel\_enable\_sysrq is not implemented [\#115](https://github.com/dev-sec/ansible-os-hardening/issues/115)
## [4.2.0](https://github.com/dev-sec/ansible-os-hardening/tree/4.2.0) (2017-08-08)
[Full Changelog](https://github.com/dev-sec/ansible-os-hardening/compare/4.1.0...4.2.0)
**Implemented enhancements:**
- add modprobe template, control os-10 [\#138](https://github.com/dev-sec/ansible-os-hardening/pull/138) ([rndmh3ro](https://github.com/rndmh3ro))
- new task for delete netrc files, control os-09 [\#137](https://github.com/dev-sec/ansible-os-hardening/pull/137) ([rndmh3ro](https://github.com/rndmh3ro))
- add passwd task, control os-03 [\#136](https://github.com/dev-sec/ansible-os-hardening/pull/136) ([rndmh3ro](https://github.com/rndmh3ro))
- remove prelink package, control package-09 [\#135](https://github.com/dev-sec/ansible-os-hardening/pull/135) ([rndmh3ro](https://github.com/rndmh3ro))
- style update [\#134](https://github.com/dev-sec/ansible-os-hardening/pull/134) ([rndmh3ro](https://github.com/rndmh3ro))
- Fix ansible.cfg and use comment filter [\#130](https://github.com/dev-sec/ansible-os-hardening/pull/130) ([fazlearefin](https://github.com/fazlearefin))
**Fixed bugs:**
- Why is rsync removed? [\#141](https://github.com/dev-sec/ansible-os-hardening/issues/141)
- playbook makes OS undetectable [\#124](https://github.com/dev-sec/ansible-os-hardening/issues/124)
- Centos7/RHEL7: Exec shield is enabled by default and not manageable anymore by sysctl.conf [\#118](https://github.com/dev-sec/ansible-os-hardening/issues/118)
- Remove rsync from package blacklist [\#142](https://github.com/dev-sec/ansible-os-hardening/pull/142) ([duk3luk3](https://github.com/duk3luk3))
**Merged pull requests:**
- remove execshield sysctl-parameter on rhel7 [\#119](https://github.com/dev-sec/ansible-os-hardening/pull/119) ([rndmh3ro](https://github.com/rndmh3ro))
## [4.1.0](https://github.com/dev-sec/ansible-os-hardening/tree/4.1.0) (2017-06-27)
[Full Changelog](https://github.com/dev-sec/ansible-os-hardening/compare/4.0.0...4.1.0)
**Fixed bugs:**
- Change system accounts not on the user provided ignore-list items are not JSON serializable [\#125](https://github.com/dev-sec/ansible-os-hardening/issues/125)
- Could not find gem 'ruby \(\>= 2.1.0\)' [\#116](https://github.com/dev-sec/ansible-os-hardening/issues/116)
- The task sysctl fails when /etc/initramfs-tools is not present [\#111](https://github.com/dev-sec/ansible-os-hardening/issues/111)
- Deprecation warning always\_run [\#103](https://github.com/dev-sec/ansible-os-hardening/issues/103)
**Closed issues:**
- Enhancement: Pin python dependencies for development and testing [\#127](https://github.com/dev-sec/ansible-os-hardening/issues/127)
- Update readme to include baselines [\#122](https://github.com/dev-sec/ansible-os-hardening/issues/122)
**Merged pull requests:**
- Converts set to JSON-serializable list [\#126](https://github.com/dev-sec/ansible-os-hardening/pull/126) ([pestaa](https://github.com/pestaa))
- add more sysctl settings, allow overwriting [\#120](https://github.com/dev-sec/ansible-os-hardening/pull/120) ([rndmh3ro](https://github.com/rndmh3ro))
## [4.0.0](https://github.com/dev-sec/ansible-os-hardening/tree/4.0.0) (2017-03-14)
[Full Changelog](https://github.com/dev-sec/ansible-os-hardening/compare/3.2.0...4.0.0)
**Implemented enhancements:**
- Description of the Ansible roles of dev-sec says "This Ansible playbook" [\#97](https://github.com/dev-sec/ansible-os-hardening/issues/97)
- install initramfs-tools [\#114](https://github.com/dev-sec/ansible-os-hardening/pull/114) ([rndmh3ro](https://github.com/rndmh3ro))
- omit empty variables [\#106](https://github.com/dev-sec/ansible-os-hardening/pull/106) ([rndmh3ro](https://github.com/rndmh3ro))
**Fixed bugs:**
- The role fails when conditionally included [\#105](https://github.com/dev-sec/ansible-os-hardening/issues/105)
- omit empty variables [\#106](https://github.com/dev-sec/ansible-os-hardening/pull/106) ([rndmh3ro](https://github.com/rndmh3ro))
**Closed issues:**
- Error running on RHEL 7 due to syntax issues [\#112](https://github.com/dev-sec/ansible-os-hardening/issues/112)
- disable password age [\#109](https://github.com/dev-sec/ansible-os-hardening/issues/109)
**Merged pull requests:**
- change shadow owner in debian systems [\#117](https://github.com/dev-sec/ansible-os-hardening/pull/117) ([rndmh3ro](https://github.com/rndmh3ro))
- Rhel7 [\#113](https://github.com/dev-sec/ansible-os-hardening/pull/113) ([tyrken](https://github.com/tyrken))
- use new Docker images [\#110](https://github.com/dev-sec/ansible-os-hardening/pull/110) ([rndmh3ro](https://github.com/rndmh3ro))
- Dont refer to this role as "playbook" in the role description [\#104](https://github.com/dev-sec/ansible-os-hardening/pull/104) ([ypid](https://github.com/ypid))
## [3.2.0](https://github.com/dev-sec/ansible-os-hardening/tree/3.2.0) (2016-10-24)
[Full Changelog](https://github.com/dev-sec/ansible-os-hardening/compare/3.1.0...3.2.0)

View File

@ -6,7 +6,7 @@
## Description
This roles provides numerous security-related configurations, providing all-round base protection.
This role provides numerous security-related configurations, providing all-round base protection. It is intended to be compliant with the [DevSec Linux Baseline](https://github.com/dev-sec/linux-baseline).
It configures:
@ -16,9 +16,10 @@ It configures:
* Shadow password suite configuration
* Configures system path permissions
* Disable core dumps via soft limits
* Restrict Root Logins to System Console
* Restrict root Logins to System Console
* Set SUIDs
* Configures kernel parameters via sysctl
* Install and configure auditd
It will not:
@ -27,7 +28,12 @@ It will not:
## Requirements
* Ansible 2.2.1
* Ansible 2.5.0
## Warning
If you're using inspec to test your machines after applying this role, please make sure to add the connecting user to the `os_ignore_users`-variable.
Otherwise inspec will fail. For more information, see [issue #124](https://github.com/dev-sec/ansible-os-hardening/issues/124).
## Variables
@ -46,7 +52,6 @@ It will not:
| `os_auth_pam_passwdqc_options`| "min=disabled,disabled,16,12,8" | set to any option line (as a string) that you want to pass to passwdqc|
| `os_security_users_allow`| [] | list of things, that a user is allowed to do. May contain `change_user`.
| `os_security_kernel_enable_module_loading`| true | true if you want to allowed to change kernel modules once the system is running (eg `modprobe`, `rmmod`)|
| `os_security_kernel_enable_sysrq`| false | sysrq is a 'magical' key combo you can hit which the kernel will respond to regardless of whatever else it is doing, unless it is completely locked up. |
| `os_security_kernel_enable_core_dump`| false | kernel is crashing or otherwise misbehaving and a kernel core dump is created |
| `os_security_suid_sgid_enforce`| true | true if you want to reduce SUID/SGID bits. There is already a list of items which are searched for configured, but you can also add your own|
| `os_security_suid_sgid_blacklist`| [] | a list of paths which should have their SUID/SGID bits removed|
@ -57,7 +62,8 @@ It will not:
| `ufw_ipt_sysctl` | '' | by default it disables IPT_SYSCTL in /etc/default/ufw. If you want to overwrite /etc/sysctl.conf values using ufw - set it to your sysctl dictionary, for example `/etc/ufw/sysctl.conf`
| `ufw_default_input_policy` | DROP | set default input policy of ufw to `DROP` |
| `ufw_default_output_policy` | ACCEPT | set default output policy of ufw to `ACCEPT` |
| `ufw_default_forward_policy` | DROP| set default forward policy of ufw to `DROP` |
| `ufw_default_forward_policy` | DROP | set default forward policy of ufw to `DROP` |
| `os_auditd_enabled` | true | Set to false to disable installing and configuring auditd. |
## Packages
@ -69,68 +75,44 @@ We remove the following packages:
* ypserv ([NSA](http://www.nsa.gov/ia/_files/os/redhat/rhel5-guide-i731.pdf), Chapter 3.2.4)
* telnet-server ([NSA](http://www.nsa.gov/ia/_files/os/redhat/rhel5-guide-i731.pdf), Chapter 3.2.2)
* rsh-server ([NSA](http://www.nsa.gov/ia/_files/os/redhat/rhel5-guide-i731.pdf), Chapter 3.2.3)
* prelink ([open-scap](https://static.open-scap.org/ssg-guides/ssg-sl7-guide-ospp-rhel7-server.html#xccdf_org.ssgproject.content_rule_disable_prelink))
## Disabled filesystems
We disable the following filesystems, because they're most likely not used:
* "cramfs"
* "freevxfs"
* "jffs2"
* "hfs"
* "hfsplus"
* "squashfs"
* "udf"
* "vfat" # only if uefi is not in use
To prevent some of the filesystems from being disabled, add them to the `os_filesystem_whitelist` variable.
## Example Playbook
- hosts: localhost
roles:
- dev-sec.os-hardening
```yaml
- hosts: localhost
roles:
- dev-sec.os-hardening
```
## Changing sysctl variables
If you want to overwrite sysctl-variables, you have to overwrite the *whole* dict, or else only the single overwritten will be actually used.
So for example if you want to change the IPv4 traffic forwarding variable to `1`, you must pass the whole dict like this:
If you want to override sysctl-variables, you can use the `sysctl_overwrite` variable (in older versions you had to override the whole `sysctl_dict`).
So for example if you want to change the IPv4 traffic forwarding variable to `1`, do it like this:
```
- hosts: localhost
roles:
- dev-sec.os-hardening
vars:
sysctl_config:
# Disable IPv4 traffic forwarding.
net.ipv4.ip_forward: 1
# Disable IPv6 traffic forwarding.
net.ipv6.conf.all.forwarding: 0
# ignore RAs on Ipv6.
net.ipv6.conf.all.accept_ra: 0
net.ipv6.conf.default.accept_ra: 0
# Enable RFC-recommended source validation feature.
net.ipv4.conf.all.rp_filter: 1
net.ipv4.conf.default.rp_filter: 1
# Reduce the surface on SMURF attacks.
# Make sure to ignore ECHO broadcasts, which are only required in broad network analysis.
net.ipv4.icmp_echo_ignore_broadcasts: 1
# There is no reason to accept bogus error responses from ICMP, so ignore them instead.
net.ipv4.icmp_ignore_bogus_error_responses: 1
# Limit the amount of traffic the system uses for ICMP.
net.ipv4.icmp_ratelimit: 100
# Adjust the ICMP ratelimit to include ping, dst unreachable,
# source quench, ime exceed, param problem, timestamp reply, information reply
net.ipv4.icmp_ratemask: 88089
# Disable IPv6
net.ipv6.conf.all.disable_ipv6: 1
# Protect against wrapping sequence numbers at gigabit speeds
net.ipv4.tcp_timestamps: 0
# Define restriction level for announcing the local source IP
net.ipv4.conf.all.arp_ignore: 1
# Define mode for sending replies in response to
# received ARP requests that resolve local target IP addresses
net.ipv4.conf.all.arp_announce: 2
# RFC 1337 fix F1
net.ipv4.tcp_rfc1337: 1
```yaml
- hosts: localhost
roles:
- dev-sec.os-hardening
vars:
sysctl_overwrite:
# Enable IPv4 traffic forwarding.
net.ipv4.ip_forward: 1
```
Alternatively you can change Ansible's [hash-behaviour](https://docs.ansible.com/ansible/intro_configuration.html#hash-behaviour) to `merge`, then you only have to overwrite the single hash you need to. But please be aware that changing the hash-behaviour changes it for all your playbooks and is not recommended by Ansible.
@ -152,27 +134,27 @@ bundle install
### Testing with Docker
```
# fast test on one machine
bundle exec kitchen test default-ubuntu-1204
bundle exec kitchen test default-ubuntu-1404
# test on all machines
bundle exec kitchen test
# for development
bundle exec kitchen create default-ubuntu-1204
bundle exec kitchen converge default-ubuntu-1204
bundle exec kitchen create default-ubuntu-1404
bundle exec kitchen converge default-ubuntu-1404
```
### Testing with Virtualbox
```
# fast test on one machine
KITCHEN_YAML=".kitchen.vagrant.yml" bundle exec kitchen test default-ubuntu-1204
KITCHEN_YAML=".kitchen.vagrant.yml" bundle exec kitchen test default-ubuntu-1404
# test on all machines
KITCHEN_YAML=".kitchen.vagrant.yml" bundle exec kitchen test
# for development
KITCHEN_YAML=".kitchen.vagrant.yml" bundle exec kitchen create default-ubuntu-1204
KITCHEN_YAML=".kitchen.vagrant.yml" bundle exec kitchen converge default-ubuntu-1204
KITCHEN_YAML=".kitchen.vagrant.yml" bundle exec kitchen create default-ubuntu-1404
KITCHEN_YAML=".kitchen.vagrant.yml" bundle exec kitchen converge default-ubuntu-1404
```
For more information see [test-kitchen](http://kitchen.ci/docs/getting-started)
@ -185,7 +167,7 @@ This role is mostly based on guides by:
* [Arch Linux wiki, Sysctl hardening](https://wiki.archlinux.org/index.php/Sysctl)
* [NSA: Guide to the Secure Configuration of Red Hat Enterprise Linux 5](http://www.nsa.gov/ia/_files/os/redhat/rhel5-guide-i731.pdf)
* [Ubuntu Security/Features](https://wiki.ubuntu.com/Security/Features)
* [Deutsche Telekom, Group IT Security, Security Requirements (German)](http://www.telekom.com/static/-/155996/7/technische-sicherheitsanforderungen-si)
* [Deutsche Telekom, Group IT Security, Security Requirements (German)](https://www.telekom.com/psa)
Thanks to all of you!
## Contributing
@ -194,7 +176,7 @@ See [contributor guideline](CONTRIBUTING.md).
## License and Author
* Author:: Sebastian Gumprich <sebastian.gumprich@38.de>
* Author:: Sebastian Gumprich
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

View File

@ -8,8 +8,9 @@
# finds first
[defaults]
ansible_managed = Ansible managed: {file} modified on %Y-%m-%d by {uid} on {host}
ansible_managed = Ansible managed: {file} modified by {uid} on {host}
# additional paths to search for roles in, colon separated
roles_path = ../
[ssh_connection]
scp_if_ssh = True

View File

@ -3,6 +3,15 @@
hosts: localhost
roles:
- ansible-os-hardening
pre_tasks:
- name: Run the equivalent of "apt-get update" as a separate step
apt:
update_cache: yes
when: ansible_os_family == 'Debian'
- name: Install firefox to get Xorg
package:
name: firefox
state: present
vars:
os_security_users_allow: change_user
os_security_kernel_enable_core_dump: false
@ -13,8 +22,53 @@
os_auth_allow_homeless: true
os_security_suid_sgid_blacklist: ['/bin/umount']
os_security_suid_sgid_whitelist: ['/usr/bin/rlogin']
os_filesystem_whitelist: ['vfat']
sysctl_config:
net.ipv4.ip_forward: 0
net.ipv6.conf.all.forwarding: 0
net.ipv6.conf.all.accept_ra: 0
net.ipv6.conf.default.accept_ra: 0
net.ipv4.conf.all.rp_filter: 1
net.ipv4.conf.default.rp_filter: 1
net.ipv4.icmp_echo_ignore_broadcasts: 1
net.ipv4.icmp_ignore_bogus_error_responses: 1
net.ipv4.icmp_ratelimit: 100
net.ipv4.icmp_ratemask: 88089
net.ipv6.conf.all.disable_ipv6: 1
net.ipv4.conf.all.arp_ignore: 1
net.ipv4.conf.all.arp_announce: 2
net.ipv4.conf.all.shared_media: 1
net.ipv4.conf.default.shared_media: 1
net.ipv4.conf.all.accept_source_route: 0
net.ipv4.conf.default.accept_source_route: 0
net.ipv4.conf.default.accept_redirects: 0
net.ipv4.conf.all.accept_redirects: 0
net.ipv4.conf.all.secure_redirects: 0
net.ipv4.conf.default.secure_redirects: 0
net.ipv6.conf.default.accept_redirects: 0
net.ipv6.conf.all.accept_redirects: 0
net.ipv4.conf.all.send_redirects: 0
net.ipv4.conf.default.send_redirects: 0
net.ipv4.conf.all.log_martians: 1
net.ipv6.conf.default.router_solicitations: 0
net.ipv6.conf.default.accept_ra_rtr_pref: 0
net.ipv6.conf.default.accept_ra_pinfo: 0
net.ipv6.conf.default.accept_ra_defrtr: 0
net.ipv6.conf.default.autoconf: 0
net.ipv6.conf.default.dad_transmits: 0
net.ipv6.conf.default.max_addresses: 1
kernel.sysrq: 0
fs.suid_dumpable: 0
kernel.randomize_va_space: 2
- name: wrapper playbook for kitchen testing "ansible-os-hardening"
hosts: localhost
pre_tasks:
- name: Run the equivalent of "apt-get update" as a separate step
apt:
update_cache: yes
when: ansible_os_family == 'Debian'
roles:
- ansible-os-hardening

View File

@ -1,6 +1,5 @@
os_desktop_enable: false
os_env_extra_user_paths: []
os_env_umask: '027'
os_auth_pw_max_age: 60
os_auth_pw_min_age: 7 # discourage password cycling
os_auth_retries: 5
@ -11,18 +10,12 @@ os_auth_pam_passwdqc_enable: true
os_auth_pam_passwdqc_options: 'min=disabled,disabled,16,12,8' # used in RHEL6
os_auth_pam_pwquality_options: 'try_first_pass retry=3 type=' # used in RHEL7
os_auth_root_ttys: [console, tty1, tty2, tty3, tty4, tty5, tty6]
os_auth_uid_min: 1000
os_auth_gid_min: 1000
os_auth_sys_uid_min: 100
os_auth_sys_uid_max: 999
os_auth_sys_gid_min: 100
os_auth_sys_gid_max: 999
os_chfn_restrict: ''
# may contain: change_user
os_security_users_allow: []
# specify system accounts those login should not be disabled and password not changed
os_ignore_users: ['vagrant']
os_ignore_users: ['vagrant', 'kitchen']
os_security_kernel_enable_module_loading: true
os_security_kernel_enable_core_dump: false
os_security_suid_sgid_enforce: true
@ -34,7 +27,7 @@ os_security_suid_sgid_remove_from_unknown: false
# remove packages with known issues
os_security_packages_clean: true
os_security_packages_list: ['xinetd','inetd','ypserv','telnet-server','rsh-server','rsync']
os_security_packages_list: ['xinetd','inetd','ypserv','telnet-server','rsh-server', 'prelink']
# Allow interactive startup (rhel, centos)
os_security_init_prompt: true
@ -58,61 +51,202 @@ ufw_default_application_policy: 'SKIP'
ufw_manage_builtins: 'no'
ufw_ipt_modules: 'nf_conntrack_ftp nf_nat_ftp nf_conntrack_netbios_ns'
# CAUTION
# If you want to overwrite sysctl-variables,
# you have to overwrite the *whole* dict, or else only the single overwritten will be actually used.
sysctl_config:
# Disable IPv4 traffic forwarding.
# Disable IPv4 traffic forwarding. | sysctl-01
net.ipv4.ip_forward: 0
# Disable IPv6 traffic forwarding.
# Disable IPv6 traffic forwarding. | sysctl-19
net.ipv6.conf.all.forwarding: 0
# ignore RAs on Ipv6.
# ignore RAs on Ipv6. | sysctl-25
net.ipv6.conf.all.accept_ra: 0
net.ipv6.conf.default.accept_ra: 0
# Enable RFC-recommended source validation feature.
# Enable RFC-recommended source validation feature. | sysctl-02
net.ipv4.conf.all.rp_filter: 1
net.ipv4.conf.default.rp_filter: 1
# Reduce the surface on SMURF attacks.
# Reduce the surface on SMURF attacks. | sysctl-04
# Make sure to ignore ECHO broadcasts, which are only required in broad network analysis.
net.ipv4.icmp_echo_ignore_broadcasts: 1
# There is no reason to accept bogus error responses from ICMP, so ignore them instead.
# There is no reason to accept bogus error responses from ICMP, so ignore them instead. | sysctl-03
net.ipv4.icmp_ignore_bogus_error_responses: 1
# Limit the amount of traffic the system uses for ICMP.
# Limit the amount of traffic the system uses for ICMP. | sysctl-05
net.ipv4.icmp_ratelimit: 100
# Adjust the ICMP ratelimit to include ping, dst unreachable,
# source quench, ime exceed, param problem, timestamp reply, information reply
# source quench, ime exceed, param problem, timestamp reply, information reply | sysctl-06
net.ipv4.icmp_ratemask: 88089
# Disable IPv6
# Disable IPv6 | sysctl-18
net.ipv6.conf.all.disable_ipv6: 1
# Protect against wrapping sequence numbers at gigabit speeds
# Protect against wrapping sequence numbers at gigabit speeds | sysctl-07
net.ipv4.tcp_timestamps: 0
# Define restriction level for announcing the local source IP
# Define restriction level for announcing the local source IP | sysctl-08
net.ipv4.conf.all.arp_ignore: 1
# Define mode for sending replies in response to
# received ARP requests that resolve local target IP addresses
# received ARP requests that resolve local target IP addresses | sysctl-09
net.ipv4.conf.all.arp_announce: 2
# RFC 1337 fix F1
# RFC 1337 fix F1 | sysctl-10
net.ipv4.tcp_rfc1337: 1
# CAUTION
# If you want to overwrite sysctl-variables,
# you have to overwrite the *whole* dict, or else only the single overwritten will be actually used.
# Send(router) or accept(host) RFC1620 shared media redirects | sysctl-12
net.ipv4.conf.all.shared_media: 1
net.ipv4.conf.default.shared_media: 1
sysctl_rhel_config:
# ExecShield protection against buffer overflows
kernel.exec-shield: 1
# Syncookies is used to prevent SYN-flooding attacks.
net.ipv4.tcp_syncookies: 1
# Accepting source route can lead to malicious networking behavior,
# so disable it if not needed. | sysctl-13
net.ipv4.conf.all.accept_source_route: 0
net.ipv4.conf.default.accept_source_route: 0
# Accepting redirects can lead to malicious networking behavior, so disable
# it if not needed. | sysctl-13 | sysctl-14 | sysctl-15 | sysctl-20
net.ipv4.conf.default.accept_redirects: 0
net.ipv4.conf.all.accept_redirects: 0
net.ipv4.conf.all.secure_redirects: 0
net.ipv4.conf.default.secure_redirects: 0
net.ipv6.conf.default.accept_redirects: 0
net.ipv6.conf.all.accept_redirects: 0
# For non-routers: don't send redirects, these settings are 0 | sysctl-16
net.ipv4.conf.all.send_redirects: 0
net.ipv4.conf.default.send_redirects: 0
# log martian packets | sysctl-17
net.ipv4.conf.all.log_martians: 1
net.ipv4.conf.default.log_martians: 1
# ipv6 config
# Disable acceptance of IPv6 router solicitations messages | sysctl-21
net.ipv6.conf.default.router_solicitations: 0
# Disable Accept Router Preference from router advertisement | sysctl-22
net.ipv6.conf.default.accept_ra_rtr_pref: 0
# Disable learning Prefix Information from router advertisement | sysctl-23
net.ipv6.conf.default.accept_ra_pinfo: 0
# Disable learning Hop limit from router advertisement | sysctl-24
net.ipv6.conf.default.accept_ra_defrtr: 0
# Disable IPv6 autoconfiguration | sysctl-26
net.ipv6.conf.default.autoconf: 0
# Disable neighbor solicitations to send out per address | sysctl-27
net.ipv6.conf.default.dad_transmits: 0
# Assign one global unicast IPv6 addresses to each interface | sysctl-28
net.ipv6.conf.default.max_addresses: 1
# This settings controls how the kernel behaves towards module changes at
# runtime. Setting to 1 will disable module loading at runtime.
# Setting it to 0 is actually never supported. | sysctl-29
# kernel.modules_disabled: 1
# Magic Sysrq should be disabled, but can also be set to a safe value if so
# desired for physical machines. It can allow a safe reboot if the system hangs
# and is a 'cleaner' alternative to hitting the reset button. | sysctl-30
# The following values are permitted:
# * **0** - disable sysrq
# * **1** - enable sysrq completely
# * **>1** - bitmask of enabled sysrq functions:
# * **2** - control of console logging level
# * **4** - control of keyboard (SAK, unraw)
# * **8** - debugging dumps of processes etc.
# * **16** - sync command
# * **32** - remount read-only
# * **64** - signalling of processes (term, kill, oom-kill)
# * **128** - reboot/poweroff
# * **256** - nicing of all RT tasks
kernel.sysrq: 0
# Prevent core dumps with SUID. These are usually only
# needed by developers and may contain sensitive information. | sysctl-31
fs.suid_dumpable: 0
# Virtual memory regions protection | sysctl-32
kernel.randomize_va_space: 2
kernel.core_uses_pid: 1
# When an attacker is trying to exploit the local kernel, it is often
# helpful to be able to examine where in memory the kernel, modules,
# and data structures live. As such, kernel addresses should be treated
# as sensitive information.
#
# Many files and interfaces contain these addresses (e.g. /proc/kallsyms,
# /proc/modules, etc), and this setting can censor the addresses. A value
# of "0" allows all users to see the kernel addresses. A value of "1"
# limits visibility to the root user, and "2" blocks even the root user.
kernel.kptr_restrict: 1
# The PTRACE system is used for debugging. With it, a single user process
# can attach to any other dumpable process owned by the same user. In the
# case of malicious software, it is possible to use PTRACE to access
# credentials that exist in memory (re-using existing SSH connections,
# extracting GPG agent information, etc).
#
# A PTRACE scope of "0" is the more permissive mode. A scope of "1" limits
# PTRACE only to direct child processes (e.g. "gdb name-of-program" and
# "strace -f name-of-program" work, but gdb's "attach" and "strace -fp $PID"
# do not). The PTRACE scope is ignored when a user has CAP_SYS_PTRACE, so
# "sudo strace -fp $PID" will work as before. For more details see:
# https://wiki.ubuntu.com/SecurityTeam/Roadmap/KernelHardening#ptrace
#
# For applications launching crash handlers that need PTRACE, exceptions can
# be registered by the debugee by declaring in the segfault handler
# specifically which process will be using PTRACE on the debugee:
# prctl(PR_SET_PTRACER, debugger_pid, 0, 0, 0);
#
# In general, PTRACE is not needed for the average running Ubuntu system.
# To that end, the default is to set the PTRACE scope to "1". This value
# may not be appropriate for developers or servers with only admin accounts.
# kernel.yama.ptrace_scope = 1
kernel.yama.ptrace_scope: 1
# Protect the zero page of memory from userspace mmap to prevent kernel
# NULL-dereference attacks against potential future kernel security
# vulnerabilities. (Added in kernel 2.6.23.)
#
# While this default is built into the Ubuntu kernel, there is no way to
# restore the kernel default if the value is changed during runtime; for
# example via package removal (e.g. wine, dosemu). Therefore, this value
# is reset to the secure default each time the sysctl values are loaded.
vm.mmap_min_addr: 65536
# These settings eliminate an entire class of security vulnerability:
# time-of-check-time-of-use cross-privilege attacks using guessable
# filenames (generally seen as "/tmp file race" vulnerabilities).
fs.protected_hardlinks: 1
fs.protected_symlinks: 1
# Do not delete the following line or otherwise the playbook will fail
# at task 'create a combined sysctl-dict if overwrites are defined'
sysctl_overwrite:
# disable unused filesystems
os_unused_filesystems:
- "cramfs"
- "freevxfs"
- "jffs2"
- "hfs"
- "hfsplus"
- "squashfs"
- "udf"
- "vfat"
# whitelist for used filesystems
os_filesystem_whitelist: []
# Set to false to turn the role into a no-op. Useful when using
# the Ansible role dependency mechanism.
os_hardening_enabled: true
# Set to false to disable installing and configuring auditd.
os_auditd_enabled: true

View File

@ -1 +1 @@
{install_date: 'Sun Apr 23 07:59:14 2017', version: 4.0.0}
{install_date: 'Mon Dec 17 12:48:33 2018', version: 5.1.0}

View File

@ -4,7 +4,7 @@ galaxy_info:
description: 'This Ansible role provides numerous security-related configurations, providing all-round base protection.'
company: Hardening Framework Team
license: Apache License 2.0
min_ansible_version: '2.2.1'
min_ansible_version: '2.5'
platforms:
- name: EL
versions:
@ -15,10 +15,12 @@ galaxy_info:
- precise
- trusty
- xenial
- bionic
- name: Debian
versions:
- wheezy
- jessie
- name: Amazon
galaxy_tags:
- system
- security

View File

@ -1,6 +1,8 @@
---
- name: remove packages
apt: name='{{item}}' state=removed
- name: remove deprecated or insecure packages | package-01 - package-09
apt:
name: '{{ item }}'
state: 'absent'
with_items:
- "{{os_security_packages_list}}"
when: os_security_packages_clean
- '{{ os_security_packages_list }}'
when: 'os_security_packages_clean'

View File

@ -0,0 +1,14 @@
---
- name: install auditd package | package-08
package:
name: '{{ auditd_package }}'
state: 'present'
- name: configure auditd | package-08
template:
src: 'etc/audit/auditd.conf.j2'
dest: '/etc/audit/auditd.conf'
owner: 'root'
group: 'root'
mode: '0640'

View File

@ -0,0 +1,12 @@
- name: find directories for minimizing access
find:
paths: '{{ outer_item }}'
recurse: yes
register: minimize_access_directories
- name: minimize access on found files
file:
path: '{{ item.path }}'
mode: 'go-w'
state: file
with_items: '{{ minimize_access_directories.files }}'

View File

@ -0,0 +1,60 @@
---
- name: Set OS family dependent variables
include_vars: '{{ ansible_os_family }}.yml'
tags: always
- name: Set OS dependent variables
include_vars: '{{ item }}'
with_first_found:
- files:
- '{{ ansible_distribution }}-{{ ansible_distribution_major_version }}.yml'
- '{{ ansible_distribution }}.yml'
- '{{ ansible_os_family }}-{{ ansible_distribution_major_version }}.yml'
skip: true
tags: always
- import_tasks: auditd.yml
tags: auditd
when: os_auditd_enabled
- import_tasks: limits.yml
tags: limits
- import_tasks: login_defs.yml
tags: login_defs
- import_tasks: minimize_access.yml
tags: minimize_access
- import_tasks: pam.yml
tags: pam
- import_tasks: modprobe.yml
tags: modprobe
- import_tasks: profile.yml
tags: profile
- import_tasks: securetty.yml
tags: securetty
- import_tasks: suid_sgid.yml
when: os_security_suid_sgid_enforce
tags: suid_sgid
- import_tasks: sysctl.yml
tags: sysctl
- import_tasks: user_accounts.yml
tags: user_accounts
- import_tasks: rhosts.yml
tags: rhosts
- import_tasks: yum.yml
when: ansible_os_family == 'RedHat'
tags: yum
- import_tasks: apt.yml
when: ansible_distribution == 'Debian' or ansible_distribution == 'Ubuntu'
tags: apt

View File

@ -1,9 +1,34 @@
---
- name: create limits.d-directory if it does not exist
file: path='/etc/security/limits.d' owner=root group=root mode=0755 state=directory
when: os_security_kernel_enable_core_dump
- block:
- name: create limits.d-directory if it does not exist | sysctl-31a, sysctl-31b
file:
path: '/etc/security/limits.d'
owner: 'root'
group: 'root'
mode: '0755'
state: 'directory'
- name: create sane limits.conf
template: src='limits.conf.j2' dest='/etc/security/limits.d/10.hardcore.conf' owner=root group=root mode=0440
when: os_security_kernel_enable_core_dump
- name: create aditional limits config file -> 10.hardcore.conf | sysctl-31a, sysctl-31b
pam_limits:
dest: '/etc/security/limits.d/10.hardcore.conf'
domain: '*'
limit_type: hard
limit_item: core
value: 0
comment: Prevent core dumps for all users. These are usually only needed by developers and may contain sensitive information
- name: set 10.hardcore.conf perms to 0400 and root ownership
file:
path: /etc/security/limits.d/10.hardcore.conf
owner: 'root'
group: 'root'
mode: '0440'
when: 'not os_security_kernel_enable_core_dump'
- name: remove 10.hardcore.conf config file
file:
path: /etc/security/limits.d/10.hardcore.conf
state: absent
when: 'os_security_kernel_enable_core_dump'

View File

@ -1,4 +1,9 @@
---
- name: create login.defs
template: src='login.defs.j2' dest='/etc/login.defs' owner=root group=root mode=0444
- name: create login.defs | os-05, os-05b
template:
src: 'etc/login.defs.j2'
dest: '/etc/login.defs'
owner: 'root'
group: 'root'
mode: '0444'

View File

@ -1,43 +1,4 @@
---
- name: add the OS specific variables
include_vars: "{{ ansible_os_family }}.yml"
tags: always
- include: limits.yml
tags: limits
- include: login_defs.yml
tags: login_defs
- include: minimize_access.yml
tags: minimize_acces
- include: pam.yml
tags: pam
- include: profile.yml
tags: profile
- include: securetty.yml
tags: securetty
- include: suid_sgid.yml
when: os_security_suid_sgid_enforce
tags: suid_sgid
- include: sysctl.yml
tags: sysctl
- include: user_accounts.yml
tags: user_accounts
- include: rhosts.yml
tags: rhosts
- include: yum.yml
when: ansible_os_family == 'RedHat'
tags: yum
- include: apt.yml
when: ansible_distribution == 'Debian' or ansible_distribution == 'Ubuntu'
tags: apt
- include_tasks: hardening.yml
when: os_hardening_enabled

View File

@ -1,26 +1,35 @@
---
# Using a two-pass approach for checking directories in order to support symlinks.
- name: find directories for minimizing access
stat:
path: "{{ item }}"
register: minimize_access_directories
with_items:
- include_tasks: find_files.yml
loop_control:
loop_var: outer_item
loop:
- '/usr/local/sbin'
- '/usr/local/bin'
- '/usr/sbin'
- '/usr/bin'
- '/sbin'
- '/bin'
- '{{os_env_extra_user_paths}}'
- '{{ os_env_extra_user_paths }}'
- name: minimize access
file: path='{{item.stat.path}}' mode='go-w' recurse=yes
when: item.stat.isdir
with_items: "{{ minimize_access_directories.results }}"
- name: change shadow ownership to root and mode to 0600 | os-02
file:
dest: '/etc/shadow'
owner: '{{ os_shadow_perms.owner }}'
group: '{{ os_shadow_perms.group }}'
mode: '{{ os_shadow_perms.mode }}'
- name: change shadow ownership to root and mode to 0600 | DTAG SEC Req 3.21-7
file: dest='/etc/shadow' owner={{ os_shadow_perms.owner }} group={{ os_shadow_perms.group }} mode={{ os_shadow_perms.mode }}
- name: change passwd ownership to root and mode to 0644 | os-03
file:
dest: '/etc/passwd'
owner: '{{ os_passwd_perms.owner }}'
group: '{{ os_passwd_perms.group }}'
mode: '{{ os_passwd_perms.mode }}'
- name: change su-binary to only be accessible to user and group root
file: dest='/bin/su' owner=root group=root mode=0750
when: os_security_users_allow != None
file:
dest: '/bin/su'
owner: 'root'
group: 'root'
mode: '0750'
when: '"change_user" not in os_security_users_allow'

View File

@ -0,0 +1,24 @@
---
- name: install modprobe to disable filesystems | os-10
package:
name: '{{modprobe_package}}'
state: 'present'
- name: check if efi is installed
stat:
path: "/sys/firmware/efi"
register: efi_installed
- name: remove vfat from fs-list if efi is used
set_fact:
os_unused_filesystems: "{{ os_unused_filesystems | difference('vfat') }}"
when: efi_installed.stat.isdir is defined and efi_installed.stat.isdir
- name: disable unused filesystems | os-10
template:
src: 'etc/modprobe.d/modprobe.j2'
dest: '/etc/modprobe.d/dev-sec.conf'
owner: 'root'
group: 'root'
mode: '0640'

View File

@ -6,56 +6,94 @@
environment:
DEBIAN_FRONTEND: noninteractive
- name: remove pam ccreds on Debian systems
apt: name='{{os_packages_pam_ccreds}}' state=absent
when: ansible_distribution == 'Debian' or ansible_distribution == 'Ubuntu'
- name: remove pam ccreds on Redhat systems
yum: name='{{os_packages_pam_ccreds}}' state=absent
when: ansible_os_family == 'RedHat'
# the reason for this is so a user cannot connect to a server,
# that isn't connected to an LDAP server anymore.
# normally caching credentials shouldn't be necessary for most machines.
# removing it provides some more security while not removing usability.
- name: remove pam ccreds to disable password caching
package:
name: '{{ os_packages_pam_ccreds }}'
state: 'absent'
- name: remove pam_cracklib, because it does not play nice with passwdqc
apt: name='{{os_packages_pam_cracklib}}' state=absent
apt:
name: '{{ os_packages_pam_cracklib }}'
state: 'absent'
when: (ansible_distribution == 'Debian' or ansible_distribution == 'Ubuntu') and os_auth_pam_passwdqc_enable
- name: install the package for strong password checking
apt: name='{{os_packages_pam_passwdqc}}' state='installed' update_cache='yes'
apt:
name: '{{ os_packages_pam_passwdqc }}'
state: 'present'
update_cache: 'yes'
when: (ansible_distribution == 'Debian' or ansible_distribution == 'Ubuntu') and os_auth_pam_passwdqc_enable
- name: configure passwdqc
template: src='pam_passwdqd.j2' mode=0640 owner=root group=root dest='{{passwdqc_path}}'
template:
src: 'usr/share/pam-configs/pam_passwdqd.j2'
dest: '{{ passwdqc_path }}'
mode: '0644'
owner: 'root'
group: 'root'
when: (ansible_distribution == 'Debian' or ansible_distribution == 'Ubuntu') and os_auth_pam_passwdqc_enable
- name: remove passwdqc
apt: name='{{os_packages_pam_passwdqc}}' state='absent'
apt:
name: '{{ os_packages_pam_passwdqc }}'
state: 'absent'
when: (ansible_distribution == 'Debian' or ansible_distribution == 'Ubuntu') and not os_auth_pam_passwdqc_enable
- name: install tally2
apt: name='libpam-modules' state='installed'
apt:
name: 'libpam-modules'
state: 'present'
when: (ansible_distribution == 'Debian' or ansible_distribution == 'Ubuntu') and not os_auth_pam_passwdqc_enable and os_auth_retries > 0
- name: configure tally2
template: src='pam_tally2.j2' dest='{{tally2_path}}' mode=0640 owner=root group=root
template:
src: 'usr/share/pam-configs/pam_tally2.j2'
dest: '{{ tally2_path }}'
mode: '0644'
owner: 'root'
group: 'root'
when: (ansible_distribution == 'Debian' or ansible_distribution == 'Ubuntu') and not os_auth_pam_passwdqc_enable and os_auth_retries > 0
- name: delete tally2 when retries is 0
file: path='{{tally2_path}}' state=absent
file:
path: '{{ tally2_path }}'
state: 'absent'
when: (ansible_distribution == 'Debian' or ansible_distribution == 'Ubuntu') and not os_auth_pam_passwdqc_enable and os_auth_retries == 0
- name: remove pam_cracklib, because it does not play nice with passwdqc
yum: name='{{os_packages_pam_cracklib}}' state='absent'
when: (ansible_os_family == 'RedHat' and ansible_distribution_version < '7') and os_auth_pam_passwdqc_enable
yum:
name: '{{ os_packages_pam_cracklib }}'
state: 'absent'
when: (ansible_os_family == 'RedHat' and ansible_distribution_version < '7' and not ansible_distribution == 'Amazon') and os_auth_pam_passwdqc_enable
- name: install the package for strong password checking
yum: name='{{os_packages_pam_passwdqc}}' state='installed'
when: (ansible_os_family == 'RedHat' and ansible_distribution_version < '7') and os_auth_pam_passwdqc_enable
yum:
name: '{{ os_packages_pam_passwdqc }}'
state: 'present'
when: (ansible_os_family == 'RedHat' and ansible_distribution_version < '7' and not ansible_distribution == 'Amazon') and os_auth_pam_passwdqc_enable
- name: remove passwdqc
yum: name='{{os_packages_pam_passwdqc}}' state='absent'
yum:
name: '{{ os_packages_pam_passwdqc }}'
state: 'absent'
when: ansible_os_family == 'RedHat' and not os_auth_pam_passwdqc_enable
- name: configure passwdqc and tally via central system-auth confic
template: src='rhel_system_auth.j2' dest='/etc/pam.d/system-auth-ac' mode=0640 owner=root group=root
template:
src: 'etc/pam.d/rhel_system_auth.j2'
dest: '/etc/pam.d/system-auth-ac'
mode: '0640'
owner: 'root'
group: 'root'
- name: NSA 2.3.3.5 Upgrade Password Hashing Algorithm to SHA-512
template: src='rhel_libuser.conf.j2' dest='/etc/libuser.conf' mode=0640 owner=root group=root
template:
src: 'etc/rhel_libuser.conf.j2'
dest: '/etc/libuser.conf'
mode: '0640'
owner: 'root'
group: 'root'

View File

@ -1,4 +1,15 @@
---
- name: create profile.conf
template: src='profile.conf.j2' dest='/etc/profile.d/pinerolo_profile.sh' owner=root group=root mode=0750
- name: add pinerolo_profile.sh to profile.d
template:
src: 'etc/profile.d/profile.conf.j2'
dest: '/etc/profile.d/pinerolo_profile.sh'
owner: 'root'
group: 'root'
mode: '0750'
when: not os_security_kernel_enable_core_dump
- name: remove pinerolo_profile.sh from profile.d
file:
path: /etc/profile.d/pinerolo_profile.sh
state: absent
when: os_security_kernel_enable_core_dump

View File

@ -1,13 +1,23 @@
---
- name: Get user accounts | DTAG SEC Req 3.21-4
- name: Get user accounts | os-09
command: "awk -F: '{print $1}' /etc/passwd"
changed_when: False
check_mode: no
check_mode: False
register: users
- name: delete rhosts-files from system | DTAG SEC Req 3.21-4
file: dest='~{{ item }}/.rhosts' state=absent
with_items: '{{ users.stdout_lines | default(omit) }}'
- name: delete rhosts-files from system | os-09
file:
dest: '~{{ item }}/.rhosts'
state: 'absent'
with_flattened: '{{ users.stdout_lines | default([]) }}'
- name: delete hosts.equiv from system | DTAG SEC Req 3.21-4
file: dest='/etc/hosts.equiv' state=absent
- name: delete hosts.equiv from system | os-01
file:
dest: '/etc/hosts.equiv'
state: 'absent'
- name: delete .netrc-files from system | os-09
file:
dest: '~{{ item }}/.netrc'
state: 'absent'
with_flattened: '{{ users.stdout_lines | default([]) }}'

View File

@ -1,3 +1,8 @@
---
- name: create securetty
template: src='securetty.j2' dest='/etc/securetty' owner=root group=root mode=0400
template:
src: 'etc/securetty.j2'
dest: '/etc/securetty'
owner: 'root'
group: 'root'
mode: '0400'

View File

@ -1,24 +1,32 @@
---
- name: remove suid/sgid bit from binaries in blacklist
file: path='{{item}}' mode='a-s' state=file follow=yes
- name: remove suid/sgid bit from binaries in blacklist | os-06
file:
path: '{{ item }}'
mode: 'a-s'
state: 'file'
follow: 'yes'
failed_when: false
with_items:
with_flattened:
- '{{ os_security_suid_sgid_system_blacklist }}'
- '{{ os_security_suid_sgid_blacklist }}'
- name: find binaries with suid/sgid set
- name: find binaries with suid/sgid set | os-06
shell: find / -xdev \( -perm -4000 -o -perm -2000 \) -type f ! -path '/proc/*' -print 2>/dev/null
register: sbit_binaries
when: os_security_suid_sgid_remove_from_unknown
changed_when: False
- name: gather files from which to remove suids/sgids and remove system white-listed files
- name: gather files from which to remove suids/sgids and remove system white-listed files | os-06
set_fact:
suid: '{{ sbit_binaries.stdout_lines | difference(os_security_suid_sgid_system_whitelist) }}'
when: os_security_suid_sgid_remove_from_unknown
- name: remove suid/sgid bit from all binaries except in system and user whitelist
file: path='{{item}}' mode='a-s' state=file follow=yes
with_items:
- '{{ suid | default(omit) | difference(os_security_suid_sgid_whitelist) }}'
- name: remove suid/sgid bit from all binaries except in system and user whitelist | os-06
file:
path: '{{ item }}'
mode: 'a-s'
state: 'file'
follow: 'yes'
with_flattened:
- '{{ suid | default([]) | difference(os_security_suid_sgid_whitelist) }}'
when: os_security_suid_sgid_remove_from_unknown

View File

@ -1,17 +1,34 @@
---
- name: protect sysctl.conf
file: path='/etc/sysctl.conf' owner=root group=root mode=0440
file:
path: '/etc/sysctl.conf'
owner: 'root'
group: 'root'
mode: '0440'
- name: NSA 2.2.4.1 Set Daemon umask, do config for rhel-family
template: src='rhel_sysconfig_init.j2' dest='/etc/sysconfig/init' owner=root group=root mode=0544
when: ansible_distribution == 'RedHat' or ansible_distribution == 'Fedora' or ansible_distribution == 'CentOS'
- name: set Daemon umask, do config for rhel-family | NSA 2.2.4.1
template:
src: 'etc/sysconfig/rhel_sysconfig_init.j2'
dest: '/etc/sysconfig/init'
owner: 'root'
group: 'root'
mode: '0544'
when: ansible_distribution == 'RedHat' or ansible_distribution == 'Fedora' or ansible_distribution == 'CentOS' or ansible_distribution == 'Amazon'
- name: install initramfs-tools
apt: name='initramfs-tools' state=installed update_cache=true
apt:
name: 'initramfs-tools'
state: 'present'
update_cache: true
when: ansible_os_family == 'Debian' and os_security_kernel_enable_module_loading
- name: rebuild initramfs with starting pack of modules, if module loading at runtime is disabled
template: src='modules.j2' dest='/etc/initramfs-tools/modules' owner=root group=root mode=0440
template:
src: 'etc/initramfs-tools/modules.j2'
dest: '/etc/initramfs-tools/modules'
owner: 'root'
group: 'root'
mode: '0440'
when: ansible_os_family == 'Debian' and os_security_kernel_enable_module_loading
register: initramfs
@ -19,6 +36,11 @@
command: 'update-initramfs -u'
when: initramfs.changed
- name: create a combined sysctl-dict if overwrites are defined
set_fact:
sysctl_config: '{{ sysctl_config | combine(sysctl_overwrite) }}'
when: sysctl_overwrite | default()
- name: Change various sysctl-settings, look at the sysctl-vars file for documentation
sysctl:
name: '{{ item.key }}'
@ -29,7 +51,7 @@
ignoreerrors: yes
with_dict: '{{ sysctl_config }}'
- name: Change various sysctl-settings on rhel-hosts, look at the sysctl-vars file for documentation
- name: Change various sysctl-settings on rhel6-hosts or older, look at the sysctl-vars file for documentation
sysctl:
name: '{{ item.key }}'
value: '{{ item.value }}'
@ -37,9 +59,11 @@
reload: yes
ignoreerrors: yes
with_dict: '{{ sysctl_rhel_config }}'
when: ansible_distribution == 'RedHat' or ansible_distribution == 'Fedora' or ansible_distribution == 'CentOS'
when: ((ansible_distribution == 'RedHat' or ansible_distribution == 'Fedora' or ansible_distribution == 'CentOS') and ansible_distribution_major_version < '7') or ansible_distribution == 'Amazon'
- name: Apply ufw defaults
template: src="ufw.j2" dest=/etc/default/ufw
template:
src: 'etc/default/ufw.j2'
dest: '/etc/default/ufw'
when: ufw_manage_defaults and (ansible_distribution == 'Debian' or ansible_distribution == 'Ubuntu')
tags: ufw

View File

@ -1,35 +1,45 @@
---
- name: get UID_MIN from login.defs
shell: awk '/^\s*UID_MIN\s*([0-9]*).*?$/ {print $2}' /etc/login.defs removes=/etc/login.defs
shell: awk '/^\s*UID_MIN\s*([0-9]*).*?$/ {print $2}' /etc/login.defs
args:
removes: /etc/login.defs
register: uid_min
check_mode: no
check_mode: False
changed_when: False
- name: calculate UID_MAX from UID_MIN by substracting 1
set_fact: uid_max='{{ uid_min.stdout | int - 1 }}'
set_fact:
uid_max: '{{ uid_min.stdout | int - 1 }}'
when: uid_min is defined
- name: set UID_MAX on Debian-systems if no login.defs exist
set_fact: uid_max='999'
set_fact:
uid_max: '999'
when: ansible_os_family == 'Debian' and not uid_min
- name: set UID_MAX on other systems if no login.defs exist
set_fact: uid_max='499'
set_fact:
uid_max: '499'
when: not uid_min
- name: get all system accounts
command: awk -F'':'' '{ if ( $3 <= {{uid_max|quote}} ) print $1}' /etc/passwd removes=/etc/passwd
command: awk -F'':'' '{ if ( $3 <= {{ uid_max|quote }} ) print $1}' /etc/passwd
args:
removes: /etc/passwd
changed_when: False
check_mode: no
check_mode: False
register: sys_accs
- name: remove always ignored system accounts from list
set_fact:
sys_accs_cond: '{{sys_accs.stdout_lines | difference(os_always_ignore_users) }}'
check_mode: no
sys_accs_cond: '{{ sys_accs.stdout_lines | difference(os_always_ignore_users) }}'
check_mode: False
- name: change system accounts not on the user provided ignore-list
user: name='{{item}}' shell='{{os_nologin_shell_path}}' password='*'
with_items:
- '{{sys_accs_cond | default(omit) | difference(os_ignore_users) }}'
user:
name: '{{ item }}'
shell: '{{ os_nologin_shell_path }}'
password: '*'
createhome: False
with_flattened:
- '{{ sys_accs_cond | default([]) | difference(os_ignore_users) | list }}'

View File

@ -1,6 +1,8 @@
---
- name: remove unused repositories
file: name='/etc/yum.repos.d/{{item}}.repo' state=absent
file:
name: '/etc/yum.repos.d/{{ item }}.repo'
state: 'absent'
with_items:
- 'CentOS-Debuginfo'
- 'CentOS-Media'
@ -13,24 +15,33 @@
register: yum_repos
- name: check if rhnplugin.conf exists
stat: path='/etc/yum/pluginconf.d/rhnplugin.conf'
stat:
path: '/etc/yum/pluginconf.d/rhnplugin.conf'
register: rhnplugin_file
# for the "default([])" see here:
# for the 'default([])' see here:
# https://github.com/dev-sec/ansible-os-hardening/issues/99 and
# https://stackoverflow.com/questions/37067827/ansible-deprecation-warning-for-undefined-variable-despite-when-clause
- name: activate gpg-check for yum-repos
replace: dest='{{item}}' regexp='^\s*gpgcheck=0' replace='gpgcheck=1'
with_items:
replace:
dest: '{{ item }}'
regexp: '^\s*gpgcheck: 0'
replace: 'gpgcheck: 1'
with_flattened:
- '/etc/yum.conf'
- '{{ yum_repos.stdout_lines| default([]) }}'
- name: activate gpg-check for yum rhn if it exists
replace: dest='/etc/yum/pluginconf.d/rhnplugin.conf' regexp='^\s*gpgcheck=0' replace='gpgcheck=1'
replace:
dest: '/etc/yum/pluginconf.d/rhnplugin.conf'
regexp: '^\s*gpgcheck: 0'
replace: 'gpgcheck: 1'
when: rhnplugin_file.stat.exists
- name: remove packages
yum: name='{{item}}' state=removed
- name: remove deprecated or insecure packages | package-01 - package-09
yum:
name: '{{ item }}'
state: 'absent'
with_items:
- "{{os_security_packages_list}}"
- '{{ os_security_packages_list }}'
when: os_security_packages_clean

View File

@ -0,0 +1,28 @@
log_file = /var/log/audit/audit.log
log_format = RAW
log_group = root
priority_boost = 4
flush = INCREMENTAL
freq = 20
num_logs = 5
disp_qos = lossy
dispatcher = /sbin/audispd
name_format = NONE
##name = mydomain
max_log_file = 6
max_log_file_action = keep_logs
space_left = 75
space_left_action = SYSLOG
action_mail_acct = root
admin_space_left = 50
admin_space_left_action = SUSPEND
disk_full_action = SUSPEND
disk_error_action = SUSPEND
##tcp_listen_port =
tcp_listen_queue = 5
tcp_max_per_addr = 1
##tcp_client_ports = 1024-65535
tcp_client_max_idle = 0
enable_krb5 = no
krb5_principal = auditd
##krb5_key_file = /etc/audit/audit.key

View File

@ -1,3 +1,4 @@
# {{ ansible_managed | comment }}
# /etc/default/ufw
#

View File

@ -1,4 +1,4 @@
# {{ ansible_managed }}
# {{ ansible_managed | comment }}
# This file contains the names of kernel modules that should be loaded at boot time, one per line. Lines beginning with "#" are ignored.
#
# A list of all available kernel modules kann be found with `find /lib/modules/$(uname -r)/kernel/`

View File

@ -1,21 +1,22 @@
# {{ ansible_managed | comment }}
# Configuration control definitions for the login package.
#
#
# Three items must be defined: `MAIL_DIR`, `ENV_SUPATH`, and `ENV_PATH`. If unspecified, some arbitrary (and possibly incorrect) value will be assumed. All other items are optional - if not specified then the described action or option will be inhibited.
#
#
# Comment lines (lines beginning with `#`) and blank lines are ignored.
#
#-- Modified for Linux. --marekm
# *REQUIRED for useradd/userdel/usermod*
#
#
# Directory where mailboxes reside, _or_ name of file, relative to the home directory. If you _do_ define `MAIL_DIR` and `MAIL_FILE`, `MAIL_DIR` takes precedence.
# Essentially:
#
#
# * `MAIL_DIR` defines the location of users mail spool files (for mbox use) by appending the username to `MAIL_DIR` as defined below.
# * `MAIL_FILE` defines the location of the users mail spool files as the fully-qualified filename obtained by prepending the user home directory before `$MAIL_FILE`
#
# *NOTE*: This is no more used for setting up users MAIL environment variable which is, starting from shadow 4.0.12-1 in Debian, entirely the job of the pam_mail PAM modules.
#
#
# See default PAM configuration files provided for login, su, etc.
# This is a temporary situation: setting these variables will soon move to `/etc/default/useradd` and the variables will then be no more supported
MAIL_DIR /var/mail
@ -25,7 +26,7 @@ MAIL_DIR /var/mail
FAILLOG_ENAB yes
# Enable display of unknown usernames when login failures are recorded.
#
#
# *WARNING*: Unknown usernames may become world readable. See #290803 and #298773 for details about how this could become a security concern
LOG_UNKFAIL_ENAB no
@ -84,7 +85,7 @@ KILLCHAR 025
# Prefix these values with `0` to get octal, `0x` to get hexadecimal.
# `022` is the "historical" value in Debian for UMASK
# `027`, or even `077`, could be considered better for privacy.
UMASK {{os_env_umask}}
UMASK {{ os_env_umask }}
# Enable setting of the umask group bits to be the same as owner bits (examples: `022` -> `002`, `077` -> `007`) for non-root users, if the uid is the same as gid, and username is the same as the primary group name.
# If set to yes, userdel will remove the user´s group if it contains no more members, and useradd will create by default a group with the name of the user.
@ -95,33 +96,33 @@ USERGROUPS_ENAB yes
# -----------------------
# Maximum number of days a password may be used.
PASS_MAX_DAYS {{os_auth_pw_max_age}}
PASS_MAX_DAYS {{ os_auth_pw_max_age }}
# Minimum number of days allowed between password changes.
PASS_MIN_DAYS {{os_auth_pw_min_age}}
PASS_MIN_DAYS {{ os_auth_pw_min_age }}
# Number of days warning given before a password expires.
PASS_WARN_AGE 7
# Min/max values for automatic uid selection in useradd
UID_MIN {{os_auth_uid_min}}
UID_MIN {{ os_auth_uid_min }}
UID_MAX 60000
# System accounts
SYS_UID_MIN {{os_auth_sys_uid_min}}
SYS_UID_MAX {{os_auth_sys_uid_max}}
SYS_UID_MIN {{ os_auth_sys_uid_min }}
SYS_UID_MAX {{ os_auth_sys_uid_max }}
# Min/max values for automatic gid selection in groupadd
GID_MIN {{os_auth_gid_min}}
GID_MIN {{ os_auth_gid_min }}
GID_MAX 60000
# System accounts
SYS_GID_MIN {{os_auth_sys_gid_min}}
SYS_GID_MAX {{os_auth_sys_gid_max}}
SYS_GID_MIN {{ os_auth_sys_gid_min }}
SYS_GID_MAX {{ os_auth_sys_gid_max }}
# Max number of login retries if password is bad. This will most likely be overriden by PAM, since the default pam_unix module has it's own built in of 3 retries. However, this is a safe fallback in case you are using an authentication module that does not enforce PAM_MAXTRIES.
LOGIN_RETRIES {{os_auth_retries}}
LOGIN_RETRIES {{ os_auth_retries }}
# Max time in seconds for login
LOGIN_TIMEOUT {{os_auth_timeout}}
LOGIN_TIMEOUT {{ os_auth_timeout }}
# Which fields may be changed by regular users using chfn - use any combination of letters "frwh" (full name, room number, work phone, home phone). If not defined, no changes are allowed.
# For backward compatibility, "yes" = "rwh" and "no" = "frwh".

View File

@ -0,0 +1,5 @@
{{ ansible_managed | comment }}
{% for fs in os_unused_filesystems | difference(os_filesystem_whitelist) %}
install {{fs}} /bin/true
{% endfor %}

View File

@ -1,9 +1,8 @@
# {{ ansible_managed }}
#---
# {{ ansible_managed | comment }}
#%PAM-1.0
{% if os_auth_retries > 0 %}
auth required pam_tally2.so deny={{os_auth_retries}} onerr=fail unlock_time={{os_auth_lockout_time}}
auth required pam_tally2.so deny={{ os_auth_retries }} onerr=fail unlock_time={{ os_auth_lockout_time }}
{% endif %}
auth required pam_env.so
auth sufficient pam_unix.so nullok try_first_pass
@ -18,11 +17,11 @@ account sufficient pam_localuser.so
account sufficient pam_succeed_if.so uid < 500 quiet
account required pam_permit.so
{% if os_auth_pam_passwdqc_enable %}
{%- if ansible_os_family == 'RedHat' and ansible_distribution_version >= '7' %}
password required pam_pwquality.so {{os_auth_pam_pwquality_options}}
{% if (os_auth_pam_passwdqc_enable|bool) %}
{%- if ((ansible_os_family == 'RedHat' and ansible_distribution_version >= '7') or ansible_distribution == 'Amazon') %}
password required pam_pwquality.so {{ os_auth_pam_pwquality_options }}
{%- else %}
password requisite pam_passwdqc.so {{os_auth_pam_passwdqc_options}}
password requisite pam_passwdqc.so {{ os_auth_pam_passwdqc_options }}
{%- endif %}
{% else %}
password requisite pam_cracklib.so try_first_pass retry=3 type=

View File

@ -1,4 +1,4 @@
# {{ ansible_managed }}
# {{ ansible_managed | comment }}
# Disable core dumps via soft limits for all users. Compliance to this setting is voluntary and can be modified by users up to a hard limit. This setting is a sane default.
ulimit -S -c 0 > /dev/null 2>&1

View File

@ -1,6 +1,6 @@
# See libuser.conf(5) for more information.
# {{ ansible_managed }}
# {{ ansible_managed | comment }}
# Do not modify the default module list if you care about unattended calls
# to programs (i.e., scripts) working!

View File

@ -1,4 +1,4 @@
# {{ ansible_managed }}
# {{ ansible_managed | comment }}
# A list of TTYs, from which root can log in

View File

@ -1,4 +1,4 @@
# {{ ansible_managed }}
# {{ ansible_managed | comment }}
# color => new RH6.0 bootup
# verbose => old-style bootup
@ -18,7 +18,7 @@ SETCOLOR_WARNING="echo -en \\033[0;33m"
# terminal sequence to reset to the default color.
SETCOLOR_NORMAL="echo -en \\033[0;39m"
# Set to anything other than 'no' to allow hotkey interactive startup...
PROMPT={{ 'yes' if os_security_init_prompt else 'no' }}
PROMPT={{ 'yes' if (os_security_init_prompt|bool) else 'no' }}
# Set to 'yes' to allow probing for devices with swap signatures
AUTOSWAP=no
# What ttys should gettys be started on?

View File

@ -1,3 +0,0 @@
# {{ansible_managed}}
# Prevent core dumps for all users. These are usually only needed by developers and may contain sensitive information.
* hard core 0

View File

@ -4,4 +4,4 @@ Priority: 1024
Conflicts: cracklib
Password-Type: Primary
Password:
requisite pam_passwdqc.so {{os_auth_pam_passwdqc_options}}
requisite pam_passwdqc.so {{ os_auth_pam_passwdqc_options }}

View File

@ -4,7 +4,7 @@ Priority: 1024
Conflicts: cracklib
Auth-Type: Primary
Auth-Initial:
required pam_tally2.so deny={{os_auth_retries}} onerr=fail unlock_time={{os_auth_lockout_time}}
required pam_tally2.so deny={{ os_auth_retries }} onerr=fail unlock_time={{ os_auth_lockout_time }}
Account-Type: Primary
Account-Initial:
required pam_tally2.so

View File

@ -0,0 +1,74 @@
---
- name: wrapper playbook for kitchen testing "ansible-os-hardening" with custom vars for testing
hosts: localhost
roles:
- ansible-os-hardening
pre_tasks:
- name: Run the equivalent of "apt-get update" as a separate step
apt:
update_cache: yes
when: ansible_os_family == 'Debian'
- name: create recursing symlink to test minimize access
shell: "rm -f /usr/bin/zzz && ln -s /usr/bin /usr/bin/zzz"
vars:
os_security_users_allow: change_user
os_security_kernel_enable_core_dump: true
os_security_suid_sgid_remove_from_unknown: true
os_auth_pam_passwdqc_enable: false
os_desktop_enable: true
os_env_extra_user_paths: ['/home']
os_auth_allow_homeless: true
os_security_suid_sgid_blacklist: ['/bin/umount']
os_security_suid_sgid_whitelist: ['/usr/bin/rlogin']
os_filesystem_whitelist: ['vfat']
sysctl_config:
net.ipv4.ip_forward: 0
net.ipv6.conf.all.forwarding: 0
net.ipv6.conf.all.accept_ra: 0
net.ipv6.conf.default.accept_ra: 0
net.ipv4.conf.all.rp_filter: 1
net.ipv4.conf.default.rp_filter: 1
net.ipv4.icmp_echo_ignore_broadcasts: 1
net.ipv4.icmp_ignore_bogus_error_responses: 1
net.ipv4.icmp_ratelimit: 100
net.ipv4.icmp_ratemask: 88089
net.ipv6.conf.all.disable_ipv6: 1
net.ipv4.conf.all.arp_ignore: 1
net.ipv4.conf.all.arp_announce: 2
net.ipv4.conf.all.shared_media: 1
net.ipv4.conf.default.shared_media: 1
net.ipv4.conf.all.accept_source_route: 0
net.ipv4.conf.default.accept_source_route: 0
net.ipv4.conf.default.accept_redirects: 0
net.ipv4.conf.all.accept_redirects: 0
net.ipv4.conf.all.secure_redirects: 0
net.ipv4.conf.default.secure_redirects: 0
net.ipv6.conf.default.accept_redirects: 0
net.ipv6.conf.all.accept_redirects: 0
net.ipv4.conf.all.send_redirects: 0
net.ipv4.conf.default.send_redirects: 0
net.ipv4.conf.all.log_martians: 1
net.ipv6.conf.default.router_solicitations: 0
net.ipv6.conf.default.accept_ra_rtr_pref: 0
net.ipv6.conf.default.accept_ra_pinfo: 0
net.ipv6.conf.default.accept_ra_defrtr: 0
net.ipv6.conf.default.autoconf: 0
net.ipv6.conf.default.dad_transmits: 0
net.ipv6.conf.default.max_addresses: 1
kernel.sysrq: 0
fs.suid_dumpable: 0
kernel.randomize_va_space: 2
- name: wrapper playbook for kitchen testing "ansible-os-hardening"
hosts: localhost
vars:
- os_auditd_enabled: false
pre_tasks:
- name: Run the equivalent of "apt-get update" as a separate step
apt:
update_cache: yes
when: ansible_os_family == 'Debian'
roles:
- ansible-os-hardening

View File

@ -0,0 +1,9 @@
---
# system accounts that do not get their login disabled and pasword changed
os_always_ignore_users: ['root','sync','shutdown','halt', 'ec2-user']
sysctl_rhel_config:
# ExecShield protection against buffer overflows
kernel.exec-shield: 1
# Syncookies is used to prevent SYN-flooding attacks.
net.ipv4.tcp_syncookies: 1

View File

@ -5,10 +5,27 @@ passwdqc_path: '/usr/share/pam-configs/passwdqc'
tally2_path: '/usr/share/pam-configs/tally2'
os_nologin_shell_path: '/usr/sbin/nologin'
auditd_package: 'auditd'
modprobe_package: 'kmod'
# Different distros use different standards for /etc/shadow perms, e.g.
# RHEL derivatives use root:root 0600, whereas Debian-based use root:shadow 0640.
# RHEL derivatives use root:root 0000, whereas Debian-based use root:shadow 0640.
# You must provide key/value pairs for owner, group, and mode if overriding.
os_shadow_perms:
owner: root
group: shadow
mode: "0640"
mode: '0640'
os_passwd_perms:
owner: root
group: root
mode: '0644'
os_env_umask: '027'
os_auth_uid_min: 1000
os_auth_gid_min: 1000
os_auth_sys_uid_min: 100
os_auth_sys_uid_max: 999
os_auth_sys_gid_min: 100
os_auth_sys_gid_max: 999

View File

@ -4,9 +4,23 @@ os_packages_pam_cracklib: 'pam_cracklib'
os_nologin_shell_path: '/sbin/nologin'
# Different distros use different standards for /etc/shadow perms, e.g.
# RHEL derivatives use root:root 0600, whereas Debian-based use root:shadow 0640.
# RHEL derivatives use root:root 0000, whereas Debian-based use root:shadow 0640.
# You must provide key/value pairs for owner, group, and mode if overriding.
os_shadow_perms:
owner: root
group: root
mode: "0600"
mode: '0000'
os_passwd_perms:
owner: root
group: root
mode: '0644'
os_env_umask: '077'
os_auth_uid_min: 1000
os_auth_gid_min: 1000
os_auth_sys_uid_min: 201
os_auth_sys_uid_max: 999
os_auth_sys_gid_min: 201
os_auth_sys_gid_max: 999

View File

@ -0,0 +1,7 @@
---
sysctl_rhel_config:
# ExecShield protection against buffer overflows
kernel.exec-shield: 1
# Syncookies is used to prevent SYN-flooding attacks.
net.ipv4.tcp_syncookies: 1

View File

@ -1,12 +1,31 @@
---
modprobe_package: 'module-init-tools'
auditd_package: 'audit'
os_packages_pam_ccreds: 'pam_ccreds'
os_packages_pam_passwdqc: 'pam_passwdqc'
os_packages_pam_cracklib: 'pam_cracklib'
os_nologin_shell_path: '/sbin/nologin'
# Different distros use different standards for /etc/shadow perms, e.g.
# RHEL derivatives use root:root 0600, whereas Debian-based use root:shadow 0640.
# RHEL derivatives use root:root 0000, whereas Debian-based use root:shadow 0640.
# You must provide key/value pairs for owner, group, and mode if overriding.
os_shadow_perms:
owner: root
group: root
mode: "0600"
mode: '0000'
os_passwd_perms:
owner: root
group: root
mode: '0644'
os_env_umask: '077'
os_auth_uid_min: 1000
os_auth_gid_min: 1000
os_auth_sys_uid_min: 201
os_auth_sys_uid_max: 999
os_auth_sys_gid_min: 201
os_auth_sys_gid_max: 999

View File

@ -8,7 +8,7 @@
# adjust values for blacklist/whitelist instead, they can override system_blacklist/whitelist
# list of suid/sgid entries that must be removed
os_security_suid_sgid_system_blacklist:
os_security_suid_sgid_system_blacklist:
# blacklist as provided by NSA
- '/usr/bin/rcp'
- '/usr/bin/rlogin'
@ -43,6 +43,7 @@ os_security_suid_sgid_system_whitelist:
- '/bin/mount'
- '/bin/ping'
- '/bin/su'
- '/usr/bin/su'
- '/bin/umount'
- '/sbin/pam_timestamp_check'
- '/sbin/unix_chkpwd'
@ -108,4 +109,3 @@ os_security_suid_sgid_system_whitelist:
# system accounts that do not get their login disabled and pasword changed
os_always_ignore_users: ['root','sync','shutdown','halt']

View File

@ -0,0 +1,37 @@
---
driver:
name: ec2
vpc_id: "vpc-4ef2ce26"
subnet_id: "subnet-b477b7df"
region: eu-central-1
transport:
max_ssh_sessions: 5
provisioner:
name: ansible_playbook
hosts: all
require_ansible_repo: false
require_chef_for_busser: false
require_ruby_for_busser: false
require_ansible_omnibus: true
ansible_verbose: true
ansible_diff: true
hosts: all
roles_path: ../ansible-ssh-hardening/
http_proxy: <%= ENV['http_proxy'] || nil %>
https_proxy: <%= ENV['https_proxy'] || nil %>
playbook: default.yml
platforms:
- name: centos-7
- name: ubuntu-16.04
verifier:
name: inspec
sudo: true
inspec_tests:
- https://github.com/dev-sec/tests-ssh-hardening
suites:
- name: os

View File

@ -16,7 +16,7 @@ provisioner:
require_ruby_for_busser: false
ansible_verbose: true
roles_path: ../ansible-ssh-hardening/
playbook: default.yml
playbook: tests/default.yml
http_proxy: <%= ENV['http_proxy'] || nil %>
https_proxy: <%= ENV['https_proxy'] || nil %>

View File

@ -9,10 +9,6 @@ driver:
transport:
max_ssh_sessions: 5
transport:
max_ssh_sessions: 5
provisioner:
name: ansible_playbook
hosts: all
@ -25,7 +21,8 @@ provisioner:
roles_path: ../ansible-ssh-hardening/
http_proxy: <%= ENV['http_proxy'] || nil %>
https_proxy: <%= ENV['https_proxy'] || nil %>
playbook: default.yml
playbook: tests/default.yml
ansible_diff: true
ansible_extra_flags:
- "--skip-tags=sysctl"
@ -38,6 +35,10 @@ platforms:
driver:
image: rndmh3ro/docker-centos7-ansible:latest
platform: centos
run_command: /sbin/init
provision_command:
- sed -i 's/UsePAM yes/UsePAM no/g' /etc/ssh/sshd_config
- systemctl enable sshd.service
- name: oracle6-ansible-latest
driver:
image: rndmh3ro/docker-oracle6-ansible:latest
@ -45,11 +46,11 @@ platforms:
- name: oracle7-ansible-latest
driver:
image: rndmh3ro/docker-oracle7-ansible:latest
run_command: /sbin/init
platform: centos
- name: ubuntu1204-ansible-latest
driver:
image: rndmh3ro/docker-ubuntu1204-ansible:latest
platform: ubuntu
provision_command:
- sed -i 's/UsePAM yes/UsePAM no/g' /etc/ssh/sshd_config
- systemctl enable sshd.service
- name: ubuntu1404-ansible-latest
driver:
image: rndmh3ro/docker-ubuntu1404-ansible:latest
@ -58,6 +59,9 @@ platforms:
driver:
image: rndmh3ro/docker-ubuntu1604-ansible:latest
platform: ubuntu
run_command: /sbin/init
provision_command:
- systemctl enable ssh.service
- name: debian7-ansible-latest
driver:
image: rndmh3ro/docker-debian7-ansible:latest
@ -66,10 +70,22 @@ platforms:
driver:
image: rndmh3ro/docker-debian8-ansible:latest
platform: debian
#- name: debian9-ansible-latest
# driver:
# image: rndmh3ro/docker-debian9-ansible:latest
# platform: debian
- name: debian9-ansible-latest
driver:
image: rndmh3ro/docker-debian9-ansible:latest
platform: debian
run_command: /sbin/init
provision_command:
- apt install -y systemd-sysv
- systemctl enable ssh.service
- name: amazon-ansible-latest
driver:
image: rndmh3ro/docker-amazon-ansible:latest
platform: centos
run_command: /sbin/init
provision_command:
- sed -i 's/UsePAM yes/UsePAM no/g' /etc/ssh/sshd_config
- systemctl enable sshd.service
verifier:
name: inspec

View File

@ -15,10 +15,10 @@ env:
version: latest
init: /sbin/init
- distro: oracle7
init: /usr/lib/systemd/systemd
run_opts: "--privileged --volume=/sys/fs/cgroup:/sys/fs/cgroup:ro"
version: latest
# - distro: oracle7
# init: /usr/lib/systemd/systemd
# run_opts: "--privileged --volume=/sys/fs/cgroup:/sys/fs/cgroup:ro"
# version: latest
- distro: ubuntu1604
version: latest
@ -29,24 +29,24 @@ env:
version: latest
init: /sbin/init
- distro: ubuntu1204
version: latest
init: /sbin/init
- distro: debian7
version: latest
init: /sbin/init
- distro: debian8
version: latest
run_opts: "--privileged --volume=/sys/fs/cgroup:/sys/fs/cgroup:ro"
init: /sbin/init
run_opts: "--privileged --volume=/sys/fs/cgroup:/sys/fs/cgroup:ro"
# - distro: debian9
# version: latest
# init: /lib/systemd/systemd
# run_opts: "--privileged --volume=/sys/fs/cgroup:/sys/fs/cgroup:ro"
- distro: debian9
version: latest
init: /lib/systemd/systemd
run_opts: "--privileged --volume=/sys/fs/cgroup:/sys/fs/cgroup:ro"
- distro: amazon
init: /lib/systemd/systemd
version: latest
run_opts: "--privileged --volume=/sys/fs/cgroup:/sys/fs/cgroup:ro"
before_install:
# Pull container
@ -58,10 +58,14 @@ script:
- 'docker run --detach --volume="${PWD}":/etc/ansible/roles/ansible-ssh-hardening:ro ${run_opts} rndmh3ro/docker-${distro}-ansible:${version} "${init}" > "${container_id}"'
# Test role.
- 'docker exec "$(cat ${container_id})" ansible-playbook /etc/ansible/roles/ansible-ssh-hardening/default.yml'
- 'docker exec "$(cat ${container_id})" ansible-playbook /etc/ansible/roles/ansible-ssh-hardening/tests/default_custom.yml'
- 'docker exec "$(cat ${container_id})" ansible-playbook /etc/ansible/roles/ansible-ssh-hardening/tests/default.yml'
# Verify role
- 'inspec exec https://github.com/dev-sec/ssh-baseline/ -t docker://$(cat ${container_id})'
# remove the UseLogin-check, see here for reasons: https://github.com/dev-sec/ansible-ssh-hardening/pull/141
- 'inspec exec https://github.com/dev-sec/ssh-baseline/ -t docker://$(cat ${container_id}) --controls=sshd-01 sshd-02 sshd-03 sshd-04 sshd-05 sshd-06 sshd-07 sshd-08 sshd-09 sshd-10 sshd-11 sshd-12 sshd-13 sshd-14 sshd-16 sshd-17 sshd-18 sshd-19 sshd-20 sshd-21 sshd-22 sshd-23 sshd-24 sshd-25 sshd-26 sshd-27 sshd-28 sshd-29 sshd-30 sshd-31 sshd-32 sshd-33 sshd-34 sshd-35 sshd-36 sshd-37 sshd-38 sshd-39 sshd-40 sshd-41 sshd-42 sshd-43 sshd-44 sshd-45 sshd-46 sshd-47 sshd-48 --no-distinct-exit'
# remove UseRoaming and RhostsRSAAuthentication because these options are deprecated - ssh-14, ssh-15, ssh-21
- 'inspec exec https://github.com/dev-sec/ssh-baseline/ -t docker://$(cat ${container_id}) --controls=ssh-01 ssh-02 ssh-03 ssh-04 ssh-05 ssh-06 ssh-07 ssh-08 ssh-09 ssh-10 ssh-11 ssh-12 ssh-13 ssh-16 ssh-17 ssh-18 ssh-19 ssh-20 --no-distinct-exit'
notifications:
webhooks: https://galaxy.ansible.com/api/v1/notifications/

View File

@ -1,11 +1,170 @@
# Change Log
## [4.4.0](https://github.com/dev-sec/ansible-ssh-hardening/tree/4.4.0) (2017-12-29)
[Full Changelog](https://github.com/dev-sec/ansible-ssh-hardening/compare/4.3.1...4.4.0)
**Implemented enhancements:**
- Changes in selinux section to avoid confusion and some inconsistencies [\#127](https://github.com/dev-sec/ansible-ssh-hardening/issues/127)
- Issue \#137: Fix sshd\_config's "Match Group sftponly" [\#138](https://github.com/dev-sec/ansible-ssh-hardening/pull/138) ([kekumu](https://github.com/kekumu))
- allow configuration of GatewayPorts [\#136](https://github.com/dev-sec/ansible-ssh-hardening/pull/136) ([pwyliu](https://github.com/pwyliu))
- Added support for AuthorizedKeysFile config setting [\#132](https://github.com/dev-sec/ansible-ssh-hardening/pull/132) ([hyrsky](https://github.com/hyrsky))
- corrected comments explaining the task's behaviour [\#131](https://github.com/dev-sec/ansible-ssh-hardening/pull/131) ([martinbydefault](https://github.com/martinbydefault))
- Add Two-Factor Authentication [\#123](https://github.com/dev-sec/ansible-ssh-hardening/pull/123) ([lazzurs](https://github.com/lazzurs))
**Fixed bugs:**
- ssh\_use\_dns used twice in defaults/main.yml [\#129](https://github.com/dev-sec/ansible-ssh-hardening/issues/129)
- line 56: Bad SSH2 mac spec [\#135](https://github.com/dev-sec/ansible-ssh-hardening/issues/135)
**Closed issues:**
- coreos support? [\#142](https://github.com/dev-sec/ansible-ssh-hardening/issues/142)
- UseLogin is deprecated on CentOS 7 [\#140](https://github.com/dev-sec/ansible-ssh-hardening/issues/140)
- sftp Match Group settings overriding global sshd\_config settings [\#137](https://github.com/dev-sec/ansible-ssh-hardening/issues/137)
- get openssh-version fails on FreeBSD \(with ansible 2.4.0.0\) [\#133](https://github.com/dev-sec/ansible-ssh-hardening/issues/133)
**Merged pull requests:**
- Remove deprecated UseLogin option [\#141](https://github.com/dev-sec/ansible-ssh-hardening/pull/141) ([syhe](https://github.com/syhe))
- Macs kex ciphers [\#139](https://github.com/dev-sec/ansible-ssh-hardening/pull/139) ([rndmh3ro](https://github.com/rndmh3ro))
- force /bin/sh when getting openssh-version [\#134](https://github.com/dev-sec/ansible-ssh-hardening/pull/134) ([gtz42](https://github.com/gtz42))
## [4.3.1](https://github.com/dev-sec/ansible-ssh-hardening/tree/4.3.1) (2017-08-14)
[Full Changelog](https://github.com/dev-sec/ansible-ssh-hardening/compare/4.3.0...4.3.1)
**Implemented enhancements:**
- Remove duplicate ssh\_use\_dns [\#130](https://github.com/dev-sec/ansible-ssh-hardening/pull/130) ([MagnusEnger](https://github.com/MagnusEnger))
**Fixed bugs:**
- System completely unresponsive after role execution [\#126](https://github.com/dev-sec/ansible-ssh-hardening/issues/126)
**Closed issues:**
- role creates duplicate parameter/values after run [\#124](https://github.com/dev-sec/ansible-ssh-hardening/issues/124)
## [4.3.0](https://github.com/dev-sec/ansible-ssh-hardening/tree/4.3.0) (2017-08-03)
[Full Changelog](https://github.com/dev-sec/ansible-ssh-hardening/compare/4.1.3...4.3.0)
**Implemented enhancements:**
- Fix ansible.cfg settings [\#122](https://github.com/dev-sec/ansible-ssh-hardening/pull/122) ([fazlearefin](https://github.com/fazlearefin))
- Finish 94 [\#116](https://github.com/dev-sec/ansible-ssh-hardening/pull/116) ([rndmh3ro](https://github.com/rndmh3ro))
**Merged pull requests:**
- Don't overwrite ssh\_host\_key\_files if set manually [\#125](https://github.com/dev-sec/ansible-ssh-hardening/pull/125) ([oakey-b1](https://github.com/oakey-b1))
- Add comment filter to {{ansible\_managed}} string [\#121](https://github.com/dev-sec/ansible-ssh-hardening/pull/121) ([fazlearefin](https://github.com/fazlearefin))
## [4.1.3](https://github.com/dev-sec/ansible-ssh-hardening/tree/4.1.3) (2017-06-30)
[Full Changelog](https://github.com/dev-sec/ansible-ssh-hardening/compare/4.2.0...4.1.3)
## [4.2.0](https://github.com/dev-sec/ansible-ssh-hardening/tree/4.2.0) (2017-06-30)
[Full Changelog](https://github.com/dev-sec/ansible-ssh-hardening/compare/4.1.2...4.2.0)
**Implemented enhancements:**
- Add support to specify a list of revoked public keys [\#120](https://github.com/dev-sec/ansible-ssh-hardening/pull/120) ([bachp](https://github.com/bachp))
- use package instead of yum so the operation works on Fedora [\#119](https://github.com/dev-sec/ansible-ssh-hardening/pull/119) ([stenwt](https://github.com/stenwt))
**Fixed bugs:**
- fails in --check mode [\#111](https://github.com/dev-sec/ansible-ssh-hardening/issues/111)
**Merged pull requests:**
- Do not use shell when not needed + Lint whitespaces [\#118](https://github.com/dev-sec/ansible-ssh-hardening/pull/118) ([krhubert](https://github.com/krhubert))
## [4.1.2](https://github.com/dev-sec/ansible-ssh-hardening/tree/4.1.2) (2017-05-31)
[Full Changelog](https://github.com/dev-sec/ansible-ssh-hardening/compare/4.1.1...4.1.2)
**Implemented enhancements:**
- added check\_mode: no to "get openssh-version" task, so it won't fail … [\#117](https://github.com/dev-sec/ansible-ssh-hardening/pull/117) ([wschaft](https://github.com/wschaft))
**Fixed bugs:**
- User login failed after running this module [\#114](https://github.com/dev-sec/ansible-ssh-hardening/issues/114)
**Closed issues:**
- Update readme to include baselines [\#110](https://github.com/dev-sec/ansible-ssh-hardening/issues/110)
## [4.1.1](https://github.com/dev-sec/ansible-ssh-hardening/tree/4.1.1) (2017-05-18)
[Full Changelog](https://github.com/dev-sec/ansible-ssh-hardening/compare/4.1.0...4.1.1)
**Implemented enhancements:**
- fix validation error [\#113](https://github.com/dev-sec/ansible-ssh-hardening/pull/113) ([pwyliu](https://github.com/pwyliu))
**Fixed bugs:**
- fix validation error [\#113](https://github.com/dev-sec/ansible-ssh-hardening/pull/113) ([pwyliu](https://github.com/pwyliu))
## [4.1.0](https://github.com/dev-sec/ansible-ssh-hardening/tree/4.1.0) (2017-05-09)
[Full Changelog](https://github.com/dev-sec/ansible-ssh-hardening/compare/4.0.0...4.1.0)
**Implemented enhancements:**
- Provide option to allow password server login [\#106](https://github.com/dev-sec/ansible-ssh-hardening/issues/106)
- Deprecation warning always\_run [\#82](https://github.com/dev-sec/ansible-ssh-hardening/issues/82)
- Added support for UseDNS config switch [\#109](https://github.com/dev-sec/ansible-ssh-hardening/pull/109) ([ftaeger](https://github.com/ftaeger))
- Added support for UseDNS config switch [\#108](https://github.com/dev-sec/ansible-ssh-hardening/pull/108) ([ftaeger](https://github.com/ftaeger))
**Fixed bugs:**
- `create ssh\_config and set permissions to root/644` step repeated [\#104](https://github.com/dev-sec/ansible-ssh-hardening/issues/104)
**Merged pull requests:**
- Added support for PermitTunnel config switch [\#112](https://github.com/dev-sec/ansible-ssh-hardening/pull/112) ([fti7](https://github.com/fti7))
- Adds option to enable password based authentication on the server [\#107](https://github.com/dev-sec/ansible-ssh-hardening/pull/107) ([colin-nolan](https://github.com/colin-nolan))
## [4.0.0](https://github.com/dev-sec/ansible-ssh-hardening/tree/4.0.0) (2017-04-22)
[Full Changelog](https://github.com/dev-sec/ansible-ssh-hardening/compare/3.2.0...4.0.0)
**Implemented enhancements:**
- Avoid small primes for DH and allow rebuild of DH primes [\#89](https://github.com/dev-sec/ansible-ssh-hardening/issues/89)
- Accommodate missing plugins in kitchen\_vagrant\_block.rb [\#100](https://github.com/dev-sec/ansible-ssh-hardening/pull/100) ([fullyint](https://github.com/fullyint))
- Use different Hostkeys according to installed ssh version [\#99](https://github.com/dev-sec/ansible-ssh-hardening/pull/99) ([rndmh3ro](https://github.com/rndmh3ro))
- Remove small dh primes [\#97](https://github.com/dev-sec/ansible-ssh-hardening/pull/97) ([rndmh3ro](https://github.com/rndmh3ro))
- Add Ed25519 SSH host key to match commit 28b4df3 in ssh-baseline [\#96](https://github.com/dev-sec/ansible-ssh-hardening/pull/96) ([techraf](https://github.com/techraf))
- Add support for FreeBSD OpenSSH server and client [\#95](https://github.com/dev-sec/ansible-ssh-hardening/pull/95) ([jbenden](https://github.com/jbenden))
- Replace deprecated always\_run with check\_mode [\#93](https://github.com/dev-sec/ansible-ssh-hardening/pull/93) ([jbenden](https://github.com/jbenden))
- Defaults: Remove DSA from SSH host keys to match ssh-baseline profile [\#92](https://github.com/dev-sec/ansible-ssh-hardening/pull/92) ([techraf](https://github.com/techraf))
- use new docker images [\#91](https://github.com/dev-sec/ansible-ssh-hardening/pull/91) ([rndmh3ro](https://github.com/rndmh3ro))
- use centos 7 in vagrant, limit ssh conns [\#88](https://github.com/dev-sec/ansible-ssh-hardening/pull/88) ([rndmh3ro](https://github.com/rndmh3ro))
- remove support for ansible 1.9 [\#87](https://github.com/dev-sec/ansible-ssh-hardening/pull/87) ([rndmh3ro](https://github.com/rndmh3ro))
- make ChallengeResponseAuthentication configurable [\#85](https://github.com/dev-sec/ansible-ssh-hardening/pull/85) ([rndmh3ro](https://github.com/rndmh3ro))
- List only one Port in ssh config [\#84](https://github.com/dev-sec/ansible-ssh-hardening/pull/84) ([fullyint](https://github.com/fullyint))
- Fix ssh config to handle custom options per Host [\#83](https://github.com/dev-sec/ansible-ssh-hardening/pull/83) ([fullyint](https://github.com/fullyint))
**Fixed bugs:**
- SELinux-specific task still runs on SELinux-disabled systems [\#74](https://github.com/dev-sec/ansible-ssh-hardening/issues/74)
- List only one Port in ssh config [\#84](https://github.com/dev-sec/ansible-ssh-hardening/pull/84) ([fullyint](https://github.com/fullyint))
- Fix ssh config to handle custom options per Host [\#83](https://github.com/dev-sec/ansible-ssh-hardening/pull/83) ([fullyint](https://github.com/fullyint))
**Closed issues:**
- Should compression be opt-in? [\#90](https://github.com/dev-sec/ansible-ssh-hardening/issues/90)
- The role fails when conditionally included [\#86](https://github.com/dev-sec/ansible-ssh-hardening/issues/86)
**Merged pull requests:**
- remove duplicate section [\#105](https://github.com/dev-sec/ansible-ssh-hardening/pull/105) ([rndmh3ro](https://github.com/rndmh3ro))
- Fix ssh\_server\_ports and ssh\_client\_ports documentation bug [\#80](https://github.com/dev-sec/ansible-ssh-hardening/pull/80) ([kivilahtio](https://github.com/kivilahtio))
## [3.2.0](https://github.com/dev-sec/ansible-ssh-hardening/tree/3.2.0) (2016-10-24)
[Full Changelog](https://github.com/dev-sec/ansible-ssh-hardening/compare/3.1.0...3.2.0)
**Implemented enhancements:**
- CentOS 7 selinux dependencies [\#76](https://github.com/dev-sec/ansible-ssh-hardening/issues/76)
- install selinux dependencies, check for already installed semodule [\#79](https://github.com/dev-sec/ansible-ssh-hardening/pull/79) ([rndmh3ro](https://github.com/rndmh3ro))
- Parameterise Banner and DebianBanner as defaults [\#77](https://github.com/dev-sec/ansible-ssh-hardening/pull/77) ([tsenart](https://github.com/tsenart))
**Fixed bugs:**
@ -13,16 +172,11 @@
- Some tasks are always run even if they are not needed [\#78](https://github.com/dev-sec/ansible-ssh-hardening/issues/78)
- Selinux issue [\#75](https://github.com/dev-sec/ansible-ssh-hardening/issues/75)
- Running the tests locally [\#61](https://github.com/dev-sec/ansible-ssh-hardening/issues/61)
- SELinux-specific task still runs on SELinux-disabled systems [\#74](https://github.com/dev-sec/ansible-ssh-hardening/issues/74)
**Closed issues:**
- Applied-Crypto-Hardening project and new cyphers. [\#28](https://github.com/dev-sec/ansible-ssh-hardening/issues/28)
**Merged pull requests:**
- install selinux dependencies, check for already installed semodule [\#79](https://github.com/dev-sec/ansible-ssh-hardening/pull/79) ([rndmh3ro](https://github.com/rndmh3ro))
## [3.1.0](https://github.com/dev-sec/ansible-ssh-hardening/tree/3.1.0) (2016-08-03)
[Full Changelog](https://github.com/dev-sec/ansible-ssh-hardening/compare/3.1...3.1.0)

View File

@ -62,7 +62,7 @@ All tests will be reviewed internally for their validity and overall project dir
### Document your code
As code is more often read than written, please provide documentation in all projects.
As code is more often read than written, please provide documentation in all projects.
Adhere to the respective guidelines for documentation:

View File

@ -6,46 +6,73 @@
## Description
This role provides secure ssh-client and ssh-server configurations.
This role provides secure ssh-client and ssh-server configurations. It is intended to be compliant with the [DevSec SSH Baseline](https://github.com/dev-sec/ssh-baseline).
Warning: This role disables root-login on the target server! Please make sure you have another user with su or sudo permissions that can login into the server.
## Requirements
* Ansible > 2.2.1
* Ansible > 2.4
## Role Variables
| Name | Default Value | Description |
| -------------- | ------------- | -----------------------------------|
|`network_ipv6_enable` | false |true if IPv6 is needed|
|`ssh_client_cbc_required` | false |true if CBC for ciphers is required. This is usually only necessary, if older M2M mechanism need to communicate with SSH, that don't have any of the configured secure ciphers enabled. CBC is a weak alternative. Anything weaker should be avoided and is thus not available.|
|`ssh_server_cbc_required` | false |true if CBC for ciphers is required. This is usually only necessary, if older M2M mechanism need to communicate with SSH, that don't have any of the configured secure ciphers enabled. CBC is a weak alternative. Anything weaker should be avoided and is thus not available.|
|`ssh_client_weak_hmac` | false |true if weaker HMAC mechanisms are required. This is usually only necessary, if older M2M mechanism need to communicate with SSH, that don't have any of the configured secure HMACs enabled.|
|`ssh_server_weak_hmac` | false |true if weaker HMAC mechanisms are required. This is usually only necessary, if older M2M mechanism need to communicate with SSH, that don't have any of the configured secure HMACs enabled.|
|`ssh_client_weak_kex` | false |true if weaker Key-Exchange (KEX) mechanisms are required. This is usually only necessary, if older M2M mechanism need to communicate with SSH, that don't have any of the configured secure KEXs enabled.|
|`ssh_server_weak_kex` | false |true if weaker Key-Exchange (KEX) mechanisms are required. This is usually only necessary, if older M2M mechanism need to communicate with SSH, that don't have any of the configured secure KEXs enabled.|
|`ssh_server_ports` | ['22'] |ports on which ssh-server should listen|
|`ssh_client_port` | '22' |port to which ssh-client should connect|
|`ssh_listen_to` | ['0.0.0.0'] |one or more ip addresses, to which ssh-server should listen to. Default is all adresseses, but should be configured to specific addresses for security reasons!|
|`ssh_host_key_files` | ['/etc/ssh/ssh_host_rsa_key', '/etc/ssh/ssh_host_dsa_key', '/etc/ssh/ssh_host_ecdsa_key'] |Host keys to look for when starting sshd.|
|`ssh_host_key_files` | [] |Host keys for sshd. If empty ['/etc/ssh/ssh_host_rsa_key', '/etc/ssh/ssh_host_ecdsa_key', '/etc/ssh/ssh_host_ed25519_key'] will be used, as far as supported by the installed sshd version|
|`ssh_client_alive_interval` | 600 | specifies an interval for sending keepalive messages |
|`ssh_client_alive_count` | 3 | defines how often keep-alive messages are sent |
|`ssh_permit_tunnel` | false | true if SSH Port Tunneling is required |
|`ssh_remote_hosts` | [] | one or more hosts and their custom options for the ssh-client. Default is empty. See examples in `defaults/main.yml`.|
|`ssh_allow_root_with_key` | false | false to disable root login altogether. Set to true to allow root to login via key-based mechanism.|
|`ssh_allow_tcp_forwarding` | false | false to disable TCP Forwarding. Set to true to allow TCP Forwarding.|
|`ssh_gateway_ports` | `false` | `false` to disable binding forwarded ports to non-loopback addresses. Set to `true` to force binding on wildcard address. Set to `clientspecified` to allow the client to specify which address to bind to.|
|`ssh_allow_agent_forwarding` | false | false to disable Agent Forwarding. Set to true to allow Agent Forwarding.|
|`ssh_pam_support` | true | true if SSH has PAM support.|
|`ssh_use_pam` | false | false to disable pam authentication.|
|`ssh_gssapi_support` | true | true if SSH has GSSAPI support.|
|`ssh_kerberos_support` | true | true if SSH has Kerberos support.|
|`ssh_deny_users` | '' | if specified, login is disallowed for user names that match one of the patterns.|
|`ssh_allow_users` | '' | if specified, login is allowed only for user names that match one of the patterns.|
|`ssh_deny_groups` | '' | if specified, login is disallowed for users whose primary group or supplementary group list matches one of the patterns.|
|`ssh_allow_groups` | '' | if specified, login is allowed only for users whose primary group or supplementary group list matches one of the patterns.|
|`ssh_authorized_keys_file` | '' | change default file that contains the public keys that can be used for user authentication.|
|`ssh_trusted_user_ca_keys_file` | '' | specifies the file containing trusted certificate authorities public keys used to sign user certificates. |
|`ssh_trusted_user_ca_keys` | [] | set the trusted certificate authorities public keys used to sign user certificates. Only used if ssh_trusted_user_ca_keys_file is set. |
|`ssh_authorized_principals_file` | '' | specifies the file containing principals that are allowed. Only used if ssh_trusted_user_ca_keys_file is set. |
|`ssh_authorized_principals` | [] | list of hashes containing file paths and authorized principals, see default_custom.yml for all options. Only used if ssh_authorized_principals_file is set. |
|`ssh_print_motd` | false | false to disable printing of the MOTD|
|`ssh_print_last_log` | false | false to disable display of last login information|
|`sftp_enabled` | false | true to enable sftp configuration|
|`sftp_chroot` | true | false to disable chroot for sftp|
|`sftp_chroot_dir` | /home/%u | change default sftp chroot location|
|`ssh_client_roaming` | false | enable experimental client roaming|
|`sshd_moduli_file` | '/etc/ssh/moduli' | path to the SSH moduli file |
|`sshd_moduli_minimum` | 2048 | remove Diffie-Hellman parameters smaller than the defined size to mitigate logjam|
|`ssh_challengeresponseauthentication` | false | Specifies whether challenge-response authentication is allowed (e.g. via PAM) |
|`ssh_client_password_login` | false | `true` to allow password-based authentication with the ssh client |
|`ssh_server_password_login` | false | `true` to allow password-based authentication with the ssh server |
|`ssh_google_auth` | false | `true` to enable google authenticator based TOTP 2FA |
|`ssh_pam_device` | false | `true` to enable public key auth with pam device 2FA |
|`ssh_banner` | `false` | `true` to print a banner on login |
|`ssh_client_hardening` | `true` | `false` to stop harden the client |
|`ssh_client_port` | `'22'` | Specifies the port number to connect on the remote host. |
|`ssh_compression` | `false` | Specifies whether compression is enabled after the user has authenticated successfully. |
|`ssh_max_auth_retries` | `2` | Specifies the maximum number of authentication attempts permitted per connection. |
|`ssh_print_debian_banner` | `false` | `true` to print debian specific banner |
|`ssh_server_enabled` | `true` | `false` to disable the opensshd server |
|`ssh_server_hardening` | `true` | `false` to stop harden the server |
|`ssh_server_match_group` | '' | Introduces a conditional block. If all of the criteria on the Match line are satisfied, the keywords on the following lines override those set in the global section of the config file, until either another Match line or the end of the file. |
|`ssh_server_match_user` | '' | Introduces a conditional block. If all of the criteria on the Match line are satisfied, the keywords on the following lines override those set in the global section of the config file, until either another Match line or the end of the file. |
|`ssh_server_permit_environment_vars` | `false` | `true` to specify that ~/.ssh/environment and environment= options in ~/.ssh/authorized_keys are processed by sshd |
|`ssh_use_dns` | `false` | Specifies whether sshd should look up the remote host name, and to check that the resolved host name for the remote IP address maps back to the very same IP address. |
|`ssh_server_revoked_keys` | [] | a list of revoked public keys that the ssh server will always reject, useful to revoke known weak or compromised keys.|
|`ssh_max_startups` | '10:30:100' | Specifies the maximum number of concurrent unauthenticated connections to the SSH daemon.|
|`ssh_macs` | [] | Change this list to overwrite macs. Defaults found in `defaults/main.yml` |
|`ssh_kex` | [] | Change this list to overwrite kexs. Defaults found in `defaults/main.yml` |
|`ssh_ciphers` | [] | Change this list to overwrite ciphers. Defaults found in `defaults/main.yml` |
## Example Playbook
@ -119,11 +146,9 @@ Always look into log files first and if possible look at the negotation between
We have seen some issues in applications (based on python and ruby) that are due to their use of an outdated crypto set. This collides with this hardening module, which reduced the list of ciphers, message authentication codes (MACs) and key exchange (KEX) algorithms to a more secure selection.
If you find this isn't enough, feel free to activate the attributes `cbc_requires` for ciphers, `weak_hmac` for MACs and `weak_kex`for KEX in the variables `ssh_client` or `ssh_server` based on where you want to support them.
**After using the role Ansibles template/copy/file module does not work anymore!**
This role deactivates SFTP. Ansible uses by default SFTP to transfer files to the remote hosts. You have to set `scp_if_ssh = True` in your ansible.cfg. This way Ansible uses SCP to copy files.
This role by default deactivates SFTP. Ansible uses by default SFTP to transfer files to the remote hosts. You have to set `scp_if_ssh = True` in your ansible.cfg. This way Ansible uses SCP to copy files. Alternatively you can enable SFTP again by setting `sftp_enabled` to `true`.
**Cannot restart sshd-service due to lack of privileges**
@ -145,7 +170,7 @@ See [contributor guideline](CONTRIBUTING.md).
## License and Author
* Author:: Sebastian Gumprich <sebastian.gumprich@38.de>
* Author:: Sebastian Gumprich
* Author:: Christoph Hartmann <chris@lollyrock.com>
Licensed under the Apache License, Version 2.0 (the "License");

View File

@ -1,14 +1,15 @@
# config file for ansible -- http://ansible.com/
# ==============================================
# nearly all parameters can be overridden in ansible-playbook
# nearly all parameters can be overridden in ansible-playbook
# or with command line flags. ansible will read ANSIBLE_CONFIG,
# ansible.cfg in the current working directory, .ansible.cfg in
# the home directory or /etc/ansible/ansible.cfg, whichever it
# finds first
[defaults]
ansible_managed = Ansible managed: {file} modified on %Y-%m-%d by {uid} on {host}
ansible_managed = Ansible managed: {file} modified by {uid} on {host}
roles_path = /vagrant
role_path = /vagrant
[ssh_connection]
scp_if_ssh = True

View File

@ -1,34 +0,0 @@
---
- name: wrapper playbook for kitchen testing "ansible-ssh-hardening" with custom settings
hosts: localhost
pre_tasks:
- package: name="{{item}}" state=installed
with_items:
- "openssh-clients"
- "openssh-server"
ignore_errors: true
- apt: name="{{item}}" state=installed update_cache=true
with_items:
- "openssh-client"
- "openssh-server"
ignore_errors: true
- file: path="/var/run/sshd" state=directory
roles:
- ansible-ssh-hardening
vars:
network_ipv6_enable: true
ssh_allow_root_with_key: true
ssh_client_password_login: true
ssh_client_cbc_required: true
ssh_server_weak_hmac: true
ssh_client_weak_kex: true
ssh_remote_hosts:
- names: ['example.com', 'example2.com']
options: ['Port 2222', 'ForwardAgent yes']
- names: ['example3.com']
options: ['StrictHostKeyChecking no']
- name: wrapper playbook for kitchen testing "ansible-ssh-hardening" with default settings
hosts: localhost
roles:
- ansible-ssh-hardening

View File

@ -1,24 +1,22 @@
# true if IPv6 is needed
network_ipv6_enable: false # sshd + ssh
# true if sshd should be started and enabled
ssh_server_enabled: true # sshd
# true if DNS resolutions are needed, look up the remote host name, defaults to false from 6.8, see: http://www.openssh.com/txt/release-6.8
ssh_use_dns: false # sshd
# true or value if compression is needed
ssh_compression: false # sshd
# For which components (client and server) to generate the configuration for. Can be useful when running against a client without an SSH server.
ssh_client_hardening: true # ssh
ssh_server_hardening: true # sshd
# true if CBC for ciphers is required. This is usually only necessary, if older M2M mechanism need to communicate with SSH, that don't have any of the configured secure ciphers enabled. CBC is a weak alternative. Anything weaker should be avoided and is thus not available.
ssh_client_cbc_required: false # ssh
ssh_server_cbc_required: false # sshd
# true if weaker HMAC mechanisms are required. This is usually only necessary, if older M2M mechanism need to communicate with SSH, that don't have any of the configured secure HMACs enabled.
ssh_client_weak_hmac: false # ssh
ssh_server_weak_hmac: false # sshd
# true if weaker Key-Exchange (KEX) mechanisms are required. This is usually only necessary, if older M2M mechanism need to communicate with SSH, that don't have any of the configured secure KEXs enabled.
ssh_client_weak_kex: false # ssh
ssh_server_weak_kex: false # sshd
# If true, password login is allowed. For sshd, it is always set to no password login.
# If true, password login is allowed
ssh_client_password_login: false # ssh
ssh_server_password_login: false # sshd
# ports on which ssh-server should listen
ssh_server_ports: ['22'] # sshd
@ -30,14 +28,17 @@ ssh_client_port: '22' # ssh
ssh_listen_to: ['0.0.0.0'] # sshd
# Host keys to look for when starting sshd.
ssh_host_key_files: ['/etc/ssh/ssh_host_rsa_key', '/etc/ssh/ssh_host_ecdsa_key', '/etc/ssh/ssh_host_ed25519_key'] # sshd
ssh_host_key_files: [] # sshd
# Specifies the maximum number of authentication attempts permitted per connection. Once the number of failures reaches half this value, additional failures are logged.
ssh_max_auth_retries: 2
ssh_client_alive_interval: 600 # sshd
ssh_client_alive_interval: 300 # sshd
ssh_client_alive_count: 3 # sshd
# Allow SSH Tunnels
ssh_permit_tunnel: false
# Hosts with custom options. # ssh
# Example:
# ssh_remote_hosts:
@ -53,12 +54,31 @@ ssh_allow_root_with_key: false # sshd
# false to disable TCP Forwarding. Set to true to allow TCP Forwarding.
ssh_allow_tcp_forwarding: false # sshd
# false to disable binding forwarded ports to non-loopback addresses. Set to true to force binding on wildcard address.
# Set to 'clientspecified' to allow the client to specify which address to bind to.
ssh_gateway_ports: false # sshd
# false to disable Agent Forwarding. Set to true to allow Agent Forwarding.
ssh_allow_agent_forwarding: false # sshd
# true if SSH has PAM support
ssh_pam_support: true
# false to disable pam authentication.
ssh_use_pam: false # sshd
# false to disable google 2fa authentication
ssh_google_auth: false # sshd
# false to disable pam device 2FA input
ssh_pam_device: false # sshd
# true if SSH support GSSAPI
ssh_gssapi_support: true
# true if SSH support Kerberos
ssh_kerberos_support: true
# if specified, login is disallowed for user names that match one of the patterns.
ssh_deny_users: '' # sshd
@ -71,6 +91,36 @@ ssh_deny_groups: '' # sshd
# if specified, login is allowed only for users whose primary group or supplementary group list matches one of the patterns.
ssh_allow_groups: '' # sshd
# change default file that contains the public keys that can be used for user authentication.
ssh_authorized_keys_file: '' # sshd
# specifies the file containing trusted certificate authorities public keys used to sign user certificates.
ssh_trusted_user_ca_keys_file: '' # sshd
# set the trusted certificate authorities public keys used to sign user certificates.
# Example:
# ssh_trusted_user_ca_keys:
# - 'ssh-rsa ... comment1'
# - 'ssh-rsa ... comment2'
ssh_trusted_user_ca_keys: [] # sshd
# specifies the file containing principals that are allowed. Only used if ssh_trusted_user_ca_keys_file is set.
# Example:
# ssh_authorized_principals_file: '/etc/ssh/auth_principals/%u'
#
# %h is replaced by the home directory of the user being authenticated, and %u is
# replaced by the username of that user. After expansion, the path is taken to be
# an absolute path or one relative to the user's home directory.
#
ssh_authorized_principals_file: '' # sshd
# list of hashes containing file paths and authorized principals. Only used if ssh_authorized_principals_file is set.
# Example:
# ssh_authorized_principals:
# - { path: '/etc/ssh/auth_principals/root', principals: [ 'root' ], owner: "{{ ssh_owner }}", group: "{{ ssh_group }}", directoryowner: "{{ ssh_owner }}", directorygroup: "{{ ssh_group}}" }
# - { path: '/etc/ssh/auth_principals/myuser', principals: [ 'masteradmin', 'webserver' ] }
ssh_authorized_principals: [] # sshd
# false to disable printing of the MOTD
ssh_print_motd: false # sshd
@ -86,16 +136,33 @@ ssh_print_debian_banner: false # sshd (Debian OS family only)
# true to enable sftp configuration
sftp_enabled: false
# false to disable sftp chroot
sftp_chroot: true
# change default sftp chroot location
sftp_chroot_dir: /home/%u
# enable experimental client roaming
ssh_client_roaming: false
# list of hashes (containing user and rules) to generate Match User blocks for.
ssh_server_match_user: false # sshd
# list of hashes (containing group and rules) to generate Match Group blocks for.
ssh_server_match_group: false # sshd
ssh_server_permit_environment_vars: false
# maximum number of concurrent unauthenticated connections to the SSH daemon
ssh_max_startups: '10:30:100' # sshd
ssh_ps53: 'yes'
ssh_ps59: 'sandbox'
ssh_macs: []
ssh_ciphers: []
ssh_kex: []
ssh_macs_53_default:
- hmac-ripemd160
- hmac-sha1
@ -105,26 +172,25 @@ ssh_macs_59_default:
- hmac-sha2-256
- hmac-ripemd160
ssh_macs_59_weak: "{{ ssh_macs_59_default + ['hmac-sha1'] }}"
ssh_macs_66_default:
- hmac-sha2-512-etm@openssh.com
- hmac-sha2-256-etm@openssh.com
- hmac-ripemd160-etm@openssh.com
- umac-128-etm@openssh.com
- hmac-sha2-512
- hmac-sha2-256
- hmac-ripemd160
ssh_macs_66_weak: "{{ ssh_macs_66_default + ['hmac-sha1'] }}"
ssh_macs_76_default:
- hmac-sha2-512-etm@openssh.com
- hmac-sha2-256-etm@openssh.com
- umac-128-etm@openssh.com
- hmac-sha2-512
- hmac-sha2-256
ssh_ciphers_53_default:
- aes256-ctr
- aes192-ctr
- aes128-ctr
ssh_ciphers_53_weak: "{{ ssh_ciphers_53_default + ['aes256-cbc', 'aes192-cbc', 'aes128-cbc'] }}"
ssh_ciphers_66_default:
- chacha20-poly1305@openssh.com
- aes256-gcm@openssh.com
@ -133,23 +199,25 @@ ssh_ciphers_66_default:
- aes192-ctr
- aes128-ctr
ssh_ciphers_66_weak: "{{ ssh_ciphers_66_default + ['aes256-cbc', 'aes192-cbc', 'aes128-cbc'] }}"
ssh_kex_59_default:
- diffie-hellman-group-exchange-sha256
ssh_kex_59_weak: "{{ ssh_kex_59_default + ['diffie-hellman-group14-sha1', 'diffie-hellman-group-exchange-sha1', 'diffie-hellman-group1-sha1'] }}"
ssh_kex_66_default:
- curve25519-sha256@libssh.org
- diffie-hellman-group-exchange-sha256
ssh_kex_66_weak: "{{ ssh_kex_66_default + ['diffie-hellman-group14-sha1', 'diffie-hellman-group-exchange-sha1', 'diffie-hellman-group1-sha1'] }}"
# directory where to store ssh_password policy
ssh_custom_selinux_dir: '/etc/selinux/local-policies'
sshd_moduli_file: '/etc/ssh/moduli'
sshd_moduli_minimum: 2048
# disable ChallengeResponseAuthentication
ssh_challengeresponseauthentication: false
# a list of public keys that are never accepted by the ssh server
ssh_server_revoked_keys: []
# Set to false to turn the role into a no-op. Useful when using
# the Ansible role dependency mechanism.
ssh_hardening_enabled: true

View File

@ -1,2 +1,4 @@
- name: restart sshd
service: name={{ sshd_service_name }} state=restarted
when: "(ssh_server_enabled|bool)"
become: yes

View File

@ -1 +1 @@
{install_date: 'Sun Apr 23 07:59:24 2017', version: 4.0.0}
{install_date: 'Mon Dec 17 12:48:22 2018', version: 5.0.0}

View File

@ -4,7 +4,7 @@ galaxy_info:
description: 'This Ansible role provides numerous security-related ssh configurations, providing all-round base protection.'
company: Hardening Framework Team
license: Apache License 2.0
min_ansible_version: '2.2.1'
min_ansible_version: '2.4'
platforms:
- name: EL
versions:
@ -19,6 +19,7 @@ galaxy_info:
versions:
- wheezy
- jessie
- name: Amazon
galaxy_tags:
- system
- security

View File

@ -0,0 +1,36 @@
---
# Install the 2FA packages and setup the config in PAM and SSH
- name: Install google authenticator PAM module
apt:
name: 'libpam-google-authenticator'
state: present
when: ansible_distribution == 'Debian' or ansible_distribution == 'Ubuntu'
- name: Install google authenticator PAM module
yum:
name: 'google-authenticator'
state: present
when: ansible_os_family == 'RedHat' or ansible_os_family == 'Oracle Linux'
- name: Add google auth module to PAM
pamd:
name: 'sshd'
type: 'auth'
control: 'required'
module_path: 'pam_google_authenticator.so'
- name: Remove password auth from PAM
pamd:
name: 'sshd'
type: 'auth'
control: 'substack'
module_path: 'password-auth'
state: absent
when: ansible_distribution == 'RedHat' or ansible_distribution == 'Oracle Linux' or ansible_distribution == 'Amazon'
- name: Remove password auth from PAM
replace:
dest: '/etc/pam.d/sshd'
regexp: '^@include common-auth'
replace: '#@include common-auth'
when: ansible_distribution == 'Debian' or ansible_distribution == 'Ubuntu'

View File

@ -0,0 +1,27 @@
---
- name: Set ssh CA pub keys
template:
src: 'trusted_user_ca_keys.j2'
dest: '{{ ssh_trusted_user_ca_keys_file }}'
mode: '0644'
owner: '{{ ssh_owner }}'
group: '{{ ssh_group }}'
notify: restart sshd
- name: Create ssh authorized principals directories
file:
path: '{{ item.path | dirname }}'
mode: '{{ item.directorymode | default(0700) }}'
owner: '{{ item.directoryowner | default(ssh_owner) }}'
group: '{{ item.directorygroup | default(ssh_group) }}'
state: directory
with_items: '{{ ssh_authorized_principals }}'
- name: Set ssh authorized principals
template:
src: 'authorized_principals.j2'
dest: '{{ item.path }}'
mode: '{{ item.filemode | default(0600) }}'
owner: '{{ item.owner| default(ssh_owner) }}'
group: '{{ item.group | default(ssh_group) }}'
with_items: '{{ ssh_authorized_principals }}'

View File

@ -0,0 +1,63 @@
---
- name: set hostkeys according to openssh-version
set_fact:
ssh_host_key_files: ['/etc/ssh/ssh_host_rsa_key', '/etc/ssh/ssh_host_ecdsa_key', '/etc/ssh/ssh_host_ed25519_key']
when: sshd_version.stdout >= '6.3' and not ssh_host_key_files
- name: set hostkeys according to openssh-version
set_fact:
ssh_host_key_files: ['/etc/ssh/ssh_host_rsa_key', '/etc/ssh/ssh_host_ecdsa_key']
when: sshd_version.stdout >= '6.0' and not ssh_host_key_files
- name: set hostkeys according to openssh-version
set_fact:
ssh_host_key_files: ['/etc/ssh/ssh_host_rsa_key']
when: sshd_version.stdout >= '5.3' and not ssh_host_key_files
###
- name: set macs according to openssh-version if openssh >= 7.6
set_fact:
ssh_macs: '{{ ssh_macs_76_default }}'
when: sshd_version.stdout >= '7.6' and not ssh_macs
- name: set macs according to openssh-version if openssh >= 6.6
set_fact:
ssh_macs: '{{ ssh_macs_66_default }}'
when: sshd_version.stdout >= '6.6' and not ssh_macs
- name: set macs according to openssh-version
set_fact:
ssh_macs: '{{ ssh_macs_59_default }}'
when: sshd_version.stdout >= '5.9' and not ssh_macs
- name: set macs according to openssh-version
set_fact:
ssh_macs: '{{ ssh_macs_53_default }}'
when: sshd_version.stdout >= '5.3' and not ssh_macs
###
- name: set ciphers according to openssh-version if openssh >= 6.6
set_fact:
ssh_ciphers: '{{ ssh_ciphers_66_default }}'
when: sshd_version.stdout >= '6.6' and not ssh_ciphers
- name: set ciphers according to openssh-version
set_fact:
ssh_ciphers: '{{ ssh_ciphers_53_default }}'
when: sshd_version.stdout >= '5.3' and not ssh_ciphers
###
- name: set kex according to openssh-version if openssh >= 6.6
set_fact:
ssh_kex: '{{ ssh_kex_66_default }}'
when: sshd_version.stdout >= '6.6' and not ssh_kex
- name: set kex according to openssh-version
set_fact:
ssh_kex: '{{ ssh_kex_59_default }}'
when: sshd_version.stdout >= '5.9' and not ssh_kex

View File

@ -0,0 +1,83 @@
---
- name: Set OS dependent variables
include_vars: '{{ item }}'
with_first_found:
- '{{ ansible_distribution }}_{{ ansible_distribution_major_version }}.yml'
- '{{ ansible_distribution }}.yml'
- '{{ ansible_os_family }}_{{ ansible_distribution_major_version }}.yml'
- '{{ ansible_os_family }}.yml'
- name: get openssh-version
shell: ssh -V 2>&1 | sed -r 's/.*_([0-9]*\.[0-9]).*/\1/g'
args:
executable: /bin/sh
changed_when: false
register: sshd_version
check_mode: no
- name: include tasks to create crypo-vars
include_tasks: crypto.yml
- name: create revoked_keys and set permissions to root/600
template:
src: 'revoked_keys.j2'
dest: '/etc/ssh/revoked_keys'
mode: '0600'
owner: '{{ ssh_owner }}'
group: '{{ ssh_group }}'
notify: restart sshd
when: ssh_server_hardening
- name: create sshd_config and set permissions to root/600
template:
src: 'opensshd.conf.j2'
dest: '/etc/ssh/sshd_config'
mode: '0600'
owner: '{{ ssh_owner }}'
group: '{{ ssh_group }}'
validate: '/usr/sbin/sshd -T -f %s'
notify: restart sshd
when: ssh_server_hardening
- name: create ssh_config and set permissions to root/644
template:
src: 'openssh.conf.j2'
dest: '/etc/ssh/ssh_config'
mode: '0644'
owner: '{{ ssh_owner }}'
group: '{{ ssh_group }}'
when: ssh_client_hardening
- name: Check if {{ sshd_moduli_file }} contains weak DH parameters
shell: awk '$5 < {{ sshd_moduli_minimum }}' {{ sshd_moduli_file }}
register: sshd_register_moduli
changed_when: false
check_mode: no
- name: remove all small primes
shell: awk '$5 >= {{ sshd_moduli_minimum }}' {{ sshd_moduli_file }} > {{ sshd_moduli_file }}.new ;
[ -r {{ sshd_moduli_file }}.new -a -s {{ sshd_moduli_file }}.new ] && mv {{ sshd_moduli_file }}.new {{ sshd_moduli_file }} || true
notify: restart sshd
when: sshd_register_moduli.stdout
- name: include tasks to setup ca keys and principals
include_tasks: ca_keys_and_principals.yml
when: ssh_trusted_user_ca_keys_file != ''
- name: include tasks to setup 2FA
include_tasks: 2fa.yml
when:
- ssh_use_pam
- ssh_challengeresponseauthentication
- ssh_google_auth
- name: test to see if selinux is installed and running
command: getenforce
register: sestatus
failed_when: false
changed_when: false
check_mode: no
- name: include selinux specific tasks
include_tasks: selinux.yml
when: sestatus.rc == 0

View File

@ -1,105 +1,4 @@
---
- name: Set OS dependent variables
include_vars: "{{ item }}"
with_first_found:
- "{{ ansible_distribution }}_{{ ansible_distribution_major_version }}.yml"
- "{{ ansible_distribution }}.yml"
- "{{ ansible_os_family }}_{{ ansible_distribution_major_version }}.yml"
- "{{ ansible_os_family }}.yml"
- name: get openssh-version
shell: ssh -V 2>&1 | sed -r 's/.*_([0-9]*\.[0-9]).*/\1/g'
changed_when: false
register: sshd_version
- name: set hostkeys according to openssh-version
set_fact:
ssh_host_key_files: ['/etc/ssh/ssh_host_rsa_key']
when: sshd_version.stdout >= '5.3'
- name: set hostkeys according to openssh-version
set_fact:
ssh_host_key_files: ['/etc/ssh/ssh_host_rsa_key', '/etc/ssh/ssh_host_ecdsa_key']
when: sshd_version.stdout >= '6.0'
- name: set hostkeys according to openssh-version
set_fact:
ssh_host_key_files: ['/etc/ssh/ssh_host_rsa_key', '/etc/ssh/ssh_host_ecdsa_key', '/etc/ssh/ssh_host_ed25519_key']
when: sshd_version.stdout >= '6.3'
- name: create sshd_config and set permissions to root/600
template: src='opensshd.conf.j2' dest='/etc/ssh/sshd_config' mode=0600 owner="{{ ssh_owner }}" group="{{ ssh_group }}" validate="/usr/sbin/sshd -T -f %s"
notify: restart sshd
when: ssh_server_hardening
- name: create ssh_config and set permissions to root/644
template: src='openssh.conf.j2' dest='/etc/ssh/ssh_config' mode=0644 owner="{{ ssh_owner }}" group="{{ ssh_group }}"
when: ssh_client_hardening
- name: Check if /etc/ssh/moduli contains weak DH parameters
shell: awk '$5 < {{ sshd_moduli_minimum }}' /etc/ssh/moduli
register: sshd_register_moduli
changed_when: false
check_mode: no
- name: remove all small primes
shell: awk '$5 >= {{ sshd_moduli_minimum }}' /etc/ssh/moduli > /etc/ssh/moduli.new ;
[ -r /etc/ssh/moduli.new -a -s /etc/ssh/moduli.new ] && mv /etc/ssh/moduli.new /etc/ssh/moduli || true
notify: restart sshd
when: sshd_register_moduli.stdout
- name: test to see if selinux is running
command: getenforce
register: sestatus
failed_when: false
changed_when: false
check_mode: no
- block: # only runs when selinux is running
- name: install selinux dependencies when selinux is installed on RHEL or Oracle Linux
yum: name="{{item}}" state=installed
with_items:
- policycoreutils-python
- checkpolicy
when: ansible_os_family == 'RedHat' or ansible_os_family == 'Oracle Linux'
- name: install selinux dependencies when selinux is installed on Debian or Ubuntu
apt: name="{{item}}" state=installed
with_items:
- policycoreutils
- checkpolicy
when: ansible_distribution == 'Debian' or ansible_distribution == 'Ubuntu'
- name: check if ssh_password module is already installed
shell: "semodule -l| grep ssh_password"
register: ssh_password_module
failed_when: false
changed_when: false
check_mode: no
# The following tasks only get executed when selinux is in state enforcing, UsePam is "no" and the ssh_password module is installed.
# See this issue for more info: https://github.com/hardening-io/ansible-ssh-hardening/issues/23
- block:
- name: Create selinux custom policy drop folder
file: path='{{ ssh_custom_selinux_dir }}' state=directory owner=root group=root mode=0750
- name: Distributing custom selinux policies
copy: src='ssh_password' dest='{{ ssh_custom_selinux_dir }}'
- name: check and compile policy
shell: checkmodule -M -m -o {{ ssh_custom_selinux_dir }}/ssh_password.mod {{ ssh_custom_selinux_dir }}/ssh_password
- name: create selinux policy module package
shell: semodule_package -o {{ ssh_custom_selinux_dir }}/ssh_password.pp -m {{ ssh_custom_selinux_dir }}/ssh_password.mod
- name: install selinux policy
shell: semodule -i {{ ssh_custom_selinux_dir }}/ssh_password.pp
when: not ssh_use_pam and sestatus.stdout != 'Disabled' and ssh_password_module.stdout.find('ssh_password') != 0
# The following tasks only get executed when selinux is in state enforcing, UsePam is "yes" and the ssh_password module is installed.
- name: remove selinux-policy when Pam is used, because Allowing sshd to read the shadow file directly is considered a potential security risk (http://danwalsh.livejournal.com/12333.html)
shell: semodule -r ssh_password
when: ssh_use_pam and ssh_password_module.stdout.find('ssh_password') == 0
when: sestatus.rc == 0
- include_tasks: hardening.yml
when: ssh_hardening_enabled

View File

@ -0,0 +1,57 @@
---
- name: install selinux dependencies when selinux is installed on RHEL or Oracle Linux
package:
name: '{{ item }}'
state: present
with_items:
- 'policycoreutils-python'
- 'checkpolicy'
when: ansible_os_family == 'RedHat' or ansible_os_family == 'Oracle Linux'
- name: install selinux dependencies when selinux is installed on Debian or Ubuntu
apt:
name: '{{ item }}'
state: present
with_items:
- 'policycoreutils'
- 'checkpolicy'
when: ansible_distribution == 'Debian' or ansible_distribution == 'Ubuntu'
- name: check if ssh_password module is already installed
shell: 'semodule -l | grep ssh_password'
register: ssh_password_module
failed_when: false
changed_when: false
check_mode: no
# The following tasks only get executed when selinux is in state enforcing, UsePam is 'no' and the ssh_password module is installed.
# See this issue for more info: https://github.com/hardening-io/ansible-ssh-hardening/issues/23
- block:
- name: Create selinux custom policy drop folder
file:
path: '{{ ssh_custom_selinux_dir }}'
state: 'directory'
owner: 'root'
group: 'root'
mode: '0750'
- name: Distributing custom selinux policies
copy:
src: 'ssh_password'
dest: '{{ ssh_custom_selinux_dir }}'
- name: check and compile policy
shell: checkmodule -M -m -o {{ ssh_custom_selinux_dir }}/ssh_password.mod {{ ssh_custom_selinux_dir }}/ssh_password
- name: create selinux policy module package
shell: semodule_package -o {{ ssh_custom_selinux_dir }}/ssh_password.pp -m {{ ssh_custom_selinux_dir }}/ssh_password.mod
- name: install selinux policy
shell: semodule -i {{ ssh_custom_selinux_dir }}/ssh_password.pp
when: not ssh_use_pam and sestatus.stdout != 'Disabled' and ssh_password_module.stdout.find('ssh_password') != 0
# The following tasks only get executed when selinux is installed, UsePam is 'yes' and the ssh_password module is installed.
- name: remove selinux-policy when Pam is used, because Allowing sshd to read the shadow file directly is considered a potential security risk (http://danwalsh.livejournal.com/12333.html)
command: semodule -r ssh_password
when: ssh_use_pam and ssh_password_module.stdout.find('ssh_password') == 0

View File

@ -0,0 +1,5 @@
# {{ansible_managed|comment}}
{% for principal in item.principals %}
{{ principal }}
{% endfor %}

View File

@ -1,4 +1,4 @@
# {{ansible_managed}}
# {{ansible_managed|comment}}
# This is the ssh client system-wide configuration file.
# See ssh_config(5) for more information on any settings used. Comments will be added only to clarify why a configuration was chosen.
@ -45,44 +45,23 @@ CheckHostIP yes
# Always ask before adding keys to the `known_hosts` file. Do not set to `yes`.
StrictHostKeyChecking ask
# **Ciphers** -- If your clients don't support CTR (eg older versions), cbc will be added
# CBC: is true if you want to connect with OpenSSL-base libraries
# eg ruby Net::SSH::Transport::CipherFactory requires cbc-versions of the given openssh ciphers to work
# -- see: (http://net-ssh.github.com/net-ssh/classes/Net/SSH/Transport/CipherFactory.html)
#
{% if ssh_client_cbc_required -%}
{% if (ansible_distribution == 'Ubuntu' and ansible_distribution_version >= '14.04') or (ansible_distribution == 'Debian' and ansible_distribution_version >= '8') or (ansible_os_family in ['Oracle Linux', 'RedHat'] and ansible_distribution_major_version >= '7') or (ansible_distribution == 'FreeBSD' and ansible_distribution_version >= '11') -%}
Ciphers {{ ssh_ciphers_66_weak | join(',') }}
{% else -%}
Ciphers {{ ssh_ciphers_53_weak | join(',') }}
{% endif %}
{% else -%}
{% if (ansible_distribution == 'Ubuntu' and ansible_distribution_version >= '14.04') or (ansible_distribution == 'Debian' and ansible_distribution_version >= '8') or (ansible_os_family in ['Oracle Linux', 'RedHat'] and ansible_distribution_major_version >= '7') or (ansible_distribution == 'FreeBSD' and ansible_distribution_version >= '11') -%}
Ciphers {{ ssh_ciphers_66_default | join(',') }}
{% else -%}
Ciphers {{ ssh_ciphers_53_default | join(',') }}
{% endif %}
{% endif %}
{# This outputs "Ciphers <list-of-ciphers>" if ssh_ciphers is defined or "#Ciphers" if ssh_ciphers is undefined #}
{{ "Ciphers "+ssh_ciphers| join(',') if ssh_ciphers else "Ciphers"|comment }}
# **Hash algorithms** -- Make sure not to use SHA1 for hashing, unless it is really necessary.
# Weak HMAC is sometimes required if older package versions are used
# eg Ruby's Net::SSH at around 2.2.* doesn't support sha2 for hmac, so this will have to be set true in this case.
#
{% if ssh_client_weak_hmac -%}
{% if (ansible_distribution == 'Ubuntu' and ansible_distribution_version >= '14.04') or (ansible_distribution == 'Debian' and ansible_distribution_version >= '8') or (ansible_os_family in ['Oracle Linux', 'RedHat'] and ansible_distribution_major_version >= '7') or (ansible_distribution == 'FreeBSD' and ansible_distribution_version >= '11') -%}
MACs {{ ssh_macs_66_weak | join(',') }}
{% elif ansible_os_family in ['Oracle Linux', 'RedHat'] and ansible_distribution_major_version <= '6' -%}
MACs {{ ssh_macs_53_default | join(',') }}
{% endif %}
{% else -%}
{% if (ansible_distribution == 'Ubuntu' and ansible_distribution_version >= '14.04') or (ansible_distribution == 'Debian' and ansible_distribution_version >= '8') or (ansible_os_family in ['Oracle Linux', 'RedHat'] and ansible_distribution_major_version >= '7') or (ansible_distribution == 'FreeBSD' and ansible_distribution_version >= '11') -%}
MACs {{ ssh_macs_66_default | join(',') }}
{% elif ansible_os_family in ['Oracle Linux', 'RedHat'] and ansible_distribution_major_version <= '6' -%}
MACs {{ ssh_macs_53_default | join(',') }}
{% else -%}
MACs {{ ssh_macs_59_default | join(',') }}
{% endif %}
{% endif %}
{# This outputs "MACs <list-of-macs>" if ssh_macs is defined or "#MACs" if ssh_macs is undefined #}
{{ "MACs "+ssh_macs| join(',') if ssh_macs else "MACs"|comment }}
# Alternative setting, if OpenSSH version is below v5.9
#MACs hmac-ripemd160
@ -90,23 +69,10 @@ StrictHostKeyChecking ask
# **Key Exchange Algorithms** -- Make sure not to use SHA1 for kex, unless it is really necessary
# Weak kex is sometimes required if older package versions are used
# eg ruby's Net::SSH at around 2.2.* doesn't support sha2 for kex, so this will have to be set true in this case.
#
{% if (ansible_distribution == 'Ubuntu' and ansible_distribution_version >= '14.04') or (ansible_distribution == 'Debian' and ansible_distribution_version >= '8') or (ansible_os_family in ['Oracle Linux', 'RedHat'] and ansible_distribution_major_version >= '7') or (ansible_distribution == 'FreeBSD' and ansible_distribution_version >= '11') -%}
{% if ssh_client_weak_kex -%}
KexAlgorithms {{ ssh_kex_66_weak | join(',') }}
{% else -%}
KexAlgorithms {{ ssh_kex_66_default | join(',') }}
{% endif %}
{% else -%}
{% if ansible_os_family in ['Oracle Linux', 'RedHat'] and ansible_distribution_major_version <= '6' -%}
#KexAlgorithms
{% elif ssh_client_weak_kex -%}
KexAlgorithms {{ ssh_kex_59_weak | join(',') }}
{% else -%}
KexAlgorithms {{ ssh_kex_59_default | join(',') }}
{% endif %}
{% endif %}
# based on: https://bettercrypto.org/static/applied-crypto-hardening.pdf
{# This outputs "KexAlgorithms <list-of-algos>" if ssh_kex is defined or "#KexAlgorithms" if ssh_kex is undefined #}
{{ "KexAlgorithms "+ssh_kex| join(',') if ssh_kex else "KexAlgorithms"|comment }}
# Disable agent forwarding, since local agent could be accessed through forwarded connection.
ForwardAgent no
@ -116,10 +82,11 @@ ForwardX11 no
# Never use host-based authentication. It can be exploited.
HostbasedAuthentication no
{% if sshd_version.stdout | float < 7.4 -%}
RhostsRSAAuthentication no
# Enable RSA authentication via identity files.
RSAAuthentication yes
{% endif %}
# Disable password-based authentication, it can allow for potentially easier brute-force attacks.
PasswordAuthentication {{ 'yes' if ssh_client_password_login else 'no' }}
@ -144,5 +111,7 @@ Compression yes
#EscapeChar ~
#VisualHostKey yes
{% if sshd_version.stdout | float <= 7.1 -%}
# Disable experimental client roaming. This is known to cause potential issues with secrets being disclosed to malicious servers and defaults to being disabled.
UseRoaming {{ 'yes' if ssh_client_roaming else 'no' }}
{% endif %}

View File

@ -1,4 +1,4 @@
# {{ansible_managed}}
# {{ansible_managed|comment}}
# This is the ssh client system-wide configuration file.
# See sshd_config(5) for more information on any settings used. Comments will be added only to clarify why a configuration was chosen.
@ -7,7 +7,7 @@
# ===================
# Either disable or only allowssh root login via certificates.
PermitRootLogin {{ 'without-password' if ssh_allow_root_with_key else 'no' }}
PermitRootLogin {{ 'without-password' if (ssh_allow_root_with_key|bool) else 'no' }}
# Define which port sshd should listen to. Default to `22`.
{% for port in ssh_server_ports -%}
@ -15,7 +15,7 @@ Port {{port}}
{% endfor %}
# Address family should always be limited to the active network configuration.
AddressFamily {{ 'any' if network_ipv6_enable else 'inet' }}
AddressFamily {{ 'any' if (network_ipv6_enable|bool) else 'inet' }}
# Define which addresses sshd should listen to. Default to `0.0.0.0`, ie make sure you put your desired address in here, since otherwise sshd will listen to everyone.
{% for address in ssh_listen_to -%}
@ -48,40 +48,17 @@ LogLevel VERBOSE
# eg ruby Net::SSH::Transport::CipherFactory requires cbc-versions of the given openssh ciphers to work
# -- see: (http://net-ssh.github.com/net-ssh/classes/Net/SSH/Transport/CipherFactory.html)
#
{% if ssh_server_cbc_required -%}
{% if (ansible_distribution == 'Ubuntu' and ansible_distribution_version >= '14.04') or (ansible_distribution == 'Debian' and ansible_distribution_version >= '8') or (ansible_os_family in ['Oracle Linux', 'RedHat'] and ansible_distribution_major_version >= '7') or (ansible_distribution == 'FreeBSD' and ansible_distribution_version >= '11') -%}
Ciphers {{ ssh_ciphers_66_weak | join(',') }}
{% else %}
Ciphers {{ ssh_ciphers_53_weak | join(',') }}
{% endif %}
{% else -%}
{% if (ansible_distribution == 'Ubuntu' and ansible_distribution_version >= '14.04') or (ansible_distribution == 'Debian' and ansible_distribution_version >= '8') or (ansible_os_family in ['Oracle Linux', 'RedHat'] and ansible_distribution_major_version >= '7') or (ansible_distribution == 'FreeBSD' and ansible_distribution_version >= '11') -%}
Ciphers {{ ssh_ciphers_66_default | join(',') }}
{% else -%}
Ciphers {{ ssh_ciphers_53_default | join(',') }}
{% endif %}
{% endif %}
{# This outputs "Ciphers <list-of-ciphers>" if ssh_ciphers is defined or "#Ciphers" if ssh_ciphers is undefined #}
{{ "Ciphers "+ssh_ciphers| join(',') if ssh_ciphers else "Ciphers"|comment }}
# **Hash algorithms** -- Make sure not to use SHA1 for hashing, unless it is really necessary.
# Weak HMAC is sometimes required if older package versions are used
# eg Ruby's Net::SSH at around 2.2.* doesn't support sha2 for hmac, so this will have to be set true in this case.
#
{% if ssh_server_weak_hmac -%}
{% if (ansible_distribution == 'Ubuntu' and ansible_distribution_version >= '14.04') or (ansible_distribution == 'Debian' and ansible_distribution_version >= '8') or (ansible_os_family in ['Oracle Linux', 'RedHat'] and ansible_distribution_major_version >= '7') or (ansible_distribution == 'FreeBSD' and ansible_distribution_version >= '11') -%}
MACs {{ ssh_macs_66_weak | join(',') }}
{% elif ansible_os_family in ['Oracle Linux', 'RedHat'] and ansible_distribution_major_version <= '6' -%}
MACs {{ ssh_macs_53_default | join(',') }}
{% endif %}
{% else -%}
{% if (ansible_distribution == 'Ubuntu' and ansible_distribution_version >= '14.04') or (ansible_distribution == 'Debian' and ansible_distribution_version >= '8') or (ansible_os_family in ['Oracle Linux', 'RedHat'] and ansible_distribution_major_version >= '7') or (ansible_distribution == 'FreeBSD' and ansible_distribution_version >= '11') -%}
MACs {{ ssh_macs_66_default | join(',') }}
{% elif ansible_os_family in ['Oracle Linux', 'RedHat'] and ansible_distribution_major_version <= '6' -%}
MACs {{ ssh_macs_53_default | join(',') }}
{% else -%}
MACs {{ ssh_macs_59_default | join(',') }}
{% endif %}
{% endif %}
{# This outputs "MACs <list-of-macs>" if ssh_macs is defined or "#MACs" if ssh_macs is undefined #}
{{ "MACs "+ssh_macs| join(',') if ssh_macs else "MACs"|comment }}
# Alternative setting, if OpenSSH version is below v5.9
#MACs hmac-ripemd160
@ -90,34 +67,22 @@ LogLevel VERBOSE
# Weak kex is sometimes required if older package versions are used
# eg ruby's Net::SSH at around 2.2.* doesn't support sha2 for kex, so this will have to be set true in this case.
# based on: https://bettercrypto.org/static/applied-crypto-hardening.pdf
{% if (ansible_distribution == 'Ubuntu' and ansible_distribution_version >= '14.04') or (ansible_distribution == 'Debian' and ansible_distribution_version >= '8') or (ansible_os_family in ['Oracle Linux', 'RedHat'] and ansible_distribution_major_version >= '7') or (ansible_distribution == 'FreeBSD' and ansible_distribution_version >= '11') -%}
{% if ssh_server_weak_kex -%}
KexAlgorithms {{ ssh_kex_66_weak | join(',') }}
{% else -%}
KexAlgorithms {{ ssh_kex_66_default | join(',') }}
{% endif %}
{% else -%}
{% if ansible_os_family in ['Oracle Linux', 'RedHat'] and ansible_distribution_major_version <= '6' -%}
#KexAlgorithms
{% elif ssh_server_weak_kex -%}
KexAlgorithms {{ sshd_kex_59_weak | join(',') }}
{% else -%}
KexAlgorithms {{ ssh_kex_59_default | join(',') }}
{% endif %}
{% endif %}
{# This outputs "KexAlgorithms <list-of-algos>" if ssh_kex is defined or "#KexAlgorithms" if ssh_kex is undefined #}
{{ "KexAlgorithms "+ssh_kex| join(',') if ssh_kex else "KexAlgorithms"|comment }}
# Authentication
# --------------
# Secure Login directives.
UseLogin no
{% if sshd_version.stdout | float < 7.5 -%}
UsePrivilegeSeparation {% if (ansible_distribution == 'Debian' and ansible_distribution_major_version <= '6') or (ansible_os_family in ['Oracle Linux', 'RedHat'] and ansible_distribution_major_version <= '6') -%}{{ssh_ps53}}{% else %}{{ssh_ps59}}{% endif %}
{% endif %}
PermitUserEnvironment no
LoginGraceTime 30s
MaxAuthTries {{ssh_max_auth_retries}}
MaxSessions 10
MaxStartups 10:30:100
MaxStartups {{ssh_max_startups}}
# Enable public key authentication
PubkeyAuthentication yes
@ -128,22 +93,37 @@ IgnoreUserKnownHosts yes
HostbasedAuthentication no
# Enable PAM to enforce system wide rules
UsePAM {{ 'yes' if ssh_use_pam else 'no' }}
{% if ssh_pam_support -%}
UsePAM {{ 'yes' if (ssh_use_pam|bool) else 'no' }}
{% endif %}
{% if ssh_google_auth %}
# Force public key auth then ask for google auth code
AuthenticationMethods publickey,keyboard-interactive
{% endif %}
# Force public key auth then ask for pam device input
{% if ssh_pam_device %}
AuthenticationMethods publickey,keyboard-interactive:pam
{% endif %}
# Disable password-based authentication, it can allow for potentially easier brute-force attacks.
PasswordAuthentication no
PasswordAuthentication {{ 'yes' if (ssh_server_password_login|bool) else 'no' }}
PermitEmptyPasswords no
ChallengeResponseAuthentication {{ 'yes' if ssh_challengeresponseauthentication else 'no' }}
ChallengeResponseAuthentication {{ 'yes' if (ssh_challengeresponseauthentication|bool) else 'no' }}
{% if ssh_kerberos_support -%}
# Only enable Kerberos authentication if it is configured.
KerberosAuthentication no
KerberosOrLocalPasswd no
KerberosTicketCleanup yes
#KerberosGetAFSToken no
{% endif %}
{% if ssh_gssapi_support -%}
# Only enable GSSAPI authentication if it is configured.
GSSAPIAuthentication no
GSSAPICleanupCredentials yes
{% endif %}
# In case you don't use PAM (`UsePAM no`), you can alternatively restrict users and groups here. For key-based authentication this is not necessary, since all keys must be explicitely enabled.
{% if ssh_deny_users -%}
@ -162,6 +142,17 @@ DenyGroups {{ssh_deny_groups}}
AllowGroups {{ssh_allow_groups}}
{% endif %}
{% if ssh_authorized_keys_file %}
AuthorizedKeysFile {{ ssh_authorized_keys_file }}
{% endif %}
{% if ssh_trusted_user_ca_keys_file %}
TrustedUserCAKeys {{ ssh_trusted_user_ca_keys_file }}
{% if ssh_authorized_principals_file %}
AuthorizedPrincipalsFile {{ ssh_authorized_principals_file }}
{% endif %}
{% endif %}
# Network
# -------
@ -173,52 +164,104 @@ ClientAliveInterval {{ssh_client_alive_interval}}
ClientAliveCountMax {{ssh_client_alive_count}}
# Disable tunneling
PermitTunnel no
PermitTunnel {{ 'yes' if (ssh_permit_tunnel|bool) else 'no' }}
# Disable forwarding tcp connections.
# no real advantage without denied shell access
AllowTcpForwarding {{ 'yes' if ssh_allow_tcp_forwarding else 'no' }}
AllowTcpForwarding {{ 'yes' if (ssh_allow_tcp_forwarding|bool) else 'no' }}
# Disable agent formwarding, since local agent could be accessed through forwarded connection.
# no real advantage without denied shell access
AllowAgentForwarding {{ 'yes' if ssh_allow_agent_forwarding else 'no' }}
AllowAgentForwarding {{ 'yes' if (ssh_allow_agent_forwarding|bool) else 'no' }}
{% if ssh_gateway_ports|bool %}
# Port forwardings are forced to bind to the wildcard address
GatewayPorts yes
{% elif ssh_gateway_ports == 'clientspecified' %}
# Clients allowed to specify which address to bind port forwardings to
GatewayPorts clientspecified
{% else %}
# Do not allow remote port forwardings to bind to non-loopback addresses.
GatewayPorts no
{% endif %}
# Disable X11 forwarding, since local X11 display could be accessed through forwarded connection.
X11Forwarding no
X11UseLocalhost yes
# User environment configuration
# ==============================
{% if ssh_server_permit_environment_vars %}
PermitUserEnvironment yes
{% for item in ssh_server_permit_environment_vars %}
AcceptEnv {{ item }}
{% endfor %}
{% else %}
PermitUserEnvironment no
{% endif %}
# Misc. configuration
# ===================
PrintMotd {{ 'yes' if ssh_print_motd else 'no' }}
Compression {{ 'yes' if (ssh_compression|bool) else 'no' }}
UseDNS {{ 'yes' if (ssh_use_dns|bool) else 'no' }}
PrintMotd {{ 'yes' if (ssh_print_motd|bool) else 'no' }}
{% if ansible_os_family != 'FreeBSD' %}
PrintLastLog {{ 'yes' if ssh_print_last_log else 'no' }}
PrintLastLog {{ 'yes' if (ssh_print_last_log|bool) else 'no' }}
{% endif %}
Banner {{ '/etc/ssh/banner.txt' if ssh_banner else 'none' }}
Banner {{ '/etc/ssh/banner.txt' if (ssh_banner|bool) else 'none' }}
{% if ansible_os_family == 'Debian' %}
DebianBanner {{ 'yes' if ssh_print_debian_banner else 'no' }}
DebianBanner {{ 'yes' if (ssh_print_debian_banner|bool) else 'no' }}
{% endif %}
# Reject keys that are explicitly blacklisted
RevokedKeys /etc/ssh/revoked_keys
{% if sftp_enabled %}
# SFTP matching configuration
# ===========================
# Configuration, in case SFTP is used
## override default of no subsystems
## Subsystem sftp /opt/app/openssh5/libexec/sftp-server
# override default of no subsystems
# Subsystem sftp /opt/app/openssh5/libexec/sftp-server
Subsystem sftp internal-sftp -l INFO -f LOCAL6
#
## These lines must appear at the *end* of sshd_config
# These lines must appear at the *end* of sshd_config
Match Group sftponly
ForceCommand internal-sftp -l INFO -f LOCAL6
ChrootDirectory {{ sftp_chroot_dir }}
AllowTcpForwarding no
AllowAgentForwarding no
PasswordAuthentication no
PermitRootLogin no
X11Forwarding no
ForceCommand internal-sftp -l INFO -f LOCAL6
{% if sftp_chroot %}
ChrootDirectory {{ sftp_chroot_dir }}
{% endif %}
AllowTcpForwarding no
AllowAgentForwarding no
PasswordAuthentication no
PermitRootLogin no
X11Forwarding no
{% endif %}
{% if ssh_server_match_group %}
# Group matching configuration
# ============================
{% for item in ssh_server_match_group %}
Match Group {{ item.group }}
{{ item.rules | indent(4) }}
{% endfor %}
{% endif %}
{% if ssh_server_match_user %}
# User matching configuration
# ===========================
{% for item in ssh_server_match_user %}
Match User {{ item.user }}
{{ item.rules | indent(4) }}
{% endfor %}
{% endif %}

Some files were not shown because too many files have changed in this diff Show More