diff --git a/AzurePowershell.Test.targets b/AzurePowershell.Test.targets
index f31479edbba2..48ec3a016fda 100644
--- a/AzurePowershell.Test.targets
+++ b/AzurePowershell.Test.targets
@@ -20,6 +20,7 @@
.\src\ServiceManagement\Sql\Commands.SqlDatabase.Test\bin\Debug\Microsoft.WindowsAzure.Commands.SqlDatabase.Test.dll
.\src\ServiceManagement\HDInsight\Commands.HDInsight.Test\bin\Debug\Microsoft.WindowsAzure.Commands.HDInsight.Test.dll
.\src\ServiceManagement\Storage\Commands.Storage.Test\bin\Debug\Microsoft.WindowsAzure.Commands.Storage.Test.dll
+ .\src\ResourceManager\KeyVault\Commands.KeyVault.Test\bin\Debug\Microsoft.Azure.Commands.KeyVault.Test.dll
"!Functional&!Scenario&!AzureRTScenario&!Sequential&!PIRTest&!Preview&!ADDomain"
All
"OneSDK&CIT"
@@ -131,6 +132,13 @@
+
+
+
+
+
+
diff --git a/build.proj b/build.proj
index 842a3404259d..dce09d5fcd58 100644
--- a/build.proj
+++ b/build.proj
@@ -194,7 +194,7 @@
-
+
diff --git a/setup/azurecmdfiles.wxi b/setup/azurecmdfiles.wxi
index a32a2abc0bf9..6fdc8829bb14 100644
--- a/setup/azurecmdfiles.wxi
+++ b/setup/azurecmdfiles.wxi
@@ -149,6 +149,65 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -2027,6 +2086,25 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/AzurePowershell.sln b/src/AzurePowershell.sln
index d06e75409380..8515793e1ade 100644
--- a/src/AzurePowershell.sln
+++ b/src/AzurePowershell.sln
@@ -143,6 +143,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Commands.Network", "Service
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Commands.Network.Test", "ServiceManagement\Network\Commands.Network.Test\Commands.Network.Test.csproj", "{FDB897BD-FCB4-44A1-8D66-AC99F22EC737}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Commands.KeyVault", "ResourceManager\KeyVault\Commands.KeyVault\Commands.KeyVault.csproj", "{9FFC40CC-A341-4D0C-A25D-DC6B78EF6C94}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Commands.KeyVault.Test", "ResourceManager\KeyVault\Commands.KeyVault.Test\Commands.KeyVault.Test.csproj", "{080B0477-7E52-4455-90AB-23BD13D1B1CE}"
+EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Commands.RecoveryServices", "ServiceManagement\RecoveryServices\Commands.RecoveryServices\Commands.RecoveryServices.csproj", "{98B10548-DF97-4FB1-8D82-2A12945D4F21}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Commands.RecoveryServices.Test", "ServiceManagement\RecoveryServices\Commands.RecoveryServices.Test\Commands.RecoveryServices.Test.csproj", "{A415F75B-EB6A-49A6-934E-5BA71B83D6EB}"
@@ -341,6 +345,10 @@ Global
{FDB897BD-FCB4-44A1-8D66-AC99F22EC737}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FDB897BD-FCB4-44A1-8D66-AC99F22EC737}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FDB897BD-FCB4-44A1-8D66-AC99F22EC737}.Release|Any CPU.Build.0 = Release|Any CPU
+ {9FFC40CC-A341-4D0C-A25D-DC6B78EF6C94}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {9FFC40CC-A341-4D0C-A25D-DC6B78EF6C94}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {9FFC40CC-A341-4D0C-A25D-DC6B78EF6C94}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {9FFC40CC-A341-4D0C-A25D-DC6B78EF6C94}.Release|Any CPU.Build.0 = Release|Any CPU
{98B10548-DF97-4FB1-8D82-2A12945D4F21}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{98B10548-DF97-4FB1-8D82-2A12945D4F21}.Debug|Any CPU.Build.0 = Debug|Any CPU
{98B10548-DF97-4FB1-8D82-2A12945D4F21}.Release|Any CPU.ActiveCfg = Release|Any CPU
@@ -349,6 +357,10 @@ Global
{A415F75B-EB6A-49A6-934E-5BA71B83D6EB}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A415F75B-EB6A-49A6-934E-5BA71B83D6EB}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A415F75B-EB6A-49A6-934E-5BA71B83D6EB}.Release|Any CPU.Build.0 = Release|Any CPU
+ {080B0477-7E52-4455-90AB-23BD13D1B1CE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {080B0477-7E52-4455-90AB-23BD13D1B1CE}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {080B0477-7E52-4455-90AB-23BD13D1B1CE}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {080B0477-7E52-4455-90AB-23BD13D1B1CE}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -378,5 +390,6 @@ Global
{F4ABAD68-64A5-4B23-B09C-42559A7524DE} = {95C16AED-FD57-42A0-86C3-2CF4300A4817}
{FDB897BD-FCB4-44A1-8D66-AC99F22EC737} = {95C16AED-FD57-42A0-86C3-2CF4300A4817}
{A415F75B-EB6A-49A6-934E-5BA71B83D6EB} = {95C16AED-FD57-42A0-86C3-2CF4300A4817}
+ {080B0477-7E52-4455-90AB-23BD13D1B1CE} = {95C16AED-FD57-42A0-86C3-2CF4300A4817}
EndGlobalSection
EndGlobal
diff --git a/src/Common/Commands.Common.Test/Mocks/MockCertificateAuthenticationFactory.cs b/src/Common/Commands.Common.Test/Mocks/MockCertificateAuthenticationFactory.cs
index 746486b575b3..ed6693abdaad 100644
--- a/src/Common/Commands.Common.Test/Mocks/MockCertificateAuthenticationFactory.cs
+++ b/src/Common/Commands.Common.Test/Mocks/MockCertificateAuthenticationFactory.cs
@@ -33,7 +33,8 @@ public MockCertificateAuthenticationFactory(string userId, X509Certificate2 cert
Certificate = certificate;
}
- public IAccessToken Authenticate(AzureAccount account, AzureEnvironment environment, string tenant, SecureString password, ShowDialog promptBehavior)
+ public IAccessToken Authenticate(AzureAccount account, AzureEnvironment environment, string tenant, SecureString password, ShowDialog promptBehavior,
+ AzureEnvironment.Endpoint resourceId = AzureEnvironment.Endpoint.ActiveDirectoryServiceEndpointResourceId)
{
if (account.Id == null)
{
diff --git a/src/Common/Commands.Common.Test/Mocks/MockTokenAuthenticationFactory.cs b/src/Common/Commands.Common.Test/Mocks/MockTokenAuthenticationFactory.cs
index ee85746615f2..e7f44786bfa0 100644
--- a/src/Common/Commands.Common.Test/Mocks/MockTokenAuthenticationFactory.cs
+++ b/src/Common/Commands.Common.Test/Mocks/MockTokenAuthenticationFactory.cs
@@ -43,7 +43,8 @@ public MockTokenAuthenticationFactory(string userId, string accessToken)
};
}
- public IAccessToken Authenticate(AzureAccount account, AzureEnvironment environment, string tenant, SecureString password, ShowDialog promptBehavior)
+ public IAccessToken Authenticate(AzureAccount account, AzureEnvironment environment, string tenant, SecureString password, ShowDialog promptBehavior,
+ AzureEnvironment.Endpoint resourceId = AzureEnvironment.Endpoint.ActiveDirectoryServiceEndpointResourceId)
{
if (account.Id == null)
{
diff --git a/src/Common/Commands.Common/Common/ManagementConstants.cs b/src/Common/Commands.Common/Common/ManagementConstants.cs
index 3b79dca0460f..ae5d4331c79f 100644
--- a/src/Common/Commands.Common/Common/ManagementConstants.cs
+++ b/src/Common/Commands.Common/Common/ManagementConstants.cs
@@ -117,5 +117,9 @@ public static class AzureEnvironmentConstants
public const string AzureTrafficManagerDnsSuffix = "trafficmanager.net";
public const string ChinaTrafficManagerDnsSuffix = "trafficmanager.cn";
+
+ public const string AzureKeyVaultDnsSuffix = "vault.azure.net";
+
+ public const string AzureKeyVaultServiceEndpointResourceId = "https://vault.azure.net";
}
}
\ No newline at end of file
diff --git a/src/Common/Commands.Common/Common/RequiredResourceLookup.cs b/src/Common/Commands.Common/Common/RequiredResourceLookup.cs
index cef962cafef4..1805032afe26 100644
--- a/src/Common/Commands.Common/Common/RequiredResourceLookup.cs
+++ b/src/Common/Commands.Common/Common/RequiredResourceLookup.cs
@@ -52,7 +52,8 @@ internal static IList RequiredProvidersForResourceManager() where T :
"microsoft.visualstudio",
"microsoft.insights",
"successbricks.cleardb",
- "microsoft.cache" };
+ "microsoft.cache",
+ "Microsoft.KeyVault"};
}
if (typeof(T).FullName.EndsWith("BatchManagementClient"))
{
diff --git a/src/Common/Commands.Common/Factories/AuthenticationFactory.cs b/src/Common/Commands.Common/Factories/AuthenticationFactory.cs
index a897f4fe3b7e..5a033b2e96b1 100644
--- a/src/Common/Commands.Common/Factories/AuthenticationFactory.cs
+++ b/src/Common/Commands.Common/Factories/AuthenticationFactory.cs
@@ -31,14 +31,15 @@ public AuthenticationFactory()
}
public ITokenProvider TokenProvider { get; set; }
+
- public IAccessToken Authenticate(AzureAccount account, AzureEnvironment environment, string tenant, SecureString password, ShowDialog promptBehavior)
+ public IAccessToken Authenticate(AzureAccount account, AzureEnvironment environment, string tenant, SecureString password, ShowDialog promptBehavior,
+ AzureEnvironment.Endpoint resourceId = AzureEnvironment.Endpoint.ActiveDirectoryServiceEndpointResourceId)
{
- var token = TokenProvider.GetAccessToken(GetAdalConfiguration(environment, tenant), promptBehavior, account.Id, password, account.Type);
+ var token = TokenProvider.GetAccessToken(GetAdalConfiguration(environment, tenant, resourceId), promptBehavior, account.Id, password, account.Type);
account.Id = token.UserId;
return token;
}
-
public SubscriptionCloudCredentials GetSubscriptionCloudCredentials(AzureContext context)
{
if (context.Subscription == null)
@@ -76,20 +77,21 @@ public SubscriptionCloudCredentials GetSubscriptionCloudCredentials(AzureContext
throw new ArgumentException(Resources.InvalidSubscriptionState, ex);
}
}
-
- private AdalConfiguration GetAdalConfiguration(AzureEnvironment environment, string tenantId)
+
+
+ private AdalConfiguration GetAdalConfiguration(AzureEnvironment environment, string tenantId,
+ AzureEnvironment.Endpoint resourceId)
{
if (environment == null)
{
throw new ArgumentNullException("environment");
}
var adEndpoint = environment.Endpoints[AzureEnvironment.Endpoint.ActiveDirectory];
- var adResourceId = environment.Endpoints[AzureEnvironment.Endpoint.ActiveDirectoryServiceEndpointResourceId];
-
+
return new AdalConfiguration
{
AdEndpoint = adEndpoint,
- ResourceClientUri = adResourceId,
+ ResourceClientUri = environment.Endpoints[resourceId],
AdDomain = tenantId
};
}
diff --git a/src/Common/Commands.Common/Interfaces/IAuthenticationFactory.cs b/src/Common/Commands.Common/Interfaces/IAuthenticationFactory.cs
index 9e052857a09d..46748f8d811a 100644
--- a/src/Common/Commands.Common/Interfaces/IAuthenticationFactory.cs
+++ b/src/Common/Commands.Common/Interfaces/IAuthenticationFactory.cs
@@ -28,8 +28,9 @@ public interface IAuthenticationFactory
///
///
///
- ///
- IAccessToken Authenticate(AzureAccount account, AzureEnvironment environment, string tenant, SecureString password, ShowDialog promptBehavior);
+ ///
+ IAccessToken Authenticate(AzureAccount account, AzureEnvironment environment, string tenant, SecureString password, ShowDialog promptBehavior,
+ AzureEnvironment.Endpoint resourceId = AzureEnvironment.Endpoint.ActiveDirectoryServiceEndpointResourceId);
SubscriptionCloudCredentials GetSubscriptionCloudCredentials(AzureContext context);
}
diff --git a/src/Common/Commands.Common/Models/AzureEnvironment.Methods.cs b/src/Common/Commands.Common/Models/AzureEnvironment.Methods.cs
index a4d3d0fee987..5525bad09fde 100644
--- a/src/Common/Commands.Common/Models/AzureEnvironment.Methods.cs
+++ b/src/Common/Commands.Common/Models/AzureEnvironment.Methods.cs
@@ -97,6 +97,8 @@ private string StorageFileEndpointFormat()
{ AzureEnvironment.Endpoint.SqlDatabaseDnsSuffix, AzureEnvironmentConstants.AzureSqlDatabaseDnsSuffix },
{ AzureEnvironment.Endpoint.Graph, AzureEnvironmentConstants.AzureGraphEndpoint },
{ AzureEnvironment.Endpoint.TrafficManagerDnsSuffix, AzureEnvironmentConstants.AzureTrafficManagerDnsSuffix },
+ { AzureEnvironment.Endpoint.AzureKeyVaultDnsSuffix, AzureEnvironmentConstants.AzureKeyVaultDnsSuffix },
+ { AzureEnvironment.Endpoint.AzureKeyVaultServiceEndpointResourceId, AzureEnvironmentConstants.AzureKeyVaultServiceEndpointResourceId },
}
}
},
@@ -255,7 +257,7 @@ public string GetPublishSettingsFileUrlWithRealm(string realm = null)
public enum Endpoint
{
- ActiveDirectoryServiceEndpointResourceId,
+ ActiveDirectoryServiceEndpointResourceId,
AdTenant,
@@ -278,6 +280,10 @@ public enum Endpoint
Graph,
TrafficManagerDnsSuffix,
+
+ AzureKeyVaultDnsSuffix,
+
+ AzureKeyVaultServiceEndpointResourceId,
}
}
}
diff --git a/src/Common/Commands.ScenarioTests.Common/Constants.cs b/src/Common/Commands.ScenarioTests.Common/Constants.cs
index 8bbf163f0c4f..3dfea33dcccf 100644
--- a/src/Common/Commands.ScenarioTests.Common/Constants.cs
+++ b/src/Common/Commands.ScenarioTests.Common/Constants.cs
@@ -50,6 +50,8 @@ public class Category
public const string Scheduler = "Scheduler";
+ public const string KeyVault = "KeyVault";
+
public const string Network = "Network";
// Owners
diff --git a/src/ResourceManager.sln b/src/ResourceManager.sln
index 2d9218889c15..26263e8addc8 100644
--- a/src/ResourceManager.sln
+++ b/src/ResourceManager.sln
@@ -37,6 +37,12 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Commands.RedisCache", "Reso
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Commands.RedisCache.Test", "ResourceManager\RedisCache\Commands.RedisCache.Test\Commands.RedisCache.Test.csproj", "{4AE5705F-62CF-461D-B72E-DD9DCD9B3609}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Commands.KeyVault", "ResourceManager\KeyVault\Commands.KeyVault\Commands.KeyVault.csproj", "{9FFC40CC-A341-4D0C-A25D-DC6B78EF6C94}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Commands.KeyVault.Test", "ResourceManager\KeyVault\Commands.KeyVault.Test\Commands.KeyVault.Test.csproj", "{080B0477-7E52-4455-90AB-23BD13D1B1CE}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Commands.Sql.Test", "ResourceManager\Sql\Commands.Sql.Test\Commands.Sql.Test.csproj", "{56ED8C97-53B9-4DF6-ACB5-7E6800105BF8}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -95,6 +101,18 @@ Global
{4AE5705F-62CF-461D-B72E-DD9DCD9B3609}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4AE5705F-62CF-461D-B72E-DD9DCD9B3609}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4AE5705F-62CF-461D-B72E-DD9DCD9B3609}.Release|Any CPU.Build.0 = Release|Any CPU
+ {9FFC40CC-A341-4D0C-A25D-DC6B78EF6C94}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {9FFC40CC-A341-4D0C-A25D-DC6B78EF6C94}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {9FFC40CC-A341-4D0C-A25D-DC6B78EF6C94}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {9FFC40CC-A341-4D0C-A25D-DC6B78EF6C94}.Release|Any CPU.Build.0 = Release|Any CPU
+ {080B0477-7E52-4455-90AB-23BD13D1B1CE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {080B0477-7E52-4455-90AB-23BD13D1B1CE}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {080B0477-7E52-4455-90AB-23BD13D1B1CE}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {080B0477-7E52-4455-90AB-23BD13D1B1CE}.Release|Any CPU.Build.0 = Release|Any CPU
+ {56ED8C97-53B9-4DF6-ACB5-7E6800105BF8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {56ED8C97-53B9-4DF6-ACB5-7E6800105BF8}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {56ED8C97-53B9-4DF6-ACB5-7E6800105BF8}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {56ED8C97-53B9-4DF6-ACB5-7E6800105BF8}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -105,5 +123,7 @@ Global
{C1BDA476-A5CC-4394-914D-48B0EC31A710} = {95C16AED-FD57-42A0-86C3-2CF4300A4817}
{D4EDAD6F-6A1D-4295-9A88-CD3F69EAD42B} = {95C16AED-FD57-42A0-86C3-2CF4300A4817}
{4AE5705F-62CF-461D-B72E-DD9DCD9B3609} = {95C16AED-FD57-42A0-86C3-2CF4300A4817}
+ {080B0477-7E52-4455-90AB-23BD13D1B1CE} = {95C16AED-FD57-42A0-86C3-2CF4300A4817}
+ {56ED8C97-53B9-4DF6-ACB5-7E6800105BF8} = {95C16AED-FD57-42A0-86C3-2CF4300A4817}
EndGlobalSection
EndGlobal
diff --git a/src/ResourceManager/KeyVault/Commands.KeyVault.Test/Commands.KeyVault.Test.csproj b/src/ResourceManager/KeyVault/Commands.KeyVault.Test/Commands.KeyVault.Test.csproj
new file mode 100644
index 000000000000..030eb98b9cb6
--- /dev/null
+++ b/src/ResourceManager/KeyVault/Commands.KeyVault.Test/Commands.KeyVault.Test.csproj
@@ -0,0 +1,164 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {080B0477-7E52-4455-90AB-23BD13D1B1CE}
+ Library
+ Properties
+ Microsoft.Azure.Commands.KeyVault.Test
+ Microsoft.Azure.Commands.KeyVault.Test
+ v4.5
+ 512
+
+ ..\..\
+ true
+ {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
+
+
+ true
+ full
+ false
+ bin\Debug
+ DEBUG;TRACE
+ prompt
+ 4
+ true
+ true
+ false
+
+
+ bin\Release
+ TRACE;SIGN
+ true
+ pdbonly
+ AnyCPU
+ bin\Release\Common.Test.dll.CodeAnalysisLog.xml
+ true
+ GlobalSuppressions.cs
+ prompt
+ MinimumRecommendedRules.ruleset
+ ;$(ProgramFiles)\Microsoft Visual Studio 12.0\Team Tools\Static Analysis Tools\Rule Sets
+ ;$(ProgramFiles)\Microsoft Visual Studio 12.0\Team Tools\Static Analysis Tools\FxCop\Rules
+ true
+ MSSharedLibKey.snk
+ true
+ true
+ false
+
+
+
+ ..\..\..\packages\Hydra.HttpRecorder.1.0.5406.28672-prerelease\lib\net45\Microsoft.Azure.Utilities.HttpRecorder.dll
+
+
+ False
+ ..\..\..\packages\Microsoft.IdentityModel.Clients.ActiveDirectory.2.11.10918.1222\lib\net45\Microsoft.IdentityModel.Clients.ActiveDirectory.WindowsForms.dll
+
+
+ False
+ ..\..\..\packages\Microsoft.KeyVault.Client.1.0.0.20\lib\net45\Microsoft.KeyVault.Client.dll
+
+
+ False
+ ..\..\..\packages\Microsoft.KeyVault.WebKey.1.0.0.10\lib\net45\Microsoft.KeyVault.WebKey.dll
+
+
+ ..\..\..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.dll
+
+
+ ..\..\..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.Extensions.dll
+
+
+ ..\..\..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.Extensions.Desktop.dll
+
+
+
+ False
+ ..\..\..\packages\Microsoft.WindowsAzure.Common.1.4.0\lib\net45\Microsoft.WindowsAzure.Common.dll
+
+
+ False
+ ..\..\..\packages\Microsoft.WindowsAzure.Common.1.4.0\lib\net45\Microsoft.WindowsAzure.Common.NetFramework.dll
+
+
+ ..\..\..\packages\Hydra.SpecTestSupport.1.0.5406.28672-prerelease\lib\net45\Microsoft.WindowsAzure.Testing.dll
+
+
+ False
+ ..\..\..\packages\Moq.4.2.1409.1722\lib\net40\Moq.dll
+
+
+ False
+ ..\..\..\packages\Newtonsoft.Json.6.0.4\lib\net45\Newtonsoft.Json.dll
+
+
+ False
+ C:\Windows\Microsoft.NET\assembly\GAC_MSIL\System.Management.Automation\v4.0_3.0.0.0__31bf3856ad364e35\System.Management.Automation.dll
+
+
+
+
+
+ ..\..\..\packages\Microsoft.Net.Http.2.2.28\lib\net45\System.Net.Http.Extensions.dll
+
+
+ ..\..\..\packages\Microsoft.Net.Http.2.2.28\lib\net45\System.Net.Http.Primitives.dll
+
+
+
+ ..\..\..\packages\xunit.1.9.2\lib\net20\xunit.dll
+
+
+
+
+
+ True
+ True
+ Resource.resx
+
+
+
+
+
+
+
+
+
+
+ Designer
+
+
+
+
+
+ {5ee72c53-1720-4309-b54b-5fb79703195f}
+ Commands.Common
+
+
+ {c1bda476-a5cc-4394-914d-48b0ec31a710}
+ Commands.ScenarioTests.Common
+
+
+ {9ffc40cc-a341-4d0c-a25d-dc6b78ef6c94}
+ Commands.KeyVault
+
+
+
+
+ ResXFileCodeGenerator
+ Resource.Designer.cs
+
+
+
+
+
+
+
+
+
+
+
+ xcopy "$(SolutionDir)Package\$(ConfigurationName)\*.*" $(TargetDir) /Y /E
+
+
\ No newline at end of file
diff --git a/src/ResourceManager/KeyVault/Commands.KeyVault.Test/MSSharedLibKey.snk b/src/ResourceManager/KeyVault/Commands.KeyVault.Test/MSSharedLibKey.snk
new file mode 100644
index 000000000000..695f1b38774e
Binary files /dev/null and b/src/ResourceManager/KeyVault/Commands.KeyVault.Test/MSSharedLibKey.snk differ
diff --git a/src/ResourceManager/KeyVault/Commands.KeyVault.Test/Models/UtilitiesTests.cs b/src/ResourceManager/KeyVault/Commands.KeyVault.Test/Models/UtilitiesTests.cs
new file mode 100644
index 000000000000..8ec81185f135
--- /dev/null
+++ b/src/ResourceManager/KeyVault/Commands.KeyVault.Test/Models/UtilitiesTests.cs
@@ -0,0 +1,72 @@
+// ----------------------------------------------------------------------------------
+//
+// Copyright Microsoft Corporation
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+// ----------------------------------------------------------------------------------
+
+using System;
+using Microsoft.Azure.Commands.KeyVault.Models;
+using Microsoft.KeyVault.WebKey;
+using Microsoft.WindowsAzure.Commands.ScenarioTest;
+using System.IO;
+using System.Linq;
+using System.Security.Cryptography;
+using Xunit;
+using System.Security.Cryptography.X509Certificates;
+
+namespace Microsoft.Azure.Commands.KeyVault.Test.Models
+{
+ public class UtilitiesTests
+ {
+ [Fact]
+ [Trait(Category.KeyVault, Category.CheckIn)]
+ public void ConvertStringAndSecureString()
+ {
+ var origStr = "this is test string";
+ var secureString = origStr.ToSecureString();
+ var convStr = secureString.ToStringExt();
+
+ Assert.Equal( origStr, convStr );
+ }
+
+ [Fact]
+ [Trait(Category.KeyVault, Category.CheckIn)]
+ public void GetWebKeyFromByok()
+ {
+ Random rnd = new Random();
+ byte[] byokBlob = new byte[100];
+ rnd.NextBytes(byokBlob);
+ string tempPath = Path.GetTempFileName() + ".byok";
+ File.WriteAllBytes(tempPath, byokBlob);
+ IWebKeyConverter converters = WebKeyConverterFactory.CreateConverterChain();
+ var webKey = converters.ConvertKeyFromFile(new FileInfo(tempPath), null);
+
+ Assert.True(webKey.T.SequenceEqual(byokBlob));
+ Assert.Equal(webKey.Kty, JsonWebKeyType.RsaHsm);
+ }
+
+ [Fact]
+ [Trait(Category.KeyVault, Category.CheckIn)]
+ public void GetWebKeyFromCertificate()
+ {
+ string password = "123";
+ string tempPath = Path.GetTempFileName() + ".pfx";
+ File.WriteAllBytes(tempPath, Resource.pfxCert);
+
+ IWebKeyConverter converters = WebKeyConverterFactory.CreateConverterChain();
+ var webKey = converters.ConvertKeyFromFile(new FileInfo(tempPath), password.ToSecureString());
+
+ Assert.True(webKey.HasPrivateKey());
+ Assert.True(webKey.IsValid());
+ Assert.Equal(webKey.Kty, JsonWebKeyType.Rsa);
+ }
+ }
+}
diff --git a/src/ResourceManager/KeyVault/Commands.KeyVault.Test/Properties/AssemblyInfo.cs b/src/ResourceManager/KeyVault/Commands.KeyVault.Test/Properties/AssemblyInfo.cs
new file mode 100644
index 000000000000..f00455fcb2ac
--- /dev/null
+++ b/src/ResourceManager/KeyVault/Commands.KeyVault.Test/Properties/AssemblyInfo.cs
@@ -0,0 +1,50 @@
+// ----------------------------------------------------------------------------------
+//
+// Copyright Microsoft Corporation
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+// ----------------------------------------------------------------------------------
+
+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: AssemblyTitle( "Microsoft.Azure.Commands.KeyVault.Test" )]
+[assembly: AssemblyDescription( "" )]
+[assembly: AssemblyConfiguration( "" )]
+[assembly: AssemblyCompany( "" )]
+[assembly: AssemblyProduct( "Microsoft.Azure.Commands.KeyVault.Test" )]
+[assembly: AssemblyCopyright( "Copyright © 2014" )]
+[assembly: AssemblyTrademark( "" )]
+[assembly: AssemblyCulture( "" )]
+
+// 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( "92c42e00-f56b-406a-af5d-0d870d454f55" )]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion( "1.0.0.0" )]
+[assembly: AssemblyFileVersion( "1.0.0.0" )]
diff --git a/src/ResourceManager/KeyVault/Commands.KeyVault.Test/Resource.Designer.cs b/src/ResourceManager/KeyVault/Commands.KeyVault.Test/Resource.Designer.cs
new file mode 100644
index 000000000000..e6ee07174dcb
--- /dev/null
+++ b/src/ResourceManager/KeyVault/Commands.KeyVault.Test/Resource.Designer.cs
@@ -0,0 +1,73 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+// Runtime Version:4.0.30319.18449
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+namespace Microsoft.Azure.Commands.KeyVault.Test {
+ using System;
+
+
+ ///
+ /// A strongly-typed resource class, for looking up localized strings, etc.
+ ///
+ // 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.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ internal class Resource {
+
+ private static global::System.Resources.ResourceManager resourceMan;
+
+ private static global::System.Globalization.CultureInfo resourceCulture;
+
+ [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ internal Resource() {
+ }
+
+ ///
+ /// Returns the cached ResourceManager instance used by this class.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Resources.ResourceManager ResourceManager {
+ get {
+ if (object.ReferenceEquals(resourceMan, null)) {
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Microsoft.Azure.Commands.KeyVault.Test.Resource", typeof(Resource).Assembly);
+ resourceMan = temp;
+ }
+ return resourceMan;
+ }
+ }
+
+ ///
+ /// Overrides the current thread's CurrentUICulture property for all
+ /// resource lookups using this strongly typed resource class.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Globalization.CultureInfo Culture {
+ get {
+ return resourceCulture;
+ }
+ set {
+ resourceCulture = value;
+ }
+ }
+
+ ///
+ /// Looks up a localized resource of type System.Byte[].
+ ///
+ internal static byte[] pfxCert {
+ get {
+ object obj = ResourceManager.GetObject("pfxCert", resourceCulture);
+ return ((byte[])(obj));
+ }
+ }
+ }
+}
diff --git a/src/ResourceManager/KeyVault/Commands.KeyVault.Test/Resource.resx b/src/ResourceManager/KeyVault/Commands.KeyVault.Test/Resource.resx
new file mode 100644
index 000000000000..2d24425dc6d2
--- /dev/null
+++ b/src/ResourceManager/KeyVault/Commands.KeyVault.Test/Resource.resx
@@ -0,0 +1,124 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+
+ Resources\pshtest.pfx;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/src/ResourceManager/KeyVault/Commands.KeyVault.Test/Resources/pshtest.pfx b/src/ResourceManager/KeyVault/Commands.KeyVault.Test/Resources/pshtest.pfx
new file mode 100644
index 000000000000..fefc03c0d0a0
Binary files /dev/null and b/src/ResourceManager/KeyVault/Commands.KeyVault.Test/Resources/pshtest.pfx differ
diff --git a/src/ResourceManager/KeyVault/Commands.KeyVault.Test/Scripts/Common.ps1 b/src/ResourceManager/KeyVault/Commands.KeyVault.Test/Scripts/Common.ps1
new file mode 100644
index 000000000000..35857d0d61ac
--- /dev/null
+++ b/src/ResourceManager/KeyVault/Commands.KeyVault.Test/Scripts/Common.ps1
@@ -0,0 +1,264 @@
+# ----------------------------------------------------------------------------------
+#
+# Copyright Microsoft Corporation
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+# http://www.apache.org/licenses/LICENSE-2.0
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+# ----------------------------------------------------------------------------------
+
+$global:createdKeys = @()
+$global:createdSecrets = @()
+
+$invocationPath = Split-Path $MyInvocation.MyCommand.Definition;
+
+<#
+.SYNOPSIS
+Get test key name
+#>
+function Get-KeyVault([bool] $haspermission=$true)
+{
+ if ($global:testEnv -eq 'BVT' -and $haspermission)
+ {
+ return 'powershellbvt'
+ }
+ elseif ($global:testEnv -eq 'BVT')
+ {
+ return 'azkmstestbvteu2'
+ }
+ elseif ($haspermission)
+ {
+ return 'azkmspsprodeus'
+ }
+ else
+ {
+ return 'azkmspsnopermprodeus'
+ }
+}
+
+<#
+.SYNOPSIS
+Get test key name
+#>
+function Get-KeyName([string]$suffix)
+{
+ return 'pshtk-' + $global:testns+ '-' + $suffix
+}
+
+<#
+.SYNOPSIS
+Get test secret name
+#>
+function Get-SecretName([string]$suffix)
+{
+ return 'pshts-' + $global:testns+ '-' + $suffix
+}
+
+
+<#
+.SYNOPSIS
+Get key file path to be imported
+The name convention of a key file is $filesuffixtest.$filesuffix
+#>
+function Get-ImportKeyFile([string]$filesuffix, [bool] $exists=$true)
+{
+ if ($exists)
+ {
+ $file = "$filesuffix"+"test.$filesuffix"
+ }
+ else
+ {
+ $file = "notexist" + ".$filesuffix"
+ }
+
+ if ($global:testEnv -eq 'BVT')
+ {
+ return Join-Path $invocationPath "bvtdata\$file"
+ }
+ else
+ {
+ return Join-Path $invocationPath "proddata\$file"
+ }
+}
+
+<#
+.SYNOPSIS
+Remove log file under a folder
+#>
+function Cleanup-Log([string]$rootfolder)
+{
+ Get-ChildItem –Path $rootfolder -Include *.debug_log -Recurse | where {$_.mode -match "a"} | Remove-Item -Force
+}
+
+<#
+.SYNOPSIS
+Remove log file under a folder
+#>
+function Move-Log([string]$rootfolder)
+{
+ $logfolder = Join-Path $rootfolder ("$global:testEnv"+"$global:testns"+"log")
+ if (Test-Path $logfolder)
+ {
+ Cleanup-Log $logfolder
+ }
+ else
+ {
+ New-Item $logfolder -type directory -force
+ }
+
+ Get-ChildItem –Path $rootfolder -Include *.debug_log -Recurse | Move-Item -Destination $logfolder
+}
+
+
+<#
+.SYNOPSIS
+Removes all keys starting with the prefix
+#>
+function Initialize-KeyTest
+{
+ $keyVault = Get-KeyVault
+ $keyPattern = Get-KeyName '*'
+ Get-AzureKeyVaultKey $keyVault | Where-Object {$_.KeyName -like $keyPattern} | Remove-AzureKeyVaultKey -Force -Confirm:$false
+}
+
+<#
+.SYNOPSIS
+Removes all secrets starting with the prefix
+#>
+function Initialize-SecretTest
+{
+ $keyVault = Get-KeyVault
+ $secretPattern = Get-SecretName '*'
+ Get-AzureKeyVaultSecret $keyVault | Where-Object {$_.SecretName -like $secretPattern} | Remove-AzureKeyVaultSecret -Force -Confirm:$false
+}
+
+
+
+<#
+.SYNOPSIS
+Removes all created keys.
+#>
+function Cleanup-SingleKeyTest
+{
+ $global:createdKeys | % {
+ if ($_ -ne $null)
+ {
+ try
+ {
+ $keyVault = Get-KeyVault
+ Write-Debug "Removing key with name $_ in vault $keyVault"
+ $catch = Remove-AzureKeyVaultKey $keyVault $_ -Force -Confirm:$false
+ }
+ catch
+ {
+ }
+ }
+ }
+
+ $global:createdKeys.Clear()
+}
+
+<#
+.SYNOPSIS
+Removes all created secrets.
+#>
+function Cleanup-SingleSecretTest
+{
+ $global:createdSecrets | % {
+ if ($_ -ne $null)
+ {
+ try
+ {
+ $keyVault = Get-KeyVault
+ Write-Debug "Removing secret with name $_ in vault $keyVault"
+ $catch = Remove-AzureKeyVaultSecret $keyVault $_ -Force -Confirm:$false
+ }
+ catch
+ {
+ }
+ }
+ }
+
+ $global:createdSecrets.Clear()
+}
+
+<#
+.SYNOPSIS
+Run a key test, with cleanup.
+#>
+function Run-KeyTest ([ScriptBlock] $test, [string] $testName)
+{
+ try
+ {
+ Run-Test $test $testName *>> "$testName.debug_log"
+ }
+ finally
+ {
+ Cleanup-SingleKeyTest *>> "$testName.debug_log"
+ }
+}
+
+function Run-SecretTest ([ScriptBlock] $test, [string] $testName)
+{
+ try
+ {
+ Run-Test $test $testName *>> "$testName.debug_log"
+ }
+ finally
+ {
+ Cleanup-SingleSecretTest *>> "$testName.debug_log"
+ }
+}
+
+function Write-FileReport
+{
+ $fileName = "$global:testEnv"+"$global:testns"+"Summary.debug_log"
+ Get-TestRunReport *>> $fileName
+}
+
+
+function Get-TestRunReport
+{
+
+ Write-Output "PASSED TEST Count=$global:passedCount"
+ Write-Output "Total TEST Count=$global:totalCount"
+ Write-Output "Start Time=$global:startTime"
+ Write-Output "End Time=$global:endTime"
+ $elapsed=$global:endTime - $global:startTime
+ Write-Output "Elapsed=$elapsed"
+
+ Write-Output "Passed TEST`tExecutionTime"
+ $global:passedTests | % { $extime=$global:times[$_]; Write-Output $_`t$extime }
+ Write-Output "Failed TEST lists"
+ $global:failedTests | % { $extime=$global:times[$_]; Write-Output $_`t$extime }
+}
+
+function Write-ConsoleReport
+{
+ Write-Host
+ Write-Host -ForegroundColor Green "$global:passedCount / $global:totalCount Key Vault Tests Pass"
+ Write-Host -ForegroundColor Green "============"
+ Write-Host -ForegroundColor Green "PASSED TESTS"
+ Write-Host -ForegroundColor Green "============"
+ $global:passedTests | % { Write-Host -ForegroundColor Green "PASSED "$_": "($global:times[$_]).ToString()}
+ Write-Host -ForegroundColor Green "============"
+ Write-Host
+ Write-Host -ForegroundColor Red "============"
+ Write-Host -ForegroundColor Red "FAILED TESTS"
+ Write-Host -ForegroundColor Red "============"
+ $global:failedTests | % { Write-Host -ForegroundColor Red "FAILED "$_": "($global:times[$_]).ToString()}
+ Write-Host -ForegroundColor Red "============"
+ Write-Host
+ Write-Host -ForegroundColor Green "======="
+ Write-Host -ForegroundColor Green "TIMES"
+ Write-Host -ForegroundColor Green "======="
+ Write-Host
+ Write-Host -ForegroundColor Green "Start Time: $global:startTime"
+ Write-Host -ForegroundColor Green "End Time: $global:endTime"
+ Write-Host -ForegroundColor Green "Elapsed: "($global:endTime - $global:startTime).ToString()
+}
\ No newline at end of file
diff --git a/src/ResourceManager/KeyVault/Commands.KeyVault.Test/Scripts/PSHCommon/Assert.ps1 b/src/ResourceManager/KeyVault/Commands.KeyVault.Test/Scripts/PSHCommon/Assert.ps1
new file mode 100644
index 000000000000..eb7db0931910
--- /dev/null
+++ b/src/ResourceManager/KeyVault/Commands.KeyVault.Test/Scripts/PSHCommon/Assert.ps1
@@ -0,0 +1,345 @@
+# ----------------------------------------------------------------------------------
+#
+# Copyright Microsoft Corporation
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+# http://www.apache.org/licenses/LICENSE-2.0
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+# ----------------------------------------------------------------------------------
+
+######################
+#
+# Validate that the given code block throws the given exception
+#
+# param [ScriptBlock] $script : The code to test
+# param [string] $message : The text of the exception that should be thrown
+#######################
+function Assert-Throws
+{
+ param([ScriptBlock] $script, [string] $message)
+ try
+ {
+ &$script
+ }
+ catch
+ {
+ if ($message -ne "")
+ {
+ $actualMessage = $_.Exception.Message
+ Write-Output ("Caught exception: '$actualMessage'")
+
+ if ($actualMessage -eq $message)
+ {
+ return $true;
+ }
+ else
+ {
+ throw "Expected exception not received: '$message' the actual message is '$actualMessage'";
+ }
+ }
+ else
+ {
+ return $true;
+ }
+ }
+
+ throw "No exception occured";
+}
+
+######################
+#
+# Validate that the given code block throws the given exception
+#
+# param [ScriptBlock] $script : The code to test
+# param [ScriptBlock] $compare : Predicate used to determine if the message meets criteria
+#######################
+function Assert-ThrowsContains
+{
+ param([ScriptBlock] $script, [string] $compare)
+ try
+ {
+ &$script
+ }
+ catch
+ {
+ if ($message -ne "")
+ {
+ $actualMessage = $_.Exception.Message
+ Write-Output ("Caught exception: '$actualMessage'")
+ if ($actualMessage.Contains($compare))
+ {
+ return $true;
+ }
+ else
+ {
+ throw "Expected exception does not contain expected text '$compare', the actual message is '$actualMessage'";
+ }
+ }
+ else
+ {
+ return $true;
+ }
+ }
+
+ throw "No exception occured";
+}
+
+<#
+.SYNOPSIS
+Given a list of variable names, assert that all of them are defined
+#>
+function Assert-Env
+{
+ param([string[]] $vars)
+ $tmp = Get-Item env:
+ $env = @{}
+ $tmp | % { $env.Add($_.Key, $_.Value)}
+ $vars | % { Assert-True {$env.ContainsKey($_)} "Environment Variable $_ Is Required. Please set the value before runnign the test"}
+}
+
+###################
+#
+# Verify that the given scriptblock returns true
+#
+# param [ScriptBlock] $script : The script to execute
+# param [string] $message : The message to return if the given script does not return true
+####################
+function Assert-True
+{
+ param([ScriptBlock] $script, [string] $message)
+
+ if (!$message)
+ {
+ $message = "Assertion failed: " + $script
+ }
+
+ $result = &$script
+ if (-not $result)
+ {
+ Write-Debug "Failure: $message"
+ throw $message
+ }
+
+ return $true
+}
+
+###################
+#
+# Verify that the given scriptblock returns false
+#
+# param [ScriptBlock] $script : The script to execute
+# param [string] $message : The message to return if the given script does not return false
+####################
+function Assert-False
+{
+ param([ScriptBlock] $script, [string] $message)
+
+ if (!$message)
+ {
+ $message = "Assertion failed: " + $script
+ }
+
+ $result = &$script
+ if ($result)
+ {
+ throw $message
+ }
+
+ return $true
+}
+
+###################
+#
+# Verify that the given scriptblock returns false
+#
+# param [ScriptBlock] $script : The script to execute
+# param [string] $message : The message to return if the given script does not return false
+####################
+function Assert-False
+{
+ param([ScriptBlock] $script, [string] $message)
+
+ if (!$message)
+ {
+ $message = "Assertion failed: " + $script
+ }
+
+ $result = &$script
+ if ($result)
+ {
+ throw $message
+ }
+
+ return $true
+}
+
+###################
+#
+# Verify that the given scriptblock does not return null
+#
+# param [object] $actual : The actual object
+# param [string] $message : The message to return if the given script does not return true
+####################
+function Assert-NotNull
+{
+ param([object] $actual, [string] $message)
+
+ if (!$message)
+ {
+ $message = "Assertion failed because the object is null: " + $actual
+ }
+
+ if ($actual -eq $null)
+ {
+ throw $message
+ }
+
+ return $true
+}
+
+######################
+#
+# Assert that the given file exists
+#
+# param [string] $path : The path to the file to test
+# param [string] $message: The text of the exception to throw if the file doesn't exist
+######################
+function Assert-Exists
+{
+ param([string] $path, [string] $message)
+ return Assert-True {Test-Path $path} $message
+}
+
+###################
+#
+# Verify that two given objects are equal
+#
+# param [object] $expected : The expected object
+# param [object] $actual : The actual object
+# param [string] $message : The message to return if the given objects are not equal
+####################
+function Assert-AreEqual
+{
+ param([object] $expected, [object] $actual, [string] $message)
+
+ if (!$message)
+ {
+ $message = "Assertion failed because expected '$expected' does not match actual '$actual'"
+ }
+
+ if ($expected -ne $actual)
+ {
+ throw $message
+ }
+
+ return $true
+}
+
+###################
+#
+# Verify that two given arrays are equal
+#
+# param [array] $expected : The expected array
+# param [array] $actual : The actual array
+# param [string] $message : The message to return if the given arrays are not equal.
+####################
+function Assert-AreEqualArray
+{
+ param([object] $expected, [object] $actual, [string] $message)
+
+ if (!$message)
+ {
+ $message = "Assertion failed because expected '$expected' does not match actual '$actual'"
+ }
+
+ $diff = Compare-Object $expected $actual -PassThru
+
+ if ($diff -ne $null)
+ {
+ throw $message
+ }
+
+ return $true
+}
+
+###################
+#
+# Verify that two given objects have equal properties
+#
+# param [object] $expected : The expected object
+# param [object] $actual : The actual object
+# param [string] $message : The message to return if the given objects are not equal.
+####################
+function Assert-AreEqualObjectProperties
+{
+ param([object] $expected, [object] $actual, [string] $message)
+
+ $properties = $expected | Get-Member -MemberType "Property" | Select -ExpandProperty Name
+ $diff = Compare-Object $expected $actual -Property $properties
+
+ if ($diff -ne $null)
+ {
+ if (!$message)
+ {
+ $message = "Assert failed because the objects don't match. Expected: " + $diff[0] + " Actual: " + $diff[1]
+ }
+
+ throw $message
+ }
+
+ return $true
+}
+
+###################
+#
+# Verify that the given value is null
+#
+# param [object] $actual : The actual object
+# param [string] $message : The message to return if the given object is not null
+####################
+function Assert-Null
+{
+ param([object] $actual, [string] $message)
+
+ if (!$message)
+ {
+ $message = "Assertion failed because the object is not null: " + $actual
+ }
+
+ if ($actual -ne $null)
+ {
+ throw $message
+ }
+
+ return $true
+}
+
+###################
+#
+# Verify that two given objects are not equal
+#
+# param [object] $expected : The expected object
+# param [object] $actual : The actual object
+# param [string] $message : The message to return if the given objects are equal
+####################
+function Assert-AreNotEqual
+{
+ param([object] $expected, [object] $actual, [string] $message)
+
+ if (!$message)
+ {
+ $message = "Assertion failed because expected '$expected' does match actual '$actual'"
+ }
+
+ if ($expected -eq $actual)
+ {
+ throw $message
+ }
+
+ return $true
+}
\ No newline at end of file
diff --git a/src/ResourceManager/KeyVault/Commands.KeyVault.Test/Scripts/PSHCommon/Common.ps1 b/src/ResourceManager/KeyVault/Commands.KeyVault.Test/Scripts/PSHCommon/Common.ps1
new file mode 100644
index 000000000000..dadbcab9bceb
--- /dev/null
+++ b/src/ResourceManager/KeyVault/Commands.KeyVault.Test/Scripts/PSHCommon/Common.ps1
@@ -0,0 +1,363 @@
+# ----------------------------------------------------------------------------------
+#
+# Copyright Microsoft Corporation
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+# http://www.apache.org/licenses/LICENSE-2.0
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+# ----------------------------------------------------------------------------------
+
+$excludedExtensions = @(".dll", ".zip", ".msi", ".exe")
+###################################
+#
+# Retrievce the contents of a powershrell transcript, stripping headers and footers
+#
+# param [string] $path: The path to the transript file to read
+###################################
+function Get-Transcript
+{
+ param([string] $path)
+ return Get-Content $path |
+ Select-String -InputObject {$_} -Pattern "^Start Time\s*:.*" -NotMatch |
+ Select-String -InputObject {$_} -Pattern "^End Time\s*:.*" -NotMatch |
+ Select-String -InputObject {$_} -Pattern "^Machine\s*:.*" -NotMatch |
+ Select-String -InputObject {$_} -Pattern "^Username\s*:.*" -NotMatch |
+ Select-String -InputObject {$_} -Pattern "^Transcript started, output file is.*" -NotMatch
+}
+
+########################
+#
+# Get a random file name in the current directory
+#
+# param [string] $rootPath: The path of the directory to contain the random file (optional)
+########################
+function Get-LogFile
+{
+ param([string] $rootPath = ".")
+ return [System.IO.Path]::Combine($rootPath, ([System.IO.Path]::GetRandomFileName()))
+}
+
+#################
+#
+# Execute a test, no exception thrown means the test passes. Can also be used to compare test
+# output to a baseline file, or to generate a baseline file
+#
+# param [scriptblock] $test: The test code to run
+# param [string] $testScript: The path to the baseline file (optional)
+# param [switch] $generate: Set if the baseline file should be generated, otherwise
+# the baseline file would be used for comparison with test output
+##################
+function Run-Test
+{
+ param([scriptblock]$test, [string] $testName = $null, [string] $testScript = $null, [switch] $generate = $false)
+ Test-Setup
+ $transFile = $testName + ".log"
+ if ($testName -eq $null)
+ {
+ $transFile = Get-LogFile "."
+ }
+ if($testScript)
+ {
+ if ($generate)
+ {
+ Write-Log "[run-test]: generating script file $testScript"
+ $transFile = $testScript
+ }
+ else
+ {
+ Write-Log "[run-test]: writing output to $transFile, using validation script $testScript"
+ }
+ }
+ else
+ {
+ Write-Log "[run-test]: Running test without file comparison"
+ }
+
+ $oldPref = $ErrorActionPreference
+ $ErrorActionPreference = "SilentlyContinue"
+ #Start-Transcript -Path $transFile
+ $success = $false;
+ $ErrorActionPreference = $oldPref
+ try
+ {
+ &$test
+ $success = $true;
+ }
+ finally
+ {
+ Test-Cleanup
+ $oldPref = $ErrorActionPreference
+ $ErrorActionPreference = "SilentlyContinue"
+ #Stop-Transcript
+ $ErrorActionPreference = $oldPref
+ if ($testScript)
+ {
+ if ($success -and -not $generate)
+ {
+ $result = Compare-Object (Get-Transcript $testScript) (Get-Transcript $transFile)
+ if ($result -ne $null)
+ {
+ throw "[run-test]: Test Failed " + (Out-String -InputObject $result) + ", Transcript at $transFile"
+ }
+
+ }
+ }
+
+ if ($success)
+ {
+ Write-Log "[run-test]: Test Passed"
+ }
+ }
+
+}
+
+##################
+#
+# Format a string for proper output to host and transcript
+#
+# param [string] $message: The text to write
+##################
+function Write-Log
+{
+ [CmdletBinding()]
+ param( [Object] [Parameter(Position=0, ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$false)] $obj = "")
+ PROCESS
+ {
+ $obj | Out-String | Write-Verbose
+ }
+}
+
+function Check-SubscriptionMatch
+{
+ param([string] $baseSubscriptionName, [Microsoft.WindowsAzure.Commands.Utilities.Common.SubscriptionData] $checkedSubscription)
+ Write-Log ("[CheckSubscriptionMatch]: base subscription: '$baseSubscriptionName', validating '" + ($checkedSubscription.SubscriptionName)+ "'")
+ Format-Subscription $checkedSubscription | Write-Log
+ if ($baseSubscriptionName -ne $checkedSubscription.SubscriptionName)
+ {
+ throw ("[Check-SubscriptionMatch]: Subscription Match Failed '" + ($baseSubscriptionName) + "' != '" + ($checkedSubscription.SubscriptionName) + "'")
+ }
+
+ Write-Log ("CheckSubscriptionMatch]: subscription check succeeded.")
+}
+
+
+##########################
+#
+# Return the fully qualified filename of a given file
+#
+# param [string] $path: The relative path to the file
+#
+##########################
+function Get-FullName
+{
+ param([string] $path)
+ $pathObj = Get-Item $path
+ return ($pathObj.FullName)
+}
+
+#############################
+#
+# PowerShell environment setup for running a test, save previous snvironment settings and
+# enable verbose, debug, and warning streams
+#
+#############################
+function Test-Setup
+{
+ $global:oldConfirmPreference = $global:ConfirmPreference
+ $global:oldDebugPreference = $global:DebugPreference
+ $global:oldErrorActionPreference = $global:ErrorActionPreference
+ $global:oldFormatEnumerationLimit = $global:FormatEnumerationLimit
+ $global:oldProgressPreference = $global:ProgressPreference
+ $global:oldVerbosePreference = $global:VerbosePreference
+ $global:oldWarningPreference = $global:WarningPreference
+ $global:oldWhatIfPreference = $global:WhatIfPreference
+ $global:ConfirmPreference = "None"
+ $global:DebugPreference = "Continue"
+ $global:ErrorActionPreference = "Stop"
+ $global:FormatEnumerationLimit = 10000
+ $global:ProgressPreference = "SilentlyContinue"
+ $global:VerbosePreference = "Continue"
+ $global:WarningPreference = "Continue"
+ $global:WhatIfPreference = 0
+}
+
+#############################
+#
+# PowerShell environment cleanup for running a test, restore previous snvironment settings
+#
+#############################
+function Test-Cleanup
+{
+ $global:ConfirmPreference = $global:oldConfirmPreference
+ $global:DebugPreference = $global:oldDebugPreference
+ $global:ErrorActionPreference = $global:oldErrorActionPreference
+ $global:FormatEnumerationLimit = $global:oldFormatEnumerationLimit
+ $global:ProgressPreference = $global:oldProgressPreference
+ $global:VerbosePreference = $global:oldVerbosePreference
+ $global:WarningPreference = $global:oldWarningPreference
+ $global:WhatIfPreference = $global:oldWhatIfPreference
+}
+
+#######################
+#
+# Dump the contents of a directory to the output stream
+#
+# param [string] $rootPath: The path to the directory
+# param [switch] $resurse : True if we should recurse directories
+######################
+function Dump-Contents
+{
+ param([string] $rootPath = ".", [switch] $recurse = $false)
+ if (-not ((Test-Path $rootPath) -eq $true))
+ {
+ throw "[dump-contents]: $rootPath does not exist"
+ }
+
+ foreach ($item in Get-ChildItem $rootPath)
+ {
+ Write-Log
+ Write-Log "---------------------------"
+ Write-Log $item.Name
+ Write-Log "---------------------------"
+ Write-Log
+ if (!$item.PSIsContainer)
+ {
+ if (Test-BinaryFile $item)
+ {
+ Write-Log "---- binary data excluded ----"
+ }
+ else
+ {
+ Get-Content ($item.PSPath)
+ }
+ }
+ elseif ($recurse)
+ {
+ Dump-Contents ($item.PSPath) -recurse
+ }
+ }
+}
+
+function Test-BinaryFile
+{
+ param ([System.IO.FileInfo] $file)
+ ($excludedExtensions | Where-Object -FilterScript {$_ -eq $file.Extension}) -ne $null
+}
+
+
+<#
+.SYNOPSIS
+Removes all current subscriptions.
+#>
+function Remove-AllSubscriptions
+{
+ Get-AzureSubscription | Remove-AzureSubscription -Force
+}
+
+<#
+.SYNOPSIS
+Waits on the specified job with the given timeout.
+
+.PARAMETER scriptBlock
+The script block to execute.
+
+.PARAMETER timeout
+The maximum timeout for the script.
+#>
+function Wait-Function
+{
+ param([ScriptBlock] $scriptBlock, [object] $breakCondition, [int] $timeout)
+
+ if ($timeout -eq 0) { $timeout = 60 * 5 }
+ $start = [DateTime]::Now
+ $current = [DateTime]::Now
+ $diff = $current - $start
+
+ do
+ {
+ Start-Sleep -s 5
+ $current = [DateTime]::Now
+ $diff = $current - $start
+ $result = &$scriptBlock
+ }
+ while(($result -ne $breakCondition) -and ($diff.TotalSeconds -lt $timeout))
+
+ if ($diff.TotalSeconds -ge $timeout)
+ {
+ Write-Warning "The script block '$scriptBlock' exceeded the timeout."
+ # End the processing so the test does not blow up
+ exit
+ }
+}
+
+
+<#
+.SYNOPSIS
+Waits for specified duration if not-mocked, otherwise skips wait.
+
+.PARAMETER timeout
+Timeout in seconds
+#>
+function Wait-Seconds
+{
+ param([int] $timeout)
+
+ [Microsoft.WindowsAzure.Testing.TestUtilities]::Wait($timeout * 1000)
+}
+
+
+<#
+.SYNOPSIS
+Retires the specified job the given numer of times, waiting the given interval between tries
+
+.PARAMETER scriptBlock
+The script block to execute. Must be a predicate (return true or false)
+
+.PARAMETER argument
+Argument to pass to the script block
+
+.PARAMETER maxTries
+The maximum number of times to retry
+
+.PARAMETER interval
+The number of seconds to wait before retrying
+#>
+function Retry-Function
+{
+ param([ScriptBlock] $scriptBlock, [Object] $argument, [int] $maxTries, [int] $interval)
+
+ if ($interval -eq 0) { $interval = 60 }
+
+ $result = Invoke-Command -ScriptBlock $scriptBlock -ArgumentList $argument;
+ $tries = 1;
+ while(( $result -ne $true) -and ($tries -le $maxTries))
+ {
+ Start-Sleep -s $interval
+ $result = Invoke-Command -ScriptBlock $scriptBlock -ArgumentList $argument;
+ $tries++;
+ }
+
+ return $result;
+}
+
+function getAssetName
+{
+ $stack = Get-PSCallStack
+ $testName = $null;
+ foreach ($frame in $stack)
+ {
+ if ($frame.Command.StartsWith("Test-", "CurrentCultureIgnoreCase"))
+ {
+ $testName = $frame.Command
+ }
+ }
+
+ $assetName = [Microsoft.Azure.Utilities.HttpRecorder.HttpMockServer]::GetAssetName($testName, "onesdk")
+
+ return $assetName
+}
\ No newline at end of file
diff --git a/src/ResourceManager/KeyVault/Commands.KeyVault.Test/Scripts/RunKeyVaultTests.ps1 b/src/ResourceManager/KeyVault/Commands.KeyVault.Test/Scripts/RunKeyVaultTests.ps1
new file mode 100644
index 000000000000..ae3fe0a01533
--- /dev/null
+++ b/src/ResourceManager/KeyVault/Commands.KeyVault.Test/Scripts/RunKeyVaultTests.ps1
@@ -0,0 +1,172 @@
+Param(
+ [Parameter(Mandatory=$True,Position=0)]
+ [ValidateSet('BVT','PROD')]
+ [string]$testenv,
+ [Parameter(Mandatory=$True,Position=1)]
+ [string]$testns
+)
+
+$invocationPath = Split-Path $MyInvocation.MyCommand.Definition;
+. (Join-Path $invocationPath "PSHCommon\Common.ps1");
+. (Join-Path $invocationPath "PSHCommon\Assert.ps1");
+. (Join-Path $invocationPath "Common.ps1");
+. (Join-Path $invocationPath "VaultKeyTests.ps1");
+. (Join-Path $invocationPath "VaultSecretTests.ps1");
+
+$global:totalCount = 0;
+$global:passedCount = 0;
+$global:passedTests = @()
+$global:failedTests = @()
+$global:times = @{}
+$global:testEnv = $testenv.ToUpperInvariant()
+$global:testns = $testns
+
+function Run-TestProtected
+{
+ param([ScriptBlock]$script, [string] $testName)
+ $testStart = Get-Date
+ try
+ {
+ Write-Host -ForegroundColor Green =====================================
+ Write-Host -ForegroundColor Green "Running test $testName"
+ Write-Host -ForegroundColor Green =====================================
+ Write-Host
+ &$script
+ $global:passedCount = $global:passedCount + 1
+ Write-Host
+ Write-Host -ForegroundColor Green =====================================
+ Write-Host -ForegroundColor Green "Test Passed"
+ Write-Host -ForegroundColor Green =====================================
+ Write-Host
+ $global:passedTests += $testName
+ }
+ catch
+ {
+ Out-String -InputObject $_.Exception | Write-Host -ForegroundColor Red
+ Write-Host
+ Write-Host -ForegroundColor Red =====================================
+ Write-Host -ForegroundColor Red "Test Failed"
+ Write-Host -ForegroundColor Red =====================================
+ Write-Host
+ $global:failedTests += $testName
+ }
+ finally
+ {
+ $testEnd = Get-Date
+ $testElapsed = $testEnd - $testStart
+ $global:times[$testName] = $testElapsed
+ $global:totalCount = $global:totalCount + 1
+ }
+}
+
+# Initialize
+Write-Host Delete log files
+Cleanup-Log $invocationPath
+
+$testkeyVault = Get-KeyVault
+Write-Host Test key vault is $testKeyVault
+Write-Host Initializing Key Tests
+Initialize-KeyTest
+Write-Host Initializing Secret Tests
+Initialize-SecretTest
+Write-Host Initialization Completed
+
+$global:startTime = Get-Date
+
+# Add-AzureKeyVaultKey tests
+Run-TestProtected { Run-KeyTest {Test_CreateSoftwareKeyWithDefaultAttributes} "Test_CreateSoftwareKeyWithDefaultAttributes" } "Test_CreateSoftwareKeyWithDefaultAttributes"
+Run-TestProtected { Run-KeyTest {Test_CreateSoftwareKeyWithCustomAttributes} "Test_CreateSoftwareKeyWithCustomAttributes" } "Test_CreateSoftwareKeyWithCustomAttributes"
+Run-TestProtected { Run-KeyTest {Test_CreateHsmKeyWithDefaultAttributes} "Test_CreateHsmKeyWithDefaultAttributes" } "Test_CreateHsmKeyWithDefaultAttributes"
+Run-TestProtected { Run-KeyTest {Test_CreateHsmKeyWithCustomAttributes} "Test_CreateHsmKeyWithCustomAttributes" } "Test_CreateHsmKeyWithCustomAttributes"
+Run-TestProtected { Run-KeyTest {Test_ImportPfxWithDefaultAttributes} "Test_ImportPfxWithDefaultAttributes" } "Test_ImportPfxWithDefaultAttributes"
+Run-TestProtected { Run-KeyTest {Test_ImportPfxWithCustomAttributes} "Test_ImportPfxWithCustomAttributes" } "Test_ImportPfxWithCustomAttributes"
+Run-TestProtected { Run-KeyTest {Test_ImportPfxAsHsmWithDefaultAttributes} "Test_ImportPfxAsHsmWithDefaultAttributes" } "Test_ImportPfxAsHsmWithDefaultAttributes"
+Run-TestProtected { Run-KeyTest {Test_ImportPfxAsHsmWithCustomAttributes} "Test_ImportPfxAsHsmWithCustomAttributes" } "Test_ImportPfxAsHsmWithCustomAttributes"
+Run-TestProtected { Run-KeyTest {Test_ImportByokWithDefaultAttributes} "Test_ImportByokWithDefaultAttributes" } "Test_ImportByokWithDefaultAttributes"
+Run-TestProtected { Run-KeyTest {Test_ImportByokWithCustomAttributes} "Test_ImportByokWithCustomAttributes" } "Test_ImportByokWithCustomAttributes"
+Run-TestProtected { Run-KeyTest {Test_AddKeyPositionalParameter} "Test_AddKeyPositionalParameter" } "Test_AddKeyPositionalParameter"
+Run-TestProtected { Run-KeyTest {Test_AddKeyAliasParameter} "Test_AddKeyAliasParameter" } "Test_AddKeyAliasParameter"
+Run-TestProtected { Run-KeyTest {Test_ImportNonExistPfxFile} "Test_ImportNonExistPfxFile" } "Test_ImportNonExistPfxFile"
+Run-TestProtected { Run-KeyTest {Test_ImportPfxFileWithIncorrectPassword} "Test_ImportPfxFileWithIncorrectPassword" } "Test_ImportPfxFileWithIncorrectPassword"
+Run-TestProtected { Run-KeyTest {Test_ImportNonExistByokFile} "Test_ImportNonExistByokFile" } "Test_ImportNonExistByokFile"
+Run-TestProtected { Run-KeyTest {Test_CreateKeyInNonExistVault} "Test_CreateKeyInNonExistVault" } "Test_CreateKeyInNonExistVault"
+Run-TestProtected { Run-KeyTest {Test_ImportByokAsSoftwareKey} "Test_ImportByokAsSoftwareKey" } "Test_ImportByokAsSoftwareKey"
+Run-TestProtected { Run-KeyTest {Test_CreateKeyInNoPermissionVault} "Test_CreateKeyInNoPermissionVault" } "Test_CreateKeyInNoPermissionVault"
+
+# Set-AzureKeyVaultKey tests
+# Uncomment it after fix bug
+#Run-TestProtected { Run-KeyTest {Test_UpdateIndividualAttributes} "Test_UpdateIndividualAttributes" } "Test_UpdateIndividualAttributes"
+Run-TestProtected { Run-KeyTest {Test_UpdateAllEditableAttributes} "Test_UpdateAllEditableAttributes" } "Test_UpdateAllEditableAttributes"
+Run-TestProtected { Run-KeyTest {Test_SetKeyPositionalParameter} "Test_SetKeyPositionalParameter" } "Test_SetKeyPositionalParameter"
+Run-TestProtected { Run-KeyTest {Test_SetKeyAliasParameter} "Test_SetKeyAliasParameter" } "Test_SetKeyAliasParameter"
+Run-TestProtected { Run-KeyTest {Test_SetKeyInNonExistVault} "Test_SetKeyInNonExistVault" } "Test_SetKeyInNonExistVault"
+Run-TestProtected { Run-KeyTest {Test_SetNonExistKey} "Test_SetNonExistKey" } "Test_SetNonExistKey"
+Run-TestProtected { Run-KeyTest {Test_SetInvalidAttributes} "Test_SetInvalidAttributes" } "Test_SetInvalidAttributes"
+Run-TestProtected { Run-KeyTest {Test_SetKeyInNoPermissionVault} "Test_SetKeyInNoPermissionVault" } "Test_SetKeyInNoPermissionVault"
+
+# Get-AzureKeyVaultKey tests
+Run-TestProtected { Run-KeyTest {Test_GetOneKey} "Test_GetOneKey" } "Test_GetOneKey"
+Run-TestProtected { Run-KeyTest {Test_GetAllKeys} "Test_GetAllKeys" } "Test_GetAllKeys"
+Run-TestProtected { Run-KeyTest {Test_GetKeyPositionalParameter} "Test_GetKeyPositionalParameter" } "Test_GetKeyPositionalParameter"
+Run-TestProtected { Run-KeyTest {Test_GetKeyAliasParameter} "Test_GetKeyAliasParameter" } "Test_GetKeyAliasParameter"
+Run-TestProtected { Run-KeyTest {Test_GetKeysInNonExistVault} "Test_GetKeysInNonExistVault" } "Test_GetKeysInNonExistVault"
+Run-TestProtected { Run-KeyTest {Test_GetNonExistKey} "Test_GetNonExistKey" } "Test_GetNonExistKey"
+Run-TestProtected { Run-KeyTest {Test_GetKeyInNoPermissionVault} "Test_GetKeyInNoPermissionVault" } "Test_GetKeyInNoPermissionVault"
+
+
+# Remove-AzureKeyVaultKey tests
+Run-TestProtected { Run-KeyTest {Test_RemoveKeyWithoutPrompt} "Test_RemoveKeyWithoutPrompt" } "Test_RemoveKeyWithoutPrompt"
+Run-TestProtected { Run-KeyTest {Test_RemoveKeyWhatIf} "Test_RemoveKeyWhatIf" } "Test_RemoveKeyWhatIf"
+Run-TestProtected { Run-KeyTest {Test_RemoveKeyPositionalParameter} "Test_RemoveKeyPositionalParameter" } "Test_RemoveKeyPositionalParameter"
+Run-TestProtected { Run-KeyTest {Test_RemoveKeyAliasParameter} "Test_RemoveKeyAliasParameter" } "Test_RemoveKeyAliasParameter"
+Run-TestProtected { Run-KeyTest {Test_RemoveKeyInNonExistVault} "Test_RemoveKeyInNonExistVault" } "Test_RemoveKeyInNonExistVault"
+Run-TestProtected { Run-KeyTest {Test_RemoveNonExistKey} "Test_RemoveNonExistKey" } "Test_RemoveNonExistKey"
+Run-TestProtected { Run-KeyTest {Test_RemoveKeyInNoPermissionVault} "Test_RemoveKeyInNoPermissionVault" } "Test_RemoveKeyInNoPermissionVault"
+
+# *-AzureKeyVaultKey pipeline tests
+Run-TestProtected { Run-KeyTest {Test_PipelineUpdateKeys} "Test_PipelineUpdateKeys" } "Test_PipelineUpdateKeys"
+Run-TestProtected { Run-KeyTest {Test_PipelineRemoveKeys} "Test_PipelineRemoveKeys" } "Test_PipelineRemoveKeys"
+
+
+# Set-AzureKeyVaultSecret tests
+Run-TestProtected { Run-SecretTest {Test_CreateSecret} "Test_CreateSecret" } "Test_CreateSecret"
+Run-TestProtected { Run-SecretTest {Test_UpdateSecret} "Test_UpdateSecret" } "Test_UpdateSecret"
+Run-TestProtected { Run-SecretTest {Test_SetSecretPositionalParameter} "Test_SetSecretPositionalParameter" } "Test_SetSecretPositionalParameter"
+Run-TestProtected { Run-SecretTest {Test_SetSecretAliasParameter} "Test_SetSecretAliasParameter" } "Test_SetSecretAliasParameter"
+Run-TestProtected { Run-SecretTest {Test_SetSecretInNonExistVault} "Test_SetSecretInNonExistVault" } "Test_SetSecretInNonExistVault"
+Run-TestProtected { Run-SecretTest {Test_SetSecretInNoPermissionVault} "Test_SetSecretInNoPermissionVault" } "Test_SetSecretInNoPermissionVault"
+
+# Get-AzureKeyVaultSecret tests
+Run-TestProtected { Run-SecretTest {Test_GetOneSecret} "Test_GetOneSecret" } "Test_GetOneSecret"
+Run-TestProtected { Run-SecretTest {Test_GetAllSecrets} "Test_GetAllSecrets" } "Test_GetAllSecrets"
+Run-TestProtected { Run-SecretTest {Test_GetSecretPositionalParameter} "Test_GetSecretPositionalParameter" } "Test_GetSecretPositionalParameter"
+Run-TestProtected { Run-SecretTest {Test_GetSecretAliasParameter} "Test_GetSecretAliasParameter" } "Test_GetSecretAliasParameter"
+Run-TestProtected { Run-SecretTest {Test_GetSecretInNonExistVault} "Test_GetSecretInNonExistVault" } "Test_GetSecretInNonExistVault"
+Run-TestProtected { Run-SecretTest {Test_GetNonExistSecret} "Test_GetNonExistSecret" } "Test_GetNonExistSecret"
+Run-TestProtected { Run-SecretTest {Test_GetSecretInNoPermissionVault} "Test_GetSecretInNoPermissionVault" } "Test_GetSecretInNoPermissionVault"
+
+# Remove-AzureKeyVaultSecret tests
+Run-TestProtected { Run-SecretTest {Test_RemoveSecretWithoutPrompt} "Test_RemoveSecretWithoutPrompt" } "Test_RemoveSecretWithoutPrompt"
+Run-TestProtected { Run-SecretTest {Test_RemoveSecretWhatIf} "Test_RemoveSecretWhatIf" } "Test_RemoveSecretWhatIf"
+Run-TestProtected { Run-SecretTest {Test_RemoveSecretPositionalParameter} "Test_RemoveSecretPositionalParameter" } "Test_RemoveSecretPositionalParameter"
+Run-TestProtected { Run-SecretTest {Test_RemoveSecretAliasParameter} "Test_RemoveSecretAliasParameter" } "Test_RemoveSecretAliasParameter"
+Run-TestProtected { Run-SecretTest {Test_RemoveSecretInNonExistVault} "Test_RemoveSecretInNonExistVault" } "Test_RemoveSecretInNonExistVault"
+Run-TestProtected { Run-SecretTest {Test_RemoveNonExistSecret} "Test_RemoveNonExistSecret" } "Test_RemoveNonExistSecret"
+Run-TestProtected { Run-SecretTest {Test_RemoveSecretInNoPermissionVault} "Test_RemoveSecretInNoPermissionVault" } "Test_RemoveSecretInNoPermissionVault"
+
+
+# *-AzureKeyVaultKey pipeline tests
+Run-TestProtected { Run-SecretTest {Test_PipelineUpdateSecrets} "Test_PipelineUpdateSecrets" } "Test_PipelineUpdateSecrets"
+Run-TestProtected { Run-SecretTest {Test_PipelineRemoveSecrets} "Test_PipelineRemoveSecrets" } "Test_PipelineRemoveSecrets"
+
+$global:endTime = Get-Date
+
+# Report
+Write-FileReport
+Write-ConsoleReport
+
+
+# Post run
+Move-Log $invocationPath
+
+
diff --git a/src/ResourceManager/KeyVault/Commands.KeyVault.Test/Scripts/RunUITests.ps1 b/src/ResourceManager/KeyVault/Commands.KeyVault.Test/Scripts/RunUITests.ps1
new file mode 100644
index 000000000000..0152b97a708f
--- /dev/null
+++ b/src/ResourceManager/KeyVault/Commands.KeyVault.Test/Scripts/RunUITests.ps1
@@ -0,0 +1,95 @@
+Param(
+ [Parameter(Mandatory=$True,Position=0)]
+ [ValidateSet('BVT','PROD')]
+ [string]$testenv,
+ [Parameter(Mandatory=$True,Position=1)]
+ [string]$testns
+)
+
+$invocationPath = Split-Path $MyInvocation.MyCommand.Definition;
+. (Join-Path $invocationPath "PSHCommon\Common.ps1");
+. (Join-Path $invocationPath "PSHCommon\Assert.ps1");
+. (Join-Path $invocationPath "Common.ps1");
+. (Join-Path $invocationPath "VaultUITests.ps1");
+
+$global:totalCount = 0;
+$global:passedCount = 0;
+$global:passedTests = @()
+$global:failedTests = @()
+$global:times = @{}
+$global:testEnv = $testenv.ToUpperInvariant()
+$global:testns = $testns+"UI"
+
+function Run-TestProtected
+{
+ param([ScriptBlock]$script, [string] $testName)
+ $testStart = Get-Date
+ try
+ {
+ Write-Host -ForegroundColor Green =====================================
+ Write-Host -ForegroundColor Green "Running test $testName"
+ Write-Host -ForegroundColor Green =====================================
+ Write-Host
+ &$script
+ $global:passedCount = $global:passedCount + 1
+ Write-Host
+ Write-Host -ForegroundColor Green =====================================
+ Write-Host -ForegroundColor Green "Test Passed"
+ Write-Host -ForegroundColor Green =====================================
+ Write-Host
+ $global:passedTests += $testName
+ }
+ catch
+ {
+ Out-String -InputObject $_.Exception | Write-Host -ForegroundColor Red
+ Write-Host
+ Write-Host -ForegroundColor Red =====================================
+ Write-Host -ForegroundColor Red "Test Failed"
+ Write-Host -ForegroundColor Red =====================================
+ Write-Host
+ $global:failedTests += $testName
+ }
+ finally
+ {
+ $testEnd = Get-Date
+ $testElapsed = $testEnd - $testStart
+ $global:times[$testName] = $testElapsed
+ $global:totalCount = $global:totalCount + 1
+ }
+}
+
+# Initialize
+Write-Host Delete log files
+Cleanup-Log $invocationPath
+
+$testkeyVault = Get-KeyVault
+Write-Host Test key vault is $testKeyVault
+Write-Host Initializing Key Tests
+Initialize-KeyTest
+Write-Host Initializing Secret Tests
+Initialize-SecretTest
+Write-Host Initialization Completed
+
+$global:startTime = Get-Date
+
+# Run key tests
+Run-TestProtected { Run-KeyTest {Test_RemoveKeyWithTwoConfirmations} "Test_RemoveKeyWithTwoConfirmations" } "Test_RemoveKeyWithTwoConfirmations"
+Run-TestProtected { Run-KeyTest {Test_RemoveKeyWithOneConfirmations} "Test_RemoveKeyWithOneConfirmations" } "Test_RemoveKeyWithOneConfirmations"
+Run-TestProtected { Run-KeyTest {Test_CancelKeyRemovalOnce} "Test_CancelKeyRemovalOnce" } "Test_CancelKeyRemovalOnce"
+Run-TestProtected { Run-KeyTest {Test_ConfirmThenCancelKeyRemoval} "Test_ConfirmThenCancelKeyRemoval" } "Test_ConfirmThenCancelKeyRemoval"
+
+# Run secret tests
+Run-TestProtected { Run-SecretTest {Test_RemoveSecretWithTwoConfirmations} "Test_RemoveSecretWithTwoConfirmations" } "Test_RemoveSecretWithTwoConfirmations"
+Run-TestProtected { Run-SecretTest {Test_RemoveSecretWithOneConfirmations} "Test_RemoveSecretWithOneConfirmations" } "Test_RemoveSecretWithOneConfirmations"
+Run-TestProtected { Run-SecretTest {Test_CancelSecretRemovalOnce} "Test_CancelSecretRemovalOnce" } "Test_CancelSecretRemovalOnce"
+Run-TestProtected { Run-SecretTest {Test_ConfirmThenCancelSecretRemoval} "Test_ConfirmThenCancelSecretRemoval" } "Test_ConfirmThenCancelSecretRemoval"
+
+
+$global:endTime = Get-Date
+
+# Report
+Write-FileReport
+Write-ConsoleReport
+
+# Post run
+Move-Log $invocationPath
diff --git a/src/ResourceManager/KeyVault/Commands.KeyVault.Test/Scripts/VaultKeyTests.ps1 b/src/ResourceManager/KeyVault/Commands.KeyVault.Test/Scripts/VaultKeyTests.ps1
new file mode 100644
index 000000000000..897e178719dd
--- /dev/null
+++ b/src/ResourceManager/KeyVault/Commands.KeyVault.Test/Scripts/VaultKeyTests.ps1
@@ -0,0 +1,693 @@
+$pfxpwd='123'
+$securepfxpwd=$pfxpwd | ConvertTo-SecureString -AsPlainText -Force
+$expires= (Get-Date).AddYears(2).ToUniversalTime()
+$nbf=(Get-Date).ToUniversalTime()
+$newexpires= (Get-Date).AddYears(5).ToUniversalTime()
+$newnbf=(Get-Date).AddYears(1).ToUniversalTime()
+$ops = "decrypt", "verify"
+$delta=[TimeSpan]::FromMinutes(2)
+
+function Equal-DateTime($left, $right)
+{
+ if ($left -eq $null -and $right -eq $null)
+ {
+ return $true
+ }
+ if ($left -eq $null -or $right -eq $null)
+ {
+ return $false
+ }
+
+ return (($left - $right).Duration() -le $delta)
+}
+
+function Assert-KeyAttributes($keyAttr, $keytype, $keyenable, $keyexp, $keynbf, $keyops)
+{
+ Assert-NotNull $keyAttr, "keyAttr is null."
+ Assert-AreEqual $keytype $keyAttr.KeyType "Expect $keytype. Get $keyAttr.KeyType"
+ Assert-AreEqual $keyenable $keyAttr.Enabled "Expect $keyenable. Get $keyAttr.Enabled"
+ if ($keyexp -ne $null)
+ {
+ Assert-True { Equal-DateTime $keyexp $keyAttr.Expires } "Expect $keyexp. Get $keyAttr.Expires"
+ }
+ if ($keynbf -ne $null)
+ {
+ Assert-True { Equal-DateTime $keynbf $keyAttr.NotBefore} "Expect $keynbf. Get $keyAttr.NotBefore"
+ }
+}
+
+
+<#
+.SYNOPSIS
+Tests create software key with default attributes
+#>
+
+function Test_CreateSoftwareKeyWithDefaultAttributes
+{
+ $keyVault = Get-KeyVault
+ $keyname=Get-KeyName 'soft'
+ $key=Add-AzureKeyVaultKey -VaultName $keyVault -Name $keyname
+ Assert-NotNull $key
+ $global:createdKeys += $keyname
+ Assert-KeyAttributes $key.Attributes 'RSA' $true $null $null $null
+}
+
+<#
+.SYNOPSIS
+Tests create software key with custom attributes
+#>
+function Test_CreateSoftwareKeyWithCustomAttributes
+{
+ $keyVault = Get-KeyVault
+ $keyname=Get-KeyName 'attr'
+ $key=Add-AzureKeyVaultKey -VaultName $keyVault -Name $keyname -Destination 'Software' -Expires $expires -NotBefore $nbf -KeyOps $ops -Disable
+ Assert-NotNull $key
+ $global:createdKeys += $keyname
+ Assert-KeyAttributes $key.Attributes 'RSA' $false $expires $nbf $ops
+}
+
+<#
+.SYNOPSIS
+Tests create Hsm key with custom attributes
+#>
+function Test_CreateHsmKeyWithDefaultAttributes
+{
+ $keyVault = Get-KeyVault
+ $keyname=Get-KeyName 'hsm'
+ $key=Add-AzureKeyVaultKey -VaultName $keyVault -Name $keyname -Destination 'HSM'
+ Assert-NotNull $key
+ $global:createdKeys += $keyname
+ Assert-KeyAttributes $key.Attributes 'RSA-HSM' $true $null $null $null
+}
+
+<#
+.SYNOPSIS
+Tests create Hsm key with custom attributes
+#>
+function Test_CreateHsmKeyWithCustomAttributes
+{
+ $keyVault = Get-KeyVault
+ $keyname=Get-KeyName 'attrhsm'
+ $key=Add-AzureKeyVaultKey -VaultName $keyVault -Name $keyname -Destination 'HSM' -Expires $expires -NotBefore $nbf -KeyOps $keyOps -Disable
+ Assert-NotNull $key
+ $global:createdKeys += $keyname
+ Assert-KeyAttributes $key.Attributes 'RSA-HSM' $false $expires $nbf $ops
+}
+
+<#
+.SYNOPSIS
+Tests import pfx with default attributes
+#>
+function Test_ImportPfxWithDefaultAttributes
+{
+ $keyVault = Get-KeyVault
+ $keyname=Get-KeyName 'pfx'
+ $pfxpath = Get-ImportKeyFile 'pfx'
+ $key=Add-AzureKeyVaultKey -VaultName $keyVault -Name $keyname -KeyFilePath $pfxpath -KeyFilePassword $securepfxpwd
+ Assert-NotNull $key
+ $global:createdKeys += $keyname
+ Assert-KeyAttributes $key.Attributes 'RSA' $true $null $null $null
+ }
+
+<#
+.SYNOPSIS
+Tests import pfx with custom attributes
+#>
+function Test_ImportPfxWithCustomAttributes
+{
+ $keyVault = Get-KeyVault
+ $keyname=Get-KeyName 'attrpfx'
+ $pfxpath = Get-ImportKeyFile 'pfx'
+ $key=Add-AzureKeyVaultKey -VaultName $keyVault -Name $keyname -Destination 'Software' -KeyFilePath $pfxpath -KeyFilePassword $securepfxpwd -Expires $expires -NotBefore $nbf -KeyOps $keyOps -Disable
+ Assert-NotNull $key
+ $global:createdKeys += $keyname
+ Assert-KeyAttributes $key.Attributes 'RSA' $false $expires $nbf $ops
+}
+
+<#
+.SYNOPSIS
+Tests import pfx as Hsm with default attributes
+#>
+function Test_ImportPfxAsHsmWithDefaultAttributes
+{
+ $keyVault = Get-KeyVault
+ $keyname=Get-KeyName 'pfxashsm'
+ $pfxpath = Get-ImportKeyFile 'pfx'
+ $key=Add-AzureKeyVaultKey -VaultName $keyVault -Name $keyname -Destination 'HSM' -KeyFilePath $pfxpath -KeyFilePassword $securepfxpwd
+ Assert-NotNull $key
+ $global:createdKeys += $keyname
+ Assert-KeyAttributes $key.Attributes 'RSA-HSM' $true $null $null $null
+}
+
+<#
+.SYNOPSIS
+Tests import pfx as Hsm with custom attributes
+#>
+function Test_ImportPfxAsHsmWithCustomAttributes
+{
+ $keyVault = Get-KeyVault
+ $keyname=Get-KeyName 'attrpfxashsm'
+ $pfxpath = Get-ImportKeyFile 'pfx'
+ $key=Add-AzureKeyVaultKey -VaultName $keyVault -Name $keyname -Destination 'HSM' -KeyFilePath $pfxpath -KeyFilePassword $securepfxpwd -Expires $expires -NotBefore $nbf -KeyOps $keyOps -Disable
+ Assert-NotNull $key
+ $global:createdKeys += $keyname
+ Assert-KeyAttributes $key.Attributes 'RSA-HSM' $false $expires $nbf $ops
+}
+
+<#
+.SYNOPSIS
+Tests import byok with default attributes
+#>
+function Test_ImportByokWithDefaultAttributes
+{
+ $keyVault = Get-KeyVault
+ $keyname=Get-KeyName 'byok'
+ $byokpath = Get-ImportKeyFile 'byok'
+ $key=Add-AzureKeyVaultKey -VaultName $keyVault -Name $keyname -KeyFilePath $byokpath
+ Assert-NotNull $key
+ $global:createdKeys += $keyname
+ Assert-KeyAttributes $key.Attributes 'RSA-HSM' $true $null $null $null
+}
+
+<#
+.SYNOPSIS
+Tests import byok with custom attributes
+#>
+function Test_ImportByokWithCustomAttributes
+{
+ $keyVault = Get-KeyVault
+ $keyname=Get-KeyName 'attrbyok'
+ $byokpath = Get-ImportKeyFile 'byok'
+ $key=Add-AzureKeyVaultKey -VaultName $keyVault -Name $keyname -Destination 'HSM' -KeyFilePath $byokpath -Expires $expires -NotBefore $nbf -KeyOps $keyOps -Disable
+ Assert-NotNull $key
+ $global:createdKeys += $keyname
+ Assert-KeyAttributes $key.Attributes 'RSA-HSM' $false $expires $nbf $ops
+}
+
+<#
+.SYNOPSIS
+Tests import byok with custom attributes
+#>
+function Test_ImportByokWithCustomAttributes
+{
+ $keyVault = Get-KeyVault
+ $keyname=Get-KeyName 'attrbyok'
+ $byokpath = Get-ImportKeyFile 'byok'
+ $key=Add-AzureKeyVaultKey -VaultName $keyVault -Name $keyname -Destination 'HSM' -KeyFilePath $byokpath -Expires $expires -NotBefore $nbf -KeyOps $keyOps -Disable
+ Assert-NotNull $key
+ $global:createdKeys += $keyname
+ Assert-KeyAttributes $key.Attributes 'RSA-HSM' $false $expires $nbf $ops
+}
+
+<#
+.SYNOPSIS
+Tests Add-AzureKeyVaultKey with positionalParameter
+#>
+function Test_AddKeyPositionalParameter
+{
+ $keyVault = Get-KeyVault
+ $keyname=Get-KeyName 'positional'
+ $key=Add-AzureKeyVaultKey $keyVault $keyname
+ Assert-NotNull $key
+ $global:createdKeys += $keyname
+}
+
+<#
+.SYNOPSIS
+Tests Add-AzureKeyVaultKey with parameter alias
+#>
+function Test_AddKeyAliasParameter
+{
+ $keyVault = Get-KeyVault
+ $keyname=Get-KeyName 'alias'
+ $key=Add-AzureKeyVaultKey -VaultName $keyVault -KeyName $keyname
+ Assert-NotNull $key
+ $global:createdKeys += $keyname
+}
+
+
+<#
+.SYNOPSIS
+Tests import non-exist pfx file
+#>
+function Test_ImportNonExistPfxFile
+{
+ $keyVault = Get-KeyVault
+ $keyname=Get-KeyName 'nonexistpfx'
+ $nonexistpfx = Get-ImportKeyFile 'pfx' $false
+ Assert-Throws {Add-AzureKeyVaultKey -VaultName $keyVault -KeyName $keyname -KeyFilePath $nonexistpfx -KeyFilePassword $securepfxpwd}
+}
+
+<#
+.SYNOPSIS
+Tests import non-exist pfx file
+#>
+function Test_ImportPfxFileWithIncorrectPassword
+{
+ $keyVault = Get-KeyVault
+ $keyname=Get-KeyName 'wrongpwdpfx'
+ $pfxpath = Get-ImportKeyFile 'pfx'
+ $wrongpwd= 'foo' | ConvertTo-SecureString -AsPlainText -Force
+ Assert-Throws {Add-AzureKeyVaultKey -VaultName $keyVault -KeyName $keyname -Name $keyname -KeyFilePath $pfxpath -KeyFilePassword $wrongpwd}
+}
+
+<#
+.SYNOPSIS
+Tests import non-exist pfx file
+#>
+function Test_ImportNonExistByokFile
+{
+ $keyVault = Get-KeyVault
+ $keyname=Get-KeyName 'nonexistbyok'
+ $nonexistbyok = Get-ImportKeyFile 'byok' $false
+ Assert-Throws {Add-AzureKeyVaultKey -VaultName $keyVault -KeyName $keyname -KeyFilePath $nonexistbyok}
+}
+
+<#
+.SYNOPSIS
+Tests import non-exist pfx file
+#>
+function Test_CreateKeyInNonExistVault
+{
+ $keyVault = 'notexistvault'
+ $keyname= 'notexitkey'
+ Assert-Throws {Add-AzureKeyVaultKey -VaultName $keyVault -KeyName $keyname}
+}
+
+<#
+.SYNOPSIS
+Tests import non-exist pfx file
+#>
+function Test_ImportByokAsSoftwareKey
+{
+ $keyVault = Get-KeyVault
+ $keyname= Get-KeyName 'byokassoftware'
+ Assert-Throws {Add-AzureKeyVaultKey -VaultName $keyVault -Name $keyname -Destination 'Software' -KeyFilePath $byokpath}
+}
+
+<#
+.SYNOPSIS
+Tests create key in a vault not have permission
+#>
+function Test_CreateKeyInNoPermissionVault
+{
+ $keyVault = Get-KeyVault $false
+ $keyname= Get-KeyName 'nopermission'
+ Assert-Throws {Add-AzureKeyVaultKey -VaultName $keyVault -Name $keyname}
+}
+
+
+<#
+.SYNOPSIS
+Tests update individual key attributes
+#>
+function Test_UpdateIndividualAttributes
+{
+ # Create a software key for updating
+ $keyVault = Get-KeyVault
+ $keyname=Get-KeyName 'updatesoft'
+ $key=Add-AzureKeyVaultKey -VaultName $keyVault -Name $keyname -Destination 'Software' -Expires $expires -NotBefore $nbf -KeyOps $ops -Disable
+ Assert-NotNull $key
+ $global:createdKeys += $keyname
+ Assert-KeyAttributes $key.Attributes 'RSA' $false $expires $nbf $ops
+
+ # Update Expires
+ $key=Set-AzureKeyVaultKey -VaultName $keyVault -Name $keyname -Expires $newexpires
+ Assert-NotNull $key
+ Assert-KeyAttributes $key.Attributes 'RSA' $false $newexpires $nbf $null
+
+ # Update NotBefore
+ $key=Set-AzureKeyVaultKey -VaultName $keyVault -Name $keyname -NotBefore $newnbf
+ Assert-NotNull $key
+ Assert-KeyAttributes $key.Attributes 'RSA' $false $newexpires $newnbf $null
+
+ # Update Enable
+ $key=Set-AzureKeyVaultKey -VaultName $keyVault -Name $keyname -Enable $true
+ Assert-NotNull $key
+ Assert-KeyAttributes $key.Attributes 'RSA' $true $newexpires $newnbf $null
+}
+
+<#
+.SYNOPSIS
+Tests update individual key attributes
+#>
+function Test_UpdateAllEditableAttributes
+{
+ # Create a software key for updating
+ $keyVault = Get-KeyVault
+ $keyname=Get-KeyName 'usoft'
+ $key=Add-AzureKeyVaultKey -VaultName $keyVault -Name $keyname -Destination 'Software' -Expires $expires -NotBefore $nbf -KeyOps $ops -Disable
+ Assert-NotNull $key
+ $global:createdKeys += $keyname
+ Assert-KeyAttributes $key.Attributes 'RSA' $false $expires $nbf $ops
+
+ # Update Expires
+ $key=Set-AzureKeyVaultKey -VaultName $keyVault -Name $keyname -Expires $newexpires -NotBefore $newnbf -Enable $true
+ Assert-KeyAttributes $key.Attributes 'RSA' $true $newexpires $newnbf $null
+
+ # Create a hsm key for updating
+ $keyname=Get-KeyName 'uhsm'
+ $key=Add-AzureKeyVaultKey -VaultName $keyVault -Name $keyname -Destination 'HSM' -Expires $expires -NotBefore $nbf -KeyOps $ops -Disable
+ Assert-NotNull $key
+ $global:createdKeys += $keyname
+ Assert-KeyAttributes $key.Attributes 'RSA-HSM' $false $expires $nbf $ops
+
+ # Update Expires
+ $key=Set-AzureKeyVaultKey -VaultName $keyVault -Name $keyname -Expires $newexpires -NotBefore $newnbf -Enable $true
+ Assert-KeyAttributes $key.Attributes 'RSA-HSM' $true $newexpires $newnbf $null
+}
+
+
+<#
+.SYNOPSIS
+Tests Set-AzureKeyVaultKey with positionalParameter
+#>
+function Test_SetKeyPositionalParameter
+{
+ $keyVault = Get-KeyVault
+ $keyname=Get-KeyName 'positional'
+ $key=Add-AzureKeyVaultKey -VaultName $keyVault -Name $keyname
+ Assert-NotNull $key
+ $global:createdKeys += $keyname
+
+ Set-AzureKeyVaultKey $keyVault $keyname -Expires $newexpires -NotBefore $newnbf -Enable $true
+}
+
+<#
+.SYNOPSIS
+Tests Set-AzureKeyVaultKey with parameter alias
+#>
+function Test_SetKeyAliasParameter
+{
+ $keyVault = Get-KeyVault
+ $keyname=Get-KeyName 'alias'
+ $key=Add-AzureKeyVaultKey -VaultName $keyVault -Name $keyname
+ Assert-NotNull $key
+ $global:createdKeys += $keyname
+
+ Set-AzureKeyVaultKey -VaultName $keyVault -KeyName $keyname -Expires $newexpires -NotBefore $newnbf -Enable $true
+}
+
+<#
+.SYNOPSIS
+Tests set a key in non-exist key vault
+#>
+function Test_SetKeyInNonExistVault
+{
+ $keyVault = 'notexistvault'
+ $keyname=Get-KeyName 'nonexist'
+ Assert-Throws {Set-AzureKeyVaultKey -VaultName $keyVault -KeyName $keyname -Enable $true}
+}
+
+<#
+.SYNOPSIS
+Tests set an not exist key
+#>
+function Test_SetNonExistKey
+{
+ $keyVault = Get-KeyVault
+ $keyname=Get-KeyName 'nonexist'
+ Assert-Throws {Set-AzureKeyVaultKey -VaultName $keyVault -KeyName $keyname -Enable $true}
+}
+
+<#
+.SYNOPSIS
+Tests set invalid
+#>
+function Test_SetInvalidAttributes
+{
+ $keyVault = Get-KeyVault
+ $keyname=Get-KeyName 'invalidattr'
+ $key=Add-AzureKeyVaultKey -VaultName $keyVault -Name $keyname
+ Assert-NotNull $key
+ $global:createdKeys += $keyname
+
+ Assert-Throws {Set-AzureKeyVaultKey -VaultName $keyVault -KeyName $keyname -Expires $nbf -NotBefore $expires }
+
+}
+
+<#
+.SYNOPSIS
+Tests set key in a vault not have permission
+#>
+function Test_SetKeyInNoPermissionVault
+{
+ $keyVault = Get-KeyVault $false
+ $keyname= Get-KeyName 'nopermission'
+ Assert-Throws {Set-AzureKeyVaultKey -VaultName $keyVault -Name $keyname -Enable $true}
+}
+
+
+<#
+.SYNOPSIS
+Tests get one key from key vault
+#>
+
+function Test_GetOneKey
+{
+ $keyVault = Get-KeyVault
+ $keyname=Get-KeyName 'getone'
+ $key=Add-AzureKeyVaultKey -VaultName $keyVault -Name $keyname
+ Assert-NotNull $key
+ $global:createdKeys += $keyname
+ Assert-KeyAttributes $key.Attributes 'RSA' $true $null $null $null
+
+ $key=Get-AzureKeyVaultKey -VaultName $keyVault -Name $keyname
+ Assert-KeyAttributes $key.Attributes 'RSA' $true $null $null $null
+}
+
+<#
+.SYNOPSIS
+Tests get all keys from key vault
+#>
+
+function Test_GetAllKeys
+{
+ $keyVault = Get-KeyVault
+ $keypartialname=Get-KeyName 'get'
+ $total=2
+ for ($i=0;$i -lt $total; $i++)
+ {
+ $keyname = $keypartialname+$i;
+ $key=Add-AzureKeyVaultKey -VaultName $keyVault -Name $keyname
+ Assert-NotNull $key
+ $global:createdKeys += $keyname
+ }
+
+ $keys=Get-AzureKeyVaultKey -VaultName $keyVault
+ Assert-True { $keys.Count -ge $total }
+}
+
+<#
+.SYNOPSIS
+Tests Get-AzureKeyVaultKey with positional Parameter
+#>
+function Test_GetKeyPositionalParameter
+{
+ $keyVault = Get-KeyVault
+ $keyname=Get-KeyName 'positional'
+ $key=Add-AzureKeyVaultKey -VaultName $keyVault -Name $keyname
+ Assert-NotNull $key
+ $global:createdKeys += $keyname
+
+ $key=Get-AzureKeyVaultKey $keyVault $keyname
+ Assert-NotNull $key
+}
+
+<#
+.SYNOPSIS
+Tests Get-AzureKeyVaultKey with parameter alias
+#>
+function Test_GetKeyAliasParameter
+{
+ $keyVault = Get-KeyVault
+ $keyname=Get-KeyName 'alias'
+ $key=Add-AzureKeyVaultKey -VaultName $keyVault -Name $keyname
+ Assert-NotNull $key
+ $global:createdKeys += $keyname
+
+ $key=Get-AzureKeyVaultKey -VaultName $keyVault -KeyName $keyname
+ Assert-NotNull $key
+}
+
+<#
+.SYNOPSIS
+Tests get a key from non-exist key vault
+#>
+function Test_GetKeysInNonExistVault
+{
+ $keyVault = 'notexistvault'
+ Assert-Throws {Get-AzureKeyVaultKey -VaultName $keyVault}
+}
+
+<#
+.SYNOPSIS
+Tests get a non-exist key
+#>
+function Test_GetNonExistKey
+{
+ $keyVault = Get-KeyVault
+ $keyname = 'notexist'
+ Assert-Throws {Get-AzureKeyVaultKey -VaultName $keyVault -KeyName $keyname}
+}
+
+<#
+.SYNOPSIS
+Tests get key in a vault not have permission
+#>
+function Test_GetKeyInNoPermissionVault
+{
+ $keyVault = Get-KeyVault $false
+ Assert-Throws {Get-AzureKeyVaultKey -VaultName $keyVault}
+}
+
+
+<#
+.SYNOPSIS
+Tests remove a key
+#>
+function Test_RemoveKeyWithoutPrompt
+{
+ $keyVault = Get-KeyVault
+ $keyname=Get-KeyName 'remove'
+ $key=Add-AzureKeyVaultKey -VaultName $keyVault -Name $keyname
+ Assert-NotNull $key
+ $global:createdKeys += $keyname
+
+ $key=Remove-AzureKeyVaultKey -VaultName $keyVault -Name $keyname -Force -Confirm:$false -PassThru
+ Assert-NotNull $key
+
+ Assert-Throws { Get-AzureKeyVaultKey -VaultName $keyVault -Name $keyname}
+}
+
+<#
+.SYNOPSIS
+Tests Remove-AzureKeyVaultKey with whatif option
+#>
+function Test_RemoveKeyWhatIf
+{
+ $keyVault = Get-KeyVault
+ $keyname=Get-KeyName 'whatif'
+ $key=Add-AzureKeyVaultKey -VaultName $keyVault -Name $keyname
+ Assert-NotNull $key
+ $global:createdKeys += $keyname
+
+ Remove-AzureKeyVaultKey -VaultName $keyVault -Name $keyname -WhatIf
+
+ $key=Get-AzureKeyVaultKey -VaultName $keyVault -Name $keyname
+ Assert-NotNull $key
+}
+
+<#
+.SYNOPSIS
+Tests Remove-AzureKeyVaultKey with positional Parameter
+#>
+function Test_RemoveKeyPositionalParameter
+{
+ $keyVault = Get-KeyVault
+ $keyname=Get-KeyName 'positional'
+ $key=Add-AzureKeyVaultKey -VaultName $keyVault -Name $keyname
+ Assert-NotNull $key
+ $global:createdKeys += $keyname
+
+ Remove-AzureKeyVaultKey $keyVault $keyname -Force -Confirm:$false
+
+ Assert-Throws { Get-AzureKeyVaultKey -VaultName $keyVault -Name $keyname}
+}
+
+<#
+.SYNOPSIS
+Tests Remove-AzureKeyVaultKey with parameter alias
+#>
+function Test_RemoveKeyAliasParameter
+{
+ $keyVault = Get-KeyVault
+ $keyname=Get-KeyName 'alias'
+ $key=Add-AzureKeyVaultKey -VaultName $keyVault -Name $keyname
+ Assert-NotNull $key
+ $global:createdKeys += $keyname
+
+ Remove-AzureKeyVaultKey -VaultName $keyVault -KeyName $keyname -Force -Confirm:$false
+
+ Assert-Throws { Get-AzureKeyVaultKey -VaultName $keyVault -Name $keyname}
+}
+
+<#
+.SYNOPSIS
+Tests get a key from non-exist key vault
+#>
+function Test_RemoveKeyInNonExistVault
+{
+ $keyVault = 'notexistvault'
+ $keyname = 'notexist'
+ Assert-Throws {Remove-AzureKeyVaultKey -VaultName $keyVault -Name $keyname -Force -Confirm:$false}
+}
+
+<#
+.SYNOPSIS
+Tests get a non-exist key
+#>
+function Test_RemoveNonExistKey
+{
+ $keyVault = Get-KeyVault
+ $keyname = 'notexist'
+ Assert-Throws {Remove-AzureKeyVaultKey -VaultName $keyVault -Name $keyname -Force -Confirm:$false}
+}
+
+<#
+.SYNOPSIS
+Tests remove key in a vault not have permission
+#>
+function Test_RemoveKeyInNoPermissionVault
+{
+ $keyVault = Get-KeyVault $false
+ $keyname= Get-KeyName 'nopermission'
+ Assert-Throws {Remove-AzureKeyVaultKey -VaultName $keyVault -Name $keyname -Enable $true -Force -Confirm:$false}
+}
+
+<#
+.SYNOPSIS
+Tests pipeline commands to update attributes of multiple keys
+#>
+
+function Test_PipelineUpdateKeys
+{
+ $keyVault = Get-KeyVault
+ $keypartialname=Get-KeyName 'pipeupdate'
+ $total=2
+ for ($i=0;$i -lt $total; $i++)
+ {
+ $keyname = $keypartialname+$i;
+ $key=Add-AzureKeyVaultKey -VaultName $keyVault -Name $keyname
+ Assert-NotNull $key
+ $global:createdKeys += $keyname
+ }
+
+ Get-AzureKeyVaultKey $keyVault | Where-Object {$_.KeyName -like $keypartialname+'*'} | Set-AzureKeyVaultKey -Enable $false
+
+ Get-AzureKeyVaultKey $keyVault | Where-Object {$_.KeyName -like $keypartialname+'*'} | ForEach-Object { Assert-False { return $_.Attributes.Enable } }
+ }
+
+<#
+.SYNOPSIS
+Tests pipeline commands to remove multiple keys
+#>
+
+function Test_PipelineRemoveKeys
+{
+ $keyVault = Get-KeyVault
+ $keypartialname=Get-KeyName 'piperemove'
+ $total=2
+ for ($i=0;$i -lt $total; $i++)
+ {
+ $keyname = $keypartialname+$i;
+ $key=Add-AzureKeyVaultKey -VaultName $keyVault -Name $keyname
+ Assert-NotNull $key
+ $global:createdKeys += $keyname
+ }
+
+ Get-AzureKeyVaultKey $keyVault | Where-Object {$_.KeyName -like $keypartialname+'*'} | Remove-AzureKeyVaultKey -Force -Confirm:$false
+
+ $keys = Get-AzureKeyVaultKey $keyVault | Where-Object {$_.KeyName -like $keypartialname+'*'}
+ Assert-AreEqual $keys.Count 0
+}
\ No newline at end of file
diff --git a/src/ResourceManager/KeyVault/Commands.KeyVault.Test/Scripts/VaultSecretTests.ps1 b/src/ResourceManager/KeyVault/Commands.KeyVault.Test/Scripts/VaultSecretTests.ps1
new file mode 100644
index 000000000000..4038295e9829
--- /dev/null
+++ b/src/ResourceManager/KeyVault/Commands.KeyVault.Test/Scripts/VaultSecretTests.ps1
@@ -0,0 +1,353 @@
+$data=123
+$securedata=$data | ConvertTo-SecureString -AsPlainText -Force
+$newdata=456
+$newsecuredata=$newdata | ConvertTo-SecureString -AsPlainText -Force
+
+<#
+.SYNOPSIS
+Create a secret
+#>
+
+function Test_CreateSecret
+{
+ $keyVault = Get-KeyVault
+ $secretname= Get-SecretName 'default'
+ $sec=Set-AzureKeyVaultSecret -VaultName $keyVault -Name $secretname -SecretValue $securedata
+ Assert-NotNull $sec
+ $global:createdSecrets += $secretname
+ Assert-AreEqual $sec.SecretValueText $data
+}
+
+
+<#
+.SYNOPSIS
+Update a secret
+#>
+
+function Test_UpdateSecret
+{
+ $keyVault = Get-KeyVault
+ $secretname= Get-SecretName 'update'
+ $sec=Set-AzureKeyVaultSecret -VaultName $keyVault -Name $secretname -SecretValue $securedata
+ Assert-NotNull $sec
+ $global:createdSecrets += $secretname
+ Assert-AreEqual $sec.SecretValueText $data
+
+ $sec=Set-AzureKeyVaultSecret -VaultName $keyVault -Name $secretname -SecretValue $newsecuredata
+ Assert-NotNull $sec
+ Assert-AreEqual $sec.SecretValueText $newdata
+}
+
+<#
+.SYNOPSIS
+Tests Set-AzureKeyVaultSecret with positional parameter
+#>
+function Test_SetSecretPositionalParameter
+{
+ $keyVault = Get-KeyVault
+ $secretname= Get-SecretName 'positional'
+ $sec=Set-AzureKeyVaultSecret $keyVault $secretname $securedata
+ Assert-NotNull $sec
+ $global:createdSecrets += $secretname
+ Assert-AreEqual $sec.SecretValueText $data
+}
+
+<#
+.SYNOPSIS
+Tests Set-AzureKeyVaultSecret with parameter alias
+#>
+function Test_SetSecretAliasParameter
+{
+ $keyVault = Get-KeyVault
+ $secretname= Get-SecretName 'alias'
+ $sec=Set-AzureKeyVaultSecret -VaultName $keyVault -SecretName $secretname -SecretValue $securedata
+ Assert-NotNull $sec
+ $global:createdSecrets += $secretname
+ Assert-AreEqual $sec.SecretValueText $data
+}
+
+<#
+.SYNOPSIS
+Tests set a secret in non-exist key vault
+#>
+function Test_SetSecretInNonExistVault
+{
+ $keyVault = 'notexistvault'
+ $secretname= Get-SecretName 'nonexist'
+ Assert-Throws {Set-AzureKeyVaultSecret -VaultName $keyVault -Name $secretname -SecretValue $securedata}
+}
+
+<#
+.SYNOPSIS
+Tests set secret in a vault the user does not have permission
+#>
+function Test_SetSecretInNoPermissionVault
+{
+ $keyVault = Get-KeyVault $false
+ $secretname= Get-SecretName 'nopermission'
+ Assert-Throws {Set-AzureKeyVaultSecret -VaultName $keyVault -Name $secretname -SecretValue $securedata}
+}
+
+<#
+.SYNOPSIS
+Tests get one secret from key vault
+#>
+
+function Test_GetOneSecret
+{
+ $keyVault = Get-KeyVault
+ $secretname= Get-SecretName 'getone'
+ $sec=Set-AzureKeyVaultSecret -VaultName $keyVault -Name $secretname -SecretValue $securedata
+ Assert-NotNull $sec
+ $global:createdSecrets += $secretname
+ Assert-AreEqual $sec.SecretValueText $data
+
+ $sec=Get-AzureKeyVaultSecret -VaultName $keyVault -Name $secretname
+ Assert-NotNull $sec
+ Assert-AreEqual $sec.SecretValueText $data
+}
+
+<#
+.SYNOPSIS
+Tests get all secrets from key vault
+#>
+
+function Test_GetAllSecrets
+{
+ $keyVault = Get-KeyVault
+ $secretpartialname=Get-SecretName 'get'
+ $total=2
+ for ($i=0;$i -lt $total; $i++)
+ {
+ $secretname = $secretpartialname+$i;
+ $sec=Set-AzureKeyVaultSecret -VaultName $keyVault -Name $secretname -SecretValue $securedata
+ Assert-NotNull $sec
+ $global:createdSecrets += $secretname
+ }
+
+ $secs=Get-AzureKeyVaultSecret -VaultName $keyVault
+ Assert-True { $secs.Count -ge $total }
+}
+
+<#
+.SYNOPSIS
+Tests Get-AzureKeyVaultSecret with positional parameter
+#>
+function Test_GetSecretPositionalParameter
+{
+ $keyVault = Get-KeyVault
+ $secretname= Get-SecretName 'positional'
+ $sec=Set-AzureKeyVaultSecret -VaultName $keyVault -Name $secretname -SecretValue $securedata
+ Assert-NotNull $sec
+ $global:createdSecrets += $secretname
+ Assert-AreEqual $sec.SecretValueText $data
+
+ $sec=Get-AzureKeyVaultSecret $keyVault $secretname
+ Assert-NotNull $sec
+ Assert-AreEqual $sec.SecretValueText $data
+}
+
+<#
+.SYNOPSIS
+Tests Get-AzureKeyVaultSecret with parameter alias
+#>
+function Test_GetSecretAliasParameter
+{
+ $keyVault = Get-KeyVault
+ $secretname= Get-SecretName 'alias'
+ $sec=Set-AzureKeyVaultSecret -VaultName $keyVault -Name $secretname -SecretValue $securedata
+ Assert-NotNull $sec
+ $global:createdSecrets += $secretname
+ Assert-AreEqual $sec.SecretValueText $data
+
+ $sec=Get-AzureKeyVaultSecret -VaultName $keyVault -SecretName $secretname
+ Assert-NotNull $sec
+ Assert-AreEqual $sec.SecretValueText $data
+}
+
+<#
+.SYNOPSIS
+Tests get a secret in non-exist key vault
+#>
+function Test_GetSecretInNonExistVault
+{
+ $keyVault = 'notexistvault'
+ Assert-Throws {Get-AzureKeyVaultSecret -VaultName $keyVault}
+}
+
+<#
+.SYNOPSIS
+Tests get a non-exist secret
+#>
+function Test_GetNonExistSecret
+{
+ $keyVault = Get-KeyVault
+ $secretname= Get-SecretName 'notexistvault'
+
+ Assert-Throws {Get-AzureKeyVaultSecret -VaultName $keyVault -Name $secretname}
+}
+
+<#
+.SYNOPSIS
+Tests get secret in a vault the user does not have permission
+#>
+function Test_GetSecretInNoPermissionVault
+{
+ $keyVault = Get-KeyVault $false
+ Assert-Throws {Get-AzureKeyVaultSecret -VaultName $keyVault}
+}
+
+<#
+.SYNOPSIS
+Tests remove a secret
+#>
+function Test_RemoveSecretWithoutPrompt
+{
+ $keyVault = Get-KeyVault
+ $secretname= Get-SecretName 'remove'
+ $sec=Set-AzureKeyVaultSecret -VaultName $keyVault -Name $secretname -SecretValue $securedata
+ Assert-NotNull $sec
+ $global:createdSecrets += $secretname
+
+ $sec=Remove-AzureKeyVaultSecret -VaultName $keyVault -Name $secretname -Force -Confirm:$false -PassThru
+ Assert-NotNull $sec
+
+ Assert-Throws { Get-AzureKeyVaultSecret -VaultName $keyVault -Name $secretname }
+}
+
+<#
+.SYNOPSIS
+Tests Remove-AzureKeyVaultSecret with whatif option
+#>
+function Test_RemoveSecretWhatIf
+{
+ $keyVault = Get-KeyVault
+ $secretname= Get-SecretName 'whatif'
+ $sec=Set-AzureKeyVaultSecret -VaultName $keyVault -Name $secretname -SecretValue $securedata
+ Assert-NotNull $sec
+ $global:createdSecrets += $secretname
+
+ Remove-AzureKeyVaultSecret -VaultName $keyVault -Name $secretname -WhatIf
+
+ $sec=Get-AzureKeyVaultSecret -VaultName $keyVault -Name $secretname
+ Assert-NotNull $sec
+}
+
+<#
+.SYNOPSIS
+Tests Remove-AzureKeyVaultSecret with positional parameter
+#>
+function Test_RemoveSecretPositionalParameter
+{
+ $keyVault = Get-KeyVault
+ $secretname= Get-SecretName 'positional'
+ $sec=Set-AzureKeyVaultSecret -VaultName $keyVault -Name $secretname -SecretValue $securedata
+ Assert-NotNull $sec
+ $global:createdSecrets += $secretname
+ Assert-AreEqual $sec.SecretValueText $data
+
+ Remove-AzureKeyVaultSecret $keyVault $secretname -Force -Confirm:$false
+
+ Assert-Throws {Get-AzureKeyVaultSecret -VaultName $keyVault -Name $secretname}
+}
+
+<#
+.SYNOPSIS
+Tests Remove-AzureKeyVaultSecret with parameter alias
+#>
+function Test_RemoveSecretAliasParameter
+{
+ $keyVault = Get-KeyVault
+ $secretname= Get-SecretName 'alias'
+ $sec=Set-AzureKeyVaultSecret -VaultName $keyVault -Name $secretname -SecretValue $securedata
+ Assert-NotNull $sec
+ $global:createdSecrets += $secretname
+ Assert-AreEqual $sec.SecretValueText $data
+
+ Remove-AzureKeyVaultSecret -VaultName $keyVault -SecretName $secretname -Force -Confirm:$false
+
+ Assert-Throws {Get-AzureKeyVaultSecret -VaultName $keyVault -Name $secretname}
+}
+
+<#
+.SYNOPSIS
+Tests remove a secret in non-exist key vault
+#>
+function Test_RemoveSecretInNonExistVault
+{
+ $keyVault = 'notexistvault'
+ $secretname= Get-SecretName 'notexistvault'
+ Assert-Throws {Remove-AzureKeyVaultSecret -VaultName $keyVault -Name $secretname -Force -Confirm:$false}
+}
+
+<#
+.SYNOPSIS
+Tests remove a non-exist secret
+#>
+function Test_RemoveNonExistSecret
+{
+ $keyVault = Get-KeyVault
+ $secretname= Get-SecretName 'notexistvault'
+
+ Assert-Throws {Remove-AzureKeyVaultSecret -VaultName $keyVault -Name $secretname -Force -Confirm:$false}
+}
+
+<#
+.SYNOPSIS
+Tests Remove a secret in a vault the user does not have permission
+#>
+function Test_RemoveSecretInNoPermissionVault
+{
+ $keyVault = Get-KeyVault $false
+ $secretname= Get-SecretName 'nopermission'
+ Assert-Throws {Remove-AzureKeyVaultSecret -VaultName $keyVault -Name $secretname -Force -Confirm:$false}
+}
+
+<#
+.SYNOPSIS
+Tests pipeline commands to update attributes of multiple secret
+#>
+
+function Test_PipelineUpdateSecrets
+{
+ $keyVault = Get-KeyVault
+ $secretpartialname=Get-KeyName 'pipeupdate'
+ $total=2
+ for ($i=0;$i -lt $total; $i++)
+ {
+ $secretname = $secretpartialname+$i;
+ $sec=Set-AzureKeyVaultSecret -VaultName $keyVault -Name $secretname -SecretValue $securedata
+ Assert-NotNull $sec
+ $global:createdSecrets += $secretname
+ Assert-AreEqual $sec.SecretValueText $data
+ }
+
+ Get-AzureKeyVaultSecret $keyVault | Where-Object {$_.SecretName -like $secretpartialname+'*'} | Set-AzureKeyVaultSecret -SecretValue $newsecuredata
+ Get-AzureKeyVaultSecret $keyVault | Where-Object {$_.SecretName -like $secretpartialname+'*'} | ForEach-Object { Assert-AreEqual $_.SecretValueText $newdata }
+}
+
+<#
+.SYNOPSIS
+Tests pipeline commands to remove multiple secrets
+#>
+
+function Test_PipelineRemoveSecrets
+{
+ $keyVault = Get-KeyVault
+ $secretpartialname=Get-KeyName 'piperemove'
+ $total=2
+ for ($i=0;$i -lt $total; $i++)
+ {
+ $secretname = $secretpartialname+$i;
+ $sec=Set-AzureKeyVaultSecret -VaultName $keyVault -Name $secretname -SecretValue $securedata
+ Assert-NotNull $sec
+ $global:createdSecrets += $secretname
+ Assert-AreEqual $sec.SecretValueText $data
+ }
+
+
+ Get-AzureKeyVaultSecret $keyVault | Where-Object {$_.SecretName -like $secretpartialname+'*'} | Remove-AzureKeyVaultSecret -Force -Confirm:$false
+
+ $secs = Get-AzureKeyVaultSecret $keyVault | Where-Object {$_.SecretName -like $secretpartialname+'*'}
+ Assert-AreEqual $secs.Count 0
+}
\ No newline at end of file
diff --git a/src/ResourceManager/KeyVault/Commands.KeyVault.Test/Scripts/VaultUITests.ps1 b/src/ResourceManager/KeyVault/Commands.KeyVault.Test/Scripts/VaultUITests.ps1
new file mode 100644
index 000000000000..7aacc6e8d024
--- /dev/null
+++ b/src/ResourceManager/KeyVault/Commands.KeyVault.Test/Scripts/VaultUITests.ps1
@@ -0,0 +1,181 @@
+$pfxpwd='123'
+$securepfxpwd=$pfxpwd | ConvertTo-SecureString -AsPlainText -Force
+$data=123
+$securedata=$data | ConvertTo-SecureString -AsPlainText -Force
+
+<#
+.SYNOPSIS
+Tests remove a key with two confirmations
+#>
+function Test_RemoveKeyWithTwoConfirmations
+{
+ Write-Host "Type 'Yes' twice"
+ $keyVault = Get-KeyVault
+ $keyname=Get-KeyName 'remove'
+ $key=Add-AzureKeyVaultKey -VaultName $keyVault -Name $keyname
+ Assert-NotNull $key
+ $global:createdKeys += $keyname
+
+ $cr=$global:ConfirmPreference
+ $global:ConfirmPreference="High"
+ Remove-AzureKeyVaultKey -VaultName $keyVault -Name $keyname
+ $global:ConfirmPreference=$cr
+
+ Assert-Throws { Get-AzureKeyVaultKey -VaultName $keyVault -Name $keyname}
+}
+
+<#
+.SYNOPSIS
+Tests remove a key with one confirmation
+#>
+function Test_RemoveKeyWithOneConfirmations
+{
+ Write-Host "Type 'Yes' once"
+ $keyVault = Get-KeyVault
+ $keyname=Get-KeyName 'remove'
+ $key=Add-AzureKeyVaultKey -VaultName $keyVault -Name $keyname
+ Assert-NotNull $key
+ $global:createdKeys += $keyname
+
+ $cr=$global:ConfirmPreference
+ $global:ConfirmPreference="High"
+ Remove-AzureKeyVaultKey -VaultName $keyVault -Name $keyname -Force
+ $global:ConfirmPreference=$cr
+
+ Assert-Throws { Get-AzureKeyVaultKey -VaultName $keyVault -Name $keyname}
+}
+
+<#
+.SYNOPSIS
+Tests cancel removing a key with once
+#>
+function Test_CancelKeyRemovalOnce
+{
+ Write-Host "Type 'No' once"
+ $keyVault = Get-KeyVault
+ $keyname=Get-KeyName 'remove'
+ $key=Add-AzureKeyVaultKey -VaultName $keyVault -Name $keyname
+ Assert-NotNull $key
+ $global:createdKeys += $keyname
+
+ $cr=$global:ConfirmPreference
+ $global:ConfirmPreference="High"
+ Remove-AzureKeyVaultKey -VaultName $keyVault -Name $keyname
+ $global:ConfirmPreference=$cr
+
+ $key=Get-AzureKeyVaultKey -VaultName $keyVault -Name $keyname
+ Assert-NotNull $key
+}
+
+<#
+.SYNOPSIS
+Tests cancel removing a key with two prompts
+#>
+function Test_ConfirmThenCancelKeyRemoval
+{
+ Write-Host "Type 'Yes' first. Then type 'No'"
+ $keyVault = Get-KeyVault
+ $keyname=Get-KeyName 'remove'
+ $key=Add-AzureKeyVaultKey -VaultName $keyVault -Name $keyname
+ Assert-NotNull $key
+ $global:createdKeys += $keyname
+
+ $cr=$global:ConfirmPreference
+ $global:ConfirmPreference="High"
+ Remove-AzureKeyVaultKey -VaultName $keyVault -Name $keyname
+ $global:ConfirmPreference=$cr
+
+ $key=Get-AzureKeyVaultKey -VaultName $keyVault -Name $keyname
+ Assert-NotNull $key
+}
+
+
+
+<#
+.SYNOPSIS
+Tests remove a secret with two confirmations
+#>
+function Test_RemoveSecretWithTwoConfirmations
+{
+ Write-Host "Type 'Yes' twice"
+ $keyVault = Get-KeyVault
+ $secretname= Get-SecretName 'remove'
+ $sec=Set-AzureKeyVaultSecret -VaultName $keyVault -Name $secretname -SecretValue $securedata
+ Assert-NotNull $sec
+ $global:createdSecrets += $secretname
+
+ $cr=$global:ConfirmPreference
+ $global:ConfirmPreference="High"
+ Remove-AzureKeyVaultSecret -VaultName $keyVault -Name $secretname
+ $global:ConfirmPreference=$cr
+
+ Assert-Throws { Get-AzureKeyVaultSecret -VaultName $keyVault -Name $secretname }
+}
+
+<#
+.SYNOPSIS
+Tests remove a secret with one confirmations
+#>
+function Test_RemoveSecretWithOneConfirmations
+{
+ Write-Host "Type 'Yes' once"
+ $keyVault = Get-KeyVault
+ $secretname= Get-SecretName 'remove'
+ $sec=Set-AzureKeyVaultSecret -VaultName $keyVault -Name $secretname -SecretValue $securedata
+ Assert-NotNull $sec
+ $global:createdSecrets += $secretname
+
+ $cr=$global:ConfirmPreference
+ $global:ConfirmPreference="High"
+ Remove-AzureKeyVaultSecret -VaultName $keyVault -Name $secretname -Force
+ $global:ConfirmPreference=$cr
+
+ Assert-Throws { Get-AzureKeyVaultSecret -VaultName $keyVault -Name $secretname }
+}
+
+<#
+.SYNOPSIS
+Tests cancel removing a secret with once
+#>
+function Test_CancelSecretRemovalOnce
+{
+ Write-Host "Type 'No' once"
+ $keyVault = Get-KeyVault
+ $secretname= Get-SecretName 'remove'
+ $sec=Set-AzureKeyVaultSecret -VaultName $keyVault -Name $secretname -SecretValue $securedata
+ Assert-NotNull $sec
+ $global:createdSecrets += $secretname
+
+ $cr=$global:ConfirmPreference
+ $global:ConfirmPreference="High"
+ Remove-AzureKeyVaultSecret -VaultName $keyVault -Name $secretname
+ $global:ConfirmPreference=$cr
+
+ $sec=Get-AzureKeyVaultSecret -VaultName $keyVault -Name $secretname
+ Assert-NotNull $sec
+}
+
+<#
+.SYNOPSIS
+Tests cancel removing a secret with two prompts
+#>
+function Test_ConfirmThenCancelSecretRemoval
+{
+ Write-Host "Type 'Yes' first. Then type 'No'"
+ $keyVault = Get-KeyVault
+ $secretname= Get-SecretName 'remove'
+ $sec=Set-AzureKeyVaultSecret -VaultName $keyVault -Name $secretname -SecretValue $securedata
+ Assert-NotNull $sec
+ $global:createdSecrets += $secretname
+
+ $cr=$global:ConfirmPreference
+ $global:ConfirmPreference="High"
+ Remove-AzureKeyVaultSecret -VaultName $keyVault -Name $secretname
+ $global:ConfirmPreference=$cr
+
+ $sec=Get-AzureKeyVaultSecret -VaultName $keyVault -Name $secretname
+ Assert-NotNull $sec
+}
+
+
+
diff --git a/src/ResourceManager/KeyVault/Commands.KeyVault.Test/Scripts/bvtdata/byoktest.byok b/src/ResourceManager/KeyVault/Commands.KeyVault.Test/Scripts/bvtdata/byoktest.byok
new file mode 100644
index 000000000000..a8c9ed149309
Binary files /dev/null and b/src/ResourceManager/KeyVault/Commands.KeyVault.Test/Scripts/bvtdata/byoktest.byok differ
diff --git a/src/ResourceManager/KeyVault/Commands.KeyVault.Test/Scripts/bvtdata/pfxtest.pfx b/src/ResourceManager/KeyVault/Commands.KeyVault.Test/Scripts/bvtdata/pfxtest.pfx
new file mode 100644
index 000000000000..fefc03c0d0a0
Binary files /dev/null and b/src/ResourceManager/KeyVault/Commands.KeyVault.Test/Scripts/bvtdata/pfxtest.pfx differ
diff --git a/src/ResourceManager/KeyVault/Commands.KeyVault.Test/Scripts/proddata/byoktest.byok b/src/ResourceManager/KeyVault/Commands.KeyVault.Test/Scripts/proddata/byoktest.byok
new file mode 100644
index 000000000000..690e20b0319e
Binary files /dev/null and b/src/ResourceManager/KeyVault/Commands.KeyVault.Test/Scripts/proddata/byoktest.byok differ
diff --git a/src/ResourceManager/KeyVault/Commands.KeyVault.Test/Scripts/proddata/pfxtest.pfx b/src/ResourceManager/KeyVault/Commands.KeyVault.Test/Scripts/proddata/pfxtest.pfx
new file mode 100644
index 000000000000..fefc03c0d0a0
Binary files /dev/null and b/src/ResourceManager/KeyVault/Commands.KeyVault.Test/Scripts/proddata/pfxtest.pfx differ
diff --git a/src/ResourceManager/KeyVault/Commands.KeyVault.Test/Scripts/readme.txt b/src/ResourceManager/KeyVault/Commands.KeyVault.Test/Scripts/readme.txt
new file mode 100644
index 000000000000..dd7823dab9f9
--- /dev/null
+++ b/src/ResourceManager/KeyVault/Commands.KeyVault.Test/Scripts/readme.txt
@@ -0,0 +1,5 @@
+This folder contains ps1 scripts testing Azure Key Vault cmdlets.
+The steps to run these tests are:
+1. Copy this folder on a server 2012 R2 or windows 8.1 machine with Azure Powershell msi installed.
+2. Setup Azure account. Please refer to "Key Vault Powershell Sign-off criteria" in spec store for user account setup.
+3. Run 63 scripting tests using RunKeyVaultTests.ps1. Run 8 tests required user inputs using RunUITests.ps1.
\ No newline at end of file
diff --git a/src/ResourceManager/KeyVault/Commands.KeyVault.Test/UnitTests/KeyVaultUnitTestBase.cs b/src/ResourceManager/KeyVault/Commands.KeyVault.Test/UnitTests/KeyVaultUnitTestBase.cs
new file mode 100644
index 000000000000..e6040c9a9014
--- /dev/null
+++ b/src/ResourceManager/KeyVault/Commands.KeyVault.Test/UnitTests/KeyVaultUnitTestBase.cs
@@ -0,0 +1,54 @@
+// ----------------------------------------------------------------------------------
+//
+// Copyright Microsoft Corporation
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+// ----------------------------------------------------------------------------------
+
+using Microsoft.Azure.Commands.KeyVault.Models;
+using Moq;
+using System.Management.Automation;
+
+namespace Microsoft.Azure.Commands.KeyVault.Test
+{
+ public class KeyVaultUnitTestBase
+ {
+ protected const string subscriptionId = "subscriptionid";
+
+ protected const string ResourceGroupName = "bar";
+
+ protected const string Location = "centralus";
+
+ protected const string VaultName = "vaultname";
+
+ protected const string KeyName = "keyfoo";
+
+ protected const string KeyName2 = "keyfoo2";
+
+ protected const string SecretValue = "secval";
+
+ protected const string SecretValue2 = "secval2";
+
+ protected const string SecretName = "secfoo";
+
+ protected const string SecretName2 = "secfoo2";
+
+ protected Mock keyVaultClientMock;
+
+ protected Mock commandRuntimeMock;
+
+ public virtual void SetupTest()
+ {
+ keyVaultClientMock = new Mock();
+
+ commandRuntimeMock = new Mock();
+ }
+ }
+}
diff --git a/src/ResourceManager/KeyVault/Commands.KeyVault.Test/UnitTests/RemoveKeyVaultKeyTests.cs b/src/ResourceManager/KeyVault/Commands.KeyVault.Test/UnitTests/RemoveKeyVaultKeyTests.cs
new file mode 100644
index 000000000000..71fb8d666652
--- /dev/null
+++ b/src/ResourceManager/KeyVault/Commands.KeyVault.Test/UnitTests/RemoveKeyVaultKeyTests.cs
@@ -0,0 +1,125 @@
+// ----------------------------------------------------------------------------------
+//
+// Copyright Microsoft Corporation
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+// ----------------------------------------------------------------------------------
+
+using Microsoft.Azure.Commands.KeyVault.Cmdlets;
+using Microsoft.Azure.Commands.KeyVault.Models;
+using Microsoft.WindowsAzure.Commands.ScenarioTest;
+using Moq;
+using System;
+using System.Management.Automation;
+using Xunit;
+
+namespace Microsoft.Azure.Commands.KeyVault.Test.UnitTests
+{
+ public class RemoveKeyVaultKeyTests : KeyVaultUnitTestBase
+ {
+ private RemoveAzureKeyVaultKey cmdlet;
+ private KeyAttributes keyAttributes;
+ private Microsoft.KeyVault.WebKey.JsonWebKey webKey;
+ private KeyBundle keyBundle;
+
+ public RemoveKeyVaultKeyTests()
+ {
+ base.SetupTest();
+
+ cmdlet = new RemoveAzureKeyVaultKey()
+ {
+ CommandRuntime = commandRuntimeMock.Object,
+ DataServiceClient = keyVaultClientMock.Object,
+ VaultName = VaultName
+ };
+
+ keyAttributes = new KeyAttributes(true, DateTime.Now, DateTime.Now, "HSM", new string[]{"All"});
+ webKey = new Microsoft.KeyVault.WebKey.JsonWebKey();
+ keyBundle = new KeyBundle() { Attributes = keyAttributes, Key = webKey, KeyName = KeyName, VaultName = VaultName };
+ }
+
+ [Fact]
+ [Trait(Category.AcceptanceType, Category.CheckIn)]
+ public void CanRemvoeKeyWithPassThruTest()
+ {
+ KeyBundle expected = keyBundle;
+ keyVaultClientMock.Setup(kv => kv.DeleteKey(VaultName, KeyName)).Returns(expected).Verifiable();
+
+ // Mock the should process to return true
+ commandRuntimeMock.Setup(cr => cr.ShouldProcess(KeyName, It.IsAny())).Returns(true);
+ cmdlet.Name = KeyName;
+ cmdlet.Force = true;
+ cmdlet.PassThru = true;
+ cmdlet.ExecuteCmdlet();
+
+ // Assert
+ keyVaultClientMock.VerifyAll();
+ commandRuntimeMock.Verify(f => f.WriteObject(expected), Times.Once());
+ }
+
+ [Fact]
+ [Trait(Category.AcceptanceType, Category.CheckIn)]
+ public void CanRemoveKeyWithNoPassThruTest()
+ {
+ KeyBundle expected = keyBundle;
+ keyVaultClientMock.Setup(kv => kv.DeleteKey(VaultName, KeyName)).Returns(expected).Verifiable();
+
+ // Mock the should process to return true
+ commandRuntimeMock.Setup(cr => cr.ShouldProcess(KeyName, It.IsAny())).Returns(true);
+ cmdlet.Name = KeyName;
+ cmdlet.Force = true;
+ cmdlet.ExecuteCmdlet();
+
+ keyVaultClientMock.VerifyAll();
+
+ // Without PassThru never call WriteObject
+ commandRuntimeMock.Verify(f => f.WriteObject(expected), Times.Never());
+ }
+
+ [Fact]
+ [Trait(Category.AcceptanceType, Category.CheckIn)]
+ public void CannotRemoveKeyWithoutShouldProcessOrForceConfirmationTest()
+ {
+ KeyBundle expected = null;
+
+ cmdlet.Name = KeyName;
+ cmdlet.PassThru = true;
+ cmdlet.ExecuteCmdlet();
+
+ // Write object should be called with null input
+ commandRuntimeMock.Verify(f => f.WriteObject(expected), Times.Once());
+
+ // Should process but without force
+ commandRuntimeMock.Setup(cr => cr.ShouldProcess(KeyName, It.IsAny())).Returns(false);
+ cmdlet.ExecuteCmdlet();
+
+ // Write object should be called with null input
+ commandRuntimeMock.Verify(f => f.WriteObject(expected), Times.Exactly(2));
+ }
+
+ [Fact]
+ [Trait(Category.AcceptanceType, Category.CheckIn)]
+ public void ErrorRemvoeKeyWithPassThruTest()
+ {
+ keyVaultClientMock.Setup(kv => kv.DeleteKey(VaultName, KeyName)).Throws(new Exception()).Verifiable();
+
+ // Mock the should process to return true
+ commandRuntimeMock.Setup(cr => cr.ShouldProcess(KeyName, It.IsAny())).Returns(true);
+ cmdlet.Name = KeyName;
+ cmdlet.Force = true;
+ cmdlet.PassThru = true;
+ cmdlet.ExecuteCmdlet();
+
+ // Assert
+ keyVaultClientMock.VerifyAll();
+ commandRuntimeMock.Verify(f => f.WriteError(It.IsAny()), Times.Once());
+ }
+ }
+}
diff --git a/src/ResourceManager/KeyVault/Commands.KeyVault.Test/UnitTests/RemoveKeyVaultSecretTests.cs b/src/ResourceManager/KeyVault/Commands.KeyVault.Test/UnitTests/RemoveKeyVaultSecretTests.cs
new file mode 100644
index 000000000000..3eed1bd872a6
--- /dev/null
+++ b/src/ResourceManager/KeyVault/Commands.KeyVault.Test/UnitTests/RemoveKeyVaultSecretTests.cs
@@ -0,0 +1,129 @@
+// ----------------------------------------------------------------------------------
+//
+// Copyright Microsoft Corporation
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+// ----------------------------------------------------------------------------------
+
+using Microsoft.Azure.Commands.KeyVault.Cmdlets;
+using Microsoft.Azure.Commands.KeyVault.Models;
+using Microsoft.WindowsAzure.Commands.ScenarioTest;
+using Moq;
+using System;
+using System.Management.Automation;
+using System.Security;
+using Xunit;
+
+namespace Microsoft.Azure.Commands.KeyVault.Test.UnitTests
+{
+ public class RemoveKeyVaultSecretTests : KeyVaultUnitTestBase
+ {
+ private RemoveAzureKeyVaultSecret cmdlet;
+
+ public RemoveKeyVaultSecretTests()
+ {
+ base.SetupTest();
+
+ cmdlet = new RemoveAzureKeyVaultSecret()
+ {
+ CommandRuntime = commandRuntimeMock.Object,
+ DataServiceClient = keyVaultClientMock.Object,
+ VaultName = VaultName
+ };
+ }
+
+ [Fact]
+ [Trait(Category.AcceptanceType, Category.CheckIn)]
+ public void CanRemoveSecretWithPassThruTest()
+ {
+ SecureString secureSecretValue = SecretValue.ToSecureString();
+ Secret expected = new Secret() { SecretName = SecretName, VaultName = VaultName, SecretValue = secureSecretValue };
+ keyVaultClientMock.Setup(kv => kv.DeleteSecret(VaultName, SecretName)).Returns(expected).Verifiable();
+
+ // Mock the should process to return true
+ commandRuntimeMock.Setup(cr => cr.ShouldProcess(SecretName, It.IsAny())).Returns(true);
+ cmdlet.Name = SecretName;
+ cmdlet.Force = true;
+ cmdlet.PassThru = true;
+ cmdlet.ExecuteCmdlet();
+
+ keyVaultClientMock.VerifyAll();
+ commandRuntimeMock.Verify(f => f.WriteObject(expected), Times.Once());
+
+ //No force but should continue
+ commandRuntimeMock.Setup(cr => cr.ShouldProcess(SecretName, It.IsAny())).Returns(true);
+ commandRuntimeMock.Setup(cr => cr.ShouldContinue(It.IsAny(), It.IsAny())).Returns(true);
+ cmdlet.Force = false;
+ cmdlet.PassThru = true;
+ cmdlet.ExecuteCmdlet();
+
+ keyVaultClientMock.VerifyAll();
+ commandRuntimeMock.Verify(f => f.WriteObject(expected), Times.Exactly(2));
+ }
+
+ [Fact]
+ [Trait(Category.AcceptanceType, Category.CheckIn)]
+ public void CanRemoveSecretWithNoPassThruTest()
+ {
+ SecureString secureSecretValue = SecretValue.ToSecureString();
+ Secret expected = new Secret() { SecretName = SecretName, VaultName = VaultName, SecretValue = secureSecretValue };
+ keyVaultClientMock.Setup(kv => kv.DeleteSecret(VaultName, SecretName)).Returns(expected).Verifiable();
+
+ // Mock the should process to return true
+ commandRuntimeMock.Setup(cr => cr.ShouldProcess(SecretName, It.IsAny())).Returns(true);
+ cmdlet.Name = SecretName;
+ cmdlet.Force = true;
+ cmdlet.ExecuteCmdlet();
+
+ keyVaultClientMock.VerifyAll();
+
+ // Without PassThru never call WriteObject
+ commandRuntimeMock.Verify(f => f.WriteObject(expected), Times.Never());
+ }
+
+ [Fact]
+ [Trait(Category.AcceptanceType, Category.CheckIn)]
+ public void CannotRemoveSecretWithoutShouldProcessOrForceConfirmationTest()
+ {
+ Secret expected = null;
+
+ cmdlet.Name = SecretName;
+ cmdlet.PassThru = true;
+ cmdlet.ExecuteCmdlet();
+
+ // Write object should be called with null input
+ commandRuntimeMock.Verify(f => f.WriteObject(expected), Times.Once());
+
+ // Should process but without force
+ commandRuntimeMock.Setup(cr => cr.ShouldProcess(SecretName, It.IsAny())).Returns(true);
+ cmdlet.ExecuteCmdlet();
+
+ // Write object should be called with null input
+ commandRuntimeMock.Verify(f => f.WriteObject(expected), Times.Exactly(2));
+ }
+
+ [Fact]
+ [Trait(Category.AcceptanceType, Category.CheckIn)]
+ public void ErrorRemoveSecretWithPassThruTest()
+ {
+ keyVaultClientMock.Setup(kv => kv.DeleteSecret(VaultName, SecretName)).Throws(new Exception()).Verifiable();
+
+ // Mock the should process to return true
+ commandRuntimeMock.Setup(cr => cr.ShouldProcess(SecretName, It.IsAny())).Returns(true);
+ cmdlet.Name = SecretName;
+ cmdlet.Force = true;
+ cmdlet.PassThru = true;
+ cmdlet.ExecuteCmdlet();
+
+ keyVaultClientMock.VerifyAll();
+ commandRuntimeMock.Verify(f => f.WriteError(It.IsAny()), Times.Once());
+ }
+ }
+}
diff --git a/src/ResourceManager/KeyVault/Commands.KeyVault.Test/UnitTests/SetKeyVaultKeyTests.cs b/src/ResourceManager/KeyVault/Commands.KeyVault.Test/UnitTests/SetKeyVaultKeyTests.cs
new file mode 100644
index 000000000000..f8f5ed4d6c70
--- /dev/null
+++ b/src/ResourceManager/KeyVault/Commands.KeyVault.Test/UnitTests/SetKeyVaultKeyTests.cs
@@ -0,0 +1,92 @@
+// ----------------------------------------------------------------------------------
+//
+// Copyright Microsoft Corporation
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+// ----------------------------------------------------------------------------------
+
+using Microsoft.Azure.Commands.KeyVault.Cmdlets;
+using Microsoft.Azure.Commands.KeyVault.Models;
+using Microsoft.WindowsAzure.Commands.ScenarioTest;
+using Moq;
+using System;
+using System.Management.Automation;
+using Xunit;
+
+namespace Microsoft.Azure.Commands.KeyVault.Test.UnitTests
+{
+ public class SetKeyVaultKeyTests : KeyVaultUnitTestBase
+ {
+ private SetAzureKeyVaultKey cmdlet;
+ private KeyAttributes keyAttributes;
+ private Microsoft.KeyVault.WebKey.JsonWebKey webKey;
+ private KeyBundle keyBundle;
+
+ public SetKeyVaultKeyTests()
+ {
+ base.SetupTest();
+
+ keyAttributes = new KeyAttributes(true, DateTime.Now, DateTime.Now, null, null);
+ webKey = new Microsoft.KeyVault.WebKey.JsonWebKey();
+ keyBundle = new KeyBundle() { Attributes = keyAttributes, Key = webKey, KeyName = KeyName, VaultName = VaultName };
+
+ cmdlet = new SetAzureKeyVaultKey()
+ {
+ CommandRuntime = commandRuntimeMock.Object,
+ DataServiceClient = keyVaultClientMock.Object,
+ VaultName = VaultName,
+ Enable = keyAttributes.Enabled,
+ Expires = keyAttributes.Expires,
+ NotBefore = keyAttributes.NotBefore,
+ Name = KeyName
+ };
+ }
+
+ [Fact]
+ [Trait(Category.AcceptanceType, Category.CheckIn)]
+ public void CanSetKeyTest()
+ {
+ KeyBundle expected = keyBundle;
+ keyVaultClientMock.Setup(kv => kv.SetKey(VaultName, KeyName,
+ It.Is(kt => kt.Enabled == keyAttributes.Enabled
+ && kt.Expires == keyAttributes.Expires
+ && kt.NotBefore == keyAttributes.NotBefore
+ && kt.KeyType == keyAttributes.KeyType
+ && kt.KeyOps == keyAttributes.KeyOps)))
+ .Returns(expected).Verifiable();
+
+ cmdlet.ExecuteCmdlet();
+
+ // Assert
+ keyVaultClientMock.VerifyAll();
+ commandRuntimeMock.Verify(f => f.WriteObject(expected), Times.Once());
+ }
+
+ [Fact]
+ [Trait(Category.AcceptanceType, Category.CheckIn)]
+ public void ErrorSetKeyTest()
+ {
+ KeyBundle expected = keyBundle;
+ keyVaultClientMock.Setup(kv => kv.SetKey(VaultName, KeyName,
+ It.Is(kt => kt.Enabled == keyAttributes.Enabled
+ && kt.Expires == keyAttributes.Expires
+ && kt.NotBefore == keyAttributes.NotBefore
+ && kt.KeyType == keyAttributes.KeyType
+ && kt.KeyOps == keyAttributes.KeyOps)))
+ .Throws(new Exception("exception")).Verifiable();
+
+ cmdlet.ExecuteCmdlet();
+
+ // Assert
+ keyVaultClientMock.VerifyAll();
+ commandRuntimeMock.Verify(f => f.WriteError(It.IsAny()), Times.Once());
+ }
+ }
+}
diff --git a/src/ResourceManager/KeyVault/Commands.KeyVault.Test/UnitTests/SetKeyVaultSecretTests.cs b/src/ResourceManager/KeyVault/Commands.KeyVault.Test/UnitTests/SetKeyVaultSecretTests.cs
new file mode 100644
index 000000000000..125643140684
--- /dev/null
+++ b/src/ResourceManager/KeyVault/Commands.KeyVault.Test/UnitTests/SetKeyVaultSecretTests.cs
@@ -0,0 +1,76 @@
+// ----------------------------------------------------------------------------------
+//
+// Copyright Microsoft Corporation
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+// ----------------------------------------------------------------------------------
+
+using Microsoft.Azure.Commands.KeyVault.Cmdlets;
+using Microsoft.Azure.Commands.KeyVault.Models;
+using Microsoft.WindowsAzure.Commands.ScenarioTest;
+using Moq;
+using System;
+using System.Management.Automation;
+using System.Security;
+using Xunit;
+
+namespace Microsoft.Azure.Commands.KeyVault.Test.UnitTests
+{
+ public class SetKeyVaultSecretTests : KeyVaultUnitTestBase
+ {
+ private SetAzureKeyVaultSecret cmdlet;
+
+ public SetKeyVaultSecretTests()
+ {
+ base.SetupTest();
+
+ cmdlet = new SetAzureKeyVaultSecret()
+ {
+ CommandRuntime = commandRuntimeMock.Object,
+ DataServiceClient = keyVaultClientMock.Object,
+ VaultName = VaultName
+ };
+ }
+
+ [Fact]
+ [Trait(Category.AcceptanceType, Category.CheckIn)]
+ public void CanSetSecretTest()
+ {
+ SecureString secureSecretValue = SecretValue.ToSecureString();
+ Secret expected = new Secret() { SecretName = SecretName, VaultName = VaultName, SecretValue = secureSecretValue };
+ keyVaultClientMock.Setup(kv => kv.SetSecret(VaultName, SecretName, secureSecretValue)).Returns(expected).Verifiable();
+
+ cmdlet.Name = SecretName;
+ cmdlet.SecretValue = secureSecretValue;
+ cmdlet.ExecuteCmdlet();
+
+ // Assert
+ keyVaultClientMock.VerifyAll();
+ commandRuntimeMock.Verify(f => f.WriteObject(expected), Times.Once());
+ }
+
+ [Fact]
+ [Trait(Category.AcceptanceType, Category.CheckIn)]
+ public void ErrorSetSecretTest()
+ {
+ SecureString secureSecretValue = SecretValue.ToSecureString();
+ keyVaultClientMock.Setup(kv => kv.SetSecret(VaultName, SecretName, secureSecretValue))
+ .Throws(new Exception("exception")).Verifiable();
+
+ cmdlet.Name = SecretName;
+ cmdlet.SecretValue = secureSecretValue;
+ cmdlet.ExecuteCmdlet();
+
+ // Assert
+ keyVaultClientMock.VerifyAll();
+ commandRuntimeMock.Verify(f => f.WriteError(It.IsAny()), Times.Once());
+ }
+ }
+}
diff --git a/src/ResourceManager/KeyVault/Commands.KeyVault.Test/packages.config b/src/ResourceManager/KeyVault/Commands.KeyVault.Test/packages.config
new file mode 100644
index 000000000000..3c30556f0994
--- /dev/null
+++ b/src/ResourceManager/KeyVault/Commands.KeyVault.Test/packages.config
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/ResourceManager/KeyVault/Commands.KeyVault/Commands.KeyVault.csproj b/src/ResourceManager/KeyVault/Commands.KeyVault/Commands.KeyVault.csproj
new file mode 100644
index 000000000000..fd935b5fa6f6
--- /dev/null
+++ b/src/ResourceManager/KeyVault/Commands.KeyVault/Commands.KeyVault.csproj
@@ -0,0 +1,162 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {9FFC40CC-A341-4D0C-A25D-DC6B78EF6C94}
+ Library
+ Properties
+ Microsoft.Azure.Commands.KeyVault
+ Microsoft.Azure.Commands.KeyVault
+ v4.5
+ 512
+
+ ..\..\..\
+ true
+
+
+ true
+ full
+ false
+ ..\..\..\Package\Debug\ResourceManager\AzureResourceManager\KeyVault
+ DEBUG;TRACE
+ prompt
+ 4
+ true
+ false
+
+
+ true
+ MSSharedLibKey.snk
+ true
+ ..\..\..\Package\Release\ResourceManager\AzureResourceManager\KeyVault
+ TRACE;SIGN
+ true
+ pdbonly
+ AnyCPU
+ bin\Release\Microsoft.Azure.Commands.KeyVault.dll.CodeAnalysisLog.xml
+ true
+ GlobalSuppressions.cs
+ prompt
+ MinimumRecommendedRules.ruleset
+ ;$(ProgramFiles)\Microsoft Visual Studio 12.0\Team Tools\Static Analysis Tools\Rule Sets
+ ;$(ProgramFiles)\Microsoft Visual Studio 12.0\Team Tools\Static Analysis Tools\FxCop\Rules
+ true
+ false
+
+
+
+ PreserveNewest
+
+
+
+ Designer
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ True
+ True
+ Resources.resx
+
+
+
+
+ ..\..\..\packages\Microsoft.KeyVault.Client.1.0.0.20\lib\net45\Microsoft.KeyVault.Client.dll
+
+
+ ..\..\..\packages\Microsoft.KeyVault.WebKey.1.0.0.10\lib\net45\Microsoft.KeyVault.WebKey.dll
+
+
+ False
+ ..\..\..\packages\Microsoft.Azure.Management.Resources.2.7.0-preview\lib\net40\Microsoft.Azure.ResourceManager.dll
+
+
+ ..\..\..\packages\Microsoft.Data.Edm.5.6.0\lib\net40\Microsoft.Data.Edm.dll
+
+
+ ..\..\..\packages\Microsoft.Data.OData.5.6.0\lib\net40\Microsoft.Data.OData.dll
+
+
+ ..\..\..\packages\Microsoft.Data.Services.Client.5.6.0\lib\net40\Microsoft.Data.Services.Client.dll
+
+
+ False
+ ..\..\..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.dll
+
+
+ False
+ ..\..\..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.Extensions.dll
+
+
+ False
+ ..\..\..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.Extensions.Desktop.dll
+
+
+ False
+ ..\..\..\packages\Microsoft.WindowsAzure.Common.1.4.0\lib\net45\Microsoft.WindowsAzure.Common.dll
+
+
+ False
+ ..\..\..\packages\Microsoft.WindowsAzure.Common.1.4.0\lib\net45\Microsoft.WindowsAzure.Common.NetFramework.dll
+
+
+ False
+ ..\..\..\packages\Newtonsoft.Json.6.0.4\lib\net45\Newtonsoft.Json.dll
+
+
+
+
+
+ ..\..\..\packages\Microsoft.Net.Http.2.2.28\lib\net45\System.Net.Http.Extensions.dll
+
+
+ ..\..\..\packages\Microsoft.Net.Http.2.2.28\lib\net45\System.Net.Http.Primitives.dll
+
+
+
+
+
+
+
+
+ {5ee72c53-1720-4309-b54b-5fb79703195f}
+ Commands.Common
+
+
+
+
+ ResXFileCodeGenerator
+ Resources.Designer.cs
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/ResourceManager/KeyVault/Commands.KeyVault/Commands/AddAzureKeyVaultKey.cs b/src/ResourceManager/KeyVault/Commands.KeyVault/Commands/AddAzureKeyVaultKey.cs
new file mode 100644
index 000000000000..8004de880891
--- /dev/null
+++ b/src/ResourceManager/KeyVault/Commands.KeyVault/Commands/AddAzureKeyVaultKey.cs
@@ -0,0 +1,264 @@
+// ----------------------------------------------------------------------------------
+//
+// Copyright Microsoft Corporation
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+// ----------------------------------------------------------------------------------
+
+using System;
+using System.IO;
+using System.Security;
+using System.Management.Automation;
+using Microsoft.Azure.Commands.KeyVault.Models;
+using Microsoft.Azure.Commands.KeyVault.Properties;
+using Microsoft.KeyVault.WebKey;
+
+
+namespace Microsoft.Azure.Commands.KeyVault
+{
+ ///
+ /// Create a new key in key vault. This cmdlet supports the following types of
+ /// key creation.
+ /// 1. Create a new HSM or software key with default key attributes
+ /// 2. Create a new HSM or software key with given key attributes
+ /// 3. Create a HSM or software key by importing key material with default key
+ /// attributes
+ /// 4 .Create a HSM or software key by importing key material with given key
+ /// attributes
+ ///
+ [Cmdlet(VerbsCommon.Add, "AzureKeyVaultKey",
+ DefaultParameterSetName=CreateParameterSet)]
+ [OutputType(typeof(KeyBundle))]
+ public class AddAzureKeyVaultKey : KeyVaultCmdletBase
+ {
+
+ #region Parameter Set Names
+
+ private const string CreateParameterSet = "Create";
+ private const string ImportParameterSet = "Import";
+
+ #endregion
+
+ #region Input Parameter Definitions
+
+ ///
+ /// Vault name
+ ///
+ [Parameter(Mandatory = true,
+ ParameterSetName = CreateParameterSet,
+ Position = 0,
+ ValueFromPipelineByPropertyName = true,
+ HelpMessage = "Vault name. Cmdlet constructs the FQDN of a vault based on the name and currently selected environment.")]
+ [Parameter(Mandatory = true,
+ ParameterSetName = ImportParameterSet,
+ Position = 0,
+ ValueFromPipelineByPropertyName = true,
+ HelpMessage = "Vault name. Cmdlet constructs the FQDN of a vault based on the name and currently selected environment.")]
+ [ValidateNotNullOrEmpty]
+ public string VaultName
+ {
+ get;
+ set;
+ }
+
+ ///
+ /// key name
+ ///
+ [Parameter(Mandatory = true,
+ ParameterSetName = CreateParameterSet,
+ Position = 1,
+ HelpMessage = "key name")]
+ [Parameter(Mandatory = true,
+ ParameterSetName = ImportParameterSet,
+ Position = 1,
+ HelpMessage = "key name")]
+ [ValidateNotNullOrEmpty]
+ [Alias("KeyName")]
+ public string Name
+ {
+ get;
+ set;
+ }
+
+ ///
+ /// Path to the local file containing to-be-imported key material.
+ /// The supported suffix are:
+ /// 1. byok
+ /// 2. pfx
+ ///
+ [Parameter(Mandatory = true,
+ ParameterSetName = ImportParameterSet,
+ HelpMessage = "Path to the local file containing to-be-imported key material")]
+ [ValidateNotNullOrEmpty]
+ public string KeyFilePath
+ {
+ get;
+ set;
+ }
+
+ ///
+ /// Password of the imported file.
+ /// Required for pfx file
+ ///
+ [Parameter(Mandatory = false,
+ ParameterSetName = ImportParameterSet,
+ HelpMessage = "Password of the imported key file")]
+ [ValidateNotNullOrEmpty]
+ public SecureString KeyFilePassword
+ {
+ get;
+ set;
+ }
+
+ ///
+ /// Destination of the key
+ ///
+ [Parameter(Mandatory = false,
+ ParameterSetName = CreateParameterSet,
+ HelpMessage = "Destination of the key")]
+ [Parameter(Mandatory = false,
+ ParameterSetName = ImportParameterSet,
+ HelpMessage = "Destination of the key")]
+ [ValidateSetAttribute(new string[] { HsmDestination, SoftwareDestination })]
+ public string Destination
+ {
+ get;
+ set;
+ }
+
+ ///
+ /// Set key in disabled state if present
+ ///
+ [Parameter(Mandatory = false,
+ ParameterSetName = CreateParameterSet,
+ HelpMessage = "Set key in disabled state if present. If not present, key is enabled.")]
+ [Parameter(Mandatory = false,
+ ParameterSetName = ImportParameterSet,
+ HelpMessage = "Set key in disabled state if present. If not present, key is enabled.")]
+ public SwitchParameter Disable
+ {
+ get;
+ set;
+ }
+
+ ///
+ /// Key operations
+ ///
+ [Parameter(Mandatory = false,
+ ParameterSetName = CreateParameterSet,
+ ValueFromPipelineByPropertyName = true,
+ HelpMessage = "The operations that can performs with the key. If not present, all operations can be performed.")]
+ [Parameter(Mandatory = false,
+ ParameterSetName = ImportParameterSet,
+ ValueFromPipelineByPropertyName = true,
+ HelpMessage = "The operations that can performs with the key. If not present, all operations can be performed.")]
+ public string[] KeyOps
+ {
+ get;
+ set;
+ }
+
+ ///
+ /// Key expires time in UTC time
+ ///
+ [Parameter(Mandatory = false,
+ ParameterSetName = CreateParameterSet,
+ ValueFromPipelineByPropertyName = true,
+ HelpMessage = "The expiration time of a key in UTC time. If not present, key will not expire.")]
+ [Parameter(Mandatory = false,
+ ParameterSetName = ImportParameterSet,
+ ValueFromPipelineByPropertyName = true,
+ HelpMessage = "The expiration time of a key in UTC time. If not present, key will not expire.")]
+ public DateTime? Expires
+ {
+ get;
+ set;
+ }
+
+ ///
+ /// The UTC time before which key can't be used
+ ///
+ [Parameter(Mandatory = false,
+ ParameterSetName = CreateParameterSet,
+ ValueFromPipelineByPropertyName = true,
+ HelpMessage = "The UTC time before which key can't be used. If not present, no limitation.")]
+ [Parameter(Mandatory = false,
+ ParameterSetName = ImportParameterSet,
+ ValueFromPipelineByPropertyName = true,
+ HelpMessage = "The UTC time before which key can't be used. If not present, no limitation.")]
+ public DateTime? NotBefore
+ {
+ get;
+ set;
+ }
+
+ #endregion
+
+ public override void ExecuteCmdlet()
+ {
+ try
+ {
+ KeyBundle keyBundle;
+ switch (ParameterSetName)
+ {
+ case CreateParameterSet:
+ keyBundle = this.DataServiceClient.CreateKey(
+ VaultName, Name,
+ CreateKeyAttributes(false));
+ break;
+
+ case ImportParameterSet:
+ keyBundle = this.DataServiceClient.ImportKey(
+ VaultName, Name,
+ CreateKeyAttributes(),
+ CreateWebKeyFromFile());
+ break;
+
+ default:
+ throw new ArgumentException(Resources.BadParameterSetName);
+ }
+
+ this.WriteObject(keyBundle);
+ }
+ catch (Exception ex)
+ {
+ this.WriteErrorDetails(ex);
+ }
+ }
+
+ internal KeyCreationAttributes CreateKeyAttributes(bool? hsmDefault=null)
+ {
+ bool? isHsm = string.IsNullOrEmpty(Destination) ? hsmDefault :
+ HsmDestination.Equals(Destination, StringComparison.OrdinalIgnoreCase);
+
+ return new KeyCreationAttributes(
+ !Disable.IsPresent,
+ Expires,
+ NotBefore,
+ isHsm,
+ KeyOps);
+ }
+
+ internal JsonWebKey CreateWebKeyFromFile()
+ {
+ FileInfo keyFile = new FileInfo(this.GetUnresolvedProviderPathFromPSPath(this.KeyFilePath));
+ if (!keyFile.Exists)
+ {
+ throw new FileNotFoundException(string.Format(Resources.KeyFileNotFound, this.KeyFilePath));
+ }
+
+ var converterChain = WebKeyConverterFactory.CreateConverterChain();
+ return converterChain.ConvertKeyFromFile(keyFile, KeyFilePassword);
+ }
+
+ private const string HsmDestination = "HSM";
+ private const string SoftwareDestination = "Software";
+ }
+}
diff --git a/src/ResourceManager/KeyVault/Commands.KeyVault/Commands/GetAzureKeyVaultKey.cs b/src/ResourceManager/KeyVault/Commands.KeyVault/Commands/GetAzureKeyVaultKey.cs
new file mode 100644
index 000000000000..3a367197cf7d
--- /dev/null
+++ b/src/ResourceManager/KeyVault/Commands.KeyVault/Commands/GetAzureKeyVaultKey.cs
@@ -0,0 +1,105 @@
+// ----------------------------------------------------------------------------------
+//
+// Copyright Microsoft Corporation
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+// ----------------------------------------------------------------------------------
+
+using System;
+using System.Linq;
+using System.Collections.Generic;
+using System.Management.Automation;
+using Microsoft.Azure.Commands.KeyVault.Models;
+using Microsoft.Azure.Commands.KeyVault.Properties;
+
+namespace Microsoft.Azure.Commands.KeyVault.Cmdlets
+{
+ [Cmdlet(VerbsCommon.Get, "AzureKeyVaultKey",
+ DefaultParameterSetName=ByVaultNameParameterSet)]
+ [OutputType(typeof(List), typeof(KeyBundle))]
+ public class GetAzureKeyVaultKey : KeyVaultCmdletBase
+ {
+
+ #region Parameter Set Names
+
+ private const string ByKeyNameParameterSet = "ByKeyName";
+ private const string ByVaultNameParameterSet = "ByVaultName";
+
+ #endregion
+
+ #region Input Parameter Definitions
+
+ ///
+ /// Vault name
+ ///
+ [Parameter(Mandatory = true,
+ Position = 0,
+ ValueFromPipelineByPropertyName = true,
+ ParameterSetName = ByKeyNameParameterSet,
+ HelpMessage = "Vault name. Cmdlet constructs the FQDN of a vault based on the name and currently selected environment.")]
+ [Parameter(Mandatory = true,
+ Position = 0,
+ ValueFromPipelineByPropertyName = true,
+ ParameterSetName = ByVaultNameParameterSet,
+ HelpMessage = "Vault name. Cmdlet constructs the FQDN of a vault based on the name and currently selected environment.")]
+
+ [ValidateNotNullOrEmpty]
+ public string VaultName
+ {
+ get;
+ set;
+ }
+
+ ///
+ /// Key name.
+ ///
+ [Parameter(Mandatory = true,
+ ParameterSetName = ByKeyNameParameterSet,
+ Position = 1,
+ ValueFromPipelineByPropertyName = true,
+ HelpMessage = "key name. Cmdlet constructs the FQDN of a key from vault name, currently selected environment and key name.")]
+ [ValidateNotNullOrEmpty]
+ [Alias("KeyName")]
+ public string Name
+ {
+ get;
+ set;
+ }
+
+ #endregion
+
+ public override void ExecuteCmdlet()
+ {
+ try
+ {
+ switch (ParameterSetName)
+ {
+ case ByKeyNameParameterSet:
+ var keyBundle = DataServiceClient.GetKey(VaultName, Name);
+ WriteObject(keyBundle);
+ break;
+
+ case ByVaultNameParameterSet:
+ IEnumerable keyBundles = DataServiceClient.GetKeys(VaultName);
+ WriteObject(keyBundles, true);
+ break;
+
+ default:
+ throw new ArgumentException(Resources.BadParameterSetName);
+ }
+ }
+ catch (Exception ex)
+ {
+ this.WriteErrorDetails(ex);
+ }
+ }
+
+ }
+}
diff --git a/src/ResourceManager/KeyVault/Commands.KeyVault/Commands/GetAzureKeyVaultSecret.cs b/src/ResourceManager/KeyVault/Commands.KeyVault/Commands/GetAzureKeyVaultSecret.cs
new file mode 100644
index 000000000000..7fc077783027
--- /dev/null
+++ b/src/ResourceManager/KeyVault/Commands.KeyVault/Commands/GetAzureKeyVaultSecret.cs
@@ -0,0 +1,102 @@
+// ----------------------------------------------------------------------------------
+//
+// Copyright Microsoft Corporation
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+// ----------------------------------------------------------------------------------
+
+using Microsoft.Azure.Commands.KeyVault.Models;
+using Microsoft.Azure.Commands.KeyVault.Properties;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Management.Automation;
+
+namespace Microsoft.Azure.Commands.KeyVault.Cmdlets
+{
+ [Cmdlet(VerbsCommon.Get, "AzureKeyVaultSecret",
+ DefaultParameterSetName = ByVaultNameParameterSet)]
+ [OutputType(typeof(List))]
+ public class GetAzureKeyVaultSecret : KeyVaultCmdletBase
+ {
+ #region Parameter Set Names
+
+ private const string BySecretNameParameterSet = "BySecretName";
+ private const string ByVaultNameParameterSet = "ByVaultName";
+
+ #endregion
+
+ #region Input Parameter Definitions
+
+ ///
+ /// Vault name
+ ///
+ [Parameter(Mandatory = true,
+ Position = 0,
+ ValueFromPipelineByPropertyName = true,
+ ParameterSetName = BySecretNameParameterSet,
+ HelpMessage = "Vault name. Cmdlet constructs the FQDN of a vault based on the name and currently selected environment.")]
+ [Parameter(Mandatory = true,
+ Position = 0,
+ ValueFromPipelineByPropertyName = true,
+ ParameterSetName = ByVaultNameParameterSet,
+ HelpMessage = "Vault name. Cmdlet constructs the FQDN of a vault based on the name and currently selected environment.")]
+ [ValidateNotNullOrEmpty]
+ public string VaultName
+ {
+ get;
+ set;
+ }
+
+ ///
+ /// Secret name
+ ///
+ [Parameter(Mandatory = true,
+ Position = 1,
+ ValueFromPipelineByPropertyName = true,
+ ParameterSetName = BySecretNameParameterSet,
+ HelpMessage = "Secret name. Cmdlet constructs the FQDN of a secret from vault name, currently selected environment and secret name.")]
+ [ValidateNotNullOrEmpty]
+ [Alias("SecretName")]
+ public string Name
+ {
+ get;
+ set;
+ }
+
+ #endregion
+
+ public override void ExecuteCmdlet()
+ {
+ try
+ {
+ switch (ParameterSetName)
+ {
+ case BySecretNameParameterSet:
+ var secret = DataServiceClient.GetSecret(VaultName, Name);
+ WriteObject(secret);
+ break;
+
+ case ByVaultNameParameterSet:
+ var secrets = DataServiceClient.GetSecrets(VaultName);
+ WriteObject(secrets, true);
+ break;
+
+ default:
+ throw new ArgumentException(Resources.BadParameterSetName);
+ }
+ }
+ catch (Exception ex)
+ {
+ this.WriteErrorDetails(ex);
+ }
+ }
+ }
+}
diff --git a/src/ResourceManager/KeyVault/Commands.KeyVault/Commands/RemoveAzureKeyVaultKey.cs b/src/ResourceManager/KeyVault/Commands.KeyVault/Commands/RemoveAzureKeyVaultKey.cs
new file mode 100644
index 000000000000..c1f90099fd36
--- /dev/null
+++ b/src/ResourceManager/KeyVault/Commands.KeyVault/Commands/RemoveAzureKeyVaultKey.cs
@@ -0,0 +1,95 @@
+// ----------------------------------------------------------------------------------
+//
+// Copyright Microsoft Corporation
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+// ----------------------------------------------------------------------------------
+
+using System;
+using System.Management.Automation;
+using Microsoft.Azure.Commands.KeyVault.Models;
+using Microsoft.Azure.Commands.KeyVault.Properties;
+
+namespace Microsoft.Azure.Commands.KeyVault.Cmdlets
+{
+ [Cmdlet(VerbsCommon.Remove, "AzureKeyVaultKey",
+ SupportsShouldProcess = true,
+ ConfirmImpact = ConfirmImpact.High)]
+ [OutputType(typeof(KeyBundle))]
+ public class RemoveAzureKeyVaultKey : KeyVaultCmdletBase
+ {
+ #region Input Parameter Definitions
+
+ ///
+ /// Vault name
+ ///
+ [Parameter(Mandatory = true,
+ Position = 0,
+ ValueFromPipelineByPropertyName = true,
+ HelpMessage = "Vault name. Cmdlet constructs the FQDN of a vault based on the name and currently selected environment.")]
+ [ValidateNotNullOrEmpty]
+ public string VaultName
+ {
+ get;
+ set;
+ }
+
+ ///
+ /// key name
+ ///
+ [Parameter(Mandatory = true,
+ Position = 1,
+ ValueFromPipelineByPropertyName = true,
+ HelpMessage = "Key name. Cmdlet constructs the FQDN of a key from vault name, currently selected environment and key name.")]
+ [ValidateNotNullOrEmpty]
+ [Alias("KeyName")]
+ public string Name
+ {
+ get;
+ set;
+ }
+
+ ///
+ /// If present, do not ask for confirmation
+ ///
+ [Parameter(Mandatory = false,
+ HelpMessage = "Do not ask for confirmation.")]
+ public SwitchParameter Force { get; set; }
+
+ [Parameter(Mandatory = false,
+ HelpMessage = "Cmdlet does not return object by default. If this switch is specified, return a bool to enable pipeline.")]
+ public SwitchParameter PassThru { get; set; }
+
+ #endregion
+ public override void ExecuteCmdlet()
+ {
+ try
+ {
+ KeyBundle keyBundle = null;
+ ConfirmOperation(
+ Resources.RemoveKeyWhatIfMessage,
+ Name,
+ Resources.RemoveKeyWarning,
+ Force.IsPresent,
+ () => { keyBundle = DataServiceClient.DeleteKey(VaultName, Name); });
+
+ if (PassThru.IsPresent)
+ {
+ WriteObject(keyBundle);
+ }
+ }
+ catch (Exception ex)
+ {
+ this.WriteErrorDetails(ex);
+ }
+ }
+
+ }
+}
diff --git a/src/ResourceManager/KeyVault/Commands.KeyVault/Commands/RemoveAzureKeyVaultSecret.cs b/src/ResourceManager/KeyVault/Commands.KeyVault/Commands/RemoveAzureKeyVaultSecret.cs
new file mode 100644
index 000000000000..a173bd673073
--- /dev/null
+++ b/src/ResourceManager/KeyVault/Commands.KeyVault/Commands/RemoveAzureKeyVaultSecret.cs
@@ -0,0 +1,95 @@
+// ----------------------------------------------------------------------------------
+//
+// Copyright Microsoft Corporation
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+// ----------------------------------------------------------------------------------
+
+using System;
+using System.Management.Automation;
+using Microsoft.Azure.Commands.KeyVault.Models;
+using Microsoft.Azure.Commands.KeyVault.Properties;
+
+namespace Microsoft.Azure.Commands.KeyVault.Cmdlets
+{
+ [Cmdlet(VerbsCommon.Remove, "AzureKeyVaultSecret",
+ SupportsShouldProcess = true,
+ ConfirmImpact = ConfirmImpact.High)]
+ [OutputType(typeof(Secret))]
+ public class RemoveAzureKeyVaultSecret : KeyVaultCmdletBase
+ {
+ #region Input Parameter Definitions
+
+ ///
+ /// Vault name
+ ///
+ [Parameter(Mandatory = true,
+ Position = 0,
+ ValueFromPipelineByPropertyName = true,
+ HelpMessage = "Vault name. Cmdlet constructs the FQDN of a vault based on the name and currently selected environment.")]
+ [ValidateNotNullOrEmpty]
+ public string VaultName
+ {
+ get;
+ set;
+ }
+
+ ///
+ /// Secret name
+ ///
+ [Parameter(Mandatory = true,
+ Position = 1,
+ ValueFromPipelineByPropertyName = true,
+ HelpMessage = "Secret name. Cmdlet constructs the FQDN of a secret from vault name, currently selected environment and secret name.")]
+ [ValidateNotNullOrEmpty]
+ [Alias("SecretName")]
+ public string Name
+ {
+ get;
+ set;
+ }
+
+ ///
+ /// If present, do not ask for confirmation
+ ///
+ [Parameter(Mandatory = false,
+ HelpMessage = "Do not ask for confirmation.")]
+ public SwitchParameter Force { get; set; }
+
+ [Parameter(Mandatory = false,
+ HelpMessage = "Cmdlet does not return object by default. If this switch is specified, return a bool to enable pipeline.")]
+ public SwitchParameter PassThru { get; set; }
+
+ #endregion
+
+ public override void ExecuteCmdlet()
+ {
+ try
+ {
+ Secret secret = null;
+ ConfirmOperation(
+ Resources.RemoveSecretWhatIfMessage,
+ Name,
+ Resources.RemoveSecretWarning,
+ Force.IsPresent,
+ () => { secret = DataServiceClient.DeleteSecret(VaultName, Name); });
+
+ if (PassThru.IsPresent)
+ {
+ WriteObject(secret);
+ }
+ }
+ catch (Exception ex)
+ {
+ this.WriteErrorDetails(ex);
+ }
+ }
+ }
+}
diff --git a/src/ResourceManager/KeyVault/Commands.KeyVault/Commands/SetAzureKeyVaultKey.cs b/src/ResourceManager/KeyVault/Commands.KeyVault/Commands/SetAzureKeyVaultKey.cs
new file mode 100644
index 000000000000..6ea1ec7a2a74
--- /dev/null
+++ b/src/ResourceManager/KeyVault/Commands.KeyVault/Commands/SetAzureKeyVaultKey.cs
@@ -0,0 +1,118 @@
+// ----------------------------------------------------------------------------------
+//
+// Copyright Microsoft Corporation
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+// ----------------------------------------------------------------------------------
+
+using System;
+using System.Management.Automation;
+using Microsoft.Azure.Commands.KeyVault.Models;
+
+namespace Microsoft.Azure.Commands.KeyVault.Cmdlets
+{
+ ///
+ /// Update attribute of a key vault key.
+ ///
+ [Cmdlet(VerbsCommon.Set, "AzureKeyVaultKey")]
+ [OutputType(typeof(KeyBundle))]
+ public class SetAzureKeyVaultKey : KeyVaultCmdletBase
+ {
+ #region Input Parameter Definitions
+
+ ///
+ /// Vault name
+ ///
+ [Parameter(Mandatory = true,
+ Position = 0,
+ ValueFromPipelineByPropertyName = true,
+ HelpMessage = "Vault name. Cmdlet constructs the FQDN of a vault based on the name and currently selected environment.")]
+ [ValidateNotNullOrEmpty]
+ public string VaultName
+ {
+ get;
+ set;
+ }
+
+ ///
+ /// key name
+ ///
+ [Parameter(Mandatory = true,
+ Position = 1,
+ ValueFromPipelineByPropertyName = true,
+ HelpMessage = "Key name. Cmdlet constructs the FQDN of a key from vault name, currently selected environment and key name.")]
+ [ValidateNotNullOrEmpty]
+ [Alias("KeyName")]
+ public string Name
+ {
+ get;
+ set;
+ }
+
+ ///
+ /// If present, enable a key if value is true.
+ /// Disable a key if value is false.
+ /// If not present, no change on current key enabled/disabled state.
+ ///
+ [Parameter(Mandatory = false,
+ HelpMessage = "If present, enable a key if value is true. Disable a key if value is false. If not present, no change on current key enabled/disabled state.")]
+ public bool? Enable
+ {
+ get;
+ set;
+ }
+
+ ///
+ /// Key expires time in UTC time
+ ///
+ [Parameter(Mandatory = false,
+ ValueFromPipelineByPropertyName = true,
+ HelpMessage = "The expiration time of a key in UTC time. If not present, key will not expire.")]
+ public DateTime? Expires
+ {
+ get;
+ set;
+ }
+
+ ///
+ /// The UTC time before which key can't be used
+ ///
+ [Parameter(Mandatory = false,
+ ValueFromPipelineByPropertyName = true,
+ HelpMessage = "The UTC time before which key can't be used. If not present, no limitation.")]
+ public DateTime? NotBefore
+ {
+ get;
+ set;
+ }
+
+
+ #endregion
+
+ public override void ExecuteCmdlet()
+ {
+ try
+ {
+ KeyAttributes attributes = new KeyAttributes
+ {
+ Enabled = this.Enable,
+ Expires = this.Expires,
+ NotBefore = this.NotBefore
+ };
+
+ WriteObject(DataServiceClient.SetKey(VaultName, Name, attributes));
+ }
+ catch (Exception ex)
+ {
+ this.WriteErrorDetails(ex);
+ }
+ }
+ }
+}
diff --git a/src/ResourceManager/KeyVault/Commands.KeyVault/Commands/SetAzureKeyVaultSecret.cs b/src/ResourceManager/KeyVault/Commands.KeyVault/Commands/SetAzureKeyVaultSecret.cs
new file mode 100644
index 000000000000..048e1b2ba3c7
--- /dev/null
+++ b/src/ResourceManager/KeyVault/Commands.KeyVault/Commands/SetAzureKeyVaultSecret.cs
@@ -0,0 +1,84 @@
+// ----------------------------------------------------------------------------------
+//
+// Copyright Microsoft Corporation
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+// ----------------------------------------------------------------------------------
+
+using System;
+using System.Security;
+using System.Management.Automation;
+using Microsoft.Azure.Commands.KeyVault.Models;
+
+namespace Microsoft.Azure.Commands.KeyVault.Cmdlets
+{
+ [Cmdlet(VerbsCommon.Set, "AzureKeyVaultSecret")]
+ [OutputType(typeof(Secret))]
+ public class SetAzureKeyVaultSecret : KeyVaultCmdletBase
+ {
+ #region Input Parameter Definitions
+
+ ///
+ /// Vault name
+ ///
+ [Parameter(Mandatory = true,
+ Position = 0,
+ ValueFromPipelineByPropertyName = true,
+ HelpMessage = "Vault name. Cmdlet constructs the FQDN of a vault based on the name and currently selected environment.")]
+ [ValidateNotNullOrEmpty]
+ public string VaultName
+ {
+ get;
+ set;
+ }
+
+ ///
+ /// Secret name
+ ///
+ [Parameter(Mandatory = true,
+ Position = 1,
+ ValueFromPipelineByPropertyName = true,
+ HelpMessage = "Secret name. Cmdlet constructs the FQDN of a secret from vault name, currently selected environment and secret name.")]
+ [ValidateNotNullOrEmpty]
+ [Alias("SecretName")]
+ public string Name
+ {
+ get;
+ set;
+ }
+
+ ///
+ /// Secret value
+ ///
+ [Parameter(Mandatory = true,
+ Position = 2,
+ HelpMessage = "Secret value")]
+ public SecureString SecretValue
+ {
+ get;
+ set;
+ }
+
+ #endregion
+
+ public override void ExecuteCmdlet()
+ {
+ try
+ {
+ var secret = DataServiceClient.SetSecret(VaultName, Name, SecretValue);
+ WriteObject(secret);
+ }
+ catch (Exception ex)
+ {
+ this.WriteErrorDetails(ex);
+ }
+ }
+ }
+}
diff --git a/src/ResourceManager/KeyVault/Commands.KeyVault/MSSharedLibKey.snk b/src/ResourceManager/KeyVault/Commands.KeyVault/MSSharedLibKey.snk
new file mode 100644
index 000000000000..695f1b38774e
Binary files /dev/null and b/src/ResourceManager/KeyVault/Commands.KeyVault/MSSharedLibKey.snk differ
diff --git a/src/ResourceManager/KeyVault/Commands.KeyVault/Microsoft.Azure.Commands.KeyVault.format.ps1xml b/src/ResourceManager/KeyVault/Commands.KeyVault/Microsoft.Azure.Commands.KeyVault.format.ps1xml
new file mode 100644
index 000000000000..f7f8539950d9
--- /dev/null
+++ b/src/ResourceManager/KeyVault/Commands.KeyVault/Microsoft.Azure.Commands.KeyVault.format.ps1xml
@@ -0,0 +1,107 @@
+
+
+
+
+ Microsoft.Azure.Commands.KeyVault.Models.KeyBundle
+
+ Microsoft.Azure.Commands.KeyVault.Models.KeyBundle
+
+
+
+
+
+ Left
+
+
+
+ Left
+
+
+
+ Left
+
+
+
+ Left
+
+
+
+ Left
+
+
+
+ Left
+
+
+
+
+
+
+ VaultName
+
+
+ KeyName
+
+
+ $_.Attributes.KeyType
+
+
+ $_.Attributes.Enabled
+
+
+ Attributes
+
+
+ Key
+
+
+
+
+
+
+
+ Microsoft.Azure.Commands.KeyVault.Models.Secret
+
+ Microsoft.Azure.Commands.KeyVault.Models.Secret
+
+
+
+
+
+ Left
+
+
+
+ Left
+
+
+
+ Left
+
+
+
+ Left
+
+
+
+
+
+
+ VaultName
+
+
+ SecretName
+
+
+ SecretValueText
+
+
+ SecretValue
+
+
+
+
+
+
+
+
diff --git a/src/ResourceManager/KeyVault/Commands.KeyVault/Models/ByokWebKeyConverter.cs b/src/ResourceManager/KeyVault/Commands.KeyVault/Models/ByokWebKeyConverter.cs
new file mode 100644
index 000000000000..cc81b09dbc28
--- /dev/null
+++ b/src/ResourceManager/KeyVault/Commands.KeyVault/Models/ByokWebKeyConverter.cs
@@ -0,0 +1,79 @@
+// ----------------------------------------------------------------------------------
+//
+// Copyright Microsoft Corporation
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+// ----------------------------------------------------------------------------------
+
+using System;
+using System.Security;
+using System.IO;
+using Microsoft.Azure.Commands.KeyVault.Properties;
+using Microsoft.KeyVault.WebKey;
+
+namespace Microsoft.Azure.Commands.KeyVault.Models
+{
+ ///
+ /// Utility class that creates web key from a BYOK file
+ ///
+ internal class ByokWebKeyConverter : IWebKeyConverter
+ {
+ public ByokWebKeyConverter(IWebKeyConverter next=null)
+ {
+ this.next = next;
+ }
+
+ public JsonWebKey ConvertKeyFromFile(FileInfo fileInfo, SecureString password)
+ {
+ if (CanProcess(fileInfo))
+ {
+ return Convert(fileInfo.FullName);
+ }
+ else if (next != null)
+ {
+ return next.ConvertKeyFromFile(fileInfo, password);
+ }
+ else
+ {
+ throw new ArgumentException(string.Format(Resources.UnsupportedFileFormat, fileInfo.Name));
+ }
+ }
+
+ private bool CanProcess(FileInfo fileInfo)
+ {
+ if (fileInfo == null || string.IsNullOrEmpty(fileInfo.Extension))
+ {
+ return false;
+ }
+
+ return ByokFileExtension.Equals(fileInfo.Extension, StringComparison.OrdinalIgnoreCase);
+ }
+
+ private JsonWebKey Convert(string byokFileName)
+ {
+ byte[] byokBlob = File.ReadAllBytes(byokFileName);
+
+ if (byokBlob == null || byokBlob.Length == 0)
+ {
+ throw new ArgumentException(string.Format(Resources.InvalidKeyBlob, "BYOK"));
+ }
+
+ return new JsonWebKey()
+ {
+ Kty = JsonWebKeyType.RsaHsm,
+ T = byokBlob,
+ };
+ }
+
+ private IWebKeyConverter next;
+ private const string ByokFileExtension = ".byok";
+
+ }
+}
diff --git a/src/ResourceManager/KeyVault/Commands.KeyVault/Models/DataServiceCredential.cs b/src/ResourceManager/KeyVault/Commands.KeyVault/Models/DataServiceCredential.cs
new file mode 100644
index 000000000000..cfffc891f9bd
--- /dev/null
+++ b/src/ResourceManager/KeyVault/Commands.KeyVault/Models/DataServiceCredential.cs
@@ -0,0 +1,103 @@
+// ----------------------------------------------------------------------------------
+//
+// Copyright Microsoft Corporation
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+// ----------------------------------------------------------------------------------
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using Microsoft.WindowsAzure.Commands.Common;
+using Microsoft.WindowsAzure.Commands.Common.Models;
+using Microsoft.WindowsAzure.Commands.Utilities.Common.Authentication;
+using Microsoft.Azure.Commands.KeyVault.Properties;
+
+namespace Microsoft.Azure.Commands.KeyVault.Models
+{
+ internal class DataServiceCredential
+ {
+ public DataServiceCredential(IAuthenticationFactory authFactory, AzureContext context)
+ {
+ if (authFactory == null)
+ {
+ throw new ArgumentNullException("authFactory");
+ }
+ if (context == null)
+ {
+ throw new ArgumentNullException("context");
+ }
+
+ var bundle = GetToken(authFactory, context);
+ this.token = bundle.Item1;
+ this.resourceId = bundle.Item2;
+ }
+
+ ///
+ /// Authentication callback method required by KeyVaultClient
+ ///
+ ///
+ ///
+ ///
+ ///
+ public string OnAuthentication(string authority, string resource, string scope)
+ {
+ // TODO: Add trace to log tokenType, resource, authority, scope etc
+ string tokenStr = string.Empty;
+ this.token.AuthorizeRequest((tokenType, tokenValue) =>
+ {
+ tokenStr = tokenValue;
+ });
+
+ return tokenStr;
+ }
+
+ private Tuple GetToken(IAuthenticationFactory authFactory, AzureContext context)
+ {
+ if (context.Subscription == null)
+ {
+ throw new ArgumentException(Resources.InvalidCurrentSubscription);
+ }
+ if (context.Account == null)
+ {
+ throw new ArgumentException(Resources.InvalidSubscriptionState);
+ }
+ if (context.Account.Type != AzureAccount.AccountType.User)
+ {
+ throw new ArgumentException(string.Format(Resources.UnsupportedAccountType, context.Account.Type));
+ }
+
+ var tenant = context.Subscription.GetPropertyAsArray(AzureSubscription.Property.Tenants)
+ .Intersect(context.Account.GetPropertyAsArray(AzureAccount.Property.Tenants))
+ .FirstOrDefault();
+ if (tenant == null)
+ {
+ throw new ArgumentException(Resources.InvalidSubscriptionState);
+ }
+
+ try
+ {
+ var accesstoken = authFactory.Authenticate(context.Account, context.Environment, tenant, null, ShowDialog.Auto,
+ ResourceIdEndpoint);
+
+ return Tuple.Create(accesstoken, context.Environment.Endpoints[ResourceIdEndpoint]);
+ }
+ catch (Exception ex)
+ {
+ throw new ArgumentException(Resources.InvalidSubscriptionState, ex);
+ }
+ }
+
+ private IAccessToken token;
+ private string resourceId;
+
+ private const AzureEnvironment.Endpoint ResourceIdEndpoint = AzureEnvironment.Endpoint.AzureKeyVaultServiceEndpointResourceId;
+ }
+}
diff --git a/src/ResourceManager/KeyVault/Commands.KeyVault/Models/IKeyVaultDataServiceClient.cs b/src/ResourceManager/KeyVault/Commands.KeyVault/Models/IKeyVaultDataServiceClient.cs
new file mode 100644
index 000000000000..441cdc3312b9
--- /dev/null
+++ b/src/ResourceManager/KeyVault/Commands.KeyVault/Models/IKeyVaultDataServiceClient.cs
@@ -0,0 +1,43 @@
+// ----------------------------------------------------------------------------------
+//
+// Copyright Microsoft Corporation
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+// ----------------------------------------------------------------------------------
+
+using Microsoft.KeyVault.WebKey;
+using System.Collections.Generic;
+using System.Security;
+
+namespace Microsoft.Azure.Commands.KeyVault.Models
+{
+ public interface IKeyVaultDataServiceClient
+ {
+ KeyBundle CreateKey(string vaultName, string keyName, KeyCreationAttributes keyAttributes);
+
+ KeyBundle ImportKey(string vaultName, string keyName, KeyCreationAttributes keyAttributes, JsonWebKey webKey);
+
+ KeyBundle SetKey(string vaultName, string keyName, KeyAttributes keyAttributes);
+
+ KeyBundle GetKey(string vaultName, string keyName);
+
+ IEnumerable GetKeys(string vaultName);
+
+ KeyBundle DeleteKey(string vaultName, string keyName);
+
+ Secret SetSecret(string vaultName, string secretName, SecureString secretValue);
+
+ Secret GetSecret(string vaultName, string secretName);
+
+ IEnumerable GetSecrets(string vaultName);
+
+ Secret DeleteSecret(string vaultName, string secretName);
+ }
+}
diff --git a/src/ResourceManager/KeyVault/Commands.KeyVault/Models/IWebKeyConverter.cs b/src/ResourceManager/KeyVault/Commands.KeyVault/Models/IWebKeyConverter.cs
new file mode 100644
index 000000000000..ee11e701226d
--- /dev/null
+++ b/src/ResourceManager/KeyVault/Commands.KeyVault/Models/IWebKeyConverter.cs
@@ -0,0 +1,26 @@
+// ----------------------------------------------------------------------------------
+//
+// Copyright Microsoft Corporation
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+// ----------------------------------------------------------------------------------
+
+using System;
+using System.IO;
+using System.Security;
+using Microsoft.KeyVault.WebKey;
+
+namespace Microsoft.Azure.Commands.KeyVault.Models
+{
+ internal interface IWebKeyConverter
+ {
+ JsonWebKey ConvertKeyFromFile(FileInfo fileInfo, SecureString password);
+ }
+}
diff --git a/src/ResourceManager/KeyVault/Commands.KeyVault/Models/KeyAttributes.cs b/src/ResourceManager/KeyVault/Commands.KeyVault/Models/KeyAttributes.cs
new file mode 100644
index 000000000000..d8265103a3e1
--- /dev/null
+++ b/src/ResourceManager/KeyVault/Commands.KeyVault/Models/KeyAttributes.cs
@@ -0,0 +1,93 @@
+// ----------------------------------------------------------------------------------
+//
+// Copyright Microsoft Corporation
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+// ----------------------------------------------------------------------------------
+
+using System;
+using System.Collections.ObjectModel;
+using Client = Microsoft.KeyVault.Client;
+
+namespace Microsoft.Azure.Commands.KeyVault.Models
+{
+ public class KeyAttributes
+ {
+ public KeyAttributes()
+ { }
+
+ internal KeyAttributes(bool? enabled, DateTime? expires, DateTime? notBefore, string keyType, string[] keyOps)
+ {
+ this.Enabled = enabled;
+ this.Expires = expires;
+ this.NotBefore = notBefore;
+ this.KeyType = keyType;
+ this.KeyOps = keyOps;
+ }
+
+ internal KeyAttributes(bool? enabled, int? expires, int? notBefore, string keyType, string[] keyOps) :
+ this(enabled, FromUnixTime(expires), FromUnixTime(notBefore), keyType, keyOps)
+ { }
+
+ public bool? Enabled { get; set; }
+
+ public DateTime? Expires { get; set; }
+
+ public DateTime? NotBefore { get; set; }
+
+ public string KeyType { get; private set; }
+
+ public string[] KeyOps { get; set; }
+
+ public static explicit operator Client.KeyAttributes(KeyAttributes attr)
+ {
+ return new Client.KeyAttributes()
+ {
+ Enabled = attr.Enabled,
+ NotBefore = attr.NotBeforeUnixTime,
+ Expires = attr.ExpiresUnixTime
+ };
+ }
+
+ internal int? ExpiresUnixTime
+ {
+ get
+ {
+ return ToUnixTime(this.Expires);
+ }
+ }
+
+ internal int? NotBeforeUnixTime
+ {
+ get
+ {
+ return ToUnixTime(this.NotBefore);
+ }
+ }
+
+ private static int? ToUnixTime(DateTime? utcTime)
+ {
+ if (!utcTime.HasValue)
+ {
+ return null;
+ }
+ return Client.UnixEpoch.ToUnixTime(utcTime.Value);
+ }
+
+ private static DateTime? FromUnixTime(int? utcTime)
+ {
+ if (!utcTime.HasValue)
+ {
+ return null;
+ }
+ return Client.UnixEpoch.FromUnixTime(utcTime.Value);
+ }
+ }
+}
diff --git a/src/ResourceManager/KeyVault/Commands.KeyVault/Models/KeyBundle.cs b/src/ResourceManager/KeyVault/Commands.KeyVault/Models/KeyBundle.cs
new file mode 100644
index 000000000000..969786d79e8a
--- /dev/null
+++ b/src/ResourceManager/KeyVault/Commands.KeyVault/Models/KeyBundle.cs
@@ -0,0 +1,64 @@
+// ----------------------------------------------------------------------------------
+//
+// Copyright Microsoft Corporation
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+// ----------------------------------------------------------------------------------
+
+using System;
+using Microsoft.KeyVault.WebKey;
+using Client = Microsoft.KeyVault.Client;
+using Microsoft.Azure.Commands.KeyVault.Properties;
+
+namespace Microsoft.Azure.Commands.KeyVault.Models
+{
+ public class KeyBundle
+ {
+ public KeyBundle()
+ { }
+
+ internal KeyBundle(Client.KeyBundle clientKeyBundle, VaultUriHelper vaultUriHelper)
+ {
+ if (vaultUriHelper == null)
+ {
+ throw new ArgumentNullException("vaultUriHelper");
+ }
+ if (clientKeyBundle == null)
+ {
+ throw new ArgumentNullException("clientKeyBundle");
+ }
+ if (clientKeyBundle.Key == null || clientKeyBundle.Attributes == null)
+ {
+ throw new ArgumentException(Resources.InvalidKeyBundle);
+ }
+
+ VaultName = vaultUriHelper.GetVaultName(clientKeyBundle.Key.Kid);
+ KeyName = vaultUriHelper.GetKeyName(clientKeyBundle.Key.Kid);
+ Key = clientKeyBundle.Key;
+ Attributes = new KeyAttributes(
+ clientKeyBundle.Attributes.Enabled,
+ clientKeyBundle.Attributes.Expires,
+ clientKeyBundle.Attributes.NotBefore,
+ clientKeyBundle.Key.Kty,
+ clientKeyBundle.Key.KeyOps);
+
+ // TODO: trace vaultUriHelper.KeyVaultDnsSuffix;
+ }
+
+ public string VaultName { get; set; }
+
+ public string KeyName { get; set; }
+
+ public KeyAttributes Attributes { get; set; }
+
+ public JsonWebKey Key { get; set; }
+
+ }
+}
diff --git a/src/ResourceManager/KeyVault/Commands.KeyVault/Models/KeyCreationAttributes.cs b/src/ResourceManager/KeyVault/Commands.KeyVault/Models/KeyCreationAttributes.cs
new file mode 100644
index 000000000000..0d0af8d1fa82
--- /dev/null
+++ b/src/ResourceManager/KeyVault/Commands.KeyVault/Models/KeyCreationAttributes.cs
@@ -0,0 +1,30 @@
+// ----------------------------------------------------------------------------------
+//
+// Copyright Microsoft Corporation
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+// ----------------------------------------------------------------------------------
+
+using System;
+using System.Collections.ObjectModel;
+
+namespace Microsoft.Azure.Commands.KeyVault.Models
+{
+ public class KeyCreationAttributes : KeyAttributes
+ {
+ public KeyCreationAttributes(bool? enabled, DateTime? expires, DateTime? notBefore, bool? hsm, string[] keyOps) :
+ base(enabled, expires, notBefore, null, keyOps)
+ {
+ this.Hsm = hsm;
+ }
+
+ public bool? Hsm { get; private set; }
+ }
+}
diff --git a/src/ResourceManager/KeyVault/Commands.KeyVault/Models/KeyVaultCmdletBase.cs b/src/ResourceManager/KeyVault/Commands.KeyVault/Models/KeyVaultCmdletBase.cs
new file mode 100644
index 000000000000..f57f9b34eb23
--- /dev/null
+++ b/src/ResourceManager/KeyVault/Commands.KeyVault/Models/KeyVaultCmdletBase.cs
@@ -0,0 +1,67 @@
+// ----------------------------------------------------------------------------------
+//
+// Copyright Microsoft Corporation
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+// ----------------------------------------------------------------------------------
+
+using System;
+using System.Net;
+using System.Net.Http;
+using Microsoft.WindowsAzure.Commands.Utilities.Common;
+using Microsoft.WindowsAzure.Commands.Common;
+
+namespace Microsoft.Azure.Commands.KeyVault.Models
+{
+ public class KeyVaultCmdletBase : AzurePSCmdlet
+ {
+ public KeyVaultCmdletBase()
+ {
+ }
+ protected void WriteErrorDetails(Exception exception)
+ {
+ // Call the handler to parse and get ErrorRecord
+ WriteError(KeyVaultExceptionHandler.RetrieveExceptionDetails(exception));
+ }
+ internal IKeyVaultDataServiceClient DataServiceClient
+ {
+ get
+ {
+ if (dataServiceClient == null)
+ {
+ this.dataServiceClient = new KeyVaultDataServiceClient(
+ AzureSession.AuthenticationFactory,
+ AzureSession.CurrentContext,
+ // TODO: determine HttpClient creation model after fully understand testing framework
+ new HttpClient());
+ }
+
+ return this.dataServiceClient;
+ }
+ set
+ {
+ this.dataServiceClient = value;
+ }
+ }
+
+ protected void ConfirmOperation(string whatIfMessage, string target, string warningMessage, bool force, Action action)
+ {
+ if (ShouldProcess(target, whatIfMessage))
+ {
+ if (force || ShouldContinue(string.Format(warningMessage, target),""))
+ {
+ action();
+ }
+ }
+ }
+
+ private IKeyVaultDataServiceClient dataServiceClient;
+ }
+}
diff --git a/src/ResourceManager/KeyVault/Commands.KeyVault/Models/KeyVaultDataServiceClient.cs b/src/ResourceManager/KeyVault/Commands.KeyVault/Models/KeyVaultDataServiceClient.cs
new file mode 100644
index 000000000000..d0575b7bbfa9
--- /dev/null
+++ b/src/ResourceManager/KeyVault/Commands.KeyVault/Models/KeyVaultDataServiceClient.cs
@@ -0,0 +1,305 @@
+// ----------------------------------------------------------------------------------
+//
+// Copyright Microsoft Corporation
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+// ----------------------------------------------------------------------------------
+
+using System;
+using System.Text;
+using System.Net.Http;
+using System.Security;
+using System.Collections.Generic;
+using System.Threading.Tasks;
+using System.Linq;
+using Microsoft.WindowsAzure;
+using Microsoft.WindowsAzure.Common.Internals;
+using Microsoft.WindowsAzure.Commands.Common;
+using Microsoft.WindowsAzure.Commands.Common.Models;
+using Microsoft.WindowsAzure.Commands.Utilities.Common.Authentication;
+using Microsoft.Azure.Commands.KeyVault.Properties;
+using Client = Microsoft.KeyVault.Client;
+using Microsoft.KeyVault.WebKey;
+
+namespace Microsoft.Azure.Commands.KeyVault.Models
+{
+ internal class KeyVaultDataServiceClient : IKeyVaultDataServiceClient
+ {
+ public KeyVaultDataServiceClient(IAuthenticationFactory authFactory, AzureContext context, HttpClient httpClient)
+ {
+ if (authFactory == null)
+ {
+ throw new ArgumentNullException("authFactory");
+ }
+ if (context == null)
+ {
+ throw new ArgumentNullException("context");
+ }
+ if (context.Environment == null)
+ {
+ throw new ArgumentException(Resources.InvalidAzureEnvironment);
+ }
+ if (httpClient == null)
+ {
+ throw new ArgumentNullException("httpClient");
+ }
+
+ var credential = new DataServiceCredential(authFactory, context);
+ this.keyVaultClient = new Client.KeyVaultClient(
+ credential.OnAuthentication,
+ SendRequestCallback,
+ ReceiveResponseCallback,
+ httpClient);
+
+
+ this.vaultUriHelper = new VaultUriHelper(
+ context.Environment.Endpoints[AzureEnvironment.Endpoint.AzureKeyVaultDnsSuffix]);
+ }
+
+ ///
+ /// Parameterless constructor for Mocking.
+ ///
+ public KeyVaultDataServiceClient()
+ {
+ }
+
+ public KeyBundle CreateKey(string vaultName, string keyName, KeyCreationAttributes keyAttributes)
+ {
+ if (string.IsNullOrEmpty(vaultName))
+ {
+ throw new ArgumentNullException("vaultName");
+ }
+ if (string.IsNullOrEmpty(keyName))
+ {
+ throw new ArgumentNullException("keyName");
+ }
+ if (keyAttributes == null)
+ {
+ throw new ArgumentNullException("keyAttributes");
+ }
+
+ string vaultAddress = this.vaultUriHelper.CreateVaultAddress(vaultName);
+ Client.KeyAttributes clientAttributes = (Client.KeyAttributes)keyAttributes;
+ clientAttributes.Hsm = keyAttributes.Hsm;
+ string keyType = JsonWebKeyType.Rsa;
+ if (keyAttributes.Hsm.HasValue && keyAttributes.Hsm.Value)
+ {
+ keyType = JsonWebKeyType.RsaHsm;
+ }
+
+ Client.KeyBundle clientKeyBundle = this.keyVaultClient.CreateKeyAsync(
+ vaultAddress, keyName, keyType, keyAttributes.KeyOps, clientAttributes).GetAwaiter().GetResult();
+
+ return new KeyBundle(clientKeyBundle, this.vaultUriHelper);
+ }
+
+ public KeyBundle ImportKey(string vaultName, string keyName, KeyCreationAttributes keyAttributes, JsonWebKey webKey)
+ {
+ if (string.IsNullOrEmpty(vaultName))
+ {
+ throw new ArgumentNullException("vaultName");
+ }
+ if (string.IsNullOrEmpty(keyName))
+ {
+ throw new ArgumentNullException("keyName");
+ }
+ if (keyAttributes == null)
+ {
+ throw new ArgumentNullException("keyAttributes");
+ }
+ if (webKey == null)
+ {
+ throw new ArgumentNullException("webKey");
+ }
+ if (keyAttributes.Hsm.HasValue && !keyAttributes.Hsm.Value &&
+ JsonWebKeyType.RsaHsm.Equals(webKey.Kty))
+ {
+ // Importing HSMRSA key blob as RSA key is not allowed
+ throw new ArgumentException(Resources.InvalidKeyDestination);
+ }
+
+ string vaultAddress = this.vaultUriHelper.CreateVaultAddress(vaultName);
+ Client.KeyAttributes clientAttributes = (Client.KeyAttributes)keyAttributes;
+ clientAttributes.Hsm = keyAttributes.Hsm;
+ webKey.KeyOps = keyAttributes.KeyOps;
+ Client.KeyBundle clientKeyBundle = new Client.KeyBundle()
+ {
+ Attributes = clientAttributes,
+ Key = webKey
+ };
+
+ clientKeyBundle = this.keyVaultClient.ImportKeyAsync(vaultAddress, keyName, clientKeyBundle).GetAwaiter().GetResult();
+
+ return new KeyBundle(clientKeyBundle, this.vaultUriHelper);
+ }
+
+ public KeyBundle SetKey(string vaultName, string keyName, KeyAttributes keyAttributes)
+ {
+ if (string.IsNullOrEmpty(vaultName))
+ {
+ throw new ArgumentNullException("vaultName");
+ }
+ if (string.IsNullOrEmpty(keyName))
+ {
+ throw new ArgumentNullException("keyName");
+ }
+ if (keyAttributes == null)
+ {
+ throw new ArgumentNullException("keyAttributes");
+ }
+
+ string keyId = this.vaultUriHelper.CreateKeyAddress(vaultName, keyName);
+ Client.KeyAttributes clientAttributes = (Client.KeyAttributes)keyAttributes;
+
+ var clientKeyBundle = this.keyVaultClient.UpdateKeyAsync(keyId, clientAttributes).GetAwaiter().GetResult();
+
+ return new KeyBundle(clientKeyBundle, this.vaultUriHelper);
+ }
+ public KeyBundle GetKey(string vaultName, string keyName)
+ {
+ if (string.IsNullOrEmpty(vaultName))
+ {
+ throw new ArgumentNullException("vaultName");
+ }
+ if (string.IsNullOrEmpty(keyName))
+ {
+ throw new ArgumentNullException("keyName");
+ }
+
+ string keyId = this.vaultUriHelper.CreateKeyAddress(vaultName, keyName);
+
+ Client.KeyBundle clientKeyBundle = this.keyVaultClient.GetKeyAsync(keyId).GetAwaiter().GetResult();
+
+ return new KeyBundle(clientKeyBundle, this.vaultUriHelper);
+ }
+
+ public IEnumerable GetKeys(string vaultName)
+ {
+ if (string.IsNullOrEmpty(vaultName))
+ {
+ throw new ArgumentNullException("vaultName");
+ }
+
+ string vaultAddress = this.vaultUriHelper.CreateVaultAddress(vaultName);
+
+ return (this.keyVaultClient.GetKeysAsync(vaultAddress).GetAwaiter().GetResult()).
+ Select( (bundle) => {return new KeyBundle(bundle, this.vaultUriHelper);} );
+ }
+
+ public KeyBundle DeleteKey(string vaultName, string keyName)
+ {
+ if (string.IsNullOrEmpty(vaultName))
+ {
+ throw new ArgumentNullException("vaultName");
+ }
+ if (string.IsNullOrEmpty(keyName))
+ {
+ throw new ArgumentNullException("keyName");
+ }
+
+ string keyId = this.vaultUriHelper.CreateKeyAddress(vaultName, keyName);
+
+ Client.KeyBundle clientKeyBundle = this.keyVaultClient.DeleteKeyAsync(keyId).GetAwaiter().GetResult();
+
+ return new KeyBundle(clientKeyBundle, this.vaultUriHelper);
+ }
+
+ public Secret SetSecret(string vaultName, string secretName, SecureString secretValue)
+ {
+ if (string.IsNullOrEmpty(vaultName))
+ {
+ throw new ArgumentNullException("vaultName");
+ }
+ if (string.IsNullOrEmpty(secretName))
+ {
+ throw new ArgumentNullException("secretName");
+ }
+ if (secretValue == null)
+ {
+ throw new ArgumentNullException("secretValue");
+ }
+
+ string vaultAddress = this.vaultUriHelper.CreateVaultAddress(vaultName);
+ string plainSecretValue = secretValue.ToStringExt();
+
+ Client.Secret clientSecret = this.keyVaultClient.SetSecretAsync(vaultAddress, secretName, plainSecretValue).GetAwaiter().GetResult();
+
+ return new Secret(clientSecret, this.vaultUriHelper);
+ }
+
+ public Secret GetSecret(string vaultName, string secretName)
+ {
+ if (string.IsNullOrEmpty(vaultName))
+ {
+ throw new ArgumentNullException("vaultName");
+ }
+ if (string.IsNullOrEmpty(secretName))
+ {
+ throw new ArgumentNullException("secretName");
+ }
+
+ string secretAddress = this.vaultUriHelper.CreateSecretAddress(vaultName, secretName);
+
+ Client.Secret clientSecret = this.keyVaultClient.GetSecretAsync(secretAddress).GetAwaiter().GetResult();
+
+ return new Secret(clientSecret, this.vaultUriHelper);
+ }
+
+ public IEnumerable GetSecrets(string vaultName)
+ {
+ if (string.IsNullOrEmpty(vaultName))
+ {
+ throw new ArgumentNullException("vaultName");
+ }
+
+ string vaultAddress = this.vaultUriHelper.CreateVaultAddress(vaultName);
+
+ return (this.keyVaultClient.GetSecretsAsync(vaultAddress).GetAwaiter().GetResult()).
+ Select((clientSecret) => { return new Secret(clientSecret, this.vaultUriHelper); });
+ }
+
+ public Secret DeleteSecret(string vaultName, string secretName)
+ {
+ if (string.IsNullOrEmpty(vaultName))
+ {
+ throw new ArgumentNullException("vaultName");
+ }
+ if (string.IsNullOrEmpty(secretName))
+ {
+ throw new ArgumentNullException("secretName");
+ }
+
+ string secretAddress = this.vaultUriHelper.CreateSecretAddress(vaultName, secretName);
+
+ Client.Secret clientSecret = this.keyVaultClient.DeleteSecretAsync(secretAddress).GetAwaiter().GetResult();
+
+ return new Secret(clientSecret, this.vaultUriHelper);
+ }
+
+ private void SendRequestCallback(string correlationId, HttpRequestMessage request)
+ {
+ if (CloudContext.Configuration.Tracing.IsEnabled)
+ {
+ Tracing.SendRequest(correlationId, request);
+ }
+ }
+
+ private void ReceiveResponseCallback(string correlationId, HttpResponseMessage response)
+ {
+ if (CloudContext.Configuration.Tracing.IsEnabled)
+ {
+ Tracing.ReceiveResponse(correlationId, response);
+ }
+ }
+
+ private VaultUriHelper vaultUriHelper;
+ private Client.KeyVaultClient keyVaultClient;
+ }
+}
diff --git a/src/ResourceManager/KeyVault/Commands.KeyVault/Models/KeyVaultExceptionHandler.cs b/src/ResourceManager/KeyVault/Commands.KeyVault/Models/KeyVaultExceptionHandler.cs
new file mode 100644
index 000000000000..ecfa8db30bb4
--- /dev/null
+++ b/src/ResourceManager/KeyVault/Commands.KeyVault/Models/KeyVaultExceptionHandler.cs
@@ -0,0 +1,46 @@
+// ----------------------------------------------------------------------------------
+//
+// Copyright Microsoft Corporation
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+// ----------------------------------------------------------------------------------
+
+using System;
+using System.Management.Automation;
+
+namespace Microsoft.Azure.Commands.KeyVault.Models
+{
+ internal static class KeyVaultExceptionHandler
+ {
+ ///
+ /// TODO: refine exception
+ ///
+ /// exception to be processed
+ ///
+ public static ErrorRecord RetrieveExceptionDetails(Exception exception)
+ {
+ if (exception == null)
+ {
+ throw new ArgumentNullException("exception");
+ }
+ ErrorRecord errorRecord = null;
+
+ Exception innerException = exception.InnerException;
+ while (innerException != null)
+ {
+ exception = innerException;
+ innerException = innerException.InnerException;
+ }
+
+ errorRecord = new ErrorRecord(exception, string.Empty, ErrorCategory.NotSpecified, null);
+ return errorRecord;
+ }
+ }
+}
diff --git a/src/ResourceManager/KeyVault/Commands.KeyVault/Models/PfxWebKeyConverter.cs b/src/ResourceManager/KeyVault/Commands.KeyVault/Models/PfxWebKeyConverter.cs
new file mode 100644
index 000000000000..ace802873326
--- /dev/null
+++ b/src/ResourceManager/KeyVault/Commands.KeyVault/Models/PfxWebKeyConverter.cs
@@ -0,0 +1,82 @@
+// ----------------------------------------------------------------------------------
+//
+// Copyright Microsoft Corporation
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+// ----------------------------------------------------------------------------------
+
+using System;
+using System.Security;
+using System.IO;
+using System.Security.Cryptography;
+using System.Security.Cryptography.X509Certificates;
+using Microsoft.Azure.Commands.KeyVault.Properties;
+using Microsoft.KeyVault.WebKey;
+
+namespace Microsoft.Azure.Commands.KeyVault.Models
+{
+ internal class PfxWebKeyConverter : IWebKeyConverter
+ {
+ public PfxWebKeyConverter(IWebKeyConverter next = null)
+ {
+ this.next = next;
+ }
+
+ public JsonWebKey ConvertKeyFromFile(FileInfo fileInfo, SecureString password)
+ {
+ if (CanProcess(fileInfo, password))
+ {
+ return Convert(fileInfo.FullName, password);
+ }
+ else if (next != null)
+ {
+ return next.ConvertKeyFromFile(fileInfo, password);
+ }
+ else
+ {
+ throw new ArgumentException(string.Format(Resources.UnsupportedFileFormat, fileInfo.Name));
+ }
+ }
+
+ private bool CanProcess(FileInfo fileInfo, SecureString password)
+ {
+ if (fileInfo == null ||
+ string.IsNullOrEmpty(fileInfo.Extension) ||
+ password == null)
+ {
+ return false;
+ }
+
+ return PfxFileExtension.Equals(fileInfo.Extension, StringComparison.OrdinalIgnoreCase);
+ }
+
+ private JsonWebKey Convert(string pfxFileName, SecureString pfxPassword)
+ {
+ var certificate = new X509Certificate2(pfxFileName, pfxPassword, X509KeyStorageFlags.Exportable);
+
+ if (!certificate.HasPrivateKey)
+ {
+ throw new ArgumentException(string.Format(Resources.InvalidKeyBlob, "pfx"));
+ }
+
+ var key = certificate.PrivateKey as RSA;
+
+ if (key == null)
+ {
+ throw new ArgumentException(string.Format(Resources.InvalidKeyBlob, "pfx"));
+ }
+
+ return new JsonWebKey(key, true);
+ }
+
+ private IWebKeyConverter next;
+ private const string PfxFileExtension = ".pfx";
+ }
+}
diff --git a/src/ResourceManager/KeyVault/Commands.KeyVault/Models/Secret.cs b/src/ResourceManager/KeyVault/Commands.KeyVault/Models/Secret.cs
new file mode 100644
index 000000000000..48cb43c93747
--- /dev/null
+++ b/src/ResourceManager/KeyVault/Commands.KeyVault/Models/Secret.cs
@@ -0,0 +1,79 @@
+// ----------------------------------------------------------------------------------
+//
+// Copyright Microsoft Corporation
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+// ----------------------------------------------------------------------------------
+
+using System;
+using System.Security;
+using Client = Microsoft.KeyVault.Client;
+
+namespace Microsoft.Azure.Commands.KeyVault.Models
+{
+ public class Secret
+ {
+ public Secret()
+ { }
+
+ ///
+ /// Internal constructor used by KeyVaultDataServiceClient
+ ///
+ /// secret returned from service
+ /// helper class
+ internal Secret(Client.Secret clientSecret, VaultUriHelper vaultUriHelper)
+ {
+ if (clientSecret == null)
+ {
+ throw new ArgumentNullException("clientSecret");
+ }
+ if (vaultUriHelper == null)
+ {
+ throw new ArgumentNullException("vaultUriHelper");
+ }
+
+ VaultName = vaultUriHelper.GetVaultName(clientSecret.Id);
+ SecretName = vaultUriHelper.GetSecretName(clientSecret.Id);
+ SecretValue = clientSecret.Value.ToSecureString();
+ SecretValueText = clientSecret.Value;
+ // TODO: trace vaultUriHelper.KeyVaultDnsSuffix;
+
+ }
+
+ public string VaultName { get; set; }
+
+ public string SecretName { get; set; }
+
+ public SecureString SecretValue
+ {
+ get
+ {
+ return secretValue;
+ }
+ set
+ {
+ secretValue = value;
+ if (secretValue != null)
+ {
+ SecretValueText = secretValue.ToStringExt();
+ }
+ else
+ {
+ SecretValueText = null;
+ }
+ }
+ }
+ private SecureString secretValue;
+
+ public string SecretValueText { get; private set; }
+
+
+ }
+}
diff --git a/src/ResourceManager/KeyVault/Commands.KeyVault/Models/SecureStringExtension.cs b/src/ResourceManager/KeyVault/Commands.KeyVault/Models/SecureStringExtension.cs
new file mode 100644
index 000000000000..ad21ecfd62be
--- /dev/null
+++ b/src/ResourceManager/KeyVault/Commands.KeyVault/Models/SecureStringExtension.cs
@@ -0,0 +1,89 @@
+// ----------------------------------------------------------------------------------
+//
+// Copyright Microsoft Corporation
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+// ----------------------------------------------------------------------------------
+
+namespace Microsoft.Azure.Commands.KeyVault.Models
+{
+ using System;
+ using System.Runtime.InteropServices;
+ using System.Security;
+
+ ///
+ /// Extends SecureString and string to convert from one to the other
+ ///
+ public static class SecureStringExtension
+ {
+
+ ///
+ /// Converts a string into a secure string.
+ ///
+ /// the string to be converted.
+ public static SecureString ToSecureString( this string str )
+ {
+ if ( str == null )
+ {
+ throw new ArgumentNullException( "str" );
+ }
+
+ SecureString secureString = null;
+
+ try
+ {
+ secureString = new SecureString();
+
+ foreach ( char ch in str )
+ {
+ secureString.AppendChar( ch );
+ }
+
+ return secureString;
+ }
+ catch ( Exception )
+ {
+ if ( secureString != null )
+ {
+ secureString.Dispose();
+ }
+
+ throw;
+ }
+ }
+
+ ///
+ /// Converts the secure string to a string.
+ ///
+ /// the secure string to be converted.
+ public static string ToStringExt( this SecureString secureString )
+ {
+ string str = null;
+ IntPtr stringPointer = IntPtr.Zero;
+
+ if ( secureString == null )
+ {
+ throw new ArgumentNullException( "secureString" );
+ }
+
+ try
+ {
+ stringPointer = Marshal.SecureStringToBSTR(secureString);
+ str = Marshal.PtrToStringBSTR(stringPointer);
+ }
+ finally
+ {
+ Marshal.ZeroFreeBSTR(stringPointer);
+ }
+
+ return str;
+ }
+ }
+}
diff --git a/src/ResourceManager/KeyVault/Commands.KeyVault/Models/VaultUriHelper.cs b/src/ResourceManager/KeyVault/Commands.KeyVault/Models/VaultUriHelper.cs
new file mode 100644
index 000000000000..cae6da443187
--- /dev/null
+++ b/src/ResourceManager/KeyVault/Commands.KeyVault/Models/VaultUriHelper.cs
@@ -0,0 +1,153 @@
+// ----------------------------------------------------------------------------------
+//
+// Copyright Microsoft Corporation
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+// ----------------------------------------------------------------------------------
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Linq;
+using Microsoft.WindowsAzure.Commands.Common.Models;
+using Microsoft.Azure.Commands.KeyVault.Properties;
+
+namespace Microsoft.Azure.Commands.KeyVault.Models
+{
+ internal class VaultUriHelper
+ {
+ public VaultUriHelper(string keyVaultDnsSuffix)
+ {
+ if (string.IsNullOrEmpty(keyVaultDnsSuffix))
+ {
+ throw new ArgumentNullException("keyVaultDnsSuffix");
+ }
+ this.KeyVaultDnsSuffix = keyVaultDnsSuffix;
+ }
+
+ public string GetVaultName(string vaultAddress)
+ {
+ Uri vaultUri = CreateAndValidateVaultUri(vaultAddress);
+ return vaultUri.Host.Split('.').First();
+ }
+
+ public string GetKeyName(string keyAddress)
+ {
+ Uri vaultUri = CreateAndValidateVaultUri(keyAddress);
+
+ var keyName = GetValueUnderPath(vaultUri, KeyPathName);
+ if (string.IsNullOrEmpty(keyName))
+ {
+ throw new ArgumentException(string.Format(Resources.InvalidKeyUri, keyAddress));
+ }
+
+ return keyName;
+ }
+
+ public string GetSecretName(string secretAddress)
+ {
+ Uri vaultUri = CreateAndValidateVaultUri(secretAddress);
+
+ var secretName = GetValueUnderPath(vaultUri, SecretPathName);
+ if (string.IsNullOrEmpty(secretName))
+ {
+ throw new ArgumentException(string.Format(Resources.InvalidSecretUri, secretAddress));
+ }
+
+ return secretName;
+ }
+
+ public String CreateVaultAddress(string vaultName)
+ {
+ return CreateVaultUri(vaultName).ToString();
+ }
+
+ public string CreateKeyAddress(string vaultName, string keyName)
+ {
+ if (string.IsNullOrEmpty(vaultName))
+ {
+ throw new ArgumentNullException("vaultName");
+ }
+ if (string.IsNullOrEmpty(keyName))
+ {
+ throw new ArgumentNullException("keyName");
+ }
+
+ return new Uri(CreateVaultUri(vaultName),
+ string.Format("/{0}/{1}/", KeyPathName, keyName)).ToString();
+ }
+
+ public string CreateSecretAddress(string vaultName, string secretName)
+ {
+ if (string.IsNullOrEmpty(vaultName))
+ {
+ throw new ArgumentNullException("vaultName");
+ }
+ if (string.IsNullOrEmpty(secretName))
+ {
+ throw new ArgumentNullException("secretName");
+ }
+
+ return new Uri(CreateVaultUri(vaultName),
+ string.Format("/{0}/{1}/", SecretPathName, secretName)).ToString();
+ }
+
+ public string KeyVaultDnsSuffix { get; private set; }
+ private Uri CreateAndValidateVaultUri(string vaultAddress)
+ {
+ if (string.IsNullOrEmpty(vaultAddress))
+ {
+ throw new ArgumentNullException("vaultAddress");
+ }
+
+ Uri vaultUri;
+ if (!Uri.TryCreate(vaultAddress, UriKind.Absolute, out vaultUri))
+ {
+ throw new ArgumentException(string.Format(Resources.InvalidVaultUri, vaultAddress, this.KeyVaultDnsSuffix));
+ }
+
+ if (vaultUri.HostNameType != UriHostNameType.Dns ||
+ !vaultUri.Host.EndsWith(this.KeyVaultDnsSuffix))
+ {
+ throw new ArgumentException(string.Format(Resources.InvalidVaultUri, vaultAddress, this.KeyVaultDnsSuffix));
+ }
+
+ return vaultUri;
+ }
+
+ private string GetValueUnderPath(Uri vaultUri, string pathName)
+ {
+ if (vaultUri.Segments == null ||
+ vaultUri.Segments.Length < 3 ||
+ !string.Equals(vaultUri.Segments[1].TrimEnd('/'), pathName, StringComparison.OrdinalIgnoreCase))
+ {
+ return string.Empty;
+ }
+
+ return vaultUri.Segments[2].TrimEnd('/');
+ }
+
+ private Uri CreateVaultUri(string vaultName)
+ {
+ if (string.IsNullOrEmpty(vaultName))
+ {
+ throw new ArgumentNullException("vaultName");
+ }
+
+ UriBuilder builder = new UriBuilder("https", vaultName + "." + this.KeyVaultDnsSuffix);
+
+ return builder.Uri;
+ }
+
+
+ private const string KeyPathName = "keys";
+ private const string SecretPathName = "secrets";
+ }
+}
diff --git a/src/ResourceManager/KeyVault/Commands.KeyVault/Models/WebKeyConverterFactory.cs b/src/ResourceManager/KeyVault/Commands.KeyVault/Models/WebKeyConverterFactory.cs
new file mode 100644
index 000000000000..665cb4ce4f5e
--- /dev/null
+++ b/src/ResourceManager/KeyVault/Commands.KeyVault/Models/WebKeyConverterFactory.cs
@@ -0,0 +1,26 @@
+// ----------------------------------------------------------------------------------
+//
+// Copyright Microsoft Corporation
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+// ----------------------------------------------------------------------------------
+
+using System;
+
+namespace Microsoft.Azure.Commands.KeyVault.Models
+{
+ internal static class WebKeyConverterFactory
+ {
+ public static IWebKeyConverter CreateConverterChain()
+ {
+ return new PfxWebKeyConverter(new ByokWebKeyConverter());
+ }
+ }
+}
diff --git a/src/ResourceManager/KeyVault/Commands.KeyVault/Properties/AssemblyInfo.cs b/src/ResourceManager/KeyVault/Commands.KeyVault/Properties/AssemblyInfo.cs
new file mode 100644
index 000000000000..81babef19f02
--- /dev/null
+++ b/src/ResourceManager/KeyVault/Commands.KeyVault/Properties/AssemblyInfo.cs
@@ -0,0 +1,38 @@
+// ----------------------------------------------------------------------------------
+//
+// Copyright Microsoft Corporation
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+// ----------------------------------------------------------------------------------
+
+using System;
+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: AssemblyTitle("Microsoft Azure Powershell - Key Vault")]
+[assembly: AssemblyCompany(Microsoft.WindowsAzure.Commands.Common.AzurePowerShell.AssemblyCompany)]
+[assembly: AssemblyProduct(Microsoft.WindowsAzure.Commands.Common.AzurePowerShell.AssemblyProduct)]
+[assembly: AssemblyCopyright(Microsoft.WindowsAzure.Commands.Common.AzurePowerShell.AssemblyCopyright)]
+
+[assembly: ComVisible(false)]
+[assembly: CLSCompliant(false)]
+
+[assembly: Guid("2994548F-69B9-4DC2-8D19-52CC0C0C85BC")]
+[assembly: AssemblyVersion(Microsoft.WindowsAzure.Commands.Common.AzurePowerShell.AssemblyVersion)]
+[assembly: AssemblyFileVersion(Microsoft.WindowsAzure.Commands.Common.AzurePowerShell.AssemblyFileVersion)]
+#if SIGN
+[assembly: InternalsVisibleTo("Microsoft.Azure.Commands.KeyVault.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")]
+#else
+[assembly: InternalsVisibleTo("Microsoft.Azure.Commands.KeyVault.Test")]
+#endif
diff --git a/src/ResourceManager/KeyVault/Commands.KeyVault/Properties/Resources.Designer.cs b/src/ResourceManager/KeyVault/Commands.KeyVault/Properties/Resources.Designer.cs
new file mode 100644
index 000000000000..c3e6e41705ad
--- /dev/null
+++ b/src/ResourceManager/KeyVault/Commands.KeyVault/Properties/Resources.Designer.cs
@@ -0,0 +1,243 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+// Runtime Version:4.0.30319.34014
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+namespace Microsoft.Azure.Commands.KeyVault.Properties {
+ using System;
+
+
+ ///
+ /// A strongly-typed resource class, for looking up localized strings, etc.
+ ///
+ // 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.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ internal class Resources {
+
+ private static global::System.Resources.ResourceManager resourceMan;
+
+ private static global::System.Globalization.CultureInfo resourceCulture;
+
+ [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ internal Resources() {
+ }
+
+ ///
+ /// Returns the cached ResourceManager instance used by this class.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Resources.ResourceManager ResourceManager {
+ get {
+ if (object.ReferenceEquals(resourceMan, null)) {
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Microsoft.Azure.Commands.KeyVault.Properties.Resources", typeof(Resources).Assembly);
+ resourceMan = temp;
+ }
+ return resourceMan;
+ }
+ }
+
+ ///
+ /// Overrides the current thread's CurrentUICulture property for all
+ /// resource lookups using this strongly typed resource class.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Globalization.CultureInfo Culture {
+ get {
+ return resourceCulture;
+ }
+ set {
+ resourceCulture = value;
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Bad Parameter Set Name.
+ ///
+ internal static string BadParameterSetName {
+ get {
+ return ResourceManager.GetString("BadParameterSetName", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Invalid AzureEnvironment..
+ ///
+ internal static string InvalidAzureEnvironment {
+ get {
+ return ResourceManager.GetString("InvalidAzureEnvironment", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to No current subscription has been designated. Use Select-AzureSubscription -Current <subscriptionName> to set the current subscription..
+ ///
+ internal static string InvalidCurrentSubscription {
+ get {
+ return ResourceManager.GetString("InvalidCurrentSubscription", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Invalid '{0}' key blob..
+ ///
+ internal static string InvalidKeyBlob {
+ get {
+ return ResourceManager.GetString("InvalidKeyBlob", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Invalid KeyBundle..
+ ///
+ internal static string InvalidKeyBundle {
+ get {
+ return ResourceManager.GetString("InvalidKeyBundle", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Can not create given key material in specified destination..
+ ///
+ internal static string InvalidKeyDestination {
+ get {
+ return ResourceManager.GetString("InvalidKeyDestination", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Invalid key name..
+ ///
+ internal static string InvalidKeyName {
+ get {
+ return ResourceManager.GetString("InvalidKeyName", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Invalid key uri '{0}'..
+ ///
+ internal static string InvalidKeyUri {
+ get {
+ return ResourceManager.GetString("InvalidKeyUri", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Invalid secret name..
+ ///
+ internal static string InvalidSecretName {
+ get {
+ return ResourceManager.GetString("InvalidSecretName", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Invalid secret uri '{0}'..
+ ///
+ internal static string InvalidSecretUri {
+ get {
+ return ResourceManager.GetString("InvalidSecretUri", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Your Azure credentials have not been set up or have expired, please run Add-AzureAccount to set up your Azure credentials..
+ ///
+ internal static string InvalidSubscriptionState {
+ get {
+ return ResourceManager.GetString("InvalidSubscriptionState", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Invalid vault name..
+ ///
+ internal static string InvalidVaultName {
+ get {
+ return ResourceManager.GetString("InvalidVaultName", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Invalid vault uri '{0}'. Vault uri must contain valid dns host name with domain suffix '{1}'..
+ ///
+ internal static string InvalidVaultUri {
+ get {
+ return ResourceManager.GetString("InvalidVaultUri", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Can not find key file '{0}'..
+ ///
+ internal static string KeyFileNotFound {
+ get {
+ return ResourceManager.GetString("KeyFileNotFound", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Are you sure you want to remove key '{0}'..
+ ///
+ internal static string RemoveKeyWarning {
+ get {
+ return ResourceManager.GetString("RemoveKeyWarning", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Remove key.
+ ///
+ internal static string RemoveKeyWhatIfMessage {
+ get {
+ return ResourceManager.GetString("RemoveKeyWhatIfMessage", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Are you sure you want to remove secret '{0}'.
+ ///
+ internal static string RemoveSecretWarning {
+ get {
+ return ResourceManager.GetString("RemoveSecretWarning", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Remove secret.
+ ///
+ internal static string RemoveSecretWhatIfMessage {
+ get {
+ return ResourceManager.GetString("RemoveSecretWhatIfMessage", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Key vault cmdlet does not support account type '{0}'..
+ ///
+ internal static string UnsupportedAccountType {
+ get {
+ return ResourceManager.GetString("UnsupportedAccountType", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to The file format of '{0}' is not supported..
+ ///
+ internal static string UnsupportedFileFormat {
+ get {
+ return ResourceManager.GetString("UnsupportedFileFormat", resourceCulture);
+ }
+ }
+ }
+}
diff --git a/src/ResourceManager/KeyVault/Commands.KeyVault/Properties/Resources.resx b/src/ResourceManager/KeyVault/Commands.KeyVault/Properties/Resources.resx
new file mode 100644
index 000000000000..ab09e7a48a5b
--- /dev/null
+++ b/src/ResourceManager/KeyVault/Commands.KeyVault/Properties/Resources.resx
@@ -0,0 +1,180 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ Bad Parameter Set Name
+
+
+ Invalid AzureEnvironment.
+
+
+ No current subscription has been designated. Use Select-AzureSubscription -Current <subscriptionName> to set the current subscription.
+
+
+ Invalid '{0}' key blob.
+
+
+ Invalid KeyBundle.
+
+
+ Can not create given key material in specified destination.
+
+
+ Invalid key name.
+
+
+ Invalid key uri '{0}'.
+
+
+ Invalid secret name.
+
+
+ Invalid secret uri '{0}'.
+
+
+ Your Azure credentials have not been set up or have expired, please run Add-AzureAccount to set up your Azure credentials.
+
+
+ Invalid vault name.
+
+
+ Invalid vault uri '{0}'. Vault uri must contain valid dns host name with domain suffix '{1}'.
+
+
+ Can not find key file '{0}'.
+
+
+ Are you sure you want to remove key '{0}'.
+
+
+ Remove key
+
+
+ Are you sure you want to remove secret '{0}'
+
+
+ Remove secret
+
+
+ Key vault cmdlet does not support account type '{0}'.
+
+
+ The file format of '{0}' is not supported.
+
+
\ No newline at end of file
diff --git a/src/ResourceManager/KeyVault/Commands.KeyVault/packages.config b/src/ResourceManager/KeyVault/Commands.KeyVault/packages.config
new file mode 100644
index 000000000000..c4ac3b61f194
--- /dev/null
+++ b/src/ResourceManager/KeyVault/Commands.KeyVault/packages.config
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/ResourceManager/Resources/Commands.Resources/AzureResourceManager.psd1 b/src/ResourceManager/Resources/Commands.Resources/AzureResourceManager.psd1
index f99a82551636..280af494bd98 100644
--- a/src/ResourceManager/Resources/Commands.Resources/AzureResourceManager.psd1
+++ b/src/ResourceManager/Resources/Commands.Resources/AzureResourceManager.psd1
@@ -63,7 +63,8 @@ FormatsToProcess = @(
'.\Resources\Microsoft.WindowsAzure.Commands.Profile.format.ps1xml',
'.\DataFactories\Microsoft.Azure.Commands.DataFactories.format.ps1xml',
'.\RedisCache\Microsoft.Azure.Commands.RedisCache.format.ps1xml',
- '.\Batch\Microsoft.Azure.Commands.Batch.format.ps1xml'
+ '.\Batch\Microsoft.Azure.Commands.Batch.format.ps1xml',
+ '.\KeyVault\Microsoft.Azure.Commands.KeyVault.format.ps1xml'
)
# Modules to import as nested modules of the module specified in ModuleToProcess
@@ -74,7 +75,8 @@ NestedModules = @(
'.\Sql\Microsoft.Azure.Commands.Sql.dll',
'.\DataFactories\Microsoft.Azure.Commands.DataFactories.dll',
'.\RedisCache\Microsoft.Azure.Commands.RedisCache.dll',
- '.\Batch\Microsoft.Azure.Commands.Batch.dll'
+ '.\Batch\Microsoft.Azure.Commands.Batch.dll',
+ '.\KeyVault\Microsoft.Azure.Commands.KeyVault.dll'
)
# Functions to export from this module
diff --git a/src/ResourceManager/Resources/Commands.Resources/Commands.Resources.csproj b/src/ResourceManager/Resources/Commands.Resources/Commands.Resources.csproj
index eebaf66df062..c0547f5600c0 100644
--- a/src/ResourceManager/Resources/Commands.Resources/Commands.Resources.csproj
+++ b/src/ResourceManager/Resources/Commands.Resources/Commands.Resources.csproj
@@ -222,6 +222,10 @@
{d470e50a-9607-48d6-a924-4f9f86502704}
Commands.Batch
+
+ {9ffc40cc-a341-4d0c-a25d-dc6b78ef6c94}
+ Commands.KeyVault
+
{c972e3ef-4461-4758-ba31-93e0947b1253}
Commands.RedisCache