public async Task <IActionResult> TestConfiguration(
            string providerConfiguration,
            HttpRequest req,
            string providerType,
            string testContext)
        {
            _ = req;

            if (!_identityService.IsUserLoggedIn)
            {
                return(new UnauthorizedResult());
            }

            Enum.TryParse <TestAsContexts>(testContext, true, out TestAsContexts testContextEnum);
            AccessTokenCredential credential = null;

            try
            {
                switch (testContextEnum)
                {
                case TestAsContexts.AsApp:
                    credential = await _identityService.GetAccessTokenForApplicationAsync();

                    break;

                case TestAsContexts.AsUser:
                    credential = await _identityService.GetAccessTokenOnBehalfOfCurrentUserAsync();

                    break;

                default:
                    return(new BadRequestErrorMessageResult("Invalid test context"));
                }
                if (credential == null || string.IsNullOrEmpty(credential.AccessToken))
                {
                    throw new Exception("Credential was empty!");
                }
            }
            catch (Exception ex)
            {
                return(new BadRequestErrorMessageResult(
                           "Error retrieving Access Token: " + Environment.NewLine +
                           ex.Message + Environment.NewLine +
                           ex.StackTrace));
            }

            var provider = _providerManager.LoadedProviders.FirstOrDefault(p => p.ProviderTypeName == providerType);

            if (provider == null)
            {
                await _eventDispatcher.DispatchEvent(AuthJanitorSystemEvents.AnomalousEventOccurred, nameof(ProvidersService.GetBlankConfiguration), "Invalid Provider specified");

                return(new NotFoundResult());
            }

            if (typeof(ICanRunSanityTests).IsAssignableFrom(provider.ProviderType))
            {
                try
                {
                    var instance = _providerManager.GetProviderInstance(provider.ProviderTypeName, providerConfiguration);
                    if (instance == null)
                    {
                        return(new BadRequestErrorMessageResult("Provider configuration is invalid!"));
                    }
                    instance.Credential = credential;
                    await(instance as ICanRunSanityTests).Test();
                }
                catch (Exception ex)
                {
                    return(new BadRequestErrorMessageResult(ex.Message));
                }
            }
            else
            {
                return(new BadRequestErrorMessageResult("Provider does not support testing!"));
            }

            return(new OkResult());
        }
        public async Task ExecuteTask(Guid taskId, CancellationToken cancellationToken)
        {
            // Prepare record
            var task = await _rekeyingTasks.GetOne(taskId, cancellationToken);

            task.RekeyingInProgress = true;
            var rekeyingAttemptLog = new RekeyingAttemptLogger();

            task.Attempts.Add(rekeyingAttemptLog);
            await _rekeyingTasks.Update(task, cancellationToken);

            var logUpdateCancellationTokenSource = new CancellationTokenSource();
            var logUpdateTask = Task.Run(async() =>
            {
                while (task.RekeyingInProgress)
                {
                    await Task.Delay(15 * 1000);
                    await _rekeyingTasks.Update(task, cancellationToken);
                }
            }, logUpdateCancellationTokenSource.Token);

            // Retrieve credentials for Task
            AccessTokenCredential credential = null;

            try
            {
                if (task.ConfirmationType == TaskConfirmationStrategies.AdminCachesSignOff)
                {
                    if (task.PersistedCredentialId == default)
                    {
                        throw new KeyNotFoundException("Cached sign-off is preferred but no credentials were persisted!");
                    }

                    if (_secureStorageProvider == null)
                    {
                        throw new NotSupportedException("Must register an ISecureStorageProvider");
                    }

                    credential = await _secureStorageProvider.Retrieve <AccessTokenCredential>(task.PersistedCredentialId);
                }
                else if (task.ConfirmationType == TaskConfirmationStrategies.AdminSignsOffJustInTime)
                {
                    credential = await _identityService.GetAccessTokenOnBehalfOfCurrentUserAsync();
                }
                else if (task.ConfirmationType.UsesServicePrincipal())
                {
                    credential = await _identityService.GetAccessTokenForApplicationAsync();
                }
                else
                {
                    throw new NotSupportedException("No Access Tokens could be generated for this Task!");
                }

                if (credential == null || string.IsNullOrEmpty(credential.AccessToken))
                {
                    throw new InvalidOperationException("Access Token was found, but was blank or invalid");
                }
            }
            catch (Exception ex)
            {
                await EmbedException(task, ex, cancellationToken, "Exception retrieving Access Token");

                await _eventDispatcherMetaService.DispatchEvent(AuthJanitorSystemEvents.RotationTaskAttemptFailed, nameof(TaskExecutionMetaService.ExecuteTask), task);

                return;
            }

            // Embed credential context in attempt log
            rekeyingAttemptLog.UserDisplayName = credential.Username;
            rekeyingAttemptLog.UserEmail       = credential.Username;
            if (task.ConfirmationType.UsesOBOTokens())
            {
                if (!string.IsNullOrEmpty(task.PersistedCredentialUser))
                {
                    rekeyingAttemptLog.UserDisplayName = task.PersistedCredentialUser;
                }
                else
                {
                    rekeyingAttemptLog.UserDisplayName = _identityService.UserName;
                    rekeyingAttemptLog.UserEmail       = _identityService.UserEmail;
                }
            }

            // Retrieve targets
            var secret = await _managedSecrets.GetOne(task.ManagedSecretId, cancellationToken);

            rekeyingAttemptLog.LogInformation("Beginning rekeying of secret ID {SecretId}", task.ManagedSecretId);
            var resources = await _resources.Get(r => secret.ResourceIds.Contains(r.ObjectId), cancellationToken);

            await _rekeyingTasks.Update(task, cancellationToken);

            // Execute rekeying workflow
            try
            {
                var providers = resources.Select(r => _providerManagerService.GetProviderInstance(
                                                     r.ProviderType,
                                                     r.ProviderConfiguration)).ToList();

                // Link in automation bindings from the outer flow
                providers.ForEach(p => p.Credential = credential);

                await _providerManagerService.ExecuteRekeyingWorkflow(rekeyingAttemptLog, secret.ValidPeriod, providers);
            }
            catch (Exception ex)
            {
                rekeyingAttemptLog.IsComplete = true;
                await EmbedException(task, ex, cancellationToken, "Error executing rekeying workflow!");

                await _eventDispatcherMetaService.DispatchEvent(AuthJanitorSystemEvents.RotationTaskAttemptFailed, nameof(TaskExecutionMetaService.ExecuteTask), task);
            }

            // Update Task record
            task.RekeyingInProgress = false;
            task.RekeyingCompleted  = rekeyingAttemptLog.IsSuccessfulAttempt;
            task.RekeyingFailed     = !rekeyingAttemptLog.IsSuccessfulAttempt;

            logUpdateCancellationTokenSource.Cancel();

            await _rekeyingTasks.Update(task, cancellationToken);

            // Run cleanup if Task is complete
            if (task.RekeyingCompleted)
            {
                try
                {
                    secret.LastChanged = DateTimeOffset.UtcNow;
                    await _managedSecrets.Update(secret, cancellationToken);

                    if (task.PersistedCredentialId != default && task.PersistedCredentialId != Guid.Empty)
                    {
                        rekeyingAttemptLog.LogInformation("Destroying persisted credential");
                        await _secureStorageProvider.Destroy(task.PersistedCredentialId);

                        task.PersistedCredentialId   = default;
                        task.PersistedCredentialUser = default;
                    }

                    rekeyingAttemptLog.LogInformation("Completed rekeying workflow for ManagedSecret '{ManagedSecretName}' (ID {ManagedSecretId})", secret.Name, secret.ObjectId);
                    rekeyingAttemptLog.LogInformation("Rekeying task completed");

                    await _rekeyingTasks.Update(task, cancellationToken);
                }
                catch (Exception ex)
                {
                    await EmbedException(task, ex, cancellationToken, "Error cleaning up after rekeying!");
                }


                if (task.ConfirmationType.UsesOBOTokens())
                {
                    await _eventDispatcherMetaService.DispatchEvent(AuthJanitorSystemEvents.RotationTaskCompletedManually, nameof(TaskExecutionMetaService.ExecuteTask), task);
                }
                else
                {
                    await _eventDispatcherMetaService.DispatchEvent(AuthJanitorSystemEvents.RotationTaskCompletedAutomatically, nameof(TaskExecutionMetaService.ExecuteTask), task);
                }
            }
            else
            {
                await _eventDispatcherMetaService.DispatchEvent(AuthJanitorSystemEvents.RotationTaskAttemptFailed, nameof(TaskExecutionMetaService.ExecuteTask), task);
            }
        }
        public async Task <IActionResult> Run(HttpRequest req, CancellationToken cancellationToken)
        {
            _ = req;

            if (!_identityService.IsUserLoggedIn)
            {
                return(new UnauthorizedResult());
            }

            var allSecrets = await _managedSecrets.Get(cancellationToken);

            var allResources = await _resources.Get(cancellationToken);

            var allTasks = await _rekeyingTasks.Get(cancellationToken);

            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         = _identityService.UserName,
                SignedInEmail        = _identityService.UserEmail,
                SignedInRoles        = string.Join(", ", _identityService.UserRoles),
                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 => _managedSecretViewModel(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 = _providerManager.GetProviderInstance(
                        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));
        }
示例#4
0
 private TProvider DuplicateProvider <TProvider>(TProvider provider)
     where TProvider : IAuthJanitorProvider => _providerManagerService.GetProviderInstance(provider);