Skip to content

Commit 7bf7edf

Browse files
committed
Merge pull request Azure#1329 from linweigao/dev
KeyVault deployment integration
2 parents 20848d7 + 35a9296 commit 7bf7edf

File tree

11 files changed

+2360
-24
lines changed

11 files changed

+2360
-24
lines changed

src/ResourceManager/Resources/Commands.Resources.Test/Commands.Resources.Test.csproj

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,12 @@
245245
</ProjectReference>
246246
</ItemGroup>
247247
<ItemGroup>
248+
<None Include="KeyVaultSetupTemplate.json">
249+
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
250+
</None>
251+
<None Include="keyVaultTemplateParams.json">
252+
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
253+
</None>
248254
<None Include="SamplePolicyDefinition.json">
249255
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
250256
</None>
@@ -321,6 +327,9 @@
321327
<None Include="SessionRecords\Microsoft.Azure.Commands.Resources.Test.ScenarioTests.DeploymentTests\TestNewDeploymentFromTemplateFile.json">
322328
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
323329
</None>
330+
<None Include="SessionRecords\Microsoft.Azure.Commands.Resources.Test.ScenarioTests.DeploymentTests\TestNewDeploymentWithKeyVaultReference.json">
331+
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
332+
</None>
324333
<None Include="SessionRecords\Microsoft.Azure.Commands.Resources.Test.ScenarioTests.MoveResourceTest\TestMoveAzureResource.json">
325334
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
326335
</None>
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
{
2+
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
3+
"contentVersion": "1.0.0.0",
4+
"parameters": {
5+
"keyVaultName": {
6+
"type": "string",
7+
"metadata": {
8+
"description": "Name of the Vault"
9+
}
10+
},
11+
"tenantId": {
12+
"type": "string",
13+
"metadata": {
14+
"description": "Tenant Id for the subscription. Available from Get-AzureRMSubscription PowerShell cmdlet"
15+
}
16+
},
17+
"objectId": {
18+
"type": "string",
19+
"metadata": {
20+
"description": "Object Id of the AD user. Available from Get-AzureRMADUser or Get-AzureRMADServicePrincipal cmdlets"
21+
}
22+
},
23+
"keysPermissions": {
24+
"type": "array",
25+
"defaultValue": [ "all" ],
26+
"metadata": {
27+
"description": "Permissions to grant user to keys in the vault. Valid values are: all, create, import, update, get, list, delete, backup, restore, encrypt, decrypt, wrapkey, unwrapkey, sign, and verify."
28+
}
29+
},
30+
"secretsPermissions": {
31+
"type": "array",
32+
"defaultValue": [ "all" ],
33+
"metadata": {
34+
"description": "Permissions to grant user to secrets in the vault. Valid values are: all, get, set, list, and delete."
35+
}
36+
},
37+
"skuName": {
38+
"type": "string",
39+
"defaultValue": "Standard",
40+
"allowedValues": [
41+
"Standard",
42+
"Premium"
43+
],
44+
"metadata": {
45+
"description": "SKU for the vault"
46+
}
47+
},
48+
"enabledForDeployment": {
49+
"type": "bool",
50+
"defaultValue": true,
51+
"metadata": {
52+
"description": "Specifies if the vault is enabled for a VM deployment"
53+
}
54+
},
55+
"enabledForTemplateDeployment": {
56+
"type": "bool",
57+
"defaultValue": true,
58+
"metadata": {
59+
"description": "Specifies if the vault is enabled for a ARM template deployment"
60+
}
61+
},
62+
"enableVaultForVolumeEncryption": {
63+
"type": "bool",
64+
"defaultValue": false,
65+
"metadata": {
66+
"description": "Specifies if the vault is enabled for volume encryption"
67+
}
68+
},
69+
"secretName": {
70+
"type": "string",
71+
"metadata": {
72+
"description": "Name of the secret to store in the vault"
73+
}
74+
},
75+
"secretValue": {
76+
"type": "securestring",
77+
"metadata": {
78+
"description": "Value of the secret"
79+
}
80+
}
81+
},
82+
"resources": [
83+
{
84+
"type": "Microsoft.KeyVault/vaults",
85+
"name": "[parameters('keyVaultName')]",
86+
"apiVersion": "2015-06-01",
87+
"location": "[resourceGroup().location]",
88+
"tags": { "displayName": "Vault" },
89+
"properties": {
90+
"enabledForDeployment": "[parameters('enabledForDeployment')]",
91+
"enabledForTemplateDeployment": "[parameters('enabledForTemplateDeployment')]",
92+
"enabledForVolumeEncryption": "[parameters('enableVaultForVolumeEncryption')]",
93+
"tenantId": "[parameters('tenantId')]",
94+
"accessPolicies": [
95+
{
96+
"tenantId": "[parameters('tenantId')]",
97+
"objectId": "[parameters('objectId')]",
98+
"permissions": {
99+
"keys": "[parameters('keysPermissions')]",
100+
"secrets": "[parameters('secretsPermissions')]"
101+
}
102+
}
103+
],
104+
"sku": {
105+
"name": "[parameters('skuName')]",
106+
"family": "A"
107+
}
108+
},
109+
"resources": [
110+
{
111+
"type": "secrets",
112+
"name": "[parameters('secretName')]",
113+
"apiVersion": "2015-06-01",
114+
"tags": { "displayName": "secret" },
115+
"properties": {
116+
"value": "[parameters('secretValue')]"
117+
},
118+
"dependsOn": [
119+
"[concat('Microsoft.KeyVault/vaults/', parameters('keyVaultName'))]"
120+
]
121+
}
122+
]
123+
}
124+
]
125+
}

src/ResourceManager/Resources/Commands.Resources.Test/ResourceGroups/NewAzureResourceGroupCommandTests.cs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,6 @@ public class NewAzureResourceGroupCommandTests : RMTestBase
3939

4040
private string templateFile = @"Resources\sampleTemplateFile.json";
4141

42-
private string storageAccountName = "myStorageAccount";
43-
4442
private Hashtable[] tags;
4543

4644
public NewAzureResourceGroupCommandTests()

src/ResourceManager/Resources/Commands.Resources.Test/ScenarioTests/DeploymentTests.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,5 +29,11 @@ public void TestNewDeploymentFromTemplateFile()
2929
{
3030
ResourcesController.NewInstance.RunPsTest("Test-NewDeploymentFromTemplateFile");
3131
}
32+
33+
[Fact]
34+
public void TestNewDeploymentWithKeyVaultReference()
35+
{
36+
ResourcesController.NewInstance.RunPsTest("Test-NewDeploymentWithKeyVaultReference");
37+
}
3238
}
3339
}

src/ResourceManager/Resources/Commands.Resources.Test/ScenarioTests/DeploymentTests.ps1

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,3 +67,60 @@ function Test-NewDeploymentFromTemplateFile
6767
Clean-ResourceGroup $rgname
6868
}
6969
}
70+
71+
<#
72+
.SYNOPSIS
73+
Tests deployment via template file and parameter file with KeyVault reference.
74+
#>
75+
function Test-NewDeploymentWithKeyVaultReference
76+
{
77+
# Setup
78+
$rgname = Get-ResourceGroupName
79+
$rname = Get-ResourceName
80+
$keyVaultname = Get-ResourceName
81+
$secretName = Get-ResourceName
82+
$rglocation = Get-ProviderLocation ResourceManagement
83+
$location = Get-ProviderLocation "Microsoft.Web/sites"
84+
$hostplanName = "xDeploymentTestHost26668"
85+
86+
try
87+
{
88+
# Test
89+
New-AzureRmResourceGroup -Name $rgname -Location $rglocation
90+
91+
$context = Get-AzureRmContext
92+
$subscriptionId = $context.Subscription.SubscriptionId
93+
$account = Get-AzureAccount -Name $context.Account.Id
94+
$tenantId = $account.Tenants
95+
$adUser = Get-AzureRmADUser -UserPrincipalName $context.Account.Id
96+
$objectId = $adUser.Id
97+
$KeyVaultResourceId = "/subscriptions/" + $subscriptionId + "/resourcegroups/" + $rgname + "/providers/Microsoft.KeyVault/vaults/" + $keyVaultname
98+
99+
$parameters = @{ "keyVaultName" = $keyVaultname; "secretName" = $secretName; "secretValue" = $hostplanName; "tenantId" = $tenantId; "objectId" = $objectId }
100+
$deployment = New-AzureRmResourceGroupDeployment -Name $rname -ResourceGroupName $rgname -TemplateFile keyVaultSetupTemplate.json -TemplateParameterObject $parameters
101+
102+
# Assert
103+
Assert-AreEqual Succeeded $deployment.ProvisioningState
104+
105+
$content = (Get-Content keyVaultTemplateParams.json) -join '' | ConvertFrom-Json
106+
$content.hostingPlanName.reference.KeyVault.id = $KeyVaultResourceId
107+
$content.hostingPlanName.reference.SecretName = $secretName
108+
$content | ConvertTo-Json -depth 999 | Out-File keyVaultTemplateParams.json
109+
110+
$deployment = New-AzureRmResourceGroupDeployment -Name $rname -ResourceGroupName $rgname -TemplateFile sampleTemplate.json -TemplateParameterFile keyVaultTemplateParams.json
111+
112+
# Assert
113+
Assert-AreEqual Succeeded $deployment.ProvisioningState
114+
115+
$subId = (Get-AzureRmContext).Subscription.SubscriptionId
116+
$deploymentId = "/subscriptions/$subId/resourcegroups/$rgname/providers/Microsoft.Resources/deployments/$rname"
117+
$getById = Get-AzureRmResourceGroupDeployment -Id $deploymentId
118+
Assert-AreEqual $getById.DeploymentName $deployment.DeploymentName
119+
}
120+
121+
finally
122+
{
123+
# Cleanup
124+
Clean-ResourceGroup $rgname
125+
}
126+
}

src/ResourceManager/Resources/Commands.Resources.Test/ScenarioTests/ResourcesController.cs

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
using System.Net.Http.Headers;
2020
using Microsoft.Azure.Commands.ResourceManager.Cmdlets.Components;
2121
using Microsoft.Azure.Commands.ResourceManager.Cmdlets.Extensions;
22-
using Microsoft.Azure.Commands.ResourceManager.Common;
2322
using Microsoft.Azure.Common.Authentication;
2423
using Microsoft.Azure.Gallery;
2524
using Microsoft.Azure.Graph.RBAC;
@@ -32,6 +31,7 @@
3231
using Microsoft.WindowsAzure.Commands.Common;
3332
using Microsoft.WindowsAzure.Commands.ScenarioTest;
3433

34+
3535
namespace Microsoft.Azure.Commands.Resources.Test.ScenarioTests
3636
{
3737
public sealed class ResourcesController
@@ -51,15 +51,15 @@ public sealed class ResourcesController
5151
public SubscriptionClient SubscriptionClient { get; private set; }
5252

5353
public GalleryClient GalleryClient { get; private set; }
54-
54+
5555
public InsightsClient InsightsClient { get; private set; }
5656

5757
public AuthorizationManagementClient AuthorizationManagementClient { get; private set; }
5858

5959
public string UserDomain { get; private set; }
6060

61-
public static ResourcesController NewInstance
62-
{
61+
public static ResourcesController NewInstance
62+
{
6363
get
6464
{
6565
return new ResourcesController();
@@ -77,18 +77,18 @@ public void RunPsTest(params string[] scripts)
7777
var mockName = TestUtilities.GetCurrentMethodName(2);
7878

7979
RunPsTestWorkflow(
80-
() => scripts,
80+
() => scripts,
8181
// no custom initializer
82-
null,
82+
null,
8383
// no custom cleanup
8484
null,
8585
callingClassType,
8686
mockName);
8787
}
8888

8989
public void RunPsTestWorkflow(
90-
Func<string[]> scriptBuilder,
91-
Action<CSMTestEnvironmentFactory> initialize,
90+
Func<string[]> scriptBuilder,
91+
Action<CSMTestEnvironmentFactory> initialize,
9292
Action cleanup,
9393
string callingClassType,
9494
string mockName)
@@ -99,22 +99,22 @@ public void RunPsTestWorkflow(
9999

100100
this.csmTestFactory = new CSMTestEnvironmentFactory();
101101

102-
if(initialize != null)
102+
if (initialize != null)
103103
{
104104
initialize(this.csmTestFactory);
105105
}
106106

107+
helper.SetupEnvironment(AzureModule.AzureResourceManager);
108+
107109
SetupManagementClients();
108110

109-
helper.SetupEnvironment(AzureModule.AzureResourceManager);
110-
111111
var callingClassName = callingClassType
112112
.Split(new[] { "." }, StringSplitOptions.RemoveEmptyEntries)
113113
.Last();
114-
helper.SetupModules(AzureModule.AzureResourceManager,
115-
"ScenarioTests\\Common.ps1",
116-
"ScenarioTests\\" + callingClassName + ".ps1",
117-
helper.RMProfileModule,
114+
helper.SetupModules(AzureModule.AzureResourceManager,
115+
"ScenarioTests\\Common.ps1",
116+
"ScenarioTests\\" + callingClassName + ".ps1",
117+
helper.RMProfileModule,
118118
helper.RMResourceModule);
119119

120120
try
@@ -131,7 +131,7 @@ public void RunPsTestWorkflow(
131131
}
132132
finally
133133
{
134-
if(cleanup !=null)
134+
if (cleanup != null)
135135
{
136136
cleanup();
137137
}

src/ResourceManager/Resources/Commands.Resources.Test/SessionRecords/Microsoft.Azure.Commands.Resources.Test.ScenarioTests.DeploymentTests/TestNewDeploymentWithKeyVaultReference.json

Lines changed: 2130 additions & 0 deletions
Large diffs are not rendered by default.
Binary file not shown.

src/ResourceManager/Resources/Commands.Resources/Models.ResourceGroups/ResourceClient.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ private string GetDeploymentParameters(Hashtable templateParameterObject)
107107
{
108108
if (templateParameterObject != null)
109109
{
110-
return SerializeHashtable(templateParameterObject, addValueLayer: true);
110+
return SerializeHashtable(templateParameterObject, addValueLayer: false);
111111
}
112112
else
113113
{

src/ResourceManager/Resources/Commands.Resources/Models.ResourceGroups/ResourceWithParameterBaseCmdlet.cs

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ public abstract class ResourceWithParameterBaseCmdlet : ResourcesBaseCmdlet
3939
protected const string ParameterlessTemplateFileParameterSetName = "Deployment via template file without parameters";
4040
protected const string ParameterlessGalleryTemplateParameterSetName = "Deployment via Gallery without parameters";
4141
protected const string ParameterlessTemplateUriParameterSetName = "Deployment via template uri without parameters";
42-
42+
4343
protected RuntimeDefinedParameterDictionary dynamicParameters;
4444

4545
private string templateFile;
@@ -143,24 +143,32 @@ public object GetDynamicParameters()
143143

144144
protected Hashtable GetTemplateParameterObject(Hashtable templateParameterObject)
145145
{
146-
templateParameterObject = templateParameterObject ?? new Hashtable();
146+
// NOTE(jogao): create a new Hashtable so that user can re-use the templateParameterObject.
147+
var prameterObject = new Hashtable();
148+
if (templateParameterObject != null)
149+
{
150+
foreach (var parameterKey in templateParameterObject.Keys)
151+
{
152+
prameterObject[parameterKey] = new Hashtable { { "value", templateParameterObject[parameterKey] } };
153+
}
154+
}
147155

148156
// Load parameters from the file
149157
string templateParameterFilePath = this.TryResolvePath(TemplateParameterFile);
150158
if (templateParameterFilePath != null && FileUtilities.DataStore.FileExists(templateParameterFilePath))
151159
{
152160
var parametersFromFile = GalleryTemplatesClient.ParseTemplateParameterFileContents(templateParameterFilePath);
153-
parametersFromFile.ForEach(dp => templateParameterObject[dp.Key] = dp.Value.Value);
161+
parametersFromFile.ForEach(dp => prameterObject[dp.Key] = new Hashtable { { "value", dp.Value.Value }, { "reference", dp.Value.Reference } });
154162
}
155163

156164
// Load dynamic parameters
157165
IEnumerable<RuntimeDefinedParameter> parameters = PowerShellUtilities.GetUsedDynamicParameters(dynamicParameters, MyInvocation);
158166
if (parameters.Any())
159167
{
160-
parameters.ForEach(dp => templateParameterObject[((ParameterAttribute)dp.Attributes[0]).HelpMessage] = dp.Value);
168+
parameters.ForEach(dp => prameterObject[((ParameterAttribute)dp.Attributes[0]).HelpMessage] = new Hashtable { { "value", dp.Value } });
161169
}
162170

163-
return templateParameterObject;
171+
return prameterObject;
164172
}
165173
}
166174
}

src/ResourceManager/Resources/Commands.Resources/Models.ResourceGroups/TemplateFileParameterV1.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ public class TemplateFileParameterV1
2525
[JsonProperty("value")]
2626
public object Value { get; set; }
2727

28+
[JsonProperty("reference")]
29+
public object Reference { get; set; }
30+
2831
[JsonProperty("defaultValue")]
2932
public object DefaultValue { get; set; }
3033

0 commit comments

Comments
 (0)