Skip to content

Commit c75ae2b

Browse files
authored
fix: Backup-AzApiManagementService: Use managed identity for connection between APIM and Storage Account (#427)
* use managed identity for connection between APIM and Storage Account * updated and added tests * add delays to see if this solves integration test issues * add delay * change default retry interval and remove `Start-Sleep -Seconds 40` * RetryIntervalSeconds fixes * simply script by using $DefaultProfile as $null in the `Backup-AzApiManagement` command if not supplied * simplify script
1 parent 0c98155 commit c75ae2b

8 files changed

Lines changed: 123 additions & 56 deletions

File tree

docs/preview/03-Features/powershell/azure-api-management.md

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -17,16 +17,18 @@ PS> Install-Module -Name Arcus.Scripting.ApiManagement
1717

1818
Backs up an API Management service (with built-in storage context retrieval).
1919

20-
| Parameter | Mandatory | Description |
21-
| --------------------------------- | --------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- |
22-
| `ResourceGroupName` | yes | The name of the of resource group under which the API Management deployment exists. |
23-
| `StorageAccountResourceGroupName` | yes | The name of the resource group under which the storage account exists. |
24-
| `StorageAccountName` | yes | The name of the Storage account for which this cmdlet gets keys. |
25-
| `ServiceName` | yes | The name of the API Management deployment that this cmdlet backs up. |
26-
| `ContainerName` | yes | The name of the container of the blob for the backup. If the container does not exist, this cmdlet creates it. |
27-
| `BlobName` | no | The name of the blob for the backup. If the blob does not exist, this cmdlet creates it (default value based on pattern: `{Name}-{yyyy-MM-dd-HH-mm}.apimbackup`. |
28-
| `PassThru` | no | Indicates that this cmdlet returns the backed up PsApiManagement object, if the operation succeeds. |
29-
| `DefaultProfile` | no | The credentials, account, tenant, and subscription used for communication with azure. |
20+
| Parameter | Mandatory | Description |
21+
| --------------------------------- | --------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
22+
| `ResourceGroupName` | yes | The name of the of resource group under which the API Management deployment exists. |
23+
| `StorageAccountResourceGroupName` | yes | The name of the resource group under which the storage account exists. |
24+
| `StorageAccountName` | yes | The name of the Storage account for which this cmdlet gets keys. |
25+
| `ServiceName` | yes | The name of the API Management deployment that this cmdlet backs up. |
26+
| `ContainerName` | yes | The name of the container of the blob for the backup. If the container does not exist, this cmdlet creates it. |
27+
| `AccessType` | yes | The type of access to be used for the connection from APIM to the storage account, valid values are `SystemAssignedManagedIdentity` and `UserAssignedManagedIdentity`. |
28+
| `IdentityClientId` | no | The client id of the managed identity to connect from API Management to Storage Account, this is only required when AccessType is set to `UserAssignedManagedIdentity`. |
29+
| `BlobName` | no | The name of the blob for the backup. If the blob does not exist, this cmdlet creates it (default value based on pattern: `{Name}-{yyyy-MM-dd-HH-mm}.apimbackup`. |
30+
| `PassThru` | no | Indicates that this cmdlet returns the backed up PsApiManagement object, if the operation succeeds. |
31+
| `DefaultProfile` | no | The credentials, account, tenant, and subscription used for communication with azure. |
3032

3133
**Example**
3234

@@ -38,7 +40,8 @@ PS> Backup-AzApiManagementService `
3840
-StorageAccountResourceGroupName "my-storage-account-resource-group" `
3941
-StorageAccountName "my-storage-account" `
4042
-ServiceName "my-service" `
41-
-ContainerName "my-target-blob-container"
43+
-ContainerName "my-target-blob-container" `
44+
-AccessType "SystemAssignedManagedIdentity"
4245
# New Azure storage context for storage account 'my-storage-account' with storage key created!
4346
# Azure API management service 'my-service' in resource group 'my-resource-group' is backed-up!
4447
```

docs/preview/03-Features/powershell/azure-storage/azure-storage-table.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ PS> Install-Module -Name Arcus.Scripting.Storage.Table
2323
| `StorageAccountName` | yes | The name of the Azure Storage Account to add the table to |
2424
| `TableName` | yes | The name of the table to add on the Azure Storage Account |
2525
| `Recreate` | no | The optional flag to indicate whether or not a possible already existing table should be deleted and re-created |
26-
| `RetryIntervalSeconds` | no | The optional amount of seconds to wait each retry-run when a failure occurs during the re-creating process (default: 5s) |
26+
| `RetryIntervalSeconds` | no | The optional amount of seconds to wait each retry-run when a failure occurs during the re-creating process (default: 10s) |
2727
| `MaxRetryCount` | no | The optional maximum amount of retry-runs should happen when a failure occurs during the re-creating process (default: 10) |
2828

2929
**Example**
@@ -49,8 +49,8 @@ PS> Create-AzStorageTable `
4949
-Recreate `
5050
-RetryIntervalSeconds 3
5151
# Azure storage table 'products' has been removed from Azure storage account 'admin'
52-
# Failed to re-create the Azure storage table 'products' in Azure storage account 'admin', retrying in 5 seconds...
53-
# Failed to re-create the Azure storage table 'products' in Azure storage account 'admin', retrying in 5 seconds...
52+
# Failed to re-create the Azure storage table 'products' in Azure storage account 'admin', retrying in 3 seconds...
53+
# Failed to re-create the Azure storage table 'products' in Azure storage account 'admin', retrying in 3 seconds...
5454
# Azure storage table 'products' created in Azure storage account 'admin'
5555
```
5656

src/Arcus.Scripting.ApiManagement/Arcus.Scripting.ApiManagement.psm1

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,12 @@
2121
.Parameter ContainerName
2222
The name of the container of the blob for the backup. If the container does not exist, this cmdlet creates it.
2323
24+
.Parameter AccessType
25+
The type of access to be used for the connection from APIM to the storage account, valid values are `SystemAssignedManagedIdentity` and `UserAssignedManagedIdentity`.
26+
27+
.Parameter IdentityClientId
28+
The client id of the managed identity to connect from API Management to Storage Account, this is only required when AccessType is set to `UserAssignedManagedIdentity`.
29+
2430
.Parameter BlobName
2531
The name of the blob for the backup. If the blob does not exist, this cmdlet creates it.
2632
This cmdlet generates a default value based on the following pattern: {Name}-{yyyy-MM-dd-HH-mm}.apimbackup
@@ -36,17 +42,19 @@ function Backup-AzApiManagementService {
3642
[Parameter(Mandatory = $true)][string] $ResourceGroupName = $(throw "Resource group name is required"),
3743
[Parameter(Mandatory = $true)][string] $StorageAccountResourceGroupName = $(throw = "Resource group for storage account is required"),
3844
[Parameter(Mandatory = $true)][string] $StorageAccountName = $(throw "Storage account name is required"),
39-
[Parameter(Mandatory = $true)][string] $ServiceName = $(throw "API managgement service name is required"),
45+
[Parameter(Mandatory = $true)][string] $ServiceName = $(throw "API management service name is required"),
4046
[Parameter(Mandatory = $true)][string] $ContainerName = $(throw "Name of the target blob container is required"),
47+
[Parameter(Mandatory = $true)][string][ValidateSet('SystemAssignedManagedIdentity', 'UserAssignedManagedIdentity')] $AccessType = $(throw "The access type is required"),
48+
[Parameter(Mandatory = $false)][string] $IdentityClientId = "",
4149
[Parameter(Mandatory = $false)][string] $BlobName = $null,
4250
[Parameter(Mandatory = $false)][switch] $PassThru = $false,
4351
[Parameter(Mandatory = $false)][Microsoft.Azure.Commands.Common.Authentication.Abstractions.Core.IAzureContextContainer] $DefaultProfile = $null
4452
)
4553

4654
if ($PassThru) {
47-
. $PSScriptRoot\Scripts\Backup-AzApiManagementService.ps1 -ResourceGroupName $ResourceGroupName -StorageAccountResourceGroupName $StorageAccountResourceGroupName -StorageAccountName $StorageAccountName -ServiceName $ServiceName -ContainerName $ContainerName -BlobName $BlobName -PassThru
55+
. $PSScriptRoot\Scripts\Backup-AzApiManagementService.ps1 -ResourceGroupName $ResourceGroupName -StorageAccountResourceGroupName $StorageAccountResourceGroupName -StorageAccountName $StorageAccountName -ServiceName $ServiceName -ContainerName $ContainerName -AccessType $AccessType -IdentityClientId $IdentityClientId -BlobName $BlobName -PassThru
4856
} else {
49-
. $PSScriptRoot\Scripts\Backup-AzApiManagementService.ps1 -ResourceGroupName $ResourceGroupName -StorageAccountResourceGroupName $StorageAccountResourceGroupName -StorageAccountName $StorageAccountName -ServiceName $ServiceName -ContainerName $ContainerName -BlobName $BlobName
57+
. $PSScriptRoot\Scripts\Backup-AzApiManagementService.ps1 -ResourceGroupName $ResourceGroupName -StorageAccountResourceGroupName $StorageAccountResourceGroupName -StorageAccountName $StorageAccountName -ServiceName $ServiceName -ContainerName $ContainerName -AccessType $AccessType -IdentityClientId $IdentityClientId -BlobName $BlobName
5058
}
5159
}
5260

src/Arcus.Scripting.ApiManagement/Scripts/Backup-AzApiManagementService.ps1

Lines changed: 30 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,19 @@ param(
22
[Parameter(Mandatory = $true)][string] $ResourceGroupName = $(throw "Resource group name is required"),
33
[Parameter(Mandatory = $true)][string] $StorageAccountResourceGroupName = $(throw = "Resource group for storage account is required"),
44
[Parameter(Mandatory = $true)][string] $StorageAccountName = $(throw "Storage account name is required"),
5-
[Parameter(Mandatory = $true)][string] $ServiceName = $(throw "API managgement service name is required"),
5+
[Parameter(Mandatory = $true)][string] $ServiceName = $(throw "API management service name is required"),
66
[Parameter(Mandatory = $true)][string] $ContainerName = $(throw "Name of the target blob container is required"),
7-
[Parameter(Mandatory = $false)][string] $BlobName = $null,
7+
[Parameter(Mandatory = $true)][string][ValidateSet('SystemAssignedManagedIdentity', 'UserAssignedManagedIdentity')] $AccessType = $(throw "The access type is required"),
8+
[Parameter(Mandatory = $false)][string] $IdentityClientId = "",
9+
[Parameter(Mandatory = $false)][string] $BlobName = $null,
810
[Parameter(Mandatory = $false)][switch] $PassThru = $false,
911
[Parameter(Mandatory = $false)][Microsoft.Azure.Commands.Common.Authentication.Abstractions.Core.IAzureContextContainer] $DefaultProfile = $null
1012
)
1113

14+
if ($AccessType -eq 'UserAssignedManagedIdentity' -and $IdentityClientId -eq "") {
15+
throw "Id of the user assigned managed identity is required if AccessType is set to 'UserAssignedManagedIdentity'"
16+
}
17+
1218
Write-Verbose "Getting Azure storage account key for storage account '$($StorageAccountName)' in resource group '$($StorageAccountResourceGroupName)'..."
1319
$storageKeys = Get-AzStorageAccountKey -ResourceGroupName $StorageAccountResourceGroupName -StorageAccountName $StorageAccountName
1420

@@ -22,36 +28,30 @@ if ($storageKeys -eq $null -or $storageKeys.count -eq 0) {
2228
$storageContext = New-AzStorageContext -StorageAccountName $StorageAccountName -StorageAccountKey $storageKey.Value
2329
Write-Host "New Azure storage context for storage account '$($StorageAccountName)' with storage key created!" -ForegroundColor Green
2430

25-
Write-Verbose "Start backing up Azure API Management instance '$($ServiceName)' in resource group '$($ResourceGroupName)'..."
26-
if ($BlobName -ne $null) {
27-
if ($PassThru) {
28-
if ($DefaultProfile -ne $null) {
29-
Backup-AzApiManagement -ResourceGroupName $ResourceGroupName -Name $ServiceName -StorageContext $storageContext -TargetContainerName $ContainerName -TargetBlobName $BlobName -PassThru -DefaultProfile $DefaultProfile
30-
} else {
31-
Backup-AzApiManagement -ResourceGroupName $ResourceGroupName -Name $ServiceName -StorageContext $storageContext -TargetContainerName $ContainerName -TargetBlobName $BlobName -PassThru
32-
}
33-
} else {
34-
if ($DefaultProfile -ne $null) {
35-
Backup-AzApiManagement -ResourceGroupName $ResourceGroupName -Name $ServiceName -StorageContext $storageContext -TargetContainerName $ContainerName -TargetBlobName $BlobName -DefaultProfile $DefaultProfile
36-
} else {
37-
Backup-AzApiManagement -ResourceGroupName $ResourceGroupName -Name $ServiceName -StorageContext $storageContext -TargetContainerName $ContainerName -TargetBlobName $BlobName
38-
}
39-
}
31+
$backupArguments = @{
32+
ResourceGroupName = $ResourceGroupName
33+
Name = $ServiceName
34+
AccessType = $AccessType
35+
StorageContext = $storageContext
36+
TargetContainerName = $ContainerName
37+
DefaultProfile = $DefaultProfile
38+
}
39+
40+
if ($PassThru) {
41+
$backupArguments.PassThru = $true
4042
} else {
41-
if ($PassThru) {
42-
if ($DefaultProfile -ne $null) {
43-
Backup-AzApiManagement -ResourceGroupName $ResourceGroupName -Name $ServiceName -StorageContext $storageContext -TargetContainerName $ContainerName -PassThru -DefaultProfile $DefaultProfile
44-
} else {
45-
Backup-AzApiManagement -ResourceGroupName $ResourceGroupName -Name $ServiceName -StorageContext $storageContext -TargetContainerName $ContainerName -PassThru
46-
}
47-
} else {
48-
if ($DefaultProfile -ne $null) {
49-
Backup-AzApiManagement -ResourceGroupName $ResourceGroupName -Name $ServiceName -StorageContext $storageContext -TargetContainerName $ContainerName -DefaultProfile $DefaultProfile
50-
} else {
51-
Backup-AzApiManagement -ResourceGroupName $ResourceGroupName -Name $ServiceName -StorageContext $storageContext -TargetContainerName $ContainerName
52-
}
53-
}
43+
$backupArguments.PassThru = $false
5444
}
5545

46+
if ($AccessType -eq 'UserAssignedManagedIdentity') {
47+
$backupArguments.IdentityClientId = $IdentityClientId
48+
}
49+
50+
if ($BlobName -ne $null -and $BlobName -ne "") {
51+
$backupArguments.TargetBlobName = $BlobName
52+
}
53+
54+
Write-Verbose "Start backing up Azure API Management instance '$($ServiceName)' in resource group '$($ResourceGroupName)'..."
55+
Backup-AzApiManagement @backupArguments
5656
Write-Host "Azure API Management instance '$($ServiceName)' in resource group '$($ResourceGroupName)' is backed-up!" -ForegroundColor Green
5757
}

src/Arcus.Scripting.Storage.Table/Arcus.Scripting.Storage.Table.psm1

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ function Create-AzStorageTable {
2929
[Parameter(Mandatory = $true)][string] $StorageAccountName = $(throw "Name of Azure storage account is required"),
3030
[Parameter(Mandatory = $true)][string] $TableName = $(throw "Name of Azure table is required"),
3131
[Parameter()][switch] $Recreate = $false,
32-
[Parameter(Mandatory = $false)][int] $RetryIntervalSeconds = 5,
32+
[Parameter(Mandatory = $false)][int] $RetryIntervalSeconds = 10,
3333
[Parameter(Mandatory = $false)][int] $MaxRetryCount = 10
3434
)
3535

src/Arcus.Scripting.Storage.Table/Scripts/Create-AzTableStorageAccountTable.ps1

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ param(
33
[Parameter(Mandatory = $true)][string] $StorageAccountName = $(throw "Name of Azure storage account is required"),
44
[Parameter(Mandatory = $true)][string] $TableName = $(throw "Name of Azure table is required"),
55
[Parameter()][switch] $Recreate = $false,
6-
[Parameter(Mandatory = $false)][int] $RetryIntervalSeconds = 5,
6+
[Parameter(Mandatory = $false)][int] $RetryIntervalSeconds = 10,
77
[Parameter(Mandatory = $false)][int] $MaxRetryCount = 10
88
)
99

@@ -55,7 +55,7 @@ if ($TableName -in $tables.Name) {
5555

5656
$retryIndex = 1
5757
while (-not (Try-CreateTable -StorageAccount $storageAccount -TableName $TableName -RetryIndex $retryIndex)) {
58-
Write-Warning "Failed to re-create the Azure storage table '$TableName' in Azure storage account '$StorageAccountName', retrying in 5 seconds..."
58+
Write-Warning "Failed to re-create the Azure storage table '$TableName' in Azure storage account '$StorageAccountName', retrying in '$RetryIntervalSeconds' seconds..."
5959
$retryIndex = $retryIndex + 1
6060
Start-Sleep -Seconds $RetryIntervalSeconds
6161
}

src/Arcus.Scripting.Tests.Integration/Arcus.Scripting.Security.tests.ps1

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,13 @@ InModuleScope Arcus.Scripting.Security {
5757
-LockLevel CanNotDelete `
5858
-Force
5959

60+
Start-Sleep -Seconds 10
61+
6062
try {
6163
# Act
6264
Remove-AzResourceGroupLocks -ResourceGroupName $targetResourceGroupName -LockName $lockName
65+
66+
Start-Sleep -Seconds 10
6367

6468
# Assert
6569
$locks = Get-AzResourceLock -ResourceGroupName $targetResourceGroupName
@@ -89,9 +93,13 @@ InModuleScope Arcus.Scripting.Security {
8993
-LockLevel CanNotDelete `
9094
-Force
9195

96+
Start-Sleep -Seconds 10
97+
9298
try {
9399
# Act
94100
Remove-AzResourceGroupLocks -ResourceGroupName $targetResourceGroupName
101+
102+
Start-Sleep -Seconds 10
95103

96104
# Assert
97105
$locks = Get-AzResourceLock -ResourceGroupName $targetResourceGroupName

0 commit comments

Comments
 (0)