Skip to content

Commit

Permalink
Merge pull request #3 from icgam/Feature/AzureKeyVault
Browse files Browse the repository at this point in the history
ADP-9462 Feature/azure key vault - Add Azure KeyVault to Easify
  • Loading branch information
moattarwork authored Jul 23, 2021
2 parents 34c8d16 + f58489f commit d6aa7cb
Show file tree
Hide file tree
Showing 8 changed files with 188 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<Title>Easify.AspNetCore.Observability.AppInsights</Title>
<Title>Easify.Azure.AspNetCore.AppInsights</Title>
<Authors>Mohammad Moattar</Authors>
<PackageProjectUrl>https://github.com/icgam/Easify.Azure</PackageProjectUrl>
<RepositoryUrl>https://github.com/icgam/Easify.Azure</RepositoryUrl>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.16.0" />
<PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.16.0" />
<PackageReference Include="Easify.Configurations" Version="1.1.4" />
</ItemGroup>

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>

<IsPackable>false</IsPackable>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="FluentAssertions" Version="5.10.3" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.8.0" />
<PackageReference Include="NSubstitute" Version="4.2.2" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="coverlet.collector" Version="1.3.0">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\Easify.Azure.AspNetCore\Easify.Azure.AspNetCore.csproj" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
using Easify.Azure.AspNetCore.KeyVaults;
using FluentAssertions;
using Microsoft.Extensions.Configuration;
using Xunit;

namespace Easify.Azure.AspNetCore.UnitTests.KeyVault
{
public class KeyVaultExtensionsTests
{
[Fact]
public void Should_AddAzureKeyVault_SkipAddingKeyVaultConfiguration_WhenNoNameHasBennProvidedForKeyVaults()
{
// Arrange
var builder = new ConfigurationBuilder();

//Act
builder.AddAzureKeyVault(m =>
{
m.KeyVaultNames = new string[]{};
m.AzureAdApplicationId = "AppID";
m.AzureAdApplicationCertThumbprint = "CertificateThumbprint";
m.AzureAdTenantId = "TenantID";
});

//Assert
builder.Sources.Count.Should().Be(0);
}

[Fact]
public void Should_AddAzureKeyVault_SkipAddingKeyVaultConfiguration_WhenTheConditionalRegistrationIsFalse()
{
// Arrange
var builder = new ConfigurationBuilder();


//Act
builder.AddAzureKeyVault(() => false, m =>
{
m.KeyVaultNames = new string[]{};
m.AzureAdApplicationId = "AppID";
m.AzureAdApplicationCertThumbprint = "CertificateThumbprint";
m.AzureAdTenantId = "TenantID";
});

//Assert
builder.Sources.Count.Should().Be(0);
}
}
}
15 changes: 15 additions & 0 deletions src/Easify.Azure.AspNetCore.UnitTests/appsettings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"Logging": {
"LogLevel": {
"Default": "Debug",
"System": "Information",
"Microsoft": "Information"
}
},
"KeyVaultOptions": {
"AzureAdTenantId": "ConfigurationTenantId",
"AzureAdApplicationId": "ConfigurationApplicationId",
"AzureAdApplicationCertThumbprint": "ConfigurationCertificateThumbprint",
"KeyVaultNames": []
}
}
19 changes: 19 additions & 0 deletions src/Easify.Azure.AspNetCore/Easify.Azure.AspNetCore.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<Title>Easify.Azure.AspNetCore</Title>
<Authors>Mohammad Moattar</Authors>
<PackageProjectUrl>https://github.com/icgam/Easify.Azure</PackageProjectUrl>
<RepositoryUrl>https://github.com/icgam/Easify.Azure</RepositoryUrl>
<LangVersion>default</LangVersion>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Azure.Extensions.AspNetCore.Configuration.Secrets" Version="1.2.1" />
<PackageReference Include="Azure.Identity" Version="1.4.0" />
<PackageReference Include="Easify.Configurations" Version="1.1.4" />
</ItemGroup>

</Project>
50 changes: 50 additions & 0 deletions src/Easify.Azure.AspNetCore/KeyVaults/KeyVaultExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
using System;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Security.Cryptography.X509Certificates;
using Azure.Extensions.AspNetCore.Configuration.Secrets;
using Azure.Identity;
using Microsoft.Extensions.Configuration;

namespace Easify.Azure.AspNetCore.KeyVaults
{
public static class KeyVaultExtensions
{
[ExcludeFromCodeCoverage]
public static IConfigurationBuilder AddAzureKeyVault(this IConfigurationBuilder builder, Action<KeyVaultOptions> configure = null)
{
if (builder == null) throw new ArgumentNullException(nameof(builder));

var config = builder.Build();
var options = new KeyVaultOptions();
config.GetSection(nameof(KeyVaultOptions)).Bind(options);

configure?.Invoke(options);

if (!options.KeyVaultNames.Any())
return builder;

using var store = new X509Store(options.LocalCertificateStore);
store.Open(OpenFlags.ReadOnly);
var certs = store.Certificates.Find(
X509FindType.FindByThumbprint,
config[options.AzureAdApplicationCertThumbprint], false);

foreach (var keyVaultName in options.KeyVaultNames)
{
builder.AddAzureKeyVault(new Uri($"https://{keyVaultName}.vault.azure.net/"),
new ClientCertificateCredential(options.AzureAdTenantId, options.AzureAdApplicationId, certs.OfType<X509Certificate2>().Single()),
new KeyVaultSecretManager());
}
store.Close();

return builder;
}

public static IConfigurationBuilder AddAzureKeyVault(this ConfigurationBuilder builder, Func<bool> condition,
Action<KeyVaultOptions> configure = null)
{
return condition() ? builder.AddAzureKeyVault(configure) : builder;
}
}
}
13 changes: 13 additions & 0 deletions src/Easify.Azure.AspNetCore/KeyVaults/KeyVaultOptions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using System.Security.Cryptography.X509Certificates;

namespace Easify.Azure.AspNetCore.KeyVaults
{
public class KeyVaultOptions
{
public string AzureAdTenantId { get; set; }
public string AzureAdApplicationId { get; set; }
public string AzureAdApplicationCertThumbprint { get; set; }
public StoreLocation LocalCertificateStore { get; set; } = StoreLocation.CurrentUser;
public string[] KeyVaultNames { get; set; } = { };
}
}
12 changes: 12 additions & 0 deletions src/Easify.Azure.sln
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Easify.Azure.AspNetCore.App
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Easify.Azure.AspNetCore.AppInsights.UnitTests", "Easify.Azure.AspNetCore.AppInsights.UnitTests\Easify.Azure.AspNetCore.AppInsights.UnitTests.csproj", "{A80E9116-95B6-43A5-A227-4C96D6C8ADB5}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Easify.Azure.AspNetCore", "Easify.Azure.AspNetCore\Easify.Azure.AspNetCore.csproj", "{D413300A-5272-4D1C-9F14-5E20C1D3B24E}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Easify.Azure.AspNetCore.UnitTests", "Easify.Azure.AspNetCore.UnitTests\Easify.Azure.AspNetCore.UnitTests.csproj", "{F647B941-F688-4C7F-A45B-5F0AD5772FE1}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand All @@ -21,6 +25,14 @@ Global
{A80E9116-95B6-43A5-A227-4C96D6C8ADB5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A80E9116-95B6-43A5-A227-4C96D6C8ADB5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A80E9116-95B6-43A5-A227-4C96D6C8ADB5}.Release|Any CPU.Build.0 = Release|Any CPU
{D413300A-5272-4D1C-9F14-5E20C1D3B24E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D413300A-5272-4D1C-9F14-5E20C1D3B24E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D413300A-5272-4D1C-9F14-5E20C1D3B24E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D413300A-5272-4D1C-9F14-5E20C1D3B24E}.Release|Any CPU.Build.0 = Release|Any CPU
{F647B941-F688-4C7F-A45B-5F0AD5772FE1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F647B941-F688-4C7F-A45B-5F0AD5772FE1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F647B941-F688-4C7F-A45B-5F0AD5772FE1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F647B941-F688-4C7F-A45B-5F0AD5772FE1}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down

0 comments on commit d6aa7cb

Please sign in to comment.