From 8982e6e0738c6991b9a4b864423bd4f75383c7f4 Mon Sep 17 00:00:00 2001 From: James Moger Date: Fri, 14 Mar 2014 12:20:45 -0400 Subject: [PATCH] Add add-key and rm-key commands that apply only to the current user --- .../com/gitblit/transport/ssh/SshDaemon.java | 18 +++--- .../transport/ssh/commands/AddKeyCommand.java | 54 ++++++++++++++++ .../ssh/commands/BaseKeyCommand.java | 58 +++++++++++++++++ .../ssh/commands/DispatchCommand.java | 6 +- .../ssh/commands/RemoveKeyCommand.java | 62 +++++++++++++++++++ .../ssh/commands/SetAccountCommand.java | 35 +---------- 6 files changed, 191 insertions(+), 42 deletions(-) create mode 100644 src/main/java/com/gitblit/transport/ssh/commands/AddKeyCommand.java create mode 100644 src/main/java/com/gitblit/transport/ssh/commands/BaseKeyCommand.java create mode 100644 src/main/java/com/gitblit/transport/ssh/commands/RemoveKeyCommand.java diff --git a/src/main/java/com/gitblit/transport/ssh/SshDaemon.java b/src/main/java/com/gitblit/transport/ssh/SshDaemon.java index 81d78784..c8c20f56 100644 --- a/src/main/java/com/gitblit/transport/ssh/SshDaemon.java +++ b/src/main/java/com/gitblit/transport/ssh/SshDaemon.java @@ -38,9 +38,11 @@ import com.gitblit.git.GitblitReceivePackFactory; import com.gitblit.git.GitblitUploadPackFactory; import com.gitblit.git.RepositoryResolver; import com.gitblit.manager.IGitblit; +import com.gitblit.transport.ssh.commands.AddKeyCommand; import com.gitblit.transport.ssh.commands.CreateRepository; import com.gitblit.transport.ssh.commands.DispatchCommand; import com.gitblit.transport.ssh.commands.Receive; +import com.gitblit.transport.ssh.commands.RemoveKeyCommand; import com.gitblit.transport.ssh.commands.ReviewCommand; import com.gitblit.transport.ssh.commands.SetAccountCommand; import com.gitblit.transport.ssh.commands.Upload; @@ -67,7 +69,7 @@ public class SshDaemon { public static enum SshSessionBackend { MINA, NIO2 } - + /** * 22: IANA assigned port number for ssh. Note that this is a distinct * concept from gitblit's default conf for ssh port -- this "default" is @@ -92,7 +94,7 @@ public class SshDaemon { public SshDaemon(IGitblit gitblit, IdGenerator idGenerator) { this.gitblit = gitblit; this.injector = ObjectGraph.create(new SshModule()); - + IStoredSettings settings = gitblit.getSettings(); int port = settings.getInteger(Keys.git.sshPort, 0); String bindInterface = settings.getString(Keys.git.sshBindInterface, @@ -107,7 +109,7 @@ public class SshDaemon { backend == SshSessionBackend.MINA ? MinaServiceFactoryFactory.class.getName() : Nio2ServiceFactoryFactory.class.getName()); - + InetSocketAddress addr; if (StringUtils.isEmpty(bindInterface)) { addr = new InetSocketAddress(port); @@ -131,6 +133,8 @@ public class SshDaemon { DispatchCommand gitblitCmd = new DispatchCommand(); gitblitCmd.registerCommand(CreateRepository.class); gitblitCmd.registerCommand(VersionCommand.class); + gitblitCmd.registerCommand(AddKeyCommand.class); + gitblitCmd.registerCommand(RemoveKeyCommand.class); gitblitCmd.registerCommand(SetAccountCommand.class); gitblitCmd.registerCommand(ReviewCommand.class); @@ -210,14 +214,14 @@ public class SshDaemon { } } } - + protected IKeyManager getKeyManager() { IKeyManager keyManager = null; IStoredSettings settings = gitblit.getSettings(); String clazz = settings.getString(Keys.git.sshKeysManager, FileKeyManager.class.getName()); if (StringUtils.isEmpty(clazz)) { clazz = FileKeyManager.class.getName(); - } + } try { Class managerClass = (Class) Class.forName(clazz); keyManager = injector.get(managerClass).start(); @@ -232,7 +236,7 @@ public class SshDaemon { } return keyManager; } - + /** * A nested Dagger graph is used for constructor dependency injection of * complex classes. @@ -252,7 +256,7 @@ public class SshDaemon { @Provides @Singleton NullKeyManager provideNullKeyManager() { return new NullKeyManager(); } - + @Provides @Singleton FileKeyManager provideFileKeyManager() { return new FileKeyManager(SshDaemon.this.gitblit); } diff --git a/src/main/java/com/gitblit/transport/ssh/commands/AddKeyCommand.java b/src/main/java/com/gitblit/transport/ssh/commands/AddKeyCommand.java new file mode 100644 index 00000000..69c4fecb --- /dev/null +++ b/src/main/java/com/gitblit/transport/ssh/commands/AddKeyCommand.java @@ -0,0 +1,54 @@ +/* + * Copyright 2014 gitblit.com. + * + * 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.gitblit.transport.ssh.commands; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import org.kohsuke.args4j.Argument; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.gitblit.transport.ssh.CommandMetaData; +import com.gitblit.transport.ssh.IKeyManager; + +/** + * Add a key to the current user's authorized keys list. + * + * @author James Moger + * + */ +@CommandMetaData(name = "add-key", description = "Add an SSH public key to your account") +public class AddKeyCommand extends BaseKeyCommand { + + protected final Logger log = LoggerFactory.getLogger(getClass()); + + @Argument(metaVar = "|KEY", usage = "the key to add") + private List addKeys = new ArrayList(); + + @Override + public void run() throws IOException, UnloggedFailure { + String username = ctx.getClient().getUsername(); + List keys = readKeys(addKeys); + IKeyManager keyManager = authenticator.getKeyManager(); + for (String key : keys) { + keyManager.addKey(username, key); + log.info("added SSH public key for {}", username); + } + authenticator.getKeyCache().invalidate(username); + } +} diff --git a/src/main/java/com/gitblit/transport/ssh/commands/BaseKeyCommand.java b/src/main/java/com/gitblit/transport/ssh/commands/BaseKeyCommand.java new file mode 100644 index 00000000..50927cc2 --- /dev/null +++ b/src/main/java/com/gitblit/transport/ssh/commands/BaseKeyCommand.java @@ -0,0 +1,58 @@ +/* + * Copyright 2014 gitblit.com. + * + * 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.gitblit.transport.ssh.commands; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.UnsupportedEncodingException; +import java.util.List; + +import com.gitblit.transport.ssh.SshKeyAuthenticator; +import com.google.common.base.Charsets; + +/** + * + * Base class for commands that read SSH keys from stdin or a parameter list. + * + */ +public abstract class BaseKeyCommand extends SshCommand { + + protected List readKeys(List sshKeys) + throws UnsupportedEncodingException, IOException { + int idx = -1; + if (sshKeys.isEmpty() || ((idx = sshKeys.indexOf("-")) >= 0)) { + String sshKey = ""; + BufferedReader br = new BufferedReader(new InputStreamReader( + in, Charsets.UTF_8)); + String line; + while ((line = br.readLine()) != null) { + sshKey += line + "\n"; + } + if (idx == -1) { + sshKeys.add(sshKey.trim()); + } else { + sshKeys.set(idx, sshKey.trim()); + } + } + return sshKeys; + } + + protected SshKeyAuthenticator authenticator; + public void setAuthenticator(SshKeyAuthenticator authenticator) { + this.authenticator = authenticator; + } +} diff --git a/src/main/java/com/gitblit/transport/ssh/commands/DispatchCommand.java b/src/main/java/com/gitblit/transport/ssh/commands/DispatchCommand.java index dc963309..672ecd61 100644 --- a/src/main/java/com/gitblit/transport/ssh/commands/DispatchCommand.java +++ b/src/main/java/com/gitblit/transport/ssh/commands/DispatchCommand.java @@ -198,9 +198,9 @@ public class DispatchCommand extends BaseCommand { d.setUploadPackFactory(gitblitUploadPackFactory); d.setReceivePackFactory(gitblitReceivePackFactory); d.setAuthenticator(authenticator); - } else if (cmd instanceof SetAccountCommand) { - SetAccountCommand setAccountCommand = (SetAccountCommand)cmd; - setAccountCommand.setAuthenticator(authenticator); + } else if (cmd instanceof BaseKeyCommand) { + BaseKeyCommand k = (BaseKeyCommand)cmd; + k.setAuthenticator(authenticator); } } diff --git a/src/main/java/com/gitblit/transport/ssh/commands/RemoveKeyCommand.java b/src/main/java/com/gitblit/transport/ssh/commands/RemoveKeyCommand.java new file mode 100644 index 00000000..0d491647 --- /dev/null +++ b/src/main/java/com/gitblit/transport/ssh/commands/RemoveKeyCommand.java @@ -0,0 +1,62 @@ +/* + * Copyright 2014 gitblit.com. + * + * 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.gitblit.transport.ssh.commands; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import org.kohsuke.args4j.Argument; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.gitblit.transport.ssh.CommandMetaData; +import com.gitblit.transport.ssh.IKeyManager; + + +/** + * Remove an SSH public key from the current user's authorized key list. + * + * @author James Moger + * + */ +@CommandMetaData(name = "rm-key", description = "Remove an SSH public key from your account") +public class RemoveKeyCommand extends BaseKeyCommand { + + protected final Logger log = LoggerFactory.getLogger(getClass()); + + private static final String ALL = "ALL"; + + @Argument(metaVar = "||ALL", usage = "the key to remove") + private List removeKeys = new ArrayList(); + + @Override + public void run() throws IOException, UnloggedFailure { + String username = ctx.getClient().getUsername(); + List keys = readKeys(removeKeys); + IKeyManager keyManager = authenticator.getKeyManager(); + if (keys.contains(ALL)) { + keyManager.removeAllKeys(username); + log.info("removed all SSH public keys from {}", username); + } else { + for (String key : keys) { + keyManager.removeKey(username, key); + log.info("removed SSH public key from {}", username); + } + } + authenticator.getKeyCache().invalidate(username); + } +} diff --git a/src/main/java/com/gitblit/transport/ssh/commands/SetAccountCommand.java b/src/main/java/com/gitblit/transport/ssh/commands/SetAccountCommand.java index 767f3cb4..0eabdce8 100644 --- a/src/main/java/com/gitblit/transport/ssh/commands/SetAccountCommand.java +++ b/src/main/java/com/gitblit/transport/ssh/commands/SetAccountCommand.java @@ -14,10 +14,7 @@ package com.gitblit.transport.ssh.commands; -import java.io.BufferedReader; import java.io.IOException; -import java.io.InputStreamReader; -import java.io.UnsupportedEncodingException; import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -27,12 +24,10 @@ import org.kohsuke.args4j.Option; import com.gitblit.transport.ssh.CommandMetaData; import com.gitblit.transport.ssh.IKeyManager; -import com.gitblit.transport.ssh.SshKeyAuthenticator; -import com.google.common.base.Charsets; /** Set a user's account settings. **/ @CommandMetaData(name = "set-account", description = "Change an account's settings") -public class SetAccountCommand extends SshCommand { +public class SetAccountCommand extends BaseKeyCommand { private static final String ALL = "ALL"; @@ -61,12 +56,12 @@ public class SetAccountCommand extends SshCommand { } private void setAccount() throws IOException, UnloggedFailure { - addSshKeys = readSshKey(addSshKeys); + addSshKeys = readKeys(addSshKeys); if (!addSshKeys.isEmpty()) { addSshKeys(addSshKeys); } - deleteSshKeys = readSshKey(deleteSshKeys); + deleteSshKeys = readKeys(deleteSshKeys); if (!deleteSshKeys.isEmpty()) { deleteSshKeys(deleteSshKeys); } @@ -91,28 +86,4 @@ public class SetAccountCommand extends SshCommand { } } } - - private List readSshKey(List sshKeys) - throws UnsupportedEncodingException, IOException { - if (!sshKeys.isEmpty()) { - String sshKey; - int idx = sshKeys.indexOf("-"); - if (idx >= 0) { - sshKey = ""; - BufferedReader br = new BufferedReader(new InputStreamReader( - in, Charsets.UTF_8)); - String line; - while ((line = br.readLine()) != null) { - sshKey += line + "\n"; - } - sshKeys.set(idx, sshKey); - } - } - return sshKeys; - } - - private SshKeyAuthenticator authenticator; - public void setAuthenticator(SshKeyAuthenticator authenticator) { - this.authenticator = authenticator; - } } -- 2.39.5