Skip to content

Commit

Permalink
Zowe Suite v3.0.0
Browse files Browse the repository at this point in the history
  • Loading branch information
zowe-robot authored Sep 12, 2024
2 parents 61f70ed + c5147d5 commit 2a413f6
Show file tree
Hide file tree
Showing 24 changed files with 1,195 additions and 3,050 deletions.
20 changes: 11 additions & 9 deletions .github/workflows/build-core.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ name: Build Core
on:
push:
branches:
- v2.x/staging
- v3.x/staging
- v3.x/rc
- v3.x/master
pull_request:
types: [opened, reopened, synchronize]

Expand All @@ -28,9 +30,9 @@ on:
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'
description: 'please enter the default branch you would like to build with, default will be v3.x/staging'
required: false
default: 'v2.x/staging'
default: 'v3.x/staging'

jobs:
check-permission:
Expand Down Expand Up @@ -147,17 +149,17 @@ jobs:
${{ runner.os }}-build-cache-node-modules-
- name: '[Prep 2] Setup Node'
uses: actions/setup-node@v2
uses: actions/setup-node@v3
with:
node-version: 16.15.0
node-version: 18

- 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@v2.x/main
uses: zowe-actions/zlux-builds/core/prepare@v3.x/main
with:
github-user: ${{ secrets.ZOWE_ROBOT_USER }}
github-password: ${{ secrets.ZOWE_ROBOT_TOKEN }}
Expand All @@ -166,7 +168,7 @@ jobs:
default-base: ${{ github.event.inputs.DEFAULT_BRANCH }}

- name: '[Prep 5] build'
uses: zowe-actions/zlux-builds/core/build@v2.x/main
uses: zowe-actions/zlux-builds/core/build@v3.x/main
with:
zlux-app-manager: ${{ github.event.inputs.ZLUX_APP_MANAGER }}
zlux-app-server: ${{ github.event.inputs.ZLUX_APP_SERVER }}
Expand All @@ -176,12 +178,12 @@ jobs:
zlux-shared: ${{ github.event.inputs.ZLUX_SHARED }}

- name: '[Prep 6] packaging'
uses: zowe-actions/zlux-builds/core/package@v2.x/main
uses: zowe-actions/zlux-builds/core/package@v3.x/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@v2.x/main
uses: zowe-actions/zlux-builds/core/deploy@v3.x/main

16 changes: 16 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,22 @@
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.

## 2.17.0
- Enhancement: Added function `isClientAttls(zoweConfig)` within `libs/util.js`. Whenever a plugin makes a network request, it should always use this to determine if a normally HTTPS request should instead be made as HTTP due to AT-TLS handling the TLS when enabled. (#544)
- Bugfix: Fixed function `isServerAttls(zoweConfig)` within `libs/util.js`, which was preventing using AT-TLS with app-server. (#544)

## 2.15.0
- Bugfix: App-server could not run in HTTP mode for AT-TLS setup because it was not able to merge HTTPS and HTTP addresses. (#984)

## 2.14.0
- Bugfix: App-server could not load when multiple discovery servers were present and the app-server was unable to reach the first one specified. Now, the app-server will iterate through the list of servers until an accessible one is reached. (#522)
- Bugfix: App-server would not correctly detect when it was running in a high-availability configuration environment. (#521)
- Bugfix: A call to GET /plugins would trigger an authorization check regardless of if rbac was set on or off (#523)

## 2.13.0
- Added support for using zowe.network and components.app-server.zowe.network to set listener IP and TLS properties including max and min version, ciphers, and ECDH curves. (#511)
- Enhanced cipher customization to allow for ciphers to be specified in IANA format in addition to the existing OpenSSL format. (#511)

## 2.12.0

- Enhancement: Auth plugins that are not requested by any dataservice found at startup are no longer loaded by the server.
Expand Down
78 changes: 42 additions & 36 deletions lib/apiml.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ const Promise = require("bluebird");
const eureka = require('@rocketsoftware/eureka-js-client').Eureka;
const zluxUtil = require('./util');
const https = require('https');
const http = require('http');

const log = zluxUtil.loggers.apiml;

Expand Down Expand Up @@ -77,10 +78,10 @@ const MEDIATION_LAYER_INSTANCE_DEFAULTS = (zluxProto, zluxHostname, zluxPort) =>
}
}};

function ApimlConnector({ hostName, port, isHttps, discoveryHost,
discoveryPort, tlsOptions, eurekaOverrides }) {
Object.assign(this, { hostName, port, isHttps, discoveryHost,
discoveryPort, tlsOptions, eurekaOverrides });
function ApimlConnector({ hostName, port, discoveryUrls,
discoveryPort, tlsOptions, eurekaOverrides, isClientAttls }) {
Object.assign(this, { hostName, port, discoveryUrls,
discoveryPort, tlsOptions, eurekaOverrides, isClientAttls });
this.vipAddress = hostName;
}

Expand Down Expand Up @@ -110,29 +111,21 @@ ApimlConnector.prototype = {
const end = Date.now() + timer;

return new Promise((resolve, reject) => {
const options = Object.assign({
host: this.discoveryHost,
port: this.discoveryPort,
method: 'GET',
path: `/eureka/apps/${serviceName}`,
headers: {'accept':'application/json'}
}, this.tlsOptions);

if (!this.tlsOptions.rejectUnauthorized) {
//Keeping these certs causes an openssl error 46, unknown cert error in a dev environment
delete options.cert;
delete options.key;
} //else, apiml expects a cert and will give a 403.
const optionsArray = this.getRequestOptionsArray('GET', `/eureka/apps/${serviceName}`);
let optionsIndex = 0;

const issueRequest = () => {
const options = optionsArray[optionsIndex];
if (Date.now() > end) {
log.warn(`ZWED0045`, this.discoveryHost, this.discoveryPort);
log.warn(`ZWED0045W`, this.discoveryHost, this.discoveryPort);
return reject(new Error(`Call timeout when fetching agent status from APIML`));
}

let data = [];

let httpModule = this.isClientAttls ? http : https;

const req = https.request(options, (res) => {
const req = httpModule.request(options, (res) => {
res.on('data', (chunk) => data.push(chunk));
res.on('end', () => {
log.debug(`Query rc=`,res.statusCode);
Expand All @@ -156,7 +149,9 @@ ApimlConnector.prototype = {
reject(new Error(`Call timeout when fetching agent status from APIML`));
});
req.on('error', (error) => {
log.warn("APIML query error:", error.message);
log.warn("ZWED0180W", options.host, options.port, error.message);
//
optionsIndex = (optionsIndex+1) % optionsArray.length;
setTimeout(issueRequest, AGENT_CHECK_RECONNECT_DELAY);
});
req.end();
Expand All @@ -173,10 +168,10 @@ ApimlConnector.prototype = {
// If the HTTP port is set to 0 then the API ML doesn't load zlux
httpPort: Number(this.port),
httpsPort: Number(this.port),
httpEnabled: !this.isHttps,
httpsEnabled: this.isHttps
httpEnabled: false,
httpsEnabled: true
};
const proto = this.isHttps? 'https' : 'http';
const proto = 'https';

log.debug("ZWED0141I", proto, this.port); //"Protocol:", proto, "Port", port);
log.debug("ZWED0142I", JSON.stringify(protocolObject)); //"Protocol Object:", JSON.stringify(protocolObject));
Expand Down Expand Up @@ -249,8 +244,7 @@ ApimlConnector.prototype = {
}
log.debug("ZWED0144I", JSON.stringify(zluxProxyServerInstanceConfig, null, 2)); //log.debug("zluxProxyServerInstanceConfig: "
//+ JSON.stringify(zluxProxyServerInstanceConfig, null, 2))
const defaultUrl = `https://${this.discoveryHost}:${this.discoveryPort}/eureka/apps`;
const serviceUrls = this.getServiceUrls(defaultUrl);
const serviceUrls = this.getServiceUrls();
zluxProxyServerInstanceConfig.eureka.serviceUrls = { default: serviceUrls };
log.info(`ZWED0020I`, serviceUrls.join(',')); //log.info(`Registering at ${url}...`);
log.debug("ZWED0145I", JSON.stringify(zluxProxyServerInstanceConfig)); //log.debug(`zluxProxyServerInstanceConfig ${JSON.stringify(zluxProxyServerInstanceConfig)}`)
Expand Down Expand Up @@ -285,17 +279,29 @@ ApimlConnector.prototype = {
});
},

getServiceUrls(defaultUrl) {
const discoveryServiceList = process.env['ZWE_DISCOVERY_SERVICES_LIST'] || '';
const serviceUrls = discoveryServiceList
.split(',')
.map(url => url.trim())
.filter(url => url.length > 0)
.map(url => url + (url.endsWith('/') ? '' : '/') + 'apps');
if (serviceUrls.length === 0) {
serviceUrls.push(defaultUrl);
}
return serviceUrls;
getServiceUrls() {
return this.discoveryUrls.map(url => url + (url.endsWith('/') ? '' : '/') + 'apps');
},

getRequestOptionsArray(method, path) {
return this.discoveryUrls.map((url)=>{
//in the form of https://host:port/eureka/, trim from https:// and following slash.
const hostAndPort = url.substring(8, url.indexOf('/', 8)).split(':');
const options = Object.assign({
host: hostAndPort[0],
port: hostAndPort[1],
method: method,
path: path,
headers: {'accept':'application/json'}
}, this.tlsOptions);

if (!this.tlsOptions.rejectUnauthorized) {
//Keeping these certs causes an openssl error 46, unknown cert error in a dev environment
delete options.cert;
delete options.key;
} //else, apiml expects a cert and will give a 403.
return options;
});
}

/*
Expand Down
20 changes: 14 additions & 6 deletions lib/apimlStorage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,17 @@ import { AxiosInstance } from 'axios';
let apimlClient: AxiosInstance;

export function configure(settings: ApimlStorageSettings) {
apimlClient = axios.create({
baseURL: `https://${settings.host}:${settings.port}`,
httpsAgent: new https.Agent(settings.tlsOptions)
});
if (settings.isHttps) {
apimlClient = axios.create({
baseURL: `https://${settings.host}:${settings.port}`,
httpsAgent: new https.Agent(settings.tlsOptions)
});
} else {
apimlClient = axios.create({
baseURL: `https://${settings.host}:${settings.port}`,
httpAgent: new http.Agent()
});
}
}

export function isConfigured(): boolean {
Expand All @@ -30,6 +37,7 @@ export interface ApimlStorageSettings {
host: string;
port: number;
tlsOptions: https.AgentOptions;
isHttps?: boolean;
}


Expand Down Expand Up @@ -162,7 +170,7 @@ async function apimlDoRequest(req: ApimlRequest): Promise<ApimlResponse> {
headers: req.headers,
});
const apimlResponse: ApimlResponse = {
headers: response.headers,
headers: response.headers as http.IncomingHttpHeaders,
statusCode: response.status,
json: response.data
};
Expand Down Expand Up @@ -375,4 +383,4 @@ class ApimlStorage {
SPDX-License-Identifier: EPL-2.0
Copyright Contributors to the Zowe Project.
*/
*/
1 change: 1 addition & 0 deletions lib/assets/i18n/log/messages_en.json
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,7 @@
"ZWED0177W":"Unable to load %s for '%s' into config",
"ZWED0178W":"Skipping authentication plugin %s because it's not HA compatible",
"ZWED0179W":"Unable to retrieve the list of certificate authorities from the keyring=%s owner=%s Error: %s",
"ZWED0180W":"Failed to query discovery server (%s:%s) for agent access: %s",

"ZWED0001E":"RESERVED: Error: %s",
"ZWED0002E":"Could not stop language manager for types=%s",
Expand Down
3 changes: 2 additions & 1 deletion lib/auth-manager.js
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,8 @@ AuthManager.prototype = {
plugin,
this.configuration,
componentConfig,
new AuthPluginContext(plugin, tlsOptions));
new AuthPluginContext(plugin, tlsOptions),
config);
// at this time we should have resolved plugin configuration to have a
// nice list of info about what we are using to authenticate against
if ((typeof authenticationHandler.authenticate) !== 'function') {
Expand Down
16 changes: 8 additions & 8 deletions lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -218,11 +218,10 @@ Server.prototype = {
this.apiml = new ApimlConnector({
hostName: webAppOptions.hostname,
port: this.port,
isHttps: util.isServerHttps(this.zoweConfig),
discoveryHost: apimlConfig.server.hostname,
discoveryPort: apimlConfig.server.port,
discoveryUrls: apimlConfig.server.discoveryUrls || [`https://${apimlConfig.server.hostname}:${apimlConfig.server.port}/eureka/`],
tlsOptions: this.tlsOptions,
eurekaOverrides: apimlConfig.eureka
eurekaOverrides: apimlConfig.eureka,
isClientAttls: util.isClientAttls(this.zoweConfig)
});
yield this.apiml.setBestIpFromConfig(this.componentConfig.node);
yield this.apiml.registerMainServerInstance();
Expand All @@ -236,7 +235,7 @@ Server.prototype = {
&& this.componentConfig.agent.mediationLayer.serviceName
&& this.componentConfig.node.mediationLayer.server?.gatewayPort) {
//at this point, we expect zss to also be attached to the mediation layer, so lets adjust.
webAppOptions.proxiedHost = apimlConfig.server.hostname;
webAppOptions.proxiedHost = apimlConfig.server.gatewayHostname;
webAppOptions.proxiedPort = this.componentConfig.node.mediationLayer.server.gatewayPort;
if (firstWorker) {
yield this.apiml.checkAgent(this.componentConfig.agent.handshakeTimeout,
Expand Down Expand Up @@ -264,7 +263,7 @@ Server.prototype = {

bootstrapLogger.info('ZWED0302I', util.isHaMode() ? 'enabled' : 'disabled'); // "HA mode is %s"
if (apimlConfig.cachingService?.enabled) {
this.configureApimlStorage(apimlConfig);
this.configureApimlStorage(apimlConfig, util.isClientAttls(this.zoweConfig));
}

const plugins = yield this.loadPlugins();
Expand Down Expand Up @@ -336,11 +335,12 @@ Server.prototype = {
return yield this.pluginLoader.loadPlugins();
}),

configureApimlStorage(apimlConfig) {
configureApimlStorage(apimlConfig, isHttps) {
apimlStorage.configure({
host: apimlConfig.server.gatewayHostname,
port: apimlConfig.server.gatewayPort,
tlsOptions: this.tlsOptions
tlsOptions: this.tlsOptions,
isHttps: isHttps
});
bootstrapLogger.info(`ZWED0300I`); // Caching Service configured
},
Expand Down
4 changes: 2 additions & 2 deletions lib/swagger-catalog.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ const Promise = require('bluebird');
const zLuxUrl = require('./url')
const path = require('path');
const fs = require('fs');
const jsyaml = require('js-yaml');
const yaml = require('yaml');
const swaggerParser = require('swagger-parser')
const os = require('os');
const zluxUtil = require('./util');
Expand Down Expand Up @@ -201,7 +201,7 @@ function readSingleSwaggerFile (dirName, serviceName, serviceVersion) {
if (err) {
return reject(err);
}
let swaggerJson = jsyaml.safeLoad(fileContent);
let swaggerJson = yaml.parse(fileContent);
swaggerParser.validate(swaggerJson).then(function(valid) {
return resolve(swaggerJson)
}).catch(function(err) {
Expand Down
Loading

0 comments on commit 2a413f6

Please sign in to comment.