mcpField
W
writing-bicep-templates

writing-bicep-templates

github.com/microsoft-foundryCloud & DevOps13357 installsUpdated 27w ago
Repository

About writing-bicep-templates

writing-bicep-templates is a skill containing conventions and examples for writing Azure Bicep infrastructure templates. It is intended for developers configuring secure Azure resources, including Container Apps, identities, and role assignments.

Key features

  1. 01Resource naming and parameter conventions
  2. 02Managed identity and RBAC patterns
  3. 03Container Apps configuration guidance
  4. 04Bicep build and deployment validation

Use cases

  1. 01Define Azure infrastructure modules
  2. 02Configure identity-based ACR pulls
  3. 03Validate templates before deployment

Install

Copy the command and run it in a terminal.

$npx skills add https://github.com/microsoft-foundry/foundry-agent-webapp --skill writing-bicep-templates

After installing, type/writing-bicep-templatesin Claude Code to confirm it loaded.

Details

From the project README

Bicep Coding Standards

Goal: Create consistent, secure Azure infrastructure

Naming Convention

Use resourceToken from uniqueString():

var token = toLower(uniqueString(subscription().id, environmentName, location))
name: '${abbrs.appContainerApps}web-${token}'  // ca-web-abc123

Exception: ACR requires alphanumeric only: cr${resourceToken}

Parameters

Always add @description() and use @allowed() for constrained values:

@description('Environment (dev, prod)')
param environmentName string

@description('Azure region')
@allowed(['eastus2', 'westus2'])
param location string = 'eastus2'

Outputs

Expose key identifiers for azd and other modules:

output containerAppName string = containerApp.name
output webEndpoint string = 'https://${containerApp.properties.configuration.ingress.fqdn}'
output identityPrincipalId string = containerApp.identity.principalId

Managed Identity

Use a user-assigned MI for ACR pull and OBO (avoids circular dependencies). Create it in the infrastructure module so its principalId is available before the Container App:

resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2024-11-30' = {
  name: '${abbrs.managedIdentityUserAssignedIdentities}web-${resourceToken}'
  location: location
  properties: { isolationScope: 'Regional' }
}
output managedIdentityPrincipalId string = managedIdentity.properties.principalId

Attach to Container App with identity: { type: 'UserAssigned', userAssignedIdentities: { '${miId}': {} } }. Use MI for ACR pull via registries: [{ server: acr.loginServer, identity: miId }].

RBAC Assignments

Use guid() for names + specify principalType:

resource roleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
  name: guid(resource.id, principalId, roleId)
  properties: {
    roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleId)
    principalId: principalId
    principalType: 'ServicePrincipal'
  }
}

Container Apps

Key settings: System identity + scale-to-zero + HTTPS only:

resource containerApp 'Microsoft.App/containerApps@2023-05-01' = {
  identity: { type: 'UserAssigned', userAssignedIdentities: { '${userAssignedIdentityId}': {} } }
  properties: {
    configuration: {
      ingress: {
        external: true
        targetPort: 8080
        allowInsecure: false
      }
    }
    template: {
      scale: { minReplicas: 0, maxReplicas: 3 }
    }
  }
}

ACR Pull Pattern

Use user-assigned MI for ACR pull (no admin credentials or secrets):

registries: [{
  server: containerRegistry.properties.loginServer
  identity: userAssignedIdentityId  // MI with AcrPull role
}]

Validation

az bicep build --file main.bicep
az deployment group what-if --template-file main.bicep

Project-Specific: Module Hierarchy

main.bicep (subscription scope)
├─ Resource group
├─ main-infrastructure.bicep (ACR + Container Apps Env + Log Analytics + User-Assigned MI)
├─ entra-app.bicep (SPA app + conditional OBO backend app with FIC + admin consent)
├─ main-app.bicep (Container App with MI-based ACR pull)
└─ RBAC (Cognitive Services User role via postprovision CLI)

Project-Specific: Container App Configuration

resource containerApp 'Microsoft.App/containerApps@2024-03-01' = {
  identity: {
    type: 'UserAssigned'
    userAssignedIdentities: { '${userAssignedIdentityId}': {} }
  }
  properties: {
    managedEnvironmentId: containerAppsEnvironmentId
    configuration: {
      ingress: {
        external: true
        targetPort: 8080
        allowInsecure: false
      }
      registries: [{
        server: containerRegistry.properties.loginServer
        identity: userAssignedIdentityId  // MI-based pull, no secrets
      }]
    }
    template: {
      containers: [{
        name: 'web'
        image: containerImage
        env: containerEnv  // Base env + conditional OBO env
        resources: { cpu: json('0.5'), memory: '1Gi' }
      }]
      scale: { minReplicas: 0, maxReplicas: 3 }
    }
  }
}

output fqdn string = containerApp.properties.configuration.ingress.fqdn
output identityPrincipalId string = containerApp.identity.principalId

Related Skills

  • deploying-to-azure - Deployment commands and hook workflow
  • writing-csharp-code - Backend configuration for Container Apps
  • troubleshooting-authentication - RBAC and managed identity debugging

Comments

Markdown supported