2.- AZ-104 Governance and Compliance

AZ-104 - Governance and Compliance - Managing Subscriptions

Organize and manage multiple Azure subscriptions
What are subscriptions

Examples:

you can define multiple subscriptions per department to identify costs

image.png

Subscription naming conventions

- Prod/Dev/Staging

 Subscriptions are named based on whether they are production, development or staging environments.

- Department/Teams

Subscriptions are named based on the department or team the subscription is intended for so that billing can then be easily associated with a given business unit.

- Region

Subscription are name based on the region of the business that uses the subscription.

AZ-104 - Governance and Compliance - Using management groups

What are Azure management groups?

Management groups

Managing subscriptions

Organize and manage subscriptions by logically grouping them into management groups

Parent-child relationships

Compliance Support

Next diagram shows how to represent an organizational hierarchy by having a Root management group, under root we have a subscription for EA, a Marketing management group and an IT management group.

The Marketing group also have 2 child subscriptions under the marketing management group and IT has another management group as a child management group.

This helps identify the hierarchy levels for our organization

image.png

All resources, permissions, etc will flow down in the hierarchy, for example if you give access to the root management group it will have access to IT, Marketing, etc it flow down in the hierarchy.

Illustration below shows 2 management groups under the main root Tenant group, we can access and add subscriptions or management groups inside an existing management group.

image.png

Here we can see the Parent management group for IManagementHTF its Tenant Root for HTF Organization since we created this management group inside our root

image.png

Root management group is not given by default

Root Management group cannot be moved or deleted

Azure RBAC is supported for management groups

Global Administrators must be elevated to User Access Administrator of root group

AZ-104 - Governance and Compliance - Understanding Azure Policy

Control and organize Azure resources with Azure Resource Manager

Understanding Azure Policy

Enforce Compliance and enable auditing

Organization need to implement enterprise-level governance and compliance capabilities.

Prohibit resources
Allowed Locations

image.png

Policy Definition

Defines the evaluation criteria for compliance, and defines the actions that take place. Either audit or deny should be something outside of compliance.

Policy Assignment

The scope at which we will assign our policy. The scope could be a management group, subscription, resource group, or resource.

Initiative Definition

 A collection of policies that are tailored to achieving a singular high-level goal together (e.g., ensuring that VMs meet standards).

image.png

Policy Definition

Evaluate if a VM is being created with our tag Project:az104. if the VM is missing the tag, then deny creation of the resource.

Policy assignment  Assign the policy at the scope of the resource where the VMs will be created

image.png

image.png


AZ-104 - Governance and Compliance - Tagging Resources

Control and organize Azure resources with Azure Resource Manager

Tags

What are tags: its a form of Name:Value

image.png

image.png

Here we can create tags, tags are not allowed to have the same name

image.png

Lets test with the following ARM template.

(refer to Arm Template here to investigate how to deploy an ARM template)

Arm template for TAG test
{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "storageAccountName": {
      "type": "string",
      "metadata": {
        "description": "Name of storage account"
      }
    },
    "adminUsername": {
      "type": "string",
      "metadata": {
        "description": "Admin username"
      }
    },
    "adminPassword": {
      "type": "securestring",
      "metadata": {
        "description": "Admin password"
      }
    },
    "dnsNameforLBIP": {
      "type": "string",
      "metadata": {
        "description": "DNS for Load Balancer IP"
      }
    },
    "vmNamePrefix": {
      "type": "string",
      "defaultValue": "myVM",
      "metadata": {
        "description": "Prefix to use for VM names"
      }
    },
    "imagePublisher": {
      "type": "string",
      "defaultValue": "MicrosoftWindowsServer",
      "metadata": {
        "description": "Image Publisher"
      }
    },
    "imageOffer": {
      "type": "string",
      "defaultValue": "WindowsServer",
      "metadata": {
        "description": "Image Offer"
      }
    },
    "imageSKU": {
      "type": "string",
      "defaultValue": "2019-Datacenter",
      "metadata": {
        "description": "Image SKU"
      }
    },
    "lbName": {
      "type": "string",
      "defaultValue": "myLB",
      "metadata": {
        "description": "Load Balancer name"
      }
    },
    "nicNamePrefix": {
      "type": "string",
      "defaultValue": "nic",
      "metadata": {
        "description": "Network Interface name prefix"
      }
    },
    "publicIPAddressName": {
      "type": "string",
      "defaultValue": "myPublicIP",
      "metadata": {
        "description": "Public IP Name"
      }
    },
    "vnetName": {
      "type": "string",
      "defaultValue": "myVNET",
      "metadata": {
        "description": "VNET name"
      }
    },
    "vmSize": {
      "type": "string",
      "defaultValue": "Standard_D2s_v3",
      "metadata": {
        "description": "Size of the VM"
      }
    },
    "location": {
      "type": "string",
      "defaultValue": "[resourceGroup().location]",
      "metadata": {
        "description": "Location for all resources"
      }
    }
  },
  "variables": {
    "storageAccountType": "Standard_LRS",
    "availabilitySetName": "myAvSet",
    "addressPrefix": "10.0.0.0/16",
    "subnetName": "Subnet-1",
    "subnetPrefix": "10.0.0.0/24",
    "publicIPAddressType": "Dynamic",
    "subnetRef": "[resourceId('Microsoft.Network/virtualNetworks/subnets', parameters('vnetName'), variables ('subnetName'))]",
    "publicIPAddressID": "[resourceId('Microsoft.Network/publicIPAddresses',parameters('publicIPAddressName'))]",
    "numberOfInstances": 2
  },
  "resources": [
    {
      "type": "Microsoft.Storage/storageAccounts",
      "name": "[parameters('storageAccountName')]",
      "apiVersion": "2019-06-01",
      "location": "[parameters('location')]",
      "sku": {
        "name": "[variables('storageAccountType')]"
      },
      "kind": "StorageV2"
    },
    {
      "type": "Microsoft.Compute/availabilitySets",
      "name": "[variables('availabilitySetName')]",
      "apiVersion": "2019-12-01",
      "location": "[parameters('location')]",
      "properties": {
        "platformFaultDomainCount": 2,
        "platformUpdateDomainCount": 5
      },
      "sku": {
        "name": "Aligned"
      }
    },
    {
      "apiVersion": "2020-05-01",
      "type": "Microsoft.Network/publicIPAddresses",
      "name": "[parameters('publicIPAddressName')]",
      "location": "[parameters('location')]",
      "properties": {
        "publicIPAllocationMethod": "[variables('publicIPAddressType')]",
        "dnsSettings": {
          "domainNameLabel": "[parameters('dnsNameforLBIP')]"
        }
      }
    },
    {
      "apiVersion": "2020-05-01",
      "type": "Microsoft.Network/virtualNetworks",
      "name": "[parameters('vnetName')]",
      "location": "[parameters('location')]",
      "properties": {
        "addressSpace": {
          "addressPrefixes": [
            "[variables('addressPrefix')]"
          ]
        },
        "subnets": [
          {
            "name": "[variables('subnetName')]",
            "properties": {
              "addressPrefix": "[variables('subnetPrefix')]"
            }
          }
        ]
      }
    },
    {
      "apiVersion": "2020-05-01",
      "type": "Microsoft.Network/networkInterfaces",
      "name": "[concat(parameters('nicNamePrefix'), copyindex())]",
      "location": "[parameters('location')]",
      "copy": {
        "name": "nicLoop",
        "count": "[variables('numberOfInstances')]"
      },
      "dependsOn": [
        "[resourceId('Microsoft.Network/virtualNetworks/', parameters('vnetName'))]",
        "[resourceId('Microsoft.Network/loadBalancers/', parameters('lbName'))]"
      ],
      "properties": {
        "ipConfigurations": [
          {
            "name": "ipconfig1",
            "properties": {
              "privateIPAllocationMethod": "Dynamic",
              "subnet": {
                "id": "[variables('subnetRef')]"
              },
              "loadBalancerBackendAddressPools": [
                {
                  "id": "[resourceId('Microsoft.Network/loadBalancers/backendAddressPools', parameters('lbName'), 'BackendPool1')]"
                }
              ],
              "loadBalancerInboundNatRules": [
                {
                  "id": "[resourceId('Microsoft.Network/loadBalancers/inboundNatRules', parameters('lbName'), concat('RDP-VM', copyindex()))]"
                }
              ]
            }
          }
        ]
      }
    },
    {
      "apiVersion": "2020-05-01",
      "name": "[parameters('lbName')]",
      "type": "Microsoft.Network/loadBalancers",
      "location": "[parameters('location')]",
      "dependsOn": [
        "[resourceId('Microsoft.Network/publicIPAddresses/', parameters('publicIPAddressName'))]"
      ],
      "properties": {
        "frontendIPConfigurations": [
          {
            "name": "LoadBalancerFrontEnd",
            "properties": {
              "publicIPAddress": {
                "id": "[variables('publicIPAddressID')]"
              }
            }
          }
        ],
        "backendAddressPools": [
          {
            "name": "BackendPool1"
          }
        ],
        "inboundNatRules": [
          {
            "name": "RDP-VM0",
            "properties": {
              "frontendIPConfiguration": {
                "id": "[resourceId('Microsoft.Network/loadBalancers/frontendIPConfigurations', parameters('lbName'), 'LoadBalancerFrontEnd')]"
              },
              "protocol": "Tcp",
              "frontendPort": 50001,
              "backendPort": 3389,
              "enableFloatingIP": false
            }
          },
          {
            "name": "RDP-VM1",
            "properties": {
              "frontendIPConfiguration": {
                "id": "[resourceId('Microsoft.Network/loadBalancers/frontendIPConfigurations', parameters('lbName'), 'LoadBalancerFrontEnd')]"
              },
              "protocol": "Tcp",
              "frontendPort": 50002,
              "backendPort": 3389,
              "enableFloatingIP": false
            }
          }
        ],
        "loadBalancingRules": [
          {
            "name": "LBRule",
            "properties": {
              "frontendIPConfiguration": {
                "id": "[resourceId('Microsoft.Network/loadBalancers/frontendIPConfigurations', parameters('lbName'), 'LoadBalancerFrontEnd')]"
              },
              "backendAddressPool": {
                "id": "[resourceId('Microsoft.Network/loadBalancers/backendAddressPools', parameters('lbName'), 'BackendPool1')]"

              },
              "protocol": "Tcp",
              "frontendPort": 80,
              "backendPort": 80,
              "enableFloatingIP": false,
              "idleTimeoutInMinutes": 5,
              "probe": {
                "id": "[resourceId('Microsoft.Network/loadBalancers/probes', parameters('lbName'), 'tcpProbe')]"
              }
            }
          }
        ],
        "probes": [
          {
            "name": "tcpProbe",
            "properties": {
              "protocol": "Tcp",
              "port": 80,
              "intervalInSeconds": 5,
              "numberOfProbes": 2
            }
          }
        ]
      }
    },
    {
      "apiVersion": "2019-12-01",
      "type": "Microsoft.Compute/virtualMachines",
      "name": "[concat(parameters('vmNamePrefix'), copyindex())]",
      "copy": {
        "name": "virtualMachineLoop",
        "count": "[variables('numberOfInstances')]"
      },
      "location": "[parameters('location')]",
      "dependsOn": [
        "[resourceId('Microsoft.Storage/storageAccounts/', parameters('storageAccountName'))]",
        "[resourceId('Microsoft.Network/networkInterfaces/', concat(parameters('nicNamePrefix'), copyindex()))]",
        "[resourceId('Microsoft.Compute/availabilitySets/', variables('availabilitySetName'))]"
      ],
      "properties": {
        "availabilitySet": {
          "id": "[resourceId('Microsoft.Compute/availabilitySets',variables('availabilitySetName'))]"
        },
        "hardwareProfile": {
          "vmSize": "[parameters('vmSize')]"
        },
        "osProfile": {
          "computerName": "[concat(parameters('vmNamePrefix'), copyIndex())]",
          "adminUsername": "[parameters('adminUsername')]",
          "adminPassword": "[parameters('adminPassword')]"
        },
        "storageProfile": {
          "imageReference": {
            "publisher": "[parameters('imagePublisher')]",
            "offer": "[parameters('imageOffer')]",
            "sku": "[parameters('imageSKU')]",
            "version": "latest"
          },
          "osDisk": {
            "createOption": "FromImage"
          }
        },
        "networkProfile": {
          "networkInterfaces": [
            {
              "id": "[resourceId('Microsoft.Network/networkInterfaces',concat(parameters('nicNamePrefix'),copyindex()))]"
            }
          ]
        },
        "diagnosticsProfile": {
          "bootDiagnostics": {
            "enabled": true,
            "storageUri": "[reference(parameters('storageAccountName'), '2019-06-01').primaryEndpoints.blob]"
          }
        }
      }
    }
  ]
}

After deploying our VMs using the ARM template, we can see that the resource group show the tags we previously assign.

image.png

If we go to our virtual machine we notice tags are not inherited from the resource group

image.png

Manage resources via tags, For example shutting down all VM's with a specific tag or developers can only update VMs with a specific tag.

Tags are not inheritance from the higher scope like a resource group, Each resource group must be tagged iinidependently. You can use Azure policy to enforce tagging.

AZ-104 - Governance and Compliance - LAB Add Remove Tags

Add, Remove and Update Tags for Resources in Azure

Introduction

In the scenario for this hands-on lab, the finance department has reached out to you. They are requesting additional taxonomy information on a recent Azure bill, including who created the resources, which department budget should be used for the resources, and if the resources are necessary for running business critical systems.

If there are any non-essential business systems, they ask that you signify that in some way.

Launch a powershell instance inside azure portal

Add Tags to the resource group

Run az group list and copy the name (395-5d062b4a-add-remove-and-update-tags-for-resou)

PS /home/cloud> az group list                                                                                                                                                      
[
  {
    "id": "/subscriptions/9734ed68-621d-47ed-babd-269110dbacb1/resourceGroups/395-5d062b4a-add-remove-and-update-tags-for-resou",
    "location": "westus",
    "managedBy": null,
    "name": "395-5d062b4a-add-remove-and-update-tags-for-resou",
    "properties": {
      "provisioningState": "Succeeded"
    },
    "tags": null,
    "type": "Microsoft.Resources/resourceGroups"
  }
]
Update the user group tags: 

- az group update --resource-group "<RESOURCE_GROUP_NAME>" --tags "Environment=Production" "Dept=IT" "CreatedBy=<YourName>"

PS /home/cloud> az group update --resource-group "395-5d062b4a-add-remove-and-update-tags-for-resou" --tags "Environment=Production" "Dept=IT" "CreatedBy=Cesar"                   
{
  "id": "/subscriptions/9734ed68-621d-47ed-babd-269110dbacb1/resourceGroups/395-5d062b4a-add-remove-and-update-tags-for-resou",
  "location": "westus",
  "managedBy": null,
  "name": "395-5d062b4a-add-remove-and-update-tags-for-resou",
  "properties": {
    "provisioningState": "Succeeded"
  },
  "tags": {
    "CreatedBy": "Cesar",
    "Dept": "IT",
    "Environment": "Production"
  },
  "type": "Microsoft.Resources/resourceGroups"
}
PS /home/cloud> 
Remove Tags for VM and Mark for Deletion
  1. In the Cloud Shell, list the existing virtual machines:
    PS /home/cloud> az vm list --query '[].{name:name, resourceGroup:resourceGroup, tags:tags}' -o json                                                                                
    [
      {
        "name": "webvm1",
        "resourceGroup": "395-5D062B4A-ADD-REMOVE-AND-UPDATE-TAGS-FOR-RESOU",
        "tags": {
          "defaultExperience": "Yes"
        }
      }
    ]
    PS /home/cloud> 
  2. Remove the existing tags from the VM:
    PS /home/cloud> az vm update -g "395-5d062b4a-add-remove-and-update-tags-for-resou" -n webvm1 --remove tags.defaultExperience                                                      
    
    {
      "additionalCapabilities": null,
      "applicationProfile": null,
      "availabilitySet": null,
      "billingProfile": null,
      "capacityReservation": null,
      "diagnosticsProfile": {
        "bootDiagnostics": {
          "enabled": true,
          "storageUri": "https://azurelalabi4q7bqaknwjqy.blob.core.windows.net/"
        }
      },
      "etag": null,
      "evictionPolicy": null,
      "extendedLocation": null,
      "extensionsTimeBudget": null,
      "hardwareProfile": {
        "vmSize": "Standard_B1ms",
        "vmSizeProperties": null
      },
      "host": null,
      "hostGroup": null,
      "id": "/subscriptions/9734ed68-621d-47ed-babd-269110dbacb1/resourceGroups/395-5d062b4a-add-remove-and-update-tags-for-resou/providers/Microsoft.Compute/virtualMachines/webvm1",
      "identity": null,
      "instanceView": null,
      "licenseType": null,
      "location": "westus",
      "managedBy": null,
      "name": "webvm1",
      "networkProfile": {
        "networkApiVersion": null,
        "networkInterfaceConfigurations": null,
        "networkInterfaces": [
          {
            "deleteOption": null,
            "id": "/subscriptions/9734ed68-621d-47ed-babd-269110dbacb1/resourceGroups/395-5d062b4a-add-remove-and-update-tags-for-resou/providers/Microsoft.Network/networkInterfaces/webvm1-nic1",
            "primary": null,
            "resourceGroup": "395-5d062b4a-add-remove-and-update-tags-for-resou"
          }
        ]
      },
      "osProfile": {
        "adminPassword": null,
        "adminUsername": "cloud_user",
        "allowExtensionOperations": null,
        "computerName": "webvm1",
        "customData": null,
        "linuxConfiguration": null,
        "requireGuestProvisionSignal": null,
        "secrets": [],
        "windowsConfiguration": {
          "additionalUnattendContent": null,
          "enableAutomaticUpdates": true,
          "enableVmAgentPlatformUpdates": false,
          "patchSettings": {
            "assessmentMode": "ImageDefault",
            "automaticByPlatformSettings": null,
            "enableHotpatching": null,
            "patchMode": "AutomaticByOS"
          },
          "provisionVmAgent": true,
          "timeZone": null,
          "winRm": null
        }
      },
      "plan": null,
      "platformFaultDomain": null,
      "priority": null,
      "provisioningState": "Succeeded",
      "proximityPlacementGroup": null,
      "resourceGroup": "395-5d062b4a-add-remove-and-update-tags-for-resou",
      "resources": null,
      "scheduledEventsProfile": null,
      "securityProfile": null,
      "storageProfile": {
        "dataDisks": [],
        "diskControllerType": null,
        "imageReference": {
          "communityGalleryImageId": null,
          "exactVersion": "14393.6709.240206",
          "id": null,
          "offer": "WindowsServer",
          "publisher": "MicrosoftWindowsServer",
          "sharedGalleryImageId": null,
          "sku": "2016-Datacenter",
          "version": "latest"
        },
        "osDisk": {
          "caching": "ReadWrite",
          "createOption": "FromImage",
          "deleteOption": "Detach",
          "diffDiskSettings": null,
          "diskSizeGb": 127,
          "encryptionSettings": null,
          "image": null,
          "managedDisk": {
            "diskEncryptionSet": null,
            "id": "/subscriptions/9734ed68-621d-47ed-babd-269110dbacb1/resourceGroups/395-5d062b4a-add-remove-and-update-tags-for-resou/providers/Microsoft.Compute/disks/webvm1_disk1_8db0168337f74a62a7160d01554e753f",
            "resourceGroup": "395-5d062b4a-add-remove-and-update-tags-for-resou",
            "securityProfile": null,
            "storageAccountType": "Premium_LRS"
          },
          "name": "webvm1_disk1_8db0168337f74a62a7160d01554e753f",
          "osType": "Windows",
          "vhd": null,
          "writeAcceleratorEnabled": null
        }
      },
      "tags": {},
      "timeCreated": "2024-02-13T20:59:23.426680+00:00",
      "type": "Microsoft.Compute/virtualMachines",
      "userData": null,
      "virtualMachineScaleSet": null,
      "vmId": "2292ae3f-ab87-42a0-b3ac-58ec941a77bc",
      "zones": null
    }
    PS /home/cloud> 
  3. Mark the VM for deletion
    PS /home/cloud> az vm update -g "395-5d062b4a-add-remove-and-update-tags-for-resou" -n webvm1 --set tags.MarkForDeletion=Yes                                                       
    
    {
      "additionalCapabilities": null,
      "applicationProfile": null,
      "availabilitySet": null,
      "billingProfile": null,
      "capacityReservation": null,
      "diagnosticsProfile": {
        "bootDiagnostics": {
          "enabled": true,
          "storageUri": "https://azurelalabi4q7bqaknwjqy.blob.core.windows.net/"
        }
      },
      "etag": null,
      "evictionPolicy": null,
      "extendedLocation": null,
      "extensionsTimeBudget": null,
      "hardwareProfile": {
        "vmSize": "Standard_B1ms",
        "vmSizeProperties": null
      },
      "host": null,
      "hostGroup": null,
      "id": "/subscriptions/9734ed68-621d-47ed-babd-269110dbacb1/resourceGroups/395-5d062b4a-add-remove-and-update-tags-for-resou/providers/Microsoft.Compute/virtualMachines/webvm1",
      "identity": null,
      "instanceView": null,
      "licenseType": null,
      "location": "westus",
      "managedBy": null,
      "name": "webvm1",
      "networkProfile": {
        "networkApiVersion": null,
        "networkInterfaceConfigurations": null,
        "networkInterfaces": [
          {
            "deleteOption": null,
            "id": "/subscriptions/9734ed68-621d-47ed-babd-269110dbacb1/resourceGroups/395-5d062b4a-add-remove-and-update-tags-for-resou/providers/Microsoft.Network/networkInterfaces/webvm1-nic1",
            "primary": null,
            "resourceGroup": "395-5d062b4a-add-remove-and-update-tags-for-resou"
          }
        ]
      },
      "osProfile": {
        "adminPassword": null,
        "adminUsername": "cloud_user",
        "allowExtensionOperations": null,
        "computerName": "webvm1",
        "customData": null,
        "linuxConfiguration": null,
        "requireGuestProvisionSignal": null,
        "secrets": [],
        "windowsConfiguration": {
          "additionalUnattendContent": null,
          "enableAutomaticUpdates": true,
          "enableVmAgentPlatformUpdates": false,
          "patchSettings": {
            "assessmentMode": "ImageDefault",
            "automaticByPlatformSettings": null,
            "enableHotpatching": null,
            "patchMode": "AutomaticByOS"
          },
          "provisionVmAgent": true,
          "timeZone": null,
          "winRm": null
        }
      },
      "plan": null,
      "platformFaultDomain": null,
      "priority": null,
      "provisioningState": "Succeeded",
      "proximityPlacementGroup": null,
      "resourceGroup": "395-5d062b4a-add-remove-and-update-tags-for-resou",
      "resources": null,
      "scheduledEventsProfile": null,
      "securityProfile": null,
      "storageProfile": {
        "dataDisks": [],
        "diskControllerType": null,
        "imageReference": {
          "communityGalleryImageId": null,
          "exactVersion": "14393.6709.240206",
          "id": null,
          "offer": "WindowsServer",
          "publisher": "MicrosoftWindowsServer",
          "sharedGalleryImageId": null,
          "sku": "2016-Datacenter",
          "version": "latest"
        },
        "osDisk": {
          "caching": "ReadWrite",
          "createOption": "FromImage",
          "deleteOption": "Detach",
          "diffDiskSettings": null,
          "diskSizeGb": 127,
          "encryptionSettings": null,
          "image": null,
          "managedDisk": {
            "diskEncryptionSet": null,
            "id": "/subscriptions/9734ed68-621d-47ed-babd-269110dbacb1/resourceGroups/395-5d062b4a-add-remove-and-update-tags-for-resou/providers/Microsoft.Compute/disks/webvm1_disk1_8db0168337f74a62a7160d01554e753f",
            "resourceGroup": "395-5d062b4a-add-remove-and-update-tags-for-resou",
            "securityProfile": null,
            "storageAccountType": "Premium_LRS"
          },
          "name": "webvm1_disk1_8db0168337f74a62a7160d01554e753f",
          "osType": "Windows",
          "vhd": null,
          "writeAcceleratorEnabled": null
        }
      },
      "tags": {
        "MarkForDeletion": "Yes"
      },
      "timeCreated": "2024-02-13T20:59:23.426680+00:00",
      "type": "Microsoft.Compute/virtualMachines",
      "userData": null,
      "virtualMachineScaleSet": null,
      "vmId": "2292ae3f-ab87-42a0-b3ac-58ec941a77bc",
      "zones": null
    }
    PS /home/cloud>
Change the Tags for the Virtual Network

In the cloud shell list the virtual networks

PS /home/cloud> az network vnet list --query '[].{name:name, resourceGroup:resourceGroup, tags:tags}' -o json                                                                      
[
  {
    "name": "vnet1",
    "resourceGroup": "395-5d062b4a-add-remove-and-update-tags-for-resou",
    "tags": {
      "Application": "MyApp",
      "Created By": "MyName",
      "Department": "MyDepartment"
    }
  }
]

Overwrite the existing tags:

PS /home/cloud> az resource tag --tags "Dept=IT" "Environment=Production" "CreatedBy=Cesar" --resource-group "395-5d062b4a-add-remove-and-update-tags-for-resou" -n "vnet1" --resource-type "Microsoft.Network/virtualNetworks"
{
  "etag": "W/\"c51873be-773d-4b96-ab24-fa37389401fe\"",
  "extendedLocation": null,
  "id": "/subscriptions/9734ed68-621d-47ed-babd-269110dbacb1/resourceGroups/395-5d062b4a-add-remove-and-update-tags-for-resou/providers/Microsoft.Network/virtualNetworks/vnet1",
  "identity": null,
  "kind": null,
  "location": "westus",
  "managedBy": null,
  "name": "vnet1",
  "plan": null,
  "properties": {
    "addressSpace": {
      "addressPrefixes": [
        "10.1.0.0/16"
      ]
    },
    "enableDdosProtection": false,
    "provisioningState": "Succeeded",
    "resourceGuid": "48583c22-680d-4ddf-97d8-1e25046de802",
    "subnets": [
      {
        "etag": "W/\"c51873be-773d-4b96-ab24-fa37389401fe\"",
        "id": "/subscriptions/9734ed68-621d-47ed-babd-269110dbacb1/resourceGroups/395-5d062b4a-add-remove-and-update-tags-for-resou/providers/Microsoft.Network/virtualNetworks/vnet1/subnets/subnet1",
        "name": "subnet1",
        "properties": {
          "addressPrefix": "10.1.1.0/24",
          "delegations": [],
          "ipConfigurations": [
            {
              "id": "/subscriptions/9734ed68-621d-47ed-babd-269110dbacb1/resourceGroups/395-5D062B4A-ADD-REMOVE-AND-UPDATE-TAGS-FOR-RESOU/providers/Microsoft.Network/networkInterfaces/WEBVM1-NIC1/ipConfigurations/IPCONFIG1",
              "resourceGroup": "395-5D062B4A-ADD-REMOVE-AND-UPDATE-TAGS-FOR-RESOU"
            }
          ],
          "networkSecurityGroup": {
            "id": "/subscriptions/9734ed68-621d-47ed-babd-269110dbacb1/resourceGroups/395-5d062b4a-add-remove-and-update-tags-for-resou/providers/Microsoft.Network/networkSecurityGroups/shared-nsg",
            "resourceGroup": "395-5d062b4a-add-remove-and-update-tags-for-resou"
          },
          "privateEndpointNetworkPolicies": "Disabled",
          "privateLinkServiceNetworkPolicies": "Enabled",
          "provisioningState": "Succeeded"
        },
        "resourceGroup": "395-5d062b4a-add-remove-and-update-tags-for-resou",
        "type": "Microsoft.Network/virtualNetworks/subnets"
      }
    ],
    "virtualNetworkPeerings": []
  },
  "resourceGroup": "395-5d062b4a-add-remove-and-update-tags-for-resou",
  "sku": null,
  "tags": {
    "CreatedBy": "MyName",
    "Dept": "IT",
    "Environment": "Production"
  },
  "type": "Microsoft.Network/virtualNetworks"
}
PS /home/cloud>

AZ-104 - Governance and Compliance - Locking and Moving Resources

 

Control and organize Azure resources with Azure Resource Manager

Move Azure resources to another resource group

 
 
What are Locks
Lock types 

Moving resources is the process of actually moving resources that are contained in a specific place in Azure

image.png

 

Navigate in azure portal to your resource group and add a lock

 

image.png

Add Lock to DontDelete or whatever random name, assign to Delete, from this page you can edit or delete the lock.

image.png

 

Now with a lock let's select all resources and ht delete

image.png

image.png

We are unable to delete because of the lock delete rule

image.png

 

Now lets go to a specific resource inside our resource group, let's go to our VM

first we need to stop the resource then hit refresh, wait for the status to stopped.

image.png

 

Let's go back to modify our resource group lock from Delete to Read Only

we go to our resource group, select lock (hit refresh if not shown) then edit, we will modify lock type from Delete to Read-only and hit ok

image.png

 

We will refresh and make sure its now read-only

image.png

 

let's go back to our resources overview, open the VM again and let's Start our VM, we get a warning message, cannot perform write operation, please remove read-only lock

 

image.png

 

Now if we go back to our resources group we can select all our resources, from here we can click on Move, here you can move resources too another resource group, to another subscription or to another region.

image.png

 

 

AZ-104 - Governance and Compliance - Managing Azure Costs

Introduction to analyzing costs and creating budgets with Microsoft Cost Management

Describe cost management in Azure

Different components on Azure cost model
Best Practices

Select the appropriate resource for the use case.

Understand needs (sizing).

De-allocate resources when not needed.

Use cloud capabilities where possible(e.g., scalability, elasticity).

Plan your cost prior to purchase.

 

Cost Tools
Pricing Calculator.
Total cost of Ownership (TCO) calculator.
Microsoft Cost Management (Analyze costs and create Budgets)

 

Inside Azure Portal search for cost management then go to cost analysis

image.png

We can identify different costs per service, resource groups, locations, etc

image.png

Using the pricing calculator

 

Pricing Calculator

image.png

 

Using the TCO Calculator

 

TCO Calculator

image.png

 

 

AZ-104 - Governance and Compliance - Building a cloud governance strategy wth Azure tooling

Building Cloud Governance

Define Governance

Planing a Cloud Strategy

Governance Services

 

Azure Blueprints

image.png