Honor DurationSeconds properly for WebIdentity (#8581)

Also cleanup code to add various constants for
verbatim strings across the code base.

Fixes #8482
This commit is contained in:
Harshavardhana
2019-11-29 05:27:54 -08:00
committed by Nitish Tiwari
parent c7844fb1fb
commit b21835f195
10 changed files with 194 additions and 95 deletions
+48 -36
View File
@@ -36,7 +36,15 @@ import (
const (
// STS API version.
stsAPIVersion = "2011-06-15"
stsAPIVersion = "2011-06-15"
stsVersion = "Version"
stsAction = "Action"
stsPolicy = "Policy"
stsToken = "Token"
stsWebIdentityToken = "WebIdentityToken"
stsDurationSeconds = "DurationSeconds"
stsLDAPUsername = "LDAPUsername"
stsLDAPPassword = "LDAPPassword"
// STS API action constants
clientGrants = "AssumeRoleWithClientGrants"
@@ -46,6 +54,10 @@ const (
stsRequestBodyLimit = 10 * (1 << 20) // 10 MiB
// JWT claim keys
expClaim = "exp"
subClaim = "sub"
// LDAP claim keys
ldapUser = "ldapUser"
ldapGroups = "ldapGroups"
@@ -71,30 +83,30 @@ func registerSTSRouter(router *mux.Router) {
}).HandlerFunc(httpTraceAll(sts.AssumeRole))
// Assume roles with JWT handler, handles both ClientGrants and WebIdentity.
stsRouter.Methods("POST").MatcherFunc(func(r *http.Request, rm *mux.RouteMatch) bool {
stsRouter.Methods(http.MethodPost).MatcherFunc(func(r *http.Request, rm *mux.RouteMatch) bool {
ctypeOk := wildcard.MatchSimple("application/x-www-form-urlencoded*", r.Header.Get(xhttp.ContentType))
noQueries := len(r.URL.Query()) == 0
return ctypeOk && noQueries
}).HandlerFunc(httpTraceAll(sts.AssumeRoleWithJWT))
// AssumeRoleWithClientGrants
stsRouter.Methods("POST").HandlerFunc(httpTraceAll(sts.AssumeRoleWithClientGrants)).
Queries("Action", clientGrants).
Queries("Version", stsAPIVersion).
Queries("Token", "{Token:.*}")
stsRouter.Methods(http.MethodPost).HandlerFunc(httpTraceAll(sts.AssumeRoleWithClientGrants)).
Queries(stsAction, clientGrants).
Queries(stsVersion, stsAPIVersion).
Queries(stsToken, "{Token:.*}")
// AssumeRoleWithWebIdentity
stsRouter.Methods("POST").HandlerFunc(httpTraceAll(sts.AssumeRoleWithWebIdentity)).
Queries("Action", webIdentity).
Queries("Version", stsAPIVersion).
Queries("WebIdentityToken", "{Token:.*}")
stsRouter.Methods(http.MethodPost).HandlerFunc(httpTraceAll(sts.AssumeRoleWithWebIdentity)).
Queries(stsAction, webIdentity).
Queries(stsVersion, stsAPIVersion).
Queries(stsWebIdentityToken, "{Token:.*}")
// AssumeRoleWithLDAPIdentity
stsRouter.Methods("POST").HandlerFunc(httpTraceAll(sts.AssumeRoleWithLDAPIdentity)).
Queries("Action", ldapIdentity).
Queries("Version", stsAPIVersion).
Queries("LDAPUsername", "{LDAPUsername:.*}").
Queries("LDAPPassword", "{LDAPPassword:.*}")
stsRouter.Methods(http.MethodPost).HandlerFunc(httpTraceAll(sts.AssumeRoleWithLDAPIdentity)).
Queries(stsAction, ldapIdentity).
Queries(stsVersion, stsAPIVersion).
Queries(stsLDAPUsername, "{LDAPUsername:.*}").
Queries(stsLDAPPassword, "{LDAPPassword:.*}")
}
func checkAssumeRoleAuth(ctx context.Context, r *http.Request) (user auth.Credentials, stsErr STSErrorCode) {
@@ -141,12 +153,12 @@ func (sts *stsAPIHandlers) AssumeRole(w http.ResponseWriter, r *http.Request) {
return
}
if r.Form.Get("Version") != stsAPIVersion {
writeSTSErrorResponse(ctx, w, ErrSTSMissingParameter, fmt.Errorf("Invalid STS API version %s, expecting %s", r.Form.Get("Version"), stsAPIVersion))
if r.Form.Get(stsVersion) != stsAPIVersion {
writeSTSErrorResponse(ctx, w, ErrSTSMissingParameter, fmt.Errorf("Invalid STS API version %s, expecting %s", r.Form.Get(stsVersion), stsAPIVersion))
return
}
action := r.Form.Get("Action")
action := r.Form.Get(stsAction)
switch action {
case assumeRole:
default:
@@ -157,7 +169,7 @@ func (sts *stsAPIHandlers) AssumeRole(w http.ResponseWriter, r *http.Request) {
ctx = newContext(r, w, action)
defer logger.AuditLog(w, r, action, nil)
sessionPolicyStr := r.Form.Get("Policy")
sessionPolicyStr := r.Form.Get(stsPolicy)
// https://docs.aws.amazon.com/STS/latest/APIReference/API_AssumeRole.html
// The plain text that you use for both inline and managed session
// policies shouldn't exceed 2048 characters.
@@ -182,7 +194,7 @@ func (sts *stsAPIHandlers) AssumeRole(w http.ResponseWriter, r *http.Request) {
var err error
m := make(map[string]interface{})
m["exp"], err = openid.GetDefaultExpiration(r.Form.Get("DurationSeconds"))
m[expClaim], err = openid.GetDefaultExpiration(r.Form.Get(stsDurationSeconds))
if err != nil {
writeSTSErrorResponse(ctx, w, ErrSTSInvalidParameterValue, err)
return
@@ -248,12 +260,12 @@ func (sts *stsAPIHandlers) AssumeRoleWithJWT(w http.ResponseWriter, r *http.Requ
return
}
if r.Form.Get("Version") != stsAPIVersion {
if r.Form.Get(stsVersion) != stsAPIVersion {
writeSTSErrorResponse(ctx, w, ErrSTSMissingParameter, fmt.Errorf("Invalid STS API version %s, expecting %s", r.Form.Get("Version"), stsAPIVersion))
return
}
action := r.Form.Get("Action")
action := r.Form.Get(stsAction)
switch action {
case clientGrants, webIdentity:
default:
@@ -275,12 +287,12 @@ func (sts *stsAPIHandlers) AssumeRoleWithJWT(w http.ResponseWriter, r *http.Requ
return
}
token := r.Form.Get("Token")
token := r.Form.Get(stsToken)
if token == "" {
token = r.Form.Get("WebIdentityToken")
token = r.Form.Get(stsWebIdentityToken)
}
m, err := v.Validate(token, r.Form.Get("DurationSeconds"))
m, err := v.Validate(token, r.Form.Get(stsDurationSeconds))
if err != nil {
switch err {
case openid.ErrTokenExpired:
@@ -291,7 +303,7 @@ func (sts *stsAPIHandlers) AssumeRoleWithJWT(w http.ResponseWriter, r *http.Requ
writeSTSErrorResponse(ctx, w, ErrSTSWebIdentityExpiredToken, err)
}
return
case openid.ErrInvalidDuration:
case auth.ErrInvalidDuration:
writeSTSErrorResponse(ctx, w, ErrSTSInvalidParameterValue, err)
return
}
@@ -299,7 +311,7 @@ func (sts *stsAPIHandlers) AssumeRoleWithJWT(w http.ResponseWriter, r *http.Requ
return
}
sessionPolicyStr := r.Form.Get("Policy")
sessionPolicyStr := r.Form.Get(stsPolicy)
// https://docs.aws.amazon.com/STS/latest/APIReference/API_AssumeRoleWithWebIdentity.html
// The plain text that you use for both inline and managed session
// policies shouldn't exceed 2048 characters.
@@ -343,7 +355,7 @@ func (sts *stsAPIHandlers) AssumeRoleWithJWT(w http.ResponseWriter, r *http.Requ
}
var subFromToken string
if v, ok := m["sub"]; ok {
if v, ok := m[subClaim]; ok {
subFromToken, _ = v.(string)
}
@@ -415,12 +427,12 @@ func (sts *stsAPIHandlers) AssumeRoleWithLDAPIdentity(w http.ResponseWriter, r *
return
}
if r.Form.Get("Version") != stsAPIVersion {
if r.Form.Get(stsVersion) != stsAPIVersion {
writeSTSErrorResponse(ctx, w, ErrSTSMissingParameter, fmt.Errorf("Invalid STS API version %s, expecting %s", r.Form.Get("Version"), stsAPIVersion))
return
}
action := r.Form.Get("Action")
action := r.Form.Get(stsAction)
switch action {
case ldapIdentity:
default:
@@ -431,15 +443,15 @@ func (sts *stsAPIHandlers) AssumeRoleWithLDAPIdentity(w http.ResponseWriter, r *
ctx = newContext(r, w, action)
defer logger.AuditLog(w, r, action, nil)
ldapUsername := r.Form.Get("LDAPUsername")
ldapPassword := r.Form.Get("LDAPPassword")
ldapUsername := r.Form.Get(stsLDAPUsername)
ldapPassword := r.Form.Get(stsLDAPPassword)
if ldapUsername == "" || ldapPassword == "" {
writeSTSErrorResponse(ctx, w, ErrSTSMissingParameter, fmt.Errorf("LDAPUsername and LDAPPassword cannot be empty"))
return
}
sessionPolicyStr := r.Form.Get("Policy")
sessionPolicyStr := r.Form.Get(stsPolicy)
// https://docs.aws.amazon.com/STS/latest/APIReference/API_AssumeRole.html
// The plain text that you use for both inline and managed session
// policies shouldn't exceed 2048 characters.
@@ -516,9 +528,9 @@ func (sts *stsAPIHandlers) AssumeRoleWithLDAPIdentity(w http.ResponseWriter, r *
}
expiryDur := globalLDAPConfig.GetExpiryDuration()
m := map[string]interface{}{
"exp": UTCNow().Add(expiryDur).Unix(),
"ldapUser": ldapUsername,
"ldapGroups": groups,
expClaim: UTCNow().Add(expiryDur).Unix(),
ldapUser: ldapUsername,
ldapGroups: groups,
}
if len(sessionPolicyStr) > 0 {