mirror of
https://github.com/minio/minio.git
synced 2024-12-24 22:25:54 -05:00
fix: remove embedded-policy as requested by the user (#14847)
this PR introduces a few changes such as - sessionPolicyName is not reused in an extracted manner to apply policies for incoming authenticated calls, instead uses a different key to designate this information for the callers. - this differentiation is needed to ensure that service account updates do not accidentally store JSON representation instead of base64 equivalent on the disk. - relax requirements for Deleting a service account, allow deleting a service account that might be unreadable, i.e a situation where the user might have removed session policy which now carries a JSON representation, making it unparsable. - introduce some constants to reuse instead of strings. fixes #14784
This commit is contained in:
parent
c59d2a6288
commit
f0462322fd
@ -1014,11 +1014,9 @@ func (a adminAPIHandlers) DeleteServiceAccount(w http.ResponseWriter, r *http.Re
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
svcAccount, _, err := globalIAMSys.GetServiceAccount(ctx, serviceAccount)
|
// We do not care if service account is readable or not at this point,
|
||||||
if err != nil {
|
// since this is a delete call we shall allow it to be deleted if possible.
|
||||||
writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL)
|
svcAccount, _, _ := globalIAMSys.GetServiceAccount(ctx, serviceAccount)
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
adminPrivilege := globalIAMSys.IsAllowed(iampolicy.Args{
|
adminPrivilege := globalIAMSys.IsAllowed(iampolicy.Args{
|
||||||
AccountName: cred.AccessKey,
|
AccountName: cred.AccessKey,
|
||||||
@ -1033,7 +1031,7 @@ func (a adminAPIHandlers) DeleteServiceAccount(w http.ResponseWriter, r *http.Re
|
|||||||
if cred.ParentUser != "" {
|
if cred.ParentUser != "" {
|
||||||
parentUser = cred.ParentUser
|
parentUser = cred.ParentUser
|
||||||
}
|
}
|
||||||
if parentUser != svcAccount.ParentUser {
|
if svcAccount.ParentUser != "" && parentUser != svcAccount.ParentUser {
|
||||||
// The service account belongs to another user but return not
|
// The service account belongs to another user but return not
|
||||||
// found error to mitigate brute force attacks. or the
|
// found error to mitigate brute force attacks. or the
|
||||||
// serviceAccount doesn't exist.
|
// serviceAccount doesn't exist.
|
||||||
@ -1042,23 +1040,21 @@ func (a adminAPIHandlers) DeleteServiceAccount(w http.ResponseWriter, r *http.Re
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
err = globalIAMSys.DeleteServiceAccount(ctx, serviceAccount, true)
|
if err := globalIAMSys.DeleteServiceAccount(ctx, serviceAccount, true); err != nil {
|
||||||
if err != nil {
|
|
||||||
writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL)
|
writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Call site replication hook - non-root user accounts are replicated.
|
// Call site replication hook - non-root user accounts are replicated.
|
||||||
if svcAccount.ParentUser != globalActiveCred.AccessKey {
|
if svcAccount.ParentUser != "" && svcAccount.ParentUser != globalActiveCred.AccessKey {
|
||||||
err = globalSiteReplicationSys.IAMChangeHook(ctx, madmin.SRIAMItem{
|
if err := globalSiteReplicationSys.IAMChangeHook(ctx, madmin.SRIAMItem{
|
||||||
Type: madmin.SRIAMItemSvcAcc,
|
Type: madmin.SRIAMItemSvcAcc,
|
||||||
SvcAccChange: &madmin.SRSvcAccChange{
|
SvcAccChange: &madmin.SRSvcAccChange{
|
||||||
Delete: &madmin.SRSvcAccDelete{
|
Delete: &madmin.SRSvcAccDelete{
|
||||||
AccessKey: serviceAccount,
|
AccessKey: serviceAccount,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
}); err != nil {
|
||||||
if err != nil {
|
|
||||||
writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL)
|
writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -235,7 +235,7 @@ func getClaimsFromTokenWithSecret(token, secret string) (map[string]interface{},
|
|||||||
logger.LogIf(GlobalContext, err, logger.Application)
|
logger.LogIf(GlobalContext, err, logger.Application)
|
||||||
return nil, errAuthentication
|
return nil, errAuthentication
|
||||||
}
|
}
|
||||||
claims.MapClaims[iampolicy.SessionPolicyName] = string(spBytes)
|
claims.MapClaims[sessionPolicyNameExtracted] = string(spBytes)
|
||||||
}
|
}
|
||||||
|
|
||||||
return claims.Map(), nil
|
return claims.Map(), nil
|
||||||
|
@ -1684,6 +1684,17 @@ func (store *IAMStoreSys) UpdateServiceAccount(ctx context.Context, accessKey st
|
|||||||
return fmt.Errorf("unable to get svc acc claims: %v", err)
|
return fmt.Errorf("unable to get svc acc claims: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Extracted session policy name string can be removed as its not useful
|
||||||
|
// at this point.
|
||||||
|
delete(m, sessionPolicyNameExtracted)
|
||||||
|
|
||||||
|
// sessionPolicy is nil and there is embedded policy attached we remove
|
||||||
|
// rembedded policy at that point.
|
||||||
|
if _, ok := m[iampolicy.SessionPolicyName]; ok && opts.sessionPolicy == nil {
|
||||||
|
delete(m, iampolicy.SessionPolicyName)
|
||||||
|
m[iamPolicyClaimNameSA()] = inheritedPolicyType
|
||||||
|
}
|
||||||
|
|
||||||
if opts.sessionPolicy != nil {
|
if opts.sessionPolicy != nil {
|
||||||
if err := opts.sessionPolicy.Validate(); err != nil {
|
if err := opts.sessionPolicy.Validate(); err != nil {
|
||||||
return err
|
return err
|
||||||
@ -1700,7 +1711,7 @@ func (store *IAMStoreSys) UpdateServiceAccount(ctx context.Context, accessKey st
|
|||||||
|
|
||||||
// Overwrite session policy claims.
|
// Overwrite session policy claims.
|
||||||
m[iampolicy.SessionPolicyName] = base64.StdEncoding.EncodeToString(policyBuf)
|
m[iampolicy.SessionPolicyName] = base64.StdEncoding.EncodeToString(policyBuf)
|
||||||
m[iamPolicyClaimNameSA()] = "embedded-policy"
|
m[iamPolicyClaimNameSA()] = embeddedPolicyType
|
||||||
}
|
}
|
||||||
|
|
||||||
cr.SessionToken, err = auth.JWTSignWithAccessKey(accessKey, m, cr.SecretKey)
|
cr.SessionToken, err = auth.JWTSignWithAccessKey(accessKey, m, cr.SecretKey)
|
||||||
|
19
cmd/iam.go
19
cmd/iam.go
@ -63,6 +63,11 @@ const (
|
|||||||
statusDisabled = "disabled"
|
statusDisabled = "disabled"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
embeddedPolicyType = "embedded-policy"
|
||||||
|
inheritedPolicyType = "inherited-policy"
|
||||||
|
)
|
||||||
|
|
||||||
// IAMSys - config system.
|
// IAMSys - config system.
|
||||||
type IAMSys struct {
|
type IAMSys struct {
|
||||||
// Need to keep them here to keep alignment - ref: https://golang.org/pkg/sync/atomic/#pkg-note-BUG
|
// Need to keep them here to keep alignment - ref: https://golang.org/pkg/sync/atomic/#pkg-note-BUG
|
||||||
@ -866,9 +871,9 @@ func (sys *IAMSys) NewServiceAccount(ctx context.Context, parentUser string, gro
|
|||||||
|
|
||||||
if len(policyBuf) > 0 {
|
if len(policyBuf) > 0 {
|
||||||
m[iampolicy.SessionPolicyName] = base64.StdEncoding.EncodeToString(policyBuf)
|
m[iampolicy.SessionPolicyName] = base64.StdEncoding.EncodeToString(policyBuf)
|
||||||
m[iamPolicyClaimNameSA()] = "embedded-policy"
|
m[iamPolicyClaimNameSA()] = embeddedPolicyType
|
||||||
} else {
|
} else {
|
||||||
m[iamPolicyClaimNameSA()] = "inherited-policy"
|
m[iamPolicyClaimNameSA()] = inheritedPolicyType
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add all the necessary claims for the service accounts.
|
// Add all the necessary claims for the service accounts.
|
||||||
@ -989,7 +994,7 @@ func (sys *IAMSys) getServiceAccount(ctx context.Context, accessKey string) (aut
|
|||||||
}
|
}
|
||||||
pt, ptok := jwtClaims.Lookup(iamPolicyClaimNameSA())
|
pt, ptok := jwtClaims.Lookup(iamPolicyClaimNameSA())
|
||||||
sp, spok := jwtClaims.Lookup(iampolicy.SessionPolicyName)
|
sp, spok := jwtClaims.Lookup(iampolicy.SessionPolicyName)
|
||||||
if ptok && spok && pt == "embedded-policy" {
|
if ptok && spok && pt == embeddedPolicyType {
|
||||||
policyBytes, err := base64.StdEncoding.DecodeString(sp)
|
policyBytes, err := base64.StdEncoding.DecodeString(sp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return auth.Credentials{}, nil, err
|
return auth.Credentials{}, nil, err
|
||||||
@ -1417,6 +1422,8 @@ func (sys *IAMSys) PolicyDBGet(name string, isGroup bool, groups ...string) ([]s
|
|||||||
return sys.store.PolicyDBGet(name, isGroup, groups...)
|
return sys.store.PolicyDBGet(name, isGroup, groups...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const sessionPolicyNameExtracted = iampolicy.SessionPolicyName + "-extracted"
|
||||||
|
|
||||||
// IsAllowedServiceAccount - checks if the given service account is allowed to perform
|
// IsAllowedServiceAccount - checks if the given service account is allowed to perform
|
||||||
// actions. The permission of the parent user is checked first
|
// actions. The permission of the parent user is checked first
|
||||||
func (sys *IAMSys) IsAllowedServiceAccount(args iampolicy.Args, parentUser string) bool {
|
func (sys *IAMSys) IsAllowedServiceAccount(args iampolicy.Args, parentUser string) bool {
|
||||||
@ -1493,12 +1500,12 @@ func (sys *IAMSys) IsAllowedServiceAccount(args iampolicy.Args, parentUser strin
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
if saPolicyClaimStr == "inherited-policy" {
|
if saPolicyClaimStr == inheritedPolicyType {
|
||||||
return combinedPolicy.IsAllowed(parentArgs)
|
return combinedPolicy.IsAllowed(parentArgs)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now check if we have a sessionPolicy.
|
// Now check if we have a sessionPolicy.
|
||||||
spolicy, ok := args.Claims[iampolicy.SessionPolicyName]
|
spolicy, ok := args.Claims[sessionPolicyNameExtracted]
|
||||||
if !ok {
|
if !ok {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@ -1646,7 +1653,7 @@ func isAllowedBySessionPolicy(args iampolicy.Args) (hasSessionPolicy bool, isAll
|
|||||||
isAllowed = false
|
isAllowed = false
|
||||||
|
|
||||||
// Now check if we have a sessionPolicy.
|
// Now check if we have a sessionPolicy.
|
||||||
spolicy, ok := args.Claims[iampolicy.SessionPolicyName]
|
spolicy, ok := args.Claims[sessionPolicyNameExtracted]
|
||||||
if !ok {
|
if !ok {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user