feat: create service accounts with same claims as parent (#13357)

allow claims from LDAP/OIDC to be inherited to service
accounts as well to allow dynamic policies.

fixes #13325
This commit is contained in:
Harshavardhana 2021-10-05 11:49:33 -07:00 committed by GitHub
parent 3d5750f31c
commit d7cb6de820
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 16 additions and 15 deletions

View File

@ -532,6 +532,7 @@ 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,
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
@ -565,16 +566,13 @@ func (a adminAPIHandlers) AddServiceAccount(w http.ResponseWriter, r *http.Reque
} }
targetGroups = requestorGroups targetGroups = requestorGroups
// In case of LDAP we need to set `opts.ldapUsername` to ensure // In case of LDAP/OIDC we need to set `opts.claims` to ensure
// it is associated with the LDAP user properly. We _only_ do // it is associated with the LDAP/OIDC user properly.
// this if this user is in LDAP (the other possibility is the for k, v := range cred.Claims {
// root user). if k == expClaim {
if globalLDAPConfig.Enabled { continue
v1, ok1 := cred.Claims[ldapUserN]
v2, ok2 := v1.(string)
if ok1 && ok2 {
opts.ldapUsername = v2
} }
opts.claims[k] = v
} }
} else { } else {
// Need permission if we are creating a service acccount for a // Need permission if we are creating a service acccount for a
@ -593,12 +591,13 @@ func (a adminAPIHandlers) AddServiceAccount(w http.ResponseWriter, r *http.Reque
// 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
// query their groups: // query their groups:
if globalLDAPConfig.Enabled { if globalLDAPConfig.Enabled {
opts.ldapUsername = targetUser opts.claims[ldapUserN] = targetUser // simple username
targetUser, targetGroups, err = globalLDAPConfig.LookupUserDN(targetUser) targetUser, targetGroups, err = globalLDAPConfig.LookupUserDN(targetUser)
if err != nil { if err != nil {
writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL) writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL)
return return
} }
opts.claims[ldapUser] = targetUser // username DN
} }
// NOTE: if not using LDAP, then internal IDP or open ID is // NOTE: if not using LDAP, then internal IDP or open ID is

View File

@ -1171,8 +1171,7 @@ type newServiceAccountOpts struct {
accessKey string accessKey string
secretKey string secretKey string
// LDAP username claims map[string]interface{}
ldapUsername string
} }
// NewServiceAccount - create a new service account // NewServiceAccount - create a new service account
@ -1260,9 +1259,12 @@ func (sys *IAMSys) NewServiceAccount(ctx context.Context, parentUser string, gro
m[iamPolicyClaimNameSA()] = "inherited-policy" m[iamPolicyClaimNameSA()] = "inherited-policy"
} }
// For LDAP service account, save the ldap username in the metadata. // Add all the necessary claims for the service accounts.
if opts.ldapUsername != "" { for k, v := range opts.claims {
m[ldapUserN] = opts.ldapUsername _, ok := m[k]
if !ok {
m[k] = v
}
} }
var ( var (