Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[JENKINS-41745] Non-Remoting-based CLI #2795

Merged
merged 64 commits into from
Apr 8, 2017

Conversation

jglick
Copy link
Member

@jglick jglick commented Mar 10, 2017

JENKINS-41745

Complete proposal

Downstream of jenkinsci/sshd-plugin#12. Also cf. jenkinsci/support-core-plugin#110, jenkins-infra/jenkins.io#802, jenkinsci-cert/SECURITY-218#8, #2834.

Proposed changelog entries:

  • JENKINS-41745: the use of Jenkins CLI in its traditional “Remoting” mode has been deprecated for security reasons; this mode will be disabled on new installations, and new downloads of jenkins-cli.jar require a -remoting option to use it. You may continue to access the CLI using a stock ssh command; or you may download a new jenkins-cli.jar supporting a new, default HTTP-based protocol as well as SSH-based access. See the client help text for options, as well as the CLI documentation.
  • The install-plugin command now supports a source of = to load a plugin *.hpi from standard input, since use of local file paths only worked in Remoting mode.
  • The build command’s -p option applied to a file parameter now supports a blank filename to load contents from standard input, since use of local file paths only worked in Remoting mode.
  • JENKINS-33595: the SSH port is now disabled by default on new installations. Use Configure Global Security to enable it.
  • implement PlainCLIProtocol on server
  • enhance client
    • implement -http mode and -auth
    • implement -ssh mode
    • -logger, and make client a little less chatty
  • deprecate Remoting-dependent APIs
    • CLICommand.channel, checkChannel, getClientEnvironmentVariable, getClientSystemProperty
    • CLI.<init> and instance methods and related members
    • ClientAuthenticationCache, CliAuthenticator
    • CommandDuringBuild and unsupportable commands
  • deprecate Remoting mode on server side
    • disable CliProtocol & CliProtocol2 in setup wizard
    • UI to enable
    • admin monitor when enabled
    • deprecate -Djenkins.CLI.disabled=true
  • new automated tests
    • tests of authentication modes in -http vs. -remoting
    • -ssh mode specifics
    • unit tests of PlainCLIProtocol
    • interleaved stdio in -http
    • interrupts à la build -s -v in all modes
    • locale & encoding in -http (neither supported by -ssh)
    • replace test usages of CLI with CLICommandInvoker where appropriate
  • improve core commands
    • InstallPluginCommand to accept - for SOURCE to read from stdin
    • FileParameterDefinition.createValue to accept - to read from stdin

@reviewbybees & @jenkinsci/code-reviewers

@jglick jglick added the work-in-progress The PR is under active development, not ready to the final review label Mar 10, 2017
jglick added 11 commits March 13, 2017 11:53
…sing Remoting transport other than SSH authentication.

(Verifying that this affects only @argument in CLICommand, not @CLIMethod.)
With the new HTTP protocol in JENKINS-41745, API tokens may be used to set a transport authentication.
…uth option passing BASIC authentication to /cli endpoint.

Simpler, does not rely on Remoting, allows use of API tokens, and bypasses JENKINS-12543.
(You could actually do this before but only by embedding userinfo in the -s URL, especially awkward for usernames containing @.)
Copy link
Member

@oleg-nenashev oleg-nenashev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sshConnection() uses Future await() calls without timeouts. There is also a case when the ClientSession may be leaked (didn't dig into).

client.setServerKeyVerifier(verifier);
client.start();

ConnectFuture cf = client.connect(user, sshHost, sshPort);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

client.stop() won't be invoked if this method or await() fail. Not sure if it matters

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should not matter. The process will exit anyway.

client.start();

ConnectFuture cf = client.connect(user, sshHost, sshPort);
cf.await();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🐛 no timeout

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So? Either it connects eventually; or the socket gives a timeout, in which case we get an exception; or the socket does not give a timeout, in which case the client waits and the user eventually kills it. Why would we need to impose an additional timeout?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in which case the client waits and the user eventually kills it

Jenkins CLI is also a tool for automation. Such possible hanging is not a good UX IMHO. Can convert to Ant if you feel strongly && can handle the possible fallout later if it happens

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Jenkins CLI is also a tool for automation.

Sure, and automated scripts typically have their own timeouts.

handle the possible fallout later if it happens

Remember that if anyone is dissatisfied with the quality of implementation of SSHCLI they can simply use an OpenSSH (or whatever) client, with its dozens of options and years of tuning and bug fixes. -ssh mode is provided as a convenience to minimize the friction of switching away from Remoting.

channel.setOut(new NoCloseOutputStream(System.out));
channel.setErr(new NoCloseOutputStream(System.err));
WaitableFuture wf = channel.open();
wf.await();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no timeout as well

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ditto.

This reverts commit 5caee58.
In fact ssh-cli-auth contains UserPropertyImpl which is used by the sshd module.
Copy link
Member

@oleg-nenashev oleg-nenashev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, here we go 🐝

@jglick jglick added ready-for-merge The PR is ready to go, and it will be merged soon if there is no negative feedback and removed needs-more-reviews Complex change, which would benefit from more eyes labels Apr 7, 2017
handleClose();
break; // TODO verify that we hit EOF immediately, not partway into framelen
} catch (IOException x) {
if (x.getCause() instanceof TimeoutException) {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On Tomcat 8 it seems this is a SocketTimeoutException. Have not yet checked whether catching that (and continuing) allows a long-running groovysh or the like to work.

We could also send empty ping packets in either direction after every 15s or so of inactivity on that side, but there is no way to know what timeouts will be applied by different containers.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jglick jglick merged commit 7ae404c into jenkinsci:master Apr 8, 2017
@jglick jglick deleted the SSH-CLI-JENKINS-41745 branch April 8, 2017 00:12
@oleg-nenashev
Copy link
Member

Well, I expected it to stay there for another day after @reviewbybees done and to ping code-reviewers. I am also not a big fan of merging PRs with 64 commits, which do not have JIRA ticket prefix or whatever. It really complicates backporting IMHO.

}

/**
* @param base the base URL of Jenkins
* @param target
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oops, should be relativeTarget.

kohsuke pushed a commit that referenced this pull request Apr 26, 2017
oleg-nenashev pushed a commit that referenced this pull request May 1, 2017
* Do not load detached plugins during tests.
Also warn about plugins which force us to create classes.jar.

* Porting POM fix from #2795: we must allow snapshots from repo.jenkins-ci.org so as to be able to test upstream component PRs.

* Fixed failures in tests which assumed detached plugins were being loaded.

* jenkins-test-harness 2.20

* Unreproducible test failure on CI, probably due to timing.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
ready-for-merge The PR is ready to go, and it will be merged soon if there is no negative feedback
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants