private async Task <string> GetEventsAsync(ComponentTask document) { var output = default(string); if (document.TaskState.IsActive() && AzureResourceIdentifier.TryParse(document.ResourceId, out var resourceId)) { try { var containerGroup = await azureResourceService .GetResourceAsync <AzureContainerGroupResource>(resourceId.ToString()) .ConfigureAwait(false); if (containerGroup is not null) { output = await containerGroup .GetEventContentAsync(document.Id) .ConfigureAwait(false); } } catch { // swallow } } return(output); }
public async Task RunActivity( [ActivityTrigger] IDurableActivityContext activityContext, ILogger log) { if (activityContext is null) { throw new ArgumentNullException(nameof(activityContext)); } var resourceId = activityContext.GetInput <string>(); try { var resource = await azureResourceService .GetResourceAsync(resourceId) .ConfigureAwait(false); await(resource?.DeleteAsync(true) ?? Task.CompletedTask) .ConfigureAwait(false); } catch (Exception exc) { log.LogError(exc, $"Activity '{nameof(ResourceDeleteActivity)} failed: {exc.Message}"); throw exc.AsSerializable(); } }
public async Task RunActivity( [ActivityTrigger] IDurableActivityContext functionContext, ILogger log) { if (functionContext is null) { throw new ArgumentNullException(nameof(functionContext)); } var(project, resourceId) = functionContext.GetInput <(Project, string)>(); using (log.BeginProjectScope(project)) { try { var resource = await azureResourceService .GetResourceAsync(resourceId, throwIfNotExists : true) .ConfigureAwait(false); await resource .SetTagsAsync(project.Tags) .ConfigureAwait(false); } catch (Exception exc) { log.LogError(exc, $"{nameof(ProjectResourceTagsActivity)} failed: {exc.Message}"); throw exc.AsSerializable(); } } }
public async Task RunActivity( [ActivityTrigger] IDurableActivityContext functionContext) { if (functionContext is null) { throw new ArgumentNullException(nameof(functionContext)); } var project = functionContext.GetInput <Project>(); var keyVault = await azureResourceService .GetResourceAsync <AzureKeyVaultResource>(project.KeyVault.VaultId, throwIfNotExists : true) .ConfigureAwait(false); var projectIdentityJson = await keyVault .GetSecretAsync(nameof(ProjectIdentity)) .ConfigureAwait(false); if (!string.IsNullOrEmpty(projectIdentityJson)) { await azureDirectoryService .DeleteServicePrincipalAsync(project.Id.ToString()) .ConfigureAwait(false); } await keyVault .SetSecretAsync(nameof(ProjectIdentity), null) .ConfigureAwait(false); }
public async Task RunActivity( [ActivityTrigger] IDurableActivityContext functionContext, ILogger log) { if (functionContext is null) { throw new ArgumentNullException(nameof(functionContext)); } var(project, resourceId) = functionContext.GetInput <(Project, string)>(); using (log.BeginProjectScope(project)) { try { var resource = await azureResourceService .GetResourceAsync(resourceId, throwIfNotExists : true) .ConfigureAwait(false); var roleAssignments = (project.Users ?? Enumerable.Empty <User>()) .ToDictionary(user => user.Id, user => Enumerable.Repeat((user.ProjectMembership(project.Id)?.Role ?? ProjectUserRole.None).ToRoleDefinitionId(), 1)); await resource .SetRoleAssignmentsAsync(roleAssignments) .ConfigureAwait(false); } catch (Exception exc) { log.LogError(exc, $"{nameof(ProjectUsersActivity)} failed: {exc.Message}"); throw exc.AsSerializable(); } } }
public async Task <ILogger> CreateLoggerAsync(ComponentTask componentTask, ILogger logger) { if (componentTask is null) { throw new ArgumentNullException(nameof(componentTask)); } logger ??= NullLogger.Instance; try { var project = await projectRepository .GetAsync(componentTask.Organization, componentTask.ProjectId) .ConfigureAwait(false); if (AzureResourceIdentifier.TryParse(project?.StorageId, out var storageId)) { var storageAccount = await azureResourceService .GetResourceAsync <AzureStorageAccountResource>(storageId.ToString(), false) .ConfigureAwait(false); if (storageAccount is not null) { var shareClient = await storageAccount .CreateShareClientAsync(componentTask.ComponentId) .ConfigureAwait(false); var directoryClient = shareClient .GetDirectoryClient(".output"); await directoryClient .CreateIfNotExistsAsync() .ConfigureAwait(false); var fileClient = directoryClient .GetFileClient($"{componentTask.Id}"); var fileStream = await fileClient .OpenWriteAsync(true, 0) .ConfigureAwait(false); return(new AdapterInitializationLogger(logger, fileStream)); } } } catch { // swallow } return(logger); }
public async Task <ISecretsStore> GetSecretsStoreAsync(Organization organization) { if (organization is null) { throw new ArgumentNullException(nameof(organization)); } if (string.IsNullOrEmpty(organization.SecretsVaultId)) { throw new ArgumentException($"Secrets vault not available.", nameof(organization)); } var keyVaultResource = await keyVaultResourceCache.GetOrAdd(organization.SecretsVaultId, (key) => new AsyncLazy <AzureKeyVaultResource>(async() => { var secretsVault = await azureResourceService .GetResourceAsync <AzureKeyVaultResource>(organization.SecretsVaultId, true) .ConfigureAwait(false); var identity = await azureResourceService.AzureSessionService .GetIdentityAsync() .ConfigureAwait(false); await secretsVault .SetAllSecretPermissionsAsync(identity.ObjectId) .ConfigureAwait(false); return(secretsVault); })).ConfigureAwait(false); try { return(ActivatorUtilities.CreateInstance <TSecretsStore>(serviceProvider, keyVaultResource)); } catch { throw; } }
public async Task RunActivity( [ActivityTrigger] IDurableActivityContext functionContext) { if (functionContext is null) { throw new ArgumentNullException(nameof(functionContext)); } var project = functionContext.GetInput <Project>(); var keyVault = await azureResourceService .GetResourceAsync <AzureKeyVaultResource>(project.KeyVault.VaultId, throwIfNotExists : true) .ConfigureAwait(false); var projectIdentityJson = await keyVault .GetSecretAsync(nameof(ProjectIdentity)) .ConfigureAwait(false); if (string.IsNullOrEmpty(projectIdentityJson)) { var servicePrincipal = await azureDirectoryService .CreateServicePrincipalAsync(project.Id.ToString()) .ConfigureAwait(false); try { var projectIdentity = new ProjectIdentity() { Id = servicePrincipal.ObjectId.ToString(), ApplicationId = servicePrincipal.ApplicationId, Secret = servicePrincipal.Password }; projectIdentityJson = JsonConvert.SerializeObject(projectIdentity); await keyVault .SetSecretAsync(nameof(ProjectIdentity), projectIdentityJson) .ConfigureAwait(false); } catch { await azureDirectoryService .DeleteServicePrincipalAsync(project.Id.ToString()) .ConfigureAwait(false); } } }
private async Task EnsureKeyVaultAccessAsync(Project project, Guid principalId) { var keyVault = await azureResourceService .GetResourceAsync <AzureKeyVaultResource>(project.KeyVault.VaultId, throwIfNotExists : true) .ConfigureAwait(false); if (keyVault != null) { var systemIdentity = await azureSessionService .GetIdentityAsync() .ConfigureAwait(false); if (systemIdentity.ObjectId == principalId) { await keyVault .SetAllCertificatePermissionsAsync(principalId) .ConfigureAwait(false); await keyVault .SetAllKeyPermissionsAsync(principalId) .ConfigureAwait(false); await keyVault .SetAllSecretPermissionsAsync(principalId) .ConfigureAwait(false); } else { await keyVault .SetCertificatePermissionsAsync(principalId, CertificatePermissions.Get, CertificatePermissions.List) .ConfigureAwait(false); await keyVault .SetKeyPermissionsAsync(principalId, KeyPermissions.Get, KeyPermissions.List) .ConfigureAwait(false); await keyVault .SetSecretPermissionsAsync(principalId, SecretPermissions.Get, SecretPermissions.List) .ConfigureAwait(false); } } }
public async Task RunActivity( [ActivityTrigger] IDurableActivityContext functionContext, ILogger log) { if (functionContext is null) { throw new ArgumentNullException(nameof(functionContext)); } var(project, resourceId) = functionContext.GetInput <(Project, string)>(); using (log.BeginProjectScope(project)) { try { var resource = await azureResourceService .GetResourceAsync(resourceId, throwIfNotExists : true) .ConfigureAwait(false); var roleAssignments = project.Users .ToRoleAssignments(project.Id, role => role == ProjectUserRole.Owner ? AzureRoleDefinition.Contributor : AzureRoleDefinition.Reader); await resource .SetRoleAssignmentsAsync(roleAssignments) .ConfigureAwait(false); } catch (Exception exc) { log.LogError(exc, $"{nameof(ProjectUsersActivity)} failed: {exc.Message}"); throw exc.AsSerializable(); } } }
private async Task <T> WithKubernetesContext <T>(Component component, DeploymentScope deploymentScope, Func <IKubernetes, KubernetesData, V1ClusterRole, V1ServiceAccount, Task <T> > callback) { if (component is null) { throw new ArgumentNullException(nameof(component)); } if (deploymentScope is null) { throw new ArgumentNullException(nameof(deploymentScope)); } if (callback is null) { throw new ArgumentNullException(nameof(callback)); } var identity = await azureResourceService .GetResourceAsync <AzureIdentityResource>(component.IdentityId, throwIfNotExists : true) .ConfigureAwait(false); var data = GetKubernetesData(deploymentScope); var client = GetKubernetesClient(data); var roleDefinition = new V1ClusterRole() { Metadata = new V1ObjectMeta() { Name = "teamcloud-runner" }, Rules = new List <V1PolicyRule>() { new V1PolicyRule() { ApiGroups = new List <string>() { "", "extensions", "apps" }, Resources = new List <string>() { "*" }, Verbs = new List <string>() { "*" } }, new V1PolicyRule() { ApiGroups = new List <string>() { "batch" }, Resources = new List <string>() { "jobs", "cronjobs" }, Verbs = new List <string>() { "*" } } } }; try { roleDefinition = await client .CreateClusterRoleAsync(roleDefinition) .ConfigureAwait(false); } catch (HttpOperationException exc) when(exc.Response.StatusCode == System.Net.HttpStatusCode.Conflict) { roleDefinition = await client .ReadClusterRoleAsync(roleDefinition.Metadata.Name) .ConfigureAwait(false); } var serviceAccount = new V1ServiceAccount() { Metadata = new V1ObjectMeta() { Name = $"{data.Namespace}-{identity.PrincipalId}" } }; try { serviceAccount = await client .CreateNamespacedServiceAccountAsync(serviceAccount, data.Namespace) .ConfigureAwait(false); } catch (HttpOperationException exc) when(exc.Response.StatusCode == System.Net.HttpStatusCode.Conflict) { serviceAccount = await client .ReadNamespacedServiceAccountAsync(serviceAccount.Metadata.Name, data.Namespace) .ConfigureAwait(false); } return(await callback(client, data, roleDefinition, serviceAccount).ConfigureAwait(false)); }
public async Task ExpandAsync(Component document) { if (document is null) { throw new ArgumentNullException(nameof(document)); } if (string.IsNullOrEmpty(document.ValueJson)) { var project = await projectRepository .GetAsync(document.Organization, document.ProjectId) .ConfigureAwait(false); if (AzureResourceIdentifier.TryParse(project?.StorageId, out var storageId)) { var cacheKey = $"{GetType()}|{document.GetType()}|{document.Id}"; try { var sasUrl = await cache .GetOrCreateAsync(cacheKey, AcquireSasUrl) .ConfigureAwait(false); if (sasUrl is null) { cache.Remove(cacheKey); } else { using var stream = await sasUrl.ToString() .WithHeader("responsecontent-disposition", "file; attachment") .WithHeader("responsecontent-type", "binary") .GetStreamAsync() .ConfigureAwait(false); if ((stream?.Length ?? 0) > 0) { using var reader = new StreamReader(stream); document.ValueJson = await reader .ReadToEndAsync() .ConfigureAwait(false); } } } catch { // swallow } } async Task <Uri> AcquireSasUrl(ICacheEntry entry) { var storageAccount = await azureResourceService .GetResourceAsync <AzureStorageAccountResource>(storageId.ToString(), false) .ConfigureAwait(false); if (storageAccount is null) { return(null); } entry.AbsoluteExpiration = DateTimeOffset.UtcNow.AddDays(1); return(await storageAccount .CreateShareFileSasUriAsync(document.Id, "value.json", ShareFileSasPermissions.Read, entry.AbsoluteExpiration.Value.AddMinutes(5)) .ConfigureAwait(false)); } } }
public override async Task <ICommandResult> HandleAsync(ComponentTaskCancelCommand 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(); try { commandResult.Result = (await componentTaskRepository .GetAsync(command.Payload.ComponentId, command.Payload.Id) .ConfigureAwait(Orchestration)) ?? command.Payload; if (commandResult.Result.Type != ComponentTaskType.Custom) { throw new Exception($"Component tasks of type '{commandResult.Result.TypeName}' cannot be canceled!"); } else if (commandResult.Result.TaskState.IsFinal()) { throw new Exception($"Component tasks in state '{commandResult.Result.TaskState}' cannot be canceled!"); } else { var status = await orchestrationContext .GetCommandStatusAsync(commandResult.Result, showInput : false) .ConfigureAwait(Orchestration); if (status is not null && status.RuntimeStatus.IsActive()) { await orchestrationContext .TerminateCommandAsync(commandResult.Result, $"Canceled by user {command.User.DisplayName}") .ConfigureAwait(Orchestration); } if (AzureResourceIdentifier.TryParse(commandResult.Result.ResourceId, out var resourceId)) { var containerGroup = await azureResourceService .GetResourceAsync <AzureContainerGroupResource>(resourceId.ToString()) .ConfigureAwait(false); if (containerGroup is not null) { await containerGroup .DeleteAsync(true) .ConfigureAwait(false); } } commandResult.Result.TaskState = TaskState.Canceled; commandResult.Result.Finished = DateTime.UtcNow; commandResult.Result.ResourceId = null; commandResult.Result = await componentTaskRepository .SetAsync(commandResult.Result) .ConfigureAwait(Orchestration); } commandResult.RuntimeStatus = CommandRuntimeStatus.Completed; } catch (Exception exc) { commandResult.Errors.Add(exc); } finally { await orchestrationContext .CleanupResourceLocksAsync() .ConfigureAwait(Orchestration); } return(commandResult); }