From 953733fd7e4505d6760d29f57ea47ba9881e421f Mon Sep 17 00:00:00 2001 From: shimonp21 Date: Thu, 6 Oct 2022 10:32:24 +0300 Subject: [PATCH] feat: convert policies to v1 - fixed many issues of duplicate rows. Each resources tested must have a single line in the output (but if our SELECT query joins with subtables, each resource may have many rows... ). - removed endpoint_api_serve_on_secure_port.. The check tested that the k8s-api was served on port 6443 or 443. But obviously the port number has very little to do with security. NSA-Cisa [page 18], of course, doesn't specify that these must be the port numbers. e.g. minikube uses port 8443 instead of 6443. The check also tested the port 'name', but that of course also doesn't necesarrily indicate the actual protocol used... - fixed `default_deny_ingress` and `default_deny_egress` policies to actually work (they always returned fail until now). Also deleted `default_dont_allow_ingress` and `default_dont_deny_egress`, since they seem to be duplicates of the `deny` policy? https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF --- plugins/source/k8s/policies/README.md | 4 + plugins/source/k8s/policies_v1/README.md | 33 ++++ .../policies_v1/create_k8s_policy_results.sql | 12 ++ .../k8s/policies_v1/nsa_cisa_v1/README.md | 0 .../nsa_cisa_v1/network_hardening.sql | 132 +++++++++++++++ .../policies_v1/nsa_cisa_v1/pod_security.sql | 152 ++++++++++++++++++ .../k8s/policies_v1/nsa_cisa_v1/policy.sql | 15 ++ plugins/source/k8s/policies_v1/policy.sql | 11 ++ .../network_hardening/daemonset_cpu_limit.sql | 25 +++ .../daemonset_cpu_request.sql | 24 +++ .../daemonset_memory_limit.sql | 24 +++ .../daemonset_memory_request.sql | 24 +++ .../deployment_cpu_limit.sql | 24 +++ .../deployment_cpu_request.sql | 24 +++ .../deployment_memory_limit.sql | 25 +++ .../deployment_memory_request.sql | 24 +++ .../network_hardening/job_cpu_limit.sql | 22 +++ .../network_hardening/job_cpu_request.sql | 22 +++ .../network_hardening/job_memory_limit.sql | 22 +++ .../network_hardening/job_memory_request.sql | 22 +++ ...amespace_limit_range_default_cpu_limit.sql | 24 +++ ...espace_limit_range_default_cpu_request.sql | 24 +++ ...space_limit_range_default_memory_limit.sql | 24 +++ ...ace_limit_range_default_memory_request.sql | 26 +++ .../namespace_resource_quota_cpu_limit.sql | 20 +++ .../namespace_resource_quota_cpu_request.sql | 20 +++ .../namespace_resource_quota_memory_limit.sql | 20 +++ ...amespace_resource_quota_memory_request.sql | 20 +++ .../network_policy_default_deny_egress.sql | 23 +++ .../network_policy_default_deny_ingress.sql | 23 +++ .../replicaset_cpu_limit.sql | 24 +++ .../replicaset_cpu_request.sql | 24 +++ .../replicaset_memory_limit.sql | 24 +++ .../replicaset_memory_request.sql | 24 +++ ...daemonset_container_privilege_disabled.sql | 21 +++ ...ontainer_privilege_escalation_disabled.sql | 21 +++ ...daemonset_host_network_access_disabled.sql | 17 ++ ...onset_hostpid_hostipc_sharing_disabled.sql | 18 +++ ...emonset_immutable_container_filesystem.sql | 22 +++ .../daemonset_non_root_container.sql | 21 +++ ...eployment_container_privilege_disabled.sql | 21 +++ ...ontainer_privilege_escalation_disabled.sql | 25 +++ ...eployment_host_network_access_disabled.sql | 17 ++ ...yment_hostpid_hostipc_sharing_disabled.sql | 18 +++ ...loyment_immutable_container_filesystem.sql | 22 +++ .../deployment_non_root_container.sql | 21 +++ .../job_container_privilege_disabled.sql | 23 +++ ...ontainer_privilege_escalation_disabled.sql | 22 +++ .../job_host_network_access_disabled.sql | 17 ++ .../job_hostpid_hostipc_sharing_disabled.sql | 18 +++ .../job_immutable_container_filesystem.sql | 22 +++ .../pod_security/job_non_root_container.sql | 22 +++ .../pod_container_privilege_disabled.sql | 22 +++ ...ontainer_privilege_escalation_disabled.sql | 21 +++ .../pod_host_network_access_disabled.sql | 17 ++ .../pod_hostpid_hostipc_sharing_disabled.sql | 17 ++ .../pod_immutable_container_filesystem.sql | 21 +++ .../pod_security/pod_non_root_container.sql | 21 +++ .../pod_service_account_token_disabled.sql | 17 ++ .../pod_security/pod_volume_host_path.sql | 21 +++ ...eplicaset_container_privilege_disabled.sql | 22 +++ ...ontainer_privilege_escalation_disabled.sql | 21 +++ ...eplicaset_host_network_access_disabled.sql | 17 ++ ...caset_hostpid_hostipc_sharing_disabled.sql | 18 +++ ...licaset_immutable_container_filesystem.sql | 22 +++ .../replicaset_non_root_container.sql | 22 +++ .../service_account_token_disabled.sql | 17 ++ 67 files changed, 1625 insertions(+) create mode 100644 plugins/source/k8s/policies_v1/README.md create mode 100644 plugins/source/k8s/policies_v1/create_k8s_policy_results.sql create mode 100644 plugins/source/k8s/policies_v1/nsa_cisa_v1/README.md create mode 100644 plugins/source/k8s/policies_v1/nsa_cisa_v1/network_hardening.sql create mode 100644 plugins/source/k8s/policies_v1/nsa_cisa_v1/pod_security.sql create mode 100644 plugins/source/k8s/policies_v1/nsa_cisa_v1/policy.sql create mode 100644 plugins/source/k8s/policies_v1/policy.sql create mode 100644 plugins/source/k8s/policies_v1/queries/network_hardening/daemonset_cpu_limit.sql create mode 100644 plugins/source/k8s/policies_v1/queries/network_hardening/daemonset_cpu_request.sql create mode 100644 plugins/source/k8s/policies_v1/queries/network_hardening/daemonset_memory_limit.sql create mode 100644 plugins/source/k8s/policies_v1/queries/network_hardening/daemonset_memory_request.sql create mode 100644 plugins/source/k8s/policies_v1/queries/network_hardening/deployment_cpu_limit.sql create mode 100644 plugins/source/k8s/policies_v1/queries/network_hardening/deployment_cpu_request.sql create mode 100644 plugins/source/k8s/policies_v1/queries/network_hardening/deployment_memory_limit.sql create mode 100644 plugins/source/k8s/policies_v1/queries/network_hardening/deployment_memory_request.sql create mode 100644 plugins/source/k8s/policies_v1/queries/network_hardening/job_cpu_limit.sql create mode 100644 plugins/source/k8s/policies_v1/queries/network_hardening/job_cpu_request.sql create mode 100644 plugins/source/k8s/policies_v1/queries/network_hardening/job_memory_limit.sql create mode 100644 plugins/source/k8s/policies_v1/queries/network_hardening/job_memory_request.sql create mode 100644 plugins/source/k8s/policies_v1/queries/network_hardening/namespace_limit_range_default_cpu_limit.sql create mode 100644 plugins/source/k8s/policies_v1/queries/network_hardening/namespace_limit_range_default_cpu_request.sql create mode 100644 plugins/source/k8s/policies_v1/queries/network_hardening/namespace_limit_range_default_memory_limit.sql create mode 100644 plugins/source/k8s/policies_v1/queries/network_hardening/namespace_limit_range_default_memory_request.sql create mode 100644 plugins/source/k8s/policies_v1/queries/network_hardening/namespace_resource_quota_cpu_limit.sql create mode 100644 plugins/source/k8s/policies_v1/queries/network_hardening/namespace_resource_quota_cpu_request.sql create mode 100644 plugins/source/k8s/policies_v1/queries/network_hardening/namespace_resource_quota_memory_limit.sql create mode 100644 plugins/source/k8s/policies_v1/queries/network_hardening/namespace_resource_quota_memory_request.sql create mode 100644 plugins/source/k8s/policies_v1/queries/network_hardening/network_policy_default_deny_egress.sql create mode 100644 plugins/source/k8s/policies_v1/queries/network_hardening/network_policy_default_deny_ingress.sql create mode 100644 plugins/source/k8s/policies_v1/queries/network_hardening/replicaset_cpu_limit.sql create mode 100644 plugins/source/k8s/policies_v1/queries/network_hardening/replicaset_cpu_request.sql create mode 100644 plugins/source/k8s/policies_v1/queries/network_hardening/replicaset_memory_limit.sql create mode 100644 plugins/source/k8s/policies_v1/queries/network_hardening/replicaset_memory_request.sql create mode 100644 plugins/source/k8s/policies_v1/queries/pod_security/daemonset_container_privilege_disabled.sql create mode 100644 plugins/source/k8s/policies_v1/queries/pod_security/daemonset_container_privilege_escalation_disabled.sql create mode 100644 plugins/source/k8s/policies_v1/queries/pod_security/daemonset_host_network_access_disabled.sql create mode 100644 plugins/source/k8s/policies_v1/queries/pod_security/daemonset_hostpid_hostipc_sharing_disabled.sql create mode 100644 plugins/source/k8s/policies_v1/queries/pod_security/daemonset_immutable_container_filesystem.sql create mode 100644 plugins/source/k8s/policies_v1/queries/pod_security/daemonset_non_root_container.sql create mode 100644 plugins/source/k8s/policies_v1/queries/pod_security/deployment_container_privilege_disabled.sql create mode 100644 plugins/source/k8s/policies_v1/queries/pod_security/deployment_container_privilege_escalation_disabled.sql create mode 100644 plugins/source/k8s/policies_v1/queries/pod_security/deployment_host_network_access_disabled.sql create mode 100644 plugins/source/k8s/policies_v1/queries/pod_security/deployment_hostpid_hostipc_sharing_disabled.sql create mode 100644 plugins/source/k8s/policies_v1/queries/pod_security/deployment_immutable_container_filesystem.sql create mode 100644 plugins/source/k8s/policies_v1/queries/pod_security/deployment_non_root_container.sql create mode 100644 plugins/source/k8s/policies_v1/queries/pod_security/job_container_privilege_disabled.sql create mode 100644 plugins/source/k8s/policies_v1/queries/pod_security/job_container_privilege_escalation_disabled.sql create mode 100644 plugins/source/k8s/policies_v1/queries/pod_security/job_host_network_access_disabled.sql create mode 100644 plugins/source/k8s/policies_v1/queries/pod_security/job_hostpid_hostipc_sharing_disabled.sql create mode 100644 plugins/source/k8s/policies_v1/queries/pod_security/job_immutable_container_filesystem.sql create mode 100644 plugins/source/k8s/policies_v1/queries/pod_security/job_non_root_container.sql create mode 100644 plugins/source/k8s/policies_v1/queries/pod_security/pod_container_privilege_disabled.sql create mode 100644 plugins/source/k8s/policies_v1/queries/pod_security/pod_container_privilege_escalation_disabled.sql create mode 100644 plugins/source/k8s/policies_v1/queries/pod_security/pod_host_network_access_disabled.sql create mode 100644 plugins/source/k8s/policies_v1/queries/pod_security/pod_hostpid_hostipc_sharing_disabled.sql create mode 100644 plugins/source/k8s/policies_v1/queries/pod_security/pod_immutable_container_filesystem.sql create mode 100644 plugins/source/k8s/policies_v1/queries/pod_security/pod_non_root_container.sql create mode 100644 plugins/source/k8s/policies_v1/queries/pod_security/pod_service_account_token_disabled.sql create mode 100644 plugins/source/k8s/policies_v1/queries/pod_security/pod_volume_host_path.sql create mode 100644 plugins/source/k8s/policies_v1/queries/pod_security/replicaset_container_privilege_disabled.sql create mode 100644 plugins/source/k8s/policies_v1/queries/pod_security/replicaset_container_privilege_escalation_disabled.sql create mode 100644 plugins/source/k8s/policies_v1/queries/pod_security/replicaset_host_network_access_disabled.sql create mode 100644 plugins/source/k8s/policies_v1/queries/pod_security/replicaset_hostpid_hostipc_sharing_disabled.sql create mode 100644 plugins/source/k8s/policies_v1/queries/pod_security/replicaset_immutable_container_filesystem.sql create mode 100644 plugins/source/k8s/policies_v1/queries/pod_security/replicaset_non_root_container.sql create mode 100644 plugins/source/k8s/policies_v1/queries/pod_security/service_account_token_disabled.sql diff --git a/plugins/source/k8s/policies/README.md b/plugins/source/k8s/policies/README.md index 88d9becc4c4f08..d3e24f16c9f849 100644 --- a/plugins/source/k8s/policies/README.md +++ b/plugins/source/k8s/policies/README.md @@ -1,3 +1,7 @@ +# Deprecation Notice + +These are the policy files for CloudQuery **v0.x.x**. Please use the [policies_v1/](../policies_v1/) directory for CloudQuery v1.x.x policies. + # CloudQuery Policies CloudQuery SQL Policies for Kubernetes diff --git a/plugins/source/k8s/policies_v1/README.md b/plugins/source/k8s/policies_v1/README.md new file mode 100644 index 00000000000000..88d9becc4c4f08 --- /dev/null +++ b/plugins/source/k8s/policies_v1/README.md @@ -0,0 +1,33 @@ +# CloudQuery Policies + +CloudQuery SQL Policies for Kubernetes + +## Policies and Compliance Frameworks Available + +- [Kubernetes NSA CISA v1](./nsa_cisa_v1/policy.sql) + +## Running + +You can execute policies with `psql`. For example: + +```bash +# Set DSN to your PostgreSQL populated by CloudQuery +export DSN=postgres://postgres:pass@localhost:5432/postgres +# Execute the NSA CISA Policy +psql ${DSN} -f ./nsa_cisa_v1/policy.sql +``` + +This will create all the results in `k8s_policy_results` table which you can query directly, connect to any BI system (Grafana, Preset, AWS QuickSight, PowerBI, …). + +You can also output it into CSV or HTML with the following built-in `psql` commands: + +```bash +# Set DSN to your PostgreSQL populated by CloudQuery +export DSN=postgres://postgres:pass@localhost:5432/postgres +# default tabular output +psql ${DSN} -c "select * from k8s_policy_results" +# CSV output +psql ${DSN} -c "select * from k8s_policy_results" --csv +# HTML output +psql ${DSN} -c "select * from k8s_policy_results" --html +``` diff --git a/plugins/source/k8s/policies_v1/create_k8s_policy_results.sql b/plugins/source/k8s/policies_v1/create_k8s_policy_results.sql new file mode 100644 index 00000000000000..e95b26a6c59779 --- /dev/null +++ b/plugins/source/k8s/policies_v1/create_k8s_policy_results.sql @@ -0,0 +1,12 @@ +create table if not exists k8s_policy_results +( + execution_time timestamp with time zone, + framework varchar(255), + check_id varchar(255), + title text, + context text, + namespace text, + resource_id varchar(1024), + resource_name text, + status varchar(16) +) \ No newline at end of file diff --git a/plugins/source/k8s/policies_v1/nsa_cisa_v1/README.md b/plugins/source/k8s/policies_v1/nsa_cisa_v1/README.md new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/plugins/source/k8s/policies_v1/nsa_cisa_v1/network_hardening.sql b/plugins/source/k8s/policies_v1/nsa_cisa_v1/network_hardening.sql new file mode 100644 index 00000000000000..9d096c71c05ae0 --- /dev/null +++ b/plugins/source/k8s/policies_v1/nsa_cisa_v1/network_hardening.sql @@ -0,0 +1,132 @@ +\echo "Executing K8S Network Hardening NSA CISA v1" + +\echo "Enforce CPU resource limits" + +\echo "Deamonsets enforce cpu limit" +\set check_id "daemonset_cpu_limit" +\ir ../queries/network_hardening/daemonset_cpu_limit.sql + +\echo "Deployments enforce cpu limit" +\set check_id "deployment_cpu_limit" +\ir ../queries/network_hardening/deployment_cpu_limit.sql + +\echo "Jobs enforce cpu limit" +\set check_id "job_cpu_limit" +\ir ../queries/network_hardening/job_cpu_limit.sql + + +\echo "Namespaces CPU limit range default" +\set check_id "namespace_limit_range_default_cpu_limit" +\ir ../queries/network_hardening/namespace_limit_range_default_cpu_limit.sql + + +\echo "Namespaces CPU limit resource quota" +\set check_id "namespace_resource_quota_cpu_limit" +\ir ../queries/network_hardening/namespace_resource_quota_cpu_limit.sql + + +\echo "ReplciaSets enforce cpu limit" +\set check_id "replicaset_cpu_limit" +\ir ../queries/network_hardening/replicaset_cpu_limit.sql + + +\echo "Enforce CPU request" + +\echo "Deamonsets enforce cpu request" +\set check_id "daemonset_cpu_request" +\ir ../queries/network_hardening/daemonset_cpu_request.sql + +\echo "Deployments enforce cpu request" +\set check_id "deployment_cpu_request" +\ir ../queries/network_hardening/deployment_cpu_request.sql + +\echo "Jobs enforce cpu request" +\set check_id "job_cpu_limit" +\ir ../queries/network_hardening/job_cpu_limit.sql + + +\echo "Namespaces CPU request range default" +\set check_id "namespace_limit_range_default_cpu_request" +\ir ../queries/network_hardening/namespace_limit_range_default_cpu_request.sql + + +\echo "Namespaces CPU request resource quota" +\set check_id "namespace_resource_quota_cpu_request" +\ir ../queries/network_hardening/namespace_resource_quota_cpu_request.sql + + +\echo "ReplciaSets enforce cpu request" +\set check_id "replicaset_cpu_request" +\ir ../queries/network_hardening/replicaset_cpu_request.sql + +\echo "Ensure memory limits set" + +\echo "Deamonsets enforce memory limit" +\set check_id "daemonset_memory_limit" +\ir ../queries/network_hardening/daemonset_memory_limit.sql + +\echo "Deployments enforce memory limit" +\set check_id "deployment_memory_limit" +\ir ../queries/network_hardening/deployment_memory_limit.sql + +\echo "Jobs enforce memory limit" +\set check_id "job_memory_limit" +\ir ../queries/network_hardening/job_memory_limit.sql + + +\echo "Namespaces CPU memory range default" +\set check_id "namespace_limit_range_default_memory_limit" +\ir ../queries/network_hardening/namespace_limit_range_default_memory_limit.sql + + +\echo "Namespaces CPU memory resource quota" +\set check_id "namespace_resource_quota_memory_limit" +\ir ../queries/network_hardening/namespace_resource_quota_memory_limit.sql + + +\echo "ReplciaSets enforce memory limit" +\set check_id "replicaset_memory_limit" +\ir ../queries/network_hardening/replicaset_memory_limit.sql + + +\echo "Enforce Memory request" + +\echo "Deamonsets enforce memory request" +\set check_id "daemonset_memory_request" +\ir ../queries/network_hardening/daemonset_memory_request.sql + +\echo "Deployments enforce memory request" +\set check_id "deployment_memory_request" +\ir ../queries/network_hardening/deployment_memory_request.sql + +\echo "Jobs enforce memory request" +\set check_id "job_memory_request" +\ir ../queries/network_hardening/job_memory_request.sql + + +\echo "Namespaces Memory request range default" +\set check_id "namespace_limit_range_default_memory_request" +\ir ../queries/network_hardening/namespace_limit_range_default_memory_request.sql + + +\echo "Namespaces Memory request resource quota" +\set check_id "namespace_resource_quota_memory_request" +\ir ../queries/network_hardening/namespace_resource_quota_memory_request.sql + + +\echo "ReplciaSets enforce cpu request" +\set check_id "replicaset_memory_request" +\ir ../queries/network_hardening/replicaset_memory_request.sql + + +\echo "Enforce default deny network policy" + +\echo "Network policy default deny egress" +\set check_id "network_policy_default_deny_egress" +\ir ../queries/network_hardening/network_policy_default_deny_egress.sql + + +\echo "Network policy default deny ingress" +\set check_id "network_policy_default_deny_ingress" +\ir ../queries/network_hardening/network_policy_default_deny_ingress.sql + diff --git a/plugins/source/k8s/policies_v1/nsa_cisa_v1/pod_security.sql b/plugins/source/k8s/policies_v1/nsa_cisa_v1/pod_security.sql new file mode 100644 index 00000000000000..75c70a6b9bcf89 --- /dev/null +++ b/plugins/source/k8s/policies_v1/nsa_cisa_v1/pod_security.sql @@ -0,0 +1,152 @@ +\echo "Executing K8S Pod Security NSA CISA v1" + +\set check_id "container_disallow_host_path" +\echo "Disallow host path access" +\ir ../queries/pod_security/pod_volume_host_path.sql + +\echo "Verify containers have privileged access disabled" + +\echo "Deamonset privileges disabled" +\set check_id "daemonset_container_privilege_disabled" +\ir ../queries/pod_security/daemonset_container_privilege_disabled.sql + +\echo "Deployment containers privileged access disabled" +\set check_id "deployment_container_privilege_disabled" +\ir ../queries/pod_security/deployment_container_privilege_disabled.sql + +\echo "Jobs container privileged access disabled" +\set check_id "job_container_privilege_disabled" +\ir ../queries/pod_security/job_container_privilege_disabled.sql + +\echo "Pod container privileged access disabled" +\set check_id "pod_container_privilege_disabled" +\ir ../queries/pod_security/pod_container_privilege_disabled.sql + +\echo "ReplicaSet container privileged access disabled" +\set check_id "replicaset_container_privilege_disabled" +\ir ../queries/pod_security/replicaset_container_privilege_disabled.sql + +\echo "Container privileged escalation disabled" + +\echo "DaemonSet container privileged escalation disabled" +\set check_id "daemonset_container_privilege_escalation_disabled" +\ir ../queries/pod_security/daemonset_container_privilege_escalation_disabled.sql + +\echo "Deployment container privileged escalation disabled" +\set check_id "deployment_container_privilege_escalation_disabled" +\ir ../queries/pod_security/deployment_container_privilege_escalation_disabled.sql + +\echo "Job container privileged escalation disabled" +\set check_id "job_container_privilege_escalation_disabled" +\ir ../queries/pod_security/job_container_privilege_escalation_disabled.sql + +\echo "Pod container privileged escalation disabled" +\set check_id "pod_container_privilege_escalation_disabled" +\ir ../queries/pod_security/pod_container_privilege_escalation_disabled.sql + +\echo "ReplicaSet container privileged escalation disabled" +\set check_id "replicaset_container_privilege_escalation_disabled" +\ir ../queries/pod_security/replicaset_container_privilege_escalation_disabled.sql + + +\echo "Host network access disabled" + +\echo "DaemonSet container hostNetwork disabled" +\set check_id "daemonset_host_network_access_disabled" +\ir ../queries/pod_security/daemonset_host_network_access_disabled.sql + +\echo "Deployment container hostNetwork disabled" +\set check_id "deployment_host_network_access_disabled" +\ir ../queries/pod_security/deployment_host_network_access_disabled.sql + +\echo "Job container hostNetwork disabled" +\set check_id "job_host_network_access_disabled" +\ir ../queries/pod_security/job_host_network_access_disabled.sql + +\echo "Pod container hostNetwork disabled" +\set check_id "pod_container_privilege_escalation_disabled" +\ir ../queries/pod_security/pod_host_network_access_disabled.sql + +\echo "ReplicaSet container hostNetwork disabled" +\set check_id "replicaset_container_privilege_escalation_disabled" +\ir ../queries/pod_security/replicaset_host_network_access_disabled.sql + + +\echo "HostPID and HostIPC sharing disabled" + +\echo "DeamonSet containers HostPID and HostIPC sharing disabled" +\set check_id "daemonset_hostpid_hostipc_sharing_disabled" +\ir ../queries/pod_security/daemonset_hostpid_hostipc_sharing_disabled.sql + +\echo "Deployment containers HostPID and HostIPC sharing disabled" +\set check_id "deployment_hostpid_hostipc_sharing_disabled" +\ir ../queries/pod_security/deployment_hostpid_hostipc_sharing_disabled.sql + +\echo "Job containers HostPID and HostIPC sharing disabled" +\set check_id "job_hostpid_hostipc_sharing_disabled" +\ir ../queries/pod_security/job_hostpid_hostipc_sharing_disabled.sql + +\echo "Pod containers HostPID and HostIPC sharing disabled" +\set check_id "pod_hostpid_hostipc_sharing_disabled" +\ir ../queries/pod_security/pod_hostpid_hostipc_sharing_disabled.sql + +\echo "ReplicaSet containers HostPID and HostIPC sharing disabled" +\set check_id "replicaset_hostpid_hostipc_sharing_disabled" +\ir ../queries/pod_security/replicaset_hostpid_hostipc_sharing_disabled.sql + +\echo "Containers root file system is read-only" + +\echo "DeamonSet containers root file system is read-only" +\set check_id "daemonset_immutable_container_filesystem" +\ir ../queries/pod_security/daemonset_immutable_container_filesystem.sql + +\echo "Deployment containers root file system is read-only" +\set check_id "deployment_immutable_container_filesystem" +\ir ../queries/pod_security/deployment_immutable_container_filesystem.sql + +\echo "Job containers root file system is read-only" +\set check_id "job_immutable_container_filesystem" +\ir ../queries/pod_security/job_immutable_container_filesystem.sql + +\echo "Pod containers root file system is read-only" +\set check_id "pod_immutable_container_filesystem" +\ir ../queries/pod_security/pod_immutable_container_filesystem.sql + +\echo "ReplicaSet containers root file system is read-only" +\set check_id "replicaset_immutable_container_filesystem" +\ir ../queries/pod_security/replicaset_immutable_container_filesystem.sql + + +\echo "Enforce containers to run as non-root" + +\echo "DeamonSet containers to run as non-root" +\set check_id "daemonset_non_root_container" +\ir ../queries/pod_security/daemonset_non_root_container.sql + +\echo "Deployment containers to run as non-root" +\set check_id "deployment_non_root_container" +\ir ../queries/pod_security/deployment_non_root_container.sql + +\echo "Job containers to run as non-root" +\set check_id "job_non_root_container" +\ir ../queries/pod_security/job_non_root_container.sql + +\echo "Pod containers to run as non-root" +\set check_id "pod_non_root_container" +\ir ../queries/pod_security/pod_non_root_container.sql + +\echo "ReplicaSet containers to run as non-root" +\set check_id "replicaset_non_root_container" +\ir ../queries/pod_security/replicaset_non_root_container.sql + + +\echo "Automatic mapping of the service account tokens disabled" + +\echo "Pod service account tokens disabled" +\set check_id "pod_service_account_token_disabled" +\ir ../queries/pod_security/pod_service_account_token_disabled.sql + +\echo "Service account tokens disabled" +\set check_id "service_account_token_disabled" +\ir ../queries/pod_security/service_account_token_disabled.sql + diff --git a/plugins/source/k8s/policies_v1/nsa_cisa_v1/policy.sql b/plugins/source/k8s/policies_v1/nsa_cisa_v1/policy.sql new file mode 100644 index 00000000000000..b023acd021c31f --- /dev/null +++ b/plugins/source/k8s/policies_v1/nsa_cisa_v1/policy.sql @@ -0,0 +1,15 @@ +\set ON_ERROR_STOP on +SET TIME ZONE 'UTC'; +-- neat trick to set execution_time if not already set +-- https://stackoverflow.com/questions/32582600/only-set-variable-in-psql-script-if-not-specified-on-the-command-line +\set execution_time :execution_time +SELECT CASE + WHEN :'execution_time' = ':execution_time' THEN to_char(now(), 'YYYY-MM-dd HH24:MI:SS.US') + ELSE :'execution_time' +END AS "execution_time" \gset + +\set framework 'cis_v1.2.0' + +\ir ../create_k8s_policy_results.sql +\ir ./network_hardening.sql +\ir ./pod_security.sql diff --git a/plugins/source/k8s/policies_v1/policy.sql b/plugins/source/k8s/policies_v1/policy.sql new file mode 100644 index 00000000000000..86c1d88edf9ee4 --- /dev/null +++ b/plugins/source/k8s/policies_v1/policy.sql @@ -0,0 +1,11 @@ +\set ON_ERROR_STOP on +SET TIME ZONE 'UTC'; +-- neat trick to set execution_time if not already set +-- https://stackoverflow.com/questions/32582600/only-set-variable-in-psql-script-if-not-specified-on-the-command-line +\set execution_time :execution_time +SELECT CASE + WHEN :'execution_time' = ':execution_time' THEN to_char(now(), 'YYYY-MM-dd HH24:MI:SS.US') + ELSE :'execution_time' +END AS "execution_time" \gset + +\ir nsa_cisa_v1/policy.sql \ No newline at end of file diff --git a/plugins/source/k8s/policies_v1/queries/network_hardening/daemonset_cpu_limit.sql b/plugins/source/k8s/policies_v1/queries/network_hardening/daemonset_cpu_limit.sql new file mode 100644 index 00000000000000..64d4bc87e0b979 --- /dev/null +++ b/plugins/source/k8s/policies_v1/queries/network_hardening/daemonset_cpu_limit.sql @@ -0,0 +1,25 @@ +-- Join every row in the daemonset table with its json array of containers. +WITH daemonset_containers AS (SELECT uid, value AS container + FROM k8s_apps_daemon_sets + CROSS JOIN jsonb_array_elements(spec_template->'spec'->'containers') AS value) + +INSERT INTO k8s_policy_results (resource_id, execution_time, framework, check_id, title, context, namespace, + resource_name, status) +select uid AS resource_id, + :'execution_time'::timestamp AS execution_time, + :'framework' AS framework, + :'check_id' AS check_id, + 'Daemonset enforces cpu limits' AS title, + context AS context, + namespace AS namespace, + name AS resource_name, + CASE + WHEN + -- Every container needs to have a CPU limit for the check to pass + (SELECT COUNT(*) FROM daemonset_containers WHERE daemonset_containers.uid = k8s_apps_daemon_sets.uid AND + daemonset_containers.container->'resources'->'limits'->>'cpu' IS NULL) > 0 + THEN 'fail' + ELSE 'pass' + END AS status +FROM k8s_apps_daemon_sets + diff --git a/plugins/source/k8s/policies_v1/queries/network_hardening/daemonset_cpu_request.sql b/plugins/source/k8s/policies_v1/queries/network_hardening/daemonset_cpu_request.sql new file mode 100644 index 00000000000000..9597f259652c5c --- /dev/null +++ b/plugins/source/k8s/policies_v1/queries/network_hardening/daemonset_cpu_request.sql @@ -0,0 +1,24 @@ +-- Join every row in the daemonset table with its json array of containers. +WITH daemonset_containers AS (SELECT uid, value AS container + FROM k8s_apps_daemon_sets + CROSS JOIN jsonb_array_elements(spec_template->'spec'->'containers') AS value) + +INSERT INTO k8s_policy_results (resource_id, execution_time, framework, check_id, title, context, namespace, + resource_name, status) +select uid AS resource_id, + :'execution_time'::timestamp AS execution_time, + :'framework' AS framework, + :'check_id' AS check_id, + 'Daemonset enforces cpu requests' AS title, + context AS context, + namespace AS namespace, + name AS resource_name, + CASE + WHEN + -- Every container needs to have a CPU request for the check to pass + (SELECT COUNT(*) FROM daemonset_containers WHERE daemonset_containers.uid = k8s_apps_daemon_sets.uid AND + daemonset_containers.container->'resources'->'requests'->>'cpu' IS NULL) > 0 + THEN 'fail' + ELSE 'pass' + END AS status +FROM k8s_apps_daemon_sets diff --git a/plugins/source/k8s/policies_v1/queries/network_hardening/daemonset_memory_limit.sql b/plugins/source/k8s/policies_v1/queries/network_hardening/daemonset_memory_limit.sql new file mode 100644 index 00000000000000..30472a8eead96e --- /dev/null +++ b/plugins/source/k8s/policies_v1/queries/network_hardening/daemonset_memory_limit.sql @@ -0,0 +1,24 @@ +-- Join every row in the daemonset table with its json array of containers. +WITH daemonset_containers AS (SELECT uid, value AS container + FROM k8s_apps_daemon_sets + CROSS JOIN jsonb_array_elements(spec_template->'spec'->'containers') AS value) + +INSERT INTO k8s_policy_results (resource_id, execution_time, framework, check_id, title, context, namespace, + resource_name, status) +select uid AS resource_id, + :'execution_time'::timestamp AS execution_time, + :'framework' AS framework, + :'check_id' AS check_id, + 'Daemonset enforces memory limits' AS title, + context AS context, + namespace AS namespace, + name AS resource_name, + CASE + WHEN + -- Every container needs to have a Memory limit for the check to pass + (SELECT COUNT(*) FROM daemonset_containers WHERE daemonset_containers.uid = k8s_apps_daemon_sets.uid AND + daemonset_containers.container->'resources'->'limits'->>'memory' IS NULL) > 0 + THEN 'fail' + ELSE 'pass' + END AS status +FROM k8s_apps_daemon_sets diff --git a/plugins/source/k8s/policies_v1/queries/network_hardening/daemonset_memory_request.sql b/plugins/source/k8s/policies_v1/queries/network_hardening/daemonset_memory_request.sql new file mode 100644 index 00000000000000..c5ecd1b2239cd1 --- /dev/null +++ b/plugins/source/k8s/policies_v1/queries/network_hardening/daemonset_memory_request.sql @@ -0,0 +1,24 @@ +-- Join every row in the daemonset table with its json array of containers. +WITH daemonset_containers AS (SELECT uid, value AS container + FROM k8s_apps_daemon_sets + CROSS JOIN jsonb_array_elements(spec_template->'spec'->'containers') AS value) + +INSERT INTO k8s_policy_results (resource_id, execution_time, framework, check_id, title, context, namespace, + resource_name, status) +select uid AS resource_id, + :'execution_time'::timestamp AS execution_time, + :'framework' AS framework, + :'check_id' AS check_id, + 'Daemonset enforces memory requests' AS title, + context AS context, + namespace AS namespace, + name AS resource_name, + CASE + WHEN + -- Every container needs to have a Memory request for the check to pass + (SELECT COUNT(*) FROM daemonset_containers WHERE daemonset_containers.uid = k8s_apps_daemon_sets.uid AND + daemonset_containers.container->'resources'->'requests'->>'memory' IS NULL) > 0 + THEN 'fail' + ELSE 'pass' + END AS status +FROM k8s_apps_daemon_sets \ No newline at end of file diff --git a/plugins/source/k8s/policies_v1/queries/network_hardening/deployment_cpu_limit.sql b/plugins/source/k8s/policies_v1/queries/network_hardening/deployment_cpu_limit.sql new file mode 100644 index 00000000000000..6f055b7a0a2cc6 --- /dev/null +++ b/plugins/source/k8s/policies_v1/queries/network_hardening/deployment_cpu_limit.sql @@ -0,0 +1,24 @@ +-- Join every row in the deployment table with its json array of containers. +WITH deployment_containers AS (SELECT uid, value AS container + FROM k8s_apps_deployments + CROSS JOIN jsonb_array_elements(spec_template->'spec'->'containers') AS value) + +INSERT INTO k8s_policy_results (resource_id, execution_time, framework, check_id, title, context, namespace, + resource_name, status) +select uid AS resource_id, + :'execution_time'::timestamp AS execution_time, + :'framework' AS framework, + :'check_id' AS check_id, + 'Deployment enforces cpu limits' AS title, + context AS context, + namespace AS namespace, + name AS resource_name, + CASE + WHEN + -- Every container needs to have a CPU limit for the check to pass + (SELECT COUNT(*) FROM deployment_containers WHERE deployment_containers.uid = k8s_apps_deployments.uid AND + deployment_containers.container->'resources'->'limits'->>'cpu' IS NULL) > 0 + THEN 'fail' + ELSE 'pass' + END AS status +FROM k8s_apps_deployments \ No newline at end of file diff --git a/plugins/source/k8s/policies_v1/queries/network_hardening/deployment_cpu_request.sql b/plugins/source/k8s/policies_v1/queries/network_hardening/deployment_cpu_request.sql new file mode 100644 index 00000000000000..e8b10bc20d9f99 --- /dev/null +++ b/plugins/source/k8s/policies_v1/queries/network_hardening/deployment_cpu_request.sql @@ -0,0 +1,24 @@ +-- Join every row in the deployment table with its json array of containers. +WITH deployment_containers AS (SELECT uid, value AS container + FROM k8s_apps_deployments + CROSS JOIN jsonb_array_elements(spec_template->'spec'->'containers') AS value) + +INSERT INTO k8s_policy_results (resource_id, execution_time, framework, check_id, title, context, namespace, + resource_name, status) +select uid AS resource_id, + :'execution_time'::timestamp AS execution_time, + :'framework' AS framework, + :'check_id' AS check_id, + 'Deployment enforces cpu requests' AS title, + context AS context, + namespace AS namespace, + name AS resource_name, + CASE + WHEN + -- Every container needs to have a CPU request for the check to pass + (SELECT COUNT(*) FROM deployment_containers WHERE deployment_containers.uid = k8s_apps_deployments.uid AND + deployment_containers.container->'resources'->'requests'->>'cpu' IS NULL) > 0 + THEN 'fail' + ELSE 'pass' + END AS status +FROM k8s_apps_deployments \ No newline at end of file diff --git a/plugins/source/k8s/policies_v1/queries/network_hardening/deployment_memory_limit.sql b/plugins/source/k8s/policies_v1/queries/network_hardening/deployment_memory_limit.sql new file mode 100644 index 00000000000000..bc5f5a3165c99b --- /dev/null +++ b/plugins/source/k8s/policies_v1/queries/network_hardening/deployment_memory_limit.sql @@ -0,0 +1,25 @@ +-- Join every row in the deployment table with its json array of containers. +WITH deployment_containers AS (SELECT uid, value AS container + FROM k8s_apps_deployments + CROSS JOIN jsonb_array_elements(spec_template->'spec'->'containers') AS value) + +INSERT INTO k8s_policy_results (resource_id, execution_time, framework, check_id, title, context, namespace, + resource_name, status) +select uid AS resource_id, + :'execution_time'::timestamp AS execution_time, + :'framework' AS framework, + :'check_id' AS check_id, + 'Deployment enforces memory limits' AS title, + context AS context, + namespace AS namespace, + name AS resource_name, + CASE + WHEN + -- Every container needs to have a Memory limit for the check to pass + (SELECT COUNT(*) FROM deployment_containers WHERE deployment_containers.uid = k8s_apps_deployments.uid AND + deployment_containers.container->'resources'->'limits'->>'memory' IS NULL) > 0 + THEN 'fail' + ELSE 'pass' + END AS status + +FROM k8s_apps_deployments \ No newline at end of file diff --git a/plugins/source/k8s/policies_v1/queries/network_hardening/deployment_memory_request.sql b/plugins/source/k8s/policies_v1/queries/network_hardening/deployment_memory_request.sql new file mode 100644 index 00000000000000..ee89aa5ad728a6 --- /dev/null +++ b/plugins/source/k8s/policies_v1/queries/network_hardening/deployment_memory_request.sql @@ -0,0 +1,24 @@ +-- Join every row in the deployment table with its json array of containers. +WITH deployment_containers AS (SELECT uid, value AS container + FROM k8s_apps_deployments + CROSS JOIN jsonb_array_elements(spec_template->'spec'->'containers') AS value) + +INSERT INTO k8s_policy_results (resource_id, execution_time, framework, check_id, title, context, namespace, + resource_name, status) +select uid AS resource_id, + :'execution_time'::timestamp AS execution_time, + :'framework' AS framework, + :'check_id' AS check_id, + 'Deployment enforces memory requests' AS title, + context AS context, + namespace AS namespace, + name AS resource_name, + CASE + WHEN + -- Every container needs to have a Memory request for the check to pass + (SELECT COUNT(*) FROM deployment_containers WHERE deployment_containers.uid = k8s_apps_deployments.uid AND + deployment_containers.container->'resources'->'requests'->>'memory' IS NULL) > 0 + THEN 'fail' + ELSE 'pass' + END AS status +FROM k8s_apps_deployments \ No newline at end of file diff --git a/plugins/source/k8s/policies_v1/queries/network_hardening/job_cpu_limit.sql b/plugins/source/k8s/policies_v1/queries/network_hardening/job_cpu_limit.sql new file mode 100644 index 00000000000000..798e12594a774c --- /dev/null +++ b/plugins/source/k8s/policies_v1/queries/network_hardening/job_cpu_limit.sql @@ -0,0 +1,22 @@ +WITH job_containers AS (SELECT uid, value AS container + FROM k8s_batch_jobs + CROSS JOIN jsonb_array_elements(spec_template->'spec'->'containers') AS value) + +INSERT INTO k8s_policy_results (resource_id, execution_time, framework, check_id, title, context, namespace, + resource_name, status) +select uid AS resource_id, + :'execution_time'::timestamp AS execution_time, + :'framework' AS framework, + :'check_id' AS check_id, + 'Job enforces cpu limits' AS title, + context AS context, + namespace AS namespace, + name AS resource_name, + CASE + WHEN + (SELECT COUNT(*) FROM job_containers WHERE job_containers.uid = k8s_batch_jobs.uid AND + job_containers.container->'resources'->'limits'->>'cpu' IS NULL) > 0 + THEN 'fail' + ELSE 'pass' + END AS status +FROM k8s_batch_jobs \ No newline at end of file diff --git a/plugins/source/k8s/policies_v1/queries/network_hardening/job_cpu_request.sql b/plugins/source/k8s/policies_v1/queries/network_hardening/job_cpu_request.sql new file mode 100644 index 00000000000000..d3c7e6c8b789c7 --- /dev/null +++ b/plugins/source/k8s/policies_v1/queries/network_hardening/job_cpu_request.sql @@ -0,0 +1,22 @@ +WITH job_containers AS (SELECT uid, value AS container + FROM k8s_batch_jobs + CROSS JOIN jsonb_array_elements(spec_template->'spec'->'containers') AS value) + +INSERT INTO k8s_policy_results (resource_id, execution_time, framework, check_id, title, context, namespace, + resource_name, status) +select uid AS resource_id, + :'execution_time'::timestamp AS execution_time, + :'framework' AS framework, + :'check_id' AS check_id, + 'Job enforces cpu requests' AS title, + context AS context, + namespace AS namespace, + name AS resource_name, + CASE + WHEN + (SELECT COUNT(*) FROM job_containers WHERE job_containers.uid = k8s_batch_jobs.uid AND + job_containers.container->'resources'->'requests'->>'cpu' IS NULL) > 0 + THEN 'fail' + ELSE 'pass' + END AS status +FROM k8s_batch_jobs \ No newline at end of file diff --git a/plugins/source/k8s/policies_v1/queries/network_hardening/job_memory_limit.sql b/plugins/source/k8s/policies_v1/queries/network_hardening/job_memory_limit.sql new file mode 100644 index 00000000000000..fd185b024e30cd --- /dev/null +++ b/plugins/source/k8s/policies_v1/queries/network_hardening/job_memory_limit.sql @@ -0,0 +1,22 @@ +WITH job_containers AS (SELECT uid, value AS container + FROM k8s_batch_jobs + CROSS JOIN jsonb_array_elements(spec_template->'spec'->'containers') AS value) + +INSERT INTO k8s_policy_results (resource_id, execution_time, framework, check_id, title, context, namespace, + resource_name, status) +select uid AS resource_id, + :'execution_time'::timestamp AS execution_time, + :'framework' AS framework, + :'check_id' AS check_id, + 'Job enforces memory limit' AS title, + context AS context, + namespace AS namespace, + name AS resource_name, + CASE + WHEN + (SELECT COUNT(*) FROM job_containers WHERE job_containers.uid = k8s_batch_jobs.uid AND + job_containers.container->'resources'->'limits'->>'memory' IS NULL) > 0 + THEN 'fail' + ELSE 'pass' + END AS status +FROM k8s_batch_jobs \ No newline at end of file diff --git a/plugins/source/k8s/policies_v1/queries/network_hardening/job_memory_request.sql b/plugins/source/k8s/policies_v1/queries/network_hardening/job_memory_request.sql new file mode 100644 index 00000000000000..05fa18faccf3a6 --- /dev/null +++ b/plugins/source/k8s/policies_v1/queries/network_hardening/job_memory_request.sql @@ -0,0 +1,22 @@ +WITH job_containers AS (SELECT uid, value AS container + FROM k8s_batch_jobs + CROSS JOIN jsonb_array_elements(spec_template->'spec'->'containers') AS value) + +INSERT INTO k8s_policy_results (resource_id, execution_time, framework, check_id, title, context, namespace, + resource_name, status) +select uid AS resource_id, + :'execution_time'::timestamp AS execution_time, + :'framework' AS framework, + :'check_id' AS check_id, + 'Job enforces memory requests' AS title, + context AS context, + namespace AS namespace, + name AS resource_name, + CASE + WHEN + (SELECT COUNT(*) FROM job_containers WHERE job_containers.uid = k8s_batch_jobs.uid AND + job_containers.container->'resources'->'requests'->>'memory' IS NULL) > 0 + THEN 'fail' + ELSE 'pass' + END AS status +FROM k8s_batch_jobs diff --git a/plugins/source/k8s/policies_v1/queries/network_hardening/namespace_limit_range_default_cpu_limit.sql b/plugins/source/k8s/policies_v1/queries/network_hardening/namespace_limit_range_default_cpu_limit.sql new file mode 100644 index 00000000000000..0d7a387a2743ed --- /dev/null +++ b/plugins/source/k8s/policies_v1/queries/network_hardening/namespace_limit_range_default_cpu_limit.sql @@ -0,0 +1,24 @@ +WITH default_cpu_limits AS ( + SELECT context, namespace, value->'default'->>'cpu' AS default_cpu_limit + FROM k8s_core_limit_ranges CROSS JOIN jsonb_array_elements(k8s_core_limit_ranges.spec_limits)) + +INSERT +INTO k8s_policy_results (resource_id, execution_time, framework, check_id, title, context, namespace, + resource_name, status) +select uid AS resource_id, + :'execution_time'::timestamp AS execution_time, + :'framework' AS framework, + :'check_id' AS check_id, + 'Namespaces CPU default resource limit' AS title, + context AS context, + name AS namespace, + name AS resource_name, + CASE + WHEN + (SELECT COUNT(default_cpu_limit) FROM default_cpu_limits + WHERE namespace = k8s_core_namespaces.name + AND context = k8s_core_namespaces.context) = 0 + THEN 'fail' + ELSE 'pass' + END AS status +FROM k8s_core_namespaces; \ No newline at end of file diff --git a/plugins/source/k8s/policies_v1/queries/network_hardening/namespace_limit_range_default_cpu_request.sql b/plugins/source/k8s/policies_v1/queries/network_hardening/namespace_limit_range_default_cpu_request.sql new file mode 100644 index 00000000000000..a07676e4808391 --- /dev/null +++ b/plugins/source/k8s/policies_v1/queries/network_hardening/namespace_limit_range_default_cpu_request.sql @@ -0,0 +1,24 @@ +WITH default_request_cpu_limits AS ( + SELECT context, namespace, value->'default_request'->>'cpu' AS default_request_cpu_limit + FROM k8s_core_limit_ranges CROSS JOIN jsonb_array_elements(k8s_core_limit_ranges.spec_limits)) + +INSERT +INTO k8s_policy_results (resource_id, execution_time, framework, check_id, title, context, namespace, + resource_name, status) +select uid AS resource_id, + :'execution_time'::timestamp AS execution_time, + :'framework' AS framework, + :'check_id' AS check_id, + 'Namespaces CPU request resource quota' AS title, + context AS context, + name AS namespace, + name AS resource_name, + CASE + WHEN + (SELECT COUNT(default_request_cpu_limit) FROM default_request_cpu_limits + WHERE namespace = k8s_core_namespaces.name + AND context = k8s_core_namespaces.context) = 0 + THEN 'fail' + ELSE 'pass' + END AS status +FROM k8s_core_namespaces; \ No newline at end of file diff --git a/plugins/source/k8s/policies_v1/queries/network_hardening/namespace_limit_range_default_memory_limit.sql b/plugins/source/k8s/policies_v1/queries/network_hardening/namespace_limit_range_default_memory_limit.sql new file mode 100644 index 00000000000000..8e1491d58c3f97 --- /dev/null +++ b/plugins/source/k8s/policies_v1/queries/network_hardening/namespace_limit_range_default_memory_limit.sql @@ -0,0 +1,24 @@ +WITH default_memory_limits AS ( + SELECT context, namespace, value->'default'->>'memory' AS default_memory_limit + FROM k8s_core_limit_ranges CROSS JOIN jsonb_array_elements(k8s_core_limit_ranges.spec_limits)) + +INSERT +INTO k8s_policy_results (resource_id, execution_time, framework, check_id, title, context, namespace, + resource_name, status) +select uid AS resource_id, + :'execution_time'::timestamp AS execution_time, + :'framework' AS framework, + :'check_id' AS check_id, + 'Namespaces Memory default resource limit' AS title, + context AS context, + name AS namespace, + name AS resource_name, + CASE + WHEN + (SELECT COUNT(default_memory_limit) FROM default_memory_limits + WHERE namespace = k8s_core_namespaces.name + AND context = k8s_core_namespaces.context) = 0 + THEN 'fail' + ELSE 'pass' + END AS status +FROM k8s_core_namespaces; \ No newline at end of file diff --git a/plugins/source/k8s/policies_v1/queries/network_hardening/namespace_limit_range_default_memory_request.sql b/plugins/source/k8s/policies_v1/queries/network_hardening/namespace_limit_range_default_memory_request.sql new file mode 100644 index 00000000000000..0c96de6787f059 --- /dev/null +++ b/plugins/source/k8s/policies_v1/queries/network_hardening/namespace_limit_range_default_memory_request.sql @@ -0,0 +1,26 @@ + + +WITH default_request_memory_limits AS ( + SELECT namespace, value->'default_request'->>'memory' AS default_request_memory_limit + FROM k8s_core_limit_ranges CROSS JOIN jsonb_array_elements(k8s_core_limit_ranges.spec_limits)) + +INSERT +INTO k8s_policy_results (resource_id, execution_time, framework, check_id, title, context, namespace, + resource_name, status) +select uid AS resource_id, + :'execution_time'::timestamp AS execution_time, + :'framework' AS framework, + :'check_id' AS check_id, + 'Namespaces Memory request resource quota' AS title, + context AS context, + name AS namespace, + name AS resource_name, + CASE + WHEN + (SELECT COUNT(default_request_memory_limit) FROM default_request_memory_limits + WHERE namespace = k8s_core_namespaces.name + AND context = k8s_core_namespaces.context) = 0 + THEN 'fail' + ELSE 'pass' + END AS status +FROM k8s_core_namespaces; \ No newline at end of file diff --git a/plugins/source/k8s/policies_v1/queries/network_hardening/namespace_resource_quota_cpu_limit.sql b/plugins/source/k8s/policies_v1/queries/network_hardening/namespace_resource_quota_cpu_limit.sql new file mode 100644 index 00000000000000..1124f35afdcc8d --- /dev/null +++ b/plugins/source/k8s/policies_v1/queries/network_hardening/namespace_resource_quota_cpu_limit.sql @@ -0,0 +1,20 @@ +INSERT INTO k8s_policy_results (resource_id, execution_time, framework, check_id, title, context, namespace, + resource_name, status) +select DISTINCT (k8s_core_namespaces.uid) AS resource_id, + :'execution_time'::timestamp AS execution_time, + :'framework' AS framework, + :'check_id' AS check_id, + 'Namespace enforces resource quota cpu limits' AS title, + k8s_core_namespaces.context AS context, + k8s_core_namespaces.name AS namespace, + k8s_core_namespaces.name AS resource_name, + CASE + WHEN + (SELECT COUNT(*) FROM k8s_core_resource_quotas + WHERE namespace = k8s_core_namespaces.name + AND context = k8s_core_namespaces.context + AND spec_hard->>'limits.cpu' IS NOT NULL) = 0 + THEN 'fail' + ELSE 'pass' + END AS status +FROM k8s_core_namespaces; \ No newline at end of file diff --git a/plugins/source/k8s/policies_v1/queries/network_hardening/namespace_resource_quota_cpu_request.sql b/plugins/source/k8s/policies_v1/queries/network_hardening/namespace_resource_quota_cpu_request.sql new file mode 100644 index 00000000000000..1ba018bda0aa89 --- /dev/null +++ b/plugins/source/k8s/policies_v1/queries/network_hardening/namespace_resource_quota_cpu_request.sql @@ -0,0 +1,20 @@ +INSERT INTO k8s_policy_results (resource_id, execution_time, framework, check_id, title, context, namespace, + resource_name, status) +select DISTINCT (k8s_core_namespaces.uid) AS resource_id, + :'execution_time'::timestamp AS execution_time, + :'framework' AS framework, + :'check_id' AS check_id, + 'Namespace enforces resource quota cpu request' AS title, + k8s_core_namespaces.context AS context, + k8s_core_namespaces.name AS namespace, + k8s_core_namespaces.name AS resource_name, + CASE + WHEN + (SELECT COUNT(*) FROM k8s_core_resource_quotas + WHERE namespace = k8s_core_namespaces.name + AND context = k8s_core_namespaces.context + AND spec_hard->>'requests.cpu' IS NOT NULL) = 0 + THEN 'fail' + ELSE 'pass' + END AS status +FROM k8s_core_namespaces; \ No newline at end of file diff --git a/plugins/source/k8s/policies_v1/queries/network_hardening/namespace_resource_quota_memory_limit.sql b/plugins/source/k8s/policies_v1/queries/network_hardening/namespace_resource_quota_memory_limit.sql new file mode 100644 index 00000000000000..ed23db9c6890d4 --- /dev/null +++ b/plugins/source/k8s/policies_v1/queries/network_hardening/namespace_resource_quota_memory_limit.sql @@ -0,0 +1,20 @@ +INSERT INTO k8s_policy_results (resource_id, execution_time, framework, check_id, title, context, namespace, + resource_name, status) +select DISTINCT (k8s_core_namespaces.uid) AS resource_id, + :'execution_time'::timestamp AS execution_time, + :'framework' AS framework, + :'check_id' AS check_id, + 'Namespace enforces resource quota memory limits' AS title, + k8s_core_namespaces.context AS context, + k8s_core_namespaces.name AS namespace, + k8s_core_namespaces.name AS resource_name, + CASE + WHEN + (SELECT COUNT(*) FROM k8s_core_resource_quotas + WHERE namespace = k8s_core_namespaces.name + AND context = k8s_core_namespaces.context + AND spec_hard->>'limits.memory' IS NOT NULL) = 0 + THEN 'fail' + ELSE 'pass' + END AS status +FROM k8s_core_namespaces; \ No newline at end of file diff --git a/plugins/source/k8s/policies_v1/queries/network_hardening/namespace_resource_quota_memory_request.sql b/plugins/source/k8s/policies_v1/queries/network_hardening/namespace_resource_quota_memory_request.sql new file mode 100644 index 00000000000000..d9ae9d65fa830e --- /dev/null +++ b/plugins/source/k8s/policies_v1/queries/network_hardening/namespace_resource_quota_memory_request.sql @@ -0,0 +1,20 @@ +INSERT INTO k8s_policy_results (resource_id, execution_time, framework, check_id, title, context, namespace, + resource_name, status) +select DISTINCT (k8s_core_namespaces.uid) AS resource_id, + :'execution_time'::timestamp AS execution_time, + :'framework' AS framework, + :'check_id' AS check_id, + 'Namespace enforces resource quota memory request' AS title, + k8s_core_namespaces.context AS context, + k8s_core_namespaces.name AS namespace, + k8s_core_namespaces.name AS resource_name, + CASE + WHEN + (SELECT COUNT(*) FROM k8s_core_resource_quotas + WHERE namespace = k8s_core_namespaces.name + AND context = k8s_core_namespaces.context + AND spec_hard->>'requests.memory' IS NOT NULL) = 0 + THEN 'fail' + ELSE 'pass' + END AS status +FROM k8s_core_namespaces; \ No newline at end of file diff --git a/plugins/source/k8s/policies_v1/queries/network_hardening/network_policy_default_deny_egress.sql b/plugins/source/k8s/policies_v1/queries/network_hardening/network_policy_default_deny_egress.sql new file mode 100644 index 00000000000000..9ecf9d6d9a0f68 --- /dev/null +++ b/plugins/source/k8s/policies_v1/queries/network_hardening/network_policy_default_deny_egress.sql @@ -0,0 +1,23 @@ +INSERT INTO k8s_policy_results (resource_id, execution_time, framework, check_id, title, context, namespace, + resource_name, status) +select uid AS resource_id, +:'execution_time'::timestamp AS execution_time, + :'framework' AS framework, + :'check_id' AS check_id, + 'Network policy default deny egress' AS title, + context AS context, + name AS namespace, + name AS resource_name, + CASE + WHEN + (SELECT COUNT(*) FROM k8s_networking_network_policies + WHERE namespace = k8s_core_namespaces.name + AND context = k8s_core_namespaces.context + AND spec_policy_types @> ARRAY['Egress'] + AND spec_pod_selector::TEXT = '{}' + AND ((spec_egress IS NULL) OR (JSONB_ARRAY_LENGTH(spec_egress) = 0))) = 0 + THEN 'fail' + ELSE 'pass' + END AS STATUS + +FROM k8s_core_namespaces \ No newline at end of file diff --git a/plugins/source/k8s/policies_v1/queries/network_hardening/network_policy_default_deny_ingress.sql b/plugins/source/k8s/policies_v1/queries/network_hardening/network_policy_default_deny_ingress.sql new file mode 100644 index 00000000000000..08c631d65a1abe --- /dev/null +++ b/plugins/source/k8s/policies_v1/queries/network_hardening/network_policy_default_deny_ingress.sql @@ -0,0 +1,23 @@ +INSERT INTO k8s_policy_results (resource_id, execution_time, framework, check_id, title, context, namespace, + resource_name, status) +select uid AS resource_id, +:'execution_time'::timestamp AS execution_time, + :'framework' AS framework, + :'check_id' AS check_id, + 'Network policy default deny ingress' AS title, + context AS context, + name AS namespace, + name AS resource_name, + CASE + WHEN + (SELECT COUNT(*) FROM k8s_networking_network_policies + WHERE namespace = k8s_core_namespaces.name + AND context = k8s_core_namespaces.context + AND spec_policy_types @> ARRAY['Ingress'] + AND spec_pod_selector::TEXT = '{}' + AND ((spec_ingress IS NULL) OR (JSONB_ARRAY_LENGTH(spec_ingress) = 0))) = 0 + THEN 'fail' + ELSE 'pass' + END AS STATUS + +FROM k8s_core_namespaces \ No newline at end of file diff --git a/plugins/source/k8s/policies_v1/queries/network_hardening/replicaset_cpu_limit.sql b/plugins/source/k8s/policies_v1/queries/network_hardening/replicaset_cpu_limit.sql new file mode 100644 index 00000000000000..f85a5aa3de353d --- /dev/null +++ b/plugins/source/k8s/policies_v1/queries/network_hardening/replicaset_cpu_limit.sql @@ -0,0 +1,24 @@ +-- Join every row in the replica_set table with its json array of containers. +WITH replica_set_containers AS (SELECT uid, value AS container + FROM k8s_apps_replica_sets + CROSS JOIN jsonb_array_elements(spec_template->'spec'->'containers') AS value) + +INSERT INTO k8s_policy_results (resource_id, execution_time, framework, check_id, title, context, namespace, + resource_name, status) +select uid AS resource_id, + :'execution_time'::timestamp AS execution_time, + :'framework' AS framework, + :'check_id' AS check_id, + 'Replicaset enforces cpu limits' AS title, + context AS context, + namespace AS namespace, + name AS resource_name, + CASE + WHEN + -- Every container needs to have a CPU limit for the check to pass + (SELECT COUNT(*) FROM replica_set_containers WHERE replica_set_containers.uid = k8s_apps_replica_sets.uid AND + replica_set_containers.container->'resources'->'limits'->>'cpu' IS NULL) > 0 + THEN 'fail' + ELSE 'pass' + END AS status +FROM k8s_apps_replica_sets \ No newline at end of file diff --git a/plugins/source/k8s/policies_v1/queries/network_hardening/replicaset_cpu_request.sql b/plugins/source/k8s/policies_v1/queries/network_hardening/replicaset_cpu_request.sql new file mode 100644 index 00000000000000..04be7198101c8a --- /dev/null +++ b/plugins/source/k8s/policies_v1/queries/network_hardening/replicaset_cpu_request.sql @@ -0,0 +1,24 @@ +-- Join every row in the replica_set table with its json array of containers. +WITH replica_set_containers AS (SELECT uid, value AS container + FROM k8s_apps_replica_sets + CROSS JOIN jsonb_array_elements(spec_template->'spec'->'containers') AS value) + +INSERT INTO k8s_policy_results (resource_id, execution_time, framework, check_id, title, context, namespace, + resource_name, status) +select uid AS resource_id, + :'execution_time'::timestamp AS execution_time, + :'framework' AS framework, + :'check_id' AS check_id, + 'Replicaset enforces cpu requests' AS title, + context AS context, + namespace AS namespace, + name AS resource_name, + CASE + WHEN + -- Every container needs to have a CPU request for the check to pass + (SELECT COUNT(*) FROM replica_set_containers WHERE replica_set_containers.uid = k8s_apps_replica_sets.uid AND + replica_set_containers.container->'resources'->'requests'->>'cpu' IS NULL) > 0 + THEN 'fail' + ELSE 'pass' + END AS status +FROM k8s_apps_replica_sets diff --git a/plugins/source/k8s/policies_v1/queries/network_hardening/replicaset_memory_limit.sql b/plugins/source/k8s/policies_v1/queries/network_hardening/replicaset_memory_limit.sql new file mode 100644 index 00000000000000..50f0fa7bd1b92a --- /dev/null +++ b/plugins/source/k8s/policies_v1/queries/network_hardening/replicaset_memory_limit.sql @@ -0,0 +1,24 @@ +-- Join every row in the replica_set table with its json array of containers. +WITH replica_set_containers AS (SELECT uid, value AS container + FROM k8s_apps_replica_sets + CROSS JOIN jsonb_array_elements(spec_template->'spec'->'containers') AS value) + +INSERT INTO k8s_policy_results (resource_id, execution_time, framework, check_id, title, context, namespace, + resource_name, status) +select uid AS resource_id, + :'execution_time'::timestamp AS execution_time, + :'framework' AS framework, + :'check_id' AS check_id, + 'Replicaset enforces memory limits' AS title, + context AS context, + namespace AS namespace, + name AS resource_name, + CASE + WHEN + -- Every container needs to have a memory limit for the check to pass + (SELECT COUNT(*) FROM replica_set_containers WHERE replica_set_containers.uid = k8s_apps_replica_sets.uid AND + replica_set_containers.container->'resources'->'limits'->>'memory' IS NULL) > 0 + THEN 'fail' + ELSE 'pass' + END AS status +FROM k8s_apps_replica_sets \ No newline at end of file diff --git a/plugins/source/k8s/policies_v1/queries/network_hardening/replicaset_memory_request.sql b/plugins/source/k8s/policies_v1/queries/network_hardening/replicaset_memory_request.sql new file mode 100644 index 00000000000000..7d90669ff1ae7d --- /dev/null +++ b/plugins/source/k8s/policies_v1/queries/network_hardening/replicaset_memory_request.sql @@ -0,0 +1,24 @@ +-- Join every row in the deployment table with its json array of containers. +With replica_set_containers AS (SELECT uid, value AS container + FROM k8s_apps_replica_sets + CROSS JOIN jsonb_array_elements(spec_template->'spec'->'containers') AS value) + +Insert Into k8s_policy_results (resource_id, execution_time, framework, check_id, title, context, namespace, + resource_name, status) +select uid AS resource_id, + :'execution_time'::timestamp AS execution_time, + :'framework' AS framework, + :'check_id' AS check_id, + 'Replicaset enforces memory requests' AS title, + context AS context, + namespace AS namespace, + name AS resource_name, + CASE + WHEN + -- Every container needs to have a memory request for the check to pass + (SELECT COUNT(*) FROM replica_set_containers WHERE replica_set_containers.uid = k8s_apps_replica_sets.uid AND + replica_set_containers.container->'resources'->'requests'->>'memory' IS NULL) > 0 + THEN 'fail' + ELSE 'pass' + END AS status +FROM k8s_apps_replica_sets \ No newline at end of file diff --git a/plugins/source/k8s/policies_v1/queries/pod_security/daemonset_container_privilege_disabled.sql b/plugins/source/k8s/policies_v1/queries/pod_security/daemonset_container_privilege_disabled.sql new file mode 100644 index 00000000000000..4ce9c75ac19c7f --- /dev/null +++ b/plugins/source/k8s/policies_v1/queries/pod_security/daemonset_container_privilege_disabled.sql @@ -0,0 +1,21 @@ +WITH daemonset_containers AS (SELECT uid, value AS container + FROM k8s_apps_daemon_sets + CROSS JOIN jsonb_array_elements(spec_template->'spec'->'containers') AS value) + +INSERT INTO k8s_policy_results (resource_id, execution_time, framework, check_id, title, context, namespace, + resource_name, status) +select uid AS resource_id, + :'execution_time'::timestamp AS execution_time, + :'framework' AS framework, + :'check_id' AS check_id, + 'DaemonSet containers privileges disabled' AS title, + context AS context, + namespace AS namespace, + name AS resource_name, + CASE WHEN + (SELECT COUNT(*) FROM daemonset_containers WHERE daemonset_containers.uid = k8s_apps_daemon_sets.uid AND + daemonset_containers.container->'securityContext'->>'privileged' = 'true') > 0 + THEN 'fail' + ELSE 'pass' + END AS status +FROM k8s_apps_daemon_sets; diff --git a/plugins/source/k8s/policies_v1/queries/pod_security/daemonset_container_privilege_escalation_disabled.sql b/plugins/source/k8s/policies_v1/queries/pod_security/daemonset_container_privilege_escalation_disabled.sql new file mode 100644 index 00000000000000..7da3b6484e3d33 --- /dev/null +++ b/plugins/source/k8s/policies_v1/queries/pod_security/daemonset_container_privilege_escalation_disabled.sql @@ -0,0 +1,21 @@ +WITH daemonset_containers AS (SELECT uid, value AS container + FROM k8s_apps_daemon_sets + CROSS JOIN jsonb_array_elements(spec_template->'spec'->'containers') AS value) + +INSERT INTO k8s_policy_results (resource_id, execution_time, framework, check_id, title, context, namespace, + resource_name, status) +select uid AS resource_id, + :'execution_time'::timestamp AS execution_time, + :'framework' AS framework, + :'check_id' AS check_id, + 'DaemonSet containers privilege escalation disabled' AS title, + context AS context, + namespace AS namespace, + name AS resource_name, + CASE WHEN + (SELECT COUNT(*) FROM daemonset_containers WHERE daemonset_containers.uid = k8s_apps_daemon_sets.uid AND + daemonset_containers.container->'securityContext'->>'allowPrivilegeEscalation' = 'true') > 0 + THEN 'fail' + ELSE 'pass' + END AS status +FROM k8s_apps_daemon_sets; diff --git a/plugins/source/k8s/policies_v1/queries/pod_security/daemonset_host_network_access_disabled.sql b/plugins/source/k8s/policies_v1/queries/pod_security/daemonset_host_network_access_disabled.sql new file mode 100644 index 00000000000000..72226dac7a1d57 --- /dev/null +++ b/plugins/source/k8s/policies_v1/queries/pod_security/daemonset_host_network_access_disabled.sql @@ -0,0 +1,17 @@ +INSERT INTO k8s_policy_results (resource_id, execution_time, framework, check_id, title, context, namespace, + resource_name, status) +select uid AS resource_id, + :'execution_time'::timestamp AS execution_time, + :'framework' AS framework, + :'check_id' AS check_id, + 'Deamonset container hostNetwork disabled' AS title, + context AS context, + namespace AS namespace, + name AS resource_name, + CASE + WHEN + spec_template -> 'spec' ->> 'hostNetwork' = 'true' + THEN 'fail' + ELSE 'pass' + END AS status +FROM k8s_apps_daemon_sets; diff --git a/plugins/source/k8s/policies_v1/queries/pod_security/daemonset_hostpid_hostipc_sharing_disabled.sql b/plugins/source/k8s/policies_v1/queries/pod_security/daemonset_hostpid_hostipc_sharing_disabled.sql new file mode 100644 index 00000000000000..bbecd7801d630d --- /dev/null +++ b/plugins/source/k8s/policies_v1/queries/pod_security/daemonset_hostpid_hostipc_sharing_disabled.sql @@ -0,0 +1,18 @@ +INSERT INTO k8s_policy_results (resource_id, execution_time, framework, check_id, title, context, namespace, + resource_name, status) +select uid AS resource_id, + :'execution_time'::timestamp AS execution_time, + :'framework' AS framework, + :'check_id' AS check_id, + 'Deamonset containers HostPID and HostIPC sharing disabled' AS title, + context AS context, + namespace AS namespace, + name AS resource_name, + CASE + WHEN + spec_template -> 'spec' ->> 'hostPID' = 'true' + OR spec_template -> 'spec' ->> 'hostIPC' = 'true' + THEN 'fail' + ELSE 'pass' + END AS status +FROM k8s_apps_daemon_sets; \ No newline at end of file diff --git a/plugins/source/k8s/policies_v1/queries/pod_security/daemonset_immutable_container_filesystem.sql b/plugins/source/k8s/policies_v1/queries/pod_security/daemonset_immutable_container_filesystem.sql new file mode 100644 index 00000000000000..504646e22146fb --- /dev/null +++ b/plugins/source/k8s/policies_v1/queries/pod_security/daemonset_immutable_container_filesystem.sql @@ -0,0 +1,22 @@ +WITH daemonset_containers AS (SELECT uid, value AS container + FROM k8s_apps_daemon_sets + CROSS JOIN jsonb_array_elements(spec_template->'spec'->'containers') AS value) + +INSERT INTO k8s_policy_results (resource_id, execution_time, framework, check_id, title, context, namespace, + resource_name, status) +select uid AS resource_id, + :'execution_time'::timestamp AS execution_time, + :'framework' AS framework, + :'check_id' AS check_id, + 'DeamonSet containers root file system is read-only' AS title, + context AS context, + namespace AS namespace, + name AS resource_name, + CASE + WHEN + (SELECT COUNT(*) FROM daemonset_containers WHERE daemonset_containers.uid = k8s_apps_daemon_sets.uid AND + daemonset_containers.container->'securityContext'->>'readOnlyRootFilesystem' IS DISTINCT FROM 'true') > 0 + THEN 'fail' + ELSE 'pass' + END AS status +FROM k8s_apps_daemon_sets; diff --git a/plugins/source/k8s/policies_v1/queries/pod_security/daemonset_non_root_container.sql b/plugins/source/k8s/policies_v1/queries/pod_security/daemonset_non_root_container.sql new file mode 100644 index 00000000000000..e420948919eca6 --- /dev/null +++ b/plugins/source/k8s/policies_v1/queries/pod_security/daemonset_non_root_container.sql @@ -0,0 +1,21 @@ +WITH daemonset_containers AS (SELECT uid, value AS container + FROM k8s_apps_daemon_sets + CROSS JOIN jsonb_array_elements(spec_template->'spec'->'containers') AS value) + +INSERT INTO k8s_policy_results (resource_id, execution_time, framework, check_id, title, context, namespace, + resource_name, status) +select uid AS resource_id, + :'execution_time'::timestamp AS execution_time, + :'framework' AS framework, + :'check_id' AS check_id, + 'DaemonSet containers to run as non-root' AS title, + context AS context, + namespace AS namespace, + name AS resource_name, + CASE WHEN + (SELECT COUNT(*) FROM daemonset_containers WHERE daemonset_containers.uid = k8s_apps_daemon_sets.uid AND + daemonset_containers.container->'securityContext'->>'runAsNonRoot' IS DISTINCT FROM 'true') > 0 + THEN 'fail' + ELSE 'pass' + END AS status +FROM k8s_apps_daemon_sets; \ No newline at end of file diff --git a/plugins/source/k8s/policies_v1/queries/pod_security/deployment_container_privilege_disabled.sql b/plugins/source/k8s/policies_v1/queries/pod_security/deployment_container_privilege_disabled.sql new file mode 100644 index 00000000000000..1719cf50f70be8 --- /dev/null +++ b/plugins/source/k8s/policies_v1/queries/pod_security/deployment_container_privilege_disabled.sql @@ -0,0 +1,21 @@ +WITH deployment_containers AS (SELECT uid, value AS container + FROM k8s_apps_deployments + CROSS JOIN jsonb_array_elements(spec_template->'spec'->'containers') AS value) + +INSERT INTO k8s_policy_results (resource_id, execution_time, framework, check_id, title, context, namespace, + resource_name, status) +select uid AS resource_id, + :'execution_time'::timestamp AS execution_time, + :'framework' AS framework, + :'check_id' AS check_id, + 'Deployments privileges disabled' AS title, + context AS context, + namespace AS namespace, + name AS resource_name, + CASE WHEN + (SELECT COUNT(*) FROM deployment_containers WHERE deployment_containers.uid = k8s_apps_deployments.uid AND + deployment_containers.container->'securityContext'->>'privileged' = 'true') > 0 + THEN 'fail' + ELSE 'pass' + END AS status +FROM k8s_apps_deployments; \ No newline at end of file diff --git a/plugins/source/k8s/policies_v1/queries/pod_security/deployment_container_privilege_escalation_disabled.sql b/plugins/source/k8s/policies_v1/queries/pod_security/deployment_container_privilege_escalation_disabled.sql new file mode 100644 index 00000000000000..4edc5b12900ff3 --- /dev/null +++ b/plugins/source/k8s/policies_v1/queries/pod_security/deployment_container_privilege_escalation_disabled.sql @@ -0,0 +1,25 @@ +WITH deployment_containers AS (SELECT uid, value AS container + FROM k8s_apps_deployments + CROSS JOIN jsonb_array_elements(spec_template->'spec'->'containers') AS value) + +INSERT INTO k8s_policy_results (resource_id, execution_time, framework, check_id, title, context, namespace, + resource_name, status) +select uid AS resource_id, + :'execution_time'::timestamp AS execution_time, + :'framework' AS framework, + :'check_id' AS check_id, + 'Deployments privilege escalation disabled' AS title, + context AS context, + namespace AS namespace, + name AS resource_name, + CASE WHEN + (SELECT COUNT(*) FROM deployment_containers WHERE deployment_containers.uid = k8s_apps_deployments.uid AND + deployment_containers.container->'securityContext'->>'allowPrivilegeEscalation' = 'true') > 0 + THEN 'fail' + ELSE 'pass' + END AS status +FROM k8s_apps_deployments; + + + + diff --git a/plugins/source/k8s/policies_v1/queries/pod_security/deployment_host_network_access_disabled.sql b/plugins/source/k8s/policies_v1/queries/pod_security/deployment_host_network_access_disabled.sql new file mode 100644 index 00000000000000..52a28321535feb --- /dev/null +++ b/plugins/source/k8s/policies_v1/queries/pod_security/deployment_host_network_access_disabled.sql @@ -0,0 +1,17 @@ +INSERT INTO k8s_policy_results (resource_id, execution_time, framework, check_id, title, context, namespace, + resource_name, status) +select uid AS resource_id, + :'execution_time'::timestamp AS execution_time, + :'framework' AS framework, + :'check_id' AS check_id, + 'Deployments container hostNetwork disabled' AS title, + context AS context, + namespace AS namespace, + name AS resource_name, + CASE + WHEN + spec_template -> 'spec' ->> 'hostNetwork' = 'true' + THEN 'fail' + ELSE 'pass' + END AS status +FROM k8s_apps_deployments; diff --git a/plugins/source/k8s/policies_v1/queries/pod_security/deployment_hostpid_hostipc_sharing_disabled.sql b/plugins/source/k8s/policies_v1/queries/pod_security/deployment_hostpid_hostipc_sharing_disabled.sql new file mode 100644 index 00000000000000..a4e7ecc372b732 --- /dev/null +++ b/plugins/source/k8s/policies_v1/queries/pod_security/deployment_hostpid_hostipc_sharing_disabled.sql @@ -0,0 +1,18 @@ +INSERT INTO k8s_policy_results (resource_id, execution_time, framework, check_id, title, context, namespace, + resource_name, status) +select uid AS resource_id, + :'execution_time'::timestamp AS execution_time, + :'framework' AS framework, + :'check_id' AS check_id, + 'Deployment containers HostPID and HostIPC sharing disabled' AS title, + context AS context, + namespace AS namespace, + name AS resource_name, + CASE + WHEN + spec_template -> 'spec' ->> 'hostPID' = 'true' + OR spec_template -> 'spec' ->> 'hostIPC' = 'true' + THEN 'fail' + ELSE 'pass' + END AS status +FROM k8s_apps_deployments; \ No newline at end of file diff --git a/plugins/source/k8s/policies_v1/queries/pod_security/deployment_immutable_container_filesystem.sql b/plugins/source/k8s/policies_v1/queries/pod_security/deployment_immutable_container_filesystem.sql new file mode 100644 index 00000000000000..ae7c91a5e339fa --- /dev/null +++ b/plugins/source/k8s/policies_v1/queries/pod_security/deployment_immutable_container_filesystem.sql @@ -0,0 +1,22 @@ +WITH deployment_containers AS (SELECT uid, value AS container + FROM k8s_apps_deployments + CROSS JOIN jsonb_array_elements(spec_template->'spec'->'containers') AS value) + +INSERT INTO k8s_policy_results (resource_id, execution_time, framework, check_id, title, context, namespace, + resource_name, status) +select uid AS resource_id, + :'execution_time'::timestamp AS execution_time, + :'framework' AS framework, + :'check_id' AS check_id, + 'Deployment containers root file system is read-only' AS title, + context AS context, + namespace AS namespace, + name AS resource_name, + CASE WHEN + (SELECT COUNT(*) FROM deployment_containers WHERE deployment_containers.uid = k8s_apps_deployments.uid AND + deployment_containers.container->'securityContext'->>'readOnlyRootFilesystem' IS DISTINCT FROM 'true') > 0 + THEN 'fail' + ELSE 'pass' + END AS status +FROM k8s_apps_deployments; + diff --git a/plugins/source/k8s/policies_v1/queries/pod_security/deployment_non_root_container.sql b/plugins/source/k8s/policies_v1/queries/pod_security/deployment_non_root_container.sql new file mode 100644 index 00000000000000..956c7399777cf2 --- /dev/null +++ b/plugins/source/k8s/policies_v1/queries/pod_security/deployment_non_root_container.sql @@ -0,0 +1,21 @@ +WITH deployment_containers AS (SELECT uid, value AS container + FROM k8s_apps_deployments + CROSS JOIN jsonb_array_elements(spec_template->'spec'->'containers') AS value) + +INSERT INTO k8s_policy_results (resource_id, execution_time, framework, check_id, title, context, namespace, + resource_name, status) +select uid AS resource_id, + :'execution_time'::timestamp AS execution_time, + :'framework' AS framework, + :'check_id' AS check_id, + 'Deployment containers to run as non-root' AS title, + context AS context, + namespace AS namespace, + name AS resource_name, + CASE WHEN + (SELECT COUNT(*) FROM deployment_containers WHERE deployment_containers.uid = k8s_apps_deployments.uid AND + deployment_containers.container->'securityContext'->>'runAsNonRoot' IS DISTINCT FROM 'true') > 0 + THEN 'fail' + ELSE 'pass' + END AS status +FROM k8s_apps_deployments; \ No newline at end of file diff --git a/plugins/source/k8s/policies_v1/queries/pod_security/job_container_privilege_disabled.sql b/plugins/source/k8s/policies_v1/queries/pod_security/job_container_privilege_disabled.sql new file mode 100644 index 00000000000000..e82b316b1e23f7 --- /dev/null +++ b/plugins/source/k8s/policies_v1/queries/pod_security/job_container_privilege_disabled.sql @@ -0,0 +1,23 @@ +WITH job_containers AS (SELECT uid, value AS container + FROM k8s_batch_jobs + CROSS JOIN jsonb_array_elements(spec_template->'spec'->'containers') AS value) + +INSERT INTO k8s_policy_results (resource_id, execution_time, framework, check_id, title, context, namespace, + resource_name, status) +select uid AS resource_id, + :'execution_time'::timestamp AS execution_time, + :'framework' AS framework, + :'check_id' AS check_id, + 'Job containers privileges disabled' AS title, + context AS context, + namespace AS namespace, + name AS resource_name, + CASE + WHEN + (SELECT COUNT(*) FROM job_containers WHERE job_containers.uid = k8s_batch_jobs.uid AND + job_containers.container->'securityContext'->>'privileged' = 'true') > 0 + THEN 'fail' + ELSE 'pass' + END AS status +FROM k8s_batch_jobs + diff --git a/plugins/source/k8s/policies_v1/queries/pod_security/job_container_privilege_escalation_disabled.sql b/plugins/source/k8s/policies_v1/queries/pod_security/job_container_privilege_escalation_disabled.sql new file mode 100644 index 00000000000000..41d1cb3ed33c95 --- /dev/null +++ b/plugins/source/k8s/policies_v1/queries/pod_security/job_container_privilege_escalation_disabled.sql @@ -0,0 +1,22 @@ +WITH job_containers AS (SELECT uid, value AS container + FROM k8s_batch_jobs + CROSS JOIN jsonb_array_elements(spec_template->'spec'->'containers') AS value) + +INSERT INTO k8s_policy_results (resource_id, execution_time, framework, check_id, title, context, namespace, + resource_name, status) +select uid AS resource_id, + :'execution_time'::timestamp AS execution_time, + :'framework' AS framework, + :'check_id' AS check_id, + 'Job containers privilege escalation disabled' AS title, + context AS context, + namespace AS namespace, + name AS resource_name, + CASE + WHEN + (SELECT COUNT(*) FROM job_containers WHERE job_containers.uid = k8s_batch_jobs.uid AND + job_containers.container->'securityContext'->>'allowPrivilegeEscalation' = 'true') > 0 + THEN 'fail' + ELSE 'pass' + END AS status +FROM k8s_batch_jobs \ No newline at end of file diff --git a/plugins/source/k8s/policies_v1/queries/pod_security/job_host_network_access_disabled.sql b/plugins/source/k8s/policies_v1/queries/pod_security/job_host_network_access_disabled.sql new file mode 100644 index 00000000000000..082a765383c020 --- /dev/null +++ b/plugins/source/k8s/policies_v1/queries/pod_security/job_host_network_access_disabled.sql @@ -0,0 +1,17 @@ +INSERT INTO k8s_policy_results (resource_id, execution_time, framework, check_id, title, context, namespace, + resource_name, status) +select uid AS resource_id, + :'execution_time'::timestamp AS execution_time, + :'framework' AS framework, + :'check_id' AS check_id, + 'Jobs container hostNetwork disabled' AS title, + context AS context, + namespace AS namespace, + name AS resource_name, + CASE + WHEN + spec_template -> 'spec' ->> 'hostNetwork' = 'true' + THEN 'fail' + ELSE 'pass' + END AS status +FROM k8s_batch_jobs; diff --git a/plugins/source/k8s/policies_v1/queries/pod_security/job_hostpid_hostipc_sharing_disabled.sql b/plugins/source/k8s/policies_v1/queries/pod_security/job_hostpid_hostipc_sharing_disabled.sql new file mode 100644 index 00000000000000..b71d18013d6431 --- /dev/null +++ b/plugins/source/k8s/policies_v1/queries/pod_security/job_hostpid_hostipc_sharing_disabled.sql @@ -0,0 +1,18 @@ +INSERT INTO k8s_policy_results (resource_id, execution_time, framework, check_id, title, context, namespace, + resource_name, status) +select uid AS resource_id, + :'execution_time'::timestamp AS execution_time, + :'framework' AS framework, + :'check_id' AS check_id, + 'Job containers HostPID and HostIPC sharing disabled' AS title, + context AS context, + namespace AS namespace, + name AS resource_name, + CASE + WHEN + spec_template -> 'spec' ->> 'hostPID' = 'true' + OR spec_template -> 'spec' ->> 'hostIPC' = 'true' + THEN 'fail' + ELSE 'pass' + END AS status +FROM k8s_batch_jobs; \ No newline at end of file diff --git a/plugins/source/k8s/policies_v1/queries/pod_security/job_immutable_container_filesystem.sql b/plugins/source/k8s/policies_v1/queries/pod_security/job_immutable_container_filesystem.sql new file mode 100644 index 00000000000000..b896d52640197a --- /dev/null +++ b/plugins/source/k8s/policies_v1/queries/pod_security/job_immutable_container_filesystem.sql @@ -0,0 +1,22 @@ +WITH job_containers AS (SELECT uid, value AS container + FROM k8s_batch_jobs + CROSS JOIN jsonb_array_elements(spec_template->'spec'->'containers') AS value) + +INSERT INTO k8s_policy_results (resource_id, execution_time, framework, check_id, title, context, namespace, + resource_name, status) +select uid AS resource_id, + :'execution_time'::timestamp AS execution_time, + :'framework' AS framework, + :'check_id' AS check_id, + 'Job containers root file system is read-only' AS title, + context AS context, + namespace AS namespace, + name AS resource_name, + CASE + WHEN + (SELECT COUNT(*) FROM job_containers WHERE job_containers.uid = k8s_batch_jobs.uid AND + job_containers.container->'securityContext'->>'readOnlyRootFilesystem' IS DISTINCT FROM 'true') > 0 + THEN 'fail' + ELSE 'pass' + END AS status +FROM k8s_batch_jobs diff --git a/plugins/source/k8s/policies_v1/queries/pod_security/job_non_root_container.sql b/plugins/source/k8s/policies_v1/queries/pod_security/job_non_root_container.sql new file mode 100644 index 00000000000000..6e0025608c6b02 --- /dev/null +++ b/plugins/source/k8s/policies_v1/queries/pod_security/job_non_root_container.sql @@ -0,0 +1,22 @@ +WITH job_containers AS (SELECT uid, value AS container + FROM k8s_batch_jobs + CROSS JOIN jsonb_array_elements(spec_template->'spec'->'containers') AS value) + +INSERT INTO k8s_policy_results (resource_id, execution_time, framework, check_id, title, context, namespace, + resource_name, status) +select uid AS resource_id, + :'execution_time'::timestamp AS execution_time, + :'framework' AS framework, + :'check_id' AS check_id, + 'Job containers run as non-root' AS title, + context AS context, + namespace AS namespace, + name AS resource_name, + CASE + WHEN + (SELECT COUNT(*) FROM job_containers WHERE job_containers.uid = k8s_batch_jobs.uid AND + job_containers.container->'securityContext'->>'runAsNonRoot' IS DISTINCT FROM 'true') > 0 + THEN 'fail' + ELSE 'pass' + END AS status +FROM k8s_batch_jobs \ No newline at end of file diff --git a/plugins/source/k8s/policies_v1/queries/pod_security/pod_container_privilege_disabled.sql b/plugins/source/k8s/policies_v1/queries/pod_security/pod_container_privilege_disabled.sql new file mode 100644 index 00000000000000..4272261e165bbc --- /dev/null +++ b/plugins/source/k8s/policies_v1/queries/pod_security/pod_container_privilege_disabled.sql @@ -0,0 +1,22 @@ +WITH pod_containers AS (SELECT uid, value AS container + FROM k8s_core_pods + CROSS JOIN jsonb_array_elements(spec_containers) AS value) + +INSERT INTO k8s_policy_results (resource_id, execution_time, framework, check_id, title, context, namespace, + resource_name, status) +select uid AS resource_id, + :'execution_time'::timestamp AS execution_time, + :'framework' AS framework, + :'check_id' AS check_id, + 'Pod container privileged access disabled' AS title, + context AS context, + namespace AS namespace, + name AS resource_name, + CASE WHEN + (SELECT COUNT(*) FROM pod_containers WHERE pod_containers.uid = k8s_core_pods.uid AND + pod_containers.container->'securityContext'->>'privileged' = 'true') > 0 + THEN 'fail' + ELSE 'pass' + END AS status +FROM k8s_core_pods; + diff --git a/plugins/source/k8s/policies_v1/queries/pod_security/pod_container_privilege_escalation_disabled.sql b/plugins/source/k8s/policies_v1/queries/pod_security/pod_container_privilege_escalation_disabled.sql new file mode 100644 index 00000000000000..bb164d3bcfe194 --- /dev/null +++ b/plugins/source/k8s/policies_v1/queries/pod_security/pod_container_privilege_escalation_disabled.sql @@ -0,0 +1,21 @@ +WITH pod_containers AS (SELECT uid, value AS container + FROM k8s_core_pods + CROSS JOIN jsonb_array_elements(spec_containers) AS value) + +INSERT INTO k8s_policy_results (resource_id, execution_time, framework, check_id, title, context, namespace, + resource_name, status) +select uid AS resource_id, + :'execution_time'::timestamp AS execution_time, + :'framework' AS framework, + :'check_id' AS check_id, + 'Pod container privilege escalation disabled' AS title, + context AS context, + namespace AS namespace, + name AS resource_name, + CASE WHEN + (SELECT COUNT(*) FROM pod_containers WHERE pod_containers.uid = k8s_core_pods.uid AND + pod_containers.container->'securityContext'->>'allowPrivilegeEscalation' = 'true') > 0 + THEN 'fail' + ELSE 'pass' + END AS status +FROM k8s_core_pods; \ No newline at end of file diff --git a/plugins/source/k8s/policies_v1/queries/pod_security/pod_host_network_access_disabled.sql b/plugins/source/k8s/policies_v1/queries/pod_security/pod_host_network_access_disabled.sql new file mode 100644 index 00000000000000..1260207c8ef5e6 --- /dev/null +++ b/plugins/source/k8s/policies_v1/queries/pod_security/pod_host_network_access_disabled.sql @@ -0,0 +1,17 @@ +INSERT INTO k8s_policy_results (resource_id, execution_time, framework, check_id, title, context, namespace, + resource_name, status) +select uid AS resource_id, + :'execution_time'::timestamp AS execution_time, + :'framework' AS framework, + :'check_id' AS check_id, + 'Pods container hostNetwork disabled' AS title, + context AS context, + namespace AS namespace, + name AS resource_name, + CASE + WHEN + spec_host_network + THEN 'fail' + ELSE 'pass' + END AS status +FROM k8s_core_pods; diff --git a/plugins/source/k8s/policies_v1/queries/pod_security/pod_hostpid_hostipc_sharing_disabled.sql b/plugins/source/k8s/policies_v1/queries/pod_security/pod_hostpid_hostipc_sharing_disabled.sql new file mode 100644 index 00000000000000..5ce9480d386dd7 --- /dev/null +++ b/plugins/source/k8s/policies_v1/queries/pod_security/pod_hostpid_hostipc_sharing_disabled.sql @@ -0,0 +1,17 @@ +INSERT INTO k8s_policy_results (resource_id, execution_time, framework, check_id, title, context, namespace, + resource_name, status) +select uid AS resource_id, + :'execution_time'::timestamp AS execution_time, + :'framework' AS framework, + :'check_id' AS check_id, + 'Pod containers HostPID and HostIPC sharing disabled' AS title, + context AS context, + namespace AS namespace, + name AS resource_name, + CASE + WHEN + spec_host_pid OR spec_host_ipc + THEN 'fail' + ELSE 'pass' + END AS status +FROM k8s_core_pods; \ No newline at end of file diff --git a/plugins/source/k8s/policies_v1/queries/pod_security/pod_immutable_container_filesystem.sql b/plugins/source/k8s/policies_v1/queries/pod_security/pod_immutable_container_filesystem.sql new file mode 100644 index 00000000000000..b8c6761b6b0f8f --- /dev/null +++ b/plugins/source/k8s/policies_v1/queries/pod_security/pod_immutable_container_filesystem.sql @@ -0,0 +1,21 @@ +WITH pod_containers AS (SELECT uid, value AS container + FROM k8s_core_pods + CROSS JOIN jsonb_array_elements(spec_containers) AS value) + +INSERT INTO k8s_policy_results (resource_id, execution_time, framework, check_id, title, context, namespace, + resource_name, status) +select uid AS resource_id, + :'execution_time'::timestamp AS execution_time, + :'framework' AS framework, + :'check_id' AS check_id, + 'Pod container filesystem is read-ony' AS title, + context AS context, + namespace AS namespace, + name AS resource_name, + CASE WHEN + (SELECT COUNT(*) FROM pod_containers WHERE pod_containers.uid = k8s_core_pods.uid AND + pod_containers.container->'securityContext'->>'readOnlyRootFilesystem' IS DISTINCT FROM 'true') > 0 + THEN 'fail' + ELSE 'pass' + END AS status +FROM k8s_core_pods; \ No newline at end of file diff --git a/plugins/source/k8s/policies_v1/queries/pod_security/pod_non_root_container.sql b/plugins/source/k8s/policies_v1/queries/pod_security/pod_non_root_container.sql new file mode 100644 index 00000000000000..41d4c9e327c7fa --- /dev/null +++ b/plugins/source/k8s/policies_v1/queries/pod_security/pod_non_root_container.sql @@ -0,0 +1,21 @@ +WITH pod_containers AS (SELECT uid, value AS container + FROM k8s_core_pods + CROSS JOIN jsonb_array_elements(spec_containers) AS value) + +INSERT INTO k8s_policy_results (resource_id, execution_time, framework, check_id, title, context, namespace, + resource_name, status) +select uid AS resource_id, + :'execution_time'::timestamp AS execution_time, + :'framework' AS framework, + :'check_id' AS check_id, + 'Pod container runs as non-root' AS title, + context AS context, + namespace AS namespace, + name AS resource_name, + CASE WHEN + (SELECT COUNT(*) FROM pod_containers WHERE pod_containers.uid = k8s_core_pods.uid AND + pod_containers.container->'securityContext'->>'runAsNonRoot' IS DISTINCT FROM 'true') > 0 + THEN 'fail' + ELSE 'pass' + END AS status +FROM k8s_core_pods; diff --git a/plugins/source/k8s/policies_v1/queries/pod_security/pod_service_account_token_disabled.sql b/plugins/source/k8s/policies_v1/queries/pod_security/pod_service_account_token_disabled.sql new file mode 100644 index 00000000000000..2d4ea27f7d4206 --- /dev/null +++ b/plugins/source/k8s/policies_v1/queries/pod_security/pod_service_account_token_disabled.sql @@ -0,0 +1,17 @@ +INSERT INTO k8s_policy_results (resource_id, execution_time, framework, check_id, title, context, namespace, + resource_name, status) +select DISTINCT uid AS resource_id, + :'execution_time'::timestamp AS execution_time, + :'framework' AS framework, + :'check_id' AS check_id, + 'Pod service account tokens disabled' AS title, + context AS context, + namespace AS namespace, + name AS resource_name, + CASE + WHEN + spec_automount_service_account_token + THEN 'fail' + ELSE 'pass' + END AS status +FROM k8s_core_pods diff --git a/plugins/source/k8s/policies_v1/queries/pod_security/pod_volume_host_path.sql b/plugins/source/k8s/policies_v1/queries/pod_security/pod_volume_host_path.sql new file mode 100644 index 00000000000000..2095fe71b96b42 --- /dev/null +++ b/plugins/source/k8s/policies_v1/queries/pod_security/pod_volume_host_path.sql @@ -0,0 +1,21 @@ +WITH pod_volumes AS (SELECT uid, value AS volumes + FROM k8s_core_pods + CROSS JOIN jsonb_array_elements(spec_volumes) AS value) + +INSERT INTO k8s_policy_results (resource_id, execution_time, framework, check_id, title, context, namespace, + resource_name, status) +select uid AS resource_id, + :'execution_time'::timestamp AS execution_time, + :'framework' AS framework, + :'check_id' AS check_id, + 'Pod volume don''t have a hostPath' AS title, + context AS context, + namespace AS namespace, + name AS resource_name, + CASE WHEN + (SELECT COUNT(*) FROM pod_volumes WHERE pod_volumes.uid = k8s_core_pods.uid AND + pod_volumes.volumes->>'hostPath' IS NOT NULL) > 0 + THEN 'fail' + ELSE 'pass' + END AS status +FROM k8s_core_pods; diff --git a/plugins/source/k8s/policies_v1/queries/pod_security/replicaset_container_privilege_disabled.sql b/plugins/source/k8s/policies_v1/queries/pod_security/replicaset_container_privilege_disabled.sql new file mode 100644 index 00000000000000..3d21fad92ed9be --- /dev/null +++ b/plugins/source/k8s/policies_v1/queries/pod_security/replicaset_container_privilege_disabled.sql @@ -0,0 +1,22 @@ +WITH replica_set_containers AS (SELECT uid, value AS container + FROM k8s_apps_replica_sets + CROSS JOIN jsonb_array_elements(spec_template->'spec'->'containers') AS value) + +INSERT INTO k8s_policy_results (resource_id, execution_time, framework, check_id, title, context, namespace, + resource_name, status) +select uid AS resource_id, + :'execution_time'::timestamp AS execution_time, + :'framework' AS framework, + :'check_id' AS check_id, + 'Replicaset privileges disabled' AS title, + context AS context, + namespace AS namespace, + name AS resource_name, + CASE WHEN + (SELECT COUNT(*) FROM replica_set_containers WHERE replica_set_containers.uid = k8s_apps_replica_sets.uid AND + replica_set_containers.container->'securityContext'->>'privileged' = 'true') > 0 + THEN 'fail' + ELSE 'pass' + END AS status +FROM k8s_apps_replica_sets; + diff --git a/plugins/source/k8s/policies_v1/queries/pod_security/replicaset_container_privilege_escalation_disabled.sql b/plugins/source/k8s/policies_v1/queries/pod_security/replicaset_container_privilege_escalation_disabled.sql new file mode 100644 index 00000000000000..1cc00d6e8d44f1 --- /dev/null +++ b/plugins/source/k8s/policies_v1/queries/pod_security/replicaset_container_privilege_escalation_disabled.sql @@ -0,0 +1,21 @@ +WITH replica_set_containers AS (SELECT uid, value AS container + FROM k8s_apps_replica_sets + CROSS JOIN jsonb_array_elements(spec_template->'spec'->'containers') AS value) + +INSERT INTO k8s_policy_results (resource_id, execution_time, framework, check_id, title, context, namespace, + resource_name, status) +select uid AS resource_id, + :'execution_time'::timestamp AS execution_time, + :'framework' AS framework, + :'check_id' AS check_id, + 'ReplicaSet container privileged escalation disabled' AS title, + context AS context, + namespace AS namespace, + name AS resource_name, + CASE WHEN + (SELECT COUNT(*) FROM replica_set_containers WHERE replica_set_containers.uid = k8s_apps_replica_sets.uid AND + replica_set_containers.container->'securityContext'->>'privileged' = 'true') > 0 + THEN 'fail' + ELSE 'pass' + END AS status +FROM k8s_apps_replica_sets; \ No newline at end of file diff --git a/plugins/source/k8s/policies_v1/queries/pod_security/replicaset_host_network_access_disabled.sql b/plugins/source/k8s/policies_v1/queries/pod_security/replicaset_host_network_access_disabled.sql new file mode 100644 index 00000000000000..118c0ab183cbc9 --- /dev/null +++ b/plugins/source/k8s/policies_v1/queries/pod_security/replicaset_host_network_access_disabled.sql @@ -0,0 +1,17 @@ +INSERT INTO k8s_policy_results (resource_id, execution_time, framework, check_id, title, context, namespace, + resource_name, status) +select uid AS resource_id, + :'execution_time'::timestamp AS execution_time, + :'framework' AS framework, + :'check_id' AS check_id, + 'ReplicaSet container hostNetwork disabled' AS title, + context AS context, + namespace AS namespace, + name AS resource_name, + CASE + WHEN + spec_template -> 'spec' ->> 'hostNetwork' = 'true' + THEN 'fail' + ELSE 'pass' + END AS status +FROM k8s_apps_replica_sets; diff --git a/plugins/source/k8s/policies_v1/queries/pod_security/replicaset_hostpid_hostipc_sharing_disabled.sql b/plugins/source/k8s/policies_v1/queries/pod_security/replicaset_hostpid_hostipc_sharing_disabled.sql new file mode 100644 index 00000000000000..2e8ccf8205901f --- /dev/null +++ b/plugins/source/k8s/policies_v1/queries/pod_security/replicaset_hostpid_hostipc_sharing_disabled.sql @@ -0,0 +1,18 @@ +INSERT INTO k8s_policy_results (resource_id, execution_time, framework, check_id, title, context, namespace, + resource_name, status) +select uid AS resource_id, + :'execution_time'::timestamp AS execution_time, + :'framework' AS framework, + :'check_id' AS check_id, + 'ReplicaSet containers HostPID and HostIPC sharing disabled' AS title, + context AS context, + namespace AS namespace, + name AS resource_name, + CASE + WHEN + spec_template -> 'spec' ->> 'hostPID' = 'true' + OR spec_template -> 'spec' ->> 'hostIPC' = 'true' + THEN 'fail' + ELSE 'pass' + END AS status +FROM k8s_apps_replica_sets; \ No newline at end of file diff --git a/plugins/source/k8s/policies_v1/queries/pod_security/replicaset_immutable_container_filesystem.sql b/plugins/source/k8s/policies_v1/queries/pod_security/replicaset_immutable_container_filesystem.sql new file mode 100644 index 00000000000000..51a1e032f3197e --- /dev/null +++ b/plugins/source/k8s/policies_v1/queries/pod_security/replicaset_immutable_container_filesystem.sql @@ -0,0 +1,22 @@ +WITH replica_set_containers AS (SELECT uid, value AS container + FROM k8s_apps_replica_sets + CROSS JOIN jsonb_array_elements(spec_template->'spec'->'containers') AS value) + +INSERT INTO k8s_policy_results (resource_id, execution_time, framework, check_id, title, context, namespace, + resource_name, status) +select uid AS resource_id, + :'execution_time'::timestamp AS execution_time, + :'framework' AS framework, + :'check_id' AS check_id, + 'ReplicaSet containers root file system is read-only' AS title, + context AS context, + namespace AS namespace, + name AS resource_name, + CASE + WHEN + (SELECT COUNT(*) FROM replica_set_containers WHERE replica_set_containers.uid = k8s_apps_replica_sets.uid AND + replica_set_containers.container->'securityContext' ->> 'readOnlyRootFilesystem' IS DISTINCT FROM 'true') > 0 + THEN 'fail' + ELSE 'pass' + END AS status +FROM k8s_apps_replica_sets; \ No newline at end of file diff --git a/plugins/source/k8s/policies_v1/queries/pod_security/replicaset_non_root_container.sql b/plugins/source/k8s/policies_v1/queries/pod_security/replicaset_non_root_container.sql new file mode 100644 index 00000000000000..f9b3dee2a56c61 --- /dev/null +++ b/plugins/source/k8s/policies_v1/queries/pod_security/replicaset_non_root_container.sql @@ -0,0 +1,22 @@ +WITH replica_set_containers AS (SELECT uid, value AS container + FROM k8s_apps_replica_sets + CROSS JOIN jsonb_array_elements(spec_template->'spec'->'containers') AS value) + +INSERT INTO k8s_policy_results (resource_id, execution_time, framework, check_id, title, context, namespace, + resource_name, status) +select uid AS resource_id, + :'execution_time'::timestamp AS execution_time, + :'framework' AS framework, + :'check_id' AS check_id, + 'ReplicaSet containers must run as non-root' AS title, + context AS context, + namespace AS namespace, + name AS resource_name, + CASE + WHEN + (SELECT COUNT(*) FROM replica_set_containers WHERE replica_set_containers.uid = k8s_apps_replica_sets.uid AND + replica_set_containers.container->'securityContext' ->> 'runAsNonRoot' IS DISTINCT FROM 'true') > 0 + THEN 'fail' + ELSE 'pass' + END AS status +FROM k8s_apps_replica_sets; \ No newline at end of file diff --git a/plugins/source/k8s/policies_v1/queries/pod_security/service_account_token_disabled.sql b/plugins/source/k8s/policies_v1/queries/pod_security/service_account_token_disabled.sql new file mode 100644 index 00000000000000..6b3735f61c0fe2 --- /dev/null +++ b/plugins/source/k8s/policies_v1/queries/pod_security/service_account_token_disabled.sql @@ -0,0 +1,17 @@ +INSERT INTO k8s_policy_results (resource_id, execution_time, framework, check_id, title, context, namespace, + resource_name, status) +select DISTINCT uid AS resource_id, + :'execution_time'::timestamp AS execution_time, + :'framework' AS framework, + :'check_id' AS check_id, + 'Pod service account tokens disabled"' AS title, + context AS context, + namespace AS namespace, + name AS resource_name, + CASE + WHEN + spec_automount_service_account_token + THEN 'fail' + ELSE 'pass' + END AS status +FROM k8s_core_service_accounts