Skip to content

Commit

Permalink
Merge pull request #2081 from zowe/ssh-error
Browse files Browse the repository at this point in the history
Ssh error
  • Loading branch information
traeok authored Mar 13, 2024
2 parents 4e08fa7 + 777a558 commit f3b9cb4
Show file tree
Hide file tree
Showing 10 changed files with 77 additions and 10 deletions.
3 changes: 2 additions & 1 deletion packages/cli/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@

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)

## `8.0.0-next.202403131702`

- BugFix: Removing stack trace for zosjobs errors. [#2078](https://github.com/zowe/zowe-cli/pull/2078)

## `8.0.0-next.202403122137`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,5 +45,4 @@ describe("zos-uss issue ssh command", () => {
expect(response.stderr.toString()).toContain('Command entered: "zos-uss issue ss"');
expect(response.stderr.toString()).toContain('Use "zowe --help" to view groups, commands, and options.');
});

});
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");
});
});
2 changes: 1 addition & 1 deletion packages/cli/src/zosuss/issue/ssh/Ssh.handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,4 @@ export default class Handler extends SshBaseHandler {
public handleStdout(data: string) {
this.parameters.response.console.log(Buffer.from(data));
}
}
}
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)

## `8.0.0-next.202403061549`

- V3 Breaking: Changed prompting logic to prompt for port if port provided is 0 [#2075](https://github.com/zowe/zowe-cli/issues/2075)
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 @@ -144,8 +144,11 @@ export class ConnectionPropsForSessCfg {
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 @@ -269,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 @@ -285,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
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)

## `8.0.0-next.202403041352`

- BugFix: Updated engine to Node 18.12.0. [#2074](https://github.com/zowe/zowe-cli/pull/2074)
Expand Down
10 changes: 7 additions & 3 deletions packages/zosuss/src/SshBaseHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,12 @@ import {
IHandlerProgressApi,
IImperativeError,
ImperativeError,
ConnectionPropsForSessCfg
ConnectionPropsForSessCfg,
SessConstants
} from "@zowe/imperative";
import { SshSession } from "./SshSession";
import { ISshSession } from "./doc/ISshSession";


/**
* This class is used by the various handlers in the project as the base class for their implementation.
*/
Expand Down Expand Up @@ -64,7 +64,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 f3b9cb4

Please sign in to comment.