-
Notifications
You must be signed in to change notification settings - Fork 13
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
ROX-23709: Trust Data Plane OAuth issuers in fleetshard authorization middleware #1801
Conversation
Skipping CI for Draft Pull Request. |
7c3d605
to
cdec282
Compare
0064307
to
fd7a041
Compare
This stack of pull requests is managed by Graphite. Learn more about stacking. |
pkg/auth/fleetshard_authz.go
Outdated
@@ -40,6 +42,8 @@ func (c *FleetShardAuthZConfig) AddFlags(fs *pflag.FlagSet) { | |||
"Fleetshard authZ middleware configuration file containing a list of allowed org IDs") | |||
fs.BoolVar(&c.Enabled, "enable-fleetshard-authz", c.Enabled, "Enable fleetshard authZ "+ | |||
"via the list of allowed org IDs") | |||
fs.StringVar(&c.AllowedSubject, "fleetshard-authz-subject", c.AllowedSubject, | |||
"Fleetshard authZ middleware allowed subject") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: maybe to make it more clear to folks reading through things:
"Fleetshard authZ middleware allowed subject") | |
"Fleetshard authZ middleware allowed subject claim of the token") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Obsolete, moved to the config file
pkg/auth/fleetshard_authz.go
Outdated
@@ -24,13 +24,15 @@ type FleetShardAuthZConfig struct { | |||
Enabled bool | |||
AllowedOrgIDs AllowedOrgIDs | |||
AllowedOrgIDsFile string | |||
AllowedSubject string |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seeing as the effort will be relatively low, might make sense to allow setting multiple subjects as allowed ones, similar to the previous org IDs? While currently not eminent, it's not a lot of work to add support for that and will make our life easier in the future.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
return | ||
} | ||
|
||
glog.Infof("fleetshard subject is not allowed (expected=%s, actual=%s)", expected, s) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In case the subject is empty or malformed:
glog.Infof("fleetshard subject is not allowed (expected=%s, actual=%s)", expected, s) | |
glog.Infof("fleetshard subject is not allowed (expected=%s, actual=%q)", expected, s) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Obsolete, added the generic claims check
@@ -47,3 +69,29 @@ func checkAllowedOrgIDs(allowedOrgIDs AllowedOrgIDs) mux.MiddlewareFunc { | |||
}) | |||
} | |||
} | |||
|
|||
func checkSubject(expected string) mux.MiddlewareFunc { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit:
func checkSubject(expected string) mux.MiddlewareFunc { | |
func checkSubject(allowedSubject string) mux.MiddlewareFunc { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Obsolete, added the generic claims check
One thing in addition that would work well besides verifying the subject would also be verifying the audience. We can set the audience to a custom one in the projected volume mount (and also should, so that the token cannot be used to access the API server) and additionally verify that here. |
Done |
cdec282
to
4834ca2
Compare
d6f9367
to
2752423
Compare
4834ca2
to
9353319
Compare
a7a9c4c
to
44ede5a
Compare
pkg/auth/acs_claims.go
Outdated
@@ -16,6 +16,11 @@ func (c *ACSClaims) VerifyIssuer(cmp string, req bool) bool { | |||
return jwt.MapClaims(*c).VerifyIssuer(cmp, req) | |||
} | |||
|
|||
// VerifyAudience wraps jwt.VerifyAudience |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
super nit: while we're at it, might make sense to give proper comments to all the functions here..
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
pkg/auth/acs_claims.go
Outdated
@@ -16,6 +16,11 @@ func (c *ACSClaims) VerifyIssuer(cmp string, req bool) bool { | |||
return jwt.MapClaims(*c).VerifyIssuer(cmp, req) | |||
} | |||
|
|||
// VerifyAudience wraps jwt.VerifyAudience | |||
func (c *ACSClaims) VerifyAudience(cmp string, req bool) bool { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking at this, does it even make sense to give clients the option to set required
to false? I don't think we should IMO, but since this is more or less pre-existing, it's fine to leave as is and address in a follow-up, but I feel like we should introduce some sane defaults here to avoid people unsetting the required by mistake.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agree, removed the required
option
audienceAccepted = true | ||
break |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
instead of breaking you could just call next.ServeHTTP
here. Then you don't have the additional indentation at the bottom with !audienceAccepted
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done, thanks
pkg/auth/acs_claims.go
Outdated
@@ -79,6 +84,15 @@ func (c *ACSClaims) GetSubject() (string, error) { | |||
return "", fmt.Errorf("can't find %q attribute in claims", tenantSubClaim) | |||
} | |||
|
|||
// GetAudience returns the audience claim of the token. It identifies the token consumer. | |||
func (c *ACSClaims) GetAudience() (interface{}, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it going to be a string or string array? Either way, I think it would be nice to have a concrete type here instead of the interface.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It can be either string or array
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added logic to cast it to []string
and a few unit tests
|
||
if !audienceAccepted { | ||
audience, _ := claims.GetAudience() | ||
glog.Infof("none of the audiences (%q) in the access token is not in the list of allowed values [%s]", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since audience
is of type interface
, what will %q
actually print here? Better to return a concrete type in GetAudience()
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed to strings.join
since claims.getAudience
now returns []string
. See the comment above.
bbf4f42
to
a40721e
Compare
26b84f6
to
d0507ef
Compare
// IsOrgAdmin ... | ||
// GetAudience returns the audience claim of the token. It identifies the token consumer. | ||
func (c *ACSClaims) GetAudience() ([]string, error) { | ||
aud := make([]string, 0) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
super nit: probably preferences, but might as well do var aud []string
🤷
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was done on purpose in order to get consistent results in the following test cases:
should return empty slice if the claim is empty array
should return empty slice if the claim is empty interface
If I change this line to var aud []string
, GetAudience
will return an empty and nil slice respectively.
pkg/auth/acs_claims.go
Outdated
for _, a := range v { | ||
vs, ok := a.(string) | ||
if !ok { | ||
return nil, fmt.Errorf("can't parse part of the audience claim: %q", a) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd rather fail open and create a log message that parts of the audience couldn't be parsed but not fail closed like we do here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
14eb2cd
to
c5a1af0
Compare
New changes are detected. LGTM label has been removed. |
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: dhaus67, kovayur 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 |
6417b2b
to
f48b741
Compare
Description
This change adds Data Plane OAuth issuers validation in fleetshard authorization middleware.
The old authorization remains for backward compatibility
Checklist (Definition of Done)
Test manual
ROX-12345: ...
Test manual
TODO: Add manual testing efforts