Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Modules/BenchPress.Azure/BenchPress.Azure.psd1
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
# Generated on: 12/1/2022
@{
RootModule = "BenchPress.Azure.psm1"
ModuleVersion = "0.2.2"
ModuleVersion = "0.2.3"
GUID = "3db0c6b2-7453-4972-a9de-402be1277ac9"
Author = "CSEDevOps"
CompanyName = "Microsoft"
Expand Down
88 changes: 49 additions & 39 deletions Modules/BenchPress.Azure/Private/Connect-Account.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -42,66 +42,76 @@ function Connect-Account {
param ( )
Begin { }
Process {
$useManagedIdentity = Get-EnvironmentVariable AZ_USE_MANAGED_IDENTITY -DontThrowIfMissing
$subscriptionId = Get-EnvironmentVariable AZ_SUBSCRIPTION_ID
$useManagedIdentity = Get-BooleanEnvironmentVariable AZ_USE_MANAGED_IDENTITY
$subscriptionId = Get-EnvironmentVariable AZ_SUBSCRIPTION_ID -DontThrowIfMissing
$applicationId = Get-EnvironmentVariable AZ_APPLICATION_ID -DontThrowIfMissing
$tenantId = Get-EnvironmentVariable AZ_TENANT_ID -DontThrowIfMissing

$currentConnection = Get-AzContext
$results = [AuthenticationResult]::new()

# Login Using Managed Identity
if ($useManagedIdentity) {
$connection = Connect-AzAccount -Identity
$subscriptionName = (Get-AzSubscription -SubscriptionId $subscriptionId).Name
Set-AzContext -Subscription $subscriptionName

if (IsCurrentAccountLoggedIn($currentConnection)) {
$results.Success = $true
$results.AuthenticationData = [AuthenticationData]::new($connection.Context.Subscription.Id)
$results.AuthenticationData = [AuthenticationData]::new(($currentConnection).Subscription.Id)
}
else {
# If the current context matches the subscription, tenant, and service principal, then we're already properly logged in.
$applicationId = Get-EnvironmentVariable AZ_APPLICATION_ID
$tenantId = Get-EnvironmentVariable AZ_TENANT_ID
# Login Using Managed Identity
if ($useManagedIdentity) {
$connection = Connect-AzAccount -Identity
if ($null -ne $subscriptionId) {
$subscriptionName = (Get-AzSubscription -SubscriptionId $subscriptionId).Name
Set-AzContext -Subscription $subscriptionName
}

if (IsCurrentAccountLoggedIn($currentConnection)) {
$results.Success = $true
$results.AuthenticationData = [AuthenticationData]::new(($currentConnection).Subscription.Id)
$results.AuthenticationData = [AuthenticationData]::new($connection.Context.Subscription.Id)
}
else {
# The current context is not correct
# Create the credentials and login to the correct account

$clientSecret = Get-EnvironmentVariable AZ_ENCRYPTED_PASSWORD | ConvertTo-SecureString
$clientSecret = New-Object System.Management.Automation.PSCredential -ArgumentList $applicationId, $clientSecret
# The current context is not correct
# Create the credentials and login to the correct account
$clientSecret = Get-EnvironmentVariable AZ_ENCRYPTED_PASSWORD | ConvertTo-SecureString
$clientSecret = New-Object System.Management.Automation.PSCredential -ArgumentList $applicationId, $clientSecret

try {
$connectionParams = @{
Credential = $clientSecret
TenantId = $tenantId
Subscription = $subscriptionId
if ($null -ne $currentConnection){
Write-Warning "Logging out of current Az.Powershell context and connecting to Subscription: $subscriptionId"
}
$connection = Connect-AzAccount -ServicePrincipal @connectionParams

$results.Success = $true
$results.AuthenticationData = [AuthenticationData]::new($connection.Context.Subscription.Id)
}
catch {
$thrownError = $_
$results.Success = $false
Write-Error $thrownError
}
}
try {
$connectionParams = @{
Credential = $clientSecret
TenantId = $tenantId
Subscription = $subscriptionId
}
$connection = Connect-AzAccount -ServicePrincipal @connectionParams

$results.Success = $true
$results.AuthenticationData = [AuthenticationData]::new($connection.Context.Subscription.Id)
}
catch {
$thrownError = $_
$results.Success = $false
Write-Error $thrownError
}
}
}

$results
}
End { }
}

function IsCurrentAccountLoggedIn($currentConnection) {
if ($null -ne $currentConnection `
-and ($currentConnection).Account.Type -eq 'ServicePrincipal' `
-and ($currentConnection).Account.Id -eq $applicationId `
-and ($currentConnection).Tenant.Id -eq $tenantId `
-and ($currentConnection).Subscription.Id -eq $subscriptionId) {
if ($null -eq $currentConnection) {
return $False
}

if ($null -eq $subscriptionId -or $null -eq $applicationId -or $null -eq $tenantId) {
return $True
}

if ($currentConnection.Account.Id -eq $applicationId `
-and $currentConnection.Tenant.Id -eq $tenantId `
-and $currentConnection.Subscription.Id -eq $subscriptionId) {
return $True
}

Expand Down
23 changes: 23 additions & 0 deletions Modules/BenchPress.Azure/Private/Get-EnvironmentVariable.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -70,3 +70,26 @@ function Get-RequiredEnvironmentVariable {
$value
}
}


function Get-BooleanEnvironmentVariable {
[OutputType([System.Boolean])]
param (
[Parameter(Mandatory = $true, Position = 0)]
[string]$VariableName
)
Begin {
$result = $False
}
Process {
$value = Get-EnvironmentVariable $VariableName -DontThrowIfMissing
try {
$result = [System.Convert]::ToBoolean($value)
} catch [FormatException] {
$result = $False
}
}
End {
$result
}
}
30 changes: 21 additions & 9 deletions Modules/BenchPress.Azure/Tests/Private/Connect-Account.Tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,28 @@ Describe "Connect-Account" {
Mock Connect-AzAccount{}
}

It "Does not Invokes Connect-AzAccount when a context exists" {
# Arrange
Mock Get-EnvironmentVariable{ return "true" } -ParameterFilter { $VariableName -eq "AZ_USE_MANAGED_IDENTITY" -and $DontThrowIfMissing -eq $true }
Mock Set-AzContext {}

Mock Get-AzContext { @{Account = @{Type = "Mocked"; Id = $MockApplicationId};
Tenant = @{Id = $MockTenantId};
Subscription = @{Id = $MockSubscriptionId}}}

# Act
Connect-Account

# Assert Connect-AzAccount was not called and we are using the existing context
Assert-MockCalled Connect-AzAccount -Exactly 0
}

It "Invokes Connect-AzAccount with -Identity when AZ_USE_MANAGED_IDENTITY is set." {
# Arrange
Mock Get-EnvironmentVariable{ return "true" } -ParameterFilter { $VariableName -eq "AZ_USE_MANAGED_IDENTITY" -and $DontThrowIfMissing -eq $true }
Mock Set-AzContext {}

Mock Get-AzContext { @{Account = @{Type = "User"; Id = $MockApplicationId};
Tenant = @{Id = $MockTenantId};
Subscription = @{Id = $MockSubscriptionId}}} `
-Verifiable
Mock Get-AzContext { return $null} -Verifiable

# Act
Connect-Account
Expand All @@ -57,11 +70,10 @@ Describe "Connect-Account" {
}
}

It "Invokes Connect-AzAccount with -ServicePrincipal when the account type is not ServicePrincipal." {
Mock Get-AzContext { @{Account = @{Type = "User"; Id = $MockApplicationId};
Tenant = @{Id = $MockTenantId};
Subscription = @{Id = $MockSubscriptionId}}} `
-Verifiable
It "Invokes Connect-AzAccount with -ServicePrincipal when the context is empty and environment variables exist" {
Mock Get-BooleanEnvironmentVariable{ return $False } -ParameterFilter { $VariableName -eq "AZ_USE_MANAGED_IDENTITY" }
Mock Get-AzContext { return $null } -Verifiable
Mock Set-AzContext {}

Connect-Account

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,15 @@ Describe "Get-ResourceByType" {

Mock $functionName {}

Get-ResourceByType @params
| Should -Invoke -CommandName $Expected -Times 1 -ParameterFilter {$filterString}
if ($filterString -eq "") {
Get-ResourceByType @params
| Should -Invoke -CommandName $Expected -Times 1
}
else{
Get-ResourceByType @params
| Should -Invoke -CommandName $Expected -Times 1 -ParameterFilter {$filterString}
}

}
}
}
Expand Down
6 changes: 3 additions & 3 deletions assets/demos/main.bicep
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ resource applicationInsights 'Microsoft.Insights/components@2020-02-02' = {
}
}

resource emailActionGroup 'Microsoft.Insights/actionGroups@2022-06-01' = {
resource emailActionGroup 'Microsoft.Insights/actionGroups@2023-01-01' = {
name: join( ['benchpress', 'email', 'action', 'group', suffix ], '-')
location: 'global'
properties: {
Expand All @@ -33,7 +33,7 @@ resource emailActionGroup 'Microsoft.Insights/actionGroups@2022-06-01' = {
}
}

resource hostingPlan 'Microsoft.Web/serverfarms@2022-03-01' = {
resource hostingPlan 'Microsoft.Web/serverfarms@2024-04-01' = {
name: join( ['benchpress', 'hosting', 'plan', suffix ], '-')
location: location
sku: {
Expand All @@ -45,7 +45,7 @@ resource hostingPlan 'Microsoft.Web/serverfarms@2022-03-01' = {
}
}

resource webApp 'Microsoft.Web/sites@2022-03-01' = {
resource webApp 'Microsoft.Web/sites@2024-04-01' = {
name: join( ['benchpress', 'web', suffix ], '-')
location: location
identity: {
Expand Down
4 changes: 2 additions & 2 deletions examples/AksCluster/aksCluster.bicep
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
param aksName string = 'aks${take(uniqueString(resourceGroup().id), 5)}'
param location string = resourceGroup().location

resource aksCluster 'Microsoft.ContainerService/managedClusters@2022-09-01' = {
resource aksCluster 'Microsoft.ContainerService/managedClusters@2024-09-01' = {
name: aksName
location: location
identity: {
Expand All @@ -24,7 +24,7 @@ resource aksCluster 'Microsoft.ContainerService/managedClusters@2022-09-01' = {

param agentPoolName string = 'ap${take(uniqueString(resourceGroup().id), 5)}'

resource agentPool 'Microsoft.ContainerService/managedClusters/agentPools@2022-09-01' = {
resource agentPool 'Microsoft.ContainerService/managedClusters/agentPools@2024-09-01' = {
name: agentPoolName
parent: aksCluster
properties: {
Expand Down
12 changes: 6 additions & 6 deletions examples/ApiManagement/ApiManagement.bicep
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
param serviceName string = 'apim${take(uniqueString(resourceGroup().id), 5)}'
param location string = resourceGroup().location

resource apiManagementService 'Microsoft.ApiManagement/service@2022-08-01' = {
resource apiManagementService 'Microsoft.ApiManagement/service@2024-05-01' = {
name: serviceName
location: location
sku: {
Expand All @@ -16,7 +16,7 @@ resource apiManagementService 'Microsoft.ApiManagement/service@2022-08-01' = {

param apiName string = 'api${take(uniqueString(resourceGroup().id), 5)}'

resource api 'Microsoft.ApiManagement/service/apis@2022-08-01' = {
resource api 'Microsoft.ApiManagement/service/apis@2024-05-01' = {
name: apiName
parent: apiManagementService
properties: {
Expand All @@ -28,7 +28,7 @@ resource api 'Microsoft.ApiManagement/service/apis@2022-08-01' = {

param workspaceName string = 'logworkspace${take(uniqueString(resourceGroup().id), 5)}'

resource workspace 'Microsoft.OperationalInsights/workspaces@2022-10-01' = {
resource workspace 'Microsoft.OperationalInsights/workspaces@2023-09-01' = {
name: workspaceName
location: location
properties: {
Expand All @@ -52,7 +52,7 @@ resource applicationInsights 'Microsoft.Insights/components@2020-02-02' = {

param loggerName string = 'log${take(uniqueString(resourceGroup().id), 5)}'

resource logger 'Microsoft.ApiManagement/service/loggers@2022-08-01' = {
resource logger 'Microsoft.ApiManagement/service/loggers@2024-05-01' = {
name: loggerName
parent: apiManagementService
properties: {
Expand All @@ -65,7 +65,7 @@ resource logger 'Microsoft.ApiManagement/service/loggers@2022-08-01' = {

param diagnosticName string = 'applicationinsights'

resource diagnostic 'Microsoft.ApiManagement/service/diagnostics@2022-08-01' = {
resource diagnostic 'Microsoft.ApiManagement/service/diagnostics@2024-05-01' = {
name: diagnosticName
parent: apiManagementService
properties: {
Expand All @@ -75,7 +75,7 @@ resource diagnostic 'Microsoft.ApiManagement/service/diagnostics@2022-08-01' = {

param policyName string = 'policy'

resource apiPolicy 'Microsoft.ApiManagement/service/apis/policies@2022-08-01' = {
resource apiPolicy 'Microsoft.ApiManagement/service/apis/policies@2024-05-01' = {
name: policyName
parent: api
properties: {
Expand Down
4 changes: 2 additions & 2 deletions examples/AppInsights/appInsights.bicep
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ param appInsightsName string = 'appinsights${take(uniqueString(resourceGroup().i
param workspaceName string = 'logworkspace${take(uniqueString(resourceGroup().id), 5)}'
param location string = resourceGroup().location

resource workspace 'Microsoft.OperationalInsights/workspaces@2022-10-01' = {
resource workspace 'Microsoft.OperationalInsights/workspaces@2023-09-01' = {
name: workspaceName
location: location
properties: {
Expand All @@ -21,7 +21,7 @@ resource applicationInsights 'Microsoft.Insights/components@2020-02-02' = {
WorkspaceResourceId: workspace.id
}
}

#disable-next-line use-recent-api-versions //Disabling since this is the latest preview version available.
resource appInsightsDiagnostics 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = {
scope: applicationInsights
name: 'default'
Expand Down
2 changes: 1 addition & 1 deletion examples/AppServicePlan/appServicePlan.bicep
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
param location string = resourceGroup().location
param name string = 'asp${take(uniqueString(resourceGroup().id), 5)}'

resource appServicePlan 'Microsoft.Web/serverfarms@2022-03-01' = {
resource appServicePlan 'Microsoft.Web/serverfarms@2024-04-01' = {
name: name
location: location
sku: {
Expand Down
6 changes: 3 additions & 3 deletions examples/ContainerApp/containerApp.bicep
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ param location string = resourceGroup().location
param targetPort int = 80
param containerImage string = 'mcr.microsoft.com/azuredocs/containerapps-helloworld:latest'

resource logAnalytics 'Microsoft.OperationalInsights/workspaces@2022-10-01' = {
resource logAnalytics 'Microsoft.OperationalInsights/workspaces@2023-09-01' = {
name: 'loganalytics${containerAppName}'
location: location
properties: {
Expand All @@ -13,7 +13,7 @@ resource logAnalytics 'Microsoft.OperationalInsights/workspaces@2022-10-01' = {
}
}

resource containerAppEnv 'Microsoft.App/managedEnvironments@2022-10-01' = {
resource containerAppEnv 'Microsoft.App/managedEnvironments@2024-03-01' = {
name: 'env${containerAppName}'
location: location
sku: {
Expand All @@ -30,7 +30,7 @@ resource containerAppEnv 'Microsoft.App/managedEnvironments@2022-10-01' = {
}
}

resource containerApp 'Microsoft.App/containerApps@2022-10-01' = {
resource containerApp 'Microsoft.App/containerApps@2024-03-01' = {
name: containerAppName
location: location
properties: {
Expand Down
Loading
Loading