Skip to content

Commit eeca2fe

Browse files
committed
feat: support crls in client traffic policies
Signed-off-by: Rudrakh Panigrahi <[email protected]>
1 parent 7768139 commit eeca2fe

19 files changed

+1200
-62
lines changed

api/v1alpha1/tls_types.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,6 @@ type ClientValidationContext struct {
167167

168168
// Crl specifies the crl configuration that can be used to validate the client initiating the TLS connection
169169
// +optional
170-
// +notImplementedHide
171170
Crl *CrlContext `json:"crl,omitempty"`
172171
}
173172

internal/gatewayapi/backendtlspolicy.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -309,7 +309,7 @@ func getCaCertsFromCARefs(namespace string, caCertificates []gwapiv1.LocalObject
309309
case resource.KindConfigMap:
310310
cm := resources.GetConfigMap(namespace, string(caRef.Name))
311311
if cm != nil {
312-
if crt, dataOk := getCaCertFromConfigMap(cm); dataOk {
312+
if crt, dataOk := getCaCertFromData(cm.Data); dataOk {
313313
if ca != "" {
314314
ca += "\n"
315315
}
@@ -323,7 +323,7 @@ func getCaCertsFromCARefs(namespace string, caCertificates []gwapiv1.LocalObject
323323
case resource.KindSecret:
324324
secret := resources.GetSecret(namespace, string(caRef.Name))
325325
if secret != nil {
326-
if crt, dataOk := getCaCertFromSecret(secret); dataOk {
326+
if crt, dataOk := getCaCertFromData(secret.Data); dataOk {
327327
if ca != "" {
328328
ca += "\n"
329329
}

internal/gatewayapi/clienttrafficpolicy.go

Lines changed: 53 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -857,7 +857,7 @@ func (t *Translator) buildListenerTLSParameters(policy *egv1a1.ClientTrafficPoli
857857
return irTLSConfig, err
858858
}
859859

860-
secretCertBytes, ok := getCaCertFromSecret(secret)
860+
secretCertBytes, ok := getCaCertFromData(secret.Data)
861861
if !ok || len(secretCertBytes) == 0 {
862862
return irTLSConfig, fmt.Errorf(
863863
"caCertificateRef secret [%s] not found", caCertRef.Name)
@@ -869,7 +869,7 @@ func (t *Translator) buildListenerTLSParameters(policy *egv1a1.ClientTrafficPoli
869869
return irTLSConfig, err
870870
}
871871

872-
configMapData, ok := getCaCertFromConfigMap(configMap)
872+
configMapData, ok := getCaCertFromData(configMap.Data)
873873
if !ok || len(configMapData) == 0 {
874874
return irTLSConfig, fmt.Errorf(
875875
"caCertificateRef configmap [%s] not found", caCertRef.Name)
@@ -892,12 +892,62 @@ func (t *Translator) buildListenerTLSParameters(policy *egv1a1.ClientTrafficPoli
892892
}
893893
irCACert.Certificate = append(irCACert.Certificate, caCertBytes...)
894894
}
895-
896895
if len(irCACert.Certificate) > 0 {
897896
irTLSConfig.CACertificate = irCACert
898897
irTLSConfig.RequireClientCertificate = !tlsParams.ClientValidation.Optional
899898
setTLSClientValidationContext(tlsParams.ClientValidation, irTLSConfig)
900899
}
900+
901+
irCrl := &ir.TLSCrl{
902+
Name: irTLSCrlName(policy.Namespace, policy.Name),
903+
}
904+
905+
if tlsParams.ClientValidation.Crl != nil {
906+
for _, crlRef := range tlsParams.ClientValidation.Crl.Refs {
907+
crlRefKind := string(ptr.Deref(crlRef.Kind, resource.KindSecret))
908+
var crlBytes []byte
909+
switch crlRefKind {
910+
case resource.KindSecret:
911+
secret, err := t.validateSecretRef(false, from, crlRef, resources)
912+
if err != nil {
913+
return irTLSConfig, err
914+
}
915+
916+
secretCrlBytes, ok := getCrlFromData(secret.Data)
917+
if !ok || len(secretCrlBytes) == 0 {
918+
return irTLSConfig, fmt.Errorf(
919+
"crl secret [%s] not found", crlRef.Name)
920+
}
921+
crlBytes = secretCrlBytes
922+
case resource.KindConfigMap:
923+
configMap, err := t.validateConfigMapRef(false, from, crlRef, resources)
924+
if err != nil {
925+
return irTLSConfig, err
926+
}
927+
928+
configMapData, ok := getCrlFromData(configMap.Data)
929+
if !ok || len(configMapData) == 0 {
930+
return irTLSConfig, fmt.Errorf(
931+
"crl configmap [%s] not found", crlRef.Name)
932+
}
933+
crlBytes = []byte(configMapData)
934+
default:
935+
return irTLSConfig, fmt.Errorf("unsupported crlRef kind:%s", crlRefKind)
936+
}
937+
938+
if err := validateCrl(crlBytes); err != nil {
939+
return irTLSConfig, fmt.Errorf(
940+
"invalid crl in %s %s: %w", crlRefKind, crlRef.Name, err)
941+
}
942+
irCrl.Data = append(irCrl.Data, crlBytes...)
943+
}
944+
if len(irCrl.Data) > 0 {
945+
irTLSConfig.Crl = irCrl
946+
}
947+
if tlsParams.ClientValidation.Crl.OnlyVerifyLeafCertificate != nil {
948+
irCrl.OnlyVerifyLeafCertificate = *tlsParams.ClientValidation.Crl.OnlyVerifyLeafCertificate
949+
}
950+
}
901951
}
902952

903953
if tlsParams.Session != nil && tlsParams.Session.Resumption != nil {

internal/gatewayapi/helpers.go

Lines changed: 21 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ const (
3838
L7Protocol = "L7"
3939

4040
caCertKey = "ca.crt"
41+
crlKey = "ca.crl"
4142
)
4243

4344
type protocolPort struct {
@@ -461,6 +462,10 @@ func irTLSCACertName(namespace, name string) string {
461462
return fmt.Sprintf("%s/%s/%s", namespace, name, caCertKey)
462463
}
463464

465+
func irTLSCrlName(namespace, name string) string {
466+
return fmt.Sprintf("%s/%s/%s", namespace, name, crlKey)
467+
}
468+
464469
func IsMergeGatewaysEnabled(resources *resource.Resources) bool {
465470
return resources.EnvoyProxyForGatewayClass != nil && resources.EnvoyProxyForGatewayClass.Spec.MergeGateways != nil && *resources.EnvoyProxyForGatewayClass.Spec.MergeGateways
466471
}
@@ -688,38 +693,26 @@ func getPreserveRouteOrder(envoyProxy *egv1a1.EnvoyProxy) bool {
688693
return false
689694
}
690695

691-
func getCaCertFromConfigMap(cm *corev1.ConfigMap) (string, bool) {
692-
var data string
693-
data, exits := cm.Data[caCertKey]
694-
switch {
695-
case exits:
696-
return data, true
697-
case len(cm.Data) == 1: // Fallback to the first key if ca.crt is not found
698-
for _, value := range cm.Data {
699-
data = value
700-
break
701-
}
702-
return data, true
703-
default:
704-
return "", false
705-
}
696+
// getCrlFromData returns crl from the data map
697+
func getCrlFromData[T any](data map[string]T) (T, bool) {
698+
return getOrFirstFromData(data, crlKey)
706699
}
707700

708-
func getCaCertFromSecret(s *corev1.Secret) ([]byte, bool) {
709-
var data []byte
710-
data, exits := s.Data[caCertKey]
711-
switch {
712-
case exits:
713-
return data, true
714-
case len(s.Data) == 1: // Fallback to the first key if ca.crt is not found
715-
for _, value := range s.Data {
716-
data = value
717-
break
701+
// getCaCertFromData returns ca certificate from the data map
702+
func getCaCertFromData[T any](data map[string]T) (T, bool) {
703+
return getOrFirstFromData(data, caCertKey)
704+
}
705+
706+
// getOrFirstFromData returns the value of the key in the data map, or the first value if the key is not found
707+
func getOrFirstFromData[T any](data map[string]T, key string) (T, bool) {
708+
if val, exists := data[key]; exists {
709+
return val, true
710+
} else if len(data) > 0 {
711+
for _, value := range data {
712+
return value, true
718713
}
719-
return data, true
720-
default:
721-
return nil, false
722714
}
715+
return *new(T), false
723716
}
724717

725718
func irStringMatch(name string, match egv1a1.StringMatch) *ir.StringMatch {

internal/gatewayapi/helpers_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -758,7 +758,7 @@ func TestGetCaCertFromConfigMap(t *testing.T) {
758758

759759
for _, tc := range cases {
760760
t.Run(tc.name, func(t *testing.T) {
761-
got, found := getCaCertFromConfigMap(tc.cm)
761+
got, found := getCaCertFromData(tc.cm.Data)
762762
require.Equal(t, tc.expectedFound, found)
763763
require.Equal(t, tc.expected, got)
764764
})
@@ -804,7 +804,7 @@ func TestGetCaCertFromSecret(t *testing.T) {
804804

805805
for _, tc := range cases {
806806
t.Run(tc.name, func(t *testing.T) {
807-
got, found := getCaCertFromSecret(tc.s)
807+
got, found := getCaCertFromData(tc.s.Data)
808808
require.Equal(t, tc.expectedFound, found)
809809
require.Equal(t, tc.expected, string(got))
810810
})

internal/gatewayapi/testdata/clienttrafficpolicy-invalid-settings.out.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,8 @@ clientTrafficPolicies:
3131
conditions:
3232
- lastTransitionTime: null
3333
message: |-
34-
TLS: caCertificateRef secret [tls-secret-1] not found
35-
TLS: caCertificateRef secret [tls-secret-1] not found.
34+
TLS: invalid certificate in Secret tls-secret-1: certificate has expired since 2025-01-25 23:15:31 +0000 UTC
35+
TLS: invalid certificate in Secret tls-secret-1: certificate has expired since 2025-01-25 23:15:31 +0000 UTC.
3636
reason: Invalid
3737
status: "False"
3838
type: Accepted

0 commit comments

Comments
 (0)