diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 00000000..84304e23 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "debug.node.autoAttach": "on" +} \ No newline at end of file diff --git a/README.md b/README.md index f51bca58..dfdcc5d6 100755 --- a/README.md +++ b/README.md @@ -76,12 +76,12 @@ For the following steps, please open the ANM configuration in Policy-Studio. You - The `Compare Attribute` filter checks if the requested API can be handled by the API-Builder project. As a basis for decision-making a criteria for each endpoint needs to be added to the filter configuration. - _At this point in time three endpoints are supported by the API Builder based Traffic-Monitor API. - The **search** endpoint which provides the data for the HTTP Traffic overview, the **circuitpath** endpoint which provides the data for the Filter Execution Path as part of the detailed view of a transaction and the **trace** endpoint which returns the trace information. Currently the API Builder Project does not cover all endpoints to completely replace the existing Traffic Monitor API yet, but more endpoints will be added soon!_ + _The following endpoints are supported by the API Builder based Traffic-Monitor API. + The **search** endpoint which provides the data for the HTTP Traffic overview, the **circuitpath** endpoint which provides the data for the Filter Execution Path as part of the detailed view of a transaction, the **trace** endpoint which returns the trace information and the **getinfo** endpoint which returns the request detail information including the http header of each leg._ For search endpoint add: `http.request.path` matches regular expression `^\/api\/router\/service\/[A-Za-z0-9-.]+\/ops\/search$` For circuitpath endpoint add: `http.request.path` matches regular expression `^\/api\/router\/service\/[A-Za-z0-9-.]+\/ops\/stream\/[A-Za-z0-9]+\/[^\/]+\/circuitpath$` For trace endpoint add: `http.request.path` matches regular expression `^\/api\/router\/service\/[A-Za-z0-9-.]+\/ops\/trace\/[A-Za-z0-9]+[\?]?.*$` - _The list of requests will be extended once the API-Builder project can serve more (e.g. the Request-Detail view)._ + For getinfo endpoint add: `http.request.path` matches regular expression `^\/api\/router\/service\/[A-Za-z0-9-.]+\/ops\/[A-Za-z0-9]+\/[A-Za-z0-9]+\/[\*0-9]{1}\/getinfo[\?]?.*$` ![Is API Managed][img6] - Adjust the URL of the Connect to URL filter to your running API-Builder docker container and port - **default is 8889**. Sample: `http://api-env:8889/api/elk/v1${http.request.rawURI}` ![Connect to ES API][img7] diff --git a/elk-traffic-monitor-api/flows/trafficMonitorApi-getinfo.json b/elk-traffic-monitor-api/flows/trafficMonitorApi-getinfo.json index 8b328dda..2707d71f 100644 --- a/elk-traffic-monitor-api/flows/trafficMonitorApi-getinfo.json +++ b/elk-traffic-monitor-api/flows/trafficMonitorApi-getinfo.json @@ -30,34 +30,164 @@ "env" ] }, - "start": "setcontext.1", + "start": "javascript.1", "nodes": { - "setcontext.1": { - "type": "nodehandler://axway-flow/setcontext", - "name": "Set Context", - "method": "setcontext", + "javascript.1": { + "type": "nodehandler://@axway/api-builder-plugin-fn-javascript/javascript", + "name": "Define Index", + "method": "Execute", "parameters": [ { - "name": "value", - "type": "array", - "value": "[\n\n{\n\t\"details\": {\"uri\":\"/healthcheck\",\"status\":200,\"statustext\":\"OK\",\"method\":\"GET\",\"vhost\":null,\"wafStatus\":0,\"bytesSent\":1331,\"bytesReceived\":1233,\"remoteName\":\"192.168.233.1\",\"remoteAddr\":\"192.168.233.1\",\"localAddr\":\"192.168.233.137\",\"remotePort\":\"57400\",\"localPort\":\"8080\",\"sslsubject\":null,\"leg\":0,\"timestamp\":1588666217689,\"duration\":49,\"correlationId\":\"691fb15ed40003055c0ea6f0\",\"serviceName\":null,\"subject\":null,\"operation\":null,\"type\":\"http\",\"finalStatus\":\"Pass\"\n\t},\n\t\"rheaders\": [\n{ \"Host\":\"api-env.demo.axway.com:8080\"},\n{ \"Connection\":\"keep-alive\"},\n{ \"Upgrade-Insecure-Requests\":\"1\"},\n{ \"User-Agent\":\"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.129 Safari/537.36\"},\n{ \"Accept\":\"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9\"},\n{ \"Accept-Encoding\":\"gzip, deflate\"},\n{ \"Accept-Language\":\"de-DE,de;q=0.9,en-US;q=0.8,en;q=0.7\"},\n{ \"Cookie\":\"_ga=GA1.2.2089149224.1588233255; _hjid=45582ae7-17d6-4d5b-be7d-891a307d4109; _gcl_au=1.1.169451176.1588238948; _mkto_trk=id:727-TDV-465&token:_mch-axway.com-1588238948318-18018; _fbp=fb.1.1588238949560.1566065746; mousestats_vi=2f25c2ce7a7dc21cdb83; _gaexp=GAX1.2.8iCZUhMtRFiOOhBG7oZNyg.18455.1; wisepops_visits=%5B%222020-04-30T09%3A31%3A36.972Z%22%2C%222020-04-30T09%3A31%3A24.285Z%22%5D; wisepops=%7B%22csd%22%3A1%2C%22popups%22%3A%7B%22201026%22%3A%7B%22dc%22%3A1%2C%22d%22%3A%222020-04-30T09%3A31%3A24.876Z%22%7D%2C%22202147%22%3A%7B%22dc%22%3A1%2C%22d%22%3A%222020-04-30T09%3A31%3A37.237Z%22%7D%7D%2C%22sub%22%3A0%2C%22ucrn%22%3A90%2C%22cid%22%3A%2248348%22%2C%22v%22%3A4%7D; portal.logintypesso=false; portal.demo=off; portal.isgridSortIgnoreCase=on\"}\n\t],\n\t\"sheaders\": [\n{ \"Date\":\"Tue, 05 May 2020 08:10:17 GMT\"},\n{ \"Server\":\"Gateway\"},\n{ \"Connection\":\"close\"},\n{ \"X-CorrelationID\":\"Id-691fb15ed40003055c0ea6f0 0\"},\n{ \"Accept\":\"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9\"},\n{ \"Accept-Language\":\"de-DE,de;q=0.9,en-US;q=0.8,en;q=0.7\"},\n{ \"Cookie\":\"_ga=GA1.2.2089149224.1588233255; _hjid=45582ae7-17d6-4d5b-be7d-891a307d4109; _gcl_au=1.1.169451176.1588238948; _mkto_trk=id:727-TDV-465&token:_mch-axway.com-1588238948318-18018; _fbp=fb.1.1588238949560.1566065746; mousestats_vi=2f25c2ce7a7dc21cdb83; _gaexp=GAX1.2.8iCZUhMtRFiOOhBG7oZNyg.18455.1; wisepops_visits=%5B%222020-04-30T09%3A31%3A36.972Z%22%2C%222020-04-30T09%3A31%3A24.285Z%22%5D; wisepops=%7B%22csd%22%3A1%2C%22popups%22%3A%7B%22201026%22%3A%7B%22dc%22%3A1%2C%22d%22%3A%222020-04-30T09%3A31%3A24.876Z%22%7D%2C%22202147%22%3A%7B%22dc%22%3A1%2C%22d%22%3A%222020-04-30T09%3A31%3A37.237Z%22%7D%7D%2C%22sub%22%3A0%2C%22ucrn%22%3A90%2C%22cid%22%3A%2248348%22%2C%22v%22%3A4%7D; portal.logintypesso=false; portal.demo=off; portal.isgridSortIgnoreCase=on\"},\n{ \"Host\":\"api-env.demo.axway.com:8080\"},\n{ \"Upgrade-Insecure-Requests\":\"1\"},\n{ \"User-Agent\":\"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.129 Safari/537.36\"},\n{ \"Content-Type\":\"text/xml\"}\n\t]\n}]", - "metaName": "value" + "name": "data", + "type": "jsonpath", + "value": "$", + "metaName": "data", + "metaDescription": "The value to apply as the `data` argument to the JavaScript code. For objects and arrays, `data` is passed by reference." + }, + { + "name": "code", + "type": "string", + "value": "\"let index = 'logstash-openlog';\\n //let index = 'getinfo_test_1688';\\n \\n if(data.config.testElasticIndex) {\\n index = data.config.testElasticIndex;\\n }\\n \\n return index;\"", + "metaName": "code", + "metaDescription": "A JavaScript function body. Supports `await` and returning promises" } ], "outputs": { "next": { - "context": "$.GetInfoPayload", + "context": "$.index", + "routes": [ + "javascript.2" + ], + "metaName": "Next" + }, + "error": { + "context": "$.error", "routes": [ "http.1" ], + "metaName": "Error" + } + }, + "metaMethod": "Execute" + }, + "javascript.2": { + "type": "nodehandler://@axway/api-builder-plugin-fn-javascript/javascript", + "name": "Check Params", + "method": "Execute", + "parameters": [ + { + "name": "data", + "type": "jsonpath", + "value": "$", + "metaName": "data", + "metaDescription": "The value to apply as the `data` argument to the JavaScript code. For objects and arrays, `data` is passed by reference." + }, + { + "name": "code", + "type": "string", + "value": "\"//only json is supported. \\n //If param format is skipped automatically json is returned\\n\\n if(data.params.format != undefined && data.params.format != 'json') {\\n throw {\\n name: \\\"unknown format exception\\\",\\n message: \\\"unknown format\\\"\\n };\\n }\\n\\n return data.params;\"", + "metaName": "code", + "metaDescription": "A JavaScript function body. Supports `await` and returning promises" + } + ], + "outputs": { + "next": { + "context": "$.params", + "routes": [ + "javascript.3" + ], "metaName": "Next" + }, + "error": { + "context": "$.error", + "routes": [ + "http.3" + ], + "metaName": "Error" } }, - "metaMethod": "Set Context" + "metaMethod": "Execute" }, - "http.1": { + "javascript.3": { + "type": "nodehandler://@axway/api-builder-plugin-fn-javascript/javascript", + "name": "Build ES query", + "method": "Execute", + "parameters": [ + { + "name": "data", + "type": "jsonpath", + "value": "$", + "metaName": "data", + "metaDescription": "The value to apply as the `data` argument to the JavaScript code. For objects and arrays, `data` is passed by reference." + }, + { + "name": "code", + "type": "string", + "value": "\"let elasticQuery = ({\\n \\\"bool\\\": {\\n \\\"must\\\": [\\n {\\\"term\\\": {\\\"correlationId\\\": data.params.correlationID}},\\n {\\\"term\\\": {\\\"processInfo.serviceId\\\": data.params.serviceID}}\\n ]\\n }\\n });\\n \\n \\n return elasticQuery;\"", + "metaName": "code", + "metaDescription": "A JavaScript function body. Supports `await` and returning promises" + } + ], + "outputs": { + "next": { + "context": "$.elasticsearch.query", + "routes": [ + "elasticsearch.1", + "javascript.4" + ], + "metaName": "Next" + }, + "error": { + "context": "$.error", + "routes": [ + "http.1" + ], + "metaName": "Error" + } + }, + "metaMethod": "Execute" + }, + "elasticsearch.1": { + "type": "nodehandler://@axway-api-builder-ext/api-builder-plugin-fn-elasticsearch/elasticsearch", + "name": "Search Info", + "method": "search", + "parameters": [ + { + "name": "index", + "type": "jsonpath", + "value": "$.index", + "metaName": "index", + "metaDescription": "Comma-separated list or wildcard expression of index names used to limit the request." + }, + { + "name": "query", + "type": "jsonpath", + "value": "$.elasticsearch.query", + "metaName": "query", + "metaDescription": "Defines the search definition using the Query DSL. Learn more: https://www.elastic.co/guide/en/elasticsearch/reference/7.x/query-dsl.html" + } + ], + "outputs": { + "next": { + "context": "$.elasticsearch.result", + "routes": [ + "javascript.4" + ], + "metaName": "Next" + }, + "error": { + "context": "$.error", + "routes": [ + "http.1" + ], + "metaName": "Error" + } + }, + "metaMethod": "Search" + }, + "http.2": { "type": "nodehandler://axway-flow/http", - "name": "Set HTTP Response", + "name": "Set HTTP 200 Response", "method": "setresponse", "parameters": [ { @@ -70,7 +200,96 @@ { "name": "body", "type": "jsonpath", - "value": "$.GetInfoPayload", + "value": "$.result", + "metaName": "body", + "metaDescription": "The response payload" + } + ], + "outputs": { + "next": { + "context": "$.response", + "routes": [], + "metaName": "Next" + } + }, + "metaMethod": "Set HTTP Response" + }, + "javascript.4": { + "type": "nodehandler://@axway/api-builder-plugin-fn-javascript/javascript", + "name": "Format Response", + "method": "Execute", + "parameters": [ + { + "name": "data", + "type": "jsonpath", + "value": "$", + "metaName": "data", + "metaDescription": "The value to apply as the `data` argument to the JavaScript code. For objects and arrays, `data` is passed by reference." + }, + { + "name": "code", + "type": "string", + "value": "\"//init variables\\n \\n let transactionInfo = {};\\n let sourceLegs = [];\\n let resultLegs = [];\\n let legParam = data.params.legID;\\n let detailsParam = data.params.details;\\n let sheadersParam = data.params.sheaders;\\n let rheadersParam = data.params.rheaders;\\n let elasticData = data.elasticsearch.result.body.hits;\\n \\n \\n transactionInfo = elasticData.hits[0]._source;\\n sourceLegs = transactionInfo.transactionElements;\\n \\n // Loop over legs\\n for (var item in sourceLegs) {\\n let sourceLeg = sourceLegs[item];\\n let resultLeg = {};\\n let details = {};\\n\\n\\tlet rheaders = [];\\n let sheaders = [];\\n \\n if (legParam == '*' || legParam == sourceLeg.leg)\\n {\\n \\n if (detailsParam == '1'){\\n details.uri = sourceLeg.protocolInfo.http.uri;\\n details.status = sourceLeg.protocolInfo.http.status;\\n details.statustext = sourceLeg.protocolInfo.http.statusText;\\n details.method = sourceLeg.protocolInfo.http.method;\\n details.vhost = (typeof sourceLeg.protocolInfo.http.vhost === 'undefined') ? null : sourceLeg.protocolInfo.http.vhost; // needs to be checked - not avail in test data\\n details.wafStatus = sourceLeg.protocolInfo.http.wafStatus;\\n details.bytesSent = sourceLeg.protocolInfo.http.bytesSent;\\n details.bytesReceived = sourceLeg.protocolInfo.http.bytesReceived;\\n details.remoteName = sourceLeg.protocolInfo.http.remoteName;\\n details.remoteAddr = sourceLeg.protocolInfo.http.remoteAddr;\\n details.localAddr = sourceLeg.protocolInfo.http.localAddr;\\n details.remotePort = sourceLeg.protocolInfo.http.remotePort;\\n details.localPort = sourceLeg.protocolInfo.http.localPort; \\n details.sslsubject = (typeof sourceLeg.protocolInfo.http.sslSubject === 'undefined') ? null : sourceLeg.protocolInfo.http.sslSubject; //need to be checked - not avail in test data \\n details.leg = sourceLeg.leg;\\n details.timestamp = Date.parse(transactionInfo.timestampOriginal); //Needs to be formatted\\n details.duration = sourceLeg.duration;\\n details.correlationId = transactionInfo.correlationId;\\n details.serviceName = sourceLeg.serviceName;\\n details.subject = sourceLeg.protocolInfo.http.authSubjectId;\\n details.operation = sourceLeg.operation;\\n details.type = 'http'; //ToDo - currently hardcoded. Get it from path param in future\\n details.finalStatus = (typeof sourceLeg.finalStatus === 'undefined') ? null : sourceLeg.finalStatus; //need to be checked - not always avail in test data \\n resultLeg.details = details;\\n } else if (detailsParam == '0'){ \\n resultLeg.details = null;\\n } else{\\n // No details element at all\\n }\\n\\n \\n // Formatting the rHeaders \\n if (rheadersParam == '1'){\\n let rawRecvHeader = [];\\n rawRecvHeader = sourceLeg.protocolInfo.recvHeader.split(\\\"\\\\r\\\\n\\\")\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t;\\n let recvAttributes = []; \\n\\n rawRecvHeader.forEach(function (item,index){\\n if (index !=0){\\n let attribObj = {}; \\n let n = item.indexOf(\\\":\\\");\\n let attribName = item.substr(0,n).toString();\\n let atrribValue = (item.substr(n+1).trim());\\n if (attribName.length != 0) {\\n attribObj[attribName]= atrribValue; \\n recvAttributes.push(attribObj);\\n }\\n }\\n });\\n resultLeg.rheaders = recvAttributes;\\n } else if (rheadersParam == '0'){ \\n resultLeg.rheaders = null;\\n } else {\\n // No rheaders elemenmt at all\\n }\\n\\n\\n // Formatting the sHeaders\\n \\n\\t if (sheadersParam == '1') {\\n let rawSendHeader = [];\\n rawSendHeader = sourceLeg.protocolInfo.sentHeader.split(\\\"\\\\r\\\\n\\\")\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t;\\n let sendAttributes = []; \\n\\n rawSendHeader.forEach(function (item,index){\\n if (index !=0){\\n let attribObj = {}; \\n let n = item.indexOf(\\\":\\\");\\n let attribName = item.substr(0,n).toString();\\n let atrribValue = (item.substr(n+1).trim());\\n if (attribName.length != 0) {\\n attribObj[attribName]= atrribValue; \\n sendAttributes.push(attribObj);\\n }\\n }\\n });\\n\\n resultLeg.sheaders = sendAttributes;\\n } else if (sheadersParam == '0') {\\n resultLeg.sheaders = null;\\n } else {\\n // No sheaders element at all\\n }\\n\\n\\t // Only when all legs are requested create an Array with leg objects.\\n // Otherwise just return the leg object.\\n\\t if (legParam == '*') {\\n \\tresultLegs.push(resultLeg);\\n } else {\\n return resultLeg;\\n }\\n\\n }\\n }\\n\\n \\n return resultLegs;\"", + "metaName": "code", + "metaDescription": "A JavaScript function body. Supports `await` and returning promises" + } + ], + "outputs": { + "next": { + "context": "$.result", + "routes": [ + "http.2" + ], + "metaName": "Next" + }, + "error": { + "context": "$.error", + "routes": [ + "http.1" + ], + "metaName": "Error" + } + }, + "metaMethod": "Execute" + }, + "http.1": { + "type": "nodehandler://axway-flow/http", + "name": "Set HTTP 500 Response", + "method": "setresponse", + "parameters": [ + { + "name": "status", + "type": "number", + "value": "500", + "metaName": "status", + "metaDescription": "The HTTP status code" + } + ], + "outputs": { + "next": { + "context": "$.response", + "routes": [], + "metaName": "Next" + } + }, + "metaMethod": "Set HTTP Response" + }, + "http.3": { + "type": "nodehandler://axway-flow/http", + "name": "Set HTTP 400 Response", + "method": "setresponse", + "parameters": [ + { + "name": "status", + "type": "number", + "value": "400", + "metaName": "status", + "metaDescription": "The HTTP status code" + }, + { + "name": "body", + "type": "jsonpath", + "value": "$.error.message", "metaName": "body", "metaDescription": "The response payload" } diff --git a/elk-traffic-monitor-api/package.json b/elk-traffic-monitor-api/package.json index 90c743a7..9f2bf274 100644 --- a/elk-traffic-monitor-api/package.json +++ b/elk-traffic-monitor-api/package.json @@ -47,7 +47,8 @@ "test": "mocha --exit --colors ./test --recursive -R spec", "test:search": "mocha --exit --colors ./test/test_search_endpoint.js -R spec", "test:circuitpath": "mocha --exit --colors ./test/test_circuitpath.js -R spec", - "test:trace": "mocha --exit --colors ./test/test_trace_endpoint.js -R spec", + "test:trace": "mocha --inspect-brk --exit --colors ./test/test_trace_endpoint.js -R spec", + "test:getinfo": "mocha --inspect-brk --exit --colors ./test/test_getinfo_endpoint.js -R spec", "test:debug": "mocha --inspect-brk --exit --colors ./test --recursive -R spec --timeout 10000" } } diff --git a/elk-traffic-monitor-api/test/documents/basic/getinfo_test_documents.js b/elk-traffic-monitor-api/test/documents/basic/getinfo_test_documents.js new file mode 100644 index 00000000..c0bec2bf --- /dev/null +++ b/elk-traffic-monitor-api/test/documents/basic/getinfo_test_documents.js @@ -0,0 +1,200 @@ +const getDate = require('../../util'); + +module.exports = [ +{ + "timestampOriginal": "2020-07-03T15:55:48.333Z", + "transactionSummaryContext": { + "monitor": true, + "service": "ARS ToDo API", + "client": "Pass Through", + "status": "success", + "duration": 383, + "method": "Get-all-todo-items" + }, + "@version": "1", + "@timestamp": "2020-07-03T15:56:11.597Z", + "transactionElements": { + "leg1": { + "duration": 176, + "operation": "Get-all-todo-items", + "protocolInfo": { + "recvHeader": "HTTP/1.1 200 OK\r\nserver: API Builder/4.27.29\r\nrequest-id: e923342a-cf72-4c93-a774-78d1fa80c002\r\nx-xss-protection: 1; mode=block\r\nx-frame-options: DENY\r\nsurrogate-control: no-store\r\ncache-control: no-store, no-cache, must-revalidate, proxy-revalidate\r\npragma: no-cache\r\nexpires: 0\r\nx-content-type-options: nosniff\r\nstart-time: 1593791748423\r\ncontent-type: application/json; charset=utf-8\r\nresponse-time: 1\r\ncontent-md5: 0c682d056c69de8e90bbdf0a677891d8\r\ncontent-length: 281\r\netag: W/\"119-iMSR0WMPy7z6deRjls2eUuMCX5I\"\r\nVary: Accept-Encoding\r\nDate: Fri, 03 Jul 2020 15:55:48 GMT\r\nConnection: close\r\n\r\n", + "sentHeader": "GET /api/todos HTTP/1.1\r\nHost: 79f6a7dbf03ba9dc3fcdda2486d26adfab68584e.cloudapp-enterprise.appcelerator.com\r\nMax-Forwards: 20\r\nVia: 1.0 api-env (Gateway)\r\naccept: */*\r\nuser-agent: loadtest/5.0.3\r\nConnection: close\r\nX-CorrelationID: Id-0455ff5e82267be8182a553d 1\r\n\r\n", + "http": { + "bytesReceived": 879, + "uri": "/api/todos", + "remoteAddr": "52.43.33.149", + "authSubjectId": "Pass Through", + "localAddr": "192.168.233.137", + "remotePort": "80", + "bytesSent": 266, + "wafStatus": 0, + "status": 200, + "localPort": "43580", + "statusText": "OK", + "method": "GET", + "remoteName": "79f6a7dbf03ba9dc3fcdda2486d26adfab68584e.cloudapp-enterprise.appcelerator.com" + }, + "recvPayload": "file:///opt/Axway/APIM/apigateway/logs/payloads/2020-07-03/08.55/0455ff5e82267be8182a553d-1-received" + }, + "leg": 1, + "serviceName": "ARS ToDo API" + }, + "leg0": { + "finalStatus": "Pass", + "operation": "Get-all-todo-items", + "protocolInfo": { + "recvHeader": "GET /ars/api/todos HTTP/1.1\r\nhost: api-env.demo.axway.com:8065\r\nuser-agent: loadtest/5.0.3\r\naccept: */*\r\nConnection: keep-alive\r\n\r\n", + "sentHeader": "HTTP/1.1 200 OK\r\nMax-Forwards: 20\r\nVia: 1.0 api-env (Gateway)\r\nConnection: close\r\nX-CorrelationID: Id-0455ff5e82267be8182a553d 0\r\ncache-control: no-store, no-cache, must-revalidate, proxy-revalidate\r\nDate: Fri, 03 Jul 2020 15:55:48 GMT\r\netag: W/\"119-iMSR0WMPy7z6deRjls2eUuMCX5I\"\r\nexpires: 0\r\npragma: no-cache\r\nrequest-id: e923342a-cf72-4c93-a774-78d1fa80c002\r\nresponse-time: 1\r\nserver: API Builder/4.27.29\r\nstart-time: 1593791748423\r\nsurrogate-control: no-store\r\nVary: Accept-Encoding\r\nx-content-type-options: nosniff\r\nx-frame-options: DENY\r\nx-xss-protection: 1; mode=block\r\ncontent-md5: 0c682d056c69de8e90bbdf0a677891d8\r\ncontent-type: application/json; charset=utf-8\r\n\r\n", + "http": { + "bytesReceived": 131, + "uri": "/ars/api/todos", + "remoteAddr": "192.168.233.1", + "authSubjectId": "Pass Through", + "localAddr": "192.168.233.137", + "remotePort": "55783", + "bytesSent": 952, + "wafStatus": 0, + "status": 200, + "localPort": "8065", + "statusText": "OK", + "method": "GET", + "remoteName": "192.168.233.1" + }, + "sentPayload": "file:///opt/Axway/APIM/apigateway/logs/payloads/2020-07-03/08.55/0455ff5e82267be8182a553d-0-sent" + }, + "serviceName": "ARS ToDo API", + "duration": 384, + "leg": 0 + } + }, + "circuitPath": [ + { + "filters": [ + { + "class": "com.vordel.circuit.vapi.VApiServiceContextFilter", + "type": "VApiServiceContextFilter", + "name": "Set service context", + "filterTime": 1593791748127, + "status": "Pass", + "execTime": 0 + }, + { + "class": "com.vordel.circuit.CircuitDelegateFilter", + "status": "Pass", + "name": "Global Request Policy", + "filterTime": 1593791748141, + "type": "CircuitDelegateFilter", + "subPaths": [ + { + "filters": [ + { + "class": "com.vordel.circuit.basic.TraceFilter", + "type": "TraceFilter", + "name": "Trace Filter", + "filterTime": 1593791748141, + "status": "Pass", + "espk": "DEFAULT_PRIMARY_VordelGateway_7.7.0:-2330724604838128298", + "execTime": 14 + } + ], + "policy": "Trace", + "execTime": 14 + } + ], + "execTime": 14 + }, + { + "class": "com.vordel.apiportal.runtime.virtualized.VApiCircuitDelegateFilter", + "type": "VApiCircuitDelegateFilter", + "status": "Pass", + "filterTime": 1593791748510, + "name": "Custom Routing", + "subPaths": [ + { + "filters": [ + { + "execTime": 369, + "class": "com.vordel.circuit.switchcase.SwitchFilter", + "type": "SwitchFilter", + "name": "Default Routing", + "filterTime": 1593791748510, + "status": "Pass", + "espk": "DEFAULT_PRIMARY_VordelGateway_7.7.0:4323849261363416160", + "subPaths": [ + { + "filters": [ + { + "class": "com.vordel.circuit.CircuitDelegateFilter", + "type": "CircuitDelegateFilter", + "name": "not-required-here", + "status": "Pass", + "filterTime": 1593791748510, + "subPaths": [ + { + "filters": [ + { + "class": "com.vordel.circuit.net.ConnectToURLFilter", + "type": "ConnectToURLFilter", + "name": "Connect to URL", + "status": "Pass", + "filterTime": 1593791748510, + "espk": "DEFAULT_PRIMARY_VordelGateway_7.7.0:5735607394361826155", + "execTime": 369 + } + ], + "policy": "Default Profile-based Routing", + "execTime": 369 + } + ], + "execTime": 369 + } + ], + "policy": "Default API Proxy Routing", + "execTime": 369 + } + ] + } + ], + "policy": "Default API Proxy Routing", + "execTime": 369 + } + ], + "execTime": 369 + } + ], + "policy": "API Broker", + "execTime": 383 + } + ], + "transactionSummary": { + "status": "success", + "protocol": "https", + "serviceContexts": [ + { + "monitor": true, + "service": "ARS ToDo API", + "client": "Pass Through", + "status": "success", + "duration": 383, + "method": "Get-all-todo-items" + } + ], + "protocolSrc": "8065", + "path": "/ars/api/todos" + }, + "correlationId": "0455ff5e82267be8182a553d", + "tags": [ + "openlog" + ], + "processInfo": { + "hostname": "api-env", + "serviceId": "instance-1", + "groupId": "group-2", + "serviceName": "QuickStart Server", + "version": "7.7.20200130", + "domainId": "ed992442-c363-4d36-963a-9e6314b0f421", + "groupName": "QuickStart Group" + } + } +] \ No newline at end of file diff --git a/elk-traffic-monitor-api/test/test_getinfo.js b/elk-traffic-monitor-api/test/test_getinfo.js deleted file mode 100644 index 364a77e2..00000000 --- a/elk-traffic-monitor-api/test/test_getinfo.js +++ /dev/null @@ -1,63 +0,0 @@ -const { expect } = require('chai'); -const { startApiBuilder, stopApiBuilder, requestAsync, sendToElasticsearch, getRandomInt } = require('./_base'); -const fs = require('fs'); - -describe('Endpoints', function () { - this.timeout(30000); - let server; - let auth; - const indexName = `getinfo_test_${getRandomInt(9999)}`; - - /** - * Start API Builder. - */ - before(() => { - return new Promise(function(resolve, reject){ - server = startApiBuilder(); - auth = { - user: server.apibuilder.config.apikey || 'test', - password: '' - }; - server.apibuilder.config.testElasticIndex = indexName; - elasticConfig = server.apibuilder.config.pluginConfig['@axway-api-builder-ext/api-builder-plugin-fn-elasticsearch'].elastic; - server.started - .then(() => { - const entryset = require('./documents/basic/search_test_documents'); - sendToElasticsearch(elasticConfig, indexName, entryset) - .then(() => { - resolve(); - }); - }); - }); - }); - - /** - * Stop API Builder after the tests. - */ - after(() => stopApiBuilder(server)); - - describe('Search', () => { - - it('[Search-0001] Execute a getInfo for a specific correlationId from instance-1', () => { - return requestAsync({ - method: 'GET', - uri: `http://localhost:${server.apibuilder.port}/api/elk/v1/api/router/service/instance-1/ops/any/bb30715e5300e189d1da43fc/*/getinfo`, - auth: auth, - json: true - }).then(({ response, body }) => { - expect(response.statusCode).to.equal(200); - expect(body).to.be.an('Array'); - /* - expect(body).to.have.lengthOf(1); - expect(body[0]).to.be.an('Object'); - expect(body[0]).to.have.property('policy'); - expect(body[0].policy).to.equal('Health Check'); - expect(body[0].filters).to.be.an('Array'); - expect(body[0].filters).to.have.lengthOf(2); - expect(body[0].filters[0].status).to.equal('Pass'); - */ - }); - }); - }); -}); - diff --git a/elk-traffic-monitor-api/test/test_getinfo_endpoint.js b/elk-traffic-monitor-api/test/test_getinfo_endpoint.js new file mode 100644 index 00000000..efb5acbb --- /dev/null +++ b/elk-traffic-monitor-api/test/test_getinfo_endpoint.js @@ -0,0 +1,145 @@ +const { expect } = require('chai'); +const { startApiBuilder, stopApiBuilder, requestAsync, sendToElasticsearch, getRandomInt } = require('./_base'); +const fs = require('fs'); + +describe('Endpoints', function () { + this.timeout(30000); + let server; + let auth; + const indexName = `getinfo_test_${getRandomInt(9999)}`; + + /** + * Start API Builder. + */ + before(() => { + return new Promise(function(resolve, reject){ + server = startApiBuilder(); + auth = { + user: server.apibuilder.config.apikey || 'test', + password: '' + }; + server.apibuilder.config.testElasticIndex = indexName; + elasticConfig = server.apibuilder.config.pluginConfig['@axway-api-builder-ext/api-builder-plugin-fn-elasticsearch'].elastic; + server.started + .then(() => { + const entryset = require('./documents/basic/getinfo_test_documents'); + sendToElasticsearch(elasticConfig, indexName, entryset) + .then(() => { + resolve(); + }); + }); + }); + }); + + /** + * Stop API Builder after the tests. + */ + after(() => stopApiBuilder(server)); + + describe('Search', () => { + + it('[Getinfo-0001] Should return http 200 with details and headers for all legs (*) ', () => { + return requestAsync({ + method: 'GET', + uri: `http://localhost:${server.apibuilder.port}/api/elk/v1/api/router/service/instance-1/ops/http/0455ff5e82267be8182a553d/*/getinfo?format=json&details=1&rheaders=1&sheaders=1`, + auth: auth, + json: true + }).then(({ response, body }) => { + expect(response.statusCode).to.equal(200); + expect(body).to.be.an('Array'); + expect(body).to.have.lengthOf(2); + expect(body[0]).to.be.an('Object'); + expect(body[0]).to.have.property('details'); + expect(body[0].details.leg).to.equal(1); + expect(body[0]).to.have.property('rheaders'); + expect(body[0]).to.have.property('sheaders'); + expect(body[1]).to.have.property('details'); + expect(body[1].details.leg).to.equal(0); + expect(body[1]).to.have.property('rheaders'); + expect(body[1]).to.have.property('sheaders'); + }); + }); + + it('[Getinfo-0002 Should return http 200 with details and all headers for leg 0', () => { + return requestAsync({ + method: 'GET', + uri: `http://localhost:${server.apibuilder.port}/api/elk/v1/api/router/service/instance-1/ops/http/0455ff5e82267be8182a553d/0/getinfo?format=json&details=1&rheaders=1&sheaders=1`, + auth: auth, + json: true + }).then(({ response, body }) => { + expect(response.statusCode).to.equal(200); + expect(body).not.to.be.an('Array'); + expect(body).to.be.an('Object'); + expect(body).to.have.property('details'); + expect(body.details.leg).to.equal(0); + expect(body).to.have.property('rheaders'); + expect(body).to.have.property('sheaders'); + }); + }); + it('[Getinfo-0003 Should return http 200 with details and all headers for leg 1', () => { + return requestAsync({ + method: 'GET', + uri: `http://localhost:${server.apibuilder.port}/api/elk/v1/api/router/service/instance-1/ops/http/0455ff5e82267be8182a553d/1/getinfo?format=json&details=1&rheaders=1&sheaders=1`, + auth: auth, + json: true + }).then(({ response, body }) => { + expect(response.statusCode).to.equal(200); + expect(body).not.to.be.an('Array'); + expect(body).to.be.an('Object'); + expect(body).to.have.property('details'); + expect(body.details.leg).to.equal(1); + expect(body).to.have.property('rheaders'); + expect(body).to.have.property('sheaders'); + }); + }); + it('[Getinfo-0004 Should return http 200 without details but all headers for all legs (*)', () => { + return requestAsync({ + method: 'GET', + uri: `http://localhost:${server.apibuilder.port}/api/elk/v1/api/router/service/instance-1/ops/http/0455ff5e82267be8182a553d/*/getinfo?format=json&details=0&rheaders=1&sheaders=1`, + auth: auth, + json: true + }).then(({ response, body }) => { + expect(response.statusCode).to.equal(200); + expect(body).to.be.an('Array'); + expect(body).to.have.lengthOf(2); + expect(body[0]).to.be.an('Object'); + expect(body[0]).to.have.property('details'); + expect(body[0].details).to.equal(null); + expect(body[0]).to.have.property('rheaders'); + expect(body[0]).to.have.property('sheaders'); + expect(body[1]).to.be.an('Object'); + expect(body[1]).to.have.property('details'); + expect(body[1].details).to.equal(null); + expect(body[1]).to.have.property('rheaders'); + expect(body[1]).to.have.property('sheaders'); + }); + }); + it('[Getinfo-0005 Should return http 200 with details but no headers for all legs (*)', () => { + return requestAsync({ + method: 'GET', + uri: `http://localhost:${server.apibuilder.port}/api/elk/v1/api/router/service/instance-1/ops/http/0455ff5e82267be8182a553d/*/getinfo?format=json&details=1&rheaders=0&sheaders=0`, + auth: auth, + json: true + }).then(({ response, body }) => { + expect(response.statusCode).to.equal(200); + expect(body).to.be.an('Array'); + expect(body).to.have.lengthOf(2); + expect(body[0]).to.be.an('Object'); + expect(body[0]).to.have.property('details'); + expect(body[0]).to.have.property('rheaders'); + expect(body[0].rheaders).to.equal(null); + expect(body[0]).to.have.property('sheaders'); + expect(body[0].sheaders).to.equal(null); + expect(body[1]).to.be.an('Object'); + expect(body[1]).to.have.property('details'); + expect(body[1]).to.have.property('rheaders'); + expect(body[1].rheaders).to.equal(null); + expect(body[1]).to.have.property('sheaders'); + expect(body[1].sheaders).to.equal(null); + }); + }); + + + }); +}); + diff --git a/elk-traffic-monitor-api/test/test_trace_endpoint.js b/elk-traffic-monitor-api/test/test_trace_endpoint.js index d88e40b1..0d7f5fd2 100644 --- a/elk-traffic-monitor-api/test/test_trace_endpoint.js +++ b/elk-traffic-monitor-api/test/test_trace_endpoint.js @@ -112,8 +112,6 @@ describe('Traffic Monitor API', function () { expect(body).to.have.lengthOf(2); }); }); - - }); }); diff --git a/imgs/IsmanagedbyElasticsearchAPI.png b/imgs/IsmanagedbyElasticsearchAPI.png index 61f19b46..056fd2fc 100644 Binary files a/imgs/IsmanagedbyElasticsearchAPI.png and b/imgs/IsmanagedbyElasticsearchAPI.png differ