Skip to content
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
5 changes: 5 additions & 0 deletions playbooks/provision_playbook.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@
name: ms3_inc.tavros.fluxtoolkit
tags: [ fluxtoolkit ]

- name: Opa Gatekeeper
include_role:
name: ms3_inc.tavros.opa_gatekeeper
tags: [ opa_gatekeeper ]

- name: sealed-secrets
include_role:
name: ms3_inc.tavros.sealed_secrets
Expand Down
8 changes: 8 additions & 0 deletions roles/opa_gatekeeper/files/helmrepo.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
apiVersion: source.toolkit.fluxcd.io/v1beta1
kind: HelmRepository
metadata:
name: opa-gatekeeper
namespace: flux-system
spec:
interval: 10m
url: https://open-policy-agent.github.io/gatekeeper/charts
7 changes: 7 additions & 0 deletions roles/opa_gatekeeper/files/kustomization.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ns.yaml
- helmrepo.yaml
- release.yaml
- policies/
4 changes: 4 additions & 0 deletions roles/opa_gatekeeper/files/ns.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
apiVersion: v1
kind: Namespace
metadata:
name: gatekeeper-system
17 changes: 17 additions & 0 deletions roles/opa_gatekeeper/files/policies/capabilities/constraint.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sPSPCapabilities
metadata:
name: capabilities-demo
spec:
match:
kinds:
- apiGroups:
- ""
kinds:
- Pod
excludedNamespaces:
- kube-system
parameters:
allowedCapabilities:
- NET_ADMIN
requiredDropCapabilities: []
67 changes: 67 additions & 0 deletions roles/opa_gatekeeper/files/policies/capabilities/template.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
apiVersion: templates.gatekeeper.sh/v1beta1
kind: ConstraintTemplate
metadata:
name: k8spspcapabilities
annotations:
description: Controls Linux capabilities.
spec:
crd:
spec:
names:
kind: K8sPSPCapabilities
validation:
# Schema for the `parameters` field
openAPIV3Schema:
type: object
properties:
allowedCapabilities:
type: array
items:
type: string
requiredDropCapabilities:
type: array
items:
type: string
targets:
- target: admission.k8s.gatekeeper.sh
rego: |
package capabilities
violation[{"msg": msg}] {
container := input.review.object.spec.containers[_]
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}] {
container := input.review.object.spec.containers[_]
missing_drop_capabilities(container)
msg := sprintf("container <%v> is not dropping all required capabilities. Container must drop all of %v", [container.name, input.parameters.requiredDropCapabilities])
}
violation[{"msg": msg}] {
container := input.review.object.spec.initContainers[_]
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}] {
container := input.review.object.spec.initContainers[_]
missing_drop_capabilities(container)
msg := sprintf("init container <%v> is not dropping all required capabilities. Container must drop all of %v", [container.name, input.parameters.requiredDropCapabilities])
}
has_disallowed_capabilities(container) {
allowed := {c | c := input.parameters.allowedCapabilities[_]}
not allowed["*"]
capabilities := {c | c := container.securityContext.capabilities.add[_]}
count(capabilities - allowed) > 0
}
missing_drop_capabilities(container) {
must_drop := {c | c := input.parameters.requiredDropCapabilities[_]}
dropped := {c | c := container.securityContext.capabilities.drop[_]}
count(must_drop - dropped) > 0
}
get_default(obj, param, _default) = out {
out = obj[param]
}
get_default(obj, param, _default) = out {
not obj[param]
not obj[param] == false
out = _default
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sPSPForbiddenSysctls
metadata:
name: psp-forbidden-sysctls
spec:
match:
kinds:
- apiGroups:
- ""
kinds:
- Pod
parameters:
forbiddenSysctls:
- "*" # * may be used to forbid all sysctls
# - kernel.*
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
apiVersion: templates.gatekeeper.sh/v1beta1
kind: ConstraintTemplate
metadata:
name: k8spspforbiddensysctls
annotations:
description: Controls the `sysctl` profile used by containers.
spec:
crd:
spec:
names:
kind: K8sPSPForbiddenSysctls
validation:
# Schema for the `parameters` field
openAPIV3Schema:
type: object
properties:
forbiddenSysctls:
type: array
items:
type: string
targets:
- target: admission.k8s.gatekeeper.sh
rego: |
package k8spspforbiddensysctls
violation[{"msg": msg, "details": {}}] {
sysctl := input.review.object.spec.securityContext.sysctls[_].name
forbidden_sysctl(sysctl)
msg := sprintf("The sysctl %v is not allowed, pod: %v. Forbidden sysctls: %v", [sysctl, input.review.object.metadata.name, input.parameters.forbiddenSysctls])
}
# * may be used to forbid all sysctls
forbidden_sysctl(sysctl) {
input.parameters.forbiddenSysctls[_] == "*"
}
forbidden_sysctl(sysctl) {
input.parameters.forbiddenSysctls[_] == sysctl
}
forbidden_sysctl(sysctl) {
startswith(sysctl, trim(input.parameters.forbiddenSysctls[_], "*"))
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sPSPHostFilesystem
metadata:
name: psp-host-filesystem
spec:
match:
kinds:
- apiGroups:
- ""
kinds:
- Pod
excludedNamespaces:
- elastic-system
- kube-system
parameters:
allowedHostPaths: []
106 changes: 106 additions & 0 deletions roles/opa_gatekeeper/files/policies/host-filesystem/template.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
apiVersion: templates.gatekeeper.sh/v1beta1
kind: ConstraintTemplate
metadata:
name: k8spsphostfilesystem
annotations:
description: Controls usage of the host filesystem.
spec:
crd:
spec:
names:
kind: K8sPSPHostFilesystem
validation:
# Schema for the `parameters` field
openAPIV3Schema:
type: object
properties:
allowedHostPaths:
type: array
items:
type: object
properties:
readOnly:
type: boolean
pathPrefix:
type: string
targets:
- target: admission.k8s.gatekeeper.sh
rego: |
package k8spsphostfilesystem
violation[{"msg": msg, "details": {}}] {
volume := input_hostpath_volumes[_]
allowedPaths := get_allowed_paths(input)
input_hostpath_violation(allowedPaths, volume)
msg := sprintf("HostPath volume %v is not allowed, pod: %v. Allowed path: %v", [volume, input.review.object.metadata.name, allowedPaths])
}
input_hostpath_violation(allowedPaths, volume) {
# An empty list means all host paths are blocked
allowedPaths == []
}
input_hostpath_violation(allowedPaths, volume) {
not input_hostpath_allowed(allowedPaths, volume)
}
get_allowed_paths(arg) = out {
not arg.parameters
out = []
}
get_allowed_paths(arg) = out {
not arg.parameters.allowedHostPaths
out = []
}
get_allowed_paths(arg) = out {
out = arg.parameters.allowedHostPaths
}
input_hostpath_allowed(allowedPaths, volume) {
allowedHostPath := allowedPaths[_]
path_matches(allowedHostPath.pathPrefix, volume.hostPath.path)
not allowedHostPath.readOnly == true
}
input_hostpath_allowed(allowedPaths, volume) {
allowedHostPath := allowedPaths[_]
path_matches(allowedHostPath.pathPrefix, volume.hostPath.path)
allowedHostPath.readOnly
not writeable_input_volume_mounts(volume.name)
}
writeable_input_volume_mounts(volume_name) {
container := input_containers[_]
mount := container.volumeMounts[_]
mount.name == volume_name
not mount.readOnly
}
# This allows "/foo", "/foo/", "/foo/bar" etc., but
# disallows "/fool", "/etc/foo" etc.
path_matches(prefix, path) {
a := path_array(prefix)
b := path_array(path)
prefix_matches(a, b)
}
path_array(p) = out {
p != "/"
out := split(trim(p, "/"), "/")
}
# This handles the special case for "/", since
# split(trim("/", "/"), "/") == [""]
path_array("/") = []
prefix_matches(a, b) {
count(a) <= count(b)
not any_not_equal_upto(a, b, count(a))
}
any_not_equal_upto(a, b, n) {
a[i] != b[i]
i < n
}
input_hostpath_volumes[v] {
v := input.review.object.spec.volumes[_]
has_field(v, "hostPath")
}
# has_field returns whether an object has a field
has_field(object, field) = true {
object[field]
}
input_containers[c] {
c := input.review.object.spec.containers[_]
}
input_containers[c] {
c := input.review.object.spec.initContainers[_]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sPSPHostNamespace
metadata:
name: psp-host-namespace
spec:
match:
kinds:
- apiGroups:
- ""
kinds:
- Pod
excludedNamespaces:
- kube-system
25 changes: 25 additions & 0 deletions roles/opa_gatekeeper/files/policies/host-namespaces/template.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
apiVersion: templates.gatekeeper.sh/v1beta1
kind: ConstraintTemplate
metadata:
name: k8spsphostnamespace
annotations:
description: Controls usage of host namespaces.
spec:
crd:
spec:
names:
kind: K8sPSPHostNamespace
targets:
- target: admission.k8s.gatekeeper.sh
rego: |
package k8spsphostnamespace
violation[{"msg": msg, "details": {}}] {
input_share_hostnamespace(input.review.object)
msg := sprintf("Sharing the host namespace is not allowed: %v", [input.review.object.metadata.name])
}
input_share_hostnamespace(o) {
o.spec.hostPID
}
input_share_hostnamespace(o) {
o.spec.hostIPC
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sPSPHostNetworkingPorts
metadata:
name: psp-host-network-ports
spec:
match:
kinds:
- apiGroups:
- ""
kinds:
- Pod
excludedNamespaces:
- kube-system
- elastic-system
- jaeger
parameters:
hostNetwork: false
min: 0
max: 0
Loading