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

chore: adding default helm values for pubsub audit connection and channel #3097

Merged
merged 13 commits into from
Oct 26, 2023
Merged
2 changes: 2 additions & 0 deletions cmd/build/helmify/static/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,8 @@ controllerManager:
# cidr: 0.0.0.0/0
audit:
enablePubsub: false
connection: audit-connection
channel: audit-channel
hostNetwork: false
dnsPolicy: ClusterFirst
metricsPort: 8888
Expand Down
2 changes: 2 additions & 0 deletions manifest_staging/charts/gatekeeper/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,8 @@ controllerManager:
# cidr: 0.0.0.0/0
audit:
enablePubsub: false
connection: audit-connection
channel: audit-channel
hostNetwork: false
dnsPolicy: ClusterFirst
metricsPort: 8888
Expand Down
4 changes: 2 additions & 2 deletions pkg/audit/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,8 @@ var (
auditEventsInvolvedNamespace = flag.Bool("audit-events-involved-namespace", false, "emit audit events for each violation in the involved objects namespace, the default (false) generates events in the namespace Gatekeeper is installed in. Audit events from cluster-scoped resources will still follow the default behavior")
auditMatchKindOnly = flag.Bool("audit-match-kind-only", false, "only use kinds specified in all constraints for auditing cluster resources. if kind is not specified in any of the constraints, it will audit all resources (same as setting this flag to false)")
apiCacheDir = flag.String("api-cache-dir", defaultAPICacheDir, "The directory where audit from api server cache are stored, defaults to /tmp/audit")
auditConnection = flag.String("audit-connection", defaultConnection, "Connection name for publishing audit violation messages")
auditChannel = flag.String("audit-channel", defaultChannel, "Channel name for publishing audit violation messages")
auditConnection = flag.String("audit-connection", defaultConnection, "Connection name for publishing audit violation messages. Defaults to audit-connection")
auditChannel = flag.String("audit-channel", defaultChannel, "Channel name for publishing audit violation messages. Defaults to audit-channel")
emptyAuditResults []updateListEntry
logStatsAudit = flag.Bool("log-stats-audit", false, "(alpha) log stats metrics for the audit run")
)
Expand Down
306 changes: 158 additions & 148 deletions website/docs/pubsub.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,15 @@ Install prerequisites such as a pubsub tool, a message broker etc.

### Setting up audit with pubsub enabled

In the audit deployment, set the `--enable-pub-sub` flag to `true` to publish audit violations. Additionally, `--audit-connection` and `--audit-channel` flags must be set to allow audit to publish violations. `--audit-connection` must be set to the name of the connection config, and `--audit-channel` must be set to name of the channel where violations should get published.
In the audit deployment, set the `--enable-pub-sub` flag to `true` to publish audit violations. Additionally, use `--audit-connection` (defaults to `audit-connection`) and `--audit-channel`(defaults to `audit-channel`) flags to allow audit to publish violations using desired connection onto desired channel. `--audit-connection` must be set to the name of the connection config, and `--audit-channel` must be set to name of the channel where violations should get published.

Create a connection configMap that supplies [a provider-specific configuration](pubsub-driver-walkthrough.md#how-to-use-different-providers) for a connection to get established. For instance, to establish a connection that uses Dapr to publish messages this configMap is appropriate:
A ConfigMap that contains `provider` and `config` fields in `data` is required to establish connection for sending violations over the channel. Following is an example ConfigMap to establish a connection that uses Dapr to publish messages:

```yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: audit-pubsub-connection
name: audit-connection
namespace: gatekeeper-system
data:
provider: "dapr"
Expand All @@ -43,185 +43,195 @@ data:
#### Available Pubsub drivers
Dapr: https://dapr.io/

### Violations

The audit pod publishes violations in following format:

```json
{
"id": "2023-07-18T21:21:52Z",
"details": {
"missing_labels": [
"test"
]
},
"eventType": "violation_audited",
"group": "constraints.gatekeeper.sh",
"version": "v1beta1",
"kind": "K8sRequiredLabels",
"name": "pod-must-have-test",
"message": "you must provide labels: {\"test\"}",
"enforcementAction": "deny",
"resourceAPIVersion": "v1",
"resourceKind": "Pod",
"resourceNamespace": "nginx",
"resourceName": "nginx-deployment-cd55c47f5-2b84x",
"resourceLabels": {
"app": "nginx",
"pod-template-hash": "cd55c47f5"
}
}
```

### Quick start with publishing violations using Dapr and Redis

> Redis is used for example purposes only. Dapr supports [many different state store options](https://docs.dapr.io/reference/components-reference/supported-state-stores/).

#### Prerequisites

1. Install Dapr

To install Dapr with specific requirements and configuration, please refer to [Dapr docs](https://docs.dapr.io/operations/hosting/kubernetes/kubernetes-deploy/).
> Dapr is installed with mtls enabled by default, for more details on the same plaase refer to [Dapr security](https://docs.dapr.io/operations/security/mtls/#setting-up-mtls-with-the-configuration-resource).
To install Dapr with specific requirements and configuration, please refer to [Dapr docs](https://docs.dapr.io/operations/hosting/kubernetes/kubernetes-deploy/).
> [!IMPORTANT]
> - Make sure to set `SIDECAR_DROP_ALL_CAPABILITIES` environment variable on `dapr-sidecar` injector pod to `true` to avoid getting `PodSecurity violation` errors for the injected sidecar container as Gatekeeper by default requires workloads to run with [restricted](https://kubernetes.io/docs/concepts/security/pod-security-standards/#restricted) policy. If using helm charts to install Dapr, you can use `--set dapr_sidecar_injector.sidecarDropALLCapabilities=true`.
> - Additionally, [configure appropriate seccompProfile for sidecar containers](https://docs.dapr.io/operations/hosting/kubernetes/kubernetes-production/#configure-seccompprofile-for-sidecar-containers) injected by Dapr to avoid getting `PodSecurity violation` errors.
JaydipGabani marked this conversation as resolved.
Show resolved Hide resolved

> Dapr is installed with mtls enabled by default, for more details on the same please refer to [Dapr security](https://docs.dapr.io/operations/security/mtls/#setting-up-mtls-with-the-configuration-resource).

2. Install Redis

Please refer to [this](https://docs.dapr.io/getting-started/tutorials/configure-state-pubsub/#step-1-create-a-redis-store) guide to install Redis.

> To install Redis with TLS, please refer to [this](https://docs.bitnami.com/kubernetes/infrastructure/redis-cluster/administration/enable-tls/) doc.
> Redis is used for example purposes only. Dapr supports [many different state store options](https://docs.dapr.io/reference/components-reference/supported-state-stores/). To install Redis with TLS, please refer to [this](https://docs.bitnami.com/kubernetes/infrastructure/redis-cluster/administration/enable-tls/) doc.

#### Configure a sample subscriber to receive violations

1. Create `fake-subscriber` namespace and redis secret

```shell
kubectl create ns fake-subscriber
kubectl get secret redis --namespace=default -o yaml | sed 's/namespace: .*/namespace: fake-subscriber/' | kubectl apply -f - # creating redis secret in subscriber namespace to allow dapr sidecar to connect to redis instance
```
```shell
kubectl create ns fake-subscriber
# creating redis secret in subscriber namespace to allow dapr sidecar to connect to redis instance
kubectl get secret redis --namespace=default -o yaml | sed 's/namespace: .*/namespace: fake-subscriber/' | kubectl apply -f -
```

2. Create Dapr pubsub component
```shell
kubectl apply -f <<EOF
apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
name: pubsub
namespace: fake-subscriber
spec:
type: pubsub.redis
version: v1
metadata:
- name: redisHost
value: redis-master.default.svc.cluster.local:6379
- name: redisPassword
secretKeyRef:
name: redis
key: redis-password
```
> Please use [this guide](https://docs.dapr.io/reference/components-reference/supported-state-stores/setup-redis/) to properly configure Redis pubsub component for Dapr.

```shell
kubectl apply -f - <<EOF
apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
name: pubsub
namespace: fake-subscriber
spec:
type: pubsub.redis
version: v1
metadata:
- name: redisHost
value: redis-master.default.svc.cluster.local:6379
- name: redisPassword
secretKeyRef:
name: redis
key: redis-password
EOF
```

> Please use [this guide](https://docs.dapr.io/reference/components-reference/supported-state-stores/setup-redis/) to properly configure Redis pubsub component for Dapr.

3. Deploy subscriber application
```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: sub
namespace: fake-subscriber
labels:
app: sub
spec:
replicas: 1
selector:
matchLabels:
app: sub
template:

```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: sub
namespace: fake-subscriber
labels:
app: sub
annotations:
dapr.io/enabled: "true"
dapr.io/app-id: "subscriber"
dapr.io/enable-api-logging: "true"
dapr.io/app-port: "6002"
spec:
containers:
- name: go-sub
image: fake-subscriber:latest
imagePullPolicy: Never
```
**Note:** Dockerfile to build image for fake-subscriber is under [gatekeeper/test/fake-subscriber](https://github.com/open-policy-agent/gatekeeper/tree/master/test/pubsub/fake-subscriber). You can find make rule to build and deploy subscriber in [Makefile](https://github.com/open-policy-agent/gatekeeper/blob/master/Makefile) under name `e2e-subscriber-build-load-image` and `e2e-subscriber-deploy`.
replicas: 1
selector:
matchLabels:
app: sub
template:
metadata:
labels:
app: sub
annotations:
dapr.io/enabled: "true"
dapr.io/app-id: "subscriber"
dapr.io/enable-api-logging: "true"
dapr.io/app-port: "6002"
spec:
containers:
- name: go-sub
image: fake-subscriber:latest
imagePullPolicy: Never
```

> [!IMPORTANT]
> Please make sure `fake-subscriber` image is built and available in your cluster. Dockerfile to build image for `fake-subscriber` is under [gatekeeper/test/fake-subscriber](https://github.com/open-policy-agent/gatekeeper/tree/master/test/pubsub/fake-subscriber).

#### Configure Gatekeeper with Pubsub enabled

1. Create Dapr pubsub component and Redis secret in Gatekeeper's namespace (`gatekeeper-system` by default). Please make sure to update `gatekeeper-system` namespace for the next steps if your cluster's Gatekeeper namespace is different.

```shell
kubectl get secret redis --namespace=default -o yaml | sed 's/namespace: .*/namespace: gatekeeper-system/' | kubectl apply -f -
kubectl apply -f - <<EOF
apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
name: pubsub
namespace: gatekeeper-system
spec:
type: pubsub.redis
version: v1
metadata:
- name: redisHost
value: redis-master.default.svc.cluster.local:6379
- name: redisPassword
secretKeyRef:
name: redis
key: redis-password
EOF
```

2. Install Gatekeeper with `--enable-pub-sub` set to `true`, `--audit-connection` set to `audit-pubsub-connection`, `--audit-channel` set to `audit` on audit pod.
1. Create Gatekeeper namespace, and create Dapr pubsub component and Redis secret in Gatekeeper's namespace (`gatekeeper-system` by default). Please make sure to update `gatekeeper-system` namespace for the next steps if your cluster's Gatekeeper namespace is different.


```shell
echo 'auditPodAnnotations: {dapr.io/enabled: "true", dapr.io/app-id: "audit", dapr.io/metrics-port: "9999"}' > .tmp/annotations.yaml # auditPodAnnotations is used to add annotations required by Dapr to inject sidecar to audit pod
helm install gatekeeper/gatekeeper --name-template=gatekeeper --namespace gatekeeper-system \
--set audit.enablePubsub=true \
--set audit.connection=audit-pubsub-connection \
--set audit.channel=audit \
--values .tmp/annotations.yaml
```

**Note:** Verify that after the audit pod is running there is a dapr sidecar injected and running along side `manager` container.
```shell
kubectl create namespace gatekeeper-system
kubectl get secret redis --namespace=default -o yaml | sed 's/namespace: .*/namespace: gatekeeper-system/' | kubectl apply -f -
JaydipGabani marked this conversation as resolved.
Show resolved Hide resolved
kubectl apply -f - <<EOF
apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
name: pubsub
namespace: gatekeeper-system
spec:
type: pubsub.redis
version: v1
metadata:
- name: redisHost
value: redis-master.default.svc.cluster.local:6379
- name: redisPassword
secretKeyRef:
name: redis
key: redis-password
EOF
```

2. To upgrade or install Gatekeeper with `--enable-pub-sub` set to `true`, `--audit-connection` set to `audit-connection`, `--audit-channel` set to `audit-channel` on audit pod.

```shell
# auditPodAnnotations is used to add annotations required by Dapr to inject sidecar to audit pod
echo 'auditPodAnnotations: {dapr.io/enabled: "true", dapr.io/app-id: "audit", dapr.io/metrics-port: "9999", dapr.io/sidecar-seccomp-profile-type: "RuntimeDefault"}' > /tmp/annotations.yaml
helm upgrade --install gatekeeper/gatekeeper --namespace gatekeeper-system \
--set audit.enablePubsub=true \
--set audit.connection=audit-connection \
--set audit.channel=audit-channel \
JaydipGabani marked this conversation as resolved.
Show resolved Hide resolved
--values /tmp/annotations.yaml
```

**Note:** Verify that after the audit pod is running there is a dapr sidecar injected and running along side `manager` container.

3. Create connection config to establish a connection.

```shell
kubectl apply -f - <<EOF
apiVersion: v1
kind: ConfigMap
metadata:
name: audit-pubsub-connection
namespace: gatekeeper-system
data:
provider: "dapr"
config: |
{
"component": "pubsub"
}
EOF
```
**Note:** Name of the connection configMap must match the value of `--audit-connection` for it to be used by audit to publish violation. At the moment, now only one connection config can exists for audit.
```shell
kubectl apply -f - <<EOF
apiVersion: v1
kind: ConfigMap
metadata:
name: audit-connection
namespace: gatekeeper-system
data:
provider: "dapr"
config: |
{
"component": "pubsub"
}
EOF
```

**Note:** Name of the connection configMap must match the value of `--audit-connection` for it to be used by audit to publish violation. At the moment, only one connection config can exists for audit.

4. Create the constraint templates and constraints, and make sure audit ran by checking constraints. If constraint status is updated with information such as `auditTimeStamp` or `totalViolations`, then audit has ran at least once. Additionally, populated `TOTAL-VIOLATIONS` field for all constraints while listing constraints also indicates that audit has ran at least once.

```log
kubectl get constraint
NAME ENFORCEMENT-ACTION TOTAL-VIOLATIONS
pod-must-have-test 0
```

4. Create the constraint templates and constraints, and make sure audit ran by checking constraints. If constaint status is updated with information such as `auditTimeStamp` or `totalViolations`, then audit has ran atleast once. Additionally, populated `TOTAL-VIOLATIONS` field for all constraints while lising constraints also indicates that audit has ran at least once.
5. Finally, check the subscriber logs to see the violations received.

```log
kubctl get constraint
NAME ENFORCEMENT-ACTION TOTAL-VIOLATIONS
pod-must-have-test 0
```
```log
kubectl logs -l app=sub -c go-sub -n fake-subscriber
2023/07/18 20:16:41 Listening...
2023/07/18 20:37:20 main.PubsubMsg{ID:"2023-07-18T20:37:19Z", Details:map[string]interface {}{"missing_labels":[]interface {}{"test"}}, EventType:"violation_audited", Group:"constraints.gatekeeper.sh", Version:"v1beta1", Kind:"K8sRequiredLabels", Name:"pod-must-have-test", Namespace:"", Message:"you must provide labels: {\"test\"}", EnforcementAction:"deny", ConstraintAnnotations:map[string]string(nil), ResourceGroup:"", ResourceAPIVersion:"v1", ResourceKind:"Pod", ResourceNamespace:"nginx", ResourceName:"nginx-deployment-58899467f5-j85bs", ResourceLabels:map[string]string{"app":"nginx", "owner":"admin", "pod-template-hash":"58899467f5"}}
```

### Violations

5. Finally, check the subscriber logs to see the violations received.
The audit pod publishes violations in following format:

```log
kubectl logs pod/sub-57bd5d694-7lvzf -c go-sub -n fake-subscriber
2023/07/18 20:16:41 Listening...
2023/07/18 20:37:20 main.PubsubMsg{ID:"2023-07-18T20:37:19Z", Details:map[string]interface {}{"missing_labels":[]interface {}{"test"}}, EventType:"violation_audited", Group:"constraints.gatekeeper.sh", Version:"v1beta1", Kind:"K8sRequiredLabels", Name:"pod-must-have-test", Namespace:"", Message:"you must provide labels: {\"test\"}", EnforcementAction:"deny", ConstraintAnnotations:map[string]string(nil), ResourceGroup:"", ResourceAPIVersion:"v1", ResourceKind:"Pod", ResourceNamespace:"nginx", ResourceName:"nginx-deployment-58899467f5-j85bs", ResourceLabels:map[string]string{"app":"nginx", "owner":"admin", "pod-template-hash":"58899467f5"}}
```json
{
"id": "2023-07-18T21:21:52Z",
"details": {
"missing_labels": [
"test"
]
},
"eventType": "violation_audited",
"group": "constraints.gatekeeper.sh",
"version": "v1beta1",
"kind": "K8sRequiredLabels",
"name": "pod-must-have-test",
"message": "you must provide labels: {\"test\"}",
"enforcementAction": "deny",
"resourceAPIVersion": "v1",
"resourceKind": "Pod",
"resourceNamespace": "nginx",
"resourceName": "nginx-deployment-cd55c47f5-2b84x",
"resourceLabels": {
"app": "nginx",
"pod-template-hash": "cd55c47f5"
}
}
```
Loading
Loading