Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Standard Hub Network deployment #1268

Merged
merged 10 commits into from
Jul 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions deploy/standard-hub/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.azure
5 changes: 5 additions & 0 deletions deploy/standard-hub/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
## Deployment Configurations and Scripts

The deployment configurations and scripts are located in this `deploy` directory.
If you are looking for the deployment instructions, please refer to the [documentation](https://docs.foundationallm.ai) and it is also available in this repository in the `docs` directory as markdown files.
[Setup Guides in Markdown format](https://github.com/solliancenet/foundationallm/blob/main/docs/setup-guides/index.md)
75 changes: 75 additions & 0 deletions deploy/standard-hub/azd-hooks/postprovision.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
#!/usr/bin/env pwsh

Set-PSDebug -Trace 0 # Echo every command (0 to disable, 1 to enable)
Set-StrictMode -Version 3.0
$ErrorActionPreference = "Stop"

# Load utility functions
Push-Location $($MyInvocation.InvocationName | Split-Path)
try {
. ./utility/Load-Utility-Functions.ps1
}
finally {
Pop-Location
}

$dnsServerIp = "${env:DNS_RESOLVER_ENDPOINT_IP}"
$outputFolderPath = "../standard-hub/config/vpn" | Get-AbsolutePath
$outputFilePath = Join-Path $outputFolderPath "VpnClientConfiguration.zip"
$resourceGroupName = "${env:RESOURCE_GROUP_NAME}"
$vpnGatewayName = "${env:VPN_GATEWAY_NAME}"
$xmlFilePath = Join-Path $outputFolderPath "AzureVPN" "azurevpnconfig.xml" # Assuming the XML file is inside the extracted folder

# Add the dns-resolver extension to the cli
az extension add --name dns-resolver --allow-preview true --yes --only-show-errors

# Get the VPN client configuration package URL
$vpnClientPackageUrl = az network vnet-gateway vpn-client generate `
--name $vpnGatewayName `
--resource-group $resourceGroupName `
--output tsv

# Download the package and extract
Invoke-WebRequest -Uri $vpnClientPackageUrl -OutFile $outputFilePath
Expand-Archive -Path $outputFilePath -DestinationPath $outputFolderPath -Force

# Assuming the XML file is directly inside the expanded folder & Read the XML file
$expandedFolder = (Get-ChildItem -Directory -Path $outputFolderPath)[0].FullName
$xmlFilePath = Join-Path -Path $expandedFolder -ChildPath "azurevpnconfig.xml"
$xmlContent = Get-Content -Path $xmlFilePath
$azureVpnClientConfig = [xml]$xmlContent

# Create a namespace manager
$namespaceManager = New-Object System.Xml.XmlNamespaceManager($azureVpnClientConfig.NameTable)
$namespaceManager.AddNamespace("ns", "http://schemas.datacontract.org/2004/07/")
$namespaceManager.AddNamespace("i", "http://www.w3.org/2001/XMLSchema-instance")

# Remove <clientconfig i:nil="true" /> node if it exists
$nilClientConfigNode = $azureVpnClientConfig.SelectSingleNode("//ns:clientconfig[@i:nil='true']", $namespaceManager)
if ($nilClientConfigNode -ne $null) {
$nilClientConfigNode.ParentNode.RemoveChild($nilClientConfigNode) | Out-Null
}

# Create DNS servers XML nodes
$dnsServersNode = $azureVpnClientConfig.CreateElement("dnsservers", "http://schemas.datacontract.org/2004/07/")
$dnsServer1 = $azureVpnClientConfig.CreateElement("dnsserver", "http://schemas.datacontract.org/2004/07/")
$dnsServer1.InnerText = $dnsServerIp
$dnsServersNode.AppendChild($dnsServer1) | Out-Null

# Locate the clientconfig node or create it if it doesn't exist
$clientConfigNode = $azureVpnClientConfig.SelectSingleNode("//ns:clientconfig", $namespaceManager)
if ($clientConfigNode -eq $null) {
$clientConfigNode = $azureVpnClientConfig.CreateElement("clientconfig", "http://schemas.datacontract.org/2004/07/")
$azureVpnClientConfig.DocumentElement.AppendChild($clientConfigNode) | Out-Null
}

# Append DNS servers to clientconfig
$clientConfigNode.AppendChild($dnsServersNode) | Out-Null

# Save the updated XML file
$azureVpnClientConfig.Save($xmlFilePath)

Write-Host -ForegroundColor Yellow `
"Please Install the Azure VPN client via https://aka.ms/azvpnclientdownload, and
then import the VPN client configuration package downloaded to $xmlFilePath. Make sure to connect
to the VPN prior to running the next step of the FLLM Install for Standard."
18 changes: 18 additions & 0 deletions deploy/standard-hub/azd-hooks/utility/Get-AbsolutePath.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#! /usr/bin/pwsh

Set-PSDebug -Trace 0 # Echo every command (0 to disable, 1 to enable)
Set-StrictMode -Version 3.0
$ErrorActionPreference = "Stop"

function Get-AbsolutePath {
<#
.SYNOPSIS
Get the absolute path of a file or directory. Relative path does not need to exist.
#>
param (
[Parameter(Mandatory = $true, ValueFromPipeline = $true, Position = 0)]
[string]$RelatviePath
)

return $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($RelatviePath)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#!/usr/bin/env pwsh

Push-Location $($MyInvocation.InvocationName | Split-Path)
try {
. ./utility/Get-AbsolutePath.ps1
}
finally {
Pop-Location
}
10 changes: 10 additions & 0 deletions deploy/standard-hub/azure.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# yaml-language-server: $schema=https://raw.githubusercontent.com/Azure/azure-dev/main/schemas/v1.0/azure.yaml.json

# Name of the application.
name: foundationallm-standard-hub
hooks:
postprovision:
shell: pwsh
continueOnError: false
interactive: true
run: azd-hooks/postprovision.ps1
137 changes: 137 additions & 0 deletions deploy/standard-hub/infra/abbreviations.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
{
"analysisServicesServers": "as",
"apiManagementService": "apim-",
"appConfigurationConfigurationStores": "appcs-",
"appManagedEnvironments": "cae-",
"appContainerApps": "ca-",
"authorizationPolicyDefinitions": "policy-",
"automationAutomationAccounts": "aa-",
"blueprintBlueprints": "bp-",
"blueprintBlueprintsArtifacts": "bpa-",
"cacheRedis": "redis-",
"cdnProfiles": "cdnp-",
"cdnProfilesEndpoints": "cdne-",
"cognitiveServicesAccounts": "cog-",
"cognitiveServicesFormRecognizer": "cog-fr-",
"cognitiveServicesTextAnalytics": "cog-ta-",
"computeAvailabilitySets": "avail-",
"computeCloudServices": "cld-",
"computeDiskEncryptionSets": "des",
"computeDisks": "disk",
"computeDisksOs": "osdisk",
"computeGalleries": "gal",
"computeSnapshots": "snap-",
"computeVirtualMachines": "vm",
"computeVirtualMachineScaleSets": "vmss-",
"containerInstanceContainerGroups": "ci",
"containerRegistryRegistries": "cr",
"containerServiceManagedClusters": "aks-",
"databricksWorkspaces": "dbw-",
"dataFactoryFactories": "adf-",
"dataLakeAnalyticsAccounts": "dla",
"dataLakeStoreAccounts": "dls",
"dataMigrationServices": "dms-",
"dBforMySQLServers": "mysql-",
"dBforPostgreSQLServers": "psql-",
"devicesIotHubs": "iot-",
"devicesProvisioningServices": "provs-",
"devicesProvisioningServicesCertificates": "pcert-",
"documentDBDatabaseAccounts": "cosmos-",
"eventGridDomains": "evgd-",
"eventGridDomainsTopics": "evgt-",
"eventGridEventSubscriptions": "evgs-",
"eventHubNamespaces": "evhns-",
"eventHubNamespacesEventHubs": "evh-",
"hdInsightClustersHadoop": "hadoop-",
"hdInsightClustersHbase": "hbase-",
"hdInsightClustersKafka": "kafka-",
"hdInsightClustersMl": "mls-",
"hdInsightClustersSpark": "spark-",
"hdInsightClustersStorm": "storm-",
"hybridComputeMachines": "arcs-",
"insightsActionGroups": "ag-",
"insightsComponents": "appi-",
"keyVaultVaults": "kv-",
"kubernetesConnectedClusters": "arck",
"kustoClusters": "dec",
"kustoClustersDatabases": "dedb",
"logicIntegrationAccounts": "ia-",
"logicWorkflows": "logic-",
"machineLearningServicesWorkspaces": "mlw-",
"managedIdentityUserAssignedIdentities": "id-",
"managementManagementGroups": "mg-",
"migrateAssessmentProjects": "migr-",
"networkApplicationGateways": "agw-",
"networkApplicationSecurityGroups": "asg-",
"networkAzureFirewalls": "afw-",
"networkBastionHosts": "bas-",
"networkConnections": "con-",
"networkDnsResolvers": "dnsr-",
"networkDnsZones": "dnsz-",
"networkExpressRouteCircuits": "erc-",
"networkFirewallPolicies": "afwp-",
"networkFirewallPoliciesWebApplication": "waf",
"networkFirewallPoliciesRuleGroups": "wafrg",
"networkFrontDoors": "fd-",
"networkFrontdoorWebApplicationFirewallPolicies": "fdfp-",
"networkLoadBalancersExternal": "lbe-",
"networkLoadBalancersInternal": "lbi-",
"networkLoadBalancersInboundNatRules": "rule-",
"networkLocalNetworkGateways": "lgw-",
"networkNatGateways": "ng-",
"networkNetworkInterfaces": "nic-",
"networkNetworkSecurityGroups": "nsg-",
"networkNetworkSecurityGroupsSecurityRules": "nsgsr-",
"networkNetworkWatchers": "nw-",
"networkPrivateDnsZones": "pdnsz-",
"networkPrivateLinkServices": "pl-",
"networkPublicIPAddresses": "pip-",
"networkPublicIPPrefixes": "ippre-",
"networkRouteFilters": "rf-",
"networkRouteTables": "rt-",
"networkRouteTablesRoutes": "udr-",
"networkTrafficManagerProfiles": "traf-",
"networkVirtualNetworkGateways": "vgw-",
"networkVirtualNetworks": "vnet-",
"networkVirtualNetworksSubnets": "snet-",
"networkVirtualNetworksVirtualNetworkPeerings": "peer-",
"networkVirtualWans": "vwan-",
"networkVpnGateways": "vpng-",
"networkVpnGatewaysVpnConnections": "vcn-",
"networkVpnGatewaysVpnSites": "vst-",
"notificationHubsNamespaces": "ntfns-",
"notificationHubsNamespacesNotificationHubs": "ntf-",
"openAiAccounts": "openai-",
"operationalInsightsWorkspaces": "log-",
"portalDashboards": "dash-",
"powerBIDedicatedCapacities": "pbi-",
"purviewAccounts": "pview-",
"recoveryServicesVaults": "rsv-",
"resourcesResourceGroups": "rg-",
"searchSearchServices": "srch-",
"serviceBusNamespaces": "sb-",
"serviceBusNamespacesQueues": "sbq-",
"serviceBusNamespacesTopics": "sbt-",
"serviceEndPointPolicies": "se-",
"serviceFabricClusters": "sf-",
"signalRServiceSignalR": "sigr",
"sqlManagedInstances": "sqlmi-",
"sqlServers": "sql-",
"sqlServersDataWarehouse": "sqldw-",
"sqlServersDatabases": "sqldb-",
"sqlServersDatabasesStretch": "sqlstrdb-",
"storageStorageAccounts": "st",
"storageStorageAccountsVm": "stvm",
"storSimpleManagers": "ssimp",
"streamAnalyticsCluster": "asa-",
"synapseWorkspaces": "syn",
"synapseWorkspacesAnalyticsWorkspaces": "synw",
"synapseWorkspacesSqlPoolsDedicated": "syndp",
"synapseWorkspacesSqlPoolsSpark": "synsp",
"timeSeriesInsightsEnvironments": "tsi-",
"webServerFarms": "plan-",
"webSitesAppService": "app-",
"webSitesAppServiceEnvironment": "ase-",
"webSitesFunctions": "func-",
"webStaticSites": "stapp-"
}
30 changes: 30 additions & 0 deletions deploy/standard-hub/infra/core/networking/dns.bicep
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
param key string
param tags object
param vnetId string
param zone string

// Resources
resource main 'Microsoft.Network/privateDnsZones@2018-09-01' = {
location: 'global'
name: zone
tags: tags
}

resource link 'Microsoft.Network/privateDnsZones/virtualNetworkLinks@2018-09-01' = {
parent: main
name: zone
location: 'global'
tags: tags

properties: {
registrationEnabled: false
virtualNetwork: {
id: vnetId
}
}
}

// Outputs
output id string = main.id
output key string = key
output name string = main.name
43 changes: 43 additions & 0 deletions deploy/standard-hub/infra/core/networking/dnsResolver.bicep
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@

param abbrs object
param environmentName string
param location string
param project string
param vnetName string

// Locals
var resolverName = namer(abbrs.networkDnsResolvers, environmentName, location, 'net', project)

// Functions
func namer(resourceAbbr string, env string, region string, workloadName string, projectId string) string =>
deltadan marked this conversation as resolved.
Show resolved Hide resolved
'${resourceAbbr}${env}-${region}-${workloadName}-${projectId}'

// Resources
resource resolver 'Microsoft.Network/dnsResolvers@2022-07-01' = {
name: resolverName
location: location
properties: {
virtualNetwork: {
id: resourceId(resourceGroup().name, 'Microsoft.Network/virtualNetworks', vnetName)
}
}
}

resource inboundEndpoint 'Microsoft.Network/dnsResolvers/inboundEndpoints@2022-07-01' = {
parent: resolver
name: resolverName
location: location
properties: {
ipConfigurations: [
{
privateIpAllocationMethod: 'Dynamic'
subnet: {
id: resourceId(resourceGroup().name, 'Microsoft.Network/virtualNetworks/subnets', vnetName, 'DNS')
}
}
]
}
}

// Outputs
output dnsResolverEndpointIp string = inboundEndpoint.properties.ipConfigurations[0].privateIpAddress
Loading
Loading