Audit.Net log SOAP client webservice calls - soap-client

My app is uses a third party SOAP webservice.
How do I use Audit.Net to log all the request/response made by my app, the SOAP client?
Similar to Audit.HttpClient extension.
Regards

One option could be to use Audit.DynamicProxy to intercept the proxy calls, so for example if you use the ChannelFactory to create the proxy, you could do the following:
using Audit.DynamicProxy;
public T CreateProxy<T>(Uri uri, HttpBindingBase binding)
{
var channelFactory = new ChannelFactory<T>(binding, new EndpointAddress(uri));
return AuditProxy.Create<T>(channelFactory.CreateChannel());
}
Then when you do a service call, for example:
var proxy = CreateProxy<ICatalogService>(uri, binding);
var product = proxy.GetDetailedProductInfo(new GetDetailedProductInfoRequest() { ProductId = "1234" };
You should get an audit event with format similar to:
{
"EventType": "generatedProxy_1.GetDetailedProductInfo",
"Environment": {
...
},
"StartDate": "2021-07-16T19:48:15.294298Z",
"EndDate": "2021-07-16T19:48:21.6566853Z",
"Duration": 6362,
"InterceptEvent": {
"ClassName": "generatedProxy_1",
"MethodName": "GetDetailedProductInfo",
"IsAsync": false,
"InstanceQualifiedName": "generatedProxy_1, ProxyBuilder, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null",
"MethodSignature": "CatalogService.GetDetailedProductInfoResponse GetDetailedProductInfo(CatalogService.GetDetailedProductInfoRequest)",
"Arguments": [
{
"Index": 0,
"Type": "GetDetailedProductInfoRequest",
"Value": {
"request": {
"ProductId": "1234"
}
}
}
],
"Success": true,
"Result": {
"Type": "GetDetailedProductInfoResponse",
"Value": {
"GetDetailedProductInfoResult": {
"Product": {
"ProductId": "1234",
"Description": "Some description".
"CreationDate": "2007-10-31T11:30:35-06:00"
}
}
}
}
}
}

You can now use the extension library Audit.WCF.Client which allows auditing client-side WCF service calls.
Please check the documentation here.
It's basically an IClientMessageInspector that intercepts the request and response messages.

Related

How to parameterize the values in workflow.json and connections.json files of azure logic app standard project

I have created azure logic app single tenant project using visual studio code by following this documentation. And then created workflow based on my requirement, this contains the data factory pipeline and send grid actions.
The workflow contains the hardcoded values in the create a pipeline run data factory action.
"Create_a_pipeline_run": {
"inputs": {
"host": {
"connection": {
"referenceName": "azuredatafactory_5"
}
},
"method": "post",
"path": "/subscriptions/#{encodeURIComponent('xxxxxxx-xxxx-xxxx-xxxx-xxxxxx')}/resourcegroups/#{encodeURIComponent('xxxxx')}/providers/Microsoft.DataFactory/factories/#{encodeURIComponent('xxxxxx')}/pipelines/#{encodeURIComponent('xxxxxxx')}/CreateRun",
"queries": {
"x-ms-api-version": "2017-09-01-preview"
}
},
"runAfter": {},
"type": "ApiConnection"
},
And the connections.json file looks file below:
"managedApiConnections": {
"sendgrid": {
"api": {
"id": "/subscriptions/#appsetting('WORKFLOWS_SUBSCRIPTION_ID')/providers/Microsoft.Web/locations/centralus/managedApis/sendgrid"
},
"authentication": {
"type": "ManagedServiceIdentity"
}
},
"azuredatafactory_5": {
"api": {
"id": "/subscriptions/#appsetting('WORKFLOWS_SUBSCRIPTION_ID')/providers/Microsoft.Web/locations/centralus/managedApis/azuredatafactory"
},
"authentication": {
"type": "ManagedServiceIdentity"
}
}
}
The above managed API connections refers the existing API connections from azure. But I want to create the new managed API connections per environment (means parameterize the values in the connections.json file based on the environment).
Can anyone suggest me how to parameterize the values in workflow.json files per environment and parameterize the values in connections.json file per environment.
A logic app standard is just an app service of kind workflowApp.
You can heavily make use of appsettings here.
Logic app parameters.
In your workflow.json, you can use parameters like that:
"Create_a_pipeline_run": {
"inputs": {
"host": {
"connection": {
"referenceName": "azuredatafactory_5"
}
},
"method": "post",
"path": "/subscriptions/#{encodeURIComponent(parameters('subscription_id'))}/resourcegroups/...",
"queries": {
"x-ms-api-version": "2017-09-01-preview"
}
},
"runAfter": {},
"type": "ApiConnection"
}
Then in your parameters.json file, reference app settings like that:
{
"subscription_id": {
"type": "String",
"value": "#appsetting('WORKFLOWS_SUBSCRIPTION_ID')"
}
}
subscription_id must be defined as an app setting in the app service.
Logic app connections.
In the same way you can use app settings and parameters for connection information in your connections.json file:
{
"managedApiConnections": {
"sendgrid": {
"api": {
"id": "/subscriptions/#appsetting('WORKFLOWS_SUBSCRIPTION_ID')/providers/Microsoft.Web/locations/centralus/managedApis/sendgrid"
},
...
"authentication": "#parameters('azure_authentication')"
}
}
}
then in your parameters.json file:
{
"azure_authentication": {
"type": "object",
"value": {
"type": "ManagedServiceIdentity"
}
}
...
}
This way you can easily offload all environment specific parameters to app settings

How to use openapi3 json specification to validate if Express application has set up correct routes?

Summary
I use orval to generate frontend code in order to fetch data from the backend. The API specification is using the openapi 3 format.
I want to be able to automatically validate if my express backend is implementing the correct endpoints by comparing the specification with the actual implementation.
Example
Let's assume that this is the specification api.json:
{
"openapi": "3.0.0",
"info": {
"version": "1.0.0",
"title": "My Service"
},
"servers": [
{
"url": "http://my.service.com/api"
}
],
"paths": {
"/my-endpoint": {
"get": {
"summary": "List all things",
"operationId": "listThings",
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Thing"
}
}
}
},
"default": {
"description": "unexpected error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
}
},
"components": {
"schemas": {
"Thing": {
"type": "object",
"required": [
"id",
"name"
],
"properties": {
"id": {
"type": "string"
},
"name": {
"type": "string"
}
}
},
"Error": {
"type": "object",
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string"
}
}
}
}
}
}
Orval generates frontend code to fetch defined endpoints via axios and the according Typescript interfaces for request and response data.
So far so good.
Problem
My express backend does not know about the openapi specification. I need to manually create the correct express endpoints and make sure that they return the correct HTTP codes, correct response types and correct error handling.
I learned there are code generators like swagger-routes-express, but my concern with those is that they hide the endpoint definition and that it could be difficult to implement extra business logic to those endpoints. I may be wrong here, but i still didn't get how that would work in this scenario.
Desired solution
I think there are two variants that would be a great outcome:
A code generator that parses the api.json above and generates correct endpoints with proper Typescript types. It needs to be able to accept custom code in those endpoints which shouldn't be overwritten the next time the specification changes and code is regenerated.
A linter that checks the code if the correct endpoints exist and have the correct request and response types. Maybe a set of eslint rules.
Is there anything out there i could use for this?

Azure REST API for running builds or pipelines

I am trying to automate the creation of Azure Pipelines for a particular branch using their REST api.
However, I am struggling to use almost all their API's, as their documentation lacks examples.
Things like List and Get are simple enough.
However, when it comes to queuing a build:
https://learn.microsoft.com/en-us/rest/api/azure/devops/build/builds/queue?view=azure-devops-rest-6.0
POST https://dev.azure.com/{organization}/{project}/_apis/build/builds?api-version=6.0
{
"parameters": <parameters>, // how do i send paramters
"definition": {
"id": 1
},
"sourceBranch": "refs/heads/feature/my-pipeline",
"sourceVersion": "d265f01aeb4e677a25725f44f20ceb3ff1d7d767"
}
I am currently struggling to send parameters.
I have tried:
Simple JSON like:
"parameters": {
"appId": "bab",
"platform": "android",
"isDemo": true
}
and stringify version of JSON like:
"parameters": "{\"appId\": \"bab\",\"platform\": \"android\",\"isDemo\": true}"
but none seems to work.
It keeps giving me the error:
{
"$id": "1",
"customProperties": {
"ValidationResults": [
{
"result": "error",
"message": "A value for the 'appId' parameter must be provided."
},
{
"result": "error",
"message": "A value for the 'platform' parameter must be provided."
},
{
"result": "error",
"message": "A value for the 'isDemo' parameter must be provided."
}
]
},
"innerException": null,
"message": "Could not queue the build because there were validation errors or warnings.",
"typeName": "Microsoft.TeamFoundation.Build.WebApi.BuildRequestValidationFailedException, Microsoft.TeamFoundation.Build2.WebApi",
"typeKey": "BuildRequestValidationFailedException",
"errorCode": 0,
"eventId": 3000
}
The docs is very unclear in how to send this data: https://learn.microsoft.com/en-us/rest/api/azure/devops/build/builds/queue?view=azure-devops-rest-6.1#propertiescollection
Thank you very much for you help.
I believe you cannot pass runtime parameters trough the Queue API. Instead, use Runs API
With that, your request body (use Content-type: application/json) should look something similar to this:
{
"resources": {
"repositories": {
"self": {
"refName": "refs/heads/feature/my-pipeline"
}
}
},
"templateParameters": {
"appId": "bab"
"platform": "android"
"isDemo": true
}
}
I just realized that in the api-version=6.0 you can also send templateParameters on the Queue Service:
POST https://dev.azure.com/{organization}/{project}/_apis/build/builds?sourceBuildId={BUILD_BUILDID}&api-version=6.0
{
"templateParameters": { "doReleaseBuild": "True" },
"definition": {
"id": 1
},
"sourceBranch": "refs/heads/feature/my-pipeline",
"sourceVersion": "d265f01aeb4e677a25725f44f20ceb3ff1d7d767"
}

How to add in a listen or timeout function in autopilot?

I have a syntax issue I believe in getting my autopilot response to work. My program works but after the autopilot asks the question, it does not give much time for the user to say the response before stopping/hanging up the call.
Is there a way to add in a timeout or pause? I have tried the syntax for this but it does not work. This is what I have:
"actions": [
{
"collect": {
"name": "user_input",
"questions": [
{
"question": "Welcome to the modem status check line?",
"name": "search",
"type": "Twilio.NUMBER"
}
],
"on_complete": {
"redirect": {
"method": "POST",
"uri": "https://website......"
}
}
}
}
]
}
When I add below
{
"listen":true
}
anywhere in this syntax it does not work and gives me an error of:
.actions[0].collect.questions[0] should NOT have additional properties
I have also tried timeout: 3 and it does not work either.
I have tried
{
"listen":true
}
and
"listen": {
before my task
Twilio developer evangelist here.
You can't use the Listen attribute in a Collect flow, and there is no easy way to add a timeout or pause. You can, however, add on a Validate action to your Collect flow like so and increase the number of max_attempts so your Autopilot bot repeats the question or asks the user to try again/say their response again.
I'm wondering why this is happening because when I use my bots via phone call, the call stays open for quite a long time waiting for the user's response.
exports.handler = function(context, event, callback) {
const responseObject = {
"actions": [
{
"collect": {
"name": "collect_clothes_order",
"questions": [
{
"question": "What is your first name?",
"name": "first_name",
"type": "Twilio.FIRST_NAME"
},
{
"question": "What type of clothes would you like?",
"name": "clothes_type",
"type": "CLOTHING",
"validate": {
"on_failure": {
"messages": [
{
"say": "Sorry, that's not a clothing type we have. We have shirts, shoes, pants, skirts, and dresses."
}
],
"repeat_question": true
},
"on_success": {
"say": "Great, I've got your the clothing type you want."
},
"max_attempts": {
"redirect": "task://collect_fallback",
"num_attempts": 3
}
}
}
],
"on_complete": {
"redirect": "https://rosewood-starling-9398.twil.io/collect"
}
}
}
]
};
callback(null, responseObject);
};
Let me know if this helps at all!

Parse text in Azure Logic Apps

I want to create Azure Logic App which will constantly request a specific website on the Internet and parse received HTML.
I've created Logic App and set up interval and HTTP request action.
Which action should I choose as the next step for simple regex operation on HTML code?
What comes to my mind is creating Azure Function which will do the job, but I wonder if there is any other solution, more suitable for such task.
I want it the be simple as possible.
Edit:
Just found out some cool feature. Logic Apps contain some basic expressions for primitive types.
Unfortunetly it lacks of any regex or string.contains.
For now, I'll try with Azure Functions.
I've managed to solve my problem with use of Workflow Definition Language and building blocks provided by Azure.
The Azure Function idea was not that bad and would fit perfectly for any more complex case, but as I mentioned, I wanted it as simple as possible, so here it is.
This is how my flow looks now.
For sake of completeness, here is the flow in JSON format
{
"$connections": {
"value": {
"wunderlist": {
"connectionId": "/subscriptions/.../providers/Microsoft.Web/connections/wunderlist",
"connectionName": "wunderlist",
"id": "/subscriptions/.../providers/Microsoft.Web/locations/northeurope/managedApis/wunderlist"
}
}
},
"definition": {
"$schema": "https://schema.management.azure.com/providers/Microsoft.Logic/schemas/2016-06-01/workflowdefinition.json#",
"actions": {
"Condition": {
"actions": {
"Create_a_task": {
"inputs": {
"body": {
"completed": false,
"list_id": 000000000,
"starred": true,
"title": "#{variables('today date')}"
},
"host": {
"connection": {
"name": "#parameters('$connections')['wunderlist']['connectionId']"
}
},
"method": "post",
"path": "/tasks",
"retryPolicy": {
"type": "none"
}
},
"limit": {
"timeout": "PT20S"
},
"runAfter": {},
"type": "ApiConnection"
},
"Set_a_reminder": {
"inputs": {
"body": {
"date": "#{addHours(utcNow(), 3)}",
"list_id": 000000,
"task_id": "#body('Create_a_task')?.id"
},
"host": {
"connection": {
"name": "#parameters('$connections')['wunderlist']['connectionId']"
}
},
"method": "post",
"path": "/reminders",
"retryPolicy": {
"type": "none"
}
},
"limit": {
"timeout": "PT20S"
},
"runAfter": {
"Create_a_task": [
"Succeeded"
]
},
"type": "ApiConnection"
}
},
"expression": "#contains(body('HTTP'), variables('today date'))",
"runAfter": {
"Initialize_variable": [
"Succeeded"
]
},
"type": "If"
},
"HTTP": {
"inputs": {
"method": "GET",
"uri": "..."
},
"runAfter": {},
"type": "Http"
},
"Initialize_variable": {
"inputs": {
"variables": [
{
"name": "today date",
"type": "String",
"value": "#{utcNow('yyyy/MM/dd')}"
}
]
},
"runAfter": {
"HTTP": [
"Succeeded"
]
},
"type": "InitializeVariable"
}
},
"contentVersion": "1.0.0.0",
"outputs": {},
"parameters": {
"$connections": {
"defaultValue": {},
"type": "Object"
}
},
"triggers": {
"Recurrence": {
"recurrence": {
"frequency": "Day",
"interval": 1,
"startTime": "2017-08-01T23:55:00Z",
"timeZone": "UTC"
},
"type": "Recurrence"
}
}
}
}
You can use inline code action in logic app to run javascript regex code (preview- May 2019) (Not supported on Flow).
Iniline Code
Logic App Inline Code Ref
You're probably on the right track. An Azure Function would be the most appropriate way to implement this right now. An API App is an option but that's a heavier platform than you need.
create an Azure Function along the lines of:
{
log.Info("C# HTTP trigger function processed a request.");
// Get request body
dynamic data = await req.Content.ReadAsAsync<object>();
// Set name to query string or body data
string input = data?.input.ToString();
var regexJson = data?.regexList;
var regexes = regexJson.ToObject<List<RegexReplace>>();
foreach (var regex in regexes)
{
var re = Regex.Replace(regex.Regex, "\\\\","\\");
var replace = Regex.Replace(regex.Replace, "\\\\","\\");
input = Regex.Replace(input, "\\\"","\"");
input = Regex.Replace(input, re, replace);
}
input = Regex.Replace(input, "[\\r\\n]", "");
return data.regexList == null
? req.CreateResponse(HttpStatusCode.BadRequest, "Please pass a name on the query string or in the request body")
: req.CreateResponse(HttpStatusCode.OK, input, "application/json");
}
public class RegexReplace
{
public string Regex { get; set; }
public string Replace { get; set; }
}
This is my function to use for replacing text in a string. this is reusable and the approach can be used for many similar type of aspects of working in Logic Apps:
using System.Net;
public static async Task<HttpResponseMessage> Run(HttpRequestMessage req, TraceWriter log)
{
dynamic data = await req.Content.ReadAsAsync<object>();
string removeme = data?.removeme;
string replacewith = data?.replacewith;
string value = data?.value;
return req.CreateResponse(HttpStatusCode.OK, value.Replace(removeme, replacewith));
}
I would then post an object like this from my logic app:
{
"removeme": "SKU-",
"replacewith": "P-",
"value": "SKU-37378633"
}
... to get the result: "P-37378633"

Resources