# 2.- AZ-104 Governance and Compliance

# AZ-104 - Governance and Compliance - Managing Subscriptions

##### [Organize and manage multiple Azure subscriptions](https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/azure-best-practices/organize-subscriptions "Organize and manage multiple Azure subscriptions")


##### What are subscriptions

- Billing unit that aggregates all costs of underlying resources
- Contain resource groups and their associated resources
- Scoping level for governance and security
- Can be associated with only a single organization (Azure AD Tenant) at a time

Examples:

you can define multiple subscriptions per department to identify costs

![image.png](https://wiki.tinod.net/uploads/images/gallery/2024-02/scaled-1680-/CvOvXZvfeQrt5OaS-image.png)


#### Subscription naming conventions

##### <span style="background-color: rgb(0, 0, 0);">- Prod/Dev/Staging</span>

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

##### <span style="background-color: rgb(0, 0, 0);">- Department/Teams</span>

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.

##### <span style="background-color: rgb(0, 0, 0);">- Region</span>

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?](https://learn.microsoft.com/en-us/azure/governance/management-groups/overview)

#### Management groups

- Define management groups
- Understanding hierarchy
- Scoping

##### Managing subscriptions

<span style="background-color: rgb(0, 0, 0); color: rgb(255, 255, 255);">Organize and manage subscriptions by logically grouping them into management groups</span>

- Organizational hierarchy
- Provides another scope for enforcing governance and compliance![image.png](https://wiki.tinod.net/uploads/images/gallery/2024-02/scaled-1680-/1jOUrASvi23P6JIU-image.png)

<span style="background-color: rgb(0, 0, 0); color: rgb(255, 255, 255);">Parent-child relationships</span>

- Root management group is the top level
- Management groups and subscriptions can have a single parent
- Supports six levels of hierarchy

<span style="background-color: rgb(0, 0, 0); color: rgb(255, 255, 255);">Compliance Support</span>

- Azure Policies
- Azure role-based access control (RBAC)

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](https://wiki.tinod.net/uploads/images/gallery/2024-02/scaled-1680-/5pKxeVC2l7vrjEXL-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](https://wiki.tinod.net/uploads/images/gallery/2024-02/scaled-1680-/I6uJ4Ej19EY22TVX-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](https://wiki.tinod.net/uploads/images/gallery/2024-02/scaled-1680-/6ZskO8RDlDYqJl43-image.png)

<p class="callout info">Root management group is not given by default</p>

<p class="callout info">Root Management group cannot be moved or deleted</p>

<p class="callout info">Azure RBAC is supported for management groups</p>

<p class="callout info">Global Administrators must be elevated to User Access Administrator of root group</p>

# AZ-104 - Governance and Compliance - Understanding Azure Policy

#### **[Control and organize Azure resources with Azure Resource Manager](https://learn.microsoft.com/en-us/training/modules/control-and-organize-with-azure-resource-manager/)**

#### **Understanding Azure Policy**

- Define Azure Policy
- Components of a Policy
- Policy Examples

Enforce Compliance and enable auditing

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

##### <span style="background-color: rgb(0, 0, 0); color: rgb(236, 240, 241);">Prohibit resources</span>

- control costs
- Restrict service access

##### <span style="background-color: rgb(0, 0, 0); color: rgb(236, 240, 241);">Allowed Locations</span>

- Geographical compliance

![image.png](https://wiki.tinod.net/uploads/images/gallery/2024-02/scaled-1680-/rq6fMYZ0dbkUWO2i-image.png)

##### <span style="background-color: rgb(0, 0, 0); color: rgb(236, 240, 241);">Policy Definition</span>

<span style="color: rgb(236, 240, 241);">Defines the evaluation criteria for compliance, and defines the actions that take place. Either audit or deny should be something outside of compliance.</span>

##### <span style="color: rgb(236, 240, 241); background-color: rgb(0, 0, 0);">Policy Assignment</span>

<span style="color: rgb(236, 240, 241);">The scope at which we will assign our policy. The scope could be a management group, subscription, resource group, or resource.</span>

##### <span style="color: rgb(236, 240, 241); background-color: rgb(0, 0, 0);">Initiative Definition</span>

<span style="color: rgb(236, 240, 241);"> A collection of policies that are tailored to achieving a singular high-level goal together (e.g., ensuring that VMs meet standards).</span>

![image.png](https://wiki.tinod.net/uploads/images/gallery/2024-02/scaled-1680-/Mv0XVLqFubS1eaEx-image.png)

<table border="1" id="bkmrk-policy-definition-ev" style="border-collapse: collapse; width: 111.111%;"><colgroup><col style="width: 19.6505%;"></col><col style="width: 80.3495%;"></col></colgroup><tbody><tr><td><span style="color: rgb(236, 240, 241);">Policy Definition</span></td><td><span style="color: rgb(236, 240, 241);">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.</span>

</td></tr><tr><td><span style="color: rgb(236, 240, 241);">Policy assignment </span></td><td><span style="color: rgb(236, 240, 241);">Assign the policy at the scope of the resource where the VMs will be created</span></td></tr></tbody></table>

![image.png](https://wiki.tinod.net/uploads/images/gallery/2024-02/scaled-1680-/vR7SrV855zZVsYyF-image.png)

[![image.png](https://wiki.tinod.net/uploads/images/gallery/2024-02/scaled-1680-/SAoyLC7QAEOA7iRZ-image.png)](https://wiki.tinod.net/uploads/images/gallery/2024-02/SAoyLC7QAEOA7iRZ-image.png)

# AZ-104 - Governance and Compliance - Tagging Resources

#### **[Control and organize Azure resources with Azure Resource Manager](https://learn.microsoft.com/en-us/training/modules/control-and-organize-with-azure-resource-manager/)**


#### **Tags**

What are tags: its a form of Name:Value

- Dept:Marketing - For example if create tag Dept:Marketing and tag all resources from Marketing this will help identify and provide billing to this resources to the Marketing department.
- Env:Prod - Identify wheather an environment is in production or dev

![image.png](https://wiki.tinod.net/uploads/images/gallery/2024-02/scaled-1680-/xKVw6SAoshsB9sqf-image.png)

- Name can be 512 characters, and value can be 256 characters.
- Storage accounts can have a name with only 128 characters.
- Tags are not inherited.
- A resource can have 50 tags max.

![image.png](https://wiki.tinod.net/uploads/images/gallery/2024-02/scaled-1680-/YJcOfcPLtfRBlXyY-image.png)

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

![image.png](https://wiki.tinod.net/uploads/images/gallery/2024-02/scaled-1680-/umpYmOKWYjS83sK1-image.png)

Lets test with the following ARM template.

(refer to [Arm Template here to investigate how to deploy an ARM template](https://wiki.tinod.net/books/az-104-learning-azure-cloud-administrator/page/az-104-administration-azure-arm-templates))

<details id="bkmrk-arm-template-for-tag"><summary>Arm template for TAG test</summary>

```
{
  "$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]"
          }
        }
      }
    }
  ]
}
```

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

![image.png](https://wiki.tinod.net/uploads/images/gallery/2024-02/scaled-1680-/RO2vJIPhP9h4mbCo-image.png)

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

![image.png](https://wiki.tinod.net/uploads/images/gallery/2024-02/scaled-1680-/qSjDdnOSYow3SCga-image.png)

<p class="callout info">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.</p>

<p class="callout info">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.</p>

# 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.

- Add Tags to resource group
- Modify tags for VM and Mark for Deletion
- Modify tags for Virtual Network

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)**

```powershell
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 "&lt;RESOURCE\_GROUP\_NAME&gt;" --tags "Environment=Production" "Dept=IT" "CreatedBy=&lt;YourName&gt;"**

```powershell
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: ```powershell
    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: ```powershell
    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 ```powershell
    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

```powershell
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:

```powershell
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](https://learn.microsoft.com/en-us/training/modules/control-and-organize-with-azure-resource-manager/)

[Move Azure resources to another resource group](https://learn.microsoft.com/en-us/training/modules/move-azure-resources-another-resource-group/ "Move Azure resources to another resource group")

#####  

#####  

##### **What are Locks**

- Locks allow you to override permissions to resources.
- You can lock subscriptions, resources groups or resources.
- Lock Restrictions apply to all users and roles.

##### Lock types 

- Read-only allows authorized users to read a resource, but they cannot delete or update the resource.
- Cannot-delete allows authorized users to read and modify a resource, but they cannot delete the resource.
- Locks are inherited from the parent scope.

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

![image.png](https://wiki.tinod.net/uploads/images/gallery/2024-02/scaled-1680-/oMBim7RaoSKWM0Wt-image.png)

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

![image.png](https://wiki.tinod.net/uploads/images/gallery/2024-02/scaled-1680-/mOz2VLJEbBwjgDdt-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](https://wiki.tinod.net/uploads/images/gallery/2024-02/scaled-1680-/vAwzf3qfiUcrtR77-image.png)

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

![image.png](https://wiki.tinod.net/uploads/images/gallery/2024-02/scaled-1680-/xzEjjtyaIk5mguTF-image.png)

![image.png](https://wiki.tinod.net/uploads/images/gallery/2024-02/scaled-1680-/OsJxieIm8fO8UQ1o-image.png)

We are unable to delete because of the lock delete rule

![image.png](https://wiki.tinod.net/uploads/images/gallery/2024-02/scaled-1680-/uEJjyj9SRy1rBS2I-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](https://wiki.tinod.net/uploads/images/gallery/2024-02/scaled-1680-/r5HexEZmy7DgEjyu-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](https://wiki.tinod.net/uploads/images/gallery/2024-02/scaled-1680-/g1DMIfySz56BnxSO-image.png)

We will refresh and make sure its now read-only

[![image.png](https://wiki.tinod.net/uploads/images/gallery/2024-02/scaled-1680-/1CLsz6K5Jj6gHma4-image.png)](https://wiki.tinod.net/uploads/images/gallery/2024-02/1CLsz6K5Jj6gHma4-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](https://wiki.tinod.net/uploads/images/gallery/2024-02/scaled-1680-/sbwKQhZSHrmthKGh-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](https://wiki.tinod.net/uploads/images/gallery/2024-02/scaled-1680-/OPwAgPWBDPttoIV2-image.png)

# AZ-104 - Governance and Compliance - Managing Azure Costs

[Introduction to analyzing costs and creating budgets with Microsoft Cost Management](https://learn.microsoft.com/en-us/training/modules/analyze-costs-create-budgets-azure-cost-management/)

[Describe cost management in Azure](https://learn.microsoft.com/en-us/training/modules/describe-cost-management-azure/)

##### <span style="background-color: rgb(0, 0, 0); color: rgb(255, 255, 255);">**Different components on Azure cost model**</span>

- **Subscription type**: Free, Pay as you go, Enterprise agreement, and Cloud Solution Provider (CSP).
- **Resource type:** For example, storage account blob storage vs Table Storage.
- **Usage Meters**: Utilities like overall CPU time, ingress/egress network traffic and disk size.
- **Resource Usage:** The cost of actually using a resource.
- **Location:** The cost for various services vary across geographical regions.

<table border="1" id="bkmrk-best-practices-selec" style="border-collapse: collapse; width: 55.1852%; height: 29.7167px;"><colgroup><col style="width: 100%;"></col></colgroup><tbody><tr><td>**Best Practices**  
</td></tr><tr><td>Select the appropriate resource for the use case.

</td></tr><tr style="height: 29.7167px;"><td style="height: 29.7167px;">Understand needs (sizing).

</td></tr><tr><td>De-allocate resources when not needed.

</td></tr><tr><td>Use cloud capabilities where possible(e.g., scalability, elasticity).

</td></tr><tr><td>Plan your cost prior to purchase.

</td></tr></tbody></table>

<table border="1" id="bkmrk-cost-tools-pricing-c" style="border-collapse: collapse; width: 54.6914%; height: 77px;"><colgroup><col style="width: 100%;"></col></colgroup><tbody><tr style="height: 29.7167px;"><td style="height: 29.7167px;">**Cost Tools**  
</td></tr><tr style="height: 29.7167px;"><td style="height: 29.7167px;">Pricing Calculator.  
</td></tr><tr><td>Total cost of Ownership (TCO) calculator.</td></tr><tr style="height: 29.7167px;"><td style="height: 29.7167px;">Microsoft Cost Management (Analyze costs and create Budgets)</td></tr></tbody></table>

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

![image.png](https://wiki.tinod.net/uploads/images/gallery/2024-02/scaled-1680-/IzzZQwcsuc4Zz5sx-image.png)

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

![image.png](https://wiki.tinod.net/uploads/images/gallery/2024-02/scaled-1680-/Zuo3r09sPa26fF76-image.png)

##### <span style="background-color: rgb(0, 0, 0); color: rgb(255, 255, 255);">**Using the pricing calculator**</span>

<span style="color: rgb(255, 255, 255);">**[Pricing Calculator](https://azure.microsoft.com/en-in/pricing/calculator/)**</span>

![image.png](https://wiki.tinod.net/uploads/images/gallery/2024-02/scaled-1680-/CnGkmwiY5kPrfjqS-image.png)

##### <span style="background-color: rgb(0, 0, 0); color: rgb(255, 255, 255);">**Using the TCO Calculator** </span>

<span style="color: rgb(255, 255, 255);">**[TCO Calculator](https://azure.microsoft.com/en-us/pricing/tco/calculator/)**</span>

![image.png](https://wiki.tinod.net/uploads/images/gallery/2024-02/scaled-1680-/gVaRKcBpe4DJPNNM-image.png)

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

[Building Cloud Governance](https://learn.microsoft.com/en-us/training/paths/describe-azure-management-governance/)

**Define Governance**

- Rules
- Policies
- Compliance standards
- Control over resources
- Enforce rules, policies, and standard

Planing a Cloud Strategy

- Define: Define cloud governance needs of he organization.
- Plan: Plan which tools will be used to implement governance.
- Ready: understand how those tools will be used to implement governance.
- Adopt: Implement governance for the organization using a cloud strategy.

Governance Services

- Management groups and subscriptions: Organize subscriptions into hierarchical structures.
- Azure RBAC: Provide resources at varying scopes.
- Policies: Implement policies to enforce standards.
- Locks and Tagging: Lock resources to prevent deletion and tag resources to categorize.

Recommended to investigate more about Azure Blueprints to better understand rules and policies.

[Azure Blueprints](https://learn.microsoft.com/en-us/azure/governance/blueprints/overview)

![image.png](https://wiki.tinod.net/uploads/images/gallery/2024-02/scaled-1680-/qQHH9VIZulwW8Rkd-image.png)