Created
March 25, 2018 19:11
-
-
Save codingoutloud/e863bde7e53d777248bf4e87a34cee19 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#r "Newtonsoft.Json" | |
using System.Net; | |
using System.Text; | |
using Newtonsoft.Json; | |
using Newtonsoft.Json.Linq; | |
#r "Newtonsoft.Json" | |
using System.Net; | |
using System.Net.Http; | |
using System.Text; | |
using Microsoft.AspNetCore.Mvc; | |
using Microsoft.Extensions.Primitives; | |
using Newtonsoft.Json; | |
using Newtonsoft.Json.Linq; | |
public static async Task<string> GetUserAgentSummaryAsync(HttpRequest req, TraceWriter log) | |
{ | |
const bool verbose = false; | |
var agents = req.Headers["User-Agent"]; | |
if (verbose) log.Info($"AGENTS COUNT = {agents.Count}"); | |
if (verbose) log.Info($"{agents}"); | |
var agentjson = $"{{ \"user_agent\": \"{agents[0]}\" }}"; | |
if (verbose) log.Info($"AGENT JSON = [{agentjson}]"); | |
const string useragent_apikey_header = "X-API-KEY"; | |
const string useragent_apikey_location = "HOSTHEADER_APIKEY"; | |
var useragent_apikey = System.Environment.GetEnvironmentVariable(useragent_apikey_location); // CONFIGURE IN YOUR ENVIRONMENT | |
if (verbose) log.Info($"API KEY LENGTH = {useragent_apikey.Length}"); | |
const string useragent_apiurl = "https://api.whatismybrowser.com/api/v2/user_agent_parse"; | |
using (var httpClient = new HttpClient()) // okay for low-scale; else see https://docs.microsoft.com/en-us/azure/architecture/antipatterns/improper-instantiation/ | |
{ | |
var request = new HttpRequestMessage() | |
{ | |
RequestUri = new Uri(useragent_apiurl), | |
Method = HttpMethod.Post, | |
Content = new StringContent(agentjson, Encoding.UTF8, "application/json") | |
}; | |
request.Headers.Add(useragent_apikey_header, useragent_apikey); | |
// not needed, not harmful: request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); | |
using (HttpResponseMessage response = await httpClient.SendAsync(request)) | |
{ | |
response.EnsureSuccessStatusCode(); // may throw | |
var result = await response.Content.ReadAsStringAsync(); | |
if (verbose) log.Info($"RESULT = {result}"); | |
if (verbose) log.Info($"AGENTS = {agents}"); | |
var json = JObject.Parse(result); | |
bool parsedOk = ((string) (json["result"]["code"])) == "success"; | |
bool is_abusive = (bool) (json["parse"]["is_abusive"]); | |
if (is_abusive || ! parsedOk) | |
{ | |
throw new Exception($"Could not parse user agent ({parsedOk}) or was malformed ({is_abusive})"); | |
} | |
var browser = (string) json["parse"]["software_name"]; | |
var os = (string) json["parse"]["operating_system_name"]; | |
var text = $"{browser} on {os}"; | |
if (verbose) text = $"{text} [details: {result}]"; | |
return text; | |
} | |
} | |
} | |
const bool format = true; | |
public static async Task<HttpResponseMessage> Run(HttpRequestMessage req, TraceWriter log) | |
{ | |
log.Info("Handling CSP Report."); | |
//dynamic data = await req.Content.ReadAsAsync<object>(); | |
var json = req.Content.ReadAsStringAsync().Result; | |
if (format) json = JValue.Parse(json).ToString(Formatting.Indented); | |
log.Info($"CSP REPORT payload (JSON):\n{json}"); | |
var logicAppUrlBase = "https://prod-29.northcentralus.logic.azure.com:443"; | |
var logicAppUrlParams = "/workflows/90485f53082e492e8c4e52d3aa2843cb/triggers/manual/paths/invoke?api-version=2016-10-01&sp=%2Ftriggers%2Fmanual%2Frun&sv=1.0&sig=7CdQoZUrRsWgyGtCZUZcraj6A518oMwovAk9FuIjbLo"; | |
// ENRICH the usual CSP reporting JSON with User Agent, if it is available | |
string summaryUserAgent; | |
try | |
{ | |
summaryUserAgent = await GetUserAgentSummaryAsync(req, log); | |
JObject report = JObject.Parse(json); | |
JObject channel = (JObject)report["csp-report"]; | |
channel.Property("blocked-uri").AddBeforeSelf(new JProperty("user-agent-summary", summaryUserAgent)); | |
} | |
catch (Exception ex) | |
{ | |
; // continue | |
} | |
// TODO: figure out WHICH (whitelisted) Reporting endpoint posted the report | |
// forward to Logic App using above credendials | |
using (var client = new HttpClient()) | |
{ | |
client.BaseAddress = new Uri(logicAppUrlBase); | |
var content = new StringContent(json, Encoding.UTF8, "application/json"); | |
var result = await client.PostAsync(logicAppUrlParams, content); | |
string resultContent = await result.Content.ReadAsStringAsync(); | |
log.Info(resultContent); | |
if (result.IsSuccessStatusCode) | |
{ | |
return req.CreateResponse(HttpStatusCode.OK); | |
} | |
else | |
{ | |
return req.CreateResponse(HttpStatusCode.BadRequest, | |
"Failed while trying to forward to LA"); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment