├── .github ├── CODEOWNERS ├── ISSUE_TEMPLATE │ ├── depracated.md │ ├── feature_request.md │ └── issue_template.md ├── pull_request_template.md └── workflows │ ├── test-coverage.yml │ └── test-policies.yml ├── .gitignore ├── .mergify.yml ├── .pre-commit-config.yaml ├── LICENSE.txt ├── README.md ├── RULES.md ├── bundle └── compliance │ ├── cis_aws │ ├── data_adapter.rego │ ├── rules │ │ ├── cis_1_10 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_1_11 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_1_12 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_1_13 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_1_14 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_1_15 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_1_16 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_1_17 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_1_19 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_1_20 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_1_4 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_1_5 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_1_6 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_1_7 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_1_8 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_1_9 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_2_1_1 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_2_1_2 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_2_1_3 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_2_1_5 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_2_2_1 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_2_3_1 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_2_3_2 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_2_3_3 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_3_1 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_3_10 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_3_11 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_3_2 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_3_3 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_3_4 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_3_5 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_3_6 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_3_7 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_3_8 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_3_9 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_4_1 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_4_10 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_4_11 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_4_12 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_4_13 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_4_14 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_4_15 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_4_16 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_4_2 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_4_3 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_4_4 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_4_5 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_4_6 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_4_7 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_4_8 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_4_9 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_5_1 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_5_2 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_5_3 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ └── cis_5_4 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ └── test_data.rego │ ├── cis_azure │ ├── data_adapter.rego │ ├── rules │ │ ├── cis_3_1 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_3_10 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_3_15 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_3_2 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_3_7 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_3_8 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_3_9 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_4_1_2 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_4_1_4 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_4_3_1 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_4_4_1 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_4_5_1 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_5_2_1 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_5_2_10 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_5_2_2 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_5_2_3 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_5_2_4 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_5_2_5 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_5_2_6 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_5_2_7 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_5_2_8 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_5_2_9 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_5_5 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_6_5 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_6_6 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_7_1 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_7_2 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_7_3 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_7_4 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_8_5 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ └── cis_9_4 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ └── test_data.rego │ ├── cis_eks │ ├── data_adapter.rego │ ├── rules │ │ ├── cis_2_1_1 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_3_1_1 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_3_1_2 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_3_1_3 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_3_1_4 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_3_2_1 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_3_2_10 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_3_2_11 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_3_2_2 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_3_2_3 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_3_2_4 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_3_2_5 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_3_2_6 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_3_2_7 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_3_2_8 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_3_2_9 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_4_2_1 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_4_2_2 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_4_2_3 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_4_2_4 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_4_2_5 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_4_2_6 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_4_2_7 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_4_2_8 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_4_2_9 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_5_1_1 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_5_3_1 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_5_4_1 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_5_4_2 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_5_4_3 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ └── cis_5_4_5 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ └── test_data.rego │ ├── cis_gcp │ ├── data_adapter.rego │ ├── rules │ │ ├── cis_1_10 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_1_11 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_1_12 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_1_14 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_1_15 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_1_17 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_1_4 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_1_5 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_1_6 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_1_7 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_1_8 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_1_9 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_2_1 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_2_10 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_2_11 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_2_12 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_2_13 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_2_16 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_2_2 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_2_3 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_2_4 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_2_5 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_2_6 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_2_7 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_2_8 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_2_9 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_3_1 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_3_2 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_3_3 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_3_4 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_3_5 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_3_6 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_3_7 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_3_8 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_4_1 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_4_11 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_4_2 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_4_3 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_4_4 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_4_5 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_4_6 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_4_7 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_4_8 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_4_9 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_5_1 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_5_2 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_6_1_2 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_6_1_3 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_6_2_1 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_6_2_2 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_6_2_3 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_6_2_4 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_6_2_5 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_6_2_6 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_6_2_7 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_6_2_8 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_6_2_9 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_6_3_1 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_6_3_2 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_6_3_3 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_6_3_4 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_6_3_5 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_6_3_6 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_6_3_7 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_6_4 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_6_5 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_6_6 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_6_7 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_7_1 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_7_2 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ └── cis_7_3 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ └── test_data.rego │ ├── cis_k8s │ ├── data_adapter.rego │ ├── rules │ │ ├── cis_1_1_1 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_1_1_11 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_1_1_12 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_1_1_13 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_1_1_14 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_1_1_15 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_1_1_16 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_1_1_17 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_1_1_18 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_1_1_19 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_1_1_2 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_1_1_20 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_1_1_21 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_1_1_3 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_1_1_4 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_1_1_5 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_1_1_6 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_1_1_7 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_1_1_8 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_1_2_10 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_1_2_11 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_1_2_12 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_1_2_13 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_1_2_14 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_1_2_15 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_1_2_16 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_1_2_17 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_1_2_18 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_1_2_19 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_1_2_2 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_1_2_20 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_1_2_21 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_1_2_22 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_1_2_23 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_1_2_24 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_1_2_25 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_1_2_26 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_1_2_27 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_1_2_28 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_1_2_29 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_1_2_32 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_1_2_4 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_1_2_5 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_1_2_6 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_1_2_7 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_1_2_8 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_1_2_9 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_1_3_2 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_1_3_3 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_1_3_4 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_1_3_5 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_1_3_6 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_1_3_7 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_1_4_1 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_1_4_2 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_2_1 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_2_2 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_2_3 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_2_4 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_2_5 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_2_6 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_4_1_1 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_4_1_10 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_4_1_2 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_4_1_5 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_4_1_6 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_4_1_9 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_4_2_1 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_4_2_10 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_4_2_11 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_4_2_12 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_4_2_13 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_4_2_2 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_4_2_3 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_4_2_4 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_4_2_5 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_4_2_6 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_4_2_7 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_4_2_8 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_4_2_9 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_5_1_3 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_5_1_5 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_5_1_6 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_5_2_10 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_5_2_2 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_5_2_3 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_5_2_4 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_5_2_5 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_5_2_6 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_5_2_7 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ ├── cis_5_2_8 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ │ └── cis_5_2_9 │ │ │ ├── data.yaml │ │ │ ├── rule.rego │ │ │ └── test.rego │ └── schemas │ │ └── input_schema.json │ ├── kubernetes_common │ └── test_data.rego │ ├── lib │ ├── assert.rego │ ├── common │ │ ├── common.rego │ │ └── test.rego │ ├── output_validations │ │ ├── output_validations.rego │ │ └── test.rego │ └── test.rego │ ├── main.rego │ └── policy │ ├── aws_cloudtrail │ ├── data_adapter.rego │ ├── ensure_cloudwatch_integration.rego │ ├── esure_no_public_accessibility.rego │ ├── pattern.rego │ ├── pattern_test.rego │ ├── trail.rego │ └── verify_s3_object_logging.rego │ ├── aws_config │ ├── data_adapter.rego │ └── ensure_config_enabled.rego │ ├── aws_ec2 │ ├── data_adapter.rego │ ├── ensure_default_security_group_restricted.rego │ ├── ensure_public_ingress.rego │ ├── ensure_security_group_public_ingress_ipv4.rego │ ├── ensure_security_group_public_ingress_ipv6.rego │ ├── ports.rego │ └── ports_test.rego │ ├── aws_ecr │ ├── data_adapter.rego │ └── ensure_image_scan.rego │ ├── aws_eks │ ├── data_adapter.rego │ ├── ensure_encryption.rego │ ├── ensure_logs_enabled.rego │ └── ensure_private_access.rego │ ├── aws_elb │ ├── data_adapter.rego │ └── ensure_certificates.rego │ ├── aws_iam │ ├── common.rego │ ├── data_adapter.rego │ ├── ensure_access_keys_use.rego │ ├── ensure_enabled_mfa.rego │ ├── ensure_hardware_mfa.rego │ ├── validate_credentials.rego │ ├── verify_keys_rotation.rego │ └── verify_user_usage.rego │ ├── aws_kms │ ├── data_adapter.rego │ └── ensure_symmetric_key_rotation_enabled.rego │ ├── aws_rds │ ├── data_adapter.rego │ └── ensure_no_public_access.rego │ ├── aws_s3 │ ├── data_adapter.rego │ ├── ensure_block_public_access.rego │ ├── ensure_bucket_policy_deny_http.rego │ ├── ensure_encryption_at_rest.rego │ └── ensure_mfa_delete_enabled.rego │ ├── aws_securityhub │ └── data_adapter.rego │ ├── azure │ ├── activity_log_alert │ │ └── activity_log_alert_operation_enabled.rego │ ├── common.rego │ ├── data_adapter.rego │ ├── disk │ │ └── ensure_encryption.rego │ └── storage_account │ │ ├── ensure_connection.rego │ │ ├── ensure_default_network_access.rego │ │ ├── ensure_encryption.rego │ │ ├── ensure_public_access.rego │ │ ├── ensure_secure_transfer.rego │ │ ├── ensure_service.rego │ │ └── ensure_tls_version.rego │ ├── file │ ├── common.rego │ ├── common_test.rego │ ├── data_adapter.rego │ ├── ensure_ownership.rego │ └── ensure_permissions.rego │ ├── gcp │ ├── bq │ │ └── ensure_cmek_is_used.rego │ ├── common.rego │ ├── compute │ │ ├── assess_instance_metadata.rego │ │ ├── ensure_fw_rule.rego │ │ └── ensure_no_use_of_default_sa.rego │ ├── data_adapter.rego │ ├── dns │ │ └── ensure_rsasha1_is_unused.rego │ ├── iam │ │ ├── ensure_admin_without_multiple_roles.rego │ │ ├── ensure_no_public_access.rego │ │ ├── ensure_policy_not_managed_by_user.rego │ │ ├── ensure_role_not_service_account_user.rego │ │ └── ensure_user_not_editor_or_owner.rego │ ├── kms │ │ └── ensure_key_rotation.rego │ ├── monitoring │ │ └── ensure_log_metric_and_alarm_exist.rego │ └── sql │ │ ├── ensure_db_flag_is_as_expected.rego │ │ └── ensure_private_ip.rego │ ├── kube_api │ ├── data_adapter.rego │ ├── ensure_external_ip.rego │ ├── ensure_service_accounts.rego │ ├── minimize_added_capabilities.rego │ ├── minimize_admission.rego │ ├── minimize_admission_root.rego │ ├── minimize_assigned_capabilities.rego │ ├── minimize_certain_capability.rego │ ├── minimize_sharing.rego │ └── minimize_wildcard.rego │ └── process │ ├── common.rego │ ├── common_test.rego │ ├── data_adapter.rego │ ├── data_adapter_test.rego │ ├── ensure_appropriate_arguments.rego │ ├── ensure_arguments_and_config.rego │ ├── ensure_arguments_contain_key.rego │ ├── ensure_arguments_contain_key_value.rego │ ├── ensure_arguments_contain_value.rego │ ├── ensure_arguments_goe.rego │ ├── ensure_arguments_if_contain_equal.rego │ ├── ensure_arguments_lte.rego │ ├── ensure_arguments_not_contain_multiple_values.rego │ ├── ensure_arguments_not_contain_value_appropriate.rego │ └── ensure_ciphers.rego ├── dev ├── README.md ├── common.py ├── generate_rule_metadata.py ├── generate_rule_templates.py ├── input │ ├── CIS_Amazon_Elastic_Kubernetes_Service_(EKS)_Benchmark_v1.0.1.xlsx │ ├── CIS_Amazon_Web_Services_Foundations_Benchmark_v1.5.0.xlsx │ ├── CIS_Google_Cloud_Platform_Foundation_Benchmark_v2.0.0.xlsx │ ├── CIS_Kubernetes_V1.23_Benchmark_v1.0.1.xlsx │ └── CIS_Microsoft_Azure_Foundations_Benchmark_v2.0.0.xlsx └── update_rule_status.py ├── poetry.lock ├── pyproject.toml └── server └── host.go /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @elastic/cloudbeat 2 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/depracated.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: DO NOT OPEN NEW ISSUES HERE 3 | about: Use cloudbeat repo instead 4 | title: 5 | labels: ["Team:Cloud Security"] 6 | assignees: '' 7 | --- 8 | 9 | Go to https://github.com/elastic/cloudbeat/issues/new/choose 10 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: 5 | labels: "Team:Cloud Security" 6 | assignees: '' 7 | --- 8 | 9 | ### Is your feature request related to a problem? Please describe 10 | 11 | A clear and concise description of what the issue is. 12 | 13 | ### Describe the solution you'd like 14 | 15 | A clear and concise description of what you want to happen. 16 | 17 | ### Describe alternatives you've considered 18 | 19 | A clear and concise description of any alternative solutions or features you've considered. 20 | 21 | ### Additional context 22 | 23 | Add any other context or screenshots about the feature request here. 24 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/issue_template.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Cloudbeat Task 3 | about: Create an issue for the Cloudbeat team 4 | title: 5 | labels: "Team:Cloud Security" 6 | assignees: '' 7 | --- 8 | 9 | ### Motivation 10 | 11 | Why are we doing this task? what is the value to the user? 12 | 13 | ### Definition of done 14 | 15 | What needs to be completed at the end of this task 16 | 17 | - [ ] Task 1 18 | - [ ] Task 2 19 | 20 | ### Out of scope 21 | 22 | What should not be included in this task 23 | 24 | ### Related tasks/epics 25 | 26 | Reference related issues and epics 27 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /output.json 2 | /input.json 3 | /data.yaml 4 | /bundle.tar.gz 5 | tmpBundles/ 6 | dev/__pycache__/ 7 | .idea 8 | -------------------------------------------------------------------------------- /bundle/compliance/cis_aws/data_adapter.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_aws.data_adapter 2 | -------------------------------------------------------------------------------- /bundle/compliance/cis_aws/rules/cis_1_10/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_aws.rules.cis_1_10 2 | 3 | import data.compliance.lib.common 4 | import data.compliance.policy.aws_iam.data_adapter 5 | import data.compliance.policy.aws_iam.ensure_enabled_mfa as audit 6 | 7 | # Ensure multi-factor authentication (MFA) is enabled for all IAM users that have a console password. 8 | finding = result { 9 | # filter 10 | data_adapter.is_iam_user 11 | 12 | # set result 13 | result := common.generate_result_without_expected( 14 | common.calculate_result(audit.ensure_mfa_device), 15 | {"IAM User:": data_adapter.iam_user}, 16 | ) 17 | } 18 | -------------------------------------------------------------------------------- /bundle/compliance/cis_aws/rules/cis_1_11/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_aws.rules.cis_1_11 2 | 3 | import data.compliance.lib.common 4 | import data.compliance.policy.aws_iam.data_adapter 5 | import data.compliance.policy.aws_iam.ensure_access_keys_use as audit 6 | 7 | # Do not setup access keys during initial user setup for all IAM users that have a console password. 8 | finding = result { 9 | # filter 10 | data_adapter.is_iam_user 11 | 12 | # set result 13 | result := common.generate_result_without_expected( 14 | common.calculate_result(audit.ensure_access_keys_use), 15 | {"IAM User:": data_adapter.iam_user}, 16 | ) 17 | } 18 | -------------------------------------------------------------------------------- /bundle/compliance/cis_aws/rules/cis_1_12/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_aws.rules.cis_1_12 2 | 3 | import data.compliance.lib.common 4 | import data.compliance.policy.aws_iam.data_adapter 5 | import data.compliance.policy.aws_iam.validate_credentials as audit 6 | 7 | # Ensure credentials unused for 45 days or greater are disabled 8 | finding = result { 9 | # filter 10 | data_adapter.is_iam_user 11 | 12 | # set result 13 | result := common.generate_result_without_expected( 14 | common.calculate_result(audit.validate_credentials), 15 | {"IAM User:": data_adapter.iam_user}, 16 | ) 17 | } 18 | -------------------------------------------------------------------------------- /bundle/compliance/cis_aws/rules/cis_1_13/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_aws.rules.cis_1_13 2 | 3 | import data.compliance.lib.common 4 | import data.compliance.policy.aws_iam.data_adapter 5 | 6 | # Ensure that there is only a single active access key per user. 7 | finding = result { 8 | # filter 9 | data_adapter.is_iam_user 10 | 11 | # set result 12 | result := common.generate_result_without_expected( 13 | common.calculate_result(count(data_adapter.active_access_keys) < 2), 14 | {"IAM User:": data_adapter.iam_user}, 15 | ) 16 | } 17 | -------------------------------------------------------------------------------- /bundle/compliance/cis_aws/rules/cis_1_14/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_aws.rules.cis_1_14 2 | 3 | import data.compliance.lib.common 4 | import data.compliance.policy.aws_iam.data_adapter 5 | import data.compliance.policy.aws_iam.verify_keys_rotation as audit 6 | 7 | # Ensure access keys are rotated every 90 days or less 8 | finding = result { 9 | # filter 10 | data_adapter.is_iam_user 11 | 12 | # set result 13 | result := common.generate_result_without_expected( 14 | common.calculate_result(audit.verify_rotation), 15 | {"IAM User:": data_adapter.iam_user}, 16 | ) 17 | } 18 | -------------------------------------------------------------------------------- /bundle/compliance/cis_aws/rules/cis_1_15/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_aws.rules.cis_1_15 2 | 3 | import data.compliance.lib.common 4 | import data.compliance.policy.aws_iam.data_adapter 5 | 6 | # Ensure IAM Users Receive Permissions Only Through Groups 7 | finding = result { 8 | # filter 9 | data_adapter.is_iam_user 10 | 11 | # set result 12 | user := data_adapter.iam_user 13 | result := common.generate_result_without_expected( 14 | common.calculate_result((count(user.attached_policies) + count(user.inline_policies)) == 0), 15 | {"IAM User:": user}, 16 | ) 17 | } 18 | -------------------------------------------------------------------------------- /bundle/compliance/cis_aws/rules/cis_1_17/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_aws.rules.cis_1_17 2 | 3 | import data.compliance.lib.common 4 | import data.compliance.policy.aws_iam.data_adapter 5 | import future.keywords.if 6 | import future.keywords.in 7 | 8 | # Ensure a support role has been created to manage incidents with AWS Support 9 | finding = result if { 10 | # filter 11 | data_adapter.is_aws_support_access 12 | 13 | # set result 14 | result := common.generate_result_without_expected( 15 | common.calculate_result(aws_support_has_attached_roles), 16 | input.resource, 17 | ) 18 | } 19 | 20 | aws_support_has_attached_roles if { 21 | # Implicitly check that the "roles" array exists and it's not empty. Check that the RoleId is not an empty string as 22 | # a sanity test. 23 | some role in data_adapter.roles 24 | role.RoleId != "" 25 | } else = false 26 | -------------------------------------------------------------------------------- /bundle/compliance/cis_aws/rules/cis_1_19/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_aws.rules.cis_1_19 2 | 3 | import data.compliance.lib.common 4 | import data.compliance.policy.aws_iam.data_adapter 5 | import future.keywords.every 6 | 7 | default rule_evaluation = false 8 | 9 | finding = result { 10 | data_adapter.is_server_certificate 11 | 12 | result := common.generate_result_without_expected( 13 | common.calculate_result(rule_evaluation), 14 | {"certificates": data_adapter.server_certificates}, 15 | ) 16 | } 17 | 18 | is_expired(date) { 19 | then := time.parse_rfc3339_ns(date) 20 | now := time.now_ns() 21 | then < now 22 | } 23 | 24 | rule_evaluation { 25 | every certificate in data_adapter.server_certificates { 26 | not is_expired(certificate.Expiration) 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /bundle/compliance/cis_aws/rules/cis_1_20/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_aws.rules.cis_1_20 2 | 3 | import data.compliance.lib.common 4 | import data.compliance.policy.aws_iam.data_adapter 5 | import future.keywords.every 6 | import future.keywords.if 7 | import future.keywords.in 8 | 9 | # Ensure that IAM Access analyzer is enabled for all regions 10 | finding = result if { 11 | # filter 12 | data_adapter.is_access_analyzers 13 | 14 | # set result 15 | result := common.generate_result_without_expected( 16 | common.calculate_result(analyzer_exists), 17 | {"Access Analyzers": input.resource}, 18 | ) 19 | } 20 | 21 | analyzer_exists if { 22 | every region in data_adapter.analyzer_regions { 23 | some analyzer in data_adapter.analyzers 24 | analyzer.Region == region 25 | analyzer.Status == "ACTIVE" 26 | } 27 | } else = false 28 | -------------------------------------------------------------------------------- /bundle/compliance/cis_aws/rules/cis_1_4/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_aws.rules.cis_1_4 2 | 3 | import data.compliance.lib.common 4 | import data.compliance.policy.aws_iam.data_adapter 5 | 6 | # Ensure no 'root' user account access key exists. 7 | finding = result { 8 | # filter 9 | data_adapter.is_root_user 10 | 11 | # set result 12 | result := common.generate_result_without_expected( 13 | common.calculate_result(count(data_adapter.active_access_keys) == 0), 14 | {"IAM User:": data_adapter.iam_user}, 15 | ) 16 | } 17 | -------------------------------------------------------------------------------- /bundle/compliance/cis_aws/rules/cis_1_5/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_aws.rules.cis_1_5 2 | 3 | import data.compliance.lib.common 4 | import data.compliance.policy.aws_iam.data_adapter 5 | 6 | # Ensure MFA is enabled for the 'root' user account. 7 | finding = result { 8 | # filter 9 | data_adapter.is_root_user 10 | 11 | # set result 12 | result := common.generate_result_without_expected( 13 | common.calculate_result(data_adapter.iam_user.mfa_active), 14 | {"IAM User:": data_adapter.iam_user}, 15 | ) 16 | } 17 | -------------------------------------------------------------------------------- /bundle/compliance/cis_aws/rules/cis_1_6/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_aws.rules.cis_1_6 2 | 3 | import data.compliance.lib.common 4 | import data.compliance.policy.aws_iam.data_adapter 5 | import data.compliance.policy.aws_iam.ensure_hardware_mfa as audit 6 | 7 | # Ensure hardware MFA is enabled for the 'root' user account. 8 | finding = result { 9 | # filter 10 | data_adapter.is_root_user 11 | 12 | # set result 13 | result := common.generate_result_without_expected( 14 | common.calculate_result(audit.ensure_hardware_mfa_device), 15 | {"IAM User:": data_adapter.iam_user}, 16 | ) 17 | } 18 | -------------------------------------------------------------------------------- /bundle/compliance/cis_aws/rules/cis_1_7/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_aws.rules.cis_1_7 2 | 3 | import data.compliance.lib.common 4 | import data.compliance.policy.aws_iam.data_adapter 5 | import data.compliance.policy.aws_iam.verify_user_usage as audit 6 | 7 | # Eliminate use of the 'root' user for administrative and daily tasks 8 | # daily interpret as a day (24h) 9 | finding = result { 10 | # filter 11 | data_adapter.is_root_user 12 | 13 | # set result 14 | result := common.generate_result_without_expected( 15 | common.calculate_result(audit.verify_user_usage), 16 | {"IAM User:": data_adapter.iam_user}, 17 | ) 18 | } 19 | -------------------------------------------------------------------------------- /bundle/compliance/cis_aws/rules/cis_1_8/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_aws.rules.cis_1_8 2 | 3 | import data.compliance.lib.common 4 | import data.compliance.policy.aws_iam.data_adapter 5 | 6 | default rule_evaluation = false 7 | 8 | finding = result { 9 | # filter 10 | data_adapter.is_pwd_policy 11 | 12 | # set result 13 | result := common.generate_result_without_expected( 14 | common.calculate_result(rule_evaluation), 15 | {"Password Policy:": data_adapter.pwd_policy}, 16 | ) 17 | } 18 | 19 | rule_evaluation { 20 | # verify password length is equal or above 14 21 | common.greater_or_equal(data_adapter.pwd_policy.minimum_length, 14) 22 | } 23 | -------------------------------------------------------------------------------- /bundle/compliance/cis_aws/rules/cis_1_9/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_aws.rules.cis_1_9 2 | 3 | import data.compliance.lib.common 4 | import data.compliance.policy.aws_iam.data_adapter 5 | 6 | default rule_evaluation = false 7 | 8 | # Ensure that the number of previous passwords that IAM users are prevented from reusing is 24. 9 | finding = result { 10 | # filter 11 | data_adapter.is_pwd_policy 12 | 13 | # set result 14 | result := common.generate_result_without_expected( 15 | common.calculate_result(data_adapter.pwd_policy.reuse_prevention_count == 24), 16 | {"Password Policy:": data_adapter.pwd_policy}, 17 | ) 18 | } 19 | -------------------------------------------------------------------------------- /bundle/compliance/cis_aws/rules/cis_2_1_1/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_aws.rules.cis_2_1_1 2 | 3 | import data.compliance.policy.aws_s3.ensure_encryption_at_rest as audit 4 | 5 | finding = audit.finding 6 | -------------------------------------------------------------------------------- /bundle/compliance/cis_aws/rules/cis_2_1_2/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_aws.rules.cis_2_1_2 2 | 3 | import data.compliance.policy.aws_s3.ensure_bucket_policy_deny_http as audit 4 | 5 | finding = audit.finding 6 | -------------------------------------------------------------------------------- /bundle/compliance/cis_aws/rules/cis_2_1_3/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_aws.rules.cis_2_1_3 2 | 3 | import data.compliance.policy.aws_s3.ensure_mfa_delete_enabled as audit 4 | 5 | finding = audit.finding 6 | -------------------------------------------------------------------------------- /bundle/compliance/cis_aws/rules/cis_2_1_5/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_aws.rules.cis_2_1_5 2 | 3 | import data.compliance.policy.aws_s3.ensure_block_public_access as audit 4 | 5 | finding = audit.finding 6 | -------------------------------------------------------------------------------- /bundle/compliance/cis_aws/rules/cis_2_2_1/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_aws.rules.cis_2_2_1 2 | 3 | import data.compliance.lib.common 4 | import data.compliance.policy.aws_ec2.data_adapter 5 | 6 | default rule_evaluation = false 7 | 8 | # Ensure EBS Volume Encryption is Enabled in all Regions 9 | finding = result { 10 | # filter 11 | data_adapter.is_ebs_policy 12 | 13 | # set result 14 | result := common.generate_result_without_expected( 15 | common.calculate_result(rule_evaluation), 16 | input.resource, 17 | ) 18 | } 19 | 20 | rule_evaluation { 21 | input.resource.enabled == true 22 | } 23 | -------------------------------------------------------------------------------- /bundle/compliance/cis_aws/rules/cis_2_3_1/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_aws.rules.cis_2_3_1 2 | 3 | import data.compliance.lib.common as lib_common 4 | import data.compliance.policy.aws_rds.data_adapter 5 | 6 | finding = result { 7 | data_adapter.is_rds 8 | 9 | result := lib_common.generate_result_without_expected( 10 | lib_common.calculate_result(data_adapter.storage_encrypted == true), 11 | {"StorageEncrypted": data_adapter.storage_encrypted}, 12 | ) 13 | } 14 | -------------------------------------------------------------------------------- /bundle/compliance/cis_aws/rules/cis_2_3_1/test.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_aws.rules.cis_2_3_1 2 | 3 | import data.cis_aws.test_data 4 | import data.compliance.cis_aws.data_adapter 5 | import data.lib.test 6 | 7 | test_violation { 8 | eval_fail with input as rule_input(false) 9 | } 10 | 11 | test_pass { 12 | eval_pass with input as rule_input(true) 13 | } 14 | 15 | test_not_evaluated { 16 | not_eval with input as test_data.not_evaluated_rds_db_instance 17 | } 18 | 19 | rule_input(encryption_enabled) = test_data.generate_rds_db_instance(encryption_enabled, true, false, []) 20 | 21 | eval_fail { 22 | test.assert_fail(finding) with data.benchmark_data_adapter as data_adapter 23 | } 24 | 25 | eval_pass { 26 | test.assert_pass(finding) with data.benchmark_data_adapter as data_adapter 27 | } 28 | 29 | not_eval { 30 | not finding with data.benchmark_data_adapter as data_adapter 31 | } 32 | -------------------------------------------------------------------------------- /bundle/compliance/cis_aws/rules/cis_2_3_2/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_aws.rules.cis_2_3_2 2 | 3 | import data.compliance.lib.common as lib_common 4 | import data.compliance.policy.aws_rds.data_adapter 5 | 6 | finding = result { 7 | data_adapter.is_rds 8 | 9 | result := lib_common.generate_result_without_expected( 10 | lib_common.calculate_result(data_adapter.auto_minor_version_upgrade == true), 11 | {"AutoMinorVersionUpgrade": data_adapter.auto_minor_version_upgrade}, 12 | ) 13 | } 14 | -------------------------------------------------------------------------------- /bundle/compliance/cis_aws/rules/cis_2_3_3/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_aws.rules.cis_2_3_3 2 | 3 | import data.compliance.policy.aws_rds.ensure_no_public_access as audit 4 | 5 | finding = audit.finding 6 | -------------------------------------------------------------------------------- /bundle/compliance/cis_aws/rules/cis_3_1/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_aws.rules.cis_3_1 2 | 3 | import data.compliance.lib.common 4 | import data.compliance.policy.aws_cloudtrail.data_adapter 5 | import data.compliance.policy.aws_cloudtrail.trail 6 | 7 | default rule_evaluation = false 8 | 9 | finding = result { 10 | # filter 11 | data_adapter.is_multi_trails_type 12 | 13 | # set result 14 | result := common.generate_result_without_expected( 15 | common.calculate_result(rule_evaluation), 16 | input.resource, 17 | ) 18 | } 19 | 20 | rule_evaluation { 21 | some i 22 | t := data_adapter.trail_items[i] 23 | trail.cloudtrail_enabled(t) 24 | } 25 | -------------------------------------------------------------------------------- /bundle/compliance/cis_aws/rules/cis_3_10/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_aws.rules.cis_3_10 2 | 3 | import data.compliance.lib.common 4 | import data.compliance.policy.aws_cloudtrail.data_adapter 5 | import data.compliance.policy.aws_cloudtrail.verify_s3_object_logging as audit 6 | 7 | # Ensure that Object-level logging for write events is enabled for S3 bucket. 8 | finding = result { 9 | # filter 10 | data_adapter.is_single_trail 11 | 12 | # set result 13 | result := common.generate_result_without_expected( 14 | common.calculate_result(rule_evaluation), 15 | input.resource, 16 | ) 17 | } 18 | 19 | rule_evaluation = audit.ensure_s3_object_logging(["All", "WriteOnly"]) 20 | -------------------------------------------------------------------------------- /bundle/compliance/cis_aws/rules/cis_3_11/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_aws.rules.cis_3_11 2 | 3 | import data.compliance.lib.common 4 | import data.compliance.policy.aws_cloudtrail.data_adapter 5 | import data.compliance.policy.aws_cloudtrail.verify_s3_object_logging as audit 6 | 7 | # Ensure that Object-level logging for read events is enabled for S3 bucket. 8 | finding = result { 9 | # filter 10 | data_adapter.is_single_trail 11 | 12 | # set result 13 | result := common.generate_result_without_expected( 14 | common.calculate_result(rule_eveluation), 15 | input.resource, 16 | ) 17 | } 18 | 19 | rule_eveluation = audit.ensure_s3_object_logging(["All", "ReadOnly"]) 20 | -------------------------------------------------------------------------------- /bundle/compliance/cis_aws/rules/cis_3_2/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_aws.rules.cis_3_2 2 | 3 | import data.compliance.lib.common 4 | import data.compliance.policy.aws_cloudtrail.data_adapter 5 | 6 | # Ensure CloudTrail log file validation is enabled. 7 | finding = result { 8 | # filter 9 | data_adapter.is_single_trail 10 | 11 | # set result 12 | result := common.generate_result_without_expected( 13 | common.calculate_result(data_adapter.trail.LogFileValidationEnabled), 14 | input.resource, 15 | ) 16 | } 17 | -------------------------------------------------------------------------------- /bundle/compliance/cis_aws/rules/cis_3_3/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_aws.rules.cis_3_3 2 | 3 | import data.compliance.lib.common 4 | import data.compliance.policy.aws_cloudtrail.data_adapter 5 | import data.compliance.policy.aws_cloudtrail.no_public_bucket_access as audit 6 | 7 | # Ensure the S3 bucket used to store CloudTrail logs is not publicly accessible. 8 | finding = result { 9 | # filter 10 | data_adapter.is_single_trail 11 | 12 | # set result 13 | result := common.generate_result_without_expected( 14 | common.calculate_result(audit.bucket_is_public == false), 15 | input.resource, 16 | ) 17 | } 18 | -------------------------------------------------------------------------------- /bundle/compliance/cis_aws/rules/cis_3_4/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_aws.rules.cis_3_4 2 | 3 | import data.compliance.lib.common 4 | import data.compliance.policy.aws_cloudtrail.data_adapter 5 | import data.compliance.policy.aws_cloudtrail.ensure_cloudwatch as audit 6 | 7 | # Ensure CloudTrail trails are integrated with CloudWatch Logs. 8 | finding = result { 9 | # filter 10 | data_adapter.is_single_trail 11 | 12 | # set result 13 | result := common.generate_result_without_expected( 14 | common.calculate_result(audit.ensure_cloudwatch_logs_enabled), 15 | input.resource, 16 | ) 17 | } 18 | -------------------------------------------------------------------------------- /bundle/compliance/cis_aws/rules/cis_3_5/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_aws.rules.cis_3_5 2 | 3 | import data.compliance.policy.aws_config.ensure_config_enabled as audit 4 | 5 | finding = audit.finding 6 | -------------------------------------------------------------------------------- /bundle/compliance/cis_aws/rules/cis_3_6/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_aws.rules.cis_3_6 2 | 3 | import data.compliance.lib.common 4 | import data.compliance.policy.aws_cloudtrail.data_adapter 5 | 6 | default rule_evaluation = false 7 | 8 | rule_evaluation { 9 | data_adapter.trail_bucket_info.logging.Enabled == true 10 | } 11 | 12 | # Ensure S3 bucket access logging is enabled on the CloudTrail S3 bucket 13 | finding = result { 14 | # filter 15 | data_adapter.is_single_trail 16 | 17 | # set result 18 | result := common.generate_result_without_expected( 19 | common.calculate_result(rule_evaluation), 20 | input.resource, 21 | ) 22 | } 23 | -------------------------------------------------------------------------------- /bundle/compliance/cis_aws/rules/cis_3_7/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_aws.rules.cis_3_7 2 | 3 | import data.compliance.lib.common 4 | import data.compliance.policy.aws_cloudtrail.data_adapter 5 | 6 | default rule_evaluation = false 7 | 8 | # Ensure CloudTrail logs are encrypted at rest using KMS CMKs. 9 | finding = result { 10 | # filter 11 | data_adapter.is_single_trail 12 | 13 | # set result 14 | result := common.generate_result_without_expected( 15 | common.calculate_result(rule_evaluation), 16 | input.resource, 17 | ) 18 | } 19 | 20 | rule_evaluation { 21 | not data_adapter.trail.KmsKeyId == null 22 | not data_adapter.trail.KmsKeyId == "" 23 | } 24 | -------------------------------------------------------------------------------- /bundle/compliance/cis_aws/rules/cis_3_8/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_aws.rules.cis_3_8 2 | 3 | import data.compliance.policy.aws_kms.ensure_symmetric_key_rotation_enabled as audit 4 | 5 | finding = audit.finding 6 | -------------------------------------------------------------------------------- /bundle/compliance/cis_aws/rules/cis_3_9/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_aws.rules.cis_3_9 2 | 3 | import data.compliance.lib.common 4 | import data.compliance.policy.aws_ec2.data_adapter 5 | 6 | default rule_evaluation = false 7 | 8 | # Ensure VPC flow logging is enabled in all VPCs. 9 | finding = result { 10 | # filter 11 | data_adapter.is_vpc_policy 12 | 13 | # set result 14 | result := common.generate_result_without_expected( 15 | common.calculate_result(rule_evaluation), 16 | input.resource, 17 | ) 18 | } 19 | 20 | rule_evaluation { 21 | count(input.resource.flow_logs) > 0 22 | } 23 | -------------------------------------------------------------------------------- /bundle/compliance/cis_aws/rules/cis_4_1/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_aws.rules.cis_4_1 2 | 3 | import data.compliance.lib.common 4 | import data.compliance.policy.aws_cloudtrail.data_adapter 5 | import data.compliance.policy.aws_cloudtrail.trail 6 | 7 | default rule_evaluation = false 8 | 9 | finding = result { 10 | # filter 11 | data_adapter.is_multi_trails_type 12 | 13 | # set result 14 | result := common.generate_result_without_expected( 15 | common.calculate_result(rule_evaluation), 16 | input.resource, 17 | ) 18 | } 19 | 20 | required_pattern = "{ ($.errorCode = \"*UnauthorizedOperation\") || ($.errorCode = \"AccessDenied*\") || ($.sourceIPAddress!=\"delivery.logs.amazonaws.com\") || ($.eventName!=\"HeadBucket\") }" 21 | 22 | rule_evaluation = trail.at_least_one_trail_satisfied([required_pattern]) 23 | -------------------------------------------------------------------------------- /bundle/compliance/cis_aws/rules/cis_4_16/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_aws.rules.cis_4_16 2 | 3 | import data.compliance.lib.common 4 | import data.compliance.policy.aws_securityhub.data_adapter 5 | 6 | default rule_evaluation = false 7 | 8 | finding = result { 9 | # filter 10 | data_adapter.is_securityhub_subType 11 | 12 | # set result 13 | result := common.generate_result_without_expected( 14 | common.calculate_result(rule_evaluation), 15 | input.resource, 16 | ) 17 | } 18 | 19 | rule_evaluation = data_adapter.securityhub_resource.Enabled 20 | -------------------------------------------------------------------------------- /bundle/compliance/cis_aws/rules/cis_4_16/test.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_aws.rules.cis_4_16 2 | 3 | import data.cis_aws.test_data 4 | import data.compliance.cis_aws.data_adapter 5 | import data.lib.test 6 | 7 | test_violation { 8 | # no enalbed field 9 | eval_fail with input as rule_input({}) 10 | eval_fail with input as rule_input({"Enabled": false}) 11 | } 12 | 13 | test_pass { 14 | eval_pass with input as rule_input({"Enabled": true}) 15 | } 16 | 17 | rule_input(entry) = test_data.generate_securityhub(entry) 18 | 19 | eval_fail { 20 | test.assert_fail(finding) with data.benchmark_data_adapter as data_adapter 21 | } 22 | 23 | eval_pass { 24 | test.assert_pass(finding) with data.benchmark_data_adapter as data_adapter 25 | } 26 | -------------------------------------------------------------------------------- /bundle/compliance/cis_aws/rules/cis_4_3/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_aws.rules.cis_4_3 2 | 3 | import data.compliance.lib.common 4 | import data.compliance.policy.aws_cloudtrail.data_adapter 5 | import data.compliance.policy.aws_cloudtrail.trail 6 | 7 | default rule_evaluation = false 8 | 9 | finding = result { 10 | # filter 11 | data_adapter.is_multi_trails_type 12 | 13 | # set result 14 | result := common.generate_result_without_expected( 15 | common.calculate_result(rule_evaluation), 16 | input.resource, 17 | ) 18 | } 19 | 20 | required_patterns = ["{ $.userIdentity.type = \"Root\" && $.userIdentity.invokedBy NOT EXISTS && $.eventType != \"AwsServiceEvent\" }"] 21 | 22 | rule_evaluation = trail.at_least_one_trail_satisfied(required_patterns) 23 | -------------------------------------------------------------------------------- /bundle/compliance/cis_aws/rules/cis_4_5/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_aws.rules.cis_4_5 2 | 3 | import data.compliance.lib.common 4 | import data.compliance.policy.aws_cloudtrail.data_adapter 5 | import data.compliance.policy.aws_cloudtrail.trail 6 | 7 | default rule_evaluation = false 8 | 9 | finding = result { 10 | # filter 11 | data_adapter.is_multi_trails_type 12 | 13 | # set result 14 | result := common.generate_result_without_expected( 15 | common.calculate_result(rule_evaluation), 16 | input.resource, 17 | ) 18 | } 19 | 20 | required_patterns = ["{ ($.eventName = CreateTrail) || ($.eventName = UpdateTrail) || ($.eventName = DeleteTrail) || ($.eventName = StartLogging) || ($.eventName = StopLogging) }"] 21 | 22 | rule_evaluation = trail.at_least_one_trail_satisfied(required_patterns) 23 | -------------------------------------------------------------------------------- /bundle/compliance/cis_aws/rules/cis_4_6/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_aws.rules.cis_4_6 2 | 3 | import data.compliance.lib.common 4 | import data.compliance.policy.aws_cloudtrail.data_adapter 5 | import data.compliance.policy.aws_cloudtrail.trail 6 | 7 | default rule_evaluation = false 8 | 9 | finding = result { 10 | # filter 11 | data_adapter.is_multi_trails_type 12 | 13 | # set result 14 | result := common.generate_result_without_expected( 15 | common.calculate_result(rule_evaluation), 16 | input.resource, 17 | ) 18 | } 19 | 20 | required_patterns = ["{ ($.eventName = ConsoleLogin) && ($.errorMessage = \"Failed authentication\") }"] 21 | 22 | rule_evaluation = trail.at_least_one_trail_satisfied(required_patterns) 23 | -------------------------------------------------------------------------------- /bundle/compliance/cis_aws/rules/cis_4_6/test.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_aws.rules.cis_4_6 2 | 3 | import data.cis_aws.test_data 4 | import data.compliance.cis_aws.data_adapter 5 | import data.lib.test 6 | 7 | test_pass { 8 | eval_pass with input as rule_input([{ 9 | "TrailInfo": { 10 | "Trail": {"IsMultiRegionTrail": true}, 11 | "Status": {"IsLogging": true}, 12 | "EventSelectors": [{"IncludeManagementEvents": true, "ReadWriteType": "All"}], 13 | }, 14 | "MetricFilters": [{"FilterName": "filter_1", "FilterPattern": "{ ($.eventName = ConsoleLogin) && ($.errorMessage = \"Failed authentication\") }"}], 15 | "MetricTopicBinding": {"filter_1": ["arn:aws:...sns"]}, 16 | }]) 17 | } 18 | 19 | rule_input(entry) = test_data.generate_monitoring_resources(entry) 20 | 21 | eval_pass { 22 | test.assert_pass(finding) with data.benchmark_data_adapter as data_adapter 23 | } 24 | -------------------------------------------------------------------------------- /bundle/compliance/cis_aws/rules/cis_4_7/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_aws.rules.cis_4_7 2 | 3 | import data.compliance.lib.common 4 | import data.compliance.policy.aws_cloudtrail.data_adapter 5 | import data.compliance.policy.aws_cloudtrail.trail 6 | 7 | default rule_evaluation = false 8 | 9 | finding = result { 10 | # filter 11 | data_adapter.is_multi_trails_type 12 | 13 | # set result 14 | result := common.generate_result_without_expected( 15 | common.calculate_result(rule_evaluation), 16 | input.resource, 17 | ) 18 | } 19 | 20 | required_patterns = ["{($.eventSource = kms.amazonaws.com) && (($.eventName=DisableKey)||($.eventName=ScheduleKeyDeletion)) }"] 21 | 22 | rule_evaluation = trail.at_least_one_trail_satisfied(required_patterns) 23 | -------------------------------------------------------------------------------- /bundle/compliance/cis_aws/rules/cis_4_9/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_aws.rules.cis_4_9 2 | 3 | import data.compliance.lib.common 4 | import data.compliance.policy.aws_cloudtrail.data_adapter 5 | import data.compliance.policy.aws_cloudtrail.trail 6 | 7 | default rule_evaluation = false 8 | 9 | finding = result { 10 | # filter 11 | data_adapter.is_multi_trails_type 12 | 13 | # set result 14 | result := common.generate_result_without_expected( 15 | common.calculate_result(rule_evaluation), 16 | input.resource, 17 | ) 18 | } 19 | 20 | required_patterns = ["{ ($.eventSource = config.amazonaws.com) && (($.eventName=StopConfigurationRecorder)||($.eventName=DeleteDeliveryChannel) ||($.eventName=PutDeliveryChannel)||($.eventName=PutConfigurationRecorder)) }"] 21 | 22 | rule_evaluation = trail.at_least_one_trail_satisfied(required_patterns) 23 | -------------------------------------------------------------------------------- /bundle/compliance/cis_aws/rules/cis_5_1/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_aws.rules.cis_5_1 2 | 3 | import data.compliance.policy.aws_ec2.ensure_public_ingress as audit 4 | 5 | # Validate that no network acl allow any traffic to remote server admin ports 6 | finding = audit.finding 7 | -------------------------------------------------------------------------------- /bundle/compliance/cis_aws/rules/cis_5_2/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_aws.rules.cis_5_2 2 | 3 | import data.compliance.policy.aws_ec2.ensure_security_group_public_ingress_ipv4 as audit 4 | 5 | finding = audit.finding 6 | -------------------------------------------------------------------------------- /bundle/compliance/cis_aws/rules/cis_5_3/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_aws.rules.cis_5_3 2 | 3 | import data.compliance.policy.aws_ec2.ensure_security_group_public_ingress_ipv6 as audit 4 | 5 | finding = audit.finding 6 | -------------------------------------------------------------------------------- /bundle/compliance/cis_aws/rules/cis_5_4/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_aws.rules.cis_5_4 2 | 3 | import data.compliance.policy.aws_ec2.ensure_default_security_group_restricted as audit 4 | 5 | finding = audit.finding 6 | -------------------------------------------------------------------------------- /bundle/compliance/cis_azure/data_adapter.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_azure.data_adapter 2 | -------------------------------------------------------------------------------- /bundle/compliance/cis_azure/rules/cis_3_1/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_azure.rules.cis_3_1 2 | 3 | import data.compliance.lib.common 4 | import data.compliance.policy.azure.data_adapter 5 | import data.compliance.policy.azure.storage_account.ensure_secure_transfer as audit 6 | 7 | finding = result { 8 | # filter 9 | data_adapter.is_storage_account 10 | 11 | # set result 12 | result := common.generate_result_without_expected( 13 | common.calculate_result(audit.is_secure_transfer_enabled), 14 | {"Resource": data_adapter.resource}, 15 | ) 16 | } 17 | -------------------------------------------------------------------------------- /bundle/compliance/cis_azure/rules/cis_3_10/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_azure.rules.cis_3_10 2 | 3 | import data.compliance.lib.common 4 | import data.compliance.policy.azure.data_adapter 5 | import data.compliance.policy.azure.storage_account.ensure_connection as audit 6 | 7 | finding = result { 8 | # filter 9 | data_adapter.is_storage_account 10 | 11 | # set result 12 | result := common.generate_result_without_expected( 13 | common.calculate_result(audit.is_private_connections), 14 | {"Resource": data_adapter.resource}, 15 | ) 16 | } 17 | -------------------------------------------------------------------------------- /bundle/compliance/cis_azure/rules/cis_3_15/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_azure.rules.cis_3_15 2 | 3 | import data.compliance.lib.common 4 | import data.compliance.policy.azure.data_adapter 5 | import data.compliance.policy.azure.storage_account.ensure_tls_version as audit 6 | 7 | finding = result { 8 | # filter 9 | data_adapter.is_storage_account 10 | 11 | # set result 12 | result := common.generate_result_without_expected( 13 | common.calculate_result(audit.is_tls_configured("TLS1_2")), 14 | {"Resource": data_adapter.resource}, 15 | ) 16 | } 17 | -------------------------------------------------------------------------------- /bundle/compliance/cis_azure/rules/cis_3_2/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_azure.rules.cis_3_2 2 | 3 | import data.compliance.lib.common 4 | import data.compliance.policy.azure.data_adapter 5 | import data.compliance.policy.azure.storage_account.ensure_encryption as audit 6 | 7 | finding = result { 8 | # filter 9 | data_adapter.is_storage_account 10 | 11 | # set result 12 | result := common.generate_result_without_expected( 13 | common.calculate_result(audit.is_encryption_enabled), 14 | {"Resource": data_adapter.resource}, 15 | ) 16 | } 17 | -------------------------------------------------------------------------------- /bundle/compliance/cis_azure/rules/cis_3_7/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_azure.rules.cis_3_7 2 | 3 | import data.compliance.lib.common 4 | import data.compliance.policy.azure.data_adapter 5 | import data.compliance.policy.azure.storage_account.ensure_public_access as audit 6 | 7 | finding = result { 8 | # filter 9 | data_adapter.is_storage_account 10 | 11 | # set result 12 | result := common.generate_result_without_expected( 13 | common.calculate_result(audit.is_public_access_disabled), 14 | {"Resource": data_adapter.resource}, 15 | ) 16 | } 17 | -------------------------------------------------------------------------------- /bundle/compliance/cis_azure/rules/cis_3_8/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_azure.rules.cis_3_8 2 | 3 | import data.compliance.lib.common 4 | import data.compliance.policy.azure.data_adapter 5 | import data.compliance.policy.azure.storage_account.ensure_default_network_access as audit 6 | 7 | finding = result { 8 | # filter 9 | data_adapter.is_storage_account 10 | 11 | # set result 12 | result := common.generate_result_without_expected( 13 | common.calculate_result(audit.is_default_network_access), 14 | {"Resource": data_adapter.resource}, 15 | ) 16 | } 17 | -------------------------------------------------------------------------------- /bundle/compliance/cis_azure/rules/cis_3_9/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_azure.rules.cis_3_9 2 | 3 | import data.compliance.lib.common 4 | import data.compliance.policy.azure.data_adapter 5 | import data.compliance.policy.azure.storage_account.ensure_service as audit 6 | 7 | finding = result { 8 | # filter 9 | data_adapter.is_storage_account 10 | 11 | # set result 12 | result := common.generate_result_without_expected( 13 | common.calculate_result(audit.evaluate_service("AzureServices")), 14 | {"Resource": data_adapter.resource}, 15 | ) 16 | } 17 | -------------------------------------------------------------------------------- /bundle/compliance/cis_azure/rules/cis_4_1_2/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_azure.rules.cis_4_1_2 2 | 3 | import data.compliance.lib.common 4 | import data.compliance.policy.azure.data_adapter 5 | 6 | finding = result { 7 | # filter 8 | data_adapter.is_sql_server 9 | 10 | # set result 11 | result := common.generate_result_without_expected( 12 | common.calculate_result(is_public_access_disabled), 13 | {"Resource": data_adapter.resource}, 14 | ) 15 | } 16 | 17 | is_public_access_disabled { 18 | data_adapter.properties.publicNetworkAccess == "Disabled" 19 | } else = false 20 | -------------------------------------------------------------------------------- /bundle/compliance/cis_azure/rules/cis_4_1_4/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_azure.rules.cis_4_1_4 2 | 3 | import data.compliance.lib.common 4 | import data.compliance.policy.azure.data_adapter 5 | 6 | finding = result { 7 | # filter 8 | data_adapter.is_sql_server 9 | 10 | # set result 11 | result := common.generate_result_without_expected( 12 | common.calculate_result(is_administrator_configured), 13 | {"Resource": data_adapter.resource}, 14 | ) 15 | } 16 | 17 | is_administrator_configured { 18 | data_adapter.properties.administrators.administratorType == "ActiveDirectory" 19 | } else = false 20 | -------------------------------------------------------------------------------- /bundle/compliance/cis_azure/rules/cis_4_3_1/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_azure.rules.cis_4_3_1 2 | 3 | import data.compliance.lib.common 4 | import data.compliance.policy.azure.data_adapter 5 | 6 | finding = result { 7 | # filter 8 | data_adapter.is_postgresql_server_db 9 | 10 | # set result 11 | result := common.generate_result_without_expected( 12 | common.calculate_result(ssl_enforcement_enabled), 13 | {"Resource": data_adapter.resource}, 14 | ) 15 | } 16 | 17 | ssl_enforcement_enabled { 18 | data_adapter.properties.sslEnforcement == "Enabled" 19 | } else = false 20 | -------------------------------------------------------------------------------- /bundle/compliance/cis_azure/rules/cis_4_4_1/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_azure.rules.cis_4_4_1 2 | 3 | import data.compliance.lib.common 4 | import data.compliance.policy.azure.data_adapter 5 | 6 | finding = result { 7 | # filter 8 | data_adapter.is_mysql_server_db 9 | 10 | # set result 11 | result := common.generate_result_without_expected( 12 | common.calculate_result(ssl_enforcement_enabled), 13 | {"Resource": data_adapter.resource}, 14 | ) 15 | } 16 | 17 | ssl_enforcement_enabled { 18 | data_adapter.properties.sslEnforcement == "Enabled" 19 | } else = false 20 | -------------------------------------------------------------------------------- /bundle/compliance/cis_azure/rules/cis_4_5_1/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_azure.rules.cis_4_5_1 2 | 3 | import data.compliance.lib.common 4 | import data.compliance.policy.azure.data_adapter 5 | 6 | finding = result { 7 | # filter 8 | data_adapter.is_document_db_database_account 9 | 10 | # set result 11 | result := common.generate_result_without_expected( 12 | common.calculate_result(is_virtual_network_filter_enabled), 13 | {"Resource": data_adapter.resource}, 14 | ) 15 | } 16 | 17 | is_virtual_network_filter_enabled { 18 | data_adapter.properties.isVirtualNetworkFilterEnabled 19 | } else = false 20 | -------------------------------------------------------------------------------- /bundle/compliance/cis_azure/rules/cis_5_2_1/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_azure.rules.cis_5_2_1 2 | 3 | import data.compliance.lib.common 4 | import data.compliance.policy.azure.activity_log_alert.activity_log_alert_operation_enabled as audit 5 | import data.compliance.policy.azure.data_adapter 6 | 7 | finding = result { 8 | # filter 9 | data_adapter.is_activity_log_alerts 10 | 11 | operations = ["Microsoft.Authorization/policyAssignments/write"] 12 | categories = ["Administrative"] 13 | 14 | # set result 15 | result := common.generate_result_without_expected( 16 | common.calculate_result(audit.activity_log_alert_operation_enabled(operations, categories)), 17 | {"Resource": data_adapter.resource}, 18 | ) 19 | } 20 | -------------------------------------------------------------------------------- /bundle/compliance/cis_azure/rules/cis_5_2_10/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_azure.rules.cis_5_2_10 2 | 3 | import data.compliance.lib.common 4 | import data.compliance.policy.azure.activity_log_alert.activity_log_alert_operation_enabled as audit 5 | import data.compliance.policy.azure.data_adapter 6 | 7 | finding = result { 8 | # filter 9 | data_adapter.is_activity_log_alerts 10 | 11 | operations = ["Microsoft.Network/publicIPAddresses/delete"] 12 | categories = ["Administrative"] 13 | 14 | # set result 15 | result := common.generate_result_without_expected( 16 | common.calculate_result(audit.activity_log_alert_operation_enabled(operations, categories)), 17 | {"Resource": data_adapter.resource}, 18 | ) 19 | } 20 | -------------------------------------------------------------------------------- /bundle/compliance/cis_azure/rules/cis_5_2_2/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_azure.rules.cis_5_2_2 2 | 3 | import data.compliance.lib.common 4 | import data.compliance.policy.azure.activity_log_alert.activity_log_alert_operation_enabled as audit 5 | import data.compliance.policy.azure.data_adapter 6 | 7 | finding = result { 8 | # filter 9 | data_adapter.is_activity_log_alerts 10 | 11 | operations = ["Microsoft.Authorization/policyAssignments/delete"] 12 | categories = ["Administrative"] 13 | 14 | # set result 15 | result := common.generate_result_without_expected( 16 | common.calculate_result(audit.activity_log_alert_operation_enabled(operations, categories)), 17 | {"Resource": data_adapter.resource}, 18 | ) 19 | } 20 | -------------------------------------------------------------------------------- /bundle/compliance/cis_azure/rules/cis_5_2_3/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_azure.rules.cis_5_2_3 2 | 3 | import data.compliance.lib.common 4 | import data.compliance.policy.azure.activity_log_alert.activity_log_alert_operation_enabled as audit 5 | import data.compliance.policy.azure.data_adapter 6 | 7 | finding = result { 8 | # filter 9 | data_adapter.is_activity_log_alerts 10 | 11 | operations = ["Microsoft.Network/networkSecurityGroups/write"] 12 | categories = ["Administrative"] 13 | 14 | # set result 15 | result := common.generate_result_without_expected( 16 | common.calculate_result(audit.activity_log_alert_operation_enabled(operations, categories)), 17 | {"Resource": data_adapter.resource}, 18 | ) 19 | } 20 | -------------------------------------------------------------------------------- /bundle/compliance/cis_azure/rules/cis_5_2_4/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_azure.rules.cis_5_2_4 2 | 3 | import data.compliance.lib.common 4 | import data.compliance.policy.azure.activity_log_alert.activity_log_alert_operation_enabled as audit 5 | import data.compliance.policy.azure.data_adapter 6 | 7 | finding = result { 8 | # filter 9 | data_adapter.is_activity_log_alerts 10 | 11 | operations = ["Microsoft.Network/networkSecurityGroups/delete"] 12 | categories = ["Administrative"] 13 | 14 | # set result 15 | result := common.generate_result_without_expected( 16 | common.calculate_result(audit.activity_log_alert_operation_enabled(operations, categories)), 17 | {"Resource": data_adapter.resource}, 18 | ) 19 | } 20 | -------------------------------------------------------------------------------- /bundle/compliance/cis_azure/rules/cis_5_2_5/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_azure.rules.cis_5_2_5 2 | 3 | import data.compliance.lib.common 4 | import data.compliance.policy.azure.activity_log_alert.activity_log_alert_operation_enabled as audit 5 | import data.compliance.policy.azure.data_adapter 6 | 7 | finding = result { 8 | # filter 9 | data_adapter.is_activity_log_alerts 10 | 11 | operations = ["Microsoft.Security/securitySolutions/write"] 12 | categories = ["Administrative"] 13 | 14 | # set result 15 | result := common.generate_result_without_expected( 16 | common.calculate_result(audit.activity_log_alert_operation_enabled(operations, categories)), 17 | {"Resource": data_adapter.resource}, 18 | ) 19 | } 20 | -------------------------------------------------------------------------------- /bundle/compliance/cis_azure/rules/cis_5_2_6/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_azure.rules.cis_5_2_6 2 | 3 | import data.compliance.lib.common 4 | import data.compliance.policy.azure.activity_log_alert.activity_log_alert_operation_enabled as audit 5 | import data.compliance.policy.azure.data_adapter 6 | 7 | finding = result { 8 | # filter 9 | data_adapter.is_activity_log_alerts 10 | 11 | operations = ["Microsoft.Security/securitySolutions/delete"] 12 | categories = ["Administrative"] 13 | 14 | # set result 15 | result := common.generate_result_without_expected( 16 | common.calculate_result(audit.activity_log_alert_operation_enabled(operations, categories)), 17 | {"Resource": data_adapter.resource}, 18 | ) 19 | } 20 | -------------------------------------------------------------------------------- /bundle/compliance/cis_azure/rules/cis_5_2_7/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_azure.rules.cis_5_2_7 2 | 3 | import data.compliance.lib.common 4 | import data.compliance.policy.azure.activity_log_alert.activity_log_alert_operation_enabled as audit 5 | import data.compliance.policy.azure.data_adapter 6 | 7 | finding = result { 8 | # filter 9 | data_adapter.is_activity_log_alerts 10 | 11 | operations = ["Microsoft.Sql/servers/firewallRules/write"] 12 | categories = ["Administrative"] 13 | 14 | # set result 15 | result := common.generate_result_without_expected( 16 | common.calculate_result(audit.activity_log_alert_operation_enabled(operations, categories)), 17 | {"Resource": data_adapter.resource}, 18 | ) 19 | } 20 | -------------------------------------------------------------------------------- /bundle/compliance/cis_azure/rules/cis_5_2_8/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_azure.rules.cis_5_2_8 2 | 3 | import data.compliance.lib.common 4 | import data.compliance.policy.azure.activity_log_alert.activity_log_alert_operation_enabled as audit 5 | import data.compliance.policy.azure.data_adapter 6 | 7 | finding = result { 8 | # filter 9 | data_adapter.is_activity_log_alerts 10 | 11 | operations = ["Microsoft.Sql/servers/firewallRules/delete"] 12 | categories = ["Administrative"] 13 | 14 | # set result 15 | result := common.generate_result_without_expected( 16 | common.calculate_result(audit.activity_log_alert_operation_enabled(operations, categories)), 17 | {"Resource": data_adapter.resource}, 18 | ) 19 | } 20 | -------------------------------------------------------------------------------- /bundle/compliance/cis_azure/rules/cis_5_2_9/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_azure.rules.cis_5_2_9 2 | 3 | import data.compliance.lib.common 4 | import data.compliance.policy.azure.activity_log_alert.activity_log_alert_operation_enabled as audit 5 | import data.compliance.policy.azure.data_adapter 6 | 7 | finding = result { 8 | # filter 9 | data_adapter.is_activity_log_alerts 10 | 11 | operations = ["Microsoft.Network/publicIPAddresses/write"] 12 | categories = ["Administrative"] 13 | 14 | # set result 15 | result := common.generate_result_without_expected( 16 | common.calculate_result(audit.activity_log_alert_operation_enabled(operations, categories)), 17 | {"Resource": data_adapter.resource}, 18 | ) 19 | } 20 | -------------------------------------------------------------------------------- /bundle/compliance/cis_azure/rules/cis_5_5/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_azure.rules.cis_5_5 2 | 3 | import data.compliance.lib.common 4 | import data.compliance.policy.azure.data_adapter 5 | 6 | finding = result { 7 | # No filter, all resources will be checked 8 | 9 | # set result 10 | result := common.generate_result_without_expected( 11 | common.calculate_result(ensure_sku_valid), 12 | {"Resource": data_adapter.resource}, 13 | ) 14 | } 15 | 16 | ensure_sku_tier { 17 | data_adapter.resource.sku.tier != "Basic" 18 | } else = false 19 | 20 | ensure_sku_valid = r { 21 | data_adapter.resource.sku != null 22 | r = ensure_sku_tier 23 | } 24 | -------------------------------------------------------------------------------- /bundle/compliance/cis_azure/rules/cis_6_5/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_azure.rules.cis_6_5 2 | 3 | import data.compliance.lib.common 4 | import data.compliance.policy.azure.data_adapter 5 | 6 | finding = result { 7 | # filter 8 | data_adapter.is_network_watchers_flow_log 9 | 10 | # set result 11 | result := common.generate_result_without_expected( 12 | common.calculate_result(ensure_retention_days), 13 | {"Resource": data_adapter.resource}, 14 | ) 15 | } 16 | 17 | ensure_retention_days { 18 | data_adapter.properties.retentionPolicy.enabled 19 | data_adapter.properties.retentionPolicy.days >= 90 20 | } else = false 21 | -------------------------------------------------------------------------------- /bundle/compliance/cis_azure/rules/cis_6_6/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_azure.rules.cis_6_6 2 | 3 | import data.compliance.lib.common 4 | import data.compliance.policy.azure.data_adapter 5 | 6 | finding = result { 7 | # filter 8 | data_adapter.is_network_watcher 9 | 10 | # set result 11 | result := common.generate_result_without_expected( 12 | common.calculate_result(ensure_enabled), 13 | {"Resource": data_adapter.resource}, 14 | ) 15 | } 16 | 17 | ensure_enabled { 18 | data_adapter.properties.provisioningState == "Succeeded" 19 | } else = false 20 | -------------------------------------------------------------------------------- /bundle/compliance/cis_azure/rules/cis_7_1/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_azure.rules.cis_7_1 2 | 3 | import data.compliance.lib.common 4 | import data.compliance.policy.azure.data_adapter 5 | 6 | finding = result { 7 | # filter 8 | data_adapter.is_bastion 9 | 10 | # set result 11 | result := common.generate_result_without_expected( 12 | common.calculate_result(at_least_one_bastion), 13 | {"Resource": data_adapter.resource}, 14 | ) 15 | } 16 | 17 | at_least_one_bastion { 18 | some i 19 | data_adapter.bastions[i].id != "" 20 | } else = false 21 | -------------------------------------------------------------------------------- /bundle/compliance/cis_azure/rules/cis_7_2/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_azure.rules.cis_7_2 2 | 3 | import data.compliance.lib.common 4 | import data.compliance.policy.azure.data_adapter 5 | 6 | finding = result { 7 | # filter 8 | data_adapter.is_vm 9 | 10 | # set result 11 | result := common.generate_result_without_expected( 12 | common.calculate_result(has_managed_disk), 13 | {"Resource": data_adapter.resource}, 14 | ) 15 | } 16 | 17 | has_managed_disk { 18 | data_adapter.properties.storageProfile.osDisk.managedDisk.id != "" 19 | } else = false 20 | -------------------------------------------------------------------------------- /bundle/compliance/cis_azure/rules/cis_7_3/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_azure.rules.cis_7_3 2 | 3 | import data.compliance.lib.common 4 | import data.compliance.policy.azure.data_adapter 5 | import data.compliance.policy.azure.disk.ensure_encryption as audit 6 | 7 | finding = result { 8 | # filter 9 | data_adapter.is_attached_disk 10 | 11 | # set result 12 | result := common.generate_result_without_expected( 13 | common.calculate_result(audit.is_encryption_enabled), 14 | {"Resource": data_adapter.resource}, 15 | ) 16 | } 17 | -------------------------------------------------------------------------------- /bundle/compliance/cis_azure/rules/cis_7_4/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_azure.rules.cis_7_4 2 | 3 | import data.compliance.lib.common 4 | import data.compliance.policy.azure.data_adapter 5 | import data.compliance.policy.azure.disk.ensure_encryption as audit 6 | 7 | finding = result { 8 | # filter 9 | data_adapter.is_unattached_disk 10 | 11 | # set result 12 | result := common.generate_result_without_expected( 13 | common.calculate_result(audit.is_encryption_enabled), 14 | {"Resource": data_adapter.resource}, 15 | ) 16 | } 17 | -------------------------------------------------------------------------------- /bundle/compliance/cis_azure/rules/cis_8_5/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_azure.rules.cis_8_5 2 | 3 | import data.compliance.lib.common 4 | import data.compliance.policy.azure.data_adapter 5 | 6 | finding = result { 7 | # filter 8 | data_adapter.is_vault 9 | 10 | # set result 11 | result := common.generate_result_without_expected( 12 | common.calculate_result(is_vault_recoverable), 13 | {"Resource": data_adapter.resource}, 14 | ) 15 | } 16 | 17 | is_vault_recoverable { 18 | data_adapter.properties.enableSoftDelete 19 | data_adapter.properties.enablePurgeProtection 20 | } else = false 21 | -------------------------------------------------------------------------------- /bundle/compliance/cis_azure/rules/cis_9_4/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_azure.rules.cis_9_4 2 | 3 | import data.compliance.lib.common 4 | import data.compliance.policy.azure.data_adapter 5 | 6 | finding = result { 7 | # filter 8 | data_adapter.is_website_asset 9 | 10 | # set result 11 | result := common.generate_result_without_expected( 12 | common.calculate_result(is_client_cert_enabled), 13 | data_adapter.resource, 14 | ) 15 | } 16 | 17 | is_client_cert_enabled { 18 | # Benchmark and Azure implementation in remediation checks previous implemented value 19 | # Reading the description and rule metadata, we've decided to check the value of the property clientCertMode 20 | data_adapter.properties.clientCertMode == "Required" 21 | } else = false 22 | -------------------------------------------------------------------------------- /bundle/compliance/cis_eks/data_adapter.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_eks.data_adapter 2 | 3 | import data.compliance.policy.process.data_adapter as process_data_adapter 4 | 5 | process_args := process_data_adapter.process_args 6 | -------------------------------------------------------------------------------- /bundle/compliance/cis_eks/rules/cis_2_1_1/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_eks.rules.cis_2_1_1 2 | 3 | import data.compliance.policy.aws_eks.ensure_logs_enabled as audit 4 | 5 | finding = audit.finding 6 | -------------------------------------------------------------------------------- /bundle/compliance/cis_eks/rules/cis_3_1_1/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_eks.rules.cis_3_1_1 2 | 3 | import data.compliance.policy.file.ensure_permissions as audit 4 | 5 | finding = result { 6 | audit.filename_filter("kubeconfig") 7 | result := audit.finding(audit.file_permission_match(6, 4, 4)) 8 | } 9 | -------------------------------------------------------------------------------- /bundle/compliance/cis_eks/rules/cis_3_1_1/test.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_eks.rules.cis_3_1_1 2 | 3 | import data.kubernetes_common.test_data 4 | import data.lib.test 5 | 6 | test_violation { 7 | test.assert_fail(finding) with input as rule_input("kubeconfig", "700") 8 | } 9 | 10 | test_pass { 11 | test.assert_pass(finding) with input as rule_input("kubeconfig", "644") 12 | } 13 | 14 | test_not_evaluated { 15 | not finding with input as rule_input("file.txt", "644") 16 | } 17 | 18 | rule_input(filename, filemode) = filesystem_input { 19 | user := "root" 20 | group := "root" 21 | filesystem_input = test_data.filesystem_input(filename, filemode, user, group) 22 | } 23 | -------------------------------------------------------------------------------- /bundle/compliance/cis_eks/rules/cis_3_1_2/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_eks.rules.cis_3_1_2 2 | 3 | import data.compliance.policy.file.ensure_ownership as audit 4 | 5 | finding = result { 6 | audit.filename_filter("kubeconfig") 7 | result := audit.finding("root", "root") 8 | } 9 | -------------------------------------------------------------------------------- /bundle/compliance/cis_eks/rules/cis_3_1_2/test.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_eks.rules.cis_3_1_2 2 | 3 | import data.kubernetes_common.test_data 4 | import data.lib.test 5 | 6 | test_violation { 7 | test.assert_fail(finding) with input as rule_input("kubeconfig", "root", "user") 8 | test.assert_fail(finding) with input as rule_input("kubeconfig", "user", "root") 9 | test.assert_fail(finding) with input as rule_input("kubeconfig", "user", "user") 10 | } 11 | 12 | test_pass { 13 | test.assert_pass(finding) with input as rule_input("kubeconfig", "root", "root") 14 | } 15 | 16 | test_not_evaluated { 17 | not finding with input as rule_input("file.txt", "root", "root") 18 | } 19 | 20 | rule_input(filename, user, group) = filesystem_input { 21 | filemode := "644" 22 | filesystem_input = test_data.filesystem_input(filename, filemode, user, group) 23 | } 24 | -------------------------------------------------------------------------------- /bundle/compliance/cis_eks/rules/cis_3_1_3/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_eks.rules.cis_3_1_3 2 | 3 | import data.compliance.policy.file.ensure_permissions as audit 4 | 5 | finding = result { 6 | audit.filename_filter("kubelet-config.json") 7 | result := audit.finding(audit.file_permission_match(6, 4, 4)) 8 | } 9 | -------------------------------------------------------------------------------- /bundle/compliance/cis_eks/rules/cis_3_1_3/test.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_eks.rules.cis_3_1_3 2 | 3 | import data.kubernetes_common.test_data 4 | import data.lib.test 5 | 6 | test_violation { 7 | test.assert_fail(finding) with input as rule_input("kubelet-config.json", "700") 8 | } 9 | 10 | test_pass { 11 | test.assert_pass(finding) with input as rule_input("kubelet-config.json", "644") 12 | } 13 | 14 | test_not_evaluated { 15 | not finding with input as rule_input("file.txt", "644") 16 | } 17 | 18 | rule_input(filename, filemode) = filesystem_input { 19 | user := "root" 20 | group := "root" 21 | filesystem_input = test_data.filesystem_input(filename, filemode, user, group) 22 | } 23 | -------------------------------------------------------------------------------- /bundle/compliance/cis_eks/rules/cis_3_1_4/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_eks.rules.cis_3_1_4 2 | 3 | import data.compliance.policy.file.ensure_ownership as audit 4 | 5 | finding = result { 6 | audit.filename_filter("kubelet-config.json") 7 | result := audit.finding("root", "root") 8 | } 9 | -------------------------------------------------------------------------------- /bundle/compliance/cis_eks/rules/cis_3_1_4/test.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_eks.rules.cis_3_1_4 2 | 3 | import data.kubernetes_common.test_data 4 | import data.lib.test 5 | 6 | test_violation { 7 | test.assert_fail(finding) with input as rule_input("kubelet-config.json", "root", "user") 8 | test.assert_fail(finding) with input as rule_input("kubelet-config.json", "user", "root") 9 | test.assert_fail(finding) with input as rule_input("kubelet-config.json", "user", "user") 10 | } 11 | 12 | test_pass { 13 | test.assert_pass(finding) with input as rule_input("kubelet-config.json", "root", "root") 14 | } 15 | 16 | test_not_evaluated { 17 | not finding with input as rule_input("file.txt", "root", "root") 18 | } 19 | 20 | rule_input(filename, user, group) = filesystem_input { 21 | filemode := "644" 22 | filesystem_input = test_data.filesystem_input(filename, filemode, user, group) 23 | } 24 | -------------------------------------------------------------------------------- /bundle/compliance/cis_eks/rules/cis_3_2_1/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_eks.rules.cis_3_2_1 2 | 3 | import data.compliance.policy.process.ensure_arguments_and_config as audit 4 | 5 | # Ensure that the --anonymous-auth argument is set to false (Automated) 6 | default rule_evaluation = false 7 | 8 | rule_evaluation { 9 | audit.process_contains_key_with_value("--anonymous-auth", "false") 10 | } 11 | 12 | # In case both flags and configuration file are specified, the executable argument takes precedence. 13 | # Checks that the entry for authentication:anonymous: enabled set to false. 14 | rule_evaluation { 15 | audit.not_process_arg_comparison("--anonymous-auth", ["authentication", "anonymous", "enabled"], false) 16 | } 17 | 18 | finding = audit.finding(rule_evaluation) 19 | -------------------------------------------------------------------------------- /bundle/compliance/cis_eks/rules/cis_3_2_10/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_eks.rules.cis_3_2_10 2 | 3 | import data.compliance.policy.process.ensure_arguments_and_config as audit 4 | 5 | # Verify that the --rotate-certificates argument is not present, or is set to true. 6 | default rule_evaluation = true 7 | 8 | rule_evaluation = false { 9 | audit.process_contains_key_with_value("--rotate-certificates", "false") 10 | } 11 | 12 | # In case both flags and configuration file are specified, the executable argument takes precedence. 13 | rule_evaluation = false { 14 | audit.not_process_arg_comparison("--rotate-certificates", ["rotateCertificates"], false) 15 | } 16 | 17 | finding = audit.finding(rule_evaluation) 18 | -------------------------------------------------------------------------------- /bundle/compliance/cis_eks/rules/cis_3_2_3/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_eks.rules.cis_3_2_3 2 | 3 | import data.compliance.policy.process.ensure_arguments_and_config as audit 4 | 5 | default rule_evaluation = false 6 | 7 | rule_evaluation { 8 | audit.process_contains_key("--client-ca-file") 9 | } 10 | 11 | # In case both flags and configuration file are specified, the executable argument takes precedence. 12 | # Checks that the entry for authentication:x509:clientCAFile: set to a valid path. 13 | rule_evaluation { 14 | audit.get_from_config(["authentication", "x509", "clientCAFile"]) 15 | } 16 | 17 | # Ensure that the --client-ca-file argument is set as appropriate (Automated) 18 | finding = audit.finding(rule_evaluation) 19 | -------------------------------------------------------------------------------- /bundle/compliance/cis_eks/rules/cis_3_2_4/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_eks.rules.cis_3_2_4 2 | 3 | import data.compliance.policy.process.ensure_arguments_and_config as audit 4 | 5 | # Verify that the --read-only-port argument is set to 0 6 | default rule_evaluation = false 7 | 8 | rule_evaluation { 9 | audit.process_contains_key_with_value("--read-only-port", "0") 10 | } 11 | 12 | # In case both flags and configuration file are specified, the executable argument takes precedence. 13 | rule_evaluation { 14 | audit.not_process_arg_comparison("--read-only-port", ["readOnlyPort"], 0) 15 | } 16 | 17 | finding = audit.finding(rule_evaluation) 18 | -------------------------------------------------------------------------------- /bundle/compliance/cis_eks/rules/cis_3_2_6/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_eks.rules.cis_3_2_6 2 | 3 | import data.compliance.policy.process.ensure_arguments_and_config as audit 4 | 5 | default rule_evaluation = false 6 | 7 | # Ensure that the --protect-kernel-defaults argument is set to true 8 | rule_evaluation { 9 | audit.process_contains_key_with_value("--protect-kernel-defaults", "true") 10 | } 11 | 12 | # In case both flags and configuration file are specified, the executable argument takes precedence. 13 | # Ensure that the protectKernelDefaults argument is set to true 14 | rule_evaluation { 15 | audit.not_process_arg_variable("--protect-kernel-defaults", ["protectKernelDefaults"]) 16 | } 17 | 18 | finding = audit.finding(rule_evaluation) 19 | -------------------------------------------------------------------------------- /bundle/compliance/cis_eks/rules/cis_3_2_7/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_eks.rules.cis_3_2_7 2 | 3 | import data.compliance.policy.process.ensure_arguments_and_config as audit 4 | 5 | default rule_evaluation = true 6 | 7 | # Ensure that the --make-iptables-util-chains argument is set to true (Automated) 8 | rule_evaluation = false { 9 | audit.process_contains_key_with_value("--make-iptables-util-chains", "false") 10 | } 11 | 12 | # In case both flags and configuration file are specified, the executable argument takes precedence. 13 | # Checks that the entry for makeIPTablesUtilChains is set to true. 14 | rule_evaluation = false { 15 | audit.not_process_arg_comparison("--make-iptables-util-chains", ["makeIPTablesUtilChains"], false) 16 | } 17 | 18 | finding = audit.finding(rule_evaluation) 19 | -------------------------------------------------------------------------------- /bundle/compliance/cis_eks/rules/cis_3_2_8/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_eks.rules.cis_3_2_8 2 | 3 | import data.compliance.policy.process.ensure_arguments_and_config as audit 4 | 5 | # Ensure that the --hostname-override argument is not set. 6 | default rule_evaluation = true 7 | 8 | # Note This setting is not configurable via the Kubelet config file. 9 | rule_evaluation = false { 10 | audit.process_contains_key("--hostname-override") 11 | } 12 | 13 | finding = audit.finding(rule_evaluation) 14 | -------------------------------------------------------------------------------- /bundle/compliance/cis_eks/rules/cis_3_2_9/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_eks.rules.cis_3_2_9 2 | 3 | import data.compliance.policy.process.ensure_arguments_and_config as audit 4 | 5 | # Ensure that the --event-qps argument is set to 0 or a level which 6 | # ensures appropriate event capture 7 | default rule_evaluation = false 8 | 9 | rule_evaluation { 10 | audit.process_contains_key_with_value("--event-qps", "0") 11 | } 12 | 13 | rule_evaluation { 14 | audit.not_process_key_comparison("--event-qps", ["eventRecordQPS"], 0) 15 | } 16 | 17 | finding = audit.finding(rule_evaluation) 18 | -------------------------------------------------------------------------------- /bundle/compliance/cis_eks/rules/cis_4_2_1/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_eks.rules.cis_4_2_1 2 | 3 | import data.compliance.policy.kube_api.minimize_admission as audit 4 | 5 | finding = result { 6 | result := audit.finding("privileged") 7 | } 8 | -------------------------------------------------------------------------------- /bundle/compliance/cis_eks/rules/cis_4_2_2/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_eks.rules.cis_4_2_2 2 | 3 | import data.compliance.policy.kube_api.minimize_sharing as audit 4 | 5 | finding = result { 6 | result := audit.finding("hostPID") 7 | } 8 | -------------------------------------------------------------------------------- /bundle/compliance/cis_eks/rules/cis_4_2_3/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_eks.rules.cis_4_2_3 2 | 3 | import data.compliance.policy.kube_api.minimize_sharing as audit 4 | 5 | finding = result { 6 | result := audit.finding("hostIPC") 7 | } 8 | -------------------------------------------------------------------------------- /bundle/compliance/cis_eks/rules/cis_4_2_4/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_eks.rules.cis_4_2_4 2 | 3 | import data.compliance.policy.kube_api.minimize_sharing as audit 4 | 5 | finding = result { 6 | result := audit.finding("hostNetwork") 7 | } 8 | -------------------------------------------------------------------------------- /bundle/compliance/cis_eks/rules/cis_4_2_5/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_eks.rules.cis_4_2_5 2 | 3 | import data.compliance.policy.kube_api.minimize_admission as audit 4 | 5 | finding = result { 6 | result := audit.finding("allowPrivilegeEscalation") 7 | } 8 | -------------------------------------------------------------------------------- /bundle/compliance/cis_eks/rules/cis_4_2_6/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_eks.rules.cis_4_2_6 2 | 3 | import data.compliance.policy.kube_api.minimize_admission_root as audit 4 | 5 | finding = result { 6 | result := audit.finding 7 | } 8 | -------------------------------------------------------------------------------- /bundle/compliance/cis_eks/rules/cis_4_2_7/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_eks.rules.cis_4_2_7 2 | 3 | import data.compliance.policy.kube_api.minimize_certain_capability as audit 4 | 5 | finding = result { 6 | result := audit.finding 7 | } 8 | -------------------------------------------------------------------------------- /bundle/compliance/cis_eks/rules/cis_4_2_8/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_eks.rules.cis_4_2_8 2 | 3 | import data.compliance.policy.kube_api.minimize_added_capabilities as audit 4 | 5 | finding = result { 6 | result := audit.finding 7 | } 8 | -------------------------------------------------------------------------------- /bundle/compliance/cis_eks/rules/cis_4_2_9/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_eks.rules.cis_4_2_9 2 | 3 | import data.compliance.policy.kube_api.minimize_assigned_capabilities as audit 4 | 5 | finding = result { 6 | result := audit.finding 7 | } 8 | -------------------------------------------------------------------------------- /bundle/compliance/cis_eks/rules/cis_5_1_1/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_eks.rules.cis_5_1_1 2 | 3 | import data.compliance.policy.aws_ecr.ensure_image_scan as audit 4 | 5 | # Check if image ScanOnPush is enabled 6 | finding = audit.finding 7 | -------------------------------------------------------------------------------- /bundle/compliance/cis_eks/rules/cis_5_1_1/test.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_eks.rules.cis_5_1_1 2 | 3 | import data.cis_eks.test_data 4 | import data.lib.test 5 | 6 | test_violation { 7 | test.assert_fail(finding) with input as violating_input_scan_on_push_disabled 8 | } 9 | 10 | test_pass { 11 | test.assert_pass(finding) with input as valid_input 12 | } 13 | 14 | test_not_evaluated { 15 | not finding with input as test_data.not_evaluated_input 16 | } 17 | 18 | violating_input_scan_on_push_disabled = test_data.generate_ecr_input_with_one_repo(false) 19 | 20 | valid_input = test_data.generate_ecr_input_with_one_repo(true) 21 | -------------------------------------------------------------------------------- /bundle/compliance/cis_eks/rules/cis_5_3_1/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_eks.rules.cis_5_3_1 2 | 3 | import data.compliance.policy.aws_eks.ensure_encryption as audit 4 | 5 | finding = audit.finding 6 | -------------------------------------------------------------------------------- /bundle/compliance/cis_eks/rules/cis_5_4_1/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_eks.rules.cis_5_4_1 2 | 3 | import data.compliance.policy.aws_eks.ensure_private_access as audit 4 | 5 | finding = audit.finding(true) 6 | -------------------------------------------------------------------------------- /bundle/compliance/cis_eks/rules/cis_5_4_2/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_eks.rules.cis_5_4_2 2 | 3 | import data.compliance.policy.aws_eks.ensure_private_access as audit 4 | 5 | finding = audit.finding(false) 6 | -------------------------------------------------------------------------------- /bundle/compliance/cis_eks/rules/cis_5_4_3/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_eks.rules.cis_5_4_3 2 | 3 | import data.compliance.policy.kube_api.ensure_external_ip as audit 4 | 5 | # Ensure there cluster node don't have a public IP 6 | default rule_evaluation = true 7 | 8 | # Verify that the node doesn't have an external IP 9 | rule_evaluation = false { 10 | audit.verify_external_ip 11 | } 12 | 13 | # Ensure there cluster node don't have a public IP 14 | finding = audit.finding(rule_evaluation) 15 | -------------------------------------------------------------------------------- /bundle/compliance/cis_eks/rules/cis_5_4_5/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_eks.rules.cis_5_4_5 2 | 3 | import data.compliance.policy.aws_elb.ensure_certificates as audit 4 | 5 | # Ensure there Kuberenetes endpoint private access is enabled 6 | finding = audit.finding 7 | -------------------------------------------------------------------------------- /bundle/compliance/cis_gcp/data_adapter.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_gcp.data_adapter 2 | -------------------------------------------------------------------------------- /bundle/compliance/cis_gcp/rules/cis_1_10/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_gcp.rules.cis_1_10 2 | 3 | import data.compliance.policy.gcp.kms.ensure_key_rotation as audit 4 | 5 | finding = audit.finding 6 | -------------------------------------------------------------------------------- /bundle/compliance/cis_gcp/rules/cis_1_12/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_gcp.rules.cis_1_12 2 | 3 | import data.compliance.lib.common 4 | import data.compliance.policy.gcp.data_adapter 5 | import future.keywords.if 6 | 7 | finding = result if { 8 | data_adapter.is_api_key 9 | 10 | is_project_apikey := startswith(data_adapter.resource.data.name, "projects/") 11 | 12 | result := common.generate_result_without_expected( 13 | common.calculate_result(is_project_apikey == false), 14 | data_adapter.resource.data.name, 15 | ) 16 | } 17 | -------------------------------------------------------------------------------- /bundle/compliance/cis_gcp/rules/cis_1_15/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_gcp.rules.cis_1_15 2 | 3 | import data.compliance.lib.common 4 | import data.compliance.policy.gcp.data_adapter 5 | import future.keywords.contains 6 | import future.keywords.if 7 | 8 | duration = sprintf("%dh", [90 * 24]) # 90 days converted to hours 9 | 10 | finding = result if { 11 | data_adapter.is_api_key 12 | 13 | result := common.generate_result_without_expected( 14 | common.calculate_result(key_created_within_last_90_days), 15 | data_adapter.resource.data.createTime, 16 | ) 17 | } 18 | 19 | key_created_within_last_90_days if { 20 | date := time.parse_rfc3339_ns(data_adapter.resource.data.createTime) 21 | common.date_within_duration(date, duration) 22 | } else = false 23 | -------------------------------------------------------------------------------- /bundle/compliance/cis_gcp/rules/cis_1_17/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_gcp.rules.cis_1_17 2 | 3 | import data.compliance.lib.common 4 | import data.compliance.policy.gcp.data_adapter 5 | import future.keywords.if 6 | 7 | default has_cusomter_encrypted_key = false 8 | 9 | finding = result if { 10 | data_adapter.is_dataproc_cluster 11 | 12 | result := common.generate_result_without_expected( 13 | common.calculate_result(has_cusomter_encrypted_key), 14 | data_adapter.resource, 15 | ) 16 | } 17 | 18 | has_cusomter_encrypted_key if { 19 | data_adapter.resource.data.config.encryptionConfig.gcePdKmsKeyName != null 20 | data_adapter.resource.data.config.encryptionConfig.gcePdKmsKeyName != "" 21 | } 22 | -------------------------------------------------------------------------------- /bundle/compliance/cis_gcp/rules/cis_1_4/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_gcp.rules.cis_1_4 2 | 3 | import data.compliance.lib.common 4 | import data.compliance.policy.gcp.data_adapter 5 | import data.compliance.policy.gcp.iam.ensure_policy_not_managed_by_user as audit 6 | import future.keywords.if 7 | 8 | finding = result if { 9 | data_adapter.is_iam_service_account 10 | data_adapter.has_policy 11 | 12 | result := common.generate_result_without_expected( 13 | common.calculate_result(audit.is_policy_not_managed_by_user), 14 | members, 15 | ) 16 | } 17 | 18 | members if { 19 | input.resource.iam_policy.bindings[i].members 20 | } 21 | -------------------------------------------------------------------------------- /bundle/compliance/cis_gcp/rules/cis_1_5/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_gcp.rules.cis_1_5 2 | 3 | import data.compliance.lib.common 4 | import data.compliance.policy.gcp.data_adapter 5 | import data.compliance.policy.gcp.iam.ensure_user_not_editor_or_owner as audit 6 | import future.keywords.every 7 | import future.keywords.if 8 | 9 | finding = result if { 10 | data_adapter.is_iam_service_account 11 | data_adapter.has_policy 12 | 13 | result := common.generate_result_without_expected( 14 | common.calculate_result(audit.is_user_owner_or_editor), 15 | data_adapter.iam_policy, 16 | ) 17 | } 18 | -------------------------------------------------------------------------------- /bundle/compliance/cis_gcp/rules/cis_1_6/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_gcp.rules.cis_1_6 2 | 3 | import data.compliance.lib.common 4 | import data.compliance.policy.gcp.data_adapter 5 | import data.compliance.policy.gcp.iam.ensure_role_not_service_account_user as audit 6 | import future.keywords.if 7 | 8 | finding = result if { 9 | data_adapter.is_cloud_resource_manager_project 10 | data_adapter.has_policy 11 | 12 | result := common.generate_result_without_expected( 13 | common.calculate_result(audit.is_role_not_service_account_user), 14 | roles, 15 | ) 16 | } 17 | 18 | roles if { 19 | data_adapter.iam_policy.bindings[i].role 20 | } 21 | -------------------------------------------------------------------------------- /bundle/compliance/cis_gcp/rules/cis_1_7/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_gcp.rules.cis_1_7 2 | 3 | import data.compliance.lib.common 4 | import data.compliance.policy.gcp.data_adapter 5 | import future.keywords.if 6 | 7 | duration = sprintf("%dh", [90 * 24]) # 90 days converted to hours 8 | 9 | finding = result if { 10 | data_adapter.is_iam_service_account_key 11 | 12 | result := common.generate_result_without_expected( 13 | common.calculate_result(key_created_within_last_90_days), 14 | data_adapter.resource.data.validAfterTime, 15 | ) 16 | } 17 | 18 | key_created_within_last_90_days if { 19 | date := time.parse_rfc3339_ns(data_adapter.resource.data.validAfterTime) 20 | common.date_within_duration(date, duration) 21 | } else = false 22 | -------------------------------------------------------------------------------- /bundle/compliance/cis_gcp/rules/cis_1_9/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_gcp.rules.cis_1_9 2 | 3 | import data.compliance.lib.assert 4 | import data.compliance.lib.common 5 | import data.compliance.policy.gcp.data_adapter 6 | import data.compliance.policy.gcp.iam.ensure_no_public_access as audit 7 | 8 | # Ensure That Cloud KMS Cryptokeys Are Not Anonymously or Publicly Accessible. 9 | finding = result { 10 | # filter 11 | data_adapter.is_cloudkms_crypto_key 12 | 13 | # set result 14 | result := common.generate_result_without_expected( 15 | common.calculate_result(assert.is_false(audit.resource_is_public)), 16 | {"KMS key": input.resource}, 17 | ) 18 | } 19 | -------------------------------------------------------------------------------- /bundle/compliance/cis_gcp/rules/cis_2_10/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_gcp.rules.cis_2_10 2 | 3 | import data.compliance.policy.gcp.monitoring.ensure_log_metric_and_alarm_exists as audit 4 | 5 | pattern := `resource.type="gcs_bucket" 6 | AND protoPayload.methodName="storage.setIamPermissions"` 7 | 8 | finding = audit.finding(pattern) 9 | -------------------------------------------------------------------------------- /bundle/compliance/cis_gcp/rules/cis_2_11/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_gcp.rules.cis_2_11 2 | 3 | import data.compliance.policy.gcp.monitoring.ensure_log_metric_and_alarm_exists as audit 4 | 5 | pattern := `protoPayload.methodName="cloudsql.instances.update"` 6 | 7 | finding = audit.finding(pattern) 8 | -------------------------------------------------------------------------------- /bundle/compliance/cis_gcp/rules/cis_2_12/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_gcp.rules.cis_2_12 2 | 3 | import data.compliance.lib.common 4 | import data.compliance.policy.gcp.data_adapter 5 | import future.keywords.if 6 | 7 | # Ensure That Cloud DNS Logging Is Enabled for All VPC Networks. 8 | finding = result if { 9 | data_adapter.is_compute_network 10 | 11 | result := common.generate_result_without_expected( 12 | common.calculate_result(is_dns_logging_enabled), 13 | data_adapter.resource, 14 | ) 15 | } 16 | 17 | is_dns_logging_enabled if { 18 | data_adapter.resource.data.enabledDnsLogging == true 19 | } else = false 20 | -------------------------------------------------------------------------------- /bundle/compliance/cis_gcp/rules/cis_2_13/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_gcp.rules.cis_2_13 2 | 3 | import data.compliance.lib.common 4 | import data.compliance.policy.gcp.data_adapter 5 | import future.keywords.if 6 | import future.keywords.in 7 | 8 | #Ensure Cloud Asset Inventory Is Enabled 9 | finding = result if { 10 | data_adapter.is_services_usage 11 | 12 | result := common.generate_result_without_expected( 13 | common.calculate_result(is_asset_inventory_enabled), 14 | input.resource.services, 15 | ) 16 | } 17 | 18 | is_asset_inventory_enabled if { 19 | some service in input.resource.services 20 | service.resource.data.name == "cloudasset.googleapis.com" 21 | service.resource.data.state == "ENABLED" 22 | } else = false 23 | -------------------------------------------------------------------------------- /bundle/compliance/cis_gcp/rules/cis_2_16/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_gcp.rules.cis_2_16 2 | 3 | import data.compliance.lib.common 4 | import data.compliance.policy.gcp.data_adapter 5 | import future.keywords.if 6 | 7 | finding = result if { 8 | data_adapter.is_backend_service 9 | data_adapter.is_https_lb 10 | 11 | result := common.generate_result_without_expected( 12 | common.calculate_result(is_logging_enabled), 13 | data_adapter.resource, 14 | ) 15 | } 16 | 17 | is_logging_enabled if { 18 | data_adapter.resource.data.logConfig.enable 19 | } else = false 20 | -------------------------------------------------------------------------------- /bundle/compliance/cis_gcp/rules/cis_2_2/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_gcp.rules.cis_2_2 2 | 3 | import data.compliance.lib.common 4 | import data.compliance.policy.gcp.data_adapter 5 | import future.keywords.if 6 | import future.keywords.in 7 | 8 | # Ensure That Sinks Are Configured for All Log Entries. 9 | finding = result if { 10 | data_adapter.is_logging_asset 11 | 12 | result := common.generate_result_without_expected( 13 | common.calculate_result(is_sink_without_filter), 14 | input.resource.log_sinks, 15 | ) 16 | } 17 | 18 | # We recieved all sinks configured at the project, folder and org level. 19 | # We check if any of the sinks are configured without a filter. 20 | is_sink_without_filter if { 21 | some sink in input.resource.log_sinks 22 | not sink.resource.data.filter 23 | } else = false 24 | -------------------------------------------------------------------------------- /bundle/compliance/cis_gcp/rules/cis_2_3/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_gcp.rules.cis_2_3 2 | 3 | import data.compliance.lib.common 4 | import data.compliance.policy.gcp.data_adapter 5 | import future.keywords.if 6 | 7 | default is_retention_policy_valid = false 8 | 9 | # Ensure That Retention Policies on Cloud Storage Buckets Used for Exporting Logs Are Configured Using Bucket Lock. 10 | finding = result if { 11 | data_adapter.is_log_bucket 12 | 13 | result := common.generate_result_without_expected( 14 | common.calculate_result(is_retention_policy_valid), 15 | data_adapter.resource, 16 | ) 17 | } 18 | 19 | is_retention_policy_valid if { 20 | data_adapter.resource.data.retentionDays > 0 21 | data_adapter.resource.data.locked == true 22 | } 23 | -------------------------------------------------------------------------------- /bundle/compliance/cis_gcp/rules/cis_2_4/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_gcp.rules.cis_2_4 2 | 3 | import data.compliance.policy.gcp.monitoring.ensure_log_metric_and_alarm_exists as audit 4 | 5 | pattern := `(protoPayload.serviceName="cloudresourcemanager.googleapis.com") 6 | AND (ProjectOwnership OR projectOwnerInvitee) 7 | OR (protoPayload.serviceData.policyDelta.bindingDeltas.action="REMOVE" 8 | AND protoPayload.serviceData.policyDelta.bindingDeltas.role="roles/owner") 9 | OR (protoPayload.serviceData.policyDelta.bindingDeltas.action="ADD" 10 | AND protoPayload.serviceData.policyDelta.bindingDeltas.role="roles/owner")` 11 | 12 | finding = audit.finding(pattern) 13 | -------------------------------------------------------------------------------- /bundle/compliance/cis_gcp/rules/cis_2_5/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_gcp.rules.cis_2_5 2 | 3 | import data.compliance.policy.gcp.monitoring.ensure_log_metric_and_alarm_exists as audit 4 | 5 | pattern := `protoPayload.methodName="SetIamPolicy" AND protoPayload.serviceData.policyDelta.auditConfigDeltas:*` 6 | 7 | finding = audit.finding(pattern) 8 | -------------------------------------------------------------------------------- /bundle/compliance/cis_gcp/rules/cis_2_6/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_gcp.rules.cis_2_6 2 | 3 | import data.compliance.policy.gcp.monitoring.ensure_log_metric_and_alarm_exists as audit 4 | 5 | pattern := `resource.type="iam_role" 6 | AND (protoPayload.methodName = "google.iam.admin.v1.CreateRole" OR 7 | protoPayload.methodName="google.iam.admin.v1.DeleteRole" OR 8 | protoPayload.methodName="google.iam.admin.v1.UpdateRole")` 9 | 10 | finding = audit.finding(pattern) 11 | -------------------------------------------------------------------------------- /bundle/compliance/cis_gcp/rules/cis_2_7/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_gcp.rules.cis_2_7 2 | 3 | import data.compliance.policy.gcp.monitoring.ensure_log_metric_and_alarm_exists as audit 4 | 5 | pattern := `resource.type="gce_firewall_rule" 6 | AND (protoPayload.methodName:"compute.firewalls.patch" 7 | OR protoPayload.methodName:"compute.firewalls.insert" 8 | OR protoPayload.methodName:"compute.firewalls.delete")` 9 | 10 | finding = audit.finding(pattern) 11 | -------------------------------------------------------------------------------- /bundle/compliance/cis_gcp/rules/cis_2_8/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_gcp.rules.cis_2_8 2 | 3 | import data.compliance.policy.gcp.monitoring.ensure_log_metric_and_alarm_exists as audit 4 | 5 | pattern := `resource.type="gce_route" 6 | AND (protoPayload.methodName:"compute.routes.delete" 7 | OR protoPayload.methodName:"compute.routes.insert")` 8 | 9 | finding = audit.finding(pattern) 10 | -------------------------------------------------------------------------------- /bundle/compliance/cis_gcp/rules/cis_2_9/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_gcp.rules.cis_2_9 2 | 3 | import data.compliance.policy.gcp.monitoring.ensure_log_metric_and_alarm_exists as audit 4 | 5 | pattern := `resource.type="gce_network" 6 | AND (protoPayload.methodName:"compute.networks.insert" 7 | OR protoPayload.methodName:"compute.networks.patch" 8 | OR protoPayload.methodName:"compute.networks.delete" 9 | OR protoPayload.methodName:"compute.networks.removePeering" 10 | OR protoPayload.methodName:"compute.networks.addPeering")` 11 | 12 | finding = audit.finding(pattern) 13 | -------------------------------------------------------------------------------- /bundle/compliance/cis_gcp/rules/cis_3_1/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_gcp.rules.cis_3_1 2 | 3 | import data.compliance.lib.common 4 | import data.compliance.policy.gcp.data_adapter 5 | 6 | # Ensure That the Default Network Does Not Exist in a Project. 7 | finding = result { 8 | # filter 9 | data_adapter.is_compute_network 10 | 11 | # set result 12 | result := common.generate_result_without_expected( 13 | common.calculate_result(is_not_default_network), 14 | data_adapter.resource, 15 | ) 16 | } 17 | 18 | is_not_default_network { 19 | not data_adapter.resource.data.name == "default" 20 | } else = false 21 | -------------------------------------------------------------------------------- /bundle/compliance/cis_gcp/rules/cis_3_2/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_gcp.rules.cis_3_2 2 | 3 | import data.compliance.lib.common 4 | import data.compliance.policy.gcp.data_adapter 5 | import future.keywords.if 6 | import future.keywords.in 7 | 8 | # Ensure Legacy Networks Do Not Exist for Older Projects 9 | finding = result if { 10 | data_adapter.is_compute_network 11 | 12 | result := common.generate_result_without_expected( 13 | common.calculate_result(is_not_legacy_network), 14 | data_adapter.resource, 15 | ) 16 | } 17 | 18 | is_not_legacy_network if { 19 | # When autoCreateSubnetworks is set to false a legacy network is being created (https://cloud.google.com/compute/docs/reference/rest/v1/networks). 20 | data_adapter.resource.data.autoCreateSubnetworks 21 | } else = false 22 | -------------------------------------------------------------------------------- /bundle/compliance/cis_gcp/rules/cis_3_3/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_gcp.rules.cis_3_3 2 | 3 | import data.compliance.lib.common 4 | import data.compliance.policy.gcp.data_adapter 5 | 6 | default is_dnssec_enabled = false 7 | 8 | # Ensure That DNSSEC Is Enabled for Cloud DNS. 9 | finding = result { 10 | # filter 11 | data_adapter.is_dns_managed_zone 12 | 13 | # only apply to public zones 14 | data_adapter.resource.data.visibility == "PUBLIC" 15 | 16 | # set result 17 | result := common.generate_result_without_expected( 18 | common.calculate_result(is_dnssec_enabled), 19 | {"Managed zone": input.resource}, 20 | ) 21 | } 22 | 23 | is_dnssec_enabled { 24 | data_adapter.resource.data.dnssecConfig.state == "ON" 25 | } 26 | -------------------------------------------------------------------------------- /bundle/compliance/cis_gcp/rules/cis_3_4/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_gcp.rules.cis_3_4 2 | 3 | import data.compliance.policy.gcp.dns.ensure_no_sha1 as audit 4 | 5 | # Ensure That RSASHA1 Is Not Used for the Key-Signing Key in Cloud DNS DNSSEC. 6 | finding = audit.finding("KEY_SIGNING") 7 | -------------------------------------------------------------------------------- /bundle/compliance/cis_gcp/rules/cis_3_5/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_gcp.rules.cis_3_5 2 | 3 | import data.compliance.policy.gcp.dns.ensure_no_sha1 as audit 4 | 5 | # Ensure That RSASHA1 Is Not Used for the Zone-Signing Key in Cloud DNS DNSSEC. 6 | finding = audit.finding("ZONE_SIGNING") 7 | -------------------------------------------------------------------------------- /bundle/compliance/cis_gcp/rules/cis_3_6/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_gcp.rules.cis_3_6 2 | 3 | import data.compliance.lib.common 4 | import data.compliance.policy.gcp.compute.ensure_fw_rule as audit 5 | import data.compliance.policy.gcp.data_adapter 6 | 7 | finding = result { 8 | # filter 9 | data_adapter.is_firewall_rule 10 | 11 | # set result 12 | result := common.generate_result_without_expected( 13 | common.calculate_result(is_rule_permissive), 14 | {"Firewall rule": data_adapter.resource}, 15 | ) 16 | } 17 | 18 | is_rule_permissive := audit.is_valid_fw_rule(22) # SSH 19 | -------------------------------------------------------------------------------- /bundle/compliance/cis_gcp/rules/cis_3_7/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_gcp.rules.cis_3_7 2 | 3 | import data.compliance.lib.common 4 | import data.compliance.policy.gcp.compute.ensure_fw_rule as audit 5 | import data.compliance.policy.gcp.data_adapter 6 | 7 | finding = result { 8 | # filter 9 | data_adapter.is_firewall_rule 10 | 11 | # set result 12 | result := common.generate_result_without_expected( 13 | common.calculate_result(is_rule_permissive), 14 | {"Firewall rule": input.resource}, 15 | ) 16 | } 17 | 18 | is_rule_permissive := audit.is_valid_fw_rule(3389) # RDP 19 | -------------------------------------------------------------------------------- /bundle/compliance/cis_gcp/rules/cis_4_1/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_gcp.rules.cis_4_1 2 | 3 | import data.compliance.lib.assert 4 | import data.compliance.lib.common 5 | import data.compliance.policy.gcp.compute.ensure_default_sa as audit 6 | import data.compliance.policy.gcp.data_adapter 7 | 8 | # Ensure That Instances Are Not Configured To Use the Default Service Account. 9 | finding = result { 10 | # filter 11 | data_adapter.is_compute_instance 12 | 13 | # set result 14 | result := common.generate_result_without_expected( 15 | common.calculate_result(assert.is_false(audit.sa_is_default)), 16 | {"Compute instance": input.resource}, 17 | ) 18 | } 19 | -------------------------------------------------------------------------------- /bundle/compliance/cis_gcp/rules/cis_4_2/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_gcp.rules.cis_4_2 2 | 3 | import data.compliance.lib.assert 4 | import data.compliance.lib.common 5 | import data.compliance.policy.gcp.compute.ensure_default_sa as audit 6 | import data.compliance.policy.gcp.data_adapter 7 | 8 | # Ensure That Instances Are Not Configured To Use the Default Service Account With Full Access to All Cloud APIs. 9 | finding = result { 10 | # filter 11 | data_adapter.is_compute_instance 12 | 13 | # set result 14 | result := common.generate_result_without_expected( 15 | common.calculate_result(assert.is_false(audit.sa_is_default_with_full_access)), 16 | {"Compute instance": input.resource}, 17 | ) 18 | } 19 | -------------------------------------------------------------------------------- /bundle/compliance/cis_gcp/rules/cis_4_3/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_gcp.rules.cis_4_3 2 | 3 | import data.compliance.lib.common 4 | import data.compliance.policy.gcp.compute.assess_instance_metadata as audit 5 | import data.compliance.policy.gcp.data_adapter 6 | 7 | # Ensure “Block Project-Wide SSH Keys” Is Enabled for VM Instances 8 | finding = result { 9 | # filter 10 | data_adapter.is_compute_instance 11 | 12 | # set result 13 | result := common.generate_result_without_expected( 14 | common.calculate_result(is_project_ssh_keys_enabled), 15 | {"Compute instance": input.resource}, 16 | ) 17 | } 18 | 19 | is_project_ssh_keys_enabled := audit.is_instance_metadata_valid("block-project-ssh-keys", "true") 20 | -------------------------------------------------------------------------------- /bundle/compliance/cis_gcp/rules/cis_4_4/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_gcp.rules.cis_4_4 2 | 3 | import data.compliance.lib.common 4 | import data.compliance.policy.gcp.compute.assess_instance_metadata as audit 5 | import data.compliance.policy.gcp.data_adapter 6 | 7 | # Ensure Oslogin Is Enabled for a Project 8 | finding = result { 9 | # filter 10 | data_adapter.is_compute_instance 11 | 12 | # VMs created by GKE should be excluded 13 | not data_adapter.is_gke_instance(data_adapter.resource.data) 14 | 15 | # set result 16 | result := common.generate_result_without_expected( 17 | common.calculate_result(is_oslogin_enabled), 18 | {"Compute instance": input.resource}, 19 | ) 20 | } 21 | 22 | is_oslogin_enabled = audit.is_instance_metadata_valid("enable-oslogin", "true") 23 | -------------------------------------------------------------------------------- /bundle/compliance/cis_gcp/rules/cis_4_5/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_gcp.rules.cis_4_5 2 | 3 | import data.compliance.lib.assert 4 | import data.compliance.lib.common 5 | import data.compliance.policy.gcp.compute.assess_instance_metadata as audit 6 | import data.compliance.policy.gcp.data_adapter 7 | 8 | # Ensure ‘Enable Connecting to Serial Ports’ Is Not Enabled for VM Instance 9 | finding = result { 10 | # filter 11 | data_adapter.is_compute_instance 12 | 13 | # set result 14 | result := common.generate_result_without_expected( 15 | common.calculate_result(assert.is_false(is_serial_port_enabled)), 16 | {"Compute instance": input.resource}, 17 | ) 18 | } 19 | 20 | is_serial_port_enabled := audit.is_instance_metadata_valid("serial-port-enable", "true") 21 | -------------------------------------------------------------------------------- /bundle/compliance/cis_gcp/rules/cis_4_6/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_gcp.rules.cis_4_6 2 | 3 | import data.compliance.lib.assert 4 | import data.compliance.lib.common 5 | import data.compliance.policy.gcp.data_adapter 6 | 7 | default is_ip_forwarding_enabled = false 8 | 9 | # Ensure That IP Forwarding Is Not Enabled on Instances 10 | finding = result { 11 | # filter 12 | data_adapter.is_compute_instance 13 | 14 | # VMs created by GKE should be excluded 15 | not data_adapter.is_gke_instance(data_adapter.resource.data) 16 | 17 | # set result 18 | result := common.generate_result_without_expected( 19 | common.calculate_result(assert.is_false(is_ip_forwarding_enabled)), 20 | {"Compute instance": input.resource}, 21 | ) 22 | } 23 | 24 | is_ip_forwarding_enabled := data_adapter.resource.data.canIpForward 25 | -------------------------------------------------------------------------------- /bundle/compliance/cis_gcp/rules/cis_4_7/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_gcp.rules.cis_4_7 2 | 3 | import data.compliance.lib.common 4 | import data.compliance.policy.gcp.data_adapter 5 | 6 | # Ensure VM Disks for Critical VMs Are Encrypted With Customer-Supplied Encryption Keys (CSEK) 7 | finding = result { 8 | # filter 9 | data_adapter.is_compute_disk 10 | 11 | # set result 12 | result := common.generate_result_without_expected( 13 | common.calculate_result(is_disk_encrypted_with_csek), 14 | {"Compute instance": data_adapter.resource}, 15 | ) 16 | } 17 | 18 | is_disk_encrypted_with_csek { 19 | data_adapter.resource.data.diskEncryptionKey.sha256 != "" 20 | } else = false 21 | -------------------------------------------------------------------------------- /bundle/compliance/cis_gcp/rules/cis_4_8/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_gcp.rules.cis_4_8 2 | 3 | import data.compliance.lib.common 4 | import data.compliance.policy.gcp.data_adapter 5 | 6 | # Ensure Compute Instances Are Launched With Shielded VM Enabled. 7 | finding = result { 8 | # filter 9 | data_adapter.is_compute_instance 10 | 11 | # set result 12 | result := common.generate_result_without_expected( 13 | common.calculate_result(is_shielded_vm), 14 | {"Compute instance": input.resource}, 15 | ) 16 | } 17 | 18 | is_shielded_vm { 19 | cfg := data_adapter.resource.data.shieldedInstanceConfig 20 | cfg.enableIntegrityMonitoring 21 | cfg.enableVtpm 22 | } else = false 23 | -------------------------------------------------------------------------------- /bundle/compliance/cis_gcp/rules/cis_4_9/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_gcp.rules.cis_4_9 2 | 3 | import data.compliance.lib.assert 4 | import data.compliance.lib.common 5 | import data.compliance.policy.gcp.data_adapter 6 | import future.keywords.in 7 | 8 | # Ensure That Compute Instances Do Not Have Public IP Addresses. 9 | finding = result { 10 | # filter 11 | data_adapter.is_compute_instance 12 | 13 | # set result 14 | result := common.generate_result_without_expected( 15 | common.calculate_result(assert.is_false(is_publicly_exposed)), 16 | {"Compute instance": input.resource}, 17 | ) 18 | } 19 | 20 | is_publicly_exposed { 21 | some networkInterface in data_adapter.resource.data.networkInterfaces 22 | networkInterface.accessConfigs 23 | } else = false 24 | -------------------------------------------------------------------------------- /bundle/compliance/cis_gcp/rules/cis_5_1/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_gcp.rules.cis_5_1 2 | 3 | import data.compliance.lib.assert 4 | import data.compliance.lib.common 5 | import data.compliance.policy.gcp.data_adapter 6 | import data.compliance.policy.gcp.iam.ensure_no_public_access as audit 7 | 8 | # Ensure That Cloud Storage Bucket Is Not Anonymously or Publicly Accessible. 9 | finding = result { 10 | # filter 11 | data_adapter.is_storage_bucket 12 | 13 | # set result 14 | result := common.generate_result_without_expected( 15 | common.calculate_result(assert.is_false(audit.resource_is_public)), 16 | {"GCS Bucket": input.resource}, 17 | ) 18 | } 19 | -------------------------------------------------------------------------------- /bundle/compliance/cis_gcp/rules/cis_5_2/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_gcp.rules.cis_5_2 2 | 3 | import data.compliance.lib.common 4 | import data.compliance.policy.gcp.data_adapter 5 | 6 | default rule_evaluation = false 7 | 8 | # Ensure That Cloud Storage Buckets Have Uniform Bucket- Level Access Enabled. 9 | finding = result { 10 | # filter 11 | data_adapter.is_storage_bucket 12 | 13 | # set result 14 | result := common.generate_result_without_expected( 15 | common.calculate_result(rule_evaluation), 16 | {"GCS Bucket": input.resource}, 17 | ) 18 | } 19 | 20 | rule_evaluation { 21 | not is_null(data_adapter.resource.data.iamConfiguration.uniformBucketLevelAccess.enabled) 22 | data_adapter.resource.data.iamConfiguration.uniformBucketLevelAccess.enabled 23 | } 24 | -------------------------------------------------------------------------------- /bundle/compliance/cis_gcp/rules/cis_6_1_2/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_gcp.rules.cis_6_1_2 2 | 3 | import data.compliance.lib.common 4 | import data.compliance.policy.gcp.data_adapter 5 | 6 | finding = result { 7 | data_adapter.is_cloud_sql 8 | data_adapter.is_cloud_my_sql 9 | 10 | result := common.generate_result_without_expected( 11 | common.calculate_result(skip_show_database_enabled), 12 | data_adapter.resource, 13 | ) 14 | } 15 | 16 | skip_show_database_enabled { 17 | flags := data_adapter.resource.data.settings.databaseFlags[_] 18 | flags.name == "skip_show_database" 19 | flags.value == "on" 20 | } else = false 21 | -------------------------------------------------------------------------------- /bundle/compliance/cis_gcp/rules/cis_6_1_3/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_gcp.rules.cis_6_1_3 2 | 3 | import data.compliance.lib.common 4 | import data.compliance.policy.gcp.data_adapter 5 | 6 | finding = result { 7 | data_adapter.is_cloud_sql 8 | data_adapter.is_cloud_my_sql 9 | 10 | result := common.generate_result_without_expected( 11 | common.calculate_result(is_local_infile_flag_disabled), 12 | data_adapter.resource, 13 | ) 14 | } 15 | 16 | is_local_infile_flag_disabled { 17 | flags := data_adapter.resource.data.settings.databaseFlags[_] 18 | flags.name == "local_infile" 19 | flags.value == "off" 20 | } else = false 21 | -------------------------------------------------------------------------------- /bundle/compliance/cis_gcp/rules/cis_6_2_2/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_gcp.rules.cis_6_2_2 2 | 3 | import data.compliance.lib.common 4 | import data.compliance.policy.gcp.data_adapter 5 | import data.compliance.policy.gcp.sql.ensure_db_flag as audit 6 | 7 | # Ensure That the ‘Log_connections’ Database Flag for Cloud SQL PostgreSQL Instance Is Set to ‘On’ 8 | finding = result { 9 | # filter 10 | data_adapter.is_cloud_sql 11 | data_adapter.is_postgres_sql 12 | 13 | # set result 14 | result := common.generate_result_without_expected( 15 | common.calculate_result(is_flag_configured_as_expected), 16 | {"DB Instance": data_adapter.resource}, 17 | ) 18 | } 19 | 20 | is_flag_configured_as_expected := audit.is_flag_configured_as_expected("log_connections", ["on"]) 21 | -------------------------------------------------------------------------------- /bundle/compliance/cis_gcp/rules/cis_6_2_3/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_gcp.rules.cis_6_2_3 2 | 3 | import data.compliance.lib.common 4 | import data.compliance.policy.gcp.data_adapter 5 | import data.compliance.policy.gcp.sql.ensure_db_flag as audit 6 | 7 | # Ensure That the ‘Log_disconnections’ Database Flag for Cloud SQL PostgreSQL Instance Is Set to ‘On’ 8 | finding = result { 9 | # filter 10 | data_adapter.is_cloud_sql 11 | data_adapter.is_postgres_sql 12 | 13 | # set result 14 | result := common.generate_result_without_expected( 15 | common.calculate_result(is_flag_configured_as_expected), 16 | {"DB Instance": data_adapter.resource}, 17 | ) 18 | } 19 | 20 | is_flag_configured_as_expected := audit.is_flag_configured_as_expected("log_disconnections", ["on"]) 21 | -------------------------------------------------------------------------------- /bundle/compliance/cis_gcp/rules/cis_6_2_4/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_gcp.rules.cis_6_2_4 2 | 3 | import data.compliance.lib.common 4 | import data.compliance.policy.gcp.data_adapter 5 | import data.compliance.policy.gcp.sql.ensure_db_flag as audit 6 | 7 | # Ensure ‘Log_statement’ Database Flag for Cloud SQL PostgreSQL Instance Is Set Appropriately. 8 | finding = result { 9 | # filter 10 | data_adapter.is_cloud_sql 11 | data_adapter.is_postgres_sql 12 | 13 | # set result 14 | result := common.generate_result_without_expected( 15 | common.calculate_result(is_flag_configured_as_expected), 16 | {"DB Instance": data_adapter.resource}, 17 | ) 18 | } 19 | 20 | is_flag_configured_as_expected := audit.is_flag_configured_as_expected("log_statement", ["ddl"]) 21 | -------------------------------------------------------------------------------- /bundle/compliance/cis_gcp/rules/cis_6_2_8/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_gcp.rules.cis_6_2_8 2 | 3 | import data.compliance.lib.common 4 | import data.compliance.policy.gcp.data_adapter 5 | import data.compliance.policy.gcp.sql.ensure_db_flag as audit 6 | 7 | # Ensure That 'cloudsql.enable_pgaudit' Database Flag for each Cloud Sql Postgresql Instance Is Set to 'on' For Centralized Logging. 8 | finding = result { 9 | # filter 10 | data_adapter.is_cloud_sql 11 | data_adapter.is_postgres_sql 12 | 13 | # set result 14 | result := common.generate_result_without_expected( 15 | common.calculate_result(is_flag_as_expected), 16 | {"DB Instance": data_adapter.resource}, 17 | ) 18 | } 19 | 20 | is_flag_as_expected := audit.is_flag_configured_as_expected("cloudsql.enable_pgaudit", ["on"]) 21 | -------------------------------------------------------------------------------- /bundle/compliance/cis_gcp/rules/cis_6_2_9/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_gcp.rules.cis_6_2_9 2 | 3 | import data.compliance.lib.common 4 | import data.compliance.policy.gcp.data_adapter 5 | import data.compliance.policy.gcp.sql.ensure_private_ip as audit 6 | 7 | # Ensure Instance IP assignment is set to private. 8 | finding = result { 9 | # filter 10 | data_adapter.is_cloud_sql 11 | data_adapter.is_postgres_sql 12 | 13 | # set result 14 | result := common.generate_result_without_expected( 15 | common.calculate_result(audit.ip_is_private), 16 | data_adapter.resource, 17 | ) 18 | } 19 | -------------------------------------------------------------------------------- /bundle/compliance/cis_gcp/rules/cis_6_3_1/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_gcp.rules.cis_6_3_1 2 | 3 | import data.compliance.lib.assert 4 | import data.compliance.lib.common 5 | import data.compliance.policy.gcp.data_adapter 6 | import data.compliance.policy.gcp.sql.ensure_db_flag as audit 7 | 8 | finding = result { 9 | # filter 10 | data_adapter.is_cloud_sql 11 | data_adapter.is_sql_server 12 | 13 | # set result 14 | result := common.generate_result_without_expected( 15 | common.calculate_result(assert.is_false(is_flag_configured_as_expected)), 16 | {"DB Instance": data_adapter.resource}, 17 | ) 18 | } 19 | 20 | is_flag_configured_as_expected := audit.is_flag_configured_as_expected("external scripts enabled", ["on"]) 21 | -------------------------------------------------------------------------------- /bundle/compliance/cis_gcp/rules/cis_6_3_2/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_gcp.rules.cis_6_3_2 2 | 3 | import data.compliance.lib.assert 4 | import data.compliance.lib.common 5 | import data.compliance.policy.gcp.data_adapter 6 | import data.compliance.policy.gcp.sql.ensure_db_flag as audit 7 | 8 | finding = result { 9 | # filter 10 | data_adapter.is_cloud_sql 11 | data_adapter.is_sql_server 12 | 13 | # set result 14 | result := common.generate_result_without_expected( 15 | common.calculate_result(assert.is_false(is_flag_configured_as_expected)), 16 | {"DB Instance": data_adapter.resource}, 17 | ) 18 | } 19 | 20 | is_flag_configured_as_expected := audit.is_flag_configured_as_expected("cross db ownership chaining", ["on"]) 21 | -------------------------------------------------------------------------------- /bundle/compliance/cis_gcp/rules/cis_6_3_3/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_gcp.rules.cis_6_3_3 2 | 3 | import data.compliance.lib.assert 4 | import data.compliance.lib.common 5 | import data.compliance.policy.gcp.data_adapter 6 | import data.compliance.policy.gcp.sql.ensure_db_flag as audit 7 | 8 | finding = result { 9 | # filter 10 | data_adapter.is_cloud_sql 11 | data_adapter.is_sql_server 12 | 13 | # set result 14 | result := common.generate_result_without_expected( 15 | common.calculate_result(assert.is_false(is_flag_limited)), 16 | {"DB Instance": data_adapter.resource}, 17 | ) 18 | } 19 | 20 | is_flag_limited = audit.is_flag_limited("user connections") 21 | -------------------------------------------------------------------------------- /bundle/compliance/cis_gcp/rules/cis_6_3_4/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_gcp.rules.cis_6_3_4 2 | 3 | import data.compliance.lib.assert 4 | import data.compliance.lib.common 5 | import data.compliance.policy.gcp.data_adapter 6 | import data.compliance.policy.gcp.sql.ensure_db_flag as audit 7 | 8 | finding = result { 9 | # filter 10 | data_adapter.is_cloud_sql 11 | data_adapter.is_sql_server 12 | 13 | # set result 14 | result := common.generate_result_without_expected( 15 | common.calculate_result(assert.is_false(is_flag_exists)), 16 | {"DB Instance": data_adapter.resource}, 17 | ) 18 | } 19 | 20 | is_flag_exists = audit.is_flag_exists("user options") 21 | -------------------------------------------------------------------------------- /bundle/compliance/cis_gcp/rules/cis_6_3_5/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_gcp.rules.cis_6_3_5 2 | 3 | import data.compliance.lib.assert 4 | import data.compliance.lib.common 5 | import data.compliance.policy.gcp.data_adapter 6 | import data.compliance.policy.gcp.sql.ensure_db_flag as audit 7 | 8 | finding = result { 9 | # filter 10 | data_adapter.is_cloud_sql 11 | data_adapter.is_sql_server 12 | 13 | # set result 14 | result := common.generate_result_without_expected( 15 | common.calculate_result(assert.is_false(is_flag_configured_as_expected)), 16 | {"DB Instance": data_adapter.resource}, 17 | ) 18 | } 19 | 20 | is_flag_configured_as_expected := audit.is_flag_configured_as_expected("remote access", ["on"]) 21 | -------------------------------------------------------------------------------- /bundle/compliance/cis_gcp/rules/cis_6_3_6/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_gcp.rules.cis_6_3_6 2 | 3 | import data.compliance.lib.common 4 | import data.compliance.policy.gcp.data_adapter 5 | import data.compliance.policy.gcp.sql.ensure_db_flag as audit 6 | 7 | finding = result { 8 | # filter 9 | data_adapter.is_cloud_sql 10 | data_adapter.is_sql_server 11 | 12 | # set result 13 | result := common.generate_result_without_expected( 14 | common.calculate_result(is_flag_configured_as_expected), 15 | {"DB Instance": data_adapter.resource}, 16 | ) 17 | } 18 | 19 | is_flag_configured_as_expected := audit.is_flag_configured_as_expected("3625", ["on"]) #trace flag 20 | -------------------------------------------------------------------------------- /bundle/compliance/cis_gcp/rules/cis_6_3_7/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_gcp.rules.cis_6_3_7 2 | 3 | import data.compliance.lib.assert 4 | import data.compliance.lib.common 5 | import data.compliance.policy.gcp.data_adapter 6 | import data.compliance.policy.gcp.sql.ensure_db_flag as audit 7 | 8 | finding = result { 9 | # filter 10 | data_adapter.is_cloud_sql 11 | data_adapter.is_sql_server 12 | 13 | # set result 14 | result := common.generate_result_without_expected( 15 | common.calculate_result(assert.is_false(is_flag_configured_as_expected)), 16 | {"DB Instance": data_adapter.resource}, 17 | ) 18 | } 19 | 20 | is_flag_configured_as_expected := audit.is_flag_configured_as_expected("contained database authentication", ["on"]) 21 | -------------------------------------------------------------------------------- /bundle/compliance/cis_gcp/rules/cis_6_5/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_gcp.rules.cis_6_5 2 | 3 | import data.compliance.lib.assert 4 | import data.compliance.lib.common 5 | import data.compliance.policy.gcp.data_adapter 6 | import future.keywords.if 7 | import future.keywords.in 8 | 9 | finding = result if { 10 | data_adapter.is_sql_instance 11 | 12 | result := common.generate_result_without_expected( 13 | common.calculate_result(assert.is_false(is_publicly_accessible)), 14 | data_adapter.resource, 15 | ) 16 | } 17 | 18 | is_publicly_accessible if { 19 | networks := object.get( 20 | data_adapter.resource.data.settings, 21 | ["ipConfiguration", "authorizedNetworks"], 22 | [{"value": ""}], 23 | ) 24 | networks[i].value == "0.0.0.0/0" 25 | } else = false 26 | -------------------------------------------------------------------------------- /bundle/compliance/cis_gcp/rules/cis_6_6/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_gcp.rules.cis_6_6 2 | 3 | import data.compliance.lib.common 4 | import data.compliance.policy.gcp.data_adapter 5 | import data.compliance.policy.gcp.sql.ensure_private_ip as audit 6 | 7 | finding = result { 8 | data_adapter.is_sql_instance 9 | is_clous_sql_instance_second_gen 10 | 11 | result := common.generate_result_without_expected( 12 | common.calculate_result(audit.ip_is_private), 13 | data_adapter.resource, 14 | ) 15 | } 16 | 17 | is_clous_sql_instance_second_gen { 18 | data_adapter.resource.data.instanceType == "CLOUD_SQL_INSTANCE" 19 | data_adapter.resource.data.backendType == "SECOND_GEN" 20 | } 21 | -------------------------------------------------------------------------------- /bundle/compliance/cis_gcp/rules/cis_6_7/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_gcp.rules.cis_6_7 2 | 3 | import data.compliance.lib.common 4 | import data.compliance.policy.gcp.data_adapter 5 | import future.keywords.if 6 | 7 | finding = result if { 8 | data_adapter.is_sql_instance 9 | 10 | result := common.generate_result_without_expected( 11 | common.calculate_result(backup_enabled), 12 | data_adapter.resource, 13 | ) 14 | } 15 | 16 | backup_enabled if { 17 | data_adapter.resource.data.settings.backupConfiguration.enabled == true 18 | } else = false 19 | -------------------------------------------------------------------------------- /bundle/compliance/cis_gcp/rules/cis_7_1/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_gcp.rules.cis_7_1 2 | 3 | import data.compliance.lib.assert 4 | import data.compliance.lib.common 5 | import data.compliance.policy.gcp.data_adapter 6 | import data.compliance.policy.gcp.iam.ensure_no_public_access as audit 7 | 8 | # Ensure That BigQuery Datasets Are Not Anonymously or Publicly Accessible. 9 | finding = result { 10 | # filter 11 | data_adapter.is_bigquery_dataset 12 | 13 | # set result 14 | result := common.generate_result_without_expected( 15 | common.calculate_result(assert.is_false(audit.resource_is_public)), 16 | {"BigQuery Dataset": input.resource}, 17 | ) 18 | } 19 | -------------------------------------------------------------------------------- /bundle/compliance/cis_gcp/rules/cis_7_2/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_gcp.rules.cis_7_2 2 | 3 | import data.compliance.lib.common 4 | import data.compliance.policy.gcp.bq.ensure_cmek_is_used as audit 5 | import data.compliance.policy.gcp.data_adapter 6 | 7 | # Ensure That All BigQuery Tables Are Encrypted With Customer-Managed Encryption Keys (CMEK). 8 | finding = result { 9 | # filter 10 | data_adapter.is_bigquery_table 11 | 12 | # set result 13 | result := common.generate_result_without_expected( 14 | common.calculate_result(audit.is_cmek_used), 15 | {"BigQuery Table": input.resource}, 16 | ) 17 | } 18 | -------------------------------------------------------------------------------- /bundle/compliance/cis_gcp/rules/cis_7_3/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_gcp.rules.cis_7_3 2 | 3 | import data.compliance.lib.common 4 | import data.compliance.policy.gcp.bq.ensure_cmek_is_used as audit 5 | import data.compliance.policy.gcp.data_adapter 6 | 7 | # Ensure That a Default Customer-Managed Encryption Key (CMEK) Is Specified for All BigQuery Data Sets. 8 | finding = result { 9 | # filter 10 | data_adapter.is_bigquery_dataset 11 | 12 | # set result 13 | result := common.generate_result_without_expected( 14 | common.calculate_result(audit.is_cmek_used), 15 | {"BigQuery Dataset": input.resource}, 16 | ) 17 | } 18 | -------------------------------------------------------------------------------- /bundle/compliance/cis_k8s/data_adapter.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_k8s.data_adapter 2 | 3 | import data.compliance.policy.process.data_adapter as process_data_adapter 4 | 5 | process_args := process_data_adapter.process_args 6 | -------------------------------------------------------------------------------- /bundle/compliance/cis_k8s/rules/cis_1_1_1/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_k8s.rules.cis_1_1_1 2 | 3 | import data.compliance.policy.file.ensure_permissions as audit 4 | 5 | finding = result { 6 | audit.filename_filter("kube-apiserver.yaml") 7 | result := audit.finding(audit.file_permission_match(6, 4, 4)) 8 | } 9 | -------------------------------------------------------------------------------- /bundle/compliance/cis_k8s/rules/cis_1_1_1/test.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_k8s.rules.cis_1_1_1 2 | 3 | import data.kubernetes_common.test_data 4 | import data.lib.test 5 | 6 | test_violation { 7 | test.assert_fail(finding) with input as rule_input("kube-apiserver.yaml", "700") 8 | } 9 | 10 | test_pass { 11 | test.assert_pass(finding) with input as rule_input("kube-apiserver.yaml", "644") 12 | } 13 | 14 | test_not_evaluated { 15 | not finding with input as rule_input("file.txt", "644") 16 | } 17 | 18 | rule_input(filename, filemode) = filesystem_input { 19 | user := "root" 20 | group := "root" 21 | filesystem_input = test_data.filesystem_input(filename, filemode, user, group) 22 | } 23 | -------------------------------------------------------------------------------- /bundle/compliance/cis_k8s/rules/cis_1_1_11/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_k8s.rules.cis_1_1_11 2 | 3 | import data.compliance.policy.file.ensure_permissions as audit 4 | 5 | finding = result { 6 | audit.path_filter("/var/lib/etcd/") 7 | result := audit.finding(audit.file_permission_match(7, 0, 0)) 8 | } 9 | -------------------------------------------------------------------------------- /bundle/compliance/cis_k8s/rules/cis_1_1_12/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_k8s.rules.cis_1_1_12 2 | 3 | import data.compliance.policy.file.ensure_ownership as audit 4 | 5 | finding = result { 6 | audit.path_filter("/var/lib/etcd/") 7 | result := audit.finding("etcd", "etcd") 8 | } 9 | -------------------------------------------------------------------------------- /bundle/compliance/cis_k8s/rules/cis_1_1_13/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_k8s.rules.cis_1_1_13 2 | 3 | import data.compliance.policy.file.ensure_permissions as audit 4 | 5 | finding = result { 6 | audit.filename_filter("admin.conf") 7 | result := audit.finding(audit.file_permission_match(6, 0, 0)) 8 | } 9 | -------------------------------------------------------------------------------- /bundle/compliance/cis_k8s/rules/cis_1_1_13/test.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_k8s.rules.cis_1_1_13 2 | 3 | import data.kubernetes_common.test_data 4 | import data.lib.test 5 | 6 | test_violation { 7 | test.assert_fail(finding) with input as rule_input("admin.conf", "700") 8 | } 9 | 10 | test_violation_too { 11 | test.assert_fail(finding) with input as rule_input("admin.conf", "644") 12 | } 13 | 14 | test_pass { 15 | test.assert_pass(finding) with input as rule_input("admin.conf", "600") 16 | } 17 | 18 | test_not_evaluated { 19 | not finding with input as rule_input("file.txt", "644") 20 | } 21 | 22 | rule_input(filename, filemode) = filesystem_input { 23 | user := "root" 24 | group := "root" 25 | filesystem_input = test_data.filesystem_input(filename, filemode, user, group) 26 | } 27 | -------------------------------------------------------------------------------- /bundle/compliance/cis_k8s/rules/cis_1_1_14/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_k8s.rules.cis_1_1_14 2 | 3 | import data.compliance.policy.file.ensure_ownership as audit 4 | 5 | finding = result { 6 | audit.filename_filter("admin.conf") 7 | result := audit.finding("root", "root") 8 | } 9 | -------------------------------------------------------------------------------- /bundle/compliance/cis_k8s/rules/cis_1_1_14/test.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_k8s.rules.cis_1_1_14 2 | 3 | import data.kubernetes_common.test_data 4 | import data.lib.test 5 | 6 | test_violation { 7 | test.assert_fail(finding) with input as rule_input("admin.conf", "root", "user") 8 | test.assert_fail(finding) with input as rule_input("admin.conf", "user", "root") 9 | test.assert_fail(finding) with input as rule_input("admin.conf", "user", "user") 10 | } 11 | 12 | test_pass { 13 | test.assert_pass(finding) with input as rule_input("admin.conf", "root", "root") 14 | } 15 | 16 | test_not_evaluated { 17 | not finding with input as rule_input("file.txt", "root", "root") 18 | } 19 | 20 | rule_input(filename, user, group) = filesystem_input { 21 | filemode := "644" 22 | filesystem_input = test_data.filesystem_input(filename, filemode, user, group) 23 | } 24 | -------------------------------------------------------------------------------- /bundle/compliance/cis_k8s/rules/cis_1_1_15/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_k8s.rules.cis_1_1_15 2 | 3 | import data.compliance.policy.file.ensure_permissions as audit 4 | 5 | finding = result { 6 | audit.filename_filter("scheduler.conf") 7 | result := audit.finding(audit.file_permission_match(6, 4, 4)) 8 | } 9 | -------------------------------------------------------------------------------- /bundle/compliance/cis_k8s/rules/cis_1_1_15/test.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_k8s.rules.cis_1_1_15 2 | 3 | import data.kubernetes_common.test_data 4 | import data.lib.test 5 | 6 | test_violation { 7 | test.assert_fail(finding) with input as rule_input("scheduler.conf", "700") 8 | } 9 | 10 | test_pass { 11 | test.assert_pass(finding) with input as rule_input("scheduler.conf", "644") 12 | } 13 | 14 | test_not_evaluated { 15 | not finding with input as rule_input("file.txt", "644") 16 | } 17 | 18 | rule_input(filename, filemode) = filesystem_input { 19 | user := "root" 20 | group := "root" 21 | filesystem_input = test_data.filesystem_input(filename, filemode, user, group) 22 | } 23 | -------------------------------------------------------------------------------- /bundle/compliance/cis_k8s/rules/cis_1_1_16/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_k8s.rules.cis_1_1_16 2 | 3 | import data.compliance.policy.file.ensure_ownership as audit 4 | 5 | finding = result { 6 | audit.filename_filter("scheduler.conf") 7 | result := audit.finding("root", "root") 8 | } 9 | -------------------------------------------------------------------------------- /bundle/compliance/cis_k8s/rules/cis_1_1_16/test.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_k8s.rules.cis_1_1_16 2 | 3 | import data.kubernetes_common.test_data 4 | import data.lib.test 5 | 6 | test_violation { 7 | test.assert_fail(finding) with input as rule_input("scheduler.conf", "root", "user") 8 | test.assert_fail(finding) with input as rule_input("scheduler.conf", "user", "root") 9 | test.assert_fail(finding) with input as rule_input("scheduler.conf", "user", "user") 10 | } 11 | 12 | test_pass { 13 | test.assert_pass(finding) with input as rule_input("scheduler.conf", "root", "root") 14 | } 15 | 16 | test_not_evaluated { 17 | not finding with input as rule_input("file.txt", "root", "root") 18 | } 19 | 20 | rule_input(filename, user, group) = filesystem_input { 21 | filemode := "644" 22 | filesystem_input = test_data.filesystem_input(filename, filemode, user, group) 23 | } 24 | -------------------------------------------------------------------------------- /bundle/compliance/cis_k8s/rules/cis_1_1_17/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_k8s.rules.cis_1_1_17 2 | 3 | import data.compliance.policy.file.ensure_permissions as audit 4 | 5 | finding = result { 6 | audit.filename_filter("controller-manager.conf") 7 | result := audit.finding(audit.file_permission_match(6, 4, 4)) 8 | } 9 | -------------------------------------------------------------------------------- /bundle/compliance/cis_k8s/rules/cis_1_1_17/test.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_k8s.rules.cis_1_1_17 2 | 3 | import data.kubernetes_common.test_data 4 | import data.lib.test 5 | 6 | test_violation { 7 | test.assert_fail(finding) with input as rule_input("controller-manager.conf", "700") 8 | } 9 | 10 | test_pass { 11 | test.assert_pass(finding) with input as rule_input("controller-manager.conf", "644") 12 | } 13 | 14 | test_not_evaluated { 15 | not finding with input as rule_input("file.txt", "644") 16 | } 17 | 18 | rule_input(filename, filemode) = filesystem_input { 19 | user := "root" 20 | group := "root" 21 | filesystem_input = test_data.filesystem_input(filename, filemode, user, group) 22 | } 23 | -------------------------------------------------------------------------------- /bundle/compliance/cis_k8s/rules/cis_1_1_18/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_k8s.rules.cis_1_1_18 2 | 3 | import data.compliance.policy.file.ensure_ownership as audit 4 | 5 | finding = result { 6 | audit.filename_filter("controller-manager.conf") 7 | result := audit.finding("root", "root") 8 | } 9 | -------------------------------------------------------------------------------- /bundle/compliance/cis_k8s/rules/cis_1_1_19/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_k8s.rules.cis_1_1_19 2 | 3 | import data.compliance.policy.file.ensure_ownership as audit 4 | 5 | finding = result { 6 | audit.path_filter("/etc/kubernetes/pki/") 7 | result := audit.finding("root", "root") 8 | } 9 | -------------------------------------------------------------------------------- /bundle/compliance/cis_k8s/rules/cis_1_1_2/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_k8s.rules.cis_1_1_2 2 | 3 | import data.compliance.policy.file.ensure_ownership as audit 4 | 5 | finding = result { 6 | audit.filename_filter("kube-apiserver.yaml") 7 | result := audit.finding("root", "root") 8 | } 9 | -------------------------------------------------------------------------------- /bundle/compliance/cis_k8s/rules/cis_1_1_20/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_k8s.rules.cis_1_1_20 2 | 3 | import data.compliance.policy.file.ensure_permissions as audit 4 | 5 | finding = result { 6 | audit.path_filter("/etc/kubernetes/pki") 7 | audit.filename_suffix_filter(".crt") 8 | result := audit.finding(audit.file_permission_match(6, 4, 4)) 9 | } 10 | -------------------------------------------------------------------------------- /bundle/compliance/cis_k8s/rules/cis_1_1_20/test.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_k8s.rules.cis_1_1_20 2 | 3 | import data.kubernetes_common.test_data 4 | import data.lib.test 5 | 6 | test_violation { 7 | test.assert_fail(finding) with input as rule_input("/etc/kubernetes/pki/client.crt", "700") 8 | } 9 | 10 | test_pass { 11 | test.assert_pass(finding) with input as rule_input("/etc/kubernetes/pki/client.crt", "644") 12 | } 13 | 14 | test_not_evaluated { 15 | not finding with input as rule_input("/etc/kubernetes/pki/client.key", "644") 16 | } 17 | 18 | rule_input(filename, filemode) = filesystem_input { 19 | user := "root" 20 | group := "root" 21 | filesystem_input = test_data.filesystem_input(filename, filemode, user, group) 22 | } 23 | -------------------------------------------------------------------------------- /bundle/compliance/cis_k8s/rules/cis_1_1_21/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_k8s.rules.cis_1_1_21 2 | 3 | import data.compliance.policy.file.ensure_permissions as audit 4 | 5 | finding = result { 6 | audit.path_filter("/etc/kubernetes/pki") 7 | audit.filename_suffix_filter(".key") 8 | result := audit.finding(audit.file_permission_match_exact(6, 0, 0)) 9 | } 10 | -------------------------------------------------------------------------------- /bundle/compliance/cis_k8s/rules/cis_1_1_21/test.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_k8s.rules.cis_1_1_21 2 | 3 | import data.kubernetes_common.test_data 4 | import data.lib.test 5 | 6 | test_violation { 7 | test.assert_fail(finding) with input as rule_input("/etc/kubernetes/pki/client.key", "700") 8 | } 9 | 10 | test_pass { 11 | test.assert_pass(finding) with input as rule_input("/etc/kubernetes/pki/client.key", "600") 12 | } 13 | 14 | test_not_evaluated { 15 | not finding with input as rule_input("/etc/kubernetes/pki/client.crt", "600") 16 | } 17 | 18 | rule_input(filename, filemode) = filesystem_input { 19 | user := "root" 20 | group := "root" 21 | filesystem_input = test_data.filesystem_input(filename, filemode, user, group) 22 | } 23 | -------------------------------------------------------------------------------- /bundle/compliance/cis_k8s/rules/cis_1_1_3/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_k8s.rules.cis_1_1_3 2 | 3 | import data.compliance.policy.file.ensure_permissions as audit 4 | 5 | finding = result { 6 | audit.filename_filter("kube-controller-manager.yaml") 7 | result := audit.finding(audit.file_permission_match(6, 4, 4)) 8 | } 9 | -------------------------------------------------------------------------------- /bundle/compliance/cis_k8s/rules/cis_1_1_3/test.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_k8s.rules.cis_1_1_3 2 | 3 | import data.kubernetes_common.test_data 4 | import data.lib.test 5 | 6 | test_violation { 7 | test.assert_fail(finding) with input as rule_input("kube-controller-manager.yaml", "700") 8 | } 9 | 10 | test_pass { 11 | test.assert_pass(finding) with input as rule_input("kube-controller-manager.yaml", "644") 12 | } 13 | 14 | test_not_evaluated { 15 | not finding with input as rule_input("file.txt", "644") 16 | } 17 | 18 | rule_input(filename, filemode) = filesystem_input { 19 | user := "root" 20 | group := "root" 21 | filesystem_input = test_data.filesystem_input(filename, filemode, user, group) 22 | } 23 | -------------------------------------------------------------------------------- /bundle/compliance/cis_k8s/rules/cis_1_1_4/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_k8s.rules.cis_1_1_4 2 | 3 | import data.compliance.policy.file.ensure_ownership as audit 4 | 5 | finding = result { 6 | audit.filename_filter("kube-controller-manager.yaml") 7 | result := audit.finding("root", "root") 8 | } 9 | -------------------------------------------------------------------------------- /bundle/compliance/cis_k8s/rules/cis_1_1_5/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_k8s.rules.cis_1_1_5 2 | 3 | import data.compliance.policy.file.ensure_permissions as audit 4 | 5 | finding = result { 6 | audit.filename_filter("kube-scheduler.yaml") 7 | result := audit.finding(audit.file_permission_match(6, 4, 4)) 8 | } 9 | -------------------------------------------------------------------------------- /bundle/compliance/cis_k8s/rules/cis_1_1_5/test.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_k8s.rules.cis_1_1_5 2 | 3 | import data.kubernetes_common.test_data 4 | import data.lib.test 5 | 6 | test_violation { 7 | test.assert_fail(finding) with input as rule_input("kube-scheduler.yaml", "700") 8 | } 9 | 10 | test_pass { 11 | test.assert_pass(finding) with input as rule_input("kube-scheduler.yaml", "644") 12 | } 13 | 14 | test_not_evaluated { 15 | not finding with input as rule_input("file.txt", "644") 16 | } 17 | 18 | rule_input(filename, filemode) = filesystem_input { 19 | user := "root" 20 | group := "root" 21 | filesystem_input = test_data.filesystem_input(filename, filemode, user, group) 22 | } 23 | -------------------------------------------------------------------------------- /bundle/compliance/cis_k8s/rules/cis_1_1_6/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_k8s.rules.cis_1_1_6 2 | 3 | import data.compliance.policy.file.ensure_ownership as audit 4 | 5 | finding = result { 6 | audit.filename_filter("kube-scheduler.yaml") 7 | result := audit.finding("root", "root") 8 | } 9 | -------------------------------------------------------------------------------- /bundle/compliance/cis_k8s/rules/cis_1_1_7/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_k8s.rules.cis_1_1_7 2 | 3 | import data.compliance.policy.file.ensure_permissions as audit 4 | 5 | finding = result { 6 | audit.filename_filter("etcd.yaml") 7 | result := audit.finding(audit.file_permission_match(6, 4, 4)) 8 | } 9 | -------------------------------------------------------------------------------- /bundle/compliance/cis_k8s/rules/cis_1_1_7/test.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_k8s.rules.cis_1_1_7 2 | 3 | import data.kubernetes_common.test_data 4 | import data.lib.test 5 | 6 | test_violation { 7 | test.assert_fail(finding) with input as rule_input("etcd.yaml", "700") 8 | } 9 | 10 | test_pass { 11 | test.assert_pass(finding) with input as rule_input("etcd.yaml", "644") 12 | } 13 | 14 | test_not_evaluated { 15 | not finding with input as rule_input("file.txt", "644") 16 | } 17 | 18 | rule_input(filename, filemode) = filesystem_input { 19 | user := "root" 20 | group := "root" 21 | filesystem_input = test_data.filesystem_input(filename, filemode, user, group) 22 | } 23 | -------------------------------------------------------------------------------- /bundle/compliance/cis_k8s/rules/cis_1_1_8/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_k8s.rules.cis_1_1_8 2 | 3 | import data.compliance.policy.file.ensure_ownership as audit 4 | 5 | finding = result { 6 | audit.filename_filter("etcd.yaml") 7 | result := audit.finding("root", "root") 8 | } 9 | -------------------------------------------------------------------------------- /bundle/compliance/cis_k8s/rules/cis_1_1_8/test.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_k8s.rules.cis_1_1_8 2 | 3 | import data.kubernetes_common.test_data 4 | import data.lib.test 5 | 6 | test_violation { 7 | test.assert_fail(finding) with input as rule_input("etcd.yaml", "root", "user") 8 | test.assert_fail(finding) with input as rule_input("etcd.yaml", "user", "root") 9 | test.assert_fail(finding) with input as rule_input("etcd.yaml", "user", "user") 10 | } 11 | 12 | test_pass { 13 | test.assert_pass(finding) with input as rule_input("etcd.yaml", "root", "root") 14 | } 15 | 16 | test_not_evaluated { 17 | not finding with input as rule_input("file.txt", "root", "root") 18 | } 19 | 20 | rule_input(filename, user, group) = filesystem_input { 21 | filemode := "644" 22 | filesystem_input = test_data.filesystem_input(filename, filemode, user, group) 23 | } 24 | -------------------------------------------------------------------------------- /bundle/compliance/cis_k8s/rules/cis_1_2_10/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_k8s.rules.cis_1_2_10 2 | 3 | import data.compliance.policy.process.ensure_arguments_contain_value as audit 4 | 5 | finding = result { 6 | result := audit.finding(audit.contains("--enable-admission-plugins", "EventRateLimit")) 7 | } 8 | -------------------------------------------------------------------------------- /bundle/compliance/cis_k8s/rules/cis_1_2_11/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_k8s.rules.cis_1_2_11 2 | 3 | import data.compliance.policy.process.ensure_arguments_contain_value as audit 4 | 5 | finding = result { 6 | result := audit.finding(audit.not_contains("--enable-admission-plugins", "AlwaysAdmit")) 7 | } 8 | -------------------------------------------------------------------------------- /bundle/compliance/cis_k8s/rules/cis_1_2_12/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_k8s.rules.cis_1_2_12 2 | 3 | import data.compliance.policy.process.ensure_arguments_contain_value as audit 4 | 5 | finding = result { 6 | result := audit.finding(audit.contains("--enable-admission-plugins", "AlwaysPullImages")) 7 | } 8 | -------------------------------------------------------------------------------- /bundle/compliance/cis_k8s/rules/cis_1_2_13/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_k8s.rules.cis_1_2_13 2 | 3 | import data.compliance.policy.process.ensure_arguments_not_contain_multiple_values as audit 4 | 5 | finding := audit.finding 6 | -------------------------------------------------------------------------------- /bundle/compliance/cis_k8s/rules/cis_1_2_14/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_k8s.rules.cis_1_2_14 2 | 3 | import data.compliance.policy.process.ensure_arguments_not_contain_value_appropriate as audit 4 | 5 | finding = result { 6 | result := audit.finding("--disable-admission-plugins", "ServiceAccount") 7 | } 8 | -------------------------------------------------------------------------------- /bundle/compliance/cis_k8s/rules/cis_1_2_15/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_k8s.rules.cis_1_2_15 2 | 3 | import data.compliance.policy.process.ensure_arguments_not_contain_value_appropriate as audit 4 | 5 | finding = result { 6 | result := audit.finding("--disable-admission-plugins", "NamespaceLifecycle") 7 | } 8 | -------------------------------------------------------------------------------- /bundle/compliance/cis_k8s/rules/cis_1_2_16/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_k8s.rules.cis_1_2_16 2 | 3 | import data.compliance.policy.process.ensure_arguments_contain_value as audit 4 | 5 | finding = result { 6 | result := audit.finding(audit.contains("--enable-admission-plugins", "NodeRestriction")) 7 | } 8 | -------------------------------------------------------------------------------- /bundle/compliance/cis_k8s/rules/cis_1_2_17/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_k8s.rules.cis_1_2_17 2 | 3 | import data.compliance.policy.process.ensure_arguments_contain_key_value as audit 4 | 5 | finding = result { 6 | audit.apiserver_filter 7 | result := audit.finding(audit.not_contains("--secure-port", "0")) 8 | } 9 | -------------------------------------------------------------------------------- /bundle/compliance/cis_k8s/rules/cis_1_2_18/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_k8s.rules.cis_1_2_18 2 | 3 | import data.compliance.policy.process.ensure_arguments_contain_key_value as audit 4 | 5 | finding = result { 6 | audit.apiserver_filter 7 | result := audit.finding(audit.contains("--profiling", "false")) 8 | } 9 | -------------------------------------------------------------------------------- /bundle/compliance/cis_k8s/rules/cis_1_2_19/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_k8s.rules.cis_1_2_19 2 | 3 | import data.compliance.policy.process.ensure_arguments_contain_key as audit 4 | 5 | finding = result { 6 | audit.apiserver_filter 7 | result := audit.finding(audit.contains("--audit-log-path")) 8 | } 9 | -------------------------------------------------------------------------------- /bundle/compliance/cis_k8s/rules/cis_1_2_2/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_k8s.rules.cis_1_2_2 2 | 3 | import data.compliance.policy.process.ensure_arguments_contain_key as audit 4 | 5 | finding = result { 6 | audit.apiserver_filter 7 | result := audit.finding(audit.not_contains("--token-auth-file")) 8 | } 9 | -------------------------------------------------------------------------------- /bundle/compliance/cis_k8s/rules/cis_1_2_20/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_k8s.rules.cis_1_2_20 2 | 3 | import data.compliance.policy.process.ensure_arguments_goe as audit 4 | 5 | finding = audit.finding("--audit-log-maxage", 30) 6 | -------------------------------------------------------------------------------- /bundle/compliance/cis_k8s/rules/cis_1_2_21/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_k8s.rules.cis_1_2_21 2 | 3 | import data.compliance.policy.process.ensure_arguments_goe as audit 4 | 5 | finding = audit.finding("--audit-log-maxbackup", 10) 6 | -------------------------------------------------------------------------------- /bundle/compliance/cis_k8s/rules/cis_1_2_22/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_k8s.rules.cis_1_2_22 2 | 3 | import data.compliance.policy.process.ensure_arguments_goe as audit 4 | 5 | finding = audit.finding("--audit-log-maxsize", 100) 6 | -------------------------------------------------------------------------------- /bundle/compliance/cis_k8s/rules/cis_1_2_23/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_k8s.rules.cis_1_2_23 2 | 3 | import data.compliance.policy.process.ensure_arguments_lte as audit 4 | 5 | finding = audit.finding("--request-timeout", "60s") 6 | -------------------------------------------------------------------------------- /bundle/compliance/cis_k8s/rules/cis_1_2_24/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_k8s.rules.cis_1_2_24 2 | 3 | import data.compliance.policy.process.ensure_arguments_if_contain_equal as audit 4 | 5 | finding = audit.finding 6 | -------------------------------------------------------------------------------- /bundle/compliance/cis_k8s/rules/cis_1_2_25/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_k8s.rules.cis_1_2_25 2 | 3 | import data.compliance.policy.process.ensure_arguments_contain_key as audit 4 | 5 | finding = result { 6 | audit.apiserver_filter 7 | result := audit.finding(audit.contains("--service-account-key-file")) 8 | } 9 | -------------------------------------------------------------------------------- /bundle/compliance/cis_k8s/rules/cis_1_2_26/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_k8s.rules.cis_1_2_26 2 | 3 | import data.compliance.policy.process.ensure_appropriate_arguments as audit 4 | 5 | finding = result { 6 | audit.apiserver_filter 7 | result := audit.finding([ 8 | "--etcd-certfile", 9 | "--etcd-keyfile", 10 | ]) 11 | } 12 | -------------------------------------------------------------------------------- /bundle/compliance/cis_k8s/rules/cis_1_2_27/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_k8s.rules.cis_1_2_27 2 | 3 | import data.compliance.policy.process.ensure_appropriate_arguments as audit 4 | 5 | finding = result { 6 | audit.apiserver_filter 7 | result := audit.finding([ 8 | "--tls-cert-file", 9 | "--tls-private-key-file", 10 | ]) 11 | } 12 | -------------------------------------------------------------------------------- /bundle/compliance/cis_k8s/rules/cis_1_2_28/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_k8s.rules.cis_1_2_28 2 | 3 | import data.compliance.policy.process.ensure_arguments_contain_key as audit 4 | 5 | finding = result { 6 | audit.apiserver_filter 7 | result := audit.finding(audit.contains("--client-ca-file")) 8 | } 9 | -------------------------------------------------------------------------------- /bundle/compliance/cis_k8s/rules/cis_1_2_29/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_k8s.rules.cis_1_2_29 2 | 3 | import data.compliance.policy.process.ensure_arguments_contain_key as audit 4 | 5 | finding = result { 6 | audit.apiserver_filter 7 | result := audit.finding(audit.contains("--etcd-cafile")) 8 | } 9 | -------------------------------------------------------------------------------- /bundle/compliance/cis_k8s/rules/cis_1_2_4/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_k8s.rules.cis_1_2_4 2 | 3 | import data.compliance.policy.process.ensure_arguments_contain_key_value as audit 4 | 5 | finding = result { 6 | audit.apiserver_filter 7 | result := audit.finding(audit.not_contains("--kubelet-https", "false")) 8 | } 9 | -------------------------------------------------------------------------------- /bundle/compliance/cis_k8s/rules/cis_1_2_5/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_k8s.rules.cis_1_2_5 2 | 3 | import data.compliance.policy.process.ensure_appropriate_arguments as audit 4 | 5 | finding = result { 6 | audit.apiserver_filter 7 | result := audit.finding([ 8 | "--kubelet-client-certificate", 9 | "--kubelet-client-key", 10 | ]) 11 | } 12 | -------------------------------------------------------------------------------- /bundle/compliance/cis_k8s/rules/cis_1_2_6/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_k8s.rules.cis_1_2_6 2 | 3 | import data.compliance.policy.process.ensure_arguments_contain_key as audit 4 | 5 | finding = result { 6 | audit.apiserver_filter 7 | result := audit.finding(audit.contains("--kubelet-certificate-authority")) 8 | } 9 | -------------------------------------------------------------------------------- /bundle/compliance/cis_k8s/rules/cis_1_2_7/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_k8s.rules.cis_1_2_7 2 | 3 | import data.compliance.policy.process.ensure_arguments_contain_value as audit 4 | 5 | finding = result { 6 | result := audit.finding(audit.not_contains("--authorization-mode", "AlwaysAllow")) 7 | } 8 | -------------------------------------------------------------------------------- /bundle/compliance/cis_k8s/rules/cis_1_2_8/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_k8s.rules.cis_1_2_8 2 | 3 | import data.compliance.policy.process.ensure_arguments_contain_value as audit 4 | 5 | finding = result { 6 | result := audit.finding(audit.contains("--authorization-mode", "Node")) 7 | } 8 | -------------------------------------------------------------------------------- /bundle/compliance/cis_k8s/rules/cis_1_2_9/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_k8s.rules.cis_1_2_9 2 | 3 | import data.compliance.policy.process.ensure_arguments_contain_value as audit 4 | 5 | finding = result { 6 | result := audit.finding(audit.contains("--authorization-mode", "RBAC")) 7 | } 8 | -------------------------------------------------------------------------------- /bundle/compliance/cis_k8s/rules/cis_1_3_2/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_k8s.rules.cis_1_3_2 2 | 3 | import data.compliance.policy.process.ensure_arguments_contain_key_value as audit 4 | 5 | finding = result { 6 | audit.controller_manager_filter 7 | result := audit.finding(audit.contains("--profiling", "false")) 8 | } 9 | -------------------------------------------------------------------------------- /bundle/compliance/cis_k8s/rules/cis_1_3_3/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_k8s.rules.cis_1_3_3 2 | 3 | import data.compliance.policy.process.ensure_arguments_contain_key_value as audit 4 | 5 | finding = result { 6 | audit.controller_manager_filter 7 | result := audit.finding(audit.contains("--use-service-account-credentials", "true")) 8 | } 9 | -------------------------------------------------------------------------------- /bundle/compliance/cis_k8s/rules/cis_1_3_4/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_k8s.rules.cis_1_3_4 2 | 3 | import data.compliance.policy.process.ensure_arguments_contain_key as audit 4 | 5 | finding = result { 6 | audit.controller_manager_filter 7 | result := audit.finding(audit.contains("--service-account-private-key-file")) 8 | } 9 | -------------------------------------------------------------------------------- /bundle/compliance/cis_k8s/rules/cis_1_3_5/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_k8s.rules.cis_1_3_5 2 | 3 | import data.compliance.policy.process.ensure_arguments_contain_key as audit 4 | 5 | finding = result { 6 | audit.controller_manager_filter 7 | result := audit.finding(audit.contains("--root-ca-file")) 8 | } 9 | -------------------------------------------------------------------------------- /bundle/compliance/cis_k8s/rules/cis_1_3_6/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_k8s.rules.cis_1_3_6 2 | 3 | import data.compliance.policy.process.ensure_arguments_contain_key_value as audit 4 | 5 | finding = result { 6 | audit.controller_manager_filter 7 | result := audit.finding(audit.contains("--feature-gates", "RotateKubeletServerCertificate=true")) 8 | } 9 | -------------------------------------------------------------------------------- /bundle/compliance/cis_k8s/rules/cis_1_3_7/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_k8s.rules.cis_1_3_7 2 | 3 | import data.compliance.policy.process.ensure_arguments_contain_key_value as audit 4 | 5 | finding = result { 6 | audit.controller_manager_filter 7 | result := audit.finding(audit.contains("--bind-address", "127.0.0.1")) 8 | } 9 | -------------------------------------------------------------------------------- /bundle/compliance/cis_k8s/rules/cis_1_4_1/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_k8s.rules.cis_1_4_1 2 | 3 | import data.compliance.policy.process.ensure_arguments_contain_key_value as audit 4 | 5 | finding = result { 6 | audit.scheduler_filter 7 | result := audit.finding(audit.contains("--profiling", "false")) 8 | } 9 | -------------------------------------------------------------------------------- /bundle/compliance/cis_k8s/rules/cis_1_4_2/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_k8s.rules.cis_1_4_2 2 | 3 | import data.compliance.policy.process.ensure_arguments_contain_key_value as audit 4 | 5 | finding = result { 6 | audit.scheduler_filter 7 | result := audit.finding(audit.contains("--bind-address", "127.0.0.1")) 8 | } 9 | -------------------------------------------------------------------------------- /bundle/compliance/cis_k8s/rules/cis_2_1/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_k8s.rules.cis_2_1 2 | 3 | import data.compliance.policy.process.ensure_appropriate_arguments as audit 4 | 5 | finding = result { 6 | audit.etcd_filter 7 | result := audit.finding([ 8 | "--cert-file", 9 | "--key-file", 10 | ]) 11 | } 12 | -------------------------------------------------------------------------------- /bundle/compliance/cis_k8s/rules/cis_2_2/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_k8s.rules.cis_2_2 2 | 3 | import data.compliance.policy.process.ensure_arguments_contain_key_value as audit 4 | 5 | finding = result { 6 | audit.etcd_filter 7 | result := audit.finding(audit.contains("--client-cert-auth", "true")) 8 | } 9 | -------------------------------------------------------------------------------- /bundle/compliance/cis_k8s/rules/cis_2_3/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_k8s.rules.cis_2_3 2 | 3 | import data.compliance.policy.process.ensure_arguments_contain_key_value as audit 4 | 5 | finding = result { 6 | audit.etcd_filter 7 | result := audit.finding(audit.not_contains("--auto-tls", "true")) 8 | } 9 | -------------------------------------------------------------------------------- /bundle/compliance/cis_k8s/rules/cis_2_4/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_k8s.rules.cis_2_4 2 | 3 | import data.compliance.policy.process.ensure_appropriate_arguments as audit 4 | 5 | finding = result { 6 | audit.etcd_filter 7 | result := audit.finding([ 8 | "--peer-cert-file", 9 | "--peer-key-file", 10 | ]) 11 | } 12 | -------------------------------------------------------------------------------- /bundle/compliance/cis_k8s/rules/cis_2_5/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_k8s.rules.cis_2_5 2 | 3 | import data.compliance.policy.process.ensure_arguments_contain_key_value as audit 4 | 5 | finding = result { 6 | audit.etcd_filter 7 | result := audit.finding(audit.contains("--peer-client-cert-auth", "true")) 8 | } 9 | -------------------------------------------------------------------------------- /bundle/compliance/cis_k8s/rules/cis_2_6/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_k8s.rules.cis_2_6 2 | 3 | import data.compliance.policy.process.ensure_arguments_contain_key_value as audit 4 | 5 | finding = result { 6 | audit.etcd_filter 7 | result := audit.finding(audit.not_contains("--peer-auto-tls", "true")) 8 | } 9 | -------------------------------------------------------------------------------- /bundle/compliance/cis_k8s/rules/cis_4_1_1/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_k8s.rules.cis_4_1_1 2 | 3 | import data.compliance.policy.file.ensure_permissions as audit 4 | 5 | finding = result { 6 | audit.filename_filter("10-kubeadm.conf") 7 | result := audit.finding(audit.file_permission_match(6, 4, 4)) 8 | } 9 | -------------------------------------------------------------------------------- /bundle/compliance/cis_k8s/rules/cis_4_1_1/test.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_k8s.rules.cis_4_1_1 2 | 3 | import data.kubernetes_common.test_data 4 | import data.lib.test 5 | 6 | test_violation { 7 | test.assert_fail(finding) with input as rule_input("10-kubeadm.conf", "700") 8 | } 9 | 10 | test_pass { 11 | test.assert_pass(finding) with input as rule_input("10-kubeadm.conf", "644") 12 | } 13 | 14 | test_not_evaluated { 15 | not finding with input as rule_input("file.txt", "644") 16 | } 17 | 18 | rule_input(filename, filemode) = filesystem_input { 19 | user := "root" 20 | group := "root" 21 | filesystem_input = test_data.filesystem_input(filename, filemode, user, group) 22 | } 23 | -------------------------------------------------------------------------------- /bundle/compliance/cis_k8s/rules/cis_4_1_10/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_k8s.rules.cis_4_1_10 2 | 3 | import data.compliance.policy.file.ensure_ownership as audit 4 | 5 | finding = result { 6 | audit.filename_filter("kubelet.conf") 7 | result := audit.finding("root", "root") 8 | } 9 | -------------------------------------------------------------------------------- /bundle/compliance/cis_k8s/rules/cis_4_1_10/test.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_k8s.rules.cis_4_1_10 2 | 3 | import data.kubernetes_common.test_data 4 | import data.lib.test 5 | 6 | test_violation { 7 | test.assert_fail(finding) with input as rule_input("kubelet.conf", "root", "user") 8 | test.assert_fail(finding) with input as rule_input("kubelet.conf", "user", "root") 9 | test.assert_fail(finding) with input as rule_input("kubelet.conf", "user", "user") 10 | } 11 | 12 | test_pass { 13 | test.assert_pass(finding) with input as rule_input("kubelet.conf", "root", "root") 14 | } 15 | 16 | test_not_evaluated { 17 | not finding with input as rule_input("file.txt", "root", "root") 18 | } 19 | 20 | rule_input(filename, user, group) = filesystem_input { 21 | filemode := "644" 22 | filesystem_input = test_data.filesystem_input(filename, filemode, user, group) 23 | } 24 | -------------------------------------------------------------------------------- /bundle/compliance/cis_k8s/rules/cis_4_1_2/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_k8s.rules.cis_4_1_2 2 | 3 | import data.compliance.policy.file.ensure_ownership as audit 4 | 5 | finding = result { 6 | audit.filename_filter("10-kubeadm.conf") 7 | result := audit.finding("root", "root") 8 | } 9 | -------------------------------------------------------------------------------- /bundle/compliance/cis_k8s/rules/cis_4_1_2/test.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_k8s.rules.cis_4_1_2 2 | 3 | import data.kubernetes_common.test_data 4 | import data.lib.test 5 | 6 | test_violation { 7 | test.assert_fail(finding) with input as rule_input("10-kubeadm.conf", "root", "user") 8 | test.assert_fail(finding) with input as rule_input("10-kubeadm.conf", "user", "root") 9 | test.assert_fail(finding) with input as rule_input("10-kubeadm.conf", "user", "user") 10 | } 11 | 12 | test_pass { 13 | test.assert_pass(finding) with input as rule_input("10-kubeadm.conf", "root", "root") 14 | } 15 | 16 | test_not_evaluated { 17 | not finding with input as rule_input("file.txt", "root", "root") 18 | } 19 | 20 | rule_input(filename, user, group) = filesystem_input { 21 | filemode := "644" 22 | filesystem_input = test_data.filesystem_input(filename, filemode, user, group) 23 | } 24 | -------------------------------------------------------------------------------- /bundle/compliance/cis_k8s/rules/cis_4_1_5/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_k8s.rules.cis_4_1_5 2 | 3 | import data.compliance.policy.file.ensure_permissions as audit 4 | 5 | finding = result { 6 | audit.filename_filter("kubelet.conf") 7 | result := audit.finding(audit.file_permission_match(6, 4, 4)) 8 | } 9 | -------------------------------------------------------------------------------- /bundle/compliance/cis_k8s/rules/cis_4_1_5/test.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_k8s.rules.cis_4_1_5 2 | 3 | import data.kubernetes_common.test_data 4 | import data.lib.test 5 | 6 | test_violation { 7 | test.assert_fail(finding) with input as rule_input("kubelet.conf", "700") 8 | } 9 | 10 | test_pass { 11 | test.assert_pass(finding) with input as rule_input("kubelet.conf", "644") 12 | } 13 | 14 | test_not_evaluated { 15 | not finding with input as rule_input("file.txt", "644") 16 | } 17 | 18 | rule_input(filename, filemode) = filesystem_input { 19 | user := "root" 20 | group := "root" 21 | filesystem_input = test_data.filesystem_input(filename, filemode, user, group) 22 | } 23 | -------------------------------------------------------------------------------- /bundle/compliance/cis_k8s/rules/cis_4_1_6/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_k8s.rules.cis_4_1_6 2 | 3 | import data.compliance.policy.file.ensure_ownership as audit 4 | 5 | finding = result { 6 | audit.filename_filter("kubelet.conf") 7 | result := audit.finding("root", "root") 8 | } 9 | -------------------------------------------------------------------------------- /bundle/compliance/cis_k8s/rules/cis_4_1_6/test.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_k8s.rules.cis_4_1_6 2 | 3 | import data.kubernetes_common.test_data 4 | import data.lib.test 5 | 6 | test_violation { 7 | test.assert_fail(finding) with input as rule_input("kubelet.conf", "root", "user") 8 | test.assert_fail(finding) with input as rule_input("kubelet.conf", "user", "root") 9 | test.assert_fail(finding) with input as rule_input("kubelet.conf", "user", "user") 10 | } 11 | 12 | test_pass { 13 | test.assert_pass(finding) with input as rule_input("kubelet.conf", "root", "root") 14 | } 15 | 16 | test_not_evaluated { 17 | not finding with input as rule_input("file.txt", "root", "root") 18 | } 19 | 20 | rule_input(filename, user, group) = filesystem_input { 21 | filemode := "644" 22 | filesystem_input = test_data.filesystem_input(filename, filemode, user, group) 23 | } 24 | -------------------------------------------------------------------------------- /bundle/compliance/cis_k8s/rules/cis_4_1_9/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_k8s.rules.cis_4_1_9 2 | 3 | import data.compliance.policy.file.ensure_permissions as audit 4 | 5 | finding = result { 6 | audit.filename_filter("config.yaml") 7 | result := audit.finding(audit.file_permission_match(6, 4, 4)) 8 | } 9 | -------------------------------------------------------------------------------- /bundle/compliance/cis_k8s/rules/cis_4_1_9/test.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_k8s.rules.cis_4_1_9 2 | 3 | import data.kubernetes_common.test_data 4 | import data.lib.test 5 | 6 | test_violation { 7 | test.assert_fail(finding) with input as rule_input("config.yaml", "700") 8 | } 9 | 10 | test_pass { 11 | test.assert_pass(finding) with input as rule_input("config.yaml", "644") 12 | } 13 | 14 | test_not_evaluated { 15 | not finding with input as rule_input("file.txt", "644") 16 | } 17 | 18 | rule_input(filename, filemode) = filesystem_input { 19 | user := "root" 20 | group := "root" 21 | filesystem_input = test_data.filesystem_input(filename, filemode, user, group) 22 | } 23 | -------------------------------------------------------------------------------- /bundle/compliance/cis_k8s/rules/cis_4_2_1/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_k8s.rules.cis_4_2_1 2 | 3 | import data.compliance.policy.process.ensure_arguments_and_config as audit 4 | 5 | default rule_evaluation = false 6 | 7 | rule_evaluation { 8 | audit.process_contains_key_with_value("--anonymous-auth", "false") 9 | } 10 | 11 | # In case both flags and configuration file are specified, the executable argument takes precedence. 12 | # Checks that the entry for authentication:anonymous: enabled set to false. 13 | rule_evaluation { 14 | audit.not_process_arg_comparison("--anonymous-auth", ["authentication", "anonymous", "enabled"], false) 15 | } 16 | 17 | finding = audit.finding(rule_evaluation) 18 | -------------------------------------------------------------------------------- /bundle/compliance/cis_k8s/rules/cis_4_2_10/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_k8s.rules.cis_4_2_10 2 | 3 | import data.compliance.policy.process.ensure_arguments_and_config as audit 4 | 5 | # Ensure that the --tls-cert-file and --tls-private-key-file arguments are set as appropriate 6 | default rule_evaluation = false 7 | 8 | rule_evaluation { 9 | audit.process_arg_multi("--tls-cert-file", "--tls-private-key-file") 10 | } 11 | 12 | rule_evaluation { 13 | audit.process_variable_multi(["tlsCertFile"], ["tlsPrivateKeyFile"]) 14 | } 15 | 16 | finding = audit.finding(rule_evaluation) 17 | -------------------------------------------------------------------------------- /bundle/compliance/cis_k8s/rules/cis_4_2_11/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_k8s.rules.cis_4_2_11 2 | 3 | import data.compliance.policy.process.ensure_arguments_and_config as audit 4 | 5 | # Verify that the --rotate-certificates argument is not present, or is set to true. 6 | default rule_evaluation = true 7 | 8 | rule_evaluation = false { 9 | audit.process_contains_key_with_value("--rotate-certificates", "false") 10 | } 11 | 12 | # In case both flags and configuration file are specified, the executable argument takes precedence. 13 | rule_evaluation = false { 14 | audit.not_process_arg_comparison("--rotate-certificates", ["rotateCertificates"], false) 15 | } 16 | 17 | finding = audit.finding(rule_evaluation) 18 | -------------------------------------------------------------------------------- /bundle/compliance/cis_k8s/rules/cis_4_2_3/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_k8s.rules.cis_4_2_3 2 | 3 | import data.compliance.policy.process.ensure_arguments_and_config as audit 4 | 5 | # Ensure that the --client-ca-file argument is set as appropriate (Automated) 6 | default rule_evaluation = false 7 | 8 | rule_evaluation { 9 | audit.process_contains_key("--client-ca-file") 10 | } 11 | 12 | # In case both flags and configuration file are specified, the executable argument takes precedence. 13 | # Checks that the entry for authentication:x509:clientCAFile: set to a valid path. 14 | rule_evaluation { 15 | audit.get_from_config(["authentication", "x509", "clientCAFile"]) 16 | } 17 | 18 | finding = audit.finding(rule_evaluation) 19 | -------------------------------------------------------------------------------- /bundle/compliance/cis_k8s/rules/cis_4_2_4/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_k8s.rules.cis_4_2_4 2 | 3 | import data.compliance.policy.process.ensure_arguments_and_config as audit 4 | 5 | # Verify that the --read-only-port argument is set to 0 6 | default rule_evaluation = false 7 | 8 | rule_evaluation { 9 | audit.process_contains_key_with_value("--read-only-port", "0") 10 | } 11 | 12 | # In case both flags and configuration file are specified, the executable argument takes precedence. 13 | rule_evaluation { 14 | audit.not_process_arg_comparison("--read-only-port", ["readOnlyPort"], 0) 15 | } 16 | 17 | finding = audit.finding(rule_evaluation) 18 | -------------------------------------------------------------------------------- /bundle/compliance/cis_k8s/rules/cis_4_2_5/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_k8s.rules.cis_4_2_5 2 | 3 | import data.compliance.policy.process.ensure_arguments_and_config as audit 4 | 5 | # Ensure that the --streaming-connection-idle-timeout argument is not set to 0 6 | default rule_evaluation = true 7 | 8 | rule_evaluation = false { 9 | audit.process_contains_key_with_value("--streaming-connection-idle-timeout", "0") 10 | } 11 | 12 | # In case both flags and configuration file are specified, the executable argument takes precedence. 13 | rule_evaluation = false { 14 | audit.not_process_arg_comparison("--streaming-connection-idle-timeout", ["streamingConnectionIdleTimeout"], 0) 15 | } 16 | 17 | finding = audit.finding(rule_evaluation) 18 | -------------------------------------------------------------------------------- /bundle/compliance/cis_k8s/rules/cis_4_2_6/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_k8s.rules.cis_4_2_6 2 | 3 | import data.compliance.policy.process.ensure_arguments_and_config as audit 4 | 5 | # Ensure that the protectKernelDefaults argument is set to true 6 | default rule_evaluation = false 7 | 8 | # Ensure that the --protect-kernel-defaults argument is set to true 9 | rule_evaluation { 10 | audit.process_contains_key_with_value("--protect-kernel-defaults", "true") 11 | } 12 | 13 | # In case both flags and configuration file are specified, the executable argument takes precedence. 14 | rule_evaluation { 15 | audit.not_process_arg_variable("--protect-kernel-defaults", ["protectKernelDefaults"]) 16 | } 17 | 18 | finding = audit.finding(rule_evaluation) 19 | -------------------------------------------------------------------------------- /bundle/compliance/cis_k8s/rules/cis_4_2_7/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_k8s.rules.cis_4_2_7 2 | 3 | import data.compliance.policy.process.ensure_arguments_and_config as audit 4 | 5 | # Ensure that the --make-iptables-util-chains argument is set to true (Automated) 6 | default rule_evaluation = true 7 | 8 | rule_evaluation = false { 9 | audit.process_contains_key_with_value("--make-iptables-util-chains", "false") 10 | } 11 | 12 | # In case both flags and configuration file are specified, the executable argument takes precedence. 13 | # Checks that the entry for makeIPTablesUtilChains is set to true. 14 | rule_evaluation = false { 15 | audit.not_process_arg_comparison("--make-iptables-util-chains", ["makeIPTablesUtilChains"], false) 16 | } 17 | 18 | finding = audit.finding(rule_evaluation) 19 | -------------------------------------------------------------------------------- /bundle/compliance/cis_k8s/rules/cis_4_2_8/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_k8s.rules.cis_4_2_8 2 | 3 | import data.compliance.policy.process.ensure_arguments_and_config as audit 4 | 5 | # Ensure that the --hostname-override argument is not set. 6 | default rule_evaluation = true 7 | 8 | # Note This setting is not configurable via the Kubelet config file. 9 | rule_evaluation = false { 10 | audit.process_contains_key("--hostname-override") 11 | } 12 | 13 | finding = audit.finding(rule_evaluation) 14 | -------------------------------------------------------------------------------- /bundle/compliance/cis_k8s/rules/cis_4_2_9/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_k8s.rules.cis_4_2_9 2 | 3 | import data.compliance.policy.process.ensure_arguments_and_config as audit 4 | 5 | # Ensure that the --event-qps argument is set to 0 or a level which ensures appropriate event capture 6 | default rule_evaluation = false 7 | 8 | rule_evaluation { 9 | audit.process_contains_key_with_value("--event-qps", "0") 10 | } 11 | 12 | rule_evaluation { 13 | audit.not_process_key_comparison("--event-qps", ["eventRecordQPS"], 0) 14 | } 15 | 16 | finding = audit.finding(rule_evaluation) 17 | -------------------------------------------------------------------------------- /bundle/compliance/cis_k8s/rules/cis_5_1_3/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_k8s.rules.cis_5_1_3 2 | 3 | import data.compliance.policy.kube_api.minimize_wildcard as audit 4 | 5 | finding = result { 6 | result := audit.finding 7 | } 8 | -------------------------------------------------------------------------------- /bundle/compliance/cis_k8s/rules/cis_5_1_5/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_k8s.rules.cis_5_1_5 2 | 3 | import data.compliance.policy.kube_api.ensure_service_accounts as audit 4 | 5 | finding = result { 6 | result := audit.finding(audit.service_account_default) 7 | } 8 | -------------------------------------------------------------------------------- /bundle/compliance/cis_k8s/rules/cis_5_1_6/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_k8s.rules.cis_5_1_6 2 | 3 | import data.compliance.policy.kube_api.ensure_service_accounts as audit 4 | 5 | finding = result { 6 | result := audit.finding(audit.service_account_automount) 7 | } 8 | -------------------------------------------------------------------------------- /bundle/compliance/cis_k8s/rules/cis_5_1_6/test.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_k8s.rules.cis_5_1_6 2 | 3 | import data.kubernetes_common.test_data 4 | import data.lib.test 5 | 6 | test_violation { 7 | test.assert_fail(finding) with input as test_data.kube_api_pod_input("pod", "name", true) 8 | test.assert_fail(finding) with input as test_data.kube_api_service_account_input("name", true) 9 | } 10 | 11 | test_pass { 12 | test.assert_pass(finding) with input as test_data.kube_api_pod_input("pod", "name", false) 13 | test.assert_pass(finding) with input as test_data.kube_api_service_account_input("name", false) 14 | } 15 | 16 | test_not_evaluated { 17 | not finding with input as test_data.not_evaluated_input 18 | not finding with input as test_data.not_evaluated_kube_api_input 19 | } 20 | -------------------------------------------------------------------------------- /bundle/compliance/cis_k8s/rules/cis_5_2_10/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_k8s.rules.cis_5_2_10 2 | 3 | import data.compliance.policy.kube_api.minimize_assigned_capabilities as audit 4 | 5 | finding = result { 6 | result := audit.finding 7 | } 8 | -------------------------------------------------------------------------------- /bundle/compliance/cis_k8s/rules/cis_5_2_2/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_k8s.rules.cis_5_2_2 2 | 3 | import data.compliance.policy.kube_api.minimize_admission as audit 4 | 5 | finding = result { 6 | result := audit.finding("privileged") 7 | } 8 | -------------------------------------------------------------------------------- /bundle/compliance/cis_k8s/rules/cis_5_2_3/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_k8s.rules.cis_5_2_3 2 | 3 | import data.compliance.policy.kube_api.minimize_sharing as audit 4 | 5 | finding = result { 6 | result := audit.finding("hostPID") 7 | } 8 | -------------------------------------------------------------------------------- /bundle/compliance/cis_k8s/rules/cis_5_2_4/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_k8s.rules.cis_5_2_4 2 | 3 | import data.compliance.policy.kube_api.minimize_sharing as audit 4 | 5 | finding = result { 6 | result := audit.finding("hostIPC") 7 | } 8 | -------------------------------------------------------------------------------- /bundle/compliance/cis_k8s/rules/cis_5_2_5/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_k8s.rules.cis_5_2_5 2 | 3 | import data.compliance.policy.kube_api.minimize_sharing as audit 4 | 5 | finding = result { 6 | result := audit.finding("hostNetwork") 7 | } 8 | -------------------------------------------------------------------------------- /bundle/compliance/cis_k8s/rules/cis_5_2_6/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_k8s.rules.cis_5_2_6 2 | 3 | import data.compliance.policy.kube_api.minimize_admission as audit 4 | 5 | finding = result { 6 | result := audit.finding("allowPrivilegeEscalation") 7 | } 8 | -------------------------------------------------------------------------------- /bundle/compliance/cis_k8s/rules/cis_5_2_7/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_k8s.rules.cis_5_2_7 2 | 3 | import data.compliance.policy.kube_api.minimize_admission_root as audit 4 | 5 | finding = result { 6 | result := audit.finding 7 | } 8 | -------------------------------------------------------------------------------- /bundle/compliance/cis_k8s/rules/cis_5_2_8/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_k8s.rules.cis_5_2_8 2 | 3 | import data.compliance.policy.kube_api.minimize_certain_capability as audit 4 | 5 | finding = result { 6 | result := audit.finding 7 | } 8 | -------------------------------------------------------------------------------- /bundle/compliance/cis_k8s/rules/cis_5_2_9/rule.rego: -------------------------------------------------------------------------------- 1 | package compliance.cis_k8s.rules.cis_5_2_9 2 | 3 | import data.compliance.policy.kube_api.minimize_added_capabilities as audit 4 | 5 | finding = result { 6 | result := audit.finding 7 | } 8 | -------------------------------------------------------------------------------- /bundle/compliance/lib/assert.rego: -------------------------------------------------------------------------------- 1 | package compliance.lib.assert 2 | 3 | is_true(value) { 4 | not is_false(value) 5 | } 6 | 7 | is_false(value) { 8 | value == false 9 | } else = false 10 | 11 | all_true(values) { 12 | not some_false(values) 13 | } 14 | 15 | all_false(values) { 16 | not some_true(values) 17 | } 18 | 19 | some_false(values) { 20 | value := values[_] 21 | not value 22 | } 23 | 24 | some_true(values) { 25 | value := values[_] 26 | value 27 | } 28 | 29 | array_is_empty(array) { 30 | count(array) == 0 31 | } else = false 32 | -------------------------------------------------------------------------------- /bundle/compliance/lib/test.rego: -------------------------------------------------------------------------------- 1 | package lib.test 2 | 3 | assert_pass(finding) { 4 | finding.evaluation == "passed" 5 | } 6 | 7 | assert_fail(finding) { 8 | finding.evaluation == "failed" 9 | } 10 | -------------------------------------------------------------------------------- /bundle/compliance/policy/aws_cloudtrail/data_adapter.rego: -------------------------------------------------------------------------------- 1 | package compliance.policy.aws_cloudtrail.data_adapter 2 | 3 | is_multi_trails_type { 4 | input.subType = "aws-multi-trails" 5 | } 6 | 7 | is_single_trail { 8 | input.subType == "aws-trail" 9 | } 10 | 11 | trail = input.resource.Trail 12 | 13 | trail_status = input.resource.Status 14 | 15 | trail_bucket_info = input.resource.bucket_info 16 | 17 | event_selectors = input.resource.EventSelectors 18 | 19 | trail_items = input.resource.Items 20 | -------------------------------------------------------------------------------- /bundle/compliance/policy/aws_cloudtrail/ensure_cloudwatch_integration.rego: -------------------------------------------------------------------------------- 1 | package compliance.policy.aws_cloudtrail.ensure_cloudwatch 2 | 3 | import data.compliance.lib.common 4 | import data.compliance.policy.aws_cloudtrail.data_adapter 5 | 6 | default ensure_cloudwatch_logs_enabled = false 7 | 8 | ensure_cloudwatch_logs_enabled { 9 | data_adapter.trail.CloudWatchLogsLogGroupArn != "" 10 | common.date_within_duration(time.parse_rfc3339_ns(data_adapter.trail_status.LatestCloudWatchLogsDeliveryTime), "24h") 11 | } 12 | -------------------------------------------------------------------------------- /bundle/compliance/policy/aws_cloudtrail/pattern.rego: -------------------------------------------------------------------------------- 1 | package compliance.policy.aws_cloudtrail.pattern 2 | 3 | # get a filter from a trail has at least one metric filter pattern that matches at least one pattern 4 | get_filter_matched_to_pattern(trail, patterns) = name { 5 | some i, j 6 | filter := trail.MetricFilters[i] 7 | pattern := patterns[j] 8 | filter.FilterPattern == pattern 9 | name := filter.FilterName 10 | } else = "" 11 | -------------------------------------------------------------------------------- /bundle/compliance/policy/aws_config/data_adapter.rego: -------------------------------------------------------------------------------- 1 | package compliance.policy.aws_config.data_adapter 2 | 3 | is_configservice { 4 | input.subType == "aws-config" 5 | } 6 | 7 | configs := input.resource 8 | -------------------------------------------------------------------------------- /bundle/compliance/policy/aws_config/ensure_config_enabled.rego: -------------------------------------------------------------------------------- 1 | package compliance.policy.aws_config.ensure_config_enabled 2 | 3 | import data.compliance.lib.common as common 4 | import data.compliance.policy.aws_config.data_adapter 5 | import future.keywords.every 6 | 7 | default rule_evaluation = false 8 | 9 | rule_evaluation { 10 | # every config needs to have at least 1 enabled recorder 11 | every config in data_adapter.configs { 12 | recorder := config.recorders[_] 13 | recorder.ConfigurationRecorder.RecordingGroup.AllSupported == true 14 | recorder.ConfigurationRecorder.RecordingGroup.IncludeGlobalResourceTypes == true 15 | } 16 | } 17 | 18 | finding = result { 19 | data_adapter.is_configservice 20 | 21 | result := common.generate_result_without_expected( 22 | common.calculate_result(rule_evaluation), 23 | data_adapter.configs, 24 | ) 25 | } 26 | -------------------------------------------------------------------------------- /bundle/compliance/policy/aws_ec2/ensure_public_ingress.rego: -------------------------------------------------------------------------------- 1 | package compliance.policy.aws_ec2.ensure_public_ingress 2 | 3 | import data.compliance.lib.common 4 | import data.compliance.policy.aws_ec2.data_adapter 5 | import data.compliance.policy.aws_ec2.ports 6 | import future.keywords.every 7 | 8 | default rule_evaluation = false 9 | 10 | finding = result { 11 | # filter 12 | data_adapter.is_nacl_policy 13 | 14 | # set result 15 | result := common.generate_result_without_expected( 16 | common.calculate_result(rule_evaluation), 17 | input.resource, 18 | ) 19 | } 20 | 21 | rule_evaluation { 22 | count(data_adapter.ingresses_with_all_ports_open) == 0 23 | every entry in data_adapter.nacl_ingresses { 24 | every port in ports.admin_ports { 25 | not ports.in_range(entry.PortRange.From, entry.PortRange.To, port) 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /bundle/compliance/policy/aws_ec2/ensure_security_group_public_ingress_ipv4.rego: -------------------------------------------------------------------------------- 1 | package compliance.policy.aws_ec2.ensure_security_group_public_ingress_ipv4 2 | 3 | import data.compliance.lib.common 4 | import data.compliance.policy.aws_ec2.data_adapter 5 | import data.compliance.policy.aws_ec2.ports 6 | import future.keywords.every 7 | 8 | default rule_evaluation = false 9 | 10 | finding = result { 11 | # filter 12 | data_adapter.is_security_group_policy 13 | 14 | # set result 15 | result := common.generate_result_without_expected( 16 | common.calculate_result(rule_evaluation), 17 | input.resource, 18 | ) 19 | } 20 | 21 | rule_evaluation { 22 | every entry in data_adapter.public_ipv4 { 23 | every port in ports.admin_ports { 24 | not ports.in_range(entry.FromPort, entry.ToPort, port) 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /bundle/compliance/policy/aws_ec2/ensure_security_group_public_ingress_ipv6.rego: -------------------------------------------------------------------------------- 1 | package compliance.policy.aws_ec2.ensure_security_group_public_ingress_ipv6 2 | 3 | import data.compliance.lib.common 4 | import data.compliance.policy.aws_ec2.data_adapter 5 | import data.compliance.policy.aws_ec2.ports 6 | import future.keywords.every 7 | 8 | default rule_evaluation = false 9 | 10 | finding = result { 11 | # filter 12 | data_adapter.is_security_group_policy 13 | 14 | # set result 15 | result := common.generate_result_without_expected( 16 | common.calculate_result(rule_evaluation), 17 | input.resource, 18 | ) 19 | } 20 | 21 | rule_evaluation { 22 | every entry in data_adapter.public_ipv6 { 23 | every port in ports.admin_ports { 24 | not ports.in_range(entry.FromPort, entry.ToPort, port) 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /bundle/compliance/policy/aws_ec2/ports.rego: -------------------------------------------------------------------------------- 1 | package compliance.policy.aws_ec2.ports 2 | 3 | # Admin ports are network ports that are reserved for use by system administrators to manage servers and other network devices. 4 | # These ports are typically used for remote management, monitoring, and control of devices over a network 5 | admin_ports = {22, 23, 25, 53, 80, 110, 143, 389, 443, 465, 587, 636, 993, 995, 3389} 6 | 7 | # check whether a given value (candidate) is within a range of values specified by from and to 8 | in_range(from, to, candidate) { 9 | candidate >= from 10 | candidate <= to 11 | } else = false 12 | -------------------------------------------------------------------------------- /bundle/compliance/policy/aws_ec2/ports_test.rego: -------------------------------------------------------------------------------- 1 | package compliance.policy.aws_ec2.ports 2 | 3 | test_pass { 4 | in_range(80, 443, 443) 5 | in_range(80, 443, 80) 6 | in_range(80, 443, 100) 7 | } 8 | 9 | test_fail { 10 | not in_range(80, 443, 444) 11 | not in_range(80, 443, 30) 12 | } 13 | -------------------------------------------------------------------------------- /bundle/compliance/policy/aws_ecr/data_adapter.rego: -------------------------------------------------------------------------------- 1 | package compliance.policy.aws_ecr.data_adapter 2 | 3 | is_aws_ecr { 4 | input.subType == "aws-ecr" 5 | } 6 | 7 | cluster = input.resource.Cluster 8 | 9 | image_scan_config = input.resource.ImageScanningConfiguration 10 | 11 | repository_name = input.resource.RepositoryName 12 | -------------------------------------------------------------------------------- /bundle/compliance/policy/aws_ecr/ensure_image_scan.rego: -------------------------------------------------------------------------------- 1 | package compliance.policy.aws_ecr.ensure_image_scan 2 | 3 | import data.compliance.lib.common as lib_common 4 | import data.compliance.policy.aws_ecr.data_adapter 5 | 6 | finding = result { 7 | data_adapter.is_aws_ecr 8 | 9 | rule_evaluation := data_adapter.image_scan_config.ScanOnPush 10 | 11 | # set result 12 | result := lib_common.generate_result_without_expected( 13 | lib_common.calculate_result(rule_evaluation), 14 | { 15 | "repository_name:": data_adapter.repository_name, 16 | "image_scanning_configuration": data_adapter.image_scan_config, 17 | }, 18 | ) 19 | } 20 | -------------------------------------------------------------------------------- /bundle/compliance/policy/aws_eks/data_adapter.rego: -------------------------------------------------------------------------------- 1 | package compliance.policy.aws_eks.data_adapter 2 | 3 | is_aws_eks { 4 | input.subType == "aws-eks" 5 | } 6 | 7 | cluster = input.resource.Cluster 8 | -------------------------------------------------------------------------------- /bundle/compliance/policy/aws_eks/ensure_encryption.rego: -------------------------------------------------------------------------------- 1 | package compliance.policy.aws_eks.ensure_encryption 2 | 3 | import data.compliance.lib.common 4 | import data.compliance.policy.aws_eks.data_adapter 5 | 6 | # Verify that there is a non empty encryption configuration 7 | is_encrypted(cluster) { 8 | cluster.EncryptionConfig 9 | count(cluster.EncryptionConfig) > 0 10 | } else = false 11 | 12 | # Ensure there Kuberenetes secrets are encrypted 13 | finding = result { 14 | # filter 15 | data_adapter.is_aws_eks 16 | 17 | rule_evaluation := is_encrypted(data_adapter.cluster) 18 | 19 | # set result 20 | result := common.generate_result_without_expected( 21 | common.calculate_result(rule_evaluation), 22 | {"encryption_config": data_adapter.cluster}, 23 | ) 24 | } 25 | -------------------------------------------------------------------------------- /bundle/compliance/policy/aws_eks/ensure_logs_enabled.rego: -------------------------------------------------------------------------------- 1 | package compliance.policy.aws_eks.ensure_logs_enabled 2 | 3 | import data.compliance.lib.assert 4 | import data.compliance.lib.common 5 | import data.compliance.policy.aws_eks.data_adapter 6 | 7 | # Ensure that all audit logs are enabled 8 | finding = result { 9 | # filter 10 | data_adapter.is_aws_eks 11 | 12 | # evaluate 13 | cluster_logging := data_adapter.cluster.Logging.ClusterLogging 14 | disabled_logs := [log | assert.is_false(cluster_logging[index].Enabled); log = cluster_logging[index].Types[_]] 15 | rule_evaluation := count(disabled_logs) == 0 16 | 17 | # set result 18 | result := common.generate_result_without_expected( 19 | common.calculate_result(rule_evaluation), 20 | {"disabled_logs": disabled_logs}, 21 | ) 22 | } 23 | -------------------------------------------------------------------------------- /bundle/compliance/policy/aws_elb/data_adapter.rego: -------------------------------------------------------------------------------- 1 | package compliance.policy.aws_elb.data_adapter 2 | 3 | is_aws_elb { 4 | input.subType == "aws-elb" 5 | } 6 | 7 | cluster = input.resource.Cluster 8 | 9 | listener_descriptions = input.resource.ListenerDescriptions 10 | 11 | load_balancer_name = input.resource.LoadBalancerName 12 | -------------------------------------------------------------------------------- /bundle/compliance/policy/aws_iam/common.rego: -------------------------------------------------------------------------------- 1 | package compliance.policy.aws_iam.common 2 | 3 | import data.compliance.lib.common 4 | import future.keywords.every 5 | 6 | are_credentials_within_duration(keys, field, duration) { 7 | every key in keys { 8 | common.date_within_duration(time.parse_rfc3339_ns(key[field]), duration) 9 | } 10 | } else = false 11 | -------------------------------------------------------------------------------- /bundle/compliance/policy/aws_iam/ensure_access_keys_use.rego: -------------------------------------------------------------------------------- 1 | package compliance.policy.aws_iam.ensure_access_keys_use 2 | 3 | import data.compliance.policy.aws_iam.data_adapter 4 | 5 | default ensure_access_keys_use = true 6 | 7 | ensure_access_keys_use = false { 8 | data_adapter.iam_user.password_enabled 9 | key := data_adapter.active_access_keys[_] 10 | not key.has_used 11 | } 12 | -------------------------------------------------------------------------------- /bundle/compliance/policy/aws_iam/ensure_enabled_mfa.rego: -------------------------------------------------------------------------------- 1 | package compliance.policy.aws_iam.ensure_enabled_mfa 2 | 3 | import data.compliance.policy.aws_iam.data_adapter 4 | 5 | default ensure_mfa_device = false 6 | 7 | ensure_mfa_device { 8 | data_adapter.iam_user.password_enabled 9 | data_adapter.iam_user.mfa_active 10 | } 11 | 12 | ensure_mfa_device { 13 | not data_adapter.iam_user.password_enabled 14 | not data_adapter.iam_user.mfa_active 15 | } 16 | -------------------------------------------------------------------------------- /bundle/compliance/policy/aws_iam/ensure_hardware_mfa.rego: -------------------------------------------------------------------------------- 1 | package compliance.policy.aws_iam.ensure_hardware_mfa 2 | 3 | import data.compliance.policy.aws_iam.data_adapter 4 | 5 | default ensure_hardware_mfa_device = false 6 | 7 | # Only one MFA device can be received as input, 8 | # even if a user has multiple MFA devices linked to their account. 9 | # This limitation is because we are unable to collect information about hardware MFA devices. 10 | # If a software MFA device is available, it will be the one that is received as input. 11 | # If no software MFA device is available and MFA is enabled, an MFA hardware device will be received instead. 12 | ensure_hardware_mfa_device { 13 | data_adapter.iam_user.mfa_active 14 | device := data_adapter.iam_user.mfa_devices[_] 15 | not device.is_virtual 16 | } 17 | -------------------------------------------------------------------------------- /bundle/compliance/policy/aws_iam/verify_keys_rotation.rego: -------------------------------------------------------------------------------- 1 | package compliance.policy.aws_iam.verify_keys_rotation 2 | 3 | import data.compliance.policy.aws_iam.common 4 | import data.compliance.policy.aws_iam.data_adapter 5 | 6 | duration = sprintf("%dh", [90 * 24]) # 90 days converted to hours 7 | 8 | default verify_rotation = false 9 | 10 | verify_rotation { 11 | common.are_credentials_within_duration(data_adapter.active_access_keys, "rotation_date", duration) 12 | } 13 | -------------------------------------------------------------------------------- /bundle/compliance/policy/aws_iam/verify_user_usage.rego: -------------------------------------------------------------------------------- 1 | package compliance.policy.aws_iam.verify_user_usage 2 | 3 | import data.compliance.policy.aws_iam.common 4 | import data.compliance.policy.aws_iam.data_adapter 5 | 6 | default verify_user_usage = false 7 | 8 | verify_user_usage { 9 | not common.are_credentials_within_duration(data_adapter.active_access_keys, "last_access", "24h") 10 | not common.are_credentials_within_duration([data_adapter.iam_user], "last_access", "24h") 11 | } 12 | 13 | verify_user_usage { 14 | count(data_adapter.active_access_keys) == 0 15 | not common.are_credentials_within_duration([data_adapter.iam_user], "last_access", "24h") 16 | } 17 | -------------------------------------------------------------------------------- /bundle/compliance/policy/aws_kms/data_adapter.rego: -------------------------------------------------------------------------------- 1 | package compliance.policy.aws_kms.data_adapter 2 | 3 | is_kms { 4 | input.subType == "aws-kms" 5 | } 6 | 7 | key_rotation_enabled := input.resource.key_rotation_enabled 8 | 9 | key_metadata := input.resource.key_metadata 10 | -------------------------------------------------------------------------------- /bundle/compliance/policy/aws_kms/ensure_symmetric_key_rotation_enabled.rego: -------------------------------------------------------------------------------- 1 | package compliance.policy.aws_kms.ensure_symmetric_key_rotation_enabled 2 | 3 | import data.compliance.lib.common as common 4 | import data.compliance.policy.aws_kms.data_adapter 5 | 6 | default rule_evaluation = false 7 | 8 | rule_evaluation { 9 | data_adapter.key_rotation_enabled == true 10 | } 11 | 12 | finding = result { 13 | data_adapter.is_kms 14 | 15 | result := common.generate_result_without_expected( 16 | common.calculate_result(rule_evaluation), 17 | { 18 | "KeyMetadata": data_adapter.key_metadata, 19 | "KeyRotationEnabled": data_adapter.key_rotation_enabled, 20 | }, 21 | ) 22 | } 23 | -------------------------------------------------------------------------------- /bundle/compliance/policy/aws_rds/data_adapter.rego: -------------------------------------------------------------------------------- 1 | package compliance.policy.aws_rds.data_adapter 2 | 3 | is_rds { 4 | input.subType == "aws-rds" 5 | } 6 | 7 | storage_encrypted := input.resource.storage_encrypted 8 | 9 | auto_minor_version_upgrade := input.resource.auto_minor_version_upgrade 10 | 11 | publicly_accessible := input.resource.publicly_accessible 12 | 13 | subnets := input.resource.subnets 14 | -------------------------------------------------------------------------------- /bundle/compliance/policy/aws_s3/data_adapter.rego: -------------------------------------------------------------------------------- 1 | package compliance.policy.aws_s3.data_adapter 2 | 3 | is_s3 { 4 | input.subType == "aws-s3" 5 | } 6 | 7 | sse_algorithm := input.resource.sse_algorithm 8 | 9 | bucket_policy := input.resource.bucket_policy 10 | 11 | bucket_policy_statements := object.get(bucket_policy, "Statement", []) 12 | 13 | bucket_versioning := input.resource.bucket_versioning 14 | 15 | public_access_block_configuration := input.resource.public_access_block_configuration 16 | 17 | account_public_access_block_configuration := input.resource.account_public_access_block_configuration 18 | -------------------------------------------------------------------------------- /bundle/compliance/policy/aws_s3/ensure_bucket_policy_deny_http.rego: -------------------------------------------------------------------------------- 1 | package compliance.policy.aws_s3.ensure_bucket_policy_deny_http 2 | 3 | import data.compliance.lib.common as lib_common 4 | import data.compliance.policy.aws_s3.data_adapter 5 | import future.keywords.in 6 | 7 | default rule_evaluation = false 8 | 9 | rule_evaluation { 10 | some statement in data_adapter.bucket_policy_statements 11 | statement.Condition.Bool["aws:SecureTransport"] == "false" 12 | statement.Action == "s3:*" 13 | statement.Effect == "Deny" 14 | statement.Principal == "*" 15 | } 16 | 17 | finding = result { 18 | data_adapter.is_s3 19 | not data_adapter.bucket_policy == null 20 | 21 | result := lib_common.generate_result_without_expected( 22 | lib_common.calculate_result(rule_evaluation), 23 | {"BucketPolicy": data_adapter.bucket_policy}, 24 | ) 25 | } 26 | -------------------------------------------------------------------------------- /bundle/compliance/policy/aws_s3/ensure_encryption_at_rest.rego: -------------------------------------------------------------------------------- 1 | package compliance.policy.aws_s3.ensure_encryption_at_rest 2 | 3 | import data.compliance.lib.common as lib_common 4 | import data.compliance.policy.aws_s3.data_adapter 5 | 6 | default rule_evaluation = false 7 | 8 | rule_evaluation { 9 | data_adapter.sse_algorithm == "AES256" 10 | } 11 | 12 | rule_evaluation { 13 | data_adapter.sse_algorithm == "aws:kms" 14 | } 15 | 16 | finding = result { 17 | data_adapter.is_s3 18 | not data_adapter.sse_algorithm == null 19 | 20 | result := lib_common.generate_result_without_expected( 21 | lib_common.calculate_result(rule_evaluation), 22 | {"SSEAlgorithm": data_adapter.sse_algorithm}, 23 | ) 24 | } 25 | -------------------------------------------------------------------------------- /bundle/compliance/policy/aws_s3/ensure_mfa_delete_enabled.rego: -------------------------------------------------------------------------------- 1 | package compliance.policy.aws_s3.ensure_mfa_delete_enabled 2 | 3 | import data.compliance.lib.common as lib_common 4 | import data.compliance.policy.aws_s3.data_adapter 5 | 6 | default rule_evaluation = false 7 | 8 | rule_evaluation { 9 | bucket_versioning := data_adapter.bucket_versioning 10 | bucket_versioning.Enabled == true 11 | bucket_versioning.MfaDelete == true 12 | } 13 | 14 | finding = result { 15 | data_adapter.is_s3 16 | not data_adapter.bucket_versioning == null 17 | 18 | result := lib_common.generate_result_without_expected( 19 | lib_common.calculate_result(rule_evaluation), 20 | {"BucketVersioning": data_adapter.bucket_versioning}, 21 | ) 22 | } 23 | -------------------------------------------------------------------------------- /bundle/compliance/policy/aws_securityhub/data_adapter.rego: -------------------------------------------------------------------------------- 1 | package compliance.policy.aws_securityhub.data_adapter 2 | 3 | is_securityhub_subType { 4 | input.subType == "aws-securityhub" 5 | } 6 | 7 | securityhub_resource = input.resource 8 | -------------------------------------------------------------------------------- /bundle/compliance/policy/azure/common.rego: -------------------------------------------------------------------------------- 1 | package compliance.policy.azure.common 2 | -------------------------------------------------------------------------------- /bundle/compliance/policy/azure/disk/ensure_encryption.rego: -------------------------------------------------------------------------------- 1 | package compliance.policy.azure.disk.ensure_encryption 2 | 3 | import data.compliance.policy.azure.data_adapter 4 | 5 | encryption_type = data_adapter.properties.encryption.type 6 | 7 | default is_encryption_enabled = false 8 | 9 | is_encryption_enabled { 10 | encryption_type == "EncryptionAtRestWithCustomerKey" 11 | } 12 | 13 | is_encryption_enabled { 14 | encryption_type == "EncryptionAtRestWithPlatformAndCustomerKeys" 15 | } 16 | -------------------------------------------------------------------------------- /bundle/compliance/policy/azure/storage_account/ensure_connection.rego: -------------------------------------------------------------------------------- 1 | package compliance.policy.azure.storage_account.ensure_connection 2 | 3 | import data.compliance.policy.azure.data_adapter 4 | 5 | import future.keywords.every 6 | 7 | is_every_private_connections { 8 | # Azure implemented it differently (like previous version of this file) 9 | # Simplified and implemented exactly like the PDF audit 10 | count(data_adapter.private_endpoint_connections) > 0 11 | } else = false 12 | 13 | is_private_connections = r { 14 | data_adapter.private_endpoint_connections 15 | r = is_every_private_connections 16 | } 17 | -------------------------------------------------------------------------------- /bundle/compliance/policy/azure/storage_account/ensure_default_network_access.rego: -------------------------------------------------------------------------------- 1 | package compliance.policy.azure.storage_account.ensure_default_network_access 2 | 3 | import data.compliance.policy.azure.data_adapter 4 | 5 | is_default_network_access_disabled { 6 | data_adapter.network_acls.defaultAction == "Deny" 7 | } else = false 8 | 9 | is_default_network_access = r { 10 | data_adapter.network_acls 11 | r = is_default_network_access_disabled 12 | } 13 | -------------------------------------------------------------------------------- /bundle/compliance/policy/azure/storage_account/ensure_encryption.rego: -------------------------------------------------------------------------------- 1 | package compliance.policy.azure.storage_account.ensure_encryption 2 | 3 | import data.compliance.policy.azure.data_adapter 4 | 5 | is_encryption_enabled { 6 | data_adapter.properties.encryption.requireInfrastructureEncryption 7 | } else = false 8 | -------------------------------------------------------------------------------- /bundle/compliance/policy/azure/storage_account/ensure_public_access.rego: -------------------------------------------------------------------------------- 1 | package compliance.policy.azure.storage_account.ensure_public_access 2 | 3 | import data.compliance.policy.azure.data_adapter 4 | 5 | import future.keywords.if 6 | 7 | verify_public_access if { 8 | data_adapter.properties.publicNetworkAccess == "Disabled" 9 | } else = false 10 | 11 | is_public_access_disabled = r if { 12 | data_adapter.properties.publicNetworkAccess 13 | r = verify_public_access 14 | } 15 | -------------------------------------------------------------------------------- /bundle/compliance/policy/azure/storage_account/ensure_secure_transfer.rego: -------------------------------------------------------------------------------- 1 | package compliance.policy.azure.storage_account.ensure_secure_transfer 2 | 3 | import data.compliance.policy.azure.data_adapter 4 | 5 | is_secure_transfer_enabled { 6 | data_adapter.properties.supportsHttpsTrafficOnly 7 | } else = false 8 | -------------------------------------------------------------------------------- /bundle/compliance/policy/azure/storage_account/ensure_service.rego: -------------------------------------------------------------------------------- 1 | package compliance.policy.azure.storage_account.ensure_service 2 | 3 | import data.compliance.policy.azure.data_adapter 4 | import future.keywords.if 5 | import future.keywords.in 6 | 7 | is_service_included(service) if { 8 | data_adapter.network_acls.defaultAction == "Deny" 9 | data_adapter.network_acls.bypass == service 10 | } else = false 11 | 12 | evaluate_service(service) = r if { 13 | data_adapter.network_acls 14 | r = is_service_included(service) 15 | } 16 | -------------------------------------------------------------------------------- /bundle/compliance/policy/azure/storage_account/ensure_tls_version.rego: -------------------------------------------------------------------------------- 1 | package compliance.policy.azure.storage_account.ensure_tls_version 2 | 3 | import data.compliance.policy.azure.data_adapter 4 | 5 | is_tls_version(version) { 6 | data_adapter.properties.minimumTlsVersion == version 7 | } else = false 8 | 9 | is_tls_configured(version) = r { 10 | data_adapter.properties.minimumTlsVersion 11 | r = is_tls_version(version) 12 | } 13 | -------------------------------------------------------------------------------- /bundle/compliance/policy/file/data_adapter.rego: -------------------------------------------------------------------------------- 1 | package compliance.policy.file.data_adapter 2 | 3 | is_filesystem { 4 | input.type == "file" 5 | } 6 | 7 | filename = file_name { 8 | is_filesystem 9 | file_name := input.resource.name 10 | } 11 | 12 | filemode = file_mode { 13 | is_filesystem 14 | file_mode := input.resource.mode 15 | } 16 | 17 | file_path = path { 18 | is_filesystem 19 | path := input.resource.path 20 | } 21 | 22 | owner_user = owner { 23 | is_filesystem 24 | owner := input.resource.owner 25 | } 26 | 27 | owner_group = group { 28 | is_filesystem 29 | group := input.resource.group 30 | } 31 | -------------------------------------------------------------------------------- /bundle/compliance/policy/file/ensure_ownership.rego: -------------------------------------------------------------------------------- 1 | package compliance.policy.file.ensure_ownership 2 | 3 | import data.compliance.lib.common as lib_common 4 | import data.compliance.policy.file.common as file_common 5 | import data.compliance.policy.file.data_adapter 6 | 7 | finding(owner_user, owner_group) = result { 8 | user = data_adapter.owner_user 9 | group = data_adapter.owner_group 10 | rule_evaluation := file_common.file_ownership_match(user, group, owner_user, owner_group) 11 | 12 | # set result 13 | result := lib_common.generate_result( 14 | lib_common.calculate_result(rule_evaluation), 15 | {"owner": user, "group": group}, 16 | {"owner": owner_user, "group": owner_group}, 17 | ) 18 | } 19 | 20 | path_filter(name) := file_common.file_in_path(name, data_adapter.file_path) 21 | 22 | filename_filter(name) := data_adapter.filename == name 23 | -------------------------------------------------------------------------------- /bundle/compliance/policy/gcp/bq/ensure_cmek_is_used.rego: -------------------------------------------------------------------------------- 1 | package compliance.policy.gcp.bq.ensure_cmek_is_used 2 | 3 | import data.compliance.policy.gcp.data_adapter 4 | 5 | default is_cmek_used = false 6 | 7 | is_cmek_used { 8 | data_adapter.resource.data.defaultEncryptionConfiguration.kmsKeyName 9 | } 10 | -------------------------------------------------------------------------------- /bundle/compliance/policy/gcp/common.rego: -------------------------------------------------------------------------------- 1 | package compliance.policy.gcp.common 2 | 3 | # parse the machine's family type from a machine type URL (e.g. https://www.googleapis.com/compute/v1/projects//zones//machineTypes/) 4 | get_machine_type_family(type_url) = family { 5 | parts := split(type_url, "/") 6 | family := parts[count(parts) - 1] 7 | } 8 | -------------------------------------------------------------------------------- /bundle/compliance/policy/gcp/compute/assess_instance_metadata.rego: -------------------------------------------------------------------------------- 1 | package compliance.policy.gcp.compute.assess_instance_metadata 2 | 3 | import data.compliance.policy.gcp.data_adapter 4 | import future.keywords.every 5 | import future.keywords.if 6 | 7 | is_instance_metadata_valid(key, expected_val) if { 8 | some item in data_adapter.resource.data.metadata.items 9 | item.key == key 10 | item.value == expected_val 11 | } else = false 12 | -------------------------------------------------------------------------------- /bundle/compliance/policy/gcp/dns/ensure_rsasha1_is_unused.rego: -------------------------------------------------------------------------------- 1 | package compliance.policy.gcp.dns.ensure_no_sha1 2 | 3 | import data.compliance.lib.assert 4 | import data.compliance.lib.common 5 | import data.compliance.policy.gcp.data_adapter 6 | import future.keywords.in 7 | 8 | finding(type) = result { 9 | # filter 10 | data_adapter.is_dns_managed_zone 11 | data_adapter.resource.data.visibility == "PUBLIC" 12 | 13 | # set result 14 | result := common.generate_result_without_expected( 15 | common.calculate_result(assert.is_false(is_sha1_used(type))), 16 | {"Managed zone": input.resource}, 17 | ) 18 | } 19 | 20 | is_sha1_used(type) { 21 | some key_spec in data_adapter.resource.data.dnssecConfig.defaultKeySpecs 22 | key_spec.keyType == type 23 | key_spec.algorithm == "RSASHA1" 24 | } else = false 25 | -------------------------------------------------------------------------------- /bundle/compliance/policy/gcp/iam/ensure_admin_without_multiple_roles.rego: -------------------------------------------------------------------------------- 1 | package compliance.policy.gcp.iam.ensure_admin_without_multiple_roles 2 | 3 | import data.compliance.policy.gcp.data_adapter 4 | import future.keywords.if 5 | 6 | admin_has_multiple_roles(admin_role, other_role) if { 7 | admin := data_adapter.iam_policy.bindings[_] 8 | admin.role == admin_role 9 | 10 | other := data_adapter.iam_policy.bindings[_] 11 | other.role == other_role 12 | 13 | m := admin.members[_] 14 | m = other.members[_] 15 | } 16 | -------------------------------------------------------------------------------- /bundle/compliance/policy/gcp/iam/ensure_no_public_access.rego: -------------------------------------------------------------------------------- 1 | package compliance.policy.gcp.iam.ensure_no_public_access 2 | 3 | import data.compliance.policy.gcp.data_adapter 4 | import future.keywords.if 5 | 6 | default resource_is_public = false 7 | 8 | resource_is_public if { 9 | # Check if the IAM policy is not empty 10 | data_adapter.iam_policy 11 | some i, j 12 | data_adapter.iam_policy.bindings[i].members[j] == "allUsers" 13 | } 14 | 15 | resource_is_public if { 16 | # Check if the IAM policy is not empty 17 | data_adapter.iam_policy 18 | some i, j 19 | data_adapter.iam_policy.bindings[i].members[j] == "allAuthenticatedUsers" 20 | } 21 | -------------------------------------------------------------------------------- /bundle/compliance/policy/gcp/iam/ensure_policy_not_managed_by_user.rego: -------------------------------------------------------------------------------- 1 | package compliance.policy.gcp.iam.ensure_policy_not_managed_by_user 2 | 3 | import data.compliance.policy.gcp.data_adapter 4 | import future.keywords.every 5 | import future.keywords.if 6 | 7 | default is_policy_not_managed_by_user = false 8 | 9 | is_policy_not_managed_by_user if { 10 | every member in data_adapter.iam_policy.bindings[i].members { 11 | not startswith(member, "user:") 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /bundle/compliance/policy/gcp/iam/ensure_role_not_service_account_user.rego: -------------------------------------------------------------------------------- 1 | package compliance.policy.gcp.iam.ensure_role_not_service_account_user 2 | 3 | import data.compliance.policy.gcp.data_adapter 4 | import future.keywords.if 5 | 6 | default is_role_not_service_account_user = false 7 | 8 | is_role_not_service_account_user if { 9 | role := data_adapter.iam_policy.bindings[i].role 10 | role != "roles/iam.serviceAccountUser" 11 | role != "roles/iam.serviceAccountTokenCreator" 12 | } 13 | -------------------------------------------------------------------------------- /bundle/compliance/policy/gcp/iam/ensure_user_not_editor_or_owner.rego: -------------------------------------------------------------------------------- 1 | package compliance.policy.gcp.iam.ensure_user_not_editor_or_owner 2 | 3 | import data.compliance.policy.gcp.data_adapter 4 | import future.keywords.if 5 | 6 | default is_user_owner_or_editor = false 7 | 8 | is_user_owner_or_editor if { 9 | # at least one member that starts with "user:" 10 | some member 11 | member = data_adapter.iam_policy.bindings[i].members[_] 12 | startswith(member, "user:") 13 | 14 | # Ensure the role is not a service account managed by Google (iam.gserviceaccount.com suffix). 15 | role := data_adapter.iam_policy.bindings[i].role 16 | not endswith(role, "iam.gserviceaccount.com") 17 | 18 | # Confirm the role is not editor/owner 19 | role != "roles/editor" 20 | role != "roles/owner" 21 | } 22 | -------------------------------------------------------------------------------- /bundle/compliance/policy/gcp/sql/ensure_private_ip.rego: -------------------------------------------------------------------------------- 1 | package compliance.policy.gcp.sql.ensure_private_ip 2 | 3 | import data.compliance.policy.gcp.data_adapter 4 | import future.keywords.every 5 | import future.keywords.if 6 | 7 | ip_is_private if { 8 | every ipAddress in data_adapter.resource.data.ipAddresses { 9 | not ipAddress.type == "PRIMARY" 10 | } 11 | } else = false 12 | -------------------------------------------------------------------------------- /bundle/compliance/policy/kube_api/minimize_added_capabilities.rego: -------------------------------------------------------------------------------- 1 | package compliance.policy.kube_api.minimize_added_capabilities 2 | 3 | import data.compliance.lib.assert 4 | import data.compliance.lib.common as lib_common 5 | import data.compliance.policy.kube_api.data_adapter 6 | 7 | finding := result { 8 | data_adapter.is_kube_api 9 | 10 | allowedCapabilities := object.get(data_adapter.pod.spec, "allowedCapabilities", []) 11 | rule_evaluation := assert.array_is_empty(allowedCapabilities) 12 | 13 | # set result 14 | result := lib_common.generate_result_without_expected( 15 | lib_common.calculate_result(rule_evaluation), 16 | {"filemode": json.filter(data_adapter.pod, [ 17 | "metadata/uid", 18 | "spec/allowedCapabilities", 19 | ])}, 20 | ) 21 | } 22 | -------------------------------------------------------------------------------- /bundle/compliance/policy/kube_api/minimize_sharing.rego: -------------------------------------------------------------------------------- 1 | package compliance.policy.kube_api.minimize_sharing 2 | 3 | import data.compliance.lib.assert 4 | import data.compliance.lib.common as lib_common 5 | import data.compliance.policy.kube_api.data_adapter 6 | 7 | finding(entity) := result { 8 | data_adapter.is_kube_api 9 | 10 | rule_evaluation := assert.is_false(lib_common.contains_key_with_value(data_adapter.pod.spec, entity, true)) 11 | 12 | # set result 13 | result := lib_common.generate_result_without_expected( 14 | lib_common.calculate_result(rule_evaluation), 15 | json.filter(data_adapter.pod, [ 16 | "metadata/uid", 17 | concat("", ["spec/", entity]), 18 | ]), 19 | ) 20 | } 21 | -------------------------------------------------------------------------------- /bundle/compliance/policy/process/common.rego: -------------------------------------------------------------------------------- 1 | package compliance.policy.process.common 2 | 3 | # checks if argument contains value (argument format is csv) 4 | arg_values_contains(arguments, key, value) { 5 | argument := arguments[key] 6 | values := split(argument, ",") 7 | value == values[_] 8 | } else = false 9 | 10 | # splits key value string by first occurrence of = 11 | split_key_value(key_value_string, delimiter) = [key, value] { 12 | seperator_index := indexof(key_value_string, delimiter) 13 | 14 | # extract key 15 | key_start_index := 0 16 | key_length := seperator_index 17 | key := substring(key_value_string, key_start_index, key_length) 18 | 19 | # extract value 20 | value_start_index := seperator_index + 1 21 | value_length := (count(key_value_string) - seperator_index) - 1 22 | value := substring(key_value_string, value_start_index, value_length) 23 | } 24 | -------------------------------------------------------------------------------- /bundle/compliance/policy/process/ensure_appropriate_arguments.rego: -------------------------------------------------------------------------------- 1 | package compliance.policy.process.ensure_appropriate_arguments 2 | 3 | import data.benchmark_data_adapter 4 | import data.compliance.lib.common as lib_common 5 | import data.compliance.policy.process.data_adapter 6 | 7 | process_args := benchmark_data_adapter.process_args 8 | 9 | finding(entities) = result { 10 | # set result 11 | result := lib_common.generate_result_without_expected( 12 | lib_common.calculate_result(rule_evaluation(entities)), 13 | {"process_args": process_args}, 14 | ) 15 | } 16 | 17 | # TODO: Change index access to cycle 18 | rule_evaluation(entities) { 19 | process_args[entities[0]] 20 | process_args[entities[1]] 21 | } else = false 22 | 23 | apiserver_filter := data_adapter.is_kube_apiserver 24 | 25 | etcd_filter := data_adapter.is_etcd 26 | -------------------------------------------------------------------------------- /bundle/compliance/policy/process/ensure_arguments_goe.rego: -------------------------------------------------------------------------------- 1 | package compliance.policy.process.ensure_arguments_goe 2 | 3 | import data.benchmark_data_adapter 4 | import data.compliance.lib.common as lib_common 5 | import data.compliance.policy.process.data_adapter 6 | 7 | process_args := benchmark_data_adapter.process_args 8 | 9 | finding(entity, value) = result { 10 | data_adapter.is_kube_apiserver 11 | 12 | # set result 13 | result := lib_common.generate_result_without_expected( 14 | lib_common.calculate_result(rule_evaluation(entity, value)), 15 | {"process_args": process_args}, 16 | ) 17 | } 18 | 19 | rule_evaluation(entity, value) { 20 | e := process_args[entity] 21 | lib_common.greater_or_equal(e, value) 22 | } else = false 23 | -------------------------------------------------------------------------------- /bundle/compliance/policy/process/ensure_arguments_lte.rego: -------------------------------------------------------------------------------- 1 | package compliance.policy.process.ensure_arguments_lte 2 | 3 | import data.benchmark_data_adapter 4 | import data.compliance.lib.common as lib_common 5 | import data.compliance.policy.process.data_adapter 6 | 7 | process_args := benchmark_data_adapter.process_args 8 | 9 | finding(entity, value) = result { 10 | data_adapter.is_kube_apiserver 11 | 12 | # set result 13 | result := lib_common.generate_result_without_expected( 14 | lib_common.calculate_result(rule_evaluation(entity, value)), 15 | {"process_args": process_args}, 16 | ) 17 | } 18 | 19 | rule_evaluation(entity, value) = false { 20 | e := process_args[entity] 21 | lib_common.duration_lte(e, value) 22 | } else = true 23 | -------------------------------------------------------------------------------- /bundle/compliance/policy/process/ensure_arguments_not_contain_value_appropriate.rego: -------------------------------------------------------------------------------- 1 | package compliance.policy.process.ensure_arguments_not_contain_value_appropriate 2 | 3 | import data.benchmark_data_adapter 4 | import data.compliance.lib.common as lib_common 5 | import data.compliance.policy.process.common as process_common 6 | import data.compliance.policy.process.data_adapter 7 | 8 | process_args := benchmark_data_adapter.process_args 9 | 10 | finding(entity, value) = result { 11 | data_adapter.is_kube_apiserver 12 | 13 | # set result 14 | result := lib_common.generate_result_without_expected( 15 | lib_common.calculate_result(rule_evaluation(entity, value)), 16 | {"process_args": process_args}, 17 | ) 18 | } 19 | 20 | rule_evaluation(entity, value) { 21 | process_args[entity] 22 | not process_common.arg_values_contains(process_args, entity, value) 23 | } else = false 24 | -------------------------------------------------------------------------------- /dev/input/CIS_Amazon_Elastic_Kubernetes_Service_(EKS)_Benchmark_v1.0.1.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elastic/csp-security-policies/167a08fcff5fec262694204f5cf16be27e4c7862/dev/input/CIS_Amazon_Elastic_Kubernetes_Service_(EKS)_Benchmark_v1.0.1.xlsx -------------------------------------------------------------------------------- /dev/input/CIS_Amazon_Web_Services_Foundations_Benchmark_v1.5.0.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elastic/csp-security-policies/167a08fcff5fec262694204f5cf16be27e4c7862/dev/input/CIS_Amazon_Web_Services_Foundations_Benchmark_v1.5.0.xlsx -------------------------------------------------------------------------------- /dev/input/CIS_Google_Cloud_Platform_Foundation_Benchmark_v2.0.0.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elastic/csp-security-policies/167a08fcff5fec262694204f5cf16be27e4c7862/dev/input/CIS_Google_Cloud_Platform_Foundation_Benchmark_v2.0.0.xlsx -------------------------------------------------------------------------------- /dev/input/CIS_Kubernetes_V1.23_Benchmark_v1.0.1.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elastic/csp-security-policies/167a08fcff5fec262694204f5cf16be27e4c7862/dev/input/CIS_Kubernetes_V1.23_Benchmark_v1.0.1.xlsx -------------------------------------------------------------------------------- /dev/input/CIS_Microsoft_Azure_Foundations_Benchmark_v2.0.0.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elastic/csp-security-policies/167a08fcff5fec262694204f5cf16be27e4c7862/dev/input/CIS_Microsoft_Azure_Foundations_Benchmark_v2.0.0.xlsx -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.poetry] 2 | name = "csp-security-policies" 3 | version = "0.1.0" 4 | description = "" 5 | authors = ["oren zohar "] 6 | 7 | [tool.poetry.dependencies] 8 | python = "^3.10" 9 | pandas = "^1.5.2" 10 | GitPython = "3.1.32" 11 | openpyxl = "^3.0.10" 12 | tabulate = "^0.9.0" 13 | numpy = "^1.23.5" 14 | Jinja2 = "^3.1.2" 15 | regex = "^2022.10.31" 16 | "ruamel.yaml" = "^0.17.21" 17 | PyYAML = "^6.0" 18 | 19 | [tool.poetry.dev-dependencies] 20 | 21 | 22 | [build-system] 23 | requires = ["poetry-core>=1.0.0"] 24 | build-backend = "poetry.core.masonry.api" 25 | -------------------------------------------------------------------------------- /server/host.go: -------------------------------------------------------------------------------- 1 | package server 2 | 3 | import ( 4 | "context" 5 | "net/http" 6 | 7 | "github.com/elastic/csp-security-policies/bundle" 8 | ) 9 | 10 | func HostCISKubernetes(path string) (http.Handler, error) { 11 | server := bundle.NewServer() 12 | err := bundle.HostBundle(path, bundle.CISKubernetesBundle(), context.Background()) 13 | if err != nil { 14 | return nil, err 15 | } 16 | 17 | return server, nil 18 | } 19 | 20 | func HostEKSKubernetes(path string) (http.Handler, error) { 21 | server := bundle.NewServer() 22 | err := bundle.HostBundle(path, bundle.CISEksBundle(), context.Background()) 23 | if err != nil { 24 | return nil, err 25 | } 26 | 27 | return server, nil 28 | } 29 | --------------------------------------------------------------------------------