From 366b64ed1a628f915c54205986bbf4292c83cc9c Mon Sep 17 00:00:00 2001 From: James Phillips Date: Mon, 12 Sep 2022 10:17:35 -0700 Subject: [PATCH 1/8] add method to entity config to produce a redacted copy Signed-off-by: James Phillips --- api/core/v3/entity_config.go | 33 ++++++++ api/core/v3/entity_config_test.go | 85 ++++++++++++++++++-- api/core/v3/internal/strings/strings.go | 60 ++++++++++++++ api/core/v3/internal/strings/strings_test.go | 34 ++++++++ 4 files changed, 207 insertions(+), 5 deletions(-) create mode 100644 api/core/v3/internal/strings/strings.go create mode 100644 api/core/v3/internal/strings/strings_test.go diff --git a/api/core/v3/entity_config.go b/api/core/v3/entity_config.go index 1549dd4313..7db48b0fa1 100644 --- a/api/core/v3/entity_config.go +++ b/api/core/v3/entity_config.go @@ -5,6 +5,7 @@ import ( "strings" corev2 "github.com/sensu/sensu-go/api/core/v2" + stringutil "github.com/sensu/sensu-go/api/core/v3/internal/strings" ) var entityConfigRBACName = (&corev2.Entity{}).RBACName() @@ -31,3 +32,35 @@ func MergeMapWithPrefix(a map[string]string, b map[string]string, prefix string) a[prefix+k] = v } } + +func redactMap(m map[string]string, redact []string) map[string]string { + if len(redact) == 0 { + redact = corev2.DefaultRedactFields + } + result := make(map[string]string, len(m)) + for k, v := range m { + if stringutil.FoundInArray(k, redact) { + result[k] = corev2.Redacted + } else { + result[k] = v + } + } + return result +} + +// ProduceRedacted redacts the entity according to the entity's Redact fields. +// A redacted copy is returned. The copy contains pointers to the original's +// memory, with different Labels and Annotations. +func (e *EntityConfig) ProduceRedacted() *EntityConfig { + if e == nil { + return nil + } + if e.Metadata == nil || (e.Metadata.Labels == nil && e.Metadata.Annotations == nil) { + return e + } + copy := &EntityConfig{} + *copy = *e + copy.Metadata.Annotations = redactMap(e.Metadata.Annotations, e.Redact) + copy.Metadata.Labels = redactMap(e.Metadata.Labels, e.Redact) + return copy +} diff --git a/api/core/v3/entity_config_test.go b/api/core/v3/entity_config_test.go index 568ce1508a..fbc00653ad 100644 --- a/api/core/v3/entity_config_test.go +++ b/api/core/v3/entity_config_test.go @@ -4,7 +4,7 @@ import ( "reflect" "testing" - v2 "github.com/sensu/sensu-go/api/core/v2" + corev2 "github.com/sensu/sensu-go/api/core/v2" ) func TestEntityConfigFields(t *testing.T) { @@ -22,26 +22,26 @@ func TestEntityConfigFields(t *testing.T) { }, { name: "exposes deregister", - args: &EntityConfig{Metadata: &v2.ObjectMeta{}, Deregister: true}, + args: &EntityConfig{Metadata: &corev2.ObjectMeta{}, Deregister: true}, wantKey: "entity_config.deregister", want: "true", }, { name: "exposes class", - args: &EntityConfig{Metadata: &v2.ObjectMeta{}, EntityClass: "agent"}, + args: &EntityConfig{Metadata: &corev2.ObjectMeta{}, EntityClass: "agent"}, wantKey: "entity_config.entity_class", want: "agent", }, { name: "exposes subscriptions", - args: &EntityConfig{Metadata: &v2.ObjectMeta{}, Subscriptions: []string{"www", "unix"}}, + args: &EntityConfig{Metadata: &corev2.ObjectMeta{}, Subscriptions: []string{"www", "unix"}}, wantKey: "entity_config.subscriptions", want: "www,unix", }, { name: "exposes labels", args: &EntityConfig{ - Metadata: &v2.ObjectMeta{ + Metadata: &corev2.ObjectMeta{ Labels: map[string]string{"region": "philadelphia"}, }, }, @@ -58,3 +58,78 @@ func TestEntityConfigFields(t *testing.T) { }) } } + +func TestEntityConfig_ProduceRedacted(t *testing.T) { + tests := []struct { + name string + in *EntityConfig + want *EntityConfig + }{ + { + name: "nil metadata", + in: func() *EntityConfig { + cfg := FixtureEntityConfig("test") + cfg.Metadata = nil + return cfg + }(), + want: func() *EntityConfig { + cfg := FixtureEntityConfig("test") + cfg.Metadata = nil + return cfg + }(), + }, + { + name: "nothing to redact", + in: func() *EntityConfig { + cfg := FixtureEntityConfig("test") + cfg.Metadata.Labels["my_field"] = "test123" + return cfg + }(), + want: func() *EntityConfig { + cfg := FixtureEntityConfig("test") + cfg.Metadata.Labels["my_field"] = "test123" + return cfg + }(), + }, + { + name: "redact default fields", + in: func() *EntityConfig { + cfg := FixtureEntityConfig("test") + cfg.Metadata.Labels["my_field"] = "test123" + cfg.Metadata.Labels["password"] = "test123" + return cfg + }(), + want: func() *EntityConfig { + cfg := FixtureEntityConfig("test") + cfg.Metadata.Labels["my_field"] = "test123" + cfg.Metadata.Labels["password"] = corev2.Redacted + return cfg + }(), + }, + { + name: "redact custom fields", + in: func() *EntityConfig { + cfg := FixtureEntityConfig("test") + cfg.Redact = []string{"my_field"} + cfg.Metadata.Labels["my_field"] = "test123" + cfg.Metadata.Labels["password"] = "test123" + return cfg + }(), + want: func() *EntityConfig { + cfg := FixtureEntityConfig("test") + cfg.Redact = []string{"my_field"} + cfg.Metadata.Labels["my_field"] = corev2.Redacted + cfg.Metadata.Labels["password"] = "test123" + return cfg + }(), + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + e := tt.in + if got := e.ProduceRedacted(); !reflect.DeepEqual(got, tt.want) { + t.Errorf("EntityConfig.ProduceRedacted() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/api/core/v3/internal/strings/strings.go b/api/core/v3/internal/strings/strings.go new file mode 100644 index 0000000000..400bb517eb --- /dev/null +++ b/api/core/v3/internal/strings/strings.go @@ -0,0 +1,60 @@ +package strings + +import ( + "strings" + "unicode" +) + +const ( + lowerAlphaStart = 97 + lowerAlphaStop = 122 +) + +func isAlpha(r rune) bool { + return r >= lowerAlphaStart && r <= lowerAlphaStop +} + +func alphaNumeric(s string) bool { + for _, r := range s { + if !(unicode.IsDigit(r) || isAlpha(r)) { + return false + } + } + return true +} + +func normalize(s string) string { + if alphaNumeric(s) { + return s + } + lowered := strings.ToLower(s) + if alphaNumeric(lowered) { + return lowered + } + trimmed := make([]rune, 0, len(lowered)) + for _, r := range lowered { + if isAlpha(r) { + trimmed = append(trimmed, r) + } + } + return string(trimmed) +} + +// FoundInArray searches array for item without distinguishing between uppercase +// and lowercase and non-alphanumeric characters. Returns true if item is a +// value of array +func FoundInArray(item string, array []string) bool { + if item == "" || len(array) == 0 { + return false + } + + item = normalize(item) + + for i := range array { + if normalize(array[i]) == item { + return true + } + } + + return false +} diff --git a/api/core/v3/internal/strings/strings_test.go b/api/core/v3/internal/strings/strings_test.go new file mode 100644 index 0000000000..5b7e040541 --- /dev/null +++ b/api/core/v3/internal/strings/strings_test.go @@ -0,0 +1,34 @@ +package strings + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestFindInArray(t *testing.T) { + var array []string + + found := FoundInArray("Foo", []string{}) + assert.False(t, found) + + array = []string{"foo", "bar"} + found = FoundInArray("Foo", array) + assert.True(t, found) + + array = []string{"foo", "bar"} + found = FoundInArray("FooBar", array) + assert.False(t, found) + + array = []string{"foo", "bar"} + found = FoundInArray("Foo ", array) + assert.True(t, found) + + array = []string{"foo_bar"} + found = FoundInArray("Foo_Bar", array) + assert.True(t, found) + + array = []string{"foobar"} + found = FoundInArray("Foo_Qux", array) + assert.False(t, found) +} From a1f9dc8abafdb5766a4d809cb5b9e4af20392f4e Mon Sep 17 00:00:00 2001 From: James Phillips Date: Mon, 12 Sep 2022 10:35:48 -0700 Subject: [PATCH 2/8] ensure metadata is sanatized Signed-off-by: James Phillips --- backend/apid/graphql/corev3.go | 7 ++++ backend/apid/graphql/corev3_test.go | 52 +++++++++++++++++++++++++++++ go.mod | 2 +- go.sum | 16 ++------- 4 files changed, 62 insertions(+), 15 deletions(-) diff --git a/backend/apid/graphql/corev3.go b/backend/apid/graphql/corev3.go index a62cef86d4..075f561705 100644 --- a/backend/apid/graphql/corev3.go +++ b/backend/apid/graphql/corev3.go @@ -39,6 +39,13 @@ func (i *corev3EntityConfigExtImpl) ID(p graphql.ResolveParams) (string, error) return GlobalIDCoreV3EntityConfig.EncodeToString(p.Context, p.Source), nil } +// ID implements response to request for 'id' field. +func (i *corev3EntityConfigExtImpl) Metadata(p graphql.ResolveParams) (interface{}, error) { + obj := p.Source.(*corev3.EntityConfig) + redacted := obj.ProduceRedacted() + return redacted.Metadata, nil +} + // ToJSON implements response to request for 'toJSON' field. func (i *corev3EntityConfigExtImpl) ToJSON(p graphql.ResolveParams) (interface{}, error) { return util_api.WrapResource(p.Source), nil diff --git a/backend/apid/graphql/corev3_test.go b/backend/apid/graphql/corev3_test.go index c7ea9a4452..fd3e0930fb 100644 --- a/backend/apid/graphql/corev3_test.go +++ b/backend/apid/graphql/corev3_test.go @@ -55,6 +55,58 @@ func Test_corev3_ID(t *testing.T) { } } +func Test_corev3_Metadata(t *testing.T) { + tests := []struct { + name string + resolver interface { + Metadata(p graphql.ResolveParams) (interface{}, error) + } + in interface{} + want interface{} + wantErr bool + }{ + { + name: "corev3EntityConfigExtImpl", + resolver: &corev3EntityConfigExtImpl{}, + in: func() *corev3.EntityConfig { + obj := corev3.FixtureEntityConfig("name") + obj.Metadata.Labels["my_label"] = "test" + obj.Metadata.Labels["password"] = "test" + return obj + }(), + want: func() *corev2.ObjectMeta { + obj := corev3.FixtureEntityConfig("name") + obj.Metadata.Labels["my_label"] = "test" + obj.Metadata.Labels["password"] = corev2.Redacted + return obj.Metadata + }(), + wantErr: false, + }, + { + name: "corev3EntityStateExtImpl", + resolver: &corev3EntityStateExtImpl{}, + in: corev3.FixtureEntityState("name"), + want: func() *corev2.ObjectMeta { + obj := corev3.FixtureEntityState("name") + return obj.Metadata + }(), + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(fmt.Sprintf("%T/%s", tt.resolver, tt.name), func(t *testing.T) { + got, err := tt.resolver.Metadata(graphql.ResolveParams{Context: context.Background(), Source: tt.in}) + if (err != nil) != tt.wantErr { + t.Errorf("%s.Metadata() error = %v, wantErr %v", tt.name, err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("%s.Metadata() = %v, want %v", tt.name, got, tt.want) + } + }) + } +} + func Test_corev3_ToJSON(t *testing.T) { tests := []struct { name string diff --git a/go.mod b/go.mod index 25456d603b..9a70b4cf99 100644 --- a/go.mod +++ b/go.mod @@ -48,7 +48,7 @@ require ( github.com/robfig/cron/v3 v3.0.1 github.com/sensu/lasr v1.2.1 github.com/sensu/sensu-go/api/core/v2 v2.14.0 - github.com/sensu/sensu-go/api/core/v3 v3.6.2 + github.com/sensu/sensu-go/api/core/v3 v3.6.3-0.20220912171820-366b64ed1a62 github.com/sensu/sensu-go/types v0.10.0 github.com/shirou/gopsutil/v3 v3.21.12 github.com/sirupsen/logrus v1.7.0 diff --git a/go.sum b/go.sum index 2269ce740a..ed4b8fe003 100644 --- a/go.sum +++ b/go.sum @@ -55,7 +55,6 @@ github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghf github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cockroachdb/datadriven v0.0.0-20200714090401-bf6692d28da5 h1:xD/lrqdvwsc+O2bjSSi3YqY73Ke3LAiSCx49aCesA0E= @@ -65,7 +64,6 @@ github.com/cockroachdb/errors v1.2.4/go.mod h1:rQD95gz6FARkaKkQXUksEje/d9a6wBJoC github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f h1:o/kfcElHqOiXqcou5a3rIlMc7oJbMQkeLk0VQJ7zgqY= github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f/go.mod h1:i/u985jwjWRlyHXQbwatDASoW0RMlZ/3i9yJHE2xLkI= github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= -github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/go-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmfM= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= @@ -100,7 +98,6 @@ github.com/emicklei/proto v1.1.0 h1:3OWZhkr68eGPyCY1AtNh1u+5IyBiVVDJMXKRX9cOFgY= github.com/emicklei/proto v1.1.0/go.mod h1:Dqn751twH9SasYqvA59Lb9Hz+itoJgmMoivX6k7OPZc= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= @@ -181,7 +178,6 @@ github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= @@ -390,7 +386,6 @@ github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzG github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/schollz/progressbar/v2 v2.13.2/go.mod h1:6YZjqdthH6SCZKv2rqGryrxPtfmRB/DWZxSMfCXPyD8= @@ -402,6 +397,8 @@ github.com/sensu/sensu-go/api/core/v2 v2.14.0/go.mod h1:XCgUjY78ApTahizBz/pkc5KU github.com/sensu/sensu-go/api/core/v3 v3.6.1/go.mod h1:aqNOkJxkrwRq+rPW47XtVWeb5Rk1K5adlCZGBW9nsvM= github.com/sensu/sensu-go/api/core/v3 v3.6.2 h1:NEkHcPxkaYwPlH4gG6kgvdvYLlwBBaswMHscA7X3V+4= github.com/sensu/sensu-go/api/core/v3 v3.6.2/go.mod h1:aqNOkJxkrwRq+rPW47XtVWeb5Rk1K5adlCZGBW9nsvM= +github.com/sensu/sensu-go/api/core/v3 v3.6.3-0.20220912171820-366b64ed1a62 h1:PeP63bXXwwB586EjCb73jg0oqzE3Tg3aOH38g9qG58k= +github.com/sensu/sensu-go/api/core/v3 v3.6.3-0.20220912171820-366b64ed1a62/go.mod h1:n2dhnBTovMrzmE1P0D7gvEbUG7TPH6hdtr7qvoPf/sY= github.com/sensu/sensu-go/types v0.10.0 h1:sm+dLuqEEECVxjW5EfXkU5weGPwrg/Jymbm28HdQpl8= github.com/sensu/sensu-go/types v0.10.0/go.mod h1:vFZJ9TYBAjSPYtYt+82PpS9P6m73Vzr4O23lmJonzrA= github.com/shirou/gopsutil/v3 v3.21.12 h1:VoGxEW2hpmz0Vt3wUvHIl9fquzYLNpVpgNNB7pGJimA= @@ -455,7 +452,6 @@ github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1 github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802 h1:uruHq4dN7GR16kFc5fp3d1RIYzJW5onx8Ybykw2YQFA= github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/ulikunitz/xz v0.5.6/go.mod h1:2bypXElzHzzJZwzH67Y6wb67pO62Rzfn7BSiF4ABRW8= -github.com/ulikunitz/xz v0.5.6/go.mod h1:2bypXElzHzzJZwzH67Y6wb67pO62Rzfn7BSiF4ABRW8= github.com/ulikunitz/xz v0.5.10 h1:t92gobL9l3HE202wg3rlk19F6X+JOxl9BBrCCMYEYd8= github.com/ulikunitz/xz v0.5.10/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= github.com/willf/pad v0.0.0-20160331131008-b3d780601022 h1:W5wMm7sF44Z3K9bpq+CHOMOipvLHN1ElD6nyQbbiy/0= @@ -470,7 +466,6 @@ github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1 github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg= github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= -go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.6 h1:/ecaJf0sk1l4l6V4awd65v2C3ILy7MSj+s/x1ADCIMU= go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4= go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= @@ -537,8 +532,6 @@ golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20190530122614-20be4c3c3ed5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20220131195533-30dcbda58838 h1:71vQrMauZZhcTVK6KdYM+rklehEEwb3E+ZhaE5jrPrE= golang.org/x/crypto v0.0.0-20220131195533-30dcbda58838/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= @@ -586,7 +579,6 @@ golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= @@ -634,7 +626,6 @@ golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -651,12 +642,9 @@ golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9sn golang.org/x/term v0.0.0-20210503060354-a79de5458b56 h1:b8jxX3zqjpqb2LklXPzKSGJhzyxCOZSz8ncv8Nv+y7w= golang.org/x/term v0.0.0-20210503060354-a79de5458b56/go.mod h1:tfny5GFUkzUvx4ps4ajbZsCe5lw1metzhBm9T3x7oIY= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= From 9e7a10cb1122b4fcbaf9abfc0eb8588eaaefa5bc Mon Sep 17 00:00:00 2001 From: James Phillips Date: Mon, 12 Sep 2022 10:37:10 -0700 Subject: [PATCH 3/8] typo Signed-off-by: James Phillips --- api/core/v3/internal/strings/strings_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/core/v3/internal/strings/strings_test.go b/api/core/v3/internal/strings/strings_test.go index 5b7e040541..d1dfc90c10 100644 --- a/api/core/v3/internal/strings/strings_test.go +++ b/api/core/v3/internal/strings/strings_test.go @@ -6,7 +6,7 @@ import ( "github.com/stretchr/testify/assert" ) -func TestFindInArray(t *testing.T) { +func TestFoundInArray(t *testing.T) { var array []string found := FoundInArray("Foo", []string{}) From 44f1d6ca723a13d6485b166dbb7305c3b9c02d76 Mon Sep 17 00:00:00 2001 From: James Phillips Date: Mon, 12 Sep 2022 11:08:36 -0700 Subject: [PATCH 4/8] fixup backend api test Signed-off-by: James Phillips --- backend/api/generic_test.go | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/backend/api/generic_test.go b/backend/api/generic_test.go index 963a56f58d..0342b09a4f 100644 --- a/backend/api/generic_test.go +++ b/backend/api/generic_test.go @@ -421,7 +421,7 @@ func TestGenericClientStoreV2(t *testing.T) { APIGroup: "core", APIVersion: "v3", Namespace: "default", - Resource: "entity_configs", + Resource: "entities", ResourceName: "default", UserName: "tom", Verb: "get", @@ -430,7 +430,7 @@ func TestGenericClientStoreV2(t *testing.T) { APIGroup: "core", APIVersion: "v3", Namespace: "default", - Resource: "entity_configs", + Resource: "entities", UserName: "tom", Verb: "list", }: true, @@ -456,7 +456,7 @@ func TestGenericClientStoreV2(t *testing.T) { APIGroup: "core", APIVersion: "v3", Namespace: "default", - Resource: "entity_configs", + Resource: "entities", ResourceName: "default", UserName: "tom", Verb: "get", @@ -465,7 +465,7 @@ func TestGenericClientStoreV2(t *testing.T) { APIGroup: "core", APIVersion: "v3", Namespace: "default", - Resource: "entity_configs", + Resource: "entities", ResourceName: "default", UserName: "tom", Verb: "create", @@ -474,7 +474,7 @@ func TestGenericClientStoreV2(t *testing.T) { APIGroup: "core", APIVersion: "v3", Namespace: "default", - Resource: "entity_configs", + Resource: "entities", ResourceName: "default", UserName: "tom", Verb: "delete", @@ -483,7 +483,7 @@ func TestGenericClientStoreV2(t *testing.T) { APIGroup: "core", APIVersion: "v3", Namespace: "default", - Resource: "entity_configs", + Resource: "entities", ResourceName: "default", UserName: "tom", Verb: "update", @@ -492,7 +492,7 @@ func TestGenericClientStoreV2(t *testing.T) { APIGroup: "core", APIVersion: "v3", Namespace: "default", - Resource: "entity_configs", + Resource: "entities", UserName: "tom", Verb: "list", }: true, From a5a7db519e68b39357ffb35d24e4cd28ea4a92a3 Mon Sep 17 00:00:00 2001 From: James Phillips Date: Mon, 12 Sep 2022 11:25:51 -0700 Subject: [PATCH 5/8] redacter interface Signed-off-by: James Phillips --- api/core/v3/entity_config.go | 2 +- api/core/v3/redacter.go | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) create mode 100644 api/core/v3/redacter.go diff --git a/api/core/v3/entity_config.go b/api/core/v3/entity_config.go index 7db48b0fa1..03e5e6f2b5 100644 --- a/api/core/v3/entity_config.go +++ b/api/core/v3/entity_config.go @@ -51,7 +51,7 @@ func redactMap(m map[string]string, redact []string) map[string]string { // ProduceRedacted redacts the entity according to the entity's Redact fields. // A redacted copy is returned. The copy contains pointers to the original's // memory, with different Labels and Annotations. -func (e *EntityConfig) ProduceRedacted() *EntityConfig { +func (e *EntityConfig) ProduceRedacted() Resource { if e == nil { return nil } diff --git a/api/core/v3/redacter.go b/api/core/v3/redacter.go new file mode 100644 index 0000000000..38d781aedb --- /dev/null +++ b/api/core/v3/redacter.go @@ -0,0 +1,7 @@ +package v3 + +// Redacter can return a redacted copy of the resource +type Redacter interface { + // ProduceRedacted returns a redacted copy of the resource + ProduceRedacted() Resource +} From b06a3c96dd54d312b7eb635a09e38eb68080ed4c Mon Sep 17 00:00:00 2001 From: James Phillips Date: Mon, 12 Sep 2022 11:31:21 -0700 Subject: [PATCH 6/8] move changes to the api package Signed-off-by: James Phillips --- backend/api/generic.go | 12 +++++-- backend/apid/graphql/corev3.go | 7 ---- backend/apid/graphql/corev3_test.go | 52 ----------------------------- go.mod | 2 +- go.sum | 2 ++ 5 files changed, 13 insertions(+), 62 deletions(-) diff --git a/backend/api/generic.go b/backend/api/generic.go index 1803fefe61..04bb2b7874 100644 --- a/backend/api/generic.go +++ b/backend/api/generic.go @@ -169,7 +169,11 @@ func (g *GenericClient) getResource(ctx context.Context, name string, value core if err != nil { return err } - return wrapper.UnwrapInto(value.Resource) + resource := value.Resource + if redacter, ok := resource.(interface{ ProduceRedacted() corev3.Resource }); ok { + resource = redacter.ProduceRedacted() + } + return wrapper.UnwrapInto(resource) } return g.Store.GetResource(ctx, name, value) } @@ -209,7 +213,11 @@ func (g *GenericClient) list(ctx context.Context, resources interface{}, pred *s } v2values := make([]corev2.Resource, len(values)) for i := range values { - v2values[i] = corev3.V3ToV2Resource(values[i]) + resource := values[i] + if redacter, ok := resource.(interface{ ProduceRedacted() corev3.Resource }); ok { + resource = redacter.ProduceRedacted() + } + v2values[i] = corev3.V3ToV2Resource(resource) } *resourceList = v2values return nil diff --git a/backend/apid/graphql/corev3.go b/backend/apid/graphql/corev3.go index 075f561705..a62cef86d4 100644 --- a/backend/apid/graphql/corev3.go +++ b/backend/apid/graphql/corev3.go @@ -39,13 +39,6 @@ func (i *corev3EntityConfigExtImpl) ID(p graphql.ResolveParams) (string, error) return GlobalIDCoreV3EntityConfig.EncodeToString(p.Context, p.Source), nil } -// ID implements response to request for 'id' field. -func (i *corev3EntityConfigExtImpl) Metadata(p graphql.ResolveParams) (interface{}, error) { - obj := p.Source.(*corev3.EntityConfig) - redacted := obj.ProduceRedacted() - return redacted.Metadata, nil -} - // ToJSON implements response to request for 'toJSON' field. func (i *corev3EntityConfigExtImpl) ToJSON(p graphql.ResolveParams) (interface{}, error) { return util_api.WrapResource(p.Source), nil diff --git a/backend/apid/graphql/corev3_test.go b/backend/apid/graphql/corev3_test.go index fd3e0930fb..c7ea9a4452 100644 --- a/backend/apid/graphql/corev3_test.go +++ b/backend/apid/graphql/corev3_test.go @@ -55,58 +55,6 @@ func Test_corev3_ID(t *testing.T) { } } -func Test_corev3_Metadata(t *testing.T) { - tests := []struct { - name string - resolver interface { - Metadata(p graphql.ResolveParams) (interface{}, error) - } - in interface{} - want interface{} - wantErr bool - }{ - { - name: "corev3EntityConfigExtImpl", - resolver: &corev3EntityConfigExtImpl{}, - in: func() *corev3.EntityConfig { - obj := corev3.FixtureEntityConfig("name") - obj.Metadata.Labels["my_label"] = "test" - obj.Metadata.Labels["password"] = "test" - return obj - }(), - want: func() *corev2.ObjectMeta { - obj := corev3.FixtureEntityConfig("name") - obj.Metadata.Labels["my_label"] = "test" - obj.Metadata.Labels["password"] = corev2.Redacted - return obj.Metadata - }(), - wantErr: false, - }, - { - name: "corev3EntityStateExtImpl", - resolver: &corev3EntityStateExtImpl{}, - in: corev3.FixtureEntityState("name"), - want: func() *corev2.ObjectMeta { - obj := corev3.FixtureEntityState("name") - return obj.Metadata - }(), - wantErr: false, - }, - } - for _, tt := range tests { - t.Run(fmt.Sprintf("%T/%s", tt.resolver, tt.name), func(t *testing.T) { - got, err := tt.resolver.Metadata(graphql.ResolveParams{Context: context.Background(), Source: tt.in}) - if (err != nil) != tt.wantErr { - t.Errorf("%s.Metadata() error = %v, wantErr %v", tt.name, err, tt.wantErr) - return - } - if !reflect.DeepEqual(got, tt.want) { - t.Errorf("%s.Metadata() = %v, want %v", tt.name, got, tt.want) - } - }) - } -} - func Test_corev3_ToJSON(t *testing.T) { tests := []struct { name string diff --git a/go.mod b/go.mod index 9a70b4cf99..5a1d1b5d73 100644 --- a/go.mod +++ b/go.mod @@ -48,7 +48,7 @@ require ( github.com/robfig/cron/v3 v3.0.1 github.com/sensu/lasr v1.2.1 github.com/sensu/sensu-go/api/core/v2 v2.14.0 - github.com/sensu/sensu-go/api/core/v3 v3.6.3-0.20220912171820-366b64ed1a62 + github.com/sensu/sensu-go/api/core/v3 v3.6.3-0.20220912182551-a5a7db519e68 github.com/sensu/sensu-go/types v0.10.0 github.com/shirou/gopsutil/v3 v3.21.12 github.com/sirupsen/logrus v1.7.0 diff --git a/go.sum b/go.sum index ed4b8fe003..f525d49320 100644 --- a/go.sum +++ b/go.sum @@ -399,6 +399,8 @@ github.com/sensu/sensu-go/api/core/v3 v3.6.2 h1:NEkHcPxkaYwPlH4gG6kgvdvYLlwBBasw github.com/sensu/sensu-go/api/core/v3 v3.6.2/go.mod h1:aqNOkJxkrwRq+rPW47XtVWeb5Rk1K5adlCZGBW9nsvM= github.com/sensu/sensu-go/api/core/v3 v3.6.3-0.20220912171820-366b64ed1a62 h1:PeP63bXXwwB586EjCb73jg0oqzE3Tg3aOH38g9qG58k= github.com/sensu/sensu-go/api/core/v3 v3.6.3-0.20220912171820-366b64ed1a62/go.mod h1:n2dhnBTovMrzmE1P0D7gvEbUG7TPH6hdtr7qvoPf/sY= +github.com/sensu/sensu-go/api/core/v3 v3.6.3-0.20220912182551-a5a7db519e68 h1:t5AsMszceHgj4yGHflRi705L3mZbb15yi5pRJfiWmy8= +github.com/sensu/sensu-go/api/core/v3 v3.6.3-0.20220912182551-a5a7db519e68/go.mod h1:n2dhnBTovMrzmE1P0D7gvEbUG7TPH6hdtr7qvoPf/sY= github.com/sensu/sensu-go/types v0.10.0 h1:sm+dLuqEEECVxjW5EfXkU5weGPwrg/Jymbm28HdQpl8= github.com/sensu/sensu-go/types v0.10.0/go.mod h1:vFZJ9TYBAjSPYtYt+82PpS9P6m73Vzr4O23lmJonzrA= github.com/shirou/gopsutil/v3 v3.21.12 h1:VoGxEW2hpmz0Vt3wUvHIl9fquzYLNpVpgNNB7pGJimA= From b863464b12ecaef53317fa942e46d4d870894c51 Mon Sep 17 00:00:00 2001 From: James Phillips Date: Mon, 12 Sep 2022 11:35:43 -0700 Subject: [PATCH 7/8] use interface Signed-off-by: James Phillips --- backend/api/generic.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/api/generic.go b/backend/api/generic.go index 04bb2b7874..3190bcf4f0 100644 --- a/backend/api/generic.go +++ b/backend/api/generic.go @@ -170,7 +170,7 @@ func (g *GenericClient) getResource(ctx context.Context, name string, value core return err } resource := value.Resource - if redacter, ok := resource.(interface{ ProduceRedacted() corev3.Resource }); ok { + if redacter, ok := resource.(corev3.Redacter); ok { resource = redacter.ProduceRedacted() } return wrapper.UnwrapInto(resource) @@ -214,7 +214,7 @@ func (g *GenericClient) list(ctx context.Context, resources interface{}, pred *s v2values := make([]corev2.Resource, len(values)) for i := range values { resource := values[i] - if redacter, ok := resource.(interface{ ProduceRedacted() corev3.Resource }); ok { + if redacter, ok := resource.(corev3.Redacter); ok { resource = redacter.ProduceRedacted() } v2values[i] = corev3.V3ToV2Resource(resource) From bfd77a51b33a82736f5ce4900ad880cff1de1d96 Mon Sep 17 00:00:00 2001 From: James Phillips Date: Mon, 12 Sep 2022 12:21:59 -0700 Subject: [PATCH 8/8] add additional test case to confirm issue is resolved Signed-off-by: James Phillips --- backend/api/generic.go | 10 ++-- backend/api/generic_test.go | 94 +++++++++++++++++++++++++++++++++++++ 2 files changed, 100 insertions(+), 4 deletions(-) diff --git a/backend/api/generic.go b/backend/api/generic.go index 3190bcf4f0..625adef719 100644 --- a/backend/api/generic.go +++ b/backend/api/generic.go @@ -169,11 +169,13 @@ func (g *GenericClient) getResource(ctx context.Context, name string, value core if err != nil { return err } - resource := value.Resource - if redacter, ok := resource.(corev3.Redacter); ok { - resource = redacter.ProduceRedacted() + if err := wrapper.UnwrapInto(value.Resource); err != nil { + return err } - return wrapper.UnwrapInto(resource) + if redacter, ok := value.Resource.(corev3.Redacter); ok { + value.Resource = redacter.ProduceRedacted() + } + return err } return g.Store.GetResource(ctx, name, value) } diff --git a/backend/api/generic_test.go b/backend/api/generic_test.go index 0342b09a4f..e9117f4bff 100644 --- a/backend/api/generic_test.go +++ b/backend/api/generic_test.go @@ -569,6 +569,100 @@ func TestGenericClientStoreV2(t *testing.T) { } } +func TestGenericClientStoreV2_sensu_enterprise_go_GH2484(t *testing.T) { + makeStore := func(entity *corev3.EntityConfig) storev2.Interface { + store := new(storetest.Store) + if entity == nil { + entity = corev3.FixtureEntityConfig("default") + entity.Redact = []string{"password"} + entity.Metadata.Labels["password"] = "test" + entity.Metadata.Labels["my_label"] = "test" + } + wrappedResource, err := storev2.WrapResource(entity) + if err != nil { + panic(err) + } + store.On("Get", mock.Anything).Return(wrappedResource, nil) + store.On("List", mock.Anything, mock.Anything).Return(wrap.List{wrappedResource.(*wrap.Wrapper)}, nil) + return store + } + v3AllAccess := func() authorization.Authorizer { + return &mockAuth{ + attrs: map[authorization.AttributesKey]bool{ + { + APIGroup: "core", + APIVersion: "v3", + Namespace: "default", + Resource: "entities", + ResourceName: "default", + UserName: "tom", + Verb: "get", + }: true, + { + APIGroup: "core", + APIVersion: "v3", + Namespace: "default", + Resource: "entities", + ResourceName: "default", + UserName: "tom", + Verb: "create", + }: true, + { + APIGroup: "core", + APIVersion: "v3", + Namespace: "default", + Resource: "entities", + ResourceName: "default", + UserName: "tom", + Verb: "delete", + }: true, + { + APIGroup: "core", + APIVersion: "v3", + Namespace: "default", + Resource: "entities", + ResourceName: "default", + UserName: "tom", + Verb: "update", + }: true, + { + APIGroup: "core", + APIVersion: "v3", + Namespace: "default", + Resource: "entities", + UserName: "tom", + Verb: "list", + }: true, + }, + } + } + + ctx := contextWithUser(defaultContext(), "tom", nil) + client := defaultV2TestClient(makeStore(nil), v3AllAccess()) + listVal := []corev2.Resource{} + if err := client.List(ctx, &listVal, &store.SelectionPredicate{}); err != nil { + t.Fatal(err) + } + if listVal[0].GetObjectMeta().Labels["password"] != corev2.Redacted { + t.Errorf("Labels['password'] = %s, got: %s", corev2.Redacted, listVal[0].GetObjectMeta().Labels["password"]) + } + if listVal[0].GetObjectMeta().Labels["my_label"] != "test" { + t.Errorf("Labels['my_label'] = %s, got: %s", "test", listVal[0].GetObjectMeta().Labels["my_label"]) + } + + client = defaultV2TestClient(makeStore(nil), v3AllAccess()) + getVal := corev3.V2ResourceProxy{Resource: &corev3.EntityConfig{}} + if err := client.Get(ctx, "default", &getVal); err != nil { + t.Fatal(err) + } + if getVal.GetObjectMeta().Labels["password"] != corev2.Redacted { + t.Errorf("Labels['password'] = %s, got: %s", corev2.Redacted, getVal.GetObjectMeta().Labels["password"]) + } + if getVal.GetObjectMeta().Labels["my_label"] != "test" { + t.Errorf("Labels['my_label'] = %s, got: %s", "test", getVal.GetObjectMeta().Labels["my_label"]) + } +} + func TestSetTypeMetaV3Resource(t *testing.T) { client := &GenericClient{} err := client.SetTypeMeta(corev2.TypeMeta{