Skip to content

Commit

Permalink
porting changes from original pr #2081
Browse files Browse the repository at this point in the history
Signed-off-by: Amber Torrise <[email protected]>
  • Loading branch information
Amber Torrise committed Mar 26, 2024
1 parent e468a93 commit 3203bb1
Show file tree
Hide file tree
Showing 8 changed files with 104 additions and 8 deletions.
2 changes: 2 additions & 0 deletions packages/cli/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ All notable changes to the Zowe CLI package will be documented in this file.

## Recent Changes

- Enhancement: Prompt for user/password on SSH commands when a token is stored in the config. [#2081](https://github.com/zowe/zowe-cli/pull/2081)

- BugFix: Updated `tar` dependency to resolve technical currency [#2101](https://github.com/zowe/zowe-cli/issues/2101)

## `7.23.5`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -272,4 +272,16 @@ describe("zowe uss issue ssh passwords and passkeys", () => {
[command, "--ssh-p", invalidPrivateKey]);
expect(response.stderr.toString()).toMatch("no such file or directory, open 'bogusKey'");
});

it("should fail command execution without trace when improper user credentials", async () => {
// create a temporary zowe profile with an invalid user
const user = "bogusUser";
const invalidCreds = await TempTestProfiles.createV2Profile(TEST_ENVIRONMENT, "ssh",
{ host, port, user, password });

const command = "echo test";
const response = await runCliScript(__dirname + "/__scripts__/issue_ssh_no_cwd.sh", TEST_ENVIRONMENT,
[command, "--ssh-p", invalidCreds]);
expect(response.stderr.toString()).toMatch("All configured authentication methods failed");
});
});
4 changes: 4 additions & 0 deletions packages/imperative/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

All notable changes to the Imperative package will be documented in this file.

## Recent Changes

- Enhancement: Prompt for user/password on SSH commands when a token is stored in the config. [#2081](https://github.com/zowe/zowe-cli/pull/2081)

## `5.22.6`

- BugFix: Updated debugging output for technical currency. [#2098](https://github.com/zowe/zowe-cli/pull/2098)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,34 @@ describe("ConnectionPropsForSessCfg tests", () => {
expect(sessCfgWithConnProps.tokenValue).toBeUndefined();
});

it("ignore token and cert if unsupported auth types and authenticate with user and pass", async() => {
const initialSessCfg = {
hostname: "SomeHost",
port: 11,
rejectUnauthorized: true
};
const args = {
$0: "zowe",
_: [""],
cert: "fakeCert",
certKey: "fakeCertKey",
tokenType: SessConstants.TOKEN_TYPE_JWT,
tokenValue: "fakeToken"
};
const fakePromptFn = jest.fn().mockReturnValue({
"user": "FakeUser",
"password": "FakePassword"
});
const sessCfgWithConnProps = await ConnectionPropsForSessCfg.addPropsOrPrompt<ISession>(
initialSessCfg, args, {getValuesBack: fakePromptFn, supportedAuthTypes: ["basic"]}
);
expect(fakePromptFn).toHaveBeenCalledWith(["user", "password"]);
expect(sessCfgWithConnProps.hostname).toBe("SomeHost");
expect(sessCfgWithConnProps.user).toBe("FakeUser");
expect(sessCfgWithConnProps.password).toBe("FakePassword");
expect(sessCfgWithConnProps.type).toBe(SessConstants.AUTH_TYPE_BASIC);
});

it("not set tokenValue if user and pass are defined", async() => {
const initialSessCfg = {
hostname: "SomeHost",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,12 +139,16 @@ export class ConnectionPropsForSessCfg {
promptForValues.push("hostname");
}

if (ConnectionPropsForSessCfg.propHasValue(sessCfgToUse.port) === false && !doNotPromptForValues.includes("port")) {
if ((ConnectionPropsForSessCfg.propHasValue(sessCfgToUse.port) === false || sessCfgToUse.port === 0) &&
!doNotPromptForValues.includes("port")) {
promptForValues.push("port");
}

if (ConnectionPropsForSessCfg.propHasValue(sessCfgToUse.tokenValue) === false &&
ConnectionPropsForSessCfg.propHasValue(sessCfgToUse.cert) === false) {
const isTokenIrrelevant = ConnectionPropsForSessCfg.propHasValue(sessCfgToUse.tokenValue) === false ||
(connOpts.supportedAuthTypes && !connOpts.supportedAuthTypes.includes(SessConstants.AUTH_TYPE_TOKEN));
const isCertIrrelevant = ConnectionPropsForSessCfg.propHasValue(sessCfgToUse.cert) === false ||
(connOpts.supportedAuthTypes && !connOpts.supportedAuthTypes.includes(SessConstants.AUTH_TYPE_CERT_PEM));
if (isTokenIrrelevant && isCertIrrelevant) {
if (ConnectionPropsForSessCfg.propHasValue(sessCfgToUse.user) === false && !doNotPromptForValues.includes("user")) {
promptForValues.push("user");
}
Expand Down Expand Up @@ -268,7 +272,11 @@ export class ConnectionPropsForSessCfg {
// }
}

if (ConnectionPropsForSessCfg.propHasValue(sessCfg.tokenValue)) {
const isTokenUsed = ConnectionPropsForSessCfg.propHasValue(sessCfg.tokenValue) &&
(connOpts.supportedAuthTypes == null || connOpts.supportedAuthTypes.includes(SessConstants.AUTH_TYPE_TOKEN));
const isCertUsed = ConnectionPropsForSessCfg.propHasValue(sessCfg.cert) &&
(connOpts.supportedAuthTypes == null || connOpts.supportedAuthTypes.includes(SessConstants.AUTH_TYPE_CERT_PEM));
if (isTokenUsed) {
// when tokenValue is set at this point, we are definitely using the token.
impLogger.debug("Using token authentication");

Expand All @@ -284,7 +292,7 @@ export class ConnectionPropsForSessCfg {
// When no tokenType supplied, user wants bearer
sessCfg.type = SessConstants.AUTH_TYPE_BEARER;
}
} else if (ConnectionPropsForSessCfg.propHasValue(sessCfg.cert)) {
} else if (isCertUsed) {
// when cert property is set at this point, we will use the certificate
if (ConnectionPropsForSessCfg.propHasValue(sessCfg.certKey)) {
impLogger.debug("Using PEM Certificate authentication");
Expand Down Expand Up @@ -352,6 +360,31 @@ export class ConnectionPropsForSessCfg {
*/
private static getValuesBack(connOpts: IOptionsForAddConnProps): (properties: string[]) => Promise<{ [key: string]: any }> {
return async (promptForValues: string[]) => {
/* ToDo: Uncomment this code block to display an informative message before prompting
* a user for connection values. Because 219 unit test fails and 144 system tests
* fail due to a minor difference in output, we chose not to implement this
* minor enhancement until we have time to devote to correcting so many tests.
*
* The following 'if' statement is only needed for tests which do not create a mock for
* the connOpts.parms.response.console.log property. In the real world, that property
* always exists for this CLI-only path of logic.
*
if (connOpts?.parms?.response?.console?.log) {
// we want to prompt for connection values, but first complain if user only has V1 profiles.
connOpts.parms.response.console.log("No Zowe client configuration exists.");
if (ConfigUtils.onlyV1ProfilesExist) {
connOpts.parms.response.console.log(
"Only V1 profiles exist. V1 profiles are no longer supported.\n" +
"You should convert your V1 profiles to a Zowe client team configuration."
);
}
connOpts.parms.response.console.log(
"Therefore, you will be asked for the connection properties\n" +
"that are required to complete your command.\n"
);
}
*/

const answers: { [key: string]: any } = {};
const profileSchema = this.loadSchemaForSessCfgProps(connOpts.parms, promptForValues);
const serviceDescription = connOpts.serviceDescription || "your service";
Expand Down Expand Up @@ -510,4 +543,4 @@ export class ConnectionPropsForSessCfg {
this.secureSessCfgProps.add(secureProp === "host" ? "hostname" : secureProp);
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

import { SessConstants } from "../../..";
import { IHandlerParameters } from "../../../../cmd";
import { AUTH_TYPE_CHOICES } from "../SessConstants";
import { IOverridePromptConnProps } from "./IOverridePromptConnProps";

/**
Expand Down Expand Up @@ -82,4 +83,10 @@ export interface IOptionsForAddConnProps {
* exists.
*/
autoStore?: boolean;

/**
* Specifies list of authentication types that are supported for your
* service. Defaults to allow all authentication types.
*/
supportedAuthTypes?: AUTH_TYPE_CHOICES[];
}
5 changes: 5 additions & 0 deletions packages/zosuss/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@

All notable changes to the Zowe z/OS USS SDK package will be documented in this file.

## Recent Changes

- Enhancement: Provide more legible errors to user when they are missing user/password credentials while
running `zowe zos-uss issue ssh` commands. [#2081](https://github.com/zowe/zowe-cli/pull/2081)

## `7.21.1`

- BugFix: Updated `ssh2` package to resolve technical currency
Expand Down
9 changes: 7 additions & 2 deletions packages/zosuss/src/SshBaseHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ import {
IHandlerProgressApi,
IImperativeError,
ImperativeError,
ConnectionPropsForSessCfg
ConnectionPropsForSessCfg,
SessConstants
} from "@zowe/imperative";
import { SshSession } from "./SshSession";
import { ISshSession } from "./doc/ISshSession";
Expand Down Expand Up @@ -71,7 +72,11 @@ export abstract class SshBaseHandler implements ICommandHandler {
}];
const sshSessCfg: ISshSession = SshSession.createSshSessCfgFromArgs(commandParameters.arguments);
const sshSessCfgWithCreds = await ConnectionPropsForSessCfg.addPropsOrPrompt<ISshSession>(
sshSessCfg, commandParameters.arguments, {parms: commandParameters, propertyOverrides: sshSessCfgOverride}
sshSessCfg, commandParameters.arguments, {
parms: commandParameters,
propertyOverrides: sshSessCfgOverride,
supportedAuthTypes: [SessConstants.AUTH_TYPE_BASIC]
}
);
this.mSession = new SshSession(sshSessCfgWithCreds);

Expand Down

0 comments on commit 3203bb1

Please sign in to comment.