Querying Azure Log Analytics from C# application - c#

I am struggling for the past few days to query custom logs from Azure Log Analytics. I've been following the tutorial provided by Microsoft from https://dev.int.loganalytics.io/documentation/1-Tutorials/Direct-API but I keep getting 403. I granted all permission on the workspace to my Azure Application
[![Azure Application permissions on the ALA Workspace][1]][1]
[1]: https://i.stack.imgur.com/xxT2A.png
Here is a simple application code I am using to try to query ALA Workspace
static async Task Main(string[] args)
{
String tenantId = "??????????????????????????????????";
String applicationId = "??????????????????????????????????";";
String applictionSecretKey = "??????????????????????????????????";;
String token;
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
Dictionary<String, String> requestData = new Dictionary<String, String>();
requestData.Add("grant_type", "client_credentials");
requestData.Add("client_id", applicationId);
requestData.Add("client_secret", applictionSecretKey);
requestData.Add("resource", "https://api.loganalytics.io/");
FormUrlEncodedContent requestBody = new FormUrlEncodedContent(requestData);
var request = await client.PostAsync($"https://login.microsoftonline.com/{tenantId}/oauth2/token", requestBody);
var response = await request.Content.ReadAsStringAsync();
token = JsonConvert.DeserializeObject<dynamic>(response).access_token;
}
String workspaceId = "??????????????????????????????????";;
String query = JsonConvert.SerializeObject(new
{
query = "ApplicationLog_CL | take 10",
timespan = "PT12H"
});
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
var postContent = new StringContent(query, Encoding.UTF8, "application/json");
var response = await client.PostAsync($"https://api.loganalytics.io/v1/workspaces/{workspaceId}/query", postContent);
HttpContent responseContent = response.Content;
var content = await response.Content.ReadAsStringAsync();
Console.WriteLine(content);
}
Console.ReadKey();
}
I keep getting 403 response from ALA API. Any clue what I am missing here?

According to the tutorial you provided, I test in my site and it works very well.
Here are some ways you could troubleshooting.
1.When you add role in Access control, you could add the AAD registered app which name is AIDemoApp like tutorial.
And the Log Analytics API permission is add in AAD.
2.Change new MediaTypeWithQualityHeaderValue("application/json") to new MediaTypeWithQualityHeaderValue("application/x-www-form-urlencoded").
3.After adding Permission in the registered app in AAD, click Grant Permission.

The problem is with the string content
var postContent = new StringContent(query, Encoding.UTF8, "application/json");
Log analytics API is expecting the charset to be empty
Add the below line to make it work.
postContent.Headers.ContentType.CharSet = string.Empty;

Related

How to add Authentication token in HttpRequest in Adaptive dialog?

I am using Botframework adaptive dialog template (c#). I already obtained a token from a HttpRequest and saved it as a conversation state property conversation.token, now I am trying to use this token to make another API call with HttpRequest. But from the official document of HttpRequest Class, it seems there is no options to add the authentication token. I tried to add the token in the Headers, but did not work, it showed 401 Unauthorized error. How should the authorization be handled in HttpRequest in adaptive dialog?
new HttpRequest()
{
Url = "http://example.com/json",
ResultProperty = "conversation.httpResponse",
Method = HttpRequest.HttpMethod.GET,
ResponseType = HttpRequest.ResponseTypes.Json,
Headers = new Dictionary<string, AdaptiveExpressions.Properties.StringExpression>()
{
{"Authorization", "Bearer ${conversation.token.content.token}"},
},
},
new SendActivity("${conversation.httpResponse}"),
Instead of using HttpRequest, I made the API call inside CodeAction with custom code.
First make a POST request to get the token, then make a GET request to call the main API. In the GET request, the authorization can be added in this way: client.DefaultRequestHeaders.Add("Authorization", "Bearer " + accessToken);.
new CodeAction(async (dc, options) =>
{
var my_jsondata = new
{
Username = "username",
Password = "password"
};
var json = JsonConvert.SerializeObject(my_jsondata);
var data = new StringContent(json, Encoding.UTF8, "application/json");
var Tokenurl = "https://example.com/token?HTTP/1.1";
using var Tokenclient = new HttpClient();
var Tokenresponse = await Tokenclient.PostAsync(Tokenurl, data);
string Toeknresult = Tokenresponse.Content.ReadAsStringAsync().Result;
var Tokenjo = JObject.Parse(Tokenresult);
using var client = new HttpClient();
var url = "https://example.com/mainapi?HTTP/1.1";
var accessToken = Tokenjo["token"];
client.DefaultRequestHeaders.Add("Authorization", "Bearer " + accessToken);
var response = await client.GetAsync(url);
string result = response.Content.ReadAsStringAsync().Result;
dc.State.SetValue("conversation.httpresponse", response);
dc.State.SetValue("conversation.result", result);
return await dc.EndDialogAsync();
}),

How to send HttpClient get method autorized in .NET Core [duplicate]

I'm trying to make a simple request to the Basecamp API, I'm following the instructions provided adding in a sample user agent and my credentials yet I keep getting a 403 Forbidden response back.
My credentials are definitely correct so is it a case of my request/credentials being set incorrectly?
This is what I have (removed personal info):
var httpClient = new HttpClient();
var content = new FormUrlEncodedContent(new[] { new KeyValuePair<string, string>("User-Agent", "MyApp [EMAIL ADDRESS]") });
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic",
Convert.ToBase64String(ASCIIEncoding.ASCII.GetBytes(string.Format("{0}:{1}", "[USERNAME]", "[PASSWORD]"))));
var response = await httpClient.PostAsync("https://basecamp.com/[USER ID]/api/v1/projects.json", content);
var responseContent = response.Content;
using (var reader = new StreamReader(await responseContent.ReadAsStreamAsync()))
{
Console.WriteLine(await reader.ReadToEndAsync());
}
A quick look over their documentation seems to indicate that the projects.json endpoint accepts the following in the body of the POST:
{
"name": "This is my new project!",
"description": "It's going to run real smooth"
}
You're sending the User-Agent as the POST body. I'd suggest you change your code as follows:
var credentials = Convert.ToBase64String(Encoding.ASCII.GetBytes(string.Format("{0}:{1}", "[USERNAME]", "[PASSWORD]")));
using (var httpClient = new HttpClient())
{
httpClient.DefaultRequestHeaders.Add("User-Agent", "MyApp [EMAIL ADDRESS]");
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", credentials);
var response = await httpClient.PostAsJsonAsync(
"https://basecamp.com/[USER ID]/api/v1/projects.json",
new {
name = "My Project",
description = "My Project Description"
});
var responseContent = await response.Content.ReadAsStringAsync();
Console.WriteLine(responseContent);
}
This posts the payload as specified in the docs and sets your user agent in the headers as it should be.

Can't authenticate correctly with headers (HttpClient)

I've checking many forums but I can't make it work. I'm trying to authenticate with headers to an url that will return a JSON string if authentication were successful. In Postman I simply used Get method with username and password in header to get the JSON data. What changes do I need to make my following C# code achieve same thing? I think I even failed to add username and password into headers.
public async Task<string> LogMeIn(string username, string password)
{
var client = new HttpClient {
BaseAddress = new Uri("http://x.com")
};
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var content = new FormUrlEncodedContent(new[] {
new KeyValuePair<string,string>("grant_type","password"),
new KeyValuePair<string,string>("Username ", username),
new KeyValuePair<string,string>("Password", password)
});
content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
var response = await client.PostAsync("/login", content); //should it be GetAsync?
var jsonResp = await response.Content.ReadAsStringAsync();
var jsonResult = JsonConvert.DeserializeObject<JsonResult>(jsonResp); //JsonResult = class for json
return jsonResult.token;
}
}

Trying to Post a Slack Message through NameValueCollection using HttpClient.PostAsync instead of WebClient

I am trying to use HttpClient to post a NameValueCollection to a specific Url. I have the code working using WebClient, but I'm trying to figure out if it is possible to do using HttpClient.
Below, you will find my working code that uses WebClient:
var payloadJson = JsonConvert.SerializeObject(new { channel, username, text });
using (var client = new WebClient())
{
var data = new NameValueCollection();
data["payload"] = payloadJson;
var response = client.UploadValues(_uri, "POST", data);
var responseText = _encoding.GetString(response);
}
I'm using this code to try to post a message to a Slack Channel using a web integration. Is there a way to implement this same functionality while using HttpClient?
The Slack error that I receive when I try to use HttpClient is "missing_text_or_fallback_or_attachment".
Thanks in advance for any help!
Using HttpClient
using (var client = new HttpClient())
{
client.BaseAddress = new Uri("http://yourdomain.com/");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var data = new NameValueCollection();
data["payload"] = payloadJson;
StringContent content = new StringContent(JsonConvert.SerializeObject(data), Encoding.UTF8, "application/json");
try
{
HttpResponseMessage response = await client.PostAsync("api/yourcontroller", content);
if (response.IsSuccessStatusCode)
{
//MessageBox.Show("Upload Successful", "Success", MessageBoxButtons.OK);
}
}
catch (Exception)
{
// ignored
}
}
While you are tagging #slack in the question, I suggest you to use Slack.Webhooks nuget package.
Example usage I found is in here;
https://volkanpaksoy.com/archive/2017/04/11/Integrating-c-applications-with-slack/
var url = "{Webhook URL created in Step 2}";
var slackClient = new SlackClient(url);
var slackMessage = new SlackMessage
{
Channel = "#general",
Text = "New message coming in!",
IconEmoji = Emoji.CreditCard,
Username = "any-name-would-do"
};
slackClient.Post(slackMessage);

HttpClient and setting Authorization headers

I'm trying to make a simple request to the Basecamp API, I'm following the instructions provided adding in a sample user agent and my credentials yet I keep getting a 403 Forbidden response back.
My credentials are definitely correct so is it a case of my request/credentials being set incorrectly?
This is what I have (removed personal info):
var httpClient = new HttpClient();
var content = new FormUrlEncodedContent(new[] { new KeyValuePair<string, string>("User-Agent", "MyApp [EMAIL ADDRESS]") });
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic",
Convert.ToBase64String(ASCIIEncoding.ASCII.GetBytes(string.Format("{0}:{1}", "[USERNAME]", "[PASSWORD]"))));
var response = await httpClient.PostAsync("https://basecamp.com/[USER ID]/api/v1/projects.json", content);
var responseContent = response.Content;
using (var reader = new StreamReader(await responseContent.ReadAsStreamAsync()))
{
Console.WriteLine(await reader.ReadToEndAsync());
}
A quick look over their documentation seems to indicate that the projects.json endpoint accepts the following in the body of the POST:
{
"name": "This is my new project!",
"description": "It's going to run real smooth"
}
You're sending the User-Agent as the POST body. I'd suggest you change your code as follows:
var credentials = Convert.ToBase64String(Encoding.ASCII.GetBytes(string.Format("{0}:{1}", "[USERNAME]", "[PASSWORD]")));
using (var httpClient = new HttpClient())
{
httpClient.DefaultRequestHeaders.Add("User-Agent", "MyApp [EMAIL ADDRESS]");
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", credentials);
var response = await httpClient.PostAsJsonAsync(
"https://basecamp.com/[USER ID]/api/v1/projects.json",
new {
name = "My Project",
description = "My Project Description"
});
var responseContent = await response.Content.ReadAsStringAsync();
Console.WriteLine(responseContent);
}
This posts the payload as specified in the docs and sets your user agent in the headers as it should be.

Categories