Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions internal/gatewayapi/backendtlspolicy.go
Original file line number Diff line number Diff line change
Expand Up @@ -476,7 +476,7 @@ func (t *Translator) getCaCertsFromCARefs(
case resource.KindConfigMap:
cm := t.GetConfigMap(namespace, string(caRef.Name))
if cm != nil {
if crt, dataOk := getOrFirstFromData(cm.Data, caCertKey); dataOk {
if crt, dataOk := getOrFirstFromData(cm.Data, CACertKey); dataOk {
if ca != "" {
ca += "\n"
}
Expand All @@ -490,7 +490,7 @@ func (t *Translator) getCaCertsFromCARefs(
case resource.KindSecret:
secret := t.GetSecret(namespace, string(caRef.Name))
if secret != nil {
if crt, dataOk := getOrFirstFromData(secret.Data, caCertKey); dataOk {
if crt, dataOk := getOrFirstFromData(secret.Data, CACertKey); dataOk {
if ca != "" {
ca += "\n"
}
Expand Down
6 changes: 4 additions & 2 deletions internal/gatewayapi/backendtrafficpolicy.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ import (

const (
MaxConsistentHashTableSize = 5000011 // https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/cluster/v3/cluster.proto#config-cluster-v3-cluster-maglevlbconfig
// ResponseBodyConfigMapKey is the key used in ConfigMaps to store custom response body data
ResponseBodyConfigMapKey = "response.body"
)

// deprecatedFieldsUsedInBackendTrafficPolicy returns a map of deprecated field paths to their alternatives.
Expand Down Expand Up @@ -1561,7 +1563,7 @@ func (t *Translator) getCustomResponseBody(
if body.Type != nil && *body.Type == egv1a1.ResponseValueTypeValueRef {
cm := t.GetConfigMap(policyNs, string(body.ValueRef.Name))
if cm != nil {
b, dataOk := cm.Data["response.body"]
b, dataOk := cm.Data[ResponseBodyConfigMapKey]
switch {
case dataOk:
data := []byte(b)
Expand All @@ -1576,7 +1578,7 @@ func (t *Translator) getCustomResponseBody(
return binData, nil
}
default:
return nil, fmt.Errorf("can't find the key response.body in the referenced configmap %s", body.ValueRef.Name)
return nil, fmt.Errorf("can't find the key %s in the referenced configmap %s", ResponseBodyConfigMapKey, body.ValueRef.Name)
}
} else {
return nil, fmt.Errorf("can't find the referenced configmap %s", body.ValueRef.Name)
Expand Down
4 changes: 2 additions & 2 deletions internal/gatewayapi/clienttrafficpolicy.go
Original file line number Diff line number Diff line change
Expand Up @@ -837,7 +837,7 @@ func (t *Translator) buildListenerTLSParameters(
}

for _, caCertRef := range tlsParams.ClientValidation.CACertificateRefs {
caCertBytes, err := t.validateAndGetDataAtKeyInRef(caCertRef, caCertKey, resources, from)
caCertBytes, err := t.validateAndGetDataAtKeyInRef(caCertRef, CACertKey, resources, from)
if err != nil {
return irTLSConfig, fmt.Errorf("failed to get certificate from ref: %w", err)
}
Expand Down Expand Up @@ -867,7 +867,7 @@ func (t *Translator) buildListenerTLSParameters(

if tlsParams.ClientValidation.Crl != nil {
for _, crlRef := range tlsParams.ClientValidation.Crl.Refs {
crlBytes, err := t.validateAndGetDataAtKeyInRef(crlRef, crlKey, resources, from)
crlBytes, err := t.validateAndGetDataAtKeyInRef(crlRef, CRLKey, resources, from)
if err != nil {
return irTLSConfig, fmt.Errorf("failed to get crl from ref: %w", err)
}
Expand Down
10 changes: 7 additions & 3 deletions internal/gatewayapi/envoyextensionpolicy.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,11 @@ import (
)

// oci URL prefix
const ociURLPrefix = "oci://"
const (
ociURLPrefix = "oci://"
// LuaConfigMapKey is the key used in ConfigMaps to store Lua scripts
LuaConfigMapKey = "lua"
)

// deprecatedFieldsUsedInEnvoyExtensionPolicy returns a map of deprecated field paths to their alternatives.
func deprecatedFieldsUsedInEnvoyExtensionPolicy(policy *egv1a1.EnvoyExtensionPolicy) map[string]string {
Expand Down Expand Up @@ -725,7 +729,7 @@ func (t *Translator) getLuaBodyFromLocalObjectReference(
) (*string, error) {
cm := t.GetConfigMap(policyNs, string(valueRef.Name))
if cm != nil {
b, dataOk := cm.Data["lua"]
b, dataOk := cm.Data[LuaConfigMapKey]
switch {
case dataOk:
return &b, nil
Expand All @@ -736,7 +740,7 @@ func (t *Translator) getLuaBodyFromLocalObjectReference(
}
return &b, nil
default:
return nil, fmt.Errorf("can't find the key lua in the referenced configmap %s", valueRef.Name)
return nil, fmt.Errorf("can't find the key %s in the referenced configmap %s", LuaConfigMapKey, valueRef.Name)
}

} else {
Expand Down
10 changes: 6 additions & 4 deletions internal/gatewayapi/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,10 @@ const (
L4Protocol = "L4"
L7Protocol = "L7"

caCertKey = "ca.crt"
crlKey = "ca.crl"
// CACertKey is the key used in ConfigMaps and Secrets to store CA certificate data
CACertKey = "ca.crt"
// CRLKey is the key used in ConfigMaps and Secrets to store certificate revocation list data
CRLKey = "ca.crl"
)

type NamespacedNameWithSection struct {
Expand Down Expand Up @@ -464,11 +466,11 @@ func irTLSListenerConfigName(secret *corev1.Secret) string {
}

func irTLSCACertName(namespace, name string) string {
return fmt.Sprintf("%s/%s/%s", namespace, name, caCertKey)
return fmt.Sprintf("%s/%s/%s", namespace, name, CACertKey)
}

func irTLSCrlName(namespace, name string) string {
return fmt.Sprintf("%s/%s/%s", namespace, name, crlKey)
return fmt.Sprintf("%s/%s/%s", namespace, name, CRLKey)
}

func IsMergeGatewaysEnabled(resources *resource.Resources) bool {
Expand Down
4 changes: 2 additions & 2 deletions internal/gatewayapi/helpers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -757,7 +757,7 @@ func TestGetCaCertFromConfigMap(t *testing.T) {

for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
got, found := getOrFirstFromData(tc.cm.Data, caCertKey)
got, found := getOrFirstFromData(tc.cm.Data, CACertKey)
require.Equal(t, tc.expectedFound, found)
require.Equal(t, tc.expected, got)
})
Expand Down Expand Up @@ -803,7 +803,7 @@ func TestGetCaCertFromSecret(t *testing.T) {

for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
got, found := getOrFirstFromData(tc.s.Data, caCertKey)
got, found := getOrFirstFromData(tc.s.Data, CACertKey)
require.Equal(t, tc.expectedFound, found)
require.Equal(t, tc.expected, string(got))
})
Expand Down
7 changes: 5 additions & 2 deletions internal/gatewayapi/securitypolicy.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ const (
// nolint: gosec
oidcHMACSecretName = "envoy-oidc-hmac"
oidcHMACSecretKey = "hmac-secret"
// JWKSConfigMapKey is the key used in ConfigMaps to store JWKS data
JWKSConfigMapKey = "jwks"
)

// deprecatedFieldsUsedInSecurityPolicy returns a map of deprecated field paths to their alternatives.
Expand Down Expand Up @@ -1228,7 +1230,7 @@ func (t *Translator) buildLocalJWKS(
return "", fmt.Errorf("local JWKS ConfigMap %s/%s not found", policy.Namespace, localJWKS.ValueRef.Name)
}

jwksBytes, ok := cm.Data["jwks"]
jwksBytes, ok := cm.Data[JWKSConfigMapKey]
if ok {
return jwksBytes, nil
}
Expand All @@ -1240,7 +1242,8 @@ func (t *Translator) buildLocalJWKS(
}

return "", fmt.Errorf(
"JWKS data not found in ConfigMap %s/%s, no 'jwks' key and no other data found",
"JWKS data not found in ConfigMap %s/%s, no %q key and no other data found",
JWKSConfigMapKey,
cm.Namespace, cm.Name)
}

Expand Down
83 changes: 83 additions & 0 deletions internal/provider/kubernetes/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
toolscache "k8s.io/client-go/tools/cache"
"sigs.k8s.io/controller-runtime/pkg/client"
gwapiv1 "sigs.k8s.io/gateway-api/apis/v1"
mcsapiv1a1 "sigs.k8s.io/mcs-api/pkg/apis/v1alpha1"
Expand All @@ -25,6 +26,33 @@ const (
gatewayClassFinalizer = gwapiv1.GatewayClassFinalizerGatewaysExist
)

var (
// cachedConfigMapKeys defines the keys to keep in ConfigMap data cache
cachedConfigMapKeys = map[string]bool{
gatewayapi.JWKSConfigMapKey: true,
gatewayapi.LuaConfigMapKey: true,
gatewayapi.ResponseBodyConfigMapKey: true,
gatewayapi.CACertKey: true,
gatewayapi.CRLKey: true,
}

// cachedSecretKeys defines the keys to keep in Secret data cache
cachedSecretKeys = map[string]bool{
corev1.TLSCertKey: true,
corev1.TLSPrivateKeyKey: true,
egv1a1.TLSOCSPKey: true,
egv1a1.OIDCClientIDKey: true,
egv1a1.OIDCClientSecretKey: true,
egv1a1.BasicAuthUsersSecretKey: true,
egv1a1.InjectedCredentialKey: true,
egv1a1.APIKeysSecretKey: true,
corev1.DockerConfigJsonKey: true,
gatewayapi.CACertKey: true,
gatewayapi.CRLKey: true,
hmacSecretKey: true,
}
)

Comment on lines +29 to +55
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to define an unified list instead of different ones for configmap vs secret? I have seen cases where we use secrets and configmaps interchangeably using SecretObjectReference.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is fine, we can add comments to remind devs to add to both places

type ObjectKindNamespacedName struct {
kind string
namespace string
Expand Down Expand Up @@ -162,3 +190,58 @@ func classAccepted(gc *gwapiv1.GatewayClass) bool {

return false
}

// expectedAndFirstFallbackFilter filters a data map to only keep expected keys plus the first key for fallback.
func expectedAndFirstFallbackFilter[T any](data map[string]T, expectedKeys map[string]bool) map[string]T {
filtered := make(map[string]T, min(len(expectedKeys)+1, len(data)))
firstFallbackKey := "" // to track lexicographically first key for fallback
for k := range data {
if expectedKeys[k] {
filtered[k] = data[k]
}
if firstFallbackKey == "" || k < firstFallbackKey {
firstFallbackKey = k
}
}
filtered[firstFallbackKey] = data[firstFallbackKey]
return filtered
}

// transformConfigMapData filters ConfigMap data to only keep needed keys to reduce memory usage.
func transformConfigMapData(obj interface{}) (interface{}, error) {
cm, ok := obj.(*corev1.ConfigMap)
if !ok || len(cm.Data) <= 1 {
return obj, nil
}

cm.Data = expectedAndFirstFallbackFilter(cm.Data, cachedConfigMapKeys)
return cm, nil
}

// transformSecretData filters Secret data to only keep needed keys to reduce memory usage.
func transformSecretData(obj interface{}) (interface{}, error) {
secret, ok := obj.(*corev1.Secret)
if !ok || len(secret.Data) <= 1 {
return obj, nil
}

secret.Data = expectedAndFirstFallbackFilter(secret.Data, cachedSecretKeys)
return secret, nil
}

// composeTransforms chains multiple transform functions together.
func composeTransforms(transforms ...toolscache.TransformFunc) toolscache.TransformFunc {
return func(obj interface{}) (interface{}, error) {
var err error
for _, transform := range transforms {
if transform == nil {
continue
}
obj, err = transform(obj)
if err != nil {
return nil, err
}
}
return obj, nil
}
}
Loading