Skip to content

Commit 65a2037

Browse files
Fix Azure#15091- Import-AzWebAppKeyVaultCertificate api version bug (Azure#15281)
* Fix Azure#15091- Import-AzWebAppKeyVaultCertificate api version bug * Updated changelog.md * Updated RequiredAssemblies for Az.Websites * Updated Test project to use Microsoft.Azure.Management.KeyVault Nuget * rolled back the AKV SDK changes * Addressed code review comments.
1 parent 9c6bcf3 commit 65a2037

File tree

6 files changed

+128
-96
lines changed

6 files changed

+128
-96
lines changed

src/Websites/Websites.Test/SessionRecords/Microsoft.Azure.Commands.Websites.Test.ScenarioTests.CertificatesTests/TestImportAzWebAppKeyVaultCertificate.json

Lines changed: 73 additions & 70 deletions
Large diffs are not rendered by default.

src/Websites/Websites/ChangeLog.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
- Additional information about change #1
1919
-->
2020
## Upcoming Release
21+
* Fixed `Import-AzWebAppKeyVaultCertificate` to support ServerFarmId [#15091]
2122

2223
## Version 2.7.0
2324
* Fixed issue that prevented removing rules by name and unique identifier in `Remove-AzWebAppAccessRestrictionRule`

src/Websites/Websites/Cmdlets/Certificates/ImportAzWebAppKeyVaultCertificate.cs

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ public class ImportAzWebAppKeyVaultCertificate : WebAppBaseClientCmdLet
1919
{
2020
const string ParameterSet1Name = "S1";
2121

22-
[Parameter(ParameterSetName = ParameterSet1Name, Position = 0, Mandatory = true, HelpMessage = "The name of the keyvault.")]
22+
[Parameter(ParameterSetName = ParameterSet1Name, Position = 0, Mandatory = true, HelpMessage = "The name of the keyvault or Id of the KeyVault.")]
2323
[ValidateNotNullOrEmpty]
2424
public string KeyVaultName { get; set; }
2525

@@ -44,11 +44,10 @@ public override void ExecuteCmdlet()
4444
{
4545
if (!string.IsNullOrWhiteSpace(ResourceGroupName) && !string.IsNullOrWhiteSpace(WebAppName))
4646
{
47+
string kvId = string.Empty, kvRgName = string.Empty, kvSubscriptionId = string.Empty;
4748
var webApp = new PSSite(WebsitesClient.GetWebApp(ResourceGroupName, WebAppName, Slot));
4849
var location = webApp.Location;
4950
var serverFarmId = webApp.ServerFarmId;
50-
string kvid = string.Empty;
51-
string kvresourcegrpname = string.Empty;
5251
var keyvaultResources = this.ResourcesClient.ResourceManagementClient.FilterResources(new FilterResourcesOptions
5352
{
5453
ResourceType = "Microsoft.KeyVault/Vaults"
@@ -58,19 +57,29 @@ public override void ExecuteCmdlet()
5857
{
5958
if (kv.Name == KeyVaultName)
6059
{
61-
kvid = kv.Id;
62-
kvresourcegrpname = kv.ResourceGroupName;
60+
kvId = kv.Id;
61+
kvRgName = kv.ResourceGroupName;
6362
break;
6463
}
6564
}
66-
if (string.IsNullOrEmpty(kvid))
65+
if (string.IsNullOrEmpty(kvId))
6766
{
68-
kvid = KeyVaultName;
67+
kvId = KeyVaultName;
68+
if (CmdletHelpers.IsValidAKVResourceId(kvId))
69+
{
70+
var details = CmdletHelpers.GetResourceDetailsFromResourceId(kvId);
71+
kvRgName = details.ResourceGroupName;
72+
KeyVaultName = details.ResourceName;
73+
kvSubscriptionId = details.Subscription;
74+
}
75+
else //default to AppService RG
76+
{
77+
kvRgName = ResourceGroupName;
78+
}
6979
}
70-
string keyvaultperm;
71-
keyvaultperm = CmdletHelpers.CheckServicePrincipalPermissions(this.ResourcesClient, this.KeyvaultClient,kvresourcegrpname, KeyVaultName);
80+
var kvpermission = CmdletHelpers.CheckServicePrincipalPermissions(this.ResourcesClient, this.KeyvaultClient, kvRgName, KeyVaultName, kvSubscriptionId);
7281
var lnk = "https://azure.github.io/AppService/2016/05/24/Deploying-Azure-Web-App-Certificate-through-Key-Vault.html";
73-
if ((keyvaultperm != "Get") & (keyvaultperm != "get"))
82+
if (kvpermission.ToLower() != "get")
7483
{
7584
WriteWarning("Unable to verify Key Vault permissions.");
7685
WriteWarning("You may need to grant Microsoft.Azure.WebSites service principal the Secret:Get permission");
@@ -80,7 +89,7 @@ public override void ExecuteCmdlet()
8089
Certificate kvc = null;
8190
var certificate = new Certificate(
8291
location: location,
83-
keyVaultId: kvid,
92+
keyVaultId: kvId,
8493
password: "",
8594
keyVaultSecretName: CertName,
8695
serverFarmId: serverFarmId

src/Websites/Websites/Utilities/CmdletHelpers.cs

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,9 @@ public static class CmdletHelpers
5454
private static readonly Regex AppServicePlanResourceIdRegex =
5555
new Regex(@"^\/subscriptions\/(?<subscriptionName>[^\/]+)\/resourceGroups\/(?<resourceGroupName>[^\/]+)\/providers\/Microsoft.Web\/serverFarms\/(?<serverFarmName>[^\/]+)$", RegexOptions.IgnoreCase);
5656

57+
private static readonly Regex KeyVaultResourceIdRegex =
58+
new Regex(@"^\/subscriptions\/(?<subscriptionName>[^\/]+)\/resourceGroups\/(?<resourceGroupName>[^\/]+)\/providers\/Microsoft.KeyVault\/vaults\/(?<vaultName>[^\/]+)$", RegexOptions.IgnoreCase);
59+
5760
private static readonly Dictionary<string, int> WorkerSizes = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase) { { "Small", 1 }, { "Medium", 2 }, { "Large", 3 }, { "ExtraLarge", 4 } };
5861

5962
private const string ProductionSlotName = "Production";
@@ -178,7 +181,7 @@ internal static bool ShouldUseDeploymentSlot(string webSiteName, string slotName
178181

179182
return result;
180183
}
181-
184+
182185
internal static HostingEnvironmentProfile CreateHostingEnvironmentProfile(string subscriptionId, string resourceGroupName, string aseResourceGroupName, string aseName)
183186
{
184187
var rg = string.IsNullOrEmpty(aseResourceGroupName) ? resourceGroupName : aseResourceGroupName;
@@ -222,7 +225,7 @@ internal static string BuildMetricFilter(DateTime? startTime, DateTime? endTime,
222225

223226
return filter;
224227
}
225-
228+
226229
internal static bool TryParseWebAppMetadataFromResourceId(string resourceId, out string resourceGroupName,
227230
out string webAppName, out string slotName, bool failIfSlot = false)
228231
{
@@ -271,6 +274,10 @@ internal static bool TryParseAppServicePlanMetadataFromResourceId(string resourc
271274
return false;
272275
}
273276

277+
internal static bool IsValidAKVResourceId(string resourceId)
278+
{
279+
return KeyVaultResourceIdRegex.Match(resourceId).Success;
280+
}
274281
internal static string GetSkuName(string tier, int workerSize)
275282
{
276283
string sku;
@@ -309,7 +316,7 @@ internal static string GetSkuName(string tier, int workerSize)
309316

310317
internal static string GetSkuName(string tier, string workerSize)
311318
{
312-
return GetSkuName(tier, WorkerSizes[workerSize]);
319+
return GetSkuName(tier, WorkerSizes[workerSize]);
313320
}
314321

315322
internal static bool IsDeploymentSlot(string name)
@@ -373,6 +380,11 @@ internal static string GetSubscriptionIdFromResourceId(string resourceId)
373380
return new ResourceIdentifier(resourceId).Subscription;
374381
}
375382

383+
internal static ResourceIdentifier GetResourceDetailsFromResourceId(string resourceId)
384+
{
385+
return new ResourceIdentifier(resourceId);
386+
}
387+
376388
internal static void ExtractWebAppPropertiesFromWebApp(Site webapp, out string resourceGroupName, out string webAppName, out string slot)
377389
{
378390
resourceGroupName = GetResourceGroupFromResourceId(webapp.Id);
@@ -414,26 +426,23 @@ internal static Certificate[] GetCertificates(ResourceClient resourceClient, Web
414426
return certificates.ToArray();
415427
}
416428

417-
internal static string CheckServicePrincipalPermissions(ResourceClient resourceClient, KeyVaultClient keyVaultClient, string resourceGroupName, string keyVault)
429+
internal static string CheckServicePrincipalPermissions(ResourceClient resourceClient, KeyVaultClient keyVaultClient, string resourceGroupName, string keyVault, string kvSubscriptionId)
418430
{
419-
var perm1 = " ";
420-
var kv2 = keyVaultClient.GetKeyVault(resourceGroupName, keyVault);
421-
foreach (var policy in kv2.Properties.AccessPolicies)
431+
var kv = keyVaultClient.GetKeyVault(resourceGroupName, keyVault, kvSubscriptionId);
432+
foreach (var policy in kv.Properties.AccessPolicies)
422433
{
423434
if (policy.ObjectId == ("f8daea97-62e7-4026-becf-13c2ea98e8b4"))
424435
{
425436
foreach (var perm in policy.Permissions.Secrets)
426437
{
427-
if ((perm == "Get") || (perm == "get"))
438+
if (perm.ToLower() == "get")
428439
{
429-
perm1 = perm;
430-
Console.WriteLine("Success");
431-
break;
440+
return perm;
432441
}
433442
}
434443
}
435444
}
436-
return perm1.ToString();
445+
return string.Empty;
437446
}
438447

439448
internal static SiteConfigResource ConvertToSiteConfigResource(this SiteConfig config)

src/Websites/Websites/Utilities/KeyVaultClient.cs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,21 @@ public KeyVaultManagementClient WrappedKeyVaultClient
2525
private set;
2626
}
2727

28-
public Vault GetKeyVault(string resourceGroupName, string vaultName)
28+
public Vault GetKeyVault(string resourceGroupName, string vaultName, string kvSubscriptionId = null)
2929
{
3030
try
3131
{
32-
return this.WrappedKeyVaultClient.Vaults.Get(resourceGroupName, vaultName);
32+
string originalSubscreptionId = this.WrappedKeyVaultClient.SubscriptionId;
33+
34+
// Replacing the actual Subscription to fetch the Vaults from other Subscriptions.
35+
if (!String.IsNullOrEmpty(kvSubscriptionId) && originalSubscreptionId != kvSubscriptionId)
36+
this.WrappedKeyVaultClient.SubscriptionId = kvSubscriptionId;
37+
38+
var vault = this.WrappedKeyVaultClient.Vaults.Get(resourceGroupName, vaultName);
39+
// Replacing back to the original Subscription after fetching Vault.
40+
this.WrappedKeyVaultClient.SubscriptionId = originalSubscreptionId;
41+
42+
return vault;
3343
}
3444
catch (Exception ex)
3545
{

src/Websites/Websites/help/Import-AzWebAppKeyVaultCertificate.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ Accept wildcard characters: False
7373
```
7474
7575
### -KeyVaultName
76-
The name of the keyvault.
76+
The name of the keyvault or Id of the KeyVault.
7777
7878
```yaml
7979
Type: System.String

0 commit comments

Comments
 (0)