Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rewrite policy-controller-validate with kyaml #197

Merged
merged 12 commits into from
Apr 6, 2021
Merged
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
exitCode: 1
runCount: 2
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
items:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add a TODO to test expected CLI output? (My previous comment)

This is important part of the UX.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding it to the .expected directory messes up with the test.
I filed kptdev/kpt#1689 and added in m2 milestone.

- message: |-
The following banned keys are being used in the ConfigMap: {"private_key"}
violatedConstraint: no-secrets-in-configmap
severity: error
resourceRef:
apiVersion: v1
kind: ConfigMap
metadata:
name: super-secret
namespace: default
file:
path: resources.yaml
index: 2
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.expected
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
# gatekeeper-validate: invalid configmap

## Overview

This example demonstrates how to validate ConfigMaps using a constraint.

There are 3 resources: a ConstraintTemplate, a K8sBannedConfigMapKeysV1 and a
ConfigMap.
The constraint disallows using `private_key` as a key in the ConfigMap.

## Function invocation

Get the package:

```shell
$ kpt pkg get https://github.com/GoogleContainerTools/kpt-functions-catalog.git/examples/validators/gatekeeper-validate/invalid-configmap .
```

Create a directory for storing the structured output.

```shell
$ cd invalid-configmap
$ mkdir results
```

Run the function:

```shell
$ kpt fn run --results-dir=results .
```

## Expected result

You should see the following output:

```
The following banned keys are being used in the ConfigMap: {"private_key"}
violatedConstraint: no-secrets-in-configmaperror: exit status 1
```

Let's take a look at the structured output:

```shell
$ cat results/results-0.yaml
items:
- message: |-
The following banned keys are being used in the ConfigMap: {"private_key"}
violatedConstraint: no-secrets-in-configmap
severity: error
resourceRef:
apiVersion: v1
kind: ConfigMap
metadata:
name: super-secret
namespace: default
file:
path: resources.yaml
index: 2
```

You can find:
- a detailed error message
- what resource violates the constraints
- what constraint does it violate
- where does the resource live and its index in the file

To pass validation, let's replace the key `private_key` in the ConfigMap in
`resources.yaml` with something else e.g. `public_key`.
Rerun the command. It will succeed (no output).

## Function Reference Doc

TODO: replace the following with the link to the reference doc when our site is live.
https://github.com/GoogleContainerTools/kpt-functions-catalog/blob/master/functions/go/gatekeeper-validate/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: my-func-config
annotations:
config.k8s.io/function: |
container:
image: gcr.io/kpt-fn/gatekeeper-validate:unstable
config.kubernetes.io/local-config: 'true'
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
apiVersion: templates.gatekeeper.sh/v1beta1
kind: ConstraintTemplate
metadata:
name: k8sbannedconfigmapkeysv1
spec:
crd:
spec:
names:
kind: K8sBannedConfigMapKeysV1
validation:
openAPIV3Schema:
properties:
keys:
type: array
items:
type: string
targets:
- target: admission.k8s.gatekeeper.sh
rego: |-
package ban_keys

violation[{"msg": sprintf("%v", [val])}] {
keys = {key | input.review.object.data[key]}
banned = {key | input.parameters.keys[_] = key}
overlap = keys & banned
count(overlap) > 0
val := sprintf("The following banned keys are being used in the ConfigMap: %v", [overlap])
}
---
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sBannedConfigMapKeysV1
metadata:
name: no-secrets-in-configmap
spec:
match:
kinds:
- apiGroups:
- ''
kinds:
- ConfigMap
parameters:
keys:
- private_key
---
apiVersion: v1
kind: ConfigMap
metadata:
name: super-secret
namespace: default
data:
private_key: sensitive data goes here
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
runCount: 2
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
items:
- message: |-
The following banned keys are being used in the ConfigMap: {"private_key"}
violatedConstraint: no-secrets-in-configmap
severity: warning
resourceRef:
apiVersion: v1
kind: ConfigMap
metadata:
name: super-secret
namespace: default
file:
path: resources.yaml
index: 2
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.expected
68 changes: 68 additions & 0 deletions examples/validators/gatekeeper-validate/warning-only/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
# gatekeeper-validate: warning only

## Overview

This example is very similar to the invalid configmap example. The major
difference is that the violations are warnings instead of errors.

In the constraint, we use `enforcementAction: warn` instead of
`enforcementAction: deny`.

## Function invocation

Get the package:

```shell
$ kpt pkg get https://github.com/GoogleContainerTools/kpt-functions-catalog.git/examples/validators/gatekeeper-validate/warnning-only .
```

Create a directory for storing the structured output.

```shell
$ cd warnning-only
$ mkdir results
```

Run the function:

```shell
$ kpt fn run --results-dir=results .
```

## Expected result

You won't any failure. But if you look at the structured output, you can find a
warning about the constraint violation.

```shell
$ cat results/results-0.yaml
items:
- message: |-
The following banned keys are being used in the ConfigMap map: {"private_key"}
violatedConstraint: no-secrets-in-configmap
severity: warning
resourceRef:
apiVersion: v1
kind: ConfigMap
metadata:
name: super-secret
namespace: default
file:
path: resources.yaml
index: 2
```

You can find:
- a detailed error message
- what resource violates the constraints
- what constraint does it violate
- where does the resource live and its index in the file

To pass validation, let's replace the key `private_key` in the ConfigMap in
`resources.yaml` with something else e.g. `public_key`.
Rerun the command. It will no longer have the warning.

## Function Reference Doc

TODO: replace the following with the link to the reference doc when our site is live.
https://github.com/GoogleContainerTools/kpt-functions-catalog/blob/master/functions/go/gatekeeper-validate/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: my-func-config
annotations:
config.k8s.io/function: |
container:
image: gcr.io/kpt-fn/gatekeeper-validate:unstable
config.kubernetes.io/local-config: 'true'
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
apiVersion: templates.gatekeeper.sh/v1beta1
kind: ConstraintTemplate
metadata:
name: k8sbannedconfigmapkeysv1
spec:
crd:
spec:
names:
kind: K8sBannedConfigMapKeysV1
validation:
openAPIV3Schema:
properties:
keys:
type: array
items:
type: string
targets:
- rego: |-
package ban_keys

violation[{"msg": sprintf("%v", [val])}] {
keys = {key | input.review.object.data[key]}
banned = {key | input.parameters.keys[_] = key}
overlap = keys & banned
count(overlap) > 0
val := sprintf("The following banned keys are being used in the ConfigMap: %v", [overlap])
}
target: admission.k8s.gatekeeper.sh
---
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sBannedConfigMapKeysV1
metadata:
name: no-secrets-in-configmap
spec:
enforcementAction: warn
match:
kinds:
- apiGroups:
- ''
kinds:
- ConfigMap
parameters:
keys:
- private_key
---
apiVersion: v1
kind: ConfigMap
metadata:
name: super-secret
namespace: default
data:
private_key: sensitive data goes here
3 changes: 2 additions & 1 deletion functions/go/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ FUNCTIONS := \
set-namespace \
starlark \
apply-setters \
search-replace
search-replace \
gatekeeper-validate

# Targets for running all function tests
FUNCTION_TESTS := $(patsubst %,%-TEST,$(FUNCTIONS))
Expand Down
15 changes: 15 additions & 0 deletions functions/go/gatekeeper-validate/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
FROM golang:1.15-alpine3.12
ENV CGO_ENABLED=0
WORKDIR /go/src/

COPY go.mod go.sum ./
RUN go mod download

COPY . .
RUN go build -o /usr/local/bin/validate ./

#############################################

FROM alpine:3.12
COPY --from=0 /usr/local/bin/validate /usr/local/bin/validate
ENTRYPOINT ["validate"]
45 changes: 45 additions & 0 deletions functions/go/gatekeeper-validate/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# gatekeeper-validate

### Overview

<!--mdtogo:Short-->

Validate the KRM resources using [Gatekeeper] constraints.

<!--mdtogo-->

### Synopsis

<!--mdtogo:Long-->

You can use Gatekeeper to validate KRM resources. To learn more about how to use
the Gatekeeper project, see: https://open-policy-agent.github.io/gatekeeper/website/docs/howto.

The function evaluates constraint policies against KRM resources.
The function takes 3 types of resources from the input resource list:

- constraint templates
- constraints
- other KRM resources

Every constraint should be backed by a constraint template that defines the
schema and logic of the constraint.

To learn more about how to write constraint templates and constraints, see:
https://cloud.google.com/anthos-config-management/docs/how-to/write-a-constraint-template
and
https://cloud.google.com/anthos-config-management/docs/how-to/creating-constraints.

<!--mdtogo-->

### Examples

<!-- TODO: update the following link to web page -->

<!--mdtogo:Examples-->

https://github.com/GoogleContainerTools/kpt-functions-catalog/tree/master/examples/validators/gatekeeper-validate/

<!--mdtogo-->

[Gatekeeper]:https://github.com/open-policy-agent/gatekeeper
Loading