From 5eafd9b6f046a03eca0576ae14673be674b9ce01 Mon Sep 17 00:00:00 2001
From: David Ostrovsky <david@ostrovsky.org>
Date: Thu, 10 Apr 2014 18:58:08 -0400
Subject: [PATCH] Add set account SSH command
---
src/main/java/com/gitblit/transport/ssh/commands/SetAccountCommand.java | 118 +++++++++++++++++++++++++++++++++++++++
src/main/java/com/gitblit/transport/ssh/FileKeyManager.java | 8 ++
src/main/java/com/gitblit/transport/ssh/IKeyManager.java | 2
src/main/java/com/gitblit/transport/ssh/SshDaemon.java | 7 ++
src/main/java/com/gitblit/transport/ssh/commands/DispatchCommand.java | 10 +++
src/main/java/com/gitblit/transport/ssh/SshKeyAuthenticator.java | 9 +++
src/main/java/com/gitblit/transport/ssh/NullKeyManager.java | 5 +
7 files changed, 157 insertions(+), 2 deletions(-)
diff --git a/src/main/java/com/gitblit/transport/ssh/FileKeyManager.java b/src/main/java/com/gitblit/transport/ssh/FileKeyManager.java
index 87912ca..f590ab2 100644
--- a/src/main/java/com/gitblit/transport/ssh/FileKeyManager.java
+++ b/src/main/java/com/gitblit/transport/ssh/FileKeyManager.java
@@ -28,6 +28,7 @@
import com.gitblit.Keys;
import com.gitblit.manager.IRuntimeManager;
+import com.gitblit.utils.FileUtils;
import com.google.common.base.Charsets;
import com.google.common.io.Files;
@@ -144,7 +145,12 @@
}
return false;
}
-
+
+ @Override
+ public boolean removeAllKey(String username) {
+ return FileUtils.delete(getKeystore(username));
+ }
+
protected File getKeystore(String username) {
File dir = runtimeManager.getFileOrFolder(Keys.git.sshKeysFolder, "${baseFolder}/ssh");
dir.mkdirs();
diff --git a/src/main/java/com/gitblit/transport/ssh/IKeyManager.java b/src/main/java/com/gitblit/transport/ssh/IKeyManager.java
index 8b94fd6..3528bf1 100644
--- a/src/main/java/com/gitblit/transport/ssh/IKeyManager.java
+++ b/src/main/java/com/gitblit/transport/ssh/IKeyManager.java
@@ -36,4 +36,6 @@
boolean addKey(String username, String data);
boolean removeKey(String username, String data);
+
+ boolean removeAllKey(String username);
}
diff --git a/src/main/java/com/gitblit/transport/ssh/NullKeyManager.java b/src/main/java/com/gitblit/transport/ssh/NullKeyManager.java
index 2a2ef36..6990d0d 100644
--- a/src/main/java/com/gitblit/transport/ssh/NullKeyManager.java
+++ b/src/main/java/com/gitblit/transport/ssh/NullKeyManager.java
@@ -63,4 +63,9 @@
public boolean removeKey(String username, String data) {
return false;
}
+
+ @Override
+ public boolean removeAllKey(String username) {
+ return false;
+ }
}
diff --git a/src/main/java/com/gitblit/transport/ssh/SshDaemon.java b/src/main/java/com/gitblit/transport/ssh/SshDaemon.java
index f0429a7..f2e1db7 100644
--- a/src/main/java/com/gitblit/transport/ssh/SshDaemon.java
+++ b/src/main/java/com/gitblit/transport/ssh/SshDaemon.java
@@ -44,6 +44,7 @@
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.SetAccountCommand;
import com.gitblit.transport.ssh.commands.Upload;
import com.gitblit.transport.ssh.commands.VersionCommand;
import com.gitblit.utils.IdGenerator;
@@ -116,12 +117,14 @@
addr = new InetSocketAddress(bindInterface, port);
}
+ SshKeyAuthenticator publickeyAuthenticator = new SshKeyAuthenticator(
+ keyManager, gitblit);
sshd = SshServer.setUpDefaultServer();
sshd.setPort(addr.getPort());
sshd.setHost(addr.getHostName());
sshd.setKeyPairProvider(new PEMGeneratorHostKeyProvider(new File(
gitblit.getBaseFolder(), HOST_KEY_STORE).getPath()));
- sshd.setPublickeyAuthenticator(new SshKeyAuthenticator(keyManager, gitblit));
+ sshd.setPublickeyAuthenticator(publickeyAuthenticator);
sshd.setPasswordAuthenticator(new SshPasswordAuthenticator(gitblit));
sshd.setSessionFactory(new SshSessionFactory(idGenerator));
sshd.setFileSystemFactory(new DisabledFilesystemFactory());
@@ -130,6 +133,7 @@
DispatchCommand gitblitCmd = new DispatchCommand();
gitblitCmd.registerCommand(CreateRepository.class);
gitblitCmd.registerCommand(VersionCommand.class);
+ gitblitCmd.registerCommand(SetAccountCommand.class);
DispatchCommand gitCmd = new DispatchCommand();
gitCmd.registerCommand(Upload.class);
@@ -142,6 +146,7 @@
root.setRepositoryResolver(new RepositoryResolver<SshSession>(gitblit));
root.setUploadPackFactory(new GitblitUploadPackFactory<SshSession>(gitblit));
root.setReceivePackFactory(new GitblitReceivePackFactory<SshSession>(gitblit));
+ root.setAuthenticator(publickeyAuthenticator);
SshCommandFactory commandFactory = new SshCommandFactory(
new WorkQueue(idGenerator),
diff --git a/src/main/java/com/gitblit/transport/ssh/SshKeyAuthenticator.java b/src/main/java/com/gitblit/transport/ssh/SshKeyAuthenticator.java
index d41afdd..f1bff4f 100644
--- a/src/main/java/com/gitblit/transport/ssh/SshKeyAuthenticator.java
+++ b/src/main/java/com/gitblit/transport/ssh/SshKeyAuthenticator.java
@@ -26,6 +26,7 @@
import com.gitblit.manager.IAuthenticationManager;
import com.gitblit.models.UserModel;
+import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
@@ -91,4 +92,12 @@
sd.authenticationError(username, "user-not-found");
return false;
}
+
+ public IKeyManager getKeyManager() {
+ return keyManager;
+ }
+
+ public Cache<String, List<PublicKey>> getKeyCache() {
+ return sshKeyCache;
+ }
}
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 597b9ea..31b718e 100644
--- a/src/main/java/com/gitblit/transport/ssh/commands/DispatchCommand.java
+++ b/src/main/java/com/gitblit/transport/ssh/commands/DispatchCommand.java
@@ -32,6 +32,7 @@
import com.gitblit.git.RepositoryResolver;
import com.gitblit.transport.ssh.AbstractGitCommand;
import com.gitblit.transport.ssh.CommandMetaData;
+import com.gitblit.transport.ssh.SshKeyAuthenticator;
import com.gitblit.transport.ssh.SshSession;
import com.gitblit.utils.cli.SubcommandHandler;
import com.google.common.base.Charsets;
@@ -196,6 +197,10 @@
d.setRepositoryResolver(repositoryResolver);
d.setUploadPackFactory(gitblitUploadPackFactory);
d.setReceivePackFactory(gitblitReceivePackFactory);
+ d.setAuthenticator(authenticator);
+ } else if (cmd instanceof SetAccountCommand) {
+ SetAccountCommand setAccountCommand = (SetAccountCommand)cmd;
+ setAccountCommand.setAuthenticator(authenticator);
}
}
@@ -213,4 +218,9 @@
public void setReceivePackFactory(GitblitReceivePackFactory<SshSession> gitblitReceivePackFactory) {
this.gitblitReceivePackFactory = gitblitReceivePackFactory;
}
+
+ private SshKeyAuthenticator authenticator;
+ public void setAuthenticator(SshKeyAuthenticator authenticator) {
+ this.authenticator = authenticator;
+ }
}
diff --git a/src/main/java/com/gitblit/transport/ssh/commands/SetAccountCommand.java b/src/main/java/com/gitblit/transport/ssh/commands/SetAccountCommand.java
new file mode 100644
index 0000000..98d9aba
--- /dev/null
+++ b/src/main/java/com/gitblit/transport/ssh/commands/SetAccountCommand.java
@@ -0,0 +1,118 @@
+//Copyright (C) 2012 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.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;
+
+import org.kohsuke.args4j.Argument;
+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 {
+
+ private static final String ALL = "ALL";
+
+ @Argument(index = 0, required = true, metaVar = "USER", usage = "full name, email-address, ssh username or account id")
+ private String user;
+
+ @Option(name = "--add-ssh-key", metaVar = "-|KEY", usage = "public keys to add to the account")
+ private List<String> addSshKeys = new ArrayList<String>();
+
+ @Option(name = "--delete-ssh-key", metaVar = "-|KEY", usage = "public keys to delete from the account")
+ private List<String> deleteSshKeys = new ArrayList<String>();
+
+ @Override
+ public void run() throws IOException, UnloggedFailure {
+ validate();
+ setAccount();
+ }
+
+ private void validate() throws UnloggedFailure {
+ if (addSshKeys.contains("-") && deleteSshKeys.contains("-")) {
+ throw new UnloggedFailure(1, "Only one option may use the stdin");
+ }
+ if (deleteSshKeys.contains(ALL)) {
+ deleteSshKeys = Collections.singletonList(ALL);
+ }
+ }
+
+ private void setAccount() throws IOException, UnloggedFailure {
+ addSshKeys = readSshKey(addSshKeys);
+ if (!addSshKeys.isEmpty()) {
+ addSshKeys(addSshKeys);
+ }
+
+ deleteSshKeys = readSshKey(deleteSshKeys);
+ if (!deleteSshKeys.isEmpty()) {
+ deleteSshKeys(deleteSshKeys);
+ }
+ authenticator.getKeyCache().invalidate(user);
+ }
+
+ private void addSshKeys(List<String> sshKeys) throws UnloggedFailure,
+ IOException {
+ IKeyManager keyManager = authenticator.getKeyManager();
+ for (String sshKey : sshKeys) {
+ keyManager.addKey(user, sshKey);
+ }
+ }
+
+ private void deleteSshKeys(List<String> sshKeys) {
+ IKeyManager keyManager = authenticator.getKeyManager();
+ if (sshKeys.contains(ALL)) {
+ keyManager.removeAllKey(user);
+ } else {
+ for (String sshKey : sshKeys) {
+ keyManager.removeKey(user, sshKey);
+ }
+ }
+ }
+
+ private List<String> readSshKey(List<String> 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;
+ }
+}
--
Gitblit v1.9.1