History

fix: handle array policies in JWT claim (#10041)

PR #10014 was not complete as only handled policy claims partially.

Harshavardhana committed 6 years ago

Commit 369a8761 parent 778e9c85 files · +90 −27Browse files

Unified · Split

5 files
  1. cmd/auth-handler.go +4 −3
  2. docs/sts/keycloak.md +14 −14
  3. pkg/bucket/policy/condition/jwt.go +4 −0
  4. pkg/iam/policy/policy.go +23 −10
  5. pkg/iam/policy/policy_test.go +45 −0
cmd/auth-handler.go+4−3
@@ -213,15 +213,15 @@ func getClaimsFromToken(r *http.Request, token string) (map[string]interface{}, · 212 unmodified lines
213 213
214 if globalPolicyOPA == nil {214 if globalPolicyOPA == nil {
215 // If OPA is not set and if ldap claim key is set, allow the claim.215 // If OPA is not set and if ldap claim key is set, allow the claim.
216 if _, ok := claims.Lookup(ldapUser); ok {216 if _, ok := claims.MapClaims[ldapUser]; ok {
217 return claims.Map(), nil217 return claims.Map(), nil
218 }218 }
219 219
220 // If OPA is not set, session token should220 // If OPA is not set, session token should
221 // have a policy and its mandatory, reject221 // have a policy and its mandatory, reject
222 // requests without policy claim.222 // requests without policy claim.
223 _, pokOpenID := claims.Lookup(iamPolicyClaimNameOpenID())223 _, pokOpenID := claims.MapClaims[iamPolicyClaimNameOpenID()]
224 _, pokSA := claims.Lookup(iamPolicyClaimNameSA())224 _, pokSA := claims.MapClaims[iamPolicyClaimNameSA()]
225 if !pokOpenID && !pokSA {225 if !pokOpenID && !pokSA {
226 return nil, errAuthentication226 return nil, errAuthentication
227 }227 }
@@ -360,6 +360,7 @@ func checkRequestAuthTypeToAccessKey(ctx context.Context, r *http.Request, actio · 132 unmodified lines
360 // Request is allowed return the appropriate access key.360 // Request is allowed return the appropriate access key.
361 return cred.AccessKey, owner, ErrNone361 return cred.AccessKey, owner, ErrNone
362 }362 }
363
363 return cred.AccessKey, owner, ErrAccessDenied364 return cred.AccessKey, owner, ErrAccessDenied
364}365}
365 366
docs/sts/keycloak.md+14−14
@@ -8,31 +8,31 @@ Configure and install keycloak server by following [Keycloak Installation Guide] · 7 unmodified lines
8 8
9### Configure Keycloak UI9### Configure Keycloak UI
10- Go to Clients10- Go to Clients
11 -> Click on account11 - Click on account
12 -> Settings12 - Settings
13 -> Enable `Implicit Flow`13 - Enable `Implicit Flow`
14 -> Save14 - Save
15 15
16- Go to Users16- Go to Users
17 -> Click on the user17 - Click on the user
18 -> Attribute, add a new attribute `Key` is `policy`, `Value` is name of the `policy` on MinIO (ex: `readwrite`)18 - Attribute, add a new attribute `Key` is `policy`, `Value` is name of the `policy` on MinIO (ex: `readwrite`)
19 -> Add and Save19 - Add and Save
20 20
21- Go to Clients21- Go to Clients
22 -> Click on `account`22 - Click on `account`
23 -> Settings, set `Valid Redirect URIs` to `*`, expand `Advanced Settings` and set `Access Token Lifespan` to `1 Hours`23 - Settings, set `Valid Redirect URIs` to `*`, expand `Advanced Settings` and set `Access Token Lifespan` to `1 Hours`
24 -> Save24 - Save
25 25
26- Go to Clients26- Go to Clients
27 -> Client on `account`27 - Client on `account`
28 -> Mappers28 - Mappers
29 -> Create29 - Create
30 - `Name` with any text30 - `Name` with any text
31 - `Mapper Type` is `User Attribute`31 - `Mapper Type` is `User Attribute`
32 - `User Attribute` is `policy`32 - `User Attribute` is `policy`
33 - `Token Claim Name` is `policy`33 - `Token Claim Name` is `policy`
34 - `Claim JSON Type` is `string`34 - `Claim JSON Type` is `string`
35 -> Save35 - Save
36 36
37- Open http://localhost:8080/auth/realms/demo/.well-known/openid-configuration to verify OpenID discovery document, verify it has `authorization_endpoint` and `jwks_uri`37- Open http://localhost:8080/auth/realms/demo/.well-known/openid-configuration to verify OpenID discovery document, verify it has `authorization_endpoint` and `jwks_uri`
38 38
pkg/bucket/policy/condition/jwt.go+4−0
@@ -31,7 +31,9 @@ const ( · 30 unmodified lines
31 // JWTJti JWT unique identifier claim substitution.31 // JWTJti JWT unique identifier claim substitution.
32 JWTJti Key = "jwt:jti"32 JWTJti Key = "jwt:jti"
33 33
34 JWTUpn Key = "jwt:upn"
34 JWTName Key = "jwt:name"35 JWTName Key = "jwt:name"
36 JWTGroups Key = "jwt:groups"
35 JWTGivenName Key = "jwt:given_name"37 JWTGivenName Key = "jwt:given_name"
36 JWTFamilyName Key = "jwt:family_name"38 JWTFamilyName Key = "jwt:family_name"
37 JWTMiddleName Key = "jwt:middle_name"39 JWTMiddleName Key = "jwt:middle_name"
@@ -57,6 +59,8 @@ var JWTKeys = []Key{ · 19 unmodified lines
57 JWTAud,59 JWTAud,
58 JWTJti,60 JWTJti,
59 JWTName,61 JWTName,
62 JWTUpn,
63 JWTGroups,
60 JWTGivenName,64 JWTGivenName,
61 JWTFamilyName,65 JWTFamilyName,
62 JWTMiddleName,66 JWTMiddleName,
pkg/iam/policy/policy.go+23−10
@@ -47,23 +47,36 @@ func GetPoliciesFromClaims(claims map[string]interface{}, policyClaimName string · 46 unmodified lines
47 if !ok {47 if !ok {
48 return s, false48 return s, false
49 }49 }
50 pnames, ok := pname.([]string)50 pnames, ok := pname.([]interface{})
51 if !ok {51 if !ok {
52 pnameStr, ok := pname.(string)52 pnameStr, ok := pname.(string)
53 if ok {53 if ok {
54 pnames = strings.Split(pnameStr, ",")54 for _, pname := range strings.Split(pnameStr, ",") {
55 } else {55 pname = strings.TrimSpace(pname)
56 return s, false56 if pname == "" {
57 // ignore any empty strings, considerate
58 // towards some user errors.
59 continue
60 }
61 s.Add(pname)
62 }
63 return s, true
57 }64 }
65 return s, false
58 }66 }
59 for _, pname := range pnames {67 for _, pname := range pnames {
60 pname = strings.TrimSpace(pname)68 pnameStr, ok := pname.(string)
61 if pname == "" {69 if ok {
62 // ignore any empty strings, considerate70 for _, pnameStr := range strings.Split(pnameStr, ",") {
63 // towards some user errors.71 pnameStr = strings.TrimSpace(pnameStr)
64 continue72 if pnameStr == "" {
73 // ignore any empty strings, considerate
74 // towards some user errors.
75 continue
76 }
77 s.Add(pnameStr)
78 }
65 }79 }
66 s.Add(pname)
67 }80 }
68 return s, true81 return s, true
69}82}
pkg/iam/policy/policy_test.go+45−0
@@ -22,10 +22,55 @@ import ( · 21 unmodified lines
22 "reflect"22 "reflect"
23 "testing"23 "testing"
24 24
25 "github.com/minio/minio-go/v6/pkg/set"
25 "github.com/minio/minio/pkg/bucket/policy"26 "github.com/minio/minio/pkg/bucket/policy"
26 "github.com/minio/minio/pkg/bucket/policy/condition"27 "github.com/minio/minio/pkg/bucket/policy/condition"
27)28)
28 29
30func TestGetPoliciesFromClaims(t *testing.T) {
31 attributesArray := `{
32 "exp": 1594690452,
33 "iat": 1594689552,
34 "auth_time": 1594689552,
35 "jti": "18ed05c9-2c69-45d5-a33f-8c94aca99ad5",
36 "iss": "http://localhost:8080/auth/realms/minio",
37 "aud": "account",
38 "sub": "7e5e2f30-1c97-4616-8623-2eae14dee9b1",
39 "typ": "ID",
40 "azp": "account",
41 "nonce": "66ZoLzwJbjdkiedI",
42 "session_state": "3df7b526-5310-4038-9f35-50ecd295a31d",
43 "acr": "1",
44 "upn": "harsha",
45 "address": {},
46 "email_verified": false,
47 "groups": [
48 "offline_access"
49 ],
50 "preferred_username": "harsha",
51 "policy": [
52 "readwrite",
53 "readwrite,readonly",
54 " readonly",
55 ""
56 ]}`
57 var m = make(map[string]interface{})
58 if err := json.Unmarshal([]byte(attributesArray), &m); err != nil {
59 t.Fatal(err)
60 }
61 var expectedSet = set.CreateStringSet("readwrite", "readonly")
62 gotSet, ok := GetPoliciesFromClaims(m, "policy")
63 if !ok {
64 t.Fatal("no policy claim was found")
65 }
66 if gotSet.IsEmpty() {
67 t.Fatal("no policies were found in policy claim")
68 }
69 if !gotSet.Equals(expectedSet) {
70 t.Fatalf("Expected %v got %v", expectedSet, gotSet)
71 }
72}
73
29func TestPolicyIsAllowed(t *testing.T) {74func TestPolicyIsAllowed(t *testing.T) {
30 case1Policy := Policy{75 case1Policy := Policy{
31 Version: DefaultVersion,76 Version: DefaultVersion,

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t