-
Notifications
You must be signed in to change notification settings - Fork 1
/
main.py
132 lines (114 loc) · 5.96 KB
/
main.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
from dotenv import load_dotenv
load_dotenv()
import aiohttp
import asyncio
import json
import os
import re
import shutil
from pathlib import Path
from azure.identity.aio import DefaultAzureCredential
from msgraph_beta import GraphServiceClient
from kiota_abstractions.native_response_handler import NativeResponseHandler
from kiota_http.middleware.options import ResponseHandlerOption
from msgraph_beta.generated.device_management.configuration_settings.configuration_settings_request_builder import ConfigurationSettingsRequestBuilder
from msgraph_beta.generated.security.microsoft_graph_security_run_hunting_query.microsoft_graph_security_run_hunting_query_request_builder import MicrosoftGraphSecurityRunHuntingQueryRequestBuilder
from msgraph_beta.generated.security.microsoft_graph_security_run_hunting_query.run_hunting_query_post_request_body import RunHuntingQueryPostRequestBody
client = GraphServiceClient(DefaultAzureCredential(), ['https://graph.microsoft.com/.default'])
# id_10699 -> id
def cleanDCv1Ids(setting):
id = '_'.join(setting.get('id').split('_')[:-1])
setting['id'] = id
for child in setting.get('childSettings', []):
cleanDCv1Ids(child)
async def main():
async with aiohttp.ClientSession() as session, session.get('https://intune.microsoft.com/signin/idpRedirect.js') as resp:
versions = await resp.text()
versions = re.search(r'\"extensionsPageVersion\":({[^}]+})', versions).group(1)
versions = json.loads(versions)
root = 'https://afd-v2.hosting.portal.azure.net'
root_devicesettings = f'{root}/intunedevicesettings/Content/{versions.get('Microsoft_Intune_DeviceSettings')[0]}/Scripts/DeviceConfiguration'
# map setting error codes to descriptions
async with session.get(f'{root_devicesettings}/Blades/DevicePoliciesStatus/SettingStatus.js') as resp:
data = await resp.text()
data = re.search(r'SettingStatusErrorMap = ({[^}]+})', data).group(1)
data = json.loads(data, strict=False) # some strings have control characters
with open('SettingStatusErrors.json', 'w', encoding='utf-8') as f:
json.dump(data, f, ensure_ascii=False, indent=4)
# DCv1 policies
output = 'DCv1'
shutil.rmtree(output)
for source in ['Configuration', 'Compliance']:
os.makedirs(Path(output, source))
async with session.get(f'{root_devicesettings}/Metadata/{source}Metadata.js') as resp:
data = await resp.text()
data = re.search(r'(?s)metadata = ({.+});', await resp.text()).group(1)
data = json.loads(data)
for family in data.values():
for setting in family:
# id_10699 -> id
id = '_'.join(setting.get('id').split('_')[:-1])
cleanDCv1Ids(setting)
path = Path(output, source, id).with_suffix('.json')
with open(path, 'w', encoding='utf-8') as f:
json.dump(setting, f, ensure_ascii=False, indent=4)
query_params = ConfigurationSettingsRequestBuilder.ConfigurationSettingsRequestBuilderGetQueryParameters(
top=10
)
request_config = ConfigurationSettingsRequestBuilder.ConfigurationSettingsRequestBuilderGetRequestConfiguration(
options=[ResponseHandlerOption(NativeResponseHandler())],
# query_parameters=query_params
)
data = await client.service_principals.with_url('https://graph.microsoft.com/beta/servicePrincipals/appId=0000000a-0000-0000-c000-000000000000/endpoints').get(request_configuration=request_config)
with open('Endpoints.json', 'w', encoding='utf-8') as f:
json.dump(data.json(), f, ensure_ascii=False, indent=4)
# Defender schemas
request_config = MicrosoftGraphSecurityRunHuntingQueryRequestBuilder.MicrosoftGraphSecurityRunHuntingQueryRequestBuilderPostRequestConfiguration(
options=[ResponseHandlerOption(NativeResponseHandler())],
)
for table in [
'AlertEvidence',
'AlertInfo',
'BehaviorEntities',
'BehaviorInfo',
'AADSignInEventsBeta',
'AADSpnSignInEventsBeta',
'CloudAppEvents',
'IdentityInfo',
'IdentityLogonEvents',
'EmailAttachmentInfo',
'EmailEvents',
'EmailPostDeliveryEvents',
'EmailUrlInfo',
'UrlClickEvents',
'ExposureGraphEdges',
'ExposureGraphNodes',
]:
data = await client.security.microsoft_graph_security_run_hunting_query.post(request_configuration=request_config, body=RunHuntingQueryPostRequestBody(
# match columns of 1P schema endpoint
query=f'{table} | getschema | project Description="", Type=split(DataType, ".")[1], Entity="", Name=ColumnName'
))
with open(f'Defender/{table}.json', 'w', encoding='utf-8') as f:
json.dump(data.json().get('results'), f, ensure_ascii=False, indent=4)
# DCv2 policies eg Settings Catalog
output = 'DCv2'
shutil.rmtree(output)
source = 'Settings'
os.makedirs(Path(output, source))
data = await client.device_management.configuration_settings.get(request_configuration=request_config)
for item in data.json().get('value'):
item.pop('version')
path = Path(output, source, item.get('id')).with_suffix('.json')
with open(path, 'w', encoding='utf-8') as f:
json.dump(item, f, ensure_ascii=False, indent=4)
# backwards compat
shutil.rmtree('settings')
shutil.copytree(Path(output, source), 'settings')
source = 'Templates'
os.makedirs(Path(output, source))
data = await client.device_management.configuration_policy_templates.get(request_configuration=request_config)
for item in data.json().get('value'):
path = Path(output, source, item.get('id')).with_suffix('.json')
with open(path, 'w', encoding='utf-8') as f:
json.dump(item, f, ensure_ascii=False, indent=4)
asyncio.run(main())