Skip to content

Commit 4097047

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

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
@@ -6,6 +6,7 @@ import (
66
"log"
77
"net/url"
88
"os"
9+
"regexp"
910
"time"
1011

1112
"github.com/hashicorp/go-multierror"
@@ -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
@@ -581,6 +590,27 @@ func ValidateAndCombineConfig(log *log.Logger, cfg Config, flags AgentCmdFlags)
581590
res.DisableCompression = flags.DisableCompression
582591
}
583592

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

pkg/agent/run.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import (
3030
"github.com/jetstack/preflight/api"
3131
"github.com/jetstack/preflight/pkg/client"
3232
"github.com/jetstack/preflight/pkg/datagatherer"
33+
"github.com/jetstack/preflight/pkg/datagatherer/k8s"
3334
"github.com/jetstack/preflight/pkg/kubeconfig"
3435
"github.com/jetstack/preflight/pkg/logs"
3536
"github.com/jetstack/preflight/pkg/version"
@@ -154,6 +155,12 @@ func Run(cmd *cobra.Command, args []string) {
154155
logs.Log.Fatalf("failed to instantiate %q data gatherer %q: %v", kind, dgConfig.Name, err)
155156
}
156157

158+
dynDg, isDynamicGatherer := newDg.(*k8s.DataGathererDynamic)
159+
if isDynamicGatherer {
160+
dynDg.ExcludeAnnotKeys = config.ExcludeAnnotationKeysRegex
161+
dynDg.ExcludeLabelKeys = config.ExcludeLabelKeysRegex
162+
}
163+
157164
logs.Log.Printf("starting %q datagatherer", dgConfig.Name)
158165

159166
// 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

@@ -258,6 +259,9 @@ type DataGathererDynamic struct {
258259
// informer watches the events around the targeted resource and updates the cache
259260
informer k8scache.SharedIndexInformer
260261
registration k8scache.ResourceEventHandlerRegistration
262+
263+
ExcludeAnnotKeys []*regexp.Regexp
264+
ExcludeLabelKeys []*regexp.Regexp
261265
}
262266

263267
// Run starts the dynamic data gatherer's informers for resource collection.
@@ -335,7 +339,7 @@ func (g *DataGathererDynamic) Fetch() (interface{}, int, error) {
335339
}
336340

337341
// Redact Secret data
338-
err := redactList(items)
342+
err := redactList(items, g.ExcludeAnnotKeys, g.ExcludeLabelKeys)
339343
if err != nil {
340344
return nil, -1, errors.WithStack(err)
341345
}
@@ -346,7 +350,7 @@ func (g *DataGathererDynamic) Fetch() (interface{}, int, error) {
346350
return list, len(items), nil
347351
}
348352

349-
func redactList(list []*api.GatheredResource) error {
353+
func redactList(list []*api.GatheredResource, excludeAnnotKeys, excludeLabelKeys []*regexp.Regexp) error {
350354
for i := range list {
351355
if item, ok := list[i].Resource.(*unstructured.Unstructured); ok {
352356
// Determine the kind of items in case this is a generic 'mixed' list.
@@ -371,6 +375,43 @@ func redactList(list []*api.GatheredResource) error {
371375

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

@@ -383,6 +424,24 @@ func redactList(list []*api.GatheredResource) error {
383424
item.GetObjectMeta().SetManagedFields(nil)
384425
delete(item.GetObjectMeta().GetAnnotations(), "kubectl.kubernetes.io/last-applied-configuration")
385426

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

0 commit comments

Comments
 (0)