Skip to content

Commit

Permalink
fix(dotnet): redact wip
Browse files Browse the repository at this point in the history
  • Loading branch information
gratcliff committed Aug 10, 2023
1 parent b593069 commit a8967f0
Show file tree
Hide file tree
Showing 8 changed files with 116 additions and 62 deletions.
3 changes: 3 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
{
"editor.codeActionsOnSave": {
"source.fixAll": true
},
"search.exclude": {
// Hide generated output
"**/package-lock.json": true,
Expand Down
106 changes: 56 additions & 50 deletions packages/dotnet/ReadMe/HarJsonTranslationLogics/RequestProcessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Primitives;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

namespace ReadMe.HarJsonObjectModels
{
Expand Down Expand Up @@ -47,80 +50,83 @@ private async Task<PostData> GetPostData()
postData.mimeType = this.request.ContentType;
if (this.request.ContentType == "application/x-www-form-urlencoded")
{
List<Params> @params = new List<Params>();
if (this.request.Form.Keys.Count > 0)
{
foreach (string key in this.request.Form.Keys)
{
if (!this.configValues.options.isAllowListEmpty)
{
if (this.CheckAllowList(key))
{
@params.Add(new Params { name = key, value = this.request.Form[key] });
}
}
else if (!this.configValues.options.isDenyListEmpty)
{
if (!this.CheckDenyList(key))
{
@params.Add(new Params { name = key, value = this.request.Form[key] });
}
}
else
{
@params.Add(new Params { name = key, value = this.request.Form[key] });
}
}
}

postData.@params = @params;
postData.@params = this.RedactPayload(this.request.Form);
}
else if (this.request.HasFormContentType)
{
List<Params> @params = new List<Params>();
if (this.request.Form.Keys.Count > 0)
postData.@params = this.RedactPayload(this.request.Form);
}
else if (this.request.ContentType == "application/json")
{
string requestBody = await this.GetRequestBodyData();
JObject parsedBody = JsonConvert.DeserializeObject<JObject>(requestBody);
IFormCollection formCollection = new FormCollection(parsedBody.Properties().ToDictionary(p => p.Name, p => new StringValues(p.Value.ToString())));

// List<Params> @params = this.RedactPayload(formCollection);
// postData.text = JsonConvert.SerializeObject(@params);
postData.text = await this.GetRequestBodyData();
}
else if (this.request.ContentType != null)
{
postData.text = await this.GetRequestBodyData();
}

return postData;
}

private bool CheckAllowList(string key)
{
return this.configValues.options.allowList.Any(v => v.Trim().ToLower() == key.Trim().ToLower()) ? true : false;
}

private bool CheckDenyList(string key)
{
return this.configValues.options.denyList.Any(v => v.Trim().ToLower() == key.Trim().ToLower()) ? true : false;
}

private string RedactValue(string value)
{
string redactedVal = value.GetType() == typeof(string) ? $" {value.Length}" : string.Empty;
return $"[REDACTED{redactedVal}]";
}

private List<Params> RedactPayload(Microsoft.AspNetCore.Http.IFormCollection payload)
{
List<Params> @params = new List<Params>();
if (payload.Keys.Count > 0)

Check warning on line 96 in packages/dotnet/ReadMe/HarJsonTranslationLogics/RequestProcessor.cs

View workflow job for this annotation

GitHub Actions / build

Elements should have the same indentation

Check warning on line 96 in packages/dotnet/ReadMe/HarJsonTranslationLogics/RequestProcessor.cs

View workflow job for this annotation

GitHub Actions / build

Elements should have the same indentation
{
foreach (string key in this.request.Form.Keys)
{
if (!this.configValues.options.isAllowListEmpty)
{
if (this.CheckAllowList(key))
{
@params.Add(new Params { name = key, value = this.request.Form[key] });
@params.Add(new Params { name = key, value = payload[key] });
}
else
{
@params.Add(new Params { name = key, value = this.RedactValue(payload[key]) });
}
}
else if (!this.configValues.options.isDenyListEmpty)
{
if (!this.CheckDenyList(key))
{
@params.Add(new Params { name = key, value = this.request.Form[key] });
@params.Add(new Params { name = key, value = payload[key] });
}
else
{
@params.Add(new Params { name = key, value = this.RedactValue(payload[key]) });
}
}
else
{
@params.Add(new Params { name = key, value = this.request.Form[key] });
@params.Add(new Params { name = key, value = payload[key] });
}
}
}

postData.@params = @params;
}
else if (this.request.ContentType != null)
{
postData.text = await this.GetRequestBodyData();
}

return postData;
}

private bool CheckAllowList(string key)
{
return this.configValues.options.allowList.Any(v => v.Trim().ToLower() == key.Trim().ToLower()) ? true : false;
}

private bool CheckDenyList(string key)
{
return this.configValues.options.denyList.Any(v => v.Trim().ToLower() == key.Trim().ToLower()) ? true : false;
return @params;
}

private async Task<string> GetRequestBodyData()
Expand Down
5 changes: 4 additions & 1 deletion packages/dotnet/examples/net6.0/appsettings.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
},
"AllowedHosts": "*",
"readme": {
"apiKey": "<Your ReadMe API Key>"
"apiKey": "<Your ReadMe API Key>",
"options": {
"denyList": ["secretKey"]
}
}
}
24 changes: 16 additions & 8 deletions packages/node/examples/express/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,22 @@ const port = process.env.PORT || 8000;
const secret = process.env.README_API_KEY;

app.use((req, res, next) => {
readme.log(process.env.README_API_KEY, req, res, {
// User's API Key
apiKey: 'owlbert-api-key',
// Username to show in the dashboard
label: 'Owlbert',
// User's email address
email: '[email protected]',
});
readme.log(
process.env.README_API_KEY,
req,
res,
{
// User's API Key
apiKey: 'owlbert-api-key',
// Username to show in the dashboard
label: 'Owlbert',
// User's email address
email: '[email protected]',
},
{
denylist: ['secretKey'],
}
);

return next();
});
Expand Down
2 changes: 1 addition & 1 deletion packages/node/examples/fastify/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ fastify.addHook('onSend', async (request, reply, payload) => {
// Fastify uses `writeHead` for performance reasons, which means those header values
// are not accessible via `reply.raw`
Object.entries(reply.getHeaders()).forEach(([name, val]) => reply.raw.setHeader(name, val));
readmeio.log(process.env.README_API_KEY, req, res, payloadData);
readmeio.log(process.env.README_API_KEY, req, res, payloadData, { denylist: ['secretKey'] });
return payload;
});

Expand Down
2 changes: 1 addition & 1 deletion packages/node/examples/hapi/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ const init = async () => {
};

req.body = request.payload;
readmeio.log(process.env.README_API_KEY, req, res, payloadData);
readmeio.log(process.env.README_API_KEY, req, res, payloadData, { denylist: ['secretKey'] });

return h.continue;
});
Expand Down
1 change: 1 addition & 0 deletions packages/python/examples/flask/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ def grouping_function(request):
metrics_extension = ReadMeMetrics(
MetricsApiConfig(
api_key=os.getenv("README_API_KEY"),
denylist=["secretKey"],
grouping_function=grouping_function,
background_worker_mode=False,
buffer_length=1,
Expand Down
35 changes: 34 additions & 1 deletion test/integration-metrics.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -350,6 +350,35 @@ describe('Metrics SDK Integration Tests', function () {
expect(response.status).to.equal(200);
});

it('should respect denyLIst', async function () {
const content = JSON.stringify({ secretKey: 'mySecretKey', user: { email: '[email protected]' } });
await fetch(`http://localhost:${PORT}/`, {
method: 'post',
headers: {
'content-type': 'application/json',
},
body: content,
});

const [, body] = await getRequest();
const [payload] = body;

const har = payload.request;
await expect(har).to.have.a.har.request;
await expect(har).to.have.a.har.response;

const { request, response } = har.log.entries[0];

expect(request.method).to.equal('POST');
expect(request.headers).to.have.header('content-type', 'application/json');
expect(request.postData).to.deep.equal({
mimeType: 'application/json',
text: JSON.stringify({ secretKey: '[REDACTED 11]', user: { email: '[email protected]' } }),
});

expect(response.status).to.equal(200);
});

/**
* We should eventually support returning the raw POST payload to Metrics in this case but Express
* has a fun quirk where if you declare the `express.json()` middleware on a route to identify
Expand Down Expand Up @@ -398,6 +427,7 @@ describe('Metrics SDK Integration Tests', function () {
it('should process an `application/x-www-url-formencoded` POST payload', async function () {
const params = new URLSearchParams();
params.append('email', '[email protected]');
params.append('secretKey', 'helloWorld');

await fetch(`http://localhost:${PORT}/`, {
method: 'post',
Expand All @@ -420,7 +450,10 @@ describe('Metrics SDK Integration Tests', function () {
expect(request.headers).to.have.header('content-type', 'application/x-www-form-urlencoded');
expect(request.postData).to.deep.equal({
mimeType: 'application/x-www-form-urlencoded',
params: [{ name: 'email', value: '[email protected]' }],
params: [
{ name: 'email', value: '[email protected]' },
{ name: 'secretKey', value: '[REDACTED 10]' },
],
});

expect(response.status).to.be.oneOf([
Expand Down

0 comments on commit a8967f0

Please sign in to comment.