Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(backendtlspolicy): enqueue for ConfigMaps #6837

Merged
merged 1 commit into from
Dec 13, 2024
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,7 @@ Adding a new version? You'll need three changes:
is applied to the service section of the Kong configuration.
[#6712](https://github.com/Kong/kubernetes-ingress-controller/pull/6712)
[#6753](https://github.com/Kong/kubernetes-ingress-controller/pull/6753)
[#6837](https://github.com/Kong/kubernetes-ingress-controller/pull/6837)
- Added the flag `--configmap-label-selector` to set the label selector for `ConfigMap`s
to ingest. By setting this flag, the `ConfigMap`s that are ingested will be limited
to those having this label set to "true". This limits the amount of resources that are kept in memory.
Expand Down
54 changes: 54 additions & 0 deletions internal/controllers/gateway/backendtlspolicy_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ func (r *BackendTLSPolicyReconciler) SetupWithManager(mgr ctrl.Manager) error {
CacheSyncTimeout: r.CacheSyncTimeout,
}).
For(&gatewayapi.BackendTLSPolicy{}).
Watches(&corev1.ConfigMap{}, handler.EnqueueRequestsFromMapFunc(r.listBackendTLSPoliciesForConfigMaps)).
Watches(&corev1.Service{}, handler.EnqueueRequestsFromMapFunc(r.listBackendTLSPoliciesForServices)).
Watches(&gatewayapi.HTTPRoute{}, handler.EnqueueRequestsFromMapFunc(r.listBackendTLSPoliciesForHTTPRoutes)).
Watches(&gatewayapi.Gateway{}, handler.EnqueueRequestsFromMapFunc(r.listBackendTLSPoliciesForGateways)).
Expand All @@ -65,6 +66,9 @@ func (r *BackendTLSPolicyReconciler) SetupWithManager(mgr ctrl.Manager) error {
// -----------------------------------------------------------------------------

const (
// backendTLSPolicyValidationCARefIndexKey is the index key for BackendTLSPolicy objects by their validation CA configmap reference.
// The value is the name of the configmap.
backendTLSPolicyValidationCARefIndexKey = "backendtlspolicy-validation-cacertificateref"
// backendTLSPolicyTargetRefIndexKey is the index key for BackendTLSPolicy objects by their target service reference.
// The value is the name of the service.
backendTLSPolicyTargetRefIndexKey = "backendtlspolicy-targetref"
Expand Down Expand Up @@ -92,6 +96,23 @@ func indexBackendTLSPolicyOnTargetRef(obj client.Object) []string {
return services
}

// indexBackendTLSPolicyOnValidationCACertificateRef indexes BackendTLSPolicy objects
// by their validation CA Certificate configmap reference.
func indexBackendTLSPolicyOnValidationCACertificateRef(obj client.Object) []string {
policy, ok := obj.(*gatewayapi.BackendTLSPolicy)
if !ok {
return []string{}
}

configmaps := []string{}
for _, cacertref := range policy.Spec.Validation.CACertificateRefs {
if (cacertref.Group == "" || cacertref.Group == "core") && cacertref.Kind == "ConfigMap" {
configmaps = append(configmaps, string(cacertref.Name))
}
}
return configmaps
}

// indexHTTPRouteOnParentRef indexes HTTPRoute objects by their parent Gateway references.
func indexHTTPRouteOnParentRef(obj client.Object) []string {
httpRoute, ok := obj.(*gatewayapi.HTTPRoute)
Expand Down Expand Up @@ -148,6 +169,15 @@ func setupBackendTLSPolicyIndices(mgr ctrl.Manager) error {
return fmt.Errorf("failed to index backendTLSPolicies on service reference: %w", err)
}

if err := mgr.GetCache().IndexField(
context.Background(),
&gatewayapi.BackendTLSPolicy{},
backendTLSPolicyValidationCARefIndexKey,
indexBackendTLSPolicyOnValidationCACertificateRef,
); err != nil {
return fmt.Errorf("failed to index backendTLSPolicies on validation CA configmap reference: %w", err)
}

if err := mgr.GetCache().IndexField(
context.Background(),
&gatewayapi.HTTPRoute{},
Expand All @@ -173,6 +203,30 @@ func setupBackendTLSPolicyIndices(mgr ctrl.Manager) error {
// BackendTLSPolicy Controller - Event Handlers
// -----------------------------------------------------------------------------

// listBackendTLSPoliciesForConfigMaps returns the list of BackendTLSPolicies that targets the given ConfigMap.
func (r *BackendTLSPolicyReconciler) listBackendTLSPoliciesForConfigMaps(ctx context.Context, obj client.Object) []reconcile.Request {
cm, ok := obj.(*corev1.ConfigMap)
if !ok {
r.Log.Error(fmt.Errorf("invalid type"), "Found invalid type in event handlers", "expected", "ConfigMap", "found", reflect.TypeOf(obj))
return nil
}
policies := &gatewayapi.BackendTLSPolicyList{}
if err := r.List(ctx, policies,
client.InNamespace(cm.Namespace),
client.MatchingFields{backendTLSPolicyValidationCARefIndexKey: cm.Name},
); err != nil {
r.Log.Error(err, "Failed to list BackendTLSPolicies for ConfigMap", "configmap", cm)
return nil
}
requests := make([]reconcile.Request, 0, len(policies.Items))
for _, policy := range policies.Items {
requests = append(requests, reconcile.Request{
NamespacedName: client.ObjectKeyFromObject(&policy),
})
}
return requests
}

// listBackendTLSPoliciesForServices returns the list of BackendTLSPolicies that targets the given Service.
func (r *BackendTLSPolicyReconciler) listBackendTLSPoliciesForServices(ctx context.Context, obj client.Object) []reconcile.Request {
service, ok := obj.(*corev1.Service)
Expand Down
16 changes: 16 additions & 0 deletions internal/controllers/gateway/backendtlspolicy_utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@ package gateway

import (
"context"
"fmt"
"sort"
"strings"

"github.com/samber/lo"
corev1 "k8s.io/api/core/v1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
k8stypes "k8s.io/apimachinery/pkg/types"
Expand Down Expand Up @@ -240,6 +242,20 @@ func (r *BackendTLSPolicyReconciler) validateBackendTLSPolicy(ctx context.Contex
invalidMessages = append(invalidMessages, "CACertificateRefs must reference ConfigMaps in the core group")
break
}

var (
cm corev1.ConfigMap
configMapNN = k8stypes.NamespacedName{
Namespace: policy.Namespace,
Name: string(caCert.Name),
}
)
if err := r.Get(ctx, configMapNN, &cm); err != nil {
invalidMessages = append(invalidMessages,
fmt.Sprintf("failed getting ConfigMap %s set as CACertificateRef: %s", configMapNN, err),
)
break
}
}
if len(policy.Spec.Validation.SubjectAltNames) > 0 {
invalidMessages = append(invalidMessages, "SubjectAltNames feature is not currently supported")
Expand Down
77 changes: 77 additions & 0 deletions internal/controllers/gateway/backendtlspolicy_utils_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
k8stypes "k8s.io/apimachinery/pkg/types"
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/client/fake"

Expand Down Expand Up @@ -764,9 +765,80 @@ func TestValidateBackendTLSPolicy(t *testing.T) {
Message: "CACertificateRefs must reference ConfigMaps in the core group - SubjectAltNames feature is not currently supported - WellKnownCACertificates feature is not currently supported",
},
},
{
name: "valid policy referencing not existing CACert (ConfigMap)",
policy: &gatewayapi.BackendTLSPolicy{
ObjectMeta: metav1.ObjectMeta{
Name: "test-policy",
Namespace: "default",
},
Spec: gatewayapi.BackendTLSPolicySpec{
TargetRefs: []gatewayapi.LocalPolicyTargetReferenceWithSectionName{
{
LocalPolicyTargetReference: gatewayapi.LocalPolicyTargetReference{
Group: "core",
Kind: "Service",
Name: "example-service",
},
},
},
Validation: gatewayapi.BackendTLSPolicyValidation{
CACertificateRefs: []gatewayapi.LocalObjectReference{
{
Group: "",
Kind: "ConfigMap",
Name: gatewayapi.ObjectName("example-configmap"),
},
},
},
},
},
expected: &metav1.Condition{
Type: string(gatewayapi.PolicyConditionAccepted),
Status: metav1.ConditionFalse,
Reason: string(gatewayapi.PolicyReasonInvalid),
Message: "failed getting ConfigMap default/example-configmap set as CACertificateRef: configmaps \"example-configmap\" not found",
},
},
{
name: "valid policy referencing not existing CACert (ConfigMap, group core)",
policy: &gatewayapi.BackendTLSPolicy{
ObjectMeta: metav1.ObjectMeta{
Name: "test-policy",
Namespace: "default",
},
Spec: gatewayapi.BackendTLSPolicySpec{
TargetRefs: []gatewayapi.LocalPolicyTargetReferenceWithSectionName{
{
LocalPolicyTargetReference: gatewayapi.LocalPolicyTargetReference{
Group: "core",
Kind: "Service",
Name: "example-service",
},
},
},
Validation: gatewayapi.BackendTLSPolicyValidation{
CACertificateRefs: []gatewayapi.LocalObjectReference{
{
Group: "core",
Kind: "ConfigMap",
Name: gatewayapi.ObjectName("example-configmap"),
},
},
},
},
},
expected: &metav1.Condition{
Type: string(gatewayapi.PolicyConditionAccepted),
Status: metav1.ConditionFalse,
Reason: string(gatewayapi.PolicyReasonInvalid),
Message: "failed getting ConfigMap default/example-configmap set as CACertificateRef: configmaps \"example-configmap\" not found",
},
},
}

scheme := runtime.NewScheme()
require.NoError(t, clientgoscheme.AddToScheme(scheme))
require.NoError(t, gatewayapi.InstallV1(scheme))
require.NoError(t, gatewayapi.InstallV1alpha3(scheme))

Expand All @@ -784,6 +856,11 @@ func TestValidateBackendTLSPolicy(t *testing.T) {
backendTLSPolicyTargetRefIndexKey,
indexBackendTLSPolicyOnTargetRef,
).
WithIndex(
&gatewayapi.BackendTLSPolicy{},
backendTLSPolicyValidationCARefIndexKey,
indexBackendTLSPolicyOnValidationCACertificateRef,
).
Build()

r := &BackendTLSPolicyReconciler{
Expand Down
Loading