Skip to content

Commit

Permalink
Merge pull request #225 from coreydaley/cleanup_go_mod_tidy
Browse files Browse the repository at this point in the history
Cleaning up some leftover packages
  • Loading branch information
openshift-merge-robot authored and candita committed Jul 1, 2021
2 parents 2b2689b + 8edef97 commit c519107
Show file tree
Hide file tree
Showing 55 changed files with 5,251 additions and 1,055 deletions.
3 changes: 3 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ require (
k8s.io/code-generator v0.21.1
k8s.io/component-base v0.21.0
k8s.io/component-helpers v0.21.0
k8s.io/klog v1.0.0
k8s.io/klog/v2 v2.8.0
k8s.io/kube-aggregator v0.21.0
k8s.io/kube-openapi v0.0.0-20210305001622-591a79e4bda7
Expand Down Expand Up @@ -78,3 +79,5 @@ replace (
k8s.io/mount-utils => k8s.io/mount-utils v0.21.0
k8s.io/sample-apiserver => k8s.io/sample-apiserver v0.21.0
)

replace github.com/openshift/api => github.com/candita/api v0.0.0-20210625204430-e467f417c5b3
14 changes: 2 additions & 12 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,8 @@ github.com/blang/semver v3.5.1+incompatible h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdn
github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps=
github.com/caddyserver/caddy v1.0.3/go.mod h1:G+ouvOY32gENkJC+jhgl62TyhvqEsFaDiZ4uw0RzP1E=
github.com/candita/api v0.0.0-20210625204430-e467f417c5b3 h1:qHQhdAnMtJ531zm2Hd4SOnQf3J4PA6SGiflowbVf8KM=
github.com/candita/api v0.0.0-20210625204430-e467f417c5b3/go.mod h1:izBmoXbUu3z5kUa4FjZhvekTsyzIWiOoaIgJiZBBMQs=
github.com/cenkalti/backoff v2.1.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
Expand Down Expand Up @@ -140,8 +142,6 @@ github.com/coreos/go-systemd/v22 v22.1.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+
github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f h1:lBNOc5arjvs8E5mO2tbpBpLoyyu8B6e44T7hJy6potg=
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
github.com/coreydaley/api v0.0.0-20210611190050-d0f48cbf0ba3 h1:baI2LyZ7k/5h2GhUUqsbkNb3a/cz1yPa1lebaVugobA=
github.com/coreydaley/api v0.0.0-20210611190050-d0f48cbf0ba3/go.mod h1:izBmoXbUu3z5kUa4FjZhvekTsyzIWiOoaIgJiZBBMQs=
github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
Expand Down Expand Up @@ -526,16 +526,6 @@ github.com/opencontainers/runc v1.0.0-rc93/go.mod h1:3NOsor4w32B2tC0Zbl8Knk4Wg84
github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
github.com/opencontainers/runtime-spec v1.0.3-0.20200929063507-e6143ca7d51d/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
github.com/opencontainers/selinux v1.8.0/go.mod h1:RScLhm78qiWa2gbVCcGkC7tCGdgk3ogry1nUQF8Evvo=
github.com/openshift/api v0.0.0-20210331162552-3e31249e6a55/go.mod h1:dZ4kytOo3svxJHNYd0J55hwe/6IQG5gAUHUE0F3Jkio=
github.com/openshift/api v0.0.0-20210331193751-3acddb19d360/go.mod h1:dZ4kytOo3svxJHNYd0J55hwe/6IQG5gAUHUE0F3Jkio=
github.com/openshift/api v0.0.0-20210603185846-379093ab5d80 h1:CSaMNuLE1JbHMLbPilrrEIutoYXdFJFw452s9Jfe+hc=
github.com/openshift/api v0.0.0-20210603185846-379093ab5d80/go.mod h1:izBmoXbUu3z5kUa4FjZhvekTsyzIWiOoaIgJiZBBMQs=
github.com/openshift/api v0.0.0-20210617200138-9f677aa140c1 h1:qwYANvePJZhyBTFPn6kMPqyuPq4Zh8fmgWRtfOPLHgM=
github.com/openshift/api v0.0.0-20210617200138-9f677aa140c1/go.mod h1:izBmoXbUu3z5kUa4FjZhvekTsyzIWiOoaIgJiZBBMQs=
github.com/openshift/api v0.0.0-20210621070332-ea13be50ba2d h1:8+4jIjWRI2FUVq2REmv4XW3bD/Ty2pKIxbC6nGKo4ic=
github.com/openshift/api v0.0.0-20210621070332-ea13be50ba2d/go.mod h1:izBmoXbUu3z5kUa4FjZhvekTsyzIWiOoaIgJiZBBMQs=
github.com/openshift/api v0.0.0-20210624153211-ae79113891b0 h1:Wbo6MbFHqjoPNV5iSONP3VZV50RR6CS8MYoVHFlKIuQ=
github.com/openshift/api v0.0.0-20210624153211-ae79113891b0/go.mod h1:izBmoXbUu3z5kUa4FjZhvekTsyzIWiOoaIgJiZBBMQs=
github.com/openshift/apiserver-library-go v0.0.0-20210426120049-59b0e972bfb7 h1:eJDIx4xV8J+9Zg1W8UJPv5SME0pGNmXttWIUU5Fg6O4=
github.com/openshift/apiserver-library-go v0.0.0-20210426120049-59b0e972bfb7/go.mod h1:nqn2IWld2A+Q9Lp/xGsbmUr2RyDCQixRU83yqAbymUM=
github.com/openshift/build-machinery-go v0.0.0-20210209125900-0da259a2c359/go.mod h1:b1BuldmJlbA/xYtdZvKi+7j5YGB44qJUJDZ9zwiNCfE=
Expand Down
441 changes: 0 additions & 441 deletions hack/openapi-violation.list

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions pkg/cmd/openshift-apiserver/openshiftadmission/register.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
buildstrategyrestrictions "github.com/openshift/openshift-apiserver/pkg/build/apiserver/admission/strategyrestrictions"
imageadmission "github.com/openshift/openshift-apiserver/pkg/image/apiserver/admission/limitrange"
projectrequestlimit "github.com/openshift/openshift-apiserver/pkg/project/apiserver/admission/requestlimit"
requiredrouteannotations "github.com/openshift/openshift-apiserver/pkg/route/apiserver/admission/requiredrouteannotations"
)

// TODO register this per apiserver or at least per process
Expand All @@ -38,6 +39,7 @@ func RegisterOpenshiftAdmissionPlugins(plugins *admission.Plugins) {
imageadmission.Register(plugins)
imagepolicy.Register(plugins)
quotaclusterresourcequota.Register(plugins)
requiredrouteannotations.Register(plugins)
}

var (
Expand All @@ -54,6 +56,7 @@ var (
"image.openshift.io/ImageLimitRange",
"image.openshift.io/ImagePolicy",
"quota.openshift.io/ClusterResourceQuota",
"route.openshift.io/RequiredRouteAnnotations",

// the rest of the kube chain goes here
"MutatingAdmissionWebhook",
Expand Down
321 changes: 321 additions & 0 deletions pkg/route/apiserver/admission/requiredrouteannotations/admission.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,321 @@
package requiredrouteannotations

import (
"context"
"errors"
"fmt"
"io"
"regexp"
"strconv"
"strings"
"time"

corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/labels"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
"k8s.io/apiserver/pkg/admission"
"k8s.io/apiserver/pkg/admission/initializer"
"k8s.io/client-go/informers"
corev1listers "k8s.io/client-go/listers/core/v1"
"k8s.io/client-go/rest"
logger "k8s.io/klog/klogr"

configv1 "github.com/openshift/api/config/v1"
routev1 "github.com/openshift/api/route/v1"
configtypedclient "github.com/openshift/client-go/config/clientset/versioned/typed/config/v1"
routetypedclient "github.com/openshift/client-go/route/clientset/versioned/typed/route/v1"
"github.com/openshift/library-go/pkg/apiserver/admission/admissionrestconfig"
routeapi "github.com/openshift/openshift-apiserver/pkg/route/apis/route"
)

var Logger = logger.New()
var log = Logger.WithName("admission")

const (
pluginName = "route.openshift.io/RequiredRouteAnnotations"
timeToWaitForCacheSync = 10 * time.Second
)

func Register(plugins *admission.Plugins) {
plugins.Register(pluginName,
func(_ io.Reader) (admission.Interface, error) {
return NewRequiredRouteAnnotations()
})
}

type requiredRouteAnnotations struct {
*admission.Handler
routeClient routetypedclient.RoutesGetter
configClient configtypedclient.IngressesGetter
nsLister corev1listers.NamespaceLister
nsListerSynced func() bool
}

// Ensure that the required OpenShift admission interfaces are implemented.
var _ = initializer.WantsExternalKubeInformerFactory(&requiredRouteAnnotations{})
var _ = admissionrestconfig.WantsRESTClientConfig(&requiredRouteAnnotations{})
var _ = admission.ValidationInterface(&requiredRouteAnnotations{})

const hstsAnnotation = "haproxy.router.openshift.io/hsts_header"

// Validate ensures that routes specify required annotations, and returns nil if valid.
func (o *requiredRouteAnnotations) Validate(ctx context.Context, a admission.Attributes, _ admission.ObjectInterfaces) (err error) {
if a.GetResource().GroupResource() != routev1.Resource("routes") {
return nil
}
if _, isRoute := a.GetObject().(*routeapi.Route); !isRoute {
return nil
}

if !o.waitForSyncedStore(time.After(timeToWaitForCacheSync)) {
return admission.NewForbidden(a, errors.New(pluginName+": caches not synchronized"))
}

ingress, err := o.configClient.Ingresses().Get(ctx, "cluster", metav1.GetOptions{})
if err != nil {
return admission.NewForbidden(a, err)
}

newRoute := a.GetObject().(*routeapi.Route)
if old := a.GetOldObject(); old != nil {
oldRoute := old.(*routeapi.Route)
// if this is an update and the annotation in question is the same, then we know the update will be allowed
if a.GetOperation() == admission.Update && newRoute.Annotations[hstsAnnotation] == oldRoute.Annotations[hstsAnnotation] {
return nil
}
}

namespace, err := o.nsLister.Get(newRoute.Namespace)
if err != nil {
return admission.NewForbidden(a, err)
}

if err = isRouteHSTSAllowed(ingress, newRoute, namespace); err != nil {
return admission.NewForbidden(a, err)
}
return nil
}

func (o *requiredRouteAnnotations) SetRESTClientConfig(restClientConfig rest.Config) {
var err error
// TODO: Use an informer for config.
o.configClient, err = configtypedclient.NewForConfig(&restClientConfig)
if err != nil {
utilruntime.HandleError(err)
return
}
o.routeClient, err = routetypedclient.NewForConfig(&restClientConfig)
if err != nil {
utilruntime.HandleError(err)
return
}
}

func (o *requiredRouteAnnotations) SetExternalKubeInformerFactory(kubeInformers informers.SharedInformerFactory) {
o.nsLister = kubeInformers.Core().V1().Namespaces().Lister()
o.nsListerSynced = kubeInformers.Core().V1().Namespaces().Informer().HasSynced
}

func (o *requiredRouteAnnotations) waitForSyncedStore(timeout <-chan time.Time) bool {
for !o.nsListerSynced() {
select {
case <-time.After(100 * time.Millisecond):
case <-timeout:
return o.nsListerSynced()
}
}

return true
}

func (o *requiredRouteAnnotations) ValidateInitialization() error {
if o.configClient == nil {
return fmt.Errorf(pluginName + " plugin needs a config client")
}
if o.routeClient == nil {
return fmt.Errorf(pluginName + " plugin needs a route client")
}
if o.nsLister == nil {
return fmt.Errorf(pluginName + " plugin needs a namespace lister")
}
if o.nsListerSynced == nil {
return fmt.Errorf(pluginName + " plugin needs a namespace lister synced")
}
return nil
}

func NewRequiredRouteAnnotations() (admission.Interface, error) {
return &requiredRouteAnnotations{
Handler: admission.NewHandler(admission.Create, admission.Update),
}, nil
}

// isRouteHSTSAllowed returns nil if the route is allowed. Otherwise, returns details and a suggestion in the error
func isRouteHSTSAllowed(ingress *configv1.Ingress, newRoute *routeapi.Route, namespace *corev1.Namespace) error {
// Invalid if a HSTS Policy is specified but this route is not TLS. Just log a warning.
if tls := newRoute.Spec.TLS; tls != nil {
switch termination := tls.Termination; termination {
case routeapi.TLSTerminationEdge, routeapi.TLSTerminationReencrypt:
// Valid case
default:
// Non-tls routes will not get HSTS headers, but can still be valid
log.Info("HSTS Policy not accepted for %s, termination type: %s", newRoute.Name, termination)
return nil
}
} else {
return fmt.Errorf("termination type is empty, must be %s or %s", routev1.TLSTerminationEdge, routev1.TLSTerminationReencrypt)
}

requirements := ingress.Spec.RequiredHSTSPolicies
for _, requirement := range requirements {
if matches, err := requiredHSTSMatchesRoute(requirement, newRoute, namespace); err != nil {
return err
} else if !matches {
continue
}

routeHSTS, err := hstsConfigFromRoute(newRoute)
if err != nil {
return err
}

requirementErr := routeHSTS.meetsRequirements(requirement)
if requirementErr != nil {
return requirementErr
}
// Validation only checks the first matching required HSTS rule.
return nil
}

// None of the requirements matched this route's domain/namespace, it is automatically allowed
return nil
}

type hstsConfig struct {
maxAge int32
preload bool
includeSubDomains bool
}

// Parse out the hstsConfig fields from the annotation
func hstsConfigFromRoute(route *routeapi.Route) (hstsConfig, error) {
ret := hstsConfig{}
ret.maxAge = -1
tokens := strings.Split(route.Annotations[hstsAnnotation], ";")
for _, token := range tokens {
trimmed := strings.Trim(token, " ")
if strings.EqualFold(trimmed, "includeSubDomains") {
ret.includeSubDomains = true
}
if strings.EqualFold(trimmed, "preload") {
ret.preload = true
}
if strings.HasPrefix(strings.ToLower(trimmed), "max-age=") {
age, err := strconv.ParseInt(trimmed[len("max-age="):], 10, 32)
if err != nil {
return hstsConfig{}, err
}
ret.maxAge = int32(age)
}
// unrecognized tokens are ignored
}

return ret, nil
}

// Make sure the given requirement meets the configured HSTS policy, validating:
// - existence and range for maxAge
// - preloadPolicy
// - includeSubDomainsPolicy
func (c hstsConfig) meetsRequirements(requirement configv1.RequiredHSTSPolicy) error {
configHasMaxAge := c.maxAge >= 0
if !configHasMaxAge {
return fmt.Errorf("max age is required")
}
if requirement.MaxAge.LargestMaxAge >= 0 && c.maxAge > requirement.MaxAge.LargestMaxAge {
return fmt.Errorf("does not match maximum age %d", requirement.MaxAge.LargestMaxAge)
}
if requirement.MaxAge.SmallestMaxAge >= 0 && c.maxAge < requirement.MaxAge.SmallestMaxAge {
return fmt.Errorf("does not match minimum age %d", requirement.MaxAge.SmallestMaxAge)
}

switch requirement.PreloadPolicy {
case configv1.DefaultPreloadPolicy, configv1.NoOpinionPreloadPolicy:
// anything is allowed, do nothing
case configv1.RequirePreloadPolicy:
if !c.preload {
return fmt.Errorf("preload must be specified")
}
case configv1.RequireNoPreloadPolicy:
if c.preload {
return fmt.Errorf("preload must not be specified")
}
}

switch requirement.IncludeSubDomainsPolicy {
case configv1.DefaultIncludeSubDomains, configv1.NoOpinionIncludeSubDomains:
// anything is allowed, do nothing
case configv1.RequireIncludeSubDomains:
if !c.includeSubDomains {
return fmt.Errorf("includeSubDomains must be specified")
}
case configv1.RequireNotIncludeSubDomains:
if c.includeSubDomains {
return fmt.Errorf("includeSubDomains must not be specified")
}
}

return nil
}

// Check if the route matches the required domain/namespace in the HSTS Policy
func requiredHSTSMatchesRoute(requirement configv1.RequiredHSTSPolicy, route *routeapi.Route, namespace *corev1.Namespace) (bool, error) {
matchesNamespace, err := matchesNamespaceSelector(requirement.NamespaceSelector, namespace)
if err != nil {
return false, err
}
if !matchesNamespace {
return false, nil
}
routeDomains := []string{route.Spec.Host}
for _, ingress := range route.Status.Ingress {
routeDomains = append(routeDomains, ingress.Host)
}
if matchesDomain(requirement.DomainPatterns, routeDomains) {
return true, nil
}

return false, nil
}

// Check all of the required domainMatcher patterns against all provided domains,
// first match returns true. If none match, return false.
func matchesDomain(domainMatchers []string, domains []string) bool {
for _, matcher := range domainMatchers {
match := regexp.MustCompile(fmt.Sprintf("^%s$", matcher))
for _, candidate := range domains {
if match.MatchString(candidate) {
return true
}
}
}

return false
}

func matchesNamespaceSelector(nsSelector *metav1.LabelSelector, namespace *corev1.Namespace) (bool, error) {
if nsSelector == nil {
return true, nil
}
selector, err := getParsedNamespaceSelector(nsSelector)
if err != nil {
return false, err
}
return selector.Matches(labels.Set(namespace.Labels)), nil
}

func getParsedNamespaceSelector(nsSelector *metav1.LabelSelector) (labels.Selector, error) {
// TODO cache this result to save time
return metav1.LabelSelectorAsSelector(nsSelector)
}
Loading

0 comments on commit c519107

Please sign in to comment.