Added iam import tests for openid (#20432)

Tests if imported service accounts have 
required access to buckets and objects.

Signed-off-by: Shubhendu Ram Tripathi <shubhendu@minio.io>

Co-authored-by: Harshavardhana <harsha@minio.io>
This commit is contained in:
Shubhendu
2024-09-17 22:15:46 +05:30
committed by GitHub
parent 3c82cf9327
commit 5bd27346ac
9 changed files with 165 additions and 50 deletions

View File

@@ -222,7 +222,7 @@ func mustGetClaimsFromToken(r *http.Request) map[string]interface{} {
return claims
}
func getClaimsFromTokenWithSecret(token, secret string) (map[string]interface{}, error) {
func getClaimsFromTokenWithSecret(token, secret string) (*xjwt.MapClaims, error) {
// JWT token for x-amz-security-token is signed with admin
// secret key, temporary credentials become invalid if
// server admin credentials change. This is done to ensure
@@ -244,7 +244,7 @@ func getClaimsFromTokenWithSecret(token, secret string) (map[string]interface{},
// If AuthZPlugin is set, return without any further checks.
if newGlobalAuthZPluginFn() != nil {
return claims.Map(), nil
return claims, nil
}
// Check if a session policy is set. If so, decode it here.
@@ -263,12 +263,16 @@ func getClaimsFromTokenWithSecret(token, secret string) (map[string]interface{},
claims.MapClaims[sessionPolicyNameExtracted] = string(spBytes)
}
return claims.Map(), nil
return claims, nil
}
// Fetch claims in the security token returned by the client.
func getClaimsFromToken(token string) (map[string]interface{}, error) {
return getClaimsFromTokenWithSecret(token, globalActiveCred.SecretKey)
jwtClaims, err := getClaimsFromTokenWithSecret(token, globalActiveCred.SecretKey)
if err != nil {
return nil, err
}
return jwtClaims.Map(), nil
}
// Fetch claims in the security token returned by the client and validate the token.
@@ -319,7 +323,7 @@ func checkClaimsFromToken(r *http.Request, cred auth.Credentials) (map[string]in
if err != nil {
return nil, toAPIErrorCode(r.Context(), err)
}
return claims, ErrNone
return claims.Map(), ErrNone
}
claims := xjwt.NewMapClaims()

View File

@@ -2031,7 +2031,7 @@ func (store *IAMStoreSys) getParentUsers(cache *iamCache) map[string]ParentUserI
var (
err error
claims map[string]interface{} = cred.Claims
claims *jwt.MapClaims
)
if cred.IsServiceAccount() {
@@ -2053,24 +2053,17 @@ func (store *IAMStoreSys) getParentUsers(cache *iamCache) map[string]ParentUserI
}
subClaimValue := cred.ParentUser
if v, ok := claims[subClaim]; ok {
subFromToken, ok := v.(string)
if ok {
subClaimValue = subFromToken
}
if v, ok := claims.Lookup(subClaim); ok {
subClaimValue = v
}
if v, ok := claims[ldapActualUser]; ok {
subFromToken, ok := v.(string)
if ok {
subClaimValue = subFromToken
}
if v, ok := claims.Lookup(ldapActualUser); ok {
subClaimValue = v
}
roleArn := openid.DummyRoleARN.String()
s, ok := claims[roleArnClaim]
val, ok2 := s.(string)
if ok && ok2 {
roleArn = val
s, ok := claims.Lookup(roleArnClaim)
if ok {
roleArn = s
}
v, ok := res[cred.ParentUser]
if ok {
@@ -2537,13 +2530,15 @@ func (store *IAMStoreSys) UpdateServiceAccount(ctx context.Context, accessKey st
// Extracted session policy name string can be removed as its not useful
// at this point.
delete(m, sessionPolicyNameExtracted)
m.Delete(sessionPolicyNameExtracted)
nosp := opts.sessionPolicy == nil || opts.sessionPolicy.Version == "" && len(opts.sessionPolicy.Statements) == 0
// sessionPolicy is nil and there is embedded policy attached we remove
// embedded policy at that point.
if _, ok := m[policy.SessionPolicyName]; ok && opts.sessionPolicy == nil {
delete(m, policy.SessionPolicyName)
m[iamPolicyClaimNameSA()] = inheritedPolicyType
if _, ok := m.Lookup(policy.SessionPolicyName); ok && nosp {
m.Delete(policy.SessionPolicyName)
m.Set(iamPolicyClaimNameSA(), inheritedPolicyType)
}
if opts.sessionPolicy != nil { // session policies is being updated
@@ -2551,21 +2546,23 @@ func (store *IAMStoreSys) UpdateServiceAccount(ctx context.Context, accessKey st
return updatedAt, err
}
policyBuf, err := json.Marshal(opts.sessionPolicy)
if err != nil {
return updatedAt, err
}
if opts.sessionPolicy.Version != "" && len(opts.sessionPolicy.Statements) > 0 {
policyBuf, err := json.Marshal(opts.sessionPolicy)
if err != nil {
return updatedAt, err
}
if len(policyBuf) > maxSVCSessionPolicySize {
return updatedAt, errSessionPolicyTooLarge
}
if len(policyBuf) > maxSVCSessionPolicySize {
return updatedAt, errSessionPolicyTooLarge
}
// Overwrite session policy claims.
m[policy.SessionPolicyName] = base64.StdEncoding.EncodeToString(policyBuf)
m[iamPolicyClaimNameSA()] = embeddedPolicyType
// Overwrite session policy claims.
m.Set(policy.SessionPolicyName, base64.StdEncoding.EncodeToString(policyBuf))
m.Set(iamPolicyClaimNameSA(), embeddedPolicyType)
}
}
cr.SessionToken, err = auth.JWTSignWithAccessKey(accessKey, m, cr.SecretKey)
cr.SessionToken, err = auth.JWTSignWithAccessKey(accessKey, m.Map(), cr.SecretKey)
if err != nil {
return updatedAt, err
}
@@ -2892,22 +2889,22 @@ func (store *IAMStoreSys) LoadUser(ctx context.Context, accessKey string) error
func extractJWTClaims(u UserIdentity) (jwtClaims *jwt.MapClaims, err error) {
keys := make([]string, 0, 3)
// Append credentials secret key itself
keys = append(keys, u.Credentials.SecretKey)
// Use site-replication credentials if found
if globalSiteReplicationSys.isEnabled() {
siteReplSecretKey, e := globalSiteReplicatorCred.Get(GlobalContext)
if e != nil {
return nil, e
secretKey, err := getTokenSigningKey()
if err != nil {
return nil, err
}
keys = append(keys, siteReplSecretKey)
keys = append(keys, secretKey)
}
// Use root credentials for credentials created with older deployments
keys = append(keys, globalActiveCred.SecretKey)
// Iterate over all keys and return with the first successful claim extraction
for _, key := range keys {
jwtClaims, err = auth.ExtractClaims(u.Credentials.SessionToken, key)
jwtClaims, err = getClaimsFromTokenWithSecret(u.Credentials.SessionToken, key)
if err == nil {
break
}

View File

@@ -1294,10 +1294,6 @@ func (sys *IAMSys) GetClaimsForSvcAcc(ctx context.Context, accessKey string) (ma
return nil, errServerNotInitialized
}
if sys.usersSysType != LDAPUsersSysType {
return nil, nil
}
sa, ok := sys.store.GetUser(accessKey)
if !ok || !sa.Credentials.IsServiceAccount() {
return nil, errNoSuchServiceAccount
@@ -2179,7 +2175,6 @@ func (sys *IAMSys) IsAllowedServiceAccount(args policy.Args, parentUser string)
return false
}
svcPolicies = newMappedPolicy(sys.rolesMap[arn]).toSlice()
default:
// Check policy for parent user of service account.
svcPolicies, err = sys.PolicyDBGet(parentUser, args.Groups...)

View File

@@ -1997,7 +1997,7 @@ func (s *TestSuiteIAM) TestLDAPCyrillicUser(c *check) {
}
// Validate claims.
dnClaim := claims[ldapActualUser].(string)
dnClaim := claims.MapClaims[ldapActualUser].(string)
if dnClaim != testCase.dn {
c.Fatalf("Test %d: unexpected dn claim: %s", i+1, dnClaim)
}
@@ -2079,11 +2079,11 @@ func (s *TestSuiteIAM) TestLDAPAttributesLookup(c *check) {
}
// Validate claims. Check if the sshPublicKey claim is present.
dnClaim := claims[ldapActualUser].(string)
dnClaim := claims.MapClaims[ldapActualUser].(string)
if dnClaim != testCase.dn {
c.Fatalf("Test %d: unexpected dn claim: %s", i+1, dnClaim)
}
sshPublicKeyClaim := claims[ldapAttribPrefix+"sshPublicKey"].([]interface{})[0].(string)
sshPublicKeyClaim := claims.MapClaims[ldapAttribPrefix+"sshPublicKey"].([]interface{})[0].(string)
if sshPublicKeyClaim == "" {
c.Fatalf("Test %d: expected sshPublicKey claim to be present", i+1)
}