зеркало из
1
0
Форкнуть 0
Adds initial plugin solution
Adds KeyVault plugin / project
This commit is contained in:
John Taubensee 2017-06-02 16:43:31 -07:00 коммит произвёл Neeraj Makam
Родитель 086a2c0774
Коммит 23d858663a
18 изменённых файлов: 987 добавлений и 0 удалений

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

@ -0,0 +1,36 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.26430.6
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{7D8B793C-F4AC-432A-8EE7-2EE3C2B16EC1}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.Azure.ServiceBus.KeyVault", "src\Microsoft.Azure.ServiceBus.KeyVault\Microsoft.Azure.ServiceBus.KeyVault.csproj", "{F942A66E-A1B7-41C3-85E8-1A108D18F890}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{B18143EB-5FF4-4AFC-B086-709DC9B92546}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.Azure.ServiceBus.KeyVault.Test", "test\Microsoft.Azure.ServiceBus.KeyVault.Test\Microsoft.Azure.ServiceBus.KeyVault.Test.csproj", "{DC8DC685-DCB5-47C7-A2B7-41D31EDDCAED}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{F942A66E-A1B7-41C3-85E8-1A108D18F890}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F942A66E-A1B7-41C3-85E8-1A108D18F890}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F942A66E-A1B7-41C3-85E8-1A108D18F890}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F942A66E-A1B7-41C3-85E8-1A108D18F890}.Release|Any CPU.Build.0 = Release|Any CPU
{DC8DC685-DCB5-47C7-A2B7-41D31EDDCAED}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{DC8DC685-DCB5-47C7-A2B7-41D31EDDCAED}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DC8DC685-DCB5-47C7-A2B7-41D31EDDCAED}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DC8DC685-DCB5-47C7-A2B7-41D31EDDCAED}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{F942A66E-A1B7-41C3-85E8-1A108D18F890} = {7D8B793C-F4AC-432A-8EE7-2EE3C2B16EC1}
{DC8DC685-DCB5-47C7-A2B7-41D31EDDCAED} = {B18143EB-5FF4-4AFC-B086-709DC9B92546}
EndGlobalSection
EndGlobal

21
appveyor.yml Normal file
Просмотреть файл

@ -0,0 +1,21 @@
version: 1.0.{build}
skip_branch_with_pr: true
skip_tags: true
matrix:
fast_finish: true
image: Visual Studio 2017
environment:
matrix:
# First build
- DotNetRunTime: netcoreapp1.0
# Second build
- DotNetRunTime: net46
azure-service-bus-dotnet/SkipCodeCoverage: true
skip_commits:
files:
- '**/*.md'
artifacts:
- path: .\build\artifacts\*
build_script:
- ps: .\build\build.ps1
test: off

130
build/build.ps1 Normal file
Просмотреть файл

@ -0,0 +1,130 @@
$ErrorActionPreference = 'Stop'
$isAppveyor = [bool]$env:APPVEYOR
$configuration = if ($CONFIGURATION -ne $null) { $CONFIGURATION } else { 'Debug' }
$platform = if ($PLATFORM -ne $null) { $PLATFORM } else { 'Any CPU' }
$projectFolder = if ($ENV:APPVEYOR_BUILD_FOLDER -ne $null) { "$ENV:APPVEYOR_BUILD_FOLDER" } else { $(Get-Location).path }
$buildFolder = $projectFolder + '\build\'
$runtime = if ($ENV:DotNetRunTime -ne $null) { $ENV:DotNetRunTime } else { 'netcoreapp1.0' }
$artifactsFolder = $buildFolder + 'artifacts\'
$appProject = $projectFolder + '\src\\Microsoft.Azure.ServiceBus.KeyVault\Microsoft.Azure.ServiceBus.KeyVault.csproj'
$testProject = $projectFolder + '\test\Microsoft.Azure.ServiceBus.KeyVault.Test\Microsoft.Azure.ServiceBus.KeyVault.Test.csproj'
$coverageFile = $buildFolder + 'coverage.xml'
$appNamespace = 'Microsoft.Azure.ServiceBus.KeyVault'
$testNamespace = 'Microsoft.Azure.ServiceBus.KeyVault.Test'
# Environment variables
$skipCodeCoverage = if ([bool][Environment]::GetEnvironmentVariable('azure-service-bus-dotnet/SkipCodeCoverage')) { $true } else { $false }
function Build-Solution
{
Write-Host "Building projects"
# Restore solution files
MSBuild.exe Microsoft.Azure.ServiceBus.Plugins.sln /t:restore /p:Configuration=$configuration /p:Platform=$platform /verbosity:minimal
# $? Returns True or False value indicating whether previous command ended with an error.
# This is used to throw an error that will cause the AppVeyor process to fail as expected.
if (-not $?)
{
throw "Package restore failed."
}
# Build solution
MSBuild.exe Microsoft.Azure.ServiceBus.Plugins.sln /p:Configuration=$configuration /p:Platform=$platform /verbosity:minimal
if (-not $?)
{
throw "Build failed."
}
else
{
Write-Host "Building complete."
}
}
function Run-UnitTests
{
if ($skipCodeCoverage)
{
dotnet test $testProject -f $runtime
if (-not $?)
{
throw "Unit tests failed."
}
return;
}
Write-Host "Running unit tests."
if (-Not (Test-Path .\nuget.exe))
{
Invoke-WebRequest -Uri "https://dist.nuget.org/win-x86-commandline/latest/nuget.exe" -outfile $buildFolder\nuget.exe
}
$openCoverVersion = '4.6.712'
$openCoverNuPkgOutFile = $buildFolder + 'OpenCover.' + $openCoverVersion + '.nupkg'
# Using a temporary version of OpenCover until a NuGet is published. https://github.com/OpenCover/opencover/issues/669
# Once there is a new NuGet package, this if statement can be removed, and so can '-source $buildFolder' in the line after
if (-Not (Test-Path $openCoverNuPkgOutFile)) {
Invoke-WebRequest `
-Uri "https://ci.appveyor.com/api/buildjobs/upad53qdyo1iv382/artifacts/main%2Fbin%2Fpackages%2Fnuget%2Fopencover%2FOpenCover.4.6.712.nupkg" `
-OutFile $openCoverNuPkgOutFile
}
& $buildFolder\nuget.exe install OpenCover -version $openCoverVersion -SolutionDirectory $buildFolder -source $buildFolder
$openCoverConsole = $buildFolder + 'packages/' + 'OpenCover.' + $openCoverVersion + '\tools\OpenCover.Console.exe'
$target = '-target:C:\Program Files\dotnet\dotnet.exe'
$targetArgs = '-targetargs: test ' + $testProject + ' -f ' + $runtime
$filter = '-filter:+[' + $appNamespace + '*]* -[' + $testNamespace + ']*'
$output = '-output:' + $coverageFile
& $openCoverConsole $target $targetArgs $filter $output '-register:user' '-oldStyle'
if (-not $?)
{
throw "Unit tests failed."
}
if (-Not (Test-Path $coverageFile))
{
return
}
if ($isAppveyor)
{
$ENV:PATH = 'C:\\Python34;C:\\Python34\\Scripts;' + $ENV:PATH
python -m pip install --upgrade pip
pip install git+git://github.com/codecov/codecov-python.git
codecov -f $coverageFile -X gcov
}
else
{
$reportGeneratorVersion = '2.5.7'
& $buildFolder\nuget.exe install ReportGenerator -version $reportGeneratorVersion -SolutionDirectory $buildFolder
$reportGenerator = $buildFolder + 'packages\' + 'ReportGenerator.' + $reportGeneratorVersion + '\tools\ReportGenerator.exe'
$targetDirectory = $buildFolder + 'OpenCoverReport\'
& $reportGenerator -reports:$coverageFile -targetdir:$targetDirectory
}
}
function CopyArtifacts
{
if (-Not $isAppveyor)
{
return
}
New-Item -ItemType Directory -Force -Path $artifactsFolder | Out-Null
MSBuild.exe $appProject /t:pack /p:Configuration=$configuration /p:Platform=$platform /p:PackageOutputPath=$artifactsFolder /verbosity:minimal
if (Test-Path $coverageFile)
{
Copy-Item $coverageFile $artifactsFolder
}
}
# Run the functions
Build-Solution
Run-UnitTests
CopyArtifacts

Двоичные данные
build/keyfile.snk Normal file

Двоичный файл не отображается.

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

@ -0,0 +1,11 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
namespace Microsoft.Azure.ServiceBus.KeyVault
{
internal static class KeyVaultMessageHeaders
{
internal const string InitializationVectorPropertyName = "KeyVault-IV";
internal const string KeyNamePropertyName = "KeyVault-KeyName";
}
}

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

@ -0,0 +1,171 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
namespace Microsoft.Azure.ServiceBus.KeyVault
{
using System;
using System.Threading.Tasks;
using Microsoft.Azure.ServiceBus.Core;
using System.Security.Cryptography;
using System.IO;
/// <summary>
/// Provides Azure KeyVault functionality for Azure Service Bus.
/// </summary>
public class KeyVaultPlugin : ServiceBusPlugin
{
private readonly string secretName;
private readonly string keyVaultEndpoint;
private KeyVaultSecretManager secretManager;
private byte[] initializationVector;
private string base64InitializationVector;
/// <summary>
/// Gets the name that is used to identify this plugin.
/// </summary>
public override string Name => "Microsoft.Azure.ServiceBus.KeyVault.KeyVaultPlugin";
/// <summary>
/// Creates a new instance of an <see cref="KeyVaultPlugin"/>.
/// </summary>
/// <param name="encryptionSecretName">The name of the secret used to encrypt / decrypt messages.</param>
/// <param name="options">The <see cref="KeyVaultPluginSettings"/> used to create a new instance.</param>
public KeyVaultPlugin(string encryptionSecretName, KeyVaultPluginSettings options)
{
if (string.IsNullOrEmpty(encryptionSecretName))
{
throw new ArgumentNullException(nameof(encryptionSecretName));
}
if (options == null)
{
throw new ArgumentNullException(nameof(options));
}
this.secretName = encryptionSecretName;
this.keyVaultEndpoint = options.Endpoint;
this.secretManager = new KeyVaultSecretManager(options.Endpoint, options.ClientId, options.ClientSecret);
this.initializationVector = KeyVaultPlugin.GenerateInitializationVector();
this.base64InitializationVector = Convert.ToBase64String(this.initializationVector);
}
/// <summary>
/// The action performed before sending a message to Service Bus. This method will load the KeyVault key and encrypt messages.
/// </summary>
/// <param name="message">The <see cref="Message"/> to be encrypted.</param>
/// <returns>The encrypted <see cref="Message"/>.</returns>
public override async Task<Message> BeforeMessageSend(Message message)
{
try
{
if (message.UserProperties.ContainsKey(KeyVaultMessageHeaders.InitializationVectorPropertyName) || message.UserProperties.ContainsKey(KeyVaultMessageHeaders.KeyNamePropertyName))
{
return message;
}
var secret = await secretManager.GetHashedSecret(secretName);
message.UserProperties.Add(KeyVaultMessageHeaders.InitializationVectorPropertyName, base64InitializationVector);
message.UserProperties.Add(KeyVaultMessageHeaders.KeyNamePropertyName, secretName);
message.Body = await KeyVaultPlugin.Encrypt(message.Body, secret, this.initializationVector);
return message;
}
catch (Exception ex)
{
throw new KeyVaultPluginException(Resources.BeforeMessageSendException, ex);
}
}
/// <summary>
/// The action performed after receiving a message from Service Bus. This method will load the KeyVault key and decrypt messages.
/// </summary>
/// <param name="message">The <see cref="Message"/> to be decrypted.</param>
/// <returns>The decrypted <see cref="Message"/>.</returns>
public override async Task<Message> AfterMessageReceive(Message message)
{
try
{
if (!message.UserProperties.ContainsKey(KeyVaultMessageHeaders.InitializationVectorPropertyName)
|| !message.UserProperties.ContainsKey(KeyVaultMessageHeaders.KeyNamePropertyName))
{
return message;
}
var iVString = message.UserProperties[KeyVaultMessageHeaders.InitializationVectorPropertyName] as string;
var iV = Convert.FromBase64String(iVString);
var secretName = message.UserProperties[KeyVaultMessageHeaders.KeyNamePropertyName] as string;
// Remove properties before giving the message back
message.UserProperties.Remove(KeyVaultMessageHeaders.InitializationVectorPropertyName);
message.UserProperties.Remove(KeyVaultMessageHeaders.KeyNamePropertyName);
var secret = await secretManager.GetHashedSecret(secretName);
var decryptedMessage = await KeyVaultPlugin.Decrypt(message.Body, secret, iV);
message.Body = decryptedMessage;
return message;
}
catch (Exception ex)
{
throw new KeyVaultPluginException(Resources.AfterMessageReceiveException, ex);
}
}
internal static byte[] GenerateInitializationVector()
{
byte[] initializationVector = null;
using (var aes = Aes.Create())
{
aes.GenerateIV();
initializationVector = aes.IV;
}
return initializationVector;
}
// Taken from the examples here: https://msdn.microsoft.com/en-us/library/system.security.cryptography.aes
internal static async Task<byte[]> Encrypt(byte[] payload, byte[] key, byte[] initializationVector)
{
// Create an Aes object
// with the specified key and IV.
using (Aes aesAlg = Aes.Create())
{
aesAlg.Key = key;
aesAlg.IV = initializationVector;
var encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);
return await PerformCryptography(encryptor, payload);
}
}
// Taken from the examples here: https://msdn.microsoft.com/en-us/library/system.security.cryptography.aes
internal static async Task<byte[]> Decrypt(byte[] payload, byte[] key, byte[] initializationVector)
{
// Create an Aes object
// with the specified key and IV.
using (Aes aesAlg = Aes.Create())
{
aesAlg.Key = key;
aesAlg.IV = initializationVector;
var decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);
return await PerformCryptography(decryptor, payload);
}
}
private static async Task<byte[]> PerformCryptography(ICryptoTransform cryptoTransform, byte[] data)
{
// Create the streams used for encryption.
using (var memoryStream = new MemoryStream())
using (var cryptoStream = new CryptoStream(memoryStream, cryptoTransform, CryptoStreamMode.Write))
{
// Write all data to the memory stream.
await cryptoStream.WriteAsync(data, 0, data.Length);
cryptoStream.FlushFinalBlock();
return memoryStream.ToArray();
}
}
}
}

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

@ -0,0 +1,17 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
namespace Microsoft.Azure.ServiceBus.KeyVault
{
using System;
/// <summary>
/// Represents errors that occur within the <see cref="KeyVaultPlugin"/>.
/// </summary>
public class KeyVaultPluginException : Exception
{
internal KeyVaultPluginException(string message, Exception innerException) : base(message, innerException)
{
}
}
}

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

@ -0,0 +1,54 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
namespace Microsoft.Azure.ServiceBus.KeyVault
{
using System;
/// <summary>
/// The endpoint settings used to create a new <see cref="KeyVaultPlugin"/>.
/// </summary>
public class KeyVaultPluginSettings
{
/// <summary>
/// Creates a new <see cref="KeyVaultPluginSettings"/> object and validates the settings.
/// </summary>
/// <param name="clientId">The endpoint should be a guid.</param>
/// <param name="endpoint">The endpoint should resemble: https://{keyvault-name}.vault.azure.net/</param>
/// <param name="clientSecret">The secret should be a token.</param>
public KeyVaultPluginSettings(string clientId, string endpoint, string clientSecret)
{
if (string.IsNullOrEmpty(clientId))
{
throw new ArgumentNullException(nameof(clientId));
}
if (string.IsNullOrEmpty(endpoint))
{
throw new ArgumentNullException(nameof(endpoint));
}
if (string.IsNullOrEmpty(clientSecret))
{
throw new ArgumentNullException(nameof(clientSecret));
}
this.ClientId = clientId;
this.Endpoint = endpoint;
this.ClientSecret = clientSecret;
}
/// <summary>
/// Gets the KeyVault endpoint.
/// </summary>
public string Endpoint { get; }
/// <summary>
/// Gets the KeyVault ClientId.
/// </summary>
public string ClientId { get; }
/// <summary>
/// Gets the KeyVaultClientSecret.
/// </summary>
public string ClientSecret { get; }
}
}

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

@ -0,0 +1,108 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
namespace Microsoft.Azure.ServiceBus.KeyVault
{
using System;
using System.Collections.Generic;
using System.Security.Cryptography;
using System.Threading.Tasks;
using Microsoft.Azure.KeyVault;
using Microsoft.IdentityModel.Clients.ActiveDirectory;
using System.Text;
internal class KeyVaultSecretManager
{
private static Dictionary<string, byte[]> secretCache;
private string azureClientId;
private string azureClientSecret;
internal string KeyVaultUrl { get; private set; }
internal KeyVaultSecretManager(string keyVaultUrl, string azureClientId, string azureClientSecret)
{
if (string.IsNullOrEmpty(keyVaultUrl))
{
throw new ArgumentNullException(nameof(keyVaultUrl));
}
if (string.IsNullOrEmpty(azureClientId))
{
throw new ArgumentNullException(nameof(azureClientId));
}
if (string.IsNullOrEmpty(azureClientSecret))
{
throw new ArgumentNullException(nameof(azureClientSecret));
}
secretCache = new Dictionary<string, byte[]>();
this.KeyVaultUrl = keyVaultUrl;
this.azureClientId = azureClientId;
this.azureClientSecret = azureClientSecret;
}
internal async Task<byte[]> GetHashedSecret(string secretName)
{
if (secretCache.ContainsKey(secretName))
{
return secretCache[secretName];
}
var secret = await GetSecretFromKeyVault(secretName);
using (var sha256 = SHA256.Create())
{
var secretAsBytes = Encoding.UTF8.GetBytes(secret);
var hashedSecret = sha256.ComputeHash(secretAsBytes);
secretCache.Add(secretName, hashedSecret);
return hashedSecret;
}
}
private async Task<string> GetSecretFromKeyVault(string secretName)
{
using (var keyVaultClient = new KeyVaultClient(GetAccessToken))
{
string secret;
try
{
var secretResult = await keyVaultClient.GetSecretAsync(this.KeyVaultUrl, secretName);
secret = secretResult.Value;
}
catch (Exception ex)
{
throw new KeyVaultPluginException(string.Format(Resources.KeyVaultKeyAcquisitionFailure, secretName, KeyVaultUrl), ex);
}
return secret;
}
// ToDo: Add support for KeyVault service side encryption/decryption
//var encryptedMessage = await keyVaultClient.EncryptAsync(
// KeyVaultUrl,
// SecretName,
// "secretVersion",
// JsonWebKeyEncryptionAlgorithm.RSA15,
// message);
}
private async Task<string> GetAccessToken(string authority, string resource, string scope)
{
var credential = new ClientCredential(this.azureClientId, this.azureClientSecret);
var ctx = new AuthenticationContext(new Uri(authority).AbsoluteUri, false);
AuthenticationResult result;
try
{
result = await ctx.AcquireTokenAsync(resource, credential);
}
catch (Exception ex)
{
throw new KeyVaultPluginException(string.Format(Resources.AzureAdTokenAcquisitionFailure, KeyVaultUrl), ex);
}
return result.AccessToken;
}
}
}

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

@ -0,0 +1,37 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Description>Microsoft.Azure.ServiceBus KeyVault extension</Description>
<AssemblyTitle>Microsoft.Azure.ServiceBus.KeyVault</AssemblyTitle>
<VersionPrefix>0.0.1-preview</VersionPrefix>
<Authors>Microsoft</Authors>
<TargetFrameworks>net451;netstandard1.3</TargetFrameworks>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<AssemblyName>Microsoft.Azure.ServiceBus.KeyVault</AssemblyName>
<AssemblyOriginatorKeyFile>../../build/keyfile.snk</AssemblyOriginatorKeyFile>
<SignAssembly>true</SignAssembly>
<PublicSign Condition=" '$(OS)' != 'Windows_NT' ">true</PublicSign>
<PackageId>Microsoft.Azure.ServiceBus.KeyVault</PackageId>
<PackageTags>Azure;Service Bus;ServiceBus;.NET;AMQP;IoT;Queue;Topic;KeyVault;Encryption;Plugin</PackageTags>
<PackageReleaseNotes>https://github.com/Azure/azure-service-bus-dotnet-plugins/releases</PackageReleaseNotes>
<PackageIconUrl>https://raw.githubusercontent.com/Azure/azure-service-bus-dotnet-plugins/master/service-bus.png</PackageIconUrl>
<PackageProjectUrl>https://github.com/Azure/azure-service-bus-dotnet-plugins</PackageProjectUrl>
<PackageLicenseUrl>https://raw.githubusercontent.com/Azure/azure-service-bus-dotnet-plugins/master/LICENSE</PackageLicenseUrl>
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance>
<PackageTargetFallback Condition=" '$(TargetFramework)' == 'netstandard1.3' ">$(PackageTargetFallback);dnxcore50</PackageTargetFallback>
<NetStandardImplicitPackageVersion Condition=" '$(TargetFramework)' == 'netstandard1.3' ">1.6.1</NetStandardImplicitPackageVersion>
<NetStandardImplicitPackageVersion>1.6.1</NetStandardImplicitPackageVersion>
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
<DocumentationFile>bin\$(Configuration)\$(TargetFramework)\Microsoft.Azure.ServiceBus.KeyVault.xml</DocumentationFile>
<DebugType>full</DebugType>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Azure.KeyVault" Version="2.0.6" />
<PackageReference Include="Microsoft.IdentityModel.Clients.ActiveDirectory" Version="3.13.9" />
<PackageReference Include="Microsoft.Azure.ServiceBus" Version="0.0.6-preview" />
</ItemGroup>
</Project>

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

@ -0,0 +1,30 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Microsoft")]
[assembly: AssemblyProduct("Microsoft.Azure.ServiceBus.KeyVault")]
[assembly: AssemblyTrademark("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("a042adf0-ef65-4f87-b634-322a409f3d61")]
// Friend Assemblies
[assembly: InternalsVisibleTo("Microsoft.Azure.ServiceBus.KeyVault.Test,PublicKey=" +
"0024000004800000940000000602000000240000525341310004000001000100fdf4acac3b2244" +
"dd8a96737e5385b31414369dc3e42f371172127252856a0650793e1f5673a16d5d78e2ac852a10" +
"4bc51e6f018dca44fdd26a219c27cb2b263956a80620223c8e9c2f8913c3c903e1e453e9e4e840" +
"98afdad5f4badb8c1ebe0a7b0a4b57a08454646a65886afe3e290a791ff3260099ce0edf0bdbcc" +
"afadfeb6")]

102
src/Microsoft.Azure.ServiceBus.KeyVault/Resources.Designer.cs сгенерированный Normal file
Просмотреть файл

@ -0,0 +1,102 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace Microsoft.Azure.ServiceBus.KeyVault {
using System;
using System.Reflection;
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
// This class was auto-generated by the StronglyTypedResourceBuilder
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
public class Resources {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
internal Resources() {
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
public static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Microsoft.Azure.ServiceBus.KeyVault.Resources", typeof(Resources).GetTypeInfo().Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
public static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
/// <summary>
/// Looks up a localized string similar to An exception occured while trying to decrypt a message.
/// </summary>
public static string AfterMessageReceiveException
{
get
{
return ResourceManager.GetString("AfterMessageReceiveException", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Could not acquire Azure AD token for KeyVault access. KeyVault: &apos;{0}&apos;.
/// </summary>
public static string AzureAdTokenAcquisitionFailure {
get {
return ResourceManager.GetString("AzureAdTokenAcquisitionFailure", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to An exception occured while trying to encrypt a message.
/// </summary>
public static string BeforeMessageSendException
{
get
{
return ResourceManager.GetString("BeforeMessageSendException", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Could not acquire KeyVault token. Token name: &apos;{0}&apos; KeyVault: &apos;{1}&apos;.
/// </summary>
public static string KeyVaultKeyAcquisitionFailure {
get {
return ResourceManager.GetString("KeyVaultKeyAcquisitionFailure", resourceCulture);
}
}
}
}

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

@ -0,0 +1,132 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="AfterMessageReceiveException" xml:space="preserve">
<value>An exception occured while trying to decrypt a message.</value>
</data>
<data name="AzureAdTokenAcquisitionFailure" xml:space="preserve">
<value>Could not acquire Azure AD token for KeyVault access. KeyVault: '{0}'</value>
</data>
<data name="BeforeMessageSendException" xml:space="preserve">
<value>An exception occured while trying to encrypt a message.</value>
</data>
<data name="KeyVaultKeyAcquisitionFailure" xml:space="preserve">
<value>Could not acquire KeyVault token. Token name: '{0}' KeyVault: '{1}'</value>
</data>
</root>

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

@ -0,0 +1,24 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
namespace Microsoft.Azure.ServiceBus.KeyVault.Test
{
using System.Reflection;
using Microsoft.Extensions.PlatformAbstractions;
using Xunit.Sdk;
public class DisplayTestMethodNameAttribute : BeforeAfterTestAttribute
{
public override void Before(MethodInfo methodUnderTest)
{
TestUtility.Log($"Begin {methodUnderTest.DeclaringType}.{methodUnderTest.Name} on {PlatformServices.Default.Application.RuntimeFramework}");
base.Before(methodUnderTest);
}
public override void After(MethodInfo methodUnderTest)
{
TestUtility.Log($"End {methodUnderTest.DeclaringType}.{methodUnderTest.Name}");
base.After(methodUnderTest);
}
}
}

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

@ -0,0 +1,33 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
namespace Microsoft.Azure.ServiceBus.KeyVault.Test
{
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Azure.ServiceBus.KeyVault;
using Xunit;
public class EncryptionTests
{
[Fact]
[DisplayTestMethodName]
public async Task SmokeTest()
{
var payload = Encoding.UTF8.GetBytes("hello");
var password = "password";
var sha256 = SHA256.Create();
var hash = sha256.ComputeHash(Encoding.UTF8.GetBytes(password));
var iV = KeyVaultPlugin.GenerateInitializationVector();
var encryptedPayload = await KeyVaultPlugin.Encrypt(payload, hash, iV);
var decryptedPayload = await KeyVaultPlugin.Decrypt(encryptedPayload, hash, iV);
Assert.Equal(payload, decryptedPayload);
}
}
}

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

@ -0,0 +1,39 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<AssemblyTitle>Microsoft.Azure.ServiceBus.KeyVault.Test</AssemblyTitle>
<TargetFrameworks>netcoreapp1.0;net46</TargetFrameworks>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<AssemblyName>Microsoft.Azure.ServiceBus.KeyVault.Test</AssemblyName>
<AssemblyOriginatorKeyFile>../../build/keyfile.snk</AssemblyOriginatorKeyFile>
<SignAssembly>true</SignAssembly>
<PublicSign Condition=" '$(OS)' != 'Windows_NT' ">true</PublicSign>
<PackageId>Microsoft.Azure.ServiceBus.KeyVault.Test</PackageId>
<GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles>
<PackageTargetFallback>$(PackageTargetFallback);dnxcore50;portable-net46+win8</PackageTargetFallback>
<RuntimeFrameworkVersion>1.0.4</RuntimeFrameworkVersion>
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
<Description />
<DelaySign>False</DelaySign>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\Microsoft.Azure.ServiceBus.KeyVault\Microsoft.Azure.ServiceBus.KeyVault.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.0.0" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.2.0" />
<PackageReference Include="Microsoft.NETCore.Platforms" Version="1.1.0" />
<PackageReference Include="xunit" Version="2.2.0" />
<PackageReference Include="Microsoft.Extensions.PlatformAbstractions" Version="1.1.0" />
</ItemGroup>
<ItemGroup>
<Service Include="{82a7f48d-3b50-4b1e-b82e-3ada8210c358}" />
</ItemGroup>
</Project>

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

@ -0,0 +1,24 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System.Reflection;
using System.Runtime.InteropServices;
using Xunit;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Microsoft")]
[assembly: AssemblyProduct("Microsoft.Azure.ServiceBus.KeyVault.Test")]
[assembly: AssemblyTrademark("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("bda98e20-3a26-4a5a-9371-cb02b73e3434")]
[assembly: CollectionBehavior(DisableTestParallelization = true)]

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

@ -0,0 +1,18 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
namespace Microsoft.Azure.ServiceBus.KeyVault.Test
{
using System;
using System.Diagnostics;
static class TestUtility
{
internal static void Log(string message)
{
var formattedMessage = $"{DateTime.Now.TimeOfDay}: {message}";
Debug.WriteLine(formattedMessage);
Console.WriteLine(formattedMessage);
}
}
}