Forum Discussion
Power Query Defender Advanced hunting bad request 400 for some tables.
- 10 months ago
I ended up using notebooks instead of Dataflow Gen2.
Thanks
Thanks for your help,
you were right that the API endpoint is not the correct one, but it wasn't a simple switch, cause the second url apperantly needs to be passed a token, which needs to be called from power query itself:
Scope = "https://api.security.microsoft.com/.default",
// Construct the body as a record (Power Query will handle encoding)
TokenRequestBody = [
grant_type = "client_credentials",
client_id = ClientId,
client_secret = ClientSecret,
scope = Scope
],
// Convert the record to form-urlencoded text
FormBody = Text.ToBinary(Uri.BuildQueryString(TokenRequestBody)),
// Make the token request
TokenResponse = Json.Document(
Web.Contents(
"https://login.microsoftonline.com/" & TenantId & "/oauth2/v2.0/token",
[
Content = FormBody,
Headers = [
#"Content-Type" = "application/x-www-form-urlencoded",
Accept = "application/json"
]
]
)
),
// Extract the access token
AccessToken = TokenResponse[access_token],ones the token is obtained,
you will proceed and call the api, passing the token
AdvancedHuntingQuery = Json.FromValue([Query = FullQuery]),
HuntingResponse = Json.Document(
Web.Contents(
HuntingUrl,
[
Content=AdvancedHuntingQuery,
Headers = [
Authorization = "Bearer " & AccessToken,
#"Content-Type" = "application/json",
Accept = "application/json"
]
]
)
),
TypeMap = #table(
{ "Type", "PowerBiType" },
{
{ "Double", Double.Type },
{ "Int64", Int64.Type },
{ "Int32", Int32.Type },
{ "Int16", Int16.Type },
{ "UInt64", Number.Type },
{ "UInt32", Number.Type },
{ "UInt16", Number.Type },
{ "Byte", Byte.Type },
{ "Single", Single.Type },
{ "Decimal", Decimal.Type },
{ "TimeSpan", Duration.Type },
{ "DateTime", DateTimeZone.Type },
{ "String", Text.Type },
{ "Boolean", Logical.Type },
{ "SByte", Logical.Type },
{ "Guid", Text.Type }
}),
Schema = Table.FromRecords(HuntingResponse[Schema]),
TypedSchema = Table.Join(Table.SelectColumns(Schema, {"Name", "Type"}), {"Type"}, TypeMap , {"Type"}),
Results = HuntingResponse[Results],
Rows = Table.FromRecords(Results, Schema[Name]),
Table = Table.TransformColumnTypes(Rows, Table.ToList(TypedSchema, (c) => {c{0}, c{2}}))
in TableThe only withdraw that i am looking to solve now is the authentication. I am unable to use a service principal authentication, but i am hard coding the parameters needed by the query, Tenant_ID, Client_ID and Client_Secret.
Is there another way to authenticate and get the token without hard coding the service principal parameters into the dataflow?
Hi mkjit256 , Thank you for reaching out to the Microsoft Fabric Community Forum.
Right now, your code works because you hard-coded the tenant, client id and secret but that’s not a safe way to keep it running long-term. The proper way in Fabric is to avoid putting secrets directly into your M script. Store the client secret in Azure Key Vault and let your Fabric workspace managed identity pull it at runtime. That way the query code stays the same but instead of writing the secret, you just call the Key Vault reference. Secrets can then be rotated or revoked without you touching the dataflow.
If you can’t set up Key Vault yet, the next-best option is to create a connection in Fabric that holds the service principal details. Your dataflow then uses that connection, so the credentials live in Fabric’s secure store and not in your script. Either way, the token flow you built stays the same, the only change is where the secret comes from. This keeps your setup secure and much easier to maintain.
Configure AKV references - Microsoft Fabric | Microsoft Learn
Azure Key Vault Reference overview (Preview) - Microsoft Fabric | Microsoft Learn
Microsoft Defender XDR advanced hunting API - Microsoft Defender XDR | Microsoft Learn