Skip to content

Commit

Permalink
updating seccompv2 to remove string building for localhost profiles
Browse files Browse the repository at this point in the history
Signed-off-by: Jaydip Gabani <[email protected]>
  • Loading branch information
JaydipGabani committed Sep 23, 2024
1 parent 0ea1c1c commit 3ed88dc
Show file tree
Hide file tree
Showing 8 changed files with 103 additions and 214 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name: k8spspseccompv2
displayName: Seccomp V2
createdAt: "2024-09-05T01:36:31Z"
description: Controls the seccomp profile used by containers. Corresponds to the `securityContext.seccompProfile` field.
digest: 82f2c64bae8f6984ac24a71793134a385ec0761a2c44be43d16f25283bac4d9b
digest: 7586bb9d19280fe3e019415023e00db4194d8f64698bb54d075f7942310d4c6c
license: Apache-2.0
homeURL: https://open-policy-agent.github.io/gatekeeper-library/website/seccompv2
keywords:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,7 @@ spec:
description: >-
An array of allowed profile values for seccomp on Pods/Containers.
Can use the annotation naming scheme: `runtime/default`, `docker/default`, `unconfined` and/or
`localhost/some-profile.json`. The item `localhost/*` will allow any localhost based profile.
Can also use the securityContext naming scheme: `RuntimeDefault`, `Unconfined`
Can use the securityContext naming scheme: `RuntimeDefault`, `Unconfined`
and/or `Localhost`. For securityContext `Localhost`, use the parameter `allowedLocalhostProfiles`
to list the allowed profile JSON files.
Expand Down Expand Up @@ -94,25 +91,22 @@ spec:
(variables.containers + variables.initContainers + variables.ephemeralContainers).filter(container,
!variables.allowAllProfiles &&
!(container.image in variables.exemptImages))
- name: inputAllowedProfiles
expression: |
!has(variables.params.allowedProfiles) ? [] : variables.params.allowedProfiles
- name: derivedAllowedLocalhostFiles
- name: inputNonLocalHostProfiles
expression: |
variables.inputAllowedProfiles.exists(profile, profile == "Localhost") ? variables.params.allowedLocalhostFiles.map(file, "Localhost/" + file) : []
- name: allowedProfiles
variables.params.allowedProfiles.filter(profile, profile != "Localhost").map(profile, {"type": profile})
- name: inputLocalHostProfiles
expression: |
variables.inputAllowedProfiles + variables.derivedAllowedLocalhostFiles
- name: allowAllLocalhostFiles
variables.params.allowedProfiles.exists(profile, profile == "Localhost") ? variables.params.allowedLocalhostFiles.map(file, {"type": "Localhost", "localHostProfile": string(file)}) : []
- name: inputAllowedProfiles
expression: |
variables.allowedProfiles.exists(profile, profile == "Localhost/*")
variables.inputNonLocalHostProfiles + variables.inputLocalHostProfiles
- name: hasPodSeccomp
expression: |
has(variables.anyObject.spec.securityContext) && has(variables.anyObject.spec.securityContext.seccompProfile)
- name: podLocalHostProfile
expression: |
variables.hasPodSeccomp && has(variables.anyObject.spec.securityContext.seccompProfile.localhostProfile) ? variables.anyObject.spec.securityContext.seccompProfile.localhostProfile : ""
- name: podSecurityContextProfile
- name: podSecurityContextProfileType
expression: |
has(variables.hasPodSeccomp) && has(variables.anyObject.spec.securityContext.seccompProfile.type) ? variables.anyObject.spec.securityContext.seccompProfile.type
: ""
Expand All @@ -123,7 +117,7 @@ spec:
variables.hasPodSeccomp
).map(container, {
"container" : container.name,
"profile" : dyn(variables.podSecurityContextProfile),
"profile" : dyn(variables.podSecurityContextProfileType),
"file" : variables.podLocalHostProfile,
"location" : dyn("pod securityContext"),
})
Expand Down Expand Up @@ -153,24 +147,23 @@ spec:
variables.podSecurityContextProfiles + variables.containerSecurityContextProfiles + variables.containerProfilesMissing
- name: badContainerProfilesWithoutFiles
expression: |
variables.allContainerProfiles.filter(badContainerProfile,
badContainerProfile.profile != "Localhost" &&
!(badContainerProfile.profile in variables.allowedProfiles)
).map(badProfile, "Seccomp profile '" + badProfile.profile + "' is not allowed for container '" + badProfile.container + "'. Found at: " + badProfile.location + ". Allowed profiles: " + variables.allowedProfiles.join(", "))
variables.allContainerProfiles.filter(container,
container.profile != "Localhost" &&
!variables.inputAllowedProfiles.exists(profile, profile.type == container.profile)
).map(badProfile, "Seccomp profile '" + badProfile.profile + "' is not allowed for container '" + badProfile.container + "'. Found at: " + badProfile.location + ". Allowed profiles: " + variables.inputAllowedProfiles.map(profile, "{\"type\": \"" + profile.type + "\"" + (has(profile.localHostProfile) ? ", \"localHostProfile\": \"" + profile.localHostProfile + "\"}" : "}")).join(", "))
- name: badContainerProfilesWithFiles
expression: |
variables.allContainerProfiles.filter(badContainerProfile,
badContainerProfile.profile == "Localhost" &&
!variables.allowAllLocalhostFiles &&
!((badContainerProfile.profile + "/" + badContainerProfile.file) in variables.allowedProfiles)
).map(badProfile, "Seccomp profile '" + badProfile.profile + "' With file '" + badProfile.file + "' is not allowed for container '" + badProfile.container + "'. Found at: " + badProfile.location + ". Allowed profiles: " + variables.allowedProfiles.join(", "))
variables.allContainerProfiles.filter(container,
container.profile == "Localhost" &&
!variables.inputAllowedProfiles.exists(profile, profile.type == "Localhost" && (has(profile.localHostProfile) && (profile.localHostProfile == container.file || profile.localHostProfile == "*")))
).map(badProfile, "Seccomp profile '" + badProfile.profile + "' With file '" + badProfile.file + "' is not allowed for container '" + badProfile.container + "'. Found at: " + badProfile.location + ". Allowed profiles: " + variables.inputAllowedProfiles.map(profile, "{\"type\": \"" + profile.type + "\"" + (has(profile.localHostProfile) ? ", \"localHostProfile\": \"" + profile.localHostProfile + "\"}" : "}")).join(", "))
validations:
- expression: 'size(variables.badContainerProfilesWithoutFiles) == 0'
messageExpression: |
variables.badContainerProfilesWithoutFiles.join("\n")
variables.badContainerProfilesWithoutFiles.join(", ")
- expression: 'size(variables.badContainerProfilesWithFiles) == 0'
messageExpression: |
variables.badContainerProfilesWithFiles.join("\n")
variables.badContainerProfilesWithFiles.join(", ")
- engine: Rego
source:
rego: |
Expand Down Expand Up @@ -218,25 +211,30 @@ spec:
# Simple allowed Profiles
allowed_profile(profile, _, allowed) {
profile != "Localhost"
profile == allowed[_]
temp = allowed[_]
profile == temp.type
}
# annotation localhost without wildcard
allowed_profile(profile, file, allowed) {
profile == "Localhost"
allowed[_] == sprintf("Localhost/%s", [file])
temp = allowed[_]
temp.type == "Localhost"
file == temp.localHostProfile
}
# The profiles explicitly in the list
get_allowed_profiles[allowed] {
allowed := input.parameters.allowedProfiles[_]
profile := input.parameters.allowedProfiles[_]
profile != "Localhost"
allowed := {"type": profile}
}
get_allowed_profiles[allowed] {
profile := input.parameters.allowedProfiles[_]
profile == "Localhost"
file := object.get(input.parameters, "allowedLocalhostFiles", [])[_]
allowed := sprintf("Localhost/%s", [file])
file := object.get(input.parameters, "allowedLocalhostFiles", [""])[_]
allowed := {"type": "Localhost", "localHostProfile": file}
}
# Container profile as defined in containers securityContext
Expand Down
127 changes: 11 additions & 116 deletions library/pod-security-policy/seccompv2/template.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,7 @@ spec:
description: >-
An array of allowed profile values for seccomp on Pods/Containers.
Can use the annotation naming scheme: `runtime/default`, `docker/default`, `unconfined` and/or
`localhost/some-profile.json`. The item `localhost/*` will allow any localhost based profile.
Can also use the securityContext naming scheme: `RuntimeDefault`, `Unconfined`
Can use the securityContext naming scheme: `RuntimeDefault`, `Unconfined`
and/or `Localhost`. For securityContext `Localhost`, use the parameter `allowedLocalhostProfiles`
to list the allowed profile JSON files.
Expand All @@ -64,113 +61,6 @@ spec:
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: allowAllProfiles
expression: |
has(variables.params.allowedProfiles) && variables.params.allowedProfiles.exists(profile, profile == "*")
- 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)))
- name: unverifiedContainers
expression: |
(variables.containers + variables.initContainers + variables.ephemeralContainers).filter(container,
!variables.allowAllProfiles &&
!(container.image in variables.exemptImages))
- name: inputAllowedProfiles
expression: |
!has(variables.params.allowedProfiles) ? [] : variables.params.allowedProfiles
- name: derivedAllowedLocalhostFiles
expression: |
variables.inputAllowedProfiles.exists(profile, profile == "Localhost") ? variables.params.allowedLocalhostFiles.map(file, "Localhost/" + file) : []
- name: allowedProfiles
expression: |
variables.inputAllowedProfiles + variables.derivedAllowedLocalhostFiles
- name: allowAllLocalhostFiles
expression: |
variables.allowedProfiles.exists(profile, profile == "Localhost/*")
- name: hasPodSeccomp
expression: |
has(variables.anyObject.spec.securityContext) && has(variables.anyObject.spec.securityContext.seccompProfile)
- name: podLocalHostProfile
expression: |
variables.hasPodSeccomp && has(variables.anyObject.spec.securityContext.seccompProfile.localhostProfile) ? variables.anyObject.spec.securityContext.seccompProfile.localhostProfile : ""
- name: podSecurityContextProfile
expression: |
has(variables.hasPodSeccomp) && has(variables.anyObject.spec.securityContext.seccompProfile.type) ? variables.anyObject.spec.securityContext.seccompProfile.type
: ""
- name: podSecurityContextProfiles
expression: |
variables.unverifiedContainers.filter(container,
!(has(container.securityContext) && has(container.securityContext.seccompProfile)) &&
variables.hasPodSeccomp
).map(container, {
"container" : container.name,
"profile" : dyn(variables.podSecurityContextProfile),
"file" : variables.podLocalHostProfile,
"location" : dyn("pod securityContext"),
})
- name: containerSecurityContextProfiles
expression: |
variables.unverifiedContainers.filter(container,
has(container.securityContext) && has(container.securityContext.seccompProfile)
).map(container, {
"container" : container.name,
"profile" : dyn(container.securityContext.seccompProfile.type),
"file" : has(container.securityContext.seccompProfile.localhostProfile) ? container.securityContext.seccompProfile.localhostProfile : dyn(""),
"location" : dyn("container securityContext"),
})
- name: containerProfilesMissing
expression: |
variables.unverifiedContainers.filter(container,
!(has(container.securityContext) && has(container.securityContext.seccompProfile)) &&
!variables.hasPodSeccomp
).map(container, {
"container" : container.name,
"profile" : dyn("not configured"),
"file" : dyn(""),
"location" : dyn("no explicit profile found"),
})
- name: allContainerProfiles
expression: |
variables.podSecurityContextProfiles + variables.containerSecurityContextProfiles + variables.containerProfilesMissing
- name: badContainerProfilesWithoutFiles
expression: |
variables.allContainerProfiles.filter(badContainerProfile,
badContainerProfile.profile != "Localhost" &&
!(badContainerProfile.profile in variables.allowedProfiles)
).map(badProfile, "Seccomp profile '" + badProfile.profile + "' is not allowed for container '" + badProfile.container + "'. Found at: " + badProfile.location + ". Allowed profiles: " + variables.allowedProfiles.join(", "))
- name: badContainerProfilesWithFiles
expression: |
variables.allContainerProfiles.filter(badContainerProfile,
badContainerProfile.profile == "Localhost" &&
!variables.allowAllLocalhostFiles &&
!((badContainerProfile.profile + "/" + badContainerProfile.file) in variables.allowedProfiles)
).map(badProfile, "Seccomp profile '" + badProfile.profile + "' With file '" + badProfile.file + "' is not allowed for container '" + badProfile.container + "'. Found at: " + badProfile.location + ". Allowed profiles: " + variables.allowedProfiles.join(", "))
validations:
- expression: 'size(variables.badContainerProfilesWithoutFiles) == 0'
messageExpression: |
variables.badContainerProfilesWithoutFiles.join("\n")
- expression: 'size(variables.badContainerProfilesWithFiles) == 0'
messageExpression: |
variables.badContainerProfilesWithFiles.join("\n")
- engine: Rego
source:
rego: |
Expand Down Expand Up @@ -218,25 +108,30 @@ spec:
# Simple allowed Profiles
allowed_profile(profile, _, allowed) {
profile != "Localhost"
profile == allowed[_]
temp = allowed[_]
profile == temp.type
}
# annotation localhost without wildcard
allowed_profile(profile, file, allowed) {
profile == "Localhost"
allowed[_] == sprintf("Localhost/%s", [file])
temp = allowed[_]
temp.type == "Localhost"
file == temp.localHostProfile
}
# The profiles explicitly in the list
get_allowed_profiles[allowed] {
allowed := input.parameters.allowedProfiles[_]
profile := input.parameters.allowedProfiles[_]
profile != "Localhost"
allowed := {"type": profile}
}
get_allowed_profiles[allowed] {
profile := input.parameters.allowedProfiles[_]
profile == "Localhost"
file := object.get(input.parameters, "allowedLocalhostFiles", [])[_]
allowed := sprintf("Localhost/%s", [file])
file := object.get(input.parameters, "allowedLocalhostFiles", [""])[_]
allowed := {"type": "Localhost", "localHostProfile": file}
}
# Container profile as defined in containers securityContext
Expand Down
5 changes: 1 addition & 4 deletions src/pod-security-policy/seccompv2/constraint.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,7 @@ spec:
description: >-
An array of allowed profile values for seccomp on Pods/Containers.

Can use the annotation naming scheme: `runtime/default`, `docker/default`, `unconfined` and/or
`localhost/some-profile.json`. The item `localhost/*` will allow any localhost based profile.

Can also use the securityContext naming scheme: `RuntimeDefault`, `Unconfined`
Can use the securityContext naming scheme: `RuntimeDefault`, `Unconfined`
and/or `Localhost`. For securityContext `Localhost`, use the parameter `allowedLocalhostProfiles`
to list the allowed profile JSON files.

Expand Down
Loading

0 comments on commit 3ed88dc

Please sign in to comment.