diff --git a/.github_changelog_generator b/.github_changelog_generator new file mode 100644 index 0000000..312d7f8 --- /dev/null +++ b/.github_changelog_generator @@ -0,0 +1 @@ +unreleased=false diff --git a/.kitchen.vagrant.yml b/.kitchen.vagrant.yml index 04340dd..a2a4126 100644 --- a/.kitchen.vagrant.yml +++ b/.kitchen.vagrant.yml @@ -62,10 +62,6 @@ platforms: - name: oracle-7 driver_config: box: boxcutter/ol72 -- 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 - name: debian-8 driver_config: box: debian-8 diff --git a/.kitchen.yml b/.kitchen.yml index 524f716..97831fd 100644 --- a/.kitchen.yml +++ b/.kitchen.yml @@ -21,8 +21,9 @@ provisioner: roles_path: ../ansible-nginx-hardening/ http_proxy: <%= ENV['http_proxy'] || nil %> https_proxy: <%= ENV['https_proxy'] || nil %> - playbook: default.yml + playbook: tests/test.yml requirements_path: requirements.yml + galaxy_ignore_certs: true platforms: - name: centos6-ansible-latest @@ -33,6 +34,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 @@ -40,11 +45,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 @@ -53,10 +58,9 @@ platforms: driver: image: rndmh3ro/docker-ubuntu1604-ansible:latest platform: ubuntu -- name: debian7-ansible-latest - driver: - image: rndmh3ro/docker-debian7-ansible:latest - platform: debian + run_command: /sbin/init + provision_command: + - systemctl enable ssh.service - name: debian8-ansible-latest driver: image: rndmh3ro/docker-debian8-ansible:latest @@ -65,12 +69,41 @@ 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 sudo: true inspec_tests: - - https://github.com/dev-sec/nginx-baseline + - ../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 diff --git a/.travis.yml b/.travis.yml index eec25ca..3102621 100644 --- a/.travis.yml +++ b/.travis.yml @@ -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,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,20 +29,21 @@ env: 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: 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}' @@ -53,13 +54,14 @@ script: - '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 install -r /etc/ansible/roles/ansible-nginx-hardening/requirements.yml -p /etc/ansible/roles/' + - '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/default.yml -vv' + - '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})' + #- '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/ diff --git a/Gemfile b/Gemfile index c11b3bf..4791b15 100644 --- a/Gemfile +++ b/Gemfile @@ -16,3 +16,7 @@ end group :tools do gem 'github_changelog_generator', '~> 1' end + +gem 'kitchen-dokken' + +gem 'rb-readline' diff --git a/default.yml b/default.yml deleted file mode 100644 index 8020c5f..0000000 --- a/default.yml +++ /dev/null @@ -1,6 +0,0 @@ ---- -- name: wrapper playbook for kitchen testing "ansible-nginx-hardening" with custom settings - hosts: localhost - roles: - - geerlingguy.nginx - - ansible-nginx-hardening diff --git a/defaults/main.yml b/defaults/main.yml index 2a84b97..13bc790 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -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" diff --git a/handlers/main.yml b/handlers/main.yml index e2dd289..97c58cb 100644 --- a/handlers/main.yml +++ b/handlers/main.yml @@ -1,2 +1,4 @@ -- name: reload nginx - service: name={{ nginx_service_name }} state=reloaded +- name: restart nginx + service: + name: "nginx" + state: restarted diff --git a/requirements.yml b/requirements.yml index 86981f9..0560ff5 100644 --- a/requirements.yml +++ b/requirements.yml @@ -1 +1,2 @@ +- src: nginxinc.nginx - src: geerlingguy.nginx diff --git a/spec/travis.yml b/spec/travis.yml deleted file mode 100644 index bb64498..0000000 --- a/spec/travis.yml +++ /dev/null @@ -1,4 +0,0 @@ -- hosts: localhost - roles: - - geerlingguy.nginx - - ansible-nginx-hardening diff --git a/tasks/main.yml b/tasks/main.yml index bd821c0..b285c26 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -1,43 +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: reload nginx + 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: reload nginx + 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 diff --git a/templates/hardening.conf.j2 b/templates/hardening.conf.j2 index eb5a9cd..a2ca2e6 100644 --- a/templates/hardening.conf.j2 +++ b/templates/hardening.conf.j2 @@ -1,15 +1,16 @@ # {{ansible_managed|comment}} # Additional configuration for Nginx. -client_header_buffer_size {{nginx_client_header_buffer_size}}; +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_dhparam {{nginx_dh_param}}; +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 %} diff --git a/tests/test.yml b/tests/test.yml new file mode 100644 index 0000000..e180140 --- /dev/null +++ b/tests/test.yml @@ -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 diff --git a/vars/Debian.yml b/vars/Debian.yml deleted file mode 100644 index 3d85fa5..0000000 --- a/vars/Debian.yml +++ /dev/null @@ -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' diff --git a/vars/Oracle Linux.yml b/vars/Oracle Linux.yml deleted file mode 100644 index 6ec8bc2..0000000 --- a/vars/Oracle Linux.yml +++ /dev/null @@ -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' diff --git a/vars/RedHat.yml b/vars/RedHat.yml deleted file mode 100644 index 6ec8bc2..0000000 --- a/vars/RedHat.yml +++ /dev/null @@ -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' diff --git a/vars/main.yml b/vars/main.yml index e69de29..ed97d53 100644 --- a/vars/main.yml +++ b/vars/main.yml @@ -0,0 +1 @@ +---