Restricting controller access with Gatekeeper (#344)

This commit is contained in:
Richard Liu 2019-09-04 20:24:51 -07:00 committed by Kubernetes Prow Robot
parent 4f2171d5d5
commit 0f59f1d28a
3 changed files with 113 additions and 0 deletions

58
gatekeeper/README.md Normal file
View File

@ -0,0 +1,58 @@
# Gatekeeper and Kubeflow
[Gatekeeper](https://github.com/open-policy-agent/gatekeeper) is a validating webhook for Kubernetes that enforces CRD-based access control policies.
In Kubeflow, we use Gatekeeper to restrict controllers to their own namespaces. The details can be found [here](https://bit.ly/2yJeU5u).
## Installation
1. Follow the instructions [here](https://github.com/open-policy-agent/gatekeeper#deploying-a-release-using-prebuilt-image) to install Gatekeeper controller.
1. Apply the constraint template in this directory:
```
kubectl apply -f constraint-template.yaml
```
## Configuration
1. In order to configure contraints for your controllers, edit the `ns-required-annotations.yaml` file.
```yaml
# Fill in the service account name
usernames: ["system:serviceaccount:(NAMESPACE):(SERVICEACCOUNT)"]
# Replace with your own labels
annotations: ["kubeflow-admins", "kubeflow-users"]
```
* Under `usernames`, enter the names of the service accounts used to deploy Kubeflow resources.
* Under `annotations`, enter your own label names.
2. Deploy the constraint:
```
kubectl apply -f ns-required-annotations.yaml
```
## Usage
The constraint is now enabled. You can test that the constraint is working by creating a namespace without the required labels:
```yaml
apiVersion: v1
kind: Namespace
metadata:
name: kubeflow
```
Then try to create any resource under this namespace using one of the restricted users' credentials. This should result in an access violation:
```
Missing labels for user SERVICEACCOUNT namespace kubeflow: Required one of labels: ["kubeflow-admins", "kubeflow-users"] Actual labels: None
```
Now add the required labels to the namespace:
```yaml
apiVersion: v1
kind: Namespace
metadata:
name: kubeflow
annotations:
category: kubeflow-admins
```
Then try to create the same source again, and it should work.

View File

@ -0,0 +1,40 @@
apiVersion: templates.gatekeeper.sh/v1alpha1
kind: ConstraintTemplate
metadata:
name: requiredannotations
spec:
crd:
spec:
names:
kind: RequiredAnnotations
listKind: RequiredAnnotationsList
plural: requiredannotations
singular: requiredannotations
validation:
# Schema for the `parameters` field
openAPIV3Schema:
properties:
labels:
type: array
items: string
targets:
- target: admission.k8s.gatekeeper.sh
rego: |
package requiredannotations
violation[{"msg": msg, "details": {"Invalid namespace": ns}}] {
# Check if the actual user is one of the restricted_users
actual_user := {input.review.userInfo.username}
restricted_users := {username | username := input.constraint.spec.parameters.usernames[_]}
# Check if the namespace is annotated with the required labels
ns := input.review.object.metadata.namespace
real_ns := data.inventory.cluster.v1.Namespace[ns]
actual := {annotation | annotation := real_ns.metadata.annotations["category"]}
required := {annotation | annotation := input.constraint.spec.parameters.annotations[_]}
count(actual_user - restricted_users) == 0
count(required & actual) == 0
msg := sprintf("Missing labels for username %v namespace %v: Required one of labels: %v Actual labels: %v", [actual_user, ns, required, actual])
}

View File

@ -0,0 +1,15 @@
apiVersion: constraints.gatekeeper.sh/v1alpha1
kind: RequiredAnnotations
metadata:
name: ns-required-annotations
spec:
match:
# Policy applies to all resources
kinds:
- apiGroups: ["*"]
kinds: ["*"]
parameters:
# Fill in the service account name
usernames: ["system:serviceaccount:(NAMESPACE):(SERVICEACCOUNT)"]
# Replace with your own labels
annotations: ["kubeflow-admins", "kubeflow-users"]