diff options
author | Antonio Barone <syntonyze@gmail.com> | 2018-11-09 10:12:24 +0000 |
---|---|---|
committer | Antonio Barone <syntonyze@gmail.com> | 2018-11-12 11:11:18 -0800 |
commit | 76394d2a89b5e38ccd4496ae39cc45dde551415f (patch) | |
tree | 47fff3582af83f286031d56e1a45d9b372bfd6e0 | |
parent | 2d1c67e51bac58ca196e455899878ce91502d5af (diff) |
Trigger audit for GIT over Http commands
Before this change only git over SSH commands were audited, this
change allows auditing of git-receive-pack and git-upload-pack
commands over http.
To allow testing AuditService is now an interface so that a fake
implementation can be injected in the tests.
Bug: Issue 9982
Change-Id: Iffcd0fbd7332ef0f6b4b4a8e57bb5d571ee4cb39
11 files changed, 349 insertions, 69 deletions
diff --git a/gerrit-acceptance-framework/src/test/java/com/google/gerrit/acceptance/AbstractDaemonTest.java b/gerrit-acceptance-framework/src/test/java/com/google/gerrit/acceptance/AbstractDaemonTest.java index 9e4595351e..3d81179e69 100644 --- a/gerrit-acceptance-framework/src/test/java/com/google/gerrit/acceptance/AbstractDaemonTest.java +++ b/gerrit-acceptance-framework/src/test/java/com/google/gerrit/acceptance/AbstractDaemonTest.java @@ -109,6 +109,7 @@ import com.google.gerrit.server.query.change.ChangeData; import com.google.gerrit.server.query.change.InternalChangeQuery; import com.google.gerrit.server.update.BatchUpdate; import com.google.gerrit.testutil.ConfigSuite; +import com.google.gerrit.testutil.FakeAuditService; import com.google.gerrit.testutil.FakeEmailSender; import com.google.gerrit.testutil.FakeEmailSender.Message; import com.google.gerrit.testutil.NoteDbMode; @@ -215,6 +216,7 @@ public abstract class AbstractDaemonTest { @Inject protected ChangeNoteUtil changeNoteUtil; @Inject protected ChangeResource.Factory changeResourceFactory; @Inject protected FakeEmailSender sender; + @Inject protected FakeAuditService auditService; @Inject protected GerritApi gApi; @Inject protected GitRepositoryManager repoManager; @Inject protected GroupCache groupCache; diff --git a/gerrit-acceptance-framework/src/test/java/com/google/gerrit/acceptance/GerritServer.java b/gerrit-acceptance-framework/src/test/java/com/google/gerrit/acceptance/GerritServer.java index f72403368e..7e5fd5cc94 100644 --- a/gerrit-acceptance-framework/src/test/java/com/google/gerrit/acceptance/GerritServer.java +++ b/gerrit-acceptance-framework/src/test/java/com/google/gerrit/acceptance/GerritServer.java @@ -33,6 +33,7 @@ import com.google.gerrit.server.util.ManualRequestContext; import com.google.gerrit.server.util.OneOffRequestContext; import com.google.gerrit.server.util.SocketUtil; import com.google.gerrit.server.util.SystemLog; +import com.google.gerrit.testutil.FakeAuditService; import com.google.gerrit.testutil.FakeEmailSender; import com.google.gerrit.testutil.NoteDbChecker; import com.google.gerrit.testutil.NoteDbMode; @@ -301,6 +302,7 @@ public class GerritServer implements AutoCloseable { }, site); daemon.setEmailModuleForTesting(new FakeEmailSender.Module()); + daemon.setAuditEventModuleForTesting(new FakeAuditService.Module()); daemon.setAdditionalSysModuleForTesting(testSysModule); daemon.setEnableSshd(desc.useSsh()); diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/git/GitOverHttpServletIT.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/git/GitOverHttpServletIT.java new file mode 100644 index 0000000000..f6d4277d63 --- /dev/null +++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/git/GitOverHttpServletIT.java @@ -0,0 +1,68 @@ +// Copyright (C) 2018 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.acceptance.git; + +import static com.google.common.truth.Truth.assertThat; + +import com.google.gerrit.audit.AuditEvent; +import java.util.Collections; +import org.eclipse.jgit.transport.CredentialsProvider; +import org.eclipse.jgit.transport.RefSpec; +import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider; +import org.junit.Before; +import org.junit.Test; + +public class GitOverHttpServletIT extends AbstractPushForReview { + + @Before + public void beforeEach() throws Exception { + CredentialsProvider.setDefault( + new UsernamePasswordCredentialsProvider(admin.username, admin.httpPassword)); + selectProtocol(AbstractPushForReview.Protocol.HTTP); + auditService.clearEvents(); + } + + @Test + public void receivePackAuditEventLog() throws Exception { + testRepo + .git() + .push() + .setRemote("origin") + .setRefSpecs(new RefSpec("HEAD:refs/for/master")) + .call(); + + // Git smart protocol makes two requests: + // https://github.com/git/git/blob/master/Documentation/technical/http-protocol.txt + assertThat(auditService.auditEvents.size()).isEqualTo(2); + + AuditEvent e = auditService.auditEvents.get(1); + assertThat(e.who.getAccountId()).isEqualTo(admin.id); + assertThat(e.what).endsWith("/git-receive-pack"); + assertThat(e.params).isEmpty(); + } + + @Test + public void uploadPackAuditEventLog() throws Exception { + testRepo.git().fetch().call(); + + assertThat(auditService.auditEvents.size()).isEqualTo(1); + + AuditEvent e = auditService.auditEvents.get(0); + assertThat(e.who.toString()).isEqualTo("ANONYMOUS"); + assertThat(e.params.get("service")) + .containsExactlyElementsIn(Collections.singletonList("git-upload-pack")); + assertThat(e.what).endsWith("service=git-upload-pack"); + } +} diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/GitOverHttpServlet.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/GitOverHttpServlet.java index 329beabfb7..0da2f92cd2 100644 --- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/GitOverHttpServlet.java +++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/GitOverHttpServlet.java @@ -15,8 +15,13 @@ package com.google.gerrit.httpd; import com.google.common.cache.Cache; +import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.ImmutableSetMultimap; +import com.google.common.collect.ListMultimap; import com.google.common.collect.Lists; +import com.google.gerrit.audit.AuditService; +import com.google.gerrit.audit.HttpAuditEvent; +import com.google.gerrit.common.TimeUtil; import com.google.gerrit.common.data.Capable; import com.google.gerrit.extensions.registration.DynamicSet; import com.google.gerrit.extensions.restapi.AuthException; @@ -141,6 +146,30 @@ public class GitOverHttpServlet extends GitServlet { addReceivePackFilter(receiveFilter); } + private static String extractWhat(HttpServletRequest request) { + StringBuilder commandName = new StringBuilder(request.getRequestURL()); + if (request.getQueryString() != null) { + commandName.append("?").append(request.getQueryString()); + } + return commandName.toString(); + } + + private static ListMultimap<String, String> extractParameters(HttpServletRequest request) { + + ListMultimap<String, String> multiMap = ArrayListMultimap.create(); + if (request.getQueryString() != null) { + request + .getParameterMap() + .forEach( + (k, v) -> { + for (int i = 0; i < v.length; i++) { + multiMap.put(k, v[i]); + } + }); + } + return multiMap; + } + static class Resolver implements RepositoryResolver<HttpServletRequest> { private final GitRepositoryManager manager; private final PermissionBackend permissionBackend; @@ -243,15 +272,21 @@ public class GitOverHttpServlet extends GitServlet { private final VisibleRefFilter.Factory refFilterFactory; private final UploadValidators.Factory uploadValidatorsFactory; private final PermissionBackend permissionBackend; + private final Provider<CurrentUser> userProvider; + private final AuditService auditService; @Inject UploadFilter( VisibleRefFilter.Factory refFilterFactory, UploadValidators.Factory uploadValidatorsFactory, - PermissionBackend permissionBackend) { + PermissionBackend permissionBackend, + Provider<CurrentUser> userProvider, + AuditService auditService) { this.refFilterFactory = refFilterFactory; this.uploadValidatorsFactory = uploadValidatorsFactory; this.permissionBackend = permissionBackend; + this.userProvider = userProvider; + this.auditService = auditService; } @Override @@ -276,7 +311,22 @@ public class GitOverHttpServlet extends GitServlet { return; } catch (PermissionBackendException e) { throw new ServletException(e); + } finally { + HttpServletRequest httpRequest = (HttpServletRequest) request; + HttpServletResponse httpResponse = (HttpServletResponse) response; + auditService.dispatch( + new HttpAuditEvent( + httpRequest.getSession().getId(), + userProvider.get(), + extractWhat(httpRequest), + TimeUtil.nowMs(), + extractParameters(httpRequest), + httpRequest.getMethod(), + httpRequest, + httpResponse.getStatus(), + httpResponse)); } + // We use getRemoteHost() here instead of getRemoteAddr() because REMOTE_ADDR // may have been overridden by a proxy server -- we'll try to avoid this. UploadValidators uploadValidators = @@ -331,13 +381,19 @@ public class GitOverHttpServlet extends GitServlet { static class ReceiveFilter implements Filter { private final Cache<AdvertisedObjectsCacheKey, Set<ObjectId>> cache; private final PermissionBackend permissionBackend; + private final Provider<CurrentUser> userProvider; + private final AuditService auditService; @Inject ReceiveFilter( @Named(ID_CACHE) Cache<AdvertisedObjectsCacheKey, Set<ObjectId>> cache, - PermissionBackend permissionBackend) { + PermissionBackend permissionBackend, + Provider<CurrentUser> userProvider, + AuditService auditService) { this.cache = cache; this.permissionBackend = permissionBackend; + this.userProvider = userProvider; + this.auditService = auditService; } @Override @@ -365,6 +421,20 @@ public class GitOverHttpServlet extends GitServlet { return; } catch (PermissionBackendException e) { throw new RuntimeException(e); + } finally { + HttpServletRequest httpRequest = (HttpServletRequest) request; + HttpServletResponse httpResponse = (HttpServletResponse) response; + auditService.dispatch( + new HttpAuditEvent( + httpRequest.getSession().getId(), + userProvider.get(), + extractWhat(httpRequest), + TimeUtil.nowMs(), + extractParameters(httpRequest), + httpRequest.getMethod(), + httpRequest, + httpResponse.getStatus(), + httpResponse)); } Capable s = arc.canUpload(); diff --git a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/Daemon.java b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/Daemon.java index edebd9a1f5..5fd3968631 100644 --- a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/Daemon.java +++ b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/Daemon.java @@ -20,6 +20,7 @@ import static java.nio.charset.StandardCharsets.UTF_8; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.MoreObjects; +import com.google.gerrit.audit.AuditModule; import com.google.gerrit.common.EventBroker; import com.google.gerrit.common.Nullable; import com.google.gerrit.elasticsearch.ElasticIndexModule; @@ -193,6 +194,7 @@ public class Daemon extends SiteProgram { private AbstractModule luceneModule; private Module emailModule; private Module testSysModule; + private Module auditEventModule; private Runnable serverStarted; private IndexType indexType; @@ -310,6 +312,11 @@ public class Daemon extends SiteProgram { } @VisibleForTesting + public void setAuditEventModuleForTesting(Module module) { + auditEventModule = module; + } + + @VisibleForTesting public void setLuceneModule(LuceneIndexModule m) { luceneModule = m; inMemoryTest = true; @@ -421,6 +428,11 @@ public class Daemon extends SiteProgram { } else { modules.add(new SmtpEmailSender.Module()); } + if (auditEventModule != null) { + modules.add(auditEventModule); + } else { + modules.add(new AuditModule()); + } modules.add(new SignedTokenEmailTokenVerifier.Module()); modules.add(new PluginRestApiModule()); modules.add(new RestCacheAdminModule()); diff --git a/gerrit-server/src/main/java/com/google/gerrit/audit/AuditModule.java b/gerrit-server/src/main/java/com/google/gerrit/audit/AuditModule.java index aedb8a7a28..d5bd8d86c7 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/audit/AuditModule.java +++ b/gerrit-server/src/main/java/com/google/gerrit/audit/AuditModule.java @@ -23,6 +23,6 @@ public class AuditModule extends AbstractModule { protected void configure() { DynamicSet.setOf(binder(), AuditListener.class); DynamicSet.setOf(binder(), GroupMemberAuditListener.class); - bind(AuditService.class); + bind(AuditService.class).to(AuditServiceImpl.class); } } diff --git a/gerrit-server/src/main/java/com/google/gerrit/audit/AuditService.java b/gerrit-server/src/main/java/com/google/gerrit/audit/AuditService.java index cc29559327..171ff45c16 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/audit/AuditService.java +++ b/gerrit-server/src/main/java/com/google/gerrit/audit/AuditService.java @@ -1,4 +1,4 @@ -// Copyright (C) 2012 The Android Open Source Project +// Copyright (C) 2018 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. @@ -14,76 +14,19 @@ package com.google.gerrit.audit; -import com.google.gerrit.extensions.registration.DynamicSet; import com.google.gerrit.reviewdb.client.Account; import com.google.gerrit.reviewdb.client.AccountGroupById; import com.google.gerrit.reviewdb.client.AccountGroupMember; -import com.google.inject.Inject; -import com.google.inject.Singleton; import java.util.Collection; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -@Singleton -public class AuditService { - private static final Logger log = LoggerFactory.getLogger(AuditService.class); +public interface AuditService { + void dispatch(AuditEvent action); - private final DynamicSet<AuditListener> auditListeners; - private final DynamicSet<GroupMemberAuditListener> groupMemberAuditListeners; + void dispatchAddAccountsToGroup(Account.Id actor, Collection<AccountGroupMember> added); - @Inject - public AuditService( - DynamicSet<AuditListener> auditListeners, - DynamicSet<GroupMemberAuditListener> groupMemberAuditListeners) { - this.auditListeners = auditListeners; - this.groupMemberAuditListeners = groupMemberAuditListeners; - } + void dispatchDeleteAccountsFromGroup(Account.Id actor, Collection<AccountGroupMember> removed); - public void dispatch(AuditEvent action) { - for (AuditListener auditListener : auditListeners) { - auditListener.onAuditableAction(action); - } - } + void dispatchAddGroupsToGroup(Account.Id actor, Collection<AccountGroupById> added); - public void dispatchAddAccountsToGroup(Account.Id actor, Collection<AccountGroupMember> added) { - for (GroupMemberAuditListener auditListener : groupMemberAuditListeners) { - try { - auditListener.onAddAccountsToGroup(actor, added); - } catch (RuntimeException e) { - log.error("failed to log add accounts to group event", e); - } - } - } - - public void dispatchDeleteAccountsFromGroup( - Account.Id actor, Collection<AccountGroupMember> removed) { - for (GroupMemberAuditListener auditListener : groupMemberAuditListeners) { - try { - auditListener.onDeleteAccountsFromGroup(actor, removed); - } catch (RuntimeException e) { - log.error("failed to log delete accounts from group event", e); - } - } - } - - public void dispatchAddGroupsToGroup(Account.Id actor, Collection<AccountGroupById> added) { - for (GroupMemberAuditListener auditListener : groupMemberAuditListeners) { - try { - auditListener.onAddGroupsToGroup(actor, added); - } catch (RuntimeException e) { - log.error("failed to log add groups to group event", e); - } - } - } - - public void dispatchDeleteGroupsFromGroup( - Account.Id actor, Collection<AccountGroupById> removed) { - for (GroupMemberAuditListener auditListener : groupMemberAuditListeners) { - try { - auditListener.onDeleteGroupsFromGroup(actor, removed); - } catch (RuntimeException e) { - log.error("failed to log delete groups from group event", e); - } - } - } + void dispatchDeleteGroupsFromGroup(Account.Id actor, Collection<AccountGroupById> removed); } diff --git a/gerrit-server/src/main/java/com/google/gerrit/audit/AuditServiceImpl.java b/gerrit-server/src/main/java/com/google/gerrit/audit/AuditServiceImpl.java new file mode 100644 index 0000000000..940742fc9d --- /dev/null +++ b/gerrit-server/src/main/java/com/google/gerrit/audit/AuditServiceImpl.java @@ -0,0 +1,94 @@ +// Copyright (C) 2018 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.audit; + +import com.google.gerrit.extensions.registration.DynamicSet; +import com.google.gerrit.reviewdb.client.Account; +import com.google.gerrit.reviewdb.client.AccountGroupById; +import com.google.gerrit.reviewdb.client.AccountGroupMember; +import com.google.inject.Inject; +import com.google.inject.Singleton; +import java.util.Collection; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +@Singleton +public class AuditServiceImpl implements AuditService { + private static final Logger log = LoggerFactory.getLogger(AuditServiceImpl.class); + + private final DynamicSet<AuditListener> auditListeners; + private final DynamicSet<GroupMemberAuditListener> groupMemberAuditListeners; + + @Inject + public AuditServiceImpl( + DynamicSet<AuditListener> auditListeners, + DynamicSet<GroupMemberAuditListener> groupMemberAuditListeners) { + this.auditListeners = auditListeners; + this.groupMemberAuditListeners = groupMemberAuditListeners; + } + + @Override + public void dispatch(AuditEvent action) { + for (AuditListener auditListener : auditListeners) { + auditListener.onAuditableAction(action); + } + } + + @Override + public void dispatchAddAccountsToGroup(Account.Id actor, Collection<AccountGroupMember> added) { + for (GroupMemberAuditListener auditListener : groupMemberAuditListeners) { + try { + auditListener.onAddAccountsToGroup(actor, added); + } catch (RuntimeException e) { + log.error("failed to log add accounts to group event", e); + } + } + } + + @Override + public void dispatchDeleteAccountsFromGroup( + Account.Id actor, Collection<AccountGroupMember> removed) { + for (GroupMemberAuditListener auditListener : groupMemberAuditListeners) { + try { + auditListener.onDeleteAccountsFromGroup(actor, removed); + } catch (RuntimeException e) { + log.error("failed to log delete accounts from group event", e); + } + } + } + + @Override + public void dispatchAddGroupsToGroup(Account.Id actor, Collection<AccountGroupById> added) { + for (GroupMemberAuditListener auditListener : groupMemberAuditListeners) { + try { + auditListener.onAddGroupsToGroup(actor, added); + } catch (RuntimeException e) { + log.error("failed to log add groups to group event", e); + } + } + } + + @Override + public void dispatchDeleteGroupsFromGroup( + Account.Id actor, Collection<AccountGroupById> removed) { + for (GroupMemberAuditListener auditListener : groupMemberAuditListeners) { + try { + auditListener.onDeleteGroupsFromGroup(actor, removed); + } catch (RuntimeException e) { + log.error("failed to log delete groups from group event", e); + } + } + } +} diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/config/GerritGlobalModule.java b/gerrit-server/src/main/java/com/google/gerrit/server/config/GerritGlobalModule.java index 2e2d675c26..773d4a9f8b 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/config/GerritGlobalModule.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/config/GerritGlobalModule.java @@ -17,7 +17,6 @@ package com.google.gerrit.server.config; import static com.google.inject.Scopes.SINGLETON; import com.google.common.cache.Cache; -import com.google.gerrit.audit.AuditModule; import com.google.gerrit.common.EventListener; import com.google.gerrit.common.UserScopedEventListener; import com.google.gerrit.extensions.annotations.Exports; @@ -299,7 +298,6 @@ public class GerritGlobalModule extends FactoryModule { bind(IdentifiedUser.GenericFactory.class).in(SINGLETON); bind(AccountControl.Factory.class); - install(new AuditModule()); bind(UiActions.class); install(new com.google.gerrit.server.access.Module()); install(new com.google.gerrit.server.account.Module()); diff --git a/gerrit-server/src/test/java/com/google/gerrit/testutil/FakeAuditService.java b/gerrit-server/src/test/java/com/google/gerrit/testutil/FakeAuditService.java new file mode 100644 index 0000000000..1eb5bdb680 --- /dev/null +++ b/gerrit-server/src/test/java/com/google/gerrit/testutil/FakeAuditService.java @@ -0,0 +1,89 @@ +// Copyright (C) 2018 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.testutil; + +import com.google.gerrit.audit.AuditEvent; +import com.google.gerrit.audit.AuditService; +import com.google.gerrit.audit.GroupMemberAuditListener; +import com.google.gerrit.extensions.registration.DynamicSet; +import com.google.gerrit.reviewdb.client.Account; +import com.google.gerrit.reviewdb.client.AccountGroupById; +import com.google.gerrit.reviewdb.client.AccountGroupMember; +import com.google.inject.AbstractModule; +import com.google.inject.Inject; +import com.google.inject.Singleton; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +@Singleton +public class FakeAuditService implements AuditService { + + private final DynamicSet<GroupMemberAuditListener> groupMemberAuditListeners; + + public static class Module extends AbstractModule { + @Override + public void configure() { + DynamicSet.setOf(binder(), GroupMemberAuditListener.class); + bind(AuditService.class).to(FakeAuditService.class); + } + } + + @Inject + public FakeAuditService(DynamicSet<GroupMemberAuditListener> groupMemberAuditListeners) { + this.groupMemberAuditListeners = groupMemberAuditListeners; + } + + public List<AuditEvent> auditEvents = new ArrayList<>(); + + public void clearEvents() { + auditEvents.clear(); + } + + @Override + public void dispatch(AuditEvent action) { + auditEvents.add(action); + } + + @Override + public void dispatchAddAccountsToGroup(Account.Id actor, Collection<AccountGroupMember> added) { + for (GroupMemberAuditListener auditListener : groupMemberAuditListeners) { + auditListener.onAddAccountsToGroup(actor, added); + } + } + + @Override + public void dispatchDeleteAccountsFromGroup( + Account.Id actor, Collection<AccountGroupMember> removed) { + for (GroupMemberAuditListener auditListener : groupMemberAuditListeners) { + auditListener.onDeleteAccountsFromGroup(actor, removed); + } + } + + @Override + public void dispatchAddGroupsToGroup(Account.Id actor, Collection<AccountGroupById> added) { + for (GroupMemberAuditListener auditListener : groupMemberAuditListeners) { + auditListener.onAddGroupsToGroup(actor, added); + } + } + + @Override + public void dispatchDeleteGroupsFromGroup( + Account.Id actor, Collection<AccountGroupById> removed) { + for (GroupMemberAuditListener auditListener : groupMemberAuditListeners) { + auditListener.onDeleteGroupsFromGroup(actor, removed); + } + } +} diff --git a/gerrit-server/src/test/java/com/google/gerrit/testutil/InMemoryModule.java b/gerrit-server/src/test/java/com/google/gerrit/testutil/InMemoryModule.java index 5f144e504c..883515086d 100644 --- a/gerrit-server/src/test/java/com/google/gerrit/testutil/InMemoryModule.java +++ b/gerrit-server/src/test/java/com/google/gerrit/testutil/InMemoryModule.java @@ -19,6 +19,7 @@ import static com.google.inject.Scopes.SINGLETON; import com.google.common.util.concurrent.ListeningExecutorService; import com.google.common.util.concurrent.MoreExecutors; +import com.google.gerrit.audit.AuditModule; import com.google.gerrit.extensions.client.AuthType; import com.google.gerrit.extensions.config.FactoryModule; import com.google.gerrit.extensions.systemstatus.ServerInformation; @@ -162,6 +163,7 @@ public class InMemoryModule extends FactoryModule { install(new DefaultPermissionBackendModule()); install(new SearchingChangeCacheImpl.Module()); factory(GarbageCollection.Factory.class); + install(new AuditModule()); bindScope(RequestScoped.class, PerThreadRequestScope.REQUEST); |