Added support for reading body in STS API (#7188)

STS API supports both URL query params and reading
from a body.
master
Harshavardhana 6 years ago committed by kannappanr
parent df418a2783
commit e4081aee62
  1. 178
      cmd/sts-handlers.go

@ -17,6 +17,7 @@
package cmd package cmd
import ( import (
"fmt"
"net/http" "net/http"
"github.com/gorilla/mux" "github.com/gorilla/mux"
@ -28,6 +29,10 @@ import (
const ( const (
// STS API version. // STS API version.
stsAPIVersion = "2011-06-15" stsAPIVersion = "2011-06-15"
// STS API action constants
clientGrants = "AssumeRoleWithClientGrants"
webIdentity = "AssumeRoleWithWebIdentity"
) )
// stsAPIHandlers implements and provides http handlers for AWS STS API. // stsAPIHandlers implements and provides http handlers for AWS STS API.
@ -41,139 +46,86 @@ func registerSTSRouter(router *mux.Router) {
// STS Router // STS Router
stsRouter := router.NewRoute().PathPrefix("/").Subrouter() stsRouter := router.NewRoute().PathPrefix("/").Subrouter()
// Assume roles with JWT handler, handles both ClientGrants and WebIdentity.
stsRouter.Methods("POST").HeadersRegexp("Content-Type", "application/x-www-form-urlencoded*").
HandlerFunc(httpTraceAll(sts.AssumeRoleWithJWT))
// AssumeRoleWithClientGrants // AssumeRoleWithClientGrants
stsRouter.Methods("POST").HandlerFunc(httpTraceAll(sts.AssumeRoleWithClientGrants)). stsRouter.Methods("POST").HandlerFunc(httpTraceAll(sts.AssumeRoleWithClientGrants)).
Queries("Action", "AssumeRoleWithClientGrants"). Queries("Action", clientGrants).
Queries("Version", stsAPIVersion). Queries("Version", stsAPIVersion).
Queries("Token", "{Token:.*}") Queries("Token", "{Token:.*}")
// AssumeRoleWithWebIdentity // AssumeRoleWithWebIdentity
stsRouter.Methods("POST").HandlerFunc(httpTraceAll(sts.AssumeRoleWithWebIdentity)). stsRouter.Methods("POST").HandlerFunc(httpTraceAll(sts.AssumeRoleWithWebIdentity)).
Queries("Action", "AssumeRoleWithWebIdentity"). Queries("Action", webIdentity).
Queries("Version", stsAPIVersion). Queries("Version", stsAPIVersion).
Queries("WebIdentityToken", "{Token:.*}") Queries("WebIdentityToken", "{Token:.*}")
} }
// AssumeRoleWithWebIdentity - implementation of AWS STS API supporting OAuth2.0 func (sts *stsAPIHandlers) AssumeRoleWithJWT(w http.ResponseWriter, r *http.Request) {
// users from web identity provider such as Facebook, Google, or any OpenID ctx := newContext(r, w, "AssumeRoleInternalFunction")
// Connect-compatible identity provider.
//
// Eg:-
// $ curl https://minio:9000/?Action=AssumeRoleWithWebIdentity&WebIdentityToken=<jwt>
func (sts *stsAPIHandlers) AssumeRoleWithWebIdentity(w http.ResponseWriter, r *http.Request) {
ctx := newContext(r, w, "AssumeRoleWithWebIdentity")
defer logger.AuditLog(w, r, "AssumeRoleWithWebIdentity", nil)
if globalIAMValidators == nil {
writeSTSErrorResponse(w, ErrSTSNotInitialized)
return
}
// NOTE: this API only accepts JWT tokens. // Parse the incoming form data.
v, err := globalIAMValidators.Get("jwt") if err := r.ParseForm(); err != nil {
if err != nil { logger.LogIf(ctx, err)
writeSTSErrorResponse(w, ErrSTSInvalidParameterValue) writeSTSErrorResponse(w, ErrSTSInvalidParameterValue)
return return
} }
vars := mux.Vars(r) if r.Form.Get("Version") != stsAPIVersion {
m, err := v.Validate(vars["Token"], r.URL.Query().Get("DurationSeconds")) logger.LogIf(ctx, fmt.Errorf("Invalid STS API version %s, expecting %s", r.Form.Get("Version"), stsAPIVersion))
if err != nil { writeSTSErrorResponse(w, ErrSTSMissingParameter)
switch err {
case validator.ErrTokenExpired:
writeSTSErrorResponse(w, ErrSTSWebIdentityExpiredToken)
case validator.ErrInvalidDuration:
writeSTSErrorResponse(w, ErrSTSInvalidParameterValue)
default:
logger.LogIf(ctx, err)
writeSTSErrorResponse(w, ErrSTSInvalidParameterValue)
}
return
}
secret := globalServerConfig.GetCredential().SecretKey
cred, err := auth.GetNewCredentialsWithMetadata(m, secret)
if err != nil {
logger.LogIf(ctx, err)
writeSTSErrorResponse(w, ErrSTSInternalError)
return return
} }
// JWT has requested a custom claim with policy value set. action := r.Form.Get("Action")
// This is a Minio STS API specific value, this value should switch action {
// be set and configured on your identity provider as part of case clientGrants, webIdentity:
// JWT custom claims. default:
var policyName string logger.LogIf(ctx, fmt.Errorf("Unsupported action %s", action))
if v, ok := m["policy"]; ok { writeSTSErrorResponse(w, ErrSTSInvalidParameterValue)
policyName, _ = v.(string)
}
var subFromToken string
if v, ok := m["sub"]; ok {
subFromToken, _ = v.(string)
}
// Set the newly generated credentials.
if err = globalIAMSys.SetTempUser(cred.AccessKey, cred, policyName); err != nil {
logger.LogIf(ctx, err)
writeSTSErrorResponse(w, ErrSTSInternalError)
return return
} }
// Notify all other Minio peers to reload temp users ctx = newContext(r, w, action)
for _, nerr := range globalNotificationSys.LoadUsers() { defer logger.AuditLog(w, r, action, nil)
if nerr.Err != nil {
logger.GetReqInfo(ctx).SetTags("peerAddress", nerr.Host.String())
logger.LogIf(ctx, nerr.Err)
}
}
encodedSuccessResponse := encodeResponse(&AssumeRoleWithWebIdentityResponse{
Result: WebIdentityResult{
Credentials: cred,
SubjectFromWebIdentityToken: subFromToken,
},
})
writeSuccessResponseXML(w, encodedSuccessResponse)
}
// AssumeRoleWithClientGrants - implementation of AWS STS extension API supporting
// OAuth2.0 client credential grants.
//
// Eg:-
// $ curl https://minio:9000/?Action=AssumeRoleWithClientGrants&Token=<jwt>
func (sts *stsAPIHandlers) AssumeRoleWithClientGrants(w http.ResponseWriter, r *http.Request) {
ctx := newContext(r, w, "AssumeRoleWithClientGrants")
defer logger.AuditLog(w, r, "AssumeRoleWithClientGrants", nil)
if globalIAMValidators == nil { if globalIAMValidators == nil {
writeSTSErrorResponse(w, ErrSTSNotInitialized) writeSTSErrorResponse(w, ErrSTSNotInitialized)
return return
} }
// NOTE: this API only accepts JWT tokens.
v, err := globalIAMValidators.Get("jwt") v, err := globalIAMValidators.Get("jwt")
if err != nil { if err != nil {
logger.LogIf(ctx, err)
writeSTSErrorResponse(w, ErrSTSInvalidParameterValue) writeSTSErrorResponse(w, ErrSTSInvalidParameterValue)
return return
} }
vars := mux.Vars(r) token := r.Form.Get("Token")
m, err := v.Validate(vars["Token"], r.URL.Query().Get("DurationSeconds")) if token == "" {
token = r.Form.Get("WebIdentityToken")
}
m, err := v.Validate(token, r.Form.Get("DurationSeconds"))
if err != nil { if err != nil {
switch err { switch err {
case validator.ErrTokenExpired: case validator.ErrTokenExpired:
writeSTSErrorResponse(w, ErrSTSClientGrantsExpiredToken) switch action {
case clientGrants:
writeSTSErrorResponse(w, ErrSTSClientGrantsExpiredToken)
case webIdentity:
writeSTSErrorResponse(w, ErrSTSWebIdentityExpiredToken)
}
return
case validator.ErrInvalidDuration: case validator.ErrInvalidDuration:
writeSTSErrorResponse(w, ErrSTSInvalidParameterValue) writeSTSErrorResponse(w, ErrSTSInvalidParameterValue)
default: return
logger.LogIf(ctx, err)
writeSTSErrorResponse(w, ErrSTSInvalidParameterValue)
} }
logger.LogIf(ctx, err)
writeSTSErrorResponse(w, ErrSTSInvalidParameterValue)
return return
} }
@ -214,12 +166,42 @@ func (sts *stsAPIHandlers) AssumeRoleWithClientGrants(w http.ResponseWriter, r *
} }
} }
encodedSuccessResponse := encodeResponse(&AssumeRoleWithClientGrantsResponse{ var encodedSuccessResponse []byte
Result: ClientGrantsResult{ switch action {
Credentials: cred, case clientGrants:
SubjectFromToken: subFromToken, encodedSuccessResponse = encodeResponse(&AssumeRoleWithClientGrantsResponse{
}, Result: ClientGrantsResult{
}) Credentials: cred,
SubjectFromToken: subFromToken,
},
})
case webIdentity:
encodedSuccessResponse = encodeResponse(&AssumeRoleWithWebIdentityResponse{
Result: WebIdentityResult{
Credentials: cred,
SubjectFromWebIdentityToken: subFromToken,
},
})
}
writeSuccessResponseXML(w, encodedSuccessResponse) writeSuccessResponseXML(w, encodedSuccessResponse)
} }
// AssumeRoleWithWebIdentity - implementation of AWS STS API supporting OAuth2.0
// users from web identity provider such as Facebook, Google, or any OpenID
// Connect-compatible identity provider.
//
// Eg:-
// $ curl https://minio:9000/?Action=AssumeRoleWithWebIdentity&WebIdentityToken=<jwt>
func (sts *stsAPIHandlers) AssumeRoleWithWebIdentity(w http.ResponseWriter, r *http.Request) {
sts.AssumeRoleWithJWT(w, r)
}
// AssumeRoleWithClientGrants - implementation of AWS STS extension API supporting
// OAuth2.0 client credential grants.
//
// Eg:-
// $ curl https://minio:9000/?Action=AssumeRoleWithClientGrants&Token=<jwt>
func (sts *stsAPIHandlers) AssumeRoleWithClientGrants(w http.ResponseWriter, r *http.Request) {
sts.AssumeRoleWithJWT(w, r)
}

Loading…
Cancel
Save