-
Notifications
You must be signed in to change notification settings - Fork 321
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
chore(k8spspcapabilities): double newlines can cause yamllint breakage (
#596) The default value for newlines in the yamllint linter (a commonly used tool for linting yaml) is 2. See https://yamllint.readthedocs.io/en/stable/rules.html#module-yamllint.rules.empty_lines for more info. This PR removes some unnecessary newlines in a rego file that trigger this linter rule. Signed-off-by: juliankatz <[email protected]>
- Loading branch information
1 parent
799d77b
commit 7a9e47d
Showing
13 changed files
with
375 additions
and
18 deletions.
There are no files selected for viewing
22 changes: 22 additions & 0 deletions
22
artifacthub/library/pod-security-policy/capabilities/1.1.1/artifacthub-pkg.yml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
version: 1.1.1 | ||
name: k8spspcapabilities | ||
displayName: Capabilities | ||
createdAt: "2024-09-07T00:11:09Z" | ||
description: Controls Linux capabilities on containers. Corresponds to the `allowedCapabilities` and `requiredDropCapabilities` fields in a PodSecurityPolicy. For more information, see https://kubernetes.io/docs/concepts/policy/pod-security-policy/#capabilities | ||
digest: 5abceb80cc25bb7daf6523ed1ebc485b8be6c763cf478e86a0269c4ce578772c | ||
license: Apache-2.0 | ||
homeURL: https://open-policy-agent.github.io/gatekeeper-library/website/capabilities | ||
keywords: | ||
- gatekeeper | ||
- open-policy-agent | ||
- policies | ||
readme: |- | ||
# Capabilities | ||
Controls Linux capabilities on containers. Corresponds to the `allowedCapabilities` and `requiredDropCapabilities` fields in a PodSecurityPolicy. For more information, see https://kubernetes.io/docs/concepts/policy/pod-security-policy/#capabilities | ||
install: |- | ||
### Usage | ||
```shell | ||
kubectl apply -f https://raw.githubusercontent.com/open-policy-agent/gatekeeper-library/master/artifacthub/library/pod-security-policy/capabilities/1.1.1/template.yaml | ||
``` | ||
provider: | ||
name: Gatekeeper Library |
2 changes: 2 additions & 0 deletions
2
artifacthub/library/pod-security-policy/capabilities/1.1.1/kustomization.yaml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
resources: | ||
- template.yaml |
14 changes: 14 additions & 0 deletions
14
.../library/pod-security-policy/capabilities/1.1.1/samples/capabilities-demo/constraint.yaml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
apiVersion: constraints.gatekeeper.sh/v1beta1 | ||
kind: K8sPSPCapabilities | ||
metadata: | ||
name: capabilities-demo | ||
spec: | ||
match: | ||
kinds: | ||
- apiGroups: [""] | ||
kinds: ["Pod"] | ||
namespaces: | ||
- "default" | ||
parameters: | ||
allowedCapabilities: ["something"] | ||
requiredDropCapabilities: ["must_drop"] |
21 changes: 21 additions & 0 deletions
21
...od-security-policy/capabilities/1.1.1/samples/capabilities-demo/disallowed_ephemeral.yaml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
apiVersion: v1 | ||
kind: Pod | ||
metadata: | ||
name: opa-disallowed | ||
labels: | ||
owner: me.agilebank.demo | ||
spec: | ||
ephemeralContainers: | ||
- name: opa | ||
image: openpolicyagent/opa:0.9.2 | ||
args: | ||
- "run" | ||
- "--server" | ||
- "--addr=localhost:8080" | ||
securityContext: | ||
capabilities: | ||
add: ["disallowedcapability"] | ||
resources: | ||
limits: | ||
cpu: "100m" | ||
memory: "30Mi" |
22 changes: 22 additions & 0 deletions
22
...ary/pod-security-policy/capabilities/1.1.1/samples/capabilities-demo/example_allowed.yaml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
apiVersion: v1 | ||
kind: Pod | ||
metadata: | ||
name: opa-allowed | ||
labels: | ||
owner: me.agilebank.demo | ||
spec: | ||
containers: | ||
- name: opa | ||
image: openpolicyagent/opa:0.9.2 | ||
args: | ||
- "run" | ||
- "--server" | ||
- "--addr=localhost:8080" | ||
securityContext: | ||
capabilities: | ||
add: ["something"] | ||
drop: ["must_drop", "another_one"] | ||
resources: | ||
limits: | ||
cpu: "100m" | ||
memory: "30Mi" |
21 changes: 21 additions & 0 deletions
21
.../pod-security-policy/capabilities/1.1.1/samples/capabilities-demo/example_disallowed.yaml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
apiVersion: v1 | ||
kind: Pod | ||
metadata: | ||
name: opa-disallowed | ||
labels: | ||
owner: me.agilebank.demo | ||
spec: | ||
containers: | ||
- name: opa | ||
image: openpolicyagent/opa:0.9.2 | ||
args: | ||
- "run" | ||
- "--server" | ||
- "--addr=localhost:8080" | ||
securityContext: | ||
capabilities: | ||
add: ["disallowedcapability"] | ||
resources: | ||
limits: | ||
cpu: "100m" | ||
memory: "30Mi" |
26 changes: 26 additions & 0 deletions
26
...thub/library/pod-security-policy/capabilities/1.1.1/samples/capabilities-demo/update.yaml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
kind: AdmissionReview | ||
apiVersion: admission.k8s.io/v1beta1 | ||
request: | ||
operation: "UPDATE" | ||
object: | ||
apiVersion: v1 | ||
kind: Pod | ||
metadata: | ||
name: opa-disallowed | ||
labels: | ||
owner: me.agilebank.demo | ||
spec: | ||
containers: | ||
- name: opa | ||
image: openpolicyagent/opa:0.9.2 | ||
args: | ||
- "run" | ||
- "--server" | ||
- "--addr=localhost:8080" | ||
securityContext: | ||
capabilities: | ||
add: ["disallowedcapability"] | ||
resources: | ||
limits: | ||
cpu: "100m" | ||
memory: "30Mi" |
25 changes: 25 additions & 0 deletions
25
artifacthub/library/pod-security-policy/capabilities/1.1.1/suite.yaml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
kind: Suite | ||
apiVersion: test.gatekeeper.sh/v1alpha1 | ||
metadata: | ||
name: capabilities | ||
tests: | ||
- name: capabilities | ||
template: template.yaml | ||
constraint: samples/capabilities-demo/constraint.yaml | ||
cases: | ||
- name: example-disallowed | ||
object: samples/capabilities-demo/example_disallowed.yaml | ||
assertions: | ||
- violations: yes | ||
- name: example-allowed | ||
object: samples/capabilities-demo/example_allowed.yaml | ||
assertions: | ||
- violations: no | ||
- name: disallowed-ephemeral | ||
object: samples/capabilities-demo/disallowed_ephemeral.yaml | ||
assertions: | ||
- violations: yes | ||
- name: update | ||
object: samples/capabilities-demo/update.yaml | ||
assertions: | ||
- violations: no |
219 changes: 219 additions & 0 deletions
219
artifacthub/library/pod-security-policy/capabilities/1.1.1/template.yaml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,219 @@ | ||
apiVersion: templates.gatekeeper.sh/v1 | ||
kind: ConstraintTemplate | ||
metadata: | ||
name: k8spspcapabilities | ||
annotations: | ||
metadata.gatekeeper.sh/title: "Capabilities" | ||
metadata.gatekeeper.sh/version: 1.1.1 | ||
description: >- | ||
Controls Linux capabilities on containers. Corresponds to the | ||
`allowedCapabilities` and `requiredDropCapabilities` fields in a | ||
PodSecurityPolicy. For more information, see | ||
https://kubernetes.io/docs/concepts/policy/pod-security-policy/#capabilities | ||
spec: | ||
crd: | ||
spec: | ||
names: | ||
kind: K8sPSPCapabilities | ||
validation: | ||
# Schema for the `parameters` field | ||
openAPIV3Schema: | ||
type: object | ||
description: >- | ||
Controls Linux capabilities on containers. Corresponds to the | ||
`allowedCapabilities` and `requiredDropCapabilities` fields in a | ||
PodSecurityPolicy. For more information, see | ||
https://kubernetes.io/docs/concepts/policy/pod-security-policy/#capabilities | ||
properties: | ||
exemptImages: | ||
description: >- | ||
Any container that uses an image that matches an entry in this list will be excluded | ||
from enforcement. Prefix-matching can be signified with `*`. For example: `my-image-*`. | ||
It is recommended that users use the fully-qualified Docker image name (e.g. start with a domain name) | ||
in order to avoid unexpectedly exempting images from an untrusted repository. | ||
type: array | ||
items: | ||
type: string | ||
allowedCapabilities: | ||
type: array | ||
description: "A list of Linux capabilities that can be added to a container." | ||
items: | ||
type: string | ||
requiredDropCapabilities: | ||
type: array | ||
description: "A list of Linux capabilities that are required to be dropped from a container." | ||
items: | ||
type: string | ||
targets: | ||
- target: admission.k8s.gatekeeper.sh | ||
code: | ||
- engine: K8sNativeValidation | ||
source: | ||
variables: | ||
- name: containers | ||
expression: 'has(variables.anyObject.spec.containers) ? variables.anyObject.spec.containers : []' | ||
- name: initContainers | ||
expression: 'has(variables.anyObject.spec.initContainers) ? variables.anyObject.spec.initContainers : []' | ||
- name: ephemeralContainers | ||
expression: 'has(variables.anyObject.spec.ephemeralContainers) ? variables.anyObject.spec.ephemeralContainers : []' | ||
- name: allContainers | ||
expression: 'variables.containers + variables.initContainers + variables.ephemeralContainers' | ||
- name: exemptImagePrefixes | ||
expression: | | ||
!has(variables.params.exemptImages) ? [] : | ||
variables.params.exemptImages.filter(image, image.endsWith("*")).map(image, string(image).replace("*", "")) | ||
- name: exemptImageExplicit | ||
expression: | | ||
!has(variables.params.exemptImages) ? [] : | ||
variables.params.exemptImages.filter(image, !image.endsWith("*")) | ||
- name: exemptImages | ||
expression: | | ||
(variables.containers + variables.initContainers + variables.ephemeralContainers).filter(container, | ||
container.image in variables.exemptImageExplicit || | ||
variables.exemptImagePrefixes.exists(exemption, string(container.image).startsWith(exemption)) | ||
).map(container, container.image) | ||
- name: allowedCapabilities | ||
expression: 'has(variables.params.allowedCapabilities) ? variables.params.allowedCapabilities : []' | ||
- name: allCapabilitiesAllowed | ||
expression: '"*" in variables.allowedCapabilities' | ||
- name: disallowedCapabilitiesByContainer | ||
expression: | | ||
variables.allContainers.map(container, !(container.image in variables.exemptImages) && | ||
!variables.allCapabilitiesAllowed && has(container.securityContext) && has(container.securityContext.capabilities) && has(container.securityContext.capabilities.add) && | ||
container.securityContext.capabilities.add.exists(capability, !(capability in variables.allowedCapabilities)), | ||
[container.name, dyn(container.securityContext.capabilities.add.filter(capability, !(capability in variables.allowedCapabilities)).join(", "))] | ||
) | ||
- name: requiredDropCapabilities | ||
expression: 'has(variables.params.requiredDropCapabilities) ? variables.params.requiredDropCapabilities : []' | ||
- name: missingDropCapabilitiesByContainer | ||
expression: | | ||
variables.allContainers.map(container, !(container.image in variables.exemptImages) && | ||
size(variables.requiredDropCapabilities) > 0 && ( | ||
!has(container.securityContext) || !has(container.securityContext.capabilities) || !has(container.securityContext.capabilities.drop) || ( | ||
!("all" in container.securityContext.capabilities.drop) && | ||
variables.requiredDropCapabilities.exists(capability, !(capability in container.securityContext.capabilities.drop)) | ||
) | ||
), | ||
[container.name, | ||
!has(container.securityContext) ? variables.requiredDropCapabilities : | ||
!has(container.securityContext.capabilities) ? variables.requiredDropCapabilities : | ||
!has(container.securityContext.capabilities.drop) ? variables.requiredDropCapabilities : | ||
variables.requiredDropCapabilities.filter(capability, !(capability in container.securityContext.capabilities.drop)) | ||
] | ||
) | ||
validations: | ||
- expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.disallowedCapabilitiesByContainer) == 0' | ||
messageExpression: | | ||
"containers have disallowed capabilities: " + variables.disallowedCapabilitiesByContainer.map(pair, "{container: " + pair[0] + ", capabilities: [" + pair[1] + "]}").join(", ") | ||
- expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.missingDropCapabilitiesByContainer) == 0' | ||
messageExpression: | | ||
"containers are not dropping all required capabilities: " + variables.missingDropCapabilitiesByContainer.map(pair, "{container: " + pair[0] + ", capabilities: [" + pair[1].join(", ") + "]}").join(", ") | ||
- engine: Rego | ||
source: | ||
rego: | | ||
package capabilities | ||
import data.lib.exclude_update.is_update | ||
import data.lib.exempt_container.is_exempt | ||
violation[{"msg": msg}] { | ||
# spec.containers.securityContext.capabilities field is immutable. | ||
not is_update(input.review) | ||
container := input.review.object.spec.containers[_] | ||
not is_exempt(container) | ||
has_disallowed_capabilities(container) | ||
msg := sprintf("container <%v> has a disallowed capability. Allowed capabilities are %v", [container.name, get_default(input.parameters, "allowedCapabilities", "NONE")]) | ||
} | ||
violation[{"msg": msg}] { | ||
not is_update(input.review) | ||
container := input.review.object.spec.containers[_] | ||
not is_exempt(container) | ||
missing_drop_capabilities(container) | ||
msg := sprintf("container <%v> is not dropping all required capabilities. Container must drop all of %v or \"ALL\"", [container.name, input.parameters.requiredDropCapabilities]) | ||
} | ||
violation[{"msg": msg}] { | ||
not is_update(input.review) | ||
container := input.review.object.spec.initContainers[_] | ||
not is_exempt(container) | ||
has_disallowed_capabilities(container) | ||
msg := sprintf("init container <%v> has a disallowed capability. Allowed capabilities are %v", [container.name, get_default(input.parameters, "allowedCapabilities", "NONE")]) | ||
} | ||
violation[{"msg": msg}] { | ||
not is_update(input.review) | ||
container := input.review.object.spec.initContainers[_] | ||
not is_exempt(container) | ||
missing_drop_capabilities(container) | ||
msg := sprintf("init container <%v> is not dropping all required capabilities. Container must drop all of %v or \"ALL\"", [container.name, input.parameters.requiredDropCapabilities]) | ||
} | ||
violation[{"msg": msg}] { | ||
not is_update(input.review) | ||
container := input.review.object.spec.ephemeralContainers[_] | ||
not is_exempt(container) | ||
has_disallowed_capabilities(container) | ||
msg := sprintf("ephemeral container <%v> has a disallowed capability. Allowed capabilities are %v", [container.name, get_default(input.parameters, "allowedCapabilities", "NONE")]) | ||
} | ||
violation[{"msg": msg}] { | ||
not is_update(input.review) | ||
container := input.review.object.spec.ephemeralContainers[_] | ||
not is_exempt(container) | ||
missing_drop_capabilities(container) | ||
msg := sprintf("ephemeral container <%v> is not dropping all required capabilities. Container must drop all of %v or \"ALL\"", [container.name, input.parameters.requiredDropCapabilities]) | ||
} | ||
has_disallowed_capabilities(container) { | ||
allowed := {c | c := lower(input.parameters.allowedCapabilities[_])} | ||
not allowed["*"] | ||
capabilities := {c | c := lower(container.securityContext.capabilities.add[_])} | ||
count(capabilities - allowed) > 0 | ||
} | ||
missing_drop_capabilities(container) { | ||
must_drop := {c | c := lower(input.parameters.requiredDropCapabilities[_])} | ||
all := {"all"} | ||
dropped := {c | c := lower(container.securityContext.capabilities.drop[_])} | ||
count(must_drop - dropped) > 0 | ||
count(all - dropped) > 0 | ||
} | ||
get_default(obj, param, _) := obj[param] | ||
get_default(obj, param, _default) := _default { | ||
not obj[param] | ||
not obj[param] == false | ||
} | ||
libs: | ||
- | | ||
package lib.exclude_update | ||
is_update(review) { | ||
review.operation == "UPDATE" | ||
} | ||
- | | ||
package lib.exempt_container | ||
is_exempt(container) { | ||
exempt_images := object.get(object.get(input, "parameters", {}), "exemptImages", []) | ||
img := container.image | ||
exemption := exempt_images[_] | ||
_matches_exemption(img, exemption) | ||
} | ||
_matches_exemption(img, exemption) { | ||
not endswith(exemption, "*") | ||
exemption == img | ||
} | ||
_matches_exemption(img, exemption) { | ||
endswith(exemption, "*") | ||
prefix := trim_suffix(exemption, "*") | ||
startswith(img, prefix) | ||
} |
Oops, something went wrong.