mirror of
https://github.com/minio/minio.git
synced 2025-07-08 08:32:18 -04:00
Support adding service accounts with expiration (#16430)
Co-authored-by: Harshavardhana <harsha@minio.io>
This commit is contained in:
parent
4d7c8e3bb8
commit
4d708cebe9
@ -650,10 +650,11 @@ func (a adminAPIHandlers) AddServiceAccount(w http.ResponseWriter, r *http.Reque
|
|||||||
}
|
}
|
||||||
|
|
||||||
opts := newServiceAccountOpts{
|
opts := newServiceAccountOpts{
|
||||||
accessKey: createReq.AccessKey,
|
accessKey: createReq.AccessKey,
|
||||||
secretKey: createReq.SecretKey,
|
secretKey: createReq.SecretKey,
|
||||||
comment: createReq.Comment,
|
comment: createReq.Comment,
|
||||||
claims: make(map[string]interface{}),
|
expiration: createReq.Expiration,
|
||||||
|
claims: make(map[string]interface{}),
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find the user for the request sender (as it may be sent via a service
|
// Find the user for the request sender (as it may be sent via a service
|
||||||
@ -775,8 +776,9 @@ func (a adminAPIHandlers) AddServiceAccount(w http.ResponseWriter, r *http.Reque
|
|||||||
|
|
||||||
createResp := madmin.AddServiceAccountResp{
|
createResp := madmin.AddServiceAccountResp{
|
||||||
Credentials: madmin.Credentials{
|
Credentials: madmin.Credentials{
|
||||||
AccessKey: newCred.AccessKey,
|
AccessKey: newCred.AccessKey,
|
||||||
SecretKey: newCred.SecretKey,
|
SecretKey: newCred.SecretKey,
|
||||||
|
Expiration: newCred.Expiration,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -809,6 +811,7 @@ func (a adminAPIHandlers) AddServiceAccount(w http.ResponseWriter, r *http.Reque
|
|||||||
Claims: opts.claims,
|
Claims: opts.claims,
|
||||||
SessionPolicy: createReq.Policy,
|
SessionPolicy: createReq.Policy,
|
||||||
Status: auth.AccountOn,
|
Status: auth.AccountOn,
|
||||||
|
Expiration: createReq.Expiration,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
UpdatedAt: updatedAt,
|
UpdatedAt: updatedAt,
|
||||||
@ -891,6 +894,7 @@ func (a adminAPIHandlers) UpdateServiceAccount(w http.ResponseWriter, r *http.Re
|
|||||||
secretKey: updateReq.NewSecretKey,
|
secretKey: updateReq.NewSecretKey,
|
||||||
status: updateReq.NewStatus,
|
status: updateReq.NewStatus,
|
||||||
comment: updateReq.NewComment,
|
comment: updateReq.NewComment,
|
||||||
|
expiration: updateReq.NewExpiration,
|
||||||
sessionPolicy: sp,
|
sessionPolicy: sp,
|
||||||
}
|
}
|
||||||
updatedAt, err := globalIAMSys.UpdateServiceAccount(ctx, accessKey, opts)
|
updatedAt, err := globalIAMSys.UpdateServiceAccount(ctx, accessKey, opts)
|
||||||
@ -910,6 +914,7 @@ func (a adminAPIHandlers) UpdateServiceAccount(w http.ResponseWriter, r *http.Re
|
|||||||
Status: opts.status,
|
Status: opts.status,
|
||||||
Comment: opts.comment,
|
Comment: opts.comment,
|
||||||
SessionPolicy: updateReq.NewPolicy,
|
SessionPolicy: updateReq.NewPolicy,
|
||||||
|
Expiration: updateReq.NewExpiration,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
UpdatedAt: updatedAt,
|
UpdatedAt: updatedAt,
|
||||||
@ -988,12 +993,18 @@ func (a adminAPIHandlers) InfoServiceAccount(w http.ResponseWriter, r *http.Requ
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var expiration *time.Time
|
||||||
|
if !svcAccount.Expiration.IsZero() && !svcAccount.Expiration.Equal(timeSentinel) {
|
||||||
|
expiration = &svcAccount.Expiration
|
||||||
|
}
|
||||||
|
|
||||||
infoResp := madmin.InfoServiceAccountResp{
|
infoResp := madmin.InfoServiceAccountResp{
|
||||||
ParentUser: svcAccount.ParentUser,
|
ParentUser: svcAccount.ParentUser,
|
||||||
Comment: svcAccount.Comment,
|
Comment: svcAccount.Comment,
|
||||||
AccountStatus: svcAccount.Status,
|
AccountStatus: svcAccount.Status,
|
||||||
ImpliedPolicy: policy == nil,
|
ImpliedPolicy: policy == nil,
|
||||||
Policy: string(policyJSON),
|
Policy: string(policyJSON),
|
||||||
|
Expiration: expiration,
|
||||||
}
|
}
|
||||||
|
|
||||||
data, err := json.Marshal(infoResp)
|
data, err := json.Marshal(infoResp)
|
||||||
@ -2436,6 +2447,7 @@ func (a adminAPIHandlers) ImportIAM(w http.ResponseWriter, r *http.Request) {
|
|||||||
secretKey: svcAcctReq.SecretKey,
|
secretKey: svcAcctReq.SecretKey,
|
||||||
status: svcAcctReq.Status,
|
status: svcAcctReq.Status,
|
||||||
comment: svcAcctReq.Comment,
|
comment: svcAcctReq.Comment,
|
||||||
|
expiration: svcAcctReq.Expiration,
|
||||||
sessionPolicy: sp,
|
sessionPolicy: sp,
|
||||||
}
|
}
|
||||||
_, err = globalIAMSys.UpdateServiceAccount(ctx, svcAcctReq.AccessKey, opts)
|
_, err = globalIAMSys.UpdateServiceAccount(ctx, svcAcctReq.AccessKey, opts)
|
||||||
@ -2451,6 +2463,7 @@ func (a adminAPIHandlers) ImportIAM(w http.ResponseWriter, r *http.Request) {
|
|||||||
sessionPolicy: sp,
|
sessionPolicy: sp,
|
||||||
claims: svcAcctReq.Claims,
|
claims: svcAcctReq.Claims,
|
||||||
comment: svcAcctReq.Comment,
|
comment: svcAcctReq.Comment,
|
||||||
|
expiration: svcAcctReq.Expiration,
|
||||||
}
|
}
|
||||||
|
|
||||||
// In case of LDAP we need to resolve the targetUser to a DN and
|
// In case of LDAP we need to resolve the targetUser to a DN and
|
||||||
|
@ -253,7 +253,7 @@ func checkClaimsFromToken(r *http.Request, cred auth.Credentials) (map[string]in
|
|||||||
return nil, ErrNoAccessKey
|
return nil, ErrNoAccessKey
|
||||||
}
|
}
|
||||||
|
|
||||||
if token == "" && cred.IsTemp() {
|
if token == "" && cred.IsTemp() && !cred.IsServiceAccount() {
|
||||||
// Temporary credentials should always have x-amz-security-token
|
// Temporary credentials should always have x-amz-security-token
|
||||||
return nil, ErrInvalidToken
|
return nil, ErrInvalidToken
|
||||||
}
|
}
|
||||||
@ -263,7 +263,7 @@ func checkClaimsFromToken(r *http.Request, cred auth.Credentials) (map[string]in
|
|||||||
return nil, ErrInvalidToken
|
return nil, ErrInvalidToken
|
||||||
}
|
}
|
||||||
|
|
||||||
if cred.IsTemp() && subtle.ConstantTimeCompare([]byte(token), []byte(cred.SessionToken)) != 1 {
|
if !cred.IsServiceAccount() && cred.IsTemp() && subtle.ConstantTimeCompare([]byte(token), []byte(cred.SessionToken)) != 1 {
|
||||||
// validate token for temporary credentials only.
|
// validate token for temporary credentials only.
|
||||||
return nil, ErrInvalidToken
|
return nil, ErrInvalidToken
|
||||||
}
|
}
|
||||||
|
@ -245,6 +245,13 @@ func (ies *IAMEtcdStore) addUser(ctx context.Context, user string, userType IAMU
|
|||||||
if u.Credentials.AccessKey == "" {
|
if u.Credentials.AccessKey == "" {
|
||||||
u.Credentials.AccessKey = user
|
u.Credentials.AccessKey = user
|
||||||
}
|
}
|
||||||
|
if u.Credentials.SessionToken != "" {
|
||||||
|
jwtClaims, err := extractJWTClaims(u)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
u.Credentials.Claims = jwtClaims.Map()
|
||||||
|
}
|
||||||
m[user] = u
|
m[user] = u
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -184,6 +184,14 @@ func (iamOS *IAMObjectStore) loadUser(ctx context.Context, user string, userType
|
|||||||
u.Credentials.AccessKey = user
|
u.Credentials.AccessKey = user
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if u.Credentials.SessionToken != "" {
|
||||||
|
jwtClaims, err := extractJWTClaims(u)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
u.Credentials.Claims = jwtClaims.Map()
|
||||||
|
}
|
||||||
|
|
||||||
m[user] = u
|
m[user] = u
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -33,6 +33,7 @@ import (
|
|||||||
"github.com/minio/minio-go/v7/pkg/set"
|
"github.com/minio/minio-go/v7/pkg/set"
|
||||||
"github.com/minio/minio/internal/auth"
|
"github.com/minio/minio/internal/auth"
|
||||||
"github.com/minio/minio/internal/config/identity/openid"
|
"github.com/minio/minio/internal/config/identity/openid"
|
||||||
|
"github.com/minio/minio/internal/jwt"
|
||||||
"github.com/minio/minio/internal/logger"
|
"github.com/minio/minio/internal/logger"
|
||||||
iampolicy "github.com/minio/pkg/iam/policy"
|
iampolicy "github.com/minio/pkg/iam/policy"
|
||||||
)
|
)
|
||||||
@ -76,8 +77,13 @@ const (
|
|||||||
iamFormatFile = "format.json"
|
iamFormatFile = "format.json"
|
||||||
|
|
||||||
iamFormatVersion1 = 1
|
iamFormatVersion1 = 1
|
||||||
|
|
||||||
|
minServiceAccountExpiry time.Duration = 15 * time.Minute
|
||||||
|
maxServiceAccountExpiry time.Duration = 365 * 24 * time.Hour
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var errInvalidSvcAcctExpiration = errors.New("invalid service account expiration")
|
||||||
|
|
||||||
type iamFormat struct {
|
type iamFormat struct {
|
||||||
Version int `json:"version"`
|
Version int `json:"version"`
|
||||||
}
|
}
|
||||||
@ -394,6 +400,19 @@ func (c *iamCache) policyDBGet(mode UsersSysType, name string, isGroup bool) ([]
|
|||||||
return policies, mp.UpdatedAt, nil
|
return policies, mp.UpdatedAt, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *iamCache) updateUserWithClaims(key string, u UserIdentity) error {
|
||||||
|
if u.Credentials.SessionToken != "" {
|
||||||
|
jwtClaims, err := extractJWTClaims(u)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
u.Credentials.Claims = jwtClaims.Map()
|
||||||
|
}
|
||||||
|
c.iamUsersMap[key] = u
|
||||||
|
c.updatedAt = time.Now()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// IAMStorageAPI defines an interface for the IAM persistence layer
|
// IAMStorageAPI defines an interface for the IAM persistence layer
|
||||||
type IAMStorageAPI interface {
|
type IAMStorageAPI interface {
|
||||||
// The role of the read-write lock is to prevent go routines from
|
// The role of the read-write lock is to prevent go routines from
|
||||||
@ -1749,14 +1768,15 @@ func (store *IAMStoreSys) DeleteUser(ctx context.Context, accessKey string, user
|
|||||||
if userType == regUser {
|
if userType == regUser {
|
||||||
for _, ui := range cache.iamUsersMap {
|
for _, ui := range cache.iamUsersMap {
|
||||||
u := ui.Credentials
|
u := ui.Credentials
|
||||||
if u.IsServiceAccount() && u.ParentUser == accessKey {
|
if u.ParentUser == accessKey {
|
||||||
_ = store.deleteUserIdentity(ctx, u.AccessKey, svcUser)
|
switch {
|
||||||
delete(cache.iamUsersMap, u.AccessKey)
|
case u.IsServiceAccount():
|
||||||
}
|
_ = store.deleteUserIdentity(ctx, u.AccessKey, svcUser)
|
||||||
// Delete any associated STS users.
|
delete(cache.iamUsersMap, u.AccessKey)
|
||||||
if u.IsTemp() && u.ParentUser == accessKey {
|
case u.IsTemp():
|
||||||
_ = store.deleteUserIdentity(ctx, u.AccessKey, stsUser)
|
_ = store.deleteUserIdentity(ctx, u.AccessKey, stsUser)
|
||||||
delete(cache.iamUsersMap, u.AccessKey)
|
delete(cache.iamUsersMap, u.AccessKey)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2106,8 +2126,9 @@ func (store *IAMStoreSys) SetUserStatus(ctx context.Context, accessKey string, s
|
|||||||
return updatedAt, err
|
return updatedAt, err
|
||||||
}
|
}
|
||||||
|
|
||||||
cache.iamUsersMap[accessKey] = uinfo
|
if err := cache.updateUserWithClaims(accessKey, uinfo); err != nil {
|
||||||
cache.updatedAt = time.Now()
|
return updatedAt, err
|
||||||
|
}
|
||||||
|
|
||||||
return uinfo.UpdatedAt, nil
|
return uinfo.UpdatedAt, nil
|
||||||
}
|
}
|
||||||
@ -2142,8 +2163,7 @@ func (store *IAMStoreSys) AddServiceAccount(ctx context.Context, cred auth.Crede
|
|||||||
return updatedAt, err
|
return updatedAt, err
|
||||||
}
|
}
|
||||||
|
|
||||||
cache.iamUsersMap[u.Credentials.AccessKey] = u
|
cache.updateUserWithClaims(u.Credentials.AccessKey, u)
|
||||||
cache.updatedAt = time.Now()
|
|
||||||
|
|
||||||
return u.UpdatedAt, nil
|
return u.UpdatedAt, nil
|
||||||
}
|
}
|
||||||
@ -2170,6 +2190,14 @@ func (store *IAMStoreSys) UpdateServiceAccount(ctx context.Context, accessKey st
|
|||||||
cr.Comment = opts.comment
|
cr.Comment = opts.comment
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if opts.expiration != nil {
|
||||||
|
expirationInUTC := opts.expiration.UTC()
|
||||||
|
if err := validateSvcExpirationInUTC(expirationInUTC); err != nil {
|
||||||
|
return updatedAt, err
|
||||||
|
}
|
||||||
|
cr.Expiration = expirationInUTC
|
||||||
|
}
|
||||||
|
|
||||||
switch opts.status {
|
switch opts.status {
|
||||||
// The caller did not ask to update status account, do nothing
|
// The caller did not ask to update status account, do nothing
|
||||||
case "":
|
case "":
|
||||||
@ -2229,8 +2257,9 @@ func (store *IAMStoreSys) UpdateServiceAccount(ctx context.Context, accessKey st
|
|||||||
return updatedAt, err
|
return updatedAt, err
|
||||||
}
|
}
|
||||||
|
|
||||||
cache.iamUsersMap[u.Credentials.AccessKey] = u
|
if err := cache.updateUserWithClaims(u.Credentials.AccessKey, u); err != nil {
|
||||||
cache.updatedAt = time.Now()
|
return updatedAt, err
|
||||||
|
}
|
||||||
|
|
||||||
return u.UpdatedAt, nil
|
return u.UpdatedAt, nil
|
||||||
}
|
}
|
||||||
@ -2331,8 +2360,9 @@ func (store *IAMStoreSys) AddUser(ctx context.Context, accessKey string, ureq ma
|
|||||||
if err := store.saveUserIdentity(ctx, accessKey, regUser, u); err != nil {
|
if err := store.saveUserIdentity(ctx, accessKey, regUser, u); err != nil {
|
||||||
return updatedAt, err
|
return updatedAt, err
|
||||||
}
|
}
|
||||||
|
if err := cache.updateUserWithClaims(accessKey, u); err != nil {
|
||||||
cache.iamUsersMap[accessKey] = u
|
return updatedAt, err
|
||||||
|
}
|
||||||
|
|
||||||
return u.UpdatedAt, nil
|
return u.UpdatedAt, nil
|
||||||
}
|
}
|
||||||
@ -2355,8 +2385,7 @@ func (store *IAMStoreSys) UpdateUserSecretKey(ctx context.Context, accessKey, se
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
cache.iamUsersMap[accessKey] = u
|
return cache.updateUserWithClaims(accessKey, u)
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetSTSAndServiceAccounts - returns all STS and Service account credentials.
|
// GetSTSAndServiceAccounts - returns all STS and Service account credentials.
|
||||||
@ -2393,8 +2422,8 @@ func (store *IAMStoreSys) UpdateUserIdentity(ctx context.Context, cred auth.Cred
|
|||||||
if err := store.saveUserIdentity(ctx, cred.AccessKey, userType, ui); err != nil {
|
if err := store.saveUserIdentity(ctx, cred.AccessKey, userType, ui); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
cache.iamUsersMap[cred.AccessKey] = ui
|
|
||||||
return nil
|
return cache.updateUserWithClaims(cred.AccessKey, ui)
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadUser - attempts to load user info from storage and updates cache.
|
// LoadUser - attempts to load user info from storage and updates cache.
|
||||||
@ -2437,3 +2466,25 @@ func (store *IAMStoreSys) LoadUser(ctx context.Context, accessKey string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func extractJWTClaims(u UserIdentity) (*jwt.MapClaims, error) {
|
||||||
|
jwtClaims, err := auth.ExtractClaims(u.Credentials.SessionToken, u.Credentials.SecretKey)
|
||||||
|
if err != nil {
|
||||||
|
// Session tokens for STS creds will be generated with root secret
|
||||||
|
jwtClaims, err = auth.ExtractClaims(u.Credentials.SessionToken, globalActiveCred.SecretKey)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return jwtClaims, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func validateSvcExpirationInUTC(expirationInUTC time.Time) error {
|
||||||
|
currentTime := time.Now().UTC()
|
||||||
|
minExpiration := currentTime.Add(minServiceAccountExpiry)
|
||||||
|
maxExpiration := currentTime.Add(maxServiceAccountExpiry)
|
||||||
|
if expirationInUTC.Before(minExpiration) || expirationInUTC.After(maxExpiration) {
|
||||||
|
return errInvalidSvcAcctExpiration
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
25
cmd/iam.go
25
cmd/iam.go
@ -933,6 +933,7 @@ type newServiceAccountOpts struct {
|
|||||||
accessKey string
|
accessKey string
|
||||||
secretKey string
|
secretKey string
|
||||||
comment string
|
comment string
|
||||||
|
expiration *time.Time
|
||||||
|
|
||||||
claims map[string]interface{}
|
claims map[string]interface{}
|
||||||
}
|
}
|
||||||
@ -1005,6 +1006,14 @@ func (sys *IAMSys) NewServiceAccount(ctx context.Context, parentUser string, gro
|
|||||||
cred.Status = string(auth.AccountOn)
|
cred.Status = string(auth.AccountOn)
|
||||||
cred.Comment = opts.comment
|
cred.Comment = opts.comment
|
||||||
|
|
||||||
|
if opts.expiration != nil {
|
||||||
|
expirationInUTC := opts.expiration.UTC()
|
||||||
|
if err := validateSvcExpirationInUTC(expirationInUTC); err != nil {
|
||||||
|
return auth.Credentials{}, time.Time{}, err
|
||||||
|
}
|
||||||
|
cred.Expiration = expirationInUTC
|
||||||
|
}
|
||||||
|
|
||||||
updatedAt, err := sys.store.AddServiceAccount(ctx, cred)
|
updatedAt, err := sys.store.AddServiceAccount(ctx, cred)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return auth.Credentials{}, time.Time{}, err
|
return auth.Credentials{}, time.Time{}, err
|
||||||
@ -1019,6 +1028,7 @@ type updateServiceAccountOpts struct {
|
|||||||
secretKey string
|
secretKey string
|
||||||
status string
|
status string
|
||||||
comment string
|
comment string
|
||||||
|
expiration *time.Time
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateServiceAccount - edit a service account
|
// UpdateServiceAccount - edit a service account
|
||||||
@ -1158,12 +1168,9 @@ func (sys *IAMSys) getAccountWithClaims(ctx context.Context, accessKey string) (
|
|||||||
return UserIdentity{}, nil, errNoSuchAccount
|
return UserIdentity{}, nil, errNoSuchAccount
|
||||||
}
|
}
|
||||||
|
|
||||||
jwtClaims, err := auth.ExtractClaims(acc.Credentials.SessionToken, acc.Credentials.SecretKey)
|
jwtClaims, err := extractJWTClaims(acc)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
jwtClaims, err = auth.ExtractClaims(acc.Credentials.SessionToken, globalActiveCred.SecretKey)
|
return UserIdentity{}, nil, err
|
||||||
if err != nil {
|
|
||||||
return UserIdentity{}, nil, err
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return acc, jwtClaims, nil
|
return acc, jwtClaims, nil
|
||||||
@ -1184,13 +1191,11 @@ func (sys *IAMSys) GetClaimsForSvcAcc(ctx context.Context, accessKey string) (ma
|
|||||||
return nil, errNoSuchServiceAccount
|
return nil, errNoSuchServiceAccount
|
||||||
}
|
}
|
||||||
|
|
||||||
jwtClaims, err := auth.ExtractClaims(sa.Credentials.SessionToken, sa.Credentials.SecretKey)
|
jwtClaims, err := extractJWTClaims(sa)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
jwtClaims, err = auth.ExtractClaims(sa.Credentials.SessionToken, globalActiveCred.SecretKey)
|
return nil, err
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return jwtClaims.Map(), nil
|
return jwtClaims.Map(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1219,6 +1219,7 @@ func (c *SiteReplicationSys) PeerSvcAccChangeHandler(ctx context.Context, change
|
|||||||
sessionPolicy: sp,
|
sessionPolicy: sp,
|
||||||
claims: change.Create.Claims,
|
claims: change.Create.Claims,
|
||||||
comment: change.Create.Comment,
|
comment: change.Create.Comment,
|
||||||
|
expiration: change.Create.Expiration,
|
||||||
}
|
}
|
||||||
_, _, err = globalIAMSys.NewServiceAccount(ctx, change.Create.Parent, change.Create.Groups, opts)
|
_, _, err = globalIAMSys.NewServiceAccount(ctx, change.Create.Parent, change.Create.Groups, opts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -1245,6 +1246,7 @@ func (c *SiteReplicationSys) PeerSvcAccChangeHandler(ctx context.Context, change
|
|||||||
status: change.Update.Status,
|
status: change.Update.Status,
|
||||||
comment: change.Update.Comment,
|
comment: change.Update.Comment,
|
||||||
sessionPolicy: sp,
|
sessionPolicy: sp,
|
||||||
|
expiration: change.Update.Expiration,
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = globalIAMSys.UpdateServiceAccount(ctx, change.Update.AccessKey, opts)
|
_, err = globalIAMSys.UpdateServiceAccount(ctx, change.Update.AccessKey, opts)
|
||||||
@ -1848,6 +1850,7 @@ func (c *SiteReplicationSys) syncToAllPeers(ctx context.Context) error {
|
|||||||
SessionPolicy: json.RawMessage(policyJSON),
|
SessionPolicy: json.RawMessage(policyJSON),
|
||||||
Status: acc.Credentials.Status,
|
Status: acc.Credentials.Status,
|
||||||
Comment: acc.Credentials.Comment,
|
Comment: acc.Credentials.Comment,
|
||||||
|
Expiration: &acc.Credentials.Expiration,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
UpdatedAt: acc.UpdatedAt,
|
UpdatedAt: acc.UpdatedAt,
|
||||||
@ -4716,6 +4719,7 @@ func (c *SiteReplicationSys) healUsers(ctx context.Context, objAPI ObjectLayer,
|
|||||||
SessionPolicy: json.RawMessage(policyJSON),
|
SessionPolicy: json.RawMessage(policyJSON),
|
||||||
Status: creds.Status,
|
Status: creds.Status,
|
||||||
Comment: creds.Comment,
|
Comment: creds.Comment,
|
||||||
|
Expiration: &creds.Expiration,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
UpdatedAt: lastUpdate,
|
UpdatedAt: lastUpdate,
|
||||||
|
1
go.mod
1
go.mod
@ -144,6 +144,7 @@ require (
|
|||||||
github.com/googleapis/gax-go/v2 v2.7.0 // indirect
|
github.com/googleapis/gax-go/v2 v2.7.0 // indirect
|
||||||
github.com/gorilla/websocket v1.5.0 // indirect
|
github.com/gorilla/websocket v1.5.0 // indirect
|
||||||
github.com/hashicorp/errwrap v1.1.0 // indirect
|
github.com/hashicorp/errwrap v1.1.0 // indirect
|
||||||
|
github.com/hashicorp/go-immutable-radix v1.3.1 // indirect
|
||||||
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
||||||
github.com/hashicorp/go-uuid v1.0.3 // indirect
|
github.com/hashicorp/go-uuid v1.0.3 // indirect
|
||||||
github.com/jcmturner/aescts/v2 v2.0.0 // indirect
|
github.com/jcmturner/aescts/v2 v2.0.0 // indirect
|
||||||
|
3
go.sum
3
go.sum
@ -580,8 +580,9 @@ github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtng
|
|||||||
github.com/hashicorp/go-hclog v0.9.1/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ=
|
github.com/hashicorp/go-hclog v0.9.1/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ=
|
||||||
github.com/hashicorp/go-hclog v1.1.0 h1:QsGcniKx5/LuX2eYoeL+Np3UKYPNaN7YKpTh29h8rbw=
|
github.com/hashicorp/go-hclog v1.1.0 h1:QsGcniKx5/LuX2eYoeL+Np3UKYPNaN7YKpTh29h8rbw=
|
||||||
github.com/hashicorp/go-hclog v1.1.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=
|
github.com/hashicorp/go-hclog v1.1.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=
|
||||||
github.com/hashicorp/go-immutable-radix v1.0.0 h1:AKDB1HM5PWEA7i4nhcpwOrO2byshxBjXVn/J/3+z5/0=
|
|
||||||
github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
|
github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
|
||||||
|
github.com/hashicorp/go-immutable-radix v1.3.1 h1:DKHmCUm2hRBK510BaiZlwvpD40f8bJFeZnpfm2KLowc=
|
||||||
|
github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
|
||||||
github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
|
github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
|
||||||
github.com/hashicorp/go-msgpack v0.5.5/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
|
github.com/hashicorp/go-msgpack v0.5.5/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
|
||||||
github.com/hashicorp/go-msgpack v1.1.5 h1:9byZdVjKTe5mce63pRVNP1L7UAmdHOTEMGehn6KvJWs=
|
github.com/hashicorp/go-msgpack v1.1.5 h1:9byZdVjKTe5mce63pRVNP1L7UAmdHOTEMGehn6KvJWs=
|
||||||
|
@ -88,6 +88,9 @@ var (
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// claim key found in credentials which are service accounts
|
||||||
|
const iamPolicyClaimNameSA = "sa-policy"
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// AccountOn indicates that credentials are enabled
|
// AccountOn indicates that credentials are enabled
|
||||||
AccountOn = "on"
|
AccountOn = "on"
|
||||||
@ -140,7 +143,8 @@ func (cred Credentials) IsTemp() bool {
|
|||||||
|
|
||||||
// IsServiceAccount - returns whether credential is a service account or not
|
// IsServiceAccount - returns whether credential is a service account or not
|
||||||
func (cred Credentials) IsServiceAccount() bool {
|
func (cred Credentials) IsServiceAccount() bool {
|
||||||
return cred.ParentUser != "" && (cred.Expiration.IsZero() || cred.Expiration.Equal(timeSentinel))
|
_, ok := cred.Claims[iamPolicyClaimNameSA]
|
||||||
|
return cred.ParentUser != "" && ok
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsValid - returns whether credential is valid or not.
|
// IsValid - returns whether credential is valid or not.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user