openapi2apigeeck2
Version:
A tool that converts openapi yaml file to Apigee API Proxy Bundle
387 lines (310 loc) • 14.7 kB
JavaScript
/**
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, {})
})
}