All skills
microsoft avatar

/azure-deploy

@d0c21c0 official

Execute Azure deployments for ALREADY-PREPARED applications that have existing .azure/deployment-plan.md and infrastructure files. DO NOT use this skill when the user asks to CREATE a new application — use azure-prepare instead. This skill runs azd up, azd deploy, terraform apply, and az deployment commands with built-in error recovery. Requires .azure/deployment-plan.md from azure-prepare and validated status from azure-validate. WHEN: "run azd up", "run azd deploy", "execute deployment", "push to production", "push to cloud", "go live", "ship it", "bicep deploy", "terraform apply", "publish to Azure", "launch on Azure". DO NOT USE WHEN: "create and deploy", "build and deploy", "create a new app", "set up infrastructure", "create and deploy to Azure using Terraform" — use azure-prepare for these.

Use this Skill: https://skilld.dev/gh/microsoft/github-copilot-for-azure/azure-deploy

This session only. Nothing lands on disk.

referencesrecipesazdsql-managed-identity.md

≈1.9k tokens on demand. Your agent reads this file only when SKILL.md points to it.

SQL Managed Identity Access

Grant Azure managed identities database permissions on Azure SQL with Entra authentication.

Prerequisites

  • Azure SQL Server with Entra ID admin configured
  • App Service/Container App with system-assigned managed identity
  • Your account is Entra ID admin on SQL Server
  • Azure CLI: az login
  • Azure CLI rdbms-connect extension: az extension add --name rdbms-connect --yes

Quick Grant

eval $(azd env get-values)
APP_NAME=$(echo "$SERVICE_API_NAME")  # or SERVICE_WEB_NAME

az sql db query \
  --server "$SQL_SERVER" \
  --database "$SQL_DATABASE" \
  --resource-group "$AZURE_RESOURCE_GROUP" \
  --auth-mode ActiveDirectoryDefault \
  --queries "
    CREATE USER [$APP_NAME] FROM EXTERNAL PROVIDER;
    ALTER ROLE db_datareader ADD MEMBER [$APP_NAME];
    ALTER ROLE db_datawriter ADD MEMBER [$APP_NAME];
    ALTER ROLE db_ddladmin ADD MEMBER [$APP_NAME];
  "

PowerShell:

azd env get-values | ForEach-Object {
    $name, $value = $_.Split('=', 2)
    Set-Item "env:$name" $value
}
$AppName = $env:SERVICE_API_NAME  # or SERVICE_WEB_NAME

$SqlQuery = @"
CREATE USER [$AppName] FROM EXTERNAL PROVIDER;
ALTER ROLE db_datareader ADD MEMBER [$AppName];
ALTER ROLE db_datawriter ADD MEMBER [$AppName];
ALTER ROLE db_ddladmin ADD MEMBER [$AppName];
"@

az sql db query `
  --server $env:SQL_SERVER `
  --database $env:SQL_DATABASE `
  --resource-group $env:AZURE_RESOURCE_GROUP `
  --auth-mode ActiveDirectoryDefault `
  --queries $SqlQuery

Database Roles

Role Permissions Use For
db_datareader SELECT Read-only queries
db_datawriter INSERT, UPDATE, DELETE CRUD operations
db_ddladmin CREATE, ALTER, DROP schema EF migrations
db_owner Full control Admin (use sparingly)

Standard app (read/write/migrations): All three roles above.
Read-only app: Only db_datareader.

Automate with azd Hook

Add postprovision hook to azure.yaml:

hooks:
  postprovision:
    shell: sh
    run: ./scripts/grant-sql-access.sh

scripts/grant-sql-access.sh:

#!/bin/bash
set -e
eval $(azd env get-values)

az sql db query \
  --server "$SQL_SERVER" \
  --database "$SQL_DATABASE" \
  --resource-group "$AZURE_RESOURCE_GROUP" \
  --auth-mode ActiveDirectoryDefault \
  --queries "
    IF NOT EXISTS (SELECT * FROM sys.database_principals WHERE name = '$SERVICE_API_NAME')
      CREATE USER [$SERVICE_API_NAME] FROM EXTERNAL PROVIDER;
    
    IF NOT EXISTS (
      SELECT 1 FROM sys.database_role_members drm
      JOIN sys.database_principals r ON drm.role_principal_id = r.principal_id
      JOIN sys.database_principals m ON drm.member_principal_id = m.principal_id
      WHERE r.name = 'db_datareader' AND m.name = '$SERVICE_API_NAME'
    )
      ALTER ROLE db_datareader ADD MEMBER [$SERVICE_API_NAME];
    
    IF NOT EXISTS (
      SELECT 1 FROM sys.database_role_members drm
      JOIN sys.database_principals r ON drm.role_principal_id = r.principal_id
      JOIN sys.database_principals m ON drm.member_principal_id = m.principal_id
      WHERE r.name = 'db_datawriter' AND m.name = '$SERVICE_API_NAME'
    )
      ALTER ROLE db_datawriter ADD MEMBER [$SERVICE_API_NAME];
    
    IF NOT EXISTS (
      SELECT 1 FROM sys.database_role_members drm
      JOIN sys.database_principals r ON drm.role_principal_id = r.principal_id
      JOIN sys.database_principals m ON drm.member_principal_id = m.principal_id
      WHERE r.name = 'db_ddladmin' AND m.name = '$SERVICE_API_NAME'
    )
      ALTER ROLE db_ddladmin ADD MEMBER [$SERVICE_API_NAME];
  "

scripts/grant-sql-access.ps1:

$ErrorActionPreference = 'Stop'
azd env get-values | ForEach-Object {
    $name, $value = $_.Split('=', 2)
    Set-Item "env:$name" $value
}

$SqlQuery = @"
IF NOT EXISTS (SELECT * FROM sys.database_principals WHERE name = '$($env:SERVICE_API_NAME)')
  CREATE USER [$($env:SERVICE_API_NAME)] FROM EXTERNAL PROVIDER;

IF NOT EXISTS (
  SELECT 1 FROM sys.database_role_members drm
  JOIN sys.database_principals r ON drm.role_principal_id = r.principal_id
  JOIN sys.database_principals m ON drm.member_principal_id = m.principal_id
  WHERE r.name = 'db_datareader' AND m.name = '$($env:SERVICE_API_NAME)'
)
  ALTER ROLE db_datareader ADD MEMBER [$($env:SERVICE_API_NAME)];

IF NOT EXISTS (
  SELECT 1 FROM sys.database_role_members drm
  JOIN sys.database_principals r ON drm.role_principal_id = r.principal_id
  JOIN sys.database_principals m ON drm.member_principal_id = m.principal_id
  WHERE r.name = 'db_datawriter' AND m.name = '$($env:SERVICE_API_NAME)'
)
  ALTER ROLE db_datawriter ADD MEMBER [$($env:SERVICE_API_NAME)];

IF NOT EXISTS (
  SELECT 1 FROM sys.database_role_members drm
  JOIN sys.database_principals r ON drm.role_principal_id = r.principal_id
  JOIN sys.database_principals m ON drm.member_principal_id = m.principal_id
  WHERE r.name = 'db_ddladmin' AND m.name = '$($env:SERVICE_API_NAME)'
)
  ALTER ROLE db_ddladmin ADD MEMBER [$($env:SERVICE_API_NAME)];
"@

az sql db query `
  --server $env:SQL_SERVER `
  --database $env:SQL_DATABASE `
  --resource-group $env:AZURE_RESOURCE_GROUP `
  --auth-mode ActiveDirectoryDefault `
  --queries $SqlQuery

💡 Make executable: chmod +x scripts/*.sh.

Verification

eval $(azd env get-values)
APP_NAME=$SERVICE_API_NAME  # or SERVICE_WEB_NAME

az sql db query --server "$SQL_SERVER" --database "$SQL_DATABASE" \
  --auth-mode ActiveDirectoryDefault --queries "
    SELECT dp.name AS UserName, dr.name AS RoleName
    FROM sys.database_principals dp
    JOIN sys.database_role_members drm ON dp.principal_id = drm.member_principal_id
    JOIN sys.database_principals dr ON drm.role_principal_id = dr.principal_id
    WHERE dp.name = '$APP_NAME'
  "

PowerShell:

azd env get-values | ForEach-Object {
    $name, $value = $_.Split('=', 2)
    Set-Item "env:$name" $value
}
$AppName = $env:SERVICE_API_NAME  # or SERVICE_WEB_NAME

$SqlQuery = @"
SELECT dp.name AS UserName, dr.name AS RoleName
FROM sys.database_principals dp
JOIN sys.database_role_members drm ON dp.principal_id = drm.member_principal_id
JOIN sys.database_principals dr ON drm.role_principal_id = dr.principal_id
WHERE dp.name = '$AppName'
"@

az sql db query --server $env:SQL_SERVER --database $env:SQL_DATABASE `
  --auth-mode ActiveDirectoryDefault --queries $SqlQuery

Expected: UserName matches $APP_NAME, RoleName includes db_datareader, db_datawriter, db_ddladmin.

Troubleshooting

Error Solution
"Cannot find the user" Verify identity exists: az webapp identity show or az containerapp identity show
"Principal does not have permission" Check you're Entra admin: az sql server ad-admin list
"Login failed for user" Run CREATE USER commands from this guide

Idempotent Script Pattern:

-- Check if user exists before creating
IF NOT EXISTS (SELECT * FROM sys.database_principals WHERE name = 'my-app')
  CREATE USER [my-app] FROM EXTERNAL PROVIDER;

-- Check role membership before adding
IF NOT EXISTS (
  SELECT 1 FROM sys.database_role_members drm
  JOIN sys.database_principals r ON drm.role_principal_id = r.principal_id
  JOIN sys.database_principals m ON drm.member_principal_id = m.principal_id
  WHERE r.name = 'db_datareader' AND m.name = 'my-app'
)
  ALTER ROLE db_datareader ADD MEMBER [my-app];

References

Source: SKILL.md on GitHub

1 alert16d4 checks · Risk SAFE
  • Gen Agent Trust Hub16d

    This skill provides comprehensive instructions and scripts for executing Azure deployments using various tools like the Azure Developer CLI (azd), Terraform, and Bicep. It includes several security considerations, such as the execution of deployment commands and the use of external scripts for database migrations. These operations are essential to the skill's intended purpose and are accompanied by extensive safety guidance, including the implementation of managed identities and mandatory user confirmation for destructive actions.

  • Socket16d

    1 alert: gptAnomaly

  • Snyk16d

    Risk: LOW · No issues

  • Runlayer6mo

    21/36 files flagged

Signed by skilld at d0c21c0. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub yesterday.

Activeupdated 5 months ago
metadata
{
  "author": "Microsoft",
  "version": "0.0.0-placeholder"
}

README badge

README badge for microsoft/github-copilot-for-azure/azure-deploy

Executes Azure deployments for applications with prepared infrastructure and validated deployment plans, running azd up, azd deploy, terraform apply, and az deployment commands with error recovery. Use this skill only after azure-prepare and azure-validate have completed — it does not create applications or infrastructure, only deploys them.

Generated from the current SKILL.md.

What prerequisites must be met before using this skill?
The azure-prepare skill must have completed (creating .azure/deployment-plan.md and infrastructure files) and the azure-validate skill must have run and confirmed status as 'Validated'. If either is missing, invoke those skills first.
Can I use this skill to create a new application?
No. This skill executes deployments for already-prepared applications only. Use the azure-prepare skill to create new applications or set up infrastructure.
What deployment methods does this skill support?
The skill runs azd up, azd deploy, terraform apply, and az deployment commands with built-in error recovery.
What happens if validation status is not 'Validated'?
The skill will not proceed. You must invoke azure-validate first and ensure the Validation Proof section in .azure/deployment-plan.md is populated with actual validation results.
Does this skill handle post-deployment configuration?
Yes. It configures SQL managed identity and applies Entity Framework migrations if applicable, following the post-deployment steps for the selected recipe.

Generated from the current SKILL.md. These answers refresh after source changes.