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)); }
private TProvider DuplicateProvider <TProvider>(TProvider provider) where TProvider : IAuthJanitorProvider => _providerManagerService.GetProviderInstance(provider);