Skip to content

Ignore errors caused by unkonwn scopes where it makes sense to do so.#20911

Merged
openshift-merge-robot merged 1 commit intoopenshift:masterfrom
simo5:allowUnknownScopes
Sep 14, 2018
Merged

Ignore errors caused by unkonwn scopes where it makes sense to do so.#20911
openshift-merge-robot merged 1 commit intoopenshift:masterfrom
simo5:allowUnknownScopes

Conversation

@simo5
Copy link
Contributor

@simo5 simo5 commented Sep 7, 2018

This allows us to interop with an OIDC/OAuth server that sends us tokens with additional scopes used for other applications than Openshift

@openshift-ci-robot openshift-ci-robot added size/S Denotes a PR that changes 10-29 lines, ignoring generated files. approved Indicates a PR has been approved by an approver from all required OWNERS files. labels Sep 7, 2018
@simo5 simo5 force-pushed the allowUnknownScopes branch from ce9b412 to cc8d9e7 Compare September 7, 2018 21:29
enj
enj previously requested changes Sep 7, 2018
func (userEvaluator) Handles(scope string) bool {
return strings.HasPrefix(scope, UserIndicator)
switch scope {
case UserFull, UserInfo, UserAccessCheck, UserListScopedProjects, UserListAllProjects:
Copy link
Contributor

Choose a reason for hiding this comment

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

Probably just easier to check Validate(scope) == nil since you are basically binding their logic.

Copy link
Contributor

Choose a reason for hiding this comment

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

@deads2k you probably have an opinion here.

}
}

if !found {
Copy link
Contributor

Choose a reason for hiding this comment

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

Hmm let us add something like ignoreUnhandledScopes as a bool param and let the caller tell us this is ok to ignore.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

all callers will tell us that though ... can do it, but sounds a bit redundant

Copy link
Contributor

Choose a reason for hiding this comment

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

Seems bad to just drop it. I keep wondering if it would just be better to let the callers ignore all errors. Sigh, I cannot tell what would be best here.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ok rebased to what it looks like with the boolean ...

@enj
Copy link
Contributor

enj commented Sep 7, 2018

@openshift/sig-security

@simo5 simo5 force-pushed the allowUnknownScopes branch 2 times, most recently from ca267a1 to ac4ef34 Compare September 10, 2018 13:23
@openshift-ci-robot openshift-ci-robot removed the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Sep 10, 2018
@simo5 simo5 force-pushed the allowUnknownScopes branch from ac4ef34 to dd48375 Compare September 10, 2018 13:29
@openshift-ci-robot openshift-ci-robot added size/M Denotes a PR that changes 30-99 lines, ignoring generated files. and removed size/S Denotes a PR that changes 10-29 lines, ignoring generated files. labels Sep 10, 2018
@simo5 simo5 force-pushed the allowUnknownScopes branch from dd48375 to 3dda4db Compare September 10, 2018 15:25
type userEvaluator struct{}

func (userEvaluator) Handles(scope string) bool {
return strings.HasPrefix(scope, UserIndicator)
Copy link
Contributor

Choose a reason for hiding this comment

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

I was expecting something like return e.Validate(scope) == nil since that forces the logic into one place.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

it's the same just makes more semantic sense inside Validate() to check for Handles() rather than in Handles() to call Validate()

Copy link
Contributor

Choose a reason for hiding this comment

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

ok

@simo5
Copy link
Contributor Author

simo5 commented Sep 10, 2018

/retest

@enj
Copy link
Contributor

enj commented Sep 10, 2018

Will give David/others a chance to look.

@simo5 simo5 dismissed enj’s stale review September 10, 2018 18:34

Changes implemented

@mrogers950
Copy link

/lgtm

@openshift-ci-robot openshift-ci-robot added the lgtm Indicates that a PR is ready to be merged. label Sep 10, 2018
@deads2k
Copy link
Contributor

deads2k commented Sep 11, 2018

If I were trying to consume a different kind of scope from a different provider, I would expect them to sanitize the scopes to indicate which ones they expect our authorizer to enforce and provide a list in a different user.Extra key for all their scopes. That would clearly delineate responsibility of enforcement instead of ignoring.

I accept that this may work, but it does seem to increase the risk of bugs. If you decide to go with this anyway, you need tests ensuring that properly fail closed when scopes are presented and none are recognized.

// ScopesToVisibleNamespaces returns a list of namespaces that the provided scopes have "get" access to.
// This exists only to support efficiently list/watch of projects (ACLed namespaces)
func ScopesToVisibleNamespaces(scopes []string, clusterRoleGetter rbaclisters.ClusterRoleLister) (sets.String, error) {
func ScopesToVisibleNamespaces(scopes []string, clusterRoleGetter rbaclisters.ClusterRoleLister, ignoreUnhandledScopes bool) (sets.String, error) {
Copy link
Contributor

Choose a reason for hiding this comment

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

It appears that every caller is setting this to true. Why have the option?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

mo requested it ...

Copy link
Contributor

Choose a reason for hiding this comment

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

I did not want to blanket remove the "unhandled scope" errors...

@simo5
Copy link
Contributor Author

simo5 commented Sep 11, 2018 via email

@simo5
Copy link
Contributor Author

simo5 commented Sep 11, 2018

Truns out we have a way to test unknown scopes by using the webhook authentication interface, so I'm going to add to the webhook integration test as well

@simo5
Copy link
Contributor Author

simo5 commented Sep 11, 2018

/hold

@openshift-ci-robot openshift-ci-robot added do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. and removed lgtm Indicates that a PR is ready to be merged. size/M Denotes a PR that changes 30-99 lines, ignoring generated files. labels Sep 11, 2018
@openshift-ci-robot openshift-ci-robot added the size/L Denotes a PR that changes 100-499 lines, ignoring generated files. label Sep 11, 2018
@simo5 simo5 force-pushed the allowUnknownScopes branch 3 times, most recently from 0f000b8 to 3ea2d37 Compare September 12, 2018 21:55
Copy link
Contributor

@enj enj left a comment

Choose a reason for hiding this comment

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

Some important role: bits, otherwise minor nits.

t.Fatalf("unexpected error: %v", err)
}

_, haroldClientConfig, err := testutil.GetClientForUser(clusterAdminClientConfig, "harold")
Copy link
Contributor

Choose a reason for hiding this comment

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

CreateNewProject already gives you a haroldClientConfig

Scopes: []string{"user:info", "user:garbage", "garbage"},
},
}
rulesReviewWithGarbageObj, err := authzv1client.SelfSubjectRulesReviews(projectName).Create(rulesReviewWithGarbage)
Copy link
Contributor

Choose a reason for hiding this comment

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

unchecked error?

}
rulesReviewOnlyGarbageObj, err := authzv1client.SelfSubjectRulesReviews(projectName).Create(rulesReviewOnlyGarbage)

//Check same rules, first we need to convert SSRR result from:
Copy link
Contributor

Choose a reason for hiding this comment

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

Can you move the conversion to its own function, it is pretty awful.

// Test with valid scope as baseline
rulesReview := &authorizationv1.SelfSubjectRulesReview{
Spec: authorizationv1.SelfSubjectRulesReviewSpec{
Scopes: []string{"user:info"},
Copy link
Contributor

Choose a reason for hiding this comment

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

Add a valid role: based scope for admin in the current namespace.

// Try adding garbage scope and check we have the same perms as baseline
rulesReviewWithGarbage := &authorizationv1.SelfSubjectRulesReview{
Spec: authorizationv1.SelfSubjectRulesReviewSpec{
Scopes: []string{"user:info", "user:garbage", "garbage"},
Copy link
Contributor

Choose a reason for hiding this comment

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

Also the same valid role: from above and also add garbage role:

t.Fatalf("unexpected error getting user harold client config: %v", err)
}

authzv1client, err := authorizationv1typedclient.NewForConfig(haroldClientConfig)
Copy link
Contributor

Choose a reason for hiding this comment

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

Is there a NewForConfigOrDie to remove some more boilerplate?

Scopes: []string{"user:garbage", "garbage"},
},
}
rulesReviewOnlyGarbageObj, err := authzv1client.SelfSubjectRulesReviews(projectName).Create(rulesReviewOnlyGarbage)
Copy link
Contributor

Choose a reason for hiding this comment

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

unchecked error?

// Make sure no rules (beyond baseline) when only garbage scopes are present
rulesReviewOnlyGarbage := &authorizationv1.SelfSubjectRulesReview{
Spec: authorizationv1.SelfSubjectRulesReviewSpec{
Scopes: []string{"user:garbage", "garbage"},
Copy link
Contributor

Choose a reason for hiding this comment

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

Add garbage role:

// semantically identical
baselineRules := []rbacv1.PolicyRule{authorizationapi.DiscoveryRule}

covers, unexpectedRules := rbacvalidation.Covers(baselineRules, rbacv1Rules)
Copy link
Contributor

Choose a reason for hiding this comment

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

An assertEqual helper function would be nice.

@simo5 simo5 force-pushed the allowUnknownScopes branch 2 times, most recently from 599453b to 6f664ef Compare September 13, 2018 20:38
@simo5
Copy link
Contributor Author

simo5 commented Sep 13, 2018

Ok all the requests should have been handled now, and I have tests that exercise both ScopesToRules and ScopesToVisibleNamespaces

@simo5 simo5 force-pushed the allowUnknownScopes branch 4 times, most recently from 22fe81e to e19ea8d Compare September 14, 2018 01:03
Copy link
Contributor

@enj enj left a comment

Choose a reason for hiding this comment

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

minor things

if err != nil {
return false, err
}
if len(projects.Items) > 0 {
Copy link
Contributor

Choose a reason for hiding this comment

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

return len(projects.Items) > 0, nil

projectClient := projectclient.NewForConfigOrDie(&impersonatingConfig)

var projects *projectapiv1.ProjectList
err = wait.Poll(100*time.Millisecond, 10*time.Second,
Copy link
Contributor

Choose a reason for hiding this comment

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

Probably want 30 seconds, CI can be slow and it is not worth the flake.

&badScopesUserInfo, *clusterAdminClientConfig)
badScopesProjectClient := projectclient.NewForConfigOrDie(&badScopesImpersonatingConfig)
projects, err = badScopesProjectClient.ProjectV1().Projects().List(metav1.ListOptions{})
if !kapierrors.IsForbidden(err) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Add a check to fail on nil error and then change this to if !kapierrors.IsForbidden(err) || !strings.Contains(err.Error(), "prevent this action, additionally the following non-fatal errors were reported"

Forbidden is the default fall through case so let us make sure the scope message is there.

Added integration tests

Signed-off-by: Simo Sorce <simo@redhat.com>
@simo5 simo5 force-pushed the allowUnknownScopes branch from e19ea8d to 0f2438c Compare September 14, 2018 18:32
@simo5
Copy link
Contributor Author

simo5 commented Sep 14, 2018

Ok addressed the last nits too.

@enj
Copy link
Contributor

enj commented Sep 14, 2018

/lgtm
/hold cancel

@openshift-ci-robot openshift-ci-robot added lgtm Indicates that a PR is ready to be merged. and removed do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. labels Sep 14, 2018
@openshift-ci-robot
Copy link

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: enj, mrogers950, simo5

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

The pull request process is described here

Details 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-robot openshift-ci-robot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Sep 14, 2018
@openshift-bot
Copy link
Contributor

/retest

Please review the full test history for this PR and help us cut down flakes.

@openshift-merge-robot openshift-merge-robot merged commit feec27a into openshift:master Sep 14, 2018
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. lgtm Indicates that a PR is ready to be merged. sig/security size/L Denotes a PR that changes 100-499 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants