SSH commands with user: create account if needed

SSH commands that accept a user as parameter (e.g.
create-group, receive-pack) fail if for a
specified user an account is not existing. With
this change the command is not immediately failing,
but if a user is specified that has no account it
tries to authenticate the user and if the
authentication is successful a user account is
automatically created so that the SSH command can
succeed.

This is e.g. useful if you have an automated
process that creates committer groups for new
projects. Since it can happen that the users that
should be assigned to the new committer group
have never logged in into Gerrit, some of these
users may not have a Gerrit account and so the group
creation fails. However these users are all known in
the used LDAP system and so a Gerrit account can be
automatically created for them. With this the group
creation can be successful even if some of the
members did not log in into Gerrit before.

Signed-off-by: Edwin Kempin <edwin.kempin@sap.com>
Change-Id: Ic3bc7b802ab5c8b0da4953fe207e47a43c54bcf7
This commit is contained in:
Edwin Kempin
2010-12-07 11:33:51 +01:00
parent efde723fa4
commit 6b14d92374
2 changed files with 27 additions and 3 deletions

View File

@@ -24,6 +24,8 @@ import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.PeerDaemonUser;
import com.google.gerrit.server.RemotePeer;
import com.google.gerrit.server.account.AccountManager;
import com.google.gerrit.server.account.ChangeUserName;
import com.google.gerrit.server.config.FactoryModule;
import com.google.gerrit.server.config.GerritRequestModule;
import com.google.gerrit.server.git.TransferConfig;
@@ -75,6 +77,8 @@ public class SshModule extends FactoryModule {
bind(WorkQueue.Executor.class).annotatedWith(StreamCommandExecutor.class)
.toProvider(StreamCommandExecutorProvider.class).in(SINGLETON);
bind(QueueProvider.class).to(CommandExecutorQueueProvider.class).in(SINGLETON);
bind(AccountManager.class);
factory(ChangeUserName.Factory.class);
bind(PublickeyAuthenticator.class).to(DatabasePubKeyAuth.class);
bind(KeyPairProvider.class).toProvider(HostKeyProvider.class).in(SINGLETON);

View File

@@ -15,7 +15,11 @@
package com.google.gerrit.sshd.args4j;
import com.google.gerrit.reviewdb.Account;
import com.google.gerrit.server.account.AccountException;
import com.google.gerrit.server.account.AccountManager;
import com.google.gerrit.server.account.AccountResolver;
import com.google.gerrit.server.account.AuthRequest;
import com.google.gerrit.server.account.AuthResult;
import com.google.gwtorm.client.OrmException;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
@@ -29,14 +33,17 @@ import org.kohsuke.args4j.spi.Setter;
public class AccountIdHandler extends OptionHandler<Account.Id> {
private final AccountResolver accountResolver;
private final AccountManager accountManager;
@SuppressWarnings("unchecked")
@Inject
public AccountIdHandler(final AccountResolver accountResolver,
final AccountManager accountManager,
@Assisted final CmdLineParser parser, @Assisted final OptionDef option,
@Assisted final Setter setter) {
super(parser, option, setter);
this.accountResolver = accountResolver;
this.accountManager = accountManager;
}
@Override
@@ -46,10 +53,11 @@ public class AccountIdHandler extends OptionHandler<Account.Id> {
final Account.Id accountId;
try {
final Account a = accountResolver.find(token);
if (a == null) {
throw new CmdLineException(owner, "\"" + token + "\" is not registered");
if (a != null) {
accountId = a.getId();
} else {
accountId = createAccountIfUserCanBeAuthenticated(token);
}
accountId = a.getId();
} catch (OrmException e) {
throw new CmdLineException(owner, "database is down");
}
@@ -57,6 +65,18 @@ public class AccountIdHandler extends OptionHandler<Account.Id> {
return 1;
}
private Account.Id createAccountIfUserCanBeAuthenticated(final String username)
throws CmdLineException {
try {
final AuthRequest areq = AuthRequest.forUser(username);
final AuthResult arsp = accountManager.authenticate(areq);
return arsp.getAccountId();
} catch (AccountException e) {
throw new CmdLineException(owner, "Unable to authenticate user \""
+ username + "\"", e);
}
}
@Override
public final String getDefaultMetaVariable() {
return "EMAIL";