From 7e879a45d5f54d44097e9753e6851cd791c4d3a9 Mon Sep 17 00:00:00 2001 From: Harshavardhana Date: Mon, 29 Oct 2018 11:08:59 -0700 Subject: [PATCH] Add policy claim support for JWT (#6660) This way temporary credentials can use canned policies on the server without configuring OPA. --- cmd/iam.go | 39 +++++++++++++++++++++++++++++++++++---- cmd/sts-handlers.go | 11 ++++++++++- docs/sts/wso2.md | 15 +++++++++------ 3 files changed, 54 insertions(+), 11 deletions(-) diff --git a/cmd/iam.go b/cmd/iam.go index 6440490c1..772800013 100644 --- a/cmd/iam.go +++ b/cmd/iam.go @@ -269,12 +269,46 @@ func (sys *IAMSys) DeleteUser(accessKey string) error { } // SetTempUser - set temporary user credentials, these credentials have an expiry. -func (sys *IAMSys) SetTempUser(accessKey string, cred auth.Credentials) error { +func (sys *IAMSys) SetTempUser(accessKey string, cred auth.Credentials, policyName string) error { objectAPI := newObjectLayerFn() if objectAPI == nil { return errServerNotInitialized } + sys.Lock() + defer sys.Unlock() + + // If OPA is not set we honor any policy claims for this + // temporary user which match with pre-configured canned + // policies for this server. + if globalPolicyOPA == nil && policyName != "" { + p, ok := sys.iamCannedPolicyMap[policyName] + if !ok { + return errInvalidArgument + } + if p.IsEmpty() { + delete(sys.iamPolicyMap, accessKey) + return nil + } + + data, err := json.Marshal(policyName) + if err != nil { + return err + } + + configFile := pathJoin(iamConfigSTSPrefix, accessKey, iamPolicyFile) + if globalEtcdClient != nil { + err = saveConfigEtcd(context.Background(), globalEtcdClient, configFile, data) + } else { + err = saveConfig(context.Background(), objectAPI, configFile, data) + } + if err != nil { + return err + } + + sys.iamPolicyMap[accessKey] = policyName + } + configFile := pathJoin(iamConfigSTSPrefix, accessKey, iamIdentityFile) data, err := json.Marshal(cred) if err != nil { @@ -291,9 +325,6 @@ func (sys *IAMSys) SetTempUser(accessKey string, cred auth.Credentials) error { return err } - sys.Lock() - defer sys.Unlock() - sys.iamUsersMap[accessKey] = cred return nil } diff --git a/cmd/sts-handlers.go b/cmd/sts-handlers.go index 3199356f5..d6d1eb3e8 100644 --- a/cmd/sts-handlers.go +++ b/cmd/sts-handlers.go @@ -162,8 +162,17 @@ func (sts *stsAPIHandlers) AssumeRoleWithClientGrants(w http.ResponseWriter, r * return } + // JWT has requested a custom claim with policy value set. + // 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 + if v, ok := m["policy"]; ok { + policyName, _ = v.(string) + } + // Set the newly generated credentials. - if err = globalIAMSys.SetTempUser(cred.AccessKey, cred); err != nil { + if err = globalIAMSys.SetTempUser(cred.AccessKey, cred, policyName); err != nil { logger.LogIf(ctx, err) writeSTSErrorResponse(w, ErrSTSInternalError) return diff --git a/docs/sts/wso2.md b/docs/sts/wso2.md index 0df990df9..60c429a3b 100644 --- a/docs/sts/wso2.md +++ b/docs/sts/wso2.md @@ -54,15 +54,18 @@ The access token received is a signed JSON Web Token (JWT). Use a JWT decoder to |Claim Name|Type|Claim Value| |:--:|:--:|:--:| -|iss| string | The issuer of the JWT. The '> Identity Provider Entity Id ' value of the OAuth2/OpenID Connect Inbound Authentication configuration of the Resident Identity Provider is returned here. | -|aud| string array | The token audience list. The client identifier of the OAuth clients that the JWT is intended for, is sent herewith. | -|azp| string | The authorized party for which the token is issued to. The client identifier of the OAuth client that the token is issued for, is sent herewith. | -|iat| integer | The token issue time. | -|exp| integer | The token expiration time. | -|jti| string | Unique identifier for the JWT token. | +|iss| _string_ | The issuer of the JWT. The '> Identity Provider Entity Id ' value of the OAuth2/OpenID Connect Inbound Authentication configuration of the Resident Identity Provider is returned here. | +|aud| _string array_ | The token audience list. The client identifier of the OAuth clients that the JWT is intended for, is sent herewith. | +|azp| _string_ | The authorized party for which the token is issued to. The client identifier of the OAuth client that the token is issued for, is sent herewith. | +|iat| _integer_ | The token issue time. | +|exp| _integer_ | The token expiration time. | +|jti| _string_ | Unique identifier for the JWT token. | +|policy| _string_ | Canned policy name to be applied for STS credentials. (Optional) | Using the above `access_token` we can perform an STS request to Minio to get temporary credentials for Minio API operations. Minio STS API uses [JSON Web Key Set Endpoint](https://docs.wso2.com/display/IS541/JSON+Web+Key+Set+Endpoint) to validate if JWT is valid and is properly signed. +Optionally you can also configure `policy` as a custom claim for the JWT service provider follow [here](https://docs.wso2.com/display/IS550/Configuring+Claims+for+a+Service+Provider) and [here](https://docs.wso2.com/display/IS550/Handling+Custom+Claims+with+the+JWT+Bearer+Grant+Type) for relevant docs on how to configure claims for a service provider. + ### 5. Setup Minio with JWKS URL Minio server expects environment variable for JWKS url as `MINIO_IAM_JWKS_URL`, this environment variable takes a single entry. ```