Skip to content

Commit 3fecd1b

Browse files
authored
feat: Add audit policy patch (#126)
1 parent a420f81 commit 3fecd1b

File tree

12 files changed

+574
-57
lines changed

12 files changed

+574
-57
lines changed

.pre-commit-config.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ repos:
101101
name: License headers - YAML and Makefiles
102102
stages: [commit]
103103
files: (^Makefile|\.(ya?ml|mk))$
104+
exclude: ^pkg/handlers/.+/embedded/.+\.ya?ml$
104105
args:
105106
- --license-filepath
106107
- hack/license-header.txt

charts/capi-runtime-extensions/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ A Helm chart for capi-runtime-extensions
3131
| controllers.enableLeaderElection | bool | `false` | |
3232
| deployment.replicas | int | `1` | |
3333
| env | object | `{}` | |
34+
| handlers.AuditPolicyPatch.enabled | bool | `true` | |
3435
| handlers.CalicoCNI.defaultInstallationConfigMaps.DockerCluster.configMap.content | string | `""` | |
3536
| handlers.CalicoCNI.defaultInstallationConfigMaps.DockerCluster.configMap.name | string | `"calico-cni-installation-dockercluster"` | |
3637
| handlers.CalicoCNI.defaultInstallationConfigMaps.DockerCluster.create | bool | `true` | |

charts/capi-runtime-extensions/values.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ handlers:
1919
enabled: true
2020
HTTPProxyPatch:
2121
enabled: true
22+
AuditPolicyPatch:
23+
enabled: true
2224

2325
deployment:
2426
replicas: 1

docs/content/audit-policy.md

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
---
2+
title: "Audit policy"
3+
---
4+
5+
Kubernetes auditing provides a security-relevant, chronological set of records documenting the sequence of actions in a
6+
cluster. The cluster audits the activities generated by users, by applications that use the Kubernetes API, and by the
7+
control plane itself. The `auditpolicypatch` external patch will generate appropriate configuration for the Kubernetes
8+
control plane.
9+
10+
To enable the audit policy enable the `auditpolicypatch` external patch on `ClusterClass`.
11+
12+
```yaml
13+
apiVersion: cluster.x-k8s.io/v1beta1
14+
kind: ClusterClass
15+
metadata:
16+
name: <NAME>
17+
spec:
18+
patches:
19+
- name: audit-policy
20+
external:
21+
generateExtension: "auditpolicypatch.<external-config-name>"
22+
```
23+
24+
Applying this configuration will result in new bootstrap files on the `KubeadmControlPlaneTemplate`.
25+
26+
This hook is enabled by default, and can be explicitly disabled by omitting the `AuditPolicyPatch` hook from the
27+
`--runtimehooks.enabled-handlers` flag.
28+
29+
If deploying via Helm, then this can be disabled by setting `handlers.AuditPolicyPatch.enabled=false`.

internal/runtimehooks/webhooks/server.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,13 @@ func (s *Server) AddFlags(prefix string, fs *pflag.FlagSet) {
6464
fs.StringSliceVar(
6565
&s.enabledHandlers,
6666
prefix+".enabled-handlers",
67-
[]string{"ServiceLoadBalancerGC", "CalicoCNI", "HTTPProxyPatch", "HTTPProxyVars"},
67+
[]string{
68+
"ServiceLoadBalancerGC",
69+
"CalicoCNI",
70+
"HTTPProxyPatch",
71+
"HTTPProxyVars",
72+
"AuditPolicyPatch",
73+
},
6874
"list of all enabled handlers",
6975
)
7076

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
// Copyright 2023 D2iQ, Inc. All rights reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
package patches
5+
6+
import (
7+
"fmt"
8+
9+
"github.com/go-logr/logr"
10+
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
11+
"k8s.io/apimachinery/pkg/runtime"
12+
clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
13+
runtimehooksv1 "sigs.k8s.io/cluster-api/exp/runtime/hooks/api/v1alpha1"
14+
15+
"github.com/d2iq-labs/capi-runtime-extensions/pkg/capi/clustertopology/patches/matchers"
16+
)
17+
18+
func Generate[T runtime.Object](
19+
obj runtime.Object,
20+
vars map[string]apiextensionsv1.JSON,
21+
holderRef *runtimehooksv1.HolderReference,
22+
patchSelector clusterv1.PatchSelector,
23+
log logr.Logger,
24+
mutFn func(T) error,
25+
) error {
26+
typed, ok := obj.(T)
27+
if !ok {
28+
log.V(5).WithValues(
29+
"objType", fmt.Sprintf("%T", obj),
30+
"expectedType", fmt.Sprintf("%T", *new(T)),
31+
).Info("not matching type")
32+
return nil
33+
}
34+
35+
if !matchers.MatchesSelector(patchSelector, obj, holderRef, vars) {
36+
log.WithValues("selector", patchSelector).Info("not matching selector")
37+
return nil
38+
}
39+
40+
return mutFn(typed)
41+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
// Copyright 2023 D2iQ, Inc. All rights reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
package selectors
5+
6+
import (
7+
clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
8+
bootstrapv1 "sigs.k8s.io/cluster-api/bootstrap/kubeadm/api/v1beta1"
9+
controlplanev1 "sigs.k8s.io/cluster-api/controlplane/kubeadm/api/v1beta1"
10+
)
11+
12+
func ControlPlane() clusterv1.PatchSelector {
13+
return clusterv1.PatchSelector{
14+
APIVersion: controlplanev1.GroupVersion.String(),
15+
Kind: "KubeadmControlPlaneTemplate",
16+
MatchResources: clusterv1.PatchSelectorMatch{
17+
ControlPlane: true,
18+
},
19+
}
20+
}
21+
22+
func DefaultWorkerSelector() clusterv1.PatchSelector {
23+
return clusterv1.PatchSelector{
24+
APIVersion: bootstrapv1.GroupVersion.String(),
25+
Kind: "KubeadmConfigTemplate",
26+
MatchResources: clusterv1.PatchSelectorMatch{
27+
MachineDeploymentClass: &clusterv1.PatchSelectorMatchMachineDeploymentClass{
28+
Names: []string{
29+
"default-worker",
30+
},
31+
},
32+
},
33+
}
34+
}
35+
36+
func AllWorkersSelector() clusterv1.PatchSelector {
37+
return clusterv1.PatchSelector{
38+
APIVersion: bootstrapv1.GroupVersion.String(),
39+
Kind: "KubeadmConfigTemplate",
40+
MatchResources: clusterv1.PatchSelectorMatch{
41+
MachineDeploymentClass: &clusterv1.PatchSelectorMatchMachineDeploymentClass{
42+
Names: []string{
43+
"*",
44+
},
45+
},
46+
},
47+
}
48+
}
Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
# Taken from https://github.com/kubernetes/kubernetes/blob/master/cluster/gce/gci/configure-helper.sh
2+
# Recommended in Kubernetes docs
3+
apiVersion: audit.k8s.io/v1
4+
kind: Policy
5+
rules:
6+
# The following requests were manually identified as high-volume and low-risk,
7+
# so drop them.
8+
- level: None
9+
users: ["system:kube-proxy"]
10+
verbs: ["watch"]
11+
resources:
12+
- group: "" # core
13+
resources: ["endpoints", "services", "services/status"]
14+
- level: None
15+
# Ingress controller reads 'configmaps/ingress-uid' through the unsecured port.
16+
# TODO(#46983): Change this to the ingress controller service account.
17+
users: ["system:unsecured"]
18+
namespaces: ["kube-system"]
19+
verbs: ["get"]
20+
resources:
21+
- group: "" # core
22+
resources: ["configmaps"]
23+
- level: None
24+
users: ["kubelet"] # legacy kubelet identity
25+
verbs: ["get"]
26+
resources:
27+
- group: "" # core
28+
resources: ["nodes", "nodes/status"]
29+
- level: None
30+
userGroups: ["system:nodes"]
31+
verbs: ["get"]
32+
resources:
33+
- group: "" # core
34+
resources: ["nodes", "nodes/status"]
35+
- level: None
36+
users:
37+
- system:kube-controller-manager
38+
- system:kube-scheduler
39+
- system:serviceaccount:kube-system:endpoint-controller
40+
verbs: ["get", "update"]
41+
namespaces: ["kube-system"]
42+
resources:
43+
- group: "" # core
44+
resources: ["endpoints"]
45+
- level: None
46+
users: ["system:apiserver"]
47+
verbs: ["get"]
48+
resources:
49+
- group: "" # core
50+
resources: ["namespaces", "namespaces/status", "namespaces/finalize"]
51+
- level: None
52+
users: ["cluster-autoscaler"]
53+
verbs: ["get", "update"]
54+
namespaces: ["kube-system"]
55+
resources:
56+
- group: "" # core
57+
resources: ["configmaps", "endpoints"]
58+
# Don't log HPA fetching metrics.
59+
- level: None
60+
users:
61+
- system:kube-controller-manager
62+
verbs: ["get", "list"]
63+
resources:
64+
- group: "metrics.k8s.io"
65+
# Don't log these read-only URLs.
66+
- level: None
67+
nonResourceURLs:
68+
- /healthz*
69+
- /version
70+
- /swagger*
71+
# Don't log events requests.
72+
- level: None
73+
resources:
74+
- group: "" # core
75+
resources: ["events"]
76+
# node and pod status calls from nodes are high-volume and can be large, don't log responses for expected updates from nodes
77+
- level: Request
78+
users: ["kubelet", "system:node-problem-detector", "system:serviceaccount:kube-system:node-problem-detector"]
79+
verbs: ["update","patch"]
80+
resources:
81+
- group: "" # core
82+
resources: ["nodes/status", "pods/status"]
83+
omitStages:
84+
- "RequestReceived"
85+
- level: Request
86+
userGroups: ["system:nodes"]
87+
verbs: ["update","patch"]
88+
resources:
89+
- group: "" # core
90+
resources: ["nodes/status", "pods/status"]
91+
omitStages:
92+
- "RequestReceived"
93+
# deletecollection calls can be large, don't log responses for expected namespace deletions
94+
- level: Request
95+
users: ["system:serviceaccount:kube-system:namespace-controller"]
96+
verbs: ["deletecollection"]
97+
omitStages:
98+
- "RequestReceived"
99+
# Secrets, ConfigMaps, and TokenReviews can contain sensitive & binary data,
100+
# so only log at the Metadata level.
101+
- level: Metadata
102+
resources:
103+
- group: "" # core
104+
resources: ["secrets", "configmaps"]
105+
- group: authentication.k8s.io
106+
resources: ["tokenreviews"]
107+
omitStages:
108+
- "RequestReceived"
109+
# Get responses can be large; skip them.
110+
- level: Request
111+
verbs: ["get", "list", "watch"]
112+
resources:
113+
- group: "" # core
114+
- group: "admissionregistration.k8s.io"
115+
- group: "apiextensions.k8s.io"
116+
- group: "apiregistration.k8s.io"
117+
- group: "apps"
118+
- group: "authentication.k8s.io"
119+
- group: "authorization.k8s.io"
120+
- group: "autoscaling"
121+
- group: "batch"
122+
- group: "certificates.k8s.io"
123+
- group: "extensions"
124+
- group: "metrics.k8s.io"
125+
- group: "networking.k8s.io"
126+
- group: "node.k8s.io"
127+
- group: "policy"
128+
- group: "rbac.authorization.k8s.io"
129+
- group: "scheduling.k8s.io"
130+
- group: "settings.k8s.io"
131+
- group: "storage.k8s.io"
132+
omitStages:
133+
- "RequestReceived"
134+
# Default level for known APIs
135+
- level: RequestResponse
136+
resources:
137+
- group: "" # core
138+
- group: "admissionregistration.k8s.io"
139+
- group: "apiextensions.k8s.io"
140+
- group: "apiregistration.k8s.io"
141+
- group: "apps"
142+
- group: "authentication.k8s.io"
143+
- group: "authorization.k8s.io"
144+
- group: "autoscaling"
145+
- group: "batch"
146+
- group: "certificates.k8s.io"
147+
- group: "extensions"
148+
- group: "metrics.k8s.io"
149+
- group: "networking.k8s.io"
150+
- group: "node.k8s.io"
151+
- group: "policy"
152+
- group: "rbac.authorization.k8s.io"
153+
- group: "scheduling.k8s.io"
154+
- group: "settings.k8s.io"
155+
- group: "storage.k8s.io"
156+
omitStages:
157+
- "RequestReceived"
158+
# Default level for all other requests.
159+
- level: Metadata
160+
omitStages:
161+
- "RequestReceived"

0 commit comments

Comments
 (0)