diff --git a/.github/workflows/devel_pipeline_validation.yml b/.github/workflows/devel_pipeline_validation.yml index 31a4a6b..fc55cbb 100644 --- a/.github/workflows/devel_pipeline_validation.yml +++ b/.github/workflows/devel_pipeline_validation.yml @@ -44,13 +44,13 @@ steps: - name: Clone ${{ github.event.repository.name }} - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: ref: ${{ github.event.pull_request.head.sha }} # Pull in terraform code for linux servers - name: Clone github IaC plan - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: repository: ansible-lockdown/github_linux_IaC path: .github/workflows/github_linux_IaC @@ -125,6 +125,7 @@ env: ANSIBLE_HOST_KEY_CHECKING: "false" ANSIBLE_DEPRECATION_WARNINGS: "false" + ANSIBLE_INJECT_FACT_VARS: "false" # Remove test system - User secrets to keep if necessary diff --git a/.github/workflows/main_pipeline_validation.yml b/.github/workflows/main_pipeline_validation.yml index 90415c4..6228ac7 100644 --- a/.github/workflows/main_pipeline_validation.yml +++ b/.github/workflows/main_pipeline_validation.yml @@ -33,13 +33,13 @@ steps: - name: Clone ${{ github.event.repository.name }} - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: ref: ${{ github.event.pull_request.head.sha }} # Pull in terraform code for linux servers - name: Clone github IaC plan - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: repository: ansible-lockdown/github_linux_IaC path: .github/workflows/github_linux_IaC @@ -114,6 +114,7 @@ env: ANSIBLE_HOST_KEY_CHECKING: "false" ANSIBLE_DEPRECATION_WARNINGS: "false" + ANSIBLE_INJECT_FACT_VARS: "false" # Remove test system - User secrets to keep if necessary diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 1acf801..3014d8a 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -7,7 +7,7 @@ ci: repos: - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.4.0 + rev: v4.6.0 hooks: # Safety - id: detect-aws-credentials @@ -37,13 +37,13 @@ repos: exclude: .config/.gitleaks-report.json - repo: https://github.com/gitleaks/gitleaks - rev: v8.17.0 + rev: v8.18.2 hooks: - id: gitleaks args: ['--baseline-path', '.config/.gitleaks-report.json'] - repo: https://github.com/ansible-community/ansible-lint - rev: v6.18.0 + rev: v24.2.1 hooks: - id: ansible-lint name: Ansible-lint @@ -62,6 +62,6 @@ repos: - ansible-core>=2.10.1 - repo: https://github.com/adrienverge/yamllint.git - rev: v1.32.0 # or higher tag + rev: v1.35.1 # or higher tag hooks: - id: yamllint diff --git a/Changelog.md b/Changelog.md index 75da505..aed863c 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,5 +1,33 @@ # Amazon 2023 CIS - 26th June 2023 +## 1.0.1 + +- thanks to @DianaMariaDDM + - #59 + - #60 + - #61 + - #62 + +- #64 thanks to @tom-henderson + +- extended with new options to force changes for 4.6.1.1|2|3 default false + - amzn2023cis_force_user_maxdays + - amzn2023cis_force_user_mindays + - amzn2023cis_force_user_warndays + +- pre-commit updates + +- general tidy up + +## 1.0 Multiple changes + +- Audit binary updated goss 0.4.4 +- audit_only option now added + - audit_only: true + +- Many Prs and associated issues + massive thanks to @DianaMariaDDM for all the PRs and Issues and time + ## 0.91 - issue #2 thanks to @babinskiy diff --git a/defaults/main.yml b/defaults/main.yml index aaf7219..34407a9 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -1,13 +1,33 @@ --- # defaults file for amazon2023-cis +# This variable is used to state if the system where +# the role is executed is a container image or not. +# The role discovers this dinamically and sets this +# variable's value to 'true' or it leaves it unchanged +# ('false') based on its findings. system_is_container: false +# This variable holds the name of the "yml" file, in which +# the role would store the container's variables. This +# file would get created only if the role determines that +# it is executed on a container image. container_vars_file: is_container.yml -# Run the OS validation check -# Supported OSs will not need for this to be changed - see README e.g. CentOS +# This variable is used to run the OS version and family +# check. This validation check determines if the role is +# executed against a supported OS. Setting it to 'true' will +# mean that the OS validation will be executed. Setting it +# to 'false' would mean otherwise. +# If you know that your OS finds itself among the supported +# Oss then this variable's value does not need to be changed. +# If not, you should change it accordingly - see README e.g. CentOS os_check: true +# The following variables are used in order to determine if +# certain sections of the role should get executed or not. +# If you desire for a certain section to not get executed +# against your OS, simply change that section's variable +# value to 'false'! amzn2023cis_section1: true amzn2023cis_section2: true amzn2023cis_section3: true @@ -15,63 +35,140 @@ amzn2023cis_section4: true amzn2023cis_section5: true amzn2023cis_section6: true -# This is used for audit purposes to run only specific level use the tags +# This is used for audit purposes to run only a specific level +# use the following tags: # e.g. # - level1-server amzn2023cis_level_1: true amzn2023cis_level_2: true +# This variable is used to determine whether SELinux +# should be enabled or not. All the tasks regarding +# the hardening of SELinux will get executed only if +# this variable's value is set to 'false'. If it is set +# to 'true', then that means that SELinux is considered +# disabled by the role, therefore the role will not +# execute any hardening tasks against it! amzn2023cis_selinux_disable: false + +# This variable refers to Legacy Boot, also known as +# Legacy BIOS boot, which is a boot mode that emulates +# the traditional BIOS. The variable is used in a task +# that ensures the necessary permissions on the bootloader +# config are in place. Setting the value to 'true', will mean +# that those permisions will be set for the configuration of +# BIOS boot. Setting it to 'false', will mean that the Legacy +# Boot (BIOS boot) is not in use, which means that the +# permissions will have to be set for the configuration of +# efi boot. amzn2023cis_legacy_boot: false ## Python Binary -## This is used for python3 Installations where python2 OS modules are used in ansible +## This is used for python3 Installations where python2 OS modules +## are used in ansible python2_bin: /bin/python2.7 -## Benchmark name used by audting control role -# The audit variable found at the base -## metadata for Audit benchmark -benchmark_version: 'v1.0.0' - +## Benchmark name and profile used by audting control role +# The audit variable can be found at the base benchmark: AMAZON2023-CIS +benchmark_version: 'v1.0.0' -# Whether to skip the reboot +# This variable states to the role whether to skip +# the reboot or not. If it is set to 'false', the role +# would reboot the system before audit, which could +# give better audit results. skip_reboot: true -# default value will change to true but wont reboot if not enabled but will error +# This variable is used in a handler task, that is notified +# if a certain task's changes are considered to be in need +# of a reboot. The default value will change to true when +# the handler gets executed but the system will reboot only +# if the 'skip_reboot' variable indicates it. +# Otherwise, a warning message will get displayed, which will +# alert the user that a reboot is needed based on the latest +# changes! change_requires_reboot: false +########################################## +### Goss is required on the remote host ### +## Refer to vars/auditd.yml for any other settings ## #### Basic external goss audit enablement settings #### #### Precise details - per setting can be found at the bottom of this file #### -### Goss is required on the remote host +## Audit setup +# Audits are carried out using Goss. This variable +# determines whether execution of the role prepares for auditing +# by installing the required binary. setup_audit: false -# How to retrive goss -# Options are copy or download - detailed settings at the bottom of this file -# you will need to access to either github or the file already dowmloaded + +## Enable audits to run - this runs the audit and get the latest content +# This variable governs whether the audit using the +# separately maintained audit role using Goss +# is carried out. +run_audit: false + +# Only run Audit do not remediate +audit_only: false +# This will enable files to be copied back to control node(part of audit_only) +fetch_audit_files: false +# Path to copy the files to will create dir structure(part of audit_only) +audit_capture_files_dir: /some/location to copy to on control node + +## How to retrieve audit binary(Goss) +# Options are 'copy' or 'download' - detailed settings at the bottom of this file +# - if 'copy': +# - the filepath mentioned via the below 'audit_bin_copy_location' var will be used to access already downloaded Goss +# - if 'download': +# - the GitHub Goss-releases URL will be used for a fresh-download, via 'audit_bin_url' and 'audit_pkg_arch_name' vars get_audit_binary_method: download -# how to get audit files onto host options -# options are git/copy/get_url - use local if already available to to the host (adjust paths accordingly) +## if get_audit_binary_method is 'copy', the following var needs to be updated for your environment +## it is expected that it will be copied from somewhere accessible to the control node +## e.g copy from ansible control node to remote host +audit_bin_copy_location: /some/accessible/path + +## How to retrieve the audit role +# The role for auditing is maintained separately. +# This variable specifies the method of how to get the audit role +# options are git/copy/get_url other e.g. if you wish to run from already downloaded conf +# onto the system. The options are as follows: +# - 'git': clone audit content from GitHub REPOSITORY, set up via `audit_file_git` var, and +# VERSION(e.g. branch, tag name), set up via `audit_git_version` var. +# - 'copy': copy from path as specified in variable `audit_conf_copy`. +# - 'archive': same as 'copy', only that the specified filepath needs to be unpacked. +# - 'get_url': Download from url as specified in variable `audit_files_url` audit_content: git -# enable audits to run - this runs the audit and get the latest content -run_audit: false +# This variable(only used when 'audit_content' is 'copy' or 'archive') should +# contain the filepath with audit-content to be copied/unarchived on server: +audit_conf_copy: "some path to copy from" -# Timeout for those cmds that take longer to run where timeout set -audit_cmd_timeout: 60000 +# This variable(only used when 'audit_content' is 'get_url') should +# contain the URL from where the audit-content must be downloaded on server: +audit_files_url: "some url maybe s3?" -# Some tests can be resource heavy allow these to take place -amzn2023cis_run_heavy_tests: true +# Run heavy tests - some tests can have more impact on a system enabling these can have greater impact on a system +audit_run_heavy_tests: true + +# Timeout for those cmds that take longer to run where timeout set +# This variable specifies the timeout (in ms) for audit commands that +# take a very long time: if a command takes too long to complete, +# it will be forcefully terminated after the specified duration. +audit_cmd_timeout: 120000 ### End Goss enablements #### -#### Detailed settings found at the end of this document #### -# These variables correspond with the CIS rule IDs or paragraph numbers defined in -# the CIS benchmark documents. -# PLEASE NOTE: These work in coordination with the section # group variables and tags. -# You must enable an entire section in order for the variables below to take effect. -# Section 1 rules +## The following variables correspond with the CIS rule IDs or paragraph numbers +## defined in the CIS benchmark documents. +## PLEASE NOTE: These work in coordination with the section # group variables +## and tags. You must enable an entire section in order for the variables below +## to take effect. If you want a specific rule to not get executed simply change +## that rule's variable's value to 'false'! + +## Section 1 rules +# Section 1 is Initial setup (FileSystem Configuration, Configure Software Updates, Filesystem Integrity Checking, +# Secure Boot Settings, Additional Process Hardening, Mandatory Access Control and Command Line Warning Banners) +# Configure Filesystem Kernel Modules amzn2023cis_rule_1_1_1_1: true amzn2023cis_rule_1_1_1_2: true amzn2023cis_rule_1_1_1_3: true @@ -79,50 +176,58 @@ amzn2023cis_rule_1_1_1_4: true amzn2023cis_rule_1_1_1_5: true amzn2023cis_rule_1_1_1_6: true amzn2023cis_rule_1_1_1_7: true +# Configure /tmp amzn2023cis_rule_1_1_2_1: true amzn2023cis_rule_1_1_2_2: true amzn2023cis_rule_1_1_2_3: true amzn2023cis_rule_1_1_2_4: true +# Configure /var amzn2023cis_rule_1_1_3_1: true amzn2023cis_rule_1_1_3_2: true amzn2023cis_rule_1_1_3_3: true +# Configure /var/tmp amzn2023cis_rule_1_1_4_1: true amzn2023cis_rule_1_1_4_2: true amzn2023cis_rule_1_1_4_3: true amzn2023cis_rule_1_1_4_4: true +# Configure /var/log amzn2023cis_rule_1_1_5_1: true amzn2023cis_rule_1_1_5_2: true amzn2023cis_rule_1_1_5_3: true amzn2023cis_rule_1_1_5_4: true +# Configure /var/log/audit amzn2023cis_rule_1_1_6_1: true amzn2023cis_rule_1_1_6_2: true amzn2023cis_rule_1_1_6_3: true amzn2023cis_rule_1_1_6_4: true +# Configure /home amzn2023cis_rule_1_1_7_1: true amzn2023cis_rule_1_1_7_2: true amzn2023cis_rule_1_1_7_3: true +# Configure /dev/shm amzn2023cis_rule_1_1_8_1: true amzn2023cis_rule_1_1_8_2: true amzn2023cis_rule_1_1_8_3: true amzn2023cis_rule_1_1_8_4: true -amzn2023cis_rule_1_1_18: true -amzn2023cis_rule_1_1_19: true -amzn2023cis_rule_1_1_20: true -amzn2023cis_rule_1_1_21: true amzn2023cis_rule_1_1_9: true +# Configure Software and Patch Management amzn2023cis_rule_1_2_1: true amzn2023cis_rule_1_2_2: true amzn2023cis_rule_1_2_3: true amzn2023cis_rule_1_2_4: true +# Filesystem Integrity Checking amzn2023cis_rule_1_3_1: true amzn2023cis_rule_1_3_2: true amzn2023cis_rule_1_3_3: true +# Secure Boot Settings amzn2023cis_rule_1_4_1: true amzn2023cis_rule_1_4_2: true +# Additional Process Hardening amzn2023cis_rule_1_5_1: true amzn2023cis_rule_1_5_2: true amzn2023cis_rule_1_5_3: true amzn2023cis_rule_1_5_4: true +# Configure SELinux amzn2023cis_rule_1_6_1_1: true amzn2023cis_rule_1_6_1_2: true amzn2023cis_rule_1_6_1_3: true @@ -131,6 +236,7 @@ amzn2023cis_rule_1_6_1_5: true amzn2023cis_rule_1_6_1_6: true amzn2023cis_rule_1_6_1_7: true amzn2023cis_rule_1_6_1_8: true +# Command Line Warning Banners amzn2023cis_rule_1_7_1: true amzn2023cis_rule_1_7_2: true amzn2023cis_rule_1_7_3: true @@ -140,9 +246,12 @@ amzn2023cis_rule_1_7_6: true amzn2023cis_rule_1_8: true amzn2023cis_rule_1_9: true -# Section 2 rules +## Section 2 rules +# Section 2 is Services (Special Purpose Services, and service clients) +# Configure Time Synchronization (chrony) amzn2023cis_rule_2_1_1: true amzn2023cis_rule_2_1_2: true +# Configure Special Purpose Services amzn2023cis_rule_2_2_1: true amzn2023cis_rule_2_2_2: true amzn2023cis_rule_2_2_3: true @@ -161,20 +270,25 @@ amzn2023cis_rule_2_2_15: true amzn2023cis_rule_2_2_16: true amzn2023cis_rule_2_2_17: true amzn2023cis_rule_2_2_18: true +# Service Clients amzn2023cis_rule_2_3_1: true amzn2023cis_rule_2_3_2: true amzn2023cis_rule_2_3_3: true amzn2023cis_rule_2_3_4: true amzn2023cis_rule_2_4: true -# Section 3 rules +## Section 3 rules +# Section 3 is Network Configuration +# Disable unused network protocols and devices amzn2023cis_rule_3_1_1: true amzn2023cis_rule_3_1_2: true amzn2023cis_rule_3_1_3: true amzn2023cis_rule_3_1_4: true amzn2023cis_rule_3_1_5: true +# Network Parameters (Host Only) amzn2023cis_rule_3_2_1: true amzn2023cis_rule_3_2_2: true +# Network Parameters (Host and Router) amzn2023cis_rule_3_3_1: true amzn2023cis_rule_3_3_2: true amzn2023cis_rule_3_3_3: true @@ -184,8 +298,10 @@ amzn2023cis_rule_3_3_6: true amzn2023cis_rule_3_3_7: true amzn2023cis_rule_3_3_8: true amzn2023cis_rule_3_3_9: true +# Configure a firewall utility amzn2023cis_rule_3_4_1_1: true amzn2023cis_rule_3_4_1_2: true +# Configure firewall rules amzn2023cis_rule_3_4_2_1: true amzn2023cis_rule_3_4_2_2: true amzn2023cis_rule_3_4_2_3: true @@ -195,6 +311,8 @@ amzn2023cis_rule_3_4_2_6: true amzn2023cis_rule_3_4_2_7: true # Section 4 rules +# Section 4 is Access, Authentication and Authorization +# Configure time-based job schedulers amzn2023cis_rule_4_1_1: true amzn2023cis_rule_4_1_2: true amzn2023cis_rule_4_1_3: true @@ -204,6 +322,7 @@ amzn2023cis_rule_4_1_6: true amzn2023cis_rule_4_1_7: true amzn2023cis_rule_4_1_8: true amzn2023cis_rule_4_1_9: true +# Configure SSH Server amzn2023cis_rule_4_2_1: true amzn2023cis_rule_4_2_2: true amzn2023cis_rule_4_2_3: true @@ -224,28 +343,27 @@ amzn2023cis_rule_4_2_17: true amzn2023cis_rule_4_2_18: true amzn2023cis_rule_4_2_19: true amzn2023cis_rule_4_2_20: true - +# Configure privilege escalation amzn2023cis_rule_4_3_1: true amzn2023cis_rule_4_3_2: true amzn2023cis_rule_4_3_3: true amzn2023cis_rule_4_3_4: true amzn2023cis_rule_4_3_5: true amzn2023cis_rule_4_3_6: true - +# Configure authselect amzn2023cis_rule_4_4_1: true amzn2023cis_rule_4_4_2: true - +# Configure PAM amzn2023cis_rule_4_5_1: true amzn2023cis_rule_4_5_2: true amzn2023cis_rule_4_5_3: true amzn2023cis_rule_4_5_4: true - +# Set Shadow Password Suite Parameters amzn2023cis_rule_4_6_1_1: true amzn2023cis_rule_4_6_1_2: true amzn2023cis_rule_4_6_1_3: true amzn2023cis_rule_4_6_1_4: true amzn2023cis_rule_4_6_1_5: true - amzn2023cis_rule_4_6_2: true amzn2023cis_rule_4_6_3: true amzn2023cis_rule_4_6_4: true @@ -253,6 +371,8 @@ amzn2023cis_rule_4_6_5: true amzn2023cis_rule_4_6_6: true # Section 5 rules +# Section 5 is Logging and Auditing +# Configure rsyslog amzn2023cis_rule_5_1_1_1: true amzn2023cis_rule_5_1_1_2: true amzn2023cis_rule_5_1_1_3: true @@ -260,30 +380,28 @@ amzn2023cis_rule_5_1_1_4: true amzn2023cis_rule_5_1_1_5: true amzn2023cis_rule_5_1_1_6: true amzn2023cis_rule_5_1_1_7: true - +# Configure journald amzn2023cis_rule_5_1_2_1_1: true amzn2023cis_rule_5_1_2_1_2: true amzn2023cis_rule_5_1_2_1_3: true amzn2023cis_rule_5_1_2_1_4: true - amzn2023cis_rule_5_1_2_2: true amzn2023cis_rule_5_1_2_3: true amzn2023cis_rule_5_1_2_4: true amzn2023cis_rule_5_1_2_5: true amzn2023cis_rule_5_1_2_6: true amzn2023cis_rule_5_1_2_7: true - amzn2023cis_rule_5_1_3: true - +# Ensure auditing is enabled amzn2023cis_rule_5_2_1_1: true amzn2023cis_rule_5_2_1_2: true amzn2023cis_rule_5_2_1_3: true amzn2023cis_rule_5_2_1_4: true - +# Configure Data Retention amzn2023cis_rule_5_2_2_1: true amzn2023cis_rule_5_2_2_2: true amzn2023cis_rule_5_2_2_3: true - +# Configure auditd rules amzn2023cis_rule_5_2_3_1: true amzn2023cis_rule_5_2_3_2: true amzn2023cis_rule_5_2_3_3: true @@ -305,7 +423,7 @@ amzn2023cis_rule_5_2_3_18: true amzn2023cis_rule_5_2_3_19: true amzn2023cis_rule_5_2_3_20: true amzn2023cis_rule_5_2_3_21: true - +# Configure auditd file access amzn2023cis_rule_5_2_4_1: true amzn2023cis_rule_5_2_4_2: true amzn2023cis_rule_5_2_4_3: true @@ -316,10 +434,11 @@ amzn2023cis_rule_5_2_4_7: true amzn2023cis_rule_5_2_4_8: true amzn2023cis_rule_5_2_4_9: true amzn2023cis_rule_5_2_4_10: true - amzn2023cis_rule_5_3: true # Section 6 rules +# Section 6 is System Maintenance +# System File Permissions amzn2023cis_rule_6_1_1: true amzn2023cis_rule_6_1_2: true amzn2023cis_rule_6_1_3: true @@ -332,6 +451,7 @@ amzn2023cis_rule_6_1_9: true amzn2023cis_rule_6_1_10: true amzn2023cis_rule_6_1_11: true amzn2023cis_rule_6_1_12: true +# Local User and Group Settings amzn2023cis_rule_6_2_1: true amzn2023cis_rule_6_2_2: true amzn2023cis_rule_6_2_3: true @@ -344,286 +464,768 @@ amzn2023cis_rule_6_2_9: true amzn2023cis_rule_6_2_10: true amzn2023cis_rule_6_2_11: true -## Section 1 vars - -#### 1.1.2 -# These settings go into the /etc/fstab file for the /tmp mount settings -# The value must contain nosuid,nodev,noexec to conform to CIS standards -# amzn2023cis_tmp_tmpfs_settings: "defaults,rw,nosuid,nodev,noexec,relatime 0 0" -# If set true uses the tmp.mount service else using fstab configuration -amzn2023cis_tmp_svc: false - -#### 1.1.9 -amzn2023cis_allow_autofs: false - -# 1.9 Set crypto policy (LEGACY, DEFAULT, FUTURE, FIPS) -# Control 1.9 states do not use LEGACY +## +## Section 1 Control Variables +## + +## Control 1.1.2 - Configure /tmp +# This variable is used in order to determine which method +# shall be used by the role in order to ensure that the +# "nodev,noexec,nosuid" options are set for "/tmp". +# If it is set to 'true', the role will use the tmp.mount +# service otherwise, the role will use the fstab configuration. +amzn2023cis_tmp_svc: true + +## Control 1.9 - Ensure system-wide crypto policy is not legacy +# This variable helps in determining which type of crypto policy +# the role will set. As per the description of Control 1.9, +# the "LEGACY" option is not to be used! A reason for this would +# be the fact that "LEGACY" includes older algorithms that might +# be considered less secure. You can choose from other options +# such as: +# "DEFAULT" - includes a set of cryptographic algorithms that are +# considered secure; +# "FUTURE" - may include newer algorithms that will replace older +# ones; +# "FIPS" - designed to comply with specific cryptographic standards +# defined by NIST. They are often required in certain +# government or regulated environments; amzn2023cis_crypto_policy: 'DEFAULT' -# Added module to be allowed as default setting (Allowed options in vars/main.yml) +# If you want to have a crypto policy module, you can specify it +# here, as the value of the following variable. Allowed options +# for this can be found in the "vars/main.yml" file at the +# "amzn2023cis_allowed_crypto_policies_modules" variable! amzn2023cis_crypto_policy_module: '' -# System network parameters (host only OR host and router) +# This variable governs whether specific CIS rules +# concerned with IP forwarding and routing of packages +# are skipped. amzn2023cis_is_router: false -# IPv6 required +## IPv6 requirement toggle +# This variable governs whether ipv6 is enabled or disabled. amzn2023cis_ipv6_required: true -# AIDE +## Control 1.3.1 - Ensure AIDE is installed +# AIDE is a file integrity checking tool, similar in nature to Tripwire. +# While it cannot prevent intrusions, it can detect unauthorized changes +# to configuration files by alerting when the files are changed. Review +# the AIDE quick start guide and AIDE documentation before proceeding. +# By setting this variable to 'true', all of the settings related to AIDE +# will be applied! amzn2023cis_config_aide: true -# AIDE cron settings + +## Control 1.3.2 - Ensure filesystem integrity is regularly checked +# These are the crontab settings for periodical checking of the filesystem's +# integrity using AIDE. The sub-settings of this variable provide the parameters +# required to configure the cron job on the target system. +# Cron is a time-based job scheduling program in Unix OSs, which allows tasks to +# be scheduled and executed automatically at a certain point in time. amzn2023cis_aide_cron: + # This variable represents the user account under which the cron job for AIDE will run. cron_user: root + # This variable represents the path to the AIDE crontab file. cron_file: /etc/cron.d/aide_cron + # This variable represents the actual command or script that the cron job + # will execute for running AIDE. aide_job: '/usr/sbin/aide --check' + # These variables define the schedule for the cron job + # This variable governs the minute of the time of day when the AIDE cronjob is run. + # It must be in the range `0-59`. aide_minute: 0 + # This variable governs the hour of the time of day when the AIDE cronjob is run. + # It must be in the range `0-23`. aide_hour: 5 + # This variable governs the day of the month when the AIDE cronjob is run. + # `*` signifies that the job is run on all days; furthermore, specific days + # can be given in the range `1-31`; several days can be concatenated with a comma. + # The specified day(s) must be in the range `1-31`. aide_day: '*' + # This variable governs months when the AIDE cronjob is run. + # `*` signifies that the job is run in every month; furthermore, specific months + # can be given in the range `1-12`; several months can be concatenated with commas. + # The specified month(s) must be in the range `1-12`. aide_month: '*' + # This variable governs the weekdays, when the AIDE cronjob is run. + # `*` signifies that the job is run on all weekdays; furthermore, specific weekdays + # can be given in the range `0-7` (both `0` and `7` represent Sunday); several weekdays + # can be concatenated with commas. aide_weekday: '*' -# SELinux policy +## Control 1.6.1.3 - Ensure SELinux policy is configured +# SELinux implements Mandatory Access Control (MAC). The SELinux policy uses +# a series of rules which define how processes can interact with each other +# and the various system resources. There are two such policies: +# "targeted" - targeted processes run in their own domain, called a confined domain. +# In a confined domain, the files that a targeted process has access to, +# are limited. If a confined process is compromised by an attacker, the +# attacker’s access to resources and the possible damage they can do is +# also limited; +# "mls" - implements Multi-Level Security (MLS), which introduces even more kinds +# of labels (sensitivity and category) and rules that govern access based +# on these; +# The following variable is used to choose which type of SELinux policy will be configured +# by the role. +# CIS provides guidance for the configuration of the "targeted" policy! amzn2023cis_selinux_pol: targeted -# chose conf or enforcing or permissive + +## Control 1.6.1.4 - Ensure the SELinux mode is not disabled +# SELinux can run in one of three modes. This variable is used to select which +# mode shall be used. These are the options: +# "enforcing" - Is the default, and recommended, mode of operation; in enforcing +# mode SELinux operates normally, enforcing the loaded security policy +# on the entire system; +# "permissive" - The system acts as if SELinux is enforcing the loaded security policy, +# including labeling objects and emitting access denial entries in the logs, +# but it does not actually deny any operations. While not recommended for +# production systems, permissive mode can be helpful for SELinux policy +# development; +# "disabled" - Is strongly DISCOURAGED; not only does the system avoid enforcing the +# SELinux policy, it also avoids labeling any persistent objects such as +# files, making it difficult to enable SELinux in the future; amzn2023cis_selinux_enforce: enforcing -# Whether or not to run tasks related to auditing/patching the desktop environment +## Controls 1.7.1, 1.7.2, 1.7.3 - Warning Banner Content +# The following variable is used in templates such as "issue.j2", +# "issue.net.j2" and "motd.j2" which are responsible for configuring +# warning banners. The value of this variable represents the +# content of the warning banner message. +amzn2023cis_warning_banner: Authorized uses only. All activity may be monitored and reported. -## 2. Services +## +## Section 2 Control Variables +## -### 2.1 Time Synchronization -#### 2.1.2 Time Synchronization servers - used in template file chrony.conf.j2 +## Control 2.1.2 - Ensure chrony is configured +# The following list of servers is present in the template file +# chrony.conf.j2 used for setting the configuration for chrony. +# These servers are Time Synchronization servers. amzn2023cis_time_synchronization_servers: - 0.pool.ntp.org - 1.pool.ntp.org - 2.pool.ntp.org - 3.pool.ntp.org +# This variable is also present in the aforementioned template file +# used for setting the chrony configuration. The variable is added next +# to each server from the above list and is used to specify the minimum +# poll interval between updates from a particular time source. Other options +# alongside their accurate and complete descriptions can be consulted at this +# link: 'https://chrony-project.org/doc/3.4/chrony.conf.html'. amzn2023cis_chrony_server_options: "minpoll 8" -### 2.2 Special Purposes -##### Service configuration booleans set true to keep service +## Control 2.2 - Special Purpose Services +# The set of rules that make up section 2.2, are used for ensuring that +# certain services are not installed on the OS. +# The following list of variables determine if a service shall be kept +# on the OS or if it shall be uninstalled. +# Set this variable to `true` to keep service `avahi`; otherwise, the service is uninstalled. amzn2023cis_avahi_server: false +# Set this variable to `true` to keep service `cups`; otherwise, the service is uninstalled. amzn2023cis_cups_server: false +# Set this variable to `true` to keep service `dhcp`; otherwise, the service is uninstalled. amzn2023cis_dhcp_server: false +# Set this variable to `true` to keep service `dns`; otherwise, the service is uninstalled. amzn2023cis_dns_server: false +# Set this variable to `true` to keep service `dnsmasq`; otherwise, the service is uninstalled. amzn2023cis_dnsmasq_server: false +# Set this variable to `true` to keep service `vsftpd`; otherwise, the service is uninstalled. amzn2023cis_vsftpd_server: false +# Set this variable to `true` to keep service `tftp`; otherwise, the service is uninstalled. amzn2023cis_tftp_server: false +# Set this variable to `true` to keep service `httpd`; otherwise, the service is uninstalled. amzn2023cis_httpd_server: false +# Set this variable to `true` to keep service `nginx`; otherwise, the service is uninstalled. amzn2023cis_nginx_server: false +# Set this variable to `true` to keep service `dovecot`; otherwise, the service is uninstalled. amzn2023cis_dovecot_server: false +# Set this variable to `true` to keep service `imap`; otherwise, the service is uninstalled. amzn2023cis_imap_server: false +# Set this variable to `true` to keep service `samba`; otherwise, the service is uninstalled. amzn2023cis_samba_server: false +# Set this variable to `true` to keep service `squid`; otherwise, the service is uninstalled. amzn2023cis_squid_server: false +# Set this variable to `true` to keep service `snmp`; otherwise, the service is uninstalled. amzn2023cis_snmp_server: false -# snmp can be a dependacy for many packages - it is masked only by default if installed + +## Control 2.2.12 - Ensure net-snmp is not installed or the snmpd service is not enabled +# The following variable is used to determine if snmp should be removed +# If snmp is installed, it is masked by default therefore it complies +# from the very begining with CIS's requirements! Given the fact that +# many packages or applications include snmp as a dependency, it would +# be best to leave this variable's value set to 'false'. amzn2023cis_remove_snmp: false + +## Control 2.2.13 - Ensure telnet-server is not installed +# This variable ensures that telnet-server is not installed on the OS. +# Switching it to 'true' will keep the server, leaving it to 'false' will +# remove it! amzn2023cis_telnet_server: false + +## Control 2.2.15 - Ensure mail transfer agent is configured for local-only mode +# This variable is used to determine whether you intend to use your machine as a mail server or not. +# If you do not intend to use it as such, the mail transfer agent (MTA) will be configured to only +# process local mail, in order to reduce chances of security risks. Set to 'false' if your machine +# is not a mail server or to 'true' if it is! amzn2023cis_is_mail_server: false -# Note the options -# Packages are used for client services and Server- only remove if you dont use the client service -# -# optional either remove or mask + +## Control 2.2.16 - Ensure nfs-utils is not installed or the nfs-server service is masked +# In order for the OS to meet CIS's requirements regarding this rule, it is accepted to +# either mask nfs-server or remove nfs-utils. Set the following variables value as it best +# suits your needs, choosing between "mask" or "remove". amzn2023cis_nfs_server: mask + +## Control 2.2.17 - Ensure rpcbind is not installed or the rpcbind services are masked +# In order for the OS to meet CIS's requirements regarding this rule, it is accepted to +# either mask rpcbind services or remove rpcbind. Set the following variables value as it +# best suits your needs, choosing between "mask" or "remove". amzn2023cis_rpc_server: mask + +## Control 2.2.18 - Ensure rsync-daemon is not installed or the rsyncd service is masked +# In order for the OS to meet CIS's requirements regarding this rule, it is accepted to +# either mask rsyncd service or remove rsync-daemon. Set the following variables value as +# it best suits your needs choosing between "mask" or "remove". amzn2023cis_rsync_server: mask -#### 2.3 Service clients +## Control 2.3.1 - Ensure telnet client is not installed +# This variable specifies to the role if telnet is required +# or not. If it is set to 'true' then telnet will not be +# uninstalled. amzn2023cis_telnet_required: false + +## Control 2.3.2 - Ensure LDAP client is not installed +# This variable specifies to the role if LDAP is required +# or not. If it is set to 'true' then LDAP will not be +# uninstalled. amzn2023cis_openldap_clients_required: false + +## Control 2.3.3 - Ensure FTP client is not installed +# This variable specifies to the role if FTP is required +# or not. If it is set to 'true' then FTP will not be +# uninstalled. amzn2023cis_ftp_client: false -## Section3 vars +## +## Section 3 Control Variables +## + ## Sysctl +# Sysctl is a command-line utility on Unix-like OSs that allows +# administrators and users to query and modify kernel parameters +# at run time. It is commonly used for performance optimization, +# security hardening, etc. +# Updating sysctl after modifications is necessary to make the +# changes persistent and ensure they are applied each time the +# system restarts! +# This variable's value controls the execution of a Post task +# responsible for updating sysctl. The default value is 'false', +# but throughout the role, some tasks need sysctl to get +# updated in order for the changes made by them to be fully +# implemented. Therefore, those tasks are setting this variable's +# value to 'true' so as to execute the needed update! amzn2023cis_sysctl_update: false + +# The following variable is responsible for the execution of a +# handler that flushes the ipv4 route table. Although the default +# value is 'false', some tasks are in need of this handler to get +# executed, therefore, they are setting this variable's value to 'true'! amzn2023cis_flush_ipv4_route: false +# The following variable is responsible for the execution of a +# handler that flushes the ipv6 route table. Although the default +# value is 'false', some tasks are in need of this handler to get +# executed, therefore, they are setting this variable's value to 'true'! amzn2023cis_flush_ipv6_route: false -### Firewall Service - either firewalld, iptables, or nftables -#### Some control allow for services to be removed or masked -#### The options are under each heading -#### absent = remove the package -#### masked = leave package if installed and mask the service +## Controls 3.4.1.x and 3.4.2.x Firewall Service +# This variable represents the toggle for which firewall service is used. +# The options are either firewalld or nftables. amzn2023cis_firewall: firewalld -##### firewalld +## Control 3.4.2.1 - Ensure firewalld default zone is set +# This variable specifies which default zone should be set +# for firewalld. A firewall zone defines the trust level for +# a connection, interface or source address binding. The +# default zone is the zone that is used for everything that +# is not explicitly bound/assigned to another zone. +# Options are: +# "block" - All incoming connections are dropped with an +# icmp-host-prohibited message. Only network +# connections initiated from within the system +# are possible; +# "**drop**" - This is the zone with the lowest level of trust. +# All incoming connections are dropped with no reply, +# and only outgoing connections are allowed; +# "public" - This represents untrusted networks. It is implemented +# when you don't trust other servers on the network. +# This is recommended when you have a server hosted on +# the cloud or local network; +# "external" - Used when you want to configure the firewall as a NAT +# gateway. The external zone is used for NAT masquerading +# such that your internal network stays private but +# reachable from external systems; +# "**internal**" - Used for internal networks when you trust other +# computers or servers on your LAN; +# "dmz" - Used for servers or computers in a DMZ ( Demilitarized Zone ). +# These will not be accessible to systems on your network +# and only specific incoming connections are allowed; +# "work" - Used at your place of work where you trust most +# of the computers and co-workers' PCs; +# "home" - Used in the home environment especially on desktops and laptops on +# your LAN. The implication is that you trust most of the +# devices on your home LAN and that some services are allowed; +# "trusted" - All connections are accepted; amzn2023cis_default_zone: public -# These settings are added to demonstrate how this update can be done (eventually will require a new control) -amzn2023cis_firewalld_ports: - - number: 80 - protocol: tcp - -#### nftables +## Control 3.4.2.2 - Ensure at least one nftables table exists +# With this variable you can chose if you want to automatically +# create a new nftable or not. Setting it to 'true' will enable +# that. Otherwise, the tasks will firstly check if there are any +# nftables and if not, they will alert the user about this! amzn2023cis_nft_tables_autonewtable: true +# This variable sets the name of the nftable created. amzn2023cis_nft_tables_tablename: filter + +## Control 3.4.2.3 - Ensure nftables base chains exist +# This variable is similar to the one from Control 3.4.2.2. +# Setting it to 'true' will automatically create nft chains. +# Otherwise, the tasks will display the already existing chains. amzn2023cis_nft_tables_autochaincreate: true -# Warning Banner Content (issue, issue.net, motd) -amzn2023cis_warning_banner: Authorized uses only. All activity may be monitored and reported. -# End Banner +## +## Section 4 Control Variables +## -## Section4 vars +# This variable stores the path to the sshd configuration file +# that the role will use, in order to implement different +# needed controls related to sshd. +amzn2023cis_sshd_config_file: /etc/ssh/sshd_config -### 4.1 Configure System Accounting -#### 4.1.2 Configure Data Retention -amzn2023cis_auditd: - space_left_action: email - action_mail_acct: root - admin_space_left_action: halt - max_log_file_action: keep_logs +## Controls 4.2.4, 4.2.19, 4.2.20 --various sshd settings +amzn2023cis_sshd: + # This variable sets the maximum number of unresponsive "keep-alive" messages + # that can be sent from the server to the client before the connection is considered + # inactive and thus, closed. + clientalivecountmax: 3 + # This variable sets the time interval in seconds between sending "keep-alive" + # messages from the server to the client. These types of messages are intended to + # keep the connection alive and prevent it from being terminated due to inactivity. + clientaliveinterval: 900 + # This variable specifies the amount of seconds allowed for successful authentication to + # the SSH server. + logingracetime: 60 + # WARNING: make sure you understand the precedence when working with the values + # of the following variables + # This variable, if specified, configures a list of USER name patterns, separated by spaces, to allow SSH + # access for users whose user name matches one of the patterns. This is done + # by setting the value of `AllowUsers` option in `/etc/ssh/sshd_config` file. + # If an USER@HOST format will be used, the specified user will be allowed only on that particular host. + # The allow/deny directives process order: DenyUsers, AllowUsers, DenyGroups, AllowGroups. + # For more info, see https://linux.die.net/man/5/sshd_config + allowusers: "" + # This variable, if specified, configures a list of GROUP name patterns, separated by spaces, to allow SSH access + # for users whose primary group or supplementary group list matches one of the patterns. This is done + # by setting the value of `AllowGroups` option in `/etc/ssh/sshd_config` file. + # The allow/deny directives process order: DenyUsers, AllowUsers, DenyGroups, AllowGroups. + # For more info, https://linux.die.net/man/5/sshd_config + allowgroups: "" + # This variable, if specified, configures a list of USER name patterns, separated by spaces, to prevent SSH access + # for users whose user name matches one of the patterns. This is done + # by setting the value of `DenyUsers` option in `/etc/ssh/sshd_config` file. + # If an USER@HOST format will be used, the specified user will be restricted only on that particular host. + # The allow/deny directives process order: DenyUsers, AllowUsers, DenyGroups, AllowGroups. + # For more info, see https://linux.die.net/man/5/sshd_config + denyusers: "" + # This variable, if specified, configures a list of GROUP name patterns, separated by spaces, to prevent SSH access + # for users whose primary group or supplementary group list matches one of the patterns. This is done + # by setting the value of `DenyGroups` option in `/etc/ssh/sshd_config` file. + # The allow/deny directives process order: DenyUsers, AllowUsers, DenyGroups, AllowGroups. + # For more info, see https://linux.die.net/man/5/sshd_config + denygroups: "" + +## Control 4.2.5 - Ensure SSH LogLevel is appropriate +# This variable refers to the loglevel used for ssh. +# The loglevel allows you to control the amount of detail +# included in the server's log files regarding ssh-related +# activities. +# Options recommended by CIS are: +# INFO - the basic level that only records login activity of +# SSH users. In many situations, such as Incident Response, +# it is important to determine when a particular user was +# active on a system. The logout record can eliminate those +# users who disconnected, which helps narrow the field; +# VERBOSE - specifies that login and logout activity as well as the key +# fingerprint for any SSH key used for login will be logged. +# This information is important for SSH key management, especially +# in legacy environments; +amzn2023cis_ssh_loglevel: INFO -# The audit_back_log_limit value should never be below 8192 -amzn2023cis_audit_back_log_limit: '8192' +## Control 4.2.16 - Ensure SSH MaxAuthTries is set to 4 or less +# This variable contains the maximum number of authentication attempts permitted +# per connection. This number should be 4 or less. +amzn2023cis_ssh_maxauthtries: 4 -# The max_log_file parameter should be based on your sites policy -amzn2023cis_max_log_file_size: '10' +## Control 4.2.18 - Ensure SSH MaxSessions is set to 10 or less +# This variable contains the maximum number of open sessions permitted +# from a given connection. This number should be 10 or less. +amzn2023cis_ssh_maxsessions: 4 -### 4.1.3.x audit template -update_audit_template: false +## Control 4.3.3 - Ensure sudo log file exists +# This variable contains the path to the sudo +# log file. +amzn2023cis_sudolog_location: "/var/log/sudo.log" -## Advanced option found in auditd post -amzn2023cis_allow_auditd_uid_user_exclusions: false +## Control 4.3.5 - Ensure sudo authentication timeout is configured correctly +# This variable contains the timeout value for sudo authentication. +# Setting a timeout value reduces the window of opportunity for +# unauthorized privileged access to another user. +# CIS requires a value of 15 or less according to your site's +# policy. +amzn2023cis_sudo_timestamp_timeout: 15 -# This can be used to configure other keys in auditd.conf -amzn2023cis_auditd_extra_conf: {} -# Example: -# amzn2023cis_auditd_extra_conf: -# admin_space_left: '10%' +## Control 4.3.6 - Ensure access to the su command is restricted +# This variable contains the name of the needed empty group +# that will be specified for use of the su command. +# This group's name should be chosen according to site +# policy. +amzn2023cis_sugroup: nosugroup + +## Controls 4.4.1, 4.4.2 - Custom authselect profile settings +# Authselect is another authentication configuration tool +# that aims to provide a more modern and modular approach +# for authentication settings configuration. +amzn2023cis_authselect: + # This setting is just a placeholder taken from the CIS + # examples, which might lead to failure. This setting needs + # to be adjusted in order to minimise risk. + custom_profile_name: custom-profile + # This setting is just a placeholder taken from the CIS + # examples, which might lead to failure. This setting needs + # to be adjusted in order to minimise risk. + default_file_to_copy: "sssd --symlink-meta" + # This setting is just a placeholder taken from the CIS + # examples, which might lead to failure. This setting needs + # to be adjusted in order to minimise risk. + options: with-sudo with-faillock without-nullok + +## Control 4.4.1 - Ensure custom authselect profile is used +# This variable enables automation to create custom profile settings, using the variables above +amzn2023cis_authselect_custom_profile_create: false + +## Control 4.4.2 - Ensure authselect includes with-faillock +# This variable enables automation to select custom profile options, using the variables above +amzn2023cis_authselect_custom_profile_select: false +# This option is used at your own risk. It is responsible for +# enabling faillock for users. +# Only to be used on a new clean system that is not using authselect! +# THIS CAN BREAK ACCESS EVEN FOR ROOT - UNDERSTAND RISKS !! +amzn2023cis_add_faillock_without_authselect: false +# This needs to be set to "ACCEPT" in order for the option +# mentioned above to be implemented! +amzn2023cis_4_4_2_risks: NEVER + +## Controls 4.4.2, 4.5.2 - faillock configurations +amzn2023cis_pam_faillock: + # This variable holds the time in seconds before the account is unlocked. + # CIS states that this value should be at least 900 and should never be 0. + unlock_time: 900 + # This variable holds the number of attempts before the account is locked. + # CIS states that this value should be greater than 0 and no greater than 5. + deny: 5 + # This variable controls for how long failed login attempts are remembered + # for an account. + remember: 5 + +## Control 4.5.1 - Ensure password creation requirements are configured +amzn2023cis_pam_password: + # This variable specifies the minimum length that a password must + # have to be considered valid. CIS states that this value should be + # at least 14. + minlen: 14 + # This variable specifies the minimum number of character classes + # that must be represented in a password. Requiring a minimum + # number of classes ensures diversity in password composition. + # CIS states that this value should be at least 4. + minclass: 4 + +## Controls 4.6.1.x - password configuration +amzn2023cis_pass: + ## Control 4.6.1.1 + # This variable governs after how many days a password expires. + # CIS requires a value of 365 or less. + max_days: 365 + ## Control 4.6.1.2 + # This variable specifies the minimum number of days allowed between changing passwords. + # CIS requires a value of at least 1. + min_days: 1 + ## Control 4.6.1.3 + # This variable governs, how many days before a password expires, the user will be warned! + # CIS requires a value of at least 7. + warn_age: 7 + +# 4.6.1.1 Allow the interactive users not in compliance to force the maxdays change +amzn2023cis_force_user_maxdays: false + +# 4.6.1.2 Allow the interactive users not in compliance to force the mindays change +amzn2023cis_force_user_mindays: false + +# 4.6.1.3 Allow the interactive users not in compliance to force the warndays change +amzn2023cis_force_user_warnage: false -## Preferred method of logging -## Whether rsyslog or journald preferred method for local logging -## Affects rsyslog cis 4.2.1.3 and journald cis 4.2.2.5 +## Control 4.6.1.4 - Ensure inactive password lock is 30 days or less +amzn2023cis_inactivelock: + # The following variable refers to the period of time when + # users can be inactive. Once that period of time is over, + # users will be automatically disabled. The value should be + # 30 or less. + lock_days: 30 + +## Control 4.6.1.5 - Ensure all users last password change date is in the past +# This variable tells the role if the fixing for control 4.6.1.5 shall +# be implemented automatically or not. Setting it to 'true' will ensure +# that the role executes all the necesary changes, in order for this rule +# to become compliant. Otherwise, the role will allert the user with a +# warning, that lists all accounts that have the last PW change date in +# the future. +amzn2023cis_futurepwchgdate_autofix: true + +## Control 4.6.3 - Ensure default user shell timeout is 900 seconds or less +amzn2023cis_shell_session_timeout: + # This variable contains the name of the file in which TMOUT will + # be configured + file: /etc/profile.d/tmout.sh + # This variable holds the value of TMOUT which determines + # the number of seconds after which a shell is automatically + # terminated. TMOUT value is in seconds (e.g. 60 seconds * 10 = 600) + # CIS states that this value shall never exceed 900 or be equal to 0. + timeout: 600 + +## +## Section 5 Control Variables +## + +## Control 5.1 - Configure Logging +# The following variable contains the preferred method used +# for logging. The options are "rsyslog" or "journald". +# The value of this variable controls the importing of +# certain tasks from section 5.1. If the chosen option +# is "rsyslog" then only tasks from 5.1.1.x will be executed. +# Otherwise, only tasks from 5.1.2.x will be executed. amzn2023cis_syslog_service: rsyslog +## Control 5.1.1.5 - Ensure logging is configured +# This variable determines if rsyslog configuration +# shall be ansible managed or not. If you set it to +# 'true' then configuration lines will be automatically +# added to rsyslog. amzn2023cis_rsyslog_ansiblemanaged: true -#### 4.2.1.6 remote and destation log server name +## Control 5.1.1.6 - Ensure rsyslog is configured to send logs to a remote log host +# This variable is used to toggle the execution of control 5.1.1.6, which +# ensures rsyslog sends logs to a remote host. If you do not wish for +# this particular feature to be implemented simply switch the value of +# the variable to 'false'. amzn2023cis_remote_log_server: false +# This variable holds the name chosen for the remote log host. amzn2023cis_remote_log_host: logagg.example.com +# This variable represents the port number for the remote log host amzn2023cis_remote_log_port: 514 +# The following variable mentions the protocol used for sending the +# logs to the remote host. amzn2023cis_remote_log_protocol: tcp +# This variable represents the number of retries that rsyslog +# will attempt to resume the transmission of logs, in case of a +# network or connection failure. amzn2023cis_remote_log_retrycount: 100 +# This variable refers to the maximum number of messages that can +# be held in the internal queue before they are transmitted to their +# destination. amzn2023cis_remote_log_queuesize: 1000 -#### 4.2.1.7 -amzn2023cis_system_is_log_server: false +## Control 5.1.1.7 - Ensure rsyslog is not configured to receive logs from a remote client +# This variable decides whether the system is considered to be a log +# server or not. In the case of option 'true' being selected, the role +# will not proceed to implement control 5.1.1.7. Otherwise, rsyslog +# will not receive logs from a remote client! +amzn2023cis_system_is_log_server: true -# 4.2.2.1.2 -# amzn2023cis_journal_upload_url is the ip address to upload the journal entries to +## Control 5.1.2.1.2 - Ensure systemd-journal-remote is configured +# The following variable represents the IP address where the entries +# of the journal will be uploaded to. amzn2023cis_journal_upload_url: 192.168.50.42 -# The paths below have the default paths/files, but allow user to create custom paths/filenames +## The following variables contain default paths. Users are allowed +## to create their own custom paths! +# This variable represents the path to the private key used by +# systemd-journal-remote. The key is part of the server's +# configuration for secure communication. amzn2023cis_journal_upload_serverkeyfile: "/etc/ssl/private/journal-upload.pem" +# This variable represents the path to the server certificate file +# used by systemd-journal-remote. This certificate is used to verify +# the server's identity. amzn2023cis_journal_servercertificatefile: "/etc/ssl/certs/journal-upload.pem" +# This variable represents the path to a file containing trusted +# certificate authorities that the client trusts. It is used by +# the client to verify the authenticity of the server's certificate. amzn2023cis_journal_trustedcertificatefile: "/etc/ssl/ca/trusted.pem" -# 4.2.2.1 -# The variables below related to journald, please set these to your site specific values -# amzn2023cis_journald_systemmaxuse is the max amount of disk space the logs will use +## Control 5.1.2.6 - Ensure journald log rotation is configured per site policy +## The variables below are related to journald log rotation, +## please set these to your site's specific values! +# This variable represents the max amount of disk space the logs will use. +# When the journal files exceed this size, older journal files +# are deleted to keep the disk space usage below the specified +# limit. The value is in megabytes. amzn2023cis_journald_systemmaxuse: 10M -# amzn2023cis_journald_systemkeepfree is the amount of disk space to keep free +# This variable represents the amount of disk space to be kept free. +# If the free disk space falls below this threshold, older logs are +# deleted to free up space. The value is in gigabytes. amzn2023cis_journald_systemkeepfree: 100G +# This variable is similar to "amzn2023cis_journald_systemmaxuse" +# only that it refers to in-memory space. "Runtime" is about logs +# that are stored in memory (RAM) and are not present on disk. +# These logs are temporary and exist only for the duration +# of the current system runtime. amzn2023cis_journald_runtimemaxuse: 10M +# This variable is similar to "amzn2023cis_journald_systemkeepfree" +# only that it refers to in-memory space that should be kept free. +# "Runtime" is about logs that are stored in memory (RAM) and are not +# present on disk. These logs are temporary and exist only for the +# duration of the current system runtime. amzn2023cis_journald_runtimekeepfree: 100G -# amzn2023cis_journald_MaxFileSec is how long in time to keep log files. Values are Xm, Xh, Xday, Xweek, Xmonth, Xyear, for example 2week is two weeks +# This variable sets the maximum time that logs are retained on disk. +# Logs older than the specified duration are deleted. +# Values are Xm, Xh, Xday, Xweek, Xmonth, Xyear. +# For example: "2week" i.e. two weeks amzn2023cis_journald_maxfilesec: 1month -#### 4.3 -amzn2023cis_logrotate: "daily" - -## Section4 vars +## Control 5.2.1.3 - Ensure audit_backlog_limit is sufficient +# This variable represents the audit backlog limit, i.e. the maximum number of audit records that the +# system can buffer in memory, if the audit subsystem is unable to process them in real-time. +# Buffering in memory is useful in situations, where the audit system is overwhelmed +# with incoming audit events, and needs to temporarily store them until they can be processed. +# This variable should be set to a sufficient value. The CIS baseline recommends at least `8192`. +amzn2023cis_audit_back_log_limit: '8192' -# This will allow use of drop in files when CIS adopts them. -amzn2023cis_sshd_config_file: /etc/ssh/sshd_config +## Control 5.2.2.1 - Ensure audit log storage size is configured +# This variable specifies the maximum size in MB that an audit log file can reach, +# before it is archived or deleted to make space for the new audit data. +# This should be set based on your sites policy. CIS does not provide a specific value. +amzn2023cis_max_log_file_size: '10' -amzn2023cis_sshd: - clientalivecountmax: 0 - clientaliveinterval: 900 - logingracetime: 60 - # WARNING: make sure you understand the precedence when working with these values!! - # allowusers: - # allowgroups: systems dba - # denyusers: - # denygroups: +## Control 5.2.2.x - Configure Data Retention +# This variable controls how the audit system behaves when +# log files are getting too full and space is getting too low. +amzn2023cis_auditd: + # This variable tells the system what action to take when the system has detected + # that it is starting to get low on disk space. + # The options for setting this variable are as follows: + # "ignore" - the system does nothing when presented with the aforementioned issue; + # "syslog" - a message is sent to the system log about disk space running low; + # "email" - the system sends an email notification to the email address + # specified in the "action_mail_acct" variable; + # "exec" - the system executes a custom command when disk space is running + # low; + # "suspend" - the system suspends recording audit events until more space is available; + # "single" - the audit daemon will put the computer system in single user mode; + # "halt" - the system is halted when disk space is critically low; + space_left_action: email + # This variable specifies an e-mail address or alias to which any alert messages + # should be sent. The default setting is root, but you can enter any local or + # remote account as long as e-mail and the network are properly configured on + # your system and /usr/lib/sendmail exists. + action_mail_acct: root + # This variable tells the system what action to take when the system has detected + # that it is low on disk space. + # The options for setting this variable are as follows: + # "ignore" - the system does nothing when presented with the aforementioned issue; + # "syslog" - a message is sent to the system log about disk space running low; + # "email" - the system sends an email notification to the email address + # specified in the "action_mail_acct" variable; + # "exec" - the system executes a custom command when disk space is running + # low; + # "suspend" - the system suspends recording audit events until more space is available; + # "single" - the audit daemon will put the computer system in single user mode; + # "halt" - the system is halted when disk space is critically low; + # CIS prescribes either `halt` or `single`. + admin_space_left_action: halt + # This variable determines what action the audit system should take when the maximum + # size of a log file is reached. + # The options for setting this variable are as follows: + # "ignore" - the system does nothing when the size of a log file is full; + # "syslog" - a message is sent to the system log indicating the problem; + # "suspend" - the system suspends recording audit events until the log file is cleared or rotated; + # "rotate" - the log file is rotated (archived) and a new empty log file is created; + # "keep_logs" - the system attempts to keep as many logs as possible without violating disk + # space constraints; + # CIS prescribes the value `keep_logs`. + max_log_file_action: keep_logs -# 4.2.5 SSH LogLevel setting. Options are INFO or VERBOSE -amzn2023cis_ssh_loglevel: INFO +## Control 5.2.3.x - Audit template +# This variable's value controls the execution of a main task +# responsible for importing the yml file needed for configuring +# the auditd rules (auditd.yml). The default value is 'false', +# but tasks responsible for the configuration mentioned earlier, +# are setting it to 'true'. +update_audit_template: false -# 4.2.19 SSH MaxSessions setting. Must be 4 our less -amzn2023cis_ssh_maxsessions: 4 -amzn2023cis_inactivelock: - lock_days: 30 +# This variable is used to condition the execution of a POST task +# from the "auditd.yml" file. That task implements an advanced option +# and it only gets executed if this variable's value is set to 'true'. +# The advance option sets users whose actions are not logged by auditd. +amzn2023cis_allow_auditd_uid_user_exclusions: false -amzn2023cis_use_authconfig: false -# 4.3.1/4.3.2 Custom authselect profile settings. Settings in place now will fail, they are place holders from the control example -# Due to the way many multiple options and ways to configure this control needs to be enabled and settings adjusted to minimise risk -amzn2023cis_authselect: - custom_profile_name: custom-profile - default_file_to_copy: "sssd --symlink-meta" - options: with-sudo with-faillock without-nullok +# This variable can be used to configure other keys in auditd.conf +# Example: +# amzn2023cis_auditd_extra_conf: +# admin_space_left: '10%' +amzn2023cis_auditd_extra_conf: + # This variable governs the threshold(MegaBytes) under which the audit daemon should perform a + # specific action to alert that the system is running low on disk space. Must be lower than + # the 'space_left' variable. + admin_space_left: 50 + # This variable governs the threshold(MegaBytes) under which the audit daemon should perform a + # specific action to alert that the system is running low on disk space(last chance to do something + # before running out of disk space). Must be lower than the 'space_left' variable. + space_left: 75 + +## Control 5.3 - Ensure logrotate is configured +# This variable is used to specify the regularity of +# log file rotation. +amzn2023cis_logrotate: "daily" -# 4.3.1 Enable automation to create custom profile settings, using the settings above -amzn2023cis_authselect_custom_profile_create: false +## +## Section 6 Control Variables +## -# 4.3.2 Enable automation to select custom profile options, using the settings above -amzn2023cis_authselect_custom_profile_select: false +## Control 6.1.9 - Ensure permissions on /etc/gshadow- are configured +# This variable contains the name of the file where the list +# of package discrepancies can be found! +amzn2023cis_rpm_audit_file: /var/tmp/rpm_file_check -amzn2023cis_pass: - max_days: 365 - min_days: 1 - warn_age: 7 +## Control 6.1.10 - Audit system file permissions +# The following variable is a toggle for enabling/disabling the automated +# removal of world-writable permissions from all files. +# Possible values are 'true' and 'false'. +amzn2023cis_no_world_write_adjust: true -# UID settings for interactive users -# These are discovered via logins.def if set true +## Control 6.2.10 - Ensure local interactive user home directories are configured +# The minimum and maximum UIDs to be used when enforcing +# and checking control 6.2.10 can either be discovered +# automatically via logins.def or set manually in this +# file. +# If min/maxx UIDs are to be discovered automatically, +# set this variable to 'true', otherwise to 'false'. discover_int_uid: false +# This variable sets the minimum number from which to search for UID +# Note that the value will be dynamically overwritten if variable "dicover_int_uid" has +# been set to 'true'. min_int_uid: 1000 +# This variable sets the maximum number at which the search stops for UID +# Note that the value will be dynamically overwritten if variable "dicover_int_uid" has +# been set to 'true'. max_int_uid: 65533 -# 4.3.3 var log location variable -amzn2023cis_sudolog_location: "/var/log/sudo.log" - -#### 4.3.6 -amzn2023cis_sudo_timestamp_timeout: 15 - -# 4.3.7 -amzn2023cis_sugroup: nosugroup - -### 4.4.2 authselect and faillock -## This option is used at your own risk it will enable faillock for users -## Only to be used on a new clean system if not using authselect -## THIS CAN BREAK ACCESS EVEN FOR ROOT - UNDERSTAND RISKS ## -amzn2023cis_add_faillock_without_authselect: false -# This needs to be set to ACCEPT -amzn2023cis_4_4_2_risks: NEVER - -# Session timeout setting file (TMOUT setting can be set in multiple files) -# Timeout value is in seconds. (60 seconds * 10 = 600) -amzn2023cis_shell_session_timeout: - file: /etc/profile.d/tmout.sh - timeout: 600 -# Allow ansible to expire password for account with a last changed date in the future. False will just display users in violation, true will expire those users passwords -amzn2023cis_futurepwchgdate_autofix: true - -# 4.5.1 -## PAM -amzn2023cis_pam_password: - minlen: 14 - minclass: 4 - -amzn2023cis_pam_faillock: - unlock_time: 900 - deny: 5 - remember: 5 - -## Section6 vars - -amzn2023cis_rpm_audit_file: /var/tmp/rpm_file_check - -# Allow ansible to adjust world-writable files. False will just display world-writable files, True will remove world-writable -amzn2023cis_no_world_write_adjust: true -amzn2023cis_passwd_label: "{{ (this_item | default(item)).id }}: {{ (this_item | default(item)).dir }}" - -# This will allow the removal of .netrc, .forward or .rhosts if found from user home_dirs +## Control 6.2.11 - Ensure local interactive user dot files access is configured +# This variable will allow the removal of .netrc, .forward or .rhosts files. amzn2023cis_remove_other_dot_files: false - +# This variable states if filesystem links should be followed or not. amzn2023cis_6_2_11_home_follow_symlinks: false #### Goss Configuration Settings #### @@ -632,47 +1234,3 @@ audit_run_script_environment: AUDIT_BIN: "{{ audit_bin }}" AUDIT_FILE: 'goss.yml' AUDIT_CONTENT_LOCATION: "{{ audit_out_dir }}" - -### Goss binary settings ### -audit_bin_release: v0.4.0 -audit_bin_version: - AMD64_checksum: 'sha256:9cb37863d3d25e2af80cb5cf55198c0c115b2477724153ba9afd0a2e544cb46e' - ARM64_checksum: 'sha256:ce364fad93f9c0702e73767d60fddbb87a8c5f2a586b0d99ec823e8331e6a73b' -audit_bin_path: /usr/local/bin/ -audit_bin: "{{ audit_bin_path }}goss" -audit_format: json - -# if get_goss_file == download change accordingly -audit_bin_url: "https://github.com/goss-org/goss/releases/download/{{ audit_bin_release }}/goss-linux-" - -## if get_goss_file - copy the following needs to be updated for your environment -## it is expected that it will be copied from somewhere accessible to the control node -## e.g copy from ansible control node to remote host -copy_goss_from_path: /some/accessible/path - -### Goss Audit Benchmark file ### -## managed by the control audit_content -# git -audit_file_git: "https://github.com/ansible-lockdown/{{ benchmark }}-Audit.git" -audit_git_version: "benchmark_{{ benchmark_version }}" - -# copy: -audit_local_copy: "some path to copy from" - -# get_url: -audit_files_url: "some url maybe s3?" - -## Goss configuration information -# Where the goss configs and outputs are stored -audit_out_dir: '/opt' -audit_conf_dir: "{{ audit_out_dir }}/{{ benchmark }}-Audit/" -pre_audit_outfile: "{{ audit_out_dir }}/{{ ansible_hostname }}-{{ benchmark }}_pre_scan_{{ ansible_date_time.epoch }}.{{ audit_format }}" -post_audit_outfile: "{{ audit_out_dir }}/{{ ansible_hostname }}-{{ benchmark }}_post_scan_{{ ansible_date_time.epoch }}.{{ audit_format }}" - -## The following should not need changing -goss_file: "{{ audit_conf_dir }}goss.yml" -audit_vars_path: "{{ audit_conf_dir }}/vars/{{ ansible_hostname }}.yml" -audit_results: | - The pre remediation results are: {{ pre_audit_summary }}. - The post remediation results are: {{ post_audit_summary }}. - Full breakdown can be found in {{ audit_out_dir }} diff --git a/tasks/LE_audit_setup.yml b/tasks/LE_audit_setup.yml index c4a2e4b..7ef94b4 100644 --- a/tasks/LE_audit_setup.yml +++ b/tasks/LE_audit_setup.yml @@ -5,12 +5,12 @@ - name: Pre Audit Setup | Set audit package name | 64bit ansible.builtin.set_fact: audit_pkg_arch_name: AMD64 - when: ansible_machine == "x86_64" + when: ansible_facts.machine == "x86_64" - name: Pre Audit Setup | Set audit package name | ARM64 ansible.builtin.set_fact: audit_pkg_arch_name: ARM64 - when: ansible_machine == "arm64" + when: ansible_facts.machine == "arm64" - name: Pre Audit Setup | Download audit binary ansible.builtin.get_url: @@ -19,7 +19,7 @@ owner: root group: root checksum: "{{ audit_bin_version[audit_pkg_arch_name + '_checksum'] }}" - mode: 0555 + mode: '0555' when: - get_audit_binary_method == 'download' @@ -27,7 +27,7 @@ ansible.builtin.copy: src: "{{ audit_bin_copy_location }}" dest: "{{ audit_bin }}" - mode: 0555 + mode: '0555' owner: root group: root when: diff --git a/tasks/audit_only.yml b/tasks/audit_only.yml new file mode 100644 index 0000000..864f5bb --- /dev/null +++ b/tasks/audit_only.yml @@ -0,0 +1,30 @@ +--- + +- name: Audit_Only | Create local Directories for hosts + ansible.builtin.file: + mode: '0755' + path: "{{ audit_capture_files_dir }}/{{ inventory_hostname }}" + recurse: true + state: directory + when: fetch_audit_files + delegate_to: localhost + become: false + +- name: Audit_only | Get audits from systems and put in group dir + ansible.builtin.fetch: + dest: "{{ audit_capture_files_dir }}/{{ inventory_hostname }}/" + flat: true + mode: '0644' + src: "{{ pre_audit_outfile }}" + when: fetch_audit_files + +- name: Audit_only | Show Audit Summary + when: + - audit_only + ansible.builtin.debug: + msg: "The Audit results are: {{ pre_audit_summary }}." + +- name: Audit_only | Stop Playbook Audit Only selected + when: + - audit_only + ansible.builtin.meta: end_play diff --git a/tasks/main.yml b/tasks/main.yml index 678c65a..b8ad6ba 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -2,12 +2,12 @@ # tasks file for AMAZON2023 - name: Check OS version and family + ansible.builtin.assert: + that: (ansible_facts.distribution == 'Amazon' and ansible_facts.distribution_major_version is version_compare('2023', '==')) + fail_msg: "This role can only be run against Supported OSs. {{ ansible_facts.distribution }} {{ ansible_facts.distribution_major_version }} is not supported." + success_msg: "This role is running against a supported OS {{ ansible_facts.distribution }} {{ ansible_facts.distribution_major_version }}" when: - os_check - ansible.builtin.assert: - that: (ansible_distribution == 'Amazon' and ansible_distribution_major_version is version_compare('2023', '==')) - fail_msg: "This role can only be run against Supported OSs. {{ ansible_distribution }} {{ ansible_distribution_major_version }} is not supported." - success_msg: "This role is running against a supported OS {{ ansible_distribution }} {{ ansible_distribution_major_version }}" tags: - always @@ -31,7 +31,7 @@ - name: Ensure root password is set ansible.builtin.assert: that: root_passwd_set.rc == 0 - fail_msg: "You have rule 5.6.6 enabled this requires that you have a root password set" + fail_msg: "You have rule 4.6.6 enabled this requires that you have a root password set" success_msg: "You have a root password set" tags: - level1-server @@ -42,8 +42,8 @@ - name: Setup rules if container when: - - ansible_connection == 'docker' or - ansible_virtualization_type in ["docker", "lxc", "openvz", "podman", "container"] + - ansible_connection == 'docker' or ( ansible_virtualization_type is defined and + ansible_virtualization_type in ["docker", "lxc", "openvz", "podman", "container"]) block: - name: Discover and set container variable if required ansible.builtin.set_fact: @@ -92,13 +92,22 @@ - prelim_tasks - always -- name: Run pre_remediation audit +- name: Include audit specific variables when: + - run_audit or audit_only + - setup_audit + tags: + - setup_audit - run_audit - ansible.builtin.include_tasks: - file: pre_remediation_audit.yml + ansible.builtin.include_vars: audit.yml + +- name: Include pre-remediation audit tasks + when: + - run_audit or audit_only + - setup_audit tags: - run_audit + ansible.builtin.import_tasks: pre_remediation_audit.yml - name: Run Section 1 tasks when: diff --git a/tasks/post_remediation_audit.yml b/tasks/post_remediation_audit.yml index f0a7664..954d9f1 100644 --- a/tasks/post_remediation_audit.yml +++ b/tasks/post_remediation_audit.yml @@ -1,46 +1,46 @@ --- -- name: "Post Audit | Run post_remediation {{ benchmark }} audit" - ansible.builtin.shell: "{{ audit_conf_dir }}/run_audit.sh -v {{ audit_vars_path }} -o {{ post_audit_outfile }} -g {{ group_names }}" +- name: Post Audit | Run post_remediation {{ benchmark }} audit + ansible.builtin.shell: "{{ audit_conf_dir }}/run_audit.sh -v {{ audit_vars_path }} -o {{ post_audit_outfile }} -g \"{{ group_names }}\"" changed_when: true environment: AUDIT_BIN: "{{ audit_bin }}" AUDIT_CONTENT_LOCATION: "{{ audit_out_dir }}" - AUDIT_FILE: "goss.yml" + AUDIT_FILE: goss.yml - name: Post Audit | ensure audit files readable by users ansible.builtin.file: path: "{{ item }}" - mode: 0644 + mode: '0644' state: file loop: - "{{ post_audit_outfile }}" - "{{ pre_audit_outfile }}" - name: Post Audit | Capture audit data if json format + when: + - audit_format == "json" block: - - name: "capture data {{ post_audit_outfile }}" - ansible.builtin.shell: "cat {{ post_audit_outfile }}" + - name: capture data {{ post_audit_outfile }} + ansible.builtin.shell: cat {{ post_audit_outfile }} register: post_audit changed_when: false - name: Capture post-audit result ansible.builtin.set_fact: - post_audit_summary: "{{ post_audit.stdout | from_json | json_query(summary) }}" + post_audit_summary: "{{ post_audit.stdout | from_json | community.general.json_query(summary) }}" vars: - summary: 'summary."summary-line"' - when: - - audit_format == "json" + summary: summary."summary-line" - name: Post Audit | Capture audit data if documentation format + when: + - audit_format == "documentation" block: - - name: "Post Audit | capture data {{ post_audit_outfile }}" - ansible.builtin.shell: "tail -2 {{ post_audit_outfile }}" + - name: Post Audit | capture data {{ post_audit_outfile }} + ansible.builtin.shell: tail -2 {{ post_audit_outfile }} register: post_audit changed_when: false - name: Post Audit | Capture post-audit result ansible.builtin.set_fact: post_audit_summary: "{{ post_audit.stdout_lines }}" - when: - - audit_format == "documentation" diff --git a/tasks/pre_remediation_audit.yml b/tasks/pre_remediation_audit.yml index 4b60075..ba1cafd 100644 --- a/tasks/pre_remediation_audit.yml +++ b/tasks/pre_remediation_audit.yml @@ -1,20 +1,21 @@ --- -- name: Pre Audit Binary Setup | Setup the LE audit - ansible.builtin.include_tasks: - file: LE_audit_setup.yml +- name: Pre Audit Setup | Setup the LE audit when: - setup_audit tags: - setup_audit + ansible.builtin.include_tasks: LE_audit_setup.yml -- name: "Pre Audit Setup | Ensure {{ audit_conf_dir }} exists" +- name: Pre Audit Setup | Ensure {{ audit_conf_dir }} exists ansible.builtin.file: path: "{{ audit_conf_dir }}" state: directory mode: '0755' - name: Pre Audit Setup | If using git for content set up + when: + - audit_content == 'git' block: - name: Pre Audit Setup | Install git ansible.builtin.package: @@ -26,32 +27,32 @@ repo: "{{ audit_file_git }}" dest: "{{ audit_conf_dir }}" version: "{{ audit_git_version }}" - when: - - audit_content == 'git' - name: Pre Audit Setup | Copy to audit content files to server - ansible.builtin.copy: - src: "{{ audit_local_copy }}" - dest: "{{ audit_conf_dest }}" - mode: preserve when: - audit_content == 'copy' + ansible.builtin.copy: + src: "{{ audit_conf_copy }}" + dest: "{{ audit_conf_dir }}" + mode: preserve - name: Pre Audit Setup | Unarchive audit content files on server + when: + - audit_content == 'archived' ansible.builtin.unarchive: src: "{{ audit_conf_copy }}" dest: "{{ audit_conf_dir }}" - when: - - audit_content == 'archived' - name: Pre Audit Setup | Get audit content from url + when: + - audit_content == 'get_url' ansible.builtin.get_url: url: "{{ audit_files_url }}" dest: "{{ audit_conf_dir }}" - when: - - audit_content == 'get_url' - name: Pre Audit Setup | Check Goss is available + when: + - run_audit block: - name: Pre Audit Setup | Check for goss file ansible.builtin.stat: @@ -59,55 +60,59 @@ register: goss_available - name: Pre Audit Setup | If audit ensure goss is available + when: + - not goss_available.stat.exists ansible.builtin.assert: - that: goss_available.stat.exists msg: "Audit has been selected: unable to find goss binary at {{ audit_bin }}" - when: - - run_audit - name: Pre Audit Setup | Copy ansible default vars values to test audit + tags: + - goss_template + - run_audit + when: + - run_audit ansible.builtin.template: src: ansible_vars_goss.yml.j2 dest: "{{ audit_vars_path }}" - mode: 0600 - when: - - run_audit - tags: - - goss_template - - always + mode: '0600' -- name: "Pre Audit | Run pre_remediation {{ benchmark }} audit" - ansible.builtin.shell: "{{ audit_conf_dir }}/run_audit.sh -v {{ audit_vars_path }} -o {{ pre_audit_outfile }} -g {{ group_names }}" +- name: Pre Audit | Run pre_remediation {{ benchmark }} audit + ansible.builtin.shell: "{{ audit_conf_dir }}/run_audit.sh -v {{ audit_vars_path }} -o {{ pre_audit_outfile }} -g \"{{ group_names }}\"" changed_when: true environment: AUDIT_BIN: "{{ audit_bin }}" AUDIT_CONTENT_LOCATION: "{{ audit_out_dir }}" - AUDIT_FILE: "goss.yml" + AUDIT_FILE: goss.yml - name: Pre Audit | Capture audit data if json format + when: + - audit_format == "json" block: - - name: "capture data {{ pre_audit_outfile }}" - ansible.builtin.shell: "cat {{ pre_audit_outfile }}" + - name: capture data {{ pre_audit_outfile }} + ansible.builtin.shell: cat {{ pre_audit_outfile }} register: pre_audit changed_when: false - name: Pre Audit | Capture pre-audit result ansible.builtin.set_fact: - pre_audit_summary: "{{ pre_audit.stdout | from_json | json_query(summary) }}" + pre_audit_summary: "{{ pre_audit.stdout | from_json | community.general.json_query(summary) }}" vars: - summary: 'summary."summary-line"' - when: - - audit_format == "json" + summary: summary."summary-line" - name: Pre Audit | Capture audit data if documentation format + when: + - audit_format == "documentation" block: - - name: "Pre Audit | capture data {{ pre_audit_outfile }} | documentation format" - ansible.builtin.shell: "tail -2 {{ pre_audit_outfile }}" + - name: Pre Audit | capture data {{ pre_audit_outfile }} | documentation format + ansible.builtin.shell: tail -2 {{ pre_audit_outfile }} register: pre_audit changed_when: false - name: Pre Audit | Capture pre-audit result | documentation format ansible.builtin.set_fact: pre_audit_summary: "{{ pre_audit.stdout_lines }}" + +- name: Audit_Only | Run Audit Only when: - - audit_format == "documentation" + - audit_only + ansible.builtin.import_tasks: audit_only.yml diff --git a/tasks/prelim.yml b/tasks/prelim.yml index 90bb606..3214e45 100644 --- a/tasks/prelim.yml +++ b/tasks/prelim.yml @@ -2,32 +2,34 @@ # Preliminary tasks that should always be run # List users in order to look files inside each home directory -- name: "PRELIM | List users accounts" - ansible.builtin.shell: "awk -F: '{print $1}' /etc/passwd" + +- name: "PRELIM | AUDIT | Interactive Users" + tags: + - always + ansible.builtin.shell: > + grep -E -v '^(root|halt|sync|shutdown)' /etc/passwd | awk -F: '(!index($7, "sbin/nologin") && $7 != "/bin/nologin" && $7 != "/bin/false") { print $1 }' changed_when: false - check_mode: false - register: users + register: discovered_interactive_usernames + +- name: "PRELIM | AUDIT | Interactive User accounts home directories" tags: - - level1-server - - users + - always + ansible.builtin.shell: > + grep -E -v '^(root|halt|sync|shutdown)' /etc/passwd | awk -F: '(!index($7, "sbin/nologin") && $7 != "/bin/nologin" && $7 != "/bin/false") { print $6 }' + changed_when: false + register: discovered_interactive_users_home + +- name: "PRELIM | AUDIT | Interactive UIDs" + tags: + - always + ansible.builtin.shell: > + grep -E -v '^(root|halt|sync|shutdown)' /etc/passwd | awk -F: '(!index($7, "sbin/nologin") && $7 != "/bin/nologin" && $7 != "/bin/false") { print $3 }' + changed_when: false + register: discovered_interactive_uids - name: "PRELIM | capture /etc/password variables" ansible.builtin.include_tasks: file: parse_etc_password.yml - tags: - - rule_5.5.2 - - rule_5.6.2 - - rule_6.2.9 - - rule_6.2.10 - - rule_6.2.11 - - amzn2023cis_section5 - - amzn2023cis_section6 - - level1-server - -- name: "PRELIM | Interactive User accounts" - ansible.builtin.shell: 'cat /etc/passwd | grep -Ev "nologin|/sbin" | cut -d: -f6' - changed_when: false - register: interactive_users_home tags: - always @@ -93,7 +95,7 @@ - name: "PRELIM | Section 1.1 | Create list of mount points" ansible.builtin.set_fact: - mount_names: "{{ ansible_mounts | map(attribute='mount') | list }}" + mount_names: "{{ ansible_facts.mounts | map(attribute='mount') | list }}" tags: - level1-server @@ -132,6 +134,8 @@ state: latest when: - amzn2023cis_rule_1_2_4 + tags: + - always - name: "PRELIM | Section 4.1 | Configure cron" ansible.builtin.package: @@ -161,6 +165,50 @@ - ssh - level1_server +- name: "PRELIM | Section 4.2 | SSH - Identify files in sshd_config.d Dir" + ansible.builtin.find: + patterns: '*.conf' + path: /etc/ssh/sshd_config.d + register: sshd_d_conf_files + when: + - "'openssh-server' in ansible_facts.packages" + tags: + - always + +- name: "PRELIM | Section 4.2 | SSH - Search for main cfg file" + ansible.builtin.stat: + path: "{{ amzn2023cis_sshd_config_file }}" + register: main_sshd_cfg + when: + - "'openssh-server' in ansible_facts.packages" + tags: + - always + +- name: "PRELIM | 4.3.4 | Find all sudoers files." + ansible.builtin.shell: "find /etc/sudoers /etc/sudoers.d/ -type f ! -name '*~' ! -name '*.*'" + changed_when: false + failed_when: false + check_mode: false + register: amzn2023cis_sudoers_files + when: + - amzn2023cis_rule_4_3_4 + tags: + - rule_4.3.4 + - sudo + - patch + +- name: "PRELIM | 4.4.x | Install authselect" + ansible.builtin.package: + name: authselect + state: present + become: true + when: + - '"authselect" not in ansible_facts.packages' + - amzn2023cis_rule_4_4_1 + - amzn2023cis_rule_4_4_2 + tags: + - always + - name: "PRELIM | Section 5.2 | Configure System Accounting (auditd)" ansible.builtin.package: name: audit @@ -194,42 +242,6 @@ - rule_5.2.4.6 - rule_5.2.4.7 -- name: "PRELIM | Install authconfig" - ansible.builtin.package: - name: authconfig - state: present - become: true - when: - - amzn2023cis_use_authconfig - - amzn2023cis_rule_5_3_1 or - amzn2023cis_rule_5_3_2 or - amzn2023cis_rule_5_3_3 or - '"authconfig" not in ansible_facts.packages or - "auditd-lib" not in ansible_facts.packages' - tags: - - level1-server - - level1-workstation - - rule_5.3.1 or - rule_5.3.2 or - rule_5.3.3 - - authconfig - - auditd - -- name: "PRELIM | 4.3.3 | Find all sudoers files." - ansible.builtin.shell: "find /etc/sudoers /etc/sudoers.d/ -type f ! -name '*~' ! -name '*.*'" - changed_when: false - failed_when: false - check_mode: false - register: amzn2023cis_sudoers_files - when: - - amzn2023cis_rule_4_3_3 or - amzn2023cis_rule_4_3_4 - tags: - - rule_4.3.3 - - rule_4.3.4 - - sudo - - patch - - name: "PRELIM | Discover Interactive UID MIN and MIN from logins.def" block: - name: "PRELIM | Capture UID_MIN information from logins.def" diff --git a/tasks/section_1/cis_1.1.2.x.yml b/tasks/section_1/cis_1.1.2.x.yml index 514651d..58bc13b 100644 --- a/tasks/section_1/cis_1.1.2.x.yml +++ b/tasks/section_1/cis_1.1.2.x.yml @@ -34,7 +34,7 @@ state: present opts: defaults,{% if amzn2023cis_rule_1_1_2_2 %}nodev,{% endif %}{% if amzn2023cis_rule_1_1_2_3 %}noexec,{% endif %}{% if amzn2023cis_rule_1_1_2_4 %}nosuid{% endif %} notify: Remount tmp - loop: "{{ ansible_mounts }}" + loop: "{{ ansible_facts.mounts }}" loop_control: label: "{{ item.device }}" when: @@ -54,7 +54,6 @@ # via systemd - name: | - "1.1.2.1 | PATCH | Ensure /tmp is configured" "1.1.2.2 | PATCH | Ensure nodev option set on /tmp partition" "1.1.2.3 | PATCH | Ensure noexec option set on /tmp partition" "1.1.2.4 | PATCH | Ensure nosuid option set on /tmp partition" @@ -67,15 +66,13 @@ notify: Systemd restart tmp.mount when: - amzn2023cis_tmp_svc - - amzn2023cis_rule_1_1_2_1 or - amzn2023cis_rule_1_1_2_2 or + - amzn2023cis_rule_1_1_2_2 or amzn2023cis_rule_1_1_2_3 or amzn2023cis_rule_1_1_2_4 tags: - level1-server - patch - mounts - - rule_1.1.2.1 - rule_1.1.2.2 - rule_1.1.2.3 - rule_1.1.2.4 diff --git a/tasks/section_1/cis_1.1.3.x.yml b/tasks/section_1/cis_1.1.3.x.yml index fda1806..3630ae9 100644 --- a/tasks/section_1/cis_1.1.3.x.yml +++ b/tasks/section_1/cis_1.1.3.x.yml @@ -31,7 +31,7 @@ fstype: "{{ item.fstype }}" state: present opts: defaults,{% if amzn2023cis_rule_1_1_3_2 %}nodev,{% endif %}{% if amzn2023cis_rule_1_1_3_3 %}nosuid,{% endif %} - loop: "{{ ansible_mounts }}" + loop: "{{ ansible_facts.mounts }}" loop_control: label: "{{ item.device }}" notify: Change_requires_reboot diff --git a/tasks/section_1/cis_1.1.4.x.yml b/tasks/section_1/cis_1.1.4.x.yml index 317635c..7034969 100644 --- a/tasks/section_1/cis_1.1.4.x.yml +++ b/tasks/section_1/cis_1.1.4.x.yml @@ -33,7 +33,7 @@ fstype: "{{ item.fstype }}" state: present opts: defaults,{% if amzn2023cis_rule_1_1_4_2 %}noexec,{% endif %}{% if amzn2023cis_rule_1_1_4_3 %}nosuid,{% endif %}{% if amzn2023cis_rule_1_1_4_4 %}nodev{% endif %} - loop: "{{ ansible_mounts }}" + loop: "{{ ansible_facts.mounts }}" loop_control: label: "{{ item.device }}" notify: Change_requires_reboot diff --git a/tasks/section_1/cis_1.1.5.x.yml b/tasks/section_1/cis_1.1.5.x.yml index 26e0926..f1643d3 100644 --- a/tasks/section_1/cis_1.1.5.x.yml +++ b/tasks/section_1/cis_1.1.5.x.yml @@ -33,7 +33,7 @@ fstype: "{{ item.fstype }}" state: present opts: defaults,{% if amzn2023cis_rule_1_1_5_2 %}nodev,{% endif %}{% if amzn2023cis_rule_1_1_5_3 %}noexec,{% endif %}{% if amzn2023cis_rule_1_1_5_4 %}nosuid{% endif %} - loop: "{{ ansible_mounts }}" + loop: "{{ ansible_facts.mounts }}" loop_control: label: "{{ item.device }}" notify: Change_requires_reboot diff --git a/tasks/section_1/cis_1.1.6.x.yml b/tasks/section_1/cis_1.1.6.x.yml index 72c6055..da21d73 100644 --- a/tasks/section_1/cis_1.1.6.x.yml +++ b/tasks/section_1/cis_1.1.6.x.yml @@ -33,7 +33,7 @@ fstype: "{{ item.fstype }}" state: present opts: defaults,{% if amzn2023cis_rule_1_1_6_2 %}noexec,{% endif %}{% if amzn2023cis_rule_1_1_6_3 %}nodev,{% endif %}{% if amzn2023cis_rule_1_1_6_4 %}nosuid{% endif %} - loop: "{{ ansible_mounts }}" + loop: "{{ ansible_facts.mounts }}" loop_control: label: "{{ item.device }}" notify: Change_requires_reboot diff --git a/tasks/section_1/cis_1.1.7.x.yml b/tasks/section_1/cis_1.1.7.x.yml index 53a7424..6c04091 100644 --- a/tasks/section_1/cis_1.1.7.x.yml +++ b/tasks/section_1/cis_1.1.7.x.yml @@ -32,13 +32,12 @@ fstype: "{{ item.fstype }}" state: present opts: defaults,{% if amzn2023cis_rule_1_1_7_2 %}nodev,{% endif %}{% if amzn2023cis_rule_1_1_7_3 %}nosuid,{% endif %} - loop: "{{ ansible_mounts }}" + loop: "{{ ansible_facts.mounts }}" loop_control: label: "{{ item.device }}" notify: Change_requires_reboot when: - item.mount == "/home" - - amzn2023cis_rule_1_1_7_1 - amzn2023cis_rule_1_1_7_2 or amzn2023cis_rule_1_1_7_3 tags: @@ -47,6 +46,5 @@ - mounts - rule_1.1.7.2 - rule_1.1.7.3 - - rule_1.1.7.4 - nist_sp800-53r5_AC-3 - nist_sp800-53r5_MP-2 diff --git a/tasks/section_1/cis_1.3.x.yml b/tasks/section_1/cis_1.3.x.yml index f951332..ba181ee 100644 --- a/tasks/section_1/cis_1.3.x.yml +++ b/tasks/section_1/cis_1.3.x.yml @@ -53,7 +53,7 @@ - rule_1.3.2 - nist_sp800-53r5_AU-2 -- name: "1.3.3 | Ensure cryptographic mechanisms are used to protect the integrity of audit tools" +- name: "1.3.3 | PATCH | Ensure cryptographic mechanisms are used to protect the integrity of audit tools" ansible.builtin.blockinfile: path: /etc/aide.conf marker: "# {mark} Audit tools - CIS benchmark - Ansible-lockdown" @@ -66,7 +66,7 @@ /sbin/autrace p+i+n+u+g+s+b+acl+xattrs+sha512 validate: aide -D --config %s when: - - amzn2023cis_rule_1_3_2 + - amzn2023cis_rule_1_3_3 tags: - level1-server - aide diff --git a/tasks/section_1/main.yml b/tasks/section_1/main.yml index f6acd63..a9db36c 100644 --- a/tasks/section_1/main.yml +++ b/tasks/section_1/main.yml @@ -54,7 +54,7 @@ file: cis_1.5.x.yml - name: "SECTION | 1.6 | Mandatory Access Control" - ansible.builtin.include_tasks: + ansible.builtin.import_tasks: file: cis_1.6.1.x.yml when: not amzn2023cis_selinux_disable @@ -67,5 +67,5 @@ file: cis_1.8.yml - name: "SECTION | 1.9 | Crypto policies" - ansible.builtin.include_tasks: + ansible.builtin.import_tasks: file: cis_1.9.yml diff --git a/tasks/section_2/cis_2.1.x.yml b/tasks/section_2/cis_2.1.x.yml index 97620c4..8311441 100644 --- a/tasks/section_2/cis_2.1.x.yml +++ b/tasks/section_2/cis_2.1.x.yml @@ -19,7 +19,7 @@ - name: "2.1.2 | PATCH | Ensure chrony is configured | Set configuration" ansible.builtin.template: src: etc/chrony.conf.j2 - dest: /etc/chrony.conf + dest: /etc/chrony.d/chrony.conf owner: root group: root mode: '0644' diff --git a/tasks/section_2/cis_2.2.x.yml b/tasks/section_2/cis_2.2.x.yml index 549600a..98677df 100644 --- a/tasks/section_2/cis_2.2.x.yml +++ b/tasks/section_2/cis_2.2.x.yml @@ -308,7 +308,7 @@ when: - amzn2023cis_rpc_server == "remove" - - name: "2.2.17 | PATCH | Ensure rpcbind is not installed or the rpcbind services are masked | mask service" + - name: "2.2.17 | PATCH | Ensure rpcbind is not installed or the rpcbind services are masked | mask socket" ansible.builtin.systemd: name: rpcbind.socket masked: true @@ -316,6 +316,15 @@ daemon_reload: true when: - amzn2023cis_rpc_server == "mask" + + - name: "2.2.17 | PATCH | Ensure rpcbind is not installed or the rpcbind services are masked | mask service" + ansible.builtin.systemd: + name: rpcbind.service + masked: true + state: stopped + daemon_reload: true + when: + - amzn2023cis_rpc_server == "mask" when: - "'rpcbind' in ansible_facts.packages" - amzn2023cis_rule_2_2_17 diff --git a/tasks/section_4/cis_4.1.x.yml b/tasks/section_4/cis_4.1.x.yml index 758c94c..5592247 100644 --- a/tasks/section_4/cis_4.1.x.yml +++ b/tasks/section_4/cis_4.1.x.yml @@ -46,7 +46,7 @@ - level1-server - patch - cron - - rule_5.1.3 + - rule_4.1.3 - nist_sp800-53r5_AC-3 - nist_sp800-53r5_MP-2 @@ -170,6 +170,6 @@ - level1-server - patch - cron - - rule_5.1.9 + - rule_4.1.9 - nist_sp800-53r5_AC-3 - nist_sp800-53r5_MP-2 diff --git a/tasks/section_4/cis_4.2.x.yml b/tasks/section_4/cis_4.2.x.yml index c8151a3..06a542a 100644 --- a/tasks/section_4/cis_4.2.x.yml +++ b/tasks/section_4/cis_4.2.x.yml @@ -1,6 +1,6 @@ --- -- name: "4.2.1 | Ensure permissions on /etc/ssh/sshd_config are configured" +- name: "4.2.1 | PATCH | Ensure permissions on /etc/ssh/sshd_config are configured" ansible.builtin.file: path: "/etc/ssh/sshd_config" owner: root @@ -125,10 +125,13 @@ - name: "4.2.5 | PATCH | Ensure SSH LogLevel is appropriate" ansible.builtin.lineinfile: - path: "{{ amzn2023cis_sshd_config_file }}" + path: "{{ item.path }}" regexp: "^#LogLevel|^LogLevel" line: 'LogLevel {{ amzn2023cis_ssh_loglevel }}' validate: sshd -t -f %s + with_items: + - "{{ sshd_d_conf_files.files }}" + - "{{ main_sshd_cfg.stat }}" when: - amzn2023cis_rule_4_2_5 tags: @@ -142,10 +145,13 @@ - name: "4.2.6 | PATCH | Ensure SSH PAM is enabled" ansible.builtin.lineinfile: - path: "{{ amzn2023cis_sshd_config_file }}" + path: "{{ item.path }}" regexp: "^#UsePAM|^UsePAM" line: 'UsePAM yes' validate: sshd -t -f %s + with_items: + - "{{ sshd_d_conf_files.files }}" + - "{{ main_sshd_cfg.stat }}" when: - amzn2023cis_rule_4_2_6 tags: @@ -161,10 +167,13 @@ - name: "4.2.7 | PATCH | Ensure SSH root login is disabled" ansible.builtin.lineinfile: - path: "{{ amzn2023cis_sshd_config_file }}" + path: "{{ item.path }}" regexp: "^#PermitRootLogin|^PermitRootLogin" line: 'PermitRootLogin no' validate: sshd -t -f %s + with_items: + - "{{ sshd_d_conf_files.files }}" + - "{{ main_sshd_cfg.stat }}" when: - amzn2023cis_rule_4_2_7 tags: @@ -176,10 +185,13 @@ - name: "4.2.8 | PATCH | Ensure SSH HostbasedAuthentication is disabled" ansible.builtin.lineinfile: - path: "{{ amzn2023cis_sshd_config_file }}" + path: "{{ item.path }}" regexp: "^#HostbasedAuthentication|^HostbasedAuthentication" line: 'HostbasedAuthentication no' validate: sshd -t -f %s + with_items: + - "{{ sshd_d_conf_files.files }}" + - "{{ main_sshd_cfg.stat }}" when: - amzn2023cis_rule_4_2_8 tags: @@ -195,10 +207,13 @@ - name: "4.2.9 | PATCH | Ensure SSH PermitEmptyPasswords is disabled" ansible.builtin.lineinfile: - path: "{{ amzn2023cis_sshd_config_file }}" + path: "{{ item.path }}" regexp: "^#PermitEmptyPasswords|^PermitEmptyPasswords" line: 'PermitEmptyPasswords no' validate: sshd -t -f %s + with_items: + - "{{ sshd_d_conf_files.files }}" + - "{{ main_sshd_cfg.stat }}" when: - amzn2023cis_rule_4_2_9 tags: @@ -214,10 +229,13 @@ - name: "4.2.10 | PATCH | Ensure SSH PermitUserEnvironment is disabled" ansible.builtin.lineinfile: - path: "{{ amzn2023cis_sshd_config_file }}" + path: "{{ item.path }}" regexp: "^#PermitUserEnvironment|^PermitUserEnvironment" line: 'PermitUserEnvironment no' validate: sshd -t -f %s + with_items: + - "{{ sshd_d_conf_files.files }}" + - "{{ main_sshd_cfg.stat }}" when: - amzn2023cis_rule_4_2_10 tags: @@ -252,10 +270,13 @@ - name: "4.2.12 | PATCH | Ensure SSH X11 forwarding is disabled" ansible.builtin.lineinfile: - path: "{{ amzn2023cis_sshd_config_file }}" + path: "{{ item.path }}" regexp: "^#X11Forwarding|^X11Forwarding" line: 'X11Forwarding no' validate: sshd -t -f %s + with_items: + - "{{ sshd_d_conf_files.files }}" + - "{{ main_sshd_cfg.stat }}" when: - amzn2023cis_rule_4_2_12 tags: @@ -267,10 +288,13 @@ - name: "4.2.13 | PATCH | Ensure SSH AllowTcpForwarding is disabled" ansible.builtin.lineinfile: - path: "{{ amzn2023cis_sshd_config_file }}" + path: "{{ item.path }}" regexp: "^#AllowTcpForwarding|^AllowTcpForwarding" line: 'AllowTcpForwarding no' validate: sshd -t -f %s + with_items: + - "{{ sshd_d_conf_files.files }}" + - "{{ main_sshd_cfg.stat }}" when: - amzn2023cis_rule_4_2_13 tags: @@ -327,10 +351,13 @@ - name: "4.2.16 | PATCH | Ensure SSH MaxAuthTries is set to 4 or less" ansible.builtin.lineinfile: - path: "{{ amzn2023cis_sshd_config_file }}" + path: "{{ item.path }}" regexp: '^(#)?MaxAuthTries \d' - line: 'MaxAuthTries 4' + line: 'MaxAuthTries {{ amzn2023cis_ssh_maxauthtries }}' validate: sshd -t -f %s + with_items: + - "{{ sshd_d_conf_files.files }}" + - "{{ main_sshd_cfg.stat }}" when: - amzn2023cis_rule_4_2_16 tags: @@ -342,10 +369,13 @@ - name: "4.2.17 | PATCH | Ensure SSH MaxStartups is configured" ansible.builtin.lineinfile: - path: "{{ amzn2023cis_sshd_config_file }}" + path: "{{ item.path }}" regexp: "^#MaxStartups|^MaxStartups" line: 'MaxStartups 10:30:60' validate: sshd -t -f %s + with_items: + - "{{ sshd_d_conf_files.files }}" + - "{{ main_sshd_cfg.stat }}" when: - amzn2023cis_rule_4_2_17 tags: @@ -361,10 +391,13 @@ - name: "4.2.18 | PATCH | Ensure SSH MaxSessions is set to 10 or less" ansible.builtin.lineinfile: - path: "{{ amzn2023cis_sshd_config_file }}" + path: "{{ item.path }}" regexp: "^#MaxSessions|^MaxSessions" line: 'MaxSessions {{ amzn2023cis_ssh_maxsessions }}' validate: sshd -t -f %s + with_items: + - "{{ sshd_d_conf_files.files }}" + - "{{ main_sshd_cfg.stat }}" when: - amzn2023cis_rule_4_2_18 tags: @@ -380,10 +413,13 @@ - name: "4.2.19 | PATCH | Ensure SSH LoginGraceTime is set to one minute or less" ansible.builtin.lineinfile: - path: "{{ amzn2023cis_sshd_config_file }}" + path: "{{ item.path }}" regexp: "^#LoginGraceTime|^LoginGraceTime" line: "LoginGraceTime {{ amzn2023cis_sshd['logingracetime'] }}" validate: sshd -t -f %s + with_items: + - "{{ sshd_d_conf_files.files }}" + - "{{ main_sshd_cfg.stat }}" when: - amzn2023cis_rule_4_2_19 tags: @@ -397,17 +433,23 @@ block: - name: "4.2.20 | PATCH | Ensure SSH Idle Timeout Interval is configured | Add line in sshd_config for ClientAliveInterval" ansible.builtin.lineinfile: - path: "{{ amzn2023cis_sshd_config_file }}" + path: "{{ item.path }}" regexp: '^ClientAliveInterval' line: "ClientAliveInterval {{ amzn2023cis_sshd['clientaliveinterval'] }}" validate: sshd -t -f %s + with_items: + - "{{ sshd_d_conf_files.files }}" + - "{{ main_sshd_cfg.stat }}" - name: "4.2.20 | PATCH | Ensure SSH Idle Timeout Interval is configured | Ensure SSH ClientAliveCountMax set to <= 3" ansible.builtin.lineinfile: - path: "{{ amzn2023cis_sshd_config_file }}" + path: "{{ item.path }}" regexp: '^ClientAliveCountMax' line: "ClientAliveCountMax {{ amzn2023cis_sshd['clientalivecountmax'] }}" validate: sshd -t -f %s + with_items: + - "{{ sshd_d_conf_files.files }}" + - "{{ main_sshd_cfg.stat }}" when: - amzn2023cis_rule_4_2_20 tags: diff --git a/tasks/section_4/cis_4.6.1.x.yml b/tasks/section_4/cis_4.6.1.x.yml index 82094ba..9a4e526 100644 --- a/tasks/section_4/cis_4.6.1.x.yml +++ b/tasks/section_4/cis_4.6.1.x.yml @@ -1,10 +1,29 @@ --- - name: "4.6.1.1 | PATCH | Ensure password expiration is 365 days or less" - ansible.builtin.lineinfile: - path: /etc/login.defs - regexp: '^PASS_MAX_DAYS' - line: "PASS_MAX_DAYS {{ amzn2023cis_pass['max_days'] }}" + block: + - name: "4.6.1.1 | PATCH | Ensure password expiration is 365 days or less" + ansible.builtin.lineinfile: + path: /etc/login.defs + regexp: '^PASS_MAX_DAYS' + line: "PASS_MAX_DAYS {{ amzn2023cis_pass['max_days'] }}" + + - name: "4.6.1.1 | AUDIT | Ensure password expiration is 365 days or less | Get existing users PASS_MAX_DAYS" + ansible.builtin.shell: "awk -F: '(/^[^:]+:[^!*]/ && ($5> {{ amzn2023cis_pass['max_days'] }} || $5< {{ amzn2023cis_pass['max_days'] }} || $5 == -1)){print $1}' /etc/shadow" + changed_when: false + failed_when: false + register: discovered_max_days + + - name: "4.6.1.1 | PATCH | Ensure password expiration is 365 days or less | Set existing users PASS_MAX_DAYS" + ansible.builtin.user: + name: "{{ item }}" + password_expire_max: "{{ amzn2023cis_pass['max_days'] }}" + loop: "{{ discovered_max_days.stdout_lines }}" + when: + - discovered_max_days.stdout_lines | length > 0 + - item in discovered_interactive_usernames.stdout + - amzn2023cis_force_user_maxdays + when: - amzn2023cis_rule_4_6_1_1 tags: @@ -19,10 +38,29 @@ - nist_sp800-53r5_IA-5 - name: "4.6.1.2 | PATCH | Ensure minimum days between password changes is configured" - ansible.builtin.lineinfile: - path: /etc/login.defs - regexp: '^PASS_MIN_DAYS' - line: "PASS_MIN_DAYS {{ amzn2023cis_pass['min_days'] }}" + block: + - name: "4.6.1.2 | PATCH | Ensure minimum days between password changes is configured | set login.defs" + ansible.builtin.lineinfile: + path: /etc/login.defs + regexp: '^PASS_MIN_DAYS' + line: "PASS_MIN_DAYS {{ amzn2023cis_pass['min_days'] }}" + + - name: "4.6.1.2 | AUDIT | Ensure minimum days between password changes is configured | Get existing users PASS_MIN_DAYS" + ansible.builtin.shell: "awk -F: '/^[^:]+:[^!*]/ && $4< {{ amzn2023cis_pass['min_days'] }} {print $1}' /etc/shadow" + changed_when: false + failed_when: false + register: discovered_min_days + + - name: "4.6.1.2 | PATCH | Ensure minimum days between password changes is configured | Set existing users PASS_MIN_DAYS" + ansible.builtin.user: + name: "{{ item }}" + password_expire_max: "{{ amzn2023cis_pass['min_days'] }}" + loop: "{{ discovered_min_days.stdout_lines }}" + when: + - discovered_min_days.stdout_lines | length > 0 + - item in discovered_interactive_usernames.stdout + - amzn2023cis_force_user_mindays + when: - amzn2023cis_rule_4_6_1_2 tags: @@ -37,10 +75,26 @@ - nist_sp800-53r5_IA-5 - name: "4.6.1.3 | PATCH | Ensure password expiration warning days is 7 or more" - ansible.builtin.lineinfile: - path: /etc/login.defs - regexp: '^PASS_WARN_AGE' - line: "PASS_WARN_AGE {{ amzn2023cis_pass['warn_age'] }}" + block: + - name: "4.6.1.3 | PATCH | Ensure password expiration warning days is 7 or more | set login.defs" + ansible.builtin.lineinfile: + path: /etc/login.defs + regexp: '^PASS_WARN_AGE' + line: "PASS_WARN_AGE {{ amzn2023cis_pass['warn_age'] }}" + + - name: "4.6.1.3 | AUDIT | Ensure password expiration warning days is 7 or more | Get existing users WARN_DAYS" + ansible.builtin.shell: "awk -F: '/^[^:]+:[^!*]/ && $6< {{ amzn2023cis_pass['warn_age'] }} {print $1}' /etc/shadow" + changed_when: false + failed_when: false + register: discovered_warn_days + + - name: "4.6.1.3 | PATCH | Ensure password expiration warning days is 7 or more | Set existing users WARN_DAYS" + ansible.builtin.shell: "chage --warndays {{ amzn2023cis_pass['warn_age'] }} {{ item }}" + loop: "{{ discovered_warn_days.stdout_lines }}" + when: + - discovered_warn_days.stdout_lines | length > 0 + - item in discovered_interactive_usernames.stdout + - amzn2023cis_force_user_warnage when: - amzn2023cis_rule_4_6_1_3 tags: diff --git a/tasks/section_4/cis_4.6.x.yml b/tasks/section_4/cis_4.6.x.yml index 88e787c..67a4046 100644 --- a/tasks/section_4/cis_4.6.x.yml +++ b/tasks/section_4/cis_4.6.x.yml @@ -2,7 +2,7 @@ - name: "4.6.2 | PATCH | Ensure system accounts are secured" block: - - name: "4.6.2 | Ensure system accounts are secured | Set nologin" + - name: "4.6.2 | PATCH | Ensure system accounts are secured | Set nologin" ansible.builtin.user: name: "{{ item.id }}" shell: /usr/sbin/nologin @@ -90,14 +90,14 @@ - name: "4.6.5 | PATCH | Ensure default user umask is 027 or more restrictive" block: - name: "4.6.5 | PATCH | Ensure default user umask is 027 or more restrictive | Set umask for /etc/login.defs pam_umask settings" - ansible.builtin.lineinfile: - path: "{{ item.path }}" - regexp: '(?i)(umask\s*)' - line: '{{ item.line }} 027' - with_items: - - { path: '/etc/bashrc', line: 'umask' } - - { path: '/etc/profile', line: 'umask' } - - { path: '/etc/login.defs', line: 'UMASK' } + ansible.builtin.replace: + path: "{{ item }}" + regexp: ^(?i)(\s*umask)\s+(?!\d*[2,7]7)\d{3,4} + replace: '\1 027' + loop: + - /etc/bashrc + - /etc/profile + - /etc/login.defs - name: "4.6.5 | PATCH | Ensure default user umask is 027 or more restrictive | Set umask for /etc/bashrc" ansible.builtin.lineinfile: diff --git a/tasks/section_5/cis_5.2.4.x.yml b/tasks/section_5/cis_5.2.4.x.yml index 1aff30d..d6aedf1 100644 --- a/tasks/section_5/cis_5.2.4.x.yml +++ b/tasks/section_5/cis_5.2.4.x.yml @@ -63,12 +63,11 @@ - name: "5.2.4.5 | PATCH | Ensure audit configuration files are 640 or more restrictive" ansible.builtin.file: path: "{{ item.path }}" - mode: '0640' - loop: "{{ auditd_conf_files.files }}" + mode: g-wx,o-rwx + loop: "{{ auditd_conf_files.files | default([]) }}" loop_control: label: "{{ item.path }}" when: - - item.mode != '06(0|4)0' - amzn2023cis_rule_5_2_4_5 tags: - level2-server diff --git a/tasks/section_5/main.yml b/tasks/section_5/main.yml index 447229f..b70adc3 100644 --- a/tasks/section_5/main.yml +++ b/tasks/section_5/main.yml @@ -37,7 +37,3 @@ - name: "SECTION | 5.3 | Configure LogRotate" ansible.builtin.import_tasks: file: cis_5.3.yml - -- name: "SECTION | 5.3 | Configure logrotate" - ansible.builtin.import_tasks: - file: cis_5.3.yml diff --git a/tasks/section_6/cis_6.1.x.yml b/tasks/section_6/cis_6.1.x.yml index 826117a..c286220 100644 --- a/tasks/section_6/cis_6.1.x.yml +++ b/tasks/section_6/cis_6.1.x.yml @@ -177,7 +177,7 @@ - name: "6.1.10 | PATCH | Ensure world writable files and directories are secured" block: - name: "6.1.10 | AUDIT | Ensure world writable files and directories are secured | Get list of world-writable files" - ansible.builtin.shell: df --local -P | awk {'if (NR!=1) print $6'} | xargs -I '{}' find '{}' -xdev -type f -perm -0002 + ansible.builtin.shell: df --local -P | awk {'if (NR!=1) print $6'} | xargs -I '{}' find \( ! -path "*/containerd/*" -a ! -path "*/kubelet/pods/*" -a ! -path "/snap/*" \) -xdev -type f -perm -0002 failed_when: false changed_when: false register: amzn2023cis_6_1_10_perms_results @@ -191,6 +191,11 @@ when: - amzn2023cis_6_1_10_perms_results.stdout_lines is defined - amzn2023cis_no_world_write_adjust + + - name: "6.1.10 | PATCH | Ensure sticky bit is set on all world-writable directories" + ansible.builtin.shell: df --local -P | awk {'if (NR!=1) print $6'} | xargs -I '{}' find '{}' -xdev -type d -perm -0002 2>/dev/null | xargs chmod a+t + changed_when: false + failed_when: false when: - amzn2023cis_rule_6_1_10 tags: @@ -198,6 +203,7 @@ - patch - files - permissions + - stickybits - rule_6.1.10 - nist_sp800-53r5_AC-3 - nist_sp800-53r5_MP-2 @@ -210,7 +216,7 @@ failed_when: false check_mode: false register: amzn2023cis_6_1_11_audit - loop: "{{ ansible_mounts }}" + loop: "{{ ansible_facts.mounts }}" loop_control: label: "{{ item.mount }}" when: @@ -237,7 +243,7 @@ failed_when: false changed_when: false register: amzn2023cis_6_1_11_audit - loop: "{{ ansible_mounts }}" + loop: "{{ ansible_facts.mounts }}" loop_control: label: "{{ item.mount }}" when: @@ -278,21 +284,6 @@ - nist_sp800-53r5_AC-3 - nist_sp800-53r5_MP-2 -- name: "6.1.12 | PATCH | Ensure sticky bit is set on all world-writable directories" - ansible.builtin.shell: df --local -P | awk {'if (NR!=1) print $6'} | xargs -I '{}' find '{}' -xdev -type d -perm -0002 2>/dev/null | xargs chmod a+t - changed_when: false - failed_when: false - when: - - amzn2023cis_rule_6_1_12 - tags: - - level1-server - - patch - - stickybits - - permissons - - rule_6.1.12 - - nist_sp800-53r5_AC-3 - - nist_sp800-53r5_MP-2 - - name: "6.1.12 | AUDIT | Ensure SUID and SGID files are reviewed" block: - name: "6.1.12 | AUDIT | Ensure SUID and SGID files are reviewed | Find all SUID executables" @@ -300,7 +291,7 @@ failed_when: false changed_when: false register: amzn2023cis_6_1_12_suid_perms - loop: "{{ ansible_mounts }}" + loop: "{{ ansible_facts.mounts }}" loop_control: label: "{{ item.mount }}" @@ -323,7 +314,7 @@ failed_when: false changed_when: false register: amzn2023cis_6_1_12_sgid_perms - loop: "{{ ansible_mounts }}" + loop: "{{ ansible_facts.mounts }}" loop_control: label: "{{ item.mount }}" diff --git a/tasks/section_6/cis_6.2.x.yml b/tasks/section_6/cis_6.2.x.yml index c100d41..ef25e44 100644 --- a/tasks/section_6/cis_6.2.x.yml +++ b/tasks/section_6/cis_6.2.x.yml @@ -78,7 +78,7 @@ - nist_sp800-53r5_CM-7 - nist_sp800-53r5_IA-5 -- name: "6.2.4 | AUDIT Ensure no duplicate UIDs exist" +- name: "6.2.4 | AUDIT | Ensure no duplicate UIDs exist" block: - name: "6.2.4 | AUDIT | Ensure no duplicate UIDs exist | Check for duplicate UIDs" ansible.builtin.shell: "pwck -r | awk -F: '{if ($3 in uid) print $1 ; else uid[$3]}' /etc/passwd" @@ -317,7 +317,7 @@ etype: group permissions: rx state: present - loop: "{{ interactive_users_home.stdout_lines }}" + loop: "{{ discovered_interactive_users_home.stdout_lines }}" when: not system_is_container - name: "6.2.10 | PATCH | Ensure local interactive user home directories exist | Set other ACL" @@ -327,7 +327,7 @@ etype: other permissions: 0 state: present - loop: "{{ interactive_users_home.stdout_lines }}" + loop: "{{ discovered_interactive_users_home.stdout_lines }}" when: not system_is_container when: - amzn2023cis_rule_6_2_10 @@ -368,9 +368,9 @@ path: "{{ item }}" state: absent loop: - - "{{ interactive_users_home.stdout_lines }}/.netrc" - - "{{ interactive_users_home.stdout_lines }}/.rhosts" - - "{{ interactive_users_home.stdout_lines }}/.forward" + - "{{ discovered_interactive_users_home.stdout_lines }}/.netrc" + - "{{ discovered_interactive_users_home.stdout_lines }}/.rhosts" + - "{{ discovered_interactive_users_home.stdout_lines }}/.forward" when: amzn2023cis_remove_other_dot_files when: diff --git a/templates/ansible_vars_goss.yml.j2 b/templates/ansible_vars_goss.yml.j2 index 00e421d..39dadbd 100644 --- a/templates/ansible_vars_goss.yml.j2 +++ b/templates/ansible_vars_goss.yml.j2 @@ -6,11 +6,11 @@ benchmark_version: '1.0.0' # If run via script this is discovered and set -host_os_distribution: {{ ansible_distribution | lower }} +host_os_distribution: {{ ansible_facts.distribution | lower }} # timeout for each command to run where set - default = 10seconds/10000ms -timeout_ms: 60000 -amzn2023cis_run_heavy_tests: {{ amzn2023cis_run_heavy_tests }} +timeout_ms: {{ audit_cmd_timeout }} +amzn2023cis_run_heavy_tests: {{ audit_run_heavy_tests }} amzn2023cis_section1: {{ amzn2023cis_section1 }} amzn2023cis_section2: {{ amzn2023cis_section2 }} @@ -463,33 +463,20 @@ amzn2023cis_sugroup: {{ amzn2023cis_sugroup }} ## Section 5 +amzn2023cis_system_is_log_server: {{ amzn2023cis_system_is_log_server }} -## Set if host is a logserver +## syslog +amzn2023cis_is_syslog_server: {{ amzn2023cis_system_is_log_server }} +amzn2023cis_syslog_service: "{{ amzn2023cis_syslog_service }}" amzn2023cis_remote_log_server: {{ amzn2023cis_remote_log_server }} -# Remote logserver settings +#### remote and destination log server name amzn2023cis_remote_log_host: {{ amzn2023cis_remote_log_host }} amzn2023cis_remote_log_port: {{ amzn2023cis_remote_log_port }} amzn2023cis_remote_log_protocol: {{ amzn2023cis_remote_log_protocol }} amzn2023cis_remote_log_retrycount: {{ amzn2023cis_remote_log_retrycount }} amzn2023cis_remote_log_queuesize: {{ amzn2023cis_remote_log_queuesize }} -## syslog -amzn2023cis_is_syslog_server: {{ amzn2023cis_system_is_log_server }} -amzn2023cis_syslog_service: "{{ amzn2023cis_syslog_service }}" -amzn2023cis_remote_log_server: "{{ amzn2023cis_remote_log_server }}" - -#### remote and destination log server name -amzn2023cis_remote_log_server: false -amzn2023cis_remote_log_host: logagg.example.com -amzn2023cis_remote_log_port: 514 -amzn2023cis_remote_log_protocol: tcp -amzn2023cis_remote_log_retrycount: 100 -amzn2023cis_remote_log_queuesize: 1000 - -amzn2023cis_system_is_log_server: {{ amzn2023cis_system_is_log_server }} - -# # amzn2023cis_journal_upload_url is the ip address to upload the journal entries to amzn2023cis_journal_upload_url: 192.168.50.42 diff --git a/vars/audit.yml b/vars/audit.yml new file mode 100644 index 0000000..26e2b87 --- /dev/null +++ b/vars/audit.yml @@ -0,0 +1,38 @@ +--- + +#### Audit Configuration Settings #### + +# if get_audit_binary_method == download change accordingly +audit_bin_url: "https://github.com/goss-org/goss/releases/download/{{ audit_bin_version.release }}/goss-linux-" + +### Goss Audit Benchmark file ### +## managed by the control audit_content +# git +audit_file_git: "https://github.com/ansible-lockdown/{{ benchmark }}-Audit.git" +audit_git_version: "benchmark_{{ benchmark_version }}" + +## Goss configuration information +# Where the goss configs and outputs are stored +audit_out_dir: '/opt' +# Where the goss audit configuration will be stored +audit_conf_dir: "{{ audit_out_dir }}/{{ benchmark }}-Audit" + +# If changed these can affect other products +pre_audit_outfile: "{{ audit_out_dir }}/{{ ansible_facts.hostname }}-{{ benchmark }}-{{ benchmark_version }}_pre_scan_{{ ansible_facts.date_time.epoch }}.{{ audit_format }}" +post_audit_outfile: "{{ audit_out_dir }}/{{ ansible_facts.hostname }}-{{ benchmark }}-{{ benchmark_version }}_post_scan_{{ ansible_facts.date_time.epoch }}.{{ audit_format }}" + +## The following should not need changing + +### Audit binary settings ### +audit_bin_version: + release: v0.4.4 + AMD64_checksum: 'sha256:1c4f54b22fde9d4d5687939abc2606b0660a5d14a98afcd09b04b793d69acdc5' +audit_bin_path: /usr/local/bin/ +audit_bin: "{{ audit_bin_path }}goss" +audit_format: json + +audit_vars_path: "{{ audit_conf_dir }}/vars/{{ ansible_facts.hostname }}.yml" +audit_results: | + The pre remediation results are: {{ pre_audit_summary }}. + The post remediation results are: {{ post_audit_summary }}. + Full breakdown can be found in {{ audit_out_dir }}