Skip to content

Commit

Permalink
fix: include Licenses and ConsumerGroups in sanitized copies of config
Browse files Browse the repository at this point in the history
  • Loading branch information
czeslavo committed Sep 22, 2023
1 parent 5cd2b5b commit ea3a7d4
Show file tree
Hide file tree
Showing 4 changed files with 76 additions and 2 deletions.
4 changes: 3 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ Adding a new version? You'll need three changes:
- KongPlugins used on multiple resources will no longer result in
`instance_name` collisions.
[#4588](https://github.com/Kong/kubernetes-ingress-controller/issues/4588)
- Fix `panic` when last known configuratino fetcher gets a `nil` Status when requesting
- Fix `panic` when last known configuration fetcher gets a `nil` Status when requesting
`/status` from Kong Gateway.
This happens when Gateway is responding with a 50x HTTP status code.
[#4627](https://github.com/Kong/kubernetes-ingress-controller/issues/4627)
Expand All @@ -137,6 +137,8 @@ Adding a new version? You'll need three changes:
deleting existing configuration during an API server restart.
[#4641](https://github.com/Kong/kubernetes-ingress-controller/issues/4641)
[#4643](https://github.com/Kong/kubernetes-ingress-controller/issues/4643)
- Fix `Licenses` and `ConsumerGroups` missing in sanitized copies of Kong configuration.
[#4710](https://github.com/Kong/kubernetes-ingress-controller/pull/4710

## [2.11.1]

Expand Down
9 changes: 8 additions & 1 deletion internal/dataplane/kongstate/kongstate.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ type KongState struct {
Upstreams []Upstream
Certificates []Certificate
CACertificates []kong.CACertificate
Licenses []kong.License
Licenses []License
Plugins []Plugin
Consumers []Consumer
ConsumerGroups []ConsumerGroup
Expand All @@ -49,6 +49,13 @@ func (ks *KongState) SanitizedCopy() *KongState {
}
return
}(),
Licenses: func() (res []License) {
for _, v := range ks.Licenses {
res = append(res, *v.SanitizedCopy())
}
return
}(),
ConsumerGroups: ks.ConsumerGroups,
}
}

Expand Down
45 changes: 45 additions & 0 deletions internal/dataplane/kongstate/kongstate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
k8stypes "k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/sets"

"github.com/kong/kubernetes-ingress-controller/v2/internal/annotations"
"github.com/kong/kubernetes-ingress-controller/v2/internal/dataplane/failures"
Expand All @@ -31,6 +32,7 @@ var kongConsumerTypeMeta = metav1.TypeMeta{
}

func TestKongState_SanitizedCopy(t *testing.T) {
testedFields := sets.New[string]()
for _, tt := range []struct {
name string
in KongState
Expand All @@ -47,6 +49,10 @@ func TestKongState_SanitizedCopy(t *testing.T) {
Consumers: []Consumer{{
KeyAuths: []*KeyAuth{{kong.KeyAuth{ID: kong.String("1"), Key: kong.String("secret")}}},
}},
Licenses: []License{{kong.License{ID: kong.String("1"), Payload: kong.String("secret")}}},
ConsumerGroups: []ConsumerGroup{{
ConsumerGroup: kong.ConsumerGroup{ID: kong.String("1"), Name: kong.String("consumer-group")},
}},
},
want: KongState{
Services: []Service{{Service: kong.Service{ID: kong.String("1")}}},
Expand All @@ -57,14 +63,53 @@ func TestKongState_SanitizedCopy(t *testing.T) {
Consumers: []Consumer{{
KeyAuths: []*KeyAuth{{kong.KeyAuth{ID: kong.String("1"), Key: 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")},
}},
},
},
} {
t.Run(tt.name, func(t *testing.T) {
testedFields.Insert(extractNotEmptyFieldNames(tt.in)...)
got := *tt.in.SanitizedCopy()
assert.Equal(t, tt.want, got)
})
}

ensureAllKongStateFieldsAreCoveredInTest(t, testedFields.UnsortedList())
}

// extractNotEmptyFieldNames returns the names of all non-empty fields in the given KongState.
// This is to programmatically find out what fields are used in a test case.
func extractNotEmptyFieldNames(s KongState) []string {
var fields []string
typ := reflect.ValueOf(s).Type()
for i := 0; i < typ.NumField(); i++ {
f := typ.Field(i)
v := reflect.ValueOf(s).Field(i)
if !f.Anonymous && f.IsExported() && !v.IsZero() {
fields = append(fields, f.Name)
}
}
return fields
}

// ensureAllKongStateFieldsAreCoveredInTest ensures that all fields in KongState are covered in a tests.
func ensureAllKongStateFieldsAreCoveredInTest(t *testing.T, testedFields []string) {
allKongStateFields := func() []string {
var fields []string
typ := reflect.ValueOf(KongState{}).Type()
for i := 0; i < typ.NumField(); i++ {
fields = append(fields, typ.Field(i).Name)
}
return fields
}()

// Meta test - ensure we have testcases covering all fields in KongState.
for _, field := range allKongStateFields {
assert.True(t, lo.Contains(testedFields, field), "field %s wasn't tested", field)
}
}

func TestGetPluginRelations(t *testing.T) {
Expand Down
20 changes: 20 additions & 0 deletions internal/dataplane/kongstate/license.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package kongstate

import "github.com/kong/go-kong/kong"

// License represents the license object in Kong.
type License struct {
kong.License
}

// SanitizedCopy returns a shallow copy with sensitive values redacted best-effort.
func (l License) SanitizedCopy() *License {
return &License{
License: kong.License{
ID: l.ID,
Payload: redactedString,
CreatedAt: l.CreatedAt,
UpdatedAt: l.UpdatedAt,
},
}
}

0 comments on commit ea3a7d4

Please sign in to comment.