Skip to content

AuthJanitor Service Usage

Anthony Turner edited this page Jan 7, 2021 · 2 revisions

Independent of all of the surrounding automation, AuthJanitor's core services can be run with a minimum of setup.

Prerequisites

  • NET Core-based application (netstandard2.1)
  • Dependency injection container in application

Create a Token Provider for your consumer application

An example ITokenCredentialProvider can be found in the Blazor Server app, which uses Microsoft.Web.Identity to acquire tokens. You can modify the code below to meet the needs of your consumer application:

public class BlazorTokenCredentialProvider : ITokenCredentialProvider
{
    public const string AZURE_SCOPE = "https://management.core.windows.net/user_impersonation";
    private readonly ISecureStorage _secureStorage;
    private readonly ITokenAcquisition _tokenAcquisition;

    public BlazorTokenCredentialProvider(
        ISecureStorage secureStorage,
        ITokenAcquisition tokenAcquisition)
    {
        _secureStorage = secureStorage;
        _tokenAcquisition = tokenAcquisition;
    }

    public async Task<AccessTokenCredential> GetToken(TokenSources source, string parameters)
    {
        switch (source)
        {
            case TokenSources.Explicit:
                return AccessTokenCredential.CreateBearer(parameters);
            case TokenSources.Persisted:
                var guid = Guid.Parse(parameters);
                return await _secureStorage.Retrieve<AccessTokenCredential>(guid);
            case TokenSources.ServicePrincipal:
                return AccessTokenCredential.CreateBearer(
                    await _tokenAcquisition.GetAccessTokenForAppAsync(AZURE_SCOPE));
            case TokenSources.OBO:
                return AccessTokenCredential.CreateBearer(
                    await _tokenAcquisition.GetAccessTokenForUserAsync(new[] { AZURE_SCOPE }));
        }
        return null;
    }
}

Register Services

var serviceCollection = new ServiceCollection();

# Registers dummy services for Secure Storage, Agent Communication, and Cryptography
# You can manually register these yourself, or implement your own interface-compatible solution
serviceCollection.AddAuthJanitorDummyServices();

# Adds AuthJanitorService to DI container
# The first argument is a callback to load Provider types. In the automation, this is accomplished by a NET Core plugin package. 
#   Regardless, the consuming application needs to be able to provide all types of Providers supported.
# The second argument is the agent name for this running service, if messaging is performed. This service will only respond to
#   messages addressed to this string identifier
serviceCollection.AddAuthJanitorService(
    (str) => LoadAssemblyFromFilenameString(str),
    "authjanitor-sample-service");

Use the Service

Once in the DI container, the AuthJanitorService can be used and injected by the consuming application. The main requirement to use this service is a serialized access token, provided as a string.

Enumerate

You can enumerate compatible services (and find linked services which work together based on the same secret) with EnumerateAsync and the access token:

var services = await authJanitorService.EnumerateAsync(AccessToken);

Dispatch/Execute

If the agent is the one responsible for performing the rotation, it will be executed locally. Otherwise, a message will be sent to the communication bus between AuthJanitor and its agents.

await authJanitorService.DispatchOrExecuteAsync(
    TimeSpan.FromDays(30),
    async (workflowCollection) =>
    {
        await Task.Yield();
        /* This is run periodically during the long task */
    },
    "secret-id",
    services.First().Parameters);

Execute

You can also run the Execute command with the assumption that the local agent is the correct identity environment in which the key rotation should be performed. It is very similar in syntax to DispatchOrExecuteAsync.

await authJanitorService.ExecuteAsync(
    TimeSpan.FromDays(30),
    async (workflowCollection) =>
    {
        await Task.Yield();
        /* This is run periodically during the long task */
    },
    services.First().Parameters);

Token Stashing

If the rotation of a secret requires a token which isn't accessible at the time of the rotation, it can be stashed to the loaded Secure Storage provider. The provider will respond with a Guid receipt, indicating how the application can find the secret later.

var stashedSecretId = await authJanitorService.StashCredentialAsync(
    AccessToken,
    DateTimeOffset.Now.AddDays(1))

Messaging

When a string message is received from the Agent Communication Provider, it can be sent into a function for processing, including executing the key rotation if necessary. This function will call the DispatchOrExecute command based on the content of the message.

await authJanitorService.ProcessMessageAsync(
    serializedMessageString,
    async (workflowCollection) =>
    {
        await Task.Yield();
        /* This is run periodically */
        /* Perform some update tasks */
    });