mirror of
https://github.com/minio/minio.git
synced 2024-12-24 22:25:54 -05:00
fix: handle array policies in JWT claim (#10041)
PR #10014 was not complete as only handled policy claims partially.
This commit is contained in:
parent
778e9c864f
commit
369a876ebe
@ -213,15 +213,15 @@ func getClaimsFromToken(r *http.Request, token string) (map[string]interface{},
|
|||||||
|
|
||||||
if globalPolicyOPA == nil {
|
if globalPolicyOPA == nil {
|
||||||
// If OPA is not set and if ldap claim key is set, allow the claim.
|
// If OPA is not set and if ldap claim key is set, allow the claim.
|
||||||
if _, ok := claims.Lookup(ldapUser); ok {
|
if _, ok := claims.MapClaims[ldapUser]; ok {
|
||||||
return claims.Map(), nil
|
return claims.Map(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// If OPA is not set, session token should
|
// If OPA is not set, session token should
|
||||||
// have a policy and its mandatory, reject
|
// have a policy and its mandatory, reject
|
||||||
// requests without policy claim.
|
// requests without policy claim.
|
||||||
_, pokOpenID := claims.Lookup(iamPolicyClaimNameOpenID())
|
_, pokOpenID := claims.MapClaims[iamPolicyClaimNameOpenID()]
|
||||||
_, pokSA := claims.Lookup(iamPolicyClaimNameSA())
|
_, pokSA := claims.MapClaims[iamPolicyClaimNameSA()]
|
||||||
if !pokOpenID && !pokSA {
|
if !pokOpenID && !pokSA {
|
||||||
return nil, errAuthentication
|
return nil, errAuthentication
|
||||||
}
|
}
|
||||||
@ -360,6 +360,7 @@ func checkRequestAuthTypeToAccessKey(ctx context.Context, r *http.Request, actio
|
|||||||
// Request is allowed return the appropriate access key.
|
// Request is allowed return the appropriate access key.
|
||||||
return cred.AccessKey, owner, ErrNone
|
return cred.AccessKey, owner, ErrNone
|
||||||
}
|
}
|
||||||
|
|
||||||
return cred.AccessKey, owner, ErrAccessDenied
|
return cred.AccessKey, owner, ErrAccessDenied
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,31 +8,31 @@ Configure and install keycloak server by following [Keycloak Installation Guide]
|
|||||||
|
|
||||||
### Configure Keycloak UI
|
### Configure Keycloak UI
|
||||||
- Go to Clients
|
- Go to Clients
|
||||||
-> Click on account
|
- Click on account
|
||||||
-> Settings
|
- Settings
|
||||||
-> Enable `Implicit Flow`
|
- Enable `Implicit Flow`
|
||||||
-> Save
|
- Save
|
||||||
|
|
||||||
- Go to Users
|
- Go to Users
|
||||||
-> Click on the user
|
- Click on the user
|
||||||
-> Attribute, add a new attribute `Key` is `policy`, `Value` is name of the `policy` on MinIO (ex: `readwrite`)
|
- Attribute, add a new attribute `Key` is `policy`, `Value` is name of the `policy` on MinIO (ex: `readwrite`)
|
||||||
-> Add and Save
|
- Add and Save
|
||||||
|
|
||||||
- Go to Clients
|
- Go to Clients
|
||||||
-> Click on `account`
|
- Click on `account`
|
||||||
-> Settings, set `Valid Redirect URIs` to `*`, expand `Advanced Settings` and set `Access Token Lifespan` to `1 Hours`
|
- Settings, set `Valid Redirect URIs` to `*`, expand `Advanced Settings` and set `Access Token Lifespan` to `1 Hours`
|
||||||
-> Save
|
- Save
|
||||||
|
|
||||||
- Go to Clients
|
- Go to Clients
|
||||||
-> Client on `account`
|
- Client on `account`
|
||||||
-> Mappers
|
- Mappers
|
||||||
-> Create
|
- Create
|
||||||
- `Name` with any text
|
- `Name` with any text
|
||||||
- `Mapper Type` is `User Attribute`
|
- `Mapper Type` is `User Attribute`
|
||||||
- `User Attribute` is `policy`
|
- `User Attribute` is `policy`
|
||||||
- `Token Claim Name` is `policy`
|
- `Token Claim Name` is `policy`
|
||||||
- `Claim JSON Type` is `string`
|
- `Claim JSON Type` is `string`
|
||||||
-> Save
|
- Save
|
||||||
|
|
||||||
- Open http://localhost:8080/auth/realms/demo/.well-known/openid-configuration to verify OpenID discovery document, verify it has `authorization_endpoint` and `jwks_uri`
|
- Open http://localhost:8080/auth/realms/demo/.well-known/openid-configuration to verify OpenID discovery document, verify it has `authorization_endpoint` and `jwks_uri`
|
||||||
|
|
||||||
|
@ -31,7 +31,9 @@ const (
|
|||||||
// JWTJti JWT unique identifier claim substitution.
|
// JWTJti JWT unique identifier claim substitution.
|
||||||
JWTJti Key = "jwt:jti"
|
JWTJti Key = "jwt:jti"
|
||||||
|
|
||||||
|
JWTUpn Key = "jwt:upn"
|
||||||
JWTName Key = "jwt:name"
|
JWTName Key = "jwt:name"
|
||||||
|
JWTGroups Key = "jwt:groups"
|
||||||
JWTGivenName Key = "jwt:given_name"
|
JWTGivenName Key = "jwt:given_name"
|
||||||
JWTFamilyName Key = "jwt:family_name"
|
JWTFamilyName Key = "jwt:family_name"
|
||||||
JWTMiddleName Key = "jwt:middle_name"
|
JWTMiddleName Key = "jwt:middle_name"
|
||||||
@ -57,6 +59,8 @@ var JWTKeys = []Key{
|
|||||||
JWTAud,
|
JWTAud,
|
||||||
JWTJti,
|
JWTJti,
|
||||||
JWTName,
|
JWTName,
|
||||||
|
JWTUpn,
|
||||||
|
JWTGroups,
|
||||||
JWTGivenName,
|
JWTGivenName,
|
||||||
JWTFamilyName,
|
JWTFamilyName,
|
||||||
JWTMiddleName,
|
JWTMiddleName,
|
||||||
|
@ -47,23 +47,36 @@ func GetPoliciesFromClaims(claims map[string]interface{}, policyClaimName string
|
|||||||
if !ok {
|
if !ok {
|
||||||
return s, false
|
return s, false
|
||||||
}
|
}
|
||||||
pnames, ok := pname.([]string)
|
pnames, ok := pname.([]interface{})
|
||||||
if !ok {
|
if !ok {
|
||||||
pnameStr, ok := pname.(string)
|
pnameStr, ok := pname.(string)
|
||||||
if ok {
|
if ok {
|
||||||
pnames = strings.Split(pnameStr, ",")
|
for _, pname := range strings.Split(pnameStr, ",") {
|
||||||
} else {
|
pname = strings.TrimSpace(pname)
|
||||||
return s, false
|
if pname == "" {
|
||||||
|
// ignore any empty strings, considerate
|
||||||
|
// towards some user errors.
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
s.Add(pname)
|
||||||
|
}
|
||||||
|
return s, true
|
||||||
}
|
}
|
||||||
|
return s, false
|
||||||
}
|
}
|
||||||
for _, pname := range pnames {
|
for _, pname := range pnames {
|
||||||
pname = strings.TrimSpace(pname)
|
pnameStr, ok := pname.(string)
|
||||||
if pname == "" {
|
if ok {
|
||||||
// ignore any empty strings, considerate
|
for _, pnameStr := range strings.Split(pnameStr, ",") {
|
||||||
// towards some user errors.
|
pnameStr = strings.TrimSpace(pnameStr)
|
||||||
continue
|
if pnameStr == "" {
|
||||||
|
// ignore any empty strings, considerate
|
||||||
|
// towards some user errors.
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
s.Add(pnameStr)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
s.Add(pname)
|
|
||||||
}
|
}
|
||||||
return s, true
|
return s, true
|
||||||
}
|
}
|
||||||
|
@ -22,10 +22,55 @@ import (
|
|||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/minio/minio-go/v6/pkg/set"
|
||||||
"github.com/minio/minio/pkg/bucket/policy"
|
"github.com/minio/minio/pkg/bucket/policy"
|
||||||
"github.com/minio/minio/pkg/bucket/policy/condition"
|
"github.com/minio/minio/pkg/bucket/policy/condition"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func TestGetPoliciesFromClaims(t *testing.T) {
|
||||||
|
attributesArray := `{
|
||||||
|
"exp": 1594690452,
|
||||||
|
"iat": 1594689552,
|
||||||
|
"auth_time": 1594689552,
|
||||||
|
"jti": "18ed05c9-2c69-45d5-a33f-8c94aca99ad5",
|
||||||
|
"iss": "http://localhost:8080/auth/realms/minio",
|
||||||
|
"aud": "account",
|
||||||
|
"sub": "7e5e2f30-1c97-4616-8623-2eae14dee9b1",
|
||||||
|
"typ": "ID",
|
||||||
|
"azp": "account",
|
||||||
|
"nonce": "66ZoLzwJbjdkiedI",
|
||||||
|
"session_state": "3df7b526-5310-4038-9f35-50ecd295a31d",
|
||||||
|
"acr": "1",
|
||||||
|
"upn": "harsha",
|
||||||
|
"address": {},
|
||||||
|
"email_verified": false,
|
||||||
|
"groups": [
|
||||||
|
"offline_access"
|
||||||
|
],
|
||||||
|
"preferred_username": "harsha",
|
||||||
|
"policy": [
|
||||||
|
"readwrite",
|
||||||
|
"readwrite,readonly",
|
||||||
|
" readonly",
|
||||||
|
""
|
||||||
|
]}`
|
||||||
|
var m = make(map[string]interface{})
|
||||||
|
if err := json.Unmarshal([]byte(attributesArray), &m); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
var expectedSet = set.CreateStringSet("readwrite", "readonly")
|
||||||
|
gotSet, ok := GetPoliciesFromClaims(m, "policy")
|
||||||
|
if !ok {
|
||||||
|
t.Fatal("no policy claim was found")
|
||||||
|
}
|
||||||
|
if gotSet.IsEmpty() {
|
||||||
|
t.Fatal("no policies were found in policy claim")
|
||||||
|
}
|
||||||
|
if !gotSet.Equals(expectedSet) {
|
||||||
|
t.Fatalf("Expected %v got %v", expectedSet, gotSet)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestPolicyIsAllowed(t *testing.T) {
|
func TestPolicyIsAllowed(t *testing.T) {
|
||||||
case1Policy := Policy{
|
case1Policy := Policy{
|
||||||
Version: DefaultVersion,
|
Version: DefaultVersion,
|
||||||
|
Loading…
Reference in New Issue
Block a user