diff --git a/.github/workflows/devel_pipeline_validation.yml b/.github/workflows/devel_pipeline_validation.yml index 39af625a..c9328cbc 100644 --- a/.github/workflows/devel_pipeline_validation.yml +++ b/.github/workflows/devel_pipeline_validation.yml @@ -1,138 +1,158 @@ --- - name: Devel pipeline - - on: # yamllint disable-line rule:truthy - pull_request_target: - types: [opened, reopened, synchronize] - branches: - - devel - paths: - - '**.yml' - - '**.sh' - - '**.j2' - - '**.ps1' - - '**.cfg' - - # A workflow run is made up of one or more jobs - # that can run sequentially or in parallel - jobs: - # This will create messages for first time contributers and direct them to the Discord server - welcome: - runs-on: ubuntu-latest - - steps: - - uses: actions/first-interaction@main - with: - repo-token: ${{ secrets.GITHUB_TOKEN }} - pr-message: |- - Congrats on opening your first pull request and thank you for taking the time to help improve Ansible-Lockdown! - Please join in the conversation happening on the [Discord Server](https://www.lockdownenterprise.com/discord) as well. - - # This workflow contains a single job that tests the playbook - playbook-test: - # The type of runner that the job will run on - runs-on: ubuntu-latest - env: - ENABLE_DEBUG: ${{ vars.ENABLE_DEBUG }} - # Imported as a variable by terraform - TF_VAR_repository: ${{ github.event.repository.name }} - defaults: - run: - shell: bash - working-directory: .github/workflows/github_linux_IaC - - steps: - - name: Clone ${{ github.event.repository.name }} - uses: actions/checkout@v4 + name: Devel pipeline + + on: # yamllint disable-line rule:truthy + pull_request_target: + types: [opened, reopened, synchronize] + branches: + - devel + paths: + - '**.yml' + - '**.sh' + - '**.j2' + - '**.ps1' + - '**.cfg' + # Allow manual running of workflow + workflow_dispatch: + + # Allow permissions for AWS auth + permissions: + id-token: write + contents: read + pull-requests: read + + # A workflow run is made up of one or more jobs + # that can run sequentially or in parallel + jobs: + # This will create messages for first time contributers and direct them to the Discord server + welcome: + runs-on: ubuntu-latest + + steps: + - uses: actions/first-interaction@main with: - ref: ${{ github.event.pull_request.head.sha }} - - # Pull in terraform code for linux servers - - name: Clone GitHub IaC plan - uses: actions/checkout@v4 - with: - repository: ansible-lockdown/github_linux_IaC - path: .github/workflows/github_linux_IaC - - - name: Add_ssh_key - working-directory: .github/workflows - env: - SSH_AUTH_SOCK: /tmp/ssh_agent.sock - PRIVATE_KEY: "${{ secrets.SSH_PRV_KEY }}" - run: | - mkdir .ssh - chmod 700 .ssh - echo $PRIVATE_KEY > .ssh/github_actions.pem - chmod 600 .ssh/github_actions.pem - - - name: DEBUG - Show IaC files - if: env.ENABLE_DEBUG == 'true' - run: | - echo "OSVAR = $OSVAR" - echo "benchmark_type = $benchmark_type" - pwd - ls - env: - # Imported from GitHub variables this is used to load the relevant OS.tfvars file - OSVAR: ${{ vars.OSVAR }} - benchmark_type: ${{ vars.BENCHMARK_TYPE }} - - - name: Terraform_Init - id: init - run: terraform init - env: - # Imported from GitHub variables this is used to load the relevant OS.tfvars file - OSVAR: ${{ vars.OSVAR }} - TF_VAR_benchmark_type: ${{ vars.BENCHMARK_TYPE }} - - - name: Terraform_Validate - id: validate - run: terraform validate - env: - # Imported from GitHub variables this is used to load the relevant OS.tfvars file - OSVAR: ${{ vars.OSVAR }} - TF_VAR_benchmark_type: ${{ vars.BENCHMARK_TYPE }} - - - name: Terraform_Apply - id: apply - env: - AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} - AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} - OSVAR: ${{ vars.OSVAR }} - TF_VAR_benchmark_type: ${{ vars.BENCHMARK_TYPE }} - run: terraform apply -var-file "github_vars.tfvars" -var-file "${OSVAR}.tfvars" --auto-approve -input=false - - ## Debug Section - - name: DEBUG - Show Ansible hostfile - if: env.ENABLE_DEBUG == 'true' - run: cat hosts.yml - - # Aws deployments taking a while to come up insert sleep or playbook fails - - - name: Sleep for 60 seconds - run: sleep ${{ vars.BUILD_SLEEPTIME }} - - # Run the Ansible playbook - - name: Run_Ansible_Playbook - uses: arillso/action.playbook@master - with: - playbook: site.yml - inventory: .github/workflows/github_linux_IaC/hosts.yml - galaxy_file: collections/requirements.yml - private_key: ${{ secrets.SSH_PRV_KEY }} - # verbose: 3 - env: - ANSIBLE_HOST_KEY_CHECKING: "false" - ANSIBLE_DEPRECATION_WARNINGS: "false" - - # Remove test system - User secrets to keep if necessary - - - name: Terraform_Destroy - if: always() && env.ENABLE_DEBUG == 'false' - env: - AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} - AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} - OSVAR: ${{ vars.OSVAR }} - TF_VAR_benchmark_type: ${{ vars.BENCHMARK_TYPE }} - run: terraform destroy -var-file "github_vars.tfvars" -var-file "${OSVAR}.tfvars" --auto-approve -input=false + repo-token: ${{ secrets.GITHUB_TOKEN }} + pr-message: |- + Congrats on opening your first pull request and thank you for taking the time to help improve Ansible-Lockdown! + Please join in the conversation happening on the [Discord Server](https://www.lockdownenterprise.com/discord) as well. + + # This workflow contains a single job that tests the playbook + playbook-test: + # The type of runner that the job will run on + runs-on: self-hosted + env: + ENABLE_DEBUG: ${{ vars.ENABLE_DEBUG }} + # Imported as a variable by terraform + TF_VAR_repository: ${{ github.event.repository.name }} + AWS_REGION: "us-east-1" + ANSIBLE_VERSION: ${{ vars.ANSIBLE_RUNNER_VERSION }} + defaults: + run: + shell: bash + working-directory: .github/workflows/github_linux_IaC + # working-directory: .github/workflows + + steps: + + - name: Git clone the lockdown repository to test + uses: actions/checkout@v4 + with: + ref: ${{ github.event.pull_request.head.sha }} + + - name: If a variable for IAC_BRANCH is set use that branch + working-directory: .github/workflows + run: | + if [ ${{ vars.IAC_BRANCH }} != '' ]; then + echo "IAC_BRANCH=${{ vars.IAC_BRANCH }}" >> $GITHUB_ENV + echo "Pipeline using the following IAC branch ${{ vars.IAC_BRANCH }}" + else + echo IAC_BRANCH=main >> $GITHUB_ENV + fi + + # Pull in terraform code for linux servers + - name: Clone GitHub IaC plan + uses: actions/checkout@v4 + with: + repository: ansible-lockdown/github_linux_IaC + path: .github/workflows/github_linux_IaC + ref: ${{ env.IAC_BRANCH }} + + # Uses dedicated restricted role and policy to enable this only for this task + # No credentials are part of github for AWS auth + - name: configure aws credentials + uses: aws-actions/configure-aws-credentials@main + with: + role-to-assume: ${{ secrets.AWS_ASSUME_ROLE }} + role-session-name: ${{ secrets.AWS_ROLE_SESSION }} + aws-region: ${{ env.AWS_REGION }} + + - name: DEBUG - Show IaC files + if: env.ENABLE_DEBUG == 'true' + run: | + echo "OSVAR = $OSVAR" + echo "benchmark_type = $benchmark_type" + echo "PRIVSUBNET_ID = $AWS_PRIVSUBNET_ID" + echo "VPC_ID" = $AWS_VPC_SECGRP_ID" + pwd + ls + env: + # Imported from GitHub variables this is used to load the relevant OS.tfvars file + OSVAR: ${{ vars.OSVAR }} + benchmark_type: ${{ vars.BENCHMARK_TYPE }} + PRIVSUBNET_ID: ${{ secrets.AWS_PRIVSUBNET_ID }} + VPC_ID: ${{ secrets.AWS_VPC_SECGRP_ID }} + + - name: Tofu init + id: init + run: tofu init + env: + # Imported from GitHub variables this is used to load the relevant OS.tfvars file + OSVAR: ${{ vars.OSVAR }} + TF_VAR_benchmark_type: ${{ vars.BENCHMARK_TYPE }} + + - name: Tofu validate + id: validate + run: tofu validate + env: + # Imported from GitHub variables this is used to load the relevant OS.tfvars file + OSVAR: ${{ vars.OSVAR }} + TF_VAR_benchmark_type: ${{ vars.BENCHMARK_TYPE }} + + - name: Tofu apply + id: apply + env: + OSVAR: ${{ vars.OSVAR }} + TF_VAR_benchmark_type: ${{ vars.BENCHMARK_TYPE }} + TF_VAR_privsubnet_id: ${{ secrets.AWS_PRIVSUBNET_ID }} + TF_VAR_vpc_secgrp_id: ${{ secrets.AWS_VPC_SECGRP_ID }} + run: tofu apply -var-file "${OSVAR}.tfvars" --auto-approve -input=false + +## Debug Section + - name: DEBUG - Show Ansible hostfile + if: env.ENABLE_DEBUG == 'true' + run: cat hosts.yml + + # Aws deployments taking a while to come up insert sleep or playbook fails + + - name: Sleep to allow system to come up + run: sleep ${{ vars.BUILD_SLEEPTIME }} + + # Run the Ansible playbook + - name: Run_Ansible_Playbook + env: + ANSIBLE_HOST_KEY_CHECKING: "false" + ANSIBLE_DEPRECATION_WARNINGS: "false" + run: | + /opt/ansible_${{ env.ANSIBLE_VERSION }}_venv/bin/ansible-playbook -i hosts.yml --private-key ~/.ssh/le_runner ../../../site.yml + + # Remove test system - User secrets to keep if necessary + + - name: Tofu Destroy + if: always() && env.ENABLE_DEBUG == 'false' + env: + OSVAR: ${{ vars.OSVAR }} + TF_VAR_benchmark_type: ${{ vars.BENCHMARK_TYPE }} + TF_VAR_privsubnet_id: ${{ secrets.AWS_PRIVSUBNET_ID }} + TF_VAR_vpc_secgrp_id: ${{ secrets.AWS_VPC_SECGRP_ID }} + run: tofu destroy -var-file "${OSVAR}.tfvars" --auto-approve -input=false diff --git a/.github/workflows/main_pipeline_validation.yml b/.github/workflows/main_pipeline_validation.yml index 8ded7018..ab11c37b 100644 --- a/.github/workflows/main_pipeline_validation.yml +++ b/.github/workflows/main_pipeline_validation.yml @@ -1,127 +1,144 @@ --- - name: Main pipeline - - on: # yamllint disable-line rule:truthy - pull_request_target: - types: [opened, reopened, synchronize] - branches: - - main - paths: - - '**.yml' - - '**.sh' - - '**.j2' - - '**.ps1' - - '**.cfg' - - # A workflow run is made up of one or more jobs - # that can run sequentially or in parallel - jobs: - - # This workflow contains a single job that tests the playbook - playbook-test: - # The type of runner that the job will run on - runs-on: ubuntu-latest - env: - ENABLE_DEBUG: ${{ vars.ENABLE_DEBUG }} - # Imported as a variable by terraform - TF_VAR_repository: ${{ github.event.repository.name }} - defaults: - run: - shell: bash - working-directory: .github/workflows/github_linux_IaC - - steps: - - name: Clone ${{ github.event.repository.name }} - 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@v4 - with: - repository: ansible-lockdown/github_linux_IaC - path: .github/workflows/github_linux_IaC - - - name: Add_ssh_key - working-directory: .github/workflows - env: - SSH_AUTH_SOCK: /tmp/ssh_agent.sock - PRIVATE_KEY: "${{ secrets.SSH_PRV_KEY }}" - run: | - mkdir .ssh - chmod 700 .ssh - echo $PRIVATE_KEY > .ssh/github_actions.pem - chmod 600 .ssh/github_actions.pem - - - name: DEBUG - Show IaC files - if: env.ENABLE_DEBUG == 'true' - run: | - echo "OSVAR = $OSVAR" - echo "benchmark_type = $benchmark_type" - pwd - ls - env: - # Imported from GitHub variables this is used to load the relevant OS.tfvars file - OSVAR: ${{ vars.OSVAR }} - benchmark_type: ${{ vars.BENCHMARK_TYPE }} - - - name: Terraform_Init - id: init - run: terraform init - env: - # Imported from GitHub variables this is used to load the relevant OS.tfvars file - OSVAR: ${{ vars.OSVAR }} - TF_VAR_benchmark_type: ${{ vars.BENCHMARK_TYPE }} - - - name: Terraform_Validate - id: validate - run: terraform validate - env: - # Imported from GitHub variables this is used to load the relevant OS.tfvars file - OSVAR: ${{ vars.OSVAR }} - TF_VAR_benchmark_type: ${{ vars.BENCHMARK_TYPE }} - - - name: Terraform_Apply - id: apply - env: - AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} - AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} - OSVAR: ${{ vars.OSVAR }} - TF_VAR_benchmark_type: ${{ vars.BENCHMARK_TYPE }} - run: terraform apply -var-file "github_vars.tfvars" -var-file "${OSVAR}.tfvars" --auto-approve -input=false - - ## Debug Section - - name: DEBUG - Show Ansible hostfile - if: env.ENABLE_DEBUG == 'true' - run: cat hosts.yml - - # Aws deployments taking a while to come up insert sleep or playbook fails - - - name: Sleep for 60 seconds - run: sleep ${{ vars.BUILD_SLEEPTIME }} - - # Run the Ansible playbook - - name: Run_Ansible_Playbook - uses: arillso/action.playbook@master - with: - playbook: site.yml - inventory: .github/workflows/github_linux_IaC/hosts.yml - galaxy_file: collections/requirements.yml - private_key: ${{ secrets.SSH_PRV_KEY }} - # verbose: 3 - env: - ANSIBLE_HOST_KEY_CHECKING: "false" - ANSIBLE_DEPRECATION_WARNINGS: "false" - - # Remove test system - User secrets to keep if necessary - - - name: Terraform_Destroy - if: always() && env.ENABLE_DEBUG == 'false' - env: - AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} - AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} - OSVAR: ${{ vars.OSVAR }} - TF_VAR_benchmark_type: ${{ vars.BENCHMARK_TYPE }} - run: terraform destroy -var-file "github_vars.tfvars" -var-file "${OSVAR}.tfvars" --auto-approve -input=false + name: Main pipeline + + on: # yamllint disable-line rule:truthy + pull_request_target: + types: [opened, reopened, synchronize] + branches: + - main + paths: + - '**.yml' + - '**.sh' + - '**.j2' + - '**.ps1' + - '**.cfg' + + # Allow permissions for AWS auth + permissions: + id-token: write + contents: read + pull-requests: read + + # A workflow run is made up of one or more jobs + # that can run sequentially or in parallel + jobs: + # This workflow contains a single job that tests the playbook + playbook-test: + # The type of runner that the job will run on + runs-on: self-hosted + env: + ENABLE_DEBUG: ${{ vars.ENABLE_DEBUG }} + # Imported as a variable by terraform + TF_VAR_repository: ${{ github.event.repository.name }} + AWS_REGION : "us-east-1" + ANSIBLE_VERSION: ${{ vars.ANSIBLE_RUNNER_VERSION }} + defaults: + run: + shell: bash + working-directory: .github/workflows/github_linux_IaC + # working-directory: .github/workflows + + steps: + + - name: Git clone the lockdown repository to test + uses: actions/checkout@v4 + with: + ref: ${{ github.event.pull_request.head.sha }} + + - name: If a variable for IAC_BRANCH is set use that branch + working-directory: .github/workflows + run: | + if [ ${{ vars.IAC_BRANCH }} != '' ]; then + echo "IAC_BRANCH=${{ vars.IAC_BRANCH }}" >> $GITHUB_ENV + echo "Pipeline using the following IAC branch ${{ vars.IAC_BRANCH }}" + else + echo IAC_BRANCH=main >> $GITHUB_ENV + fi + + # Pull in terraform code for linux servers + - name: Clone GitHub IaC plan + uses: actions/checkout@v4 + with: + repository: ansible-lockdown/github_linux_IaC + path: .github/workflows/github_linux_IaC + ref: ${{ env.IAC_BRANCH }} + + # Uses dedicated restricted role and policy to enable this only for this task + # No credentials are part of github for AWS auth + - name: configure aws credentials + uses: aws-actions/configure-aws-credentials@main + with: + role-to-assume: ${{ secrets.AWS_ASSUME_ROLE }} + role-session-name: ${{ secrets.AWS_ROLE_SESSION }} + aws-region: ${{ env.AWS_REGION }} + + - name: DEBUG - Show IaC files + if: env.ENABLE_DEBUG == 'true' + run: | + echo "OSVAR = $OSVAR" + echo "benchmark_type = $benchmark_type" + echo "PRIVSUBNET_ID = $AWS_PRIVSUBNET_ID" + echo "VPC_ID" = $AWS_VPC_SECGRP_ID" + pwd + ls + env: + # Imported from GitHub variables this is used to load the relevant OS.tfvars file + OSVAR: ${{ vars.OSVAR }} + benchmark_type: ${{ vars.BENCHMARK_TYPE }} + PRIVSUBNET_ID: ${{ secrets.AWS_PRIVSUBNET_ID }} + VPC_ID: ${{ secrets.AWS_VPC_SECGRP_ID }} + + - name: Tofu init + id: init + run: tofu init + env: + # Imported from GitHub variables this is used to load the relevant OS.tfvars file + OSVAR: ${{ vars.OSVAR }} + TF_VAR_benchmark_type: ${{ vars.BENCHMARK_TYPE }} + + - name: Tofu validate + id: validate + run: tofu validate + env: + # Imported from GitHub variables this is used to load the relevant OS.tfvars file + OSVAR: ${{ vars.OSVAR }} + TF_VAR_benchmark_type: ${{ vars.BENCHMARK_TYPE }} + + - name: Tofu apply + id: apply + env: + OSVAR: ${{ vars.OSVAR }} + TF_VAR_benchmark_type: ${{ vars.BENCHMARK_TYPE }} + TF_VAR_privsubnet_id: ${{ secrets.AWS_PRIVSUBNET_ID }} + TF_VAR_vpc_secgrp_id: ${{ secrets.AWS_VPC_SECGRP_ID }} + run: tofu apply -var-file "${OSVAR}.tfvars" --auto-approve -input=false + +## Debug Section + - name: DEBUG - Show Ansible hostfile + if: env.ENABLE_DEBUG == 'true' + run: cat hosts.yml + + # Aws deployments taking a while to come up insert sleep or playbook fails + + - name: Sleep to allow system to come up + run: sleep ${{ vars.BUILD_SLEEPTIME }} + + # Run the Ansible playbook + - name: Run_Ansible_Playbook + env: + ANSIBLE_HOST_KEY_CHECKING: "false" + ANSIBLE_DEPRECATION_WARNINGS: "false" + run: | + /opt/ansible_${{ env.ANSIBLE_VERSION }}_venv/bin/ansible-playbook -i hosts.yml --private-key ~/.ssh/le_runner ../../../site.yml + + # Remove test system - User secrets to keep if necessary + + - name: Tofu Destroy + if: always() && env.ENABLE_DEBUG == 'false' + env: + OSVAR: ${{ vars.OSVAR }} + TF_VAR_benchmark_type: ${{ vars.BENCHMARK_TYPE }} + TF_VAR_privsubnet_id: ${{ secrets.AWS_PRIVSUBNET_ID }} + TF_VAR_vpc_secgrp_id: ${{ secrets.AWS_VPC_SECGRP_ID }} + run: tofu destroy -var-file "${OSVAR}.tfvars" --auto-approve -input=false diff --git a/.github/workflows/update_galaxy.yml b/.github/workflows/update_galaxy.yml index f9352800..b6ee6a1f 100644 --- a/.github/workflows/update_galaxy.yml +++ b/.github/workflows/update_galaxy.yml @@ -1,19 +1,19 @@ --- -name: update galaxy + name: update galaxy -on: - push: - branches: - - main -jobs: - update_role: - runs-on: ubuntu-latest - steps: - - name: Checkout repo - uses: actions/checkout@v4 + on: + push: + branches: + - main + jobs: + update_role: + runs-on: ubuntu-latest + steps: + - name: Checkout repo + uses: actions/checkout@v4 - - name: Action Ansible Galaxy Release ${{ github.ref_name }} - uses: ansible-actions/ansible-galaxy-action@main - with: - galaxy_api_key: ${{ secrets.GALAXY_API_KEY }} + - name: Action Ansible Galaxy Release ${{ github.ref_name }} + uses: ansible-actions/ansible-galaxy-action@main + with: + galaxy_api_key: ${{ secrets.GALAXY_API_KEY }} diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 82858b54..a679c82a 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.5.0 + rev: v5.0.0 hooks: # Safety - id: detect-aws-credentials @@ -30,19 +30,19 @@ repos: # Scan for passwords - repo: https://github.com/Yelp/detect-secrets - rev: v1.4.0 + rev: v1.5.0 hooks: - id: detect-secrets args: [ '--baseline', '.config/.secrets.baseline' ] - repo: https://github.com/gitleaks/gitleaks - rev: v8.18.2 + rev: v8.21.2 hooks: - id: gitleaks args: ['--baseline-path', '.config/.gitleaks-report.json'] - repo: https://github.com/ansible-community/ansible-lint - rev: v24.2.0 + rev: v24.9.2 hooks: - id: ansible-lint name: Ansible-lint diff --git a/ChangeLog.md b/ChangeLog.md index 608849fd..86a695a3 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -1,5 +1,29 @@ # Changelog +## 3.2 STIG v3R14 24th Jan 2024 + +- Audit updated + - moved audit into prelim + - updates to audit logic for copy and archive options + +- RHEL-07-020019 - title and ruleid update +- RHEL-07-020022 - ruleid update +- RHEL-07-020210 - ruleid update +- RHEL-07-020220 - ruleid update +- RHEL-07-020100 - ruleid update and bin/false +- RHEL-07-020101 - ruleid update and bin/false +- RHEL-07-040180 - ruleid update and bin/false +- RHEL-07-040190 - ruleid update and bin/false + +## 3.1 STIG V3R13 25th Oct 2023 + +- RHEL_07_010310 - ruleid updated and INACTIVE var created +- RHEL_07_020020 - ruleid +- RHEL_07_020021 - ruleid +- RHEL_07_020023 - ruleid +- RHEL_07_020230 - ruleid +- RHEL_07_021700 - ruleid + ## 3.0 Stig V3R12 26th July 2023 - RHEL-07-010199 - pamd password and system auth rewrite and ruleid updated diff --git a/README.md b/README.md index f8a2adec..61645cec 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ ## Configure a RHEL7 based system to be complaint with Disa STIG -This role is based on RHEL 7 DISA STIG: [ Version 3, Rel 11 released on July 23, 2023 ](https://dl.dod.cyber.mil/wp-content/uploads/stigs/zip/U_RHEL_7_V3R12_STIG.zip). +This role is based on RHEL 7 DISA STIG: [ Version 3, Rel 14 released on January 24, 2024 ](https://dl.dod.cyber.mil/wp-content/uploads/stigs/zip/U_RHEL_7_V3R14_STIG.zip). --- @@ -47,7 +47,7 @@ Configure a RHEL 7 system to be DISA STIG compliant. Non-disruptive CAT I, CAT II, and CAT III findings will be corrected by default. Disruptive finding remediation can be enabled by setting `rhel7stig_disruption_high` to `true`. -# Caution(s) +## Caution(s) This role **will make changes to the system** which may have unintended consequences. This is not an auditing tool but rather a remediation tool to be used after an audit has been conducted. @@ -222,5 +222,8 @@ pre-commit run This repo originated from work done by [Sam Doran](https://github.com/samdoran/ansible-role-stig) Massive thanks to the fantastic community and all its members. + + This includes a huge thanks and credit to the original authors and maintainers. -Josh Springer, Daniel Shepherd, Bas Meijeri, James Cassell, Mike Renfro, DFed, George Nalen, Mark Bolwell + +- Josh Springer, Daniel Shepherd, Bas Meijeri, James Cassell, Mike Renfro, DFed, George Nalen, Mark Bolwell diff --git a/defaults/main.yml b/defaults/main.yml index 89b65ab1..7850f265 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -13,31 +13,67 @@ python2_bin: /bin/python2.7 # audit variable found at the base benchmark: RHEL7-STIG ## metadata for Audit benchmark -benchmark_version: 'v3r12' +benchmark_version: 'v3r14' # Whether to skip the reboot rhel7stig_skip_reboot: true -### Audit Binary is required on the remote host +# With CentOS being EoL many mirrors no longer exist and fail for updates +# setting to true will replace the default /etc/yum.repos.d/CentOS-Base.repo +# It will add the new vaulted location where it is possible to get updates and package +rhel7stig_add_updated_repo: false + +########################################### +### Goss is required on the remote host ### +### vars/auditd.yml for other settings ### + +# Allow audit to setup the requirements including installing git (if option chosen and downloading and adding goss binary to system) setup_audit: false + +# enable audits to run - this runs the audit and get the latest content +run_audit: false +# 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 + +## Only run Audit do not remediate +audit_only: false +### As part of audit_only ### +# This will enable files to be copied back to control node in audit_only mode +fetch_audit_files: false +# Path to copy the files to will create dir structure in audit_only mode +audit_capture_files_dir: /some/location to copy to on control node +############################# + # How to retrieve audit binary # 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 get_audit_binary_method: download +## if get_audit_binary_method - 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 +audit_bin_copy_location: /some/accessible/path + # how to get audit files onto host options -# options are git/copy/get_url other e.g. if you wish to run from already downloaded conf +# options are git/copy/archive/get_url other e.g. if you wish to run from already downloaded conf audit_content: git -# enable audits to run - this runs the audit and get the latest content -run_audit: false +# If using either archive, copy, get_url: +## Note will work with .tar files - zip will require extra configuration +### If using get_url this is expecting github url in tar.gz format e.g. +### https://github.com/ansible-lockdown/UBUNTU22-CIS-Audit/archive/refs/heads/benchmark-v1.0.0.tar.gz +audit_conf_source: "some path or url to copy from" -# 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 -audit_cmd_timeout: 60000 +# Destination for the audit content to be placed on managed node +# note may not need full path e.g. /opt with the directory being the {{ benchmark }}-Audit directory +audit_conf_dest: "/opt" + +# Where the audit logs are stored +audit_log_dir: '/opt' + +### Goss Settings ## +####### END ######## -### End Audit enablements #### #### Detailed settings found at the end of this document #### # We've defined complexity-high to mean that we cannot automatically remediate @@ -336,8 +372,8 @@ rhel_07_040000: true rhel_07_040530: true rhel_07_040600: true -# Whether or not to run tasks related to auditing/patching the desktop environment -rhel7stig_gui: false +# Whether or not to run tasks related to auditing/patching the desktop environment - is discovered if using gnome +rhel7stig_gui: "{{ prelim_gnome_present.stat.exists | default(false) }}" # Whether to configure dconf rules unconditionally (ignoring presence of dconf # or rhel7stig_gui) @@ -348,6 +384,9 @@ rhel7stig_smartcard: false # Configure your smartcard driver rhel7stig_smartcarddriver: cackey +# RHEL_07_010310 +# Must be 35 or less but not 0 or -1 +rhel_07_010310_inactive: 35 # RHEL_07_020020 # Set "selinux_change_users" false to disable this control's actions and just report results. # You will need to adjust the paths for installed HIPS/HBSS for this control. @@ -650,10 +689,6 @@ update_audit_template: false # RHEL-07-030300 uncomment and set the value to a remote IP address that can receive audit logs # rhel7stig_audisp_remote_server: 10.10.10.10 -# RHEL-07-030330: set this to 25% of the free space in /var/log/audit (measured in megabytes) -rhel7stig_auditd_space_left: "{{ ( ansible_mounts | json_query(rhel7stig_audit_disk_size_query) | int / 4 / 1024 / 1024 ) | int + 1 }}" -rhel7stig_audit_disk_size_query: "[?mount=='{{ rhel7stig_audit_part }}'].size_total | [0]" - # RHEL-07-030350 rhel7stig_audit_daemon: auditd rhel7stig_auditd_mail_acct: root @@ -707,12 +742,6 @@ rhel7stig_efi_boot_path: '/boot/efi/EFI/' rhel7stig_passwd_label: "{{ (this_item | default(item)).id }}: {{ (this_item | default(item)).dir }}" -rhel7stig_local_mounts: "{{ ansible_mounts | to_json | from_json | json_query(rhel7stig_local_mounts_query) }}" -rhel7stig_local_mounts_query: "[?starts_with(device, '/dev/')].mount" - -rhel7stig_nfs_mounts: "{{ ansible_mounts | to_json | from_json | json_query(rhel7stig_nfs_mounts_query) }}" -rhel7stig_nfs_mounts_query: "[?starts_with(fstype, 'nfs')].mount" - # DNS Servers to configure, you need two to conform to STIG standards rhel_07_040600_dns_servers: - 9.9.9.9 @@ -734,56 +763,3 @@ rhel7stig_world_write_files_owner_root: false # The value given to Defaults timestamp timeout= in the sudo file. # Value must be greater than 0 to conform to STIG standards rhel7stig_sudo_timestamp_timeout: 1 - -#### Audit Configuration Settings #### -# Set correct env for the run_audit.sh script from https://github.com/ansible-lockdown/{{ benchmark }}-Audit.git" -audit_run_script_environment: - AUDIT_BIN: "{{ audit_bin }}" - AUDIT_FILE: 'goss.yml' - AUDIT_CONTENT_LOCATION: "{{ audit_out_dir }}" - -### Audit binary settings ### -audit_bin_version: - release: v0.3.21 - checksum: 'sha256:9a9200779603acf0353d2c0e85ae46e083596c10838eaf4ee050c924678e4fe3' -audit_bin_path: /usr/local/bin/ -audit_bin: "{{ audit_bin_path }}goss" -audit_format: json - -# 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-amd64" - -## if get_audit_binary_method - 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 -audit_bin_copy_location: /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 }}_rh7" - -# 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' -# 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_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 -audit_control_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/handlers/main.yml b/handlers/main.yml index 88fb8027..0180d931 100644 --- a/handlers/main.yml +++ b/handlers/main.yml @@ -37,7 +37,7 @@ src: "{{ rhel7stig_bootloader_path }}/{{ item }}" dest: "{{ rhel7stig_not_boot_path }}/{{ item }}" remote_src: true - mode: 0600 + mode: '0600' with_items: - grub.cfg - user.cfg diff --git a/site.yml b/site.yml index 830c253d..171abc53 100644 --- a/site.yml +++ b/site.yml @@ -1,10 +1,6 @@ --- -- hosts: all # noqa: name[play] +- name: Ansible Lockdown Remediation Role + hosts: all become: true - vars: - is_container: false - roles: - - role: "{{ playbook_dir }}" - rhel7stig_system_is_container: "{{ is_container | default(false) }}" - rhel7stig_skip_for_travis: false + - role: "{{ playbook_dir }}" diff --git a/tasks/LE_audit_setup.yml b/tasks/LE_audit_setup.yml index fd75cea5..b08985e2 100644 --- a/tasks/LE_audit_setup.yml +++ b/tasks/LE_audit_setup.yml @@ -1,22 +1,32 @@ --- -- name: Download audit binary +- name: Pre Audit Setup | Set audit package name + block: + - name: Pre Audit Setup | Set audit package name | 64bit + when: ansible_facts.machine == "x86_64" + ansible.builtin.set_fact: + audit_pkg_arch_name: AMD64 + + - name: Pre Audit Setup | Set audit package name | ARM64 + when: ansible_facts.machine == "arm64" + ansible.builtin.set_fact: + audit_pkg_arch_name: ARM64 + +- name: Pre Audit Setup | Download audit binary + when: get_audit_binary_method == 'download' ansible.builtin.get_url: - url: "{{ audit_bin_url }}" + url: "{{ audit_bin_url }}{{ audit_pkg_arch_name }}" dest: "{{ audit_bin }}" owner: root group: root - checksum: "{{ audit_bin_version.checksum }}" - mode: 0555 - when: - - get_audit_binary_method == 'download' + checksum: "{{ audit_bin_version[audit_pkg_arch_name + '_checksum'] }}" + mode: '0555' -- name: copy audit binary +- name: Pre Audit Setup | Copy audit binary + when: get_audit_binary_method == 'copy' ansible.builtin.copy: src: "{{ audit_bin_copy_location }}" dest: "{{ audit_bin }}" - mode: 0555 + mode: '0555' owner: root group: root - when: - - get_audit_binary_method == 'copy' diff --git a/tasks/audit_only.yml b/tasks/audit_only.yml new file mode 100644 index 00000000..66b036d3 --- /dev/null +++ b/tasks/audit_only.yml @@ -0,0 +1,30 @@ +--- + +- name: Audit_Only | Create local Directories for hosts + when: fetch_audit_files + delegate_to: localhost + become: false + ansible.builtin.file: + mode: '0755' + path: "{{ audit_capture_files_dir }}/{{ inventory_hostname }}" + recurse: true + state: directory + +- name: Audit_only | Get audits from systems and put in group dir + when: fetch_audit_files + ansible.builtin.fetch: + dest: "{{ audit_capture_files_dir }}/{{ inventory_hostname }}/" + flat: true + mode: '0644' + src: "{{ pre_audit_outfile }}" + +- name: Audit_only | Show Audit Summary + when: + - audit_only + ansible.builtin.debug: + msg: "{{ audit_results.split('\n') }}" + +- name: Audit_only | Stop Playbook Audit Only selected + when: + - audit_only + ansible.builtin.meta: end_play diff --git a/tasks/fix-cat1.yml b/tasks/fix-cat1.yml index a8dab97d..99a580c6 100644 --- a/tasks/fix-cat1.yml +++ b/tasks/fix-cat1.yml @@ -1,4 +1,5 @@ --- + - name: "HIGH | RHEL-07-010010 | The Red Hat Enterprise Linux operating system must be configured so that the file permissions, ownership, and group membership of system files and commands match the vendor values." block: - name: "HIGH | RHEL-07-010010 | AUDIT | The Red Hat Enterprise Linux operating system must be configured so that the file permissions, ownership, and group membership of system files and commands match the vendor values." @@ -306,7 +307,7 @@ - CAT1 - CCI-000366 - SRG-OS-000480-GPOS-00227 - - SV-204455r833106_rule + - SV-204455r928574_rule - V-204455 - systemctl @@ -377,52 +378,58 @@ - V-204462 - accounts -- name: "HIGH | RHEL-07-021350 | The Red Hat Enterprise Linux operating system must implement NIST FIPS-validated cryptography for the following: to provision digital signatures, to generate cryptographic hashes, and to protect data requiring data-at-rest protections in accordance with applicable federal laws, Executive Orders, directives, policies, regulations, and standards." +- name: "HIGH | RHEL-07-021350 | PATCH | The Red Hat Enterprise Linux operating system must implement NIST FIPS-validated cryptography for the following: to provision digital signatures, to generate cryptographic hashes, and to protect data requiring data-at-rest protections in accordance with applicable federal laws, Executive Orders, directives, policies, regulations, and standards." block: - - name: "HIGH | RHEL-07-021350 | PATCH | The Red Hat Enterprise Linux operating system must implement NIST FIPS-validated cryptography for the following: to provision digital signatures, to generate cryptographic hashes, and to protect data requiring data-at-rest protections in accordance with applicable federal laws, Executive Orders, directives, policies, regulations, and standards." + - name: "HIGH | RHEL-07-021350 | PATCH | The Red Hat Enterprise Linux operating system must implement NIST FIPS-validated cryptography for the following: to provision digital signatures, to generate cryptographic hashes, and to protect data requiring data-at-rest protections in accordance with applicable federal laws, Executive Orders, directives, policies, regulations, and standards. | install FIPS" ansible.builtin.package: name: dracut-fips state: present vars: ansible_python_interpreter: "{{ python2_bin }}" - notify: rebuild initramfs - when: - - "'dracut-fips' not in ansible_facts.packages" + notify: + - rebuild initramfs + when: "'dracut-fips' not in ansible_facts.packages" - name: "HIGH | RHEL-07-021350 | PATCH | Disable prelinking." ansible.builtin.lineinfile: path: /etc/sysconfig/prelink regexp: ^#?PRELINKING line: PRELINKING=no + when: "'prelink' in ansible_facts.packages" notify: undo existing prelinking - when: - - "'prelink' in ansible_facts.packages" - - name: "HIGH | RHEL-07-021350 | AUDIT | Check /etc/default/grub exists" - ansible.builtin.stat: - path: /etc/default/grub - register: rhel7_stig_default_grub - - - name: "HIGH | RHEL-07-021350 | AUDIT | Capture GRUB_CMDLINE_LINUX from /proc/cmdline" - block: - - name: "HIGH | RHEL-07-021350 | AUDIT | Capture GRUB_CMDLINE_LINUX from /proc/cmdline" - ansible.builtin.shell: grep -oP ' ro \K.*?(?= ?LANG=)' /proc/cmdline - check_mode: false - changed_when: false - failed_when: rhel_07_021350_grub_cmdline_linux_audit.rc > 1 - register: rhel_07_021350_grub_cmdline_linux_audit - - - name: "HIGH | RHEL-07-021350 | PATCH | Copy over a sane /etc/default/grub" - ansible.builtin.template: - src: etc_default_grub.j2 - dest: /etc/default/grub - owner: root - group: root - mode: 0644 - register: rhel7_stig_grub_template - vars: - grub_cmdline_linux: "{{ rhel_07_021350_grub_cmdline_linux_audit.stdout }}" - when: not rhel7_stig_default_grub.stat.exists + - name: "HIGH | RHEL-07-021350 | AUDIT | Check for GRUB_CMDLINE_LINUX in /etc/default/grub" + ansible.builtin.shell: grep -P '^\s*GRUB_CMDLINE_LINUX=".*"$' /etc/default/grub + failed_when: false + changed_when: rhel_07_021350_default_grub_missing_audit.rc > 0 + check_mode: false + register: rhel_07_021350_default_grub_missing_audit + + - name: "HIGH | RHEL-07-021350 | AUDIT | Parse sane GRUB_CMDLINE_LINUX from /proc/cmdline" + ansible.builtin.shell: grep -oP ' ro \K.*?(?= ?LANG=)' /proc/cmdline + changed_when: false + failed_when: rhel_07_021350_grub_cmdline_linux_audit.rc > 1 + check_mode: false + when: rhel_07_021350_default_grub_missing_audit is changed # noqa no-handler + register: rhel_07_021350_grub_cmdline_linux_audit + + - name: "HIGH | RHEL-07-021350 | PATCH | Copy over a sane /etc/default/grub" + ansible.builtin.template: + src: etc_default_grub.j2 + dest: /etc/default/grub + owner: root + group: root + mode: '0644' + vars: + grub_cmdline_linux: "{{ rhel_07_021350_grub_cmdline_linux_audit.stdout }}" + when: rhel_07_021350_default_grub_missing_audit is changed # noqa no-handler + + - name: "HIGH | RHEL-07-021350 | AUDIT | Verify fips kernel parameters in /etc/default/grub" + ansible.builtin.shell: grep -P '^\s*GRUB_CMDLINE_LINUX=".*(?<=[" ])fips=1(?=[" ]).*"$' /etc/default/grub + changed_when: false + failed_when: rhel_07_021350_fips_kernel_set.rc not in [ 0, 1 ] + check_mode: false + register: rhel_07_021350_fips_kernel_set - name: "HIGH | RHEL-07-021350 | PATCH | fips=1 must be in /etc/default/grub" ansible.builtin.replace: @@ -432,71 +439,69 @@ vars: key: GRUB_CMDLINE_LINUX param: fips - value: "{{ fips_value }}" + value: 1 append: true # this is the default - notify: confirm grub2 user cfg when: - not ansible_check_mode or - rhel7_stig_grub_template is not changed + rhel_07_021350_default_grub_missing_audit is not changed + - rhel_07_021350_fips_kernel_set.stdout | length == 0 + notify: + - confirm grub2 user cfg + + - name: "HIGH | RHEL-07-021350 | AUDIT | Verify boot kernel parameters in /etc/default/grub" + ansible.builtin.shell: grep -P '^\s*GRUB_CMDLINE_LINUX=".*(?<=[" ])boot=UUID={{ rhel7stig_boot_uuid.stdout }}(?=[" ]).*"$' /etc/default/grub + changed_when: false + failed_when: rhel_07_021350_boot_kernel_set.rc not in [ 0, 1 ] + check_mode: false + register: rhel_07_021350_boot_kernel_set - name: "HIGH | RHEL-07-021350 | PATCH | If /boot or /boot/efi reside on separate partitions, the kernel parameter boot= must be added to the kernel command line." - block: - - name: "HIGH | RHEL-07-021350 | PATCH | If /boot or /boot/efi reside on separate partitions, the kernel parameter boot= must be added to the kernel command line." - ansible.builtin.replace: - path: /etc/default/grub - regexp: "{{ rhel7stig_regexp_quoted_params }}" - replace: "{{ rhel7stig_replace_quoted_params }}" - with_items: - - "{{ ansible_mounts | json_query(query) }}" - vars: - query: "[?mount=='{{ rhel7stig_boot_part }}'] | [0]" # noqa: jinja[invalid] - key: GRUB_CMDLINE_LINUX - param: boot - value: UUID={{ item.uuid }} - insert: true - when: - - rhel7stig_boot_part not in ['/', ''] - - item.uuid is defined - - not ansible_check_mode or - rhel7_stig_grub_template is not changed - notify: confirm grub2 user cfg - register: result - - - name: "HIGH | RHEL-07-021350 | AUDIT | Verify kernel parameters in /etc/default/grub" - ansible.builtin.shell: grep -P '^\s*GRUB_CMDLINE_LINUX=".*(?<=[" ]){{ item | regex_escape }}(?=[" ]).*"$' /etc/default/grub - check_mode: false - with_items: - - "fips={{ fips_value }}" - - boot=UUID={{ ansible_mounts | json_query(query) }} - vars: - query: "[?mount=='{{ rhel7stig_boot_part }}'].uuid | [0]" # noqa: jinja[invalid] - register: rhel_07_021350_audit - changed_when: - - ansible_check_mode - - rhel_07_021350_audit is failed - failed_when: - - rhel_07_021350_audit.rc not in [ 0, 1 ] - - not ansible_check_mode - - when: - - not ansible_check_mode or - rhel7_stig_grub_template is not changed - - rhel7stig_boot_part not in ['/', ''] or - 'boot=' not in item + ansible.builtin.replace: + path: /etc/default/grub + regexp: "{{ rhel7stig_regexp_quoted_params }}" + replace: "{{ rhel7stig_replace_quoted_params }}" + vars: + query: "{{ rhel7stig_boot_part.stdout }}" + key: GRUB_CMDLINE_LINUX + param: boot + value: UUID={{ rhel7stig_boot_uuid.stdout }} + insert: true + when: + - rhel7stig_boot_part.stdout not in ['/', ''] + - rhel_07_021350_boot_kernel_set.stdout | length == 0 + - not ansible_check_mode or + rhel_07_021350_default_grub_missing_audit is not changed + notify: confirm grub2 user cfg + + - name: "HIGH | RHEL-07-021350 | AUDIT | Verify kernel parameters in /etc/default/grub" + ansible.builtin.shell: grep -P '^\s*GRUB_CMDLINE_LINUX=".*(?<=[" ]){{ item | regex_escape }}(?=[" ]).*"$' /etc/default/grub + changed_when: + - ansible_check_mode + - rhel_07_021350_audit is failed + failed_when: + - rhel_07_021350_audit is failed + - not ansible_check_mode or + rhel_07_021350_audit.rc > 1 + check_mode: false + register: rhel_07_021350_audit + with_items: + - fips=1 + - boot=UUID={{ rhel7stig_boot_uuid.stdout }} + when: + - not ansible_check_mode or + rhel_07_021350_default_grub_missing_audit is not changed + - "rhel7stig_boot_part.stdout not in ['/', ''] or + 'boot=' not in item" when: - rhel_07_021350 - rhel7stig_use_fips tags: - RHEL-07-021350 - CAT1 - - CCI-001199 - CCI-000068 - - CCI-002450 - - CCI-002476 - SRG-OS-000033-GPOS-00014 - - SV-204497r603261_rule - - V-204497 - - fips + - SV-230223r928585_rule + - V-230223 - name: "HIGH | RHEL-07-021710 | PATCH | The Red Hat Enterprise Linux operating system must not have the telnet-server package installed." ansible.builtin.package: @@ -567,9 +572,9 @@ - name: "HIGH | RHEL-07-040540 | The Red Hat Enterprise Linux operating system must not contain .shosts files." block: - name: "HIGH | RHEL-07-040540 | AUDIT | The Red Hat Enterprise Linux operating system must not contain .shosts files." - ansible.builtin.shell: find {{ rhel7stig_local_mounts | join(' ') }} -xdev -name '.shosts' - check_mode: false + ansible.builtin.shell: find / -xdev -not -fstype nfs -name '.shosts' changed_when: false + check_mode: false register: rhel_07_040540_audit - name: "HIGH | RHEL-07-040540 | PATCH | The Red Hat Enterprise Linux operating system must not contain .shosts files." @@ -592,9 +597,9 @@ - name: "HIGH | RHEL-07-040550 | The Red Hat Enterprise Linux operating system must not contain shosts.equiv files." block: - name: "HIGH | RHEL-07-040550 | AUDIT | The Red Hat Enterprise Linux operating system must not contain shosts.equiv files." - ansible.builtin.shell: find {{ rhel7stig_local_mounts | join(' ') }} -xdev -name 'shosts.equiv' - check_mode: false + ansible.builtin.shell: find / -xdev -not -fstype nfs -name 'shosts.equiv' changed_when: false + check_mode: false register: rhel_07_040550_audit - name: "HIGH | RHEL-07-040550 | PATCH | The Red Hat Enterprise Linux operating system must not contain shosts.equiv files." @@ -662,9 +667,9 @@ block: - name: "HIGH | RHEL-07-040800 | AUDIT | SNMP community strings on the Red Hat Enterprise Linux operating system must be changed from the default." ansible.builtin.shell: grep {{ item }} /etc/snmp/snmpd.conf - check_mode: false failed_when: false changed_when: false + check_mode: false register: rhel_07_040800_audit with_items: - public diff --git a/tasks/fix-cat2.yml b/tasks/fix-cat2.yml index 1ea2f6de..0744996b 100644 --- a/tasks/fix-cat2.yml +++ b/tasks/fix-cat2.yml @@ -67,7 +67,7 @@ dest: "{{ item }}" owner: root group: root - mode: 0644 + mode: '0644' with_items: - /etc/issue - /etc/issue.net @@ -338,7 +338,7 @@ dest: /etc/pam.d/system-auth regexp: '^#?password\s+(required|requisite) pam_pwquality.so retry' line: password requisite pam_pwquality.so retry=3 - mode: 0644 + mode: '0644' when: - rhel_07_010119 tags: @@ -356,7 +356,7 @@ dest: /etc/security/pwquality.conf regexp: '^#?\s*ucredit' line: "ucredit = {{ rhel7stig_password_complexity.ucredit | default('-1') }}" - mode: 0644 + mode: '0644' when: - rhel_07_010120 tags: @@ -374,7 +374,7 @@ dest: /etc/security/pwquality.conf regexp: '^#?\s*lcredit' line: "lcredit = {{ rhel7stig_password_complexity.lcredit | default('-1') }}" - mode: 0644 + mode: '0644' when: - rhel_07_010130 tags: @@ -392,7 +392,7 @@ dest: /etc/security/pwquality.conf regexp: '^#?\s*dcredit' line: "dcredit = {{ rhel7stig_password_complexity.dcredit | default('-1') }}" - mode: 0644 + mode: '0644' when: - rhel_07_010140 tags: @@ -409,7 +409,7 @@ dest: /etc/security/pwquality.conf regexp: '^#?\s*ocredit' line: "ocredit = {{ rhel7stig_password_complexity.ocredit | default('-1') }}" - mode: 0644 + mode: '0644' when: - rhel_07_010150 tags: @@ -427,7 +427,7 @@ dest: /etc/security/pwquality.conf regexp: '^#?\s*difok' line: "difok = {{ rhel7stig_password_complexity.difok | default('8') }}" - mode: 0644 + mode: '0644' when: - rhel_07_010160 tags: @@ -445,7 +445,7 @@ dest: /etc/security/pwquality.conf regexp: '^#?\s*minclass' line: "minclass = {{ rhel7stig_password_complexity.minclass | default('4') }}" - mode: 0644 + mode: '0644' when: - rhel_07_010170 tags: @@ -463,7 +463,7 @@ dest: /etc/security/pwquality.conf regexp: '^#?\s*maxrepeat' line: "maxrepeat = {{ rhel7stig_password_complexity.maxrepeat | default('3') }}" - mode: 0644 + mode: '0644' when: - rhel_07_010180 tags: @@ -481,7 +481,7 @@ dest: /etc/security/pwquality.conf regexp: '^#?\s*maxclassrepeat' line: "maxclassrepeat = {{ rhel7stig_password_complexity.maxclassrepeat | default('4') }}" - mode: 0644 + mode: '0644' when: - rhel_07_010190 tags: @@ -501,7 +501,7 @@ dest: "/{{ item }}" owner: root group: root - mode: 0644 + mode: '0644' loop: - etc/pam.d/password-auth-local - etc/pam.d/system-auth-local @@ -594,7 +594,7 @@ dest: /etc/login.defs regexp: ^#?PASS_MIN_DAYS line: "PASS_MIN_DAYS {{ rhel7stig_login_defaults.pass_min_days | default('1') }}" - mode: 0644 + mode: '0644' when: - rhel_07_010230 tags: @@ -610,14 +610,14 @@ block: - name: "MEDIUM | RHEL-07-010240 | AUDIT | Passwords must be restricted to a 24 hours/1 day minimum lifetime." ansible.builtin.shell: "awk -F: '$1 !~ /^root$/ && $2 !~ /^[!*]/ && $4 < 1 {print $1}' /etc/shadow" - check_mode: false changed_when: false + check_mode: false register: rhel_07_010240_audit - name: "MEDIUM | RHEL-07-010240 | PATCH | Passwords must be restricted to a 24 hours/1 day minimum lifetime." ansible.builtin.shell: chage -m 1 {{ item }} - check_mode: false changed_when: true + check_mode: false with_items: - "{{ rhel_07_010240_audit.stdout_lines }}" when: @@ -637,7 +637,7 @@ dest: /etc/login.defs regexp: ^#?PASS_MAX_DAYS line: "PASS_MAX_DAYS {{ rhel7stig_login_defaults.pass_max_days | default('60') }}" - mode: 0644 + mode: '0644' when: - rhel_07_010250 tags: @@ -653,8 +653,8 @@ block: - name: "MEDIUM | RHEL-07-010260 | AUDIT | The Red Hat Enterprise Linux operating system must be configured so that existing passwords are restricted to a 60-day maximum lifetime." ansible.builtin.shell: "awk -F: '$1 !~ /^root$/ && $2 !~ /^[!*]/ && $5 > 60 {print $1}' /etc/shadow" - check_mode: false changed_when: false + check_mode: false register: rhel_07_010260_audit - name: "MEDIUM | RHEL-07-010260 | PATCH | Reset password timeout to prevent locking out user." @@ -740,7 +740,7 @@ dest: /etc/security/pwquality.conf regexp: '^#?\s*minlen' line: "minlen = {{ rhel7stig_password_complexity.minlen | default('15') }}" - mode: 0644 + mode: '0644' when: - rhel_07_010280 tags: @@ -756,7 +756,7 @@ ansible.builtin.lineinfile: path: /etc/default/useradd regexp: ^#?INACTIVE - line: INACTIVE=35 + line: "INACTIVE={{ rhel_07_010310_inactive }}" when: - rhel_07_010310 tags: @@ -1051,6 +1051,7 @@ path: /etc/grub.d/01_users regexp: "{{ item.regexp }}" line: "{{ item.line }}" + create: true notify: - make grub2 config with_items: @@ -1136,7 +1137,7 @@ dest: /etc/pam_pkcs11/pkcs11_eventmgr.conf regexp: '^#?/usr/X11R6/bin/xscreensaver-command -lock' line: "/usr/X11R6/bin/xscreensaver-command -lock" - mode: 0644 + mode: '0644' # This remediates the pam_pkcs11.conf file to enforce the cackey usage for smartcard authentication ### NOTE: If you have custom rules for /etc/pam_pkcs11/pam_pkcs11.conf then change the template pam_pkcs11.conf.j2 @@ -1146,7 +1147,7 @@ dest: /etc/pam_pkcs11/pam_pkcs11.conf owner: root group: root - mode: 0644 + mode: '0644' when: - rhel_07_010500pkcs11install is changed when: @@ -1167,15 +1168,15 @@ # ############################## # This control should be manually implemented -- name: "MEDIUM | RHEL-07-020020 | AUDIT | The Red Hat Enterprise Linux operating system must prevent non-privileged users from executing privileged functions to include disabling, circumventing, or altering implemented security safeguards/countermeasures." +- name: "MEDIUM | RHEL-07-020020 | AUDIT | The Red Hat Enterprise Linux operating system must prevent nonprivileged users from executing privileged functions to include disabling, circumventing, or altering implemented security safeguards/countermeasures." block: - - name: "MEDIUM | RHEL-07-020020 | AUDIT | The Red Hat Enterprise Linux operating system must prevent non-privileged users from executing privileged functions to include disabling, circumventing, or altering implemented security safeguards/countermeasures. | Get SELinux authorized users" + - name: "MEDIUM | RHEL-07-020020 | AUDIT | The Red Hat Enterprise Linux operating system must prevent nonprivileged users from executing privileged functions to include disabling, circumventing, or altering implemented security safeguards/countermeasures. | Get SELinux authorized users" ansible.builtin.shell: semanage login -l changed_when: false failed_when: false register: rhel_07_020020_sel_auth_users - - name: "MEDIUM | RHEL-07-020020 | AUDIT | The Red Hat Enterprise Linux operating system must prevent non-privileged users from executing privileged functions to include disabling, circumventing, or altering implemented security safeguards/countermeasures. | Show SELinux authorized users" + - name: "MEDIUM | RHEL-07-020020 | AUDIT | The Red Hat Enterprise Linux operating system must prevent nonprivileged users from executing privileged functions to include disabling, circumventing, or altering implemented security safeguards/countermeasures. | Show SELinux authorized users" ansible.builtin.debug: msg: - "Warning!! Below is your SELinux user/group list. Please review and make sure all of the following are met:" @@ -1184,7 +1185,7 @@ - "{{ rhel_07_020020_sel_auth_users.stdout_lines }}" when: rhel_07_020020_sel_auth_users.stdout | length > 0 - - name: "MEDIUM | RHEL-07-020020 | AUDIT | The Red Hat Enterprise Linux operating system must prevent non-privileged users from executing privileged functions to include disabling, circumventing, or altering implemented security safeguards/countermeasures. | Warn that semanage is not installed" + - name: "MEDIUM | RHEL-07-020020 | AUDIT | The Red Hat Enterprise Linux operating system must prevent nonprivileged users from executing privileged functions to include disabling, circumventing, or altering implemented security safeguards/countermeasures. | Warn that semanage is not installed" ansible.builtin.debug: msg: - "Warning!! You do not have semanage installed! Please installed the needed packages" @@ -1197,7 +1198,7 @@ - CCI-002235 - CCI-002165 - SRG-OS-000324-GPOS-00125 - - SV-204444r754744_rule + - SV-204444r928571_rule - V-204444 - name: "MEDIUM | RHEL-07-020028 | PATCH | The Red Hat Enterprise Linux operating system must be configured to allow sending email notifications of configuration changes and adverse events to designated personnel." @@ -1283,7 +1284,7 @@ create: true owner: root group: root - mode: "0644" + mode: '0644' with_items: - file: /etc/modprobe.d/blacklist.conf insertafter: "^#blacklist usb-storage(\\s+|$)" @@ -1292,7 +1293,7 @@ - file: /etc/modprobe.d/usb-storage.conf insertafter: "^#install usb-storage" regexp: "^install usb-storage" - line: install usb-storage /bin/true + line: install usb-storage /bin/false when: - rhel_07_020100 tags: @@ -1302,7 +1303,7 @@ - CCI-000778 - CCI-000366 - SRG-OS-000114-GPOS-00059 - - SV-204449r603261_rule + - SV-204449r942894_rule - V-204449 - usb_devices @@ -1315,7 +1316,7 @@ create: true owner: root group: root - mode: "0644" + mode: '0644' with_items: - file: /etc/modprobe.d/blacklist.conf insertafter: ^#blacklist dccp @@ -1324,7 +1325,7 @@ - file: /etc/modprobe.d/dccp.conf insertafter: ^#install dccp regexp: "^install dccp " - line: install dccp /bin/true + line: install dccp /bin/false when: - rhel_07_020101 tags: @@ -1332,7 +1333,7 @@ - CAT2 - CCI-001958 - SRG-OS-000378-GPOS-00163 - - SV-204450r603261_rule + - SV-204450r942897_rule - V-204450 - dccp @@ -1382,7 +1383,7 @@ - CCI-002696 - CCI-002165 - SRG-OS-000445-GPOS-00199 - - SV-204453r754746_rule + - SV-204453r942900_rule - V-204453 - RHEL-07-020220 - SV-204454r754748_rule @@ -1427,9 +1428,9 @@ block: - name: "MEDIUM | RHEL-07-020270 | AUDIT | The Red Hat Enterprise Linux operating system must not have unnecessary accounts." ansible.builtin.shell: "grep '^{{ item }}:' /etc/passwd" - check_mode: false failed_when: rhel_07_020270_audit.rc > 1 changed_when: rhel_07_020270_audit.rc == 0 + check_mode: false register: rhel_07_020270_audit with_items: - "{{ rhel7stig_unnecessary_accounts }}" @@ -1463,18 +1464,17 @@ - name: "MEDIUM | RHEL-07-020320 | The Red Hat Enterprise Linux operating system must be configured so that all files and directories have a valid owner." block: - name: "MEDIUM | RHEL-07-020320 | AUDIT | The Red Hat Enterprise Linux operating system must be configured so that all files and directories have a valid owner." - ansible.builtin.shell: find "{{ item.mount }}" -xdev -nouser - check_mode: false + ansible.builtin.shell: find "{{ item }}" -xdev -nouser failed_when: false changed_when: false + check_mode: false register: rhel_07_020320_audit with_items: - - "{{ ansible_mounts }}" - when: item['device'].startswith('/dev') and not 'bind' in item['options'] + - "{{ prelim_local_mount_names }}" - name: "MEDIUM | RHEL-07-020320 | PATCH | The Red Hat Enterprise Linux operating system must be configured so that all files and directories have a valid owner." ansible.builtin.debug: - msg: "Warning!! Manual intervention is required -- missing owner on items in {{ item.item.mount }}: {{ item.stdout_lines | join(', ') }}" + msg: "Warning!! Manual intervention is required -- missing owner on items in {{ item.stdout_lines }}" changed_when: rhel7stig_audit_complex with_items: - "{{ rhel_07_020320_audit.results }}" @@ -1496,18 +1496,17 @@ - name: "MEDIUM | RHEL-07-020330 | The Red Hat Enterprise Linux operating system must be configured so that all files and directories have a valid group owner." block: - name: "MEDIUM | RHEL-07-020330 | AUDIT | The Red Hat Enterprise Linux operating system must be configured so that all files and directories have a valid group owner." - ansible.builtin.shell: find "{{ item.mount }}" -xdev -nogroup - check_mode: false + ansible.builtin.shell: find "{{ item }}" -xdev -nogroup failed_when: false changed_when: false + check_mode: false register: rhel_07_020330_audit with_items: - - "{{ ansible_mounts }}" - when: item['device'].startswith('/dev') and not 'bind' in item['options'] + - "{{ prelim_local_mount_names }}" - name: "MEDIUM | RHEL-07-020330 | PATCH | The Red Hat Enterprise Linux operating system must be configured so that all files and directories have a valid group owner." ansible.builtin.debug: - msg: "Warning!! Manual intervention is required -- missing group on items in {{ item.item.mount }}: {{ item.stdout_lines | join(', ') }}" + msg: "Warning!! Manual intervention is required -- missing group on items in {{ item.stdout_lines }}" changed_when: rhel7stig_audit_complex with_items: - "{{ rhel_07_020330_audit.results }}" @@ -1547,7 +1546,7 @@ ansible.builtin.file: path: "{{ item.dir }}" state: directory - mode: 0700 + mode: '0700' with_items: - "{{ rhel7stig_passwd }}" loop_control: @@ -1589,7 +1588,7 @@ ansible.builtin.file: path: "{{ item.dir }}" owner: "{{ item.id }}" - mode: 0700 + mode: '0700' state: directory with_items: - "{{ rhel7stig_passwd }}" @@ -1612,7 +1611,7 @@ path: "{{ item.dir }}" group: "{{ item.gid }}" # noqa risky-file-permissions state: directory - mode: 0700 + mode: '0700' with_items: - "{{ rhel7stig_passwd }}" loop_control: @@ -1633,8 +1632,8 @@ block: - name: "MEDIUM | RHEL-07-020660 | AUDIT | The Red Hat Enterprise Linux operating system must be configured so that all files and directories contained in local interactive user home directories are owned by the owner of the home directory." ansible.builtin.shell: "{{ find_command_base }} -print -quit" - check_mode: false changed_when: rhel_07_020660_audit.stdout |length > 0 + check_mode: false register: rhel_07_020660_audit with_items: "{{ rhel7stig_passwd }}" loop_control: @@ -1670,8 +1669,8 @@ block: - name: "MEDIUM | RHEL-07-020670 | AUDIT | Get all GIDs for each user." ansible.builtin.shell: id -G "{{ item.id }}" - check_mode: false changed_when: false + check_mode: false register: rhel_07_all_gid_audit with_items: - "{{ rhel7stig_passwd }}" @@ -1680,8 +1679,8 @@ - name: "MEDIUM | RHEL-07-020670 | AUDIT | The Red Hat Enterprise Linux operating system must be configured so that all files and directories contained in local interactive user home directories are group-owned by a group of which the home directory owner is a member." ansible.builtin.shell: "{{ find_command_base }} -print -quit" - check_mode: false changed_when: rhel_07_020670_audit.stdout| length > 0 + check_mode: false register: rhel_07_020670_audit with_items: - "{{ rhel_07_all_gid_audit.results }}" @@ -1726,8 +1725,8 @@ - name: "MEDIUM | RHEL-07-020680 | AUDIT | The Red Hat Enterprise Linux operating system must be configured so that all files and directories contained in local interactive user home directories have a mode of 0750 or less permissive." ansible.builtin.shell: find -H {{ item.0 | quote }} -not -type l -perm /027 - check_mode: false changed_when: rhel_07_020680_patch_audit.stdout| length > 0 + check_mode: false register: rhel_07_020680_patch_audit with_together: - "{{ rhel_07_020680_audit.results | map(attribute='item') | list }}" @@ -1786,8 +1785,8 @@ block: - name: "MEDIUM | RHEL-07-020690 | AUDIT | The Red Hat Enterprise Linux operating system must be configured so that all local initialization files for interactive users are owned by the home directory user or root." ansible.builtin.shell: "{{ find_command_base }} -print -quit" - check_mode: false changed_when: rhel_07_020690_audit.stdout | length > 0 + check_mode: false register: rhel_07_020690_audit with_items: - "{{ rhel7stig_passwd }}" @@ -1824,8 +1823,8 @@ block: - name: "MEDIUM | RHEL-07-020700 | AUDIT | The Red Hat Enterprise Linux operating system must be configured so that all local initialization files for local interactive users are be group-owned by the users primary group or root." ansible.builtin.shell: "{{ find_command_base }} -print -quit" - check_mode: false changed_when: rhel_07_020700_audit.stdout| length > 0 + check_mode: false register: rhel_07_020700_audit with_items: - "{{ rhel7stig_passwd }}" @@ -1880,7 +1879,7 @@ - name: "MEDIUM | RHEL-07-020720 | AUDIT | The Red Hat Enterprise Linux operating system must be configured so that all local interactive user initialization files executable search paths contain only paths that resolve to the users home directory." block: - name: "MEDIUM | RHEL-07-020720 | AUDIT | The Red Hat Enterprise Linux operating system must be configured so that all local interactive user initialization files executable search paths contain only paths that resolve to the users home directory." - ansible.builtin.shell: find "{{ item }}" -maxdepth 1 -type f | xargs grep "PATH=" | cut -d':' -f1 | xargs realpath + ansible.builtin.shell: find "{{ item }}" -maxdepth 1 -type f | xargs grep "PATH=" | cut -d':' -f1 | xargs realpath with_items: "{{ rhel_07_stig_interactive_homedir_results }}" changed_when: false failed_when: false @@ -1920,7 +1919,7 @@ block: # Let's find any progerams with world-writable permissions. - name: "MEDIUM | RHEL-07-020730 | AUDIT | The Red Hat Enterprise Linux operating system must be configured so that local initialization files do not execute world-writable programs." - ansible.builtin.shell: find / -xdev -perm -002 -type f -exec ls -ld {} \; | awk '{print $9}' + ansible.builtin.shell: find / -xdev -not -fstype nfs -perm -002 -type f -exec ls -ld {} \; | awk '{print $9}' failed_when: false changed_when: false register: rhel_07_020730_perms_results @@ -1981,7 +1980,7 @@ - name: "MEDIUM | RHEL-07-020900 | The Red Hat Enterprise Linux operating system must be configured so that all system device files are correctly labeled to prevent unauthorized modification." block: - name: "MEDIUM | RHEL-07-020900 | AUDIT | The Red Hat Enterprise Linux operating system must be configured so that all system device files are correctly labeled to prevent unauthorized modification." - ansible.builtin.shell: find {{ rhel7stig_local_mounts | join(' ') }} -xdev -context *:device_t:* -o -context *:unlabeled_t:* -type c -o -type b -printf '%p %Z\n' + ansible.builtin.shell: find / -xdev -not -fstype nfs -context *:device_t:* -o -context *:unlabeled_t:* -type c -o -type b -printf '%p %Z\n' changed_when: false check_mode: false register: rhel_07_020900_audit @@ -2012,15 +2011,16 @@ ansible.posix.mount: path: /home state: mounted - src: "{{ home_mount.device }}" - fstype: "{{ home_mount.fstype }}" - opts: "{{ home_mount.options }},nosuid" - vars: - home_mount: "{{ ansible_mounts | json_query('[?mount == `/home`] | [0]') }}" # noqa: jinja[invalid] + src: "{{ item.device }}" + fstype: "{{ item.fstype }}" + opts: "{{ item.options }},nosuid" + loop: "{{ ansible_facts.mounts }}" + loop_control: + label: "{{ item.device }}" when: - rhel_07_021000 - - ansible_mounts | selectattr('mount', 'match', '^/home$') | list | length != 0 - - "'nosuid' not in home_mount.options" + - item.mount == "/home" + - "'nosuid' not in item.options" tags: - RHEL-07-021000 - CAT2 @@ -2035,27 +2035,29 @@ ansible.posix.mount: path: /media state: mounted - src: "{{ removable_mount.device }}" - fstype: "{{ removable_mount.fstype }}" - opts: "{{ removable_mount.options }},nosuid" - vars: - removable_mount: "{{ ansible_mounts | json_query('[?mount == `/media`] | [0]') }}" # noqa: jinja[invalid] + src: "{{ item.device }}" + fstype: "{{ item.fstype }}" + opts: "{{ item.options }},nosuid" + loop: "{{ ansible_facts.mounts }}" + loop_control: + label: "{{ item.device }}" when: - - ansible_mounts | selectattr('mount', 'match', '^/media$') | list | length != 0 - - "'nosuid' not in removable_mount.options" + - item.mount == "/media" + - "'nosuid' not in item.options" - name: "MEDIUM | RHEL-07-021010 | AUDIT | The Red Hat Enterprise Linux operating system must prevent files with the setuid and setgid bit set from being executed on file systems that are used with removable media." ansible.posix.mount: path: /mnt state: mounted - src: "{{ removable_mount2.device }}" - fstype: "{{ removable_mount2.fstype }}" - opts: "{{ removable_mount2.options }},nosuid" - vars: - removable_mount2: "{{ ansible_mounts | json_query('[?mount == `/mnt`] | [0]') }}" # noqa: jinja[invalid] + src: "{{ item.device }}" + fstype: "{{ item.fstype }}" + opts: "{{ item.options }},nosuid" + loop: "{{ ansible_facts.mounts }}" + loop_control: + label: "{{ item.device }}" when: - - ansible_mounts | selectattr('mount', 'match', '^/mnt$') | list | length != 0 - - "'nosuid' not in removable_mount2.options" + - item.mount == "/mnt" + - "'nosuid' not in item.options" when: - rhel_07_021010 - not (rhel7stig_system_is_chroot and rhel7stig_system_is_container) @@ -2070,19 +2072,15 @@ - name: "MEDIUM | RHEL-07-021020 | PATCH | The Red Hat Enterprise Linux operating system must prevent files with the setuid and setgid bit set from being executed on file systems that are being imported via Network File System (NFS)." ansible.posix.mount: path: "{{ item }}" - src: "{{ ansible_mounts | json_query(device_query) }}" - fstype: "{{ ansible_mounts | json_query(fstype_query) }}" - opts: "{{ ansible_mounts | json_query(options_query) }},nosuid" + src: "{{ item.src }}" + fstype: "{{ aitem.fstype }}" + opts: "{{ item.opts,nosuid }}" state: mounted - vars: - device_query: '[?mount == `{{ item }}`] | [0].device' # noqa: jinja[invalid] - fstype_query: '[?mount == `{{ item }}`] | [0].fstype' # noqa: jinja[invalid] - options_query: '[?mount == `{{ item }}`] | [0].options' # noqa: jinja[invalid] with_items: - - "{{ rhel7stig_nfs_mounts }}" + - "{{ prelim_nfs_mount_names }}" when: - rhel_07_021020 - - "'nosuid' not in (ansible_mounts | json_query(options_query))" + - "'nosuid' not in item" tags: - RHEL-07-021020 - CAT2 @@ -2095,19 +2093,15 @@ - name: "MEDIUM | RHEL-07-021021 | PATCH | The Red Hat Enterprise Linux operating system must prevent binary files from being executed on file systems that are being imported via Network File System (NFS)." ansible.posix.mount: path: "{{ item }}" - src: "{{ ansible_mounts | json_query(device_query) }}" - fstype: "{{ ansible_mounts | json_query(fstype_query) }}" - opts: "{{ ansible_mounts | json_query(options_query) }},noexec" + src: "{{ item.src }}" + fstype: "{{ aitem.fstype }}" + opts: "{{ item.opts,noexec }}" state: mounted - vars: - device_query: '[?mount == `{{ item }}`] | [0].device' # noqa: jinja[invalid] - fstype_query: '[?mount == `{{ item }}`] | [0].fstype' # noqa: jinja[invalid] - options_query: '[?mount == `{{ item }}`] | [0].options' # noqa: jinja[invalid] with_items: - - "{{ rhel7stig_nfs_mounts }}" + - "{{ prelim_nfs_mount_names }}" when: - rhel_07_021021 - - "'noexec' not in (ansible_mounts | json_query(options_query))" + - "'noexec' not in item" tags: - RHEL-07-021021 - CAT2 @@ -2120,7 +2114,7 @@ - name: "MEDIUM | RHEL-07-021030 | The Red Hat Enterprise Linux operating system must be configured so that all world-writable directories are group-owned by root, sys, bin, or an application group." block: - name: "MEDIUM | RHEL-07-021030 | AUDIT | The Red Hat Enterprise Linux operating system must be configured so that all world-writable directories are group-owned by root, sys, bin, or an application group." - ansible.builtin.shell: find {{ rhel7stig_local_mounts | join(' ') }} -xdev -type d -perm -002 -gid +999 + ansible.builtin.shell: find / -xdev -not -fstype nfs -type d -perm -002 -gid +999 changed_when: rhel_07_021030_audit.stdout != "" check_mode: false register: rhel_07_021030_audit @@ -2206,7 +2200,7 @@ state: file owner: root group: root - mode: 0600 + mode: '0600' when: cron_allow_file_check.stat.exists when: - rhel_07_021110 @@ -2226,9 +2220,9 @@ block: - name: "MEDIUM | RHEL-07-021300 | PATCH | The Red Hat Enterprise Linux operating system must disable Kernel core dumps unless needed." ansible.builtin.shell: "systemctl show kdump | grep LoadState | cut -d = -f 2" - register: rhel_07_021300_kdump_service_status changed_when: false check_mode: false + register: rhel_07_021300_kdump_service_status - name: "MEDIUM | RHEL-07-021300 | PATCH | The Red Hat Enterprise Linux operating system must disable Kernel core dumps unless needed." ansible.builtin.service: @@ -2307,7 +2301,7 @@ - CCI-001813 - CCI-000318 - SRG-OS-000364-GPOS-00151 - - SV-204501r603261_rule + - SV-204501r928576_rule - V-204501 - grub - bootloader @@ -2371,7 +2365,7 @@ regexp: "{{ item.regexp }}" line: "{{ item.line }}" create: true - mode: 0640 + mode: '0640' notify: restart auditd with_items: - { regexp: '^active =', line: 'active = yes'} @@ -2498,7 +2492,7 @@ ansible.builtin.lineinfile: path: /etc/audit/auditd.conf regexp: ^space_left += - line: "space_left = {{ [rhel7stig_auditd_space_left | int, 51] | max }}" + line: "space_left = 25%" when: - rhel_07_030330 tags: @@ -3296,7 +3290,7 @@ - name: "MEDIUM | RHEL-07-040160 | PATCH | The Red Hat Enterprise Linux operating system must be configured so that all network connections associated with a communication session are terminated at the end of the session or after 15 minutes of inactivity from the user at a command prompt, except to fulfill documented and validated mission requirements." ansible.builtin.blockinfile: create: true - mode: 0644 + mode: '0644' dest: "{{ item.dest }}" state: "{{ item.state }}" marker: "# {mark} ANSIBLE MANAGED" @@ -3358,9 +3352,9 @@ "MEDIUM | RHEL-07-040190 | AUDIT | The Red Hat Enterprise Linux operating system must implement cryptography to protect the integrity of Lightweight Directory Access Protocol (LDAP) communications." "MEDIUM | RHEL-07-040200 | AUDIT | The Red Hat Enterprise Linux operating system must implement cryptography to protect the integrity of Lightweight Directory Access Protocol (LDAP) communications." ansible.builtin.shell: systemctl status sssd.service | grep "Active" | cut -d ':' -f1 | tr " " "\n" | sed '/^$/d' - check_mode: false failed_when: false changed_when: false + check_mode: false register: rhel_07_040180_audit - name: | @@ -3385,7 +3379,7 @@ path: /etc/sssd/sssd.conf insertafter: "^ldap_search_base*" create: true - mode: 0600 + mode: '0600' when: rhel_07_040180_audit.stdout == "Active" when: - rhel_07_040180 or @@ -3399,10 +3393,10 @@ - SV-204581r603261_rule - V-204581 - RHEL-07-040190 - - SV-204582r603261_rule + - SV-204582r942909_rule - V-204582 - RHEL-07-040200 - - SV-204583r603261_rule + - SV-204583r942912_rule - V-204583 - ldap @@ -3475,7 +3469,7 @@ regexp: "(?i)^#?ClientAliveInterval" line: ClientAliveInterval {{ rhel7stig_ssh_session_timeout }} validate: /usr/sbin/sshd -t -f %s - mode: 0600 + mode: '0600' notify: restart sshd when: - rhel_07_040320 @@ -3517,7 +3511,7 @@ regexp: "(?i)^#?ClientAliveCountMax" line: ClientAliveCountMax 0 validate: /usr/sbin/sshd -t -f %s - mode: 0600 + mode: '0600' notify: restart sshd when: - rhel_07_040340 @@ -3578,7 +3572,7 @@ line: PermitRootLogin no insertafter: '(?i)^#?authentication' validate: /usr/sbin/sshd -t -f %s - mode: 0600 + mode: '0600' notify: restart sshd when: - rhel_07_040370 @@ -3598,7 +3592,7 @@ regexp: "(?i)^#?IgnoreUserKnownHosts" line: IgnoreUserKnownHosts yes validate: /usr/sbin/sshd -t -f %s - mode: 0600 + mode: '0600' notify: restart sshd when: - rhel_07_040380 @@ -3619,7 +3613,7 @@ regexp: "(?i)^#?MACs" line: "MACs {{ rhel7stig_ssh_macs }}" validate: /usr/sbin/sshd -t -f %s - mode: 0600 + mode: '0600' notify: restart sshd when: - rhel_07_040400 @@ -3703,7 +3697,7 @@ regexp: "(?i)^#?GSSAPIAuthentication" line: GSSAPIAuthentication no validate: /usr/sbin/sshd -t -f %s - mode: 0600 + mode: '0600' notify: restart sshd when: - rhel_07_040430 @@ -3826,7 +3820,7 @@ dest: "{{ rhel7stig_time_service_configs[rhel7stig_time_service].conf }}" regexp: "{{ item.regexp }}" line: "{{ item.line }}" - mode: 0600 + mode: '0600' notify: restart {{ rhel7stig_time_service }} with_items: - "{{ rhel7stig_time_service_configs[rhel7stig_time_service].lines }}" @@ -4111,8 +4105,8 @@ block: - name: "MEDIUM | RHEL-07-040680 | AUDIT | The Red Hat Enterprise Linux operating system must be configured to prevent unrestricted mail relaying." ansible.builtin.shell: "/usr/sbin/postconf -n smtpd_client_restrictions" - check_mode: false changed_when: false + check_mode: false register: rhel_07_040680_postconf_audit when: "'postfix' in ansible_facts.packages" @@ -4138,7 +4132,7 @@ regexp: "(?i)^#?X11Forwarding" line: X11Forwarding no validate: /usr/sbin/sshd -t -f %s - mode: 0600 + mode: '0600' notify: restart sshd when: - rhel_07_040710 @@ -4159,7 +4153,7 @@ regexp: "(?i)^#?KexAlgorithms" line: KexAlgorithms "{{ rhel7stig_ssh_kex }}" validate: /usr/sbin/sshd -t -f %s - mode: 0600 + mode: '0600' notify: restart sshd when: - rhel_07_040712 @@ -4198,9 +4192,7 @@ - name: "MEDIUM | RHEL-07-040730 | PATCH | The Red Hat Enterprise Linux operating system must not have an X Windows display manager installed unless approved." ansible.builtin.package: - name: - - "@x11" - - xorg-x11-server-common + name: "{{ rhel7stig_gui_pkgs }}" state: absent vars: ansible_python_interpreter: "{{ python2_bin }}" @@ -4239,10 +4231,10 @@ block: - name: "MEDIUM | RHEL-07-040750 | PATCH | The Red Hat Enterprise Linux operating system must be configured so that the Network File System (NFS) is configured to use RPCSEC_GSS." ansible.builtin.shell: cat /etc/fstab | grep nfs - register: rhel_07_040750_nfssec_check changed_when: false failed_when: false check_mode: false + register: rhel_07_040750_nfssec_check - name: "MEDIUM | RHEL-07-040750 | PATCH | The Red Hat Enterprise Linux operating system must be configured so that the Network File System (NFS) is configured to use RPCSEC_GSS." ansible.builtin.debug: @@ -4369,13 +4361,13 @@ block: - name: "MEDIUM | RHEL-07-041002 | AUDIT | Check if pam service is configured in sssd file" ansible.builtin.shell: 'grep -E "^\s*services\s*=.*pam" /etc/sssd/sssd.conf' - check_mode: false changed_when: - sssd_services_check.rc == 1 - not rhel7stig_skip_for_travis failed_when: false # todo: only run if sssd installed and config file present # failed_when: sssd_services_check.rc > 1 + check_mode: false register: sssd_services_check - name: "MEDIUM | RHEL-07-041002 | PATCH | The Red Hat Enterprise Linux operating system must implement multifactor authentication for access to privileged accounts via pluggable authentication modules (PAM)." @@ -4419,16 +4411,35 @@ - name: "MEDIUM | RHEL-07-041010 | The Red Hat Enterprise Linux operating system must be configured so that all wireless network adapters are disabled." block: + - name: "MEDIUM | RHEL-07-041010 | The Red Hat Enterprise Linux operating system must be configured so that all wireless network adapters are disabled. | Discover if wirelss adapter on system" + ansible.builtin.shell: find /sys/class/net/*/ -type d -name wireless + changed_when: false + failed_when: discovered_wireless_adapters.rc not in [ 0, 1 ] + register: discovered_wireless_adapters + + - name: "MEDIUM | RHEL-07-041010 | The Red Hat Enterprise Linux operating system must be configured so that all wireless network adapters are disabled. | if wireless adapter present" + ansible.builtin.package: + name: NetworkManager + state: present + when: + - discovered_wireless_adapters.rc == 0 + - "'NetworkManager' not in ansible_facts.packages" + - name: "MEDIUM | RHEL-07-041010 | AUDIT | check if wifi is enabled" ansible.builtin.shell: nmcli radio wifi changed_when: false + failed_when: rhel_07_wifi_enabled.rc not in [ 0, 1 ] check_mode: false register: rhel_07_wifi_enabled + when: + - discovered_wireless_adapters.rc == 0 - name: "MEDIUM | RHEL-07-041010 | PATCH | The Red Hat Enterprise Linux operating system must be configured so that all wireless network adapters are disabled." ansible.builtin.shell: nmcli radio wifi off when: + - discovered_wireless_adapters.rc == 0 - "'enabled' in rhel_07_wifi_enabled.stdout" + - rhel_07_wifi_enabled.rc == 0 when: - rhel_07_041010 - "'NetworkManager' in ansible_facts.packages" @@ -4444,11 +4455,11 @@ - wifi - networking -- name: "MEDIUM | RHEL-07-020019 | AUDIT | The Red Hat Enterprise Linux operating system must have a host-based intrusion detection tool installed." +- name: "MEDIUM | RHEL-07-020019 | AUDIT | The Red Hat Enterprise Linux operating system must implement the Endpoint Security for Linux Threat Prevention tool." ansible.builtin.debug: msg: - - "Please install and enable the latest McAfee HIPS package, available from USCYBERCOM." - - "If the system does not support the McAfee HIPS package, install and enable a supported intrusion detection system application and document its use with the Authorizing Official." + - "Please install and enable the latest Trellix ENSLTP package." + - "If the system does not support the Trellix ENSLTP package, install and enable a supported intrusion detection system application and document its use with the Authorizing Official." when: - rhel_07_020019 tags: @@ -4457,7 +4468,7 @@ - CAT2 - CCI-001263 - SRG-OS-000480-GPOS-00227 - - SV-214800r603261_rule + - SV-214800r942888_rule - V-214800 - antivirus @@ -4540,7 +4551,7 @@ path: "{{ item.path }}" owner: root group: root - mode: 0600 + mode: '0600' with_items: - "{{ rhel_07_910055_audit_log_files.files }}" when: item.mode is not search '(0[4,6]00)' @@ -4565,7 +4576,7 @@ regexp: "(?i)^#?X11UseLocalhost" line: X11UseLocalhost yes validate: /usr/sbin/sshd -t -f %s - mode: 0600 + mode: '0600' notify: restart sshd when: - rhel_07_040711 @@ -4742,7 +4753,7 @@ - CCI-002165 - CCI-002235 - SRG-OS-000324-GPOS-00125 - - SV-250312r792843_rule + - SV-250312r928579_rule - V-250312 - name: "MEDIUM | RHEL-07-020022 | PATCH | The Red Hat Enterprise Linux operating system must not allow privileged accounts to utilize SSH." @@ -4758,7 +4769,7 @@ - CCI-002165 - CI-002235 - SRG-OS-000324-GPOS-00125 - - SV-250313r792846_rule + - SV-250313r942891_rule - V-250313 - name: "MEDIUM | RHEL-07-020023 | AUDIT | The Red Hat Enterprise Linux operating system must elevate the SELinux context when an administrator calls the sudo command" @@ -4791,5 +4802,5 @@ - CCI-002165 - CCI-002235 - SRG-OS-000324-GPOS-00125 - - SV-250314r861076_rule + - SV-250314r877392_rule - V-250314 diff --git a/tasks/main.yml b/tasks/main.yml index 2041044a..e2ca6494 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -72,27 +72,25 @@ tags: - always -- name: include prelim tasks +- name: Update CentOS repo for packages - Use vaulted/archive URL - backup original + ansible.builtin.template: + src: etc/yum.repos.d/CentOS-Base.repo.j2 + dest: /etc/yum.repos.d/CentOS-Base.repo + owner: root + group: root + mode: '0644' + backup: true + when: + - rhel7stig_add_updated_repo + - ansible_distribution == "CentOS" + +- name: Include prelim tasks ansible.builtin.import_tasks: file: prelim.yml tags: - prelim_tasks - run_audit -- name: include pre-remediation audit - ansible.builtin.import_tasks: - file: pre_remediation_audit.yml - when: - - run_audit - tags: - - run_audit - -- name: Gather the package facts - ansible.builtin.package_facts: - manager: auto - tags: - - always - - name: Include CAT I patches ansible.builtin.import_tasks: file: fix-cat1.yml @@ -117,13 +115,13 @@ - cat3 - low -- name: update auditd +- name: Update auditd ansible.builtin.template: src: audit/99_auditd.rules.j2 dest: /etc/audit/rules.d/99_auditd.rules owner: root group: root - mode: 0600 + mode: '0600' register: auditd_file notify: restart auditd when: diff --git a/tasks/parse_etc_passwd.yml b/tasks/parse_etc_passwd.yml index 4df03de1..22c9fcbf 100644 --- a/tasks/parse_etc_passwd.yml +++ b/tasks/parse_etc_passwd.yml @@ -2,7 +2,7 @@ - name: "PRELIM | {{ rhel7stig_passwd_tasks }} | Parse /etc/passwd" block: - name: "PRELIM | {{ rhel7stig_passwd_tasks }} | Parse /etc/passwd" - ansible.builtin.shell: cat /etc/passwd + ansible.builtin.shell: cat /etc/passwd | grep -v '/sbin/nologin\|/usr/sbin/nologin' changed_when: false check_mode: false register: rhel7stig_passwd_file_audit @@ -15,7 +15,7 @@ vars: ld_passwd_regex: >- ^(?P[^:]*):(?P[^:]*):(?P[^:]*):(?P[^:]*):(?P[^:]*):(?P[^:]*):(?P[^:]*) - ld_passwd_yaml: | + ld_passwd_yaml: | # pragma: allowlist secret id: >-4 \g password: >-4 diff --git a/tasks/post_remediation_audit.yml b/tasks/post_remediation_audit.yml index 6d20eeaa..ad433527 100644 --- a/tasks/post_remediation_audit.yml +++ b/tasks/post_remediation_audit.yml @@ -1,44 +1,44 @@ --- -- 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 }}" - environment: "{{ audit_run_script_environment | default({}) }}" - changed_when: false - register: audit_run_post_remediation +- name: Post Audit | Run post_remediation {{ benchmark }} audit + ansible.builtin.shell: "{{ audit_conf_dir }}/run_audit.sh -v {{ audit_vars_path }} -f {{ audit_format }} -o {{ post_audit_outfile }} -g \"{{ group_names }}\"" + changed_when: true + environment: + AUDIT_BIN: "{{ audit_bin }}" + AUDIT_CONTENT_LOCATION: "{{ audit_conf_dest | default('/opt') }}" + 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: "Post Audit | capture data {{ post_audit_outfile }} | JSON format" - ansible.builtin.shell: "cat {{ post_audit_outfile }}" - register: post_audit + - name: Post Audit | Capture audit data if json format + ansible.builtin.shell: grep -E '"summary-line.*Count:.*Failed' "{{ post_audit_outfile }}" | cut -d'"' -f4 changed_when: false + register: post_audit_summary - - name: PostAudit | Capture post-audit result | JSON format + - name: Post Audit | Set Fact for audit summary ansible.builtin.set_fact: - post_audit_summary: "{{ post_audit.stdout | from_json | json_query(summary) }}" - vars: - summary: 'summary."summary-line"' - when: - - audit_format == "json" + post_audit_results: "{{ post_audit_summary.stdout }}" - name: Post Audit | Capture audit data if documentation format + when: + - audit_format == "documentation" block: - - name: "Post Audit | capture data {{ post_audit_outfile }} | documentation format" - ansible.builtin.shell: "tail -2 {{ post_audit_outfile }}" - register: post_audit + - name: Post Audit | Capture audit data if documentation format + ansible.builtin.shell: "tail -2 /opt/audit_ubuntu2204-CIS-UBUNTU22_1720624848.documentation" changed_when: false + register: post_audit_summary - - name: Post Audit | Capture post-audit result | documentation format + - name: Post Audit | Set Fact for audit summary ansible.builtin.set_fact: - post_audit_summary: "{{ post_audit.stdout_lines }}" - when: - - audit_format == "documentation" + post_audit_results: "{{ post_audit_summary.stdout }}" diff --git a/tasks/pre_remediation_audit.yml b/tasks/pre_remediation_audit.yml index 7b4d06f5..d822b587 100644 --- a/tasks/pre_remediation_audit.yml +++ b/tasks/pre_remediation_audit.yml @@ -1,62 +1,64 @@ --- -- name: 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: + file: 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 (rh8 python3) - ansible.builtin.package: - name: git - state: present - when: ansible_distribution_major_version == '8' - - - name: Pre Audit Setup | Install git (rh7 python2) + - name: Pre Audit Setup | Install git + when: ansible_distribution_major_version == '7' ansible.builtin.package: name: git state: present vars: ansible_python_interpreter: "{{ python2_bin }}" - when: ansible_distribution_major_version == '7' - - name: Pre Audit Setup | retrieve audit content files from git + - name: Pre Audit Setup | Retrieve audit content files from git ansible.builtin.git: 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_dir }}" - mode: 0644 +- name: Pre Audit Setup | Copy to audit content files to server when: - audit_content == 'copy' + ansible.builtin.copy: + src: "{{ audit_conf_source }}" + dest: "{{ audit_conf_dest }}" + mode: preserve + +- name: Pre Audit Setup | Unarchive audit content files on server + when: + - audit_content == 'archive' + ansible.builtin.unarchive: + src: "{{ audit_conf_source }}" + dest: "{{ audit_conf_dest }}" -- name: Pre Audit Setup | get audit content from url - ansible.builtin.get_url: - url: "{{ audit_files_url }}" - dest: "{{ audit_conf_dir }}" - owner: root - group: root - mode: 0755 +- name: Pre Audit Setup | Get audit content from url when: - audit_content == 'get_url' + ansible.builtin.unarchive: + src: "{{ audit_conf_source }}" + dest: "{{ audit_conf_dest }}/{{ benchmark }}-Audit" + remote_src: "{{ ( audit_conf_source is contains ('http'))| ternary(true, false ) }}" + extra_opts: "{{ (audit_conf_source is contains ('github')) | ternary('--strip-components=1', [] ) }}" - name: Pre Audit Setup | Check Goss is available + when: + - run_audit block: - name: Pre Audit Setup | Check for goss file ansible.builtin.stat: @@ -64,52 +66,58 @@ 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 + 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 }}" - environment: "{{ audit_run_script_environment | default({}) }}" - changed_when: audit_run_pre_remediation.rc == 0 - register: audit_run_pre_remediation +- name: Pre Audit | Run pre_remediation {{ benchmark }} audit + ansible.builtin.shell: "{{ audit_conf_dir }}/run_audit.sh -v {{ audit_vars_path }} -f {{ audit_format }} -o {{ pre_audit_outfile }} -g \"{{ group_names }}\"" + changed_when: true + environment: + AUDIT_BIN: "{{ audit_bin }}" + AUDIT_CONTENT_LOCATION: "{{ audit_conf_dest | default('/opt') }}" + 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 }}" - register: pre_audit + - name: Pre Audit | Capture audit data if json format + ansible.builtin.shell: grep -E '\"summary-line.*Count:.*Failed' "{{ pre_audit_outfile }}" | cut -d'"' -f4 changed_when: false + register: pre_audit_summary - - name: Pre Audit | Capture pre-audit result + - name: Pre Audit | Set Fact for audit summary ansible.builtin.set_fact: - pre_audit_summary: "{{ pre_audit.stdout | from_json | json_query(summary) }}" - vars: - summary: 'summary."summary-line"' - when: - - audit_format == "json" + pre_audit_results: "{{ pre_audit_summary.stdout }}" - name: Pre Audit | Capture audit data if documentation format + when: + - audit_format == "documentation" block: - - name: "capture data {{ pre_audit_outfile }}" - ansible.builtin.shell: "tail -2 {{ pre_audit_outfile }}" - register: pre_audit + - name: Pre Audit | Capture audit data if documentation format + ansible.builtin.shell: tail -2 "{{ pre_audit_outfile }}" | tac | tr '\n' ' ' changed_when: false + register: pre_audit_summary - - name: Pre Audit | Capture pre-audit result + - name: Pre Audit | Set Fact for audit summary ansible.builtin.set_fact: - pre_audit_summary: "{{ pre_audit.stdout_lines }}" - when: - - audit_format == "documentation" + pre_audit_results: "{{ pre_audit_summary.stdout }}" + +- name: Audit_Only | Run Audit Only + when: + - audit_only + ansible.builtin.import_tasks: + file: audit_only.yml diff --git a/tasks/prelim.yml b/tasks/prelim.yml index a4cdb913..44bb85f2 100644 --- a/tasks/prelim.yml +++ b/tasks/prelim.yml @@ -1,5 +1,84 @@ --- +- name: Set bootloader type + block: + - name: "PRELIM | Check whether machine is UEFI-based" + ansible.builtin.stat: + path: /sys/firmware/efi + register: rhel7_efi_boot + + - name: "PRELIM | set fact if UEFI boot | RHEL or OEL" + ansible.builtin.set_fact: + rhel7stig_bootloader_path: "{{ rhel7stig_efi_boot_path }}redhat" + rhel7stig_not_boot_path: "{{ rhel7stig_legacy_boot_path }}" + rhel7stig_legacy_boot: false + when: + - rhel7_efi_boot.stat.exists + - ansible_distribution != 'CentOS' # Note: rhel & OEL both use redhat path + + - name: "PRELIM | set fact if UEFI boot | CentOS " + ansible.builtin.set_fact: + rhel7stig_bootloader_path: "{{ rhel7stig_efi_boot_path }}centos" + rhel7stig_not_boot_path: "{{ rhel7stig_legacy_boot_path }}" + rhel7stig_legacy_boot: false + when: + - rhel7_efi_boot.stat.exists + - ansible_distribution == 'CentOS' + + - name: "PRELIM | set if not UEFI boot" + ansible.builtin.set_fact: + rhel7stig_bootloader_path: "{{ rhel7stig_legacy_boot_path }}" + rhel7stig_not_boot_path: "{{ rhel7stig_efi_boot_path }}" + rhel7stig_legacy_boot: true + when: not rhel7_efi_boot.stat.exists + + - name: PRELIM | output bootloader and efi state + ansible.builtin.debug: + msg: + - "bootloader path set to {{ rhel7stig_bootloader_path }}" + - "legacy boot equals {{ rhel7stig_legacy_boot }}" + tags: + - always + +- name: "PRELIM | Gather interactive user ID min" + block: + - name: "PRELIM | Gather interactive user ID min" + ansible.builtin.shell: grep ^UID_MIN /etc/login.defs | awk '{print $2}' + changed_when: false + failed_when: false + register: rhel7stig_min_uid + + - name: "PRELIM | Gather interactive user ID max" + ansible.builtin.shell: grep ^UID_MAX /etc/login.defs | awk '{print $2}' + changed_when: false + failed_when: false + register: rhel7stig_max_uid + + - name: "PRELIM | Setting the fact" + ansible.builtin.set_fact: + rhel7stig_interactive_uid_start: "{{ rhel7stig_min_uid.stdout }}" + rhel7stig_interactive_uid_stop: "{{ rhel7stig_max_uid.stdout }}" + tags: + - always + - auditd + +- name: "PRELIM | Include audit specific variables" + ansible.builtin.include_vars: audit.yml + when: + - run_audit or audit_only + - setup_audit + tags: + - setup_audit + - run_audit + +- name: "PRELIM | Include pre-remediation audit tasks" + ansible.builtin.import_tasks: pre_remediation_audit.yml + when: + - run_audit or audit_only + - setup_audit + tags: + - run_audit + - name: "PRELIM | Check required packages installed | Python2" ansible.builtin.package: name: @@ -43,6 +122,47 @@ vars: ansible_python_interpreter: "{{ python2_bin }}" +- name: "PRELIM | RHEL-07-021350" + block: + - name: "PRELIM | RHEL-07-021350 | Check if /boot or /boot/efi reside on separate partitions" + ansible.builtin.shell: df --output=target /boot | tail -n 1 + changed_when: false + check_mode: false + register: rhel7stig_boot_part + + - name: "PRELIM | RHEL-07-021350 | Check if /boot or /boot/efi reside on separate partitions | get UUID" + ansible.builtin.shell: lsblk -f | grep -E "{{ rhel7stig_boot_part.stdout }}$" | awk '{ print $3 }' + changed_when: false + check_mode: false + register: rhel7stig_boot_uuid + when: + - rhel_07_021350 + tags: + - RHEL-07-021350 + - CAT1 + - CCI-001199 + - CCI-000068 + - CCI-002450 + - CCI-002476 + - SRG-OS-000033-GPOS-00014 + - SV-204497r603261_rule + - V-204497 + - fips + +- name: PRELIM | Gnome Desktop Environment Discovery + tags: + - always + block: + - name: PRELIM | Gnome Desktop Environment Discovery + ansible.builtin.stat: + path: /usr/share/gnome/gnome-version.xml + register: prelim_gnome_present + + - name: PRELIM | Gnome Desktop Environment Discovery | add packages if x11 not required + when: rhel_07_040710 + ansible.builtin.set_fact: + rhel7stig_gui_pkgs: "{{ rhel7stig_gui_pkgs + [ '@X11', 'xorg-x11-*' ] }}" + - name: "PRELIM | dconf" block: - name: "PRELIM | Check for dconf availability" @@ -194,6 +314,13 @@ tags: - always +- name: "PRELIM | AUDIT | Create list of mount points" + ansible.builtin.set_fact: + prelim_local_mount_names: "{{ ansible_facts.mounts | map(attribute='mount') | list }}" + prelim_nfs_mount_names: "{{ ansible_facts.mounts | selectattr('fstype', 'equalto', 'nfs') | map(attribute='mount') | list | default([]) }}" + tags: + - always + - name: "PRELIM | Gather mount information" ansible.builtin.setup: gather_subset: hardware,!all,!min @@ -203,7 +330,7 @@ tags: - always -- name: "PRELIM | ensure cronie is available" +- name: "PRELIM | Ensure cronie is available" ansible.builtin.package: name: cronie state: present @@ -211,8 +338,7 @@ ansible_python_interpreter: "{{ python2_bin }}" when: - rhel_07_020030 or - rhel_07_020040 or - false + rhel_07_020040 tags: - cat2 - medium @@ -234,21 +360,9 @@ rhel_07_020670 or rhel_07_020680 or rhel_07_020690 or - rhel_07_020700 or - false + rhel_07_020700 tags: - - cat2 - - medium - - RHEL-07-020600 - - RHEL-07-020620 - - RHEL-07-020630 - - RHEL-07-020640 - - RHEL-07-020650 - - RHEL-07-020660 - - RHEL-07-020670 - - RHEL-07-020680 - - RHEL-07-020690 - - RHEL-07-020700 + - always # NOTE: You will need to adjust the UID range in parenthases below. # ALSO NOTE: We weed out any user with a home dir not in standard locations because interactive users shouldn't have those paths as a home dir. Add or removed directory paths as needed below. @@ -410,49 +524,6 @@ when: - rhel7stig_ssh_required -- name: "PRELIM | Check whether machine is UEFI-based" - ansible.builtin.stat: - path: /sys/firmware/efi - register: rhel7_efi_boot - tags: - - goss_template - - always - -- name: set bootloader type - block: - - name: "PRELIM | set fact if UEFI boot | RHEL or OEL" - ansible.builtin.set_fact: - rhel7stig_bootloader_path: "{{ rhel7stig_efi_boot_path }}redhat" - rhel7stig_not_boot_path: "{{ rhel7stig_legacy_boot_path }}" - rhel7stig_legacy_boot: false - when: - - rhel7_efi_boot.stat.exists - - ansible_distribution != 'CentOS' # Note: rhel & OEL both use redhat path - - - name: "PRELIM | set fact if UEFI boot | CentOS " - ansible.builtin.set_fact: - rhel7stig_bootloader_path: "{{ rhel7stig_efi_boot_path }}centos" - rhel7stig_not_boot_path: "{{ rhel7stig_legacy_boot_path }}" - rhel7stig_legacy_boot: false - when: - - rhel7_efi_boot.stat.exists - - ansible_distribution == 'CentOS' - - - name: "PRELIM | set if not UEFI boot" - ansible.builtin.set_fact: - rhel7stig_bootloader_path: "{{ rhel7stig_legacy_boot_path }}" - rhel7stig_not_boot_path: "{{ rhel7stig_efi_boot_path }}" - rhel7stig_legacy_boot: true - when: not rhel7_efi_boot.stat.exists - - - name: PRELIM | output bootloader and efi state - ansible.builtin.debug: - msg: - - "bootloader path set to {{ rhel7stig_bootloader_path }}" - - "legacy boot equals {{ rhel7stig_legacy_boot }}" - tags: - - always - - name: "PRELIM | Gather interactive user ID min" block: - name: "PRELIM | Gather interactive user ID min" @@ -474,3 +545,9 @@ tags: - always - auditd + +- name: Gather the package facts + ansible.builtin.package_facts: + manager: auto + tags: + - always diff --git a/templates/ansible_vars_goss.yml.j2 b/templates/ansible_vars_goss.yml.j2 index 8e562654..199dac24 100644 --- a/templates/ansible_vars_goss.yml.j2 +++ b/templates/ansible_vars_goss.yml.j2 @@ -164,7 +164,6 @@ RHEL_07_030201: {{ rhel_07_030201 }} RHEL_07_030210: {{ rhel_07_030210 }} RHEL_07_030211: {{ rhel_07_030211 }} # if you set 030300 to 'true' ensure you define rhel7stig_audisp_remote_server -RHEL_07_010375: {{ rhel_07_010375 }} RHEL_07_030300: {{ rhel_07_030300 }} RHEL_07_030310: {{ rhel_07_030310 }} RHEL_07_030320: {{ rhel_07_030320 }} diff --git a/templates/etc/yum.repos.d/CentOS-Base.repo.j2 b/templates/etc/yum.repos.d/CentOS-Base.repo.j2 new file mode 100644 index 00000000..f2a66f9b --- /dev/null +++ b/templates/etc/yum.repos.d/CentOS-Base.repo.j2 @@ -0,0 +1,34 @@ +# Note the BaseUrl Changes +## This is due to CentOS being End Of Life +# This will now use the legacy archived path +# Original paths +# mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=os&infra=$infra +# #baseurl=http://mirror.centos.org/centos/$releasever/os/$basearch/ + +[base] +name=CentOS-$releasever - Base +baseurl=https://vault.centos.org/7.9.2009/os/$basearch +gpgcheck=1 +gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7 + +#released updates +[updates] +name=CentOS-$releasever - Updates +baseurl=https://vault.centos.org/7.9.2009/updates/$basearch +gpgcheck=1 +gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7 + +#additional packages that may be useful +[extras] +name=CentOS-$releasever - Extras +baseurl=https://vault.centos.org/7.9.2009/extras/$basearch +gpgcheck=1 +gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7 + +#additional packages that extend functionality of existing packages +[centosplus] +name=CentOS-$releasever - Plus +baseurl=https://vault.centos.org/7.9.2009/centosplus/$basearch +gpgcheck=1 +enabled=0 +gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7 diff --git a/vars/audit.yml b/vars/audit.yml new file mode 100644 index 00000000..7a2e9ec8 --- /dev/null +++ b/vars/audit.yml @@ -0,0 +1,41 @@ +--- + +#### Audit Configuration Settings #### + +# Timeout for those cmds that take longer to run where timeout set +audit_cmd_timeout: 120000 + +# 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 audit configuration will be stored - NOTE benchmark-audit is expected +audit_conf_dir: "{{ audit_conf_dest | default('/opt') }}/{{ benchmark }}-Audit" + +# If changed these can affect other products +pre_audit_outfile: "{{ audit_log_dir }}/{{ ansible_facts.hostname }}-{{ benchmark }}-{{ benchmark_version }}_pre_scan_{{ ansible_facts.date_time.epoch }}.{{ audit_format }}" +post_audit_outfile: "{{ audit_log_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.8 + AMD64_checksum: 'sha256:85d00b7bba5f175bec95de7dfe1f71f8f25204914aad4c6f03c8457868eb6e2f' + ARM64_checksum: 'sha256:bca8c898bfd35b94c51455ece6193c95e2cd7b2b183ac2047b2d76291e73e47d' +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{% if not audit_only %} pre remediation{% endif %} audit results are: {{ pre_audit_results }} + {% if not audit_only %}The post remediation audit results are: {{ post_audit_results }}{% endif %} + + Full breakdown can be found in {{ audit_log_dir }} diff --git a/vars/main.yml b/vars/main.yml index dbe06ca9..00654713 100644 --- a/vars/main.yml +++ b/vars/main.yml @@ -1,6 +1,8 @@ --- rhel7stig_min_ansible_version: 2.10.1 +is_container: false + rhel7stig_dconf_available: "{{ rhel7stig_gui or rhel7stig_dconf_audit.rc == 0 or rhel7stig_always_configure_dconf }}" rhel7stig_has_dconf_command: "{{ rhel7stig_gui or rhel7stig_dconf_audit.rc == 0 }}" @@ -41,3 +43,8 @@ rhel7stig_re_qp_key_end: (?:" *) # insert the parameter at the beginning or append to the end, default append rhel7stig_re_qp_insert: "{{ insert | default(not (append | default(true))) }}" + +rhel7stig_gui_pkgs: + - xorg-x11-server-common + - '@^gnome-desktop' + - 'gnome*'