Week 14 - Infrastructure as Code
Why use Infrastructure as Code
This page is optional. Nothing here is required for Week 14's learning goals or the assignment. Back to the Going Further overview.
Your assignment template uses four constructs: param, var, resource, and module, plus output. That is genuinely most of Bicep. This page covers the language features you meet next, in roughly the order a real template grows into them. Recognition is enough; you do not need to ship any of this to pass the week.
A loop deploys many similar resources without copy-paste. Your assignment declares raw and curated as two separate resource blocks, which is fine for two. At six containers it stops being fine:
param containerNames array = ['raw', 'curated', 'archive']
resource containers 'Microsoft.Storage/storageAccounts/blobServices/containers@2023-01-01' = [
for name in containerNames: {
parent: blobService
name: name
properties: {
publicAccess: 'None'
}
}
]
The same pattern covers role assignments from a parameter array, one subnet per address range, or one storage account per environment. The trade-off: a looped resource is harder to read in what-if output, because every instance appears separately with an index.
A resource can be declared conditionally with if, which is how one template serves environments that are nearly identical:
param environment string
resource backupAccount 'Microsoft.Storage/storageAccounts@2023-01-01' = if (environment == 'prod') {
// ...
}
This is the cleaner answer to "prod needs one extra thing" than maintaining a second template. Watch one sharp edge: a resource excluded by a false condition is deleted under complete-mode deployments on current CLI versions. See Deleting infrastructure.
Sometimes you need to reference a resource your template does not own, for example a Key Vault the platform team provisioned. The existing keyword gives you a typed reference without declaring ownership:
resource kv 'Microsoft.KeyVault/vaults@2023-07-01' existing = {
name: 'kv-hyf-data'
}
Nothing is created or modified. You get the resource's properties and its id for use elsewhere in the file. This is how templates stay small: declare what you own, reference what you do not.
Week 14 keeps secrets out of templates with @secure() parameters passed at deploy time. That still means the value exists somewhere in your pipeline. The next step is having the template read the secret from Azure Key Vault during deployment, so the value never sits in a pipeline variable at all:
resource kv 'Microsoft.KeyVault/vaults@2023-07-01' existing = {
name: 'kv-hyf-data'
}
module db 'modules/db.bicep' = {
name: 'dbDeploy'
params: {
adminPassword: kv.getSecret('db-admin-password')
}
}
getSecret works only when passing a parameter to a module, and only for parameters marked @secure(). That restriction is deliberate: it is what stops the value being printed in an output or a log.
This pattern is genuinely useful and easy to misconfigure on a shared class subscription, which is why it stays optional here. You already met the same discipline from the other direction in Week 12, fetching the Postgres URL from Key Vault at runtime.
getSecret and the module restriction.@secure().The HackYourFuture curriculum is licensed under CC BY-NC-SA 4.0 https://hackyourfuture.net/

Built with ❤️ by the HackYourFuture community · Thank you, contributors
Found a mistake or have a suggestion? Let us know in the feedback form.