Skip to content

Commit 8b6c206

Browse files
authored
fix: added MEM to datasource utilityMicrosoft365EndpointReference (#1279)
* fix: added MEM to datasource utilityMicrosoft365EndpointReference * chore: updated docs
1 parent 0674517 commit 8b6c206

File tree

13 files changed

+3766
-19
lines changed

13 files changed

+3766
-19
lines changed

docs/data-sources/utility_microsoft_365_endpoint_reference.md

Lines changed: 150 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ page_title: "microsoft365_utility_microsoft_365_endpoint_reference Data Source -
33
subcategory: "Utility"
44

55
description: |-
6-
Retrieves Microsoft 365 network endpoints from the official Microsoft 365 IP Address and URL Web Service. This datasource queries https://endpoints.office.com to get current IP addresses, URLs, and ports for Microsoft 365 services. Useful for configuring firewalls, proxy servers, SD-WAN devices, and PAC files. Data is filtered by cloud instance (Worldwide, US Government, China) and can be narrowed by service area and category.
6+
Retrieves Microsoft 365 network endpoints from the official Microsoft 365 IP Address and URL Web Service. This datasource queries https://endpoints.office.com with all service areas (MEM, Exchange, Skype, SharePoint, Common) to get current IP addresses, URLs, and ports for Microsoft 365 services including Intune/Endpoint Manager. Useful for configuring firewalls, proxy servers, SD-WAN devices, and PAC files. Data is filtered by cloud instance (Worldwide, US Government, China) and can be narrowed by service area and category.
77
See Managing Microsoft 365 endpoints https://learn.microsoft.com/en-us/microsoft-365/enterprise/managing-office-365-endpoints for configuration guidance.
88
---
99

@@ -76,6 +76,7 @@ See [Microsoft 365 Network Connectivity Principles](https://learn.microsoft.com/
7676

7777
## Service Areas
7878

79+
- **MEM**: Microsoft Endpoint Manager (Intune, Autopilot, Windows Updates, Remote Help)
7980
- **Exchange**: Exchange Online, Outlook, Exchange Online Protection (EOP)
8081
- **SharePoint**: SharePoint Online and OneDrive for Business
8182
- **Skype**: Microsoft Teams and Skype for Business Online
@@ -622,11 +623,155 @@ output "network_summary" {
622623
}
623624
```
624625

626+
### Microsoft Endpoint Manager (Intune) Endpoints
627+
628+
```terraform
629+
# Example: Get all MEM (Microsoft Endpoint Manager / Intune) endpoints
630+
data "microsoft365_utility_microsoft_365_endpoint_reference" "mem_all" {
631+
instance = "worldwide"
632+
service_areas = ["MEM"]
633+
}
634+
635+
# Output: Total count of MEM endpoints
636+
output "mem_endpoints_count" {
637+
description = "Total number of MEM endpoints (Expected: 15 for Worldwide)"
638+
value = length(data.microsoft365_utility_microsoft_365_endpoint_reference.mem_all.endpoints)
639+
}
640+
641+
# Output: All MEM URLs/FQDNs (flattened list)
642+
output "mem_urls" {
643+
description = "All MEM/Intune URLs that need to be allowed"
644+
value = flatten([
645+
for endpoint in data.microsoft365_utility_microsoft_365_endpoint_reference.mem_all.endpoints :
646+
coalesce(endpoint.urls, [])
647+
])
648+
}
649+
650+
# Output: All MEM IP ranges (flattened list)
651+
output "mem_ip_ranges" {
652+
description = "All MEM/Intune IP ranges in CIDR notation"
653+
value = flatten([
654+
for endpoint in data.microsoft365_utility_microsoft_365_endpoint_reference.mem_all.endpoints :
655+
coalesce(endpoint.ips, [])
656+
])
657+
}
658+
659+
# Output: Detailed breakdown of each MEM endpoint
660+
output "mem_endpoint_details" {
661+
description = "Detailed information for each MEM endpoint"
662+
value = [
663+
for endpoint in data.microsoft365_utility_microsoft_365_endpoint_reference.mem_all.endpoints : {
664+
id = endpoint.id
665+
display_name = endpoint.service_area_display_name
666+
category = endpoint.category
667+
required = endpoint.required
668+
express_route = endpoint.express_route
669+
tcp_ports = endpoint.tcp_ports
670+
udp_ports = endpoint.udp_ports
671+
url_count = length(coalesce(endpoint.urls, []))
672+
ip_count = length(coalesce(endpoint.ips, []))
673+
urls = coalesce(endpoint.urls, [])
674+
ips = coalesce(endpoint.ips, [])
675+
notes = endpoint.notes
676+
}
677+
]
678+
}
679+
680+
# Example: Get only REQUIRED MEM endpoints
681+
data "microsoft365_utility_microsoft_365_endpoint_reference" "mem_required" {
682+
instance = "worldwide"
683+
service_areas = ["MEM"]
684+
required_only = true
685+
}
686+
687+
output "mem_required_urls" {
688+
description = "Required MEM URLs only"
689+
value = flatten([
690+
for endpoint in data.microsoft365_utility_microsoft_365_endpoint_reference.mem_required.endpoints :
691+
coalesce(endpoint.urls, [])
692+
])
693+
}
694+
695+
# Example: Generate firewall rules for MEM endpoints
696+
locals {
697+
mem_firewall_rules = flatten([
698+
for endpoint in data.microsoft365_utility_microsoft_365_endpoint_reference.mem_all.endpoints : [
699+
for url in coalesce(endpoint.urls, []) : {
700+
destination = url
701+
tcp_ports = endpoint.tcp_ports != "" ? endpoint.tcp_ports : null
702+
udp_ports = endpoint.udp_ports != "" ? endpoint.udp_ports : null
703+
category = endpoint.category
704+
required = endpoint.required
705+
express_route = endpoint.express_route
706+
}
707+
]
708+
])
709+
710+
# Group MEM endpoints by category
711+
mem_by_category = {
712+
for category in distinct([
713+
for endpoint in data.microsoft365_utility_microsoft_365_endpoint_reference.mem_all.endpoints :
714+
endpoint.category
715+
]) :
716+
category => [
717+
for endpoint in data.microsoft365_utility_microsoft_365_endpoint_reference.mem_all.endpoints :
718+
endpoint if endpoint.category == category
719+
]
720+
}
721+
}
722+
723+
output "mem_firewall_rules" {
724+
description = "Firewall rules for MEM endpoints"
725+
value = local.mem_firewall_rules
726+
}
727+
728+
output "mem_by_category" {
729+
description = "MEM endpoints grouped by category (Allow/Default)"
730+
value = {
731+
for category, endpoints in local.mem_by_category :
732+
category => {
733+
count = length(endpoints)
734+
urls = distinct(flatten([for ep in endpoints : coalesce(ep.urls, [])]))
735+
ips = distinct(flatten([for ep in endpoints : coalesce(ep.ips, [])]))
736+
}
737+
}
738+
}
739+
740+
# Example: Extract specific Intune services
741+
output "intune_core_management" {
742+
description = "Core Intune management endpoints (ID 163)"
743+
value = [
744+
for endpoint in data.microsoft365_utility_microsoft_365_endpoint_reference.mem_all.endpoints :
745+
{
746+
urls = coalesce(endpoint.urls, [])
747+
ips = coalesce(endpoint.ips, [])
748+
}
749+
if endpoint.id == 163
750+
]
751+
}
752+
753+
output "windows_update_urls" {
754+
description = "Windows Update delivery endpoints for Intune"
755+
value = flatten([
756+
for endpoint in data.microsoft365_utility_microsoft_365_endpoint_reference.mem_all.endpoints :
757+
coalesce(endpoint.urls, [])
758+
if(endpoint.notes != null && (
759+
strcontains(lower(endpoint.notes), "windows") ||
760+
strcontains(lower(endpoint.notes), "update")
761+
)) ||
762+
length([
763+
for url in coalesce(endpoint.urls, []) :
764+
url if strcontains(lower(url), "update") || strcontains(lower(url), "windowsupdate")
765+
]) > 0
766+
])
767+
}
768+
```
769+
625770
## Argument Reference
626771

627772
* `instance` - (Required) The Microsoft 365 cloud instance to query. Valid values: `worldwide`, `usgov-dod`, `usgov-gcchigh`, `china`.
628773

629-
* `service_areas` - (Optional) Filter endpoints by service area. Valid values: `Exchange`, `SharePoint`, `Skype`, `Common`. If omitted, returns all service areas.
774+
* `service_areas` - (Optional) Filter endpoints by service area. Valid values: `MEM`, `Exchange`, `SharePoint`, `Skype`, `Common`. If omitted, returns all service areas.
630775

631776
* `categories` - (Optional) Filter endpoints by network optimization category. Valid values: `Optimize`, `Allow`, `Default`. If omitted, returns all categories.
632777

@@ -642,7 +787,7 @@ output "network_summary" {
642787

643788
* `endpoints` - List of endpoint objects. Each endpoint contains:
644789
- `id` - Unique identifier for this endpoint set (from Microsoft's service)
645-
- `service_area` - Service area code: `Exchange`, `SharePoint`, `Skype`, or `Common`
790+
- `service_area` - Service area code: `MEM`, `Exchange`, `SharePoint`, `Skype`, or `Common`
646791
- `service_area_display_name` - Human-readable service area name
647792
- `urls` - List of URL patterns/FQDNs (may include wildcards like `*.office.com`)
648793
- `ips` - List of IP address ranges in CIDR notation (e.g., `40.96.0.0/13`)
@@ -683,6 +828,7 @@ If omitted, returns endpoints for all categories. See [Microsoft 365 Network Con
683828
- `express_route` (Boolean) If `true`, only returns endpoints that support Azure ExpressRoute for Microsoft 365. Useful for organizations using ExpressRoute for optimized connectivity. Defaults to `false` (returns all endpoints regardless of ExpressRoute support).
684829
- `required_only` (Boolean) If `true`, only returns endpoints marked as required by Microsoft. Optional endpoints provide enhanced functionality but are not necessary for core service operation. Defaults to `false` (returns all endpoints).
685830
- `service_areas` (Set of String) Filter endpoints by service area. Valid values:
831+
- `MEM` - Microsoft Endpoint Manager (Intune, Autopilot, Windows Updates)
686832
- `Exchange` - Exchange Online and Exchange Online Protection
687833
- `SharePoint` - SharePoint Online and OneDrive for Business
688834
- `Skype` - Skype for Business Online and Microsoft Teams
@@ -715,7 +861,7 @@ Read-Only:
715861
- `ips` (List of String) List of IP address ranges in CIDR notation (e.g., `40.96.0.0/13`). May be empty for URL-only endpoints.
716862
- `notes` (String) Additional notes about this endpoint from Microsoft, such as third-party services or optional features.
717863
- `required` (Boolean) Whether this endpoint is required for core Microsoft 365 functionality.
718-
- `service_area` (String) The service area: `Exchange`, `SharePoint`, `Skype`, or `Common`.
864+
- `service_area` (String) The service area: `MEM`, `Exchange`, `SharePoint`, `Skype`, or `Common`.
719865
- `service_area_display_name` (String) Human-readable display name for the service area.
720866
- `tcp_ports` (String) TCP ports used by this endpoint (comma-separated, e.g., `80,443` or ranges like `1024-65535`).
721867
- `udp_ports` (String) UDP ports used by this endpoint (comma-separated, e.g., `3478-3481`).
Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
# Example: Get all MEM (Microsoft Endpoint Manager / Intune) endpoints
2+
data "microsoft365_utility_microsoft_365_endpoint_reference" "mem_all" {
3+
instance = "worldwide"
4+
service_areas = ["MEM"]
5+
}
6+
7+
# Output: Total count of MEM endpoints
8+
output "mem_endpoints_count" {
9+
description = "Total number of MEM endpoints (Expected: 15 for Worldwide)"
10+
value = length(data.microsoft365_utility_microsoft_365_endpoint_reference.mem_all.endpoints)
11+
}
12+
13+
# Output: All MEM URLs/FQDNs (flattened list)
14+
output "mem_urls" {
15+
description = "All MEM/Intune URLs that need to be allowed"
16+
value = flatten([
17+
for endpoint in data.microsoft365_utility_microsoft_365_endpoint_reference.mem_all.endpoints :
18+
coalesce(endpoint.urls, [])
19+
])
20+
}
21+
22+
# Output: All MEM IP ranges (flattened list)
23+
output "mem_ip_ranges" {
24+
description = "All MEM/Intune IP ranges in CIDR notation"
25+
value = flatten([
26+
for endpoint in data.microsoft365_utility_microsoft_365_endpoint_reference.mem_all.endpoints :
27+
coalesce(endpoint.ips, [])
28+
])
29+
}
30+
31+
# Output: Detailed breakdown of each MEM endpoint
32+
output "mem_endpoint_details" {
33+
description = "Detailed information for each MEM endpoint"
34+
value = [
35+
for endpoint in data.microsoft365_utility_microsoft_365_endpoint_reference.mem_all.endpoints : {
36+
id = endpoint.id
37+
display_name = endpoint.service_area_display_name
38+
category = endpoint.category
39+
required = endpoint.required
40+
express_route = endpoint.express_route
41+
tcp_ports = endpoint.tcp_ports
42+
udp_ports = endpoint.udp_ports
43+
url_count = length(coalesce(endpoint.urls, []))
44+
ip_count = length(coalesce(endpoint.ips, []))
45+
urls = coalesce(endpoint.urls, [])
46+
ips = coalesce(endpoint.ips, [])
47+
notes = endpoint.notes
48+
}
49+
]
50+
}
51+
52+
# Example: Get only REQUIRED MEM endpoints
53+
data "microsoft365_utility_microsoft_365_endpoint_reference" "mem_required" {
54+
instance = "worldwide"
55+
service_areas = ["MEM"]
56+
required_only = true
57+
}
58+
59+
output "mem_required_urls" {
60+
description = "Required MEM URLs only"
61+
value = flatten([
62+
for endpoint in data.microsoft365_utility_microsoft_365_endpoint_reference.mem_required.endpoints :
63+
coalesce(endpoint.urls, [])
64+
])
65+
}
66+
67+
# Example: Generate firewall rules for MEM endpoints
68+
locals {
69+
mem_firewall_rules = flatten([
70+
for endpoint in data.microsoft365_utility_microsoft_365_endpoint_reference.mem_all.endpoints : [
71+
for url in coalesce(endpoint.urls, []) : {
72+
destination = url
73+
tcp_ports = endpoint.tcp_ports != "" ? endpoint.tcp_ports : null
74+
udp_ports = endpoint.udp_ports != "" ? endpoint.udp_ports : null
75+
category = endpoint.category
76+
required = endpoint.required
77+
express_route = endpoint.express_route
78+
}
79+
]
80+
])
81+
82+
# Group MEM endpoints by category
83+
mem_by_category = {
84+
for category in distinct([
85+
for endpoint in data.microsoft365_utility_microsoft_365_endpoint_reference.mem_all.endpoints :
86+
endpoint.category
87+
]) :
88+
category => [
89+
for endpoint in data.microsoft365_utility_microsoft_365_endpoint_reference.mem_all.endpoints :
90+
endpoint if endpoint.category == category
91+
]
92+
}
93+
}
94+
95+
output "mem_firewall_rules" {
96+
description = "Firewall rules for MEM endpoints"
97+
value = local.mem_firewall_rules
98+
}
99+
100+
output "mem_by_category" {
101+
description = "MEM endpoints grouped by category (Allow/Default)"
102+
value = {
103+
for category, endpoints in local.mem_by_category :
104+
category => {
105+
count = length(endpoints)
106+
urls = distinct(flatten([for ep in endpoints : coalesce(ep.urls, [])]))
107+
ips = distinct(flatten([for ep in endpoints : coalesce(ep.ips, [])]))
108+
}
109+
}
110+
}
111+
112+
# Example: Extract specific Intune services
113+
output "intune_core_management" {
114+
description = "Core Intune management endpoints (ID 163)"
115+
value = [
116+
for endpoint in data.microsoft365_utility_microsoft_365_endpoint_reference.mem_all.endpoints :
117+
{
118+
urls = coalesce(endpoint.urls, [])
119+
ips = coalesce(endpoint.ips, [])
120+
}
121+
if endpoint.id == 163
122+
]
123+
}
124+
125+
output "windows_update_urls" {
126+
description = "Windows Update delivery endpoints for Intune"
127+
value = flatten([
128+
for endpoint in data.microsoft365_utility_microsoft_365_endpoint_reference.mem_all.endpoints :
129+
coalesce(endpoint.urls, [])
130+
if(endpoint.notes != null && (
131+
strcontains(lower(endpoint.notes), "windows") ||
132+
strcontains(lower(endpoint.notes), "update")
133+
)) ||
134+
length([
135+
for url in coalesce(endpoint.urls, []) :
136+
url if strcontains(lower(url), "update") || strcontains(lower(url), "windowsupdate")
137+
]) > 0
138+
])
139+
}
140+

internal/services/datasources/utility/microsoft_365_endpoint_reference/datasource.go

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,8 @@ func (d *Microsoft365EndpointReferenceDataSource) Configure(_ context.Context, r
4848
func (d *Microsoft365EndpointReferenceDataSource) Schema(ctx context.Context, _ datasource.SchemaRequest, resp *datasource.SchemaResponse) {
4949
resp.Schema = schema.Schema{
5050
MarkdownDescription: "Retrieves Microsoft 365 network endpoints from the official Microsoft 365 IP Address and URL Web Service. " +
51-
"This datasource queries `https://endpoints.office.com` to get current IP addresses, URLs, and ports for Microsoft 365 services. " +
51+
"This datasource queries `https://endpoints.office.com` with all service areas (MEM, Exchange, Skype, SharePoint, Common) " +
52+
"to get current IP addresses, URLs, and ports for Microsoft 365 services including Intune/Endpoint Manager. " +
5253
"Useful for configuring firewalls, proxy servers, SD-WAN devices, and PAC files. " +
5354
"Data is filtered by cloud instance (Worldwide, US Government, China) and can be narrowed by service area and category.\n\n" +
5455
"See [Managing Microsoft 365 endpoints](https://learn.microsoft.com/en-us/microsoft-365/enterprise/managing-office-365-endpoints) for configuration guidance.",
@@ -73,14 +74,15 @@ func (d *Microsoft365EndpointReferenceDataSource) Schema(ctx context.Context, _
7374
ElementType: types.StringType,
7475
Optional: true,
7576
MarkdownDescription: "Filter endpoints by service area. Valid values:\n" +
77+
" - `MEM` - Microsoft Endpoint Manager (Intune, Autopilot, Windows Updates)\n" +
7678
" - `Exchange` - Exchange Online and Exchange Online Protection\n" +
7779
" - `SharePoint` - SharePoint Online and OneDrive for Business\n" +
7880
" - `Skype` - Skype for Business Online and Microsoft Teams\n" +
7981
" - `Common` - Microsoft 365 Common (Microsoft Entra ID, Office in browser, etc.)\n\n" +
8082
"If omitted, returns endpoints for all service areas.",
8183
Validators: []validator.Set{
8284
setvalidator.ValueStringsAre(
83-
stringvalidator.OneOf("Exchange", "SharePoint", "Skype", "Common"),
85+
stringvalidator.OneOf("MEM", "Exchange", "SharePoint", "Skype", "Common"),
8486
),
8587
},
8688
},
@@ -122,7 +124,7 @@ func (d *Microsoft365EndpointReferenceDataSource) Schema(ctx context.Context, _
122124
},
123125
"service_area": schema.StringAttribute{
124126
Computed: true,
125-
MarkdownDescription: "The service area: `Exchange`, `SharePoint`, `Skype`, or `Common`.",
127+
MarkdownDescription: "The service area: `MEM`, `Exchange`, `SharePoint`, `Skype`, or `Common`.",
126128
},
127129
"service_area_display_name": schema.StringAttribute{
128130
Computed: true,

internal/services/datasources/utility/microsoft_365_endpoint_reference/read.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ import (
1717

1818
const (
1919
endpointsAPIBaseURL = "https://endpoints.office.com/endpoints"
20-
versionAPIURL = "https://endpoints.office.com/version"
2120
apiTimeout = 30 * time.Second
2221
)
2322

@@ -101,7 +100,11 @@ func getAllowListEndpoints(ctx context.Context, instance string) ([]Microsoft365
101100

102101
clientRequestID := uuid.New().String()
103102

104-
url := fmt.Sprintf("%s/%s?clientrequestid=%s", endpointsAPIBaseURL, instance, clientRequestID)
103+
// Include all service areas to get maximum endpoint coverage (79 for Worldwide)
104+
// Without ServiceAreas=MEM, the API only returns 64 endpoints and misses all 15 Intune/MEM endpoints
105+
// Reference: https://learn.microsoft.com/en-us/microsoft-365/enterprise/microsoft-365-ip-web-service
106+
serviceAreas := "MEM,Exchange,Skype,SharePoint,Common"
107+
url := fmt.Sprintf("%s/%s?ServiceAreas=%s&ClientRequestId=%s", endpointsAPIBaseURL, instance, serviceAreas, clientRequestID)
105108

106109
tflog.Debug(ctx, fmt.Sprintf("Calling Microsoft 365 endpoints API: %s", url))
107110

0 commit comments

Comments
 (0)