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

Bug 1986408: NE-310 HSTS Route Admission Plugin #224

Merged
merged 2 commits into from
Jul 28, 2021

Conversation

candita
Copy link
Contributor

@candita candita commented Jun 29, 2021

Administrators who are tasked with route management and/or regulatory compliance face a number of issues with regard to enforcing HSTS. For efficiency and protection against configuration errors, they have requested to automatically and globally enable HSTS on the basis of the cluster Ingress domains. However, because enabling HSTS automatically and globally can cause disruption of service on a wide scale, they should also be able to audit and change HSTS configuration without further outages. Finally, they should be able to consistently apply the same HSTS configuration and predict the outcome on any cluster.

  • Register a new plugin route.openshift.io/RequiredRouteAnnotations
  • Add a new admissions package called requiredrouteannotations, with methods to validate route annotation configuration
  • Add unit tests

Enhancement proposal: openshift/enhancements#749

@openshift-ci openshift-ci bot added do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. labels Jun 29, 2021
@openshift-ci openshift-ci bot requested review from knobunc and sttts June 29, 2021 00:48
@openshift-ci openshift-ci bot removed the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Jun 29, 2021
@candita
Copy link
Contributor Author

candita commented Jun 29, 2021

/test verify

@candita
Copy link
Contributor Author

candita commented Jun 29, 2021

/test verify

@candita candita force-pushed the NE-310-HSTS branch 3 times, most recently from c519107 to 4c2a30e Compare July 2, 2021 22:14
@candita candita force-pushed the NE-310-HSTS branch 3 times, most recently from b04f2d4 to 99a1e68 Compare July 3, 2021 01:32
@candita candita force-pushed the NE-310-HSTS branch 2 times, most recently from f086f86 to 75c9f66 Compare July 12, 2021 22:12
@openshift-ci openshift-ci bot added the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Jul 12, 2021
@candita candita force-pushed the NE-310-HSTS branch 2 times, most recently from 563caf7 to 565807d Compare July 12, 2021 22:45
@openshift-ci openshift-ci bot removed the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Jul 12, 2021
@candita candita force-pushed the NE-310-HSTS branch 2 times, most recently from 73ec38b to 37689fc Compare July 13, 2021 17:46
@openshift-ci openshift-ci bot added the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Jul 13, 2021
@candita candita force-pushed the NE-310-HSTS branch 2 times, most recently from 3d1e059 to cb5076d Compare July 13, 2021 19:33
@openshift-ci openshift-ci bot removed the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Jul 13, 2021
if synced := o.waitForSyncedStore(ctx); !synced {
return admission.NewForbidden(a, errors.New(pluginName+": caches not synchronized"))
}
o.cachesSynced = true
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this races

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

needs locking or an atomic datatype

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Discussed with @sanchezl - removing the boolean, and now checking every time.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could do the following:

diff --git a/pkg/route/apiserver/admission/requiredrouteannotations/admission.go b/pkg/route/apiserver/admission/requiredrouteannotations/admission.go
index f6b2f9279..268ab3fb0 100644
--- a/pkg/route/apiserver/admission/requiredrouteannotations/admission.go
+++ b/pkg/route/apiserver/admission/requiredrouteannotations/admission.go
@@ -9,6 +9,7 @@ import (
 	"regexp"
 	"strconv"
 	"strings"
+	"sync"
 	"time"
 
 	corev1 "k8s.io/api/core/v1"
@@ -50,7 +51,7 @@ type requiredRouteAnnotations struct {
 	routeLister   routev1listers.RouteLister
 	nsLister      corev1listers.NamespaceLister
 	ingressLister configv1listers.IngressLister
-	cachesSynced  bool
+	cachesSynced  cacheSync
 	cachesToSync  []cache.InformerSynced
 }
 
@@ -62,6 +63,24 @@ var _ = openshiftapiserveradmission.WantsOpenShiftRouteInformers(&requiredRouteA
 
 var maxAgeRegExp = regexp.MustCompile(`max-age=(\d+)`)
 
+type cacheSync struct {
+	readMu    sync.RWMutex
+	writeMu   sync.RWMutex
+	hasSynced bool
+}
+
+func (cs *cacheSync) HasSycned() bool {
+	cs.readMu.Lock()
+	defer cs.readMu.Unlock()
+	return cs.hasSynced
+}
+
+func (cs *cacheSync) SetSynced() {
+	cs.writeMu.Lock()
+	cs.hasSynced = true
+	cs.writeMu.Unlock()
+}
+
 // Validate ensures that routes specify required annotations, and returns nil if valid.
 // The admission handler ensures this is only called for Create/Update operations.
 func (o *requiredRouteAnnotations) Validate(ctx context.Context, a admission.Attributes, _ admission.ObjectInterfaces) (err error) {
@@ -90,11 +109,11 @@ func (o *requiredRouteAnnotations) Validate(ctx context.Context, a admission.Att
 	}
 
 	// Wait up to 30 seconds for all caches to sync.  This is needed only once.
-	if !o.cachesSynced {
-		if synced := o.waitForSyncedStore(ctx); !synced {
+	if !o.cachesSynced.HasSycned() {
+		if !o.waitForSyncedStore(ctx) {
 			return admission.NewForbidden(a, errors.New(pluginName+": caches not synchronized"))
 		}
-		o.cachesSynced = true
+		o.cachesSynced.SetSynced()
 	}
 
 	ingress, err := o.ingressLister.Get("cluster")

or more discretely with locking on the read and write access. I tried to encapsulate here to avoid any mistakes.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixing my typo;

func (cs *cacheSync) HasSynced() bool {

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I made the funcs private and changed a few other minor things.

@candita
Copy link
Contributor Author

candita commented Jul 28, 2021

/test e2e-aws-upgrade

Copy link
Contributor

@sanchezl sanchezl left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

/lgtm
/retest

@openshift-ci openshift-ci bot added the lgtm Indicates that a PR is ready to be merged. label Jul 28, 2021
@frobware
Copy link
Contributor

@candita, @sttts mentioned to me that the we only have 30s for admission calls to complete so let's go for 20s on the sync. Sorry for the churn.

@openshift-ci openshift-ci bot removed the lgtm Indicates that a PR is ready to be merged. label Jul 28, 2021
@frobware
Copy link
Contributor

/lgtm

@openshift-ci openshift-ci bot added the lgtm Indicates that a PR is ready to be merged. label Jul 28, 2021
nsLister corev1listers.NamespaceLister
ingressLister configv1listers.IngressLister
cachesToSync []cache.InformerSynced
cacheSyncLock cacheSync
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
cacheSyncLock cacheSync
<empty line>
isSyncedLock sync.RWMutex
isSynced bool

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And delete the data type above

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

per our chat, this is a moot point

Comment on lines 113 to 114
if !o.cacheSyncLock.hasSynced() {
if !o.waitForSyncedStore(ctx) {
return admission.NewForbidden(a, errors.New(pluginName+": caches not synchronized"))
}
o.cacheSyncLock.setSynced()
}
Copy link
Contributor

@sttts sttts Jul 28, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if !o.cacheSyncLock.hasSynced() {
if !o.waitForSyncedStore(ctx) {
return admission.NewForbidden(a, errors.New(pluginName+": caches not synchronized"))
}
o.cacheSyncLock.setSynced()
}
if !o.waitForSyncedStore(ctx) {
return admission.NewForbidden(a, errors.New(pluginName+": caches not synchronized"))
}

Comment on lines 143 to 150
func (o *requiredRouteAnnotations) waitForSyncedStore(ctx context.Context) bool {
syncCtx, cancelFn := context.WithTimeout(ctx, timeToWaitForCacheSync)
defer cancelFn()
return cache.WaitForCacheSync(syncCtx.Done(), o.cachesToSync...)
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
func (o *requiredRouteAnnotations) waitForSyncedStore(ctx context.Context) bool {
syncCtx, cancelFn := context.WithTimeout(ctx, timeToWaitForCacheSync)
defer cancelFn()
return cache.WaitForCacheSync(syncCtx.Done(), o.cachesToSync...)
}
func (o *requiredRouteAnnotations) waitForSyncedStore(ctx context.Context) bool {
isSyncedLock.RLock()
defer isSyncedLock.RLock()
if o.isSynced {
return nil
}
syncCtx, cancelFn := context.WithTimeout(ctx, timeToWaitForCacheSync)
defer cancelFn()
err := cache.WaitForCacheSync(syncCtx.Done(), o.cachesToSync...)
if err != nil {
return err
}
o.isSyncedLock.Lock()
defer o.isSyncedLock.Unlock()
o.isSynced = true
return err
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I made a similar change, ptal and let me know if you approve by approving. :)

@openshift-ci openshift-ci bot removed the lgtm Indicates that a PR is ready to be merged. label Jul 28, 2021
// waitForSyncedStore calls cache.WaitForCacheSync, which will wait up to timeToWaitForCacheSync
// for the cachesToSync to synchronize.
func (o *requiredRouteAnnotations) waitForSyncedStore(ctx context.Context) bool {
syncCtx, cancelFn := context.WithTimeout(ctx, timeToWaitForCacheSync)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't know whether we're just endlessly bike shedding now, particularly if this is temporary and we're gravitating to a more general solution, but creating the context should move insider the if below. Is there any value in creating this each and every call?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will take this as a followup, per our discussion.

@frobware
Copy link
Contributor

/lgtm

@openshift-ci openshift-ci bot added the lgtm Indicates that a PR is ready to be merged. label Jul 28, 2021
@sttts
Copy link
Contributor

sttts commented Jul 28, 2021

/retest

@sttts
Copy link
Contributor

sttts commented Jul 28, 2021

/approve

@openshift-ci
Copy link
Contributor

openshift-ci bot commented Jul 28, 2021

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: candita, frobware, sanchezl, sttts

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@openshift-ci openshift-ci bot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Jul 28, 2021
@openshift-merge-robot openshift-merge-robot merged commit a127b27 into openshift:master Jul 28, 2021
@openshift-ci
Copy link
Contributor

openshift-ci bot commented Jul 28, 2021

@candita: All pull requests linked via external trackers have merged:

Bugzilla bug 1986408 has been moved to the MODIFIED state.

In response to this:

Bug 1986408: NE-310 HSTS Route Admission Plugin

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
approved Indicates a PR has been approved by an approver from all required OWNERS files. bugzilla/severity-high Referenced Bugzilla bug's severity is high for the branch this PR is targeting. bugzilla/valid-bug Indicates that a referenced Bugzilla bug is valid for the branch this PR is targeting. lgtm Indicates that a PR is ready to be merged.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants