Skip to content
This repository was archived by the owner on Dec 14, 2022. It is now read-only.

Commit 1a3b292

Browse files
author
Chris Wiechmann
committed
Refactored API-Manager config parsing added unit tests (#76)
1 parent 37ba511 commit 1a3b292

File tree

7 files changed

+417
-115
lines changed

7 files changed

+417
-115
lines changed

apibuilder4elastic/custom_flow_nodes/api-builder-plugin-axway-api-management/src/actions.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -364,7 +364,6 @@ async function _getGroupRegionFilename(basefilename, groupId, region) {
364364
}
365365

366366
async function _getCurrentGWUser(requestHeaders) {
367-
debugger;
368367
var options = {
369368
path: '/api/rbac/currentuser',
370369
headers: requestHeaders,

apibuilder4elastic/custom_flow_nodes/api-builder-plugin-axway-api-management/src/index.js

Lines changed: 5 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ const { SDK } = require('@axway/api-builder-sdk');
33
const { lookupCurrentUser, lookupAPIDetails, getCustomPropertiesConfig, isIgnoreAPI, lookupApplication } = require('./actions');
44
const { mergeCustomProperties } = require('./customProperties');
55
const NodeCache = require( "node-cache" );
6-
const { sendRequest, _getSession, getManagerConfig } = require('./utils');
6+
const { checkAPIManagers, parseAPIManagerConfig } = require('./utils');
77
const https = require('https');
88

99
/**
@@ -32,44 +32,11 @@ async function getPlugin(pluginConfig, options) {
3232
if(!pluginConfig.apigateway.url) {
3333
throw new Error(`Required parameter: apigateway.url is not set.`);
3434
}
35-
if(!pluginConfig.apimanager.url) {
36-
// If no API-Manager URL is given, use the Admin-Node-Manager URL
37-
const managerURL = new URL(pluginConfig.apigateway.url);
38-
managerURL.port = 8075;
39-
pluginConfig.apimanager.url = managerURL.toString();
40-
} else {
41-
// Check, if multiple API-Manager URLs based on the groupId and regions are given (Format: groupId|managerUrl or groupId|region|managerUrl)
42-
if(pluginConfig.apimanager.url.indexOf('|')!=-1) {
43-
pluginConfig.apimanager.perGroupAndRegion = true;
44-
// Looks like manager URLs are given based on groupIds and regions
45-
pluginConfig.apimanager.url.split(',').forEach(groupRegionAndURL => {
46-
groupRegionAndURL = groupRegionAndURL.trim().toLowerCase().split('|');
47-
if(groupRegionAndURL.length == 1) {
48-
// The default API-Manager
49-
pluginConfig.apimanager.url = groupRegionAndURL[0]
50-
} else if(groupRegionAndURL.length == 2) {
51-
// Just the Group-ID is given
52-
pluginConfig.apimanager[groupRegionAndURL[0]] = { url: groupRegionAndURL[1] };
53-
} else if(groupRegionAndURL.length == 3) {
54-
// Group-ID and region is given (Just create a map with a special key)
55-
pluginConfig.apimanager[`${groupRegionAndURL[0]}###${groupRegionAndURL[1]}`] = { url: groupRegionAndURL[2] };
56-
} else {
57-
return Promise.reject(`Unexpected API-Manager format: ${groupRegionAndURL}`);
58-
59-
}
60-
});
61-
}
62-
}
63-
if(!pluginConfig.apimanager.username) {
64-
throw new Error(`Required parameter: apimanager.username is not set.`)
65-
}
66-
if(!pluginConfig.apimanager.password) {
67-
throw new Error(`Required parameter: apimanager.password is not set.`)
68-
}
35+
pluginConfig.apimanager = await parseAPIManagerConfig(pluginConfig);
6936
if(pluginConfig.validateConfig==true) {
70-
var isAdmin = await isAPIManagerUserAdmin(pluginConfig.apimanager, options.logger);
71-
if(!isAdmin) {
72-
throw new Error(`Configured API-Manager user: ${pluginConfig.apimanager.username} is either incorrect or has no Admin-Role.`);
37+
var isValid = await checkAPIManagers(pluginConfig.apimanager, options.logger);
38+
if(!isValid) {
39+
throw new Error(`Error checking configured API-Manager(s). ${JSON.stringify(pluginConfig.apimanager)}`);
7340
} else {
7441
options.logger.info("Connection to API-Manager successfully validated.");
7542
}
@@ -82,65 +49,6 @@ async function getPlugin(pluginConfig, options) {
8249
return sdk.getPlugin();
8350
}
8451

85-
async function isAPIManagerUserAdmin(apiManagerConfig, logger) {
86-
let groupIds = [];
87-
if(apiManagerConfig.url.indexOf('#') != -1) {
88-
apiManagerConfig.url.split(',').forEach(groupAndURL => {
89-
groupAndURL = groupAndURL.trim().split();
90-
groupIds.push(getManagerConfig(apiManagerConfig, groupAndURL[0]));
91-
});
92-
} else {
93-
// The groupId doesn't matter if we don't have multiple configured
94-
groupIds[0] = "NOT_SPECIFIED";
95-
}
96-
for (var i = 0; i < groupIds.length; ++i) {
97-
var groupId = groupIds[i].trim();
98-
let config = getManagerConfig(apiManagerConfig, groupId);
99-
try {
100-
var data = `username=${config.username}&password=${config.password}`;
101-
var options = {
102-
path: `/api/portal/v1.3/login`,
103-
method: 'POST',
104-
headers: {
105-
'Content-Type': 'application/x-www-form-urlencoded',
106-
'Content-Length': data.length
107-
},
108-
agent: new https.Agent({ rejectUnauthorized: false })
109-
};
110-
const result = await sendRequest(config.url, options, data, 303)
111-
.then(response => {
112-
return response;
113-
})
114-
.catch(err => {
115-
throw new Error(`Cannot login to API-Manager: '${config.url}'. Got error: ${err}`);
116-
});
117-
const session = _getSession(result.headers);
118-
var options = {
119-
path: `/api/portal/v1.3/currentuser`,
120-
headers: {
121-
'Cookie': `APIMANAGERSESSION=${session}`
122-
},
123-
agent: new https.Agent({ rejectUnauthorized: false })
124-
};
125-
const currentUser = await sendRequest(apiManagerConfig.url, options)
126-
.then(response => {
127-
return response;
128-
})
129-
.catch(err => {
130-
throw new Error(`Cant get current user: ${err}`);
131-
});
132-
if(currentUser.body.role!='admin') {
133-
logger.error(`User: ${currentUser.body.loginName} has no admin role.`);
134-
return false;
135-
}
136-
return true;
137-
} catch (ex) {
138-
logger.error(ex);
139-
throw ex;
140-
}
141-
}
142-
}
143-
14452
/**
14553
* This adds a number of Keys into the cache that are triggered
14654
* by the Logstash-Pipeline tests.

apibuilder4elastic/custom_flow_nodes/api-builder-plugin-axway-api-management/src/utils.js

Lines changed: 117 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -85,32 +85,139 @@ function isDeveloperMode() {
8585
}
8686
}
8787

88+
async function parseAPIManagerConfig(pluginConfig) {
89+
var configuredManagers = {};
90+
if(!pluginConfig.apimanager.username) {
91+
throw new Error(`Required parameter: apimanager.username is not set.`)
92+
}
93+
if(!pluginConfig.apimanager.password) {
94+
throw new Error(`Required parameter: apimanager.password is not set.`)
95+
}
96+
if(!pluginConfig.apimanager.url) {
97+
// If no API-Manager URL is given, use the Admin-Node-Manager URL
98+
const managerURL = new URL(pluginConfig.apigateway.url);
99+
managerURL.port = 8075;
100+
configuredManagers = {
101+
default: {
102+
url: managerURL.toString(),
103+
username: pluginConfig.apimanager.username,
104+
password: pluginConfig.apimanager.password
105+
}
106+
}
107+
} else {
108+
// Check, if multiple API-Manager URLs based on the groupId and regions are given (Format: groupId|managerUrl or groupId|region|managerUrl)
109+
if(pluginConfig.apimanager.url.indexOf('|')!=-1) {
110+
configuredManagers.perGroupAndRegion = true;
111+
// Looks like manager URLs are given based on groupIds and regions
112+
pluginConfig.apimanager.url.split(',').forEach(groupRegionAndURL => {
113+
groupRegionAndURL = groupRegionAndURL.trim().toLowerCase().split('|');
114+
if(groupRegionAndURL.length == 1) {
115+
// The default API-Manager
116+
configuredManagers.default = { url: groupRegionAndURL[0], username: pluginConfig.apimanager.username, password: pluginConfig.apimanager.password }
117+
} else if(groupRegionAndURL.length == 2) {
118+
// Only the Group-ID is given
119+
configuredManagers[groupRegionAndURL[0]] = { url: groupRegionAndURL[1], username: pluginConfig.apimanager.username, password: pluginConfig.apimanager.password }
120+
} else if(groupRegionAndURL.length == 3) {
121+
// Group-ID and region is given (Just create a map with a special key)
122+
configuredManagers[`${groupRegionAndURL[0]}###${groupRegionAndURL[1]}`] = { url: groupRegionAndURL[2], username: pluginConfig.apimanager.username, password: pluginConfig.apimanager.password}
123+
} else {
124+
return Promise.reject(`Unexpected API-Manager format: ${groupRegionAndURL}`);
125+
}
126+
});
127+
} else { // If not, create a default API-Manager
128+
configuredManagers = {
129+
default: {
130+
url: pluginConfig.apimanager.url,
131+
username: pluginConfig.apimanager.username,
132+
password: pluginConfig.apimanager.password
133+
}
134+
}
135+
}
136+
}
137+
return configuredManagers;
138+
}
139+
88140
function getManagerConfig(apiManagerConfig, groupId, region) {
89141
if(groupId == undefined && region == undefined) {
90-
return apiManagerConfig;
142+
if(apiManagerConfig.default == undefined) {
143+
throw new Error(`Cannot return API-Manager config without groupId and region as no default API-Manager is configured.`);
144+
} else {
145+
return apiManagerConfig.default;
146+
}
91147
}
92148
var key = groupId;
93149
if(region != undefined) {
94150
key = `${groupId}###${region}`.toLowerCase();
95151
}
152+
// Check if the requested combination based on groupId and region exists and return it directly
96153
if (apiManagerConfig[key]) {
97-
if (!apiManagerConfig[key].password) {
98-
apiManagerConfig[key].password = apiManagerConfig.password;
99-
apiManagerConfig[key].username = apiManagerConfig.username;
100-
}
101154
return apiManagerConfig[key];
102155
} else {
103-
if (apiManagerConfig.perGroupAndRegion) {
104-
throw new Error(`You have configured API-Manager URLs based on groupIds (e.g. group-a|https://manager-host.com:8075), but the groupId: ${groupId} is NOT configured. Please check the configuration parameter: API_MANAGER`);
156+
//
157+
if (apiManagerConfig.perGroupAndRegion && !apiManagerConfig.default) {
158+
throw new Error(`You have configured API-Manager URLs based on groupIds (e.g. group-a|https://manager-host.com:8075), but the groupId: ${groupId} is NOT configured and no default is configured. Please check the configuration parameter: API_MANAGER`);
159+
}
160+
return apiManagerConfig.default;
161+
}
162+
}
163+
164+
async function checkAPIManagers(apiManagerConfig, logger) {
165+
var finalResult = true;
166+
for (const [key, config] of Object.entries(apiManagerConfig)) {
167+
if(key == "perGroupAndRegion") continue;
168+
try {
169+
var data = `username=${config.username}&password=${config.password}`;
170+
var options = {
171+
path: `/api/portal/v1.3/login`,
172+
method: 'POST',
173+
headers: {
174+
'Content-Type': 'application/x-www-form-urlencoded',
175+
'Content-Length': data.length
176+
},
177+
agent: new https.Agent({ rejectUnauthorized: false })
178+
};
179+
const result = await sendRequest(config.url, options, data, 303)
180+
.then(response => {
181+
return response;
182+
})
183+
.catch(err => {
184+
throw new Error(`Cannot login to API-Manager: '${config.url}'. Got error: ${err}`);
185+
});
186+
const session = _getSession(result.headers);
187+
var options = {
188+
path: `/api/portal/v1.3/currentuser`,
189+
headers: {
190+
'Cookie': `APIMANAGERSESSION=${session}`
191+
},
192+
agent: new https.Agent({ rejectUnauthorized: false })
193+
};
194+
const currentUser = await sendRequest(config.url, options)
195+
.then(response => {
196+
return response;
197+
})
198+
.catch(err => {
199+
throw new Error(`Cant get current user: ${err}`);
200+
});
201+
if(currentUser.body.role!='admin') {
202+
logger.error(`User: ${currentUser.body.loginName} has no admin role on API-Manager: ${config.url}.`);
203+
config.isValid = false;
204+
finalResult = false;
205+
} else {
206+
config.isValid = true;
207+
}
208+
} catch (ex) {
209+
logger.error(ex);
210+
throw ex;
105211
}
106-
return apiManagerConfig;
107212
}
213+
return finalResult;
108214
}
109215

110216
module.exports = {
111217
sendRequest,
112218
_getCookie,
113-
_getSession,
114219
isDeveloperMode,
115-
getManagerConfig
220+
getManagerConfig,
221+
checkAPIManagers,
222+
parseAPIManagerConfig
116223
}

apibuilder4elastic/custom_flow_nodes/api-builder-plugin-axway-api-management/test/test-grp-based-apilookup.js

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,15 +28,19 @@ describe('Test group based API lookup', () => {
2828

2929
describe('#lookupAPIDetails', () => {
3030
// This only fails, if really multiple API-Manager are configured (for that the parameter-value of API_MANAGER is checked if it contains a #)
31-
it('should return an error for a given groupId: group-unknown, which is not configured', async () => {
32-
31+
it('should use the default API-Manager for the given unknown group', async () => {
32+
// default
33+
nock('https://mocked-api-manager-0:8075').get('/api/portal/v1.3/proxies?field=name&op=eq&value=Petstore HTTPS').replyWithFile(200, './test/testReplies/apimanager/manager-1/apiProxyManager1.json');
34+
nock('https://mocked-api-manager-0:8075').get(`/api/portal/v1.3/organizations/2bfaa1c2-49ab-4059-832d-team-a`).replyWithFile(200, './test/testReplies/apimanager/manager-1/orgTeamA.json');
3335
const { value, output } = await flowNode.lookupAPIDetails({
3436
apiName: 'Petstore HTTPS', apiPath: '/v1/petstore', groupId: 'group-unknown'
3537
});
3638

37-
expect(value).to.be.instanceOf(Error)
38-
.and.to.have.property('message', 'You have configured API-Manager URLs based on groupIds (e.g. group-a|https://manager-host.com:8075), but the groupId: group-unknown is NOT configured. Please check the configuration parameter: API_MANAGER');
39-
expect(output).to.equal('error');
39+
expect(value.organizationName).to.equal(`Team A`);
40+
expect(value.name).to.equal(`Petstore HTTPS`);
41+
expect(value.path).to.equal(`/v1/petstore`);
42+
expect(value.version).to.equal(`1.0.5 Manager 1`);
43+
expect(output).to.equal('next');
4044
});
4145

4246
it('should return the API-Details from the correct API-Manager based on the given groupId', async () => {

apibuilder4elastic/custom_flow_nodes/api-builder-plugin-axway-api-management/test/test-setup.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ describe('Configuration parameter tests', () => {
9292
expect(output).to.equal('error');
9393
} catch(e) {
9494
expect(e).to.be.an('Error')
95-
.and.to.have.property('message', 'Configured API-Manager user: user is either incorrect or has no Admin-Role.');
95+
.and.to.have.property('message', 'Error checking configured API-Manager(s). {"default":{"url":"https://mocked-api-gateway:8175","username":"user","password":"invalid","isValid":false}}');
9696
}
9797
nock.cleanAll();
9898
});

0 commit comments

Comments
 (0)