Skip to content

Commit

Permalink
Update AuthPolicy status for overrides in the Enforced status block. (K…
Browse files Browse the repository at this point in the history
  • Loading branch information
Boomatang authored Apr 22, 2024
1 parent c849153 commit 7cdd23b
Show file tree
Hide file tree
Showing 3 changed files with 113 additions and 4 deletions.
72 changes: 71 additions & 1 deletion controllers/authpolicy_status.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ import (
"fmt"
"slices"

kuadrantgatewayapi "github.com/kuadrant/kuadrant-operator/pkg/library/gatewayapi"
"k8s.io/utils/ptr"

"github.com/go-logr/logr"
authorinoapi "github.com/kuadrant/authorino/api/v1beta2"
apierrors "k8s.io/apimachinery/pkg/api/errors"
Expand Down Expand Up @@ -88,13 +91,18 @@ func (r *AuthPolicyReconciler) acceptedCondition(policy kuadrant.Policy, specErr
func (r *AuthPolicyReconciler) enforcedCondition(ctx context.Context, policy *api.AuthPolicy, targetNetworkObject client.Object) *metav1.Condition {
logger, _ := logr.FromContext(ctx)

t, err := r.generateTopology(ctx)
if err != nil {
logger.V(1).Info("Failed to generate topology", "error", err)
return nil
}
// Check if the policy is overridden
// Note: This logic assumes synchronous processing, where computing the desired AuthConfig, marking the AuthPolicy
// as overridden, and calculating the Enforced condition happen sequentially.
// Introducing a goroutine in this flow could break this assumption and lead to unexpected behavior.
if r.OverriddenPolicyMap.IsPolicyOverridden(policy) {
logger.V(1).Info("Gateway Policy is overridden")
return r.handleGatewayPolicyOverride(logger, policy, targetNetworkObject)
return r.handlePolicyOverride(logger, policy, targetNetworkObject, t)
}

// Check if the AuthConfig is ready
Expand Down Expand Up @@ -130,6 +138,18 @@ func (r *AuthPolicyReconciler) isAuthConfigReady(ctx context.Context, policy *ap
return authConfig.Status.Ready(), nil
}

func (r *AuthPolicyReconciler) handlePolicyOverride(logger logr.Logger, policy *api.AuthPolicy, targetNetworkObject client.Object, t *kuadrantgatewayapi.Topology) *metav1.Condition {
switch targetNetworkObject.(type) {
case *gatewayapiv1.Gateway:
return r.handleGatewayPolicyOverride(logger, policy, targetNetworkObject)
case *gatewayapiv1.HTTPRoute:
return r.handleHTTPRoutePolicyOverride(logger, policy, targetNetworkObject, t)
default:
logger.Error(errors.New("this point should never be reached"), "failed to match target network object", targetNetworkObject)
return nil
}
}

// handleGatewayPolicyOverride handles the case where the Gateway Policy is overridden by filtering policy references
// and creating a corresponding error condition.
func (r *AuthPolicyReconciler) handleGatewayPolicyOverride(logger logr.Logger, policy *api.AuthPolicy, targetNetworkObject client.Object) *metav1.Condition {
Expand All @@ -146,3 +166,53 @@ func (r *AuthPolicyReconciler) handleGatewayPolicyOverride(logger logr.Logger, p
}
return kuadrant.EnforcedCondition(policy, kuadrant.NewErrOverridden(policy.Kind(), string(jsonData)), false)
}

// handleHTTPRoutePolicyOverride handles the case where the HTTPRoute Policy is overridden by filtering policy references
// and creating a corresponding error condition.
func (r *AuthPolicyReconciler) handleHTTPRoutePolicyOverride(logger logr.Logger, policy *api.AuthPolicy, targetNetworkObject client.Object, t *kuadrantgatewayapi.Topology) *metav1.Condition {
obj := targetNetworkObject.(*gatewayapiv1.HTTPRoute)
httpRouteWrapper := kuadrant.HTTPRouteWrapper{HTTPRoute: obj, Referrer: policy}
refs := httpRouteWrapper.PolicyRefs(t)
jsonData, err := json.Marshal(refs)
if err != nil {
logger.Error(err, "Failed to marshal filtered references")
return kuadrant.EnforcedCondition(policy, kuadrant.NewErrUnknown(policy.Kind(), err), false)
}
return kuadrant.EnforcedCondition(policy, kuadrant.NewErrOverridden(policy.Kind(), string(jsonData)), false)
}

func (r *AuthPolicyReconciler) generateTopology(ctx context.Context) (*kuadrantgatewayapi.Topology, error) {
logger, _ := logr.FromContext(ctx)

gwList := &gatewayapiv1.GatewayList{}
err := r.Client().List(ctx, gwList)
logger.V(1).Info("topology: list gateways", "#Gateways", len(gwList.Items), "err", err)
if err != nil {
return nil, err
}

routeList := &gatewayapiv1.HTTPRouteList{}
err = r.Client().List(ctx, routeList)
logger.V(1).Info("topology: list httproutes", "#HTTPRoutes", len(routeList.Items), "err", err)
if err != nil {
return nil, err
}

aplist := &api.AuthPolicyList{}
err = r.Client().List(ctx, aplist)
logger.V(1).Info("topology: list rate limit policies", "#RLPS", len(aplist.Items), "err", err)
if err != nil {
return nil, err
}

policies := utils.Map(aplist.Items, func(p api.AuthPolicy) kuadrantgatewayapi.Policy {
return &p
})

return kuadrantgatewayapi.NewTopology(
kuadrantgatewayapi.WithGateways(utils.Map(gwList.Items, ptr.To[gatewayapiv1.Gateway])),
kuadrantgatewayapi.WithRoutes(utils.Map(routeList.Items, ptr.To[gatewayapiv1.HTTPRoute])),
kuadrantgatewayapi.WithPolicies(policies),
kuadrantgatewayapi.WithLogger(logger),
)
}
4 changes: 1 addition & 3 deletions pkg/library/kuadrant/apimachinery_status_conditions.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,6 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
gatewayapiv1alpha2 "sigs.k8s.io/gateway-api/apis/v1alpha2"

"github.com/kuadrant/kuadrant-operator/pkg/library/gatewayapi"
)

const (
Expand Down Expand Up @@ -55,7 +53,7 @@ func (o *OverriddenPolicyMap) RemoveOverriddenPolicy(p Policy) {

// IsPolicyOverridden checks if the provided Policy is overridden based on the tracking map maintained.
func (o *OverriddenPolicyMap) IsPolicyOverridden(p Policy) bool {
return o.policies[p.GetUID()] && gatewayapi.IsTargetRefGateway(p.GetTargetRef())
return o.policies[p.GetUID()]
}

// ConditionMarshal marshals the set of conditions as a JSON array, sorted by condition type.
Expand Down
41 changes: 41 additions & 0 deletions pkg/library/kuadrant/httproute_wrapper.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package kuadrant

import (
"github.com/kuadrant/kuadrant-operator/pkg/common"
kuadrantgatewayapi "github.com/kuadrant/kuadrant-operator/pkg/library/gatewayapi"
gatewayapiv1 "sigs.k8s.io/gateway-api/apis/v1"
)

type HTTPRouteWrapper struct {
*gatewayapiv1.HTTPRoute
Referrer
}

func (r HTTPRouteWrapper) PolicyRefs(t *kuadrantgatewayapi.Topology) []string {
if r.HTTPRoute == nil {
return make([]string, 0)
}
refs := make([]string, 0)
for _, gw := range t.Gateways() {
authPolicyRefs, ok := gw.GetAnnotations()[common.AuthPolicyBackRefAnnotation]
if !ok {
continue
}
refs = append(refs, authPolicyRefs)
}
return refs
}

// HTTPRouteWrapperList is a list of HTTPRouteWrapper that implements sort.interface
// impl: sort.interface
type HTTPRouteWrapperList []HTTPRouteWrapper

func (l HTTPRouteWrapperList) Len() int { return len(l) }

func (l HTTPRouteWrapperList) Less(i, j int) bool {
return l[i].CreationTimestamp.Before(&l[j].CreationTimestamp)
}

func (l HTTPRouteWrapperList) Swap(i, j int) {
l[i], l[j] = l[j], l[i]
}

0 comments on commit 7cdd23b

Please sign in to comment.