diff --git a/pkg/deploy/assets/gateway-production-parameters.json b/pkg/deploy/assets/gateway-production-parameters.json index f22951ee635..83a7f0ca464 100644 --- a/pkg/deploy/assets/gateway-production-parameters.json +++ b/pkg/deploy/assets/gateway-production-parameters.json @@ -88,6 +88,12 @@ "vmssCleanupEnabled": { "value": true }, + "vmssIpTags": { + "value": [] + }, + "vmssIpTagsDisabledRegions": { + "value": [] + }, "vmssName": { "value": "" } diff --git a/pkg/deploy/assets/gateway-production.json b/pkg/deploy/assets/gateway-production.json index dede5178049..28f3ea8cb90 100644 --- a/pkg/deploy/assets/gateway-production.json +++ b/pkg/deploy/assets/gateway-production.json @@ -94,6 +94,14 @@ "type": "bool", "defaultValue": true }, + "vmssIpTags": { + "type": "array", + "defaultValue": [] + }, + "vmssIpTagsDisabledRegions": { + "type": "array", + "defaultValue": [] + }, "vmssName": { "type": "string" } @@ -271,7 +279,10 @@ }, "primary": true, "publicIPAddressConfiguration": { - "name": "gateway-vmss-pip" + "name": "gateway-vmss-pip", + "properties": { + "ipTags": "[if(or(contains(parameters('vmssIpTagsDisabledRegions'), resourceGroup().location), equals(length(parameters('vmssIpTags')), 0)), createArray(), createArray(createObject('ipTagType', parameters('vmssIpTags')[0].type, 'tag', parameters('vmssIpTags')[0].value)))]" + } }, "loadBalancerBackendAddressPools": [ { diff --git a/pkg/deploy/assets/rp-development.json b/pkg/deploy/assets/rp-development.json index dead5690887..ee50e7ecd13 100644 --- a/pkg/deploy/assets/rp-development.json +++ b/pkg/deploy/assets/rp-development.json @@ -16,6 +16,14 @@ }, "rpServicePrincipalId": { "type": "string" + }, + "vmssIpTags": { + "type": "array", + "defaultValue": [] + }, + "vmssIpTagsDisabledRegions": { + "type": "array", + "defaultValue": [] } }, "resources": [ diff --git a/pkg/deploy/assets/rp-production-parameters.json b/pkg/deploy/assets/rp-production-parameters.json index 734573cf4ad..41335cda695 100644 --- a/pkg/deploy/assets/rp-production-parameters.json +++ b/pkg/deploy/assets/rp-production-parameters.json @@ -188,6 +188,12 @@ "vmssCleanupEnabled": { "value": true }, + "vmssIpTags": { + "value": [] + }, + "vmssIpTagsDisabledRegions": { + "value": [] + }, "vmssName": { "value": "" } diff --git a/pkg/deploy/assets/rp-production.json b/pkg/deploy/assets/rp-production.json index 587187eb6bc..01a74437be6 100644 --- a/pkg/deploy/assets/rp-production.json +++ b/pkg/deploy/assets/rp-production.json @@ -215,6 +215,14 @@ "type": "bool", "defaultValue": true }, + "vmssIpTags": { + "type": "array", + "defaultValue": [] + }, + "vmssIpTagsDisabledRegions": { + "type": "array", + "defaultValue": [] + }, "vmssName": { "type": "string" } @@ -438,7 +446,10 @@ }, "primary": true, "publicIPAddressConfiguration": { - "name": "rp-vmss-pip" + "name": "rp-vmss-pip", + "properties": { + "ipTags": "[if(or(contains(parameters('vmssIpTagsDisabledRegions'), resourceGroup().location), equals(length(parameters('vmssIpTags')), 0)), createArray(), createArray(createObject('ipTagType', parameters('vmssIpTags')[0].type, 'tag', parameters('vmssIpTags')[0].value)))]" + } }, "loadBalancerBackendAddressPools": [ { diff --git a/pkg/deploy/config.go b/pkg/deploy/config.go index 546d130a9a9..109fc7c72f9 100644 --- a/pkg/deploy/config.go +++ b/pkg/deploy/config.go @@ -101,6 +101,8 @@ type Configuration struct { SubscriptionResourceGroupLocation *string `json:"subscriptionResourceGroupLocation,omitempty" value:"required"` VMSize *string `json:"vmSize,omitempty" value:"required"` VMSSCleanupEnabled *bool `json:"vmssCleanupEnabled,omitempty"` + VmssIpTags []IPTag `json:"vmssIpTags,omitempty"` + VmssIpTagsDisabledRegions []string `json:"vmssIpTagsDisabledRegions,omitempty"` OIDCStorageAccountName *string `json:"oidcStorageAccountName,omitempty" value:"required"` OtelAuditQueueSize *string `json:"otelAuditQueueSize,omitempty" value:"required"` MsiRpEndpoint *string `json:"msiRpEndpoint,omitempty" value:"required"` @@ -118,6 +120,12 @@ type CosmosDBConfiguration struct { GatewayProvisionedThroughput int `json:"gatewayProvisionedThroughput,omitempty"` } +// IPTag represents an IP tag configuration for Azure resources +type IPTag struct { + Type string `json:"type,omitempty"` + Value string `json:"value,omitempty"` +} + // GetConfig return RP configuration from the file func GetConfig(path, location string) (*RPConfig, error) { data, err := os.ReadFile(path) diff --git a/pkg/deploy/deploy_gateway.go b/pkg/deploy/deploy_gateway.go index 6bb19c9a8e7..9e6944e47c0 100644 --- a/pkg/deploy/deploy_gateway.go +++ b/pkg/deploy/deploy_gateway.go @@ -55,6 +55,12 @@ func (d *deployer) DeployGateway(ctx context.Context) error { parameters.Parameters["vmssName"] = &arm.ParametersParameter{ Value: d.version, } + parameters.Parameters["vmssIpTags"] = &arm.ParametersParameter{ + Value: d.config.Configuration.VmssIpTags, + } + parameters.Parameters["vmssIpTagsDisabledRegions"] = &arm.ParametersParameter{ + Value: d.config.Configuration.VmssIpTagsDisabledRegions, + } parameters.Parameters["azureCloudName"] = &arm.ParametersParameter{ Value: d.env.Environment().ActualCloudName, } diff --git a/pkg/deploy/deploy_rp.go b/pkg/deploy/deploy_rp.go index 1bd49c85f24..02c46c57ef0 100644 --- a/pkg/deploy/deploy_rp.go +++ b/pkg/deploy/deploy_rp.go @@ -76,6 +76,12 @@ func (d *deployer) DeployRP(ctx context.Context) error { parameters.Parameters["vmssName"] = &arm.ParametersParameter{ Value: d.version, } + parameters.Parameters["vmssIpTags"] = &arm.ParametersParameter{ + Value: d.config.Configuration.VmssIpTags, + } + parameters.Parameters["vmssIpTagsDisabledRegions"] = &arm.ParametersParameter{ + Value: d.config.Configuration.VmssIpTagsDisabledRegions, + } parameters.Parameters["keyvaultDNSSuffix"] = &arm.ParametersParameter{ Value: d.env.Environment().KeyVaultDNSSuffix, } diff --git a/pkg/deploy/generator/resources_gateway.go b/pkg/deploy/generator/resources_gateway.go index 5a4716e7175..402d1d8e619 100644 --- a/pkg/deploy/generator/resources_gateway.go +++ b/pkg/deploy/generator/resources_gateway.go @@ -335,6 +335,9 @@ func (g *generator) gatewayVMSS() *arm.Resource { Primary: pointerutils.ToPtr(true), PublicIPAddressConfiguration: &mgmtcompute.VirtualMachineScaleSetPublicIPAddressConfiguration{ Name: pointerutils.ToPtr("gateway-vmss-pip"), + VirtualMachineScaleSetPublicIPAddressConfigurationProperties: &mgmtcompute.VirtualMachineScaleSetPublicIPAddressConfigurationProperties{ + IPTags: &[]mgmtcompute.VirtualMachineScaleSetIPTag{}, + }, }, LoadBalancerBackendAddressPools: &[]mgmtcompute.SubResource{ { diff --git a/pkg/deploy/generator/resources_rp.go b/pkg/deploy/generator/resources_rp.go index eac27e71ba9..12f924f0567 100644 --- a/pkg/deploy/generator/resources_rp.go +++ b/pkg/deploy/generator/resources_rp.go @@ -556,6 +556,9 @@ func (g *generator) rpVMSS() *arm.Resource { Primary: pointerutils.ToPtr(true), PublicIPAddressConfiguration: &mgmtcompute.VirtualMachineScaleSetPublicIPAddressConfiguration{ Name: pointerutils.ToPtr("rp-vmss-pip"), + VirtualMachineScaleSetPublicIPAddressConfigurationProperties: &mgmtcompute.VirtualMachineScaleSetPublicIPAddressConfigurationProperties{ + IPTags: &[]mgmtcompute.VirtualMachineScaleSetIPTag{}, + }, }, LoadBalancerBackendAddressPools: &[]mgmtcompute.SubResource{ { diff --git a/pkg/deploy/generator/templates.go b/pkg/deploy/generator/templates.go index 30d68926ef9..36011558655 100644 --- a/pkg/deploy/generator/templates.go +++ b/pkg/deploy/generator/templates.go @@ -53,6 +53,8 @@ func (g *generator) templateFixup(t *arm.Template) ([]byte, error) { b = bytes.ReplaceAll(b, []byte(`"throughput": `+strconv.Itoa(cosmosDbGatewayProvisionedThroughputHack)), []byte(`"throughput": "[parameters('cosmosDB').gatewayProvisionedThroughput]"`)) // pickZones doesn't work for regions that don't have zones. We have created param nonZonalRegions in both rp and gateway and set default values to include all those regions. It cannot be passed in-line to contains function, has to be created as an array in a parameter :( b = bytes.ReplaceAll(b, []byte(`"zones": []`), []byte(`"zones": "[if(contains(parameters('nonZonalRegions'),toLower(replace(resourceGroup().location, ' ', ''))),'',pickZones('Microsoft.Network', 'publicIPAddresses', resourceGroup().location, 3))]"`)) + // IP tags conditional logic: if region is disabled OR no IP tags configured, use empty array, otherwise use configured tags + b = bytes.ReplaceAll(b, []byte(`"ipTags": []`), []byte(`"ipTags": "[if(or(contains(parameters('vmssIpTagsDisabledRegions'), resourceGroup().location), equals(length(parameters('vmssIpTags')), 0)), createArray(), createArray(createObject('ipTagType', parameters('vmssIpTags')[0].type, 'tag', parameters('vmssIpTags')[0].value)))]"`)) b = bytes.ReplaceAll(b, []byte(`"routes": []`), []byte(`"routes": "[parameters('routes')]"`)) if g.production { diff --git a/pkg/deploy/generator/templates_gateway.go b/pkg/deploy/generator/templates_gateway.go index 1835df4c70b..d734ad42a98 100644 --- a/pkg/deploy/generator/templates_gateway.go +++ b/pkg/deploy/generator/templates_gateway.go @@ -34,6 +34,8 @@ func (g *generator) gatewayTemplate() *arm.Template { "gatewayServicePrincipalId", "gatewayVmSize", "gatewayVmssCapacity", + "vmssIpTags", + "vmssIpTagsDisabledRegions", "keyvaultDNSSuffix", "keyvaultPrefix", "mdmFrontendUrl", @@ -61,6 +63,12 @@ func (g *generator) gatewayTemplate() *arm.Template { case "gatewayVmssCapacity": p.Type = "int" p.DefaultValue = 3 + case "vmssIpTags": + p.Type = "array" + p.DefaultValue = []interface{}{} + case "vmssIpTagsDisabledRegions": + p.Type = "array" + p.DefaultValue = []string{} case "vmssCleanupEnabled": p.Type = "bool" p.DefaultValue = true diff --git a/pkg/deploy/generator/templates_rp.go b/pkg/deploy/generator/templates_rp.go index 84413178fc2..6b83296f157 100644 --- a/pkg/deploy/generator/templates_rp.go +++ b/pkg/deploy/generator/templates_rp.go @@ -30,6 +30,8 @@ func (g *generator) rpTemplate() *arm.Template { "fpServicePrincipalId", "rpServicePrincipalId", "globalDevopsServicePrincipalId", + "vmssIpTags", + "vmssIpTagsDisabledRegions", } if g.production { params = append(params, @@ -124,6 +126,12 @@ func (g *generator) rpTemplate() *arm.Template { p.Type = "array" case "miseValidAppIDs": p.Type = "array" + case "vmssIpTags": + p.Type = "array" + p.DefaultValue = []interface{}{} + case "vmssIpTagsDisabledRegions": + p.Type = "array" + p.DefaultValue = []string{} case "nonZonalRegions": p.Type = "array" p.DefaultValue = []string{ @@ -156,6 +164,7 @@ func (g *generator) rpTemplate() *arm.Template { if g.production { t.Variables = map[string]interface{}{ + "rpCosmoDbVirtualNetworkRules": &[]mgmtdocumentdb.VirtualNetworkRule{ { ID: pointerutils.ToPtr("[resourceId('Microsoft.Network/virtualNetworks/subnets', 'rp-vnet', 'rp-subnet')]"),