Skip to content

Commit

Permalink
make hub network optional (#166)
Browse files Browse the repository at this point in the history
* make hub network and firewall optional

* make hub network and firewall optional

* make hub network and firewall optional

* make hub network and firewall optional

* make firewall mandatory when deploying hub

* ensure the resource id validation correctly classifies the resource id

* improve variable used for default dedicated workload profile

* Update deploy.aca-environment.bicep

remove the option to deploy dedicated profile with ACA environment until bug is fixed on the product side

* minor fix
  • Loading branch information
mosabami authored Oct 24, 2024
1 parent a65572c commit 1407ca0
Show file tree
Hide file tree
Showing 16 changed files with 1,190 additions and 463 deletions.
36 changes: 34 additions & 2 deletions scenarios/aca-internal/azure-resource-manager/main-portal-ux.json
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,22 @@
}
]
},
{
"name": "deployHub",
"type": "Microsoft.Common.CheckBox",
"label": "Deploy Hub",
"subLabel": "",
"defaultValue": true,
"toolTip": "Enable or disable the creation of a hub network and its supporting resources.",
"constraints": {
"required": false,
"regex": "",
"validationMessage": "",
"validations": []
},
"infoMessages": [],
"visible": true
},
{
"name": "vnetAddressPrefixes",
"type": "Microsoft.Common.TextBox",
Expand Down Expand Up @@ -536,8 +552,24 @@
},
{
"name": "flags",
"label": "Deployment feature flags",
"elements": [
"label": "Deployment dedicated workload profile",
"elements": [
{
"name": "workloadProfile",
"type": "Microsoft.Common.CheckBox",
"label": "Deploy Hub",
"subLabel": "",
"defaultValue": true,
"toolTip": "Enable this if you would like to deploy a dedicated workload profile called default.",
"constraints": {
"required": false,
"regex": "",
"validationMessage": "",
"validations": []
},
"infoMessages": [],
"visible": true
},
{
"name": "enableBastion",
"type": "Microsoft.Common.DropDown",
Expand Down
1,231 changes: 915 additions & 316 deletions scenarios/aca-internal/azure-resource-manager/main.json

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@
"tags": {
"value": {}
},
"deployHub": {
"value": true
},
"enableTelemetry": {
"value": true
},
Expand All @@ -30,6 +33,10 @@
"enableBastion": {
"value": true
},
// Should a dedicated workload profile called default be provisioned?
"dedicatedWorkloadProfile": {
"value": false
},
"gatewaySubnetAddressPrefix": {
"value": "10.0.0.0/27"
},
Expand Down
31 changes: 21 additions & 10 deletions scenarios/aca-internal/bicep/main.bicep
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ targetScope = 'subscription'
@maxLength(10)
param workloadName string = 'aca-lza'

@description('Optional, Add a workload profile.')
param dedicatedWorkloadProfile bool = false

@description('The name of the environment (e.g. "dev", "test", "prod", "uat", "dr", "qa"). Up to 8 characters long.')
@maxLength(8)
param environment string = 'test'
Expand All @@ -18,6 +21,9 @@ param location string = deployment().location
@description('Optional. The tags to be assigned to the created resources.')
param tags object = {}

@description('Optional. Enable or disable the creation of the Hub network and it\'s supporting services.')
param deployHub bool = true

@description('Optional. The name of the hub resource group to create the resources in. If set, it overrides the name generated by the template.')
param hubResourceGroupName string = ''

Expand Down Expand Up @@ -144,7 +150,8 @@ var rgSpokeName = !empty(spokeResourceGroupName) ? spokeResourceGroupName : '${n
// ------------------
// RESOURCES
// ------------------
module hub 'modules/01-hub/deploy.hub.bicep' = {

module hub 'modules/01-hub/deploy.hub.bicep' = if (deployHub) {
name: take('hub-${deployment().name}-deployment', 64)
params: {
location: location
Expand All @@ -154,7 +161,7 @@ module hub 'modules/01-hub/deploy.hub.bicep' = {
workloadName: workloadName
vnetAddressPrefixes: vnetAddressPrefixes
enableBastion: enableBastion
bastionSku:bastionSku
bastionSku: bastionSku
bastionSubnetAddressPrefix: bastionSubnetAddressPrefix
azureFirewallSubnetAddressPrefix: azureFirewallSubnetAddressPrefix
azureFirewallSubnetManagementAddressPrefix: azureFirewallSubnetManagementAddressPrefix
Expand All @@ -177,12 +184,15 @@ module spoke 'modules/02-spoke/deploy.spoke.bicep' = {
tags: tags
environment: environment
workloadName: workloadName
hubVNetId: hub.outputs.hubVNetId
hubVNetId: deployHub ? hub.outputs.hubVNetId : ''
enableBastion: enableBastion
bastionSku: bastionSku
bastionSubnetAddressPrefix: bastionSubnetAddressPrefix
spokeApplicationGatewaySubnetAddressPrefix: spokeApplicationGatewaySubnetAddressPrefix
spokeInfraSubnetAddressPrefix: spokeInfraSubnetAddressPrefix
spokePrivateEndpointsSubnetAddressPrefix: spokePrivateEndpointsSubnetAddressPrefix
spokeVNetAddressPrefixes: spokeVNetAddressPrefixes
networkApplianceIpAddress: hub.outputs.networkApplianceIpAddress
networkApplianceIpAddress: deployHub ? hub.outputs.networkApplianceIpAddress : ''
vmSize: vmSize
vmAdminUsername: vmAdminUsername
vmAdminPassword: vmAdminPassword
Expand All @@ -204,7 +214,7 @@ module supportingServices 'modules/03-supporting-services/deploy.supporting-serv
environment: environment
workloadName: workloadName
spokeVNetId: spoke.outputs.spokeVNetId
hubVNetId: hub.outputs.hubVNetId
hubVNetId: deployHub ? hub.outputs.hubVNetId : ''
deployRedisCache: deployRedisCache
logAnalyticsWorkspaceId: spoke.outputs.logAnalyticsWorkspaceId
deployOpenAi: deployOpenAi
Expand All @@ -219,13 +229,14 @@ module containerAppsEnvironment 'modules/04-container-apps-environment/deploy.ac
tags: tags
environment: environment
workloadName: workloadName
hubVNetId: hub.outputs.hubVNetId
hubVNetId: deployHub ? hub.outputs.hubVNetId : ''
spokeVNetName: spoke.outputs.spokeVNetName
spokeInfraSubnetName: spoke.outputs.spokeInfraSubnetName
enableApplicationInsights: enableApplicationInsights
enableDaprInstrumentation: enableDaprInstrumentation
enableTelemetry: enableTelemetry
logAnalyticsWorkspaceId: spoke.outputs.logAnalyticsWorkspaceId
dedicatedWorkloadProfile: dedicatedWorkloadProfile
}
}

Expand Down Expand Up @@ -265,15 +276,15 @@ module applicationGateway 'modules/06-application-gateway/deploy.app-gateway.bic
// ------------------


// Hub

@description('The resource ID of hub virtual network.')
output hubVNetId string = hub.outputs.hubVNetId
output hubVNetId string = deployHub ? hub.outputs.hubVNetId : ''

@description('The name of hub virtual network.')
output hubVNetName string = hub.outputs.hubVnetName
output hubVNetName string = deployHub ? hub.outputs.hubVnetName : ''

@description('The name of the Hub resource group.')
output hubResourceGroupName string = hub.outputs.resourceGroupName
output hubResourceGroupName string = deployHub ? hub.outputs.resourceGroupName : ''

// Spoke
@description('The name of the Spoke resource group.')
Expand Down
10 changes: 7 additions & 3 deletions scenarios/aca-internal/bicep/main.parameters.jsonc
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@
"tags": {
"value": {}
},
"deployHub": {
"value": true
},
"enableTelemetry": {
"value": true
},
Expand All @@ -30,6 +33,10 @@
"enableBastion": {
"value": true
},
// Should a dedicated workload profile called default be provisioned?
"dedicatedWorkloadProfile": {
"value": false
},
"gatewaySubnetAddressPrefix": {
"value": "10.0.0.0/27"
},
Expand All @@ -54,9 +61,6 @@
"vmLinuxSshAuthorizedKeys": {
"value": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDpNpoh248rsraL3uejAwKlla+pHaDLbp4DM7bKFoc3Rt1DeXPs0XTutJcNtq4iRq+ooRQ1T7WaK42MfQQxt3qkXwjyv8lPJ4v7aElWkAbxZIRYVYmQVxxwfw+zyB1rFdaCQD/kISg/zXxCWw+gdds4rEy7eq23/bXFM0l7pNvbAULIB6ZY7MRpC304lIAJusuZC59iwvjT3dWsDNWifA1SJtgr39yaxB9Fb01UdacwJNuvfGC35GNYH0VJ56c+iCFeAnMXIT00cYuHf0FCRTP0WvTKl+PQmeD1pwxefdFvKCVpidU2hOARb4ooapT0SDM1SODqjaZ/qwWP18y/qQ/v imported-openssh-key"
},
"vmAuthenticationType": {
"value": "sshPublicKey"
},
"vmJumpboxOSType": {
"value": "linux"
},
Expand Down
4 changes: 2 additions & 2 deletions scenarios/aca-internal/bicep/modules/01-hub/deploy.hub.bicep
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ module vnetHub '../../../../shared/bicep/network/vnet.bicep' = {
}

@description('The Azure Firewall deployment. This would normally be already provisioned by your platform team.')
module azfw './modules/azureFirewall.bicep' = {
module azfw './modules/azureFirewall.bicep' = {
scope: hubResourceGroup
name: take('afw-${deployment().name}', 64)
params: {
Expand Down Expand Up @@ -194,4 +194,4 @@ output hubVnetName string = vnetHub.outputs.vnetName
output resourceGroupName string = hubResourceGroup.name

@description('The private IP address of the Azure Firewall.')
output networkApplianceIpAddress string = azfw.outputs.afwPrivateIp
output networkApplianceIpAddress string = azfw.outputs.afwPrivateIp
10 changes: 10 additions & 0 deletions scenarios/aca-internal/bicep/modules/02-spoke/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,21 @@ After executing these steps you'll have the spoke resource group (`rg-lzaaca-spo
- Jump box virtual machine (optional)

## Steps

:warning: If you are running these commands on windows, you might need to run the command below to ensure windows captures the RESOURCEID_VNET_HUB correctly:

```bash
export MSYS_NO_PATHCONV=1
```

1. Set the desired region for the whole reference implementation.

:stop_sign: Update this to your desired region.

```bash
LOCATION=eastus # or any location that suits your needs, ensure Azure OpenAI service is available there.
```

:warning: You will need to get the IP address of your Azure firewall or whatever network appliance you are using and replace the `[IP OF THE NETWORK APPLIANCE] placeholder in the deploy.spoke.paramters.jsonc file with it.

1. Get the private IP address of your Azure firewall
Expand Down
67 changes: 55 additions & 12 deletions scenarios/aca-internal/bicep/modules/02-spoke/deploy.spoke.bicep
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,14 @@ param vmAuthenticationType string = 'password'
@description('Optional, default value is true. If true, Azure Policies will be deployed')
param deployAzurePolicies bool = true

@description('Enable or disable the creation of the Azure Bastion in spoke network.')
param enableBastion bool = false

@description('CIDR to use for the Azure Bastion subnet.')
param bastionSubnetAddressPrefix string = '10.1.2.64/26'

param bastionSku string = 'Basic'

// ------------------
// VARIABLES
// ------------------
Expand All @@ -98,16 +106,22 @@ var nsgAppGwRules = loadJsonContent('./nsgAppGwRules.jsonc', 'securityRules')
var namingRules = json(loadTextContent('../../../../shared/bicep/naming/naming-rules.jsonc'))

var rgSpokeName = !empty(spokeResourceGroupName) ? spokeResourceGroupName : '${namingRules.resourceTypeAbbreviations.resourceGroup}-${workloadName}-spoke-${environment}-${namingRules.regionAbbreviations[toLower(location)]}'
var hubVNetResourceIdTokens = !empty(hubVNetId) ? split(hubVNetId, '/') : array('')

var hubVNetResourceIdTokens = contains(hubVNetId, '/') ? split(hubVNetId, '/') : array('')

// check to ensure the hubVNetResourceIdTokens was valid by checking the length of the array created in previous step
@description('The name of the hub virtual network.')
var hubVNetName = length(hubVNetResourceIdTokens) > 7 ? hubVNetResourceIdTokens[8] : ''

@description('The ID of the subscription containing the hub virtual network.')
var hubSubscriptionId = hubVNetResourceIdTokens[2]
var hubSubscriptionId = length(hubVNetResourceIdTokens) > 1 ? hubVNetResourceIdTokens[2] : ''

@description('The name of the resource group containing the hub virtual network.')
var hubResourceGroupName = hubVNetResourceIdTokens[4]
var hubResourceGroupName = length(hubVNetResourceIdTokens) > 3 ? hubVNetResourceIdTokens[4] : ''

@description('The name of the hub virtual network.')
var hubVNetName = hubVNetResourceIdTokens[8]

// This cannot be another value
var bastionSubnetName = 'AzureBastionSubnet'

// Subnet definition taking in consideration feature flags
var defaultSubnets = [
Expand All @@ -118,9 +132,9 @@ var defaultSubnets = [
networkSecurityGroup: {
id: nsgContainerAppsEnvironment.outputs.nsgId
}
routeTable: {
routeTable: networkApplianceIpAddress != '' ? {
id: egressLockdownUdr.outputs.resourceId
}
} : null
delegations: [
{
name: 'envdelegation'
Expand All @@ -142,8 +156,19 @@ var defaultSubnets = [
}
]


// Append optional bastion subnet, if required
var bastionAndDefaultSubnets = (empty(hubVNetName) && enableBastion ) ? concat(defaultSubnets, [
{
name: bastionSubnetName
properties: {
addressPrefix: bastionSubnetAddressPrefix
}
}
]) : defaultSubnets

// Append optional application gateway subnet, if required
var appGwAndDefaultSubnets = !empty(spokeApplicationGatewaySubnetAddressPrefix) ? concat(defaultSubnets, [
var appGwAndDefaultSubnets = !empty(spokeApplicationGatewaySubnetAddressPrefix) ? concat(bastionAndDefaultSubnets, [
{
name: spokeApplicationGatewaySubnetName
properties: {
Expand All @@ -153,7 +178,7 @@ var appGwAndDefaultSubnets = !empty(spokeApplicationGatewaySubnetAddressPrefix)
}
}
}
]) : defaultSubnets
]) : bastionAndDefaultSubnets

//Append optional jumpbox subnet, if required
var spokeSubnets = vmJumpboxOSType != 'none' ? concat(appGwAndDefaultSubnets, [
Expand Down Expand Up @@ -252,7 +277,7 @@ module nsgPep '../../../../shared/bicep/network/nsg.bicep' = {
}

@description('Spoke peering to regional hub network. This peering would normally already be provisioned by your subscription vending process.')
module peerSpokeToHub '../../../../shared/bicep/network/peering.bicep' = if (!empty(hubVNetId)) {
module peerSpokeToHub '../../../../shared/bicep/network/peering.bicep' = if (!empty(hubVNetName)) {
name: take('${deployment().name}-peerSpokeToHubDeployment', 64)
scope: spokeResourceGroup
params: {
Expand All @@ -264,7 +289,7 @@ module peerSpokeToHub '../../../../shared/bicep/network/peering.bicep' = if (!em
}

@description('Regional hub peering to this spoke network. This peering would normally already be provisioned by your subscription vending process.')
module peerHubToSpoke '../../../../shared/bicep/network/peering.bicep' = if (!empty(hubVNetId)) {
module peerHubToSpoke '../../../../shared/bicep/network/peering.bicep' = if (!empty(hubVNetName)) {
name: take('${deployment().name}-peerHubToSpokeDeployment', 64)
scope: resourceGroup(hubSubscriptionId, hubResourceGroupName)
params: {
Expand All @@ -275,7 +300,7 @@ module peerHubToSpoke '../../../../shared/bicep/network/peering.bicep' = if (!em
}
}
@description('The Route Table deployment')
module egressLockdownUdr '../../../../shared/bicep/routeTables/main.bicep' = {
module egressLockdownUdr '../../../../shared/bicep/routeTables/main.bicep' = if (networkApplianceIpAddress != '') {
name: take('egressLockdownUdr-${uniqueString(spokeResourceGroup.id)}', 64)
scope: spokeResourceGroup
params: {
Expand Down Expand Up @@ -346,6 +371,24 @@ module policyAssignments './modules/policy/policy-definition.module.bicep' = if
}
}

@description('An optional Azure Bastion deployment for jump box access in your spoke network. This would normally be already provisioned by your platform team. This resource will not be provisioned, if you have a valid hub network resource id')
module bastion '../01-hub/modules/bastion.bicep' = if (empty(hubVNetName) && enableBastion ) {
name: take('bastion-${deployment().name}', 64)
scope: spokeResourceGroup
params: {
location: location
tags: tags
sku:bastionSku
bastionName: naming.outputs.resourcesNames.bastion
bastionNetworkSecurityGroupName: naming.outputs.resourcesNames.bastionNsg
bastionPublicIpName: naming.outputs.resourcesNames.bastionPip
bastionSubnetName: bastionSubnetName
bastionSubnetAddressPrefix: bastionSubnetAddressPrefix
bastionVNetName: vnetSpoke.outputs.vnetName
}
}


// ------------------
// OUTPUTS
// ------------------
Expand Down
Loading

0 comments on commit 1407ca0

Please sign in to comment.