{"id":236,"date":"2022-04-05T16:32:02","date_gmt":"2022-04-05T14:32:02","guid":{"rendered":"https:\/\/www.panahy.nl\/?p=236"},"modified":"2022-04-06T22:20:47","modified_gmt":"2022-04-06T20:20:47","slug":"getting-started-with-bicep","status":"publish","type":"post","link":"http:\/\/panahy.nl\/index.php\/2022\/04\/05\/getting-started-with-bicep\/","title":{"rendered":"Getting Started with Bicep"},"content":{"rendered":"\n<p>Install Bicep to your local environment:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"powershell\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\"># Create the install folder\n$installPath = \"$env:USERPROFILE\\.bicep\"\n$installDir = New-Item -ItemType Directory -Path $installPath -Force\n$installDir.Attributes += 'Hidden'\n# Fetch the latest Bicep CLI binary\n(New-Object Net.WebClient).DownloadFile(\"https:\/\/github.com\/Azure\/bicep\/releases\/latest\/download\/bicep-win-x64.exe\", \"$installPath\\bicep.exe\")\n# Add bicep to your PATH\n$currentPath = (Get-Item -path \"HKCU:\\Environment\" ).GetValue('Path', '', 'DoNotExpandEnvironmentNames')\nif (-not $currentPath.Contains(\"%USERPROFILE%\\.bicep\")) { setx PATH ($currentPath + \";%USERPROFILE%\\.bicep\") }\nif (-not $env:path.Contains($installPath)) { $env:path += \";$installPath\" }\n# Verify you can now access the 'bicep' command.\nbicep --help\n# Done!<\/pre>\n\n\n\n<p>Install Bicep extension on VS Code<\/p>\n\n\n\n<p>Look into Bicep documentations: https:\/\/docs.microsoft.com\/en-us\/azure\/azure-resource-manager\/bicep\/<\/p>\n\n\n\n<p>Deploy your main.bicep file using PowerShell:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"powershell\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">Connect-AzAccount\n$context = Get-AzSubscription -SubscriptionName 'Concierge Subscription'\nSet-AzContext $context\n\nGet-AzSubscription\nSet-AzDefault -ResourceGroupName learn-8ea5f9c3-7fab-4c37-8fc7-f424f67ef1a5\n\nNew-AzResourceGroupDeployment -TemplateFile main.bicep<\/pre>\n\n\n\n<h2>Using KeyVault Secrets as Parameter value<\/h2>\n\n\n\n<p>Assume you need a login and password in your main bicep resource:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">resource sqlServer 'Microsoft.Sql\/servers@2020-11-01-preview' = {\n  name: sqlServerName\n  location: location\n  properties: {\n    administratorLogin: sqlServerAdministratorLogin\n    administratorLoginPassword: sqlServerAdministratorPassword\n  }\n}<\/pre>\n\n\n\n<p>So you define these 2 as parameters like this:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">@secure()\n@description('The administrator login username for the SQL server.')\nparam sqlServerAdministratorLogin string\n\n@secure()\n@description('The administrator login password for the SQL server.')\nparam sqlServerAdministratorPassword string<\/pre>\n\n\n\n<p>But you can&#8217;t pass these sensitive values in your pipeline. Instead you put them in the parameters.json to get the value from KeyVault:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"json\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">{\n    \"$schema\": \"https:\/\/schema.management.azure.com\/schemas\/2019-04-01\/deploymentParameters.json#\",\n    \"contentVersion\": \"1.0.0.0\",\n    \"parameters\": {\n      \"sqlServerAdministratorLogin\": {\n        \"reference\": {\n          \"keyVault\": {\n            \"id\": \"\/subscriptions\/a597e5fe-3c45-4412-b944-53e730b31c57\/resourceGroups\/learn-bicep-rg\/providers\/Microsoft.KeyVault\/vaults\/example-bicep-kv\"\n          },\n          \"secretName\": \"sqlServerAdministratorLogin\"\n        }\n      },\n      \"sqlServerAdministratorPassword\": {\n        \"reference\": {\n          \"keyVault\": {\n            \"id\": \"\/subscriptions\/a597e5fe-3c45-4412-b944-53e730b31c57\/resourceGroups\/learn-bicep-rg\/providers\/Microsoft.KeyVault\/vaults\/example-bicep-kv\"\n          },\n          \"secretName\": \"sqlServerAdministratorPassword\"\n        }\n      }\n    }\n  }<\/pre>\n\n\n\n<h2>Using Conditions<\/h2>\n\n\n\n<p>Deploying resources may also deppend on a given parameter. In this case put the condition before the object definition:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">@allowed([\n  'Development'\n  'Production'\n])\nparam environmentName string\n\n\/\/ define your condition\nvar auditingEnabled = environmentName == 'Production'\n\nresource auditingSettings 'Microsoft.Sql\/servers\/auditingSettings@2020-11-01-preview' = if (auditingEnabled) {\n  parent: server\n  name: 'default'\n  properties: {\n  }\n}<\/pre>\n\n\n\n<p>You may also want to use conditions in properties section. Assuming you have defined an auditStorageAccount in this main bicep file, you can use the properties of this storage resource to assign values to auditSettings too:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">resource auditStorageAccount 'Microsoft.Storage\/storageAccounts@2021-02-01' = if (auditingEnabled) {\n  name: auditStorageAccountName\n  location: location\n  sku: {\n    name: storageAccountSkuName\n  }\n  kind: 'StorageV2'\n}\nresource auditingSettings 'Microsoft.Sql\/servers\/auditingSettings@2020-11-01-preview' = if (auditingEnabled) {\n  parent: server\n  name: 'default'\n  properties: {\n    state: 'Enabled'\n    storageEndpoint: environmentName == 'Production' ? auditStorageAccount.properties.primaryEndpoints.blob : ''\n    storageAccountAccessKey: environmentName == 'Production' ? listKeys(auditStorageAccount.id, auditStorageAccount.apiVersion).keys[0].value : ''\n  }\n}<\/pre>\n\n\n\n<h2>Use Copy loops<\/h2>\n\n\n\n<p>You can use an array to create multiple resources in a loop<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">param storageAccountNames array = [\n  'saauditus'\n  'saauditeurope'\n  'saauditapac'\n]\n\nresource storageAccountResources 'Microsoft.Storage\/storageAccounts@2021-01-01' = [for storageAccountName in storageAccountNames: {\n  name: storageAccountName\n  location: resourceGroup().location\n  kind: 'StorageV2'\n  sku: {\n    name: 'Standard_LRS'\n  }\n}]<\/pre>\n\n\n\n<h2>Loop based on a count<\/h2>\n\n\n\n<p>Bicep provides the\u00a0<code>range()<\/code>\u00a0function, which creates an array of numbers.\u00a0<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">resource storageAccountResources 'Microsoft.Storage\/storageAccounts@2021-01-01' = [for i in range(1,4): {\n  name: 'sa${i}'\n  location: resourceGroup().location\n  kind: 'StorageV2'\n  sku: {\n    name: 'Standard_LRS'\n  }\n}]<\/pre>\n\n\n\n<h2>Access the iteration index<\/h2>\n\n\n\n<p>When you need both the value in each iteration and index of that value you can specify the index variable with the array iterator:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">param locations array = [\n  'westeurope'\n  'eastus2'\n  'eastasia'\n]\n\nresource sqlServers 'Microsoft.Sql\/servers@2020-11-01-preview' = [for (location, i) in locations: {\n  name: 'sqlserver-${i+1}'\n  location: location\n  properties: {\n    administratorLogin: administratorLogin\n    administratorLoginPassword: administratorLoginPassword\n  }\n}]<\/pre>\n\n\n\n<h2>Filter items with loops<\/h2>\n\n\n\n<p>Sometimes one value in a given array is enough, but we might need more associated parameters:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">param sqlServerDetails array = [\n  {\n    name: 'sqlserver-we'\n    location: 'westeurope'\n    environmentName: 'Production'\n  }\n  {\n    name: 'sqlserver-eus2'\n    location: 'eastus2'\n    environmentName: 'Development'\n  }\n  {\n    name: 'sqlserver-eas'\n    location: 'eastasia'\n    environmentName: 'Production'\n  }\n]\n\nresource sqlServers 'Microsoft.Sql\/servers@2020-11-01-preview' = [for sqlServer in sqlServerDetails: if (sqlServer.environmentName == 'Production') {\n  name: sqlServer.name\n  location: sqlServer.location\n  properties: {\n    administratorLogin: administratorLogin\n    administratorLoginPassword: administratorLoginPassword\n  }\n  tags: {\n    environment: sqlServer.environmentName\n  }\n}]<\/pre>\n\n\n\n<h2>Use loops with resource properties<\/h2>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">param subnetNames array = [\n  'api'\n  'worker'\n]\n\nvar subnetCount = 2\n\nresource virtualNetworks 'Microsoft.Network\/virtualNetworks@2020-11-01' = [for (location, i) in locations : {\n  name: 'vnet-${location}'\n  location: location\n  properties: {\n    addressSpace:{\n      addressPrefixes:[\n        '10.${i}.0.0\/16'\n      ]\n    }\n    subnets: [for j in range(1, subnetCount): {\n      name: 'subnet-${j}'\n      properties: {\n        addressPrefix: '10.${i}.${j}.0\/24'\n      }\n    }]\n  }\n}]<\/pre>\n\n\n\n<h2>Variable loops<\/h2>\n\n\n\n<p>The next example creates an array that contains the values\u00a0<code>item1<\/code>,\u00a0<code>item2<\/code>,\u00a0<code>item3<\/code>,\u00a0<code>item4<\/code>, and\u00a0<code>item5<\/code>.<\/p>\n\n\n\n<p><code>var items = [for i in range(1, 5): 'item${i}']<\/code><\/p>\n\n\n\n<div class=\"wp-container-2 wp-block-columns\">\n<div class=\"wp-container-1 wp-block-column\" style=\"flex-basis:100%\">\n<blockquote class=\"wp-block-quote\"><p>Don&#8217;t use outputs to return secrets, such as access keys or passwords. Outputs are logged, and they aren&#8217;t designed for handling secure data.<\/p><\/blockquote>\n<\/div>\n<\/div>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Install Bicep to your local environment: Install Bicep extension on VS Code Look into Bicep documentations: https:\/\/docs.microsoft.com\/en-us\/azure\/azure-resource-manager\/bicep\/ Deploy your main.bicep file using PowerShell: Using KeyVault Secrets as Parameter value Assume you need a login and password in your main bicep resource: So you define these 2 as parameters like this: But you can&#8217;t pass these &hellip; <a href=\"http:\/\/panahy.nl\/index.php\/2022\/04\/05\/getting-started-with-bicep\/\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;Getting Started with Bicep&#8221;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[4,114,113,115],"tags":[109,110,112,111],"uagb_featured_image_src":{"full":false,"thumbnail":false,"medium":false,"medium_large":false,"large":false,"1536x1536":false,"2048x2048":false,"post-thumbnail":false},"uagb_author_info":{"display_name":"Pouya Panahy","author_link":"http:\/\/panahy.nl\/index.php\/author\/pouya\/"},"uagb_comment_info":0,"uagb_excerpt":"Install Bicep to your local environment: Install Bicep extension on VS Code Look into Bicep documentations: https:\/\/docs.microsoft.com\/en-us\/azure\/azure-resource-manager\/bicep\/ Deploy your main.bicep file using PowerShell: Using KeyVault Secrets as Parameter value Assume you need a login and password in your main bicep resource: So you define these 2 as parameters like this: But you can&#8217;t pass these&hellip;","_links":{"self":[{"href":"http:\/\/panahy.nl\/index.php\/wp-json\/wp\/v2\/posts\/236"}],"collection":[{"href":"http:\/\/panahy.nl\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/panahy.nl\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/panahy.nl\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/panahy.nl\/index.php\/wp-json\/wp\/v2\/comments?post=236"}],"version-history":[{"count":5,"href":"http:\/\/panahy.nl\/index.php\/wp-json\/wp\/v2\/posts\/236\/revisions"}],"predecessor-version":[{"id":244,"href":"http:\/\/panahy.nl\/index.php\/wp-json\/wp\/v2\/posts\/236\/revisions\/244"}],"wp:attachment":[{"href":"http:\/\/panahy.nl\/index.php\/wp-json\/wp\/v2\/media?parent=236"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/panahy.nl\/index.php\/wp-json\/wp\/v2\/categories?post=236"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/panahy.nl\/index.php\/wp-json\/wp\/v2\/tags?post=236"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}