Reputation: 1008
We currently can control which Kubernetes services of type "LoadBalancer" can be created.
ConstraintTemplate
spec:
crd:
spec:
names:
kind: K8sMetalLBServicesGK
validation:
openAPIV3Schema:
properties:
allowedLBServices:
type: array
items:
type: string
targets:
- target: admission.k8s.gatekeeper.sh
rego: |
package k8smetallbservicesgk
# Deny not whitelisted Service LB names
violation[{"msg": msg}] {
is_not_getting_deleted
is_type_loadbalancer
svc := input.review.object.metadata.name
satisfied := [good | pattern := input.parameters.allowedLBServices[_] ; good = glob.match(pattern, [], svc)]
not any(satisfied)
msg := sprintf("%v" service creation was denied by GateKeeper,[svc])
}
is_not_getting_deleted() = true {
input.review.operation != "DELETE"
not input.review.object.metadata.deletionTimestamp
}
is_type_loadbalancer() = true {
input.review.object.spec.type == "LoadBalancer"
}
Constraint
spec:
match:
excludedNamespaces: ["*-system"]
kinds:
- apiGroups: ["*"]
kinds: ["Service"]
parameters:
allowedLBServices:
- pakalu
We would like to extend this by controlling which service of type "LoadBalancer" can be created per namespace. For that, we would need to change the validation in the template and the rule logic. So constraint
could look similar to this, if we want to allow services named "pakalu" and "papito" in namespace "ham", and allow services named "pakalu" and "foo" in namespace "spam".
spec:
match:
excludedNamespaces: ["*-system"]
kinds:
- apiGroups: ["*"]
kinds: ["Service"]
parameters:
allowedLBServices:
- ham:
- pakalu
- papito
- spam:
- pakalu
- foo
Upvotes: 0
Views: 1163
Reputation: 2315
You could modify the constraint template to expect an object for allowedLBServices
, and modify the policy to work with that:
apiVersion: templates.gatekeeper.sh/v1
kind: ConstraintTemplate
metadata:
name: k8smetallbservicesgk
spec:
crd:
spec:
names:
kind: K8sMetalLBServicesGK
validation:
openAPIV3Schema:
type: object
properties:
allowedLBServices:
type: object
targets:
- target: admission.k8s.gatekeeper.sh
rego: |
package k8smetallbservicesgk
# Deny not whitelisted Service LB names
violation[{"msg": msg}] {
is_not_getting_deleted
is_type_loadbalancer
not allowed_in_namespace
msg := sprintf("%v service creation was denied by GateKeeper", [input.review.object.metadata.name])
}
allowed_in_namespace {
namespace := input.review.object.metadata.namespace
pattern := input.parameters.allowedLBServices[namespace][_]
glob.match(pattern, [], input.review.object.metadata.name)
}
is_not_getting_deleted {
input.review.operation != "DELETE"
not input.review.object.metadata.deletionTimestamp
}
is_type_loadbalancer {
input.review.object.spec.type == "LoadBalancer"
}
And update the constraint to use an object as well:
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sMetalLBServicesGK
metadata:
name: foo
spec:
match:
excludedNamespaces: ["*-system"]
kinds:
- apiGroups: ["*"]
kinds: ["Service"]
parameters:
allowedLBServices:
foo:
- pakalu
Nit: I'd use rules over functions, unless you want to provide arguments.
Upvotes: 1