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