public async Task Run([TimerTrigger("0 */2 * * * *")] TimerInfo myTimer, ILogger log) { _ = myTimer; // unused but required for attribute log.LogInformation($"C# Timer trigger function executed at: {DateTime.Now}"); var toRekey = await RekeyingTasks.GetAsync(t => (t.ConfirmationType == TaskConfirmationStrategies.AdminCachesSignOff || t.ConfirmationType == TaskConfirmationStrategies.AutomaticRekeyingAsNeeded || t.ConfirmationType == TaskConfirmationStrategies.AutomaticRekeyingScheduled) && DateTimeOffset.UtcNow + TimeSpan.FromHours(ServiceConfiguration.AutomaticRekeyableJustInTimeLeadTimeHours) > t.Expiry); foreach (var task in toRekey) { task.RekeyingInProgress = true; await RekeyingTasks.UpdateAsync(task); var aggregatedStringLogger = new RekeyingAttemptLogger(log) { UserDisplayName = "Agent Identity", UserEmail = string.Empty }; await ExecuteRekeyingWorkflow(task, aggregatedStringLogger); task.RekeyingInProgress = false; task.RekeyingCompleted = aggregatedStringLogger.IsSuccessfulAttempt; task.RekeyingFailed = !aggregatedStringLogger.IsSuccessfulAttempt; task.Attempts.Add(aggregatedStringLogger); await RekeyingTasks.UpdateAsync(task); } }
public async Task <IActionResult> Run( [HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = "secrets/{managedSecretId:guid}/{nonce}")] HttpRequest req, Guid managedSecretId, string nonce, ILogger log) { _ = req; // unused but required for attribute log.LogInformation("External signal called to check ManagedSecret ID {0} against nonce {1}", managedSecretId, nonce); var secret = await ManagedSecrets.GetAsync(managedSecretId); if (secret == null) { return(new BadRequestErrorMessageResult("Invalid ManagedSecret ID")); } if (!secret.TaskConfirmationStrategies.HasFlag(TaskConfirmationStrategies.ExternalSignal)) { return(new BadRequestErrorMessageResult("This ManagedSecret cannot be used with External Signals")); } if ((await RekeyingTasks.GetAsync(t => t.ManagedSecretId == secret.ObjectId)) .Any(t => t.RekeyingInProgress)) { return(new OkObjectResult(RETURN_RETRY_SHORTLY)); } if ((secret.IsValid && secret.TimeRemaining <= TimeSpan.FromHours(ServiceConfiguration.ExternalSignalRekeyableLeadTimeHours)) || !secret.IsValid) { var rekeyingTask = new Task(async() => { var task = new RekeyingTask() { ManagedSecretId = secret.ObjectId, Expiry = secret.Expiry, Queued = DateTimeOffset.UtcNow, RekeyingInProgress = true }; await RekeyingTasks.CreateAsync(task); var rekeyingAttemptLogger = new RekeyingAttemptLogger(log) { UserDisplayName = "Agent Identity", UserEmail = string.Empty }; try { await ExecuteRekeyingWorkflow(task, rekeyingAttemptLogger); } catch (Exception ex) { rekeyingAttemptLogger.OuterException = JsonConvert.SerializeObject(ex, Formatting.Indented); } task.RekeyingInProgress = false; task.RekeyingCompleted = rekeyingAttemptLogger.IsSuccessfulAttempt; task.RekeyingFailed = !rekeyingAttemptLogger.IsSuccessfulAttempt; task.Attempts.Add(rekeyingAttemptLogger); await RekeyingTasks.UpdateAsync(task); }, TaskCreationOptions.LongRunning); rekeyingTask.Start(); if (!rekeyingTask.Wait(TimeSpan.FromSeconds(MAX_EXECUTION_SECONDS_BEFORE_RETRY))) { log.LogInformation("Rekeying workflow was started but exceeded the maximum request time! ({0})", TimeSpan.FromSeconds(MAX_EXECUTION_SECONDS_BEFORE_RETRY)); return(new OkObjectResult(RETURN_RETRY_SHORTLY)); } else { log.LogInformation("Completed rekeying workflow within maximum time! ({0})", TimeSpan.FromSeconds(MAX_EXECUTION_SECONDS_BEFORE_RETRY)); return(new OkObjectResult(RETURN_CHANGE_OCCURRED)); } } return(new OkObjectResult(RETURN_NO_CHANGE)); }