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);
            }
        }
Example #2
0
        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));
        }