Skip to content

Commit f3e10d8

Browse files
committed
annot-exclusion: it is now possible to exclude labels and annotations
1 parent d2fb4f0 commit f3e10d8

File tree

8 files changed

+266
-52
lines changed

8 files changed

+266
-52
lines changed

deploy/charts/venafi-kubernetes-agent/README.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -423,6 +423,26 @@ Control Plane.
423423
> ```yaml
424424
> helm.sh/release.v1
425425
> ```
426+
#### **config.excludeAnnotationKeysRegex** ~ `array`
427+
> Default value:
428+
> ```yaml
429+
> []
430+
> ```
431+
432+
You can configure Venafi Kubernetes Agent to exclude some annotations or labels from being pushed to the Venafi Control Plane. All Kubernetes objects are affected. The objects are still pushed, but the specified annotations and labels are removed before being sent to the Venafi Control Plane.
433+
434+
If you would like to exclude annotations keys that contain the word
435+
`secret`, use the regular expression `.*secret.*`. The leading and ending .*
436+
are important if you want to filter out keys that contain `secret` anywhere in the key string.
437+
438+
Note that the annotation `kubectl.kubernetes.io/last-applied-configuration` is already excluded by default, you don't need to exclude it explicitly.
439+
440+
Example: excludeAnnotationKeysRegex: [".*secret.*"]
441+
#### **config.excludeLabelKeysRegex** ~ `array`
442+
> Default value:
443+
> ```yaml
444+
> []
445+
> ```
426446
#### **config.configmap.name** ~ `unknown`
427447
> Default value:
428448
> ```yaml

deploy/charts/venafi-kubernetes-agent/templates/configmap.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ data:
1313
cluster_description: {{ .Values.config.clusterDescription | quote }}
1414
server: {{ .Values.config.server | quote }}
1515
period: {{ .Values.config.period | quote }}
16+
exclude-annotation-keys-regex:
17+
{{ .Values.config.excludeAnnotationKeysRegex | nindent 6 }}
18+
exclude-label-keys-regex:
19+
{{ .Values.config.excludeLabelKeysRegex | nindent 6 }}
1620
venafi-cloud:
1721
uploader_id: "no"
1822
upload_path: "/v1/tlspk/upload/clusterdata"

deploy/charts/venafi-kubernetes-agent/values.schema.json

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,12 @@
165165
"configmap": {
166166
"$ref": "#/$defs/helm-values.config.configmap"
167167
},
168+
"excludeAnnotationKeysRegex": {
169+
"$ref": "#/$defs/helm-values.config.excludeAnnotationKeysRegex"
170+
},
171+
"excludeLabelKeysRegex": {
172+
"$ref": "#/$defs/helm-values.config.excludeLabelKeysRegex"
173+
},
168174
"ignoredSecretTypes": {
169175
"$ref": "#/$defs/helm-values.config.ignoredSecretTypes"
170176
},
@@ -206,6 +212,17 @@
206212
},
207213
"helm-values.config.configmap.key": {},
208214
"helm-values.config.configmap.name": {},
215+
"helm-values.config.excludeAnnotationKeysRegex": {
216+
"default": [],
217+
"description": "You can configure Venafi Kubernetes Agent to exclude some annotations or labels from being pushed to the Venafi Control Plane. All Kubernetes objects are affected. The objects are still pushed, but the specified annotations and labels are removed before being sent to the Venafi Control Plane.\n\nIf you would like to exclude annotations keys that contain the word\n`secret`, use the regular expression `.*secret.*`. The leading and ending .*\nare important if you want to filter out keys that contain `secret` anywhere in the key string.\n\nNote that the annotation `kubectl.kubernetes.io/last-applied-configuration` is already excluded by default, you don't need to exclude it explicitly.\n\nExample: excludeAnnotationKeysRegex: [\".*secret.*\"]",
218+
"items": {},
219+
"type": "array"
220+
},
221+
"helm-values.config.excludeLabelKeysRegex": {
222+
"default": [],
223+
"items": {},
224+
"type": "array"
225+
},
209226
"helm-values.config.ignoredSecretTypes": {
210227
"items": {
211228
"$ref": "#/$defs/helm-values.config.ignoredSecretTypes[0]"

deploy/charts/venafi-kubernetes-agent/values.yaml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,23 @@ config:
238238
- bootstrap.kubernetes.io/token
239239
- helm.sh/release.v1
240240

241+
# You can configure Venafi Kubernetes Agent to exclude some annotations or
242+
# labels from being pushed to the Venafi Control Plane. All Kubernetes objects
243+
# are affected. The objects are still pushed, but the specified annotations
244+
# and labels are removed before being sent to the Venafi Control Plane.
245+
#
246+
# If you would like to exclude annotations keys that contain the word
247+
# `secret`, use the regular expression `.*secret.*`. The leading and ending .*
248+
# are important if you want to filter out keys that contain `secret` anywhere
249+
# in the key string.
250+
#
251+
# Note that the annotation `kubectl.kubernetes.io/last-applied-configuration`
252+
# is already excluded by default, you don't need to exclude it explicitly.
253+
#
254+
# Example: excludeAnnotationKeysRegex: [".*secret.*"]
255+
excludeAnnotationKeysRegex: []
256+
excludeLabelKeysRegex: []
257+
241258
# Specify ConfigMap details to load config from an existing resource.
242259
# This should be blank by default unless you have you own config.
243260
configmap:

pkg/agent/config.go

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"io"
66
"net/url"
77
"os"
8+
"regexp"
89
"time"
910

1011
"github.com/go-logr/logr"
@@ -54,6 +55,12 @@ type Config struct {
5455
InputPath string `yaml:"input-path"`
5556
// For testing purposes.
5657
OutputPath string `yaml:"output-path"`
58+
59+
// Skips annotation keys that match the given set of regular expressions.
60+
// Example: ".*someprivateannotation.*".
61+
ExcludeAnnotationKeysRegex []string `yaml:"exclude-annotation-keys-regex"`
62+
// Skips label keys that match the given set of regular expressions.
63+
ExcludeLabelKeysRegex []string `yaml:"exclude-label-keys-regex"`
5764
}
5865

5966
type Endpoint struct {
@@ -339,7 +346,9 @@ type CombinedConfig struct {
339346
VenConnNS string
340347

341348
// VenafiCloudKeypair and VenafiCloudVenafiConnection modes only.
342-
DisableCompression bool
349+
DisableCompression bool
350+
ExcludeAnnotationKeysRegex []*regexp.Regexp
351+
ExcludeLabelKeysRegex []*regexp.Regexp
343352

344353
// Only used for testing purposes.
345354
OutputPath string
@@ -585,6 +594,27 @@ func ValidateAndCombineConfig(log logr.Logger, cfg Config, flags AgentCmdFlags)
585594
res.DisableCompression = flags.DisableCompression
586595
}
587596

597+
// Validation of the config fields exclude_annotation_keys_regex and
598+
// exclude_label_keys_regex.
599+
{
600+
for i, regex := range cfg.ExcludeAnnotationKeysRegex {
601+
r, err := regexp.Compile(regex)
602+
if err != nil {
603+
errs = multierror.Append(errs, fmt.Errorf("invalid exclude_annotation_keys_regex[%d]: %w", i, err))
604+
continue
605+
}
606+
res.ExcludeAnnotationKeysRegex = append(res.ExcludeAnnotationKeysRegex, r)
607+
}
608+
for i, regex := range cfg.ExcludeLabelKeysRegex {
609+
r, err := regexp.Compile(regex)
610+
if err != nil {
611+
errs = multierror.Append(errs, fmt.Errorf("invalid exclude_label_keys_regex[%d]: %w", i, err))
612+
continue
613+
}
614+
res.ExcludeLabelKeysRegex = append(res.ExcludeLabelKeysRegex, r)
615+
}
616+
}
617+
588618
if errs != nil {
589619
return CombinedConfig{}, nil, errs
590620
}

pkg/agent/run.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ import (
3434
"github.com/jetstack/preflight/api"
3535
"github.com/jetstack/preflight/pkg/client"
3636
"github.com/jetstack/preflight/pkg/datagatherer"
37+
"github.com/jetstack/preflight/pkg/datagatherer/k8s"
3738
"github.com/jetstack/preflight/pkg/kubeconfig"
3839
"github.com/jetstack/preflight/pkg/logs"
3940
"github.com/jetstack/preflight/pkg/version"
@@ -176,6 +177,12 @@ func Run(cmd *cobra.Command, args []string) (returnErr error) {
176177
return fmt.Errorf("failed to instantiate %q data gatherer %q: %v", kind, dgConfig.Name, err)
177178
}
178179

180+
dynDg, isDynamicGatherer := newDg.(*k8s.DataGathererDynamic)
181+
if isDynamicGatherer {
182+
dynDg.ExcludeAnnotKeys = config.ExcludeAnnotationKeysRegex
183+
dynDg.ExcludeLabelKeys = config.ExcludeLabelKeysRegex
184+
}
185+
179186
log.V(logs.Debug).Info("Starting DataGatherer", "name", dgConfig.Name)
180187

181188
// start the data gatherers and wait for the cache sync

pkg/datagatherer/k8s/dynamic.go

Lines changed: 61 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package k8s
33
import (
44
"context"
55
"fmt"
6+
"regexp"
67
"strings"
78
"time"
89

@@ -260,6 +261,9 @@ type DataGathererDynamic struct {
260261
// informer watches the events around the targeted resource and updates the cache
261262
informer k8scache.SharedIndexInformer
262263
registration k8scache.ResourceEventHandlerRegistration
264+
265+
ExcludeAnnotKeys []*regexp.Regexp
266+
ExcludeLabelKeys []*regexp.Regexp
263267
}
264268

265269
// Run starts the dynamic data gatherer's informers for resource collection.
@@ -338,7 +342,7 @@ func (g *DataGathererDynamic) Fetch() (interface{}, int, error) {
338342
}
339343

340344
// Redact Secret data
341-
err := redactList(items)
345+
err := redactList(items, g.ExcludeAnnotKeys, g.ExcludeLabelKeys)
342346
if err != nil {
343347
return nil, -1, errors.WithStack(err)
344348
}
@@ -349,7 +353,7 @@ func (g *DataGathererDynamic) Fetch() (interface{}, int, error) {
349353
return list, len(items), nil
350354
}
351355

352-
func redactList(list []*api.GatheredResource) error {
356+
func redactList(list []*api.GatheredResource, excludeAnnotKeys, excludeLabelKeys []*regexp.Regexp) error {
353357
for i := range list {
354358
if item, ok := list[i].Resource.(*unstructured.Unstructured); ok {
355359
// Determine the kind of items in case this is a generic 'mixed' list.
@@ -374,6 +378,43 @@ func redactList(list []*api.GatheredResource) error {
374378

375379
// remove managedFields from all resources
376380
Redact(RedactFields, resource)
381+
382+
annotsRaw, ok, err := unstructured.NestedFieldNoCopy(resource.Object, "metadata", "annotations")
383+
if err != nil {
384+
return fmt.Errorf("wasn't able to find the metadata.annotations field: %w", err)
385+
}
386+
if ok {
387+
annots, ok := annotsRaw.(map[string]interface{})
388+
if !ok {
389+
return fmt.Errorf("metadata.annotations isn't a map on the resource %s in namespace %s: %w", resource.GetName(), resource.GetNamespace(), err)
390+
}
391+
for key := range annots {
392+
for _, excludeAnnotKey := range excludeAnnotKeys {
393+
if excludeAnnotKey.MatchString(key) {
394+
delete(annots, key)
395+
}
396+
}
397+
}
398+
}
399+
400+
labelsRaw, ok, err := unstructured.NestedFieldNoCopy(resource.Object, "metadata", "labels")
401+
if err != nil {
402+
return fmt.Errorf("wasn't able to find the metadata.labels field for the resource %s in namespace %s: %w", resource.GetName(), resource.GetNamespace(), err)
403+
}
404+
if ok {
405+
labels, ok := labelsRaw.(map[string]interface{})
406+
if !ok {
407+
return fmt.Errorf("metadata.labels isn't a map on the resource %s in namespace %s: %w", resource.GetName(), resource.GetNamespace(), err)
408+
}
409+
for key := range labels {
410+
for _, excludeLabelKey := range excludeLabelKeys {
411+
if excludeLabelKey.MatchString(key) {
412+
delete(labels, key)
413+
}
414+
}
415+
}
416+
}
417+
377418
continue
378419
}
379420

@@ -386,6 +427,24 @@ func redactList(list []*api.GatheredResource) error {
386427
item.GetObjectMeta().SetManagedFields(nil)
387428
delete(item.GetObjectMeta().GetAnnotations(), "kubectl.kubernetes.io/last-applied-configuration")
388429

430+
annots := item.GetObjectMeta().GetAnnotations()
431+
for key := range annots {
432+
for _, excludeAnnotKey := range excludeAnnotKeys {
433+
if excludeAnnotKey.MatchString(key) {
434+
delete(annots, key)
435+
}
436+
}
437+
}
438+
439+
labels := item.GetObjectMeta().GetLabels()
440+
for key := range labels {
441+
for _, excludeLabelKey := range excludeLabelKeys {
442+
if excludeLabelKey.MatchString(key) {
443+
delete(labels, key)
444+
}
445+
}
446+
}
447+
389448
resource := item.(runtime.Object)
390449
gvks, _, err := scheme.Scheme.ObjectKinds(resource)
391450
if err != nil {

0 commit comments

Comments
 (0)