public async Task <ICommandResult> HandleAsync(ProjectIdentityCreateCommand command, IAsyncCollector <ICommand> commandQueue, IDurableOrchestrationContext orchestrationContext, ILogger log) { if (command is null) { throw new ArgumentNullException(nameof(command)); } if (commandQueue is null) { throw new ArgumentNullException(nameof(commandQueue)); } var commandResult = command.CreateResult(); var projectIdentity = command.Payload; try { var servicePrincipal = await graphService .CreateServicePrincipalAsync(projectIdentity.Id) .ConfigureAwait(false); projectIdentity.ObjectId = servicePrincipal.Id; projectIdentity.TenantId = servicePrincipal.TenantId; projectIdentity.ClientId = servicePrincipal.AppId; projectIdentity.ClientSecret = servicePrincipal.Password; if (projectIdentity.RedirectUrls is not null) { projectIdentity.RedirectUrls = await graphService .SetServicePrincipalRedirectUrlsAsync(projectIdentity.ObjectId.ToString(), projectIdentity.RedirectUrls) .ConfigureAwait(false); } commandResult.Result = await projectIdentityRepository .AddAsync(projectIdentity) .ConfigureAwait(false); commandResult.RuntimeStatus = CommandRuntimeStatus.Completed; } catch (Exception exc) { await commandQueue .AddAsync(new ProjectIdentityDeleteCommand(command.User, projectIdentity)) .ConfigureAwait(false); commandResult.Errors.Add(exc); } return(commandResult); }
#pragma warning restore CS0618 // Type or member is obsolete public virtual async Task <AzureServicePrincipal> GetServiceIdentityAsync(Component component, bool withPassword = false) { if (this is IAdapterIdentity) { var servicePrincipalKey = Guid.Parse(component.Organization) .Combine(Guid.Parse(component.DeploymentScopeId), Guid.Parse(component.ProjectId)); var servicePrincipalName = $"{this.GetType().Name}/{servicePrincipalKey}"; var servicePrincipal = await graphService .GetServicePrincipalAsync(servicePrincipalName) .ConfigureAwait(false); if (servicePrincipal is null) { // there is no service principal for the current deployment scope // create a new one that we can use to create/update the corresponding // service endpoint in the current team project servicePrincipal = await graphService .CreateServicePrincipalAsync(servicePrincipalName) .ConfigureAwait(false); } else if (servicePrincipal.ExpiresOn.GetValueOrDefault(DateTime.MinValue) < DateTime.UtcNow) { // a service principal exists, but its secret is expired. lets refresh // the service principal (create a new secret) so we can move on // creating/updating the corresponding service endpoint. servicePrincipal = await graphService .RefreshServicePrincipalAsync(servicePrincipalName) .ConfigureAwait(false); } if (!string.IsNullOrEmpty(servicePrincipal.Password)) { var project = await projectRepository .GetAsync(component.Organization, component.ProjectId) .ConfigureAwait(false); var secretsStore = await secretsStoreProvider .GetSecretsStoreAsync(project) .ConfigureAwait(false); servicePrincipal = await secretsStore .SetSecretAsync(servicePrincipal.Id.ToString(), servicePrincipal) .ConfigureAwait(false); } else if (withPassword) { var project = await projectRepository .GetAsync(component.Organization, component.ProjectId) .ConfigureAwait(false); var secretsStore = await secretsStoreProvider .GetSecretsStoreAsync(project) .ConfigureAwait(false); servicePrincipal = (await secretsStore .GetSecretAsync <AzureServicePrincipal>(servicePrincipal.Id.ToString()) .ConfigureAwait(false)) ?? servicePrincipal; } return(servicePrincipal); } return(null); }