Skip to content

Commit

Permalink
Pull token fields from the ldap attributes instead of the old user
Browse files Browse the repository at this point in the history
  • Loading branch information
nflynt committed Aug 17, 2023
1 parent e33bba9 commit 064526f
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 21 deletions.
30 changes: 20 additions & 10 deletions pkg/agent/clean/adunmigration/ldap.go
Expand Up @@ -103,29 +103,38 @@ func escapeUUID(s string) string {
return buffer.String()
}

func findDistinguishedName(guid string, lConn *ldapv3.Conn, adConfig *v3.ActiveDirectoryConfig) (string, error) {
func findLdapUser(guid string, lConn *ldapv3.Conn, adConfig *v3.ActiveDirectoryConfig) (string, *v3.Principal, error) {
query := fmt.Sprintf("(&(%v=%v)(%v=%v))", AttributeObjectClass, adConfig.UserObjectClass, AttributeObjectGUID, escapeUUID(guid))
search := ldapv3.NewSearchRequest(adConfig.UserSearchBase, ldapv3.ScopeWholeSubtree, ldapv3.NeverDerefAliases,
0, 0, false,
query, ldap.GetUserSearchAttributes("memberOf", "objectClass", adConfig), nil)

result, err := lConn.Search(search)
if err != nil {
return "", err
return "", nil, err
}

if len(result.Entries) < 1 {
return "", LdapErrorNotFound{}
return "", nil, LdapErrorNotFound{}
} else if len(result.Entries) > 1 {
return "", LdapFoundDuplicateGUID{}
return "", nil, LdapFoundDuplicateGUID{}
}

//user, err := ldap.AttributesToPrincipal(entry.Attributes, result.Entries[0].DN, UserScope, Name,
// config.UserObjectClass, config.UserNameAttribute, config.UserLoginAttribute, config.GroupObjectClass, config.GroupNameAttribute)

entry := result.Entries[0]
distinguishedName := entry.DN
principal, err := ldap.AttributesToPrincipal(entry.Attributes, distinguishedName, activeDirectoryScope, activeDirecotryName,
adConfig.UserObjectClass, adConfig.UserNameAttribute, adConfig.UserLoginAttribute, adConfig.GroupObjectClass, adConfig.GroupNameAttribute)
if err != nil {
return "", nil, fmt.Errorf("failed to generate principal from ldap attributes")
}

return entry.DN, nil
return entry.DN, principal, nil
}

func findDistinguishedNameWithRetries(guid string, sLConn *sharedLdapConnection, adConfig *v3.ActiveDirectoryConfig) (string, error) {
func findLdapUserWithRetries(guid string, sLConn *sharedLdapConnection, adConfig *v3.ActiveDirectoryConfig) (string, *v3.Principal, error) {
// These settings range from 2 seconds for minor blips to around a full minute for repeated failures
backoff := wait.Backoff{
Duration: 2 * time.Second,
Expand All @@ -134,7 +143,8 @@ func findDistinguishedNameWithRetries(guid string, sLConn *sharedLdapConnection,
Steps: 10, // number of retries before we consider this failure to be permanent
}

distinguishedName := ""
var distinguishedName string
var principal *v3.Principal
err := wait.ExponentialBackoff(backoff, func() (finished bool, err error) {
if !sLConn.isOpen {
sLConn.lConn, err = ldapConnection(adConfig)
Expand All @@ -145,7 +155,7 @@ func findDistinguishedNameWithRetries(guid string, sLConn *sharedLdapConnection,
sLConn.isOpen = true
}

distinguishedName, err = findDistinguishedName(guid, sLConn.lConn, adConfig)
distinguishedName, principal, err = findLdapUser(guid, sLConn.lConn, adConfig)
if err == nil || errors.Is(err, LdapErrorNotFound{}) || errors.Is(err, LdapFoundDuplicateGUID{}) {
return true, err
}
Expand All @@ -159,7 +169,7 @@ func findDistinguishedNameWithRetries(guid string, sLConn *sharedLdapConnection,
return false, err
})

return distinguishedName, err
return distinguishedName, principal, err
}

func adConfiguration(sc *config.ScaledContext) (*v3.ActiveDirectoryConfig, error) {
Expand Down Expand Up @@ -374,7 +384,7 @@ func migrateAllowedUserPrincipals(workunits *[]migrateUserWorkUnit, missingUsers
logrus.Errorf("[%v] found invalid principal ID in allowed user list, refusing to process: %v", migrateAdUserOperation, err)
newPrincipalIDs = append(newPrincipalIDs, principalID)
} else {
dn, err := findDistinguishedNameWithRetries(guid, &sharedLConn, originalAdConfig)
dn, _, err := findLdapUserWithRetries(guid, &sharedLConn, originalAdConfig)
if errors.Is(err, LdapConnectionPermanentlyFailed{}) || errors.Is(err, LdapFoundDuplicateGUID{}) {
// Whelp; keep this one as-is and yell about it
logrus.Errorf("[%v] ldap connection error when checking distinguished name for guid-based principal %v, skipping: %v", migrateAdUserOperation, principalID, err)
Expand Down
6 changes: 4 additions & 2 deletions pkg/agent/clean/adunmigration/migrate.go
Expand Up @@ -32,6 +32,7 @@ const (
migrateCrtbsOperation = "migrate-ad-crtbs"
migratePrtbsOperation = "migrate-ad-prtbs"
migrateGrbsOperation = "migrate-ad-grbs"
activeDirecotryName = "activedirectory"
activeDirectoryScope = "activedirectory_user"
activeDirectoryPrefix = "activedirectory_user://"
localPrefix = "local://"
Expand All @@ -54,6 +55,7 @@ type migrateUserWorkUnit struct {
guid string
originalUser *v3.User
duplicateUsers []*v3.User
principal *v3.Principal

activeDirectoryCRTBs []v3.ClusterRoleTemplateBinding
duplicateLocalCRTBs []v3.ClusterRoleTemplateBinding
Expand Down Expand Up @@ -348,7 +350,7 @@ func identifyMigrationWorkUnits(users *v3.UserList, adConfig *v3.ActiveDirectory
missingUsers[i].duplicateUsers = append(missingUsers[i].duplicateUsers, userCopy)
continue
}
dn, err := findDistinguishedNameWithRetries(guid, &sharedLConn, adConfig)
dn, principal, err := findLdapUserWithRetries(guid, &sharedLConn, adConfig)
if errors.Is(err, LdapConnectionPermanentlyFailed{}) {
logrus.Warnf("[%v] LDAP connection has permanently failed! will continue to migrate previously identified users", identifyAdUserOperation)
skippedUsers = append(skippedUsers, skippedUserWorkUnit{guid: guid, originalUser: userCopy})
Expand All @@ -365,7 +367,7 @@ func identifyMigrationWorkUnits(users *v3.UserList, adConfig *v3.ActiveDirectory
knownGUIDWorkUnits[guid] = len(usersToMigrate)
knownDnWorkUnits[dn] = len(usersToMigrate)
var emptyDuplicateList []*v3.User
usersToMigrate = append(usersToMigrate, migrateUserWorkUnit{guid: guid, distinguishedName: dn, originalUser: userCopy, duplicateUsers: emptyDuplicateList})
usersToMigrate = append(usersToMigrate, migrateUserWorkUnit{guid: guid, distinguishedName: dn, principal: principal, originalUser: userCopy, duplicateUsers: emptyDuplicateList})
}
}
}
Expand Down
18 changes: 9 additions & 9 deletions pkg/agent/clean/adunmigration/tokens.go
Expand Up @@ -46,7 +46,7 @@ func collectTokens(workunits *[]migrateUserWorkUnit, sc *config.ScaledContext) e
return nil
}

func updateToken(tokenInterface v3norman.TokenInterface, userToken v3.Token, newPrincipalID string, guid string, originalUser *v3.User) error {
func updateToken(tokenInterface v3norman.TokenInterface, userToken v3.Token, newPrincipalID string, guid string, targetUser *v3.User, targetPrincipal *v3.Principal) error {
latestToken, err := tokenInterface.Get(userToken.Name, metav1.GetOptions{})
if err != nil {
logrus.Errorf("[%v] token %s no longer exists: %v", migrateTokensOperation, userToken.Name, err)
Expand All @@ -59,15 +59,15 @@ func updateToken(tokenInterface v3norman.TokenInterface, userToken v3.Token, new
if latestToken.Labels == nil {
latestToken.Labels = make(map[string]string)
}
latestToken.Labels[tokens.UserIDLabel] = originalUser.Name
latestToken.Labels[tokens.UserIDLabel] = targetUser.Name
latestToken.Labels[adGUIDMigrationLabel] = migratedLabelValue
// use the new dnPrincipalID for the token name
latestToken.UserPrincipal.Name = newPrincipalID
// copy over other relevant fields to match the originalUser we want to keep
latestToken.UserPrincipal.UID = originalUser.UID
latestToken.UserPrincipal.LoginName = originalUser.Username
latestToken.UserPrincipal.DisplayName = originalUser.DisplayName
latestToken.UserID = originalUser.Name
// copy over other relevant fields to match the user we are attaching this token to
latestToken.UserPrincipal.UID = targetUser.UID
latestToken.UserPrincipal.LoginName = targetPrincipal.LoginName
latestToken.UserPrincipal.DisplayName = targetPrincipal.DisplayName
latestToken.UserID = targetUser.Name

// If we get an internal error during any of these ops, there's a good chance the webhook is overwhelmed.
// We'll take the opportunity to rate limit ourselves and try again a few times.
Expand Down Expand Up @@ -107,7 +107,7 @@ func migrateTokens(workunit *migrateUserWorkUnit, sc *config.ScaledContext, dryR
"and a label, %v, to indicate that this token has been migrated",
migrateTokensOperation, userToken.Name, userToken.UserPrincipal.Name, dnPrincipalID, adGUIDMigrationAnnotation, adGUIDMigrationLabel)
} else {
err := updateToken(tokenInterface, userToken, dnPrincipalID, workunit.guid, workunit.originalUser)
err := updateToken(tokenInterface, userToken, dnPrincipalID, workunit.guid, workunit.originalUser, workunit.principal)
if err != nil {
logrus.Errorf("[%v] error while migrating tokens for user '%v': %v", migrateTokensOperation, workunit.originalUser.Name, err)
}
Expand All @@ -121,7 +121,7 @@ func migrateTokens(workunit *migrateUserWorkUnit, sc *config.ScaledContext, dryR
"Would add annotation, %v, and label, %v, to indicate migration status",
migrateTokensOperation, userToken.Name, userToken.UserPrincipal.Name, localPrincipalID, adGUIDMigrationAnnotation, adGUIDMigrationLabel)
} else {
err := updateToken(tokenInterface, userToken, localPrincipalID, workunit.guid, workunit.originalUser)
err := updateToken(tokenInterface, userToken, localPrincipalID, workunit.guid, workunit.originalUser, workunit.principal)
if err != nil {
logrus.Errorf("[%v] error while migrating tokens for user '%v': %v", migrateTokensOperation, workunit.originalUser.Name, err)
}
Expand Down

0 comments on commit 064526f

Please sign in to comment.