public ExternalGroupResult Read(IUser user, CancellationToken cancellationToken) { if (!configurationStore.GetIsEnabled() || !configurationStore.GetAreSecurityGroupsEnabled()) { return(new ExternalGroupResult(DirectoryServicesAuthentication.ProviderName, "Not enabled")); } if (user.Username == User.GuestLogin) { return(new ExternalGroupResult(DirectoryServicesAuthentication.ProviderName, "Not valid for Guest user")); } if (user.Identities.All(p => p.IdentityProviderName != DirectoryServicesAuthentication.ProviderName)) { return(new ExternalGroupResult(DirectoryServicesAuthentication.ProviderName, "No identities matching this provider")); } // if the user has multiple, unique identities assigned then the group list should be the distinct union of the groups from // all of the identities var wasAbleToRetrieveSomeGroups = false; var newGroups = new HashSet <string>(); var adIdentities = user.Identities.Where(p => p.IdentityProviderName == DirectoryServicesAuthentication.ProviderName); foreach (var adIdentity in adIdentities) { var samAccountName = adIdentity.Claims[IdentityCreator.SamAccountNameClaimType].Value; var result = groupLocator.GetGroupIdsForUser(samAccountName, cancellationToken); if (result.WasAbleToRetrieveGroups) { foreach (var groupId in result.GroupsIds.Where(g => !newGroups.Contains(g))) { newGroups.Add(groupId); } wasAbleToRetrieveSomeGroups = true; } else { log.WarnFormat("Couldn't retrieve groups for samAccountName {0}", samAccountName); } } if (!wasAbleToRetrieveSomeGroups) { log.ErrorFormat("Couldn't retrieve groups for user {0}", user.Username); return(new ExternalGroupResult(DirectoryServicesAuthentication.ProviderName, $"Couldn't retrieve groups for user {user.Username}")); } return(new ExternalGroupResult(DirectoryServicesAuthentication.ProviderName, newGroups.Select(g => g).ToArray())); }
public HashSet <string> EnsureExternalSecurityGroupsAreUpToDate(IUser user, bool forceRefresh = false) { if (!configurationStore.GetIsEnabled() || !configurationStore.GetAreSecurityGroupsEnabled() || string.IsNullOrWhiteSpace(user.ExternalId)) { return(new HashSet <string>()); } // We will retrieve the user's external groups when they initially log in. We can also refresh // them in the background periodically. This is to cater for environments where the group // membership is managed outside of Octopus Deploy, e.g. Active Directory, and we need to balance // performance vs keeping the group list up to date. if (forceRefresh || expiryChecker.ShouldFetchExternalGroups(user)) { try { var result = groupLocator.GetGroupIdsForUser(user.ExternalId); if (!result.WasAbleToRetrieveGroups) { return(new HashSet <string>()); } var newGroups = new HashSet <string>(result.GroupsIds, StringComparer.OrdinalIgnoreCase); userStore.UpdateUsersExternalGroups(user, newGroups); return(newGroups); } catch (Exception ex) { LogWarning(user, ex, "foreground loading"); } } else if (expiryChecker.ShouldFetchExternalGroupsInBackground(user)) { RefreshMemberExternalSecurityGroups(user); } return(new HashSet <string>()); }