├── .gitattributes
├── .github
├── ISSUE_TEMPLATE
│ ├── bug_report.md
│ ├── config.yml
│ └── feature_request.md
├── PULL_REQUEST_TEMPLATE.md
└── workflows
│ ├── stale.yml
│ └── sync-labels.yml
├── .gitignore
├── CHANGELOG.md
├── LICENSE
├── README.md
├── all_controls
├── all_controls.pp
├── cluster_role_binding.pp
├── config_map.pp
├── cronjob.pp
├── daemonset.pp
├── deployment.pp
├── docs
│ └── all_controls_overview.md
├── endpoint.pp
├── ingress.pp
├── job.pp
├── namespace.pp
├── network_policy.pp
├── pod.pp
├── pod_security_policy.pp
├── pod_template.pp
├── replicaset.pp
├── replication_controller.pp
├── role.pp
├── role_binding.pp
├── secret.pp
├── service.pp
├── service_account.pp
└── statefulset.pp
├── cis_kube_v120
├── cis_kube_v120.pp
├── cis_kube_v120_v100.pp
└── docs
│ ├── cis_kube_v120_v100_5_1_6.md
│ ├── cis_kube_v120_v100_5_2_1.md
│ ├── cis_kube_v120_v100_5_2_2.md
│ ├── cis_kube_v120_v100_5_2_3.md
│ ├── cis_kube_v120_v100_5_2_4.md
│ ├── cis_kube_v120_v100_5_2_5.md
│ ├── cis_kube_v120_v100_5_2_6.md
│ ├── cis_kube_v120_v100_5_3_2.md
│ ├── cis_kube_v120_v100_5_7_2.md
│ ├── cis_kube_v120_v100_5_7_4.md
│ └── cis_kube_v120_v100_overview.md
├── cis_v170
├── cis.pp
├── docs
│ ├── cis_v170_5_1.md
│ ├── cis_v170_5_1_3.md
│ ├── cis_v170_5_1_6.md
│ ├── cis_v170_5_3.md
│ ├── cis_v170_5_3_2.md
│ ├── cis_v170_5_7.md
│ ├── cis_v170_5_7_2.md
│ ├── cis_v170_5_7_4.md
│ └── cis_v170_overview.md
└── section_5.pp
├── controls
├── cluster_role_binding.pp
├── config_map.pp
├── cronjob.pp
├── daemonset.pp
├── deployment.pp
├── endpoint.pp
├── ingress.pp
├── job.pp
├── local.pp
├── namespace.pp
├── network_policy.pp
├── pod.pp
├── pod_security_policy.pp
├── pod_template.pp
├── replicaset.pp
├── replication_controller.pp
├── role.pp
├── role_binding.pp
├── secret.pp
├── service.pp
├── service_account.pp
└── statefulset.pp
├── docs
├── index.md
├── kubernetes_cis_v120.png
├── kubernetes_compliance_dashboard.png
├── kubernetes_compliance_mod_console_output.png
└── kubernetes_nsa_csa_v1.png
├── mod.pp
├── nsa_cisa_v1
├── docs
│ └── nsa_cisa_v1_overview.md
├── nsa_cisa_v1.pp
├── nsa_cisa_v1_network_hardening.pp
└── nsa_cisa_v1_pod_security.pp
├── powerpipe.ppvars.example
├── query
├── cluster_role_binding.pp
├── config_map.pp
├── cronjob.pp
├── daemonset.pp
├── deployment.pp
├── endpoint.pp
├── ingress.pp
├── job.pp
├── namespace.pp
├── network_policy.pp
├── pod.pp
├── pod_security_policy.pp
├── pod_template.pp
├── replicaset.pp
├── replication_controller.pp
├── role.pp
├── role_binding.pp
├── secret.pp
├── service.pp
├── service_account.pp
└── statefulset.pp
└── variables.pp
/.gitattributes:
--------------------------------------------------------------------------------
1 | **/*.sp linguist-language=HCL
2 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 | title: ''
5 | labels: bug
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Describe the bug**
11 | A clear and concise description of what the bug is.
12 |
13 | **Powerpipe version (`powerpipe -v`)**
14 | Example: v0.3.0
15 |
16 | **Steampipe version (`steampipe -v`)**
17 | Example: v0.3.0
18 |
19 | **Plugin version (`steampipe plugin list`)**
20 | Example: v0.5.0
21 |
22 | **To reproduce**
23 | Steps to reproduce the behavior (please include relevant code and/or commands).
24 |
25 | **Expected behavior**
26 | A clear and concise description of what you expected to happen.
27 |
28 | **Additional context**
29 | Add any other context about the problem here.
30 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/config.yml:
--------------------------------------------------------------------------------
1 | blank_issues_enabled: false
2 | contact_links:
3 | - name: Questions
4 | url: https://turbot.com/community/join
5 | about: GitHub issues in this repository are only intended for bug reports and feature requests. Other issues will be closed. Please ask and answer questions through the Steampipe Slack community.
6 | - name: Powerpipe CLI Bug Reports and Feature Requests
7 | url: https://github.com/turbot/powerpipe/issues/new/choose
8 | about: Powerpipe CLI has its own codebase. Bug reports and feature requests for those pieces of functionality should be directed to that repository.
9 | - name: Steampipe CLI Bug Reports and Feature Requests
10 | url: https://github.com/turbot/steampipe/issues/new/choose
11 | about: Steampipe CLI has its own codebase. Bug reports and feature requests for those pieces of functionality should be directed to that repository.
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Suggest an idea for this project
4 | title: ''
5 | labels: enhancement
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Is your feature request related to a problem? Please describe.**
11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
12 |
13 | **Describe the solution you'd like**
14 | A clear and concise description of what you want to happen.
15 |
16 | **Describe alternatives you've considered**
17 | A clear and concise description of any alternative solutions or features you've considered.
18 |
19 | **Additional context**
20 | Add any other context or screenshots about the feature request here.
21 |
--------------------------------------------------------------------------------
/.github/PULL_REQUEST_TEMPLATE.md:
--------------------------------------------------------------------------------
1 | ### Checklist
2 | - [ ] Issue(s) linked
3 |
--------------------------------------------------------------------------------
/.github/workflows/stale.yml:
--------------------------------------------------------------------------------
1 | name: Stale Issues and PRs
2 | on:
3 | schedule:
4 | - cron: "30 23 * * *"
5 | workflow_dispatch:
6 | inputs:
7 | dryRun:
8 | description: Set to true for a dry run
9 | required: false
10 | default: "false"
11 | type: string
12 |
13 | jobs:
14 | stale_workflow:
15 | uses: turbot/steampipe-workflows/.github/workflows/stale.yml@main
16 | with:
17 | dryRun: ${{ github.event.inputs.dryRun }}
--------------------------------------------------------------------------------
/.github/workflows/sync-labels.yml:
--------------------------------------------------------------------------------
1 | name: Sync Labels
2 | on:
3 | schedule:
4 | - cron: "30 22 * * 1"
5 | workflow_dispatch:
6 |
7 | jobs:
8 | sync_labels_workflow:
9 | uses: turbot/steampipe-workflows/.github/workflows/sync-labels.yml@main
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Binaries for programs and plugins
2 | *.exe
3 | *.exe~
4 | *.dll
5 | *.so
6 | *.dylib
7 |
8 | # Swap files
9 | *.swp
10 |
11 | .DS_Store
12 |
13 | # Steampipe variable files
14 | *.spvars
15 | *.auto.spvars
16 |
17 | # Powerpipe variable files
18 | *.ppvars
19 | *.auto.ppvars
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | ## v1.0.2 [2025-04-15]
2 |
3 | _Bug fixes_
4 |
5 | - Fixed the `pod_host_network_access_disabled` query to include the `Kubernetes/Pod` service tag. ([#94](https://github.com/turbot/steampipe-mod-kubernetes-compliance/pull/94))
6 |
7 | ## v1.0.1 [2024-10-24]
8 |
9 | _Bug fixes_
10 |
11 | - Renamed `steampipe.spvars.example` files to `powerpipe.ppvars.example` and updated documentation. ([#92](https://github.com/turbot/steampipe-mod-kubernetes-compliance/pull/92))
12 |
13 | ## v1.0.0 [2024-10-22]
14 |
15 | This mod now requires [Powerpipe](https://powerpipe.io). [Steampipe](https://steampipe.io) users should check the [migration guide](https://powerpipe.io/blog/migrating-from-steampipe).
16 |
17 | ## v0.18 [2024-03-06]
18 |
19 | _Powerpipe_
20 |
21 | [Powerpipe](https://powerpipe.io) is now the preferred way to run this mod! [Migrating from Steampipe →](https://powerpipe.io/blog/migrating-from-steampipe)
22 |
23 | All v0.x versions of this mod will work in both Steampipe and Powerpipe, but v1.0.0 onwards will be in Powerpipe format only.
24 |
25 | _Enhancements_
26 |
27 | - Focus documentation on Powerpipe commands.
28 | - Show how to combine Powerpipe mods with Steampipe plugins.
29 |
30 | ## v0.17 [2023-11-03]
31 |
32 | _Breaking changes_
33 |
34 | - Updated the plugin dependency section of the mod to use `min_version` instead of `version`. ([#82](https://github.com/turbot/steampipe-mod-kubernetes-compliance/pull/82))
35 |
36 | _Bug fixes_
37 |
38 | - Updated the docs to include the correct links for the `nsa_cisa_v1` benchmark. ([#80](https://github.com/turbot/steampipe-mod-kubernetes-compliance/pull/80)) (Thanks [@aniketh-varma](https://github.com/aniketh-varma) for the contribution!)
39 | - Fixed the following queries to cast the data to boolean format. ([#79](https://github.com/turbot/steampipe-mod-kubernetes-compliance/pull/79))
40 | - `cronjob_container_privilege_disabled`
41 | - `cronjob_host_network_access_disabled`
42 | - `cronjob_hostpid_hostipc_sharing_disabled`
43 | - `cronjob_immutable_container_filesystem`
44 | - `cronjob_non_root_container`
45 | - `daemonset_container_privilege_disabled`
46 | - `daemonset_host_network_access_disabled`
47 | - `daemonset_hostpid_hostipc_sharing_disabled`
48 | - `daemonset_immutable_container_filesystem`
49 | - `daemonset_non_root_container`
50 | - `deployment_container_privilege_disabled`
51 | - `deployment_host_network_access_disabled`
52 | - `deployment_hostpid_hostipc_sharing_disabled`
53 | - `deployment_immutable_container_filesystem`
54 | - `deployment_non_root_container`
55 | - `job_container_privilege_disabled`
56 | - `job_host_network_access_disabled`
57 | - `job_hostpid_hostipc_sharing_disabled`
58 | - `job_immutable_container_filesystem`
59 | - `job_non_root_container`
60 | - `pod_container_privilege_disabled`
61 | - `pod_immutable_container_filesystem`
62 | - `pod_non_root_container`
63 | - `pod_service_account_token_enabled`
64 | - `pod_template_container_privilege_disabled`
65 | - `pod_template_immutable_container_filesystem`
66 | - `replicaset_container_privilege_disabled`
67 | - `replicaset_host_network_access_disabled`
68 | - `replicaset_hostpid_hostipc_sharing_disabled`
69 | - `replicaset_immutable_container_filesystem`
70 | - `replicaset_non_root_container`
71 | - `replication_controller_container_privilege_disabled`
72 | - `replication_controller_host_network_access_disabled`
73 | - `replication_controller_hostpid_hostipc_sharing_disabled`
74 | - `replication_controller_immutable_container_filesystem`
75 | - `replication_controller_non_root_container`
76 | - `statefulset_container_privilege_disabled`
77 | - `statefulset_host_network_access_disabled`
78 | - `statefulset_hostpid_hostipc_sharing_disabled`
79 | - `statefulset_immutable_container_filesystem`
80 | - `statefulset_non_root_container`
81 |
82 | ## v0.16 [2023-10-04]
83 |
84 | _Bug fixes_
85 |
86 | - Fixed queries to correctly return data for `connection_name` and `tags` dimensions instead of an error. ([#73](https://github.com/turbot/steampipe-mod-kubernetes-compliance/pull/73))
87 |
88 | ## v0.15 [2023-10-03]
89 |
90 | _What's new?_
91 |
92 | - Added 39 new controls for the `ClusterRoleBinding`, `CronJob`, `DaemonSet`, `Ingress`, `Job`, `Pod` resource types to the `all_controls` benchmark. ([#68](https://github.com/turbot/steampipe-mod-kubernetes-compliance/pull/68))
93 |
94 | ## v0.14 [2023-09-29]
95 |
96 | _What's new?_
97 |
98 | - Added 350+ new controls across all resource types to the `all_controls` benchmark. ([#64](https://github.com/turbot/steampipe-mod-kubernetes-compliance/pull/64))
99 |
100 | _Enhancements_
101 |
102 | - Added `path` to default set of `common_dimensions`, so now any file paths will appear by default in the additional dimensions in control results. ([#63](https://github.com/turbot/steampipe-mod-kubernetes-compliance/pull/63))
103 | - Added `iac` category to mod definition.
104 |
105 | _Dependencies_
106 |
107 | - Kubernetes plugin `v0.23.0` or higher is now required.
108 |
109 | ## v0.13 [2023-09-25]
110 |
111 | _Enhancements_
112 |
113 | - Added 112 new controls to the `All Controls` benchmark for the following services: ([#59](https://github.com/turbot/steampipe-mod-kubernetes-compliance/pull/59))
114 | - `CronJob`
115 | - `DaemonSet`
116 | - `Deployment`
117 | - `Job`
118 | - `Pod`
119 | - `ReplicaSet`
120 | - `ReplicationController`
121 | - `StatefulSet`
122 |
123 | ## v0.12 [2023-09-15]
124 |
125 | _Enhancements_
126 |
127 | - Added 90 new controls to the `All Controls` benchmark for the following services: ([#56](https://github.com/turbot/steampipe-mod-kubernetes-compliance/pull/56))
128 | - `CronJob`
129 | - `DaemonSet`
130 | - `Deployment`
131 | - `Job`
132 | - `Pod`
133 | - `ReplicaSet`
134 | - `ReplicationController`
135 | - `StatefulSet`
136 |
137 | _Bug fixes_
138 |
139 | - Fixed the `role_with_wildcards_used` control to correctly return data instead of an error. ([#54](https://github.com/turbot/steampipe-mod-kubernetes-compliance/pull/54))
140 |
141 | ## v0.11 [2023-09-05]
142 |
143 | _Breaking changes_
144 |
145 | - The `Other Compliance Checks` benchmark (`steampipe check benchmark.other_checks`) has been removed and replaced by the new `All Controls` benchmark (`steampipe check benchmark.all_controls`). This new benchmark includes 154 service-specific controls. ([#47](https://github.com/turbot/steampipe-mod-kubernetes-compliance/pull/47))
146 |
147 | _Bug fixes_
148 |
149 | - Fixed the `namespace_*` queries to use the correct common dimensions. ([#49](https://github.com/turbot/steampipe-mod-kubernetes-compliance/pull/49))
150 |
151 | ## v0.10 [2023-06-02]
152 |
153 | _Dependencies_
154 |
155 | - Kubernetes plugin `v0.20.0` or higher is now required. ([#41](https://github.com/turbot/steampipe-mod-kubernetes-compliance/pull/41))
156 |
157 | _What's new?_
158 |
159 | - Added `path` and `source_type` in the common dimensions to group and filter findings. (see [var.common_dimensions](https://hub.steampipe.io/mods/turbot/kubernetes_compliance/variables)) ([#41](https://github.com/turbot/steampipe-mod-kubernetes-compliance/pull/41))
160 |
161 | _Enhancements_
162 |
163 | - Updated the `resource` column to use `path` and `start_line` for manifest resources. ([#41](https://github.com/turbot/steampipe-mod-kubernetes-compliance/pull/41))
164 |
165 | ## v0.9 [2023-05-18]
166 |
167 | _What's new?_
168 |
169 | - Added CIS v1.7.0 for Kubernetes v1.25 benchmark (`steampipe check benchmark.cis_v170`). ([#35](https://github.com/turbot/steampipe-mod-kubernetes-compliance/pull/35))
170 | - Added `connection_name` in the common dimensions to group and filter findings. (see [var.common_dimensions](https://hub.steampipe.io/mods/turbot/kubernetes_compliance/variables)) ([#34](https://github.com/turbot/steampipe-mod-kubernetes-compliance/pull/34))
171 | - Added `tags` as dimensions to group and filter findings. (see [var.tag_dimensions](https://hub.steampipe.io/mods/turbot/kubernetes_compliance/variables)) ([#34](https://github.com/turbot/steampipe-mod-kubernetes-compliance/pull/34))
172 |
173 | _Bug fixes_
174 |
175 | - Fixed dashboard localhost URLs in README and index doc. ([#37](https://github.com/turbot/steampipe-mod-kubernetes-compliance/pull/37))
176 |
177 | ## v0.8 [2023-04-13]
178 |
179 | _Bug fixes_
180 |
181 | - Fixed the structure and the order of sub-benchmarks and controls of `cis_kube_v120_v100_5` benchmark based on the CIS documentation. ([#30](https://github.com/turbot/steampipe-mod-kubernetes-compliance/pull/30))
182 |
183 | ## v0.7 [2022-11-22]
184 |
185 | _Bug fixes_
186 |
187 | - Fixed `pod_service_account_token_disabled`, `pod_security_policy_*` and `service_account_token_disabled` queries to include the name of the relevant resource in the `Reason` column of the compliance report. ([#23](https://github.com/turbot/steampipe-mod-kubernetes-compliance/pull/23))
188 |
189 | ## v0.6 [2022-05-09]
190 |
191 | _Enhancements_
192 |
193 | - Added `category`, `service`, and `type` tags to benchmarks and controls. ([#18](https://github.com/turbot/steampipe-mod-kubernetes-compliance/pull/18))
194 |
195 | _Breaking changes_
196 |
197 | - Updated all CIS Kubernetes v1.20 v1.0.0 filenames, benchmarks, and controls to include the Kubernetes version for future version compatibility. ([#18](https://github.com/turbot/steampipe-mod-kubernetes-compliance/pull/18))
198 | - Fixed all typos in control and query names namesapce->namespace. ([#18](https://github.com/turbot/steampipe-mod-kubernetes-compliance/pull/18))
199 |
200 | ## v0.5 [2022-01-19]
201 |
202 | _What's new?_
203 |
204 | - Added a new benchmark (`cis_v100_5_7_2`) to the `CIS v1.0.0 for Kubernetes v1.20` benchmark ([#13](https://github.com/turbot/steampipe-mod-kubernetes-compliance/pull/13))
205 | - Added new controls for `CronJob`, `ConfigMap`, `Ingress`, `Role`, `RoleBinding`, `Secret` and `StatefulSet` resource types to `CIS v1.0.0 for Kubernetes v1.20`, `Extra Checks` and `NSA CISA Kubernetes Hardening Guidance v1` benchmarks ([#13](https://github.com/turbot/steampipe-mod-kubernetes-compliance/pull/13))
206 |
207 | ## v0.4 [2021-11-12]
208 |
209 | _Enhancements_
210 |
211 | - `docs/index.md` file now includes the console output image
212 |
213 | ## v0.3 [2021-11-10]
214 |
215 | _What's new?_
216 |
217 | - Added: CIS v1.0.0 for Kubernetes v1.20 benchmark (`steampipe check kubernetes_compliance.benchmark.cis_kubernetes_v120`)
218 | - Added: Extra Checks benchmark (`steampipe check kubernetes_compliance.benchmark.extra_checks`) to provide additional information around other Kubernetes compliance best practices
219 |
220 | ## v0.2 [2021-09-22]
221 |
222 | _Bug fixes_
223 |
224 | - Fixed: Broken links in docs/index.md to mod controls and queries
225 |
226 | ## v0.1 [2021-09-22]
227 |
228 | _What's new?_
229 |
230 | - Added: NSA CISA Kubernetes Hardening Guidance v1 benchmark (`steampipe check benchmark.nsa_cisa_v1`)
231 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "[]"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright [yyyy] [name of copyright owner]
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Kubernetes Compliance Mod for Powerpipe
2 |
3 | Multiple checks covering industry defined security best practices for Kubernetes. The mod supports parsing and analyzing Kubernetes manifest files, allowing you to assess compliance directly on your configuration files before deployment. Includes support for CIS, National Security Agency (NSA) and Cybersecurity and Infrastructure Security Agency (CISA) Cybersecurity technical report for Kubernetes hardening.
4 |
5 | Run checks in a dashboard:
6 | 
7 |
8 | Or in a terminal:
9 | 
10 |
11 | ## Documentation
12 |
13 | - **[Benchmarks and controls →](https://hub.powerpipe.io/mods/turbot/kubernetes_compliance/controls)**
14 | - **[Named queries →](https://hub.powerpipe.io/mods/turbot/kubernetes_compliance/queries)**
15 |
16 | ## Getting Started
17 |
18 | ### Installation
19 |
20 | Install Powerpipe (https://powerpipe.io/downloads), or use Brew:
21 |
22 | ```sh
23 | brew install turbot/tap/powerpipe
24 | ```
25 |
26 | This mod also requires [Steampipe](https://steampipe.io) with the [Kubernetes plugin](https://hub.steampipe.io/plugins/turbot/kubernetes) as the data source. Install Steampipe (https://steampipe.io/downloads), or use Brew:
27 |
28 | ```sh
29 | brew install turbot/tap/steampipe
30 | steampipe plugin install kubernetes
31 | ```
32 |
33 | Steampipe will automatically use your default Kubernetes credentials. Optionally, you can [setup multiple context connections](https://hub.steampipe.io/plugins/turbot/kubernetes#multiple-context-connections) or [customize Kubernetes credentials](https://hub.steampipe.io/plugins/turbot/kubernetes#configuring-kubernetes-cluster-credentials).
34 |
35 | Finally, install the mod:
36 |
37 | ```sh
38 | mkdir dashboards
39 | cd dashboards
40 | powerpipe mod init
41 | powerpipe mod install github.com/turbot/steampipe-mod-kubernetes-compliance
42 | ```
43 |
44 | ### Browsing Dashboards
45 |
46 | Start Steampipe as the data source:
47 |
48 | ```sh
49 | steampipe service start
50 | ```
51 |
52 | Start the dashboard server:
53 |
54 | ```sh
55 | powerpipe server
56 | ```
57 |
58 | Browse and view your dashboards at **http://localhost:9033**.
59 |
60 | ### Running Checks in Your Terminal
61 |
62 | Instead of running benchmarks in a dashboard, you can also run them within your
63 | terminal with the `powerpipe benchmark` command:
64 |
65 | List available benchmarks:
66 |
67 | ```sh
68 | powerpipe benchmark list
69 | ```
70 |
71 | Run a benchmark:
72 |
73 | ```sh
74 | powerpipe benchmark run kubernetes_compliance.benchmark.cis_v170
75 | ```
76 |
77 | Different output formats are also available, for more information please see
78 | [Output Formats](https://powerpipe.io/docs/reference/cli/benchmark#output-formats).
79 |
80 | ### Common and Tag Dimensions
81 |
82 | The benchmark queries use common properties (like `connection_name`, `context_name`, `namespace`, `path` and `source_type`) and tags that are defined in the form of a default list of strings in the `variables.sp` file. These properties can be overwritten in several ways:
83 |
84 | It's easiest to setup your vars file, starting with the sample:
85 |
86 | ```sh
87 | cp powerpipe.ppvars.example powerpipe.ppvars
88 | vi powerpipe.ppvars
89 | ```
90 |
91 | Alternatively you can pass variables on the command line:
92 |
93 | ```sh
94 | powerpipe benchmark run kubernetes_compliance.benchmark.cis_v170 --var 'tag_dimensions=["Environment", "Owner"]'
95 | ```
96 |
97 | Or through environment variables:
98 |
99 | ```sh
100 | export PP_VAR_common_dimensions='["connection_name", "context_name", "namespace", "path", "source_type"]'
101 | export PP_VAR_tag_dimensions='["Environment", "Owner"]'
102 | powerpipe benchmark run kubernetes_compliance.benchmark.cis_v170
103 | ```
104 |
105 | ## Open Source & Contributing
106 |
107 | This repository is published under the [Apache 2.0 license](https://www.apache.org/licenses/LICENSE-2.0). Please see our [code of conduct](https://github.com/turbot/.github/blob/main/CODE_OF_CONDUCT.md). We look forward to collaborating with you!
108 |
109 | [Steampipe](https://steampipe.io) and [Powerpipe](https://powerpipe.io) are products produced from this open source software, exclusively by [Turbot HQ, Inc](https://turbot.com). They are distributed under our commercial terms. Others are allowed to make their own distribution of the software, but cannot use any of the Turbot trademarks, cloud services, etc. You can learn more in our [Open Source FAQ](https://turbot.com/open-source).
110 |
111 | ## Get Involved
112 |
113 | **[Join #powerpipe on Slack →](https://turbot.com/community/join)**
114 |
115 | Want to help but don't know where to start? Pick up one of the `help wanted` issues:
116 |
117 | - [Powerpipe](https://github.com/turbot/powerpipe/labels/help%20wanted)
118 | - [Kubernetes Compliance Mod](https://github.com/turbot/steampipe-mod-kubernetes-compliance/labels/help%20wanted)
119 |
--------------------------------------------------------------------------------
/all_controls/all_controls.pp:
--------------------------------------------------------------------------------
1 | locals {
2 | all_controls_common_tags = merge(local.kubernetes_compliance_common_tags, {
3 | type = "Benchmark"
4 | })
5 | }
6 |
7 | benchmark "all_controls" {
8 | title = "All Controls"
9 | description = "This benchmark contains all controls grouped by component to help you detect resource configurations that do not meet best practices."
10 | documentation = file("./all_controls/docs/all_controls_overview.md")
11 | children = [
12 | benchmark.all_controls_cluster_role_binding,
13 | benchmark.all_controls_config_map,
14 | benchmark.all_controls_cronjob,
15 | benchmark.all_controls_daemonset,
16 | benchmark.all_controls_deployment,
17 | benchmark.all_controls_endpoint,
18 | benchmark.all_controls_ingress,
19 | benchmark.all_controls_job,
20 | benchmark.all_controls_namespace,
21 | benchmark.all_controls_network_policy,
22 | benchmark.all_controls_pod,
23 | benchmark.all_controls_pod_security_policy,
24 | benchmark.all_controls_pod_template,
25 | benchmark.all_controls_replicaset,
26 | benchmark.all_controls_replication_controller,
27 | benchmark.all_controls_role,
28 | benchmark.all_controls_role_binding,
29 | benchmark.all_controls_secret,
30 | benchmark.all_controls_service,
31 | benchmark.all_controls_service_account,
32 | benchmark.all_controls_statefulset
33 | ]
34 |
35 | tags = local.all_controls_common_tags
36 | }
37 |
--------------------------------------------------------------------------------
/all_controls/cluster_role_binding.pp:
--------------------------------------------------------------------------------
1 | locals {
2 | all_controls_cluster_role_binding_common_tags = merge(local.all_controls_common_tags, {
3 | service = "Kubernetes/ClusterRoleBinding"
4 | })
5 | }
6 |
7 | benchmark "all_controls_cluster_role_binding" {
8 | title = "Cluster Role Binding"
9 | description = "This section contains recommendations for configuring Cluster Role Binding resources."
10 | children = [
11 | control.cluster_role_binding_default_service_account_binding_not_active
12 | ]
13 |
14 | tags = merge(local.all_controls_cluster_role_binding_common_tags, {
15 | type = "Benchmark"
16 | })
17 | }
18 |
--------------------------------------------------------------------------------
/all_controls/config_map.pp:
--------------------------------------------------------------------------------
1 | locals {
2 | all_controls_config_map_common_tags = merge(local.all_controls_common_tags, {
3 | service = "Kubernetes/ConfigMap"
4 | })
5 | }
6 |
7 | benchmark "all_controls_config_map" {
8 | title = "ConfigMap"
9 | description = "This section contains recommendations for configuring ConfigMap resources."
10 | children = [
11 | control.config_map_default_namespace_used
12 | ]
13 |
14 | tags = merge(local.all_controls_config_map_common_tags, {
15 | type = "Benchmark"
16 | })
17 | }
18 |
--------------------------------------------------------------------------------
/all_controls/cronjob.pp:
--------------------------------------------------------------------------------
1 | locals {
2 | all_controls_cronjob_common_tags = merge(local.all_controls_common_tags, {
3 | service = "Kubernetes/CronJob"
4 | })
5 | }
6 |
7 | benchmark "all_controls_cronjob" {
8 | title = "CronJob"
9 | description = "This section contains recommendations for configuring CronJob resources."
10 | children = [
11 | control.cronjob_container_admission_capability_restricted,
12 | control.cronjob_container_admission_control_plugin_always_pull_images,
13 | control.cronjob_container_admission_control_plugin_no_always_admit,
14 | control.cronjob_container_arg_peer_client_cert_auth_enabled,
15 | control.cronjob_container_argument_anonymous_auth_disabled,
16 | control.cronjob_container_argument_audit_log_maxage_greater_than_30,
17 | control.cronjob_container_argument_audit_log_maxbackup_greater_than_10,
18 | control.cronjob_container_argument_audit_log_maxsize_greater_than_100,
19 | control.cronjob_container_argument_audit_log_path_configured,
20 | control.cronjob_container_argument_authorization_mode_no_always_allow,
21 | control.cronjob_container_argument_authorization_mode_node,
22 | control.cronjob_container_argument_authorization_mode_rbac,
23 | control.cronjob_container_argument_etcd_auto_tls_disabled,
24 | control.cronjob_container_argument_etcd_cafile_configured,
25 | control.cronjob_container_argument_etcd_certfile_and_keyfile_configured,
26 | control.cronjob_container_argument_etcd_client_cert_auth_enabled,
27 | control.cronjob_container_argument_etcd_peer_certfile_and_peer_keyfile_configured,
28 | control.cronjob_container_argument_event_qps_less_than_5,
29 | control.cronjob_container_argument_insecure_port_0,
30 | control.cronjob_container_argument_kube_apiserver_etcd_certfile_and_keyfile_configured,
31 | control.cronjob_container_argument_kube_apiserver_profiling_disabled,
32 | control.cronjob_container_argument_kube_apiserver_tls_cert_file_and_tls_private_key_file_configured,
33 | control.cronjob_container_argument_kube_controller_manager_bind_address_127_0_0_1,
34 | control.cronjob_container_argument_kube_controller_manager_profiling_disabled,
35 | control.cronjob_container_argument_kube_controller_manager_root_ca_file_configured,
36 | control.cronjob_container_argument_kube_controller_manager_service_account_credentials_enabled,
37 | control.cronjob_container_argument_kube_controller_manager_service_account_private_key_file_configured,
38 | control.cronjob_container_argument_kube_scheduler_bind_address_127_0_0_1,
39 | control.cronjob_container_argument_kube_scheduler_profiling_disabled,
40 | control.cronjob_container_argument_kubelet_authorization_mode_no_always_allow,
41 | control.cronjob_container_argument_kubelet_client_ca_file_configured,
42 | control.cronjob_container_argument_kubelet_client_certificate_and_key_configured,
43 | control.cronjob_container_argument_kubelet_https_enabled,
44 | control.cronjob_container_argument_kubelet_read_only_port_0,
45 | control.cronjob_container_argument_kubelet_terminated_pod_gc_threshold_configured,
46 | control.cronjob_container_argument_kubelet_tls_cert_file_and_tls_private_key_file_configured,
47 | control.cronjob_container_argument_make_iptables_util_chains_enabled,
48 | control.cronjob_container_argument_namespace_lifecycle_enabled,
49 | control.cronjob_container_argument_node_restriction_enabled,
50 | control.cronjob_container_argument_pod_security_policy_enabled,
51 | control.cronjob_container_argument_protect_kernel_defaults_enabled,
52 | control.cronjob_container_argument_request_timeout_appropriate,
53 | control.cronjob_container_argument_rotate_kubelet_server_certificate_enabled,
54 | control.cronjob_container_argument_secure_port_not_0,
55 | control.cronjob_container_argument_security_context_deny_enabled,
56 | control.cronjob_container_argument_service_account_enabled,
57 | control.cronjob_container_argument_service_account_key_file_appropriate,
58 | control.cronjob_container_argument_service_account_lookup_enabled,
59 | control.cronjob_container_capabilities_drop_all,
60 | control.cronjob_container_encryption_providers_configured,
61 | control.cronjob_container_host_port_not_specified,
62 | control.cronjob_container_image_pull_policy_always,
63 | control.cronjob_container_image_tag_specified,
64 | control.cronjob_container_kubelet_certificate_authority_configured,
65 | control.cronjob_container_kubernetes_dashboard_not_deployed,
66 | control.cronjob_container_liveness_probe,
67 | control.cronjob_container_no_argument_basic_auth_file,
68 | control.cronjob_container_no_argument_hostname_override_configured,
69 | control.cronjob_container_no_argument_insecure_bind_address,
70 | control.cronjob_container_privilege_disabled,
71 | control.cronjob_container_privilege_escalation_disabled,
72 | control.cronjob_container_privilege_port_mapped,
73 | control.cronjob_container_readiness_probe,
74 | control.cronjob_container_rotate_certificate_enabled,
75 | control.cronjob_container_secrets_defined_as_files,
76 | control.cronjob_container_security_context_exists,
77 | control.cronjob_container_streaming_connection_idle_timeout_not_zero,
78 | control.cronjob_container_strong_kube_apiserver_cryptographic_ciphers,
79 | control.cronjob_container_strong_kubelet_cryptographic_ciphers,
80 | control.cronjob_container_sys_admin_capability_disabled,
81 | control.cronjob_container_token_auth_file_not_configured,
82 | control.cronjob_container_with_added_capabilities,
83 | control.cronjob_cpu_limit,
84 | control.cronjob_cpu_request,
85 | control.cronjob_default_namespace_used,
86 | control.cronjob_default_seccomp_profile_enabled,
87 | control.cronjob_host_network_access_disabled,
88 | control.cronjob_hostpid_hostipc_sharing_disabled,
89 | control.cronjob_immutable_container_filesystem,
90 | control.cronjob_memory_limit,
91 | control.cronjob_memory_request,
92 | control.cronjob_non_root_container
93 | ]
94 |
95 | tags = merge(local.all_controls_cronjob_common_tags, {
96 | type = "Benchmark"
97 | })
98 | }
99 |
--------------------------------------------------------------------------------
/all_controls/daemonset.pp:
--------------------------------------------------------------------------------
1 | locals {
2 | all_controls_daemonset_common_tags = merge(local.all_controls_common_tags, {
3 | service = "Kubernetes/DaemonSet"
4 | })
5 | }
6 |
7 | benchmark "all_controls_daemonset" {
8 | title = "DaemonSet"
9 | description = "This section contains recommendations for configuring DaemonSet resources."
10 | children = [
11 | control.daemonset_container_admission_capability_restricted,
12 | control.daemonset_container_admission_control_plugin_always_pull_images,
13 | control.daemonset_container_admission_control_plugin_no_always_admit,
14 | control.daemonset_container_arg_peer_client_cert_auth_enabled,
15 | control.daemonset_container_argument_anonymous_auth_disabled,
16 | control.daemonset_container_argument_audit_log_maxage_greater_than_30,
17 | control.daemonset_container_argument_audit_log_maxbackup_greater_than_10,
18 | control.daemonset_container_argument_audit_log_maxsize_greater_than_100,
19 | control.daemonset_container_argument_audit_log_path_configured,
20 | control.daemonset_container_argument_authorization_mode_no_always_allow,
21 | control.daemonset_container_argument_authorization_mode_node,
22 | control.daemonset_container_argument_authorization_mode_rbac,
23 | control.daemonset_container_argument_etcd_auto_tls_disabled,
24 | control.daemonset_container_argument_etcd_cafile_configured,
25 | control.daemonset_container_argument_etcd_certfile_and_keyfile_configured,
26 | control.daemonset_container_argument_etcd_client_cert_auth_enabled,
27 | control.daemonset_container_argument_etcd_peer_certfile_and_peer_keyfile_configured,
28 | control.daemonset_container_argument_event_qps_less_than_5,
29 | control.daemonset_container_argument_insecure_port_0,
30 | control.daemonset_container_argument_kube_apiserver_etcd_certfile_and_keyfile_configured,
31 | control.daemonset_container_argument_kube_apiserver_profiling_disabled,
32 | control.daemonset_container_argument_kube_apiserver_tls_cert_file_and_tls_private_key_file_configured,
33 | control.daemonset_container_argument_kube_controller_manager_bind_address_127_0_0_1,
34 | control.daemonset_container_argument_kube_controller_manager_profiling_disabled,
35 | control.daemonset_container_argument_kube_controller_manager_root_ca_file_configured,
36 | control.daemonset_container_argument_kube_controller_manager_service_account_credentials_enabled,
37 | control.daemonset_container_argument_kube_controller_manager_service_account_private_key_file_configured,
38 | control.daemonset_container_argument_kube_scheduler_bind_address_127_0_0_1,
39 | control.daemonset_container_argument_kube_scheduler_profiling_disabled,
40 | control.daemonset_container_argument_kubelet_authorization_mode_no_always_allow,
41 | control.daemonset_container_argument_kubelet_client_ca_file_configured,
42 | control.daemonset_container_argument_kubelet_client_certificate_and_key_configured,
43 | control.daemonset_container_argument_kubelet_https_enabled,
44 | control.daemonset_container_argument_kubelet_read_only_port_0,
45 | control.daemonset_container_argument_kubelet_terminated_pod_gc_threshold_configured,
46 | control.daemonset_container_argument_kubelet_tls_cert_file_and_tls_private_key_file_configured,
47 | control.daemonset_container_argument_make_iptables_util_chains_enabled,
48 | control.daemonset_container_argument_namespace_lifecycle_enabled,
49 | control.daemonset_container_argument_node_restriction_enabled,
50 | control.daemonset_container_argument_pod_security_policy_enabled,
51 | control.daemonset_container_argument_protect_kernel_defaults_enabled,
52 | control.daemonset_container_argument_request_timeout_appropriate,
53 | control.daemonset_container_argument_rotate_kubelet_server_certificate_enabled,
54 | control.daemonset_container_argument_secure_port_not_0,
55 | control.daemonset_container_argument_security_context_deny_enabled,
56 | control.daemonset_container_argument_service_account_enabled,
57 | control.daemonset_container_argument_service_account_key_file_appropriate,
58 | control.daemonset_container_argument_service_account_lookup_enabled,
59 | control.daemonset_container_capabilities_drop_all,
60 | control.daemonset_container_encryption_providers_configured,
61 | control.daemonset_container_host_port_not_specified,
62 | control.daemonset_container_image_pull_policy_always,
63 | control.daemonset_container_image_tag_specified,
64 | control.daemonset_container_kubelet_certificate_authority_configured,
65 | control.daemonset_container_kubernetes_dashboard_not_deployed,
66 | control.daemonset_container_liveness_probe,
67 | control.daemonset_container_no_argument_basic_auth_file,
68 | control.daemonset_container_no_argument_hostname_override_configured,
69 | control.daemonset_container_no_argument_insecure_bind_address,
70 | control.daemonset_container_privilege_disabled,
71 | control.daemonset_container_privilege_escalation_disabled,
72 | control.daemonset_container_privilege_port_mapped,
73 | control.daemonset_container_readiness_probe,
74 | control.daemonset_container_rotate_certificate_enabled,
75 | control.daemonset_container_secrets_defined_as_files,
76 | control.daemonset_container_security_context_exists,
77 | control.daemonset_container_streaming_connection_idle_timeout_not_zero,
78 | control.daemonset_container_strong_kube_apiserver_cryptographic_ciphers,
79 | control.daemonset_container_strong_kubelet_cryptographic_ciphers,
80 | control.daemonset_container_sys_admin_capability_disabled,
81 | control.daemonset_container_token_auth_file_not_configured,
82 | control.daemonset_container_with_added_capabilities,
83 | control.daemonset_cpu_limit,
84 | control.daemonset_cpu_request,
85 | control.daemonset_default_namespace_used,
86 | control.daemonset_default_seccomp_profile_enabled,
87 | control.daemonset_host_network_access_disabled,
88 | control.daemonset_hostpid_hostipc_sharing_disabled,
89 | control.daemonset_immutable_container_filesystem,
90 | control.daemonset_memory_limit,
91 | control.daemonset_memory_request,
92 | control.daemonset_non_root_container
93 | ]
94 |
95 | tags = merge(local.all_controls_daemonset_common_tags, {
96 | type = "Benchmark"
97 | })
98 | }
99 |
--------------------------------------------------------------------------------
/all_controls/deployment.pp:
--------------------------------------------------------------------------------
1 | locals {
2 | all_controls_deployment_common_tags = merge(local.all_controls_common_tags, {
3 | service = "Kubernetes/Deployment"
4 | })
5 | }
6 |
7 | benchmark "all_controls_deployment" {
8 | title = "Deployment"
9 | description = "This section contains recommendations for configuring Deployment resources."
10 | children = [
11 | control.deployment_container_admission_capability_restricted,
12 | control.deployment_container_admission_control_plugin_always_pull_images,
13 | control.deployment_container_admission_control_plugin_no_always_admit,
14 | control.deployment_container_arg_peer_client_cert_auth_enabled,
15 | control.deployment_container_argument_anonymous_auth_disabled,
16 | control.deployment_container_argument_audit_log_maxage_greater_than_30,
17 | control.deployment_container_argument_audit_log_maxbackup_greater_than_10,
18 | control.deployment_container_argument_audit_log_maxsize_greater_than_100,
19 | control.deployment_container_argument_audit_log_path_configured,
20 | control.deployment_container_argument_authorization_mode_no_always_allow,
21 | control.deployment_container_argument_authorization_mode_node,
22 | control.deployment_container_argument_authorization_mode_rbac,
23 | control.deployment_container_argument_etcd_auto_tls_disabled,
24 | control.deployment_container_argument_etcd_cafile_configured,
25 | control.deployment_container_argument_etcd_certfile_and_keyfile_configured,
26 | control.deployment_container_argument_etcd_client_cert_auth_enabled,
27 | control.deployment_container_argument_etcd_peer_certfile_and_peer_keyfile_configured,
28 | control.deployment_container_argument_event_qps_less_than_5,
29 | control.deployment_container_argument_insecure_port_0,
30 | control.deployment_container_argument_kube_apiserver_etcd_certfile_and_keyfile_configured,
31 | control.deployment_container_argument_kube_apiserver_profiling_disabled,
32 | control.deployment_container_argument_kube_apiserver_tls_cert_file_and_tls_private_key_file_configured,
33 | control.deployment_container_argument_kube_controller_manager_bind_address_127_0_0_1,
34 | control.deployment_container_argument_kube_controller_manager_profiling_disabled,
35 | control.deployment_container_argument_kube_controller_manager_root_ca_file_configured,
36 | control.deployment_container_argument_kube_controller_manager_service_account_credentials_enabled,
37 | control.deployment_container_argument_kube_controller_manager_service_account_private_key_file_configured,
38 | control.deployment_container_argument_kube_scheduler_bind_address_127_0_0_1,
39 | control.deployment_container_argument_kube_scheduler_profiling_disabled,
40 | control.deployment_container_argument_kubelet_authorization_mode_no_always_allow,
41 | control.deployment_container_argument_kubelet_client_ca_file_configured,
42 | control.deployment_container_argument_kubelet_client_certificate_and_key_configured,
43 | control.deployment_container_argument_kubelet_https_enabled,
44 | control.deployment_container_argument_kubelet_read_only_port_0,
45 | control.deployment_container_argument_kubelet_terminated_pod_gc_threshold_configured,
46 | control.deployment_container_argument_kubelet_tls_cert_file_and_tls_private_key_file_configured,
47 | control.deployment_container_argument_make_iptables_util_chains_enabled,
48 | control.deployment_container_argument_namespace_lifecycle_enabled,
49 | control.deployment_container_argument_node_restriction_enabled,
50 | control.deployment_container_argument_pod_security_policy_enabled,
51 | control.deployment_container_argument_protect_kernel_defaults_enabled,
52 | control.deployment_container_argument_request_timeout_appropriate,
53 | control.deployment_container_argument_rotate_kubelet_server_certificate_enabled,
54 | control.deployment_container_argument_secure_port_not_0,
55 | control.deployment_container_argument_security_context_deny_enabled,
56 | control.deployment_container_argument_service_account_enabled,
57 | control.deployment_container_argument_service_account_key_file_appropriate,
58 | control.deployment_container_argument_service_account_lookup_enabled,
59 | control.deployment_container_capabilities_drop_all,
60 | control.deployment_container_encryption_providers_configured,
61 | control.deployment_container_host_port_not_specified,
62 | control.deployment_container_image_pull_policy_always,
63 | control.deployment_container_image_tag_specified,
64 | control.deployment_container_kubelet_certificate_authority_configured,
65 | control.deployment_container_kubernetes_dashboard_not_deployed,
66 | control.deployment_container_liveness_probe,
67 | control.deployment_container_no_argument_basic_auth_file,
68 | control.deployment_container_no_argument_hostname_override_configured,
69 | control.deployment_container_no_argument_insecure_bind_address,
70 | control.deployment_container_privilege_disabled,
71 | control.deployment_container_privilege_escalation_disabled,
72 | control.deployment_container_privilege_port_mapped,
73 | control.deployment_container_readiness_probe,
74 | control.deployment_container_rotate_certificate_enabled,
75 | control.deployment_container_secrets_defined_as_files,
76 | control.deployment_container_security_context_exists,
77 | control.deployment_container_streaming_connection_idle_timeout_not_zero,
78 | control.deployment_container_strong_kube_apiserver_cryptographic_ciphers,
79 | control.deployment_container_strong_kubelet_cryptographic_ciphers,
80 | control.deployment_container_sys_admin_capability_disabled,
81 | control.deployment_container_token_auth_file_not_configured,
82 | control.deployment_container_with_added_capabilities,
83 | control.deployment_cpu_limit,
84 | control.deployment_cpu_request,
85 | control.deployment_default_namespace_used,
86 | control.deployment_default_seccomp_profile_enabled,
87 | control.deployment_host_network_access_disabled,
88 | control.deployment_hostpid_hostipc_sharing_disabled,
89 | control.deployment_immutable_container_filesystem,
90 | control.deployment_memory_limit,
91 | control.deployment_memory_request,
92 | control.deployment_non_root_container,
93 | control.deployment_replica_minimum_3
94 | ]
95 |
96 | tags = merge(local.all_controls_deployment_common_tags, {
97 | type = "Benchmark"
98 | })
99 | }
100 |
--------------------------------------------------------------------------------
/all_controls/docs/all_controls_overview.md:
--------------------------------------------------------------------------------
1 | ## Overview
2 |
3 | We are adding additional checks to improve the information gathering around other Kubernetes compliance best practices, these checks are out of the scope of any predefined benchmarks for Kubernetes but we consider them very helpful.
--------------------------------------------------------------------------------
/all_controls/endpoint.pp:
--------------------------------------------------------------------------------
1 | locals {
2 | all_controls_endpoint_common_tags = merge(local.all_controls_common_tags, {
3 | service = "Kubernetes/Endpoint"
4 | })
5 | }
6 |
7 | benchmark "all_controls_endpoint" {
8 | title = "Endpoint"
9 | description = "This section contains recommendations for configuring Endpoint resources."
10 | children = [
11 | control.endpoint_api_serve_on_secure_port
12 | ]
13 |
14 | tags = merge(local.all_controls_endpoint_common_tags, {
15 | type = "Benchmark"
16 | })
17 | }
18 |
--------------------------------------------------------------------------------
/all_controls/ingress.pp:
--------------------------------------------------------------------------------
1 | locals {
2 | all_controls_ingress_common_tags = merge(local.all_controls_common_tags, {
3 | service = "Kubernetes/Ingress"
4 | })
5 | }
6 |
7 | benchmark "all_controls_ingress" {
8 | title = "Ingress"
9 | description = "This section contains recommendations for configuring Ingress resources."
10 | children = [
11 | control.ingress_default_namespace_used,
12 | control.ingress_nginx_annotations_all_snippets_not_used,
13 | control.ingress_nginx_annotations_snippets_alias_not_used,
14 | control.ingress_nginx_annotations_snippets_lua_code_not_used
15 | ]
16 |
17 | tags = merge(local.all_controls_ingress_common_tags, {
18 | type = "Benchmark"
19 | })
20 | }
21 |
--------------------------------------------------------------------------------
/all_controls/job.pp:
--------------------------------------------------------------------------------
1 | locals {
2 | all_controls_job_common_tags = merge(local.all_controls_common_tags, {
3 | service = "Kubernetes/Job"
4 | })
5 | }
6 |
7 | benchmark "all_controls_job" {
8 | title = "Job"
9 | description = "This section contains recommendations for configuring Job resources."
10 | children = [
11 | control.job_container_admission_capability_restricted,
12 | control.job_container_admission_control_plugin_always_pull_images,
13 | control.job_container_admission_control_plugin_no_always_admit,
14 | control.job_container_arg_peer_client_cert_auth_enabled,
15 | control.job_container_argument_anonymous_auth_disabled,
16 | control.job_container_argument_audit_log_maxage_greater_than_30,
17 | control.job_container_argument_audit_log_maxbackup_greater_than_10,
18 | control.job_container_argument_audit_log_maxsize_greater_than_100,
19 | control.job_container_argument_audit_log_path_configured,
20 | control.job_container_argument_authorization_mode_no_always_allow,
21 | control.job_container_argument_authorization_mode_node,
22 | control.job_container_argument_authorization_mode_rbac,
23 | control.job_container_argument_etcd_auto_tls_disabled,
24 | control.job_container_argument_etcd_cafile_configured,
25 | control.job_container_argument_etcd_certfile_and_keyfile_configured,
26 | control.job_container_argument_etcd_client_cert_auth_enabled,
27 | control.job_container_argument_etcd_peer_certfile_and_peer_keyfile_configured,
28 | control.job_container_argument_event_qps_less_than_5,
29 | control.job_container_argument_insecure_port_0,
30 | control.job_container_argument_kube_apiserver_etcd_certfile_and_keyfile_configured,
31 | control.job_container_argument_kube_apiserver_profiling_disabled,
32 | control.job_container_argument_kube_apiserver_tls_cert_file_and_tls_private_key_file_configured,
33 | control.job_container_argument_kube_controller_manager_bind_address_127_0_0_1,
34 | control.job_container_argument_kube_controller_manager_profiling_disabled,
35 | control.job_container_argument_kube_controller_manager_root_ca_file_configured,
36 | control.job_container_argument_kube_controller_manager_service_account_credentials_enabled,
37 | control.job_container_argument_kube_controller_manager_service_account_private_key_file_configured,
38 | control.job_container_argument_kube_scheduler_bind_address_127_0_0_1,
39 | control.job_container_argument_kube_scheduler_profiling_disabled,
40 | control.job_container_argument_kubelet_authorization_mode_no_always_allow,
41 | control.job_container_argument_kubelet_client_ca_file_configured,
42 | control.job_container_argument_kubelet_client_certificate_and_key_configured,
43 | control.job_container_argument_kubelet_https_enabled,
44 | control.job_container_argument_kubelet_read_only_port_0,
45 | control.job_container_argument_kubelet_terminated_pod_gc_threshold_configured,
46 | control.job_container_argument_kubelet_tls_cert_file_and_tls_private_key_file_configured,
47 | control.job_container_argument_make_iptables_util_chains_enabled,
48 | control.job_container_argument_namespace_lifecycle_enabled,
49 | control.job_container_argument_node_restriction_enabled,
50 | control.job_container_argument_pod_security_policy_enabled,
51 | control.job_container_argument_protect_kernel_defaults_enabled,
52 | control.job_container_argument_request_timeout_appropriate,
53 | control.job_container_argument_rotate_kubelet_server_certificate_enabled,
54 | control.job_container_argument_secure_port_not_0,
55 | control.job_container_argument_security_context_deny_enabled,
56 | control.job_container_argument_service_account_enabled,
57 | control.job_container_argument_service_account_key_file_appropriate,
58 | control.job_container_argument_service_account_lookup_enabled,
59 | control.job_container_capabilities_drop_all,
60 | control.job_container_encryption_providers_configured,
61 | control.job_container_host_port_not_specified,
62 | control.job_container_image_pull_policy_always,
63 | control.job_container_image_tag_specified,
64 | control.job_container_kubelet_certificate_authority_configured,
65 | control.job_container_kubernetes_dashboard_not_deployed,
66 | control.job_container_liveness_probe,
67 | control.job_container_no_argument_basic_auth_file,
68 | control.job_container_no_argument_hostname_override_configured,
69 | control.job_container_no_argument_insecure_bind_address,
70 | control.job_container_privilege_disabled,
71 | control.job_container_privilege_escalation_disabled,
72 | control.job_container_privilege_port_mapped,
73 | control.job_container_readiness_probe,
74 | control.job_container_rotate_certificate_enabled,
75 | control.job_container_secrets_defined_as_files,
76 | control.job_container_security_context_exists,
77 | control.job_container_streaming_connection_idle_timeout_not_zero,
78 | control.job_container_strong_kube_apiserver_cryptographic_ciphers,
79 | control.job_container_strong_kubelet_cryptographic_ciphers,
80 | control.job_container_sys_admin_capability_disabled,
81 | control.job_container_token_auth_file_not_configured,
82 | control.job_container_with_added_capabilities,
83 | control.job_cpu_limit,
84 | control.job_cpu_request,
85 | control.job_default_namespace_used,
86 | control.job_default_seccomp_profile_enabled,
87 | control.job_host_network_access_disabled,
88 | control.job_hostpid_hostipc_sharing_disabled,
89 | control.job_immutable_container_filesystem,
90 | control.job_memory_limit,
91 | control.job_memory_request,
92 | control.job_non_root_container
93 | ]
94 |
95 | tags = merge(local.all_controls_job_common_tags, {
96 | type = "Benchmark"
97 | })
98 | }
99 |
--------------------------------------------------------------------------------
/all_controls/namespace.pp:
--------------------------------------------------------------------------------
1 | locals {
2 | all_controls_namespace_common_tags = merge(local.all_controls_common_tags, {
3 | service = "Kubernetes/Namespace"
4 | })
5 | }
6 |
7 | benchmark "all_controls_namespace" {
8 | title = "Namespace"
9 | description = "This section contains recommendations for configuring Namespace resources."
10 | children = [
11 | control.namespace_limit_range_default_cpu_limit,
12 | control.namespace_limit_range_default_cpu_request,
13 | control.namespace_limit_range_default_memory_limit,
14 | control.namespace_limit_range_default_memory_request,
15 | control.namespace_resource_quota_cpu_limit,
16 | control.namespace_resource_quota_cpu_request,
17 | control.namespace_resource_quota_memory_limit,
18 | control.namespace_resource_quota_memory_request
19 | ]
20 |
21 | tags = merge(local.all_controls_namespace_common_tags, {
22 | type = "Benchmark"
23 | })
24 | }
25 |
--------------------------------------------------------------------------------
/all_controls/network_policy.pp:
--------------------------------------------------------------------------------
1 | locals {
2 | all_controls_network_policy_common_tags = merge(local.all_controls_common_tags, {
3 | service = "Kubernetes/NetworkPolicy"
4 | })
5 | }
6 |
7 | benchmark "all_controls_network_policy" {
8 | title = "Network Policy"
9 | description = "This section contains recommendations for configuring Network Policy resources."
10 | children = [
11 | control.network_policy_default_deny_egress,
12 | control.network_policy_default_deny_ingress,
13 | control.network_policy_default_dont_allow_egress,
14 | control.network_policy_default_dont_allow_ingress
15 | ]
16 |
17 | tags = merge(local.all_controls_network_policy_common_tags, {
18 | type = "Benchmark"
19 | })
20 | }
21 |
--------------------------------------------------------------------------------
/all_controls/pod.pp:
--------------------------------------------------------------------------------
1 | locals {
2 | all_controls_pod_common_tags = merge(local.all_controls_common_tags, {
3 | service = "Kubernetes/Pod"
4 | })
5 | }
6 |
7 | benchmark "all_controls_pod" {
8 | title = "Pod"
9 | description = "This section contains recommendations for configuring Pod resources."
10 | children = [
11 | control.pod_container_admission_capability_restricted,
12 | control.pod_container_admission_control_plugin_always_pull_images,
13 | control.pod_container_admission_control_plugin_no_always_admit,
14 | control.pod_container_arg_peer_client_cert_auth_enabled,
15 | control.pod_container_argument_anonymous_auth_disabled,
16 | control.pod_container_argument_audit_log_maxage_greater_than_30,
17 | control.pod_container_argument_audit_log_maxbackup_greater_than_10,
18 | control.pod_container_argument_audit_log_maxsize_greater_than_100,
19 | control.pod_container_argument_audit_log_path_configured,
20 | control.pod_container_argument_authorization_mode_no_always_allow,
21 | control.pod_container_argument_authorization_mode_node,
22 | control.pod_container_argument_authorization_mode_rbac,
23 | control.pod_container_argument_etcd_auto_tls_disabled,
24 | control.pod_container_argument_etcd_cafile_configured,
25 | control.pod_container_argument_etcd_certfile_and_keyfile_configured,
26 | control.pod_container_argument_etcd_client_cert_auth_enabled,
27 | control.pod_container_argument_etcd_peer_certfile_and_peer_keyfile_configured,
28 | control.pod_container_argument_event_qps_less_than_5,
29 | control.pod_container_argument_insecure_port_0,
30 | control.pod_container_argument_kube_apiserver_etcd_certfile_and_keyfile_configured,
31 | control.pod_container_argument_kube_apiserver_profiling_disabled,
32 | control.pod_container_argument_kube_apiserver_tls_cert_file_and_tls_private_key_file_configured,
33 | control.pod_container_argument_kube_controller_manager_bind_address_127_0_0_1,
34 | control.pod_container_argument_kube_controller_manager_profiling_disabled,
35 | control.pod_container_argument_kube_controller_manager_root_ca_file_configured,
36 | control.pod_container_argument_kube_controller_manager_service_account_credentials_enabled,
37 | control.pod_container_argument_kube_controller_manager_service_account_private_key_file_configured,
38 | control.pod_container_argument_kube_scheduler_bind_address_127_0_0_1,
39 | control.pod_container_argument_kube_scheduler_profiling_disabled,
40 | control.pod_container_argument_kubelet_authorization_mode_no_always_allow,
41 | control.pod_container_argument_kubelet_client_ca_file_configured,
42 | control.pod_container_argument_kubelet_client_certificate_and_key_configured,
43 | control.pod_container_argument_kubelet_https_enabled,
44 | control.pod_container_argument_kubelet_read_only_port_0,
45 | control.pod_container_argument_kubelet_terminated_pod_gc_threshold_configured,
46 | control.pod_container_argument_kubelet_tls_cert_file_and_tls_private_key_file_configured,
47 | control.pod_container_argument_make_iptables_util_chains_enabled,
48 | control.pod_container_argument_namespace_lifecycle_enabled,
49 | control.pod_container_argument_node_restriction_enabled,
50 | control.pod_container_argument_pod_security_policy_enabled,
51 | control.pod_container_argument_protect_kernel_defaults_enabled,
52 | control.pod_container_argument_request_timeout_appropriate,
53 | control.pod_container_argument_rotate_kubelet_server_certificate_enabled,
54 | control.pod_container_argument_secure_port_not_0,
55 | control.pod_container_argument_security_context_deny_enabled,
56 | control.pod_container_argument_service_account_enabled,
57 | control.pod_container_argument_service_account_key_file_appropriate,
58 | control.pod_container_argument_service_account_lookup_enabled,
59 | control.pod_container_capabilities_drop_all,
60 | control.pod_container_encryption_providers_configured,
61 | control.pod_container_host_port_not_specified,
62 | control.pod_container_image_pull_policy_always,
63 | control.pod_container_image_tag_specified,
64 | control.pod_container_kubelet_certificate_authority_configured,
65 | control.pod_container_kubernetes_dashboard_not_deployed,
66 | control.pod_container_liveness_probe,
67 | control.pod_container_memory_limit,
68 | control.pod_container_memory_request,
69 | control.pod_container_no_argument_basic_auth_file,
70 | control.pod_container_no_argument_hostname_override_configured,
71 | control.pod_container_no_argument_insecure_bind_address,
72 | control.pod_container_privilege_disabled,
73 | control.pod_container_privilege_escalation_disabled,
74 | control.pod_container_privilege_port_mapped,
75 | control.pod_container_readiness_probe,
76 | control.pod_container_rotate_certificate_enabled,
77 | control.pod_container_run_as_user_10000,
78 | control.pod_container_secrets_defined_as_files,
79 | control.pod_container_security_context_exists,
80 | control.pod_container_streaming_connection_idle_timeout_not_zero,
81 | control.pod_container_strong_kube_apiserver_cryptographic_ciphers,
82 | control.pod_container_strong_kubelet_cryptographic_ciphers,
83 | control.pod_container_sys_admin_capability_disabled,
84 | control.pod_container_token_auth_file_not_configured,
85 | control.pod_container_with_added_capabilities,
86 | control.pod_default_namespace_used,
87 | control.pod_default_seccomp_profile_enabled,
88 | control.pod_host_network_access_disabled,
89 | control.pod_hostpid_hostipc_sharing_disabled,
90 | control.pod_immutable_container_filesystem,
91 | control.pod_non_root_container,
92 | control.pod_service_account_not_exist,
93 | control.pod_service_account_token_disabled,
94 | control.pod_service_account_token_enabled,
95 | control.pod_volume_host_path
96 | ]
97 |
98 | tags = merge(local.all_controls_pod_common_tags, {
99 | type = "Benchmark"
100 | })
101 | }
102 |
--------------------------------------------------------------------------------
/all_controls/pod_security_policy.pp:
--------------------------------------------------------------------------------
1 | locals {
2 | all_controls_pod_security_policy_common_tags = merge(local.all_controls_common_tags, {
3 | service = "Kubernetes/PodSecurityPolicy"
4 | })
5 | }
6 |
7 | benchmark "all_controls_pod_security_policy" {
8 | title = "Pod Security Policy"
9 | description = "This section contains recommendations for configuring Pod Security Policy resources."
10 | children = [
11 | control.pod_security_policy_allowed_host_path,
12 | control.pod_security_policy_container_privilege_disabled,
13 | control.pod_security_policy_container_privilege_escalation_disabled,
14 | control.pod_security_policy_default_seccomp_profile_enabled,
15 | control.pod_security_policy_host_network_access_disabled,
16 | control.pod_security_policy_hostipc_sharing_disabled,
17 | control.pod_security_policy_hostpid_hostipc_sharing_disabled,
18 | control.pod_security_policy_hostpid_sharing_disabled,
19 | control.pod_security_policy_immutable_container_filesystem,
20 | control.pod_security_policy_non_root_container,
21 | control.pod_security_policy_security_services_hardening
22 | ]
23 |
24 | tags = merge(local.all_controls_pod_security_policy_common_tags, {
25 | type = "Benchmark"
26 | })
27 | }
28 |
--------------------------------------------------------------------------------
/all_controls/pod_template.pp:
--------------------------------------------------------------------------------
1 | locals {
2 | all_controls_pod_template_common_tags = merge(local.all_controls_common_tags, {
3 | service = "Kubernetes/PodTemplate"
4 | })
5 | }
6 |
7 | benchmark "all_controls_pod_template" {
8 | title = "PodTemplate"
9 | description = "This section contains recommendations for configuring PodTemplate resources."
10 |
11 | children = [
12 | control.pod_template_container_admission_capability_restricted,
13 | control.pod_template_container_admission_control_plugin_always_pull_images,
14 | control.pod_template_container_admission_control_plugin_no_always_admit,
15 | control.pod_template_container_argument_api_server_anonymous_auth_disabled,
16 | control.pod_template_container_argument_api_server_etcd_certfile_and_keyfile_configured,
17 | control.pod_template_container_argument_audit_log_maxage_greater_than_30,
18 | control.pod_template_container_argument_audit_log_maxbackup_greater_than_10,
19 | control.pod_template_container_argument_audit_log_maxsize_greater_than_100,
20 | control.pod_template_container_argument_audit_log_path_configured,
21 | control.pod_template_container_argument_authorization_mode_no_always_allow,
22 | control.pod_template_container_argument_authorization_mode_node,
23 | control.pod_template_container_argument_authorization_mode_rbac,
24 | control.pod_template_container_argument_bind_address_127_0_0_1,
25 | control.pod_template_container_argument_etcd_auto_tls_disabled,
26 | control.pod_template_container_argument_etcd_cafile_configured,
27 | control.pod_template_container_argument_etcd_certfile_and_keyfile_configured,
28 | control.pod_template_container_argument_etcd_client_cert_auth_enabled,
29 | control.pod_template_container_argument_etcd_peer_certfile_and_peer_keyfile_configured,
30 | control.pod_template_container_argument_event_qps_less_than_5,
31 | control.pod_template_container_argument_insecure_port_0,
32 | control.pod_template_container_argument_kube_apiserver_profiling_disabled,
33 | control.pod_template_container_argument_kube_apiserver_tls_cert_file_and_tls_private_key_file_configured,
34 | control.pod_template_container_argument_kube_controller_manager_bind_address_127_0_0_1,
35 | control.pod_template_container_argument_kube_controller_manager_profiling_disabled,
36 | control.pod_template_container_argument_kube_controller_manager_root_ca_file_configured,
37 | control.pod_template_container_argument_kube_controller_manager_service_account_credentials_enabled,
38 | control.pod_template_container_argument_kube_controller_manager_service_account_private_key_file_configured,
39 | control.pod_template_container_argument_kube_scheduler_profiling_disabled,
40 | control.pod_template_container_argument_kubelet_anonymous_auth_disabled,
41 | control.pod_template_container_argument_kubelet_authorization_mode_no_always_allow,
42 | control.pod_template_container_argument_kubelet_client_ca_file_configured,
43 | control.pod_template_container_argument_kubelet_client_certificate_and_key_configured,
44 | control.pod_template_container_argument_kubelet_https_enabled,
45 | control.pod_template_container_argument_kubelet_read_only_port_0,
46 | control.pod_template_container_argument_kubelet_terminated_pod_gc_threshold_configured,
47 | control.pod_template_container_argument_make_iptables_util_chains_enabled,
48 | control.pod_template_container_argument_namespace_lifecycle_enabled,
49 | control.pod_template_container_argument_node_restriction_enabled,
50 | control.pod_template_container_argument_pod_security_policy_enabled,
51 | control.pod_template_container_argument_protect_kernel_defaults_enabled,
52 | control.pod_template_container_argument_request_timeout_appropriate,
53 | control.pod_template_container_argument_rotate_kubelet_server_certificate_enabled,
54 | control.pod_template_container_argument_secure_port_not_0,
55 | control.pod_template_container_argument_security_context_deny_enabled,
56 | control.pod_template_container_argument_service_account_enabled,
57 | control.pod_template_container_argument_service_account_key_file_appropriate,
58 | control.pod_template_container_argument_service_account_lookup_enabled,
59 | control.pod_template_container_argument_tls_cert_file_and_tls_private_key_file_configured,
60 | control.pod_template_container_capabilities_drop_all,
61 | control.pod_template_container_encryption_providers_configured,
62 | control.pod_template_container_host_port_not_specified,
63 | control.pod_template_container_image_pull_policy_always,
64 | control.pod_template_container_image_tag_specified,
65 | control.pod_template_container_kubelet_certificate_authority_configured,
66 | control.pod_template_container_kubelet_streaming_connection_idle_timeout_not_zero,
67 | control.pod_template_container_kubernetes_dashboard_not_deployed,
68 | control.pod_template_container_liveness_probe,
69 | control.pod_template_container_no_argument_basic_auth_file,
70 | control.pod_template_container_no_argument_hostname_override_configured,
71 | control.pod_template_container_no_argument_insecure_bind_address,
72 | control.pod_template_container_privilege_disabled,
73 | control.pod_template_container_privilege_escalation_disabled,
74 | control.pod_template_container_readiness_probe,
75 | control.pod_template_container_rotate_certificate_enabled,
76 | control.pod_template_container_secrets_defined_as_files,
77 | control.pod_template_container_security_context_exists,
78 | control.pod_template_container_strong_kube_apiserver_cryptographic_ciphers,
79 | control.pod_template_container_strong_kubelet_cryptographic_ciphers,
80 | control.pod_template_container_sys_admin_capability_disabled,
81 | control.pod_template_container_token_auth_file_not_configured,
82 | control.pod_template_container_with_added_capabilities,
83 | control.pod_template_cpu_limit,
84 | control.pod_template_cpu_request,
85 | control.pod_template_immutable_container_filesystem,
86 | control.pod_template_memory_limit,
87 | control.pod_template_memory_request
88 | ]
89 |
90 | tags = merge(local.all_controls_pod_template_common_tags, {
91 | type = "Benchmark"
92 | })
93 | }
94 |
--------------------------------------------------------------------------------
/all_controls/replicaset.pp:
--------------------------------------------------------------------------------
1 | locals {
2 | all_controls_replicaset_common_tags = merge(local.all_controls_common_tags, {
3 | service = "Kubernetes/ReplicaSet"
4 | })
5 | }
6 |
7 | benchmark "all_controls_replicaset" {
8 | title = "ReplicaSet"
9 | description = "This section contains recommendations for configuring ReplicaSet resources."
10 | children = [
11 | control.replicaset_container_admission_capability_restricted,
12 | control.replicaset_container_admission_control_plugin_always_pull_images,
13 | control.replicaset_container_admission_control_plugin_no_always_admit,
14 | control.replicaset_container_arg_peer_client_cert_auth_enabled,
15 | control.replicaset_container_argument_anonymous_auth_disabled,
16 | control.replicaset_container_argument_audit_log_maxage_greater_than_30,
17 | control.replicaset_container_argument_audit_log_maxbackup_greater_than_10,
18 | control.replicaset_container_argument_audit_log_maxsize_greater_than_100,
19 | control.replicaset_container_argument_audit_log_path_configured,
20 | control.replicaset_container_argument_authorization_mode_no_always_allow,
21 | control.replicaset_container_argument_authorization_mode_node,
22 | control.replicaset_container_argument_authorization_mode_rbac,
23 | control.replicaset_container_argument_etcd_auto_tls_disabled,
24 | control.replicaset_container_argument_etcd_cafile_configured,
25 | control.replicaset_container_argument_etcd_certfile_and_keyfile_configured,
26 | control.replicaset_container_argument_etcd_client_cert_auth_enabled,
27 | control.replicaset_container_argument_etcd_peer_certfile_and_peer_keyfile_configured,
28 | control.replicaset_container_argument_event_qps_less_than_5,
29 | control.replicaset_container_argument_insecure_port_0,
30 | control.replicaset_container_argument_kube_apiserver_etcd_certfile_and_keyfile_configured,
31 | control.replicaset_container_argument_kube_apiserver_profiling_disabled,
32 | control.replicaset_container_argument_kube_apiserver_tls_cert_file_and_tls_private_key_file_configured,
33 | control.replicaset_container_argument_kube_controller_manager_bind_address_127_0_0_1,
34 | control.replicaset_container_argument_kube_controller_manager_profiling_disabled,
35 | control.replicaset_container_argument_kube_controller_manager_root_ca_file_configured,
36 | control.replicaset_container_argument_kube_controller_manager_service_account_credentials_enabled,
37 | control.replicaset_container_argument_kube_controller_manager_service_account_private_key_file_configured,
38 | control.replicaset_container_argument_kube_scheduler_bind_address_127_0_0_1,
39 | control.replicaset_container_argument_kube_scheduler_profiling_disabled,
40 | control.replicaset_container_argument_kubelet_authorization_mode_no_always_allow,
41 | control.replicaset_container_argument_kubelet_client_ca_file_configured,
42 | control.replicaset_container_argument_kubelet_client_certificate_and_key_configured,
43 | control.replicaset_container_argument_kubelet_https_enabled,
44 | control.replicaset_container_argument_kubelet_read_only_port_0,
45 | control.replicaset_container_argument_kubelet_terminated_pod_gc_threshold_configured,
46 | control.replicaset_container_argument_kubelet_tls_cert_file_and_tls_private_key_file_configured,
47 | control.replicaset_container_argument_make_iptables_util_chains_enabled,
48 | control.replicaset_container_argument_namespace_lifecycle_enabled,
49 | control.replicaset_container_argument_node_restriction_enabled,
50 | control.replicaset_container_argument_pod_security_policy_enabled,
51 | control.replicaset_container_argument_protect_kernel_defaults_enabled,
52 | control.replicaset_container_argument_request_timeout_appropriate,
53 | control.replicaset_container_argument_rotate_kubelet_server_certificate_enabled,
54 | control.replicaset_container_argument_secure_port_not_0,
55 | control.replicaset_container_argument_security_context_deny_enabled,
56 | control.replicaset_container_argument_service_account_enabled,
57 | control.replicaset_container_argument_service_account_key_file_appropriate,
58 | control.replicaset_container_argument_service_account_lookup_enabled,
59 | control.replicaset_container_capabilities_drop_all,
60 | control.replicaset_container_encryption_providers_configured,
61 | control.replicaset_container_host_port_not_specified,
62 | control.replicaset_container_image_pull_policy_always,
63 | control.replicaset_container_image_tag_specified,
64 | control.replicaset_container_kubelet_certificate_authority_configured,
65 | control.replicaset_container_kubernetes_dashboard_not_deployed,
66 | control.replicaset_container_liveness_probe,
67 | control.replicaset_container_no_argument_basic_auth_file,
68 | control.replicaset_container_no_argument_hostname_override_configured,
69 | control.replicaset_container_no_argument_insecure_bind_address,
70 | control.replicaset_container_privilege_disabled,
71 | control.replicaset_container_privilege_escalation_disabled,
72 | control.replicaset_container_privilege_port_mapped,
73 | control.replicaset_container_readiness_probe,
74 | control.replicaset_container_rotate_certificate_enabled,
75 | control.replicaset_container_secrets_defined_as_files,
76 | control.replicaset_container_security_context_exists,
77 | control.replicaset_container_streaming_connection_idle_timeout_not_zero,
78 | control.replicaset_container_strong_kube_apiserver_cryptographic_ciphers,
79 | control.replicaset_container_strong_kubelet_cryptographic_ciphers,
80 | control.replicaset_container_sys_admin_capability_disabled,
81 | control.replicaset_container_token_auth_file_not_configured,
82 | control.replicaset_container_with_added_capabilities,
83 | control.replicaset_cpu_limit,
84 | control.replicaset_cpu_request,
85 | control.replicaset_default_namespace_used,
86 | control.replicaset_default_seccomp_profile_enabled,
87 | control.replicaset_host_network_access_disabled,
88 | control.replicaset_hostpid_hostipc_sharing_disabled,
89 | control.replicaset_immutable_container_filesystem,
90 | control.replicaset_memory_limit,
91 | control.replicaset_memory_request,
92 | control.replicaset_non_root_container
93 | ]
94 |
95 |
96 | tags = merge(local.all_controls_replicaset_common_tags, {
97 | type = "Benchmark"
98 | })
99 | }
100 |
--------------------------------------------------------------------------------
/all_controls/replication_controller.pp:
--------------------------------------------------------------------------------
1 | locals {
2 | all_controls_replication_controller_common_tags = merge(local.all_controls_common_tags, {
3 | service = "Kubernetes/ReplicationController"
4 | })
5 | }
6 |
7 | benchmark "all_controls_replication_controller" {
8 | title = "ReplicationController"
9 | description = "This section contains recommendations for configuring ReplicationController resources."
10 | children = [
11 | control.replication_controller_container_admission_capability_restricted,
12 | control.replication_controller_container_admission_control_plugin_always_pull_images,
13 | control.replication_controller_container_admission_control_plugin_no_always_admit,
14 | control.replication_controller_container_arg_peer_client_cert_auth_enabled,
15 | control.replication_controller_container_argument_anonymous_auth_disabled,
16 | control.replication_controller_container_argument_audit_log_maxage_greater_than_30,
17 | control.replication_controller_container_argument_audit_log_maxbackup_greater_than_10,
18 | control.replication_controller_container_argument_audit_log_maxsize_greater_than_100,
19 | control.replication_controller_container_argument_audit_log_path_configured,
20 | control.replication_controller_container_argument_authorization_mode_no_always_allow,
21 | control.replication_controller_container_argument_authorization_mode_node,
22 | control.replication_controller_container_argument_authorization_mode_rbac,
23 | control.replication_controller_container_argument_etcd_auto_tls_disabled,
24 | control.replication_controller_container_argument_etcd_cafile_configured,
25 | control.replication_controller_container_argument_etcd_certfile_and_keyfile_configured,
26 | control.replication_controller_container_argument_etcd_client_cert_auth_enabled,
27 | control.replication_controller_container_argument_etcd_peer_certfile_and_peer_keyfile_configured,
28 | control.replication_controller_container_argument_event_qps_less_than_5,
29 | control.replication_controller_container_argument_insecure_port_0,
30 | control.replication_controller_container_argument_kube_apiserver_etcd_certfile_and_keyfile_configured,
31 | control.replication_controller_container_argument_kube_apiserver_profiling_disabled,
32 | control.replication_controller_container_argument_kube_apiserver_tls_cert_file_and_tls_private_key_file_configured,
33 | control.replication_controller_container_argument_kube_controller_manager_bind_address_127_0_0_1,
34 | control.replication_controller_container_argument_kube_controller_manager_profiling_disabled,
35 | control.replication_controller_container_argument_kube_controller_manager_root_ca_file_configured,
36 | control.replication_controller_container_argument_kube_controller_manager_service_account_credentials_enabled,
37 | control.replication_controller_container_argument_kube_controller_manager_service_account_private_key_file_configured,
38 | control.replication_controller_container_argument_kube_scheduler_bind_address_127_0_0_1,
39 | control.replication_controller_container_argument_kube_scheduler_profiling_disabled,
40 | control.replication_controller_container_argument_kubelet_authorization_mode_no_always_allow,
41 | control.replication_controller_container_argument_kubelet_client_ca_file_configured,
42 | control.replication_controller_container_argument_kubelet_client_certificate_and_key_configured,
43 | control.replication_controller_container_argument_kubelet_https_enabled,
44 | control.replication_controller_container_argument_kubelet_read_only_port_0,
45 | control.replication_controller_container_argument_kubelet_terminated_pod_gc_threshold_configured,
46 | control.replication_controller_container_argument_kubelet_tls_cert_file_and_tls_private_key_file_configured,
47 | control.replication_controller_container_argument_make_iptables_util_chains_enabled,
48 | control.replication_controller_container_argument_namespace_lifecycle_enabled,
49 | control.replication_controller_container_argument_node_restriction_enabled,
50 | control.replication_controller_container_argument_pod_security_policy_enabled,
51 | control.replication_controller_container_argument_protect_kernel_defaults_enabled,
52 | control.replication_controller_container_argument_request_timeout_appropriate,
53 | control.replication_controller_container_argument_rotate_kubelet_server_certificate_enabled,
54 | control.replication_controller_container_argument_secure_port_not_0,
55 | control.replication_controller_container_argument_security_context_deny_enabled,
56 | control.replication_controller_container_argument_service_account_enabled,
57 | control.replication_controller_container_argument_service_account_key_file_appropriate,
58 | control.replication_controller_container_argument_service_account_lookup_enabled,
59 | control.replication_controller_container_capabilities_drop_all,
60 | control.replication_controller_container_encryption_providers_configured,
61 | control.replication_controller_container_host_port_not_specified,
62 | control.replication_controller_container_image_pull_policy_always,
63 | control.replication_controller_container_image_tag_specified,
64 | control.replication_controller_container_kubelet_certificate_authority_configured,
65 | control.replication_controller_container_kubernetes_dashboard_not_deployed,
66 | control.replication_controller_container_liveness_probe,
67 | control.replication_controller_container_no_argument_basic_auth_file,
68 | control.replication_controller_container_no_argument_hostname_override_configured,
69 | control.replication_controller_container_no_argument_insecure_bind_address,
70 | control.replication_controller_container_privilege_disabled,
71 | control.replication_controller_container_privilege_escalation_disabled,
72 | control.replication_controller_container_privilege_port_mapped,
73 | control.replication_controller_container_readiness_probe,
74 | control.replication_controller_container_rotate_certificate_enabled,
75 | control.replication_controller_container_secrets_defined_as_files,
76 | control.replication_controller_container_security_context_exists,
77 | control.replication_controller_container_streaming_connection_idle_timeout_not_zero,
78 | control.replication_controller_container_strong_kube_apiserver_cryptographic_ciphers,
79 | control.replication_controller_container_strong_kubelet_cryptographic_ciphers,
80 | control.replication_controller_container_sys_admin_capability_disabled,
81 | control.replication_controller_container_token_auth_file_not_configured,
82 | control.replication_controller_container_with_added_capabilities,
83 | control.replication_controller_cpu_limit,
84 | control.replication_controller_cpu_request,
85 | control.replication_controller_default_namespace_used,
86 | control.replication_controller_default_seccomp_profile_enabled,
87 | control.replication_controller_host_network_access_disabled,
88 | control.replication_controller_hostpid_hostipc_sharing_disabled,
89 | control.replication_controller_immutable_container_filesystem,
90 | control.replication_controller_memory_limit,
91 | control.replication_controller_memory_request,
92 | control.replication_controller_non_root_container
93 | ]
94 |
95 | tags = merge(local.all_controls_replication_controller_common_tags, {
96 | type = "Benchmark"
97 | })
98 | }
99 |
--------------------------------------------------------------------------------
/all_controls/role.pp:
--------------------------------------------------------------------------------
1 | locals {
2 | all_controls_role_common_tags = merge(local.all_controls_common_tags, {
3 | service = "Kubernetes/Role"
4 | })
5 | }
6 |
7 | benchmark "all_controls_role" {
8 | title = "Role"
9 | description = "This section contains recommendations for configuring Role resources."
10 | children = [
11 | control.cluster_role_with_validating_or_mutating_admission_webhook_configurations,
12 | control.role_default_namespace_used,
13 | control.role_with_bind_cluster_role_bindings,
14 | control.role_with_rbac_approve_certificate_signing_requests,
15 | control.role_with_rbac_escalate_permissions,
16 | control.role_with_wildcards_used
17 | ]
18 |
19 | tags = merge(local.all_controls_role_common_tags, {
20 | type = "Benchmark"
21 | })
22 | }
23 |
--------------------------------------------------------------------------------
/all_controls/role_binding.pp:
--------------------------------------------------------------------------------
1 | locals {
2 | all_controls_role_binding_common_tags = merge(local.all_controls_common_tags, {
3 | service = "Kubernetes/RoleBinding"
4 | })
5 | }
6 |
7 | benchmark "all_controls_role_binding" {
8 | title = "Role Binding"
9 | description = "This section contains recommendations for configuring Role Binding resources."
10 | children = [
11 | control.role_binding_default_namespace_used,
12 | control.role_binding_default_service_account_binding_not_active
13 | ]
14 |
15 | tags = merge(local.all_controls_role_binding_common_tags, {
16 | type = "Benchmark"
17 | })
18 | }
19 |
--------------------------------------------------------------------------------
/all_controls/secret.pp:
--------------------------------------------------------------------------------
1 | locals {
2 | all_controls_secret_common_tags = merge(local.all_controls_common_tags, {
3 | service = "Kubernetes/Secret"
4 | })
5 | }
6 |
7 | benchmark "all_controls_secret" {
8 | title = "Secret"
9 | description = "This section contains recommendations for configuring Secret resources."
10 | children = [
11 | control.secret_default_namespace_used
12 | ]
13 |
14 | tags = merge(local.all_controls_secret_common_tags, {
15 | type = "Benchmark"
16 | })
17 | }
18 |
--------------------------------------------------------------------------------
/all_controls/service.pp:
--------------------------------------------------------------------------------
1 | locals {
2 | all_controls_service_common_tags = merge(local.all_controls_common_tags, {
3 | service = "Kubernetes/Service"
4 | })
5 | }
6 |
7 | benchmark "all_controls_service" {
8 | title = "Service"
9 | description = "This section contains recommendations for configuring Service resources."
10 | children = [
11 | control.service_default_namespace_used,
12 | control.service_no_tiller_deployed,
13 | control.service_no_tiller_service,
14 | control.service_type_forbidden
15 | ]
16 |
17 | tags = merge(local.all_controls_service_common_tags, {
18 | type = "Benchmark"
19 | })
20 | }
21 |
--------------------------------------------------------------------------------
/all_controls/service_account.pp:
--------------------------------------------------------------------------------
1 | locals {
2 | all_controls_service_account_common_tags = merge(local.all_controls_common_tags, {
3 | service = "Kubernetes/ServiceAccount"
4 | })
5 | }
6 |
7 | benchmark "all_controls_service_account" {
8 | title = "Service Account"
9 | description = "This section contains recommendations for configuring Service Account resources."
10 | children = [
11 | control.service_account_default_namespace_used,
12 | control.service_account_token_disabled
13 | ]
14 |
15 | tags = merge(local.all_controls_service_account_common_tags, {
16 | type = "Benchmark"
17 | })
18 | }
19 |
--------------------------------------------------------------------------------
/all_controls/statefulset.pp:
--------------------------------------------------------------------------------
1 | locals {
2 | all_controls_statefulset_common_tags = merge(local.all_controls_common_tags, {
3 | service = "Kubernetes/StatefulSet"
4 | })
5 | }
6 |
7 | benchmark "all_controls_statefulset" {
8 | title = "StatefulSet"
9 | description = "This section contains recommendations for configuring StatefulSet resources."
10 | children = [
11 | control.statefulset_container_admission_capability_restricted,
12 | control.statefulset_container_admission_control_plugin_always_pull_images,
13 | control.statefulset_container_admission_control_plugin_no_always_admit,
14 | control.statefulset_container_arg_peer_client_cert_auth_enabled,
15 | control.statefulset_container_argument_anonymous_auth_disabled,
16 | control.statefulset_container_argument_audit_log_maxage_greater_than_30,
17 | control.statefulset_container_argument_audit_log_maxbackup_greater_than_10,
18 | control.statefulset_container_argument_audit_log_maxsize_greater_than_100,
19 | control.statefulset_container_argument_audit_log_path_configured,
20 | control.statefulset_container_argument_authorization_mode_no_always_allow,
21 | control.statefulset_container_argument_authorization_mode_node,
22 | control.statefulset_container_argument_authorization_mode_rbac,
23 | control.statefulset_container_argument_etcd_auto_tls_disabled,
24 | control.statefulset_container_argument_etcd_cafile_configured,
25 | control.statefulset_container_argument_etcd_certfile_and_keyfile_configured,
26 | control.statefulset_container_argument_etcd_client_cert_auth_enabled,
27 | control.statefulset_container_argument_etcd_peer_certfile_and_peer_keyfile_configured,
28 | control.statefulset_container_argument_event_qps_less_than_5,
29 | control.statefulset_container_argument_insecure_port_0,
30 | control.statefulset_container_argument_kube_apiserver_etcd_certfile_and_keyfile_configured,
31 | control.statefulset_container_argument_kube_apiserver_profiling_disabled,
32 | control.statefulset_container_argument_kube_apiserver_tls_cert_file_and_tls_private_key_file_configured,
33 | control.statefulset_container_argument_kube_controller_manager_bind_address_127_0_0_1,
34 | control.statefulset_container_argument_kube_controller_manager_profiling_disabled,
35 | control.statefulset_container_argument_kube_controller_manager_root_ca_file_configured,
36 | control.statefulset_container_argument_kube_controller_manager_service_account_credentials_enabled,
37 | control.statefulset_container_argument_kube_controller_manager_service_account_private_key_file_configured,
38 | control.statefulset_container_argument_kube_scheduler_bind_address_127_0_0_1,
39 | control.statefulset_container_argument_kube_scheduler_profiling_disabled,
40 | control.statefulset_container_argument_kubelet_authorization_mode_no_always_allow,
41 | control.statefulset_container_argument_kubelet_client_ca_file_configured,
42 | control.statefulset_container_argument_kubelet_client_certificate_and_key_configured,
43 | control.statefulset_container_argument_kubelet_https_enabled,
44 | control.statefulset_container_argument_kubelet_read_only_port_0,
45 | control.statefulset_container_argument_kubelet_terminated_pod_gc_threshold_configured,
46 | control.statefulset_container_argument_kubelet_tls_cert_file_and_tls_private_key_file_configured,
47 | control.statefulset_container_argument_make_iptables_util_chains_enabled,
48 | control.statefulset_container_argument_namespace_lifecycle_enabled,
49 | control.statefulset_container_argument_node_restriction_enabled,
50 | control.statefulset_container_argument_pod_security_policy_enabled,
51 | control.statefulset_container_argument_protect_kernel_defaults_enabled,
52 | control.statefulset_container_argument_request_timeout_appropriate,
53 | control.statefulset_container_argument_rotate_kubelet_server_certificate_enabled,
54 | control.statefulset_container_argument_secure_port_not_0,
55 | control.statefulset_container_argument_security_context_deny_enabled,
56 | control.statefulset_container_argument_service_account_enabled,
57 | control.statefulset_container_argument_service_account_key_file_appropriate,
58 | control.statefulset_container_argument_service_account_lookup_enabled,
59 | control.statefulset_container_capabilities_drop_all,
60 | control.statefulset_container_encryption_providers_configured,
61 | control.statefulset_container_host_port_not_specified,
62 | control.statefulset_container_image_pull_policy_always,
63 | control.statefulset_container_image_tag_specified,
64 | control.statefulset_container_kubelet_certificate_authority_configured,
65 | control.statefulset_container_kubernetes_dashboard_not_deployed,
66 | control.statefulset_container_liveness_probe,
67 | control.statefulset_container_no_argument_basic_auth_file,
68 | control.statefulset_container_no_argument_hostname_override_configured,
69 | control.statefulset_container_no_argument_insecure_bind_address,
70 | control.statefulset_container_privilege_disabled,
71 | control.statefulset_container_privilege_escalation_disabled,
72 | control.statefulset_container_privilege_port_mapped,
73 | control.statefulset_container_readiness_probe,
74 | control.statefulset_container_rotate_certificate_enabled,
75 | control.statefulset_container_secrets_defined_as_files,
76 | control.statefulset_container_security_context_exists,
77 | control.statefulset_container_streaming_connection_idle_timeout_not_zero,
78 | control.statefulset_container_strong_kube_apiserver_cryptographic_ciphers,
79 | control.statefulset_container_strong_kubelet_cryptographic_ciphers,
80 | control.statefulset_container_sys_admin_capability_disabled,
81 | control.statefulset_container_token_auth_file_not_configured,
82 | control.statefulset_container_with_added_capabilities,
83 | control.statefulset_cpu_limit,
84 | control.statefulset_cpu_request,
85 | control.statefulset_default_namespace_used,
86 | control.statefulset_default_seccomp_profile_enabled,
87 | control.statefulset_host_network_access_disabled,
88 | control.statefulset_hostpid_hostipc_sharing_disabled,
89 | control.statefulset_immutable_container_filesystem,
90 | control.statefulset_memory_limit,
91 | control.statefulset_memory_request,
92 | control.statefulset_non_root_container
93 | ]
94 |
95 | tags = merge(local.all_controls_statefulset_common_tags, {
96 | type = "Benchmark"
97 | })
98 | }
99 |
--------------------------------------------------------------------------------
/cis_kube_v120/cis_kube_v120.pp:
--------------------------------------------------------------------------------
1 | locals {
2 | cis_kube_v120_common_tags = merge(local.kubernetes_compliance_common_tags, {
3 | cis = "true"
4 | kubernetes_version = "v1.20"
5 | })
6 | }
7 |
8 | benchmark "cis_kube_v120" {
9 | title = "CIS Kubernetes v1.20"
10 | description = "CIS Kubernetes v1.20 benchmark provides prescriptive guidance for establishing a secure configuration posture for Kubernetes 1.19 - 1.20."
11 | children = [
12 | benchmark.cis_kube_v120_v100
13 | ]
14 |
15 | tags = merge(local.cis_kube_v120_common_tags, {
16 | type = "Benchmark"
17 | })
18 | }
19 |
--------------------------------------------------------------------------------
/cis_kube_v120/docs/cis_kube_v120_v100_5_1_6.md:
--------------------------------------------------------------------------------
1 | ## Description
2 |
3 | Service accounts tokens should not be mounted in pods except where the workload
4 | running in the pod explicitly needs to communicate with the API server.
5 |
6 | Mounting service account tokens inside pods can provide an avenue for privilege escalation
7 | attacks where an attacker is able to compromise a single pod in the cluster.
8 |
9 | Avoiding mounting these tokens removes this attack avenue.
10 |
11 | ## Remediation
12 |
13 | Modify the definition of pods and service accounts which do not need to mount service account tokens to disable it.
14 |
15 | **References**
16 |
17 | 1. https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/
18 |
--------------------------------------------------------------------------------
/cis_kube_v120/docs/cis_kube_v120_v100_5_2_1.md:
--------------------------------------------------------------------------------
1 | ## Description
2 |
3 | Do not generally permit containers to be run with the **securityContext.privileged** flag
4 | set to **true**.
5 |
6 | Privileged containers have access to all Linux Kernel capabilities and devices. A container
7 | running with full privileges can do almost everything that the host can do. This flag exists
8 | to allow special use-cases, like manipulating the network stack and accessing devices.
9 | There should be at least one PodSecurityPolicy (PSP) defined which does not permit
10 | privileged containers.
11 |
12 | If you need to run privileged containers, this should be defined in a separate PSP and you
13 | should carefully check RBAC controls to ensure that only limited service accounts and
14 | users are given permission to access that PSP.
15 |
16 | ## Remediation
17 |
18 | Create a PSP as described in the Kubernetes documentation, ensuring that the **.spec.privileged** field is **omitted** or set to **false**.
19 |
20 | **References**
21 |
22 | 1. https://kubernetes.io/docs/concepts/policy/pod-security-policy/#enabling-pod-security-policies
--------------------------------------------------------------------------------
/cis_kube_v120/docs/cis_kube_v120_v100_5_2_2.md:
--------------------------------------------------------------------------------
1 | ## Description
2 |
3 | Do not generally permit containers to be run with the **hostPID** flag set to **true**.
4 |
5 | A container running in the host's PID namespace can inspect processes running outside the
6 | container. If the container also has access to ptrace capabilities this can be used to escalate
7 | privileges outside of the container.
8 |
9 | There should be at least one PodSecurityPolicy (PSP) defined which does not permit
10 | containers to share the host PID namespace.
11 |
12 | If you need to run containers which require hostPID, this should be defined in a separate
13 | PSP and you should carefully check RBAC controls to ensure that only limited service
14 | accounts and users are given permission to access that PSP.
15 |
16 | ## Remediation
17 |
18 | Create a PSP as described in the Kubernetes documentation, ensuring that the **.spec.hostPID** field is **omitted** or set to **false**.
19 |
20 | **References**
21 |
22 | 1. https://kubernetes.io/docs/concepts/policy/pod-security-policy/
--------------------------------------------------------------------------------
/cis_kube_v120/docs/cis_kube_v120_v100_5_2_3.md:
--------------------------------------------------------------------------------
1 | ## Description
2 |
3 | Do not generally permit containers to be run with the **hostIPC** flag set to **true**.
4 |
5 | A container running in the host's IPC namespace can use IPC to interact with processes
6 | outside the container.
7 |
8 | There should be at least one PodSecurityPolicy (PSP) defined which does not permit
9 | containers to share the host IPC namespace.
10 |
11 | If you have a requirement to containers which require hostIPC, this should be defined in a
12 | separate PSP and you should carefully check RBAC controls to ensure that only limited
13 | service accounts and users are given permission to access that PSP.
14 |
15 | ## Remediation
16 |
17 | Create a PSP as described in the Kubernetes documentation, ensuring that the **.spec.hostIPC** field is **omitted** or set to **false**.
18 |
19 | **References**
20 |
21 | 1. https://kubernetes.io/docs/concepts/policy/pod-security-policy/
--------------------------------------------------------------------------------
/cis_kube_v120/docs/cis_kube_v120_v100_5_2_4.md:
--------------------------------------------------------------------------------
1 | ## Description
2 |
3 | Do not generally permit containers to be run with the **hostNetwork** flag set to **true**.
4 |
5 | A container running in the host's network namespace could access the local loopback
6 | device, and could access network traffic to and from other pods.
7 |
8 | There should be at least one PodSecurityPolicy (PSP) defined which does not permit
9 | containers to share the host network namespace.
10 |
11 | If you have need to run containers which require hostNetwork, this should be defined in a
12 | separate PSP and you should carefully check RBAC controls to ensure that only limited
13 | service accounts and users are given permission to access that PSP.
14 |
15 | ## Remediation
16 |
17 | Create a PSP as described in the Kubernetes documentation, ensuring that the **.spec.hostNetwork** field is **omitted** or set to **false**.
18 |
19 | **References**
20 |
21 | 1. https://kubernetes.io/docs/concepts/policy/pod-security-policy/
--------------------------------------------------------------------------------
/cis_kube_v120/docs/cis_kube_v120_v100_5_2_5.md:
--------------------------------------------------------------------------------
1 | ## Description
2 |
3 | Do not generally permit containers to be run with the **allowPrivilegeEscalation** flag set
4 | to **true**.
5 |
6 | A container running with the allowPrivilegeEscalation flag set to true may have
7 | processes that can gain more privileges than their parent.
8 |
9 | There should be at least one PodSecurityPolicy (PSP) defined which does not permit
10 | containers to allow privilege escalation. The option exists (and is defaulted to true) to
11 | permit setuid binaries to run.
12 |
13 | If you have need to run containers which use setuid binaries or require privilege escalation,
14 | this should be defined in a separate PSP and you should carefully check RBAC controls to
15 | ensure that only limited service accounts and users are given permission to access that
16 | PSP.
17 |
18 | ## Remediation
19 |
20 | Create a PSP as described in the Kubernetes documentation, ensuring that the **.spec.allowPrivilegeEscalation** field is **omitted** or set to **false**.
21 |
22 | **References**
23 |
24 | 1. https://kubernetes.io/docs/concepts/policy/pod-security-policy/
--------------------------------------------------------------------------------
/cis_kube_v120/docs/cis_kube_v120_v100_5_2_6.md:
--------------------------------------------------------------------------------
1 | ## Description
2 |
3 | Do not generally permit containers to be run as the root user.
4 |
5 | Containers may run as any Linux user. Containers which run as the root user, whilst
6 | constrained by Container Runtime security features still have a escalated likelihood of
7 | container breakout.
8 |
9 | Ideally, all containers should run as a defined non-UID 0 user.
10 |
11 | There should be at least one PodSecurityPolicy (PSP) defined which does not permit root
12 | users in a container.
13 |
14 | If you need to run root containers, this should be defined in a separate PSP and you should
15 | carefully check RBAC controls to ensure that only limited service accounts and users are
16 | given permission to access that PSP.
17 |
18 | ## Remediation
19 |
20 | Create a PSP as described in the Kubernetes documentation, ensuring that the **.spec.runAsUser.rule** is set to either **MustRunAsNonRoot** or **MustRunAs** with the range of UIDs not including 0.
21 |
22 | **References**
23 |
24 | 1. https://kubernetes.io/docs/concepts/policy/pod-security-policy/#enabling-pod-security-policies
--------------------------------------------------------------------------------
/cis_kube_v120/docs/cis_kube_v120_v100_5_3_2.md:
--------------------------------------------------------------------------------
1 | ## Description
2 |
3 | Use network policies to isolate traffic in your cluster network.
4 |
5 | Running different applications on the same Kubernetes cluster creates a risk of one
6 | compromised application attacking a neighboring application. Network segmentation is
7 | important to ensure that containers can communicate only with those they are supposed
8 | to. A network policy is a specification of how selections of pods are allowed to
9 | communicate with each other and other network endpoints.
10 |
11 | Network Policies are namespace scoped. When a network policy is introduced to a given
12 | namespace, all traffic not allowed by the policy is denied. However, if there are no network
13 | policies in a namespace all traffic will be allowed into and out of the pods in that
14 | namespace.
15 |
16 | ## Remediation
17 |
18 | Follow the documentation and create **NetworkPolicy** objects as you need them. By default, network policies are not created.
19 |
20 | **References**
21 |
22 | 1. https://kubernetes.io/docs/concepts/services-networking/networkpolicies/
23 | 2. https://octetz.com/posts/k8s-network-policy-apis
24 | 3. https://kubernetes.io/docs/tasks/configure-pod-container/declare-network-policy/
--------------------------------------------------------------------------------
/cis_kube_v120/docs/cis_kube_v120_v100_5_7_2.md:
--------------------------------------------------------------------------------
1 | ## Description
2 |
3 | Enable docker/default seccomp profile in your pod definitions.
4 |
5 | Seccomp (secure computing mode) is used to restrict the set of system calls applications
6 | can make, allowing cluster administrators greater control over the security of workloads
7 | running in the cluster. Kubernetes disables seccomp profiles by default for historical
8 | reasons. You should enable it to ensure that the workloads have restricted actions available
9 | within the container.
10 |
11 | ## Remediation
12 |
13 | Use security context to enable the docker/default seccomp profile in your pod definitions.
14 |
15 | **References**
16 |
17 | 1. https://kubernetes.io/docs/tutorials/clusters/seccomp/
18 | 2. https://docs.docker.com/engine/security/seccomp/
19 |
--------------------------------------------------------------------------------
/cis_kube_v120/docs/cis_kube_v120_v100_5_7_4.md:
--------------------------------------------------------------------------------
1 | ## Description
2 |
3 | Kubernetes provides a default namespace, where objects are placed if no namespace is
4 | specified for them. Placing objects in this namespace makes application of RBAC and other
5 | controls more difficult.
6 |
7 | ## Remediation
8 |
9 | Ensure that namespaces are created to allow for appropriate segregation of Kubernetes
10 | resources and that all new resources are created in a specific namespace.
--------------------------------------------------------------------------------
/cis_kube_v120/docs/cis_kube_v120_v100_overview.md:
--------------------------------------------------------------------------------
1 | To obtain the latest version of this guide, please visit http://www.cisecurity.org.
2 |
3 | ## Overview
4 |
5 | CIS Kubernetes v1.20 benchmark provides prescriptive guidance for establishing a secure configuration posture for Kubernetes 1.19 - 1.20.
6 |
--------------------------------------------------------------------------------
/cis_v170/cis.pp:
--------------------------------------------------------------------------------
1 | locals {
2 | cis_v170_common_tags = merge(local.kubernetes_compliance_common_tags, {
3 | cis = "true"
4 | cis_version = "v1.7.0"
5 | kubernetes_version = "v1.25"
6 | })
7 | }
8 |
9 | benchmark "cis_v170" {
10 | title = "CIS v1.7.0"
11 | description = "CIS v1.7.0 benchmark provides prescriptive guidance for establishing a secure configuration posture for Kubernetes v1.25."
12 | documentation = file("./cis_v170/docs/cis_v170_overview.md")
13 | children = [
14 | benchmark.cis_v170_5
15 | ]
16 |
17 | tags = merge(local.cis_v170_common_tags, {
18 | type = "Benchmark"
19 | })
20 | }
21 |
--------------------------------------------------------------------------------
/cis_v170/docs/cis_v170_5_1.md:
--------------------------------------------------------------------------------
1 | ## Overview
2 |
3 | This section contains recommendations for various Kubernetes RBAC policies which can also govern the behavior of software resources, that Kubernetes identifies as service accounts.
--------------------------------------------------------------------------------
/cis_v170/docs/cis_v170_5_1_3.md:
--------------------------------------------------------------------------------
1 | ## Description
2 |
3 | Kubernetes Roles and ClusterRoles provide access to resources based on sets of objects and actions that can be taken on those objects. It is possible to set either of these to be the wildcard "*" which matches all items.
4 |
5 | Use of wildcards is not optimal from a security perspective as it may allow for inadvertent access to be granted when new resources are added to the Kubernetes API either as CRDs or in later versions of the product.
6 |
7 | The principle of least privilege recommends that users are provided only the access required for their role and nothing more. The use of wildcard rights grants is likely to provide excessive rights to the Kubernetes API.
8 |
9 | ## Remediation
10 |
11 | Where possible replace any use of wildcards in clusterroles and roles with specific objects or actions.
--------------------------------------------------------------------------------
/cis_v170/docs/cis_v170_5_1_6.md:
--------------------------------------------------------------------------------
1 | ## Description
2 |
3 | Service accounts tokens should not be mounted in pods except where the workload running in the pod explicitly needs to communicate with the API server.
4 |
5 | Mounting service account tokens inside pods can provide an avenue for privilege escalation attacks where an attacker is able to compromise a single pod in the cluster.
6 |
7 | Avoiding mounting these tokens removes this attack avenue.
8 |
9 | ## Remediation
10 |
11 | Modify the definition of pods and service accounts which do not need to mount service account tokens to disable it.
12 |
13 | **Default Value:** By default, all pods get a service account token mounted in them.
--------------------------------------------------------------------------------
/cis_v170/docs/cis_v170_5_3.md:
--------------------------------------------------------------------------------
1 | ## Overview
2 |
3 | This section contains recommendations for Network Policies and the Container Network Interface (CNI). It recommends implementing Network Policies ensuring that only authorized connections are allowed.
--------------------------------------------------------------------------------
/cis_v170/docs/cis_v170_5_3_2.md:
--------------------------------------------------------------------------------
1 | ## Description
2 |
3 | Use network policies to isolate traffic in your cluster network.
4 |
5 | Running different applications on the same Kubernetes cluster creates a risk of one compromised application attacking a neighboring application. Network segmentation is important to ensure that containers can communicate only with those they are supposed to. A network policy is a specification of how selections of pods are allowed to communicate with each other and other network endpoints.
6 |
7 | Network Policies are namespace scoped. When a network policy is introduced to a given namespace, all traffic not allowed by the policy is denied. However, if there are no network policies in a namespace all traffic will be allowed into and out of the pods in that namespace.
8 |
9 | ## Remediation
10 |
11 | Follow the documentation and create `NetworkPolicy` objects as you need them. By default, network policies are not created.
12 |
13 | **Default Value:** By default, network policies are not created.
--------------------------------------------------------------------------------
/cis_v170/docs/cis_v170_5_7.md:
--------------------------------------------------------------------------------
1 | ## Overview
2 |
3 | These policies relate to general cluster management topics, like namespace best practices and policies applied to pod objects in the cluster.
--------------------------------------------------------------------------------
/cis_v170/docs/cis_v170_5_7_2.md:
--------------------------------------------------------------------------------
1 | ## Description
2 |
3 | Enable `docker/default` seccomp profile in your pod definitions.
4 |
5 | Seccomp (secure computing mode) is used to restrict the set of system calls applications
6 | can make, allowing cluster administrators greater control over the security of workloads
7 | running in the cluster. Kubernetes disables seccomp profiles by default for historical
8 | reasons. You should enable it to ensure that the workloads have restricted actions available
9 | within the container.
10 |
11 | ## Remediation
12 |
13 | Use security context to enable the docker/default seccomp profile in your pod definitions. An example is as below:
14 |
15 | ```yaml
16 | securityContext:
17 | seccompProfile:
18 | type: RuntimeDefault
19 | ```
20 |
21 | **Default Value:** By default, seccomp profile is set to unconfined which means that no seccomp profiles are enabled.
--------------------------------------------------------------------------------
/cis_v170/docs/cis_v170_5_7_4.md:
--------------------------------------------------------------------------------
1 | ## Description
2 |
3 | Kubernetes provides a default namespace, where objects are placed if no namespace is specified for them. Placing objects in this namespace makes application of RBAC and other controls more difficult.
4 |
5 | Resources in a Kubernetes cluster should be segregated by namespace, to allow for security controls to be applied at that level and to make it easier to manage resources.
6 |
7 | ## Remediation
8 |
9 | Ensure that namespaces are created to allow for appropriate segregation of Kubernetes resources and that all new resources are created in a specific namespace.
10 |
11 | **Default Value:** Unless a namespace is specific on object creation, the `default` namespace will be used.
--------------------------------------------------------------------------------
/cis_v170/docs/cis_v170_overview.md:
--------------------------------------------------------------------------------
1 | To obtain the latest version of this guide, please visit http://www.cisecurity.org.
2 |
3 | ## Overview
4 |
5 | CIS v1.7.0 benchmark provides prescriptive guidance for establishing a secure configuration posture for Kubernetes v1.25.
--------------------------------------------------------------------------------
/cis_v170/section_5.pp:
--------------------------------------------------------------------------------
1 | locals {
2 | cis_v170_5_common_tags = merge(local.cis_v170_common_tags, {
3 | cis_section_id = "5"
4 | })
5 | }
6 |
7 | locals {
8 | cis_v170_5_1_common_tags = merge(local.cis_v170_5_common_tags, {
9 | cis_section_id = "5.1"
10 | })
11 |
12 | cis_v170_5_3_common_tags = merge(local.cis_v170_5_common_tags, {
13 | cis_section_id = "5.3"
14 | })
15 |
16 | cis_v170_5_7_common_tags = merge(local.cis_v170_5_common_tags, {
17 | cis_section_id = "5.7"
18 | })
19 | }
20 |
21 | benchmark "cis_v170_5" {
22 | title = "5 Policies"
23 | description = "This section contains recommendations for various Kubernetes policies which are important to the security of the environment."
24 | children = [
25 | benchmark.cis_v170_5_1,
26 | benchmark.cis_v170_5_3,
27 | benchmark.cis_v170_5_7
28 | ]
29 |
30 | tags = merge(local.cis_v170_5_common_tags, {
31 | type = "Benchmark"
32 | })
33 | }
34 |
35 | benchmark "cis_v170_5_1" {
36 | title = "5.1 RBAC and Service Accounts"
37 | description = "This section contains recommendations for various Kubernetes RBAC policies which can also govern the behavior of software resources, that Kubernetes identifies as service accounts."
38 | documentation = file("./cis_v170/docs/cis_v170_5_1.md")
39 | children = [
40 | control.cis_v170_5_1_3,
41 | control.cis_v170_5_1_6
42 | ]
43 |
44 | tags = merge(local.cis_v170_5_1_common_tags, {
45 | type = "Benchmark"
46 | })
47 | }
48 |
49 | control "cis_v170_5_1_3" {
50 | title = "5.1.3 Minimize wildcard use in Roles and ClusterRoles"
51 | description = "Kubernetes Roles and ClusterRoles provide access to resources based on sets of objects and actions that can be taken on those objects. It is possible to set either of these to be the wildcard \"*\" which matches all items. Use of wildcards is not optimal from a security perspective as it may allow for inadvertent access to be granted when new resources are added to the Kubernetes API either as CRDs or in later versions of the product."
52 | query = query.role_with_wildcards_used
53 | documentation = file("./cis_v170/docs/cis_v170_5_1_3.md")
54 |
55 | tags = merge(local.cis_v170_5_1_common_tags, {
56 | cis_level = "1"
57 | cis_item_id = "5.1.3"
58 | cis_type = "manual"
59 | service = "Kubernetes/Role"
60 | })
61 | }
62 |
63 | control "cis_v170_5_1_6" {
64 | title = "5.1.6 Ensure that Service Account Tokens are only mounted where necessary"
65 | description = "Service accounts tokens should not be mounted in pods except where the workload running in the pod explicitly needs to communicate with the API server."
66 | query = query.pod_service_account_token_disabled
67 | documentation = file("./cis_v170/docs/cis_v170_5_1_6.md")
68 |
69 | tags = merge(local.cis_v170_5_1_common_tags, {
70 | cis_level = "1"
71 | cis_item_id = "5.1.6"
72 | cis_type = "manual"
73 | service = "Kubernetes/Pod"
74 | })
75 | }
76 |
77 | benchmark "cis_v170_5_3" {
78 | title = "5.3 Network Policies and CNI"
79 | description = "This section contains recommendations for network policies and the Container Network Interface (CNI). It recommends implementing network policies ensuring that only authorized connections are allowed."
80 | documentation = file("./cis_v170/docs/cis_v170_5_3.md")
81 | children = [
82 | benchmark.cis_v170_5_3_2
83 | ]
84 |
85 | tags = merge(local.cis_v170_5_3_common_tags, {
86 | type = "Benchmark"
87 | })
88 | }
89 |
90 | benchmark "cis_v170_5_3_2" {
91 | title = "5.3.2 Ensure that all Namespaces have Network Policies defined"
92 | description = "Use network policies to isolate traffic in your cluster network."
93 | documentation = file("./cis_v170/docs/cis_v170_5_3_2.md")
94 | children = [
95 | control.network_policy_default_deny_egress,
96 | control.network_policy_default_deny_ingress,
97 | control.network_policy_default_dont_allow_egress,
98 | control.network_policy_default_dont_allow_ingress
99 | ]
100 |
101 | tags = merge(local.cis_v170_5_3_common_tags, {
102 | cis_level = "2"
103 | cis_item_id = "5.3.2"
104 | cis_type = "manual"
105 | type = "Benchmark"
106 | })
107 | }
108 |
109 | benchmark "cis_v170_5_7" {
110 | title = "5.7 General Policies"
111 | description = "These policies relate to general cluster management topics, like namespace best practices and policies applied to pod objects in the cluster."
112 | documentation = file("./cis_v170/docs/cis_v170_5_7.md")
113 | children = [
114 | benchmark.cis_v170_5_7_2,
115 | benchmark.cis_v170_5_7_4
116 | ]
117 |
118 | tags = merge(local.cis_v170_5_7_common_tags, {
119 | type = "Benchmark"
120 | })
121 | }
122 |
123 | benchmark "cis_v170_5_7_2" {
124 | title = "5.7.2 Ensure that the seccomp profile is set to docker/default in your Pod definitions"
125 | description = "Enable `docker/default` seccomp profile in your pod definitions."
126 | documentation = file("./cis_v170/docs/cis_v170_5_7_2.md")
127 | children = [
128 | control.cronjob_default_seccomp_profile_enabled,
129 | control.daemonset_default_seccomp_profile_enabled,
130 | control.deployment_default_seccomp_profile_enabled,
131 | control.job_default_seccomp_profile_enabled,
132 | control.pod_default_seccomp_profile_enabled,
133 | control.replicaset_default_seccomp_profile_enabled,
134 | control.replication_controller_default_seccomp_profile_enabled,
135 | control.statefulset_default_seccomp_profile_enabled
136 | ]
137 |
138 | tags = merge(local.cis_v170_5_7_common_tags, {
139 | cis_level = "2"
140 | cis_item_id = "5.7.2"
141 | cis_type = "manual"
142 | type = "Benchmark"
143 | })
144 | }
145 |
146 | benchmark "cis_v170_5_7_4" {
147 | title = "5.7.4 The default namespace should not be used"
148 | description = "Kubernetes provides a default namespace, where objects are placed if no namespace is specified for them. Placing objects in this namespace makes application of RBAC and other controls more difficult."
149 | documentation = file("./cis_v170/docs/cis_v170_5_7_4.md")
150 | children = [
151 | control.config_map_default_namespace_used,
152 | control.cronjob_default_namespace_used,
153 | control.daemonset_default_namespace_used,
154 | control.deployment_default_namespace_used,
155 | control.ingress_default_namespace_used,
156 | control.job_default_namespace_used,
157 | control.pod_default_namespace_used,
158 | control.replicaset_default_namespace_used,
159 | control.replication_controller_default_namespace_used,
160 | control.role_binding_default_namespace_used,
161 | control.role_default_namespace_used,
162 | control.secret_default_namespace_used,
163 | control.service_account_default_namespace_used,
164 | control.service_default_namespace_used,
165 | control.statefulset_default_namespace_used
166 | ]
167 |
168 | tags = merge(local.cis_v170_5_7_common_tags, {
169 | cis_level = "2"
170 | cis_item_id = "5.7.4"
171 | cis_type = "manual"
172 | type = "Benchmark"
173 | })
174 | }
175 |
--------------------------------------------------------------------------------
/controls/cluster_role_binding.pp:
--------------------------------------------------------------------------------
1 | locals {
2 | cluster_role_binding_common_tags = merge(local.kubernetes_compliance_common_tags, {
3 | service = "Kubernetes/ClusterRoleBinding"
4 | })
5 | }
6 |
7 | control "cluster_role_binding_default_service_account_binding_not_active" {
8 | title = "ClusterRoleBinding subjects should not actively use default service accounts"
9 | description = "Default service accounts should not be used by ClusterRoleBinding subjects."
10 | query = query.cluster_role_binding_default_service_account_binding_not_active
11 |
12 | tags = local.cluster_role_binding_common_tags
13 | }
14 |
--------------------------------------------------------------------------------
/controls/config_map.pp:
--------------------------------------------------------------------------------
1 | locals {
2 | config_map_common_tags = merge(local.kubernetes_compliance_common_tags, {
3 | service = "Kubernetes/ConfigMap"
4 | })
5 | }
6 |
7 | control "config_map_default_namespace_used" {
8 | title = "ConfigMap definition should not use default namespace"
9 | description = "Default namespace should not be used by ConfigMap definition. Placing objects in this namespace makes application of RBAC and other controls more difficult."
10 | query = query.config_map_default_namespace_used
11 |
12 | tags = merge(local.config_map_common_tags, {
13 | cis = "true"
14 | })
15 | }
16 |
--------------------------------------------------------------------------------
/controls/endpoint.pp:
--------------------------------------------------------------------------------
1 | locals {
2 | endpoint_common_tags = merge(local.kubernetes_compliance_common_tags, {
3 | service = "Kubernetes/Endpoint"
4 | })
5 | }
6 |
7 | control "endpoint_api_serve_on_secure_port" {
8 | title = "Kubernetes API should serve on secure port"
9 | description = "Kubernetes API should serve on port 443 or port 6443, protected by TLS. Once TLS is established, the HTTP request moves to the authentication step. If the request cannot be authenticated, it is rejected with HTTP status code 401."
10 | query = query.endpoint_api_serve_on_secure_port
11 |
12 | tags = merge(local.endpoint_common_tags, {
13 | nsa_cisa_v1 = "true"
14 | })
15 | }
16 |
--------------------------------------------------------------------------------
/controls/ingress.pp:
--------------------------------------------------------------------------------
1 | locals {
2 | ingress_common_tags = merge(local.kubernetes_compliance_common_tags, {
3 | service = "Kubernetes/Ingress"
4 | })
5 | }
6 |
7 | control "ingress_default_namespace_used" {
8 | title = "Ingress definition should not use default namespace"
9 | description = "Default namespace should not be used by Ingress definition. Placing objects in this namespace makes application of RBAC and other controls more difficult."
10 | query = query.ingress_default_namespace_used
11 |
12 | tags = merge(local.ingress_common_tags, {
13 | cis = "true"
14 | })
15 | }
16 |
17 | control "ingress_nginx_annotations_snippets_alias_not_used" {
18 | title = "Ingress definition should not have NGINX ingress annotation snippets containing alias statements"
19 | description = "This check ensures that the NGINX ingress annotation snippets in the Ingress do not contain alias statements."
20 | query = query.ingress_nginx_annotations_snippets_alias_not_used
21 |
22 | tags = local.ingress_common_tags
23 | }
24 |
25 | control "ingress_nginx_annotations_all_snippets_not_used" {
26 | title = "Ingress definition should not allow any usage of NGINX ingress annotation snippets"
27 | description = "This check ensures that the NGINX ingress annotation snippets usage is not allowed in the Ingress."
28 | query = query.ingress_nginx_annotations_all_snippets_not_used
29 |
30 | tags = local.ingress_common_tags
31 | }
32 |
33 | control "ingress_nginx_annotations_snippets_lua_code_not_used" {
34 | title = "Ingress definition should not have NGINX ingress annotation snippets containing lua code snippets"
35 | description = "This check ensures that the NGINX ingress annotation snippets in the Ingress do not contain lua code snippets."
36 | query = query.ingress_nginx_annotations_snippets_lua_code_not_used
37 |
38 | tags = local.ingress_common_tags
39 | }
40 |
--------------------------------------------------------------------------------
/controls/local.pp:
--------------------------------------------------------------------------------
1 | locals {
2 | container_cpu_limit_title = "__KIND__ containers should have a CPU limit"
3 | container_cpu_limit_desc = "Containers in a __KIND__ should have CPU limit which restricts the container to use no more than a given amount of CPU."
4 |
5 | container_cpu_request_title = "__KIND__ containers should have a CPU request"
6 | container_cpu_request_desc = "Containers in a __KIND__ should have CPU request. If required Kubernetes will make sure your containers get the CPU they requested."
7 |
8 | container_memory_limit_title = "__KIND__ containers should have a memory limit"
9 | container_memory_limit_desc = "Containers in a __KIND__ should have memory limit which restricts the container to use no more than a given amount of user or system memory."
10 |
11 | container_memory_request_title = "__KIND__ containers should have a memory request"
12 | container_memory_request_desc = "Containers in a __KIND__ should have memory request. If required Kubernetes will make sure your containers get the memory they requested."
13 |
14 | container_disallow_host_path_title = "__KIND__ containers should not allow privilege escalation"
15 | container_disallow_host_path_desc = "Containers in a __KIND__ should not able to access any specific paths of the host file system. There are many ways a container with unrestricted access to the host filesystem can escalate privileges, including reading data from other containers, and abusing the credentials of system services, such as Kubelet."
16 |
17 | container_privilege_disabled_title = "__KIND__ containers should not have privileged access"
18 | container_privilege_disabled_desc = "Containers in a __KIND__ should not have privileged access. To prevent security issues, it is recommended that you do not run privileged containers in your environment. Instead, provide granular permissions and capabilities to the container environment. Giving containers full access to the host can create security flaws in your production environment."
19 |
20 | container_privilege_escalation_disabled_title = "__KIND__ containers should not allow privilege escalation"
21 | container_privilege_escalation_disabled_desc = "Containers in a __KIND__ should not allow privilege escalation. A container running with the `allowPrivilegeEscalation` flag set to true may have processes that can gain more privileges than their parent."
22 |
23 | host_network_access_disabled_title = "__KIND__ containers should not run with host network access"
24 | host_network_access_disabled_desc = "Containers in a __KIND__ should not run in the host network of the node where the pod is deployed. When running on the host network, the pod can use the network namespace and network resources of the node. In this case, the pod can access loopback devices, listen to addresses, and monitor the traffic of other pods on the node."
25 |
26 | hostpid_hostipc_sharing_disabled_title = "__KIND__ containers should not share the host process namespace"
27 | hostpid_hostipc_sharing_disabled_desc = "Containers in a __KIND__ should not share the host process PID or IPC namespace. Sharing the host’s process namespace allows the container to see all of the processes on the host system. This reduces the benefit of process level isolation between the host and the containers. Under these circumstances a malicious user who has access to a container could get access to processes on the host itself, manipulate them, and even be able to kill them."
28 |
29 | immutable_container_filesystem_title = "__KIND__ containers should run with a read only root file system"
30 | immutable_container_filesystem_desc = "Containers in a __KIND__ should always run with a read only root file system. Using an immutable root filesystem and a verified boot mechanism prevents against attackers from owning the machine through permanent local changes. An immutable root filesystem can also prevent malicious binaries from writing to the host system."
31 |
32 | non_root_container_title = "__KIND__ containers should not run with root privileges"
33 | non_root_container_desc = "Containers in a __KIND__ should not run with root privileges. By default, many container services run as the privileged root user, and applications execute inside the container as root despite not requiring privileged execution. Preventing root execution by using non-root containers or a rootless container engine limits the impact of a container compromise."
34 |
35 | pod_service_account_not_exist_desc = "Pods should not refer to a service account which is not available."
36 |
37 | service_account_token_disabled_desc = "Automatic mapping of service account token should be disabled. By default, Kubernetes automatically provisions a service account when creating a Pod and mounts the account’s secret token within the Pod at runtime. Many containerized applications do not require direct access to the service account as Kubernetes orchestration occurs transparently in the background. If an application is compromised, account tokens in Pods can be gleaned by cyber actors and used to further compromise the cluster. When an application does not need to access the service account directly, Kubernetes administrators should ensure that Pod specifications disable the secret token being mounted. This can be accomplished using the `automountServiceAccountToken: false` directive in the Pod's YAML specification."
38 |
39 | service_type_forbidden_desc = "Containers should not be exposed through a forbidden service type such as `NodePort` or `LoadBalancer`."
40 | }
41 |
--------------------------------------------------------------------------------
/controls/namespace.pp:
--------------------------------------------------------------------------------
1 | locals {
2 | namespace_common_tags = merge(local.kubernetes_compliance_common_tags, {
3 | service = "Kubernetes/Namespace"
4 | })
5 | }
6 |
7 | control "namespace_limit_range_default_cpu_limit" {
8 | title = "Namespaces should have default CPU limit in limitRange policy"
9 | description = "Administrators should use default limitRange policy for CPU limit for each namespace."
10 | query = query.namespace_limit_range_default_cpu_limit
11 |
12 | tags = merge(local.namespace_common_tags, {
13 | nsa_cisa_v1 = "true"
14 | })
15 | }
16 |
17 | control "namespace_resource_quota_cpu_limit" {
18 | title = "Namespaces should be restricted on CPU usage with resourceQuota CPU limit"
19 | description = "Administrators should use resourceQuota CPU limit to restrict namespaces CPU usage."
20 | query = query.namespace_resource_quota_cpu_limit
21 |
22 | tags = merge(local.namespace_common_tags, {
23 | nsa_cisa_v1 = "true"
24 | })
25 | }
26 |
27 | control "namespace_limit_range_default_cpu_request" {
28 | title = "Namespaces should have default CPU request in limitRange policy"
29 | description = "Administrators should use default limitRange policy for CPU request for each namespace."
30 | query = query.namespace_limit_range_default_cpu_request
31 |
32 | tags = merge(local.namespace_common_tags, {
33 | nsa_cisa_v1 = "true"
34 | })
35 | }
36 |
37 | control "namespace_resource_quota_cpu_request" {
38 | title = "Namespaces should have resourceQuota CPU request"
39 | description = "Administrators should use resourceQuota CPU request for each namespace."
40 | query = query.namespace_resource_quota_cpu_request
41 |
42 | tags = merge(local.namespace_common_tags, {
43 | nsa_cisa_v1 = "true"
44 | })
45 | }
46 |
47 | control "namespace_limit_range_default_memory_limit" {
48 | title = "Namespaces should have default memory limit in limitRange policy"
49 | description = "Administrators should use default limitRange policy for memory limit for each namespace."
50 | query = query.namespace_limit_range_default_memory_limit
51 |
52 | tags = merge(local.namespace_common_tags, {
53 | nsa_cisa_v1 = "true"
54 | })
55 | }
56 |
57 | control "namespace_resource_quota_memory_limit" {
58 | title = "Namespaces should be restricted on memory usage with resourceQuota memory limit"
59 | description = "Administrators should use resourceQuota memory limit to restrict namespaces memory usage."
60 | query = query.namespace_resource_quota_memory_limit
61 |
62 | tags = merge(local.namespace_common_tags, {
63 | nsa_cisa_v1 = "true"
64 | })
65 | }
66 |
67 | control "namespace_limit_range_default_memory_request" {
68 | title = "Namespaces should have default memory request in limitRange policy"
69 | description = "Administrators should use default limitRange policy for memory request for each namespace."
70 | query = query.namespace_limit_range_default_memory_request
71 |
72 | tags = merge(local.namespace_common_tags, {
73 | nsa_cisa_v1 = "true"
74 | })
75 | }
76 |
77 | control "namespace_resource_quota_memory_request" {
78 | title = "Namespaces should have resourceQuota memory request"
79 | description = "Administrators should use resourceQuota memory request for each namespace."
80 | query = query.namespace_resource_quota_memory_request
81 |
82 | tags = merge(local.namespace_common_tags, {
83 | nsa_cisa_v1 = "true"
84 | })
85 | }
86 |
--------------------------------------------------------------------------------
/controls/network_policy.pp:
--------------------------------------------------------------------------------
1 | locals {
2 | network_policy_common_tags = merge(local.kubernetes_compliance_common_tags, {
3 | service = "Kubernetes/NetworkPolicy"
4 | })
5 | }
6 |
7 | control "network_policy_default_deny_egress" {
8 | title = "Namespaces should have a default network policy to deny all egress traffic"
9 | description = "Administrators should use a default policy selecting all Pods to deny all egress traffic and ensure any unselected Pods are isolated. Additional policies could then relax these restrictions for permissible connections."
10 | query = query.network_policy_default_deny_egress
11 |
12 | tags = merge(local.network_policy_common_tags, {
13 | cis = "true"
14 | nsa_cisa_v1 = "true"
15 | })
16 | }
17 |
18 | control "network_policy_default_deny_ingress" {
19 | title = "Namespaces should have a default network policy to deny all ingress traffic"
20 | description = "Administrators should use a default policy selecting all Pods to deny all ingress traffic and ensure any unselected Pods are isolated. Additional policies could then relax these restrictions for permissible connections."
21 | query = query.network_policy_default_deny_ingress
22 |
23 | tags = merge(local.network_policy_common_tags, {
24 | cis = "true"
25 | nsa_cisa_v1 = "true"
26 | })
27 | }
28 |
29 | control "network_policy_default_dont_allow_egress" {
30 | title = "Network policies should not have a default policy to allow all egress traffic"
31 | description = "Administrators should use a default policy selecting all Pods to deny all ingress and egress traffic and ensure any unselected Pods are isolated. An 'allow all' policy would override this default and should not be used. Instead, use specific policies to relax these restrictions only for permissible connections. "
32 | query = query.network_policy_default_dont_allow_egress
33 |
34 | tags = merge(local.network_policy_common_tags, {
35 | cis = "true"
36 | nsa_cisa_v1 = "true"
37 | })
38 | }
39 |
40 | control "network_policy_default_dont_allow_ingress" {
41 | title = "Network policies should not have a default policy to allow all ingress traffic"
42 | description = "Administrators should use a default policy selecting all Pods to deny all ingress and egress traffic and ensure any unselected Pods are isolated. An 'allow all' policy would override this default and should not be used. Instead, use specific policies to relax these restrictions only for permissible connections. "
43 | query = query.network_policy_default_dont_allow_ingress
44 |
45 | tags = merge(local.network_policy_common_tags, {
46 | cis = "true"
47 | nsa_cisa_v1 = "true"
48 | })
49 | }
50 |
--------------------------------------------------------------------------------
/controls/pod_security_policy.pp:
--------------------------------------------------------------------------------
1 | locals {
2 | pod_security_policy_common_tags = merge(local.kubernetes_compliance_common_tags, {
3 | service = "Kubernetes/PodSecurityPolicy"
4 | })
5 | }
6 |
7 | control "pod_security_policy_allowed_host_path" {
8 | title = "Pod Security Policy should prohibit hostPaths volumes"
9 | description = "The Pod Security Policy `allowedHostPaths` specifies a list of host paths that are allowed to be used by hostPath volumes. An empty list means there is no restriction on host paths used. This is defined as a list of objects with a single pathPrefix field, which allows hostPath volumes to mount a path that begins with an allowed prefix, and a readOnly field indicating it must be mounted read-only."
10 | query = query.pod_security_policy_allowed_host_path
11 |
12 | tags = merge(local.pod_security_policy_common_tags, {
13 | nsa_cisa_v1 = "true"
14 | })
15 | }
16 |
17 | control "pod_security_policy_container_privilege_disabled" {
18 | title = "Pod Security Policy should prohibit containers to run with privilege access"
19 | description = "Pod Security Policy `privileged` controls whether the Pod containers may run with `privileged` access. ${replace(local.container_privilege_disabled_desc, "__KIND__", "Pod")}"
20 | query = query.pod_security_policy_container_privilege_disabled
21 |
22 | tags = merge(local.pod_security_policy_common_tags, {
23 | nsa_cisa_v1 = "true"
24 | })
25 | }
26 |
27 | control "pod_security_policy_container_privilege_escalation_disabled" {
28 | title = "Pod Security Policy should prohibit privilege escalation"
29 | description = "Pod Security Policy `allowPrivilegeEscalation` controls whether the Pod containers may request for privilege escalation. ${replace(local.container_privilege_escalation_disabled_desc, "__KIND__", "Pod")}"
30 | query = query.pod_security_policy_container_privilege_escalation_disabled
31 |
32 | tags = merge(local.pod_security_policy_common_tags, {
33 | nsa_cisa_v1 = "true"
34 | })
35 | }
36 |
37 | control "pod_security_policy_security_services_hardening" {
38 | title = "Containerized applications should use security services such as SELinux or AppArmor or Seccomp"
39 | description = "The underlying host OS needs to be secured in order to prevent container breaches from affecting the host. For this, Linux provides several out-of-the-box security modules. Some of the popular ones are SELinux, AppArmor and Seccomp."
40 | query = query.pod_security_policy_security_services_hardening
41 |
42 | tags = merge(local.pod_security_policy_common_tags, {
43 | nsa_cisa_v1 = "true"
44 | })
45 | }
46 |
47 | control "pod_security_policy_host_network_access_disabled" {
48 | title = "Pod Security Policy should prohibit host network access "
49 | description = "Pod Security Policy host network controls whether the Pod may use the node network namespace. Doing so gives the Pod access to the loopback device, services listening on localhost, and could be used to snoop on network activity of other Pods on the same node."
50 | query = query.pod_security_policy_host_network_access_disabled
51 |
52 | tags = merge(local.pod_security_policy_common_tags, {
53 | nsa_cisa_v1 = "true"
54 | })
55 | }
56 |
57 | control "pod_security_policy_hostpid_hostipc_sharing_disabled" {
58 | title = "Pod Security Policy should prohibit containers from sharing the host process namespaces"
59 | description = "Pod Security Policy `hostPID` and `hostIPC` controls whether the Pod may share the host process namespaces. ${replace(local.hostpid_hostipc_sharing_disabled_desc, "__KIND__", "Pod")}"
60 | query = query.pod_security_policy_hostpid_hostipc_sharing_disabled
61 |
62 | tags = merge(local.pod_security_policy_common_tags, {
63 | nsa_cisa_v1 = "true"
64 | })
65 | }
66 |
67 | control "pod_security_policy_immutable_container_filesystem" {
68 | title = "Pod Security Policy should force containers to run with read-only root file system"
69 | description = "Pod Security Policy `readOnlyRootFilesystem` controls whether the Pod containers run with read-only root file system. ${replace(local.immutable_container_filesystem_desc, "__KIND__", "Pod")}"
70 | query = query.pod_security_policy_immutable_container_filesystem
71 |
72 | tags = merge(local.pod_security_policy_common_tags, {
73 | nsa_cisa_v1 = "true"
74 | })
75 | }
76 |
77 | control "pod_security_policy_non_root_container" {
78 | title = "Pod Security Policy should prohibit containers from running as root"
79 | description = "Pod Security Policy should prohibit containers from running as root. ${replace(local.non_root_container_desc, "__KIND__", "Pod")}"
80 | query = query.pod_security_policy_non_root_container
81 |
82 | tags = merge(local.pod_security_policy_common_tags, {
83 | nsa_cisa_v1 = "true"
84 | })
85 | }
86 |
87 | control "pod_security_policy_default_seccomp_profile_enabled" {
88 | title = "Seccomp profile is set to docker/default in Pod security policy"
89 | description = "In Pod security policy seccomp profile should be set to docker/default. Seccomp (secure computing mode) is used to restrict the set of system calls applications can make, allowing cluster administrators greater control over the security of workloads running in the cluster. Kubernetes disables seccomp profiles by default for historical reasons. It should be enabled to ensure that the workloads have restricted actions available within the container."
90 | query = query.pod_security_policy_default_seccomp_profile_enabled
91 |
92 | tags = merge(local.pod_security_policy_common_tags, {
93 | cis = "true"
94 | })
95 | }
96 |
97 | control "pod_security_policy_hostpid_sharing_disabled" {
98 | title = "Minimize the admission of containers wishing to share the host process ID namespace"
99 | description = "A container running in the host's PID namespace can inspect processes running outside the container. If the container also has access to ptrace capabilities this can be used to escalate privileges outside of the container. There should be at least one PodSecurityPolicy (PSP) defined which does not permit containers to share the host PID namespace."
100 | query = query.pod_security_policy_hostpid_sharing_disabled
101 |
102 | tags = merge(local.pod_security_policy_common_tags, {
103 | cis = "true"
104 | })
105 | }
106 |
107 | control "pod_security_policy_hostipc_sharing_disabled" {
108 | title = "Minimize the admission of containers wishing to share the host IPC namespace"
109 | description = "A container running in the host's IPC namespace can use IPC to interact with processes outside the container. There should be at least one PodSecurityPolicy (PSP) defined which does not permit containers to share the host IPC namespace."
110 | query = query.pod_security_policy_hostipc_sharing_disabled
111 |
112 | tags = merge(local.pod_security_policy_common_tags, {
113 | cis = "true"
114 | })
115 | }
116 |
--------------------------------------------------------------------------------
/controls/role.pp:
--------------------------------------------------------------------------------
1 | locals {
2 | role_common_tags = merge(local.kubernetes_compliance_common_tags, {
3 | service = "Kubernetes/Role"
4 | })
5 | }
6 |
7 | control "role_default_namespace_used" {
8 | title = "Role definition should not use default namespace"
9 | description = "Default namespace should not be used by Role definition. Placing objects in this namespace makes application of RBAC and other controls more difficult."
10 | query = query.role_default_namespace_used
11 |
12 | tags = merge(local.role_common_tags, {
13 | cis = "true"
14 | })
15 | }
16 |
17 | control "role_with_wildcards_used" {
18 | title = "Minimize wildcard use in Roles and ClusterRoles"
19 | description = "Kubernetes Roles and ClusterRoles provide access to resources based on sets of objects and actions that can be taken on those objects. It is possible to set either of these to be the wildcard \"*\" which matches all items. Use of wildcards is not optimal from a security perspective as it may allow for inadvertent access to be granted when new resources are added to the Kubernetes API either as CRDs or in later versions of the product."
20 | query = query.role_with_wildcards_used
21 |
22 | tags = merge(local.role_common_tags, {
23 | cis = "true"
24 | })
25 | }
26 |
27 | control "role_with_rbac_escalate_permissions" {
28 | title = "ClusterRoles permissions to escalate Roles or ClusterRoles should be minimized"
29 | description = "Minimize the permissions granted to ClusterRoles to escalate Roles or ClusterRoles. It is recommended to follow the principle of least privilege to enhance security."
30 | query = query.role_with_rbac_escalate_permissions
31 |
32 | tags = local.role_common_tags
33 | }
34 |
35 | control "role_with_bind_cluster_role_bindings" {
36 | title = "ClusterRoles permissions to bind RoleBindings or ClusterRoleBindings should be minimized"
37 | description = "Minimize the permissions granted to bind RoleBindings or ClusterRoleBinding. It is recommended to follow the principle of least privilege to enhance security."
38 | query = query.role_with_bind_cluster_role_bindings
39 |
40 | tags = local.role_common_tags
41 | }
42 |
43 | control "cluster_role_with_validating_or_mutating_admission_webhook_configurations" {
44 | title = "ClusterRoles permissions for managing the configuration of validation or mutation admission webhooks should be minimized"
45 | description = "Minimize the permissions granted to ClusterRoles for managing admission webhooks. It is recommended to follow the principle of least privilege to enhance security."
46 | query = query.cluster_role_with_validating_or_mutating_admission_webhook_configurations
47 |
48 | tags = local.role_common_tags
49 | }
50 |
51 | control "role_with_rbac_approve_certificate_signing_requests" {
52 | title = "ClusterRoles permissions for approving CertificateSigningRequests"
53 | description = "Minimize the permissions granted to ClusterRoles for approving CertificateSigningRequests. It is recommended to follow the principle of least privilege to enhance security."
54 | query = query.role_with_rbac_approve_certificate_signing_requests
55 |
56 | tags = local.role_common_tags
57 | }
58 |
--------------------------------------------------------------------------------
/controls/role_binding.pp:
--------------------------------------------------------------------------------
1 | locals {
2 | role_binding_common_tags = merge(local.kubernetes_compliance_common_tags, {
3 | service = "Kubernetes/RoleBinding"
4 | })
5 | }
6 |
7 | control "role_binding_default_namespace_used" {
8 | title = "RoleBinding definition should not use default namespace"
9 | description = "Default namespace should not be used by RoleBinding definition. Placing objects in this namespace makes application of RBAC and other controls more difficult."
10 | query = query.role_binding_default_namespace_used
11 |
12 | tags = merge(local.role_binding_common_tags, {
13 | cis = "true"
14 | })
15 | }
16 |
17 | control "role_binding_default_service_account_binding_not_active" {
18 | title = "RoleBinding subjects should not actively use default service accounts"
19 | description = "Default service accounts should not be used by RoleBinding subjects."
20 | query = query.role_binding_default_service_account_binding_not_active
21 |
22 | tags = local.role_binding_common_tags
23 | }
24 |
--------------------------------------------------------------------------------
/controls/secret.pp:
--------------------------------------------------------------------------------
1 | locals {
2 | secret_common_tags = merge(local.kubernetes_compliance_common_tags, {
3 | service = "Kubernetes/Secret"
4 | })
5 | }
6 |
7 | control "secret_default_namespace_used" {
8 | title = "Secret definition should not use default namespace"
9 | description = "Default namespace should not be used by Secret definition. Placing objects in this namespace makes application of RBAC and other controls more difficult."
10 | query = query.secret_default_namespace_used
11 |
12 | tags = merge(local.secret_common_tags, {
13 | cis = "true"
14 | })
15 | }
16 |
--------------------------------------------------------------------------------
/controls/service.pp:
--------------------------------------------------------------------------------
1 | locals {
2 | service_common_tags = merge(local.kubernetes_compliance_common_tags, {
3 | service = "Kubernetes/Service"
4 | })
5 | }
6 |
7 | control "service_type_forbidden" {
8 | title = "Containers should not be exposed through a forbidden service type"
9 | description = local.service_type_forbidden_desc
10 | query = query.service_type_forbidden
11 |
12 | tags = merge(local.service_common_tags, {
13 | nsa_cisa_v1 = "true"
14 | })
15 | }
16 |
17 | control "service_default_namespace_used" {
18 | title = "Services should not use default namespace"
19 | description = "Default namespace should not be used by services. Placing objects in this namespace makes application of RBAC and other controls more difficult."
20 | query = query.service_default_namespace_used
21 |
22 | tags = merge(local.service_common_tags, {
23 | cis = "true"
24 | })
25 | }
26 |
27 | control "service_no_tiller_service" {
28 | title = "Services should not have tiller service"
29 | description = "Services should avoid using Tiller service as it is not recommended due to security concerns."
30 | query = query.service_no_tiller_service
31 |
32 | tags = local.service_common_tags
33 | }
34 |
35 | control "service_no_tiller_deployed" {
36 | title = "Services should not have tiller (helm v2) deployed"
37 | description = "Services should not deploy tiller (helm v2) as it is not recommended due to security concerns."
38 | query = query.service_no_tiller_deployed
39 |
40 | tags = local.service_common_tags
41 | }
42 |
43 |
--------------------------------------------------------------------------------
/controls/service_account.pp:
--------------------------------------------------------------------------------
1 | locals {
2 | service_account_common_tags = merge(local.kubernetes_compliance_common_tags, {
3 | service = "Kubernetes/ServiceAccount"
4 | })
5 | }
6 |
7 | control "service_account_token_disabled" {
8 | title = "Automatic mapping of the service account tokens should be disabled in service account"
9 | description = local.service_account_token_disabled_desc
10 | query = query.service_account_token_disabled
11 |
12 | tags = merge(local.service_account_common_tags, {
13 | nsa_cisa_v1 = "true"
14 | })
15 | }
16 |
17 | control "service_account_default_namespace_used" {
18 | title = "ServiceAccount definition should not use default namespace"
19 | description = "Default namespace should not be used by ServiceAccount definition. Placing objects in this namespace makes application of RBAC and other controls more difficult."
20 | query = query.service_account_default_namespace_used
21 |
22 | tags = merge(local.service_account_common_tags, {
23 | cis = "true"
24 | })
25 | }
26 |
--------------------------------------------------------------------------------
/docs/index.md:
--------------------------------------------------------------------------------
1 | # Kubernetes Compliance Mod
2 |
3 | Run individual controls or full compliance benchmarks for `NSA and CISA Kubernetes Hardening Guidance` and `CIS` across all of your Kubernetes clusters.
4 |
5 |
6 |
7 |
8 |
9 |
10 | ## Documentation
11 |
12 | - **[Benchmarks and controls →](https://hub.powerpipe.io/mods/turbot/kubernetes_compliance/controls)**
13 | - **[Named queries →](https://hub.powerpipe.io/mods/turbot/kubernetes_compliance/queries)**
14 |
15 | ## Getting Started
16 |
17 | ### Installation
18 |
19 | Install Powerpipe (https://powerpipe.io/downloads), or use Brew:
20 |
21 | ```sh
22 | brew install turbot/tap/powerpipe
23 | ```
24 |
25 | This mod also requires [Steampipe](https://steampipe.io) with the [Kubernetes plugin](https://hub.steampipe.io/plugins/turbot/kubernetes) as the data source. Install Steampipe (https://steampipe.io/downloads), or use Brew:
26 |
27 | ```sh
28 | brew install turbot/tap/steampipe
29 | steampipe plugin install kubernetes
30 | ```
31 |
32 | Steampipe will automatically use your default Kubernetes credentials. Optionally, you can [setup multiple context connections](https://hub.steampipe.io/plugins/turbot/kubernetes#multiple-context-connections) or [customize Kubernetes credentials](https://hub.steampipe.io/plugins/turbot/kubernetes#configuring-kubernetes-cluster-credentials).
33 |
34 | Finally, install the mod:
35 |
36 | ```sh
37 | mkdir dashboards
38 | cd dashboards
39 | powerpipe mod init
40 | powerpipe mod install github.com/turbot/steampipe-mod-kubernetes-compliance
41 | ```
42 |
43 | ### Browsing Dashboards
44 |
45 | Start Steampipe as the data source:
46 |
47 | ```sh
48 | steampipe service start
49 | ```
50 |
51 | Start the dashboard server:
52 |
53 | ```sh
54 | powerpipe server
55 | ```
56 |
57 | Browse and view your dashboards at **http://localhost:9033**.
58 |
59 | ### Running Checks in Your Terminal
60 |
61 | Instead of running benchmarks in a dashboard, you can also run them within your
62 | terminal with the `powerpipe benchmark` command:
63 |
64 | List available benchmarks:
65 |
66 | ```sh
67 | powerpipe benchmark list
68 | ```
69 |
70 | Run a benchmark:
71 |
72 | ```sh
73 | powerpipe benchmark run kubernetes_compliance.benchmark.cis_v170
74 | ```
75 |
76 | Different output formats are also available, for more information please see
77 | [Output Formats](https://powerpipe.io/docs/reference/cli/benchmark#output-formats).
78 |
79 | ### Common and Tag Dimensions
80 |
81 | The benchmark queries use common properties (like `connection_name`, `context_name`, `namespace`, `path` and `source_type`) and tags that are defined in the form of a default list of strings in the `variables.sp` file. These properties can be overwritten in several ways:
82 |
83 | It's easiest to setup your vars file, starting with the sample:
84 |
85 | ```sh
86 | cp powerpipe.ppvars.example powerpipe.ppvars
87 | vi powerpipe.ppvars
88 | ```
89 |
90 | Alternatively you can pass variables on the command line:
91 |
92 | ```sh
93 | powerpipe benchmark run kubernetes_compliance.benchmark.cis_v170 --var 'tag_dimensions=["Environment", "Owner"]'
94 | ```
95 |
96 | Or through environment variables:
97 |
98 | ```sh
99 | export PP_VAR_common_dimensions='["connection_name", "context_name", "namespace", "path", "source_type"]'
100 | export PP_VAR_tag_dimensions='["Environment", "Owner"]'
101 | powerpipe benchmark run kubernetes_compliance.benchmark.cis_v170
102 | ```
103 |
104 | ## Open Source & Contributing
105 |
106 | This repository is published under the [Apache 2.0 license](https://www.apache.org/licenses/LICENSE-2.0). Please see our [code of conduct](https://github.com/turbot/.github/blob/main/CODE_OF_CONDUCT.md). We look forward to collaborating with you!
107 |
108 | [Steampipe](https://steampipe.io) and [Powerpipe](https://powerpipe.io) are products produced from this open source software, exclusively by [Turbot HQ, Inc](https://turbot.com). They are distributed under our commercial terms. Others are allowed to make their own distribution of the software, but cannot use any of the Turbot trademarks, cloud services, etc. You can learn more in our [Open Source FAQ](https://turbot.com/open-source).
109 |
110 | ## Get Involved
111 |
112 | **[Join #powerpipe on Slack →](https://turbot.com/community/join)**
113 |
114 | Want to help but don't know where to start? Pick up one of the `help wanted` issues:
115 |
116 | - [Powerpipe](https://github.com/turbot/powerpipe/labels/help%20wanted)
117 | - [Kubernetes Compliance Mod](https://github.com/turbot/steampipe-mod-kubernetes-compliance/labels/help%20wanted)
118 |
--------------------------------------------------------------------------------
/docs/kubernetes_cis_v120.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/turbot/steampipe-mod-kubernetes-compliance/eb10e73bd24c833a3ba65cb77a172cea1a55e299/docs/kubernetes_cis_v120.png
--------------------------------------------------------------------------------
/docs/kubernetes_compliance_dashboard.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/turbot/steampipe-mod-kubernetes-compliance/eb10e73bd24c833a3ba65cb77a172cea1a55e299/docs/kubernetes_compliance_dashboard.png
--------------------------------------------------------------------------------
/docs/kubernetes_compliance_mod_console_output.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/turbot/steampipe-mod-kubernetes-compliance/eb10e73bd24c833a3ba65cb77a172cea1a55e299/docs/kubernetes_compliance_mod_console_output.png
--------------------------------------------------------------------------------
/docs/kubernetes_nsa_csa_v1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/turbot/steampipe-mod-kubernetes-compliance/eb10e73bd24c833a3ba65cb77a172cea1a55e299/docs/kubernetes_nsa_csa_v1.png
--------------------------------------------------------------------------------
/mod.pp:
--------------------------------------------------------------------------------
1 | mod "kubernetes_compliance" {
2 | # Hub metadata
3 | title = "Kubernetes Compliance"
4 | description = "Run individual controls or full compliance benchmarks for CIS, NSA CISA Kubernetes Hardening Guidance across all of your Kubernetes clusters using Powerpipe and Steampipe."
5 | color = "#0089D6"
6 | documentation = file("./docs/index.md")
7 | icon = "/images/mods/turbot/kubernetes-compliance.svg"
8 | categories = ["kubernetes", "compliance", "iac", "software development", "security"]
9 |
10 | opengraph {
11 | title = "Powerpipe Mod for Kubernetes Compliance"
12 | description = "Run individual controls or full compliance benchmarks for CIS, NSA CISA Kubernetes Hardening Guidance across all of your Kubernetes clusters using Powerpipe and Steampipe."
13 | image = "/images/mods/turbot/kubernetes-compliance-social-graphic.png"
14 | }
15 | requires {
16 | plugin "kubernetes" {
17 | min_version = "0.23.0"
18 | }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/nsa_cisa_v1/docs/nsa_cisa_v1_overview.md:
--------------------------------------------------------------------------------
1 | To get the latest version of the official guide, please visit [here](https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF).
2 |
3 | ## Overview
4 |
5 | Kubernetes is an open-source system that automates the deployment, scaling, and management of applications run in containers, and is often hosted in a cloud environment. The hardening guidance detailed in this report is designed to help organizations handle associated risks and enjoy the benefits of using this technology.
6 |
7 | ## Control Categories
8 |
9 | These are the available categories for Kubernetes Compliance controls. The category for a control reflects the security function that the control applies to.
10 |
11 | ### Kubernetes Pod Security
12 |
13 | A Pod Security Policy is a cluster-level resource that controls security sensitive aspects of the pod specification. The PodSecurityPolicy objects define a set of conditions that a pod must run with in order to be accepted into the system, as well as defaults for the related fields.
14 |
15 | ### Network Separation and Hardening
16 |
17 | Cluster networking is a central concept of Kubernetes. Communication between containers, Pods, services, and external services must be taken into consideration. By default, there are few network policies in place to separate resources and prevent lateral movement or escalation if a cluster is compromised. Resource separation and encryption can be an effective way to limit a cyber actor’s movement and escalation within a cluster.
18 |
--------------------------------------------------------------------------------
/nsa_cisa_v1/nsa_cisa_v1.pp:
--------------------------------------------------------------------------------
1 | locals {
2 | nsa_cisa_v1_common_tags = merge(local.kubernetes_compliance_common_tags, {
3 | nsa_cisa_v1 = "true"
4 | })
5 | }
6 |
7 | benchmark "nsa_cisa_v1" {
8 | title = "NSA and CISA Kubernetes Hardening Guidance v1.0"
9 | documentation = file("./nsa_cisa_v1/docs/nsa_cisa_v1_overview.md")
10 | children = [
11 | benchmark.nsa_cisa_v1_pod_security,
12 | benchmark.nsa_cisa_v1_network_hardening
13 | ]
14 |
15 | tags = merge(local.nsa_cisa_v1_common_tags, {
16 | type = "Benchmark"
17 | })
18 | }
19 |
--------------------------------------------------------------------------------
/nsa_cisa_v1/nsa_cisa_v1_network_hardening.pp:
--------------------------------------------------------------------------------
1 | locals {
2 | nsa_cisa_v1_network_hardening_common_tags = merge(local.nsa_cisa_v1_common_tags, {
3 | })
4 | }
5 |
6 | benchmark "nsa_cisa_v1_network_hardening" {
7 | title = "Network Separation and Hardening"
8 | children = [
9 | benchmark.nsa_cisa_v1_network_hardening_cpu_limit,
10 | benchmark.nsa_cisa_v1_network_hardening_cpu_request,
11 | benchmark.nsa_cisa_v1_network_hardening_api_serve_on_secure_port_endpoint,
12 | benchmark.nsa_cisa_v1_network_hardening_memory_limit,
13 | benchmark.nsa_cisa_v1_network_hardening_memory_request,
14 | benchmark.nsa_cisa_v1_network_hardening_default_deny_network_policy
15 | ]
16 |
17 | tags = merge(local.nsa_cisa_v1_network_hardening_common_tags, {
18 | type = "Benchmark"
19 | })
20 | }
21 |
22 | benchmark "nsa_cisa_v1_network_hardening_cpu_limit" {
23 | title = "Containers should have a CPU limit"
24 | description = "Containers should have CPU limit which restricts the container to use no more than a given amount of CPU."
25 | children = [
26 | control.cronjob_cpu_limit,
27 | control.daemonset_cpu_limit,
28 | control.deployment_cpu_limit,
29 | control.job_cpu_limit,
30 | control.namespace_limit_range_default_cpu_limit,
31 | control.namespace_resource_quota_cpu_limit,
32 | control.replicaset_cpu_limit,
33 | control.replication_controller_cpu_limit,
34 | control.statefulset_cpu_limit
35 | ]
36 |
37 | tags = merge(local.nsa_cisa_v1_network_hardening_common_tags, {
38 | type = "Benchmark"
39 | })
40 | }
41 |
42 | benchmark "nsa_cisa_v1_network_hardening_cpu_request" {
43 | title = "Containers should have a CPU request"
44 | description = "Containers should have CPU request. If required Kubernetes will make sure your containers get the CPU they requested."
45 | children = [
46 | control.cronjob_cpu_request,
47 | control.daemonset_cpu_request,
48 | control.deployment_cpu_request,
49 | control.job_cpu_request,
50 | control.namespace_limit_range_default_cpu_request,
51 | control.namespace_resource_quota_cpu_request,
52 | control.replicaset_cpu_request,
53 | control.replication_controller_cpu_request,
54 | control.statefulset_cpu_request
55 | ]
56 |
57 | tags = merge(local.nsa_cisa_v1_network_hardening_common_tags, {
58 | type = "Benchmark"
59 | })
60 | }
61 |
62 | benchmark "nsa_cisa_v1_network_hardening_api_serve_on_secure_port_endpoint" {
63 | title = "Kubernetes API should serve on secure port"
64 | description = "Kubernetes API should serve on port 443 or port 6443, protected by TLS. Once TLS is established, the HTTP request moves to the authentication step. If the request cannot be authenticated, it is rejected with HTTP status code 401."
65 | children = [
66 | control.endpoint_api_serve_on_secure_port,
67 | ]
68 |
69 | tags = merge(local.nsa_cisa_v1_network_hardening_common_tags, {
70 | type = "Benchmark"
71 | })
72 | }
73 |
74 | benchmark "nsa_cisa_v1_network_hardening_memory_limit" {
75 | title = "Containers should have a memory limit"
76 | description = "Containers should have a memory limit which restricts the container to use no more than a given amount of user or system memory."
77 | children = [
78 | control.cronjob_memory_limit,
79 | control.daemonset_memory_limit,
80 | control.deployment_memory_limit,
81 | control.job_memory_limit,
82 | control.namespace_limit_range_default_memory_limit,
83 | control.namespace_resource_quota_memory_limit,
84 | control.replicaset_memory_limit,
85 | control.replication_controller_memory_limit,
86 | control.statefulset_memory_limit
87 | ]
88 |
89 | tags = merge(local.nsa_cisa_v1_network_hardening_common_tags, {
90 | type = "Benchmark"
91 | })
92 | }
93 |
94 | benchmark "nsa_cisa_v1_network_hardening_memory_request" {
95 | title = "Containers should have a memory request"
96 | description = "Containers should have memory request. If required Kubernetes will make sure your containers get the memory they requested."
97 | children = [
98 | control.cronjob_memory_request,
99 | control.daemonset_memory_request,
100 | control.deployment_memory_request,
101 | control.job_memory_request,
102 | control.namespace_limit_range_default_memory_request,
103 | control.namespace_resource_quota_memory_request,
104 | control.replicaset_memory_request,
105 | control.replication_controller_memory_request,
106 | control.statefulset_memory_request
107 | ]
108 |
109 | tags = merge(local.nsa_cisa_v1_network_hardening_common_tags, {
110 | type = "Benchmark"
111 | })
112 | }
113 |
114 | benchmark "nsa_cisa_v1_network_hardening_default_deny_network_policy" {
115 | title = "Network policy should have a default policy to deny all ingress and egress traffic"
116 | description = "Administrators should use a default policy selecting all Pods to deny all ingress and egress traffic and ensure any unselected Pods are isolated. Additional policies could then relax these restrictions for permissible connections."
117 | children = [
118 | control.network_policy_default_deny_egress,
119 | control.network_policy_default_deny_ingress,
120 | control.network_policy_default_dont_allow_egress,
121 | control.network_policy_default_dont_allow_ingress
122 | ]
123 |
124 | tags = merge(local.nsa_cisa_v1_network_hardening_common_tags, {
125 | type = "Benchmark"
126 | })
127 | }
128 |
--------------------------------------------------------------------------------
/nsa_cisa_v1/nsa_cisa_v1_pod_security.pp:
--------------------------------------------------------------------------------
1 | locals {
2 | nsa_cisa_v1_pod_security_common_tags = merge(local.nsa_cisa_v1_common_tags, {
3 | })
4 | }
5 |
6 | benchmark "nsa_cisa_v1_pod_security" {
7 | title = "Kubernetes Pod Security"
8 | children = [
9 | benchmark.nsa_cisa_v1_pod_security_container_disallow_host_path,
10 | benchmark.nsa_cisa_v1_pod_security_container_privilege_disabled,
11 | benchmark.nsa_cisa_v1_pod_security_container_privilege_escalation_disabled,
12 | benchmark.nsa_cisa_v1_pod_security_container_security_service_hardening,
13 | benchmark.nsa_cisa_v1_pod_security_host_network_access_disabled,
14 | benchmark.nsa_cisa_v1_pod_security_hostpid_hostipc_sharing_disabled,
15 | benchmark.nsa_cisa_v1_pod_security_immutable_container_filesystem,
16 | benchmark.nsa_cisa_v1_pod_security_non_root_container,
17 | benchmark.nsa_cisa_v1_pod_security_service_account_token_disabled
18 | ]
19 |
20 | tags = merge(local.nsa_cisa_v1_pod_security_common_tags, {
21 | type = "Benchmark"
22 | })
23 | }
24 |
25 | benchmark "nsa_cisa_v1_pod_security_container_disallow_host_path" {
26 | title = "Containers should not use hostPath mounts"
27 | description = "Containers should not able to access any specific paths of the host file system. There are many ways a container with unrestricted access to the host filesystem can escalate privileges, including reading data from other containers, and abusing the credentials of system services, such as Kubelet."
28 | children = [
29 | control.pod_security_policy_allowed_host_path,
30 | control.pod_volume_host_path
31 | ]
32 |
33 | tags = merge(local.nsa_cisa_v1_pod_security_common_tags, {
34 | type = "Benchmark"
35 | })
36 | }
37 |
38 | benchmark "nsa_cisa_v1_pod_security_container_privilege_disabled" {
39 | title = "Containers should not have privileged access"
40 | description = "Containers should not have privileged access. To prevent security issues, it is recommended that you do not run privileged containers in your environment. Instead, provide granular permissions and capabilities to the container environment. Giving containers full access to the host can create security flaws in your production environment."
41 | children = [
42 | control.cronjob_container_privilege_disabled,
43 | control.daemonset_container_privilege_disabled,
44 | control.deployment_container_privilege_disabled,
45 | control.job_container_privilege_disabled,
46 | control.pod_container_privilege_disabled,
47 | control.pod_security_policy_container_privilege_disabled,
48 | control.replicaset_container_privilege_disabled,
49 | control.replication_controller_container_privilege_disabled,
50 | control.statefulset_container_privilege_disabled
51 | ]
52 |
53 | tags = merge(local.nsa_cisa_v1_pod_security_common_tags, {
54 | type = "Benchmark"
55 | })
56 | }
57 |
58 | benchmark "nsa_cisa_v1_pod_security_container_privilege_escalation_disabled" {
59 | title = "Containers should not allow privilege escalation"
60 | description = "Containers should not allow privilege escalation. A container running with the `allowPrivilegeEscalation` flag set to true may have processes that can gain more privileges than their parent."
61 | children = [
62 | control.cronjob_container_privilege_escalation_disabled,
63 | control.daemonset_container_privilege_escalation_disabled,
64 | control.deployment_container_privilege_escalation_disabled,
65 | control.job_container_privilege_escalation_disabled,
66 | control.pod_container_privilege_escalation_disabled,
67 | control.pod_security_policy_container_privilege_escalation_disabled,
68 | control.replicaset_container_privilege_escalation_disabled,
69 | control.replication_controller_container_privilege_escalation_disabled,
70 | control.statefulset_container_privilege_escalation_disabled
71 | ]
72 |
73 | tags = merge(local.nsa_cisa_v1_pod_security_common_tags, {
74 | type = "Benchmark"
75 | })
76 | }
77 |
78 | benchmark "nsa_cisa_v1_pod_security_container_security_service_hardening" {
79 | title = "Containerized applications should use security services"
80 | description = "Linux provides several out-of-the-box security modules. Some of the popular ones are SELinux, AppArmor and Seccomp. Containerized applications should use these security services."
81 | children = [
82 | control.pod_security_policy_security_services_hardening,
83 | ]
84 |
85 | tags = merge(local.nsa_cisa_v1_pod_security_common_tags, {
86 | type = "Benchmark"
87 | })
88 | }
89 |
90 | benchmark "nsa_cisa_v1_pod_security_host_network_access_disabled" {
91 | title = "Containers should not run with host network access"
92 | description = "Pod host network controls whether the Pod may use the node network namespace. Doing so gives the Pod access to the loopback device, services listening on localhost, and could be used to snoop on network activity of other Pods on the same node."
93 | children = [
94 | control.cronjob_host_network_access_disabled,
95 | control.daemonset_host_network_access_disabled,
96 | control.deployment_host_network_access_disabled,
97 | control.job_host_network_access_disabled,
98 | control.pod_host_network_access_disabled,
99 | control.pod_security_policy_host_network_access_disabled,
100 | control.replicaset_host_network_access_disabled,
101 | control.replication_controller_host_network_access_disabled,
102 | control.statefulset_host_network_access_disabled
103 | ]
104 |
105 | tags = merge(local.nsa_cisa_v1_pod_security_common_tags, {
106 | type = "Benchmark"
107 | })
108 | }
109 |
110 | benchmark "nsa_cisa_v1_pod_security_hostpid_hostipc_sharing_disabled" {
111 | title = "Containers should not share the host process namespace"
112 | description = "Containers should not share the host process PID or IPC namespace. Sharing the host’s process namespace allows the container to see all of the processes on the host system. This reduces the benefit of process level isolation between the host and the containers. Under these circumstances a malicious user who has access to a container could get access to processes on the host itself, manipulate them, and even be able to kill them."
113 | children = [
114 | control.cronjob_hostpid_hostipc_sharing_disabled,
115 | control.daemonset_hostpid_hostipc_sharing_disabled,
116 | control.deployment_hostpid_hostipc_sharing_disabled,
117 | control.job_hostpid_hostipc_sharing_disabled,
118 | control.pod_hostpid_hostipc_sharing_disabled,
119 | control.pod_security_policy_hostpid_hostipc_sharing_disabled,
120 | control.replicaset_hostpid_hostipc_sharing_disabled,
121 | control.replication_controller_hostpid_hostipc_sharing_disabled,
122 | control.statefulset_hostpid_hostipc_sharing_disabled
123 | ]
124 |
125 | tags = merge(local.nsa_cisa_v1_pod_security_common_tags, {
126 | type = "Benchmark"
127 | })
128 | }
129 |
130 | benchmark "nsa_cisa_v1_pod_security_immutable_container_filesystem" {
131 | title = "Containers should run with a read only root file system"
132 | description = "Containers should always run with a read only root file system. Using an immutable root filesystem and a verified boot mechanism prevents against attackers from owning the machine through permanent local changes. An immutable root filesystem can also prevent malicious binaries from writing to the host system."
133 | children = [
134 | control.cronjob_immutable_container_filesystem,
135 | control.daemonset_immutable_container_filesystem,
136 | control.deployment_immutable_container_filesystem,
137 | control.job_immutable_container_filesystem,
138 | control.pod_immutable_container_filesystem,
139 | control.pod_security_policy_immutable_container_filesystem,
140 | control.replicaset_immutable_container_filesystem,
141 | control.replication_controller_immutable_container_filesystem,
142 | control.statefulset_immutable_container_filesystem
143 | ]
144 |
145 | tags = merge(local.nsa_cisa_v1_pod_security_common_tags, {
146 | type = "Benchmark"
147 | })
148 | }
149 |
150 | benchmark "nsa_cisa_v1_pod_security_non_root_container" {
151 | title = "Containers should not run with root privileges"
152 | description = "Containers should not be deployed with root privileges. By default, many container services run as the privileged root user, and applications execute inside the container as root despite not requiring privileged execution. Preventing root execution by using non-root containers or a rootless container engine limits the impact of a container compromise."
153 | children = [
154 | control.cronjob_non_root_container,
155 | control.daemonset_non_root_container,
156 | control.deployment_non_root_container,
157 | control.job_non_root_container,
158 | control.pod_non_root_container,
159 | control.pod_security_policy_non_root_container,
160 | control.replicaset_non_root_container,
161 | control.replication_controller_non_root_container,
162 | control.statefulset_non_root_container
163 | ]
164 |
165 | tags = merge(local.nsa_cisa_v1_pod_security_common_tags, {
166 | type = "Benchmark"
167 | })
168 | }
169 |
170 | benchmark "nsa_cisa_v1_pod_security_service_account_token_disabled" {
171 | title = "Automatic mapping of the service account tokens should be disabled"
172 | description = local.service_account_token_disabled_desc
173 | children = [
174 | control.pod_service_account_token_disabled,
175 | control.service_account_token_disabled
176 | ]
177 |
178 | tags = merge(local.nsa_cisa_v1_pod_security_common_tags, {
179 | type = "Benchmark"
180 | })
181 | }
182 |
--------------------------------------------------------------------------------
/powerpipe.ppvars.example:
--------------------------------------------------------------------------------
1 | # Dimensions
2 | # Possible values for common_dimensions include "connection_name", "context_name", "namespace", "path" and "source_type"
3 | common_dimensions = [ "context_name", "namespace", "path", "source_type" ]
4 | tag_dimensions = []
5 |
--------------------------------------------------------------------------------
/query/cluster_role_binding.pp:
--------------------------------------------------------------------------------
1 | query "cluster_role_binding_default_service_account_binding_not_active" {
2 | sql = <<-EOQ
3 | select
4 | coalesce(uid, concat(path, ':', start_line)) as resource,
5 | case
6 | when (subject ->> 'kind') = 'ServiceAccount' and (subject ->> 'name') = 'default' then 'alarm'
7 | else 'ok'
8 | end as status,
9 | case
10 | when (subject ->> 'kind' = 'ServiceAccount') and (subject ->> 'name' = 'default') then name || ' default service accounts active.'
11 | else name || ' default service accounts not active.'
12 | end as reason,
13 | name as cluster_role_binding_name
14 | ${local.tag_dimensions_sql}
15 | ${local.common_dimensions_non_namespace_sql}
16 | from
17 | kubernetes_cluster_role_binding,
18 | jsonb_array_elements(subjects) as subject;
19 | EOQ
20 | }
21 |
--------------------------------------------------------------------------------
/query/config_map.pp:
--------------------------------------------------------------------------------
1 | query "config_map_default_namespace_used" {
2 | sql = <<-EOQ
3 | select
4 | coalesce(uid, concat(path, ':', start_line)) as resource,
5 | case
6 | when namespace = 'default' then 'alarm'
7 | else 'ok'
8 | end as status,
9 | case
10 | when namespace = 'default' then name || ' uses default namespace.'
11 | else name || ' not using the default namespace.'
12 | end as reason
13 | ${local.tag_dimensions_sql}
14 | ${local.common_dimensions_sql}
15 | from
16 | kubernetes_config_map;
17 | EOQ
18 | }
19 |
20 |
--------------------------------------------------------------------------------
/query/endpoint.pp:
--------------------------------------------------------------------------------
1 | query "endpoint_api_serve_on_secure_port" {
2 | sql = <<-EOQ
3 | select
4 | coalesce(uid, concat(path, ':', start_line)) as resource,
5 | case
6 | when p ->> 'name' = 'https' and (p ->> 'port' = '443' or p ->> 'port' = '6443') then 'ok'
7 | else 'alarm'
8 | end as status,
9 | case
10 | when p ->> 'name' = 'https' and (p ->> 'port' = '443' or p ->> 'port' = '6443') then name || ' Kubernetes API serving on secure port.'
11 | else name || ' Kubernetes API not serving on secure port.'
12 | end as reason,
13 | name as endpoint_name
14 | ${local.tag_dimensions_sql}
15 | ${local.common_dimensions_sql}
16 | from
17 | kubernetes_endpoint,
18 | jsonb_array_elements(subsets) as s,
19 | jsonb_array_elements(s -> 'ports') as p
20 | where name = 'kubernetes';
21 | EOQ
22 | }
23 |
24 |
--------------------------------------------------------------------------------
/query/ingress.pp:
--------------------------------------------------------------------------------
1 | query "ingress_default_namespace_used" {
2 | sql = <<-EOQ
3 | select
4 | coalesce(uid, concat(path, ':', start_line)) as resource,
5 | case
6 | when namespace = 'default' then 'alarm'
7 | else 'ok'
8 | end as status,
9 | case
10 | when namespace = 'default' then name || ' uses default namespace.'
11 | else name || ' not using the default namespace.'
12 | end as reason,
13 | name as ingress_name
14 | ${local.tag_dimensions_sql}
15 | ${local.common_dimensions_sql}
16 | from
17 | kubernetes_ingress;
18 | EOQ
19 | }
20 |
21 | query "ingress_nginx_annotations_snippets_alias_not_used" {
22 | sql = <<-EOQ
23 | select
24 | coalesce(uid, concat(path, ':', start_line)) as resource,
25 | case when a.key like '%snippet%' and a.value like '%alias%' then 'alarm'
26 | else 'ok'
27 | end as status,
28 | case
29 | when a.key like '%snippet%' and a.value like '%alias%' then a.key || ' annotation snippet contains alias statements.'
30 | else a.key || ' annotation snippet not containing alias statements.'
31 | end as reason,
32 | name as ingress_name
33 | ${local.tag_dimensions_sql}
34 | ${local.common_dimensions_sql}
35 | from
36 | kubernetes_ingress,
37 | jsonb_each_text(annotations) as a;
38 | EOQ
39 | }
40 |
41 | query "ingress_nginx_annotations_all_snippets_not_used" {
42 | sql = <<-EOQ
43 | select
44 | coalesce(uid, concat(path, ':', start_line)) as resource,
45 | case when a.key like '%snippet%' then 'alarm'
46 | else 'ok'
47 | end as status,
48 | case
49 | when a.key like '%snippet%' then a.key || ' annotation snippet used.'
50 | else a.key || ' annotation snippet not used.'
51 | end as reason,
52 | name as ingress_name
53 | ${local.tag_dimensions_sql}
54 | ${local.common_dimensions_sql}
55 | from
56 | kubernetes_ingress,
57 | jsonb_each_text(annotations) as a;
58 | EOQ
59 | }
60 |
61 | query "ingress_nginx_annotations_snippets_lua_code_not_used" {
62 | sql = <<-EOQ
63 | select
64 | coalesce(uid, concat(path, ':', start_line)) as resource,
65 | case when a.key like '%snippet%' and a.value ~ '(lua_|_lua|_lua_|kubernetes\.io)' then 'alarm'
66 | else 'ok'
67 | end as status,
68 | case
69 | when a.key like '%snippet%' and a.value ~ '(lua_|_lua|_lua_|kubernetes\.io)' then a.key || ' annotation snippet contains lua code execution.'
70 | else a.key || ' annotation snippet does not contain lua code execution.'
71 | end as reason,
72 | name as ingress_name
73 | ${local.tag_dimensions_sql}
74 | ${local.common_dimensions_sql}
75 | from
76 | kubernetes_ingress,
77 | jsonb_each_text(annotations) as a;
78 | EOQ
79 | }
--------------------------------------------------------------------------------
/query/namespace.pp:
--------------------------------------------------------------------------------
1 | query "namespace_limit_range_default_memory_limit" {
2 | sql = <<-EOQ
3 | with default_limit_range as (
4 | select
5 | namespace,
6 | l -> 'default' as default_limit,
7 | l -> 'defaultRequest' as default_request
8 | from
9 | kubernetes_limit_range,
10 | jsonb_array_elements(spec_limits) as l
11 | )
12 | select
13 | coalesce(n.uid, concat(n.path, ':', n.start_line)) as resource,
14 | case
15 | when default_limit ->> 'memory' is null then 'alarm'
16 | else 'ok'
17 | end as status,
18 | case
19 | when default_limit ->> 'memory' is null then n.name || ' do not have LimitRange default memory limit.'
20 | else n.name || ' has LimitRange default memory limit.'
21 | end as reason
22 | ${replace(local.tag_dimensions_qualifier_sql, "__QUALIFIER__", "n.")}
23 | ${replace(local.common_dimensions_qualifier_namespace_sql, "__QUALIFIER__", "n.")}
24 | from
25 | kubernetes_namespace n
26 | left join default_limit_range r
27 | on n.name = r.namespace;
28 | EOQ
29 | }
30 |
31 | query "namespace_resource_quota_memory_limit" {
32 | sql = <<-EOQ
33 | select
34 | distinct(coalesce(n.uid, concat(n.path, ':', n.start_line))) as resource,
35 | case
36 | when q.spec_hard -> 'limits.memory' is null then 'alarm'
37 | else 'ok'
38 | end as status,
39 | case
40 | when q.spec_hard -> 'limits.memory' is null then n.name || ' do not have ResourceQuota for memory limit.'
41 | else n.name || ' have ResourceQuota for memory limit.'
42 | end as reason
43 | ${replace(local.tag_dimensions_qualifier_sql, "__QUALIFIER__", "n.")}
44 | ${replace(local.common_dimensions_qualifier_namespace_sql, "__QUALIFIER__", "n.")}
45 | from
46 | kubernetes_namespace n
47 | left join kubernetes_resource_quota q
48 | on n.name = q.namespace;
49 | EOQ
50 | }
51 |
52 | query "namespace_resource_quota_cpu_limit" {
53 | sql = <<-EOQ
54 | select
55 | distinct(coalesce(n.uid, concat(n.path, ':', n.start_line))) as resource,
56 | case
57 | when q.spec_hard -> 'limits.cpu' is null then 'alarm'
58 | else 'ok'
59 | end as status,
60 | case
61 | when q.spec_hard -> 'limits.cpu' is null then n.name || ' do not have ResourceQuota for CPU limit.'
62 | else n.name || ' have ResourceQuota for CPU limit.'
63 | end as reason
64 | ${replace(local.tag_dimensions_qualifier_sql, "__QUALIFIER__", "n.")}
65 | ${replace(local.common_dimensions_qualifier_namespace_sql, "__QUALIFIER__", "n.")}
66 | from
67 | kubernetes_namespace n
68 | left join kubernetes_resource_quota q
69 | on n.name = q.namespace;
70 | EOQ
71 | }
72 |
73 | query "namespace_limit_range_default_memory_request" {
74 | sql = <<-EOQ
75 | with default_limit_range as (
76 | select
77 | namespace,
78 | l -> 'default' as default_limit,
79 | l -> 'defaultRequest' as default_request
80 | from
81 | kubernetes_limit_range,
82 | jsonb_array_elements(spec_limits) as l
83 | )
84 | select
85 | coalesce(n.uid, concat(n.path, ':', n.start_line)) as resource,
86 | case
87 | when default_request ->> 'memory' is null then 'alarm'
88 | else 'ok'
89 | end as status,
90 | case
91 | when default_request ->> 'memory' is null then n.name || ' do not have LimitRange default memory request.'
92 | else n.name || ' has LimitRange default memory request.'
93 | end as reason
94 | ${replace(local.tag_dimensions_qualifier_sql, "__QUALIFIER__", "n.")}
95 | ${replace(local.common_dimensions_qualifier_namespace_sql, "__QUALIFIER__", "n.")}
96 | from
97 | kubernetes_namespace n
98 | left join default_limit_range r
99 | on n.name = r.namespace;
100 | EOQ
101 | }
102 |
103 | query "namespace_limit_range_default_cpu_request" {
104 | sql = <<-EOQ
105 | with default_limit_range as (
106 | select
107 | namespace,
108 | l -> 'default' as default_limit,
109 | l -> 'defaultRequest' as default_request
110 | from
111 | kubernetes_limit_range,
112 | jsonb_array_elements(spec_limits) as l
113 | )
114 | select
115 | coalesce(n.uid, concat(n.path, ':', n.start_line)) as resource,
116 | case
117 | when default_request ->> 'cpu' is null then 'alarm'
118 | else 'ok'
119 | end as status,
120 | case
121 | when default_request ->> 'cpu' is null then n.name || ' do not have LimitRange default CPU request.'
122 | else n.name || ' has LimitRange default CPU request.'
123 | end as reason
124 | ${replace(local.tag_dimensions_qualifier_sql, "__QUALIFIER__", "n.")}
125 | ${replace(local.common_dimensions_qualifier_namespace_sql, "__QUALIFIER__", "n.")}
126 | from
127 | kubernetes_namespace n
128 | left join default_limit_range r
129 | on n.name = r.namespace;
130 | EOQ
131 | }
132 |
133 | query "namespace_resource_quota_memory_request" {
134 | sql = <<-EOQ
135 | select
136 | distinct(coalesce(n.uid, concat(n.path, ':', n.start_line))) as resource,
137 | case
138 | when q.spec_hard -> 'requests.memory' is null and q.spec_hard -> 'memory' is null then 'alarm'
139 | else 'ok'
140 | end as status,
141 | case
142 | when q.spec_hard -> 'requests.memory' is null and q.spec_hard -> 'memory' is null then n.name || ' do not have ResourceQuota for memory request.'
143 | else n.name || ' have ResourceQuota for memory request.'
144 | end as reason
145 | ${replace(local.tag_dimensions_qualifier_sql, "__QUALIFIER__", "n.")}
146 | ${replace(local.common_dimensions_qualifier_namespace_sql, "__QUALIFIER__", "n.")}
147 | from
148 | kubernetes_namespace n
149 | left join kubernetes_resource_quota q
150 | on n.name = q.namespace;
151 | EOQ
152 | }
153 |
154 | query "namespace_limit_range_default_cpu_limit" {
155 | sql = <<-EOQ
156 | with default_limit_range as (
157 | select
158 | namespace,
159 | l -> 'default' as default_limit,
160 | l -> 'defaultRequest' as default_request
161 | from
162 | kubernetes_limit_range,
163 | jsonb_array_elements(spec_limits) as l
164 | )
165 | select
166 | coalesce(n.uid, concat(n.path, ':', n.start_line)) as resource,
167 | case
168 | when default_limit ->> 'cpu' is null then 'alarm'
169 | else 'ok'
170 | end as status,
171 | case
172 | when default_limit ->> 'cpu' is null then n.name || ' do not have LimitRange default CPU limit.'
173 | else n.name || ' has LimitRange default CPU limit.'
174 | end as reason
175 | ${replace(local.tag_dimensions_qualifier_sql, "__QUALIFIER__", "n.")}
176 | ${replace(local.common_dimensions_qualifier_namespace_sql, "__QUALIFIER__", "n.")}
177 | from
178 | kubernetes_namespace n
179 | left join default_limit_range r
180 | on n.name = r.namespace;
181 | EOQ
182 | }
183 |
184 | query "namespace_resource_quota_cpu_request" {
185 | sql = <<-EOQ
186 | select
187 | distinct(coalesce(n.uid, concat(n.path, ':', n.start_line))) as resource,
188 | case
189 | when q.spec_hard -> 'requests.cpu' is null and q.spec_hard -> 'cpu' is null then 'alarm'
190 | else 'ok'
191 | end as status,
192 | case
193 | when q.spec_hard -> 'requests.cpu' is null and q.spec_hard -> 'cpu' is null then n.name || ' do not have ResourceQuota for CPU request.'
194 | else n.name || ' have ResourceQuota for CPU request.'
195 | end as reason
196 | ${replace(local.tag_dimensions_qualifier_sql, "__QUALIFIER__", "n.")}
197 | ${replace(local.common_dimensions_qualifier_namespace_sql, "__QUALIFIER__", "n.")}
198 | from
199 | kubernetes_namespace n
200 | left join kubernetes_resource_quota q
201 | on n.name = q.namespace;
202 | EOQ
203 | }
204 |
205 |
--------------------------------------------------------------------------------
/query/network_policy.pp:
--------------------------------------------------------------------------------
1 | query "network_policy_default_dont_allow_ingress" {
2 | sql = <<-EOQ
3 | with default_allows_all_ingress_count as (
4 | select
5 | namespace,
6 | name,
7 | uid,
8 | context_name,
9 | _ctx,
10 | tags,
11 | p.path,
12 | p.start_line,
13 | p.end_line,
14 | p.source_type,
15 | -- Get the count of default allow Ingress policy
16 | count(*) filter (where rule = '{}') as num_allow_all_rules
17 | from
18 | kubernetes_network_policy p
19 | left join jsonb_array_elements(ingress) as rule on true
20 | group by
21 | namespace,
22 | name,
23 | uid,
24 | context_name,
25 | rule,
26 | policy_types,
27 | tags,
28 | _ctx,
29 | p.path,
30 | p.start_line,
31 | p.end_line,
32 | p.source_type
33 | )
34 | select
35 | coalesce(uid, concat(p.path, ':', p.start_line)) as resource,
36 | case
37 | when num_allow_all_rules > 0 then 'alarm'
38 | else 'ok'
39 | end as status,
40 | case
41 | when num_allow_all_rules > 0 then name || ' allows all ingress'
42 | else name || ' does not allow all ingress'
43 | end as reason,
44 | name as network_policy_name
45 | ${local.tag_dimensions_sql}
46 | ${local.common_dimensions_sql}
47 | from
48 | default_allows_all_ingress_count p;
49 | EOQ
50 | }
51 |
52 | query "network_policy_default_dont_allow_egress" {
53 | sql = <<-EOQ
54 | with default_allows_all_egress_count as (
55 | select
56 | namespace,
57 | name,
58 | uid,
59 | context_name,
60 | tags,
61 | _ctx,
62 | p.path,
63 | p.start_line,
64 | p.end_line,
65 | p.source_type,
66 | -- Get the count of default allow Egress policy
67 | count(*) filter (where rule = '{}') as num_allow_all_rules
68 | from
69 | kubernetes_network_policy p
70 | left join jsonb_array_elements(egress) as rule on true
71 | group by
72 | namespace,
73 | name,
74 | uid,
75 | context_name,
76 | rule,
77 | policy_types,
78 | tags,
79 | _ctx,
80 | p.path,
81 | p.start_line,
82 | p.end_line,
83 | p.source_type
84 | )
85 | select
86 | coalesce(uid, concat(path, ':', start_line)) as resource,
87 | case
88 | when num_allow_all_rules > 0 then 'alarm'
89 | else 'ok'
90 | end as status,
91 | case
92 | when num_allow_all_rules > 0 then name || ' allows all egress'
93 | else name || ' does not allow all egress'
94 | end as reason,
95 | name as network_policy_name
96 | ${local.tag_dimensions_sql}
97 | ${local.common_dimensions_sql}
98 | from
99 | default_allows_all_egress_count;
100 | EOQ
101 | }
102 |
103 | query "network_policy_default_deny_ingress" {
104 | sql = <<-EOQ
105 | with default_deny_ingress_count as (
106 | select
107 | ns.uid,
108 | ns.name as namespace,
109 | ns.context_name,
110 | count(pol.*) as num_netpol,
111 | ns.tags,
112 | ns._ctx,
113 | ns.path,
114 | ns.start_line,
115 | ns.end_line,
116 | ns.source_type,
117 | -- Get the count of default deny Ingress policy assoicated to each namespace
118 | count(*) filter (where policy_types @> '["Ingress"]' and pod_selector = '{}' and ingress is null) AS num_default_deny
119 | from kubernetes_namespace as ns
120 | left join kubernetes_network_policy as pol on pol.namespace = ns.name and pol.source_type = ns.source_type
121 | group by
122 | ns.name,
123 | ns.uid,
124 | ns.context_name,
125 | ns.tags,
126 | ns._ctx,
127 | ns.path,
128 | ns.start_line,
129 | ns.end_line,
130 | ns.source_type
131 | )
132 | select
133 | coalesce(uid, concat(path, ':', start_line)) as resource,
134 | case
135 | when num_default_deny > 0 then 'ok'
136 | else 'alarm'
137 | end as status,
138 | namespace || ' has ' || num_default_deny || ' default deny ingress policies.' as reason
139 | ${local.tag_dimensions_sql}
140 | ${local.common_dimensions_sql}
141 | from
142 | default_deny_ingress_count;
143 | EOQ
144 | }
145 |
146 | query "network_policy_default_deny_egress" {
147 | sql = <<-EOQ
148 | with default_deny_egress_count as (
149 | select
150 | ns.uid,
151 | ns.name as namespace,
152 | ns.context_name,
153 | ns._ctx,
154 | count(pol.*) as num_netpol,
155 | ns.tags,
156 | ns.path,
157 | ns.start_line,
158 | ns.end_line,
159 | ns.source_type,
160 | -- Get the count of default deny Egress policy assoicated to each namespace
161 | COUNT(*) FILTER (where policy_types @> '["Egress"]' and pod_selector = '{}' and egress is null) AS num_default_deny
162 | from kubernetes_namespace as ns
163 | left join kubernetes_network_policy as pol on pol.namespace = ns.name and pol.source_type = ns.source_type
164 | group by
165 | ns.name,
166 | ns.uid,
167 | ns.context_name,
168 | ns.tags,
169 | ns._ctx,
170 | ns.path,
171 | ns.start_line,
172 | ns.end_line,
173 | ns.source_type
174 | )
175 | select
176 | coalesce(uid, concat(path, ':', start_line)) as resource,
177 | case
178 | when num_default_deny > 0 then 'ok'
179 | else 'alarm'
180 | end as status,
181 | namespace || ' has ' || num_default_deny || ' default deny egress policies.' as reason
182 | ${local.tag_dimensions_sql}
183 | ${local.common_dimensions_sql}
184 | from
185 | default_deny_egress_count;
186 | EOQ
187 | }
188 |
189 |
--------------------------------------------------------------------------------
/query/pod_security_policy.pp:
--------------------------------------------------------------------------------
1 | query "pod_security_policy_host_network_access_disabled" {
2 | sql = <<-EOQ
3 | select
4 | coalesce(uid, concat(path, ':', start_line)) as resource,
5 | case
6 | when host_network then 'alarm'
7 | else 'ok'
8 | end as status,
9 | case
10 | when host_network then 'Pod security policy ' || name || ' pods can use the host network.'
11 | else 'Pod security policy ' || name || ' pods cannot use the host network.'
12 | end as reason
13 | ${local.tag_dimensions_sql}
14 | ${local.common_dimensions_non_namespace_sql}
15 | from
16 | kubernetes_pod_security_policy;
17 | EOQ
18 | }
19 |
20 | query "pod_security_policy_allowed_host_path" {
21 | sql = <<-EOQ
22 | select
23 | coalesce(uid, concat(path, ':', start_line)) as resource,
24 | case
25 | when allowed_host_paths is null then 'alarm'
26 | else 'ok'
27 | end as status,
28 | case
29 | when allowed_host_paths is null then 'Pod security policy ' || name || ' containers can use all host paths.'
30 | else 'Pod security policy ' || name || ' containers using specified host path.'
31 | end as reason
32 | ${local.tag_dimensions_sql}
33 | ${local.common_dimensions_non_namespace_sql}
34 | from
35 | kubernetes_pod_security_policy;
36 | EOQ
37 | }
38 |
39 | query "pod_security_policy_container_privilege_escalation_disabled" {
40 | sql = <<-EOQ
41 | select
42 | coalesce(uid, concat(path, ':', start_line)) as resource,
43 | case
44 | when not allow_privilege_escalation then 'ok'
45 | else 'alarm'
46 | end as status,
47 | case
48 | when not allow_privilege_escalation then 'Pod security policy ' || name || ' pods can not request to allow privilege escalation.'
49 | else 'Pod security policy ' || name || ' pods can request to allow privilege escalation.'
50 | end as reason
51 | ${local.tag_dimensions_sql}
52 | ${local.common_dimensions_non_namespace_sql}
53 | from
54 | kubernetes_pod_security_policy;
55 | EOQ
56 | }
57 |
58 | query "pod_security_policy_non_root_container" {
59 | sql = <<-EOQ
60 | select
61 | coalesce(uid, concat(path, ':', start_line)) as resource,
62 | case
63 | when run_as_user ->> 'rule' = 'MustRunAsNonRoot' then 'ok'
64 | else 'alarm'
65 | end as status,
66 | case
67 | when run_as_user ->> 'rule' = 'MustRunAsNonRoot' then 'Pod security policy ' || name || ' restrict containers to run as non-root user.'
68 | else 'Pod security policy ' || name || ' does not restrict containers to run as non-root user.'
69 | end as reason
70 | ${local.tag_dimensions_sql}
71 | ${local.common_dimensions_non_namespace_sql}
72 | from
73 | kubernetes_pod_security_policy;
74 | EOQ
75 | }
76 |
77 | query "pod_security_policy_hostpid_hostipc_sharing_disabled" {
78 | sql = <<-EOQ
79 | select
80 | coalesce(uid, concat(path, ':', start_line)) as resource,
81 | case
82 | when host_pid or host_ipc then 'alarm'
83 | else 'ok'
84 | end as status,
85 | case
86 | when host_pid then 'Pod security policy ' || name || ' pods can share host PID namespaces.'
87 | when host_ipc then 'Pod security policy ' || name || ' pods can share host IPC namespaces.'
88 | else 'Pod security policy ' || name || ' pods cannot share host process namespaces.'
89 | end as reason
90 | ${local.tag_dimensions_sql}
91 | ${local.common_dimensions_non_namespace_sql}
92 | from
93 | kubernetes_pod_security_policy;
94 | EOQ
95 | }
96 |
97 | query "pod_security_policy_immutable_container_filesystem" {
98 | sql = <<-EOQ
99 | select
100 | coalesce(uid, concat(path, ':', start_line)) as resource,
101 | case
102 | when read_only_root_filesystem then 'ok'
103 | else 'alarm'
104 | end as status,
105 | case
106 | when read_only_root_filesystem then 'Pod security policy ' || name || ' containers running with read-only root file system.'
107 | else 'Pod security policy ' || name || ' containers not running with read-only root file system.'
108 | end as reason
109 | ${local.tag_dimensions_sql}
110 | ${local.common_dimensions_non_namespace_sql}
111 | from
112 | kubernetes_pod_security_policy;
113 | EOQ
114 | }
115 |
116 | query "pod_security_policy_container_privilege_disabled" {
117 | sql = <<-EOQ
118 | select
119 | coalesce(uid, concat(path, ':', start_line)) as resource,
120 | case
121 | when privileged then 'alarm'
122 | else 'ok'
123 | end as status,
124 | case
125 | when privileged then 'Pod security policy ' || name || ' pods can run privileged containers.'
126 | else 'Pod security policy ' || name || ' pods can not run privileged containers.'
127 | end as reason
128 | ${local.tag_dimensions_sql}
129 | ${local.common_dimensions_non_namespace_sql}
130 | from
131 | kubernetes_pod_security_policy;
132 | EOQ
133 | }
134 |
135 | query "pod_security_policy_hostipc_sharing_disabled" {
136 | sql = <<-EOQ
137 | select
138 | coalesce(uid, concat(path, ':', start_line)) as resource,
139 | case
140 | when host_ipc then 'alarm'
141 | else 'ok'
142 | end as status,
143 | case
144 | when host_ipc then 'Pod security policy ' || name || ' pods can share host IPC namespaces.'
145 | else 'Pod security policy ' || name || ' pods cannot share host IPC namespaces.'
146 | end as reason
147 | ${local.tag_dimensions_sql}
148 | ${local.common_dimensions_non_namespace_sql}
149 | from
150 | kubernetes_pod_security_policy;
151 | EOQ
152 | }
153 |
154 | query "pod_security_policy_hostpid_sharing_disabled" {
155 | sql = <<-EOQ
156 | select
157 | coalesce(uid, concat(path, ':', start_line)) as resource,
158 | case
159 | when host_pid then 'alarm'
160 | else 'ok'
161 | end as status,
162 | case
163 | when host_pid then 'Pod security policy ' || name || ' pods can share host PID namespaces.'
164 | else 'Pod security policy ' || name || ' pods cannot share host PID namespaces.'
165 | end as reason
166 | ${local.tag_dimensions_sql}
167 | ${local.common_dimensions_non_namespace_sql}
168 | from
169 | kubernetes_pod_security_policy;
170 | EOQ
171 | }
172 |
173 | query "pod_security_policy_security_services_hardening" {
174 | sql = <<-EOQ
175 | select
176 | coalesce(uid, concat(path, ':', start_line)) as resource,
177 | case
178 | when se_linux -> 'rule' = '"MustRunAs"' then 'ok'
179 | when annotations -> 'apparmor.security.beta.kubernetes.io/defaultProfileName' = '"runtime/default"' then 'ok'
180 | when annotations -> 'seccomp.security.alpha.kubernetes.io/defaultProfileName' = '"runtime/default"' then 'ok'
181 | else 'alarm'
182 | end as status,
183 | case
184 | when se_linux -> 'rule' = '"MustRunAs"' then 'Applications using SELinux security service.'
185 | when annotations -> 'apparmor.security.beta.kubernetes.io/defaultProfileName' = '"runtime/default"' then 'Pod security policy ' || name || ' using AppArmor security service.'
186 | when annotations -> 'seccomp.security.alpha.kubernetes.io/defaultProfileName' = '"runtime/default"' then 'Pod security policy ' || name || ' using Seccomp security service.'
187 | else 'Pod security policy ' || name || ' not using securty services.'
188 | end as reason
189 | ${local.tag_dimensions_sql}
190 | ${local.common_dimensions_non_namespace_sql}
191 | from
192 | kubernetes_pod_security_policy;
193 | EOQ
194 | }
195 |
196 | query "pod_security_policy_default_seccomp_profile_enabled" {
197 | sql = <<-EOQ
198 | select
199 | coalesce(uid, concat(path, ':', start_line)) as resource,
200 | case
201 | when annotations -> 'seccomp.security.alpha.kubernetes.io/defaultProfileName' = '"docker/default"' then 'ok'
202 | else 'alarm'
203 | end as status,
204 | case
205 | when annotations -> 'seccomp.security.alpha.kubernetes.io/defaultProfileName' = '"docker/default"' then name || ' seccompProfile enabled.'
206 | else name || ' seccompProfile disabled.'
207 | end as reason
208 | ${local.tag_dimensions_sql}
209 | ${local.common_dimensions_non_namespace_sql}
210 | from
211 | kubernetes_pod_security_policy;
212 | EOQ
213 | }
214 |
--------------------------------------------------------------------------------
/query/role.pp:
--------------------------------------------------------------------------------
1 | query "role_default_namespace_used" {
2 | sql = <<-EOQ
3 | select
4 | coalesce(uid, concat(path, ':', start_line)) as resource,
5 | case
6 | when namespace = 'default' then 'alarm'
7 | else 'ok'
8 | end as status,
9 | case
10 | when namespace = 'default' then name || ' uses default namespace.'
11 | else name || ' not using the default namespace.'
12 | end as reason,
13 | name as role_name
14 | ${local.tag_dimensions_sql}
15 | ${local.common_dimensions_sql}
16 | from
17 | kubernetes_role;
18 | EOQ
19 | }
20 |
21 | query "role_with_wildcards_used" {
22 | sql = <<-EOQ
23 | select
24 | coalesce(uid, concat(path, ':', start_line)) as resource,
25 | case
26 | when rule ->> 'apiGroups' like '%*%'
27 | or rule ->> 'resources' like '%*%'
28 | or rule ->> 'verbs' like '%*%' then 'alarm'
29 | else 'ok'
30 | end as status,
31 | case
32 | when rule ->> 'apiGroups' like '%*%' then name || ' api groups use wildcards.'
33 | when rule ->> 'resources' like '%*%' then name || ' resources use wildcards.'
34 | when rule ->> 'verbs' like '%*%' then name || ' actions use wildcards.'
35 | else name || ' uses no wildcard.'
36 | end as reason,
37 | name as role_name
38 | ${local.tag_dimensions_sql}
39 | ${local.common_dimensions_non_namespace_sql}
40 | from
41 | kubernetes_cluster_role,
42 | jsonb_array_elements(rules) rule
43 | where
44 | name not like '%system%'
45 | group by
46 | uid,
47 | status,
48 | reason,
49 | role_name,
50 | path,
51 | start_line,
52 | end_line,
53 | source_type,
54 | context_name,
55 | tags,
56 | _ctx;
57 | EOQ
58 | }
59 |
60 | query "role_with_rbac_escalate_permissions" {
61 | sql = <<-EOQ
62 | with role_with_escalate as (
63 | select
64 | uid,
65 | count(*) as num
66 | from
67 | kubernetes_cluster_role,
68 | jsonb_array_elements(rules) rule
69 | where
70 | rule -> 'apiGroups' @> '["rbac.authorization.k8s.io"]'
71 | and (
72 | rule -> 'resources' @> '["roles"]'
73 | or rule -> 'resources' @> '["clusterroles"]'
74 | )
75 | and rule -> 'verbs' @> '["escalate"]'
76 | group by
77 | uid
78 | union
79 | select
80 | uid,
81 | count(*) as num
82 | from
83 | kubernetes_role,
84 | jsonb_array_elements(rules) rule
85 | where
86 | rule -> 'apiGroups' @> '["rbac.authorization.k8s.io"]'
87 | and (
88 | rule -> 'resources' @> '["roles"]'
89 | or rule -> 'resources' @> '["clusterroles"]'
90 | )
91 | and rule -> 'verbs' @> '["escalate"]'
92 | group by
93 | uid
94 | ), union_role_and_cluster_role as (
95 | select
96 | uid,
97 | path,
98 | name,
99 | start_line,
100 | end_line,
101 | source_type,
102 | context_name,
103 | tags,
104 | _ctx
105 | from
106 | kubernetes_role
107 | union
108 | select
109 | uid,
110 | path,
111 | name,
112 | start_line,
113 | end_line,
114 | source_type,
115 | context_name,
116 | tags,
117 | _ctx
118 | from
119 | kubernetes_cluster_role
120 | )
121 | select
122 | coalesce(r.uid, concat(r.path, ':', r.start_line)) as resource,
123 | case
124 | when e.num > 0 then 'alarm'
125 | else 'ok'
126 | end as status,
127 | case
128 | when e.num > 0 then name || ' contains ' || e.num || ' RBAC escalate permissions.'
129 | else name || ' does not contain any RBAC escalate permissions.'
130 | end as reason,
131 | name as role_name
132 | ${local.tag_dimensions_sql}
133 | ${local.common_dimensions_non_namespace_sql}
134 | from
135 | union_role_and_cluster_role as r
136 | left join role_with_escalate as e on e.uid = r.uid
137 | EOQ
138 | }
139 |
140 | query "role_with_bind_cluster_role_bindings" {
141 | sql = <<-EOQ
142 | with role_with_escalate as (
143 | select
144 | uid,
145 | count(*) as num
146 | from
147 | kubernetes_cluster_role,
148 | jsonb_array_elements(rules) rule
149 | where
150 | rule -> 'apiGroups' @> '["rbac.authorization.k8s.io"]'
151 | and (
152 | rule -> 'resources' @> '["rolebindings"]'
153 | or rule -> 'resources' @> '["clusterrolebindings"]'
154 | )
155 | and rule -> 'verbs' @> '["bind"]'
156 | group by
157 | uid
158 | union
159 | select
160 | uid,
161 | count(*) as num
162 | from
163 | kubernetes_role,
164 | jsonb_array_elements(rules) rule
165 | where
166 | rule -> 'apiGroups' @> '["rbac.authorization.k8s.io"]'
167 | and (
168 | rule -> 'resources' @> '["rolebindings"]'
169 | or rule -> 'resources' @> '["clusterrolebindings"]'
170 | )
171 | and rule -> 'verbs' @> '["bind"]'
172 | group by
173 | uid
174 | ), union_role_and_cluster_role as (
175 | select
176 | uid,
177 | path,
178 | name,
179 | start_line,
180 | end_line,
181 | source_type,
182 | context_name,
183 | tags,
184 | _ctx
185 | from
186 | kubernetes_role
187 | union
188 | select
189 | uid,
190 | path,
191 | name,
192 | start_line,
193 | end_line,
194 | source_type,
195 | context_name,
196 | tags,
197 | _ctx
198 | from
199 | kubernetes_cluster_role
200 | )
201 | select
202 | coalesce(r.uid, concat(r.path, ':', r.start_line)) as resource,
203 | case
204 | when e.num > 0 then 'alarm'
205 | else 'ok'
206 | end as status,
207 | case
208 | when e.num > 0 then name || ' contains ' || e.num || ' RBAC bind role bindings or cluster role bindings permissions.'
209 | else name || ' does not contain any RBAC bind role bindings or cluster role bindings permissions.'
210 | end as reason,
211 | name as role_name
212 | ${local.tag_dimensions_sql}
213 | ${local.common_dimensions_non_namespace_sql}
214 | from
215 | union_role_and_cluster_role as r
216 | left join role_with_escalate as e on e.uid = r.uid;
217 | EOQ
218 | }
219 |
220 | query "cluster_role_with_validating_or_mutating_admission_webhook_configurations" {
221 | sql = <<-EOQ
222 | with role_with_escalate as (
223 | select
224 | uid,
225 | count(*) as num
226 | from
227 | kubernetes_cluster_role,
228 | jsonb_array_elements(rules) rule
229 | where
230 | rule -> 'apiGroups' @> '["admissionregistration.k8s.io"]'
231 | and (
232 | rule -> 'resources' @> '["mutatingwebhookconfigurations"]'
233 | or rule -> 'resources' @> '["validatingwebhookconfigurations"]'
234 | )
235 | and rule -> 'verbs' @> '["create", "update", "patch"]'
236 | group by
237 | uid
238 | )
239 | select
240 | coalesce(r.uid, concat(r.path, ':', r.start_line)) as resource,
241 | case
242 | when e.num > 0 then 'alarm'
243 | else 'ok'
244 | end as status,
245 | case
246 | when e.num > 0 then name || ' contains ' || e.num || ' RBAC cluster role validating or mutating admission webhook configurations permissions.'
247 | else name || ' does not contain any bind role bindings or cluster role validating or mutating admission webhook configurations permissions.'
248 | end as reason,
249 | name as role_name
250 | ${local.tag_dimensions_sql}
251 | ${local.common_dimensions_non_namespace_sql}
252 | from
253 | kubernetes_cluster_role as r
254 | left join role_with_escalate as e on e.uid = r.uid;
255 | EOQ
256 | }
257 |
258 | query "role_with_rbac_approve_certificate_signing_requests" {
259 | sql = <<-EOQ
260 | with role_with_escalate as (
261 | select
262 | uid,
263 | count(*) as num
264 | from
265 | kubernetes_cluster_role,
266 | jsonb_array_elements(rules) rule
267 | where
268 | rule -> 'apiGroups' @> '["certificates.k8s.io"]'
269 | and
270 | ((rule -> 'resources' @> '["certificatesigningrequests/approval"]' and rule -> 'verbs' @> '["update", "patch"]')
271 | or (rule -> 'resources' @> '["signers"]' and rule -> 'verbs' @> '["approve"]'))
272 | group by
273 | uid
274 | )
275 | select
276 | coalesce(r.uid, concat(r.path, ':', r.start_line)) as resource,
277 | case
278 | when e.num > 0 then 'alarm'
279 | else 'ok'
280 | end as status,
281 | case
282 | when e.num > 0 then name || ' contains ' || e.num || ' RBAC cluster role grant permissions to approve CertificateSigningRequests.'
283 | else name || ' does not contains any cluster role granting permissions to approve CertificateSigningRequests.'
284 | end as reason,
285 | name as role_name
286 | ${local.tag_dimensions_sql}
287 | ${local.common_dimensions_non_namespace_sql}
288 | from
289 | kubernetes_cluster_role as r
290 | left join role_with_escalate as e on e.uid = r.uid;
291 | EOQ
292 | }
--------------------------------------------------------------------------------
/query/role_binding.pp:
--------------------------------------------------------------------------------
1 | query "role_binding_default_namespace_used" {
2 | sql = <<-EOQ
3 | select
4 | coalesce(uid, concat(path, ':', start_line)) as resource,
5 | case
6 | when namespace = 'default' then 'alarm'
7 | else 'ok'
8 | end as status,
9 | case
10 | when namespace = 'default' then name || ' uses default namespace.'
11 | else name || ' not using the default namespace.'
12 | end as reason,
13 | name as role_binding_name
14 | ${local.tag_dimensions_sql}
15 | ${local.common_dimensions_sql}
16 | from
17 | kubernetes_role_binding;
18 | EOQ
19 | }
20 |
21 | query "role_binding_default_service_account_binding_not_active" {
22 | sql = <<-EOQ
23 | select
24 | coalesce(uid, concat(path, ':', start_line)) as resource,
25 | case
26 | when (subject ->> 'kind') = 'ServiceAccount' and (subject ->> 'name') = 'default' then 'alarm'
27 | else 'ok'
28 | end as status,
29 | case
30 | when (subject ->> 'kind' = 'ServiceAccount') and (subject ->> 'name' = 'default') then name || ' default service accounts active.'
31 | else name || ' default service accounts not active.'
32 | end as reason,
33 | name as role_binding_name
34 | ${local.tag_dimensions_sql}
35 | ${local.common_dimensions_sql}
36 | from
37 | kubernetes_role_binding,
38 | jsonb_array_elements(subjects) as subject;
39 | EOQ
40 | }
41 |
--------------------------------------------------------------------------------
/query/secret.pp:
--------------------------------------------------------------------------------
1 | query "secret_default_namespace_used" {
2 | sql = <<-EOQ
3 | select
4 | coalesce(uid, concat(path, ':', start_line)) as resource,
5 | case
6 | when namespace = 'default' then 'alarm'
7 | else 'ok'
8 | end as status,
9 | case
10 | when namespace = 'default' then name || ' uses default namespace.'
11 | else name || ' not using the default namespace.'
12 | end as reason,
13 | name as secret_name
14 | ${local.tag_dimensions_sql}
15 | ${local.common_dimensions_sql}
16 | from
17 | kubernetes_secret;
18 | EOQ
19 | }
20 |
21 |
--------------------------------------------------------------------------------
/query/service.pp:
--------------------------------------------------------------------------------
1 | query "service_default_namespace_used" {
2 | sql = <<-EOQ
3 | select
4 | coalesce(uid, concat(path, ':', start_line)) as resource,
5 | case
6 | when namespace = 'default' then 'alarm'
7 | else 'ok'
8 | end as status,
9 | case
10 | when namespace = 'default' then name || ' uses default namespace.'
11 | else name || ' not using the default namespace.'
12 | end as reason
13 | ${local.tag_dimensions_sql}
14 | ${local.common_dimensions_sql}
15 | from
16 | kubernetes_service;
17 | EOQ
18 | }
19 |
20 | query "service_type_forbidden" {
21 | sql = <<-EOQ
22 | select
23 | coalesce(uid, concat(path, ':', start_line)) as resource,
24 | case
25 | when type in ('NodePort','LoadBalancer') then 'alarm'
26 | else 'ok'
27 | end as status,
28 | case
29 | when type in ('NodePort','LoadBalancer') then 'Containers using ' || name || ' service exposed through ' || type || ' service type.'
30 | else 'Containers using ' || name || ' service not exposed through a forbidden service type.'
31 | end as reason
32 | ${local.tag_dimensions_sql}
33 | ${local.common_dimensions_sql}
34 | from
35 | kubernetes_service;
36 | EOQ
37 | }
38 |
39 | query "service_no_tiller_service" {
40 | sql = <<-EOQ
41 | with tiller_service as (
42 | select
43 | distinct uid
44 | from
45 | kubernetes_service
46 | where
47 | (select 'tiller' ilike any (select jsonb_object_keys(tags)::text))
48 | or (select 'tiller' ilike any (select jsonb_object_keys(selector)::text))
49 | )
50 | select
51 | coalesce(s.uid, concat(s.path, ':', s.start_line)) as resource,
52 | case
53 | when t.uid is not null then 'alarm'
54 | else 'ok'
55 | end as status,
56 | case
57 | when t.uid is not null then name || ' using tiller service.'
58 | else name || ' not using tiller service.'
59 | end as reason
60 | ${local.tag_dimensions_sql}
61 | ${local.common_dimensions_sql}
62 | from
63 | kubernetes_service as s
64 | left join tiller_service as t on t.uid = s.uid;
65 | EOQ
66 | }
67 |
68 | query "service_no_tiller_deployed" {
69 | sql = <<-EOQ
70 | select
71 | coalesce(uid, concat(path, ':', start_line)) as resource,
72 | name,
73 | case
74 | when labels ->> 'app' = 'helm' or labels ->> 'name' = 'tiller' then 'alarm'
75 | else 'ok'
76 | end as status,
77 | case
78 | when labels ->> 'app' = 'helm' or labels ->> 'name' = 'tiller' then name || ' has tiller deployed.'
79 | else name || ' does not have tiller deployed.'
80 | end as reason
81 | ${local.tag_dimensions_sql}
82 | ${local.common_dimensions_sql}
83 | from
84 | kubernetes_service;
85 | EOQ
86 | }
--------------------------------------------------------------------------------
/query/service_account.pp:
--------------------------------------------------------------------------------
1 | query "service_account_token_disabled" {
2 | sql = <<-EOQ
3 | select
4 | coalesce(uid, concat(path, ':', start_line)) as resource,
5 | case
6 | when automount_service_account_token then 'alarm'
7 | else 'ok'
8 | end as status,
9 | case
10 | when automount_service_account_token then name || ' service account token will be automatically mounted.'
11 | else name || ' service account token will not be automatically mounted.'
12 | end as reason,
13 | name as service_account_name
14 | ${local.tag_dimensions_sql}
15 | ${local.common_dimensions_sql}
16 | from
17 | kubernetes_service_account;
18 | EOQ
19 | }
20 |
21 | query "service_account_default_namespace_used" {
22 | sql = <<-EOQ
23 | select
24 | coalesce(uid, concat(path, ':', start_line)) as resource,
25 | case
26 | when namespace = 'default' then 'alarm'
27 | else 'ok'
28 | end as status,
29 | case
30 | when namespace = 'default' then name || ' uses default namespace.'
31 | else name || ' not using the default namespace.'
32 | end as reason,
33 | name as service_account_name
34 | ${local.tag_dimensions_sql}
35 | ${local.common_dimensions_sql}
36 | from
37 | kubernetes_service_account;
38 | EOQ
39 | }
40 |
41 |
--------------------------------------------------------------------------------
/variables.pp:
--------------------------------------------------------------------------------
1 | // Benchmarks and controls for specific services should override the "service" tag
2 | locals {
3 | kubernetes_compliance_common_tags = {
4 | category = "Compliance"
5 | plugin = "kubernetes"
6 | service = "Kubernetes"
7 | }
8 | }
9 |
10 | variable "common_dimensions" {
11 | type = list(string)
12 | description = "A list of common dimensions to add to each control."
13 | # Define which common dimensions should be added to each control.
14 | # - connection_name (_ctx ->> 'connection_name')
15 | # - context_name
16 | # - namespace
17 | # - path
18 | # - source_type
19 | default = ["context_name", "namespace", "path", "source_type"]
20 | }
21 |
22 | variable "tag_dimensions" {
23 | type = list(string)
24 | description = "A list of tags to add as dimensions to each control."
25 | # A list of tag names to include as dimensions for resources that support
26 | # tags (e.g. "Owner", "Environment"). Default to empty since tag names are
27 | # a personal choice - for commonly used tag names see
28 | # https://kubernetes.io/docs/concepts/overview/working-with-objects/common-labels/
29 | default = []
30 | }
31 |
32 | locals {
33 |
34 | # Local internal variable to build the SQL select clause for common
35 | # dimensions using a table name qualifier if required. Do not edit directly.
36 | common_dimensions_qualifier_sql = <<-EOQ
37 | %{~if contains(var.common_dimensions, "connection_name")}, __QUALIFIER___ctx ->> 'connection_name' as connection_name%{endif~}
38 | %{~if contains(var.common_dimensions, "context_name")}, coalesce(__QUALIFIER__context_name, '') as context_name%{endif~}
39 | %{~if contains(var.common_dimensions, "namespace")}, __QUALIFIER__namespace%{endif~}
40 | %{~if contains(var.common_dimensions, "source_type")}, __QUALIFIER__source_type%{endif~}
41 | %{~if contains(var.common_dimensions, "path")}, coalesce(__QUALIFIER__path || ':' || __QUALIFIER__start_line || '-' || __QUALIFIER__end_line, '') as path%{endif~}
42 | EOQ
43 |
44 | common_dimensions_qualifier_namespace_sql = <<-EOQ
45 | %{~if contains(var.common_dimensions, "connection_name")}, __QUALIFIER___ctx ->> 'connection_name' as connection_name%{endif~}
46 | %{~if contains(var.common_dimensions, "context_name")}, coalesce(__QUALIFIER__context_name, '') as context_name%{endif~}
47 | %{~if contains(var.common_dimensions, "namespace")}, __QUALIFIER__name%{endif~}
48 | %{~if contains(var.common_dimensions, "source_type")}, __QUALIFIER__source_type%{endif~}
49 | %{~if contains(var.common_dimensions, "path")}, coalesce(__QUALIFIER__path || ':' || __QUALIFIER__start_line || '-' || __QUALIFIER__end_line, '') as path%{endif~}
50 | EOQ
51 |
52 | common_dimensions_non_namespace_qualifier_sql = <<-EOQ
53 | %{~if contains(var.common_dimensions, "connection_name")}, __QUALIFIER___ctx ->> 'connection_name' as connection_name%{endif~}
54 | %{~if contains(var.common_dimensions, "context_name")}, coalesce(__QUALIFIER__context_name, '') as context_name%{endif~}
55 | %{~if contains(var.common_dimensions, "source_type")}, __QUALIFIER__source_type%{endif~}
56 | %{~if contains(var.common_dimensions, "path")}, coalesce(__QUALIFIER__path || ':' || __QUALIFIER__start_line || '-' || __QUALIFIER__end_line, '') as path%{endif~}
57 | EOQ
58 |
59 | # Local internal variable to build the SQL select clause for tag
60 | # dimensions. Do not edit directly.
61 | tag_dimensions_qualifier_sql = <<-EOQ
62 | %{~for dim in var.tag_dimensions}, __QUALIFIER__tags ->> '${dim}' as "${replace(dim, "\"", "\"\"")}"%{endfor~}
63 | EOQ
64 | }
65 |
66 | locals {
67 |
68 | # Local internal variable with the full SQL select clause for common
69 | # dimensions. Do not edit directly.
70 | common_dimensions_sql = replace(local.common_dimensions_qualifier_sql, "__QUALIFIER__", "")
71 | common_dimensions_namespace_sql = replace(local.common_dimensions_qualifier_namespace_sql, "__QUALIFIER__", "")
72 | common_dimensions_non_namespace_sql = replace(local.common_dimensions_non_namespace_qualifier_sql, "__QUALIFIER__", "")
73 | tag_dimensions_sql = replace(local.tag_dimensions_qualifier_sql, "__QUALIFIER__", "")
74 | }
75 |
--------------------------------------------------------------------------------