AKS-Construction/bicep/network.bicep

542 строки
16 KiB
Bicep

param resourceName string
param location string = resourceGroup().location
param networkPluginIsKubenet bool = false
param aksPrincipleId string = ''
param vnetAddressPrefix string
param vnetAksSubnetAddressPrefix string
param cniDynamicIpAllocation bool = false
@description('Provide the vnetPodAddressPrefix when using cniDynamicIpAllocation')
param vnetPodAddressPrefix string = ''
//Nsg
param workspaceName string = ''
param workspaceResourceGroupName string = ''
param networkSecurityGroups bool = true
//Firewall
param azureFirewalls bool = false
param azureFirewallSku string = 'Basic'
param azureFirewallsManagementSeperation bool = azureFirewalls && azureFirewallSku=='Basic'
param vnetFirewallSubnetAddressPrefix string = ''
param vnetFirewallManagementSubnetAddressPrefix string = ''
//Ingress
param ingressApplicationGateway bool = false
param ingressApplicationGatewayPublic bool = false
param vnetAppGatewaySubnetAddressPrefix string =''
//Private Link
param privateLinks bool = false
param privateLinkSubnetAddressPrefix string = ''
param privateLinkAcrId string = ''
param privateLinkAkvId string = ''
//ACR
param acrPrivatePool bool = false
param acrAgentPoolSubnetAddressPrefix string = ''
//NatGatewayEgress
param natGateway bool = false
param natGatewayPublicIps int = 2
param natGatewayIdleTimeoutMins int = 30
//Bastion
param bastion bool =false
param bastionSubnetAddressPrefix string = ''
@description('Used by the Bastion Public IP')
param availabilityZones array = []
var bastion_subnet_name = 'AzureBastionSubnet'
var bastion_baseSubnet = {
name: bastion_subnet_name
properties: {
addressPrefix: bastionSubnetAddressPrefix
}
}
var bastion_subnet = bastion && networkSecurityGroups ? union(bastion_baseSubnet, nsgBastion.outputs.nsgSubnetObj) : bastion_baseSubnet
//NatGatewayEgress
var NatAvailabilityZone = array(first(availabilityZones))
var acrpool_subnet_name = 'acrpool-sn'
var acrpool_baseSubnet = {
name: acrpool_subnet_name
properties: {
addressPrefix: acrAgentPoolSubnetAddressPrefix
}
}
var acrpool_subnet = privateLinks && networkSecurityGroups ? union(acrpool_baseSubnet, nsgAcrPool.outputs.nsgSubnetObj) : acrpool_baseSubnet
var private_link_subnet_name = 'privatelinks-sn'
var private_link_baseSubnet = {
name: private_link_subnet_name
properties: {
addressPrefix: privateLinkSubnetAddressPrefix
privateEndpointNetworkPolicies: 'Disabled'
privateLinkServiceNetworkPolicies: 'Enabled'
}
}
var private_link_subnet = privateLinks && networkSecurityGroups ? union(private_link_baseSubnet, nsgPrivateLinks.outputs.nsgSubnetObj) : private_link_baseSubnet
var appgw_subnet_name = 'appgw-sn'
var appgw_baseSubnet = {
name: appgw_subnet_name
properties: {
addressPrefix: vnetAppGatewaySubnetAddressPrefix
}
}
var appgw_subnet = ingressApplicationGateway && networkSecurityGroups ? union(appgw_baseSubnet, nsgAppGw.outputs.nsgSubnetObj) : appgw_baseSubnet
var fw_subnet_name = 'AzureFirewallSubnet' // Required by FW
var fw_subnet = {
name: fw_subnet_name
properties: {
addressPrefix: vnetFirewallSubnetAddressPrefix
}
}
/// ---- Firewall VNET config
module calcAzFwIp './calcAzFwIp.bicep' = if (azureFirewalls) {
name: take('${deployment().name}-calcAzFwIp',64)
params: {
vnetFirewallSubnetAddressPrefix: vnetFirewallSubnetAddressPrefix
}
}
var fwmgmt_subnet_name = 'AzureFirewallManagementSubnet' // Required by FW
var fwmgmt_subnet = {
name: fwmgmt_subnet_name
properties: {
addressPrefix: vnetFirewallManagementSubnetAddressPrefix
}
}
var routeFwTableName = 'rt-afw-${resourceName}'
resource vnet_udr 'Microsoft.Network/routeTables@2023-04-01' = if (azureFirewalls) {
name: routeFwTableName
location: location
properties: {
routes: [
{
name: 'AKSNodesEgress'
properties: {
addressPrefix: '0.0.0.0/0'
nextHopType: 'VirtualAppliance'
nextHopIpAddress: azureFirewalls ? calcAzFwIp.outputs.FirewallPrivateIp : null
}
}
]
}
}
var contributorRoleId = subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')
@description('Required for kubenet networking.')
resource vnet_udr_rbac 'Microsoft.Authorization/roleAssignments@2022-04-01' = if (azureFirewalls && !empty(aksPrincipleId) && networkPluginIsKubenet) {
scope: vnet_udr
name: guid(vnet_udr.id, aksPrincipleId, contributorRoleId)
properties: {
principalId: aksPrincipleId
roleDefinitionId: contributorRoleId
principalType: 'ServicePrincipal'
}
}
var aks_subnet_name = 'aks-sn'
var aks_baseSubnet = {
name: aks_subnet_name
properties: union({
addressPrefix: vnetAksSubnetAddressPrefix
}, privateLinks ? {
privateEndpointNetworkPolicies: 'Disabled'
privateLinkServiceNetworkPolicies: 'Enabled'
} : {}, natGateway ? {
natGateway: {
id: natGw.id
}
} : {}, azureFirewalls ? {
routeTable: {
id: vnet_udr.id //resourceId('Microsoft.Network/routeTables', routeFwTableName)
}
}: {})
}
var aks_podSubnet_name = 'aks-pods-sn'
var aks_podSubnet = {
name: aks_podSubnet_name
properties: union({
addressPrefix: vnetPodAddressPrefix
}, privateLinks ? {
privateEndpointNetworkPolicies: 'Disabled'
privateLinkServiceNetworkPolicies: 'Enabled'
} : {}, natGateway ? {
natGateway: {
id: natGw.id
}
} : {}, azureFirewalls ? {
routeTable: {
id: vnet_udr.id //resourceId('Microsoft.Network/routeTables', routeFwTableName)
}
}: {})
}
var aks_subnet = networkSecurityGroups ? union(aks_baseSubnet, nsgAks.outputs.nsgSubnetObj) : aks_baseSubnet
var aks_finalPodSubnet = networkSecurityGroups ? union(aks_podSubnet, nsgAks.outputs.nsgSubnetObj) : aks_podSubnet
var subnets = union(
array(aks_subnet),
cniDynamicIpAllocation ? array(aks_finalPodSubnet) : [],
azureFirewalls ? array(fw_subnet) : [],
privateLinks ? array(private_link_subnet) : [],
acrPrivatePool ? array(acrpool_subnet) : [],
bastion ? array(bastion_subnet) : [],
ingressApplicationGateway ? array(appgw_subnet) : [],
azureFirewallsManagementSeperation ? array(fwmgmt_subnet) : []
)
output debugSubnets array = subnets
var vnetName = 'vnet-${resourceName}'
resource vnet 'Microsoft.Network/virtualNetworks@2023-04-01' = {
name: vnetName
location: location
properties: {
addressSpace: {
addressPrefixes: [
vnetAddressPrefix
]
}
subnets: subnets
}
}
output vnetId string = vnet.id
output vnetName string = vnet.name
output aksSubnetId string = resourceId('Microsoft.Network/virtualNetworks/subnets', vnet.name, aks_subnet_name)
output aksPodSubnetId string = cniDynamicIpAllocation ? resourceId('Microsoft.Network/virtualNetworks/subnets', vnet.name, aks_podSubnet_name) : ''
output fwSubnetId string = azureFirewalls ? '${vnet.id}/subnets/${fw_subnet_name}' : ''
output fwMgmtSubnetId string = azureFirewallsManagementSeperation ? '${vnet.id}/subnets/${fwmgmt_subnet_name}' : ''
output acrPoolSubnetId string = acrPrivatePool ? '${vnet.id}/subnets/${acrpool_subnet_name}' : ''
output appGwSubnetId string = resourceId('Microsoft.Network/virtualNetworks/subnets', vnet.name, appgw_subnet_name)
output privateLinkSubnetId string = resourceId('Microsoft.Network/virtualNetworks/subnets', vnet.name, private_link_subnet_name)
module aks_vnet_con 'networksubnetrbac.bicep' = if (!empty(aksPrincipleId)) {
name: take('${deployment().name}-subnetRbac',64)
params: {
servicePrincipalId: aksPrincipleId
subnetName: aks_subnet_name
vnetName: vnet.name
}
}
/* -------------------------------------------------------------------------- Private Link for ACR */
var privateLinkAcrName = 'pl-acr-${resourceName}'
resource privateLinkAcr 'Microsoft.Network/privateEndpoints@2023-04-01' = if (!empty(privateLinkAcrId)) {
name: privateLinkAcrName
location: location
properties: {
customNetworkInterfaceName: 'nic-${privateLinkAcrName}'
privateLinkServiceConnections: [
{
name: 'Acr-Connection'
properties: {
privateLinkServiceId: privateLinkAcrId
groupIds: [
'registry'
]
}
}
]
subnet: {
id: '${vnet.id}/subnets/${private_link_subnet_name}'
}
}
}
resource privateDnsAcr 'Microsoft.Network/privateDnsZones@2020-06-01' = if (!empty(privateLinkAcrId)) {
name: 'privatelink.azurecr.io'
location: 'global'
}
var privateDnsAcrLinkName = 'vnet-dnscr-${resourceName}'
resource privateDnsAcrLink 'Microsoft.Network/privateDnsZones/virtualNetworkLinks@2020-06-01' = if (!empty(privateLinkAcrId)) {
parent: privateDnsAcr
name: privateDnsAcrLinkName
location: 'global'
properties: {
registrationEnabled: false
virtualNetwork: {
id: vnet.id
}
}
}
resource privateDnsAcrZoneGroup 'Microsoft.Network/privateEndpoints/privateDnsZoneGroups@2023-04-01' = if (!empty(privateLinkAcrId)) {
parent: privateLinkAcr
name: 'default'
properties: {
privateDnsZoneConfigs: [
{
name: 'vnet-pl-acr'
properties: {
privateDnsZoneId: privateDnsAcr.id
}
}
]
}
}
/* -------------------------------------------------------------------------- Private Link for KeyVault */
var privateLinkAkvName = 'pl-akv-${resourceName}'
resource privateLinkAkv 'Microsoft.Network/privateEndpoints@2023-04-01' = if (!empty(privateLinkAkvId)) {
name: privateLinkAkvName
location: location
properties: {
customNetworkInterfaceName: 'nic-${privateLinkAkvName}'
privateLinkServiceConnections: [
{
name: 'Akv-Connection'
properties: {
privateLinkServiceId: privateLinkAkvId
groupIds: [
'vault'
]
}
}
]
subnet: {
id: '${vnet.id}/subnets/${private_link_subnet_name}'
}
}
}
resource privateDnsAkv 'Microsoft.Network/privateDnsZones@2020-06-01' = if (!empty(privateLinkAkvId)) {
name: 'privatelink.vaultcore.azure.net'
location: 'global'
}
var privateDnsAkvLinkName = 'vnet-dnscr-${resourceName}'
resource privateDnsAkvLink 'Microsoft.Network/privateDnsZones/virtualNetworkLinks@2020-06-01' = if (!empty(privateLinkAkvId)) {
parent: privateDnsAkv
name: privateDnsAkvLinkName
location: 'global'
properties: {
registrationEnabled: false
virtualNetwork: {
id: vnet.id
}
}
}
resource privateDnsAkvZoneGroup 'Microsoft.Network/privateEndpoints/privateDnsZoneGroups@2023-04-01' = if (!empty(privateLinkAkvId)) {
parent: privateLinkAkv
name: 'default'
properties: {
privateDnsZoneConfigs: [
{
name: 'vnet-pl-akv'
properties: {
privateDnsZoneId: privateDnsAkv.id
}
}
]
}
}
param bastionHostName string = 'bas-${resourceName}'
var publicIpAddressName = 'pip-${bastionHostName}'
@allowed([
'Standard'
'Basic'
])
param bastionSku string = 'Standard'
resource bastionPip 'Microsoft.Network/publicIPAddresses@2023-04-01' = if(bastion) {
name: publicIpAddressName
location: location
sku: {
name: 'Standard'
}
zones: !empty(availabilityZones) ? availabilityZones : []
properties: {
publicIPAllocationMethod: 'Static'
}
}
resource bastionHost 'Microsoft.Network/bastionHosts@2023-04-01' = if(bastion) {
name: bastionHostName
location: location
sku: {
name: bastionSku
}
properties: {
enableTunneling: true
ipConfigurations: [
{
name: 'IpConf'
properties: {
subnet: {
id: '${vnet.id}/subnets/${bastion_subnet_name}'
}
publicIPAddress: {
id: bastionPip.id
}
}
}
]
}
}
resource log 'Microsoft.OperationalInsights/workspaces@2022-10-01' existing = if(networkSecurityGroups && !empty(workspaceName)) {
name: workspaceName
scope: resourceGroup(workspaceResourceGroupName)
}
param CreateNsgFlowLogs bool = false
var flowLogStorageName = take(replace(toLower('stflow${resourceName}${uniqueString(resourceGroup().id, resourceName)}'),'-',''),24)
resource flowLogStor 'Microsoft.Storage/storageAccounts@2023-01-01' = if(CreateNsgFlowLogs && networkSecurityGroups) {
name: flowLogStorageName
kind: 'StorageV2'
sku: {
name: 'Standard_LRS'
}
location: location
properties: {
minimumTlsVersion: 'TLS1_2'
}
}
//NSG's
module nsgAks 'nsg.bicep' = if(networkSecurityGroups) {
name: take('${deployment().name}-nsgAks',64)
params: {
location: location
resourceName: '${aks_subnet_name}-${resourceName}'
workspaceId: !empty(workspaceName) ? log.properties.customerId : ''
workspaceRegion: !empty(workspaceName) ? log.location : ''
workspaceResourceId: !empty(workspaceName) ? log.id : ''
ruleInAllowInternetHttp: true
ruleInAllowInternetHttps: true
ruleInDenySsh: true
FlowLogStorageAccountId: CreateNsgFlowLogs ? flowLogStor.id : ''
}
}
module nsgAcrPool 'nsg.bicep' = if(acrPrivatePool && networkSecurityGroups) {
name: take('${deployment().name}-nsgAcrPool',64)
params: {
location: location
resourceName: '${acrpool_subnet_name}-${resourceName}'
workspaceId: !empty(workspaceName) ? log.properties.customerId : ''
workspaceRegion: !empty(workspaceName) ? log.location : ''
workspaceResourceId: !empty(workspaceName) ? log.id : ''
FlowLogStorageAccountId: CreateNsgFlowLogs ? flowLogStor.id : ''
}
dependsOn: [
nsgAks
]
}
module nsgAppGw 'nsg.bicep' = if(ingressApplicationGateway && networkSecurityGroups) {
name: take('${deployment().name}-nsgAppGw',64)
params: {
location: location
resourceName: '${appgw_subnet_name}-${resourceName}'
workspaceId: !empty(workspaceName) ? log.properties.customerId : ''
workspaceRegion: !empty(workspaceName) ? log.location : ''
workspaceResourceId: !empty(workspaceName) ? log.id : ''
ruleInAllowInternetHttp: ingressApplicationGatewayPublic
ruleInAllowInternetHttps: ingressApplicationGatewayPublic
ruleInAllowGwManagement: true
ruleInAllowAzureLoadBalancer: true
ruleInDenyInternet: true
ruleInGwManagementPort: '65200-65535'
FlowLogStorageAccountId: CreateNsgFlowLogs ? flowLogStor.id : ''
}
dependsOn: [
nsgAcrPool
]
}
module nsgBastion 'nsg.bicep' = if(bastion && networkSecurityGroups) {
name: take('${deployment().name}-nsgBastion',64)
params: {
location: location
resourceName: '${bastion_subnet_name}-${resourceName}'
workspaceId: !empty(workspaceName) ? log.properties.customerId : ''
workspaceRegion: !empty(workspaceName) ? log.location : ''
workspaceResourceId: !empty(workspaceName) ? log.id : ''
ruleInAllowBastionHostComms: true
ruleInAllowInternetHttps: true
ruleInAllowGwManagement: true
ruleInAllowAzureLoadBalancer: true
ruleOutAllowBastionComms: true
ruleInGwManagementPort: '443'
FlowLogStorageAccountId: CreateNsgFlowLogs ? flowLogStor.id : ''
}
dependsOn: [
nsgAppGw
]
}
module nsgPrivateLinks 'nsg.bicep' = if(privateLinks && networkSecurityGroups) {
name: take('${deployment().name}-nsgPrivateLinks',64)
params: {
location: location
resourceName: '${private_link_subnet_name}-${resourceName}'
workspaceId: !empty(workspaceName) ? log.properties.customerId : ''
workspaceRegion: !empty(workspaceName) ? log.location : ''
workspaceResourceId: !empty(workspaceName) ? log.id : ''
FlowLogStorageAccountId: CreateNsgFlowLogs ? flowLogStor.id : ''
}
dependsOn: [
nsgBastion
]
}
resource natGwIp 'Microsoft.Network/publicIPAddresses@2023-04-01' = [for i in range(0, natGatewayPublicIps): if(natGateway) {
name: 'pip-${natGwName}-${i+1}'
location: location
sku: {
name: 'Standard'
}
zones: !empty(availabilityZones) ? NatAvailabilityZone : []
properties: {
publicIPAllocationMethod: 'Static'
}
}]
output natGwIpArr array = [for i in range(0, natGatewayPublicIps): natGateway ? natGwIp[i].properties.ipAddress : null]
var natGwName = 'ng-${resourceName}'
resource natGw 'Microsoft.Network/natGateways@2023-04-01' = if(natGateway) {
name: natGwName
location: location
sku: {
name: 'Standard'
}
zones: !empty(availabilityZones) ? NatAvailabilityZone : []
properties: {
publicIpAddresses: [for i in range(0, natGatewayPublicIps): {
id: natGwIp[i].id
}]
idleTimeoutInMinutes: natGatewayIdleTimeoutMins
}
dependsOn: [
natGwIp
]
}