diff --git a/charts/cloud-controls/.helmignore b/charts/cloud-controls/.helmignore new file mode 100644 index 00000000..0e8a0eb3 --- /dev/null +++ b/charts/cloud-controls/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/charts/cloud-controls/Chart.yaml b/charts/cloud-controls/Chart.yaml new file mode 100644 index 00000000..a3dacb32 --- /dev/null +++ b/charts/cloud-controls/Chart.yaml @@ -0,0 +1,24 @@ +apiVersion: v2 +name: cloud-controls +description: Cloud Controls Helm Chart +version: 0.0.1 +keywords: + - kubernetes + - nirmata + - kyverno + - policy + - cloud-controller +maintainers: + - name: Nirmata + url: https://nirmata.com/ +dependencies: + - name: aws-ecs-best-practices + condition: aws-ecs-best-practices.enabled + repository: file://charts/ecs + - name: aws-eks-best-practices + condition: aws-eks-best-practices.enabled + repository: file://charts/eks + - name: aws-lambda-best-practices + condition: aws-lambda-best-practices.enabled + repository: file://charts/lambda + diff --git a/charts/cloud-controls/charts/ecs/.helmignore b/charts/cloud-controls/charts/ecs/.helmignore new file mode 100644 index 00000000..0e8a0eb3 --- /dev/null +++ b/charts/cloud-controls/charts/ecs/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/charts/cloud-controls/charts/ecs/Chart.yaml b/charts/cloud-controls/charts/ecs/Chart.yaml new file mode 100644 index 00000000..8ed17d18 --- /dev/null +++ b/charts/cloud-controls/charts/ecs/Chart.yaml @@ -0,0 +1,14 @@ +apiVersion: v2 +name: aws-ecs-best-practices +description: Aws ECS Best Practices CloudController Policy Set +type: application +version: 0.0.1 +keywords: + - kubernetes + - nirmata + - kyverno + - policy + - cloud-controller +maintainers: + - name: Nirmata + url: https://nirmata.com/ diff --git a/charts/cloud-controls/charts/ecs/templates/check-awsvpc-network-mode.yaml b/charts/cloud-controls/charts/ecs/templates/check-awsvpc-network-mode.yaml new file mode 100644 index 00000000..970bdfff --- /dev/null +++ b/charts/cloud-controls/charts/ecs/templates/check-awsvpc-network-mode.yaml @@ -0,0 +1,40 @@ +{{- if .Values.enabled }} +{{- $camelCaseName := "checkAwsvpcNetworkMode" }} +{{- $name := "check-awsvpc-network-mode" }} +{{- if not (has $name .Values.disabledPolicies) }} +apiVersion: {{ .Values.global.apiVersion | default "nirmata.io/v1alpha1" }} +kind: {{ .Values.global.policyKind | default "ValidatingPolicy" }} +metadata: + name: {{ $name }} + annotations: + policies.kyverno.io/title: Check Awsvpc Network Mode + policies.kyverno.io/category: ECS Best Practices + policies.kyverno.io/severity: medium + policies.kyverno.io/description: >- + The awsvpc network mode restricts the flow of traffic between different + tasks or between your tasks and other services that run within your Amazon VPC. + The awsvpc network mode provides task-level network isolation for tasks + that run on Amazon EC2. + labels: + app: kyverno +spec: + failureAction: {{ if hasKey .Values $camelCaseName }}{{ if hasKey (index .Values $camelCaseName) "failureAction" }}{{ index (index .Values $camelCaseName) "failureAction" }}{{ else }}{{ .Values.failureAction | default "Audit" }}{{ end }}{{ else }}{{ .Values.failureAction | default "Audit" }}{{ end }} + scan: {{ if hasKey .Values $camelCaseName }}{{ if hasKey (index .Values $camelCaseName) "scanner" }}{{ index (index .Values $camelCaseName) "scanner" }}{{ else if hasKey .Values "scanner" }}{{ .Values.scanner }}{{ else }}true{{ end }}{{ else if hasKey .Values "scanner" }}{{ .Values.scanner }}{{ else }}true{{ end }} + admission: {{ if hasKey .Values $camelCaseName }}{{ if hasKey (index .Values $camelCaseName) "admission" }}{{ index (index .Values $camelCaseName) "admission" }}{{ else if hasKey .Values "admission" }}{{ .Values.admission }}{{ else }}true{{ end }}{{ else if hasKey .Values "admission" }}{{ .Values.admission }}{{ else }}true{{ end }} + rules: + - name: {{ $name }} + identifier: payload.family + match: + all: + - (metadata.provider): AWS + - (metadata.service): ECS + - (metadata.resource): TaskDefinition + assert: + all: + - message: >- + ECS task definitions are required to use awsvpc network mode. + check: + payload: + networkMode: awsvpc +{{- end }} +{{- end }} diff --git a/charts/cloud-controls/charts/ecs/templates/validate-ecs-container-insights-enabled.yaml b/charts/cloud-controls/charts/ecs/templates/validate-ecs-container-insights-enabled.yaml new file mode 100644 index 00000000..745bbc51 --- /dev/null +++ b/charts/cloud-controls/charts/ecs/templates/validate-ecs-container-insights-enabled.yaml @@ -0,0 +1,39 @@ +{{- if .Values.enabled }} +{{- $camelCaseName := "validateEcsContainerInsightsAreEnabled" }} +{{- $name := "validate-ecs-container-insights-enabled" }} +{{- if not (has $name .Values.disabledPolicies) }} +apiVersion: {{ .Values.global.apiVersion | default "nirmata.io/v1alpha1" }} +kind: {{ .Values.global.policyKind | default "ValidatingPolicy" }} +metadata: + name: {{ $name }} + annotations: + policies.kyverno.io/title: Validate ECS Container Insights are Enabled + policies.kyverno.io/category: ECS Best Practices + policies.kyverno.io/severity: medium + policies.kyverno.io/description: >- + Container Insights enhances the operational visibility of ECS clusters, allowing for proactive issue resolution. + Enabling this feature ensures that diagnostic information is readily available, contributing to a more efficient and reliable containerized environment. + labels: + app: kyverno +spec: + failureAction: {{ if hasKey .Values $camelCaseName }}{{ if hasKey (index .Values $camelCaseName) "failureAction" }}{{ index (index .Values $camelCaseName) "failureAction" }}{{ else }}{{ .Values.failureAction | default "Audit" }}{{ end }}{{ else }}{{ .Values.failureAction | default "Audit" }}{{ end }} + scan: {{ if hasKey .Values $camelCaseName }}{{ if hasKey (index .Values $camelCaseName) "scanner" }}{{ index (index .Values $camelCaseName) "scanner" }}{{ else if hasKey .Values "scanner" }}{{ .Values.scanner }}{{ else }}true{{ end }}{{ else if hasKey .Values "scanner" }}{{ .Values.scanner }}{{ else }}true{{ end }} + admission: {{ if hasKey .Values $camelCaseName }}{{ if hasKey (index .Values $camelCaseName) "admission" }}{{ index (index .Values $camelCaseName) "admission" }}{{ else if hasKey .Values "admission" }}{{ .Values.admission }}{{ else }}true{{ end }}{{ else if hasKey .Values "admission" }}{{ .Values.admission }}{{ else }}true{{ end }} + rules: + - name: {{ $name }} + identifier: payload.clusterName + match: + all: + - (metadata.provider): AWS + - (metadata.service): ECS + - (metadata.resource): Cluster + assert: + all: + - message: >- + ECS container insights must be enabled + check: + payload: + ~.(clusterSettings[?name == 'containerInsights'] || settings[?name == 'containerInsights']): + value: enabled +{{- end }} +{{- end }} \ No newline at end of file diff --git a/charts/cloud-controls/charts/ecs/templates/validate-ecs-containers-nonprivileged.yaml b/charts/cloud-controls/charts/ecs/templates/validate-ecs-containers-nonprivileged.yaml new file mode 100644 index 00000000..6d48c60d --- /dev/null +++ b/charts/cloud-controls/charts/ecs/templates/validate-ecs-containers-nonprivileged.yaml @@ -0,0 +1,39 @@ +{{- if .Values.enabled }} +{{- $camelCaseName := "validateEcsContainersNonprivileged" }} +{{- $name := "validate-ecs-containers-nonprivileged" }} +{{- if not (has $name .Values.disabledPolicies) }} +apiVersion: {{ .Values.global.apiVersion | default "nirmata.io/v1alpha1" }} +kind: {{ .Values.global.policyKind | default "ValidatingPolicy" }} +metadata: + name: {{ $name }} + annotations: + policies.kyverno.io/title: Validate ECS Containers Are Set to Non-Privileged + policies.kyverno.io/category: ECS Best Practices + policies.kyverno.io/severity: medium + policies.kyverno.io/description: >- + When privileged is set to true, the container is given elevated permissions on the host container instance (similar to the root user). + This policy checks that the privileged parameter in the container definition is set to false. + labels: + app: kyverno +spec: + failureAction: {{ if hasKey .Values $camelCaseName }}{{ if hasKey (index .Values $camelCaseName) "failureAction" }}{{ index (index .Values $camelCaseName) "failureAction" }}{{ else }}{{ .Values.failureAction | default "Audit" }}{{ end }}{{ else }}{{ .Values.failureAction | default "Audit" }}{{ end }} + scan: {{ if hasKey .Values $camelCaseName }}{{ if hasKey (index .Values $camelCaseName) "scanner" }}{{ index (index .Values $camelCaseName) "scanner" }}{{ else if hasKey .Values "scanner" }}{{ .Values.scanner }}{{ else }}true{{ end }}{{ else if hasKey .Values "scanner" }}{{ .Values.scanner }}{{ else }}true{{ end }} + admission: {{ if hasKey .Values $camelCaseName }}{{ if hasKey (index .Values $camelCaseName) "admission" }}{{ index (index .Values $camelCaseName) "admission" }}{{ else if hasKey .Values "admission" }}{{ .Values.admission }}{{ else }}true{{ end }}{{ else if hasKey .Values "admission" }}{{ .Values.admission }}{{ else }}true{{ end }} + rules: + - name: {{ $name }} + identifier: payload.family + match: + all: + - (metadata.provider): AWS + - (metadata.service): ECS + - (metadata.resource): TaskDefinition + assert: + all: + - message: >- + The `privileged` field, if present, should be set to `false` + check: + payload: + ~.(containerDefinitions): + (!!privileged): false +{{- end }} +{{- end }} \ No newline at end of file diff --git a/charts/cloud-controls/charts/ecs/templates/validate-ecs-containers-readonly.yaml b/charts/cloud-controls/charts/ecs/templates/validate-ecs-containers-readonly.yaml new file mode 100644 index 00000000..0c5b0096 --- /dev/null +++ b/charts/cloud-controls/charts/ecs/templates/validate-ecs-containers-readonly.yaml @@ -0,0 +1,40 @@ +{{- if .Values.enabled }} +{{- $camelCaseName := "validateEcsContainersReadonly" }} +{{- $name := "validate-ecs-containers-readonly" }} +{{- if not (has $name .Values.disabledPolicies) }} +apiVersion: {{ .Values.global.apiVersion | default "nirmata.io/v1alpha1" }} +kind: {{ .Values.global.policyKind | default "ValidatingPolicy" }} +metadata: + name: {{ $name }} + annotations: + policies.kyverno.io/title: Validate if ECS Containers only have read-only access to its root filesystem + policies.kyverno.io/category: ECS Best Practices + policies.kyverno.io/severity: medium + policies.kyverno.io/description: >- + When managing containers within AWS ECS, it's crucial to enforce security measures to prevent unauthorized modifications. + One significant aspect is restricting write access to the containers' root filesystem. + This policy checks if ECS Containers have read-only access to its root filesystem. + labels: + app: kyverno +spec: + failureAction: {{ if hasKey .Values $camelCaseName }}{{ if hasKey (index .Values $camelCaseName) "failureAction" }}{{ index (index .Values $camelCaseName) "failureAction" }}{{ else }}{{ .Values.failureAction | default "Audit" }}{{ end }}{{ else }}{{ .Values.failureAction | default "Audit" }}{{ end }} + scan: {{ if hasKey .Values $camelCaseName }}{{ if hasKey (index .Values $camelCaseName) "scanner" }}{{ index (index .Values $camelCaseName) "scanner" }}{{ else if hasKey .Values "scanner" }}{{ .Values.scanner }}{{ else }}true{{ end }}{{ else if hasKey .Values "scanner" }}{{ .Values.scanner }}{{ else }}true{{ end }} + admission: {{ if hasKey .Values $camelCaseName }}{{ if hasKey (index .Values $camelCaseName) "admission" }}{{ index (index .Values $camelCaseName) "admission" }}{{ else if hasKey .Values "admission" }}{{ .Values.admission }}{{ else }}true{{ end }}{{ else if hasKey .Values "admission" }}{{ .Values.admission }}{{ else }}true{{ end }} + rules: + - name: {{ $name }} + identifier: payload.family + match: + all: + - (metadata.provider): AWS + - (metadata.service): ECS + - (metadata.resource): TaskDefinition + assert: + all: + - message: >- + ECS Containers should have read-only access to its root filesystem + check: + payload: + ~.(containerDefinitions): + readonlyRootFilesystem: true +{{- end }} +{{- end }} \ No newline at end of file diff --git a/charts/cloud-controls/charts/ecs/templates/validate-ecs-task-definition-log-configuration.yaml b/charts/cloud-controls/charts/ecs/templates/validate-ecs-task-definition-log-configuration.yaml new file mode 100644 index 00000000..295f62e5 --- /dev/null +++ b/charts/cloud-controls/charts/ecs/templates/validate-ecs-task-definition-log-configuration.yaml @@ -0,0 +1,41 @@ +{{- if .Values.enabled }} +{{- $camelCaseName := "validateEcsTaskDefinitionLogConfiguration" }} +{{- $name := "validate-ecs-task-definition-log-configuration" }} +{{- if not (has $name .Values.disabledPolicies) }} +apiVersion: {{ .Values.global.apiVersion | default "nirmata.io/v1alpha1" }} +kind: {{ .Values.global.policyKind | default "ValidatingPolicy" }} +metadata: + name: {{ $name }} + annotations: + policies.kyverno.io/title: Validate ECS Task Definition Log Configuration + policies.kyverno.io/category: ECS Best Practices + policies.kyverno.io/severity: medium + policies.kyverno.io/description: >- + The LogConfiguration property specifies log configuration options to send to a custom log driver for the container. + Having all logs at a central place simplifies troubleshooting and debugging since you don't have to log into individual instances + to access container logs. It also allows integration with monitoring tools to set up metrics and alerts based on log data. + This policy checks if ECS TaskDefinitions and Services have logConfiguration defined. + labels: + app: kyverno +spec: + failureAction: {{ if hasKey .Values $camelCaseName }}{{ if hasKey (index .Values $camelCaseName) "failureAction" }}{{ index (index .Values $camelCaseName) "failureAction" }}{{ else }}{{ .Values.failureAction | default "Audit" }}{{ end }}{{ else }}{{ .Values.failureAction | default "Audit" }}{{ end }} + scan: {{ if hasKey .Values $camelCaseName }}{{ if hasKey (index .Values $camelCaseName) "scanner" }}{{ index (index .Values $camelCaseName) "scanner" }}{{ else if hasKey .Values "scanner" }}{{ .Values.scanner }}{{ else }}true{{ end }}{{ else if hasKey .Values "scanner" }}{{ .Values.scanner }}{{ else }}true{{ end }} + admission: {{ if hasKey .Values $camelCaseName }}{{ if hasKey (index .Values $camelCaseName) "admission" }}{{ index (index .Values $camelCaseName) "admission" }}{{ else if hasKey .Values "admission" }}{{ .Values.admission }}{{ else }}true{{ end }}{{ else if hasKey .Values "admission" }}{{ .Values.admission }}{{ else }}true{{ end }} + rules: + - name: {{ $name }} + identifier: payload.family + match: + all: + - (metadata.provider): AWS + - (metadata.service): ECS + - (metadata.resource): TaskDefinition + assert: + all: + - message: >- + logConfiguration must be set for ECS Task Definition + check: + payload: + ~.(containerDefinitions): + (!logConfiguration): false +{{- end }} +{{- end }} \ No newline at end of file diff --git a/charts/cloud-controls/charts/ecs/templates/validate-ecs-task-definition-memory-hard-limit.yaml b/charts/cloud-controls/charts/ecs/templates/validate-ecs-task-definition-memory-hard-limit.yaml new file mode 100644 index 00000000..ee7b333f --- /dev/null +++ b/charts/cloud-controls/charts/ecs/templates/validate-ecs-task-definition-memory-hard-limit.yaml @@ -0,0 +1,42 @@ +{{- if .Values.enabled }} +{{- $camelCaseName := "validateEcsTaskDefinitionMemoryHardLimit" }} +{{- $name := "validate-ecs-task-definition-memory-hard-limit" }} +{{- if not (has $name .Values.disabledPolicies) }} +apiVersion: {{ .Values.global.apiVersion | default "nirmata.io/v1alpha1" }} +kind: {{ .Values.global.policyKind | default "ValidatingPolicy" }} +metadata: + name: {{ $name }} + annotations: + policies.kyverno.io/title: Validate ECS Task Definition Memory Hard Limit + policies.kyverno.io/category: ECS Best Practices + policies.kyverno.io/severity: medium + policies.kyverno.io/description: >- + This policy checks if Amazon Elastic Container Service + (ECS) task definitions and tasks have a set memory limit for its container definitions. + If a memory limit is not set for a container, it can consume excessive memory, potentially starving other containers running on the same host. + Therefore, it is crucial to enforce a hard memory limit on each container to prevent resource contention. + If a container exceeds its memory limit, it will be terminated by ECS. + labels: + app: kyverno +spec: + failureAction: {{ if hasKey .Values $camelCaseName }}{{ if hasKey (index .Values $camelCaseName) "failureAction" }}{{ index (index .Values $camelCaseName) "failureAction" }}{{ else }}{{ .Values.failureAction | default "Audit" }}{{ end }}{{ else }}{{ .Values.failureAction | default "Audit" }}{{ end }} + scan: {{ if hasKey .Values $camelCaseName }}{{ if hasKey (index .Values $camelCaseName) "scanner" }}{{ index (index .Values $camelCaseName) "scanner" }}{{ else if hasKey .Values "scanner" }}{{ .Values.scanner }}{{ else }}true{{ end }}{{ else if hasKey .Values "scanner" }}{{ .Values.scanner }}{{ else }}true{{ end }} + admission: {{ if hasKey .Values $camelCaseName }}{{ if hasKey (index .Values $camelCaseName) "admission" }}{{ index (index .Values $camelCaseName) "admission" }}{{ else if hasKey .Values "admission" }}{{ .Values.admission }}{{ else }}true{{ end }}{{ else if hasKey .Values "admission" }}{{ .Values.admission }}{{ else }}true{{ end }} + rules: + - name: {{ $name }} + identifier: payload.family + match: + all: + - (metadata.provider): AWS + - (metadata.service): ECS + - (metadata.resource): TaskDefinition + assert: + all: + - message: >- + Memory limit for container definitions should be set in the task definition + check: + payload: + ~.(containerDefinitions): + (!memory): false +{{- end }} +{{- end }} \ No newline at end of file diff --git a/charts/cloud-controls/charts/ecs/templates/validate-ecs-task-definition-nonroot-user.yaml b/charts/cloud-controls/charts/ecs/templates/validate-ecs-task-definition-nonroot-user.yaml new file mode 100644 index 00000000..6bf786a8 --- /dev/null +++ b/charts/cloud-controls/charts/ecs/templates/validate-ecs-task-definition-nonroot-user.yaml @@ -0,0 +1,44 @@ +{{- if .Values.enabled }} +{{- $camelCaseName := "validateEcsTaskDefinitionNonrootUser" }} +{{- $name := "validate-ecs-task-definition-nonroot-user" }} +{{- if not (has $name .Values.disabledPolicies) }} +apiVersion: {{ .Values.global.apiVersion | default "nirmata.io/v1alpha1" }} +kind: {{ .Values.global.policyKind | default "ValidatingPolicy" }} +metadata: + name: {{ $name }} + annotations: + policies.kyverno.io/title: Validate ECS Task Definition Nonroot User for EC2 Instances + policies.kyverno.io/category: ECS Best Practices + policies.kyverno.io/severity: medium + policies.kyverno.io/description: >- + This policy checks if ECSTaskDefinitions specify a user for + Amazon Elastic Container Service (Amazon ECS) EC2 launch type + containers to run on. The rule fails if the `user` parameter is not present or is `root`. + Running containers as non-root users can help prevent running commands with root privileges + which adds an extra layer of security by limiting the potential damage a compromised container can do. + It also follows the security principle of least privilege, which dictates that applications and processes + should operate with minimum privileges necessary to perform their functions. + labels: + app: kyverno +spec: + failureAction: {{ if hasKey .Values $camelCaseName }}{{ if hasKey (index .Values $camelCaseName) "failureAction" }}{{ index (index .Values $camelCaseName) "failureAction" }}{{ else }}{{ .Values.failureAction | default "Audit" }}{{ end }}{{ else }}{{ .Values.failureAction | default "Audit" }}{{ end }} + scan: {{ if hasKey .Values $camelCaseName }}{{ if hasKey (index .Values $camelCaseName) "scanner" }}{{ index (index .Values $camelCaseName) "scanner" }}{{ else if hasKey .Values "scanner" }}{{ .Values.scanner }}{{ else }}true{{ end }}{{ else if hasKey .Values "scanner" }}{{ .Values.scanner }}{{ else }}true{{ end }} + admission: {{ if hasKey .Values $camelCaseName }}{{ if hasKey (index .Values $camelCaseName) "admission" }}{{ index (index .Values $camelCaseName) "admission" }}{{ else if hasKey .Values "admission" }}{{ .Values.admission }}{{ else }}true{{ end }}{{ else if hasKey .Values "admission" }}{{ .Values.admission }}{{ else }}true{{ end }} + rules: + - name: {{ $name }} + identifier: payload.family + match: + all: + - (metadata.provider): AWS + - (metadata.service): ECS + - (metadata.resource): TaskDefinition + assert: + all: + - message: >- + For ECS EC2 containers, `user` parameter should not be unset or be root + check: + payload: + ~.(containerDefinitions): + (user == null || user == 'root' || user == '0' || starts_with(user, '0:') || ends_with(user, ':0')): false +{{- end }} +{{- end }} \ No newline at end of file diff --git a/charts/cloud-controls/charts/ecs/templates/validate-ecs-task-definition-pid-mode-check.yaml b/charts/cloud-controls/charts/ecs/templates/validate-ecs-task-definition-pid-mode-check.yaml new file mode 100644 index 00000000..a07c9dc6 --- /dev/null +++ b/charts/cloud-controls/charts/ecs/templates/validate-ecs-task-definition-pid-mode-check.yaml @@ -0,0 +1,41 @@ +{{- if .Values.enabled }} +{{- $camelCaseName := "validateEcsTaskDefinitionPidModeCheck" }} +{{- $name := "validate-ecs-task-definition-pid-mode-check" }} +{{- if not (has $name .Values.disabledPolicies) }} +apiVersion: {{ .Values.global.apiVersion | default "nirmata.io/v1alpha1" }} +kind: {{ .Values.global.policyKind | default "ValidatingPolicy" }} +metadata: + name: {{ $name }} + annotations: + policies.kyverno.io/title: Validate ECS Task Definition PID Mode Check + policies.kyverno.io/category: ECS Best Practices + policies.kyverno.io/severity: medium + policies.kyverno.io/description: >- + This policy ensures that Amazon ECS Task Definitions do not share the host's process namespace with its containers. + If the host's process namespace is shared with containers, it would allow containers to see all of the processes on the host system. + This reduces the benefit of process level isolation between the host and the containers. + These circumstances could lead to unauthorized access to processes on the host itself, including + the ability to manipulate and terminate them. Customers shouldn't share the host's process namespace with containers running on it. + labels: + app: kyverno +spec: + failureAction: {{ if hasKey .Values $camelCaseName }}{{ if hasKey (index .Values $camelCaseName) "failureAction" }}{{ index (index .Values $camelCaseName) "failureAction" }}{{ else }}{{ .Values.failureAction | default "Audit" }}{{ end }}{{ else }}{{ .Values.failureAction | default "Audit" }}{{ end }} + scan: {{ if hasKey .Values $camelCaseName }}{{ if hasKey (index .Values $camelCaseName) "scanner" }}{{ index (index .Values $camelCaseName) "scanner" }}{{ else if hasKey .Values "scanner" }}{{ .Values.scanner }}{{ else }}true{{ end }}{{ else if hasKey .Values "scanner" }}{{ .Values.scanner }}{{ else }}true{{ end }} + admission: {{ if hasKey .Values $camelCaseName }}{{ if hasKey (index .Values $camelCaseName) "admission" }}{{ index (index .Values $camelCaseName) "admission" }}{{ else if hasKey .Values "admission" }}{{ .Values.admission }}{{ else }}true{{ end }}{{ else if hasKey .Values "admission" }}{{ .Values.admission }}{{ else }}true{{ end }} + rules: + - name: {{ $name }} + identifier: payload.family + match: + all: + - (metadata.provider): AWS + - (metadata.service): ECS + - (metadata.resource): TaskDefinition + assert: + all: + - message: >- + ECS task definitions containers should not share the host's process namespace + check: + payload: + (pidMode != 'host'): true +{{- end }} +{{- end }} \ No newline at end of file diff --git a/charts/cloud-controls/charts/ecs/templates/validate-ecs-task-definition-user-for-host-mode-check.yaml b/charts/cloud-controls/charts/ecs/templates/validate-ecs-task-definition-user-for-host-mode-check.yaml new file mode 100644 index 00000000..46b3ea8e --- /dev/null +++ b/charts/cloud-controls/charts/ecs/templates/validate-ecs-task-definition-user-for-host-mode-check.yaml @@ -0,0 +1,41 @@ +{{- if .Values.enabled }} +{{- $camelCaseName := "validateEcsTaskDefinitionUserForHostModeCheck" }} +{{- $name := "validate-ecs-task-definition-user-for-host-mode-check" }} +{{- if not (has $name .Values.disabledPolicies) }} +apiVersion: {{ .Values.global.apiVersion | default "nirmata.io/v1alpha1" }} +kind: {{ .Values.global.policyKind | default "ValidatingPolicy" }} +metadata: + name: {{ $name }} + annotations: + policies.kyverno.io/title: Validate ECS Task Definition User for Host Mode + policies.kyverno.io/category: ECS Best Practices + policies.kyverno.io/severity: medium + policies.kyverno.io/description: >- + This policy ensures that ECS task definitions avoid using the root user for the host network mode when privileged is set to false or is not specified. + In scenarios where tasks employ the `host` network mode, it's crucial to avoid running containers with the root user (UID 0) for enhanced security. + As a recommended security practice, it is recommended to opt for a non-root user. + labels: + app: kyverno +spec: + failureAction: {{ if hasKey .Values $camelCaseName }}{{ if hasKey (index .Values $camelCaseName) "failureAction" }}{{ index (index .Values $camelCaseName) "failureAction" }}{{ else }}{{ .Values.failureAction | default "Audit" }}{{ end }}{{ else }}{{ .Values.failureAction | default "Audit" }}{{ end }} + scan: {{ if hasKey .Values $camelCaseName }}{{ if hasKey (index .Values $camelCaseName) "scanner" }}{{ index (index .Values $camelCaseName) "scanner" }}{{ else if hasKey .Values "scanner" }}{{ .Values.scanner }}{{ else }}true{{ end }}{{ else if hasKey .Values "scanner" }}{{ .Values.scanner }}{{ else }}true{{ end }} + admission: {{ if hasKey .Values $camelCaseName }}{{ if hasKey (index .Values $camelCaseName) "admission" }}{{ index (index .Values $camelCaseName) "admission" }}{{ else if hasKey .Values "admission" }}{{ .Values.admission }}{{ else }}true{{ end }}{{ else if hasKey .Values "admission" }}{{ .Values.admission }}{{ else }}true{{ end }} + rules: + - name: {{ $name }} + identifier: payload.family + match: + all: + - (metadata.provider): AWS + - (metadata.service): ECS + - (metadata.resource): TaskDefinition + assert: + all: + - message: >- + User should be set to a non-root user when NetworkMode is set to host and privileged is set to false or not specified + check: + payload: + ~.(containerDefinitions[?!privileged]): + (user == null || user == 'root' || user == '0' || starts_with(user, '0:') || ends_with(user, ':0')): false +{{- end }} +{{- end }} + \ No newline at end of file diff --git a/charts/cloud-controls/charts/ecs/templates/validate-ecs-task-public-ip.yaml b/charts/cloud-controls/charts/ecs/templates/validate-ecs-task-public-ip.yaml new file mode 100644 index 00000000..f43bb42a --- /dev/null +++ b/charts/cloud-controls/charts/ecs/templates/validate-ecs-task-public-ip.yaml @@ -0,0 +1,41 @@ +{{- if .Values.enabled }} +{{- $camelCaseName := "validateEcsTaskPublicIp" }} +{{- $name := "validate-ecs-task-public-ip" }} +{{- if not (has $name .Values.disabledPolicies) }} +apiVersion: {{ .Values.global.apiVersion | default "nirmata.io/v1alpha1" }} +kind: {{ .Values.global.policyKind | default "ValidatingPolicy" }} +metadata: + name: {{ $name }} + annotations: + policies.kyverno.io/title: Validate ECS Task Public IP + policies.kyverno.io/category: ECS Best Practices + policies.kyverno.io/severity: medium + policies.kyverno.io/description: >- + ECS tasks with public IP address enabled, are easily reachable from the internet. + This policy validates whether public IP address is enabled on the ECS task + labels: + app: kyverno +spec: + failureAction: {{ if hasKey .Values $camelCaseName }}{{ if hasKey (index .Values $camelCaseName) "failureAction" }}{{ index (index .Values $camelCaseName) "failureAction" }}{{ else }}{{ .Values.failureAction | default "Audit" }}{{ end }}{{ else }}{{ .Values.failureAction | default "Audit" }}{{ end }} + scan: {{ if hasKey .Values $camelCaseName }}{{ if hasKey (index .Values $camelCaseName) "scanner" }}{{ index (index .Values $camelCaseName) "scanner" }}{{ else if hasKey .Values "scanner" }}{{ .Values.scanner }}{{ else }}true{{ end }}{{ else if hasKey .Values "scanner" }}{{ .Values.scanner }}{{ else }}true{{ end }} + admission: {{ if hasKey .Values $camelCaseName }}{{ if hasKey (index .Values $camelCaseName) "admission" }}{{ index (index .Values $camelCaseName) "admission" }}{{ else if hasKey .Values "admission" }}{{ .Values.admission }}{{ else }}true{{ end }}{{ else if hasKey .Values "admission" }}{{ .Values.admission }}{{ else }}true{{ end }} + rules: + - name: {{ $name }} + identifier: payload.family + match: + all: + - (metadata.provider): AWS + - (metadata.service): ECS + - (metadata.resource): Service + assert: + all: + - message: >- + Public IP address should not be enabled + check: + payload: + networkConfiguration: + awsvpcConfiguration: + assignPublicIp: DISABLED +{{- end }} +{{- end }} + \ No newline at end of file diff --git a/charts/cloud-controls/charts/ecs/templates/validate-efs-volume-encryption.yaml b/charts/cloud-controls/charts/ecs/templates/validate-efs-volume-encryption.yaml new file mode 100644 index 00000000..d7294338 --- /dev/null +++ b/charts/cloud-controls/charts/ecs/templates/validate-efs-volume-encryption.yaml @@ -0,0 +1,40 @@ +{{- if .Values.enabled }} +{{- $camelCaseName := "validateEfsVolumeEncryption" }} +{{- $name := "validate-efs-volume-encryption" }} +{{- if not (has $name .Values.disabledPolicies) }} +apiVersion: {{ .Values.global.apiVersion | default "nirmata.io/v1alpha1" }} +kind: {{ .Values.global.policyKind | default "ValidatingPolicy" }} +metadata: + name: {{ $name }} + annotations: + policies.kyverno.io/title: Validate EFS Volume Encryption + policies.kyverno.io/category: ECS Best Practices + policies.kyverno.io/severity: medium + policies.kyverno.io/description: >- + Amazon EFS file systems can be used with Amazon ECS to export file system data across your fleet of container instances. + To ensure encryption is enabled in transit, this policy validates whether `transitEncryption` is set to ENABLED in the task definition. + labels: + app: kyverno +spec: + failureAction: {{ if hasKey .Values $camelCaseName }}{{ if hasKey (index .Values $camelCaseName) "failureAction" }}{{ index (index .Values $camelCaseName) "failureAction" }}{{ else }}{{ .Values.failureAction | default "Audit" }}{{ end }}{{ else }}{{ .Values.failureAction | default "Audit" }}{{ end }} + scan: {{ if hasKey .Values $camelCaseName }}{{ if hasKey (index .Values $camelCaseName) "scanner" }}{{ index (index .Values $camelCaseName) "scanner" }}{{ else if hasKey .Values "scanner" }}{{ .Values.scanner }}{{ else }}true{{ end }}{{ else if hasKey .Values "scanner" }}{{ .Values.scanner }}{{ else }}true{{ end }} + admission: {{ if hasKey .Values $camelCaseName }}{{ if hasKey (index .Values $camelCaseName) "admission" }}{{ index (index .Values $camelCaseName) "admission" }}{{ else if hasKey .Values "admission" }}{{ .Values.admission }}{{ else }}true{{ end }}{{ else if hasKey .Values "admission" }}{{ .Values.admission }}{{ else }}true{{ end }} + rules: + - name: {{ $name }} + identifier: payload.family + match: + all: + - (metadata.provider): AWS + - (metadata.service): ECS + - (metadata.resource): TaskDefinition + assert: + all: + - message: >- + Transit Encryption should be set to ENABLED for EFS volumes in ECS Task Definitions + check: + payload: + ~.(volumes[?eFSVolumeConfiguration || efsVolumeConfiguration]): + (eFSVolumeConfiguration || efsVolumeConfiguration): + transitEncryption: ENABLED +{{- end }} +{{- end }} \ No newline at end of file diff --git a/charts/cloud-controls/charts/eks/.helmignore b/charts/cloud-controls/charts/eks/.helmignore new file mode 100644 index 00000000..0e8a0eb3 --- /dev/null +++ b/charts/cloud-controls/charts/eks/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/charts/cloud-controls/charts/eks/Chart.yaml b/charts/cloud-controls/charts/eks/Chart.yaml new file mode 100644 index 00000000..cdcb71c3 --- /dev/null +++ b/charts/cloud-controls/charts/eks/Chart.yaml @@ -0,0 +1,14 @@ +apiVersion: v2 +name: aws-eks-best-practices +description: Aws EKS Best Practices CloudController Policy Set +type: application +version: 0.0.1 +keywords: + - kubernetes + - nirmata + - kyverno + - policy + - cloud-controller +maintainers: + - name: Nirmata + url: https://nirmata.com/ diff --git a/charts/cloud-controls/charts/eks/templates/check-public-access-cidr.yaml b/charts/cloud-controls/charts/eks/templates/check-public-access-cidr.yaml new file mode 100644 index 00000000..99ac2aff --- /dev/null +++ b/charts/cloud-controls/charts/eks/templates/check-public-access-cidr.yaml @@ -0,0 +1,37 @@ +{{- if .Values.enabled }} +{{- $camelCaseName := "checkPublicAccessCidr" }} +{{- $name := "check-public-access-cidr" }} +{{- if not (has $name .Values.disabledPolicies) }} +apiVersion: {{ .Values.global.apiVersion | default "nirmata.io/v1alpha1" }} +kind: {{ .Values.global.policyKind | default "ValidatingPolicy" }} +metadata: + name: {{ $name }} + annotations: + policies.kyverno.io/title: Check Public Access Cidr + policies.kyverno.io/category: EKS Best Practices + policies.kyverno.io/severity: high + policies.kyverno.io/description: >- + Ensuring that the Amazon EKS public endpoint is not accessible to 0.0.0.0/0 is a fundamental security measure that helps protect your EKS clusters from unauthorized access, security threats, and compliance violations. + labels: + app: kyverno +spec: + failureAction: {{ if hasKey .Values $camelCaseName }}{{ if hasKey (index .Values $camelCaseName) "failureAction" }}{{ index (index .Values $camelCaseName) "failureAction" }}{{ else }}{{ .Values.failureAction | default "Audit" }}{{ end }}{{ else }}{{ .Values.failureAction | default "Audit" }}{{ end }} + scan: {{ if hasKey .Values $camelCaseName }}{{ if hasKey (index .Values $camelCaseName) "scanner" }}{{ index (index .Values $camelCaseName) "scanner" }}{{ else if hasKey .Values "scanner" }}{{ .Values.scanner }}{{ else }}true{{ end }}{{ else if hasKey .Values "scanner" }}{{ .Values.scanner }}{{ else }}true{{ end }} + admission: {{ if hasKey .Values $camelCaseName }}{{ if hasKey (index .Values $camelCaseName) "admission" }}{{ index (index .Values $camelCaseName) "admission" }}{{ else if hasKey .Values "admission" }}{{ .Values.admission }}{{ else }}true{{ end }}{{ else if hasKey .Values "admission" }}{{ .Values.admission }}{{ else }}true{{ end }} + rules: + - name: {{ $name }} + identifier: payload.clusterName + match: + all: + - (metadata.provider): "AWS" + - (metadata.service): EKS + - (metadata.resource): "Cluster" + assert: + all: + - message: "Ensuring that the Amazon EKS public endpoint is not accessible to 0.0.0.0/0" + check: + payload: + resourcesVpcConfig: + ((endpointPublicAccess == `false`) || (endpointPublicAccess == `true` && publicAccessCidrs[?@ == '0.0.0.0/0'] | length(@) == `0`)): true +{{- end }} +{{- end }} diff --git a/charts/cloud-controls/charts/eks/templates/check-public-endpoint.yaml b/charts/cloud-controls/charts/eks/templates/check-public-endpoint.yaml new file mode 100644 index 00000000..94c7ae6b --- /dev/null +++ b/charts/cloud-controls/charts/eks/templates/check-public-endpoint.yaml @@ -0,0 +1,39 @@ +{{- if .Values.enabled }} +{{- $camelCaseName := "checkPublicEndpoint" }} +{{- $name := "check-public-endpoint" }} +{{- if not (has $name .Values.disabledPolicies) }} +apiVersion: {{ .Values.global.apiVersion | default "nirmata.io/v1alpha1" }} +kind: {{ .Values.global.policyKind | default "ValidatingPolicy" }} +metadata: + name: check-public-endpoint + annotations: + policies.kyverno.io/title: Check Public Endpoint + policies.kyverno.io/category: EKS Best Practices + policies.kyverno.io/severity: high + policies.kyverno.io/description: >- + Disabling the public endpoint minimizes the risk of unauthorized access and potential security breaches by reducing the attack surface of the EKS control plane. + It protects against external threats and enforces network segmentation, restricting access to only trusted entities within the network environment. + This measure helps organizations meet compliance requirements, maintains operational security, and safeguards the reliability and performance of Kubernetes clusters. + labels: + app: kyverno +spec: + failureAction: {{ if hasKey .Values $camelCaseName }}{{ if hasKey (index .Values $camelCaseName) "failureAction" }}{{ index (index .Values $camelCaseName) "failureAction" }}{{ else }}{{ .Values.failureAction | default "Audit" }}{{ end }}{{ else }}{{ .Values.failureAction | default "Audit" }}{{ end }} + scan: {{ if hasKey .Values $camelCaseName }}{{ if hasKey (index .Values $camelCaseName) "scanner" }}{{ index (index .Values $camelCaseName) "scanner" }}{{ else if hasKey .Values "scanner" }}{{ .Values.scanner }}{{ else }}true{{ end }}{{ else if hasKey .Values "scanner" }}{{ .Values.scanner }}{{ else }}true{{ end }} + admission: {{ if hasKey .Values $camelCaseName }}{{ if hasKey (index .Values $camelCaseName) "admission" }}{{ index (index .Values $camelCaseName) "admission" }}{{ else if hasKey .Values "admission" }}{{ .Values.admission }}{{ else }}true{{ end }}{{ else if hasKey .Values "admission" }}{{ .Values.admission }}{{ else }}true{{ end }} + rules: + - name: {{ $name }} + identifier: payload.clusterName + match: + all: + - (metadata.provider): "AWS" + - (metadata.service): EKS + - (metadata.resource): "Cluster" + assert: + all: + - message: "Public access to EKS cluster endpoint must be explicitly set to false" + check: + payload: + resourcesVpcConfig: + endpointPublicAccess: false +{{- end }} +{{- end }} \ No newline at end of file diff --git a/charts/cloud-controls/charts/eks/templates/check-secrets-encryption.yaml b/charts/cloud-controls/charts/eks/templates/check-secrets-encryption.yaml new file mode 100644 index 00000000..e3e373c8 --- /dev/null +++ b/charts/cloud-controls/charts/eks/templates/check-secrets-encryption.yaml @@ -0,0 +1,36 @@ +{{- if .Values.enabled }} +{{- $camelCaseName := "checkSecretsEncryption" }} +{{- $name := "check-secrets-encryption" }} +{{- if not (has $name .Values.disabledPolicies) }} +apiVersion: {{ .Values.global.apiVersion | default "nirmata.io/v1alpha1" }} +kind: {{ .Values.global.policyKind | default "ValidatingPolicy" }} +metadata: + name: {{ $name }} + annotations: + policies.kyverno.io/title: Check Cluster Secrets Encryption + policies.kyverno.io/category: EKS Best Practices + policies.kyverno.io/severity: medium + policies.kyverno.io/description: >- + Cluster secrets encryption should be enabled. + labels: + app: kyverno +spec: + failureAction: {{ if hasKey .Values $camelCaseName }}{{ if hasKey (index .Values $camelCaseName) "failureAction" }}{{ index (index .Values $camelCaseName) "failureAction" }}{{ else }}{{ .Values.failureAction | default "Audit" }}{{ end }}{{ else }}{{ .Values.failureAction | default "Audit" }}{{ end }} + scan: {{ if hasKey .Values $camelCaseName }}{{ if hasKey (index .Values $camelCaseName) "scanner" }}{{ index (index .Values $camelCaseName) "scanner" }}{{ else if hasKey .Values "scanner" }}{{ .Values.scanner }}{{ else }}true{{ end }}{{ else if hasKey .Values "scanner" }}{{ .Values.scanner }}{{ else }}true{{ end }} + admission: {{ if hasKey .Values $camelCaseName }}{{ if hasKey (index .Values $camelCaseName) "admission" }}{{ index (index .Values $camelCaseName) "admission" }}{{ else if hasKey .Values "admission" }}{{ .Values.admission }}{{ else }}true{{ end }}{{ else if hasKey .Values "admission" }}{{ .Values.admission }}{{ else }}true{{ end }} + rules: + - name: check-secrets-encryption + identifier: payload.name + match: + all: + - (metadata.provider): "AWS" + - (metadata.service): EKS + - (metadata.resource): "Cluster" + assert: + all: + - message: "Secrets encryption is enabled. The field cluster.encryptionConfig is defined for secrets." + check: + payload: + (encryptionConfig[].resources[] | contains(@, 'secrets')): true +{{- end }} +{{- end }} \ No newline at end of file diff --git a/charts/cloud-controls/charts/eks/templates/check-supported-k8s-version.yaml b/charts/cloud-controls/charts/eks/templates/check-supported-k8s-version.yaml new file mode 100644 index 00000000..2a6ada58 --- /dev/null +++ b/charts/cloud-controls/charts/eks/templates/check-supported-k8s-version.yaml @@ -0,0 +1,43 @@ +{{- if .Values.enabled }} +{{- $camelCaseName := "checkSupportedK8sVersion" }} +{{- $name := "check-supported-k8s-version" }} +{{- if not (has $name .Values.disabledPolicies) }} +apiVersion: {{ .Values.global.apiVersion | default "nirmata.io/v1alpha1" }} +kind: {{ .Values.global.policyKind | default "ValidatingPolicy" }} +metadata: + name: {{ $name }} + annotations: + policies.kyverno.io/title: Check Supported K8s Version + policies.kyverno.io/category: EKS Best Practices + policies.kyverno.io/severity: medium + policies.kyverno.io/description: >- + This policy checks that EKS clusters are on a standard supported Kubernetes version + labels: + app: kyverno +spec: + failureAction: {{ if hasKey .Values $camelCaseName }}{{ if hasKey (index .Values $camelCaseName) "failureAction" }}{{ index (index .Values $camelCaseName) "failureAction" }}{{ else }}{{ .Values.failureAction | default "Audit" }}{{ end }}{{ else }}{{ .Values.failureAction | default "Audit" }}{{ end }} + scan: {{ if hasKey .Values $camelCaseName }}{{ if hasKey (index .Values $camelCaseName) "scanner" }}{{ index (index .Values $camelCaseName) "scanner" }}{{ else if hasKey .Values "scanner" }}{{ .Values.scanner }}{{ else }}true{{ end }}{{ else if hasKey .Values "scanner" }}{{ .Values.scanner }}{{ else }}true{{ end }} + admission: {{ if hasKey .Values $camelCaseName }}{{ if hasKey (index .Values $camelCaseName) "admission" }}{{ index (index .Values $camelCaseName) "admission" }}{{ else if hasKey .Values "admission" }}{{ .Values.admission }}{{ else }}true{{ end }}{{ else if hasKey .Values "admission" }}{{ .Values.admission }}{{ else }}true{{ end }} + rules: + - name: {{ $name }} + identifier: payload.name + match: + all: + - (metadata.provider): "AWS" + - (metadata.service): EKS + - (metadata.resource): "Cluster" + context: + - name: supported_k8s_versions + variable: + - '1.29' + - '1.30' + - '1.31' + assert: + all: + - message: "Version specified must be one of these suppported versions ['1.29', '1.30', '1.31']" + check: + payload: + version: + (contains($supported_k8s_versions, @)): true +{{- end }} +{{- end }} \ No newline at end of file diff --git a/charts/cloud-controls/charts/lambda/.helmignore b/charts/cloud-controls/charts/lambda/.helmignore new file mode 100644 index 00000000..0e8a0eb3 --- /dev/null +++ b/charts/cloud-controls/charts/lambda/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/charts/cloud-controls/charts/lambda/Chart.yaml b/charts/cloud-controls/charts/lambda/Chart.yaml new file mode 100644 index 00000000..61456bda --- /dev/null +++ b/charts/cloud-controls/charts/lambda/Chart.yaml @@ -0,0 +1,14 @@ +apiVersion: v2 +name: aws-lambda-best-practices +description: Aws Lambda Best Practices CloudController Policy Set +type: application +version: 0.0.1 +keywords: + - kubernetes + - nirmata + - kyverno + - policy + - cloud-controller +maintainers: + - name: Nirmata + url: https://nirmata.com/ diff --git a/charts/cloud-controls/charts/lambda/templates/check-dead-letter-queue.yaml b/charts/cloud-controls/charts/lambda/templates/check-dead-letter-queue.yaml new file mode 100644 index 00000000..4bd10772 --- /dev/null +++ b/charts/cloud-controls/charts/lambda/templates/check-dead-letter-queue.yaml @@ -0,0 +1,38 @@ +{{- if .Values.enabled }} +{{- $camelCaseName := "checkDeadLetterQueueConfig" }} +{{- $name := "check-dead-letter-queue-config" }} +{{- if not (has $name .Values.disabledPolicies) }} +apiVersion: {{ .Values.global.apiVersion | default "nirmata.io/v1alpha1" }} +kind: {{ .Values.global.policyKind | default "ValidatingPolicy" }} +metadata: + name: {{ $name }} + annotations: + policies.kyverno.io/title: check-dead-letter-queue-config + policies.kyverno.io/category: AWS Lambda Best Practices + policies.kyverno.io/severity: medium + policies.kyverno.io/description: >- + Ensure that AWS Lambda function is configured for a Dead Letter Queue(DLQ). + labels: + app: kyverno +spec: + failureAction: {{ if hasKey .Values $camelCaseName }}{{ if hasKey (index .Values $camelCaseName) "failureAction" }}{{ index (index .Values $camelCaseName) "failureAction" }}{{ else }}{{ .Values.failureAction | default "Audit" }}{{ end }}{{ else }}{{ .Values.failureAction | default "Audit" }}{{ end }} + scan: {{ if hasKey .Values $camelCaseName }}{{ if hasKey (index .Values $camelCaseName) "scanner" }}{{ index (index .Values $camelCaseName) "scanner" }}{{ else if hasKey .Values "scanner" }}{{ .Values.scanner }}{{ else }}true{{ end }}{{ else if hasKey .Values "scanner" }}{{ .Values.scanner }}{{ else }}true{{ end }} + admission: {{ if hasKey .Values $camelCaseName }}{{ if hasKey (index .Values $camelCaseName) "admission" }}{{ index (index .Values $camelCaseName) "admission" }}{{ else if hasKey .Values "admission" }}{{ .Values.admission }}{{ else }}true{{ end }}{{ else if hasKey .Values "admission" }}{{ .Values.admission }}{{ else }}true{{ end }} + rules: + - name: {{ $name }} + identifier: payload.functionName + match: + all: + - (metadata.provider): "AWS" + - (metadata.service): "Lambda" + - (metadata.resource): "Function" + assert: + all: + - message: AWS Lambda function should be configured for a Dead Letter Queue. + check: + payload: + deadLetterConfig: + (targetArn != null): true +{{- end }} +{{- end }} + diff --git a/charts/cloud-controls/charts/lambda/templates/check-env-var-encryption.yaml b/charts/cloud-controls/charts/lambda/templates/check-env-var-encryption.yaml new file mode 100644 index 00000000..b597c343 --- /dev/null +++ b/charts/cloud-controls/charts/lambda/templates/check-env-var-encryption.yaml @@ -0,0 +1,36 @@ +{{- if .Values.enabled }} +{{- $camelCaseName := "checkEnvVarEncryption" }} +{{- $name := "check-env-var-encryption" }} +{{- if not (has $name .Values.disabledPolicies) }} +apiVersion: {{ .Values.global.apiVersion | default "nirmata.io/v1alpha1" }} +kind: {{ .Values.global.policyKind | default "ValidatingPolicy" }} +metadata: + name: {{ $name }} + annotations: + policies.kyverno.io/title: check-env-var-encryption + policies.kyverno.io/category: AWS Lambda Best Practices + policies.kyverno.io/severity: medium + policies.kyverno.io/description: >- + This policy ensures that if environment variables are used in a Lambda function, they should be encrypted. + labels: + app: kyverno +spec: + failureAction: {{ if hasKey .Values $camelCaseName }}{{ if hasKey (index .Values $camelCaseName) "failureAction" }}{{ index (index .Values $camelCaseName) "failureAction" }}{{ else }}{{ .Values.failureAction | default "Audit" }}{{ end }}{{ else }}{{ .Values.failureAction | default "Audit" }}{{ end }} + scan: {{ if hasKey .Values $camelCaseName }}{{ if hasKey (index .Values $camelCaseName) "scanner" }}{{ index (index .Values $camelCaseName) "scanner" }}{{ else if hasKey .Values "scanner" }}{{ .Values.scanner }}{{ else }}true{{ end }}{{ else if hasKey .Values "scanner" }}{{ .Values.scanner }}{{ else }}true{{ end }} + admission: {{ if hasKey .Values $camelCaseName }}{{ if hasKey (index .Values $camelCaseName) "admission" }}{{ index (index .Values $camelCaseName) "admission" }}{{ else if hasKey .Values "admission" }}{{ .Values.admission }}{{ else }}true{{ end }}{{ else if hasKey .Values "admission" }}{{ .Values.admission }}{{ else }}true{{ end }} + rules: + - name: {{ $name }} + identifier: payload.functionName + match: + all: + - (metadata.provider): "AWS" + - (metadata.service): "Lambda" + - (metadata.resource): "Function" + assert: + all: + - message: Enable the encryption of environment variable for the AWS Lambda function by specifying correct value to "kms_key_arn" attribute. + check: + payload: + ((environment.variables == null && kmsKeyArn == null && kMSKeyArn == null) || (environment.variables != null && (kmsKeyArn != null || kMSKeyArn != null))): true +{{- end }} +{{- end }} \ No newline at end of file diff --git a/charts/cloud-controls/charts/lambda/templates/check-function-concurrency.yaml b/charts/cloud-controls/charts/lambda/templates/check-function-concurrency.yaml new file mode 100644 index 00000000..38523d6f --- /dev/null +++ b/charts/cloud-controls/charts/lambda/templates/check-function-concurrency.yaml @@ -0,0 +1,37 @@ +{{- if .Values.enabled }} +{{- $camelCaseName := "checkFunctionConcurrency" }} +{{- $name := "check-function-concurrency" }} +{{- if not (has $name .Values.disabledPolicies) }} +apiVersion: {{ .Values.global.apiVersion | default "nirmata.io/v1alpha1" }} +kind: {{ .Values.global.policyKind | default "ValidatingPolicy" }} +metadata: + name: {{ $name }} + annotations: + policies.kyverno.io/title: check-function-concurrency + policies.kyverno.io/category: AWS Lambda Best Practicess + policies.kyverno.io/severity: medium + policies.kyverno.io/description: >- + This policy checks whether concurrency level config is set for the Lambda function. + labels: + app: kyverno +spec: + failureAction: {{ if hasKey .Values $camelCaseName }}{{ if hasKey (index .Values $camelCaseName) "failureAction" }}{{ index (index .Values $camelCaseName) "failureAction" }}{{ else }}{{ .Values.failureAction | default "Audit" }}{{ end }}{{ else }}{{ .Values.failureAction | default "Audit" }}{{ end }} + scan: {{ if hasKey .Values $camelCaseName }}{{ if hasKey (index .Values $camelCaseName) "scanner" }}{{ index (index .Values $camelCaseName) "scanner" }}{{ else if hasKey .Values "scanner" }}{{ .Values.scanner }}{{ else }}true{{ end }}{{ else if hasKey .Values "scanner" }}{{ .Values.scanner }}{{ else }}true{{ end }} + admission: {{ if hasKey .Values $camelCaseName }}{{ if hasKey (index .Values $camelCaseName) "admission" }}{{ index (index .Values $camelCaseName) "admission" }}{{ else if hasKey .Values "admission" }}{{ .Values.admission }}{{ else }}true{{ end }}{{ else if hasKey .Values "admission" }}{{ .Values.admission }}{{ else }}true{{ end }} + rules: + - name: {{ $name }} + identifier: payload.functionName + match: + all: + - (metadata.provider): "AWS" + - (metadata.service): "Lambda" + - (metadata.resource): "Function" + assert: + all: + - message: Configure the AWS Lambda function for function-level concurrent execution limit using reserved_concurrent_execution attribute. + check: + payload: + (reservedConcurrentExecutions > `0`): true +{{- end }} +{{- end }} + diff --git a/charts/cloud-controls/charts/lambda/templates/check-lambda-runtime.yaml b/charts/cloud-controls/charts/lambda/templates/check-lambda-runtime.yaml new file mode 100644 index 00000000..7c8615df --- /dev/null +++ b/charts/cloud-controls/charts/lambda/templates/check-lambda-runtime.yaml @@ -0,0 +1,43 @@ +{{- if .Values.enabled }} +{{- $camelCaseName := "checkDeprecatedRuntime" }} +{{- $name := "check-deprecated-runtime" }} +{{- if not (has $name .Values.disabledPolicies) }} +apiVersion: {{ .Values.global.apiVersion | default "nirmata.io/v1alpha1" }} +kind: {{ .Values.global.policyKind | default "ValidatingPolicy" }} +metadata: + name: {{ $name }} + annotations: + policies.kyverno.io/title: check-deprecated-runtime + policies.kyverno.io/category: AWS Lambda Best Practices + policies.kyverno.io/severity: medium + policies.kyverno.io/description: >- + This policy ensures that Lambda Runtime is not deprecated + labels: + app: kyverno +spec: + failureAction: {{ if hasKey .Values $camelCaseName }}{{ if hasKey (index .Values $camelCaseName) "failureAction" }}{{ index (index .Values $camelCaseName) "failureAction" }}{{ else }}{{ .Values.failureAction | default "Audit" }}{{ end }}{{ else }}{{ .Values.failureAction | default "Audit" }}{{ end }} + scan: {{ if hasKey .Values $camelCaseName }}{{ if hasKey (index .Values $camelCaseName) "scanner" }}{{ index (index .Values $camelCaseName) "scanner" }}{{ else if hasKey .Values "scanner" }}{{ .Values.scanner }}{{ else }}true{{ end }}{{ else if hasKey .Values "scanner" }}{{ .Values.scanner }}{{ else }}true{{ end }} + admission: {{ if hasKey .Values $camelCaseName }}{{ if hasKey (index .Values $camelCaseName) "admission" }}{{ index (index .Values $camelCaseName) "admission" }}{{ else if hasKey .Values "admission" }}{{ .Values.admission }}{{ else }}true{{ end }}{{ else if hasKey .Values "admission" }}{{ .Values.admission }}{{ else }}true{{ end }} + rules: + - name: {{ $name }} + identifier: payload.functionName + match: + all: + - (metadata.provider): "AWS" + - (metadata.service): "Lambda" + - (metadata.resource): "Function" + context: + - name: forbidden_values + variable: + - python3.8 + - nodejs16.x + - dotnet7 + assert: + all: + - message: The runtime is deprecated for AWS lambda function, use another version. + check: + payload: + (contains($forbidden_values, runtime || '')): false +{{- end }} +{{- end }} + diff --git a/charts/cloud-controls/charts/lambda/templates/check-lambda-vpc.yaml b/charts/cloud-controls/charts/lambda/templates/check-lambda-vpc.yaml new file mode 100644 index 00000000..97e92e3d --- /dev/null +++ b/charts/cloud-controls/charts/lambda/templates/check-lambda-vpc.yaml @@ -0,0 +1,37 @@ +{{- if .Values.enabled }} +{{- $camelCaseName := "checkLambdaVpc" }} +{{- $name := "check-lambda-vpc" }} +{{- if not (has $name .Values.disabledPolicies) }} +apiVersion: {{ .Values.global.apiVersion | default "nirmata.io/v1alpha1" }} +kind: {{ .Values.global.policyKind | default "ValidatingPolicy" }} +metadata: + name: {{ $name }} + annotations: + policies.kyverno.io/title: Check Lambda VPC + policies.kyverno.io/category: AWS Lambda Best Practices + policies.kyverno.io/severity: medium + policies.kyverno.io/description: >- + VPC provides isolation and enhanced security to Lambda functions. + This policy validates whether vpc_config is specified for the Lambda function. + labels: + app: kyverno +spec: + failureAction: {{ if hasKey .Values $camelCaseName }}{{ if hasKey (index .Values $camelCaseName) "failureAction" }}{{ index (index .Values $camelCaseName) "failureAction" }}{{ else }}{{ .Values.failureAction | default "Audit" }}{{ end }}{{ else }}{{ .Values.failureAction | default "Audit" }}{{ end }} + scan: {{ if hasKey .Values $camelCaseName }}{{ if hasKey (index .Values $camelCaseName) "scanner" }}{{ index (index .Values $camelCaseName) "scanner" }}{{ else if hasKey .Values "scanner" }}{{ .Values.scanner }}{{ else }}true{{ end }}{{ else if hasKey .Values "scanner" }}{{ .Values.scanner }}{{ else }}true{{ end }} + admission: {{ if hasKey .Values $camelCaseName }}{{ if hasKey (index .Values $camelCaseName) "admission" }}{{ index (index .Values $camelCaseName) "admission" }}{{ else if hasKey .Values "admission" }}{{ .Values.admission }}{{ else }}true{{ end }}{{ else if hasKey .Values "admission" }}{{ .Values.admission }}{{ else }}true{{ end }} + rules: + - name: {{ $name }} + identifier: payload.functionName + match: + all: + - (metadata.provider): "AWS" + - (metadata.service): "Lambda" + - (metadata.resource): "Function" + assert: + all: + - message: VPCConfig must be present for the Lambda function + check: + payload: + (vpcConfig != null): true +{{- end }} +{{- end }} diff --git a/charts/cloud-controls/charts/lambda/templates/check-x-ray-tracing-enabled.yaml b/charts/cloud-controls/charts/lambda/templates/check-x-ray-tracing-enabled.yaml new file mode 100644 index 00000000..e1b27e51 --- /dev/null +++ b/charts/cloud-controls/charts/lambda/templates/check-x-ray-tracing-enabled.yaml @@ -0,0 +1,40 @@ +{{- if .Values.enabled }} +{{- $camelCaseName := "checkXRayTracingEnabled" }} +{{- $name := "check-x-ray-tracing-enabled" }} +{{- if not (has $name .Values.disabledPolicies) }} +apiVersion: {{ .Values.global.apiVersion | default "nirmata.io/v1alpha1" }} +kind: {{ .Values.global.policyKind | default "ValidatingPolicy" }} +metadata: + name: {{ $name }} + annotations: + policies.kyverno.io/title: check-x-ray-tracing-enabled + policies.kyverno.io/category: AWS Lambda Best Practices + policies.kyverno.io/severity: medium + policies.kyverno.io/description: >- + AWS X-Ray to visualize the components of your application, + identify performance bottlenecks, and troubleshoot requests that + resulted in an error. This policy checks whether X-Ray is enabled + for Labmda function. + labels: + app: kyverno +spec: + failureAction: {{ if hasKey .Values $camelCaseName }}{{ if hasKey (index .Values $camelCaseName) "failureAction" }}{{ index (index .Values $camelCaseName) "failureAction" }}{{ else }}{{ .Values.failureAction | default "Audit" }}{{ end }}{{ else }}{{ .Values.failureAction | default "Audit" }}{{ end }} + scan: {{ if hasKey .Values $camelCaseName }}{{ if hasKey (index .Values $camelCaseName) "scanner" }}{{ index (index .Values $camelCaseName) "scanner" }}{{ else if hasKey .Values "scanner" }}{{ .Values.scanner }}{{ else }}true{{ end }}{{ else if hasKey .Values "scanner" }}{{ .Values.scanner }}{{ else }}true{{ end }} + admission: {{ if hasKey .Values $camelCaseName }}{{ if hasKey (index .Values $camelCaseName) "admission" }}{{ index (index .Values $camelCaseName) "admission" }}{{ else if hasKey .Values "admission" }}{{ .Values.admission }}{{ else }}true{{ end }}{{ else if hasKey .Values "admission" }}{{ .Values.admission }}{{ else }}true{{ end }} + rules: + - name: {{ $name }} + identifier: payload.functionName + match: + all: + - (metadata.provider): "AWS" + - (metadata.service): "Lambda" + - (metadata.resource): "Function" + assert: + all: + - message: Use the `tracing_config` block in the `aws_lambda_function` resource to set the mode to `Active` + check: + payload: + tracingConfig: + (mode == 'Active'): true +{{- end }} +{{- end }} \ No newline at end of file diff --git a/charts/cloud-controls/values.yaml b/charts/cloud-controls/values.yaml new file mode 100644 index 00000000..8e368b32 --- /dev/null +++ b/charts/cloud-controls/values.yaml @@ -0,0 +1,29 @@ +aws-eks-best-practices: + failureAction: Audit + enabled: true + scanner: true + admission: true + disabledPolicies: [] + +aws-ecs-best-practices: + failureAction: Audit + enabled: true + scanner: true + admission: true + disabledPolicies: [] + # For policy-specific values, use the policy name in CamelCase format. + # Example: + # checkAwsvpcNetworkMode: + # failureAction: Enforce + # scanner: false + +aws-lambda-best-practices: + failureAction: Audit + enabled: true + scanner: true + admission: true + disabledPolicies: [] + +global: + policyKind: ValidatingPolicy + apiVersion: nirmata.io/v1alpha1