Azure
Azure
# Install Azure CLI.
curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash
# Show current configs of azure cli. (subscription_id, tenant_id)
az account show
# Create a service principal for terraform to operate on Azure, and save the credentials into a file.
# If we specify scope in subscription level, then this service principal will have access within subscription scope.
az ad sp create-for-rbac --name="sp-contributor-terraform" --role="Contributor" \
--scopes="/subscriptions/$AZ_SUBSCRIPTION_ID" \
> az_sp_terraform.json
# Delete the network watcher resource. Network Watcher is a regional service that enables you to monitor and diagnose conditions at a network scenario level in, to, and from Azure.
az network watcher configure --resource-group NetworkWatcherRG --locations \
eastus --enabled false
# Delete the resource group
az group delete <resource_group_name NetworkWatcherRG>
# List all locations/regions available on Azure. Useful when provisioning resources using IaC
az account list-locations -o table
# List resource groups that exist in current scope.
az group list
# List all available subscriptions.
az account list --output table
# Change the current subscription into another one
az account set --subscription "<subscription_name>"
# Lists all storage accounts
az storage account list
# Get the storage account name
az storage account list --query "[].name" --output tsv
# Get the containers within a storage account
az storage container list --account-name <storage_account_name> --auth-mode \
login --query "[].name" --output tsv
VM Connections within same Virtual Network?
If we create virtual machines within the same virtual network, they will be able to create ssh connections just by using their VM names. ssh web would work, for instance. (If there’s an NSG associated with one of them that has a rule to prevent SSH connections, then the connection won’t be established.)
# List all available locations/regions in Azure
az account list-locations -o table
# List all available vm images according to the specifications
az vm image list --publisher <PublisherName Canonical> --offer <OfferName UbuntuServer> --sku <SKUName 18.04-LTS> --location <Location germanywestcentral> --all --output tsv
# Get IP addresses of VMs.
az vm list-ip-addresses --output table
Budgets vs. Cost Alerts?
- Budgets:
- Budgets allow you to set a financial spending limit for a specific subscription, resource group, or service over a defined time period (e.g., monthly, quarterly).
- You can monitor and track your spending relative to the budget you have set.
- Azure provides notifications when your spending reaches a certain percentage of your budget (e.g., 50%, 75%, or 100%), but it doesn’t stop services automatically when the budget is exceeded.
- Example: You set a budget of $500 for your Azure subscription for the month. Azure will notify you when your spending hits $250 (50%), $375 (75%), and $500 (100%).
- Cost Alerts:
- Cost alerts are used to notify you based on specific spending thresholds or anomalies.
- These alerts can be set independently of a budget and can be triggered when unexpected spending occurs, or specific conditions are met.
- Example: You create a cost alert to notify you when your spending exceeds $100 in a week, regardless of your monthly budget.
Summary:
- Budgets help you plan and monitor your spending over time.
- Cost Alerts provide immediate notifications for custom thresholds or unexpected cost spikes.
# Retrieve specific Subscription ID
az account list --refresh --query "[?contains(name, '$SUBSCRIPTION_NAME')].id" --output table
# See all subscriptions, tenants available, check subscriptions, get subs
az account list --output table
# Set subscription, select subscription
az account set --subscription $YOUR_SUBSCRIPTION_ID
# Subscription resource id follows the format:
/subscriptions/$SUBSCRIPTION_ID
# Retrieve resource groups
az group list --output table
# Set default resource group
az configure --defaults group=$RESOURCE_GROUP_NAME
# Retrieve resources
az resource list --output table
# Check current Azure config, context
az account show
# List all available tenants
az account tenant list
# clear azure account
# When az cli gives authorization error, logging out and logging in solves the problem
az logout
az login
# Deploy Bicep template
az deployment group create --name $DEPLOYMENT_GROUP_NAME --template-file $TEMPLATE_FILE_PATH --parameters location=$LOCATION
# List statuses of deployment group deployments
az deployment group list --resource-group $YourResourceGroupName --output table
# List the output variables from a deployment group
az deployment group show --name "YourDeploymentName" --resource-group "YourResourceGroupName" --query properties.outputs --output json
# List role assignments for the current subscription scope
az role assignment list --scope "/subscriptions/$(az account show --query id -o tsv)"
# List role assignments for a specific resource group
az role assignment list --scope "/subscriptions/${subscriptionId}/resourceGroups/${resourceGroupName}" --output table
Q) What exactly Azure Private DNS Zone is?
Azure Private DNS Zone is essentially a table (or database) that maps domain names to private IP addresses within an Azure Virtual Network (VNet).
We can think of it like this:
| Hostname | Record Type | IP Address |
|---|---|---|
web.internal.azure | A | 10.0.0.10 |
db.internal.azure | A | 10.0.0.20 |
api.internal.azure | CNAME | web.internal.azure |
This table allows VMs, containers, or other resources inside the private network to resolve names without needing public DNS or manually managing host files.
Q) How az cli handles switching into another tenant?
When we switch into another subscription, and if that subscription is in another tenant, az cli automatically switches to that tenant, since each of them have globally unique id.
# List subnets of specific vnet
az network vnet subnet list --resource-group "YourResourceGroupName" --vnet-name "YourVNetName" --output table
# Filter resources to only show vnets deployed
az resource list --query "[?type=='Microsoft.Network/virtualNetworks']" --output table
# Show the details of app service deployment
az webapp show --name "YourAppServiceName" --resource-group "YourResourceGroupName" --output json
# Every Azure Resource has a unique ID. This uniqueness comes from the uniqueness of subscription IDs.
/subscriptions/A123b4567c-1234-1a2b-2b1a-1234abc12345/resourceGroups/ToyDevelopment/providers/Microsoft.Storage/storageAccounts/secrettoys
Q) How resource id’s are constructed (fully qualified resource name)?
It is possible to have multiple levels of child resources:
/subscriptions/A123b4567c-1234-1a2b-2b1a-1234abc12345/resourceGroups/ToyDevelopment/providers/Microsoft.Storage/storageAccounts/secrettoys/blobServices/default/containers/toyimages
The naming goes like → resourceProvider/resourceType/resourceName/resourceType/resourceName
# Deploy resources at subscription level
az deployment sub create --name $DEPLOYMENT_NAME --location $LOCATION --template-file $FILE_PATH --parameters main.parameters.json
Q) What’s the difference between child and extension resource? How do their resource ID’s differ?
Child Resource:
/subscriptions/A123b4567c-1234-1a2b-2b1a-1234abc12345/resourceGroups/ToyDevelopment/providers/Microsoft.Storage/storageAccounts/secrettoys/blobServices/default/containers/toyimages
Extension Resource:
/subscriptions/A123b4567c-1234-1a2b-2b1a-1234abc12345/resourceGroups/ToyDevelopment/providers/Microsoft.Storage/storageAccounts/secrettoys/providers/Microsoft.Authorization/locks/PreventDeletion
Differences:
Path Structure: A child resource ID has a single
/providers/.../segment, followed by the resource path. An extension resource ID has two/providers/.../segments.Relationship: A child resource is a fundamental component of its parent (e.g., a container must exist within a storage account’s blob service). An extension resource adds functionality to its parent, but is a separate, distinct resource entity.
# what-if deployment
az deployment group what-if --resource-group ToyStorage --template-file $templateFile --result-format FullResourcePayloads
Q) What are the deployment modes in Azure?
Incremental Mode
- This is the default deployment mode .In this mode, resource manager does not delete anything, if the item that is in Azure but not listed in bicep template, it simply ignores it.
Complete Mode
- Resources which are not inside of the bicep template are getting deleted in this mode. Not all of them though, to check which ones are getting effected → Complete mode deletion - Azure Resource Manager | Microsoft Learn
- To make it, we must explicitly set the parameter to
--mode Completeand the scope should begroupnotsub.
# Complete mode deployment az deployment group create --name main --mode Complete --confirm-with-what-if --template-file main.bicep -g ldz-test-tuna
Q) Can we place a resource into a subnet that resides in another subscription? No, each VNet and its subnets are tied to a specific subscription, and resources like VMs must be deployed to a subnet within a VNet that is in the same subscription.
Q) How does the Resource Hierarchy in Azure look like?

- tenant corresponds to Microsoft Entra instance.
- Management groups provide a way to organize Azure subscriptions, and we can apply policy and access-control restrictions to management groups, and all subscriptions below that management group in the hierarchy inherit these restrictions.
- Subscriptions act as billing accounts, and they contain resource groups and resources.
- Resource groups are logical containers for your resources.
Q) How to set the subscription which resources will be deployed to?
We can set the target subscription by using scope and then providing the subscription ID of the targeted scope.
targetScope = 'subscription'
@description('Subscription Id for the resource group creation')
param parSubscriptionId string
module modResourceGroup 'modules/resourceGroup.bicep' = {
// Here is the part where we define the correct scope
scope: subscription(parSubscriptionId)
name: varModuleDeploymentNames.modResourceGroup
params: {
parLocation: parLocation
parResourceGroupName: parResourceGroupName
}
}
# List management groups
az account management-group list --output table
Q) How to decide which scope to use in Bicep?
- resourceGroup → We want to deploy resources in resource groups
- subscription → We want to deploy resource groups, grant access to all resources within that fall under a subscription, defining and applying policy for subscriptions
- managementGroup → Grant access to all resources within a management group, defining and assigning policies that fall under management group (all subscriptions here), or even if we use tenantManagementGroup, we can apply this policy to our entire workload
- tenant → Create Azure Subscriptions, create or configure management groups, no creation of role assignments or policies are allowed within tenant scope
Q) How resource IDs differ from resources within rg level, and within mg/subscription level?
# This is a resource ID for a management group
/providers/Microsoft.Management/managementGroups/ProductionMG
# When there's a resource deployed at mg scope, the id looks like this
/providers/Microsoft.Management/managementGroups/ProductionMG/providers/Microsoft.Authorization/roleDefinitions/00000000-0000-0000-0000-000000000000
# For subscription level, a resource ID might look like this,
# it includes the subscription ID
/subscriptions/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/providers/Microsoft.Authorization/roleDefinitions/00000000-0000-0000-0000-000000000000
Q) What are differences between using template spec or storing bicep files in a different location, git for instance?
- Bicep modules retain all of the original Bicep code, including comments, symbolic names, and whitespace. When you create a template spec by using Bicep, your Bicep code is converted to JSON and some of this information is lost. So you need to keep the source Bicep file somewhere else as well. That’s why, using source control for bicep module templates is still necessary, regardless of using template specs or not.
Q) How does template specs work?
- First, we create our bicep files, nothing changes at this step.
- Second, we create a deployment called template spec into a rg, alongside with the version of the deployment.
- Third, we use these templates for our deployment, and these templates can also be used for different scopes (subs, tenants etc)
# Create a template spec
az ts create --name ToyCosmosDBAccount --location germanywestcentral --display-name "Cosmos DB account" --description "This template spec creates a Cosmos DB account that meets our company's requirements." --version 1.1 --template-file modules/cosmosDB.bicep -g ldz-test-tuna
# Deploy template spec
# First retrieve the id of template spec
az ts show --name ToyCosmosDBAccount --resource-group "[sandbox resource group name]" --version "1.0" --query "id"
# OPTIONAL - if the template spec resides in different subscription, then --subscription
# parameter is necessary
az ts show --name RG-vNet --resource-group "ldz-test-tuna" --version "1.0" --query "id" --subscription "<subscription-id>"
# Then, deploy it
az deployment group create --template-spec $TEMPLATE_SPEC_RESOURCE_ID
# It is not good practice to do versioning often for template specs,
# If there's a hotfix, then it's better to use update cmd which will update existing version
az ts update --resource-group MyResourceGroup --name MyTemplateSpec --version 1.0 --template-file azuredeploy.json
# Delete template spec(ts) version
az ts delete --resource-group MyResourceGroup --name MyTemplateSpec --version 1.0
Q) What are the differences between template specs and registries for modules? Which one to use?
A good rule of thumb is: if the template is going to be deployed as-is throughout your organization, template specs are probably a good fit. But if you’re likely to reuse this template within multiple parent templates, Bicep modules might serve your needs better. A registry is a good way to share modules.
# Deploy Azure Container Registry (acr)
# Premium because basic and standard sku does not support --public-network-enabled flag
az acr create --name acr-test --sku Premium --location germanywestcentral -g ldz-test-tuna --public-network-enabled false
# Publish bicep files to ACR
az bicep publish --file $FILE_NAME --target 'br:YOUR_CONTAINER_REGISTRY_NAME.azurecr.io/website:v1'
Q) What do we mean by an application ?
Microsoft Entra ID has a concept of an application, which represents a system, piece of software, process, or some other non-human agent. You can think of a deployment workflow as an application, too.
Q) Why we do not use managed identities for github workflows, but rather we use federated credentials? Managed identities require that you own and manage the Azure resources that run your deployments. When you work with GitHub Actions, you usually rely on shared infrastructure that Microsoft or GitHub provides.
Q) How does federated credentials work?
- When your workflow needs to communicate with Azure, GitHub securely contacts Microsoft Entra ID to request an access token. GitHub provides information about the GitHub organization (
my-github-user), the repository (my-repo), and the branch on which the workflow is running (main). It also includes your tenant ID within Microsoft Entra ID, the application ID of the workflow identity’s application registration, and the Azure subscription ID to which your workflow wants to deploy. - Microsoft Entra ID validates the application ID and checks whether a federated credential exists within the application for the GitHub organization, repository, and branch.
- After Microsoft Entra ID determines that the request is valid, it issues an access token. Your workflow uses the access token when it communicates with Azure Resource Manager.
Create a workload identity for a GitHub Actions workflow - Training | Microsoft Learn
Q) How does a typical Bicep code deployment workflow look like?
- Lint: Use the Bicep linter to verify that the Bicep file is well formed and doesn’t contain any obvious errors.
- Validate: Use the Azure Resource Manager preflight validation process to check for problems that might occur when you deploy.
- Preview: Use the what-if command to validate the list of changes that are applied against your Azure environment. Ask a human to manually review the what-if results and approve the workflow to proceed.
- Deploy: Submit your deployment to Resource Manager and wait for it to finish.
- Smoke Test: Run basic post-deployment checks against some of the important resources that you deployed. These checks are called infrastructure smoke tests.
Q) What does linter check?
- Unused parameters. The linter scans for any parameters that aren’t used anywhere in the Bicep file. By eliminating unused parameters, you make it easier to deploy your template because you don’t have to provide unnecessary values. You also reduce confusion when someone tries to work with your Bicep file.
- String interpolation. The linter checks if your file uses the
concat()function instead of Bicep string interpolation. String interpolation makes your Bicep files more readable. - Default values for secure parameters. The linter warns you if you set default values for parameters marked with the
@secure()decorator. Setting defaults for secure parameters is a bad practice because it gives the secure parameter a human-readable value, and people might not change it before they deploy.
Q) What is Microsoft Graph API? How does it differ from ARM API?
Microsoft Graph API is scoped to Microsoft Entra ID (Azure AD) resources.
Examples:
- Users, Groups, App Registrations (Service Principals)
- Conditional Access, Devices, Licenses
- Used for: Identity, authentication, and user/app/resource graph.
🔗 Think of it as the API for identity-related tasks.
Azure Resource Manager (ARM) API is scoped to Azure resources, subscriptions and management groups.
| Feature | Graph API | ARM API |
|---|---|---|
| Domain | Microsoft Entra ID (Azure AD) | Azure Subscription Resources |
| Example Entity | App Registration (SPN) | VM, Storage Account |
| Tool to Access | Microsoft Graph | Azure Resource Manager |
| Privilege Needed | Azure AD roles | Azure RBAC roles |
| Resource | API Scope | Managed By |
|---|---|---|
| Subscription | ARM | Azure Resource Manager |
| Management Group | ARM | Azure Resource Manager |
| App Registration | Graph | Microsoft Entra ID |
| User / Group | Graph | Microsoft Entra ID |
Q) How does IP groups work, and how firewalls can access IP groups that are in other vnets?
IP Groups are global and can be used across regions regardless where they are stored.
Q) What is the difference between AppID and ObjectID of a registered application on Microsoft Entra?
| Term | Meaning | Uniqueness | Example usage |
|---|---|---|---|
| App ID | Also called Client ID – it’s the globally unique ID of the App Registration (shared across tenants). | Globally unique | Used by OAuth clients, SP creation |
| Object ID | Unique ID of the App Registration within the tenant’s directory. | Unique per tenant | Used for managing app metadata or deletion |