Skip to content

Commit

Permalink
sotw: auth
Browse files Browse the repository at this point in the history
* AuthPolicies validation
* Effective auth policies
* Authorino AuthConfigs
* Istio/Envoy Gateway cluster patches
* Istio/Envoy Gateway wasm extensions
* (Most part of) AuthPolicy status update

Signed-off-by: Guilherme Cassolato <[email protected]>
  • Loading branch information
guicassolato committed Oct 23, 2024
1 parent 43052b4 commit bc688df
Show file tree
Hide file tree
Showing 36 changed files with 2,000 additions and 2,330 deletions.
42 changes: 33 additions & 9 deletions api/v1beta1/topology.go
Original file line number Diff line number Diff line change
@@ -1,23 +1,28 @@
package v1beta1

import (
authorinov1beta1 "github.com/kuadrant/authorino-operator/api/v1beta1"
authorinooperatorv1beta1 "github.com/kuadrant/authorino-operator/api/v1beta1"
authorinov1beta2 "github.com/kuadrant/authorino/api/v1beta2"
limitadorv1alpha1 "github.com/kuadrant/limitador-operator/api/v1alpha1"
"github.com/kuadrant/policy-machinery/controller"
"github.com/kuadrant/policy-machinery/machinery"
"github.com/samber/lo"
"k8s.io/apimachinery/pkg/runtime/schema"
gwapiv1 "sigs.k8s.io/gateway-api/apis/v1"
gatewayapiv1 "sigs.k8s.io/gateway-api/apis/v1"
)

var (
AuthorinoGroupKind = schema.GroupKind{Group: authorinov1beta1.GroupVersion.Group, Kind: "Authorino"}
KuadrantGroupKind = schema.GroupKind{Group: GroupVersion.Group, Kind: "Kuadrant"}
LimitadorGroupKind = schema.GroupKind{Group: limitadorv1alpha1.GroupVersion.Group, Kind: "Limitador"}
KuadrantGroupKind = schema.GroupKind{Group: GroupVersion.Group, Kind: "Kuadrant"}
LimitadorGroupKind = schema.GroupKind{Group: limitadorv1alpha1.GroupVersion.Group, Kind: "Limitador"}
AuthorinoGroupKind = schema.GroupKind{Group: authorinooperatorv1beta1.GroupVersion.Group, Kind: "Authorino"}
AuthConfigGroupKind = schema.GroupKind{Group: authorinov1beta2.GroupVersion.Group, Kind: "AuthConfig"}

AuthorinosResource = authorinov1beta1.GroupVersion.WithResource("authorinos")
KuadrantsResource = GroupVersion.WithResource("kuadrants")
LimitadorsResource = limitadorv1alpha1.GroupVersion.WithResource("limitadors")
KuadrantsResource = GroupVersion.WithResource("kuadrants")
LimitadorsResource = limitadorv1alpha1.GroupVersion.WithResource("limitadors")
AuthorinosResource = authorinooperatorv1beta1.GroupVersion.WithResource("authorinos")
AuthConfigsResource = authorinov1beta2.GroupVersion.WithResource("authconfigs")

AuthConfigHTTPRouteRuleAnnotation = machinery.HTTPRouteRuleGroupKind.String()
)

var _ machinery.Object = &Kuadrant{}
Expand All @@ -31,7 +36,7 @@ func LinkKuadrantToGatewayClasses(objs controller.Store) machinery.LinkFunc {

return machinery.LinkFunc{
From: KuadrantGroupKind,
To: schema.GroupKind{Group: gwapiv1.GroupVersion.Group, Kind: "GatewayClass"},
To: schema.GroupKind{Group: gatewayapiv1.GroupVersion.Group, Kind: "GatewayClass"},
Func: func(_ machinery.Object) []machinery.Object {
parents := make([]machinery.Object, len(kuadrants))
for _, parent := range kuadrants {
Expand Down Expand Up @@ -69,3 +74,22 @@ func LinkKuadrantToAuthorino(objs controller.Store) machinery.LinkFunc {
},
}
}

func LinkHTTPRouteRuleToAuthConfig(objs controller.Store) machinery.LinkFunc {
httpRoutes := lo.Map(objs.FilterByGroupKind(machinery.HTTPRouteGroupKind), controller.ObjectAs[*gatewayapiv1.HTTPRoute])
httpRouteRules := lo.FlatMap(lo.Map(httpRoutes, func(r *gatewayapiv1.HTTPRoute, _ int) *machinery.HTTPRoute {
return &machinery.HTTPRoute{HTTPRoute: r}
}), machinery.HTTPRouteRulesFromHTTPRouteFunc)

return machinery.LinkFunc{
From: machinery.HTTPRouteRuleGroupKind,
To: AuthConfigGroupKind,
Func: func(child machinery.Object) []machinery.Object {
return lo.FilterMap(httpRouteRules, func(httpRouteRule *machinery.HTTPRouteRule, _ int) (machinery.Object, bool) {
authConfig := child.(*controller.RuntimeObject).Object.(*authorinov1beta2.AuthConfig)
annotations := authConfig.GetAnnotations()
return httpRouteRule, annotations != nil && annotations[AuthConfigHTTPRouteRuleAnnotation] == httpRouteRule.GetLocator()
})

Check warning on line 92 in api/v1beta1/topology.go

View check run for this annotation

Codecov / codecov/patch

api/v1beta1/topology.go#L88-L92

Added lines #L88 - L92 were not covered by tests
},
}
}
42 changes: 42 additions & 0 deletions api/v1beta3/authpolicy_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (
"github.com/go-logr/logr"
"github.com/google/go-cmp/cmp"
authorinov1beta2 "github.com/kuadrant/authorino/api/v1beta2"
"github.com/samber/lo"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime/schema"
gatewayapiv1 "sigs.k8s.io/gateway-api/apis/v1"
Expand Down Expand Up @@ -489,6 +490,39 @@ func (r *MergeablePatternExpressionOrRef) WithSource(source string) kuadrantv1.M
r.Source = source
return r

Check warning on line 491 in api/v1beta3/authpolicy_types.go

View check run for this annotation

Codecov / codecov/patch

api/v1beta3/authpolicy_types.go#L487-L491

Added lines #L487 - L491 were not covered by tests
}
func (r *MergeablePatternExpressionOrRef) ToWhenConditions(namedPatterns map[string]MergeablePatternExpressions) []WhenCondition {
if ref := r.PatternRef.Name; ref != "" {
if pattern, ok := namedPatterns[ref]; ok {
return lo.Map(pattern.PatternExpressions, func(p authorinov1beta2.PatternExpression, _ int) WhenCondition {
return WhenCondition{
Selector: ContextSelector(p.Selector),
Operator: WhenConditionOperator(p.Operator),
Value: p.Value,
}
})

Check warning on line 502 in api/v1beta3/authpolicy_types.go

View check run for this annotation

Codecov / codecov/patch

api/v1beta3/authpolicy_types.go#L493-L502

Added lines #L493 - L502 were not covered by tests
}
}

if allOf := r.All; len(allOf) > 0 {
return lo.Map(allOf, func(p authorinov1beta2.UnstructuredPatternExpressionOrRef, _ int) WhenCondition {
return WhenCondition{
Selector: ContextSelector(p.Selector),
Operator: WhenConditionOperator(p.Operator),
Value: p.Value,
}
})

Check warning on line 513 in api/v1beta3/authpolicy_types.go

View check run for this annotation

Codecov / codecov/patch

api/v1beta3/authpolicy_types.go#L506-L513

Added lines #L506 - L513 were not covered by tests
}

// FIXME: anyOf cannot be represented in the current schema of the wasm config

return []WhenCondition{
{
Selector: ContextSelector(r.Selector),
Operator: WhenConditionOperator(r.Operator),
Value: r.Value,
},
}

Check warning on line 524 in api/v1beta3/authpolicy_types.go

View check run for this annotation

Codecov / codecov/patch

api/v1beta3/authpolicy_types.go#L518-L524

Added lines #L518 - L524 were not covered by tests
}

type MergeableAuthenticationSpec struct {
authorinov1beta2.AuthenticationSpec `json:",inline"`
Expand All @@ -501,6 +535,14 @@ func (r *MergeableAuthenticationSpec) WithSource(source string) kuadrantv1.Merge
r.Source = source
return r

Check warning on line 536 in api/v1beta3/authpolicy_types.go

View check run for this annotation

Codecov / codecov/patch

api/v1beta3/authpolicy_types.go#L532-L536

Added lines #L532 - L536 were not covered by tests
}
func (r *MergeableAuthenticationSpec) UnmarshalJSON(j []byte) error {
spec := authorinov1beta2.AuthenticationSpec{}
if err := json.Unmarshal(j, &spec); err != nil {
return err
}
r.AuthenticationSpec = spec
return nil

Check warning on line 544 in api/v1beta3/authpolicy_types.go

View check run for this annotation

Codecov / codecov/patch

api/v1beta3/authpolicy_types.go#L538-L544

Added lines #L538 - L544 were not covered by tests
}

type MergeableMetadataSpec struct {
authorinov1beta2.MetadataSpec `json:",inline"`
Expand Down
60 changes: 60 additions & 0 deletions controllers/auth_policies_validator.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package controllers

import (
"context"
"sync"

"github.com/kuadrant/policy-machinery/controller"
"github.com/kuadrant/policy-machinery/machinery"
"github.com/samber/lo"
apierrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/utils/ptr"

kuadrantv1beta3 "github.com/kuadrant/kuadrant-operator/api/v1beta3"
kuadrant "github.com/kuadrant/kuadrant-operator/pkg/library/kuadrant"
)

type AuthPolicyValidator struct{}

// AuthPolicyValidator subscribes to events with potential to flip the validity of auth policies
func (r *AuthPolicyValidator) Subscription() controller.Subscription {
return controller.Subscription{
ReconcileFunc: r.Validate,
Events: []controller.ResourceEventMatcher{
{Kind: &machinery.GatewayGroupKind},
{Kind: &machinery.HTTPRouteGroupKind},
{Kind: &kuadrantv1beta3.AuthPolicyGroupKind, EventType: ptr.To(controller.CreateEvent)},
{Kind: &kuadrantv1beta3.AuthPolicyGroupKind, EventType: ptr.To(controller.UpdateEvent)},
},
}
}

func (r *AuthPolicyValidator) Validate(ctx context.Context, _ []controller.ResourceEvent, topology *machinery.Topology, _ error, state *sync.Map) error {
logger := controller.LoggerFromContext(ctx).WithName("AuthPolicyValidator")

policies := topology.Policies().Items(func(o machinery.Object) bool {
return o.GroupVersionKind().GroupKind() == kuadrantv1beta3.AuthPolicyGroupKind
})

logger.V(1).Info("validating auth policies", "policies", len(policies))
defer logger.V(1).Info("finished validating auth policies")

state.Store(StateAuthPolicyValid, lo.SliceToMap(policies, func(policy machinery.Policy) (string, error) {
var err error
if len(policy.GetTargetRefs()) > 0 && len(topology.Targetables().Children(policy)) == 0 {
ref := policy.GetTargetRefs()[0]
var res schema.GroupResource
switch ref.GroupVersionKind().Kind {
case machinery.GatewayGroupKind.Kind:
res = controller.GatewaysResource.GroupResource()
case machinery.HTTPRouteGroupKind.Kind:
res = controller.HTTPRoutesResource.GroupResource()

Check warning on line 52 in controllers/auth_policies_validator.go

View check run for this annotation

Codecov / codecov/patch

controllers/auth_policies_validator.go#L44-L52

Added lines #L44 - L52 were not covered by tests
}
err = kuadrant.NewErrPolicyTargetNotFound(kuadrantv1beta3.AuthPolicyGroupKind.Kind, ref, apierrors.NewNotFound(res, ref.GetName()))

Check warning on line 54 in controllers/auth_policies_validator.go

View check run for this annotation

Codecov / codecov/patch

controllers/auth_policies_validator.go#L54

Added line #L54 was not covered by tests
}
return policy.GetLocator(), err

Check warning on line 56 in controllers/auth_policies_validator.go

View check run for this annotation

Codecov / codecov/patch

controllers/auth_policies_validator.go#L56

Added line #L56 was not covered by tests
}))

return nil
}
Loading

0 comments on commit bc688df

Please sign in to comment.