Skip to content

Commit

Permalink
Zowe Suite v1.28.0
Browse files Browse the repository at this point in the history
  • Loading branch information
zowe-robot authored May 11, 2022
2 parents 012d4a9 + 5ac7d01 commit 5a3ca6d
Show file tree
Hide file tree
Showing 14 changed files with 3,383 additions and 700 deletions.
104 changes: 104 additions & 0 deletions .github/workflows/build-core.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
name: Build Core
on:
push:
branches:
- v1.x/staging
- master
- rc
pull_request:
types: [opened, reopened, synchronize]

workflow_dispatch:
inputs:
ZLUX_APP_MANAGER:
description: 'zlux-app-manager PR number'
required: false
ZLUX_APP_SERVER:
description: 'zlux-app-server PR number'
required: false
ZLUX_BUILD:
description: 'zlux-build PR number'
required: false
ZLUX_PLATFORM:
description: 'zlux-platform PR number'
required: false

ZLUX_SERVER_FRAMEWORK:
description: 'zlux-server-framework PR number'
required: false
ZLUX_SHARED:
description: 'zlux-shared PR number'
required: false
DEFAULT_BRANCH:
description: 'please enter the default branch you would like to build with, default will be v2.x/staging'
required: false
default: 'v1.x/staging'

jobs:
check-permission:
runs-on: ubuntu-latest
steps:
# this action will fail the whole workflow if permission check fails
- name: check permission
uses: zowe-actions/shared-actions/permission-check@main
with:
user: ${{ github.actor }}
github-repo: ${{ github.repository }}
github-token: ${{ secrets.GITHUB_TOKEN }}

build:
runs-on: ubuntu-latest
needs: check-permission
steps:

- name: '[Prep 1] Cache node modules'
uses: actions/cache@v2
with:
# npm cache files are stored in `~/.npm` on Linux/macOS
path: |
~/.npm
~/.nvm/.cache
~/.nvm/versions
key: ${{ runner.os }}-build-cache-node-modules-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-build-cache-node-modules-
- name: '[Prep 2] Setup Node'
uses: actions/setup-node@v2
with:
node-version: 16

- name: '[Prep 3] Setup jFrog CLI'
uses: jfrog/setup-jfrog-cli@v2
env:
JF_ARTIFACTORY_1: ${{ secrets.JF_ARTIFACTORY_TOKEN }}

- name: '[Prep 4] prepare workflow'
uses: zowe-actions/zlux-builds/core/prepare@main
with:
github-user: ${{ secrets.ZOWE_ROBOT_USER }}
github-password: ${{ secrets.ZOWE_ROBOT_TOKEN }}
github-email: ${{ secrets.ZOWE_ROBOT_EMAIL }}
github-branch: ${{ github.event.inputs.BRANCH_NAME }}
default-base: ${{ github.event.inputs.DEFAULT_BRANCH }}

- name: '[Prep 5] build'
uses: zowe-actions/zlux-builds/core/build@main
with:
zlux-app-manager: ${{ github.event.inputs.ZLUX_APP_MANAGER }}
zlux-app-server: ${{ github.event.inputs.ZLUX_APP_SERVER }}
zlux-build: ${{ github.event.inputs.ZLUX_BUILD }}
zlux-platform: ${{ github.event.inputs.ZLUX_PLATFORM }}
zlux-server-framework: ${{ github.event.inputs.ZLUX_SERVER_FRAMEWORK }}
zlux-shared: ${{ github.event.inputs.ZLUX_SHARED }}

- name: '[Prep 6] packaging'
uses: zowe-actions/zlux-builds/core/package@main
with:
pax-ssh-username: ${{ secrets.SSH_MARIST_USERNAME }}
pax-ssh-password: ${{ secrets.SSH_MARIST_RACF_PASSWORD }}
pax-name: zlux-core

- name: '[Prep 7] deploy'
uses: zowe-actions/zlux-builds/core/deploy@main

7 changes: 6 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,15 @@
All notable changes to the Zlux Server Framework package will be documented in this file.
This repo is part of the app-server Zowe Component, and the change logs here may appear on Zowe.org in that section.

## 1.28.0

- Bugfix: keyring_js did not worked properly for finding CAs due to using an older version in package.json than needed for the listKeyring function
- Bugfix: Prevent loop upon EACCES error encountered when doing a TCP port bind
- Bugfix: Avoid retrying APIML login if initial attempt fails for any reason

## 1.27.0

- Bugfix: Added small check on agent network configuration to avoid throwing an exception if the agent configuration included JWT information, but not network information
- Bugfix: keyring_js did not worked properly for finding CAs due to using an older version in package.json than needed for the listKeyring function

## 1.25.0

Expand Down
5 changes: 3 additions & 2 deletions lib/apiml.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
Copyright Contributors to the Zowe Project.
*/
const Promise = require("bluebird");
const eureka = require('eureka-js-client').Eureka;
const eureka = require('@rocketsoftware/eureka-js-client').Eureka;
const zluxUtil = require('./util');
const https = require('https');

Expand Down Expand Up @@ -78,7 +78,8 @@ const MEDIATION_LAYER_INSTANCE_DEFAULTS = (zluxProto, zluxHostname, zluxPort) =>
+' Proxy Server',
'mfaas.api-info.apiVersionProperties.v1.version': '1.0.0',
'mfaas.api-info.apiVersionProperties.v1.version': '1.0.0',
'apiml.apiInfo.api-v1.swaggerUrl':`${zluxProto}://${zluxHostname}:${zluxPort}/api-docs/server`
'apiml.apiInfo.api-v1.swaggerUrl':`${zluxProto}://${zluxHostname}:${zluxPort}/api-docs/server`,
'apiml.authentication.scheme': 'zoweJwt'
}
}};

Expand Down
3 changes: 2 additions & 1 deletion lib/assets/i18n/log/messages_en.json
Original file line number Diff line number Diff line change
Expand Up @@ -377,5 +377,6 @@
"ZWED0154E":"RESERVED: (%s) is not a supported architecture for %s. Skipping (%s)... Supported: %s",
"ZWED0155E":"RESERVED: (%s) is not a supported endpoint for %s. Skipping (%s)... Supported: %s",
"ZWED0156E":"RESERVED: Could not register default plugins into app-server",
"ZWED0157E":"RESERVED: Could not register default plugin %s into app-server"
"ZWED0157E":"RESERVED: Could not register default plugin %s into app-server",
"ZWED0158E":"Could not listen on address %s:%s. Insufficient permissions to perform port bind."
}
13 changes: 10 additions & 3 deletions lib/url.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,19 +14,26 @@ function makePluginURL(productCode, pluginID) {
return `/${productCode}/plugins/${pluginID}`;
}

function makeServiceSubURL(service, latest, omitVersion) {
function makeServiceSubURL(service, latest, omitVersion, path) {
let url;
let nameForURL;
if (service.type === 'import') {
nameForURL = service.localName;
} else {
nameForURL = service.name;
}
if (omitVersion) {
return `/services/${nameForURL}`;
url = `/services/${nameForURL}`;
} else {
const version = latest? '_current' : service.version;
return `/services/${nameForURL}/${version}`;
url = `/services/${nameForURL}/${version}`;
}
if(path) {
return `${url}/${path}`;
} else {
return url;
}

}

function join(baseUrl, relativePath) {
Expand Down
7 changes: 4 additions & 3 deletions lib/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -402,14 +402,15 @@ module.exports.getRemoteIframeTemplate = function(remoteUrl) {

module.exports.makeRemoteUrl = function(destination, req, serverConfig) {
let referer = req.get('Referer');
let hostname = !referer ? '' : new URL(referer).hostname;
loggers.utilLogger.debug(`referer: ${referer}`);

let zoweExternalHost;
let zoweExternalPort;

if(destination.includes('ZOWE_EXTERNAL_HOST') || destination.includes('ZWE_EXTERNAL_HOST')) {
if( referer > '') {
zoweExternalHost = referer.split(':')[1].substring(2);
if( hostname > '') {
zoweExternalHost = hostname;
} else if (process.env.ZWE_EXTERNAL_HOST) {
zoweExternalHost = process.env.ZWE_EXTERNAL_HOST;
} else if (process.env.ZOWE_EXTERNAL_HOST) {
Expand Down
75 changes: 65 additions & 10 deletions lib/webapp.js
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ const jsonParser = bodyParser.json()
const urlencodedParser = bodyParser.urlencoded({ extended: false })
const ZLUX_LOOPBACK_HEADER = 'X-ZLUX-Loopback';
const proxyMap = new Map();

const pluginsArray = [];

//Referrer check used to be done for security, but the same thing can be accomplished in a much less obtrusive way
// via samesite attribute of cookies, which all supported browsers support
Expand Down Expand Up @@ -433,10 +433,10 @@ const staticHandlers = {
const loader = webapp.options.pluginLoader;
loader.readNewPluginDefs().then((defs)=> {
if (defs.length === 0) {
respondToGetPlugins(req, res, webapp, type, webapp.plugins);
respondToGetPlugins(req, res, webapp, type, pluginsArray);
} else {
loader.once('refreshFinish', (event) => {
respondToGetPlugins(req, res, webapp, type, webapp.plugins);
respondToGetPlugins(req, res, webapp, type, pluginsArray);
});
loader.installPlugins(defs).then( () => {
return;
Expand All @@ -445,7 +445,7 @@ const staticHandlers = {
});
}
} else {
respondToGetPlugins(req, res, webapp, type, webapp.plugins);
respondToGetPlugins(req, res, webapp, type, pluginsArray);
}
}
},
Expand Down Expand Up @@ -873,6 +873,7 @@ WebServiceHandle.prototype = {
urlPrefix: null,

call(path, options, originalRequest, originalRes) {
let serviceModified = true;
return new Promise((resolve, reject) => {
if (typeof path === "object") {
options = path;
Expand Down Expand Up @@ -929,6 +930,28 @@ WebServiceHandle.prototype = {
requestOptions.headers = headers;
}

while(this.service && this.service.type === 'import' && serviceModified) {
let reqDataservices;
serviceModified = false;
const reqPlugin = pluginsArray.filter(plugin => plugin.identifier === this.service.sourcePlugin);
reqPlugin.filter(plugin => {
if(plugin.dataServices) {
reqDataservices = plugin.dataServices.filter(dataService => dataService.name === this.service.sourceName);
}
})
if(reqDataservices) {
const sourcePlugin = this.service.sourcePlugin;
const sourceName = this.service.sourceName;
this.service = {...reqDataservices[0], sourcePlugin: sourcePlugin, sourceName: sourceName, imported: true };
serviceModified = true;
}
}

if(this.service && this.service.imported) {
requestOptions.path = zLuxUrl.makePluginURL('ZLUX', this.service.sourcePlugin) + zLuxUrl.makeServiceSubURL(this.service, false, false, path);
routingLog.debug(`Call agent host=%s import resolved to path=%s`,requestOptions.hostname, requestOptions.path);
}

let httpOrHttps;
if (this.isAgentService || (this.service && (this.service.type === 'external' || this.service.type === 'service'))) {
if(this.service && this.service.type === 'external') {
Expand Down Expand Up @@ -978,15 +1001,32 @@ WebServiceHandle.prototype = {

}

// Populating req.query with the query parameters
const queryString = path.includes('?') ? path.substring(path.indexOf('?') + 1) : '';
if(queryString !== '') {
const queryStringArray = queryString.split('&');
queryStringArray.forEach(pair => {
pair = pair.split('=');
req.query[pair[0]] = pair[1] || '';
})
}

if (options.body) {
req._body=options.body;
// We need to parse the JSON body since few services expect the parsed JSON but if the body isn't JSON then send as it is.
if (req.headers['content-type'] === 'application/json') {
req._body = JSON.parse(options.body);
req.body = JSON.parse(options.body);
} else {
req._body = options.body;
req.body = options.body;
}
} else {
delete req._body;
delete req.body;
}
if (!req.headers['content-length']) {
req.headers['content-length']='0';
}


res.end = (body)=> {
utilLog.debug('router returned with body=',body.length);
Expand All @@ -996,7 +1036,9 @@ WebServiceHandle.prototype = {
}
resolve(res);
}
expressApp._router.handle(req, res);
expressApp._router.handle(req, res, function(err) {
routingLog.debug(`Errors during processing the req with path=%s. Error=%s`, requestOptions.path, err);
});
} else {
routingLog.debug(`Call loopback path=%s`, requestOptions.path);
//loopback call to get to router
Expand All @@ -1005,6 +1047,20 @@ WebServiceHandle.prototype = {
}
//if not internal routing
if (httpOrHttps) {
// Removing the version from requestOptions.path if request is for zss
// Expected syntax for the req to app-server is /ZLUX/plugins/${service.pluginname}/services/${service.name}/${version}/${reqParam}
// Expected syntax for the req to zss is /ZLUX/plugins/${service.pluginname}/services/${service.name}/${reqParam}
if(requestOptions.hostname === this.environment.agentRequestOptions.host && requestOptions.port === this.environment.agentRequestOptions.port) {
const versionPattern = new RegExp('^([1-9]\d*|0)(\.(([1-9]\d*)|0)){2}$');
const pathArray = requestOptions.path.split('/');
const reqPathVersion = pathArray.length >= 7 ? pathArray[6] : '';
if(versionPattern.test(reqPathVersion) || reqPathVersion === '_current') {
//Removing the version from pathArray
pathArray.splice(6,1);
requestOptions.path = pathArray.join('/');
}
routingLog.debug(`Call agent host=%s path w/o version=%s`,requestOptions.hostname, requestOptions.path);
}
const request = httpOrHttps.request(requestOptions, (response) => {
var chunks = [];
response.on('data',(chunk)=> {
Expand Down Expand Up @@ -1378,7 +1434,6 @@ function WebApp(options){
}
//more stuff can be added
};
this.plugins = [];
//hack for pseudo-SSO
this.authServiceHandleMaps = {};
}
Expand Down Expand Up @@ -1586,7 +1641,7 @@ WebApp.prototype = {
serviceHandleMap['auth'] = new WebServiceHandle('/auth', this.wsEnvironment);
this._installRootService('/plugins', 'get', staticHandlers.plugins(this),
{needJson: false, needAuth: true, authType: "semi", isPseudoSso: false});
this._installRootService('/plugins', 'use', staticHandlers.pluginLifecycle(this.options, this.plugins),
this._installRootService('/plugins', 'use', staticHandlers.pluginLifecycle(this.options, pluginsArray),
{needJson: true, needAuth: true, isPseudoSso: false});
serviceHandleMap['plugins'] = new WebServiceHandle('/plugins', this.wsEnvironment);
this._installRootService('/server/proxies','get',staticHandlers.getServerProxies(this.options),
Expand Down Expand Up @@ -2016,7 +2071,7 @@ WebApp.prototype = {
throw e;
}
this._resolveImports(plugin, urlBase);
this.plugins.push(plugin);
pluginsArray.push(plugin);
}),

installErrorHanders() {
Expand Down
15 changes: 13 additions & 2 deletions lib/webauth.js
Original file line number Diff line number Diff line change
Expand Up @@ -222,10 +222,21 @@ module.exports = function(authManager, cookiePort, isSecurePort) {
const _doLogoutInner = Promise.coroutine(function*(req, res) {
//FIXME XSRF
const handlers = getRelevantHandlers(authManager, req.body);
const result = new LoginResult();
const result = new LoginResult();
let authServiceHandleMaps;
if (req[`${constants.APP_NAME}Data`] && req[`${constants.APP_NAME}Data`].webApp &&
req[`${constants.APP_NAME}Data`].webApp.authServiceHandleMaps) {
authServiceHandleMaps = req[`${constants.APP_NAME}Data`].webApp.authServiceHandleMaps
}

for (const handler of handlers) {
const pluginID = handler.pluginID;

if (authServiceHandleMaps) {
if (req[`${constants.APP_NAME}Data`].plugin) {
req[`${constants.APP_NAME}Data`].plugin.services = authServiceHandleMaps[pluginID];
}
}

let handlerResult;
if (handler.getCapabilities) {
try {
Expand Down
4 changes: 4 additions & 0 deletions lib/webserver.js
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,10 @@ WebServer.prototype = {
//making logging poor unless passed
server.on('error',(e)=> {
switch (e.code) {
case 'EACCES':
networkLogger.severe(`ZWED0158E`, ipAddress, port); //Could not listen on address %s:%s. Insufficient permissions to perform port bind.
process.exit(constants.EXIT_HTTPS_LOAD);
break;
case 'EADDRINUSE':
networkLogger.severe(`ZWED0004E`, ipAddress, port); //networkLogger.severe(`Could not listen on address ${ipAddress}:${port}. It is already in use by another process.`);
process.exit(constants.EXIT_HTTPS_LOAD);
Expand Down
Loading

0 comments on commit 5a3ca6d

Please sign in to comment.