Skip to content

Commit

Permalink
Merge pull request dev-sec#162 from dev-sec/refactor
Browse files Browse the repository at this point in the history
yaml-lint update, refactor tasks
  • Loading branch information
rndmh3ro authored Jun 29, 2018
2 parents d2d9656 + 9e6b428 commit d7e6f74
Show file tree
Hide file tree
Showing 10 changed files with 200 additions and 118 deletions.
37 changes: 37 additions & 0 deletions .kitchen.aws.yml
Original file line number Diff line number Diff line change
@@ -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
2 changes: 1 addition & 1 deletion .kitchen.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ 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"
Expand Down
4 changes: 2 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,8 @@ 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_custom.yml'
- '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
# remove the UseLogin-check, see here for reasons: https://github.com/dev-sec/ansible-ssh-hardening/pull/141
Expand Down
36 changes: 36 additions & 0 deletions tasks/2fa.yml
Original file line number Diff line number Diff line change
@@ -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'
25 changes: 20 additions & 5 deletions tasks/ca_keys_and_principals.yml
Original file line number Diff line number Diff line change
@@ -1,12 +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 }}"
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 }}"
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 }}"
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 }}'
30 changes: 15 additions & 15 deletions tasks/crypto.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,80 +19,80 @@

- name: set weak macs according to openssh-version if openssh >= 7.6
set_fact:
ssh_macs: "{{ssh_macs_76_default}}"
ssh_macs: '{{ ssh_macs_76_default }}'
when: sshd_version.stdout >= '7.6' and not ssh_macs

- name: set weak macs according to openssh-version if openssh >= 6.6
set_fact:
ssh_macs: "{{ssh_macs_66_weak}}"
ssh_macs: '{{ ssh_macs_66_weak }}'
when: sshd_version.stdout >= '6.6' and ssh_server_weak_hmac and not ssh_macs

- name: set macs according to openssh-version if openssh >= 6.6
set_fact:
ssh_macs: "{{ssh_macs_66_default}}"
ssh_macs: '{{ ssh_macs_66_default }}'
when: sshd_version.stdout >= '6.6' and not ssh_macs

- name: set weak macs according to openssh-version
set_fact:
ssh_macs: "{{ssh_macs_59_weak}}"
ssh_macs: '{{ ssh_macs_59_weak }}'
when: sshd_version.stdout >= '5.9' and ssh_server_weak_hmac and not ssh_macs

- name: set macs according to openssh-version
set_fact:
ssh_macs: "{{ssh_macs_59_default}}"
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}}"
ssh_macs: '{{ ssh_macs_53_default }}'
when: sshd_version.stdout >= '5.3' and not ssh_macs

- name: set macs according to openssh-version
set_fact:
ssh_macs: "{{ssh_macs_53_default}}"
ssh_macs: '{{ ssh_macs_53_default }}'
when: sshd_version.stdout >= '5.3' and not ssh_macs

###

- name: set weak ciphers according to openssh-version if openssh >= 6.6
set_fact:
ssh_ciphers: "{{ssh_ciphers_66_weak}}"
ssh_ciphers: '{{ ssh_ciphers_66_weak }}'
when: sshd_version.stdout >= '6.6' and ssh_server_cbc_required and not ssh_ciphers

- name: set ciphers according to openssh-version if openssh >= 6.6
set_fact:
ssh_ciphers: "{{ssh_ciphers_66_default}}"
ssh_ciphers: '{{ ssh_ciphers_66_default }}'
when: sshd_version.stdout >= '6.6' and not ssh_ciphers

- name: set weak ciphers according to openssh-version
set_fact:
ssh_ciphers: "{{ssh_ciphers_53_weak}}"
ssh_ciphers: '{{ ssh_ciphers_53_weak }}'
when: sshd_version.stdout >= '5.3' and ssh_server_cbc_required and not ssh_ciphers

- name: set ciphers according to openssh-version
set_fact:
ssh_ciphers: "{{ssh_ciphers_53_default}}"
ssh_ciphers: '{{ ssh_ciphers_53_default }}'
when: sshd_version.stdout >= '5.3' and not ssh_ciphers

###

- name: set weak kex according to openssh-version if openssh >= 6.6
set_fact:
ssh_kex: "{{ssh_kex_66_weak}}"
ssh_kex: '{{ ssh_kex_66_weak }}'
when: sshd_version.stdout >= '6.6' and ssh_server_weak_hmac and not ssh_kex

- name: set kex according to openssh-version if openssh >= 6.6
set_fact:
ssh_kex: "{{ssh_kex_66_default}}"
ssh_kex: '{{ ssh_kex_66_default }}'
when: sshd_version.stdout >= '6.6' and not ssh_kex

- name: set weak kex according to openssh-version
set_fact:
ssh_kex: "{{ssh_kex_59_weak}}"
ssh_kex: '{{ ssh_kex_59_weak }}'
when: sshd_version.stdout >= '5.9' and ssh_server_weak_hmac and not ssh_kex

- name: set kex according to openssh-version
set_fact:
ssh_kex: "{{ssh_kex_59_default}}"
ssh_kex: '{{ ssh_kex_59_default }}'
when: sshd_version.stdout >= '5.9' and not ssh_kex

127 changes: 32 additions & 95 deletions tasks/main.yml
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
---
- name: Set OS dependent variables
include_vars: "{{ item }}"
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"
- '{{ 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'
Expand All @@ -18,17 +18,33 @@
- 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 }}"
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"
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 }}"
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
Expand All @@ -46,98 +62,19 @@
- include_tasks: ca_keys_and_principals.yml
when: ssh_trusted_user_ca_keys_file != ''

- name: test to see if selinux is installed and running
command: getenforce
register: sestatus
failed_when: false
changed_when: false
check_mode: no

# Install the 2FA packages and setup the config in PAM and SSH

- block:
- 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'

- 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

- block: # only runs when selinux is installed
- 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

- include_tasks: selinux.yml
when: sestatus.rc == 0
Loading

0 comments on commit d7e6f74

Please sign in to comment.