Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add k8sallowedreposv2 Policy with Exact Match & Glob Support #616

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Empty file modified LICENSE
100644 → 100755
Empty file.
Empty file modified Makefile
100644 → 100755
Empty file.
Empty file modified NOTICE
100644 → 100755
Empty file.
Empty file modified README.md
100644 → 100755
Empty file.
Empty file modified SECURITY.md
100644 → 100755
Empty file.
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name: k8sallowedrepos
displayName: Allowed Repositories
createdAt: "2023-10-30T20:59:57Z"
description: Requires container images to begin with a string from the specified list.
digest: eaff16a982c2d3029b280b3d4061d82b55215ac648efaafa341e25c7c77b635f
digest: 1ee1bb4b4fb6128bdcd6bd84c81d1d1e02b4b9c0f9bd3eb85f9fd30e82742dd1
license: Apache-2.0
homeURL: https://open-policy-agent.github.io/gatekeeper-library/website/allowedrepos
keywords:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ metadata:
metadata.gatekeeper.sh/version: 1.0.1
description: >-
Requires container images to begin with a string from the specified list.
To prevent bypasses, ensure a '/' is added when specifying DockerHub repositories or custom registries.
If exact matches or glob-like syntax are preferred, use the k8sallowedreposv2 policy.
spec:
crd:
spec:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
version: 1.0.0
name: k8sallowedreposv2
displayName: Allowed Images
createdAt: "2024-12-17T13:21:26Z"
description: 'This policy enforces that container images must begin with a string from a specified list. The updated version, K8sAllowedReposv2, introduces support for exact match and glob-like syntax to enhance security: 1. Exact Match: By default, if the * character is not specified, the policy strictly checks for an exact match of the full registry, repository, and/or the image name. 2. Glob-like Syntax: Adding * at the end of a prefix allows prefix-based matching (e.g., registry.example.com/project/*). Only the * wildcard at the end of a string is supported. 3. Security Note: To avoid bypasses scenarios, ensure prefixes include a trailing / where appropriate (e.g., registry.example.com/project/*).'
digest: f0cc8c9d1d326a9a23ae7a5c6e8a9c0b909e9fd1fab95fb5822519514e07a717
license: Apache-2.0
homeURL: https://open-policy-agent.github.io/gatekeeper-library/website/allowedreposv2
keywords:
- gatekeeper
- open-policy-agent
- policies
readme: |-
# Allowed Images
This policy enforces that container images must begin with a string from a specified list. The updated version, K8sAllowedReposv2, introduces support for exact match and glob-like syntax to enhance security: 1. Exact Match: By default, if the * character is not specified, the policy strictly checks for an exact match of the full registry, repository, and/or the image name. 2. Glob-like Syntax: Adding * at the end of a prefix allows prefix-based matching (e.g., registry.example.com/project/*). Only the * wildcard at the end of a string is supported. 3. Security Note: To avoid bypasses scenarios, ensure prefixes include a trailing / where appropriate (e.g., registry.example.com/project/*).
install: |-
### Usage
```shell
kubectl apply -f https://raw.githubusercontent.com/open-policy-agent/gatekeeper-library/master/artifacthub/library/general/allowedreposv2/1.0.0/template.yaml
```
provider:
name: Gatekeeper Library
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
resources:
- template.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sAllowedReposv2
metadata:
name: repo-is-openpolicyagent
spec:
match:
kinds:
- apiGroups: [""]
kinds: ["Pod"]
namespaces:
- "default"
parameters:
allowedImages:
- "openpolicyagent/*"
- "myregistry.azurecr.io/*"
- "mydockerhub/*"
- "ubuntu"
- "123456789123.dkr.ecr.eu-west-1.amazonaws.com/postgres"
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
apiVersion: v1
kind: Pod
metadata:
name: nginx-disallowed
spec:
initContainers:
- name: nginx
image: nginx
resources:
limits:
cpu: "100m"
memory: "30Mi"
containers:
- name: nginx
image: nginx
resources:
limits:
cpu: "100m"
memory: "30Mi"
ephemeralContainers:
- name: nginx
image: nginx
resources:
limits:
cpu: "100m"
memory: "30Mi"
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
apiVersion: v1
kind: Pod
metadata:
name: opa-allowed
spec:
containers:
- name: opa
image: openpolicyagent/opa:0.9.2
args:
- "run"
- "--server"
- "--addr=localhost:8080"
resources:
limits:
cpu: "100m"
memory: "30Mi"
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
apiVersion: v1
kind: Pod
metadata:
name: opa-allowed
spec:
containers:
- name: image
image: ubuntu
resources:
limits:
cpu: "100m"
memory: "30Mi"
- name: image_with_version
image: ubuntu:20.04
resources:
limits:
cpu: "200m"
memory: "50Mi"
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
apiVersion: v1
kind: Pod
metadata:
name: nginx-disallowed
spec:
initContainers:
- name: nginxinit
image: nginx
resources:
limits:
cpu: "100m"
memory: "30Mi"
containers:
- name: nginx
image: nginx
resources:
limits:
cpu: "100m"
memory: "30Mi"
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
apiVersion: v1
kind: Pod
metadata:
name: nginx-disallowed
spec:
containers:
- name: nginx
image: nginx
resources:
limits:
cpu: "100m"
memory: "30Mi"
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
apiVersion: v1
kind: Pod
metadata:
name: image-disallowed
spec:
containers:
- name: image-1-malicious-basic-image-disallow
image: ubuntumalicious
resources:
limits:
cpu: "100m"
memory: "30Mi"
- name: image-2-basic-image-allow
image: ubuntu
resources:
limits:
cpu: "200m"
memory: "50Mi"
- name: image-3-malicious-image-with-registry-disallow
image: 123456789123.dkr.ecr.eu-west-1.amazonaws.com/postgresmalicious
resources:
limits:
cpu: "50m"
memory: "10Mi"
- name: image-4-image-with-registry-allow
image: 123456789123.dkr.ecr.eu-west-1.amazonaws.com/postgres
resources:
limits:
cpu: "50m"
memory: "10Mi"
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
apiVersion: v1
kind: Pod
metadata:
name: nginx-disallowed
spec:
initContainers:
- name: nginxinit
image: nginx
resources:
limits:
cpu: "100m"
memory: "30Mi"
containers:
- name: opa
image: openpolicyagent/opa:0.9.2
args:
- "run"
- "--server"
- "--addr=localhost:8080"
resources:
limits:
cpu: "100m"
memory: "30Mi"
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
apiVersion: v1
kind: Pod
metadata:
name: registry-repository-disallowed
spec:
containers:
- name: image-1-malicious-registry-disallow
image: myregistry.azurecr.io.malicious.com/malicious-image
resources:
limits:
cpu: "100m"
memory: "30Mi"
- name: image-2-registry-allow
image: myregistry.azurecr.io/nginx
resources:
limits:
cpu: "200m"
memory: "50Mi"
- name: image-3-malicious-image-with-registry-disallow
image: mydockerhubmalicious/python
resources:
limits:
cpu: "50m"
memory: "10Mi"
- name: image-4-image-with-registry-allow
image: mydockerhub/python
resources:
limits:
cpu: "50m"
memory: "10Mi"
57 changes: 57 additions & 0 deletions artifacthub/library/general/allowedreposv2/1.0.0/suite.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
kind: Suite
apiVersion: test.gatekeeper.sh/v1alpha1
metadata:
name: allowedreposv2
tests:
- name: allowed-reposv2
template: template.yaml
constraint: samples/repo-must-be-openpolicyagent/constraint.yaml
cases:
- name: example-allowed
object: samples/repo-must-be-openpolicyagent/example_allowed.yaml
assertions:
- violations: no
- name: example-allowed-images
object: samples/repo-must-be-openpolicyagent/example_allowed_images.yaml
assertions:
- violations: 1
- name: container-disallowed
object: samples/repo-must-be-openpolicyagent/example_disallowed_container.yaml
assertions:
- violations: yes
message: container
- name: initcontainer-disallowed
object: samples/repo-must-be-openpolicyagent/example_disallowed_initcontainer.yaml
assertions:
- violations: 1
message: initContainer
- violations: 0
message: container
- name: both-disallowed
object: samples/repo-must-be-openpolicyagent/example_disallowed_both.yaml
assertions:
- violations: 2
- message: initContainer
violations: 1
- message: container
violations: 1
- name: all-disallowed
object: samples/repo-must-be-openpolicyagent/disallowed_all.yaml
assertions:
- violations: 3
- message: initContainer
violations: 1
- message: container
violations: 1
- message: ephemeralContainer
violations: 1
- name: disallowed-repository-and-registry
object: samples/repo-must-be-openpolicyagent/example_disallowed_registry_and_repository.yaml
assertions:
- violations: 2
- message: container
- name: disallowed-repository-images
object: samples/repo-must-be-openpolicyagent/example_disallowed_images.yaml
assertions:
- violations: 2
- message: container
63 changes: 63 additions & 0 deletions artifacthub/library/general/allowedreposv2/1.0.0/template.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
apiVersion: templates.gatekeeper.sh/v1
kind: ConstraintTemplate
metadata:
name: k8sallowedreposv2
annotations:
metadata.gatekeeper.sh/title: "Allowed Images"
metadata.gatekeeper.sh/version: 1.0.0
description: >-
This policy enforces that container images must begin with a string from a specified list.
The updated version, K8sAllowedReposv2, introduces support for exact match and glob-like syntax to enhance security:
1. Exact Match: By default, if the * character is not specified, the policy strictly checks for an exact match of the full registry, repository, and/or the image name.
2. Glob-like Syntax: Adding * at the end of a prefix allows prefix-based matching (e.g., registry.example.com/project/*). Only the * wildcard at the end of a string is supported.
3. Security Note: To avoid bypasses scenarios, ensure prefixes include a trailing / where appropriate (e.g., registry.example.com/project/*).
spec:
crd:
spec:
names:
kind: K8sAllowedReposv2
validation:
# Schema for the `parameters` field
openAPIV3Schema:
type: object
properties:
allowedImages:
description: A list of allowed container image prefixes. Supports exact matches and prefixes ending with '*'.
type: array
items:
type: string
targets:
- target: admission.k8s.gatekeeper.sh
rego: |
package k8sallowedreposv2

violation[{"msg": msg}] {
container := input.review.object.spec.containers[_]
not image_matches(container.image, input.parameters.allowedImages)
msg := sprintf("container <%v> has an invalid image <%v>, allowed images are %v", [container.name, container.image, input.parameters.allowedImages])
}

violation[{"msg": msg}] {
container := input.review.object.spec.initContainers[_]
not image_matches(container.image, input.parameters.allowedImages)
msg := sprintf("initContainer <%v> has an invalid image <%v>, allowed images are %v", [container.name, container.image, input.parameters.allowedImages])
}

violation[{"msg": msg}] {
container := input.review.object.spec.ephemeralContainers[_]
not image_matches(container.image, input.parameters.allowedImages)
msg := sprintf("ephemeralContainer <%v> has an invalid image <%v>, allowed images are %v", [container.name, container.image, input.parameters.allowedImages])
}

image_matches(image, images) {
i_image := images[_] # Iterate through all images in the allowed list
not endswith(i_image, "*") # Check for exact match if the image does not end with *
i_image == image
}

image_matches(image, images) {
i_image := images[_] # Iterate through all images in the allowed list
endswith(i_image, "*") # Check for prefix match if the image ends with *
prefix := trim_suffix(i_image, "*")
startswith(image, prefix)
}
Empty file modified go.work
100644 → 100755
Empty file.
2 changes: 2 additions & 0 deletions library/general/allowedrepos/template.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ metadata:
metadata.gatekeeper.sh/version: 1.0.1
description: >-
Requires container images to begin with a string from the specified list.
To prevent bypasses, ensure a '/' is added when specifying DockerHub repositories or custom registries.
If exact matches or glob-like syntax are preferred, use the k8sallowedreposv2 policy.
spec:
crd:
spec:
Expand Down
2 changes: 2 additions & 0 deletions library/general/allowedreposv2/kustomization.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
resources:
- template.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sAllowedReposv2
metadata:
name: repo-is-openpolicyagent
spec:
match:
kinds:
- apiGroups: [""]
kinds: ["Pod"]
namespaces:
- "default"
parameters:
allowedImages:
- "openpolicyagent/*"
- "myregistry.azurecr.io/*"
- "mydockerhub/*"
- "ubuntu"
- "123456789123.dkr.ecr.eu-west-1.amazonaws.com/postgres"
Loading