Skip to content

Commit

Permalink
UPSTREAM: <carry>: Add RouteExternalCertificate validation in Route O…
Browse files Browse the repository at this point in the history
…bjectValidator

Co-authored-by: Thejas N <thn@redhat.com>
Signed-off-by: Swarup Ghosh <swghosh@redhat.com>
  • Loading branch information
Thejas N authored and dinhxuanvu committed Apr 15, 2024
1 parent 47d3e19 commit 2a676ab
Show file tree
Hide file tree
Showing 4 changed files with 149 additions and 16 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,26 +6,20 @@ import (
"io"

"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/util/validation/field"
"k8s.io/apiserver/pkg/admission"
authorizationv1client "k8s.io/client-go/kubernetes/typed/authorization/v1"
corev1client "k8s.io/client-go/kubernetes/typed/core/v1"

routev1 "github.com/openshift/api/route/v1"
routevalidation "github.com/openshift/library-go/pkg/route/validation"
"k8s.io/kubernetes/openshift-kube-apiserver/admission/customresourcevalidation"
)

const PluginName = "route.openshift.io/ValidateRoute"

func Register(plugins *admission.Plugins) {
plugins.Register(PluginName, func(config io.Reader) (admission.Interface, error) {
return customresourcevalidation.NewValidator(
map[schema.GroupResource]bool{
{Group: routev1.GroupName, Resource: "routes"}: true,
},
map[schema.GroupVersionKind]customresourcevalidation.ObjectValidator{
routev1.GroupVersion.WithKind("Route"): routeV1{},
})
return NewValidateRoute()
})
}

Expand All @@ -46,18 +40,21 @@ func toRoute(uncastObj runtime.Object) (*routev1.Route, field.ErrorList) {
}

type routeV1 struct {
secretsGetter corev1client.SecretsGetter
sarGetter authorizationv1client.SubjectAccessReviewsGetter
routeValidationOptsGetter RouteValidationOptionGetter
}

func (routeV1) ValidateCreate(_ context.Context, obj runtime.Object) field.ErrorList {
func (r routeV1) ValidateCreate(ctx context.Context, obj runtime.Object) field.ErrorList {
routeObj, errs := toRoute(obj)
if len(errs) > 0 {
return errs
}

return routevalidation.ValidateRoute(routeObj)
return routevalidation.ValidateRoute(ctx, routeObj, r.sarGetter.SubjectAccessReviews(), r.secretsGetter, r.routeValidationOptsGetter.GetValidationOptions())
}

func (routeV1) ValidateUpdate(_ context.Context, obj runtime.Object, oldObj runtime.Object) field.ErrorList {
func (r routeV1) ValidateUpdate(ctx context.Context, obj runtime.Object, oldObj runtime.Object) field.ErrorList {
routeObj, errs := toRoute(obj)
if len(errs) > 0 {
return errs
Expand All @@ -68,10 +65,10 @@ func (routeV1) ValidateUpdate(_ context.Context, obj runtime.Object, oldObj runt
return errs
}

return routevalidation.ValidateRouteUpdate(routeObj, routeOldObj)
return routevalidation.ValidateRouteUpdate(ctx, routeObj, routeOldObj, r.sarGetter.SubjectAccessReviews(), r.secretsGetter, r.routeValidationOptsGetter.GetValidationOptions())
}

func (c routeV1) ValidateStatusUpdate(_ context.Context, obj runtime.Object, oldObj runtime.Object) field.ErrorList {
func (routeV1) ValidateStatusUpdate(_ context.Context, obj runtime.Object, oldObj runtime.Object) field.ErrorList {
routeObj, errs := toRoute(obj)
if len(errs) > 0 {
return errs
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package route

import (
"k8s.io/apiserver/pkg/util/feature"
"k8s.io/component-base/featuregate"

configv1 "github.com/openshift/api/config/v1"
routecommon "github.com/openshift/library-go/pkg/route"
)

type RouteValidationOptionGetter interface {
GetValidationOptions() routecommon.RouteValidationOptions
}

type RouteValidationOpts struct {
opts routecommon.RouteValidationOptions
}

var _ RouteValidationOptionGetter = &RouteValidationOpts{}

func NewRouteValidationOpts() *RouteValidationOpts {
return &RouteValidationOpts{}
}

func (o *RouteValidationOpts) GetValidationOptions() routecommon.RouteValidationOptions {
return o.opts
}

func (o *RouteValidationOpts) Initialize() *RouteValidationOpts {
o.opts = routecommon.RouteValidationOptions{
AllowExternalCertificates: feature.DefaultMutableFeatureGate.Enabled(featuregate.Feature(configv1.FeatureGateRouteExternalCertificate)),
}

return o
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
package route

import (
"fmt"

routev1 "github.com/openshift/api/route/v1"
"github.com/openshift/library-go/pkg/apiserver/admission/admissionrestconfig"
authorizationv1client "k8s.io/client-go/kubernetes/typed/authorization/v1"
corev1client "k8s.io/client-go/kubernetes/typed/core/v1"

"k8s.io/apimachinery/pkg/runtime/schema"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
"k8s.io/apiserver/pkg/admission"
"k8s.io/client-go/rest"
"k8s.io/kubernetes/openshift-kube-apiserver/admission/customresourcevalidation"
)

type validateCustomResourceWithClient struct {
admission.ValidationInterface

secretsGetter corev1client.SecretsGetter
sarGetter authorizationv1client.SubjectAccessReviewsGetter
routeValidationOptsGetter RouteValidationOptionGetter
}

func NewValidateRoute() (admission.Interface, error) {
ret := &validateCustomResourceWithClient{}

delegate, err := customresourcevalidation.NewValidator(
map[schema.GroupResource]bool{
routev1.GroupVersion.WithResource("routes").GroupResource(): true,
},
map[schema.GroupVersionKind]customresourcevalidation.ObjectValidator{
routev1.GroupVersion.WithKind("Route"): routeV1{
secretsGetter: ret.getSecretsGetter(),
sarGetter: ret.getSubjectAccessReviewsGetter(),
routeValidationOptsGetter: ret.getRouteValidationOptions(),
},
})
if err != nil {
return nil, err
}
ret.ValidationInterface = delegate

return ret, nil
}

var _ admissionrestconfig.WantsRESTClientConfig = &validateCustomResourceWithClient{}

func (a *validateCustomResourceWithClient) getSecretsGetter() corev1client.SecretsGetter {
return a.secretsGetter
}

func (a *validateCustomResourceWithClient) getSubjectAccessReviewsGetter() authorizationv1client.SubjectAccessReviewsGetter {
return a.sarGetter
}

func (a *validateCustomResourceWithClient) getRouteValidationOptions() RouteValidationOptionGetter {
return a.routeValidationOptsGetter
}

func (a *validateCustomResourceWithClient) SetRESTClientConfig(restClientConfig rest.Config) {
var err error

a.secretsGetter, err = corev1client.NewForConfig(&restClientConfig)
if err != nil {
utilruntime.HandleError(err)
return
}

a.sarGetter, err = authorizationv1client.NewForConfig(&restClientConfig)
if err != nil {
utilruntime.HandleError(err)
return
}

a.routeValidationOptsGetter = NewRouteValidationOpts().Initialize()
}

func (a *validateCustomResourceWithClient) ValidateInitialization() error {
if a.secretsGetter == nil {
return fmt.Errorf("%s needs a secretsGetter", PluginName)
}
if a.sarGetter == nil {
return fmt.Errorf("%s needs a subjectAccessReviewsGetter", PluginName)
}
if a.routeValidationOptsGetter == nil {
return fmt.Errorf("%s needs a routeValidationOptsGetter", PluginName)
}

initializationValidator, ok := a.ValidationInterface.(admission.InitializationValidator)
if !ok {
return fmt.Errorf("%s InitializationValidator type check for ValidationInterface failed", PluginName)
}

return initializationValidator.ValidateInitialization()
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@ import (

routev1 "github.com/openshift/api/route/v1"
"github.com/openshift/library-go/pkg/config/helpers"
routecommon "github.com/openshift/library-go/pkg/route"
"github.com/openshift/library-go/pkg/route/hostassignment"
"k8s.io/kubernetes/openshift-kube-apiserver/admission/customresourcevalidation/route"
hostassignmentapi "k8s.io/kubernetes/openshift-kube-apiserver/admission/route/apis/hostassignment"
hostassignmentv1 "k8s.io/kubernetes/openshift-kube-apiserver/admission/route/apis/hostassignment/v1"
)
Expand All @@ -38,6 +40,7 @@ type hostAssignment struct {

hostnameGenerator hostassignment.HostnameGenerator
sarClient authorizationv1.SubjectAccessReviewInterface
validationOpts routecommon.RouteValidationOptions
}

func readConfig(reader io.Reader) (*hostassignmentapi.HostAssignmentAdmissionConfig, error) {
Expand Down Expand Up @@ -112,7 +115,7 @@ func (a *hostAssignment) Admit(ctx context.Context, attributes admission.Attribu
if len(errs) > 0 {
return errors.NewInvalid(attributes.GetKind().GroupKind(), attributes.GetName(), errs)
}
errs = hostassignment.AllocateHost(ctx, r, a.sarClient, a.hostnameGenerator)
errs = hostassignment.AllocateHost(ctx, r, a.sarClient, a.hostnameGenerator, a.validationOpts)
if len(errs) > 0 {
return errors.NewInvalid(attributes.GetKind().GroupKind(), attributes.GetName(), errs)
}
Expand All @@ -132,7 +135,7 @@ func (a *hostAssignment) Admit(ctx context.Context, attributes admission.Attribu
if len(errs) > 0 {
return errors.NewInvalid(attributes.GetKind().GroupKind(), attributes.GetName(), errs)
}
errs = hostassignment.ValidateHostUpdate(ctx, r, old, a.sarClient)
errs = hostassignment.ValidateHostUpdate(ctx, r, old, a.sarClient, a.validationOpts)
if len(errs) > 0 {
return errors.NewInvalid(attributes.GetKind().GroupKind(), attributes.GetName(), errs)
}
Expand All @@ -147,6 +150,7 @@ var _ initializer.WantsExternalKubeClientSet = &hostAssignment{}

func (a *hostAssignment) SetExternalKubeClientSet(clientset kubernetes.Interface) {
a.sarClient = clientset.AuthorizationV1().SubjectAccessReviews()
a.validationOpts = route.NewRouteValidationOpts().Initialize().GetValidationOptions()
}

func (a *hostAssignment) ValidateInitialization() error {
Expand Down

0 comments on commit 2a676ab

Please sign in to comment.