Skip to content

Commit 543e678

Browse files
tas50claude
andcommitted
⭐ azure: roll out private endpoint connections, identity, and provenance
Expand security context across several Azure resources with three verified additions. Each candidate was checked against its vendored SDK first, so resources whose SDK cannot populate a field were left alone. Private endpoint connections — add a typed `privateEndpointConnections() []azure.subscription.privateEndpointConnection` accessor to resources that lacked one: - Service Bus namespace, Event Hubs namespace, IoT Hub, Cognitive Services account, App Configuration store, SignalR, Web PubSub, and Synapse workspace read the connections already embedded in the parent's properties (no extra API call). - AKS cluster fetches them through the dedicated PrivateEndpointConnectionsClient, tolerating 404/403 as "none". - API Management exposes the full typed list; its `privateEndpointConnectionCount` is deprecated in favor of it. A shared helper (`private_endpoint_connections.go`) normalizes any SDK connection type through a dict, since they all share the same JSON shape, and gives the nested connection-state a derived id to avoid cache collisions. Managed identity — IoT Hub gains identityType, principalId, tenantId, and userAssignedIdentities; API Management gains principalId, tenantId, and userAssignedIdentities. Customer-managed-key encryption was evaluated and is not exposed by either SDK, so it was not modeled. Provenance — Purview account gains `systemMetadata()`, adding the ARM last-modified provenance its bespoke createdAt/createdBy fields lack. No new provider permissions. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 3be57ed commit 543e678

14 files changed

Lines changed: 756 additions & 60 deletions

providers/azure/resources/aks.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -561,6 +561,38 @@ func (a *mqlAzureSubscriptionAksServiceClusterIdentityBinding) id() (string, err
561561
return a.Id.Data, nil
562562
}
563563

564+
func (a *mqlAzureSubscriptionAksServiceCluster) privateEndpointConnections() ([]any, error) {
565+
conn := a.MqlRuntime.Connection.(*connection.AzureConnection)
566+
ctx := context.Background()
567+
token := conn.Token()
568+
569+
resourceID, err := ParseResourceID(a.Id.Data)
570+
if err != nil {
571+
return nil, err
572+
}
573+
574+
client, err := clusters.NewPrivateEndpointConnectionsClient(resourceID.SubscriptionID, token, &arm.ClientOptions{
575+
ClientOptions: conn.ClientOptions(),
576+
})
577+
if err != nil {
578+
return nil, err
579+
}
580+
581+
resp, err := client.List(ctx, resourceID.ResourceGroup, a.Name.Data, nil)
582+
if err != nil {
583+
// Private endpoint connections are absent on clusters without private
584+
// networking, and the endpoint returns 403 when the caller lacks
585+
// access. Treat both as "no connections" rather than failing.
586+
var respErr *azcore.ResponseError
587+
if errors.As(err, &respErr) && (respErr.StatusCode == http.StatusNotFound || respErr.StatusCode == http.StatusForbidden) {
588+
return []any{}, nil
589+
}
590+
return nil, err
591+
}
592+
593+
return azurePrivateEndpointConnectionsToMql(a.MqlRuntime, resp.Value)
594+
}
595+
564596
func (a *mqlAzureSubscriptionAksServiceCluster) identityBindings() ([]any, error) {
565597
conn := a.MqlRuntime.Connection.(*connection.AzureConnection)
566598
ctx := context.Background()

providers/azure/resources/apimanagement.go

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,18 @@ import (
2323
)
2424

2525
type mqlAzureSubscriptionApiManagementServiceServiceInternal struct {
26-
cachePublicIpAddressId string
27-
cacheSystemData any
26+
cachePublicIpAddressId string
27+
cacheSystemData any
28+
cacheUserAssignedIdentityIds []string
29+
cachePrivateEndpointConnections []*apim.RemotePrivateEndpointConnectionWrapper
30+
}
31+
32+
func (a *mqlAzureSubscriptionApiManagementServiceService) userAssignedIdentities() ([]any, error) {
33+
return resolveUserAssignedIdentities(a.MqlRuntime, a.cacheUserAssignedIdentityIds)
34+
}
35+
36+
func (a *mqlAzureSubscriptionApiManagementServiceService) privateEndpointConnections() ([]any, error) {
37+
return azurePrivateEndpointConnectionsToMql(a.MqlRuntime, a.cachePrivateEndpointConnections)
2838
}
2939

3040
// API Management encodes its gateway TLS protocol and cipher policy as
@@ -112,8 +122,15 @@ func (a *mqlAzureSubscriptionApiManagementService) services() ([]any, error) {
112122
}
113123

114124
var identityType string
115-
if svc.Identity != nil && svc.Identity.Type != nil {
116-
identityType = string(*svc.Identity.Type)
125+
var identityPrincipalId, identityTenantId *string
126+
var userAssignedIdentityIds []string
127+
if svc.Identity != nil {
128+
if svc.Identity.Type != nil {
129+
identityType = string(*svc.Identity.Type)
130+
}
131+
identityPrincipalId = svc.Identity.PrincipalID
132+
identityTenantId = svc.Identity.TenantID
133+
userAssignedIdentityIds = sortedUserAssignedIdentityIDs(svc.Identity.UserAssignedIdentities)
117134
}
118135

119136
var (
@@ -285,6 +302,8 @@ func (a *mqlAzureSubscriptionApiManagementService) services() ([]any, error) {
285302
"tripleDesEnabled": llx.BoolDataPtr(tripleDesEnabled),
286303
"http2Enabled": llx.BoolDataPtr(http2Enabled),
287304
"identityType": llx.StringData(identityType),
305+
"principalId": llx.StringDataPtr(identityPrincipalId),
306+
"tenantId": llx.StringDataPtr(identityTenantId),
288307
"publicIpAddresses": llx.ArrayData(publicIpAddresses, types.String),
289308
"privateIpAddresses": llx.ArrayData(privateIpAddresses, types.String),
290309
"outboundPublicIpAddresses": llx.ArrayData(outboundPublicIpAddresses, types.String),
@@ -297,6 +316,10 @@ func (a *mqlAzureSubscriptionApiManagementService) services() ([]any, error) {
297316
}
298317
svcRes := mqlSvc.(*mqlAzureSubscriptionApiManagementServiceService)
299318
svcRes.cachePublicIpAddressId = publicIpAddressId
319+
svcRes.cacheUserAssignedIdentityIds = userAssignedIdentityIds
320+
if p := svc.Properties; p != nil {
321+
svcRes.cachePrivateEndpointConnections = p.PrivateEndpointConnections
322+
}
300323
sysData, err := convert.JsonToDict(svc.SystemData)
301324
if err != nil {
302325
return nil, err

providers/azure/resources/appconfiguration.go

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,9 +163,17 @@ func configurationStoreToMql(runtime *plugin.Runtime, store *armappconfiguration
163163
return nil, err
164164
}
165165
mqlStore.cacheSystemData = sysData
166+
if store.Properties != nil {
167+
mqlStore.cachePrivateEndpointConnections = store.Properties.PrivateEndpointConnections
168+
}
166169
return mqlStore, nil
167170
}
168171

169172
type mqlAzureSubscriptionAppConfigurationServiceConfigurationStoreInternal struct {
170-
cacheSystemData any
173+
cacheSystemData any
174+
cachePrivateEndpointConnections []*armappconfiguration.PrivateEndpointConnectionReference
175+
}
176+
177+
func (a *mqlAzureSubscriptionAppConfigurationServiceConfigurationStore) privateEndpointConnections() ([]any, error) {
178+
return azurePrivateEndpointConnectionsToMql(a.MqlRuntime, a.cachePrivateEndpointConnections)
171179
}

providers/azure/resources/azure.lr

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7816,6 +7816,8 @@ azure.subscription.aksService.cluster @defaults("name location kubernetesVersion
78167816
kubeletIdentity() azure.subscription.managedIdentity
78177817
// Client ID of the legacy service principal used by the cluster; empty when the cluster uses a managed identity
78187818
servicePrincipalClientId string
7819+
// Private endpoint connections to the cluster API server
7820+
privateEndpointConnections() []azure.subscription.privateEndpointConnection
78197821
// Creation and last-modification provenance recorded by Azure Resource Manager
78207822
systemMetadata() azure.subscription.systemData
78217823
// Whether the AKS API server is reachable from the public internet
@@ -8246,6 +8248,16 @@ private azure.subscription.iotService.iotHub @defaults("id name location") {
82468248
enableDataResidency bool
82478249
// Network rule set: defaultAction, applyToBuiltInEventHubEndpoint, ipRules
82488250
networkRuleSet dict
8251+
// Managed identity type ("None", "SystemAssigned", "UserAssigned", "SystemAssigned, UserAssigned")
8252+
identityType string
8253+
// Principal ID of the system-assigned managed identity
8254+
principalId string
8255+
// Tenant ID of the system-assigned managed identity
8256+
tenantId string
8257+
// User-assigned managed identities associated with the IoT hub
8258+
userAssignedIdentities() []azure.subscription.managedIdentity
8259+
// Private endpoint connections to the IoT hub
8260+
privateEndpointConnections() []azure.subscription.privateEndpointConnection
82498261
// Diagnostic settings configured on the IoT hub (forwarding logs and metrics to Log Analytics, storage, or Event Hub)
82508262
diagnosticSettings() []azure.subscription.monitorService.diagnosticsetting
82518263
// Creation and last-modification provenance recorded by Azure Resource Manager
@@ -8628,6 +8640,8 @@ azure.subscription.synapseService.workspace @defaults("name location") {
86288640
cmkKey() azure.subscription.keyVaultService.key
86298641
// User-assigned managed identities associated with the workspace
86308642
userAssignedIdentities() []azure.subscription.managedIdentity
8643+
// Private endpoint connections to the workspace
8644+
privateEndpointConnections() []azure.subscription.privateEndpointConnection
86318645
}
86328646

86338647
// Azure Container Registry service
@@ -9595,6 +9609,8 @@ azure.subscription.serviceBusService.namespace @defaults("id name location") {
95959609
queues() []azure.subscription.serviceBusService.namespace.queue
95969610
// Topics in this namespace
95979611
topics() []azure.subscription.serviceBusService.namespace.topic
9612+
// Private endpoint connections to the namespace
9613+
privateEndpointConnections() []azure.subscription.privateEndpointConnection
95989614
// When the namespace was created
95999615
creationTime time
96009616
// Creation and last-modification provenance recorded by Azure Resource Manager
@@ -9783,6 +9799,8 @@ azure.subscription.eventHubService.namespace @defaults("id name location") {
97839799
networkRules() azure.subscription.eventHubService.namespace.networkRules
97849800
// Event Hubs in this namespace
97859801
eventHubs() []azure.subscription.eventHubService.namespace.eventHub
9802+
// Private endpoint connections to the namespace
9803+
privateEndpointConnections() []azure.subscription.privateEndpointConnection
97869804
// When the namespace was created
97879805
creationTime time
97889806
// Creation and last-modification provenance recorded by Azure Resource Manager
@@ -11023,14 +11041,24 @@ azure.subscription.apiManagementService.service @defaults("name location skuName
1102311041
http2Enabled bool
1102411042
// Identity type ("None", "SystemAssigned", "UserAssigned", "SystemAssigned, UserAssigned")
1102511043
identityType string
11044+
// Principal ID of the system-assigned managed identity
11045+
principalId string
11046+
// Tenant ID of the system-assigned managed identity
11047+
tenantId string
11048+
// User-assigned managed identities associated with the service
11049+
userAssignedIdentities() []azure.subscription.managedIdentity
1102611050
// Public load-balanced IPv4 addresses of the service in its primary region (Basic / Standard / Premium / Isolated SKUs)
1102711051
publicIpAddresses []string
1102811052
// Private load-balanced IPv4 addresses of the service in its primary region when deployed in an Internal VNet
1102911053
privateIpAddresses []string
1103011054
// Outbound public IPv4 prefixes associated with NAT Gateway-deployed services (Premium SKU on stv2)
1103111055
outboundPublicIpAddresses []string
1103211056
// Number of private endpoint connections to the service
11033-
privateEndpointConnectionCount int
11057+
//
11058+
// Deprecated in favor of `privateEndpointConnections`.
11059+
privateEndpointConnectionCount @maturity("deprecated") int
11060+
// Private endpoint connections to the service
11061+
privateEndpointConnections() []azure.subscription.privateEndpointConnection
1103411062
// Availability zones the service is spread across
1103511063
zones []string
1103611064
// Public IP address attached to the service (null when not configured)
@@ -11106,6 +11134,8 @@ private azure.subscription.purviewService.account @defaults("name location publi
1110611134
createdBy string
1110711135
// Unmodeled raw properties returned by the Azure API
1110811136
properties dict
11137+
// Creation and last-modification provenance recorded by Azure Resource Manager
11138+
systemMetadata() azure.subscription.systemData
1110911139
}
1111011140

1111111141
// Azure AI Search
@@ -11652,6 +11682,8 @@ azure.subscription.appConfigurationService.configurationStore @defaults("id name
1165211682
defaultKeyValueRevisionRetentionPeriodInSeconds int
1165311683
// When the configuration store was created
1165411684
creationTime time
11685+
// Private endpoint connections to the configuration store
11686+
privateEndpointConnections() []azure.subscription.privateEndpointConnection
1165511687
// Creation and last-modification provenance recorded by Azure Resource Manager
1165611688
systemMetadata() azure.subscription.systemData
1165711689
}
@@ -11741,6 +11773,8 @@ azure.subscription.cognitiveServicesService.account @defaults("id name location
1174111773
projects() []azure.subscription.cognitiveServicesService.account.project
1174211774
// Account-scoped connections to external resources, model providers, data sources, and tool servers
1174311775
connections() []azure.subscription.cognitiveServicesService.account.connection
11776+
// Private endpoint connections to the account
11777+
privateEndpointConnections() []azure.subscription.privateEndpointConnection
1174411778
// Creation and last-modification provenance recorded by Azure Resource Manager
1174511779
systemMetadata() azure.subscription.systemData
1174611780
}
@@ -12163,6 +12197,8 @@ azure.subscription.signalRService.signalR @defaults("id name location publicNetw
1216312197
networkAclsDefaultAction string
1216412198
// Provisioning state
1216512199
provisioningState string
12200+
// Private endpoint connections to the instance
12201+
privateEndpointConnections() []azure.subscription.privateEndpointConnection
1216612202
// Creation and last-modification provenance recorded by Azure Resource Manager
1216712203
systemMetadata() azure.subscription.systemData
1216812204
}
@@ -12222,6 +12258,8 @@ azure.subscription.webPubSubService.webPubSub @defaults("id name location public
1222212258
networkAclsDefaultAction string
1222312259
// Provisioning state
1222412260
provisioningState string
12261+
// Private endpoint connections to the instance
12262+
privateEndpointConnections() []azure.subscription.privateEndpointConnection
1222512263
// Creation and last-modification provenance recorded by Azure Resource Manager
1222612264
systemMetadata() azure.subscription.systemData
1222712265
}

0 commit comments

Comments
 (0)