From 1ce7f480c3a342fd038287590e4414c4f06502cd Mon Sep 17 00:00:00 2001 From: Travis Raines <571832+rainest@users.noreply.github.com> Date: Fri, 3 May 2024 14:20:02 -0700 Subject: [PATCH] fix(konnect) avoid collisions when redacting Change the static redacted pretend Vault string to a function that generates a random pretend Vault string. This avoids collisions for certain types of values when go-database-reconciler builds configuration. It uses an in-memory database that looks up Kong entities by unique fields. If these fields aren't actually unique, go-database-reconciler will detect a conflict and abort. --- CHANGELOG.md | 2 ++ internal/dataplane/kongstate/consumer_test.go | 10 +++++----- internal/dataplane/kongstate/credentials.go | 19 ++++++++++++------- .../dataplane/kongstate/credentials_test.go | 10 +++++----- .../dataplane/kongstate/kongstate_test.go | 8 ++++---- internal/dataplane/kongstate/license.go | 2 +- internal/dataplane/kongstate/plugin.go | 4 ++-- internal/dataplane/kongstate/types.go | 2 +- internal/dataplane/kongstate/types_test.go | 2 +- 9 files changed, 33 insertions(+), 26 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2ce15c5551..78de9f9978 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -138,6 +138,8 @@ Adding a new version? You'll need three changes: `parentRefs`'s group/kind is not `gateway.network.k8s.io/Gateway`, the item is seen as a parent other than the controller and ignored in parentRef check. [#5919](https://github.com/Kong/kubernetes-ingress-controller/pull/5919) +- Redacted values no longer cause collisions in configuration reported to Konnect. + [5964](https://github.com/Kong/kubernetes-ingress-controller/pull/5964) ### Changed diff --git a/internal/dataplane/kongstate/consumer_test.go b/internal/dataplane/kongstate/consumer_test.go index 644e79bccc..a2cf61525f 100644 --- a/internal/dataplane/kongstate/consumer_test.go +++ b/internal/dataplane/kongstate/consumer_test.go @@ -50,13 +50,13 @@ func TestConsumer_SanitizedCopy(t *testing.T) { Tags: []*string{kong.String("5.1"), kong.String("5.2")}, }, Plugins: []kong.Plugin{{ID: kong.String("1")}}, - KeyAuths: []*KeyAuth{{kong.KeyAuth{ID: kong.String("1"), Key: redactedString}}}, - HMACAuths: []*HMACAuth{{kong.HMACAuth{ID: kong.String("1"), Secret: redactedString}}}, - JWTAuths: []*JWTAuth{{kong.JWTAuth{ID: kong.String("1"), Secret: redactedString}}}, - BasicAuths: []*BasicAuth{{kong.BasicAuth{ID: kong.String("1"), Password: redactedString}}}, + KeyAuths: []*KeyAuth{{kong.KeyAuth{ID: kong.String("1"), Key: redactedString()}}}, + HMACAuths: []*HMACAuth{{kong.HMACAuth{ID: kong.String("1"), Secret: redactedString()}}}, + JWTAuths: []*JWTAuth{{kong.JWTAuth{ID: kong.String("1"), Secret: redactedString()}}}, + BasicAuths: []*BasicAuth{{kong.BasicAuth{ID: kong.String("1"), Password: redactedString()}}}, ACLGroups: []*ACLGroup{{kong.ACLGroup{ID: kong.String("1")}}}, Oauth2Creds: []*Oauth2Credential{ - {kong.Oauth2Credential{ID: kong.String("1"), ClientSecret: redactedString}}, + {kong.Oauth2Credential{ID: kong.String("1"), ClientSecret: redactedString()}}, }, MTLSAuths: []*MTLSAuth{{kong.MTLSAuth{ID: kong.String("1"), SubjectName: kong.String("foo@example.com")}}}, K8sKongConsumer: kongv1.KongConsumer{Username: "foo"}, diff --git a/internal/dataplane/kongstate/credentials.go b/internal/dataplane/kongstate/credentials.go index 48d9b4d608..dcb41627a2 100644 --- a/internal/dataplane/kongstate/credentials.go +++ b/internal/dataplane/kongstate/credentials.go @@ -3,14 +3,19 @@ package kongstate import ( "fmt" + "github.com/google/uuid" "github.com/kong/go-kong/kong" "github.com/mitchellh/mapstructure" ) // redactedString is used to redact sensitive values in the KongState. // It uses a vault URI to pass Konnect Admin API validations (e.g. when a TLS key is expected, it's only possible -// to pass a valid key or a vault URI). -var redactedString = kong.String("{vault://redacted-value}") +// to pass a valid key or a vault URI). The value is random to avoid collisions when the sensitive field must be +// unique, such as for key-auths. +func redactedString() *string { + s := fmt.Sprintf("{vault://%s}", uuid.NewString()) + return &s +} // KeyAuth represents a key-auth credential. type KeyAuth struct { @@ -158,7 +163,7 @@ func (c *KeyAuth) SanitizedCopy() *KeyAuth { // Consumer field omitted CreatedAt: c.CreatedAt, ID: c.ID, - Key: redactedString, + Key: redactedString(), Tags: c.Tags, }, } @@ -172,7 +177,7 @@ func (c *HMACAuth) SanitizedCopy() *HMACAuth { CreatedAt: c.CreatedAt, ID: c.ID, Username: c.Username, - Secret: redactedString, + Secret: redactedString(), Tags: c.Tags, }, } @@ -188,7 +193,7 @@ func (c *JWTAuth) SanitizedCopy() *JWTAuth { Algorithm: c.Algorithm, Key: c.Key, // despite field name, "key" is an identifier RSAPublicKey: c.RSAPublicKey, - Secret: redactedString, + Secret: redactedString(), Tags: c.Tags, }, } @@ -202,7 +207,7 @@ func (c *BasicAuth) SanitizedCopy() *BasicAuth { CreatedAt: c.CreatedAt, ID: c.ID, Username: c.Username, - Password: redactedString, + Password: redactedString(), Tags: c.Tags, }, } @@ -217,7 +222,7 @@ func (c *Oauth2Credential) SanitizedCopy() *Oauth2Credential { ID: c.ID, Name: c.Name, ClientID: c.ClientID, - ClientSecret: redactedString, + ClientSecret: redactedString(), RedirectURIs: c.RedirectURIs, Tags: c.Tags, }, diff --git a/internal/dataplane/kongstate/credentials_test.go b/internal/dataplane/kongstate/credentials_test.go index 23d7bf27dd..2f076d998b 100644 --- a/internal/dataplane/kongstate/credentials_test.go +++ b/internal/dataplane/kongstate/credentials_test.go @@ -25,7 +25,7 @@ func TestKeyAuth_SanitizedCopy(t *testing.T) { want: KeyAuth{kong.KeyAuth{ CreatedAt: kong.Int(1), ID: kong.String("2"), - Key: redactedString, + Key: redactedString(), Tags: []*string{kong.String("4.1"), kong.String("4.2")}, }}, }, @@ -57,7 +57,7 @@ func TestHMACAuth_SanitizedCopy(t *testing.T) { CreatedAt: kong.Int(1), ID: kong.String("2"), Username: kong.String("3"), - Secret: redactedString, + Secret: redactedString(), Tags: []*string{kong.String("5.1"), kong.String("5.2")}, }}, }, @@ -93,7 +93,7 @@ func TestJWTAuth_SanitizedCopy(t *testing.T) { Algorithm: kong.String("3"), Key: kong.String("4"), RSAPublicKey: kong.String("5"), - Secret: redactedString, + Secret: redactedString(), Tags: []*string{kong.String("7.1"), kong.String("7.2")}, }}, }, @@ -125,7 +125,7 @@ func TestBasicAuth_SanitizedCopy(t *testing.T) { CreatedAt: kong.Int(1), ID: kong.String("2"), Username: kong.String("3"), - Password: redactedString, + Password: redactedString(), Tags: []*string{kong.String("5.1"), kong.String("5.2")}, }}, }, @@ -160,7 +160,7 @@ func TestOauth2Credential_SanitizedCopy(t *testing.T) { ID: kong.String("2"), Name: kong.String("3"), ClientID: kong.String("4"), - ClientSecret: redactedString, + ClientSecret: redactedString(), RedirectURIs: []*string{kong.String("6.1"), kong.String("6.2")}, Tags: []*string{kong.String("7.1"), kong.String("7.2")}, }}, diff --git a/internal/dataplane/kongstate/kongstate_test.go b/internal/dataplane/kongstate/kongstate_test.go index 522707a549..f546bbe805 100644 --- a/internal/dataplane/kongstate/kongstate_test.go +++ b/internal/dataplane/kongstate/kongstate_test.go @@ -79,16 +79,16 @@ func TestKongState_SanitizedCopy(t *testing.T) { want: KongState{ Services: []Service{{Service: kong.Service{ID: kong.String("1")}}}, Upstreams: []Upstream{{Upstream: kong.Upstream{ID: kong.String("1")}}}, - Certificates: []Certificate{{Certificate: kong.Certificate{ID: kong.String("1"), Key: redactedString}}}, + Certificates: []Certificate{{Certificate: kong.Certificate{ID: kong.String("1"), Key: redactedString()}}}, CACertificates: []kong.CACertificate{{ID: kong.String("1")}}, Plugins: []Plugin{{ SensitiveFieldsMeta: PluginSensitiveFieldsMetadata{WholeConfigIsSensitive: true}, - Plugin: kong.Plugin{ID: kong.String("1"), Config: kong.Configuration{"secret": *redactedString}}, + Plugin: kong.Plugin{ID: kong.String("1"), Config: kong.Configuration{"secret": *redactedString()}}, }}, Consumers: []Consumer{{ - KeyAuths: []*KeyAuth{{kong.KeyAuth{ID: kong.String("1"), Key: redactedString}}}, + KeyAuths: []*KeyAuth{{kong.KeyAuth{ID: kong.String("1"), Key: redactedString()}}}, }}, - Licenses: []License{{kong.License{ID: kong.String("1"), Payload: redactedString}}}, + Licenses: []License{{kong.License{ID: kong.String("1"), Payload: redactedString()}}}, ConsumerGroups: []ConsumerGroup{{ ConsumerGroup: kong.ConsumerGroup{ID: kong.String("1"), Name: kong.String("consumer-group")}, }}, diff --git a/internal/dataplane/kongstate/license.go b/internal/dataplane/kongstate/license.go index 2d714cbb6b..5c2458aee6 100644 --- a/internal/dataplane/kongstate/license.go +++ b/internal/dataplane/kongstate/license.go @@ -14,7 +14,7 @@ func (l License) SanitizedCopy() *License { return &License{ License: kong.License{ ID: l.ID, - Payload: redactedString, + Payload: redactedString(), CreatedAt: l.CreatedAt, UpdatedAt: l.UpdatedAt, }, diff --git a/internal/dataplane/kongstate/plugin.go b/internal/dataplane/kongstate/plugin.go index 598b023f51..6097d724e9 100644 --- a/internal/dataplane/kongstate/plugin.go +++ b/internal/dataplane/kongstate/plugin.go @@ -62,7 +62,7 @@ func (p Plugin) SanitizedCopy() Plugin { patchOperations = append(patchOperations, fmt.Sprintf( `{"op":"replace","path":"%s","value":"%s"}`, path, - *redactedString, + *redactedString(), )) } @@ -100,7 +100,7 @@ func (p Plugin) SanitizedCopy() Plugin { func sanitizeWholePluginConfig(config kong.Configuration) kong.Configuration { sanitized := config.DeepCopy() for k := range config { - sanitized[k] = *redactedString + sanitized[k] = *redactedString() } return sanitized } diff --git a/internal/dataplane/kongstate/types.go b/internal/dataplane/kongstate/types.go index 282d81081f..73bc116a45 100644 --- a/internal/dataplane/kongstate/types.go +++ b/internal/dataplane/kongstate/types.go @@ -58,7 +58,7 @@ func (c *Certificate) SanitizedCopy() *Certificate { kong.Certificate{ ID: c.ID, Cert: c.Cert, - Key: redactedString, + Key: redactedString(), CreatedAt: c.CreatedAt, SNIs: c.SNIs, Tags: c.Tags, diff --git a/internal/dataplane/kongstate/types_test.go b/internal/dataplane/kongstate/types_test.go index adb201c2e7..ab54e2d261 100644 --- a/internal/dataplane/kongstate/types_test.go +++ b/internal/dataplane/kongstate/types_test.go @@ -26,7 +26,7 @@ func TestCertificate_SanitizedCopy(t *testing.T) { want: Certificate{kong.Certificate{ ID: kong.String("1"), Cert: kong.String("2"), - Key: redactedString, + Key: redactedString(), CreatedAt: int64Ptr(4), SNIs: []*string{kong.String("5.1"), kong.String("5.2")}, Tags: []*string{kong.String("6.1"), kong.String("6.2")},