Skip to content

Commit 19fb771

Browse files
Merge pull request #688 from jetstack/VC-43753-include-extra-metadata
[VC-43753] Collect creationTimestamp, deletionTimestamp and resourceVersion metadata for Secret and Route resources
2 parents 68fd53f + cd2ac29 commit 19fb771

File tree

3 files changed

+53
-3
lines changed

3 files changed

+53
-3
lines changed

pkg/datagatherer/k8s/dynamic.go

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -350,6 +350,18 @@ func (g *DataGathererDynamic) Fetch() (interface{}, int, error) {
350350
return list, len(items), nil
351351
}
352352

353+
// redactList removes sensitive and superfluous data from the supplied resource list.
354+
// All resources have superfluous managed-data fields removed.
355+
// All resources have sensitive labels and annotations removed.
356+
// Secret and Route are processed as special cases. For these
357+
// resources there is an allow-list of fields that should be retained.
358+
// For Secret resources, the `data` is redacted, to prevent private keys or sensitive
359+
// data being collected; only the tls.crt and ca.crt data keys are retained.
360+
// For Route resources, only the fields related to CA certificate and policy are retained.
361+
// TODO(wallrj): A short coming of the current allow-list implementation is that
362+
// you have to specify absolute fields paths. It is not currently possible to
363+
// select all metadata with: `{metadata}`. This means that the metadata for
364+
// Secret and Route has fewer fields than the metadata for all other resources.
353365
func redactList(list []*api.GatheredResource, excludeAnnotKeys, excludeLabelKeys []*regexp.Regexp) error {
354366
for i := range list {
355367
if item, ok := list[i].Resource.(*unstructured.Unstructured); ok {
@@ -361,7 +373,7 @@ func redactList(list []*api.GatheredResource, excludeAnnotKeys, excludeLabelKeys
361373

362374
resource := item
363375

364-
// Redact item if it is a:
376+
// Redact item if it is a Secret or a Route.
365377
for _, gvk := range gvks {
366378
// secret object
367379
if gvk.Kind == "Secret" && (gvk.Group == "core" || gvk.Group == "") {

pkg/datagatherer/k8s/fieldfilter.go

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,10 @@ import (
55
)
66

77
// SecretSelectedFields is the list of fields sent from Secret objects to the
8-
// backend
8+
// backend.
9+
// The `data` is redacted, to prevent private keys or sensitive data being
10+
// collected. Only the following none-sensitive keys are retained: tls.crt,
11+
// ca.crt. These keys are assumed to always contain public TLS certificates.
912
var SecretSelectedFields = []FieldPath{
1013
{"kind"},
1114
{"apiVersion"},
@@ -16,14 +19,26 @@ var SecretSelectedFields = []FieldPath{
1619
{"metadata", "ownerReferences"},
1720
{"metadata", "selfLink"},
1821
{"metadata", "uid"},
22+
{"metadata", "creationTimestamp"},
23+
{"metadata", "deletionTimestamp"},
24+
{"metadata", "resourceVersion"},
1925

2026
{"type"},
2127
{"data", "tls.crt"},
2228
{"data", "ca.crt"},
2329
}
2430

2531
// RouteSelectedFields is the list of fields sent from OpenShift Route objects to the
26-
// backend
32+
// backend.
33+
// The Route resource is redacted because it may contain private keys for TLS.
34+
//
35+
// TODO(wallrj): Find out if the `.tls.key` field is the only one that may
36+
// contain sensitive data and if so, that field could be redacted instead
37+
// selecting everything else, for consistency with Ingress or any of the other
38+
// resources that are collected. Or alternatively add an comment to explain why
39+
// for Route, the set of fields is allow-listed while for Ingress, all fields
40+
// are collected.
41+
// https://docs.redhat.com/en/documentation/openshift_container_platform/4.19/html/network_apis/route-route-openshift-io-v1#spec-tls-3
2742
var RouteSelectedFields = []FieldPath{
2843
{"kind"},
2944
{"apiVersion"},
@@ -33,6 +48,9 @@ var RouteSelectedFields = []FieldPath{
3348
{"metadata", "ownerReferences"},
3449
{"metadata", "selfLink"},
3550
{"metadata", "uid"},
51+
{"metadata", "creationTimestamp"},
52+
{"metadata", "deletionTimestamp"},
53+
{"metadata", "resourceVersion"},
3654

3755
{"spec", "host"},
3856
{"spec", "to", "kind"},

pkg/datagatherer/k8s/fieldfilter_test.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,13 @@ func TestSelect(t *testing.T) {
2525
"labels": map[string]interface{}{
2626
"foo": "bar",
2727
},
28+
"resourceVersion": "fake-resource-version",
29+
"creationTimestamp": "2025-08-15T00:00:01Z",
30+
"deletionTimestamp": "2025-08-15T00:00:02Z",
31+
// Examples of fields which are dropped
32+
"deletionGracePeriodSeconds": 10,
33+
"finalizers": []string{"example.com/fake-finalizer"},
34+
"generation": 11,
2835
},
2936
"type": "kubernetes.io/tls",
3037
"data": map[string]interface{}{
@@ -47,6 +54,9 @@ func TestSelect(t *testing.T) {
4754
"labels": map[string]interface{}{
4855
"foo": "bar",
4956
},
57+
"resourceVersion": "fake-resource-version",
58+
"creationTimestamp": "2025-08-15T00:00:01Z",
59+
"deletionTimestamp": "2025-08-15T00:00:02Z",
5060
},
5161
"type": "kubernetes.io/tls",
5262
"data": map[string]interface{}{
@@ -68,6 +78,13 @@ func TestSelect(t *testing.T) {
6878
"labels": map[string]interface{}{
6979
"foo": "bar",
7080
},
81+
"resourceVersion": "fake-resource-version",
82+
"creationTimestamp": "2025-08-15T00:00:01Z",
83+
"deletionTimestamp": "2025-08-15T00:00:02Z",
84+
// Examples of fields which are dropped
85+
"deletionGracePeriodSeconds": 10,
86+
"finalizers": []string{"example.com/fake-finalizer"},
87+
"generation": 11,
7188
},
7289
"spec": map[string]interface{}{
7390
"host": "www.example.com",
@@ -94,6 +111,9 @@ func TestSelect(t *testing.T) {
94111
// "Select". "Redact" removes it.
95112
"kubectl.kubernetes.io/last-applied-configuration": "secret",
96113
},
114+
"resourceVersion": "fake-resource-version",
115+
"creationTimestamp": "2025-08-15T00:00:01Z",
116+
"deletionTimestamp": "2025-08-15T00:00:02Z",
97117
},
98118
"spec": map[string]interface{}{
99119
"host": "www.example.com",

0 commit comments

Comments
 (0)