Search
  • AmistadGroup

Azure - Blueprints Deployment

The document scope is to explain how to deploy in an automated way what I am thinking to be an Azure base subscription with all the resources needed for future growth. When I am saying all resources I am referring to a dedicated resource group for the virtual network, network security groups, and route table; and a resource group dedicated to infrastructure resources like virtual machines, private links, recovery vault, key vault, and storage accounts.

Azure blueprint is very well explained in this Microsoft link https://docs.microsoft.com/en-us/azure/governance/blueprints/overview

At this stage, we assume the fact that a new subscription is created, added to your management group, and a user-assigned managed identity is created based on this link https://docs.microsoft.com/en-us/azure/active-directory/managed-identities-azure-resources/how-to-manage-ua-identity-portal

Azure Blueprints portal looks like this one:

We have two options: to create a new blueprint and for that, we need to choose Bluperiont definitions or to use an existing blueprint definition and for that, we need to choose Assigned blueprints.

At this stage, I will go for Blueprint definitions and create a new blueprint, a blank new blueprint

Blueprints are using artifacts and these are the artifacts that you can deploy using a blueprint


For this case only, we will use the Resource Group artifact.

To deploy a Route Table, I used this piece of code


{
      "type": "Microsoft.Network/routeTables",
      "apiVersion": "2019-11-01",
      "name": "[parameters('routeTables_RT_name')]",
      "location": "northeurope",
      "tags": {
        "Environment": "Production",
        "Service": "Route Table"
      },
      "properties": {
        "disableBgpRoutePropagation": false,
        "routes": [
          {
            "name": "Defaultroute",
            "properties": {
              "addressPrefix": "0.0.0.0/0",
              "nextHopType": "VirtualAppliance",
              "nextHopIpAddress": "192.168.180.1"
            }
          }
        ]
      }
    }

To deploy a Vnet with 3 different subnets, with custom DNS servers, DDOS disabled because is done a hub-spoke level, and peering back to a hub-spoke subscription, I used this piece of code


{
      "type": "Microsoft.Network/virtualNetworks",
      "apiVersion": "2019-11-01",
      "name": "[parameters('virtualNetworks_Vnet_name')]",
      "location": "northeurope",
      "dependsOn": [
        "[resourceId('Microsoft.Network/networkSecurityGroups', parameters('networkSecurityGroups_WEB_NSG_name'))]",
        "[resourceId('Microsoft.Network/routeTables', parameters('routeTables_RT_name'))]",
        "[resourceId('Microsoft.Network/networkSecurityGroups', parameters('networkSecurityGroups_DATA_NSG_name'))]",
        "[resourceId('Microsoft.Network/networkSecurityGroups', parameters('networkSecurityGroups_APP_NSG_name'))]"
      ],
      "tags": {
        "Environment": "Production",
        "Service": "Vnet"
      },
      "properties": {
        "addressSpace": {
          "addressPrefixes": [
            "[parameters('addressSpace_TIER_range')]"
          ]
        },
        "dhcpOptions": {
          "dnsServers": [
            "192.168.0.21",
            "192.168.0.22"            
          ]
        },
        "subnets": [
          {
            "name": "[parameters('WEB')]",
            "properties": {
              "addressPrefix": "[parameters('subnetaddressPrefix_WEB_range')]",
              "addressPrefixes": [],
              "networkSecurityGroup": {
                "id": "[resourceId('Microsoft.Network/networkSecurityGroups', parameters('networkSecurityGroups_WEB_NSG_name'))]"
              },
              "routeTable": {
                "id": "[resourceId('Microsoft.Network/routeTables', parameters('routeTables_RT_name'))]"
              },
              "serviceEndpoints": [],
              "delegations": [],
              "privateEndpointNetworkPolicies": "Enabled",
              "privateLinkServiceNetworkPolicies": "Enabled"
            }
          },
          {
            "name": "[parameters('DATA')]",
            "properties": {
              "addressPrefix": "[parameters('subnetaddressPrefix_DATA_range')]",
              "addressPrefixes": [],
              "networkSecurityGroup": {
                "id": "[resourceId('Microsoft.Network/networkSecurityGroups', parameters('networkSecurityGroups_DATA_NSG_name'))]"
              },
              "routeTable": {
                "id": "[resourceId('Microsoft.Network/routeTables', parameters('routeTables_RT_name'))]"
              },
              "serviceEndpoints": [],
              "delegations": [],
              "privateEndpointNetworkPolicies": "Enabled",
              "privateLinkServiceNetworkPolicies": "Enabled"
            }
          },
          {
            "name": "[parameters('APP')]",
            "properties": {
              "addressPrefix": "[parameters('subnetaddressPrefix_APP_range')]",
              "addressPrefixes": [],
              "networkSecurityGroup": {
                "id": "[resourceId('Microsoft.Network/networkSecurityGroups', parameters('networkSecurityGroups_APP_NSG_name'))]"
              },
              "routeTable": {
                "id": "[resourceId('Microsoft.Network/routeTables', parameters('routeTables_RT_name'))]"
              },
              "serviceEndpoints": [],
              "delegations": [],
              "privateEndpointNetworkPolicies": "Enabled",
              "privateLinkServiceNetworkPolicies": "Enabled"
            }
          }
        ],
        "virtualNetworkPeerings": [
          {
            "name": "[concat(parameters('virtualNetworks_Vnet_name'), '-PEER-hub-spoke-VNet')]",
            "properties": {
              "peeringState": "Connected",
              "remoteVirtualNetwork": {
                "id": "[parameters('virtualNetworks_VNet_NE_externalid')]"
              },
              "allowVirtualNetworkAccess": true,
              "allowForwardedTraffic": true,
              "allowGatewayTransit": false,
              "useRemoteGateways": true,
              "remoteAddressSpace": {
                "addressPrefixes": [
                  "10.10.2.0/23"
                ]
              }
            }
          }
        ],
        "enableDdosProtection": false,
        "enableVmProtection": false
      }
    }

To deploy a networks security group (NSG) with a DENY ALL rule,I used this piece of code


{
      "type": "Microsoft.Network/networkSecurityGroups",
      "apiVersion": "2019-11-01",
      "name": "[parameters('networkSecurityGroups_APP_NSG_name')]",
      "location": "northeurope",
      "tags": {
        "Environment": "Production",
        "Service": "NSG"
      },
      "properties": {
        "securityRules": [
          {
            "name": "Deny_All",
            "properties": {
              "protocol": "*",
              "sourcePortRange": "*",
              "destinationPortRange": "*",
              "sourceAddressPrefix": "*",
              "destinationAddressPrefix": "VirtualNetwork",
              "access": "Deny",
              "priority": 4000,
              "direction": "Inbound",
              "sourcePortRanges": [],
              "destinationPortRanges": [],
              "sourceAddressPrefixes": [],
              "destinationAddressPrefixes": []
            }
          },
        }

To deploy a Key Vault with full permissions I used this piece of code


    {
      "type": "Microsoft.KeyVault/vaults",
      "apiVersion": "2016-10-01",
      "name": "[parameters('vaults_KeyVault_name')]",
      "location": "northeurope",
      "properties": {
        "sku": {
          "family": "A",
          "name": "Standard"
        },
        "tenantId": "xxx",
        "accessPolicies": [
          {
            "tenantId": "xxx",
            "objectId": "yyy",
            "permissions": {
              "keys": [
                "Get",
                "List",
                "Update",
                "Create",
                "Import",
                "Delete",
                "Recover",
                "Backup",
                "Restore",
                "Decrypt",
                "Encrypt",
                "UnwrapKey",
                "WrapKey",
                "Verify",
                "Sign",
                "Purge"
              ],
              "secrets": [
                "Get",
                "List",
                "Set",
                "Delete",
                "Recover",
                "Backup",
                "Restore"
              ],
              "certificates": []
            }
          },
          {
            "tenantId": "xxx",
            "objectId": "yyy",
            "permissions": {
              "keys": [
                "Get",
                "List",
                "Update",
                "Create",
                "Import",
                "Delete",
                "Recover",
                "Backup",
                "Restore",
                "Decrypt",
                "Encrypt",
                "UnwrapKey",
                "WrapKey",
                "Verify",
                "Sign",
                "Purge"
              ],
              "secrets": [
                "Get",
                "List",
                "Set",
                "Delete",
                "Recover",
                "Backup",
                "Restore",
                "Purge"
              ],
              "certificates": [
                "Get",
                "List",
                "Update",
                "Create",
                "Import",
                "Delete",
                "Recover",
                "Backup",
                "Restore",
                "ManageContacts",
                "ManageIssuers",
                "GetIssuers",
                "ListIssuers",
                "SetIssuers",
                "DeleteIssuers",
                "Purge"
              ],
              "storage": []
            }
          }
        ],
        "enabledForDeployment": true,
        "enabledForDiskEncryption": true,
        "enabledForTemplateDeployment": true,
        "enableSoftDelete": true
      }
    }

To deploy a storage account to be used for virtual machine diagnostics, I used this piece of code:


    {
      "type": "Microsoft.Storage/storageAccounts",
      "apiVersion": "2019-06-01",
      "name": "[parameters('storageAccounts_vmdiagnostics')]",
      "location": "northeurope",
      "sku": {
        "name": "Standard_RAGRS",
        "tier": "Standard"
      },
      "kind": "StorageV2",
      "properties": {
        "networkAcls": {
          "bypass": "AzureServices",
          "virtualNetworkRules": [],
          "ipRules": [],
          "defaultAction": "Allow"
        },
        "supportsHttpsTrafficOnly": true,
        "encryption": {
          "services": {
            "file": {
              "keyType": "Account",
              "enabled": true
            },
            "blob": {
              "keyType": "Account",
              "enabled": true
            }
          },
          "keySource": "Microsoft.Storage"
        },
        "accessTier": "Hot"
      }
    },
    {
      "type": "Microsoft.Storage/storageAccounts/blobServices",
      "apiVersion": "2019-06-01",
      "name": "[concat(parameters('storageAccounts_vmdiagnostics'), '/default')]",
      "dependsOn": [
        "[resourceId('Microsoft.Storage/storageAccounts', parameters('storageAccounts_vmdiagnostics'))]"
      ],
      "sku": {
        "name": "Standard_RAGRS",
        "tier": "Standard"
      },
      "properties": {
        "cors": {
          "corsRules": []
        },
        "deleteRetentionPolicy": {
          "enabled": false
        }
      }
    },
    {
      "type": "Microsoft.Storage/storageAccounts/fileServices",
      "apiVersion": "2019-06-01",
      "name": "[concat(parameters('storageAccounts_vmdiagnostics'), '/default')]",
      "dependsOn": [
        "[resourceId('Microsoft.Storage/storageAccounts', parameters('storageAccounts_vmdiagnostics'))]"
      ],
      "sku": {
        "name": "Standard_RAGRS",
        "tier": "Standard"
      },
      "properties": {
        "cors": {
          "corsRules": []
        }
      }
    }

When you completed your blueprint creation you need to save that under a name that best describes what this blueprint does and publish that blueprint.

The most important thing after the blueprint publishing is to assign that blueprint to a subscription and to see this message

Task completed.


Thank you!

AmistadGroup IT Team

(https://www.amistadgroup.ro/)

50 views0 comments

Recent Posts

See All

Venitul net anual din activități independente se determină în sistem real, pe baza datelor din contabilitate, ca diferență între venitul brut și cheltuielile deductibile efectuate în scopul realizării