797 lines
19 KiB
Markdown
797 lines
19 KiB
Markdown
## 🚨 CRITICAL GUIDELINES
|
|
|
|
### Windows File Path Requirements
|
|
|
|
**MANDATORY: Always Use Backslashes on Windows for File Paths**
|
|
|
|
When using Edit or Write tools on Windows, you MUST use backslashes (`\`) in file paths, NOT forward slashes (`/`).
|
|
|
|
**Examples:**
|
|
- ❌ WRONG: `D:/repos/project/file.tsx`
|
|
- ✅ CORRECT: `D:\repos\project\file.tsx`
|
|
|
|
This applies to:
|
|
- Edit tool file_path parameter
|
|
- Write tool file_path parameter
|
|
- All file operations on Windows systems
|
|
|
|
### Documentation Guidelines
|
|
|
|
**NEVER create new documentation files unless explicitly requested by the user.**
|
|
|
|
- **Priority**: Update existing README.md files rather than creating new documentation
|
|
- **Repository cleanliness**: Keep repository root clean - only README.md unless user requests otherwise
|
|
- **Style**: Documentation should be concise, direct, and professional - avoid AI-generated tone
|
|
- **User preference**: Only create additional .md files when user specifically asks for documentation
|
|
|
|
---
|
|
|
|
|
|
# Azure Deployment Stacks - 2025 GA Features
|
|
|
|
Complete knowledge base for Azure Deployment Stacks, the successor to Azure Blueprints (GA 2024, best practices 2025).
|
|
|
|
## Overview
|
|
|
|
Azure Deployment Stacks is a resource type for managing a collection of Azure resources as a single, atomic unit. It provides unified lifecycle management, resource protection, and automatic cleanup capabilities.
|
|
|
|
## Key Features
|
|
|
|
### 1. Unified Resource Management
|
|
- Manage multiple resources as a single entity
|
|
- Update, export, and delete operations on the entire stack
|
|
- Track all managed resources in one place
|
|
- Consistent deployment across environments
|
|
|
|
### 2. Deny Settings (Resource Protection)
|
|
Prevent unauthorized modifications to managed resources:
|
|
- **None**: No restrictions (default)
|
|
- **DenyDelete**: Prevent resource deletion
|
|
- **DenyWriteAndDelete**: Prevent updates and deletions
|
|
|
|
### 3. ActionOnUnmanage (Cleanup Policies)
|
|
Control what happens to resources no longer in template:
|
|
- **detachAll**: Remove from stack management, keep resources
|
|
- **deleteAll**: Delete resources not in template
|
|
- **deleteResources**: Delete unmanaged resources, keep resource groups
|
|
|
|
### 4. Scope Flexibility
|
|
Deploy stacks at:
|
|
- Resource group scope
|
|
- Subscription scope
|
|
- Management group scope
|
|
|
|
### 5. Replaces Azure Blueprints
|
|
Azure Blueprints will be deprecated in **July 2026**. Deployment Stacks is the recommended replacement.
|
|
|
|
## Prerequisites
|
|
|
|
### Azure CLI Version
|
|
```bash
|
|
# Requires Azure CLI 2.61.0 or later
|
|
az version
|
|
|
|
# Upgrade if needed
|
|
az upgrade
|
|
```
|
|
|
|
### Azure PowerShell Version
|
|
```bash
|
|
# Requires Azure PowerShell 12.0.0 or later
|
|
Get-InstalledModule -Name Az
|
|
Update-Module -Name Az
|
|
```
|
|
|
|
## Creating Deployment Stacks
|
|
|
|
### Subscription Scope Stack
|
|
|
|
```bash
|
|
# Create deployment stack at subscription level
|
|
az stack sub create \
|
|
--name MyProductionStack \
|
|
--location eastus \
|
|
--template-file main.bicep \
|
|
--parameters @parameters.json \
|
|
--deny-settings-mode DenyWriteAndDelete \
|
|
--deny-settings-excluded-principals <devops-service-principal-id> <admin-group-id> \
|
|
--action-on-unmanage deleteAll \
|
|
--description "Production infrastructure managed by deployment stack" \
|
|
--tags Environment=Production ManagedBy=DeploymentStack CostCenter=Engineering
|
|
|
|
# What-if analysis before deployment
|
|
az stack sub what-if \
|
|
--name MyProductionStack \
|
|
--location eastus \
|
|
--template-file main.bicep \
|
|
--parameters @parameters.json
|
|
|
|
# Create with confirmation prompt disabled
|
|
az stack sub create \
|
|
--name MyDevStack \
|
|
--location eastus \
|
|
--template-file main.bicep \
|
|
--deny-settings-mode None \
|
|
--action-on-unmanage detachAll \
|
|
--yes
|
|
```
|
|
|
|
### Resource Group Scope Stack
|
|
|
|
```bash
|
|
# Create resource group
|
|
az group create \
|
|
--name MyRG \
|
|
--location eastus \
|
|
--tags Environment=Production
|
|
|
|
# Create deployment stack
|
|
az stack group create \
|
|
--name MyAppStack \
|
|
--resource-group MyRG \
|
|
--template-file main.bicep \
|
|
--parameters environment=production \
|
|
--deny-settings-mode DenyDelete \
|
|
--action-on-unmanage deleteAll \
|
|
--description "Application infrastructure stack"
|
|
```
|
|
|
|
### Management Group Scope Stack
|
|
|
|
```bash
|
|
# Create stack at management group level
|
|
az stack mg create \
|
|
--name MyEnterpriseStack \
|
|
--management-group-id MyMgmtGroup \
|
|
--location eastus \
|
|
--template-file main.bicep \
|
|
--deny-settings-mode DenyWriteAndDelete \
|
|
--action-on-unmanage detachAll
|
|
```
|
|
|
|
## Bicep Template for Deployment Stack
|
|
|
|
### Production Stack Template
|
|
|
|
```bicep
|
|
// main.bicep
|
|
targetScope = 'subscription'
|
|
|
|
@description('Environment name')
|
|
@allowed([
|
|
'dev'
|
|
'staging'
|
|
'production'
|
|
])
|
|
param environment string = 'production'
|
|
|
|
@description('Primary location')
|
|
param location string = 'eastus'
|
|
|
|
@description('Secondary location for geo-replication')
|
|
param secondaryLocation string = 'westus'
|
|
|
|
// Resource naming
|
|
var namingPrefix = 'myapp-${environment}'
|
|
|
|
// Resource Group for core infrastructure
|
|
resource coreRG 'Microsoft.Resources/resourceGroups@2024-03-01' = {
|
|
name: '${namingPrefix}-core-rg'
|
|
location: location
|
|
tags: {
|
|
Environment: environment
|
|
ManagedBy: 'DeploymentStack'
|
|
Purpose: 'Core Infrastructure'
|
|
}
|
|
}
|
|
|
|
// Resource Group for data services
|
|
resource dataRG 'Microsoft.Resources/resourceGroups@2024-03-01' = {
|
|
name: '${namingPrefix}-data-rg'
|
|
location: location
|
|
tags: {
|
|
Environment: environment
|
|
ManagedBy: 'DeploymentStack'
|
|
Purpose: 'Data Services'
|
|
}
|
|
}
|
|
|
|
// Log Analytics Workspace
|
|
module logAnalytics 'modules/log-analytics.bicep' = {
|
|
name: 'logAnalyticsDeploy'
|
|
scope: coreRG
|
|
params: {
|
|
name: '${namingPrefix}-logs'
|
|
location: location
|
|
retentionInDays: environment == 'production' ? 90 : 30
|
|
}
|
|
}
|
|
|
|
// AKS Automatic Cluster
|
|
module aksCluster 'modules/aks-automatic.bicep' = {
|
|
name: 'aksClusterDeploy'
|
|
scope: coreRG
|
|
params: {
|
|
name: '${namingPrefix}-aks'
|
|
location: location
|
|
kubernetesVersion: '1.34'
|
|
workspaceId: logAnalytics.outputs.workspaceId
|
|
enableZoneRedundancy: environment == 'production'
|
|
}
|
|
}
|
|
|
|
// Container Apps Environment
|
|
module containerEnv 'modules/container-env.bicep' = {
|
|
name: 'containerEnvDeploy'
|
|
scope: coreRG
|
|
params: {
|
|
name: '${namingPrefix}-containerenv'
|
|
location: location
|
|
workspaceId: logAnalytics.outputs.workspaceId
|
|
zoneRedundant: environment == 'production'
|
|
}
|
|
}
|
|
|
|
// Azure OpenAI
|
|
module openAI 'modules/openai.bicep' = {
|
|
name: 'openAIDeploy'
|
|
scope: dataRG
|
|
params: {
|
|
name: '${namingPrefix}-openai'
|
|
location: location
|
|
deployGPT5: environment == 'production'
|
|
}
|
|
}
|
|
|
|
// Cosmos DB with geo-replication
|
|
module cosmosDB 'modules/cosmos-db.bicep' = {
|
|
name: 'cosmosDBDeploy'
|
|
scope: dataRG
|
|
params: {
|
|
name: '${namingPrefix}-cosmos'
|
|
primaryLocation: location
|
|
secondaryLocation: secondaryLocation
|
|
enableAutomaticFailover: environment == 'production'
|
|
}
|
|
}
|
|
|
|
// Key Vault
|
|
module keyVault 'modules/key-vault.bicep' = {
|
|
name: 'keyVaultDeploy'
|
|
scope: coreRG
|
|
params: {
|
|
name: '${namingPrefix}-kv'
|
|
location: location
|
|
enablePurgeProtection: environment == 'production'
|
|
}
|
|
}
|
|
|
|
// Outputs
|
|
output aksClusterName string = aksCluster.outputs.clusterName
|
|
output containerEnvId string = containerEnv.outputs.environmentId
|
|
output openAIEndpoint string = openAI.outputs.endpoint
|
|
output cosmosDBEndpoint string = cosmosDB.outputs.endpoint
|
|
output keyVaultUri string = keyVault.outputs.vaultUri
|
|
```
|
|
|
|
### AKS Automatic Module
|
|
|
|
```bicep
|
|
// modules/aks-automatic.bicep
|
|
@description('Cluster name')
|
|
param name string
|
|
|
|
@description('Location')
|
|
param location string
|
|
|
|
@description('Kubernetes version')
|
|
param kubernetesVersion string = '1.34'
|
|
|
|
@description('Log Analytics workspace ID')
|
|
param workspaceId string
|
|
|
|
@description('Enable zone redundancy')
|
|
param enableZoneRedundancy bool = true
|
|
|
|
resource aksCluster 'Microsoft.ContainerService/managedClusters@2025-01-01' = {
|
|
name: name
|
|
location: location
|
|
sku: {
|
|
name: 'Automatic'
|
|
tier: 'Standard'
|
|
}
|
|
identity: {
|
|
type: 'SystemAssigned'
|
|
}
|
|
properties: {
|
|
kubernetesVersion: kubernetesVersion
|
|
dnsPrefix: '${name}-dns'
|
|
enableRBAC: true
|
|
aadProfile: {
|
|
managed: true
|
|
enableAzureRBAC: true
|
|
}
|
|
networkProfile: {
|
|
networkPlugin: 'azure'
|
|
networkPluginMode: 'overlay'
|
|
networkDataplane: 'cilium'
|
|
serviceCidr: '10.0.0.0/16'
|
|
dnsServiceIP: '10.0.0.10'
|
|
}
|
|
autoScalerProfile: {
|
|
'balance-similar-node-groups': 'true'
|
|
expander: 'least-waste'
|
|
}
|
|
autoUpgradeProfile: {
|
|
upgradeChannel: 'stable'
|
|
nodeOSUpgradeChannel: 'NodeImage'
|
|
}
|
|
securityProfile: {
|
|
defender: {
|
|
securityMonitoring: {
|
|
enabled: true
|
|
}
|
|
}
|
|
workloadIdentity: {
|
|
enabled: true
|
|
}
|
|
}
|
|
oidcIssuerProfile: {
|
|
enabled: true
|
|
}
|
|
addonProfiles: {
|
|
omsagent: {
|
|
enabled: true
|
|
config: {
|
|
logAnalyticsWorkspaceResourceID: workspaceId
|
|
}
|
|
}
|
|
azurePolicy: {
|
|
enabled: true
|
|
}
|
|
}
|
|
}
|
|
zones: enableZoneRedundancy ? ['1', '2', '3'] : null
|
|
}
|
|
|
|
output clusterName string = aksCluster.name
|
|
output clusterId string = aksCluster.id
|
|
output oidcIssuerUrl string = aksCluster.properties.oidcIssuerProfile.issuerUrl
|
|
output kubeletIdentity string = aksCluster.properties.identityProfile.kubeletidentity.objectId
|
|
```
|
|
|
|
## Managing Deployment Stacks
|
|
|
|
### Update Stack
|
|
|
|
```bash
|
|
# Update with new template version
|
|
az stack sub update \
|
|
--name MyProductionStack \
|
|
--template-file main.bicep \
|
|
--parameters @parameters.json \
|
|
--action-on-unmanage deleteAll
|
|
|
|
# Update deny settings
|
|
az stack sub update \
|
|
--name MyProductionStack \
|
|
--deny-settings-mode DenyWriteAndDelete \
|
|
--deny-settings-excluded-principals <new-principal-id>
|
|
```
|
|
|
|
### View Stack Details
|
|
|
|
```bash
|
|
# Show stack information
|
|
az stack sub show \
|
|
--name MyProductionStack \
|
|
--output json
|
|
|
|
# List all stacks in subscription
|
|
az stack sub list --output table
|
|
|
|
# List stacks in resource group
|
|
az stack group list \
|
|
--resource-group MyRG \
|
|
--output table
|
|
```
|
|
|
|
### Export Stack Template
|
|
|
|
```bash
|
|
# Export template from deployed stack
|
|
az stack sub export \
|
|
--name MyProductionStack \
|
|
--output-file exported-stack.json
|
|
|
|
# Export and save parameters
|
|
az stack sub show \
|
|
--name MyProductionStack \
|
|
--query "parameters" \
|
|
--output json > parameters-backup.json
|
|
```
|
|
|
|
### Delete Stack
|
|
|
|
```bash
|
|
# Delete stack and all managed resources
|
|
az stack sub delete \
|
|
--name MyProductionStack \
|
|
--action-on-unmanage deleteAll \
|
|
--yes
|
|
|
|
# Delete stack but keep resources
|
|
az stack sub delete \
|
|
--name MyProductionStack \
|
|
--action-on-unmanage detachAll \
|
|
--yes
|
|
|
|
# Delete with confirmation prompt
|
|
az stack sub delete --name MyProductionStack
|
|
```
|
|
|
|
## Deny Settings in Detail
|
|
|
|
### DenyDelete Mode
|
|
|
|
Prevents deletion but allows updates:
|
|
|
|
```bash
|
|
az stack sub create \
|
|
--name MyStack \
|
|
--location eastus \
|
|
--template-file main.bicep \
|
|
--deny-settings-mode DenyDelete \
|
|
--deny-settings-excluded-principals \
|
|
<emergency-access-principal-id> \
|
|
<devops-service-principal-id>
|
|
```
|
|
|
|
**Use cases:**
|
|
- Protect production databases
|
|
- Prevent accidental resource deletion
|
|
- Allow configuration updates
|
|
|
|
### DenyWriteAndDelete Mode
|
|
|
|
Prevents both updates and deletions:
|
|
|
|
```bash
|
|
az stack sub create \
|
|
--name MyStack \
|
|
--location eastus \
|
|
--template-file main.bicep \
|
|
--deny-settings-mode DenyWriteAndDelete \
|
|
--deny-settings-excluded-principals <break-glass-principal-id>
|
|
```
|
|
|
|
**Use cases:**
|
|
- Immutable infrastructure
|
|
- Compliance requirements
|
|
- Critical production workloads
|
|
|
|
### Excluded Principals
|
|
|
|
Bypass deny settings for specific identities:
|
|
|
|
```bash
|
|
# Get principal IDs
|
|
SERVICE_PRINCIPAL_ID=$(az ad sp show --id <app-id> --query id -o tsv)
|
|
ADMIN_GROUP_ID=$(az ad group show --group "Cloud Admins" --query id -o tsv)
|
|
|
|
# Apply with exclusions
|
|
az stack sub create \
|
|
--name MyStack \
|
|
--location eastus \
|
|
--template-file main.bicep \
|
|
--deny-settings-mode DenyWriteAndDelete \
|
|
--deny-settings-excluded-principals $SERVICE_PRINCIPAL_ID $ADMIN_GROUP_ID
|
|
```
|
|
|
|
## ActionOnUnmanage Policies
|
|
|
|
### detachAll
|
|
|
|
Resources are removed from stack management but not deleted:
|
|
|
|
```bash
|
|
az stack sub create \
|
|
--name MyStack \
|
|
--location eastus \
|
|
--template-file main.bicep \
|
|
--action-on-unmanage detachAll
|
|
```
|
|
|
|
**Use when:**
|
|
- Testing deployment changes
|
|
- Migrating resources to another stack
|
|
- Temporary stack management
|
|
|
|
### deleteAll
|
|
|
|
All unmanaged resources are deleted:
|
|
|
|
```bash
|
|
az stack sub create \
|
|
--name MyStack \
|
|
--location eastus \
|
|
--template-file main.bicep \
|
|
--action-on-unmanage deleteAll
|
|
```
|
|
|
|
**Use when:**
|
|
- Ephemeral environments (dev, test)
|
|
- Clean slate deployments
|
|
- Strict infrastructure-as-code enforcement
|
|
|
|
### deleteResources
|
|
|
|
Delete resources but keep resource groups:
|
|
|
|
```bash
|
|
az stack sub create \
|
|
--name MyStack \
|
|
--location eastus \
|
|
--template-file main.bicep \
|
|
--action-on-unmanage deleteResources
|
|
```
|
|
|
|
## RBAC for Deployment Stacks
|
|
|
|
### Built-in Roles
|
|
|
|
**Azure Deployment Stack Contributor**
|
|
- Manage deployment stacks
|
|
- Cannot create or delete deny-assignments
|
|
|
|
**Azure Deployment Stack Owner**
|
|
- Full stack management
|
|
- Can create and delete deny-assignments
|
|
|
|
### Assign Roles
|
|
|
|
```bash
|
|
# Assign Stack Contributor role
|
|
az role assignment create \
|
|
--assignee <user-or-service-principal-id> \
|
|
--role "Azure Deployment Stack Contributor" \
|
|
--scope /subscriptions/<subscription-id>
|
|
|
|
# Assign Stack Owner role
|
|
az role assignment create \
|
|
--assignee <admin-principal-id> \
|
|
--role "Azure Deployment Stack Owner" \
|
|
--scope /subscriptions/<subscription-id>
|
|
```
|
|
|
|
## CI/CD Integration
|
|
|
|
### GitHub Actions
|
|
|
|
```yaml
|
|
name: Deploy Deployment Stack
|
|
|
|
on:
|
|
push:
|
|
branches: [main]
|
|
workflow_dispatch:
|
|
|
|
permissions:
|
|
id-token: write
|
|
contents: read
|
|
|
|
jobs:
|
|
deploy:
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
|
|
- name: Azure Login
|
|
uses: azure/login@v2
|
|
with:
|
|
client-id: ${{ secrets.AZURE_CLIENT_ID }}
|
|
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
|
|
subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
|
|
|
|
- name: What-if Analysis
|
|
run: |
|
|
az stack sub what-if \
|
|
--name MyProductionStack \
|
|
--location eastus \
|
|
--template-file main.bicep \
|
|
--parameters @parameters.json
|
|
|
|
- name: Deploy Stack
|
|
run: |
|
|
az stack sub create \
|
|
--name MyProductionStack \
|
|
--location eastus \
|
|
--template-file main.bicep \
|
|
--parameters @parameters.json \
|
|
--deny-settings-mode DenyWriteAndDelete \
|
|
--deny-settings-excluded-principals ${{ secrets.DEVOPS_PRINCIPAL_ID }} \
|
|
--action-on-unmanage deleteAll \
|
|
--yes
|
|
```
|
|
|
|
### Azure DevOps Pipeline
|
|
|
|
```yaml
|
|
trigger:
|
|
branches:
|
|
include:
|
|
- main
|
|
|
|
pool:
|
|
vmImage: 'ubuntu-latest'
|
|
|
|
variables:
|
|
azureSubscription: 'MyAzureConnection'
|
|
stackName: 'MyProductionStack'
|
|
location: 'eastus'
|
|
|
|
steps:
|
|
- task: AzureCLI@2
|
|
displayName: 'What-if Analysis'
|
|
inputs:
|
|
azureSubscription: $(azureSubscription)
|
|
scriptType: 'bash'
|
|
scriptLocation: 'inlineScript'
|
|
inlineScript: |
|
|
az stack sub what-if \
|
|
--name $(stackName) \
|
|
--location $(location) \
|
|
--template-file main.bicep \
|
|
--parameters @parameters.json
|
|
|
|
- task: AzureCLI@2
|
|
displayName: 'Deploy Stack'
|
|
inputs:
|
|
azureSubscription: $(azureSubscription)
|
|
scriptType: 'bash'
|
|
scriptLocation: 'inlineScript'
|
|
inlineScript: |
|
|
az stack sub create \
|
|
--name $(stackName) \
|
|
--location $(location) \
|
|
--template-file main.bicep \
|
|
--parameters @parameters.json \
|
|
--deny-settings-mode DenyWriteAndDelete \
|
|
--action-on-unmanage deleteAll \
|
|
--yes
|
|
```
|
|
|
|
## Monitoring and Auditing
|
|
|
|
### View Stack Events
|
|
|
|
```bash
|
|
# Get deployment operations
|
|
az stack sub show \
|
|
--name MyProductionStack \
|
|
--query "deploymentId" \
|
|
--output tsv | \
|
|
xargs -I {} az deployment sub show --name {}
|
|
|
|
# List managed resources
|
|
az stack sub show \
|
|
--name MyProductionStack \
|
|
--query "resources[].id" \
|
|
--output table
|
|
```
|
|
|
|
### Activity Logs
|
|
|
|
```bash
|
|
# Query stack operations
|
|
az monitor activity-log list \
|
|
--resource-group MyRG \
|
|
--namespace Microsoft.Resources \
|
|
--start-time 2025-01-01T00:00:00Z \
|
|
--query "[?contains(authorization.action, 'Microsoft.Resources/deploymentStacks')]" \
|
|
--output table
|
|
```
|
|
|
|
## Migration from Azure Blueprints
|
|
|
|
### Assessment
|
|
|
|
1. **Inventory Blueprints**: List all blueprints and assignments
|
|
2. **Document Parameters**: Export parameters and configurations
|
|
3. **Plan Conversion**: Map blueprints to deployment stacks
|
|
4. **Test in Dev**: Validate converted templates
|
|
|
|
### Conversion Steps
|
|
|
|
```bash
|
|
# 1. Export Blueprint as ARM template
|
|
# (Use Azure Portal or PowerShell)
|
|
|
|
# 2. Convert ARM to Bicep
|
|
az bicep decompile --file blueprint-template.json
|
|
|
|
# 3. Create Deployment Stack
|
|
az stack sub create \
|
|
--name ConvertedFromBlueprint \
|
|
--location eastus \
|
|
--template-file converted.bicep \
|
|
--parameters @blueprint-parameters.json \
|
|
--deny-settings-mode DenyWriteAndDelete \
|
|
--action-on-unmanage detachAll
|
|
|
|
# 4. Validate resources
|
|
az stack sub show --name ConvertedFromBlueprint
|
|
|
|
# 5. Delete Blueprint assignment (after validation)
|
|
# Remove-AzBlueprintAssignment -Name MyBlueprintAssignment
|
|
```
|
|
|
|
## Best Practices
|
|
|
|
✓ **Use Deployment Stacks for all new infrastructure**
|
|
✓ **Always run what-if analysis before deployment**
|
|
✓ **Use DenyWriteAndDelete for production stacks**
|
|
✓ **Exclude break-glass principals from deny settings**
|
|
✓ **Tag stacks with Environment, CostCenter, Owner**
|
|
✓ **Use deleteAll for ephemeral environments**
|
|
✓ **Use detachAll for migration scenarios**
|
|
✓ **Implement CI/CD pipelines for stack deployment**
|
|
✓ **Monitor stack operations via activity logs**
|
|
✓ **Document stack architecture and dependencies**
|
|
|
|
## Troubleshooting
|
|
|
|
### Stack Creation Fails
|
|
|
|
```bash
|
|
# Check deployment errors
|
|
az stack sub show \
|
|
--name MyStack \
|
|
--query "error" \
|
|
--output json
|
|
|
|
# Validate template
|
|
az deployment sub validate \
|
|
--location eastus \
|
|
--template-file main.bicep \
|
|
--parameters @parameters.json
|
|
```
|
|
|
|
### Deny Settings Blocking Operations
|
|
|
|
```bash
|
|
# Check deny assignments
|
|
az role assignment list \
|
|
--scope /subscriptions/<subscription-id> \
|
|
--include-inherited \
|
|
--query "[?type=='Microsoft.Authorization/denyAssignments']"
|
|
|
|
# Add principal to exclusions
|
|
az stack sub update \
|
|
--name MyStack \
|
|
--deny-settings-excluded-principals <new-principal-id>
|
|
```
|
|
|
|
### Resources Not Deleted
|
|
|
|
```bash
|
|
# Check action-on-unmanage setting
|
|
az stack sub show \
|
|
--name MyStack \
|
|
--query "actionOnUnmanage" \
|
|
--output tsv
|
|
|
|
# Update to deleteAll
|
|
az stack sub update \
|
|
--name MyStack \
|
|
--action-on-unmanage deleteAll
|
|
```
|
|
|
|
## References
|
|
|
|
- [Deployment Stacks Documentation](https://learn.microsoft.com/en-us/azure/azure-resource-manager/bicep/deployment-stacks)
|
|
- [Deployment Stacks Quickstart](https://learn.microsoft.com/en-us/azure/azure-resource-manager/bicep/quickstart-create-deployment-stacks)
|
|
- [Migrate from Blueprints](https://learn.microsoft.com/en-us/azure/governance/blueprints/how-to/migrate-to-deployment-stacks)
|
|
|
|
Deployment Stacks represents the future of Azure infrastructure lifecycle management!
|