@ -20,7 +20,6 @@ import (
"context"
"context"
"crypto/subtle"
"crypto/subtle"
"encoding/json"
"encoding/json"
"encoding/xml"
"errors"
"errors"
"fmt"
"fmt"
"io"
"io"
@ -2202,54 +2201,61 @@ type LoginSTSArgs struct {
Token string ` json:"token" form:"token" `
Token string ` json:"token" form:"token" `
}
}
var errSTSNotInitialized = errors . New ( "STS API not initialized, please configure STS support" )
// LoginSTS - STS user login handler.
// LoginSTS - STS user login handler.
func ( web * webAPIHandlers ) LoginSTS ( r * http . Request , args * LoginSTSArgs , reply * LoginRep ) error {
func ( web * webAPIHandlers ) LoginSTS ( r * http . Request , args * LoginSTSArgs , reply * LoginRep ) error {
ctx := newWebContext ( r , args , "WebLoginSTS" )
ctx := newWebContext ( r , args , "WebLoginSTS" )
v := url . Values { }
if globalOpenIDValidators == nil {
v . Set ( "Action" , webIdentity )
return toJSONError ( ctx , errSTSNotInitialized )
v . Set ( "WebIdentityToken" , args . Token )
v . Set ( "Version" , stsAPIVersion )
scheme := "http"
if sourceScheme := handlers . GetSourceScheme ( r ) ; sourceScheme != "" {
scheme = sourceScheme
}
if globalIsTLS {
scheme = "https"
}
}
u := & url . URL {
v , err := globalOpenIDValidators . Get ( "jwt" )
Scheme : scheme ,
if err != nil {
Host : r . Host ,
logger . LogIf ( ctx , err )
return toJSONError ( ctx , errSTSNotInitialized )
}
}
u . RawQuery = v . Encode ( )
m , err := v . Validate ( args . Token , "" )
req , err := http . NewRequest ( http . MethodPost , u . String ( ) , nil )
if err != nil {
if err != nil {
return toJSONError ( ctx , err )
return toJSONError ( ctx , err )
}
}
clnt := & http . Client {
// JWT has requested a custom claim with policy value set.
Transport : NewGatewayHTTPTransport ( ) ,
// This is a MinIO STS API specific value, this value should
// be set and configured on your identity provider as part of
// JWT custom claims.
var policyName string
policySet , ok := iampolicy . GetPoliciesFromClaims ( m , iamPolicyClaimNameOpenID ( ) )
if ok {
policyName = globalIAMSys . CurrentPolicies ( strings . Join ( policySet . ToSlice ( ) , "," ) )
}
}
resp , err := clnt . Do ( req )
if policyName == "" && globalPolicyOPA == nil {
return toJSONError ( ctx , fmt . Errorf ( "%s claim missing from the JWT token, credentials will not be generated" , iamPolicyClaimNameOpenID ( ) ) )
}
m [ iamPolicyClaimNameOpenID ( ) ] = policyName
secret := globalActiveCred . SecretKey
cred , err := auth . GetNewCredentialsWithMetadata ( m , secret )
if err != nil {
if err != nil {
return toJSONError ( ctx , err )
return toJSONError ( ctx , err )
}
}
defer xhttp . DrainBody ( resp . Body )
if resp . StatusCode != http . StatusOK {
// Set the newly generated credentials.
return toJSONError ( ctx , errors . New ( resp . Status ) )
if err = globalIAMSys . SetTempUser ( cred . AccessKey , cred , policyName ) ; err != nil {
return toJSONError ( ctx , err )
}
}
a := AssumeRoleWithWebIdentityResponse { }
// Notify all other MinIO peers to reload temp users
if err = xml . NewDecoder ( resp . Body ) . Decode ( & a ) ; err != nil {
for _ , nerr := range globalNotificationSys . LoadUser ( cred . AccessKey , true ) {
return toJSONError ( ctx , err )
if nerr . Err != nil {
logger . GetReqInfo ( ctx ) . SetTags ( "peerAddress" , nerr . Host . String ( ) )
logger . LogIf ( ctx , nerr . Err )
}
}
}
reply . Token = a . Result . Credentials . SessionToken
reply . Token = c red. SessionToken
reply . UIVersion = browser . UIVersion
reply . UIVersion = browser . UIVersion
return nil
return nil
}
}
@ -2304,6 +2310,8 @@ func toWebAPIError(ctx context.Context, err error) APIError {
HTTPStatusCode : http . StatusBadRequest ,
HTTPStatusCode : http . StatusBadRequest ,
Description : err . Error ( ) ,
Description : err . Error ( ) ,
}
}
case errSTSNotInitialized :
return APIError ( stsErrCodes . ToSTSErr ( ErrSTSNotInitialized ) )
case errServerNotInitialized :
case errServerNotInitialized :
return APIError {
return APIError {
Code : "XMinioServerNotInitialized" ,
Code : "XMinioServerNotInitialized" ,