From 641fc788e39629d86540a712e7ccc9f2ed5063dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hugo=20Ar=C3=A8s?= Date: Thu, 8 Jan 2015 14:24:07 -0500 Subject: [PATCH] Add command to close SSH connection show-connections command display all the SSH connections but there was no command to close one. Change-Id: Ib90502892901428bd5c1a540266f359daafcbfd2 --- Documentation/cmd-close-connection.txt | 38 ++++++++ Documentation/cmd-index.txt | 3 + .../gerrit/sshd/commands/CloseConnection.java | 97 +++++++++++++++++++ .../sshd/commands/DefaultCommandModule.java | 1 + 4 files changed, 139 insertions(+) create mode 100644 Documentation/cmd-close-connection.txt create mode 100644 gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/CloseConnection.java diff --git a/Documentation/cmd-close-connection.txt b/Documentation/cmd-close-connection.txt new file mode 100644 index 0000000000..331432689d --- /dev/null +++ b/Documentation/cmd-close-connection.txt @@ -0,0 +1,38 @@ += gerrit close-connection + +== NAME +gerrit close-connection - Close the specified SSH connection + +== SYNOPSIS +-- +'ssh' -p 'gerrit close-connection' + [--wait] +-- + +== DESCRIPTION +Close an SSH connection. + +The connection closing is done asynchronously by default. Use `--wait` option to +wait for connection to close. + +An error message will be displayed if no connection with the specified session +ID is found. + +== ACCESS +Caller must be a member of the privileged 'Administrators' group. + +== SCRIPTING +Intended for interactive use only. + +OPTIONS +------- + +`--wait` +: Wait for connection to close before exiting. + +GERRIT +------ +Part of link:index.html[Gerrit Code Review] + +SEARCHBOX +--------- diff --git a/Documentation/cmd-index.txt b/Documentation/cmd-index.txt index 22d65add31..7c664ac728 100644 --- a/Documentation/cmd-index.txt +++ b/Documentation/cmd-index.txt @@ -96,6 +96,9 @@ git upload-pack:: [[admin_commands]]Administrator Commands ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +link:cmd-close-connection.html[gerrit close-connection]:: + Close the specified SSH connection. + link:cmd-create-account.html[gerrit create-account]:: Create a new user account. diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/CloseConnection.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/CloseConnection.java new file mode 100644 index 0000000000..91dd1dbdba --- /dev/null +++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/CloseConnection.java @@ -0,0 +1,97 @@ +// Copyright (C) 2015 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package com.google.gerrit.sshd.commands; + +import static com.google.gerrit.sshd.CommandMetaData.Mode.MASTER_OR_SLAVE; + +import com.google.gerrit.common.data.GlobalCapability; +import com.google.gerrit.extensions.annotations.RequiresCapability; +import com.google.gerrit.sshd.AdminHighPriorityCommand; +import com.google.gerrit.sshd.CommandMetaData; +import com.google.gerrit.sshd.SshCommand; +import com.google.gerrit.sshd.SshDaemon; +import com.google.gerrit.sshd.SshSession; +import com.google.inject.Inject; + +import org.apache.sshd.common.io.IoAcceptor; +import org.apache.sshd.common.io.IoCloseFuture; +import org.apache.sshd.common.io.IoSession; +import org.apache.sshd.server.session.ServerSession; +import org.kohsuke.args4j.Argument; +import org.kohsuke.args4j.Option; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.List; + +/** Close specified SSH connections */ +@AdminHighPriorityCommand +@RequiresCapability(GlobalCapability.ADMINISTRATE_SERVER) +@CommandMetaData(name = "close-connection", + description = "Close the specified SSH connection", runsAt = MASTER_OR_SLAVE) +final class CloseConnection extends SshCommand { + + private static final Logger log = LoggerFactory.getLogger(CloseConnection.class); + + @Inject + private SshDaemon sshDaemon; + + @Argument(index = 0, multiValued = true, required = true, + metaVar = "SESSION_ID", usage = "List of SSH session IDs to be closed") + private final List sessionIds = new ArrayList<>(); + + @Option(name = "--wait", + usage = "wait for connection to close before exiting") + private boolean wait; + + @Override + protected void run() throws Failure { + IoAcceptor acceptor = sshDaemon.getIoAcceptor(); + if (acceptor == null) { + throw new Failure(1, "fatal: sshd no longer running"); + } + for (String sessionId : sessionIds) { + boolean connectionFound = false; + int id = (int) Long.parseLong(sessionId, 16); + for (IoSession io : acceptor.getManagedSessions().values()) { + ServerSession serverSession = + (ServerSession) ServerSession.getSession(io, true); + SshSession sshSession = + serverSession != null + ? serverSession.getAttribute(SshSession.KEY) + : null; + if (sshSession != null && sshSession.getSessionId() == id) { + connectionFound = true; + stdout.println("closing connection " + sessionId + "..."); + IoCloseFuture future = io.close(true); + if (wait) { + try { + future.await(); + stdout.println("closed connection " + sessionId); + } catch (InterruptedException e) { + log.warn("Wait for connection to close interrupted: " + + e.getMessage()); + } + } + break; + } + } + if (!connectionFound) { + stderr.print("close connection " + sessionId + ": no such connection\n"); + } + } + } +} diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/DefaultCommandModule.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/DefaultCommandModule.java index cd20f2a830..f75eb2b191 100644 --- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/DefaultCommandModule.java +++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/DefaultCommandModule.java @@ -38,6 +38,7 @@ public class DefaultCommandModule extends CommandModule { command(gerrit).toProvider(new DispatchCommandProvider(gerrit)); command(gerrit, AproposCommand.class); command(gerrit, BanCommitCommand.class); + command(gerrit, CloseConnection.class); command(gerrit, FlushCaches.class); command(gerrit, ListProjectsCommand.class); command(gerrit, ListMembersCommand.class);