private async Task CreateAndNotify(IEnumerable <RekeyingTask> tasks) { if (!tasks.Any()) { return; } await Task.WhenAll(tasks.Select(t => RekeyingTasks.CreateAsync(t))); foreach (var task in tasks) { var secret = await ManagedSecrets.GetAsync(task.ManagedSecretId); if (task.ConfirmationType == TaskConfirmationStrategies.AdminCachesSignOff || task.ConfirmationType == TaskConfirmationStrategies.AdminSignsOffJustInTime) { await NotificationProvider.DispatchNotification_AdminApprovalRequiredTaskCreated( secret.AdminEmails.ToArray(), task); } else if (task.ConfirmationType == TaskConfirmationStrategies.AutomaticRekeyingAsNeeded || task.ConfirmationType == TaskConfirmationStrategies.AutomaticRekeyingScheduled) { await NotificationProvider.DispatchNotification_AutoRekeyingTaskCreated( secret.AdminEmails.ToArray(), task); } } }
public async Task <IActionResult> List( [HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "tasks")] HttpRequest req, ILogger log) { if (!req.IsValidUser()) { return(new UnauthorizedResult()); } log.LogInformation("List all Tasks."); return(new OkObjectResult((await RekeyingTasks.ListAsync()).Select(t => GetViewModel(t)))); }
public async Task <IActionResult> Get( [HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "tasks/{taskId:guid}")] HttpRequest req, Guid taskId, ILogger log) { if (!req.IsValidUser()) { return(new UnauthorizedResult()); } log.LogInformation("Preview Actions for Task ID {0}.", taskId); return(new OkObjectResult(GetViewModel((await RekeyingTasks.GetAsync(taskId))))); }
private async Task <List <ManagedSecret> > GetSecretsForRekeyingTask( TaskConfirmationStrategies taskConfirmationStrategies, int leadTimeHours) { var secretsToRotate = await ManagedSecrets.GetAsync(s => s.TaskConfirmationStrategies.HasFlag(taskConfirmationStrategies) && s.Expiry < DateTimeOffset.UtcNow + TimeSpan.FromHours(leadTimeHours)); var rekeyingTasks = await RekeyingTasks.ListAsync(); return(secretsToRotate .Where(s => !rekeyingTasks.Any(t => t.ManagedSecretId == s.ObjectId && !t.RekeyingCompleted)) .ToList()); }
public async Task <IActionResult> Delete( [HttpTrigger(AuthorizationLevel.Anonymous, "delete", Route = "tasks/{taskId:guid}")] HttpRequest req, Guid taskId, ILogger log) { if (!req.IsValidUser(AuthJanitorRoles.ServiceOperator, AuthJanitorRoles.GlobalAdmin)) { return(new UnauthorizedResult()); } log.LogInformation("Deleting Task ID {0}.", taskId); if (!await RekeyingTasks.ContainsIdAsync(taskId)) { return(new BadRequestErrorMessageResult("Task not found!")); } await RekeyingTasks.DeleteAsync(taskId); return(new OkResult()); }
public async Task <IActionResult> Create( [HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = "tasks")] string secretId, HttpRequest req, ILogger log) { if (!req.IsValidUser(AuthJanitorRoles.ServiceOperator, AuthJanitorRoles.GlobalAdmin)) { return(new UnauthorizedResult()); } log.LogInformation("Creating new Task."); if (!await ManagedSecrets.ContainsIdAsync(Guid.Parse(secretId))) { return(new BadRequestErrorMessageResult("Invalid Managed Secret ID")); } var secret = await ManagedSecrets.GetAsync(Guid.Parse(secretId)); if (!secret.TaskConfirmationStrategies.HasFlag(TaskConfirmationStrategies.AdminCachesSignOff) && !secret.TaskConfirmationStrategies.HasFlag(TaskConfirmationStrategies.AdminSignsOffJustInTime)) { return(new BadRequestErrorMessageResult("Managed Secret does not support administrator approval!")); } RekeyingTask newTask = new RekeyingTask() { Queued = DateTimeOffset.UtcNow, Expiry = secret.Expiry, ManagedSecretId = secret.ObjectId }; await RekeyingTasks.CreateAsync(newTask); return(new OkObjectResult(newTask)); }
public async Task <IActionResult> Run( [HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "dashboard")] HttpRequest req, ClaimsPrincipal claimsPrincipal, ILogger log) { if (!req.IsValidUser()) { return(new UnauthorizedResult()); } log.LogInformation("Requested Dashboard metrics"); var allSecrets = await ManagedSecrets.ListAsync(); var allResources = await Resources.ListAsync(); var allTasks = await RekeyingTasks.ListAsync(); var expiringInNextWeek = allSecrets.Where(s => DateTimeOffset.UtcNow.AddDays(7) < (s.LastChanged + s.ValidPeriod)); var expired = allSecrets.Where(s => !s.IsValid); var metrics = new DashboardMetricsViewModel() { SignedInName = claimsPrincipal.FindFirst(ClaimTypes.GivenName)?.Value + " " + claimsPrincipal.FindFirst(ClaimTypes.Surname)?.Value, SignedInEmail = claimsPrincipal.FindFirst(ClaimTypes.Email)?.Value, SignedInRole = AuthJanitorRoleExtensions.GetUserRole(req), TotalResources = allResources.Count, TotalSecrets = allSecrets.Count, TotalPendingApproval = allTasks.Where(t => t.ConfirmationType.HasFlag(TaskConfirmationStrategies.AdminCachesSignOff) || t.ConfirmationType.HasFlag(TaskConfirmationStrategies.AdminSignsOffJustInTime)).Count(), TotalExpiringSoon = expiringInNextWeek.Count(), TotalExpired = expired.Count(), ExpiringSoon = expiringInNextWeek.Select(s => GetViewModel(s)), PercentExpired = (int)((double)expired.Count() / allSecrets.Count) * 100, TasksInError = allTasks.Count(t => t.RekeyingFailed) }; foreach (var secret in allSecrets) { var riskScore = 0; foreach (var resourceId in secret.ResourceIds) { var resource = allResources.FirstOrDefault(r => r.ObjectId == resourceId); var provider = GetProvider(new RekeyingAttemptLogger(log), resource.ProviderType, resource.ProviderConfiguration); riskScore += provider.GetRisks(secret.ValidPeriod).Sum(r => r.Score); } if (riskScore > 85) { metrics.RiskOver85++; } else if (riskScore > 60) { metrics.Risk85++; } else if (riskScore > 35) { metrics.Risk60++; } else if (riskScore > 0) { metrics.Risk35++; } else if (riskScore == 0) { metrics.Risk0++; } } return(new OkObjectResult(metrics)); }
public async Task <IActionResult> Approve( [HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = "tasks/{taskId:guid}/approve")] HttpRequest req, Guid taskId, ClaimsPrincipal claimsPrincipal, ILogger log) { if (!req.IsValidUser(AuthJanitorRoles.ServiceOperator, AuthJanitorRoles.GlobalAdmin)) { return(new UnauthorizedResult()); } log.LogInformation("Administrator approved Task ID {0}", taskId); var task = await RekeyingTasks.GetAsync(taskId); log.LogInformation("Registering incoming user credential..."); try { await RegisterUserCredential(req); } catch (Exception ex) { var logger = new RekeyingAttemptLogger(); logger.LogCritical(ex, "Error registering user credential!"); task.Attempts.Add(logger); await RekeyingTasks.UpdateAsync(task); return(new BadRequestErrorMessageResult(ex.Message)); } if (task.ConfirmationType == TaskConfirmationStrategies.AdminCachesSignOff) { var credential = CredentialProvider.Get(MultiCredentialProvider.CredentialType.UserCredential); var persisted = await SecureStorageProvider.Persist <Azure.Core.AccessToken>( credential.Expiry, new Azure.Core.AccessToken(credential.AccessToken, credential.Expiry)); task.PersistedCredentialId = persisted; task.PersistedCredentialUser = credential.Username; await RekeyingTasks.UpdateAsync(task); return(new OkResult()); } else if (task.ConfirmationType == TaskConfirmationStrategies.AdminSignsOffJustInTime) { task.RekeyingInProgress = true; await RekeyingTasks.UpdateAsync(task); var aggregatedStringLogger = new RekeyingAttemptLogger(log) { UserDisplayName = claimsPrincipal.FindFirst(ClaimTypes.GivenName)?.Value + " " + claimsPrincipal.FindFirst(ClaimTypes.Surname)?.Value, UserEmail = claimsPrincipal.FindFirst(ClaimTypes.Email)?.Value }; try { await ExecuteRekeyingWorkflow(task, aggregatedStringLogger); task.RekeyingInProgress = false; task.RekeyingCompleted = aggregatedStringLogger.IsSuccessfulAttempt; task.RekeyingFailed = !aggregatedStringLogger.IsSuccessfulAttempt; } catch (Exception ex) { task.RekeyingInProgress = false; task.RekeyingCompleted = false; task.RekeyingFailed = true; if (aggregatedStringLogger.OuterException == null) { aggregatedStringLogger.OuterException = JsonConvert.SerializeObject(ex, Formatting.Indented); } } task.Attempts.Add(aggregatedStringLogger); await RekeyingTasks.UpdateAsync(task); if (task.RekeyingFailed) { return(new BadRequestErrorMessageResult(aggregatedStringLogger.OuterException)); } else { return(new OkResult()); } } else { log.LogError("Task does not support an Administrator's approval!"); return(new BadRequestErrorMessageResult("Task does not support an Administrator's approval!")); } }