I have started using the Azure Developer CLI to standardize & simplify my deployments to Azure (both Infrastructure as Code deployment & application deployment).
I needed to deploy an Azure SQL database and I wanted it to use Azure AD authentication & have IP firewall rules set up by default to allow my local computer to access the DB, but not anyone else.
Normally, I would have had to manually look up my AAD user principal name & IP address manually and pass them in as command line arguments.
Luckily, the Developer CLI includes command and event hooks. These let me inject my own code as various stages of the deployment.
In my case, I wanted to look up these two values (user principal & IP address) and then pass them into the Bicep templates I am using to do my deployment.
Bicep template for deploying Azure SQL
Here is my template for creating the Azure SQL database. Notice that I accept the sqlAdminLoginName
, sqlAdminLoginObjectId
& sqlClientIpAddress
as parameters to the template.
param sqlServerName string
param sqlDbName string
param location string
param sqlAdminLoginName string
param sqlAdminLoginObjectId string
param sqlClientIpAddress string
resource sqlServer 'Microsoft.Sql/servers@2022-05-01-preview' = {
name: sqlServerName
location: location
tags: tags
properties: {
administrators: {
azureADOnlyAuthentication: true
administratorType: 'ActiveDirectory'
tenantId: subscription().tenantId
principalType: 'User'
login: sqlAdminLoginName
sid: sqlAdminLoginObjectId
}
publicNetworkAccess: 'Enabled'
}
}
resource sqlDB 'Microsoft.Sql/servers/databases@2022-05-01-preview' = {
parent: sqlServer
name: sqlDbName
tags: tags
location: location
sku: {
name: 'Standard'
tier: 'Standard'
}
}
resource clientFirewallRules 'Microsoft.Sql/servers/firewallRules@2022-08-01-preview' = {
name: 'AllowClientIp'
parent: sqlServer
properties: {
startIpAddress: sqlClientIpAddress
endIpAddress: sqlClientIpAddress
}
}
Bicep parameters
In my main.parameters.json
file, I use the Developer CLI placeholders for the values I need populated when the template is deployed. The Developer CLI will substitute the correct values.
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"environmentName": {
"value": "${AZURE_ENV_NAME}"
},
"location": {
"value": "${AZURE_LOCATION}"
},
"sqlAdminLoginName": {
"value": "${AZURE_PRINCIPAL_NAME}"
},
"sqlAdminLoginObjectId": {
"value": "${AZURE_PRINCIPAL_ID}"
},
"sqlClientIpAddress": {
"value": "${MY_IP}"
}
}
}
The AZURE_ENV_NAME
, AZURE_LOCATION
& AZURE_PRINCIPAL_ID
are default environment variables that the Azure Developer CLI will always have & populate. I needed to add and populate the AZURE_PRINCIPAL_NAME
and MY_IP
environment variables.
preprovision
Azure Developer CLI hook
Now for the magic. The Developer CLI exposes the preprovision
hook that I can add my own code into that will run before the Bicep templates are deployed.
In the azure.yaml
file, I can add my custom code (PowerShell in my case).
name: wth-logicapp
hooks:
preprovision:
shell: pwsh
continueOnError: false
interactive: true
run: |
$upn = $(az ad signed-in-user show --query userPrincipalName -o tsv)
azd env set AZURE_PRINCIPAL_NAME $upn
$myIP = $(Invoke-WebRequest -Uri "https://api.ipify.org").Content
azd env set MY_IP $myIP
services:
api:
project: ./src/api
language: dotnet
host: function
In this example, I run the Azure CLI command to find out who the signed-in user is and then query for the userPrincipalName
. I also query a common website that lists what your current IP address is. With this information, I can populate the two environment variables.
Deployment
Now that I have written my Bicep templates, set up the parameters file & added code to the preprovision hook, I can run my code.
azd up