コード例 #1
0
 /// <summary>
 /// Stash a given credentials object in the preferred
 /// secure storage, and return the Guid of the stashed object.
 /// </summary>
 /// <param name="token">AccessTokenCredential to stash</param>
 /// <param name="expiry">When the credentials expire, if unused</param>
 /// <returns>Guid of stashed object</returns>
 public async Task <Guid> StashCredentialAsync(
     AccessTokenCredential token,
     DateTimeOffset expiry = default)
 {
     if (expiry == default)
     {
         expiry = DateTimeOffset.Now.AddDays(7);
     }
     return(await _secureStorage.Persist(expiry, token));
 }
コード例 #2
0
        /// <summary>
        /// Process a given set of providerConfigurations and execute the
        /// workflow locally. If the Instance ID doesn't match the expected
        /// Agent ID, this will return immediately.
        ///
        /// The periodicUpdateFunction will be executed regularly throughout
        /// the execution of the workflow.
        /// </summary>
        /// <param name="secretValidPeriod">Secret's period of validity</param>
        /// <param name="periodicUpdateFunction">Function which is invoked periodically to communicate runtime status</param>
        /// <param name="providerConfigurations">Provider configurations</param>
        /// <returns></returns>
        public async Task <ProviderWorkflowActionCollection> ExecuteAsync(
            TimeSpan secretValidPeriod,
            Func <ProviderWorkflowActionCollection, Task> periodicUpdateFunction,
            params ProviderExecutionParameters[] providerConfigurations)
        {
            ProviderWorkflowActionCollection workflowCollection =
                new ProviderWorkflowActionCollection();

            try
            {
                var persisted = new Dictionary <Guid, AccessTokenCredential>();
                if (providerConfigurations.Any(p => p.TokenSource == TokenSources.Persisted))
                {
                    _logger.LogInformation("Downloading persisted tokens");
                    foreach (var item in providerConfigurations.Where(p => p.TokenSource == TokenSources.Persisted))
                    {
                        var guid = Guid.Parse(item.TokenParameter);
                        persisted[guid] = await _secureStorage.Retrieve <AccessTokenCredential>(guid);
                    }
                }

                AccessTokenCredential obo = null, msi = null;
                if (providerConfigurations.Any(p => p.TokenSource == TokenSources.OBO))
                {
                    _logger.LogInformation("Acquiring OBO token");
                    obo = await _identityService.GetAccessTokenOnBehalfOfCurrentUserAsync();
                }
                if (providerConfigurations.Any(p => p.TokenSource == TokenSources.ServicePrincipal))
                {
                    _logger.LogInformation("Acquiring application token");
                    msi = await _identityService.GetAccessTokenForApplicationAsync();
                }

                _logger.LogInformation("Getting providers for {ResourceCount} resources", providerConfigurations.Count());
                await Task.WhenAll(providerConfigurations.Select(async r =>
                {
                    switch (r.TokenSource)
                    {
                    case TokenSources.Explicit:
                        r.AccessToken = JsonConvert.DeserializeObject <AccessTokenCredential>(r.TokenParameter);
                        break;

                    case TokenSources.OBO:
                        r.AccessToken = obo;
                        r.AccessToken.DisplayEmail    = _identityService.UserEmail;
                        r.AccessToken.DisplayUserName = _identityService.UserName;
                        break;

                    case TokenSources.Persisted:
                        r.AccessToken = persisted[Guid.Parse(r.TokenParameter)];
                        r.AccessToken.DisplayEmail    = r.AccessToken.Username;
                        r.AccessToken.DisplayUserName = r.AccessToken.Username;
                        break;

                    case TokenSources.ServicePrincipal:
                        r.AccessToken = msi;
                        break;

                    case TokenSources.Unknown:
                    default:
                        await _eventDispatcher.DispatchEvent(AuthJanitorSystemEvents.AnomalousEventOccurred,
                                                             nameof(AuthJanitorService.ExecuteAsync),
                                                             $"TokenSource was unknown for a provider! ({r.ProviderType})");
                        break;
                    }
                    return(r);
                }));

                // --- end access token acquisition/embed ---

                var providers = providerConfigurations.Select(r =>
                {
                    var p = _providerManagerService.GetProviderInstance(
                        r.ProviderType,
                        r.ProviderConfiguration);
                    if (r.AccessToken != null)
                    {
                        p.Credential = r.AccessToken;
                    }
                    return(p);
                }).ToList();

                workflowCollection = _providerManagerService.CreateWorkflowCollection(
                    secretValidPeriod,
                    providers);

                _logger.LogInformation("Creating workflow execution task");
                Task workflowCollectionRunTask = new Task(async() =>
                {
                    try { await workflowCollection.Run(); }
                    catch (Exception ex)
                    {
                        _logger.LogError(ex, "Error executing action(s)");
                        throw ex;
                    }
                });

                _logger.LogInformation("Creating tracker task for workflow collection");
                var logUpdateCancellationTokenSource = new CancellationTokenSource();
                var periodicUpdateTask = Task.Run(async() =>
                {
                    while (!workflowCollectionRunTask.IsCompleted &&
                           !workflowCollectionRunTask.IsCanceled)
                    {
                        await Task.Delay(5 * 1000);
                        await periodicUpdateFunction(workflowCollection);
                    }
                }, logUpdateCancellationTokenSource.Token);

                _logger.LogInformation("Executing {ActionCount} actions", workflowCollection.Actions.Count);
                await workflowCollectionRunTask;
                _logger.LogInformation("Execution complete", workflowCollection.Actions.Count);

                logUpdateCancellationTokenSource.Cancel();
                await periodicUpdateFunction(workflowCollection);

                if (workflowCollection.HasBeenExecutedSuccessfully)
                {
                    if (providerConfigurations.Any(p => p.TokenSource == TokenSources.Persisted))
                    {
                        _logger.LogInformation("Cleaning up persisted tokens");
                        foreach (var item in providerConfigurations.Where(p => p.TokenSource == TokenSources.Persisted))
                        {
                            await _secureStorage.Destroy(Guid.Parse(item.TokenParameter));
                        }
                    }
                }

                return(workflowCollection);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error preparing workflow: {ex}", ex);
                await _eventDispatcher.DispatchEvent(
                    AuthJanitorSystemEvents.RotationTaskAttemptFailed,
                    nameof(AuthJanitorService.ExecuteAsync),
                    "Error executing provider workflow");

                return(workflowCollection);
            }
        }
コード例 #3
0
        /// <summary>
        /// Enumerate potential candidates for a given Provider module using
        /// a given AccessTokenCredential
        /// </summary>
        /// <param name="credential">Credentials to access cloud service to enumerate</param>
        /// <param name="provider">Provider to enumerate</param>
        /// <returns>Collection of suggestions of Provider configurations based on existing services</returns>
        public async Task <IEnumerable <ProviderResourceSuggestion> > EnumerateProviders(AccessTokenCredential credential, IAuthJanitorProvider provider)
        {
            provider.Credential = credential;
            if (provider is ICanEnumerateResourceCandidates)
            {
                var enumerable = provider as ICanEnumerateResourceCandidates;
                try
                {
                    var results = await enumerable.EnumerateResourceCandidates(GetProviderConfiguration(provider.GetType().AssemblyQualifiedName, provider.SerializedConfiguration));

                    return(results.Select(r => new ProviderResourceSuggestion()
                    {
                        Name = r.Name,
                        ProviderType = r.ProviderType,
                        Configuration = r.Configuration,
                        SerializedConfiguration = JsonSerializer.Serialize <object>(r.Configuration),
                        AddressableNames = r.AddressableNames.Distinct(),
                        ResourceValues = r.ResourceValues.Distinct(),
                        ResourcesAddressingThis = r.ResourcesAddressingThis
                    }));
                }
                catch (Exception ex)
                {
                    _serviceProvider.GetRequiredService <ILogger <ProviderManagerService> >().LogError(ex, "Error enumerating resource candidates for provider type " + provider.GetType().AssemblyQualifiedName);
                }
            }
            return(new ProviderResourceSuggestion[0]);
        }
コード例 #4
0
        public async Task <AccessTokenCredential> GetTokenCredentialAsync(Guid taskId, CancellationToken cancellationToken)
        {
            var task = await _rekeyingTasks.GetOne(taskId, cancellationToken);

            // 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");
                }

                credential.DisplayUserName = credential.Username;
                credential.DisplayEmail    = credential.Username;
                if (task.ConfirmationType.UsesOBOTokens())
                {
                    if (!string.IsNullOrEmpty(task.PersistedCredentialUser))
                    {
                        credential.DisplayUserName = task.PersistedCredentialUser;
                    }
                    else
                    {
                        credential.DisplayUserName = _identityService.UserName;
                        credential.DisplayEmail    = _identityService.UserEmail;
                    }
                }

                return(credential);
            }
            catch (Exception ex)
            {
                await _eventDispatcherService.DispatchEvent(AuthJanitorSystemEvents.RotationTaskAttemptFailed, nameof(TaskExecutionMetaService.ExecuteTask), task);

                throw ex;
            }
        }
コード例 #5
0
        /// <summary>
        /// Enumerate potential candidates for all loaded Provider modules using
        /// a given AccessTokenCredential
        /// </summary>
        /// <param name="credential">Credentials to access cloud service to enumerate</param>
        /// <returns>Collection of suggestions of Provider configurations based on existing services</returns>
        public async Task <IEnumerable <ProviderResourceSuggestion> > EnumerateProviders(AccessTokenCredential credential)
        {
            var providers = (await Task.WhenAll(
                                 LoadedProviders.Select(p => GetProviderInstanceDefault(p.ProviderTypeName))
                                 .OfType <ICanEnumerateResourceCandidates>()
                                 .Select(p => EnumerateProviders(credential, p))))
                            .Where(c => c != null)
                            .SelectMany(c => c);

            foreach (var provider in providers.Where(p => p.AddressableNames.Any()))
            {
                foreach (var name in provider.AddressableNames)
                {
                    var refs = providers.Where(p => p.ResourceValues.Any(r => r.Contains(name)));
                    provider.ResourcesAddressingThis.AddRange(refs);
                }
            }

            return(providers);
        }