Skip to content

Commit e100d5a

Browse files
[AppService]: fix Azure#13109 - Assigning user assigned managed identity to app service slot (Azure#20961)
* [AppService]: fix Azure#13109 - Assigning user assigned managed identity to app service slot * Addressed review comments * Update NewAzureWebAppSlot.cs * Update NewAzureWebAppSlot.cs --------- Co-authored-by: Beisi Zhou <[email protected]>
1 parent 37e14ec commit e100d5a

File tree

6 files changed

+506
-483
lines changed

6 files changed

+506
-483
lines changed

src/Websites/Websites.Test/ScenarioTests/WebAppSlotTests.ps1

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -439,7 +439,7 @@ function Test-SetWebAppSlot
439439
Assert-AreEqual $serverFarm1.Id $webApp.ServerFarmId
440440

441441
# Create deployment slot
442-
$slot = New-AzWebAppSlot -ResourceGroupName $rgname -Name $appname -Slot $slotname -AppServicePlan $planName1
442+
$slot = New-AzWebAppSlot -ResourceGroupName $rgname -Name $appname -Slot $slotname -AppServicePlan $planName1 -CopyIdentity
443443
$appWithSlotName = "$appname/$slotname"
444444

445445
# Assert

src/Websites/Websites.Test/SessionRecords/Microsoft.Azure.Commands.Websites.Test.ScenarioTests.WebAppSlotTests/TestCreateNewWebAppSlot.json

Lines changed: 387 additions & 387 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+
* Added a new parameter `-CopyIdentity` for `New-AzWebAppSlot` to copy the identity from the parent app to the slot.
2122
* Updated `New-AzWebAppSSLBinding` to support -WhatIf parameter
2223

2324
## Version 2.12.1

src/Websites/Websites/Cmdlets/DeploymentSlots/NewAzureWebAppSlot.cs

Lines changed: 99 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ namespace Microsoft.Azure.Commands.WebApps.Cmdlets.DeploymentSlots
3535
public class NewAzureWebAppSlotCmdlet : WebAppBaseClientCmdLet
3636
{
3737

38-
[Parameter(Position = 0, Mandatory = true, HelpMessage = "The name of the resource group.")]
38+
[Parameter(Position = 0, Mandatory = true, HelpMessage = "The name of the resource group.")]
3939
[ResourceGroupCompleter]
4040
[ValidateNotNullOrEmpty]
4141
public string ResourceGroupName { get; set; }
@@ -77,98 +77,102 @@ public class NewAzureWebAppSlotCmdlet : WebAppBaseClientCmdLet
7777
[ValidateNotNullOrEmpty]
7878
public string AseResourceGroupName { get; set; }
7979

80-
[Parameter(Mandatory = false, HelpMessage = "Container Image Name and optional tag, for example (image:tag)")]
81-
[ValidateNotNullOrEmpty]
82-
public string ContainerImageName { get; set; }
83-
84-
[Parameter(Mandatory = false, HelpMessage = "Private Container Registry Server Url")]
85-
[ValidateNotNullOrEmpty]
86-
public string ContainerRegistryUrl { get; set; }
87-
88-
[Parameter(Mandatory = false, HelpMessage = "Private Container Registry Username")]
89-
[ValidateNotNullOrEmpty]
90-
public string ContainerRegistryUser { get; set; }
91-
92-
[Parameter(Mandatory = false, HelpMessage = "Private Container Registry Password")]
93-
[ValidateNotNullOrEmpty]
94-
public SecureString ContainerRegistryPassword { get; set; }
95-
96-
[Parameter(Mandatory = false, HelpMessage = "Enables/Disables container continuous deployment webhook")]
97-
public SwitchParameter EnableContainerContinuousDeployment { get; set; }
98-
99-
100-
[Parameter(Mandatory = false, HelpMessage = "Run cmdlet in the background")]
101-
public SwitchParameter AsJob { get; set; }
102-
103-
[Parameter(Mandatory = false, HelpMessage = "Tags are name/value pairs that enable you to categorize resources")]
104-
public Hashtable Tag { get; set; }
105-
106-
private Hashtable GetAppSettingsToUpdate()
107-
{
108-
Hashtable appSettings = new Hashtable();
109-
if (ContainerRegistryUrl != null)
110-
{
111-
appSettings[CmdletHelpers.DockerRegistryServerUrl] = ContainerRegistryUrl;
112-
}
113-
if (ContainerRegistryUser != null)
114-
{
115-
appSettings[CmdletHelpers.DockerRegistryServerUserName] = ContainerRegistryUser;
116-
}
117-
if (ContainerRegistryPassword != null)
118-
{
119-
appSettings[CmdletHelpers.DockerRegistryServerPassword] = ContainerRegistryPassword.ConvertToString();
120-
}
121-
if (EnableContainerContinuousDeployment.IsPresent)
122-
{
123-
appSettings[CmdletHelpers.DockerEnableCI] = "true";
124-
}
125-
return appSettings;
126-
}
127-
128-
private void UpdateConfigIfNeeded(Site site)
129-
{
130-
SiteConfig siteConfig = site.SiteConfig;
131-
132-
bool configUpdateRequired = false;
80+
[Parameter(Mandatory = false, HelpMessage = "Container Image Name and optional tag, for example (image:tag)")]
81+
[ValidateNotNullOrEmpty]
82+
public string ContainerImageName { get; set; }
83+
84+
[Parameter(Mandatory = false, HelpMessage = "Private Container Registry Server Url")]
85+
[ValidateNotNullOrEmpty]
86+
public string ContainerRegistryUrl { get; set; }
87+
88+
[Parameter(Mandatory = false, HelpMessage = "Private Container Registry Username")]
89+
[ValidateNotNullOrEmpty]
90+
public string ContainerRegistryUser { get; set; }
91+
92+
[Parameter(Mandatory = false, HelpMessage = "Private Container Registry Password")]
93+
[ValidateNotNullOrEmpty]
94+
public SecureString ContainerRegistryPassword { get; set; }
95+
96+
[Parameter(Mandatory = false, HelpMessage = "Enables/Disables container continuous deployment webhook")]
97+
public SwitchParameter EnableContainerContinuousDeployment { get; set; }
98+
99+
[Parameter( Mandatory = false, HelpMessage = "Copies the managed identity from the parent or source WebApp")]
100+
[ValidateNotNullOrEmpty]
101+
public SwitchParameter CopyIdentity { get; set; }
102+
103+
[Parameter(Mandatory = false, HelpMessage = "Run cmdlet in the background")]
104+
public SwitchParameter AsJob { get; set; }
105+
106+
[Parameter(Mandatory = false, HelpMessage = "Tags are name/value pairs that enable you to categorize resources")]
107+
public Hashtable Tag { get; set; }
108+
109+
private Hashtable GetAppSettingsToUpdate()
110+
{
111+
Hashtable appSettings = new Hashtable();
112+
if (ContainerRegistryUrl != null)
113+
{
114+
appSettings[CmdletHelpers.DockerRegistryServerUrl] = ContainerRegistryUrl;
115+
}
116+
if (ContainerRegistryUser != null)
117+
{
118+
appSettings[CmdletHelpers.DockerRegistryServerUserName] = ContainerRegistryUser;
119+
}
120+
if (ContainerRegistryPassword != null)
121+
{
122+
appSettings[CmdletHelpers.DockerRegistryServerPassword] = ContainerRegistryPassword.ConvertToString();
123+
}
124+
if (EnableContainerContinuousDeployment.IsPresent)
125+
{
126+
appSettings[CmdletHelpers.DockerEnableCI] = "true";
127+
}
128+
return appSettings;
129+
}
130+
131+
private void UpdateConfigIfNeeded(Site site)
132+
{
133+
SiteConfig siteConfig = site.SiteConfig;
134+
135+
bool configUpdateRequired = false;
133136

134-
if (ContainerImageName != null)
135-
{
136-
if (site.IsXenon.GetValueOrDefault())
137-
{
138-
siteConfig.WindowsFxVersion = CmdletHelpers.DockerImagePrefix + ContainerImageName;
139-
configUpdateRequired = true;
140-
}
141-
}
142-
143-
Hashtable appSettings = GetAppSettingsToUpdate();
144-
if (appSettings.Count > 0)
145-
{
146-
configUpdateRequired = true;
147-
}
148-
149-
if (configUpdateRequired && siteConfig.AppSettings != null)
150-
{
151-
foreach (NameValuePair nameValuePair in siteConfig.AppSettings)
152-
{
153-
if (!appSettings.ContainsKey(nameValuePair.Name))
154-
{
155-
appSettings[nameValuePair.Name] = nameValuePair.Value;
156-
}
157-
}
158-
}
159-
160-
if (configUpdateRequired)
161-
{
162-
WebsitesClient.UpdateWebAppConfiguration(ResourceGroupName, site.Location, Name, Slot, siteConfig, appSettings.ConvertToStringDictionary());
163-
site = WebsitesClient.GetWebApp(ResourceGroupName, Name, Slot);
164-
}
165-
WriteObject(site);
166-
}
167-
public override void ExecuteCmdlet()
137+
if (ContainerImageName != null)
138+
{
139+
if (site.IsXenon.GetValueOrDefault())
140+
{
141+
siteConfig.WindowsFxVersion = CmdletHelpers.DockerImagePrefix + ContainerImageName;
142+
configUpdateRequired = true;
143+
}
144+
}
145+
146+
Hashtable appSettings = GetAppSettingsToUpdate();
147+
if (appSettings.Count > 0)
148+
{
149+
configUpdateRequired = true;
150+
}
151+
152+
if (configUpdateRequired && siteConfig.AppSettings != null)
153+
{
154+
foreach (NameValuePair nameValuePair in siteConfig.AppSettings)
155+
{
156+
if (!appSettings.ContainsKey(nameValuePair.Name))
157+
{
158+
appSettings[nameValuePair.Name] = nameValuePair.Value;
159+
}
160+
}
161+
}
162+
163+
if (configUpdateRequired)
164+
{
165+
WebsitesClient.UpdateWebAppConfiguration(ResourceGroupName, site.Location, Name, Slot, siteConfig, appSettings.ConvertToStringDictionary());
166+
site = WebsitesClient.GetWebApp(ResourceGroupName, Name, Slot);
167+
}
168+
WriteObject(site);
169+
}
170+
171+
public override void ExecuteCmdlet()
168172
{
169173
base.ExecuteCmdlet();
170-
171-
CloningInfo cloningInfo = null;
174+
ManagedServiceIdentity sourceIdentity = null;
175+
CloningInfo cloningInfo = null;
172176
if (SourceWebApp != null)
173177
{
174178
cloningInfo = new CloningInfo
@@ -181,11 +185,13 @@ public override void ExecuteCmdlet()
181185
AppSettingsOverrides = AppSettingsOverrides == null ? null : AppSettingsOverrides.Cast<DictionaryEntry>().ToDictionary(kvp => kvp.Key.ToString(), kvp => kvp.Value.ToString(), StringComparer.Ordinal)
182186
};
183187
cloningInfo = new PSCloningInfo(cloningInfo);
184-
}
188+
if(CopyIdentity.IsPresent) sourceIdentity = SourceWebApp.Identity;
189+
}
185190

186191
var webApp = new PSSite(WebsitesClient.GetWebApp(ResourceGroupName, Name, null));
187-
var site = new PSSite(WebsitesClient.CreateWebApp(ResourceGroupName, Name, Slot, webApp.Location, AppServicePlan==null?webApp.ServerFarmId : AppServicePlan, cloningInfo, AseName, AseResourceGroupName, (IDictionary<string, string>)CmdletHelpers.ConvertToStringDictionary(Tag)));
188-
UpdateConfigIfNeeded(site);
192+
if (CopyIdentity.IsPresent && sourceIdentity == null) sourceIdentity = webApp.Identity;
193+
var site = new PSSite(WebsitesClient.CreateWebApp(ResourceGroupName, Name, Slot, webApp.Location, AppServicePlan==null?webApp.ServerFarmId : AppServicePlan, cloningInfo, AseName, AseResourceGroupName, (IDictionary<string, string>)CmdletHelpers.ConvertToStringDictionary(Tag),sourceIdentity));
194+
UpdateConfigIfNeeded(site);
189195
}
190196
}
191197
}

src/Websites/Websites/Utilities/WebsitesClient.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ public WebSiteManagementClient WrappedWebsitesClient
5353
private set;
5454
}
5555

56-
public Site CreateWebApp(string resourceGroupName, string webAppName, string slotName, string location, string serverFarmId, CloningInfo cloningInfo, string aseName, string aseResourceGroupName, IDictionary<string, string> tags = null)
56+
public Site CreateWebApp(string resourceGroupName, string webAppName, string slotName, string location, string serverFarmId, CloningInfo cloningInfo, string aseName, string aseResourceGroupName, IDictionary<string, string> tags = null, ManagedServiceIdentity sourceIdentity=null)
5757
{
5858
Site createdWebSite = null;
5959
string qualifiedSiteName;
@@ -69,7 +69,8 @@ public Site CreateWebApp(string resourceGroupName, string webAppName, string slo
6969
ServerFarmId = serverFarmId,
7070
CloningInfo = cloningInfo,
7171
HostingEnvironmentProfile = profile,
72-
Tags = tags
72+
Tags = tags,
73+
Identity = sourceIdentity
7374
});
7475
}
7576
else

src/Websites/Websites/help/New-AzWebAppSlot.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,21 @@ Accept pipeline input: False
175175
Accept wildcard characters: False
176176
```
177177
178+
### -CopyIdentity
179+
Copies the managed identity from the parent or source WebApp.
180+
181+
```yaml
182+
Type: System.Management.Automation.SwitchParameter
183+
Parameter Sets: (All)
184+
Aliases:
185+
186+
Required: False
187+
Position: Named
188+
Default value: None
189+
Accept pipeline input: False
190+
Accept wildcard characters: False
191+
```
192+
178193
### -DefaultProfile
179194
The credentials, account, tenant, and subscription used for communication with azure.
180195

0 commit comments

Comments
 (0)