This commit is contained in:
Anthony Turner 2020-10-11 10:33:08 -04:00
Родитель 75ad7f6f6c
Коммит 8c2fb2f0aa
6 изменённых файлов: 202 добавлений и 0 удалений

Просмотреть файл

@ -0,0 +1,47 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
using System;
using System.Collections.Generic;
namespace AuthJanitor.AgentBridges
{
public class AgentActionMessage
{
public string AgentId { get; set; }
public TimeSpan ValidPeriod { get; set; }
public IEnumerable<AgentActionMessageProvider> Providers { get; set; } = new AgentActionMessageProvider[0];
public AgentActionMessage() { }
public AgentActionMessage(string agentId, TimeSpan secretValidPeriod, params AgentActionMessageProvider[] providers)
{
AgentId = agentId;
ValidPeriod = secretValidPeriod;
Providers = providers;
}
}
public class AgentActionMessageProvider
{
public string ProviderType { get; set; }
public string ProviderConfiguration { get; set; }
public AgentActionMessageProvider() { }
public AgentActionMessageProvider(string providerType, string providerConfiguration)
{
ProviderType = providerType;
ProviderConfiguration = providerConfiguration;
}
}
public class MessageEnvelope
{
public string Signature { get; set; }
public string Message { get; set; }
public MessageEnvelope() { }
public MessageEnvelope(string signature, string message)
{
Signature = signature;
Message = message;
}
}
}

Просмотреть файл

@ -0,0 +1,56 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
using AuthJanitor.Integrations.CryptographicImplementations;
using AuthJanitor.SecureStorage;
using System;
using System.Collections.Generic;
using System.Text.Json;
using System.Threading.Tasks;
namespace AuthJanitor.AgentBridges
{
public interface IAgentBridge
{
Task<MessageEnvelope> CreateAgentMessage(string agentId, TimeSpan secretValidPeriod, params AgentActionMessageProvider[] providers);
Task<AgentActionMessage> DecryptAgentMessage(MessageEnvelope envelope);
}
public class AzureQueuesAgentBridge : IAgentBridge
{
private ICryptographicImplementation _cryptographicImplementation;
private ISecureStorage _secureStorage;
public AzureQueuesAgentBridge(
ICryptographicImplementation cryptographicImplementation,
ISecureStorage secureStorage)
{
_cryptographicImplementation = cryptographicImplementation;
_secureStorage = secureStorage;
}
public async Task<AgentActionMessage> DecryptAgentMessage(MessageEnvelope envelope)
{
var serverPublicKey = new byte[0];
var agentPrivateKey = new byte[0];
if (!await _cryptographicImplementation.Verify(serverPublicKey, envelope.Message, envelope.Signature))
{
throw new Exception("Signature invalid!");
}
var decrypted = await _cryptographicImplementation.Decrypt(agentPrivateKey, envelope.Message);
return JsonSerializer.Deserialize<AgentActionMessage>(decrypted);
}
public async Task<MessageEnvelope> CreateAgentMessage(string agentId, TimeSpan secretValidPeriod, params AgentActionMessageProvider[] providers)
{
var serverPrivateKey = new byte[0];
var agentPublicKey = new byte[0];
var agentActionMessage = new AgentActionMessage(agentId, secretValidPeriod, providers);
var encrypted = await _cryptographicImplementation.Encrypt(agentPublicKey, JsonSerializer.Serialize(agentActionMessage));
var signature = await _cryptographicImplementation.Sign(serverPrivateKey, encrypted);
return new MessageEnvelope(encrypted, signature);
}
}
}

Просмотреть файл

@ -0,0 +1,22 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
namespace AuthJanitor.KeyProvider
{
public class GeneratedKeyProvider : IKeyProvider
{
public Task<byte[]> GetPrivateKey(string keyName)
{
return new byte[0];
}
public Task<byte[]> GetPublicKey(string keyName)
{
return new byte[0];
}
}
}

Просмотреть файл

@ -0,0 +1,12 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
using System.Threading.Tasks;
namespace AuthJanitor.KeyProvider
{
public interface IKeyProvider
{
Task<byte[]> GetPublicKey(string keyName);
Task<byte[]> GetPrivateKey(string keyName);
}
}

Просмотреть файл

@ -11,6 +11,7 @@
<PackageReference Include="Microsoft.Azure.Functions.Extensions" Version="1.0.0" />
<PackageReference Include="Microsoft.Azure.WebJobs.Extensions" Version="3.0.6" />
<PackageReference Include="Microsoft.Azure.WebJobs.Extensions.Http" Version="3.0.2" />
<PackageReference Include="Microsoft.Azure.WebJobs.Extensions.Storage" Version="4.0.2" />
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="3.1.6" />
<PackageReference Include="Microsoft.NET.Sdk.Functions" Version="3.0.9" />
</ItemGroup>

Просмотреть файл

@ -0,0 +1,64 @@
using System;
using System.Linq;
using System.Threading.Tasks;
using AuthJanitor.AgentBridges;
using AuthJanitor.IdentityServices;
using AuthJanitor.Integrations.CryptographicImplementations;
using AuthJanitor.Providers;
using Microsoft.Azure.WebJobs;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
namespace AuthJanitor
{
public class PerformProviderWorkflow
{
private ICryptographicImplementation _cryptographicImplementation;
private IIdentityService _identityService;
private ProviderManagerService _providerManagerService;
public PerformProviderWorkflow(
ICryptographicImplementation cryptographicImplementation,
IIdentityService identityService,
ProviderManagerService providerManagerService)
{
_cryptographicImplementation = cryptographicImplementation;
_identityService = identityService;
_providerManagerService = providerManagerService;
}
[FunctionName("PerformProviderWorkflow")]
public async Task Run(
[QueueTrigger("%agent-receive-queue%", Connection = "AuthJanitorAgentBridge")] string agentQueueItem,
ILogger log)
{
// Set "agent-receive-queue" in settings
var message = await GetAgentActionMessage(agentQueueItem);
var logger = new RekeyingAttemptLogger(log);
var providers = message.Providers.Select(p => _providerManagerService.GetProviderInstance(p.ProviderType, p.ProviderConfiguration)).ToList();
var agentCredential = await _identityService.GetAccessTokenForApplicationAsync();
if (agentCredential == null || string.IsNullOrEmpty(agentCredential.AccessToken))
throw new Exception("Could not acquire access token for Agent application");
providers.ForEach(p => p.Credential = agentCredential);
// todo: relay log output messages to send queue
await _providerManagerService.ExecuteRekeyingWorkflow(logger, message.ValidPeriod, providers);
}
private async Task<AgentActionMessage> GetAgentActionMessage(string queueItemContent)
{
var envelope = JsonConvert.DeserializeObject<MessageEnvelope>(queueItemContent);
byte[] ajServicePublicKey = new byte[0]; // get from settings
byte[] agentPrivateKey = new byte[0]; // get from settings
if (await _cryptographicImplementation.Verify(ajServicePublicKey, envelope.Message, envelope.Signature))
{
var decryptedMessage = await _cryptographicImplementation.Decrypt(agentPrivateKey, envelope.Message);
return JsonConvert.DeserializeObject<AgentActionMessage>(decryptedMessage);
}
throw new Exception("Signature verification failed!");
}
}
}