-
Notifications
You must be signed in to change notification settings - Fork 17
AuthJanitor Service Usage
Independent of all of the surrounding automation, AuthJanitor's core services can be run with a minimum of setup.
- NET Core-based application (netstandard2.1)
- Dependency injection container in 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;
}
}
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");
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.
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);
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);
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);
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))
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 */
});