From fe62fb0aa377057c247896e9a2924e02cd5c7111 Mon Sep 17 00:00:00 2001 From: Bas Date: Fri, 10 Mar 2023 14:59:16 +0100 Subject: [PATCH] Bugfixes * hardening * Amended for Yum mirrors * meta-data * Codespace (#2) * No sudo in ubi8 * checkout@v3 * fixes --- .ansible-lint | 7 +- .devcontainer/Dockerfile | 20 ++++++ .devcontainer/devcontainer.json | 46 +++++++++++++ .github/workflows/molecule.yml | 4 +- .pre-commit-config.yaml | 29 ++++++++ .vscode/extensions.json | 13 ++++ .vscode/settings.json | 21 ++++++ .yamllint | 20 +++++- handlers/main.yml | 14 ++-- molecule/almalinux8/molecule.yml | 4 +- molecule/default/molecule.yml | 13 ++-- molecule/full/molecule.yml | 4 +- molecule/jenkins/converge.yml | 2 +- molecule/jenkins/molecule.yml | 6 +- molecule/localhost/molecule.yml | 1 + molecule/resources/playbooks/converge.yml | 11 ++-- molecule/resources/playbooks/verify.yml | 14 ++++ requirements.txt | 66 +++++++++++++++++++ tasks/Debian11.yml | 2 +- tasks/crypto_policy.yml | 20 +++--- tasks/main.yml | 56 +++++++--------- tasks/sshd_crypto.yml | 2 +- tasks/strict_config.yml | 13 +++- tasks/verify.yml | 23 +++++++ tasks/weak_keys.yml | 38 +++++------ .../resources/tests => tests}/test_sshd.py | 0 vars/main.yml | 6 +- 27 files changed, 354 insertions(+), 101 deletions(-) create mode 100644 .devcontainer/Dockerfile create mode 100644 .devcontainer/devcontainer.json create mode 100644 .pre-commit-config.yaml create mode 100644 .vscode/extensions.json create mode 100644 .vscode/settings.json create mode 100644 molecule/resources/playbooks/verify.yml create mode 100644 requirements.txt create mode 100644 tasks/verify.yml rename {molecule/resources/tests => tests}/test_sshd.py (100%) diff --git a/.ansible-lint b/.ansible-lint index d10b8f6..031a4b6 100644 --- a/.ansible-lint +++ b/.ansible-lint @@ -1,6 +1,7 @@ --- +# https://ansible-lint.readthedocs.io/en/latest/default_rules/ +exclude_paths: + - ./.github + - ./.vscode skip_list: - experimental # all rules tagged as experimental - - fqcn-builtins # Use FQCN for builtin actions. - - unnamed-task # All tasks should be named. -... diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile new file mode 100644 index 0000000..f937ca9 --- /dev/null +++ b/.devcontainer/Dockerfile @@ -0,0 +1,20 @@ +# See here for image contents: https://github.com/microsoft/vscode-dev-containers/tree/v0.134.0/containers/python-3/.devcontainer/base.Dockerfile +ARG VARIANT="3.8" +FROM mcr.microsoft.com/vscode/devcontainers/python:0-${VARIANT} + +# [Optional] Allow the vscode user to pip install globally w/o sudo +ENV PIP_TARGET=/usr/local/pip-global +ENV PYTHONPATH=${PIP_TARGET}:${PYTHONPATH} +ENV PATH=${PIP_TARGET}/bin:${PATH} +RUN mkdir -p ${PIP_TARGET} \ + && chown vscode:root ${PIP_TARGET} \ + && echo "if [ \"\$(stat -c '%U' ${PIP_TARGET})\" != \"vscode\" ]; then chown -R vscode:root ${PIP_TARGET}; fi" \ + | tee -a /root/.bashrc /home/vscode/.bashrc /root/.zshrc >> /home/vscode/.zshrc + +COPY requirements.txt /workspaces/session/ +RUN pip --disable-pip-version-check --no-cache-dir install -r /workspaces/session/requirements.txt + +# [Optional] Uncomment this section to install additional OS packages. +# RUN apt-get update \ +# && export DEBIAN_FRONTEND=noninteractive \ +# && apt-get -y install --no-install-recommends diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 0000000..32fa46a --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,46 @@ +{ + "name": "Python 3", + "build": { + "dockerfile": "Dockerfile", + "context": "..", + "args": {"VARIANT": "3.8"} + }, + "customizations": { + "vscode": { + "settings": { + "python.pythonPath": "/usr/local/bin/python", + "python.linting.enabled": true, + "python.linting.pylintEnabled": true, + "python.formatting.autopep8Path": "/usr/local/py-utils/bin/autopep8", + "python.formatting.blackPath": "/usr/local/py-utils/bin/black", + "python.formatting.yapfPath": "/usr/local/py-utils/bin/yapf", + "python.linting.banditPath": "/usr/local/py-utils/bin/bandit", + "python.linting.flake8Path": "/usr/local/py-utils/bin/flake8", + "python.linting.mypyPath": "/usr/local/py-utils/bin/mypy", + "python.linting.pycodestylePath": "/usr/local/py-utils/bin/pycodestyle", + "python.linting.pydocstylePath": "/usr/local/py-utils/bin/pydocstyle", + "python.linting.pylintPath": "/usr/local/py-utils/bin/pylint" + }, + "extensions": [ + "redhat.ansible", + "ms-python.python", + "ms-python.pylint", + "ms-vscode.test-adapter-converter", + "hbenl.vscode-test-explorer", + "littlefoxteam.vscode-python-test-adapter", + "timonwong.shellcheck" + ] + } + }, + "features": { + "ghcr.io/devcontainers/features/docker-outside-of-docker:1": {}, + "ghcr.io/guiyomh/features/vim:0": {}, + "ghcr.io/jungaretti/features/make:1": {}, + "ghcr.io/devcontainers-contrib/features/nmap-apt-get:1": {}, + "ghcr.io/lukewiwa/features/shellcheck:0": {}, + "ghcr.io/devcontainers-contrib/features/curl-apt-get:1": {}, + "ghcr.io/eitsupi/devcontainer-features/jq-likes:1": {} + }, + "forwardPorts": [2211], + "remoteUser": "root" +} diff --git a/.github/workflows/molecule.yml b/.github/workflows/molecule.yml index f9e3d6b..2a0f04c 100644 --- a/.github/workflows/molecule.yml +++ b/.github/workflows/molecule.yml @@ -12,7 +12,7 @@ jobs: runs-on: ubuntu-20.04 steps: - name: checkout - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: path: "${{ github.repository }}" - name: molecule @@ -27,7 +27,7 @@ jobs: fail-fast: false steps: - name: checkout - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: path: "${{ github.repository }}" - name: molecule diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..0cd23b4 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,29 @@ +--- +# https://pre-commit.com/hooks.html +default_language_version: + python: python3 +exclude: .venv +repos: + + - repo: https://github.com/adrienverge/yamllint + rev: v1.27.1 + hooks: + - id: yamllint + args: [-c=.yamllint] + + - repo: https://github.com/robertdebock/pre-commit + rev: v1.5.2 + hooks: + - id: ansible_role_find_unused_variable + - id: ansible_role_find_empty_files + - id: ansible_role_find_empty_directories + + - repo: https://github.com/jumanjihouse/pre-commit-hooks + rev: 3.0.0 # or specific git tag + hooks: + - id: shellcheck + + - repo: https://github.com/PyCQA/flake8 + rev: 6.0.0 + hooks: + - id: flake8 diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..15d5466 --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,13 @@ +{ + "recommendations": [ + "redhat.ansible", + "ms-python.python", + "ms-python.pylint", + "ms-vscode.test-adapter-converter", + "hbenl.vscode-test-explorer", + "littlefoxteam.vscode-python-test-adapter", + "timonwong.shellcheck", + "davidanson.vscode-markdownlint", + "eamodio.gitlens" + ] +} diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..51d313e --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,21 @@ +{ + "editor.rulers": [ + 120 + ], + "files.associations": { + "**/molecule/**/molecule.yml": "yaml", + "**/templates/*.j2": "ansible-jinja", + "*.yml": "ansible" + }, + "files.insertFinalNewline": true, + "files.trimTrailingWhitespace": true, + "python.testing.unittestArgs": [ + "-v", + "-s", + "./test", + "-p", + "test*.py" + ], + "python.testing.pytestEnabled": false, + "python.testing.unittestEnabled": true +} diff --git a/.yamllint b/.yamllint index d2e1359..d50c7e1 100644 --- a/.yamllint +++ b/.yamllint @@ -1,8 +1,26 @@ --- +# https://yamllint.readthedocs.io/en/stable/rules.html extends: default rules: + braces: + max-spaces-inside: 1 + level: error + brackets: + max-spaces-inside: 1 + level: error + indentation: + indent-sequences: consistent + spaces: 2 + level: error + line-length: + max: 120 + level: warning + key-duplicates: enable + new-line-at-end-of-file: enable + new-lines: + type: unix + trailing-spaces: enable truthy: allowed-values: ['true', 'false'] check-keys: false -... diff --git a/handlers/main.yml b/handlers/main.yml index 8b8b2c0..2f2876f 100644 --- a/handlers/main.yml +++ b/handlers/main.yml @@ -1,7 +1,7 @@ --- - name: Restart sshd - debug: + ansible.builtin.debug: msg: "checking /etc/ssh/sshd_config first" changed_when: true notify: @@ -9,26 +9,22 @@ - Restart sshd - after config check - name: Check sshd configuration - become: true - command: '/usr/sbin/sshd -t' + ansible.builtin.command: '/usr/sbin/sshd -t' register: sshd_config changed_when: "sshd_config.rc != 0" - name: Restart sshd - after config check - become: true - service: + ansible.builtin.service: name: sshd state: restarted - name: Start RNG Entropy Gatherer - become: true - systemd: + ansible.builtin.systemd: name: rngd state: restarted enabled: true - name: Update crypto policies - become: true - command: update-crypto-policies + ansible.builtin.command: update-crypto-policies notify: Restart sshd ... diff --git a/molecule/almalinux8/molecule.yml b/molecule/almalinux8/molecule.yml index 0970abe..f34b40b 100644 --- a/molecule/almalinux8/molecule.yml +++ b/molecule/almalinux8/molecule.yml @@ -30,7 +30,7 @@ provisioner: executable: /bin/bash playbooks: converge: ../resources/playbooks/converge.yml + verify: ../resources/playbooks/verify.yml verifier: - name: testinfra - directory: ../resources/tests + name: ansible ... diff --git a/molecule/default/molecule.yml b/molecule/default/molecule.yml index f63cd8f..5befd67 100644 --- a/molecule/default/molecule.yml +++ b/molecule/default/molecule.yml @@ -10,14 +10,15 @@ lint: | ansible-lint flake8 platforms: - - name: ssh-centos8 - image: quay.io/centos/centos:stream8 - command: /sbin/init + - name: ssh-ubi8 + image: registry.access.redhat.com/ubi8/ubi-init + pre_build_image: true + command: /usr/sbin/init cgroupns_mode: host capabilities: - SYS_ADMIN published_ports: - - 127.0.0.1:2258:22 + - 127.0.0.1:2211:22 tmpfs: - /run - /tmp @@ -32,7 +33,7 @@ provisioner: executable: /bin/bash playbooks: converge: ../resources/playbooks/converge.yml + verify: ../resources/playbooks/verify.yml verifier: - name: testinfra - directory: ../resources/tests + name: ansible ... diff --git a/molecule/full/molecule.yml b/molecule/full/molecule.yml index ef18284..30dd9ad 100644 --- a/molecule/full/molecule.yml +++ b/molecule/full/molecule.yml @@ -68,7 +68,7 @@ provisioner: executable: /bin/bash playbooks: converge: ../resources/playbooks/converge.yml + verify: ../resources/playbooks/verify.yml verifier: - name: testinfra - directory: ../resources/tests + name: ansible ... diff --git a/molecule/jenkins/converge.yml b/molecule/jenkins/converge.yml index 999ff98..6d583a9 100644 --- a/molecule/jenkins/converge.yml +++ b/molecule/jenkins/converge.yml @@ -4,6 +4,6 @@ hosts: all tasks: - name: "Run ansible role" - include_role: + ansible.builtin.include_role: name: "workspace" ... diff --git a/molecule/jenkins/molecule.yml b/molecule/jenkins/molecule.yml index bcc7e86..fb52c4e 100644 --- a/molecule/jenkins/molecule.yml +++ b/molecule/jenkins/molecule.yml @@ -26,7 +26,9 @@ provisioner: defaults: stdout_callback: yaml executable: /bin/bash + playbooks: + converge: ../resources/playbooks/converge.yml + verify: ../resources/playbooks/verify.yml verifier: - name: testinfra - directory: ../resources/tests + name: ansible ... diff --git a/molecule/localhost/molecule.yml b/molecule/localhost/molecule.yml index b91e43b..9cb4ca2 100644 --- a/molecule/localhost/molecule.yml +++ b/molecule/localhost/molecule.yml @@ -23,6 +23,7 @@ provisioner: executable: /bin/bash playbooks: converge: ../resources/playbooks/converge.yml + verify: ../resources/playbooks/verify.yml verifier: name: testinfra directory: ../resources/tests diff --git a/molecule/resources/playbooks/converge.yml b/molecule/resources/playbooks/converge.yml index a67de52..7b1b6a7 100644 --- a/molecule/resources/playbooks/converge.yml +++ b/molecule/resources/playbooks/converge.yml @@ -2,9 +2,12 @@ # Standards: 0.2 - name: Converge hosts: all - become: true + + vars: + role_name: "{{ lookup('env', 'MOLECULE_PROJECT_DIRECTORY') | basename }}" + tasks: - - name: "Run ansible_role_ssh" - include_role: - name: "ansible_role_ssh" + - name: "Include {{ role_name }}" + ansible.builtin.include_role: + name: "{{ role_name }}" ... diff --git a/molecule/resources/playbooks/verify.yml b/molecule/resources/playbooks/verify.yml new file mode 100644 index 0000000..cd54346 --- /dev/null +++ b/molecule/resources/playbooks/verify.yml @@ -0,0 +1,14 @@ +--- +# Standards: 0.2 +- name: Verify + hosts: all + + vars: + role_name: "{{ lookup('env', 'MOLECULE_PROJECT_DIRECTORY') | basename }}" + + tasks: + - name: "Include {{ role_name }}" + ansible.builtin.include_role: + name: "{{ role_name }}" + tasks_from: verify +... diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..bbd776c --- /dev/null +++ b/requirements.txt @@ -0,0 +1,66 @@ +ansible==6.2.0 +ansible-compat==2.2.0 +ansible-core==2.13.3 +ansible-lint==6.4.0 +ansible-runner==2.2.1 +arrow==1.2.2 +attrs==22.1.0 +binaryornot==0.4.4 +bindep==2.11.0 +bracex==2.3.post1 +Cerberus==1.3.2 +certifi==2022.6.15 +cffi==1.15.1 +chardet==5.0.0 +charset-normalizer==2.1.0 +click==8.1.3 +click-help-colors==0.9.1 +commonmark==0.9.1 +cookiecutter==2.1.1 +cryptography==37.0.4 +distro==1.7.0 +docutils==0.19 +enrich==1.2.7 +flake8==6.0.0 +idna==3.3 +importlib-resources==5.9.0 +iniconfig==1.1.1 +Jinja2==3.1.2 +jinja2-time==0.2.0 +jsonschema>=4.17.3 +lockfile==0.12.2 +MarkupSafe==2.1.1 +molecule==4.0.1 +molecule-docker==2.0.0 +onigurumacffi==1.2.0 +packaging==21.3 +Parsley==1.3 +pathspec==0.9.0 +pbr==5.10.0 +pexpect==4.8.0 +pkgutil_resolve_name==1.3.10 +pluggy==1.0.0 +pre-commit==3.1.00 +ptyprocess==0.7.0 +py==1.11.0 +pycparser==2.21 +Pygments==2.13.0 +pyparsing==3.0.9 +pyrsistent==0.18.1 +pytest==7.1.2 +PyYAML==6.0 +requests==2.28.1 +rich==12.5.1 +ruamel.yaml==0.17.21 +ruamel.yaml.clib==0.2.6 +selinux==0.2.1 +six==1.16.0 +text-unidecode==1.3 +tomli==2.0.1 +tox==3.21.4 +types-setuptools==64.0.1 +typing_extensions==4.3.0 +tzdata==2022.2 +urllib3==1.26.11 +wcmatch==8.4 +yamllint==1.27.1 diff --git a/tasks/Debian11.yml b/tasks/Debian11.yml index 2aeaedf..b43d17e 100644 --- a/tasks/Debian11.yml +++ b/tasks/Debian11.yml @@ -1,7 +1,7 @@ --- - name: Harden SSH configuration - lineinfile: + ansible.builtin.lineinfile: dest: /etc/ssh/sshd_config.d/ssh-audit_hardening.conf regexp: "{{ item.regexp }}" line: "{{ item.line }}" diff --git a/tasks/crypto_policy.yml b/tasks/crypto_policy.yml index 5c7b3a7..1a4245c 100644 --- a/tasks/crypto_policy.yml +++ b/tasks/crypto_policy.yml @@ -1,20 +1,20 @@ --- - name: Install crypto-policies - package: + ansible.builtin.package: name: - crypto-policies - - rng-tools + - crypto-policies-scripts state: present - name: Inquire which crypto policy is configured - command: "update-crypto-policies --show" + ansible.builtin.command: "update-crypto-policies --show" changed_when: false register: current_policy - name: Install STRICT policy when: crypto_policy == 'STRICT' - template: + ansible.builtin.template: src: STRICT.pol dest: /usr/share/crypto-policies/policies/ owner: root @@ -23,35 +23,35 @@ - name: "Ensure {{ crypto_policy }} policy is configured" when: current_policy.stdout != crypto_policy - command: "update-crypto-policies --set {{ crypto_policy }}" + ansible.builtin.command: "update-crypto-policies --set {{ crypto_policy }}" changed_when: true notify: Restart sshd - name: Apply crypto policy (reboot recommended) when: current_policy.stdout != crypto_policy - command: /bin/sh /usr/share/crypto-policies/reload-cmds.sh + ansible.builtin.command: /bin/sh /usr/share/crypto-policies/reload-cmds.sh changed_when: false - name: SSH client uses strong entropy to seed (Bash-like shells) - copy: + ansible.builtin.copy: dest: /etc/profile.d/cc-ssh-strong-rng.sh content: "export SSH_USE_STRONG_RNG=32\n" mode: 0644 - name: SSH client uses strong entropy to seed (for CSH like shells) - copy: + ansible.builtin.copy: dest: /etc/profile.d/cc-ssh-strong-rng.csh content: "setenv SSH_USE_STRONG_RNG 32\n" mode: 0644 - name: Remove RekeyLimit from ssh_config - lineinfile: + ansible.builtin.lineinfile: dest: /etc/ssh/ssh_config regexp: '^(#)?RekeyLimit' state: absent - name: Configure RekeyLimit in ssh_config override - lineinfile: + ansible.builtin.lineinfile: dest: /etc/ssh/ssh_config.d/02-rekey-limit.conf create: true regexp: '^(#)?RekeyLimit' diff --git a/tasks/main.yml b/tasks/main.yml index 09e93da..44fe7e3 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -1,10 +1,10 @@ --- # yamllint disable rule:line-length - name: Setup - setup: + ansible.builtin.setup: - name: Print out operating system details - debug: + ansible.builtin.debug: msg: >- os_family: {{ ansible_os_family }}, @@ -12,42 +12,42 @@ {{ ansible_distribution }}{{ ansible_distribution_major_version }} - name: Set distro_version - set_fact: + ansible.builtin.set_fact: distro_version: "{{ ansible_distribution }}{{ ansible_distribution_major_version }}" - name: Install SSH server - package: + ansible.builtin.package: name: openssh-server state: present update_cache: true - name: Ensure privilege separation directory exists when: ansible_os_family == 'Debian' - file: + ansible.builtin.file: path: /run/sshd state: directory mode: 0750 - name: "Fedora {{ crypto_policy }} crypto policy" when: ansible_distribution == 'Fedora' - include_tasks: crypto_policy.yml + ansible.builtin.include_tasks: crypto_policy.yml - name: "Update {{ crypto_policy }} crypto policy" when: distro_version in [ 'RedHat8', 'CentOS8', 'AlmaLinux8', 'Ubuntu20', 'Rocky8'] - include_tasks: crypto_policy.yml + ansible.builtin.include_tasks: crypto_policy.yml - name: Check if /etc/ssh/moduli contains weak Diffie-Hellman parameters - shell: awk '$5 < {{ min_dh_size }}' /etc/ssh/moduli + ansible.builtin.shell: awk '$5 < {{ min_dh_size }}' /etc/ssh/moduli register: sshd_register_moduli changed_when: false check_mode: false - name: Deactivate short Diffie-Hellman moduli when: sshd_register_moduli.stdout - shell: "awk '$5 >= {{ min_dh_size }}' /etc/ssh/moduli > /etc/ssh/moduli.tmp && mv -f /etc/ssh/moduli.tmp /etc/ssh/moduli" + ansible.builtin.shell: "awk '$5 >= {{ min_dh_size }}' /etc/ssh/moduli > /etc/ssh/moduli.tmp && mv -f /etc/ssh/moduli.tmp /etc/ssh/moduli" - name: Harden SSH configuration - lineinfile: + ansible.builtin.lineinfile: dest: /etc/ssh/sshd_config regexp: "{{ item.regexp }}" line: "{{ item.line }}" @@ -60,51 +60,44 @@ when: - crypto_policy == 'STRICT' - distro_version in [ 'RedHat8', 'CentOS8', 'AlmaLinux8', 'Debian11', 'Rocky8'] - include_tasks: "strict_config.yml" + ansible.builtin.include_tasks: "strict_config.yml" - name: Apply STRICT hardening for sshd when: - crypto_policy == 'STRICT' - distro_version not in [ 'RedHat8', 'CentOS8', 'AlmaLinux8', 'Debian11', 'Rocky8'] - include_tasks: sshd_crypto.yml + ansible.builtin.include_tasks: sshd_crypto.yml - name: Create login banner - copy: + ansible.builtin.copy: src: issue dest: /etc/issue mode: 0644 -- name: Ensure SSH server is started - systemd: - name: sshd - enabled: true - state: started - failed_when: false # for initializing - -- block: +- name: Manage ed25519 host key + block: - name: Check the ed25519 host key - become: true - stat: + ansible.builtin.stat: path: /etc/ssh/ssh_host_ed25519_key register: ed25519 - name: Generate ed25519 host key - become: true - command: ssh-keygen -t ed25519 -f /etc/ssh/ssh_host_ed25519_key -N "" + ansible.builtin.systemd: + name: sshd-keygen@ed25519.service + state: started + masked: false + enabled: true when: - not ed25519.stat.exists|bool notify: Restart sshd - changed_when: true - name: Set host key permissions - become: true - file: + ansible.builtin.file: path: /etc/ssh/ssh_host_ed25519_key mode: 0600 - name: Configure ed25519 host key - become: true - lineinfile: + ansible.builtin.lineinfile: dest: /etc/ssh/sshd_config regexp: '^HostKey /etc/ssh/ssh_host_ed25519_key' line: 'HostKey /etc/ssh/ssh_host_ed25519_key' @@ -122,8 +115,7 @@ # See http://bada55.cr.yp.to/ - name: Remove ed25519 host key in FIPS mode - become: true - lineinfile: + ansible.builtin.lineinfile: dest: /etc/ssh/sshd_config regexp: '^HostKey /etc/ssh/ssh_host_ed25519_key' mode: 0600 diff --git a/tasks/sshd_crypto.yml b/tasks/sshd_crypto.yml index ffb2782..02b4288 100644 --- a/tasks/sshd_crypto.yml +++ b/tasks/sshd_crypto.yml @@ -1,7 +1,7 @@ --- - name: Harden crypto in sshd_config - lineinfile: + ansible.builtin.lineinfile: dest: /etc/ssh/sshd_config regexp: "{{ item.regexp }}" line: "{{ item.line }}" diff --git a/tasks/strict_config.yml b/tasks/strict_config.yml index 784fee7..d603251 100644 --- a/tasks/strict_config.yml +++ b/tasks/strict_config.yml @@ -4,7 +4,7 @@ # update-crypto-policies on RHEL 8.5 leaves weak algorithms due # to the implementation in the python script. - name: Override CRYPTO_POLICY for sshd - lineinfile: + ansible.builtin.lineinfile: path: /etc/sysconfig/sshd regex: '^CRYPTO_POLICY' line: "CRYPTO_POLICY='-oCiphers={{ Ciphers }} -oMACs={{ MACs }} -oKexAlgorithms={{ KexAlgorithms }} -oHostKeyAlgorithms={{ HostKeyAlgorithms }}'" @@ -13,12 +13,21 @@ mode: 0640 notify: Restart sshd +- name: Install rgn-tools for entropy, if available + ansible.builtin.package: + name: + - rng-tools + state: present + ignore_errors: true # when a repo doesn't list it + register: entropy + - name: Configure strong entropy for sshd - lineinfile: + ansible.builtin.lineinfile: path: /etc/sysconfig/sshd regexp: '^SSH_USE_STRONG_RNG' line: 'SSH_USE_STRONG_RNG=32' state: present mode: 0640 + when: entropy.changed | bool # noqa no-handler notify: Start RNG Entropy Gatherer ... diff --git a/tasks/verify.yml b/tasks/verify.yml new file mode 100644 index 0000000..264bb84 --- /dev/null +++ b/tasks/verify.yml @@ -0,0 +1,23 @@ +--- + +- name: Gather package facts + ansible.builtin.package_facts: + +- name: Assert package is installed + ansible.builtin.assert: + quiet: true + that: + - "'{{ item }}' in ansible_facts.packages" + loop: "{{ ssh_packages }}" + +- name: Gather service facts + ansible.builtin.service_facts: + +- name: Assert that service is OK + ansible.builtin.assert: + quiet: true + that: + - ansible_facts.services['sshd.service'].status == 'enabled' + - ansible_facts.services['sshd.service'].state == 'running' + - ansible_facts.services['sshd-keygen@ecdsa.service'].status == 'masked' + - ansible_facts.services['sshd-keygen@rsa.service'].status == 'masked' diff --git a/tasks/weak_keys.yml b/tasks/weak_keys.yml index 3a3fbcc..e1cc5c7 100644 --- a/tasks/weak_keys.yml +++ b/tasks/weak_keys.yml @@ -1,28 +1,26 @@ --- -- name: Remove weak keys from sshd_config - become: true - lineinfile: +- name: "Mask generation of {{ item }} host key" + ansible.builtin.systemd: + name: "{{ hostkey }}" + masked: true + loop: + - sshd-keygen@ecdsa.service + - sshd-keygen@rsa.service + loop_control: + loop_var: hostkey + +- name: Remove {{ item }} host key from sshd_config + ansible.builtin.lineinfile: dest: /etc/ssh/sshd_config - regexp: 'HostKey /etc/ssh/{{ item }}' - line: 'HostKey /etc/ssh/{{ item }}' + regexp: "HostKey /etc/ssh/ssh_host_{{ item }}_key" + line: "HostKey /etc/ssh/ssh_host_{{ item }}_key" state: absent notify: Restart sshd -- name: "Check weak key presence for {{ item }}" - become: true - stat: - path: "/etc/ssh/{{ item }}" - register: - weak_key_found +- name: "Remove {{ item }} host key" + ansible.builtin.file: + path: "/etc/ssh/ssh_host_{{ item }}_key" + state: absent -# Weak keys have weak permissions so sshd ignores them. -- name: "Disable weak host key {{ item }}" - become: true - when: - - weak_key_found.stat.exists is defined - - weak_key_found.stat.exists|bool - file: - path: "/etc/ssh/{{ item }}" - mode: 0666 ... diff --git a/molecule/resources/tests/test_sshd.py b/tests/test_sshd.py similarity index 100% rename from molecule/resources/tests/test_sshd.py rename to tests/test_sshd.py diff --git a/vars/main.yml b/vars/main.yml index 5a2b9b6..8e33d18 100644 --- a/vars/main.yml +++ b/vars/main.yml @@ -9,8 +9,8 @@ ssh_packages: # https://eprint.iacr.org/2020/014.pdf # More info https://www.openssh.com/txt/release-8.2 weak_host_keys: - - ssh_host_rsa_key - - ssh_host_ecdsa_key + - rsa + - ecdsa # https://www.ssh-audit.com/hardening_guides.html @@ -18,7 +18,7 @@ Ciphers: chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh HostKeyAlgorithms: ssh-ed25519-cert-v01@openssh.com,ssh-ed25519 # This is a compatible subset -KexAlgorithms: curve25519-sha256,curve25519-sha256@libssh.org,diffie-hellman-group16-sha512,diffie-hellman-group18-sha512,diffie-hellman-group14-sha256 +KexAlgorithms: curve25519-sha256,curve25519-sha256@libssh.org,diffie-hellman-group16-sha512,diffie-hellman-group18-sha512,diffie-hellman-group14-sha256,diffie-hellman-group-exchange-sha256 MACs: hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com,umac-128-etm@openssh.com