Skip to content

Commit 87f6ad6

Browse files
committed
refactor and improve PrivateEndpointConnectionApproval handling
1 parent 27081c7 commit 87f6ad6

File tree

10 files changed

+115
-92
lines changed

10 files changed

+115
-92
lines changed

Diff for: lib/network.bicep

+9-2
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,13 @@ Private Endpoint connection names from own and other tenants with either manual
6868
@export()
6969
var privateEndpointConnectionNames = _networkVar.privateEndpointConnectionNames
7070

71+
@description('''
72+
Lookup array to check if the connection is still pending.
73+
Some private endpoint connections do not like to be approved twice. This depends on the parent resource type.
74+
''')
75+
@export()
76+
var privateEndpointConnectionNamesPendingLookup = _networkVar.privateEndpointConnectionNamesPendingLookup
77+
7178
/* ----------------------------------------
7279
7380
😎 Bicep# - Public types 😎
@@ -183,9 +190,9 @@ func buildPrivateEndpoint(targetResourceName string, targetResourceId string, gr
183190
Build a private endpoint connection approval.
184191
''')
185192
@export()
186-
func buildBuildPrivateEndpointConnectionApproval(connectionName string, additionalInfo string) _resourceType.resourceFormat => {
193+
func buildPrivateEndpointConnectionApproval(connectionName string, additionalInfo string) _resourceType.resourceFormat => {
187194
name: connectionName
188-
properties: _networkFunction.buildBuildPrivateEndpointConnectionApprovalProperties(connectionName, additionalInfo)
195+
properties: _networkFunction.buildPrivateEndpointConnectionApprovalProperties(connectionName, additionalInfo)
189196
}
190197

191198
@description('''

Diff for: lib/private/functions/network.bicep

+2-3
Original file line numberDiff line numberDiff line change
@@ -90,13 +90,12 @@ func buildNsgRuleProperties(
9090

9191
@description('''
9292
Build Private Endpoint Connection Approval properties
93-
94-
Because the approval properties are the same for each resource, we can just pick one resource and get the privateEndpointConnectionProperties for that.
9593
''')
9694
@export()
97-
func buildBuildPrivateEndpointConnectionApprovalProperties(connectionName string, additionalInfo string) _networkType.privateEndpointConnectionProperties => {
95+
func buildPrivateEndpointConnectionApprovalProperties(connectionName string, additionalInfo string) _networkType.privateEndpointConnectionApprovalProperties => {
9896
privateLinkServiceConnectionState: {
9997
status: 'Approved'
10098
description: 'Approved by pipeline. For Resource ${split(connectionName, '.')[0]}. Additional info: ${additionalInfo}.'
99+
actionRequired: 'None'
101100
}
102101
}

Diff for: lib/private/types/network.bicep

+7-1
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,13 @@ type subnet = resource<'Microsoft.Network/virtualNetworks@2023-09-01'>.propertie
3636
type vnetProperties = resource<'Microsoft.Network/virtualNetworks@2023-09-01'>.properties
3737

3838
@export()
39-
type privateEndpointConnectionProperties = resource<'Microsoft.Network/applicationGateways/privateEndpointConnections@2023-09-01'>.properties
39+
type privateEndpointConnectionApprovalProperties = {
40+
privateLinkServiceConnectionState: {
41+
status: string
42+
description: string
43+
actionRequired: string
44+
}
45+
}
4046

4147
@export()
4248
type serviceTagRegional =

Diff for: lib/private/variables/generated/peConnectionsAutoAppr.json renamed to lib/private/variables/generated/peConApproved.json

+3
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,8 @@
22
"peSthellosharpdev001Blob": "sthellosharpdev001.af5357a5-c192-4999-83a7-2ab87e0f2a36",
33
"peSthellosharpdev001Dfs": "sthellosharpdev001.22c40a51-bd4e-4895-8687-b749ce63c434",
44
"peSthellosharpdev001Queue": "sthellosharpdev001.c6cfcd4c-26b2-455d-b7c5-c2875e26d352",
5+
"synGuanchen_MpeMountainArchive001": "sthellosharpdev001.b688df18-92cf-4608-b83f-a202c14d20f2",
6+
"synGuanchen_MpeMountainArchive002": "sthellosharpdev001.4267eaf9-71fd-4dd5-8908-bf5e47908ec8",
7+
"synGuanchen_MpeMountainArchive003": "sthellosharpdev001.05a5c9b5-e15a-4922-9fc3-029811e0e1a1",
58
"synGuanchen_SynapseWsSqlSynGuanchen": "syn-guanchen.synapse-ws-sql--syn-guanchen-b177bad0-434d-4a3f-a1b4-75697f90cfaf"
69
}

Diff for: lib/private/variables/generated/peConPending.json

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{}
+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
[]

Diff for: lib/private/variables/generated/peConnectionsManual.json

-4
This file was deleted.

Diff for: lib/private/variables/network.bicep

+70-70
Original file line numberDiff line numberDiff line change
@@ -142,75 +142,69 @@ var nsgRuleServiceTagsInboundAndOutbound = {
142142
var nsgRuleServiceTagsRegional = loadJsonContent('./generated/serviceTagsRegional.json')
143143

144144
@export()
145-
var nsgRuleServiceTagsInbound = union(
146-
nsgRuleServiceTagsInboundAndOutbound,
147-
{
148-
dataConnectorsForMicrosoftScurityProducts: 'Scuba'
149-
azureVPNGatewayAndApplicationGateway: 'GatewayManager'
150-
actionGroup: 'ActionGroup'
151-
apiManagement: 'ApiManagement'
152-
applicationInsightsAvailability: 'ApplicationInsightsAvailability'
153-
azureAISearch: 'AzureCognitiveSearch'
154-
azureDataExplorerManagement: 'AzureDataExplorerManagement'
155-
azureDevOps: 'AzureDevOps'
156-
azureDigitalTwins: 'AzureDigitalTwins'
157-
azureLoadTestingInstanceManagement: 'AzureLoadTestingInstanceManagement'
158-
azureMachineLearningInference: 'AzureMachineLearningInference'
159-
microsoftSentinel: 'AzureSentinel'
160-
azureTrafficManager: 'AzureTrafficManager'
161-
azureHDInsight: 'HDInsight'
162-
logicAppsManagement: 'LogicAppsManagement'
163-
office365ManagementActivityAPIWebhook: 'M365ManagementActivityApiWebhook'
164-
powerPlatformextensionExecution: 'PowerPlatformPlex'
165-
serialConsoleService: 'SerialConsole'
166-
}
167-
)
145+
var nsgRuleServiceTagsInbound = union(nsgRuleServiceTagsInboundAndOutbound, {
146+
dataConnectorsForMicrosoftScurityProducts: 'Scuba'
147+
azureVPNGatewayAndApplicationGateway: 'GatewayManager'
148+
actionGroup: 'ActionGroup'
149+
apiManagement: 'ApiManagement'
150+
applicationInsightsAvailability: 'ApplicationInsightsAvailability'
151+
azureAISearch: 'AzureCognitiveSearch'
152+
azureDataExplorerManagement: 'AzureDataExplorerManagement'
153+
azureDevOps: 'AzureDevOps'
154+
azureDigitalTwins: 'AzureDigitalTwins'
155+
azureLoadTestingInstanceManagement: 'AzureLoadTestingInstanceManagement'
156+
azureMachineLearningInference: 'AzureMachineLearningInference'
157+
microsoftSentinel: 'AzureSentinel'
158+
azureTrafficManager: 'AzureTrafficManager'
159+
azureHDInsight: 'HDInsight'
160+
logicAppsManagement: 'LogicAppsManagement'
161+
office365ManagementActivityAPIWebhook: 'M365ManagementActivityApiWebhook'
162+
powerPlatformextensionExecution: 'PowerPlatformPlex'
163+
serialConsoleService: 'SerialConsole'
164+
})
168165

169166
@export()
170-
var nsgRuleServiceTagsOutbound = union(
171-
nsgRuleServiceTagsInboundAndOutbound,
172-
{
173-
appConfiguration: 'AppConfiguration'
174-
azureAppService: 'AppService'
175-
microsoftEntraID: 'AzureActiveDirectory'
176-
azureAdvancedThreatProtection: 'AzureAdvancedThreatProtection'
177-
azureArcInfrastructure: 'AzureArcInfrastructure'
178-
azureAttestation: 'AzureAttestation'
179-
azureBackup: 'AzureBackup'
180-
azureContainerRegistry: 'AzureContainerRegistry'
181-
azureCosmosDB: 'AzureCosmosDB'
182-
azureDataLakeStorageGen1: 'AzureDataLake'
183-
azureDevSpaces: 'AzureDevSpaces'
184-
azureInformationProtection: 'AzureInformationProtection'
185-
azureIoTHub: 'AzureIoTHub'
186-
azureKeyVault: 'AzureKeyVault'
187-
azureManagedGrafana: 'AzureManagedGrafana'
188-
azureMonitor: 'AzureMonitor'
189-
azureOpenDatasets: 'AzureOpenDatasets'
190-
azureResourceManager: 'AzureResourceManager'
191-
azureSignalR: 'AzureSignalR'
192-
azureSiteRecovery: 'AzureSiteRecovery'
193-
azureSpringApps: 'AzureSpringCloud'
194-
azureStackBridgeServices: 'AzureStack'
195-
azureUpdateDelivery: 'AzureUpdateDelivery'
196-
azureDataFactoryManagement: 'DataFactoryManagement'
197-
azureEventHubs: 'EventHub'
198-
azureAutomationAndGuestConfiguration: 'GuestAndHybridManagement'
199-
office365ManagementActivityAPI: 'M365ManagementActivityApi'
200-
azureMicrosoftFluidRelayServer: 'MicrosoftAzureFluidRelay'
201-
microsoftDefenderForCloudApps: 'MicrosoftCloudAppSecurity'
202-
microsoftContainerRegistry: 'MicrosoftContainerRegistry'
203-
azureServiceBus: 'ServiceBus'
204-
azureSql: 'Sql'
205-
azureStorage: 'Storage'
206-
storageMover: 'StorageMover'
207-
windowsAdminCenter: 'WindowsAdminCenter'
208-
azurePlatformDNS: 'AzurePlatformDNS'
209-
azurePlatformAzureInstanceMetadataServiceIMDS: 'AzurePlatformIMDS'
210-
azurePlatformlicensingOrKeyManagementServiceLKM: 'AzurePlatformLKM'
211-
microsoftPurviewPolicyDistribution: 'MicrosoftPurviewPolicyDistribution'
212-
}
213-
)
167+
var nsgRuleServiceTagsOutbound = union(nsgRuleServiceTagsInboundAndOutbound, {
168+
appConfiguration: 'AppConfiguration'
169+
azureAppService: 'AppService'
170+
microsoftEntraID: 'AzureActiveDirectory'
171+
azureAdvancedThreatProtection: 'AzureAdvancedThreatProtection'
172+
azureArcInfrastructure: 'AzureArcInfrastructure'
173+
azureAttestation: 'AzureAttestation'
174+
azureBackup: 'AzureBackup'
175+
azureContainerRegistry: 'AzureContainerRegistry'
176+
azureCosmosDB: 'AzureCosmosDB'
177+
azureDataLakeStorageGen1: 'AzureDataLake'
178+
azureDevSpaces: 'AzureDevSpaces'
179+
azureInformationProtection: 'AzureInformationProtection'
180+
azureIoTHub: 'AzureIoTHub'
181+
azureKeyVault: 'AzureKeyVault'
182+
azureManagedGrafana: 'AzureManagedGrafana'
183+
azureMonitor: 'AzureMonitor'
184+
azureOpenDatasets: 'AzureOpenDatasets'
185+
azureResourceManager: 'AzureResourceManager'
186+
azureSignalR: 'AzureSignalR'
187+
azureSiteRecovery: 'AzureSiteRecovery'
188+
azureSpringApps: 'AzureSpringCloud'
189+
azureStackBridgeServices: 'AzureStack'
190+
azureUpdateDelivery: 'AzureUpdateDelivery'
191+
azureDataFactoryManagement: 'DataFactoryManagement'
192+
azureEventHubs: 'EventHub'
193+
azureAutomationAndGuestConfiguration: 'GuestAndHybridManagement'
194+
office365ManagementActivityAPI: 'M365ManagementActivityApi'
195+
azureMicrosoftFluidRelayServer: 'MicrosoftAzureFluidRelay'
196+
microsoftDefenderForCloudApps: 'MicrosoftCloudAppSecurity'
197+
microsoftContainerRegistry: 'MicrosoftContainerRegistry'
198+
azureServiceBus: 'ServiceBus'
199+
azureSql: 'Sql'
200+
azureStorage: 'Storage'
201+
storageMover: 'StorageMover'
202+
windowsAdminCenter: 'WindowsAdminCenter'
203+
azurePlatformDNS: 'AzurePlatformDNS'
204+
azurePlatformAzureInstanceMetadataServiceIMDS: 'AzurePlatformIMDS'
205+
azurePlatformlicensingOrKeyManagementServiceLKM: 'AzurePlatformLKM'
206+
microsoftPurviewPolicyDistribution: 'MicrosoftPurviewPolicyDistribution'
207+
})
214208

215209
@export()
216210
var nsgRuleDestinationServices = {
@@ -251,9 +245,15 @@ var nsgRuleDestinationServices = {
251245
dynamicPorts: { portRange: '49152-65535', protocol: 'TCP' }
252246
}
253247

254-
var privateEndpointConnectionNamesAutoApproved = loadJsonContent('./generated/peConnectionsAutoAppr.json')
248+
var privateEndpointConnectionNamesApproved = loadJsonContent('./generated/peConApproved.json')
255249

256-
var privateEndpointConnectionNamesManual = loadJsonContent('./generated/peConnectionsManual.json')
250+
var privateEndpointConnectionNamesPending = loadJsonContent('./generated/peConPending.json')
251+
252+
@export()
253+
var privateEndpointConnectionNames = union(
254+
privateEndpointConnectionNamesApproved,
255+
privateEndpointConnectionNamesPending
256+
)
257257

258258
@export()
259-
var privateEndpointConnectionNames = union(privateEndpointConnectionNamesAutoApproved, privateEndpointConnectionNamesManual)
259+
var privateEndpointConnectionNamesPendingLookup = loadJsonContent('./generated/peConPendingLookup.json')

Diff for: samples/modules/storage-account.bicep

+8-3
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,9 @@ param groupIds array = [
3636
]
3737

3838
param privateEndpointConnectionApprovalNames array = [
39-
sharpNetwork.privateEndpointConnectionNames.synGuanchen_MpeMountainArchive
39+
sharpNetwork.privateEndpointConnectionNames.synGuanchen_MpeMountainArchive001
40+
sharpNetwork.privateEndpointConnectionNames.synGuanchen_MpeMountainArchive002
41+
sharpNetwork.privateEndpointConnectionNames.synGuanchen_MpeMountainArchive003
4042
]
4143

4244
@description('Id of the subnet to attach the private endpoints to')
@@ -46,7 +48,7 @@ var sharpPrivateEndpoints = [
4648
for groupId in groupIds: sharpNetwork.buildPrivateEndpoint(sa.name, sa.id, groupId, subnetId)
4749
]
4850
var sharpPrivateEndpointConnectionApprovals = [
49-
for privateEndpointConnectionApprovalName in privateEndpointConnectionApprovalNames: sharpNetwork.buildBuildPrivateEndpointConnectionApproval(
51+
for privateEndpointConnectionApprovalName in privateEndpointConnectionApprovalNames: sharpNetwork.buildPrivateEndpointConnectionApproval(
5052
privateEndpointConnectionApprovalName,
5153
5254
)
@@ -115,7 +117,10 @@ resource privateEndpoints 'Microsoft.Network/privateEndpoints@2023-09-01' = [
115117
]
116118

117119
resource privateEndpointConnectionApprovals 'Microsoft.Storage/storageAccounts/privateEndpointConnections@2023-04-01' = [
118-
for sharpPrivateEndpointConnectionApproval in sharpPrivateEndpointConnectionApprovals: {
120+
for sharpPrivateEndpointConnectionApproval in sharpPrivateEndpointConnectionApprovals: if (contains(
121+
sharpNetwork.privateEndpointConnectionNamesPendingLookup,
122+
sharpPrivateEndpointConnectionApproval.name
123+
)) {
119124
parent: sa
120125
name: sharpPrivateEndpointConnectionApproval.name
121126
properties: sharpPrivateEndpointConnectionApproval.properties

Diff for: scripts/New-PeConnectionDict.ps1

+14-9
Original file line numberDiff line numberDiff line change
@@ -13,17 +13,18 @@ resources
1313
| where array_length(properties.privateEndpointConnections) > 0
1414
| mv-expand properties.privateEndpointConnections
1515
| extend id2 = properties_privateEndpointConnections.id
16-
| mv-expand properties_privateEndpointConnections.properties.privateLinkServiceConnectionState.description
16+
| mv-expand properties_privateEndpointConnections.properties.privateLinkServiceConnectionState.status
1717
| mv-expand properties_privateEndpointConnections.properties.privateEndpoint.id
18-
| extend state = properties_privateEndpointConnections_properties_privateLinkServiceConnectionState_description
18+
| extend state = properties_privateEndpointConnections_properties_privateLinkServiceConnectionState_status
1919
| extend peName = split(properties_privateEndpointConnections_properties_privateEndpoint_id, '`/')[-1]
2020
| extend name2 = split(id2, '`/')
2121
| extend connectionName = name2[-1]
2222
| project name, connectionName, state, peName
2323
"@
2424

25-
$connectionNamesAutoApproved = [System.Collections.SortedList]::new()
26-
$connectionNamesManual = [System.Collections.SortedList]::new()
25+
$connectionNamesApproved = [System.Collections.SortedList]::new()
26+
$connectionNamesPending = [System.Collections.SortedList]::new()
27+
$connectionNamesPendingLookup = [System.Collections.Generic.SortedSet[string]]::new()
2728

2829
foreach ($privateEndpoint in $privateEndpoints) {
2930

@@ -32,13 +33,17 @@ foreach ($privateEndpoint in $privateEndpoints) {
3233
$First, $Rest = $privateEndpoint.peName -Replace '[^0-9A-Z.]', ' ' -Split ' ', 2
3334
$nameLowerCamelCase = $First.Tolower() + (Get-Culture).TextInfo.ToTitleCase($Rest) -Replace ' ' -Replace '\.', '_'
3435

35-
if ($privateEndpoint.state -eq "Auto-Approved") {
36-
$connectionNamesAutoApproved.Add($nameLowerCamelCase, $privateEndpoint.connectionName )
36+
if ($privateEndpoint.state -eq "Approved") {
37+
$connectionNamesApproved.Add($nameLowerCamelCase, $privateEndpoint.connectionName )
3738
}
3839
else {
39-
$connectionNamesManual.Add($nameLowerCamelCase, $privateEndpoint.connectionName )
40+
$connectionNamesPending.Add($nameLowerCamelCase, $privateEndpoint.connectionName )
41+
$connectionNamesPendingLookup.Add($privateEndpoint.connectionName) | Out-Null
4042
}
4143
}
4244

43-
$connectionNamesAutoApproved | ConvertTo-Json | Out-File "./lib/private/variables/generated/peConnectionsAutoAppr.json"
44-
$connectionNamesManual | ConvertTo-Json | Out-File "./lib/private/variables/generated/peConnectionsManual.json"
45+
$connectionNamesApproved | ConvertTo-Json | Out-File "./lib/private/variables/generated/peConApproved.json"
46+
$connectionNamesPending | ConvertTo-Json | Out-File "./lib/private/variables/generated/peConPending.json"
47+
48+
# Don't use a pipeline operator or else it does not handle empty arrays nicely
49+
ConvertTo-Json -InputObject $connectionNamesPendingLookup | Out-File "./lib/private/variables/generated/peConPendingLookup.json"

0 commit comments

Comments
 (0)