我正在尝试按照此学习文章对 Microsoft Defender for Endpoint 的 API 服务进行身份验证:
我通常使用“请求”库进行 REST 调用,因此我没有完全遵循上面的代码片段。当运行我的上述代码版本时:
import json
import requests
MDE_CLIENT_ID = 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXX'
MDE_CLIENT_SECRET = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
TENANT_ID = 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXX'
AUTHORITY = 'https://login.microsoftonline.com/'
MDE_URI = 'https://api.securitycenter.microsoft.com'
class RESTError(Exception):
def __init__(self, status_code, message):
self.status_code = status_code
self.message = str(self.status_code) + ' ' + json.dumps(message)
super().__init__(self.message)
def authenticate_mde():
headers = {
'content-type': 'application/x-www-form-urlencoded'
}
body = {
'resource': MDE_URI,
'client_id': MDE_CLIENT_ID,
'client_secret': MDE_CLIENT_SECRET,
'grant_type': 'client_credentials'
}
response = requests.post(AUTHORITY + TENANT_ID + '/oauth2/token', data = json.dumps(body), headers = headers)
if (response.status_code < 200 or response.status_code > 299):
raise RESTError(response.status_code, response.json())
return response.json()['access_token']
def main():
token = authenticate_mde()
print(token)
if (__name__ == '__main__'):
main()
当我运行此代码时,我收到来自身份验证服务的 400 错误,抱怨缺少主体参数“grant_type”。然而,正如您在代码中看到的,我显然以与 MSFT 的代码片段相同的方式包含了它。
Traceback (most recent call last):
File "C:\Users\24724\Documents\code\python\scripts\mde-executor.py", line 42, in <module>
main()
File "C:\Users\24724\Documents\code\python\scripts\mde-executor.py", line 38, in main
token = authenticate_mde()
File "C:\Users\24724\Documents\code\python\scripts\mde-executor.py", line 32, in authenticate_mde
raise RESTError(response.status_code, response.json())
__main__.RESTError: 400 {"error": "invalid_request", "error_description": "AADSTS900144: The request body must contain the following parameter: 'grant_type'.\r\nTrace ID: e4d0d06e-aae6-4b6d-80e2-2b3997f74302\r\nCorrelation ID: 5788089d-f94e-4e9a-8667-d6e36c183af8\r\nTimestamp: 2023-01-06 17:00:23Z", "error_codes": [900144], "timestamp": "2023-01-06 17:00:23Z", "trace_id": "e4d0d06e-aae6-4b6d-80e2-2b3997f74302", "correlation_id": "5788089d-f94e-4e9a-8667-d6e36c183af8", "error_uri": "https://login.microsoftonline.com/error?code=900144"}
我还尝试准确复制 MSFT 的代码片段并插入我自己的全局变量信息,但收到相同的错误。我尝试将正文移动到 url 参数、标头,将其拆分为正文、参数和标头。运气不好。我也在标题中尝试了不同的内容类型,并尝试不使用任何标题。似乎没有一个起作用,我在这一点上被难住了。
我解决了这个问题。将“资源”传递到主体中显然是把事情搞砸了,尽管这里的 python 示例表明:
import json
import urllib.request
import urllib.parse
tenantId = '00000000-0000-0000-0000-000000000000' # Paste your own tenant ID here
appId = '11111111-1111-1111-1111-111111111111' # Paste your own app ID here
appSecret = '22222222-2222-2222-2222-222222222222' # Paste your own app secret here
url = "https://login.microsoftonline.com/%s/oauth2/token" % (tenantId)
resourceAppIdUri = 'https://api.securitycenter.microsoft.com'
body = {
'resource' : resourceAppIdUri,
'client_id' : appId,
'client_secret' : appSecret,
'grant_type' : 'client_credentials'
}
data = urllib.parse.urlencode(body).encode("utf-8")
req = urllib.request.Request(url, data)
response = urllib.request.urlopen(req)
jsonResponse = json.loads(response.read())
aadToken = jsonResponse["access_token"]
按照他们在此处给出的 cURL 示例,并使用“scope”参数来修复它。
curl -i -X POST -H "Content-Type:application/x-www-form-urlencoded" -d "grant_type=client_credentials" -d "client_id=%CLIENT_ID%" -d "scope=https://securitycenter.onmicrosoft.com/windowsatpservice/.default" -d "client_secret=%CLIENT_SECRET%" "https://login.microsoftonline.com/%TENANT_ID%/oauth2/v2.0/token" -k