UNPKG

openapi2apigeeck2

Version:

A tool that converts openapi yaml file to Apigee API Proxy Bundle

387 lines (310 loc) 14.7 kB
/** Copyright 2022 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at https://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ var builder = require('xmlbuilder') var fs = require('fs') var path = require('path') var serviceUtils = require('../../util/service.js') module.exports = function generateProxyEndPoint (apiProxy, options, api, cb) { var useCors var destination = options.destination || path.join(__dirname, '../../../api_bundles') if (destination.substr(-1) === '/') { destination = destination.substr(0, destination.length - 1) } var rootDirectory = destination + '/' + apiProxy + '/apiproxy' var root = builder.create('ProxyEndpoint') root.att('name', 'default') root.ele('Description', {}, api.info.title) //steps to add default fault rule var defaultFaultRule = root.ele('DefaultFaultRule', { name: 'default-fault' }) var preFlow = root.ele('PreFlow', { name: 'PreFlow' }) step = defaultFaultRule.ele('Step') step.ele('Name', {}, 'FC-LogError') step = defaultFaultRule.ele('Step') //step.ele('Condition', {}, 'fault.name != "RaiseFault"') step.ele('Name', {}, 'FC-FaultHandling') // Add steps to preflow. var raiseFaultName var requestPipe = preFlow.ele('Request') var responsePipe = preFlow.ele('Response') var services = serviceUtils.servicesToArray(api) console.log('Services ',services) if (options.oauth === 'true') { step = requestPipe.ele('Step', {}) step.ele('Name', {}, 'verifyAccessToken') var step2 = requestPipe.ele('Step', {}) step2.ele('Name', {}, 'removeHeaderAuthorization') } services.forEach(function (serviceItem) { console.log('serviceItem ',serviceItem) //TODO fault rule policies if(serviceItem.provider.indexOf('FC-')> -1 && serviceItem['apply'].endPoint.indexOf('proxy') > -1 && serviceItem['apply'].place.indexOf('fault') > -1) { step = defaultFaultRule.ele('Step') step.ele('Condition', {}, 'fault.name != "RaiseFault"') step.ele('Name', {}, serviceItem.name) } if (serviceItem.provider === 'x-cors') { useCors = serviceItem.name var step = requestPipe.ele('Step', {}) step.ele('Name', {}, serviceItem.name) // step.ele('Condition', {}, 'request.verb == "OPTIONS"') } //for api key in preflow request if(serviceItem.provider ==='oauth'){ step = requestPipe.ele('Step') step.ele('Condition', {}, 'request.verb != "OPTIONS"') step.ele('Name', {}, serviceItem.name) } if(serviceItem.provider ==='basicAuth'){ step = requestPipe.ele('Step') step.ele('Condition', {}, 'request.verb != "OPTIONS"') step.ele('Name', {}, serviceItem.name) } if(serviceItem.provider.indexOf('FC-')> -1 && serviceItem['apply'].endPoint.indexOf('proxy') > -1) { if (serviceItem['apply'].pipe.indexOf('request') > -1 && serviceItem['options'].displayName) { step = requestPipe.ele('Step') step.ele('Condition', {}, 'request.verb != "OPTIONS"') step.ele('Name', {}, serviceItem.name) } } if(serviceItem.provider.indexOf('FC-')> -1 && serviceItem['apply'].endPoint.indexOf('proxy') > -1 && serviceItem['apply'].place.indexOf('flow') > -1) { if (serviceItem['apply'].pipe.indexOf('response') > -1 && serviceItem['options'].displayName) { step = responsePipe.ele('Step') step.ele('Condition', {}, 'request.verb != "OPTIONS"') step.ele('Name', {}, serviceItem.name) } } if(serviceItem.provider.indexOf('KVM-')> -1 && serviceItem['apply'].endPoint.indexOf('proxy') > -1 && serviceItem['apply'].place.indexOf('flow') > -1) { if (serviceItem['apply'].pipe.indexOf('request') > -1 && serviceItem['options'].displayName) { step = requestPipe.ele('Step') step.ele('Name', {}, serviceItem.name) } } if (serviceItem.provider === 'x-input-validation' && serviceItem['apply'].endPoint.indexOf('proxy') > -1) { if (serviceItem['apply'].pipe.indexOf('request') > -1 && serviceItem['options'].displayName) { step = requestPipe.ele('Step', {}) step.ele('Name', {}, 'Extract Path Parameters') step = requestPipe.ele('Step', {}) step.ele('Name', {}, serviceItem['options'].displayName) } } if (serviceItem.provider === 'x-raiseInputValidationFault' && serviceItem['apply'].endPoint.indexOf('proxy') > -1) { if (serviceItem['apply'].pipe.indexOf('request') > -1 && serviceItem['options'].displayName) { raiseFaultName = serviceItem['options'].displayName step = requestPipe.ele('Step', {}) step.ele('Condition', {}, '(INPUT.error equals true)') step.ele('Name', {}, raiseFaultName) } } if (serviceItem.provider === 'x-regex-protection' && serviceItem['apply'].endPoint.indexOf('proxy') > -1) { if (serviceItem['apply'].pipe.indexOf('request') > -1 && serviceItem['options'].displayName) { step = requestPipe.ele('Step', {}) step.ele('Name', {}, serviceItem['options'].displayName) } } if (serviceItem.provider === 'x-raiseFault' && serviceItem['apply'].endPoint.indexOf('proxy') > -1) { if (serviceItem['apply'].pipe.indexOf('request') > -1 && serviceItem['options'].displayName) { raiseFaultName = serviceItem['options'].displayName step = requestPipe.ele('Step', {}) step.ele('Condition', {}, '(FILTER.block equals true)') step.ele('Name', {}, raiseFaultName) } } }) var flows = root.ele('Flows', {}) // if (useCors) { // preFlow = flows.ele('Flow', { name: 'OptionsPreFlight' }) // preFlow.ele('Condition', {}, 'request.verb == "OPTIONS"') // preFlow.ele('Request') // var preFlowResponse = preFlow.ele('Response') // var requestStep = preFlowResponse.ele('Step') // requestStep.ele('Name', {}, useCors) // } var allowedVerbs = ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS', 'HEAD', 'TRACE', 'CONNECT', 'PATCH'] var Condition404 = '' for (var apiPath in api.paths) { for (var resource in api.paths[apiPath]) { if (allowedVerbs.indexOf(resource.toUpperCase()) >= 0) { var resourceItem = api.paths[apiPath][resource] resourceItem.operationId = resourceItem.operationId || resource.toUpperCase() + ' ' + apiPath var flow = flows.ele('Flow', { name: resourceItem.operationId }) var flowCondition = '(proxy.pathsuffix MatchesPath "' + apiPath + '") and (request.verb = "' + resource.toUpperCase() + '")' Condition404 += '(proxy.pathsuffix MatchesPath "' + apiPath + '") or ' flow.ele('Condition').raw(flowCondition) flow.ele('Description', {}, resourceItem.summary) requestPipe = flow.ele('Request') // Add conditions for parameters. if (raiseFaultName && resource.toUpperCase() === 'GET' && resourceItem.parameters) { var parameters = resourceItem.parameters var paramCondition = '' var cnt = 0 parameters.forEach(function (param) { if (param.required && param.in === 'query') { var op = (cnt > 0) ? ' or ' : '' paramCondition += op + '(request.queryparam.' + param.name + ' Equals null)' cnt++ } // if (param.required && param.in === 'path') { // var op = (cnt > 0) ? ' or ' : ''; // paramCondition += op + '(request.queryparam.' + param.name + ' Equals null)'; // cnt++; // } }) if (paramCondition.length > 0) { requestStep = requestPipe.ele('Step') requestStep.ele('Condition').raw(paramCondition) requestStep.ele('Name', {}, raiseFaultName) } } responsePipe = flow.ele('Response') if (resourceItem['x-a127-apply']) { for (var service in resourceItem['x-a127-apply']) { console.log("service",service) if (resourceItem['x-a127-apply'][service].endPoint.indexOf('proxy') > -1) { if (resourceItem['x-a127-apply'][service].pipe.indexOf('request') > -1) { var step = requestPipe.ele('Step', {}) step.ele('Name', {}, service) } if (resourceItem['x-a127-apply'][service].pipe.indexOf('response') > -1) { step = responsePipe.ele('Step', {}) step.ele('Name', {}, service) } // pipe request / response if ends here } // proxy check ends here } // for loop ends here } // check for normal policies ends here // Check for Security Policies in a-127 if (resourceItem['security']) { for (var security in resourceItem['security']) { for (var stepName in resourceItem['security'][security]) { if (stepName === 'oauth2' || stepName === 'apiKeyHeader' || stepName === 'apiKeyQuery') { // Attach verify access token policy.. step = requestPipe.ele('Step', {}) step.ele('Name', {}, 'verifyAccessToken') } } } } } // methods check ends here } // for loop for resources ends here } // for loop for paths ends here ////////////////// 405 var condition405 = ''; for (var apiPath in api.paths) { var verbs = []; for (var method in api.paths[apiPath]) { if (allowedVerbs.includes(method.toUpperCase())) { verbs.push(method.toUpperCase()); } } if (verbs.length > 0) { var verbConditions = verbs.map(v => `request.verb == "${v}"`).join(' or '); condition405 += `((proxy.pathsuffix MatchesPath "${apiPath}") and !(${verbConditions})) or `; } } var methodNotAllowedFlow = flows.ele('Flow', { name: 'MethodNotAllowed' }); methodNotAllowedFlow.ele('Condition').raw(condition405.slice(0, -4)); // removes last " or " var methodRequest = methodNotAllowedFlow.ele('Request'); methodRequest.ele('Step').ele('Name', {}, 'FC-405MethodNotAllowed'); /////////// console.log('condition-----',Condition404.slice(0, -4)) var notFoundFlow = flows.ele('Flow', { name: 'MethodNotFound' }); //notFoundFlow.ele('Condition').raw('!'+Condition404.slice(0, -3)); var requestPipe = notFoundFlow.ele('Request'); var requestStep = requestPipe.ele('Step'); requestStep.ele('Name', {}, 'FC-404NotFound'); //////////////////////// var notFoundFlow = flows.ele('Flow', { name: 'OptionsPreFlight' }); //notFoundFlow.ele('Condition').raw('!'+Condition404.slice(0, -3)); var requestPipe = notFoundFlow.ele('Request'); notFoundFlow.ele('Condition',{},'request.verb is "OPTIONS"') ///////////////////// var postFlow = root.ele('PostFlow', { name: 'PostFlow' }) postFlow.ele('Request') var postFlowPipe = postFlow.ele('Response') for (var srv in api['x-a127-services']) { var serviceItem = api['x-a127-services'][srv] if (serviceItem.provider === 'x-output-validation' && serviceItem['apply'].endPoint.indexOf('proxy') > -1) { if (serviceItem['apply'].pipe.indexOf('response') > -1 && serviceItem['options'].displayName) { step = postFlowPipe.ele('Step', {}) step.ele('Name', {}, serviceItem['options'].displayName) } } if (serviceItem.provider === 'x-raiseOutputValidationFault' && serviceItem['apply'].endPoint.indexOf('proxy') > -1) { if (serviceItem['apply'].pipe.indexOf('response') > -1 && serviceItem['options'].displayName) { raiseFaultName = serviceItem['options'].displayName step = postFlowPipe.ele('Step', {}) step.ele('Condition', {}, '(SCHEMA.error equals true)') step.ele('Name', {}, raiseFaultName) } } if (serviceItem.provider === 'x-headers' && serviceItem['apply'].endPoint.indexOf('proxy') > -1) { if (serviceItem['apply'].pipe.indexOf('response') > -1 && serviceItem['options'].displayName) { raiseFaultName = serviceItem['options'].displayName step = postFlowPipe.ele('Step', {}) // step.ele('Condition', {}, '(SCHEMA.error equals true)'); step.ele('Name', {}, raiseFaultName) } } } var httpProxyConn = root.ele('HTTPProxyConnection') if (options.basepath) { httpProxyConn.ele('BasePath', {}, options.basepath) } else if (api.basePath !== undefined) { httpProxyConn.ele('BasePath', {}, api.basePath) } else { httpProxyConn.ele('BasePath', {}, '/' + apiProxy) } var virtualhosts = (options.virtualhosts) ? options.virtualhosts.split(',') : ['default'] virtualhosts.forEach(function (virtualhost) { httpProxyConn.ele('VirtualHost', {}, virtualhost) }) var postClientFlow = root.ele('PostClientFlow'); var response = postClientFlow.ele('Response'); var step = response.ele('Step'); step.ele('Condition', {}, 'request.verb != "OPTIONS"'); step.ele('Name', {}, 'FC-MessageLogging'); var routeRule1 = root.ele('RouteRule', { name: 'noRoute' }) routeRule1.ele('Condition', {}, 'request.verb == "OPTIONS" AND request.header.origin IsNot null and request.header.Access-Control-Request-Method IsNot null') var routeRule2 = root.ele('RouteRule', { name: 'default' }) routeRule2.ele('TargetEndpoint', {}, 'default') var xmlString = root.end({ pretty: true, indent: ' ', newline: '\n' }) fs.writeFile(rootDirectory + '/proxies/default.xml', xmlString, function (err) { if (err) { return cb(err, {}) } cb(null, {}) }) }