functions/azure/Set-TemporaryAzureResourceNetworkAccess.Tests.ps1
$here = Split-Path -Parent $MyInvocation.MyCommand.Path $sut = (Split-Path -Leaf $MyInvocation.MyCommand.Path).Replace(".Tests.ps1", ".ps1") . "$here\$sut" # load the handler implementations Get-ChildItem "$here\_azureResourceNetworkAccessHandlers\*.ps1" | ForEach-Object { . $_.FullName } # Suppress the connection validation logic function _EnsureAzureConnection {} Describe "Set-TemporaryAzureResourceNetworkAccess Integration Tests" -Tag Integration { BeforeAll { $currentUser = Get-AzADUser -SignedIn # Generate stable user-specific naming conventions that will work for users and service principals $suffix = ($currentUser.Id -replace "-","").SubString(0,20) $rg = "pester-tempnetaccess-$($currentUser.Id)" $location = "uksouth" New-AzResourceGroup -ResourceGroupName $rg -Location $location -Tag @{Environment = "Pester"} -Force } AfterAll { Write-Host "`n`nCleaning-up Azure test resources..." Remove-AzResourceGroup -ResourceGroupName $rg -Force Remove-AzKeyVault -VaultName $suffix -Location $location -InRemovedState -Force } Context "Azure Storage Account" { Mock Write-Host {} BeforeAll { # Create storage account $saParams = @{ ResourceGroupName = $rg Name = $suffix Tag = @{Environment = "Pester"} Kind = "StorageV2" Sku = "Standard_LRS" AccessTier = "Hot" Location = $location MinimumTlsVersion = "TLS1_2" EnableHttpsTrafficOnly = $true } New-AzStorageAccount @saParams -ErrorAction Ignore | Out-Null $sa = Get-AzStorageAccount -ResourceGroupName $saParams.ResourceGroupName -Name $saParams.Name # Ensure the test has the necessary data-plane permissions New-AzRoleAssignment -Scope $sa.Id -RoleDefinitionName "Storage Blob Data Contributor" -ObjectId $currentUser.Id -ErrorAction Ignore # Lockdown access to the storage account $sa | Update-AzStorageAccountNetworkRuleSet -DefaultAction Deny -Bypass None # Pause to ensure the change has taken effect Write-Host "Waiting for storage firewall to update..." Start-Sleep -Seconds 30 } It "should not have permissions before enabling temporary network access" { { Get-AzStorageBlob -Container "foo" -Blob "foo/bar.txt" -Context $sa.Context -ErrorAction Stop } | Should -Throw "This request is not authorized to perform this operation." } It "should not be able to connect immediately when not waiting for the temporary network access" { Set-TemporaryAzureResourceNetworkAccess -ResourceType StorageAccount -ResourceGroupName $rg -ResourceName $suffix { Get-AzStorageBlob -Container "foo" -Blob "foo/bar.txt" -Context $sa.Context -ErrorAction Stop } | Should -Throw "This request is not authorized to perform this operation." } It "should connect successfully after waiting for the temporary network access" { Start-Sleep -Seconds 30 { Get-AzStorageBlob -Container "foo" -Blob "foo/bar.txt" -Context $sa.Context -ErrorAction Stop } | Should -Throw "Can not find blob 'foo/bar.txt' in container 'foo', or the blob type is unsupported." } It "should not have permissions after using the 'Revoke' flag" { Set-TemporaryAzureResourceNetworkAccess -ResourceType StorageAccount -ResourceGroupName $rg -ResourceName $suffix -Revoke -Wait { Get-AzStorageBlob -Container "foo" -Blob "foo/bar.txt" -Context $sa.Context -ErrorAction Stop } | Should -Throw "This request is not authorized to perform this operation." } } Context "Azure SQL Server" { Mock Write-Host {} BeforeAll { # Create SQL server $sqlParams = @{ ResourceGroupName = $rg ServerName = $suffix Tags = @{Environment = "Pester"} EnableActiveDirectoryOnlyAuthentication = $true ExternalAdminName = $currentUser.UserPrincipalName MinimalTlsVersion = "1.2" Location = $location } New-AzSqlServer @sqlParams -ErrorAction Ignore | Out-Null $server = Get-AzSqlServer -ResourceGroupName $sqlParams.ResourceGroupName -ServerName $sqlParams.ServerName # Prepare the test SQL query $sqlCmd = { Invoke-Sqlcmd ` -Query "select * from sys.tables" ` -ServerInstance "$suffix.database.windows.net" ` -Database master ` -AccessToken (Get-AzAccessToken -ResourceUrl "https://database.windows.net").Token ` -AbortOnError ` -ErrorAction Stop } } It "should not have permissions before enabling temporary network access" { { $sqlCmd.Invoke() } | Should -Throw } It "should connect successfully after enabling temporary network access" { Set-TemporaryAzureResourceNetworkAccess -ResourceType SqlServer -ResourceGroupName $rg -ResourceName $suffix -Wait $res = $sqlCmd.Invoke() $res | Should -Not -BeNullOrEmpty } It "should not have permissions after using the 'Revoke' flag" { Set-TemporaryAzureResourceNetworkAccess -ResourceType SqlServer -ResourceGroupName $rg -ResourceName $suffix -Revoke -Wait { $sqlCmd.Invoke() } | Should -Throw } } Context "Azure Web App" { Mock Write-Host {} BeforeAll { # Create the App Service $aspParams = @{ ResourceGroupName = $rg ResourceType = "microsoft.web/serverfarms" ResourceName = $suffix Sku = @{ name = "B1" tier = "Basic" family = "B" capacity = "1" } Kind = "Linux" Properties = @{ Reserved = $true } Location = $location Force = $true } New-AzResource @aspParams -ErrorAction Ignore | Out-Null $asp = Get-AzAppServicePlan -ResourceGroupName $aspParams.ResourceGroupName -Name $aspParams.ResourceName $webParams = @{ ResourceGroupName = $rg Name = $suffix AppServicePlan = $aspParams.ResourceName ContainerImageName = "nginx:latest" EnableContainerContinuousDeployment = $false Location = $location } New-AzWebApp @webParams -ErrorAction Ignore | Out-Null # Workaround: https://github.com/Azure/azure-powershell/issues/10645 $config = Get-AzResource -ResourceGroupName $rg -ResourceType "Microsoft.Web/sites/config" -ResourceName $suffix -ApiVersion 2018-02-01 $config.Properties.linuxFxVersion = "DOCKER|nginx:latest" $config | Set-AzResource -ApiVersion 2018-02-01 -Force | Out-Null $web = Get-AzWebApp -ResourceGroupName $webParams.ResourceGroupName -Name $webParams.Name # Lockdown web site $config.Properties.ipSecurityRestrictionsDefaultAction = "Deny" $config.Properties.scmIpSecurityRestrictionsUseMain = $true $config | Set-AzResource -ApiVersion 2018-02-01 -Force | Out-Null } It "should not have permissions before enabling temporary network access" { $resp = Invoke-WebRequest -uri https://$($web.DefaultHostName) -SkipHttpErrorCheck $resp.StatusCode | Should -Be 403 } It "should connect successfully after enabling temporary network access" { Set-TemporaryAzureResourceNetworkAccess -ResourceType WebApp -ResourceGroupName $rg -ResourceName $suffix -Wait # Pause to ensure the change has taken effect Start-Sleep -Seconds 5 $resp = Invoke-WebRequest -uri https://$($web.DefaultHostName) $resp.StatusCode | Should -Be 200 } It "should not have permissions after using the 'Revoke' flag" { Set-TemporaryAzureResourceNetworkAccess -ResourceType WebApp -ResourceGroupName $rg -ResourceName $suffix -Revoke -Wait $resp = Invoke-WebRequest -uri https://$($web.DefaultHostName) -SkipHttpErrorCheck $resp.StatusCode | Should -Be 403 } } Context "Azure Key Vault" { Mock Write-Host {} BeforeAll { # Create key vault $kvParams = @{ ResourceGroupName = $rg Name = $suffix Sku = "Standard" Tag = @{Environment = "Pester"} Location = $location EnablePurgeProtection = $false EnableRbacAuthorization = $true } New-AzKeyVault @kvParams -ErrorAction Ignore | Out-Null $kv = Get-AzKeyVault -ResourceGroupName $kvParams.ResourceGroupName -Name $kvParams.Name # Ensure the test has the necessary data-plane permissions New-AzRoleAssignment -Scope $kv.ResourceId -RoleDefinitionName "Key Vault Secrets Officer" -ObjectId $currentUser.Id -ErrorAction Ignore # Lockdown access to the storage account $kv | Update-AzKeyVaultNetworkRuleSet -DefaultAction Deny -Bypass None # Pause to ensure the change has taken effect Write-Host "Waiting for key vault firewall to update..." Start-Sleep -Seconds 10 } It "should not have permissions before enabling temporary network access" { { Get-AzKeyVaultSecret -VaultName $suffix -SecretName "foo" -ErrorAction Stop } | Should -Throw "Operation returned an invalid status code 'Forbidden'" } It "should connect successfully after waiting for the temporary network access" { Set-TemporaryAzureResourceNetworkAccess -ResourceType KeyVault -ResourceGroupName $rg -ResourceName $suffix Start-Sleep -Seconds 5 Get-AzKeyVaultSecret -VaultName $suffix -SecretName "foo" -ErrorAction Stop | Should -Be $null } It "should not have permissions after using the 'Revoke' flag" { Set-TemporaryAzureResourceNetworkAccess -ResourceType KeyVault -ResourceGroupName $rg -ResourceName $suffix -Revoke -Wait { Get-AzKeyVaultSecret -VaultName $suffix -SecretName "foo" -ErrorAction Stop } | Should -Throw "Operation returned an invalid status code 'Forbidden'" } } } |