Redact sensitive information when using ServiceStack.Text to serialize to log files - servicestack

I am using ServiceStack.Text and ServiceStack.Logging.NLog to log the DTO requests sent to/from a web service from a .NET client application. While the machines are generally secure, I'd like to redact sensitive information that might be stored in plain-text (think name, address, basic auth creds, etc.).
I've looked at the various JsConfig<T> methods, but it seems like I'd have to implement a SerializeFn<T> for every DTO. There is risk in "missing one", and I'd want to apply it only to the scope of logging.
I've looked at NLog filters, and when just changes whether the message is logged.
Is there some universal way to replace sensitive properties/keys/attributes with a redaction marker when logging DTOs with ServiceStack.Logging \ NLog?

There's no scoped serializer options that changes what fields should be serialized.
Possible solutions I'd be looking at would be maintaining a whitelist of DTO Types with sensitive info that should not be logged or using reflection to set properties you don't want to null.
ServiceStack has APIs for converting Types in an object dictionary and rehydrate types from Dictionaries so you could do something like:
var map = requestDto.ToObjectDictionary();
ProtectedNames.ForEach(x => map.Remove(x));
You can then either serialize the remaining properties in map or convert it back into the Request DTO without the removed properties:
var safeDto = map.FromObjectDictionary(requestDto.GetType());

Related

Node typescript library environment specific configuration

I am new to node and typescript. I am working on developing a node library that reaches out to another rest API to get and post data. This library is consumed by a/any UI application to send and receive data from the API service. Now my question is, how do I maintain environment specific configuration within the library? Like for ex:
Consumer calls GET /user
user end point on the consumer side calls a method in the library to get data
But if the consumer is calling the user end point in test environment I want the library to hit the following API Url
for test http://api.test.userinformation.company.com/user
for beta http://api.beta.userinformation.company.com/user
As far as I understand the library is just a reference and is running within the consumer application. Library can for sure get the environment from the consumer, but I do not want the consumer having to specify the full URL that needs to be hit, since that would be the responsibility of the library to figure out.
Note: URL is not the only problem, I can solve that with environment switch within the library, I have some client secrets based on environments which I can neither store in the code nor checkin to source control.
Additional Information
(as per jfriend00's request in comments)
My library has a LibExecutionEngine class and one method in it, which is the entry point of the library:
export class LibExecutionEngine implements ExecutionEngine {
constructor(private environment: Environments, private trailLoader:
TrailLoader) {}
async GetUserInfo(
userId: string,
userGroupVersion: string
): Promise<UserInfo> {
return this.userLoader.loadUserInfo(userId, userGroupVersion)
}
}
export interface ExecutionEngine {
GetUserInfo(userId: string, userGroupVersion: string): Promise<UserInfo>
}
The consumer starts to use the library by creating an instance of the LibraryExecution then calling the getuserinfo for example. As you see the constructor for the class accepts an environment. Once I have the environment in the library, I need to somehow load the values for keys API Url, APIClientId and APIClientSecret from within the constructor. I know of two ways to do this:
Option 1
I could do something like this._configLoader.SetConfigVariables(environment) where configLoader.ts is a class that loads the specific configuration values from files({environment}.json), but this would mean I maintain the above mentioned URL variables and the respective clientid, clientsecret to be able to hit the URL in a json file, which I should not be checking in to source control.
Option 2
I could use dotenv npm package, and create one .env file where I define the three keys, and then the values are stored in the deployment configuration which works perfectly for an independently deployable application, but this is a library and doesn't run by itself in any environment.
Option 3
Accept a configuration object from the consumer, which means that the consumer of the library provides the URL, clientId, and clientSecret based on the environment for the library to access, but why should the responsibility of maintaining the necessary variables for library be put on the consumer?
Please suggest on how best to implement this.
So, I think I got some clarity. Lets call my Library L, and consuming app C1 and the API that the library makes a call out to get user info as A. All are internal applications in our org and have a OAuth setup to be able to communicate, our infosec team provides those clientids and secrets to individual applications, so I think my clarity here is: C1 would request their own clientid and clientsecret to hit A's URL, C1 would then pass in the three config values to the library, which the library uses to communicate with A. Same applies for some C2 in the future.
Which would mean that L somehow needs to accept a full configuration object with all required config values from its consumers C1, C2 etc.
Yes, that sounds like the proper approach. The library is just some code doing what it's told. It's the client in this case that had to fetch the clientid and clientsecret from the infosec team and maintain them and keep them safe and the client also has the URL that goes with them. So, the client passes all this into your library, ideally just once per instance and you then keep it in your instance data for the duration of that instance

Generate openApi DTO's with NestJS without a Controller

I am writing a NestJS service that provides a REST API and it publishes some messages to NATS. We are using the NestJS support to generate OpenAPI docs, and from the OpenAPI docs we generate an SDK that we import into our clients. This all works great, but only the REST API of our code is in the SDK.
What we'd like to also do is to have NestJS include the DTO's for the content for the messages we publish to NATS. Then our SDK will also include interfaces for these DTO's, and then our clients can cast the message content to the correct interface (based on the message subject). This way, the publisher of an event defines the content of the event, and users of it don't have to replicate the interface, yet they get strongly-typed code.
I've tried adding the #Api decorators to the DTO, but it appears that unless the DTO is used in the definition of an #Controller, it is not included in the resultant openApi docs.
I was hoping for a way to decorate a "random" DTO in my code so it will then be included in the swagger docs, and in-turn included in a generated SDK. Is something like that possible?
you can also pass extraModels array as a part of SwaggerDocumentOptions
SwaggerModule.createDocument(app, config, {
extraModels: [.......]
});
https://github.com/nestjs/swagger/issues/241

Foxx/ArangoDB: Can you create a response that adhere to JSON API specification?

I am currently writing some micro services with Foxx to be consumed by Ember.js. Ember data plays very nicely with JSON API (http://jsonapi.org) responses. So I tried to serialize the Foxx responses with the json-api-serializer (https://www.npmjs.com/package/json-api-serializer) - but with no luck. I only found the forClient method, but this only allows me to operate on the JSON representation of single objects, not the whole response. So my question: Is it possible to implement JSON API with Foxx/ArangoDB?
You can return arbitrary responses from Foxx routes, so it's entirely possible to generate JSON responses that conform to JSON API.
However there's no built-in way to do this automatically.
I don't see anything in json-api-serializer that shouldn't work in Foxx, so I'm not sure what problems you are encountering. You should be able to simply return the output object with res.json(outputFromSerializer) and set the content type with res.set('content-type', 'application/vnd.api+json').
If everything else fails you can just write your own helper functions to generate the boilerplate and metadata JSON API expects.

Create a new content type to consume JSON

I need to create a new content type in orchard cms that will only have a field indicating a json url to be consumed.
My question is how to consume json in content-type and return the data consumed.
Thanks
You need to issue a web request using eg. RestSharp (or built-in WebClient class) and return deserialized data. RestSharp already has a JSON deserializer built-in, but if you need more robust solution you can use JSON.NET.
The request would be best done in one of the content part handler events (eg. OnLoaded) - just set a value of some property on your custom part to the returned data from there.

Extending log4net - Adding additional data to each log

We're working on logging in our applications, using log4net. We'd like to capture certain information automatically with every call. The code calling log.Info or log.Warn should call them normally, without specify this information.
I'm looking for a way to create something we can plug into log4net. Something between the ILog applications use to log and the appenders, so that we can put this information into the log message somehow. Either into ThreadContext, or the LogEventInfo.
The information we're looking to capture is asp.net related; the request url, user agent, etc. There's also some information from the apps .config file we want to include (an application id).
I want to get between the normal ILog.Info and appender so that this information is also automatically included for 3rd party libraries which also use log4net (Nhibernate, NServiceBus, etc).
Any suggestions on where the extensibility I want would be?
Thanks
What you are looking for is called log event context. This tutorial explains how it works:
http://www.beefycode.com/post/Log4Net-Tutorial-pt-6-Log-Event-Context.aspx
In particular the chapter 'Calculated Context Values' will interesting for you.
Update:
My idea was to use the global context. It is easy to see how this works for something like application ID (in fact there you do not even need a calculated context object). Dynamic information like request url could be done like this:
public class RequestUrlContext
{
public override string ToString()
{
string url;
// retrieve url from request
return url;
}
}
The object is global but the method is called on the thread that handles the request and thus you get the correct information. I also recommend that you create one class per "information entity" so that you have a lot of flexibility with the output in the log destination.

Resources