Go Home Documentation Home
- Shared Subscription between all Apps/Tenants
- Shared Hub between all Apps/Tenants
- Shared Global resource Group between all Apps/Tenants
- You have a subscription to deploy into, preferrably a blank subscription, this is a Greenfields project, not Brownfields
- You are an owner on the Subscription
- You know your /20 Network Range that you can deploy into, you need 2 of these
- One range in the Primary (Azure Partner) Region
- One range in the Secondary (Azure Partner) Region
-
There are several setup/management scripts in this directory: ADF\1-PrereqsToDeploy\CustomResources
-
There are several shared metadata files in your Tenant Directory e.g. Global-Global, AZC1-Global, AZE2-Global
-
We will start with the HUB Tenant, this is the Shared Hub
-
We will also deploy the HUB Global Resource, this is shared Global resources
-
Open the following File and fill out all of the information ADF\tenants\HUB\Global-Global.json
- All of the info below should be filled out ahead of time
- Replace the 3 Characters that map to the Name of your App, in this case HUB, you can leave HUB
"Global": { "tenantId": "3254f91d-4657-40df-962d-c8e6dad75963", // Your Azure AD TenantID "SubscriptionID": "1f0713fe-9b12-4c8f-ab0c-26aba7aaa3e5", // The Subscription ID where your Resource Groups will be deployed "hubSubscriptionID": "1f0713fe-9b12-4c8f-ab0c-26aba7aaa3e5", // The Subscription ID where your Hub VNET will be deployed "OrgName": "BRW", // "3-Letter-Company-Name" e.g. This is required to ensure all public resources deployed have a unique name // This should stay the same across ALL Tenants, only the AppName will change // Be sure to keep this consistent "AppName": "HUB", // "3-Letter-App-Name" e.g. in this project, we call this the tenant name. "SAName": "azc1brwhubg1saglobal", // "{Primary-Azure-Region-azxx-lower-case}{orgname-3-char-max-lower-case}{appname-3-char-max-lower-case}g1saglobal" // max length of storage account is 24 chars and requires lowercase "GlobalRGName": "AZC1-BRW-HUB-RG-G1", // "{Primary-Azure-Region-AZXX}-{appname-3-characters-max-upper-case}-RG-G1" G1 is Global "PrimaryLocation": "CentralUS", // "CentralUS" e.g. partner region to East US 2 "PrimaryPrefix": "AZC1", // "AZ{2-character-letters-for-the-Azure-Region}" e.g. C1 Central US 1, E2 East US 2 Etc "SecondaryLocation": "EastUS2", // "EastUS2" e.g. partner region to Central US "SecondaryPrefix": "AZE2", // "AZ{2-character-letters-for-the-Azure-Region}" e.g. C1 Central US 1, E2 East US 2 Etc "PublicIPAddressforRemoteAccess": "73.157.100.227/32", // This IP will be used on NSG's if you have a Public IP "vmAdminUserName": "brw", // "Local-Admin-UserName-for-Virtual-Machines" "DomainName": "psthing.com", // "Interntal Active Directory Domain" "DomainNameExt": "psthing.com", // "External Public DNS Name"
-
Open the following File and fill out all of the information ADF\tenants\HUB\AZC1-Global.json
- The file name should match your Primary Azure Region that you will deploy into
"Global": { "HubRGName": "AZC1-BRW-HUB-RG-P0", // "{Primary-Azure-Region-AZXX}-{appname-3-characters-max-upper-case}-RG-P0" P0 is a Hub "hubVnetName": "AZC1-BRW-HUB-P0-vn", // "{Primary-Azure-Region-AZXX}-{appname-3-characters-max-upper-case}-P0-vn" P0 is a Hub "KVName": "AZC1-BRW-HUB-P0-kvVault01", // "{Primary-Azure-Region-AZXX}-{orgname-3-char-max-upper-case}-{appname-3-characters-max-upper-case}-P0-kvVault01" P0 is a Hub // max length of keyvault name is 24 chars "KVUrl": "https://AZC1-BRW-HUB-P0-kvVault01.vault.azure.net/", // Given we haven't deployed this as yet, you will have to update the CertURL later. "certificateUrl": "https://azc1-brw-hub-p0-kvvault01.vault.azure.net:443/secrets/WildcardCert/e0066997eae945529c84fbf815f7759f", "networkId": ["10.0.",144], // The is the /20 Network Address Space that will be divided up in this region "nsgRGName": "AZC1-BRW-HUB-RG-P0", // "{Primary-Azure-Region-AZXX}-{appname-3-characters-max-upper-case}-RG-P0" P0 is a Hub "RTRGName": "AZC1-BRW-HUB-RG-P0", // "{Primary-Azure-Region-AZXX}-{appname-3-characters-max-upper-case}-RG-P0" P0 is a Hub "RTName": "rtContoso-Hub", "dnsZoneRGName": "AZC1-BRW-HUB-RG-P0" // "{Primary-Azure-Region-AZXX}-{appname-3-characters-max-upper-case}-RG-P0" P0 is a Hub
- The file name should match your Primary Azure Region that you will deploy into
-
Open the following File and fill out all of the information ADF\tenants\HUB\AZE2-Global.json
- The file name should match your Secondary Azure Region that you will deploy into
- This will have a different network range etc, this is for DR
- Fill out the appropriate information, including the Keyvault and RG name references, since we will bootstrap those in both regions.
-
We are now ready to Deploy the initial Storage Account
- Make sure you are logged into Azure PowerShell
- First make sure you are in the correct Azure Tenant/Subscription
- More info is in this file: [ADF\1-PrereqsToDeploy\0-ConnectToAzureSelectSubscription.ps1]
- Although these helper scripts live in this directory [ADF\1-PrereqsToDeploy], we deploy them from a helper script from within your Tenant.
- Open up the Helper Script [ADF\tenants\HUB\azure-Deploy.ps1]
- In order to Load some settings into memory, once you open that file you press F5 to load it.
- You should see something similar to the following after you run F5
VERBOSE: ArtifactStagingDirectory is [D:\repos\AzureDeploymentFramework\ADF] and App is [HUB]
- Then after that you can create the intial Resource Group and Storage Account
- You will see the lines below, that you can execute (make sure you did F5 first! and are in your subscription)
# Pre-reqs # Create Global Storage Account . ADF:\1-PrereqsToDeploy\1-CreateStorageAccountGlobal.ps1 -APP $App
- You wil see an output similar to below once the RG and Storage are created.
- This storage account is used for uploading Assets (for IaaS/VM Deployments) that you may need, such as software installs and also used for your Template Deployments.
VERBOSE: Global RGName: AZC1-BRW-HUB-RG-G1 ResourceGroupName : AZC1-BRW-HUB-RG-G1 Location : centralus ProvisioningState : Succeeded Tags : ResourceId : /subscriptions/1f0713fe-9b12-4c8f-ab0c-26aba7aaa3e5/resourceGroups/AZC1-BRW-HUB-RG-G1 ResourceGroupName : AZC1-BRW-HUB-RG-G1 StorageAccountName : azc1brwhubg1saglobal Id : /subscriptions/1f0713fe-9b12-4c8f-ab0c-26aba7aaa3e5/resourceGroups/AZC1-BRW-HUB-RG-G1/providers/Microsoft.Storage/storageAccounts/azc1brwhubg1saglobal Location : centralus Sku : Microsoft.Azure.Commands.Management.Storage.Models.PSSku Kind : StorageV2 Encryption : Microsoft.Azure.Management.Storage.Models.Encryption AccessTier : Hot CreationTime : 1/17/2021 8:51:11 PM
- Make sure you are logged into Azure PowerShell
-
In order to use Friendly Names for our Role Assignments in your configurations we need to do a 1 time export of these from your Subscription.
- Working in the same file [ADF\tenants\HUB\azure-Deploy.ps1]
- Execute this following line
# Export all role defintions . ADF:\1-PrereqsToDeploy\4.1-getRoleDefinitionTable.ps1 -APP $App
- This process will actually update the JSON object in the following file [ADF\tenants\HUB\Global-Config.json]
- You can open that file and format it if you like and then save it.
- Once you format it you will see the Role Definition Friendly names and the associated GUIDs
"RolesGroupsLookup": { "Storage Blob Delegator": { "Id": "db58b8e5-c6ad-4a2a-8342-4190687cbf4a", "Description": "Allows for generation of a user delegation key which can be used to sign SAS tokens" }, "Managed Application Contributor Role": { "Id": "641177b8-a67a-45b9-a033-47bc880bb21e", "Description": "Allows for creating managed application resources." }, ...
- If you add custom Role definitions in the future, then you should re-run this command to re-export them over the top
-
Create your Service Principals (Scripts are provided for GitHub and Azure DevOps), this document assumes GitHub
- This will create 1 Principal per Resource Group, Per Application
- You can go ahead and create all of them ahead of time, if you like
- You can always come back add more or also re-run this, it will check if they exist
- Execute this following line/s (One for each region)
# Create Service principal for Env. . ADF:\1-PrereqsToDeploy\4-Start-CreateServicePrincipalGH.ps1 -APP $App -Prefix AZC1 -Environments P0,G0,G1,D2,S1 . ADF:\1-PrereqsToDeploy\4-Start-CreateServicePrincipalGH.ps1 -APP $App -Prefix AZE2 -Environments P0,S1
- Sample Output, this does several things
- Create the Application/Service Principal in Azure ActiveDirectory
- Creates the Secret in GitHub, this is used for Deployments (GitHub Workflows/Actions)
- Updates the Global-Global.json file to do friendly name lookups for the ServicePrincipal to the objectid
Secret : System.Security.SecureString ServicePrincipalNames : {55ec7612-2d3a-43b8-a5b7-4a53fd905655, http://AzureDeploymentFramework_AZC1-BRW-HUB-RG-P0} ApplicationId : 55ec7612-2d3a-43b8-a5b7-4a53fd905655 ObjectType : ServicePrincipal DisplayName : AzureDeploymentFramework_AZC1-BRW-HUB-RG-P0 Id : 9b537c42-3cfc-423b-955d-a83dbbfa0ac3 Type : WARNING: Assigning role 'Reader' over scope '/subscriptions/1f0713fe-9b12-4c8f-ab0c-26aba7aaa3e5' to the new service principal. {"clientId":"55ec7612-2d3a-43b8-a5b7-4a53fd905655","clientSecret":"6b72ed30-80e9-4ca5-8178-5b4755f84b27","tenantId":"3254f91d-4657-40df-962d-c8e6dad75963","subscriptionId":"1f0713fe-9b12-4c8f-ab0c-26aba7aaa3e5","activeDirectoryEndpointUrl":"https://login.microsoftonline.com","resourceManagerEndpointUrl":"https://management.azure.com/","activeDirectoryGraphResourceId":"https://graph.windows.net/","sqlManagementEndpointUrl":"https://management.core.windows.net:8443/","galleryEndpointUrl":"https://gallery.azure.com/","managementEndpointUrl":"https://management.core.windows.net/"} ✓ Set secret AZC1_HUB_RG_P0 for brwilkinson/AzureDeploymentFramework VERBOSE: Adding Service Principal [AzureDeploymentFramework_AZC1-BRW-HUB-RG-P0] to Global-Global.json AzureDeploymentFramework_AZC1-BRW-HUB-RG-P0 : 9b537c42-3cfc-423b-955d-a83dbbfa0ac3 AzureDeploymentFramework_AZC1-BRW-HUB-RG-G0 : c4acb09d-7fe0-4e50-8988-b11b67711841 AzureDeploymentFramework_AZC1-BRW-HUB-RG-G1 : a744f350-9757-4943-b42e-f96e88b42f96 AzureDeploymentFramework_AZC1-BRW-HUB-RG-D2 : 8c1101e5-d23e-4f15-bb4d-9b2156898d8f AzureDeploymentFramework_AZC1-BRW-HUB-RG-S1 : 1509358e-331b-44d3-83e1-3a880832328f
- Sample Output, this does several things
-
BootStrap the Hub Resource Group Creation and also the Keyvaults in the Primary and Secondary Region
- Although these helper scripts live in this directory [ADF\1-PrereqsToDeploy], we deploy them from a helper script from within your Tenant.
- Open up the Helper Script [ADF\tenants\HUB\azure-Deploy.ps1]
- Then execute the following
# Bootstrap Hub RGs and Keyvaults . ADF:\1-PrereqsToDeploy\1-CreateHUBKeyVaults.ps1 -APP $App
- You should see the following output
VERBOSE: Primary HUB RGName: AZC1-BRW-HUB-RG-P0 VERBOSE: Primary KV Name: AZC1-BRW-HUB-P0-kvVLT01 VERBOSE: Secondary HUB RGName: AZE2-BRW-HUB-RG-P0 VERBOSE: Secondary KV Name: AZE2-BRW-HUB-P0-kvVLT01
- Following this you can manually create the following 2 Secrets
- localadmin, then provide the local admin password for your Virtual Machines
-
In order to deploy from these Service Principals, they need to be delegated access over certain scopes in Azure
- These Role Assignments are handled within the Deployment Scripts, however there is a chicken or egg problem
- I would recommend 2 Manual Role assignements to get things started
- Assign the [GO] Principal E.g. "AzureDeploymentFramework_AZC1-BRW-HUB-RG-G0" as Owner on the Subscription.
- This is the principal that executes all role assignments and also creates RG's.
- As a reminder, G0 stands for Subscription Level.
- This principal will do the following:
- Upload files to the storage account, so inherits access via owner to the storage account keys
- Deploy a Template by reading from the Keyvault (1 in each regional hub)
- Then it will run the intial template deployment to Create RG's and perform RBAC Assignments on those RG's
- Assign the [G0] Principal E.g. E.g. "AzureDeploymentFramework_AZC1-BRW-HUB-RG-G0" as "Key Vault Secrets User (preview)"
- You will want to do this on both Hubs i.e. both P0 Resource Groups.
- While you are setting this up, you should also assign the below RBAC Role Assignments on your own account
- "Owner" on Subscription
- "Key Vault Secrets Officer (preview)" on the Hub RG's i.e. P0
- We will need to create 2 secrets in order to deploy in the next step, so this will enable you to create these
- You can easily remove these later, once the Workflows have all been setup.
- Assign the [GO] Principal E.g. "AzureDeploymentFramework_AZC1-BRW-HUB-RG-G0" as Owner on the Subscription.
-
Go into the Keyvault in your primary Hub.
- Create 2 Secrets (These are the default securestring parameters on all templates, you can add more later)
- localadmin (choose your domain or local admin password here)
- sshPublic (any value here, Update this later), consider moving, now this is on GitHub, not azureDevops
- Create 2 Secrets (These are the default securestring parameters on all templates, you can add more later)
-
In order to deploy WebSites, you should create some Web Certs, you can also do this from a Public Provider, however we will use self signed here.
- Although these helper scripts live in this directory [ADF\1-PrereqsToDeploy], we deploy them from a helper script from within your Tenant.
- Open up the Helper Script [ADF\tenants\HUB\azure-Deploy.ps1]
- Then execute the following
# Create Global Web Create . ADF:\1-PrereqsToDeploy\2-CreateUploadWebCertAdminCreds.ps1 -APP $App
- The cert will be created using the password from your keyvault localadmin secret that you set earlier
- The DNS names used on the cert are from the Global-Global.json [CertURLs] property.
- This certificate will be deploy to all VM's in the Root/Trusted/My root stores
- When you execute the above script it will also update the [CertificateThumbprint] value in the Global-Global.json file
- When you deploy websites, this cert will be bound to SSL sites in IIS.
-
Once you have Created the Secrets in the Primary Regional Hub Keyvault, you can sync the secrets to the Secondary Regional Hub Keyvault
- Although these helper scripts live in this directory [ADF\1-PrereqsToDeploy], we deploy them from a helper script from within your Tenant.
- Open up the Helper Script [ADF\tenants\HUB\azure-Deploy.ps1]
- Then execute the following
# Sync the keyvault from CentralUS to EastUS2 (Primary Region to Secondary Region) . ADF:\1-PrereqsToDeploy\3-Start-AzureKVSync.ps1
- The Primary and Secondary KV Name and Region Etc. comes from the Global meta data file that you updated earlier.
- i.e. [ADF\tenants\HUB\Global-Global.json]