# AZ CLI Azure provides three administration tools: * The Azure portal * The Azure CLI : https://learn.microsoft.com/en-us/cli/azure/reference-index?view=azure-cli-latest#az-login * Azure PowerShell ## Cloud Shell [Azure Cloud Shell](https://learn.microsoft.com/en-us/azure/cloud-shell/overview){:target="_blank"} is an interactive, browser-accessible shell for managing Azure resources. It provides the flexibility of choosing the shell experience that best suits the way you work. Linux users can opt for a Bash experience, while Windows users can opt for PowerShell. Azure Cloud Shell features * Is temporary and requires a new or existing Azure Files share to be mounted. * Requires a resource group, storage account, and Azure File share. * Persists $HOME using a 5-GB image held in your file share. * Uses the same Azure file share for both Bash and PowerShell. * Offers an integrated graphical text editor based on the open-source Monaco Editor. * Authenticates automatically for instant access to your resources. * Runs on a temporary host provided on a per-session, per-user basis. * Times out after 20 minutes without interactive activity. * Is assigned to one machine per user account. * Permissions are set as a regular Linux user in Bash. **Cloud Shell direct Url**: [https://shell.azure.com](https://shell.azure.com){:target="_blank"} ## Azure CLI [azure cli](https://learn.microsoft.com/en-us/cli/azure/){:target="_blank"} Azure CLI is a command-line program to connect to Azure and execute administrative commands on Azure resources. It runs on **Linux, macOS, and Windows** (cross-platform) ``` # default config az config get az config set defaults.group=$RG # LOGIN //login with user az login az login -u -p //to avoid password isplay in console read -sp "Azure password: " AZ_PASS && echo && az login -u -p $AZ_PASS //Powershell $AzCred = Get-Credential -UserName az login -u $AzCred.UserName -p $AzCred.GetNetworkCredential().Password //login with service principal sp az login --service-principal -u -p --tenant read -sp "Azure password: " AZ_PASS && echo && az login --service-principal -u -p $AZ_PASS --tenant //powershell $AzCred = Get-Credential -UserName az login --service-principal -u $AzCred.UserName -p $AzCred.GetNetworkCredential().Password --tenant // login with managed identity az login --identity // change tenant az login --tenant ## Subscription & MG // change the active subscription using the subscription name az account set --subscription "My Demos" // change the active subscription using the subscription ID az account set --subscription "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" //change the active subscription using a variable subscriptionId="$(az account list --query "[?isDefault].id" -o tsv)" az account set --subscription $subscriptionId // lock subs az account lock create --name "Cannot delete subscription" --lock-type CanNotDelete //MG az account management-group create --name Contoso01 az account management-group list // Add subscriptions to your new group az account management-group subscription add --name Contoso01 --subscription "My Demos" az account management-group subscription add --name Contoso01 --subscription "My Second Demos" ``` ``` //vm az vm create \ --resource-group CrmTestingResourceGroup \ --name CrmUnitTests \ --image UbuntuLTS // disk az group create --name $RG --location eastus az group show $RG az group list --output table az group list --query "[?name == '$RESOURCE_GROUP']" az storage account create --resource-group MyResourceGroup --name storage134 --location eastus --sku Standard_LRS az disk create ---resource-group $RG --name $DISKANAME --size-gb --sku Standard_LRS az disk update ---resource-group $RG --name $DISKANAME --size-gb 64 || az disk update -g $RG -n $DISKANAME --size-gb 64 az disk show ---resource-group $RG --name $DISKANAME --query diskSizeGb //change disk type az disk update ---resource-group $RG --name $DISKANAME --sku 'Premium_LRS' az disk show ---resource-group $RG --name $DISKANAME --query sku ``` **App service: web app** ``` az appservice plan create --name $AZURE_APP_PLAN --resource-group $RESOURCE_GROUP --location $AZURE_REGION --sku FREE az appservice plan list --output table az webapp create --name $AZURE_WEB_APP --resource-group $RESOURCE_GROUP --plan $AZURE_APP_PLAN az webapp list --output table // deploy code from GitHub az webapp deployment source config --name $AZURE_WEB_APP --resource-group $RESOURCE_GROUP --repo-url "https://github.com/Azure-Samples/php-docs-hello-world" --branch master --manual-integration curl $AZURE_WEB_APP.azurewebsites.net Hello World! **deploy a local ARM template** templateFile="{provide-the-path-to-the-template-file}" az deployment group create \ --name blanktemplate \ --resource-group myResourceGroup \ --template-file $templateFile ``` ## Azure Powershell [azure powershell](https://learn.microsoft.com/en-us/powershell/azure/?view=azps-9.4.0&viewFallbackFrom=azps-6.5.0){:target="_blank"} Suppose you've chosen Azure PowerShell as your automation solution. Your administrators prefer to run their scripts locally rather than in the Azure Cloud Shell. The team uses machines that run Linux, macOS, and Windows. You need to get Azure PowerShell working on all their devices. We'll go through the actual installation instructions in the next unit, but let's look at the two components that make up Azure PowerShell. * The base PowerShell product This comes in two variants: Windows PowerShell and **PowerShell 7.x, which can be installed on Windows, macOS, and Linux**. * The Azure **Az PowerShell module** This extra module must be installed to add the Azure-specific commands to PowerShell. ``` Deploy powershell on Linux: https://learn.microsoft.com/en-us/training/modules/automate-azure-tasks-with-powershell/4-exercise-install-azure-powershell?pivots=linux //login Connect-AzAccount Set-AzContext -Subscription '00000000-0000-0000-0000-000000000000' Get-AzResourceGroup | Format-Table New-AzResourceGroup -Name -Location //diks $location = (Get-AzResourceGroup -Name xxxx).Location New-AzDiskConfig -Location $location -DiskSizeGb 32 -Sku Standard_LRS Get-AzDisk -ResourceGroupName $RG -Name $diskname New-AzDiskUpdateConfig -DiskSizeGB 64 | Update-AzDisk -ResourceGroupName $RG -Name $diskname New-AzDiskUpdateConfig -Sku Premium_LRS | Update-AzDisk -ResourceGroupName $RG -Name $diskname (Get-AzDisk -ResourceGroupName $RG -Name $diskname).Sku ``` **VM** ``` az vm image list --sku Wordpress --output table --all az vm image list --output table az vm create \ --resource-group [sandbox resource group name] \ --location westus \ --name SampleVM \ --image UbuntuLTS \ --admin-username azureuser \ --generate-ssh-keys \ --verbose New-AzVm ` -ResourceGroupName "CrmTestingResourceGroup" ` -Name "CrmUnitTests" ` -Image "UbuntuLTS" //resize //get list of possible size az vm list-vm-resize-options \ --resource-group [sandbox resource group name] \ --name SampleVM \ --output table az vm resize \ --resource-group [sandbox resource group name] \ --name SampleVM \ --size Standard_D2s_v3 Get-AzVM -Name MyVM -ResourceGroupName CrmUnitTests New-AzVm -ResourceGroupName myRG -Name "testvm-eus-01" -Location "East US" -Image Canonical:0001-com-ubuntu-server-focal:20_04-lts:latest -OpenPorts 22 -PublicIpAddressName "testvm-01" -Credential (Get-Credential) $vm = (Get-AzVM -Name "testvm-eus-01" -ResourceGroupName myRG) $vm.StorageProfile.OsDisk $vm | Get-AzVMSize // get your public IP address az vm list-ip-addresses -n SampleVM -o table Get-AzPublicIpAddress -ResourceGroupName myRG -Name "testvm-01" Stop-AzVM -Name $vm.Name -ResourceGroupName $vm.ResourceGroupName Remove-AzVM -Name $vm.Name -ResourceGroupName $vm.ResourceGroupName //The Remove-AzVM command just deletes the VM. It doesn't clean up any of the other resources. At this point, we'd likely just delete the resource group itself and be done with it. // However,let's run through the exercise to clean it up manually. You should see a pattern in the commands. // Delete the network interface: $vm | Remove-AzNetworkInterface –Force // Delete the managed OS disks and storage account Get-AzDisk -ResourceGroupName $vm.ResourceGroupName -DiskName $vm.StorageProfile.OSDisk.Name | Remove-AzDisk -Force Next, delete the virtual network: Get-AzVirtualNetwork -ResourceGroupName $vm.ResourceGroupName | Remove-AzVirtualNetwork -Force // Delete the network security group Get-AzNetworkSecurityGroup -ResourceGroupName $vm.ResourceGroupName | Remove-AzNetworkSecurityGroup -Force // And finally, delete the public IP address: Get-AzPublicIpAddress -ResourceGroupName $vm.ResourceGroupName | Remove-AzPublicIpAddress -Force // open vm port az vm open-port \ --port 80 \ --resource-group [sandbox resource group name] \ --name SampleVM ``` **ARM template** ``` // deploy a local ARM template $templateFile = "{provide-the-path-to-the-template-file}" New-AzResourceGroupDeployment ` -Name blanktemplate ` -ResourceGroupName myResourceGroup ` -TemplateFile $templateFile ``` ## Manage identities and governance in Azure Vue IHM Search bar : Active Directory * Overview : Manage tenant * ... * Users * Groups * External identities * Role and Administrators * Administrative Units * .... * User settings Dynamic membership role : (user.jobTitle -eq "Cloud Administrator") You can add individual user accounts through the Azure portal, Azure PowerShell, or the Azure CLI. You can add individual user accounts through the Azure portal, Azure PowerShell, or the Azure CLI. ``` # create a new user az ad user create / delete New-AzureADUser / Remove-AzADUser //You can bulk create member users and guests accounts. The following example shows how to bulk invite guest users. $invitations = import-csv c:\bulkinvite\invitations.csv $messageInfo = New-Object Microsoft.Open.MSGraph.Model.InvitedUserMessageInfo $messageInfo.customizedMessageBody = "Hello. You are invited to the Contoso organization." foreach ($email in $invitations) {New-AzureADMSInvitation ` -InvitedUserEmailAddress $email.InvitedUserEmailAddress ` -InvitedUserDisplayName $email.Name ` -InviteRedirectUrl https://myapps.microsoft.com ` -InvitedUserMessageInfo $messageInfo ` -SendInvitationMessage $true } ``` **Azure policy** ``` New-AzPolicyDefinition -Name 'AuditStorageAccounts' -DisplayName 'Audit Storage Accounts Open to Public Networks' -Policy 'AuditStorageAccounts.json' $rg = Get-AzResourceGroup -Name 'ContosoRG' $Policy = Get-AzPolicyDefinition -Name 'AuditStorageAccounts' New-AzPolicyAssignment -Name 'AuditStorageAccounts' -PolicyDefinition $Policy -Scope $rg.ResourceId //bash az policy definition create --name 'audit-storage-accounts-open-to-public-networks' --display-name 'Audit Storage Accounts Open to Public Networks' --description 'This policy ensures that storage accounts with exposures to public networks are audited.' --rules '' --mode All az policy definition show --name 'Audit Storage Accounts with Open Public Networks' az policy assignment create --name '' --scope '' --policy '' ``` ### Implement and manage storage in Azure ``` //create blob container New-AzStorageContainer export STORAGENAME=medicalrecords$RANDOM az storage account create \ --name $STORAGENAME \ --access-tier hot \ --kind StorageV2 \ --resource-group [sandbox resource group] az storage container create \ --name patient-images \ --account-name $STORAGENAME \ --public-access off az storage blob upload-batch \ --source sas \ --destination patient-images \ --account-name $STORAGENAME \ --pattern *.jpg ``` ### AKS az group create --name myResourceGroup --location eastus2 az aks create \ --resource-group myResourceGroup \ --name myAKSCluster \ --generate-ssh-keys \ --vm-set-type VirtualMachineScaleSets \ --load-balancer-sku standard \ --node-count 3 \ --zones 1 2 3 # --enable-cluster-autoscaler \ # --min-count 1 \ # --max-count 3 az aks get-credentials --resource-group myResourceGroup --name myAKSCluster // manual scale az aks scale \ --resource-group myResourceGroup \ --name myAKSCluster \ --node-count 5 /// add autoscaler in existing cluster az aks update \ --resource-group myResourceGroup \ --name myAKSCluster \ --enable-cluster-autoscaler \ --min-count 1 \ --max-count 3 ## App service //deploy zip file az webapp deployment source config-zip // in code folder az webapp up cd ~/BestBikeApp dotnet publish -o pub cd pub zip -r site.zip * az webapp deployment source config-zip \ --src site.zip \ --resource-group [sandbox resource group name] \ --name ### VNet - Subnet az network vnet create \ --resource-group [sandbox resource group name] \ --name ManufacturingVnet \ --address-prefixes 10.30.0.0/16 \ --location northeurope az network vnet subnet create \ --resource-group [sandbox resource group name] \ --vnet-name ManufacturingVnet \ --name ManufacturingSystemSubnet \ --address-prefixes 10.30.10.0/24 az network vnet subnet create \ --resource-group [sandbox resource group name] \ --vnet-name ManufacturingVnet \ --name SensorSubnet1 \ --address-prefixes 10.30.20.0/24 az network vnet subnet list \ --resource-group [sandbox resource group name] \ --vnet-name ManufacturingVnet \ --output table ### VNet peering //create the peering connection between the SalesVNet and MarketingVNet virtual network az network vnet peering create \ --name SalesVNet-To-MarketingVNet \ --remote-vnet MarketingVNet \ --resource-group [sandbox resource group name] \ --vnet-name SalesVNet \ --allow-vnet-access // create a reciprocal connection from MarketingVNet to SalesVNet. az network vnet peering create \ --name MarketingVNet-To-SalesVNet \ --remote-vnet SalesVNet \ --resource-group [sandbox resource group name] \ --vnet-name MarketingVNet \ --allow-vnet-access az network vnet peering list \ --resource-group [sandbox resource group name] \ --vnet-name SalesVNet \ --query "[].{Name:name, Resource:resourceGroup, PeeringState:peeringState, AllowVnetAccess:allowVirtualNetworkAccess}"\ --output table ### route and route table // route table az network route-table create \ --name publictable \ --resource-group [sandbox resource group name] \ --disable-bgp-route-propagation false //create a custom route. az network route-table route create \ --route-table-name publictable \ --resource-group [sandbox resource group name] \ --name productionsubnet \ --address-prefix 10.0.1.0/24 \ --next-hop-type VirtualAppliance \ --next-hop-ip-address 10.0.2.4 // Create a virtual network and subnets az network vnet create \ --name vnet \ --resource-group [sandbox resource group name] \ --address-prefixes 10.0.0.0/16 \ --subnet-name publicsubnet \ --subnet-prefixes 10.0.0.0/24 az network vnet create \ --name vnet \ --resource-group [sandbox resource group name] \ --address-prefixes 10.0.0.0/16 \ --subnet-name publicsubnet \ --subnet-prefixes 10.0.0.0/24 //Associate the route table with the public subnet az network vnet subnet update \ --name publicsubnet \ --vnet-name vnet \ --resource-group [sandbox resource group name] \ --route-table publictable ### deploy network virtual Appliance https://learn.microsoft.com/en-us/training/modules/control-network-traffic-flow-with-routes/5-exercise-create-nva-vm ### Azure LB 1 Create a new public IP address. az network public-ip create \ --resource-group [sandbox resource group name] \ --allocation-method Static \ --name myPublicIP 2 Create the load balancer. az network lb create \ --resource-group [sandbox resource group name] \ --name myLoadBalancer \ --public-ip-address myPublicIP \ --frontend-ip-name myFrontEndPool \ --backend-pool-name myBackEndPool 3 To allow the load balancer to monitor the status of the healthcare portal az network lb probe create \ --resource-group [sandbox resource group name] \ --lb-name myLoadBalancer \ --name myHealthProbe \ --protocol tcp \ --port 80 4 rule az network lb rule create \ --resource-group [sandbox resource group name] \ --lb-name myLoadBalancer \ --name myHTTPRule \ --protocol tcp \ --frontend-port 80 \ --backend-port 80 \ --frontend-ip-name myFrontEndPool \ --backend-pool-name myBackEndPool \ --probe-name myHealthProbe 5 Connect the VMs to the back-end pool by updating the network interfaces az network nic ip-config update \ --resource-group [sandbox resource group name] \ --nic-name webNic1 \ --name ipconfig1 \ --lb-name myLoadBalancer \ --lb-address-pools myBackEndPool az network nic ip-config update \ --resource-group [sandbox resource group name] \ --nic-name webNic2 \ --name ipconfig1 \ --lb-name myLoadBalancer \ --lb-address-pools myBackEndPool echo http://$(az network public-ip show \ --resource-group [sandbox resource group name] \ --name myPublicIP \ --query ipAddress \ --output tsv) ### monitor metrics az monitor metrics alert create \ -n "Cpu80PercentAlert" \ --resource-group [sandbox resource group name] \ --scopes $VMID \ --condition "max percentage CPU > 80" \ --description "Virtual machine is running at or greater than 80% CPU utilization" \ --evaluation-frequency 1m \ --window-size 1m \ --severity 3