KEYCLOAK-3006 Fix admin event inconsistencies (points 2,5-14 from JIRA)

This commit is contained in:
mposolda 2016-05-25 09:46:37 +02:00
parent 5f73c338d8
commit 022be3aee5
20 changed files with 123 additions and 57 deletions

View file

@ -115,7 +115,7 @@ public class AttackDetectionResource {
UsernameLoginFailureModel model = session.sessions().getUserLoginFailure(realm, username.toLowerCase()); UsernameLoginFailureModel model = session.sessions().getUserLoginFailure(realm, username.toLowerCase());
if (model != null) { if (model != null) {
session.sessions().removeUserLoginFailure(realm, username); session.sessions().removeUserLoginFailure(realm, username);
adminEvent.operation(OperationType.DELETE).success(); adminEvent.operation(OperationType.DELETE).resourcePath(uriInfo).success();
} }
} }
@ -131,7 +131,7 @@ public class AttackDetectionResource {
auth.requireManage(); auth.requireManage();
session.sessions().removeAllUserLoginFailures(realm); session.sessions().removeAllUserLoginFailures(realm);
adminEvent.operation(OperationType.DELETE).success(); adminEvent.operation(OperationType.DELETE).resourcePath(uriInfo).success();
} }

View file

@ -108,6 +108,7 @@ public class ClientInitialAccessResource {
auth.requireManage(); auth.requireManage();
session.sessions().removeClientInitialAccessModel(realm, id); session.sessions().removeClientInitialAccessModel(realm, id);
adminEvent.operation(OperationType.DELETE).resourcePath(uriInfo).success();
} }
private ClientInitialAccessPresentation wrap(ClientInitialAccessModel model) { private ClientInitialAccessPresentation wrap(ClientInitialAccessModel model) {

View file

@ -485,7 +485,7 @@ public class ClientResource {
} }
if (logger.isDebugEnabled()) logger.debug("Register node: " + node); if (logger.isDebugEnabled()) logger.debug("Register node: " + node);
client.registerNode(node, Time.currentTime()); client.registerNode(node, Time.currentTime());
adminEvent.operation(OperationType.ACTION).resourcePath(uriInfo).success(); adminEvent.operation(OperationType.CREATE).resourcePath(uriInfo, node).success();
} }
/** /**
@ -532,9 +532,9 @@ public class ClientResource {
} }
logger.debug("Test availability of cluster nodes"); logger.debug("Test availability of cluster nodes");
adminEvent.operation(OperationType.ACTION).resourcePath(uriInfo).success(); GlobalRequestResult result = new ResourceAdminManager(session).testNodesAvailability(uriInfo.getRequestUri(), realm, client);
return new ResourceAdminManager(session).testNodesAvailability(uriInfo.getRequestUri(), realm, client); adminEvent.operation(OperationType.ACTION).resourcePath(uriInfo).representation(result).success();
return result;
} }
} }

View file

@ -144,7 +144,7 @@ public class GroupResource {
if (child == null) { if (child == null) {
throw new NotFoundException("Could not find child by id"); throw new NotFoundException("Could not find child by id");
} }
adminEvent.operation(OperationType.CREATE).resourcePath(uriInfo).representation(rep).success(); adminEvent.operation(OperationType.UPDATE);
} else { } else {
child = realm.createGroup(rep.getName()); child = realm.createGroup(rep.getName());
updateGroup(rep, child); updateGroup(rep, child);
@ -152,10 +152,13 @@ public class GroupResource {
.path(uriInfo.getMatchedURIs().get(2)) .path(uriInfo.getMatchedURIs().get(2))
.path(child.getId()).build(); .path(child.getId()).build();
builder.status(201).location(uri); builder.status(201).location(uri);
adminEvent.operation(OperationType.UPDATE).resourcePath(uriInfo).representation(rep).success(); rep.setId(child.getId());
adminEvent.operation(OperationType.CREATE);
} }
realm.moveGroup(child, group); realm.moveGroup(child, group);
adminEvent.resourcePath(uriInfo).representation(rep).success();
GroupRepresentation childRep = ModelToRepresentation.toGroupHierarchy(child, true); GroupRepresentation childRep = ModelToRepresentation.toGroupHierarchy(child, true);
return builder.type(MediaType.APPLICATION_JSON_TYPE).entity(childRep).build(); return builder.type(MediaType.APPLICATION_JSON_TYPE).entity(childRep).build();
} }

View file

@ -108,16 +108,20 @@ public class GroupsResource {
if (child == null) { if (child == null) {
throw new NotFoundException("Could not find child by id"); throw new NotFoundException("Could not find child by id");
} }
adminEvent.operation(OperationType.UPDATE).resourcePath(uriInfo).representation(rep).success(); adminEvent.operation(OperationType.UPDATE).resourcePath(uriInfo);
} else { } else {
child = realm.createGroup(rep.getName()); child = realm.createGroup(rep.getName());
GroupResource.updateGroup(rep, child); GroupResource.updateGroup(rep, child);
URI uri = uriInfo.getAbsolutePathBuilder() URI uri = uriInfo.getAbsolutePathBuilder()
.path(child.getId()).build(); .path(child.getId()).build();
builder.status(201).location(uri); builder.status(201).location(uri);
adminEvent.operation(OperationType.CREATE).resourcePath(uriInfo).representation(rep).success();
rep.setId(child.getId());
adminEvent.operation(OperationType.CREATE).resourcePath(uriInfo, child.getId());
} }
realm.moveGroup(child, null); realm.moveGroup(child, null);
adminEvent.representation(rep).success();
return builder.build(); return builder.build();
} }
} }

View file

@ -189,7 +189,8 @@ public class IdentityProvidersResource {
IdentityProviderModel identityProvider = RepresentationToModel.toModel(realm, representation); IdentityProviderModel identityProvider = RepresentationToModel.toModel(realm, representation);
this.realm.addIdentityProvider(identityProvider); this.realm.addIdentityProvider(identityProvider);
adminEvent.operation(OperationType.CREATE).resourcePath(uriInfo, identityProvider.getInternalId()) representation.setInternalId(identityProvider.getInternalId());
adminEvent.operation(OperationType.CREATE).resourcePath(uriInfo, identityProvider.getAlias())
.representation(representation).success(); .representation(representation).success();
return Response.created(uriInfo.getAbsolutePathBuilder().path(representation.getAlias()).build()).build(); return Response.created(uriInfo.getAbsolutePathBuilder().path(representation.getAlias()).build()).build();

View file

@ -354,8 +354,9 @@ public class RealmAdminResource {
public GlobalRequestResult pushRevocation() { public GlobalRequestResult pushRevocation() {
auth.requireManage(); auth.requireManage();
adminEvent.operation(OperationType.ACTION).resourcePath(uriInfo).success(); GlobalRequestResult result = new ResourceAdminManager(session).pushRealmRevocationPolicy(uriInfo.getRequestUri(), realm);
return new ResourceAdminManager(session).pushRealmRevocationPolicy(uriInfo.getRequestUri(), realm); adminEvent.operation(OperationType.ACTION).resourcePath(uriInfo).representation(result).success();
return result;
} }
/** /**
@ -369,8 +370,9 @@ public class RealmAdminResource {
auth.init(RealmAuth.Resource.USER).requireManage(); auth.init(RealmAuth.Resource.USER).requireManage();
session.sessions().removeUserSessions(realm); session.sessions().removeUserSessions(realm);
adminEvent.operation(OperationType.ACTION).resourcePath(uriInfo).success(); GlobalRequestResult result = new ResourceAdminManager(session).logoutAll(uriInfo.getRequestUri(), realm);
return new ResourceAdminManager(session).logoutAll(uriInfo.getRequestUri(), realm); adminEvent.operation(OperationType.ACTION).resourcePath(uriInfo).representation(result).success();
return result;
} }
/** /**
@ -730,6 +732,8 @@ public class RealmAdminResource {
throw new NotFoundException("Group not found"); throw new NotFoundException("Group not found");
} }
realm.addDefaultGroup(group); realm.addDefaultGroup(group);
adminEvent.operation(OperationType.CREATE).resourcePath(uriInfo).success();
} }
@DELETE @DELETE
@ -743,6 +747,8 @@ public class RealmAdminResource {
throw new NotFoundException("Group not found"); throw new NotFoundException("Group not found");
} }
realm.removeDefaultGroup(group); realm.removeDefaultGroup(group);
adminEvent.operation(OperationType.DELETE).resourcePath(uriInfo).success();
} }
@ -794,11 +800,12 @@ public class RealmAdminResource {
public void clearRealmCache() { public void clearRealmCache() {
auth.requireManage(); auth.requireManage();
adminEvent.operation(OperationType.ACTION).resourcePath(uriInfo).success();
CacheRealmProvider cache = session.getProvider(CacheRealmProvider.class); CacheRealmProvider cache = session.getProvider(CacheRealmProvider.class);
if (cache != null) { if (cache != null) {
cache.clear(); cache.clear();
} }
adminEvent.operation(OperationType.ACTION).resourcePath(uriInfo).success();
} }
/** /**
@ -810,11 +817,12 @@ public class RealmAdminResource {
public void clearUserCache() { public void clearUserCache() {
auth.requireManage(); auth.requireManage();
adminEvent.operation(OperationType.ACTION).resourcePath(uriInfo).success();
CacheUserProvider cache = session.getProvider(CacheUserProvider.class); CacheUserProvider cache = session.getProvider(CacheUserProvider.class);
if (cache != null) { if (cache != null) {
cache.clear(); cache.clear();
} }
adminEvent.operation(OperationType.ACTION).resourcePath(uriInfo).success();
} }
} }

View file

@ -190,7 +190,11 @@ public class UserFederationProviderResource {
throw new NotFoundException("Unknown action: " + action); throw new NotFoundException("Unknown action: " + action);
} }
adminEvent.operation(OperationType.ACTION).resourcePath(uriInfo).success(); Map<String, Object> eventRep = new HashMap<>();
eventRep.put("action", action);
eventRep.put("result", syncResult);
adminEvent.operation(OperationType.ACTION).resourcePath(uriInfo).representation(eventRep).success();
return syncResult; return syncResult;
} }
@ -422,7 +426,10 @@ public class UserFederationProviderResource {
throw new NotFoundException("Unknown direction: " + direction); throw new NotFoundException("Unknown direction: " + direction);
} }
adminEvent.operation(OperationType.ACTION).resourcePath(uriInfo).success(); Map<String, Object> eventRep = new HashMap<>();
eventRep.put("action", direction);
eventRep.put("result", syncResult);
adminEvent.operation(OperationType.ACTION).resourcePath(uriInfo).representation(eventRep).success();
return syncResult; return syncResult;
} }

View file

@ -37,11 +37,9 @@ import org.keycloak.representations.idm.ConfigPropertyRepresentation;
import org.keycloak.representations.idm.CredentialRepresentation; import org.keycloak.representations.idm.CredentialRepresentation;
import org.keycloak.representations.idm.UserFederationProviderFactoryRepresentation; import org.keycloak.representations.idm.UserFederationProviderFactoryRepresentation;
import org.keycloak.representations.idm.UserFederationProviderRepresentation; import org.keycloak.representations.idm.UserFederationProviderRepresentation;
import org.keycloak.services.ErrorResponse;
import org.keycloak.services.ErrorResponseException; import org.keycloak.services.ErrorResponseException;
import org.keycloak.services.ServicesLogger; import org.keycloak.services.ServicesLogger;
import org.keycloak.services.managers.UsersSyncManager; import org.keycloak.services.managers.UsersSyncManager;
import org.keycloak.timer.TimerProvider;
import org.keycloak.utils.CredentialHelper; import org.keycloak.utils.CredentialHelper;
import javax.ws.rs.Consumes; import javax.ws.rs.Consumes;
@ -211,8 +209,8 @@ public class UserFederationProvidersResource {
logger.addedKerberosToRealmCredentials(); logger.addedKerberosToRealmCredentials();
} }
rep.setId(model.getId());
adminEvent.operation(OperationType.CREATE).resourcePath(uriInfo).representation(rep).success(); adminEvent.operation(OperationType.CREATE).resourcePath(uriInfo, model.getId()).representation(rep).success();
return Response.created(uriInfo.getAbsolutePathBuilder().path(model.getId()).build()).build(); return Response.created(uriInfo.getAbsolutePathBuilder().path(model.getId()).build()).build();
} }

View file

@ -17,13 +17,12 @@
package org.keycloak.testsuite.admin; package org.keycloak.testsuite.admin;
import org.jboss.arquillian.graphene.page.Page;
import org.jboss.arquillian.test.api.ArquillianResource; import org.jboss.arquillian.test.api.ArquillianResource;
import org.junit.Test; import org.junit.Test;
import org.keycloak.admin.client.resource.AttackDetectionResource; import org.keycloak.admin.client.resource.AttackDetectionResource;
import org.keycloak.common.util.Time; import org.keycloak.events.admin.OperationType;
import org.keycloak.representations.idm.RealmRepresentation; import org.keycloak.representations.idm.RealmRepresentation;
import org.keycloak.testsuite.pages.LoginPage; import org.keycloak.testsuite.util.AdminEventPaths;
import org.keycloak.testsuite.util.OAuthClient; import org.keycloak.testsuite.util.OAuthClient;
import org.keycloak.testsuite.util.UserBuilder; import org.keycloak.testsuite.util.UserBuilder;
@ -33,7 +32,6 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
/** /**
* TODO adminEvents: Add adminEvents once resourcePath is added in AttackDetectionResource (server-side) events
* *
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a> * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/ */
@ -69,11 +67,13 @@ public class AttackDetectionResourceTest extends AbstractAdminTest {
assertBruteForce(detection.bruteForceUserStatus("nosuchuser"), 0, false, false); assertBruteForce(detection.bruteForceUserStatus("nosuchuser"), 0, false, false);
detection.clearBruteForceForUser("test-user@localhost"); detection.clearBruteForceForUser("test-user@localhost");
assertAdminEvents.assertEvent("test", OperationType.DELETE, AdminEventPaths.attackDetectionClearBruteForceForUserPath("test-user@localhost"));
assertBruteForce(detection.bruteForceUserStatus("test-user@localhost"), 0, false, false); assertBruteForce(detection.bruteForceUserStatus("test-user@localhost"), 0, false, false);
assertBruteForce(detection.bruteForceUserStatus("test-user2"), 2, true, true); assertBruteForce(detection.bruteForceUserStatus("test-user2"), 2, true, true);
detection.clearAllBruteForce(); detection.clearAllBruteForce();
assertAdminEvents.assertEvent("test", OperationType.DELETE, AdminEventPaths.attackDetectionClearAllBruteForcePath());
assertBruteForce(detection.bruteForceUserStatus("test-user@localhost"), 0, false, false); assertBruteForce(detection.bruteForceUserStatus("test-user@localhost"), 0, false, false);
assertBruteForce(detection.bruteForceUserStatus("test-user2"), 0, false, false); assertBruteForce(detection.bruteForceUserStatus("test-user2"), 0, false, false);

View file

@ -258,18 +258,18 @@ public class ClientTest extends AbstractAdminTest {
ClientRepresentation client = createAppClient(); ClientRepresentation client = createAppClient();
String id = client.getId(); String id = client.getId();
realm.clients().get(id).registerNode(Collections.singletonMap("node", suiteContext.getAuthServerInfo().getContextRoot().getHost())); String myhost = suiteContext.getAuthServerInfo().getContextRoot().getHost();
realm.clients().get(id).registerNode(Collections.singletonMap("node", myhost));
realm.clients().get(id).registerNode(Collections.singletonMap("node", "invalid")); realm.clients().get(id).registerNode(Collections.singletonMap("node", "invalid"));
// TODO adminEvents: should be rather CREATE and include nodePath like in DELETE event assertAdminEvents.assertEvent(realmId, OperationType.CREATE, AdminEventPaths.clientNodePath(id, myhost));
assertAdminEvents.assertEvent(realmId, OperationType.ACTION, AdminEventPaths.clientNodesPath(id)); assertAdminEvents.assertEvent(realmId, OperationType.CREATE, AdminEventPaths.clientNodePath(id, "invalid"));
assertAdminEvents.assertEvent(realmId, OperationType.ACTION, AdminEventPaths.clientNodesPath(id));
GlobalRequestResult result = realm.clients().get(id).testNodesAvailable(); GlobalRequestResult result = realm.clients().get(id).testNodesAvailable();
assertEquals(1, result.getSuccessRequests().size()); assertEquals(1, result.getSuccessRequests().size());
assertEquals(1, result.getFailedRequests().size()); assertEquals(1, result.getFailedRequests().size());
assertAdminEvents.assertEvent(realmId, OperationType.ACTION, AdminEventPaths.clientTestNodesAvailablePath(id)); assertAdminEvents.assertEvent(realmId, OperationType.ACTION, AdminEventPaths.clientTestNodesAvailablePath(id), result);
TestAvailabilityAction testAvailable = testingClient.testApp().getTestAvailable(); TestAvailabilityAction testAvailable = testingClient.testApp().getTestAvailable();
assertEquals("test-app", testAvailable.getResource()); assertEquals("test-app", testAvailable.getResource());

View file

@ -17,7 +17,6 @@
package org.keycloak.testsuite.admin; package org.keycloak.testsuite.admin;
import org.hamcrest.Matchers;
import org.jboss.resteasy.plugins.providers.multipart.MultipartFormDataOutput; import org.jboss.resteasy.plugins.providers.multipart.MultipartFormDataOutput;
import org.junit.Test; import org.junit.Test;
import org.keycloak.admin.client.resource.IdentityProviderResource; import org.keycloak.admin.client.resource.IdentityProviderResource;
@ -166,8 +165,7 @@ public class IdentityProviderTest extends AbstractAdminTest {
Assert.assertNotNull(ApiUtil.getCreatedId(response)); Assert.assertNotNull(ApiUtil.getCreatedId(response));
response.close(); response.close();
// TODO adminEvents: should rather use alias instead of internalId (same issue like for roles) assertAdminEvents.assertEvent(realmId, OperationType.CREATE, AdminEventPaths.identityProviderPath(idpRep.getAlias()), idpRep);
assertAdminEvents.assertEvent(realmId, OperationType.CREATE, Matchers.startsWith(AdminEventPaths.identityProviderCreatePath()), idpRep);
} }
private IdentityProviderRepresentation createRep(String id, String providerId) { private IdentityProviderRepresentation createRep(String id, String providerId) {

View file

@ -69,13 +69,22 @@ public class InitialAccessTokenResourceTest extends AbstractAdminTest {
rep.setCount(4); rep.setCount(4);
response = resource.create(rep); response = resource.create(rep);
assertAdminEvents.assertEvent(realmId, OperationType.CREATE, AdminEventPaths.clientInitialAccessPath(response.getId()), rep); String lastId = response.getId();
assertAdminEvents.assertEvent(realmId, OperationType.CREATE, AdminEventPaths.clientInitialAccessPath(lastId), rep);
List<ClientInitialAccessPresentation> list = resource.list(); List<ClientInitialAccessPresentation> list = resource.list();
assertEquals(3, list.size()); assertEquals(3, list.size());
assertEquals(9, list.get(0).getCount() + list.get(1).getCount() + list.get(2).getCount()); assertEquals(9, list.get(0).getCount() + list.get(1).getCount() + list.get(2).getCount());
assertNull(list.get(0).getToken()); assertNull(list.get(0).getToken());
// Delete last and assert it was deleted
resource.delete(lastId);
assertAdminEvents.assertEvent(realmId, OperationType.DELETE, AdminEventPaths.clientInitialAccessPath(lastId));
list = resource.list();
assertEquals(2, list.size());
assertEquals(5, list.get(0).getCount() + list.get(1).getCount());
} }
} }

View file

@ -65,7 +65,7 @@ public class UserFederationMapperTest extends AbstractAdminTest {
Response resp = realm.userFederation().create(ldapRep); Response resp = realm.userFederation().create(ldapRep);
this.ldapProviderId = ApiUtil.getCreatedId(resp); this.ldapProviderId = ApiUtil.getCreatedId(resp);
resp.close(); resp.close();
assertAdminEvents.assertEvent(realmId, OperationType.CREATE, AdminEventPaths.userFederationCreateResourcePath(), ldapRep); assertAdminEvents.assertEvent(realmId, OperationType.CREATE, AdminEventPaths.userFederationResourcePath(this.ldapProviderId), ldapRep);
UserFederationProviderRepresentation dummyRep = UserFederationProviderBuilder.create() UserFederationProviderRepresentation dummyRep = UserFederationProviderBuilder.create()
.displayName("dummy-1") .displayName("dummy-1")
@ -75,7 +75,7 @@ public class UserFederationMapperTest extends AbstractAdminTest {
resp = realm.userFederation().create(dummyRep); resp = realm.userFederation().create(dummyRep);
this.dummyProviderId = ApiUtil.getCreatedId(resp); this.dummyProviderId = ApiUtil.getCreatedId(resp);
resp.close(); resp.close();
assertAdminEvents.assertEvent(realmId, OperationType.CREATE, AdminEventPaths.userFederationCreateResourcePath(), dummyRep); assertAdminEvents.assertEvent(realmId, OperationType.CREATE, AdminEventPaths.userFederationResourcePath(this.dummyProviderId), dummyRep);
} }
@After @After
@ -254,11 +254,16 @@ public class UserFederationMapperTest extends AbstractAdminTest {
// Try fed To Keycloak sync // Try fed To Keycloak sync
UserFederationSyncResultRepresentation result = ldapProviderResource().syncMapperData(mapperId, "fedToKeycloak"); UserFederationSyncResultRepresentation result = ldapProviderResource().syncMapperData(mapperId, "fedToKeycloak");
Assert.assertEquals("dummyFedToKeycloakSuccess mapper=some-dummy", result.getStatus()); Assert.assertEquals("dummyFedToKeycloakSuccess mapper=some-dummy", result.getStatus());
assertAdminEvents.assertEvent(realmId, OperationType.ACTION, AdminEventPaths.userFederationMapperResourcePath(ldapProviderId, mapperId) + "/sync");
Map<String, Object> eventRep = new HashMap<>();
eventRep.put("action", "fedToKeycloak");
assertAdminEvents.assertEvent(realmId, OperationType.ACTION, AdminEventPaths.userFederationMapperResourcePath(ldapProviderId, mapperId) + "/sync", eventRep);
// Try keycloak to fed // Try keycloak to fed
result = ldapProviderResource().syncMapperData(mapperId, "keycloakToFed"); result = ldapProviderResource().syncMapperData(mapperId, "keycloakToFed");
Assert.assertEquals("dummyKeycloakToFedSuccess mapper=some-dummy", result.getStatus()); Assert.assertEquals("dummyKeycloakToFedSuccess mapper=some-dummy", result.getStatus());
eventRep.put("action", "keycloakToFed");
assertAdminEvents.assertEvent(realmId, OperationType.ACTION, AdminEventPaths.userFederationMapperResourcePath(ldapProviderId, mapperId) + "/sync"); assertAdminEvents.assertEvent(realmId, OperationType.ACTION, AdminEventPaths.userFederationMapperResourcePath(ldapProviderId, mapperId) + "/sync");
} }

View file

@ -17,8 +17,10 @@
package org.keycloak.testsuite.admin; package org.keycloak.testsuite.admin;
import java.util.HashMap;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Map;
import javax.ws.rs.BadRequestException; import javax.ws.rs.BadRequestException;
import javax.ws.rs.NotFoundException; import javax.ws.rs.NotFoundException;
@ -251,6 +253,7 @@ public class UserFederationTest extends AbstractAdminTest {
// Switch kerberos authenticator to DISABLED // Switch kerberos authenticator to DISABLED
kerberosExecution.setRequirement(AuthenticationExecutionModel.Requirement.DISABLED.toString()); kerberosExecution.setRequirement(AuthenticationExecutionModel.Requirement.DISABLED.toString());
realm.flows().updateExecutions("browser", kerberosExecution); realm.flows().updateExecutions("browser", kerberosExecution);
assertAdminEvents.assertEvent(realmId, OperationType.UPDATE, AdminEventPaths.authUpdateExecutionPath("browser"), kerberosExecution);
// update LDAP provider with kerberos // update LDAP provider with kerberos
ldapRep = userFederation().get(id).toRepresentation(); ldapRep = userFederation().get(id).toRepresentation();
@ -264,6 +267,7 @@ public class UserFederationTest extends AbstractAdminTest {
// Cleanup // Cleanup
kerberosExecution.setRequirement(AuthenticationExecutionModel.Requirement.DISABLED.toString()); kerberosExecution.setRequirement(AuthenticationExecutionModel.Requirement.DISABLED.toString());
realm.flows().updateExecutions("browser", kerberosExecution); realm.flows().updateExecutions("browser", kerberosExecution);
assertAdminEvents.assertEvent(realmId, OperationType.UPDATE, AdminEventPaths.authUpdateExecutionPath("browser"), kerberosExecution);
removeUserFederationProvider(id); removeUserFederationProvider(id);
} }
@ -297,7 +301,10 @@ public class UserFederationTest extends AbstractAdminTest {
// Sync and assert it happened // Sync and assert it happened
UserFederationSyncResultRepresentation syncResult = userFederation().get(id1).syncUsers("triggerFullSync"); UserFederationSyncResultRepresentation syncResult = userFederation().get(id1).syncUsers("triggerFullSync");
Assert.assertEquals("0 imported users, 0 updated users", syncResult.getStatus()); Assert.assertEquals("0 imported users, 0 updated users", syncResult.getStatus());
assertAdminEvents.assertEvent(realmId, OperationType.ACTION, AdminEventPaths.userFederationResourcePath(id1) + "/sync");
Map<String, Object> eventRep = new HashMap<>();
eventRep.put("action", "triggerFullSync");
assertAdminEvents.assertEvent(realmId, OperationType.ACTION, AdminEventPaths.userFederationResourcePath(id1) + "/sync", eventRep);
int fullSyncTime = userFederation().get(id1).toRepresentation().getLastSync(); int fullSyncTime = userFederation().get(id1).toRepresentation().getLastSync();
Assert.assertTrue(fullSyncTime > 0); Assert.assertTrue(fullSyncTime > 0);
@ -305,7 +312,9 @@ public class UserFederationTest extends AbstractAdminTest {
// Changed sync // Changed sync
setTimeOffset(50); setTimeOffset(50);
syncResult = userFederation().get(id1).syncUsers("triggerChangedUsersSync"); syncResult = userFederation().get(id1).syncUsers("triggerChangedUsersSync");
assertAdminEvents.assertEvent(realmId, OperationType.ACTION, AdminEventPaths.userFederationResourcePath(id1) + "/sync");
eventRep.put("action", "triggerChangedUsersSync");
assertAdminEvents.assertEvent(realmId, OperationType.ACTION, AdminEventPaths.userFederationResourcePath(id1) + "/sync", eventRep);
Assert.assertEquals("0 imported users, 0 updated users", syncResult.getStatus()); Assert.assertEquals("0 imported users, 0 updated users", syncResult.getStatus());
int changedSyncTime = userFederation().get(id1).toRepresentation().getLastSync(); int changedSyncTime = userFederation().get(id1).toRepresentation().getLastSync();
@ -323,8 +332,7 @@ public class UserFederationTest extends AbstractAdminTest {
resp.close(); resp.close();
String federationProviderId = ApiUtil.getCreatedId(resp); String federationProviderId = ApiUtil.getCreatedId(resp);
// TODO adminEvents: should be rather whole path include ID (consistency with UPDATE and DELETE) assertAdminEvents.assertEvent(realmId, OperationType.CREATE, AdminEventPaths.userFederationResourcePath(federationProviderId), rep);
assertAdminEvents.assertEvent(realmId, OperationType.CREATE, AdminEventPaths.userFederationCreateResourcePath(), rep);
return federationProviderId; return federationProviderId;
} }

View file

@ -353,7 +353,7 @@ public class UserTest extends AbstractAdminTest {
rep.setProviderId("social-provider-type"); rep.setProviderId("social-provider-type");
realm.identityProviders().create(rep); realm.identityProviders().create(rep);
assertAdminEvents.assertEvent(realmId, OperationType.CREATE, Matchers.startsWith(AdminEventPaths.identityProviderCreatePath()), rep); assertAdminEvents.assertEvent(realmId, OperationType.CREATE, AdminEventPaths.identityProviderPath(rep.getAlias()), rep);
} }
private void removeSampleIdentityProvider() { private void removeSampleIdentityProvider() {
@ -742,6 +742,7 @@ public class UserTest extends AbstractAdminTest {
RequiredActionProviderRepresentation updatePasswordReqAction = realm.flows().getRequiredAction(UserModel.RequiredAction.UPDATE_PASSWORD.toString()); RequiredActionProviderRepresentation updatePasswordReqAction = realm.flows().getRequiredAction(UserModel.RequiredAction.UPDATE_PASSWORD.toString());
updatePasswordReqAction.setDefaultAction(true); updatePasswordReqAction.setDefaultAction(true);
realm.flows().updateRequiredAction(UserModel.RequiredAction.UPDATE_PASSWORD.toString(), updatePasswordReqAction); realm.flows().updateRequiredAction(UserModel.RequiredAction.UPDATE_PASSWORD.toString(), updatePasswordReqAction);
assertAdminEvents.assertEvent(realmId, OperationType.UPDATE, AdminEventPaths.authRequiredActionPath(UserModel.RequiredAction.UPDATE_PASSWORD.toString()), updatePasswordReqAction);
// Create user // Create user
String userId = createUser("user1", "user1@localhost"); String userId = createUser("user1", "user1@localhost");
@ -754,6 +755,7 @@ public class UserTest extends AbstractAdminTest {
updatePasswordReqAction = realm.flows().getRequiredAction(UserModel.RequiredAction.UPDATE_PASSWORD.toString()); updatePasswordReqAction = realm.flows().getRequiredAction(UserModel.RequiredAction.UPDATE_PASSWORD.toString());
updatePasswordReqAction.setDefaultAction(true); updatePasswordReqAction.setDefaultAction(true);
realm.flows().updateRequiredAction(UserModel.RequiredAction.UPDATE_PASSWORD.toString(), updatePasswordReqAction); realm.flows().updateRequiredAction(UserModel.RequiredAction.UPDATE_PASSWORD.toString(), updatePasswordReqAction);
assertAdminEvents.assertEvent(realmId, OperationType.UPDATE, AdminEventPaths.authRequiredActionPath(UserModel.RequiredAction.UPDATE_PASSWORD.toString()), updatePasswordReqAction);
} }
@Test @Test

View file

@ -130,8 +130,7 @@ public class GroupTest extends AbstractGroupTest {
String groupId = ApiUtil.getCreatedId(response); String groupId = ApiUtil.getCreatedId(response);
response.close(); response.close();
// TODO adminEvents: ID of group is missing in create event assertAdminEvents.assertEvent("test", OperationType.CREATE, AdminEventPaths.groupPath(groupId), group);
assertAdminEvents.assertEvent("test", OperationType.CREATE, AdminEventPaths.groupsPath(), group);
// Set ID to the original rep // Set ID to the original rep
group.setId(groupId); group.setId(groupId);
@ -176,8 +175,7 @@ public class GroupTest extends AbstractGroupTest {
level2Group.setName("level2"); level2Group.setName("level2");
Response response = realm.groups().group(topGroup.getId()).subGroup(level2Group); Response response = realm.groups().group(topGroup.getId()).subGroup(level2Group);
response.close(); response.close();
// TODO adminEvents: Should be CREATE assertAdminEvents.assertEvent("test", OperationType.CREATE, AdminEventPaths.groupSubgroupsPath(topGroup.getId()), level2Group);
assertAdminEvents.assertEvent("test", OperationType.UPDATE, AdminEventPaths.groupSubgroupsPath(topGroup.getId()), level2Group);
URI location = response.getLocation(); URI location = response.getLocation();
final String level2Id = ApiUtil.getCreatedId(response); final String level2Id = ApiUtil.getCreatedId(response);
@ -204,8 +202,7 @@ public class GroupTest extends AbstractGroupTest {
level3Group.setName("level3"); level3Group.setName("level3");
response = realm.groups().group(level2Group.getId()).subGroup(level3Group); response = realm.groups().group(level2Group.getId()).subGroup(level3Group);
response.close(); response.close();
// TODO adminEvents: Should be CREATE assertAdminEvents.assertEvent("test", OperationType.CREATE, AdminEventPaths.groupSubgroupsPath(level2Group.getId()), level3Group);
assertAdminEvents.assertEvent("test", OperationType.UPDATE, AdminEventPaths.groupSubgroupsPath(level2Group.getId()), level3Group);
level3Group = realm.getGroupByPath("/top/level2/level3"); level3Group = realm.getGroupByPath("/top/level2/level3");
Assert.assertNotNull(level3Group); Assert.assertNotNull(level3Group);
@ -232,7 +229,7 @@ public class GroupTest extends AbstractGroupTest {
UserRepresentation user = realm.users().search("direct-login", -1, -1).get(0); UserRepresentation user = realm.users().search("direct-login", -1, -1).get(0);
realm.users().get(user.getId()).joinGroup(level3Group.getId()); realm.users().get(user.getId()).joinGroup(level3Group.getId());
assertAdminEvents.assertEvent("test", OperationType.CREATE, Matchers.startsWith(AdminEventPaths.userGroupPath(user.getId(), level3Group.getId()))); assertAdminEvents.assertEvent("test", OperationType.CREATE, AdminEventPaths.userGroupPath(user.getId(), level3Group.getId()));
List<GroupRepresentation> membership = realm.users().get(user.getId()).groups(); List<GroupRepresentation> membership = realm.users().get(user.getId()).groups();
assertEquals(1, membership.size()); assertEquals(1, membership.size());
@ -244,6 +241,7 @@ public class GroupTest extends AbstractGroupTest {
assertTrue(token.getRealmAccess().getRoles().contains("level3Role")); assertTrue(token.getRealmAccess().getRoles().contains("level3Role"));
realm.addDefaultGroup(level3Group.getId()); realm.addDefaultGroup(level3Group.getId());
assertAdminEvents.assertEvent("test", OperationType.CREATE, AdminEventPaths.defaultGroupPath(level3Group.getId()));
List<GroupRepresentation> defaultGroups = realm.getDefaultGroups(); List<GroupRepresentation> defaultGroups = realm.getDefaultGroups();
assertEquals(1, defaultGroups.size()); assertEquals(1, defaultGroups.size());
@ -262,6 +260,8 @@ public class GroupTest extends AbstractGroupTest {
assertEquals("level3", membership.get(0).getName()); assertEquals("level3", membership.get(0).getName());
realm.removeDefaultGroup(level3Group.getId()); realm.removeDefaultGroup(level3Group.getId());
assertAdminEvents.assertEvent("test", OperationType.DELETE, AdminEventPaths.defaultGroupPath(level3Group.getId()));
defaultGroups = realm.getDefaultGroups(); defaultGroups = realm.getDefaultGroups();
assertEquals(0, defaultGroups.size()); assertEquals(0, defaultGroups.size());
@ -347,19 +347,19 @@ public class GroupTest extends AbstractGroupTest {
assertAdminEvents.assertEvent("test", OperationType.CREATE, AdminEventPaths.userResourcePath(userBId)); assertAdminEvents.assertEvent("test", OperationType.CREATE, AdminEventPaths.userResourcePath(userBId));
realm.users().get(userAId).joinGroup(groupId); realm.users().get(userAId).joinGroup(groupId);
assertAdminEvents.assertEvent("test", OperationType.CREATE, AdminEventPaths.userGroupPath(userAId, groupId)); assertAdminEvents.assertEvent("test", OperationType.CREATE, AdminEventPaths.userGroupPath(userAId, groupId), group);
List<UserRepresentation> members = realm.groups().group(groupId).members(0, 10); List<UserRepresentation> members = realm.groups().group(groupId).members(0, 10);
assertNames(members, "user-a"); assertNames(members, "user-a");
realm.users().get(userBId).joinGroup(groupId); realm.users().get(userBId).joinGroup(groupId);
assertAdminEvents.assertEvent("test", OperationType.CREATE, AdminEventPaths.userGroupPath(userBId, groupId)); assertAdminEvents.assertEvent("test", OperationType.CREATE, AdminEventPaths.userGroupPath(userBId, groupId), group);
members = realm.groups().group(groupId).members(0, 10); members = realm.groups().group(groupId).members(0, 10);
assertNames(members, "user-a", "user-b"); assertNames(members, "user-a", "user-b");
realm.users().get(userAId).leaveGroup(groupId); realm.users().get(userAId).leaveGroup(groupId);
assertAdminEvents.assertEvent("test", OperationType.DELETE, AdminEventPaths.userGroupPath(userAId, groupId)); assertAdminEvents.assertEvent("test", OperationType.DELETE, AdminEventPaths.userGroupPath(userAId, groupId), group);
members = realm.groups().group(groupId).members(0, 10); members = realm.groups().group(groupId).members(0, 10);
assertNames(members, "user-b"); assertNames(members, "user-b");

View file

@ -523,7 +523,7 @@ public class RealmTest extends AbstractAdminTest {
assertAdminEvents.assertEvent(realmId, OperationType.UPDATE, Matchers.nullValue(String.class), rep); assertAdminEvents.assertEvent(realmId, OperationType.UPDATE, Matchers.nullValue(String.class), rep);
GlobalRequestResult globalRequestResult = realm.pushRevocation(); GlobalRequestResult globalRequestResult = realm.pushRevocation();
assertAdminEvents.assertEvent(realmId, OperationType.ACTION, "push-revocation"); assertAdminEvents.assertEvent(realmId, OperationType.ACTION, "push-revocation", globalRequestResult);
assertEquals(1, globalRequestResult.getSuccessRequests().size()); assertEquals(1, globalRequestResult.getSuccessRequests().size());
assertEquals("http://localhost:8180/auth/realms/master/app/admin", globalRequestResult.getSuccessRequests().get(0)); assertEquals("http://localhost:8180/auth/realms/master/app/admin", globalRequestResult.getSuccessRequests().get(0));
@ -548,7 +548,7 @@ public class RealmTest extends AbstractAdminTest {
oauth.doLogin("user", "password"); oauth.doLogin("user", "password");
GlobalRequestResult globalRequestResult = realm.logoutAll(); GlobalRequestResult globalRequestResult = realm.logoutAll();
assertAdminEvents.assertEvent(realmId, OperationType.ACTION, "logout-all"); assertAdminEvents.assertEvent(realmId, OperationType.ACTION, "logout-all", globalRequestResult);
assertEquals(1, globalRequestResult.getSuccessRequests().size()); assertEquals(1, globalRequestResult.getSuccessRequests().size());
assertEquals("http://localhost:8180/auth/realms/master/app/admin", globalRequestResult.getSuccessRequests().get(0)); assertEquals("http://localhost:8180/auth/realms/master/app/admin", globalRequestResult.getSuccessRequests().get(0));

View file

@ -21,6 +21,7 @@ import java.net.URI;
import javax.ws.rs.core.UriBuilder; import javax.ws.rs.core.UriBuilder;
import org.keycloak.admin.client.resource.AttackDetectionResource;
import org.keycloak.admin.client.resource.AuthenticationManagementResource; import org.keycloak.admin.client.resource.AuthenticationManagementResource;
import org.keycloak.admin.client.resource.ClientAttributeCertificateResource; import org.keycloak.admin.client.resource.ClientAttributeCertificateResource;
import org.keycloak.admin.client.resource.ClientInitialAccessResource; import org.keycloak.admin.client.resource.ClientInitialAccessResource;
@ -55,6 +56,11 @@ public class AdminEventPaths {
return uri.toString(); return uri.toString();
} }
public static String defaultGroupPath(String groupId) {
URI uri = UriBuilder.fromUri("").path(RealmResource.class, "addDefaultGroup").build(groupId);
return uri.toString();
}
// CLIENT RESOURCE // CLIENT RESOURCE
@ -432,5 +438,21 @@ public class AdminEventPaths {
return uri.toString(); return uri.toString();
} }
// ATTACK DETECTION
public static String attackDetectionClearBruteForceForUserPath(String username) {
URI uri = UriBuilder.fromUri("").path(RealmResource.class, "attackDetection")
.path(AttackDetectionResource.class, "clearBruteForceForUser")
.build(username);
return uri.toString();
}
public static String attackDetectionClearAllBruteForcePath() {
URI uri = UriBuilder.fromUri("").path(RealmResource.class, "attackDetection")
.path(AttackDetectionResource.class, "clearAllBruteForce")
.build();
return uri.toString();
}
} }

View file

@ -182,8 +182,8 @@ public class AssertAdminEvents implements TestRule {
public AdminEventRepresentation assertEvent(AdminEventRepresentation actual) { public AdminEventRepresentation assertEvent(AdminEventRepresentation actual) {
Assert.assertEquals(expected.getRealmId(), actual.getRealmId()); Assert.assertEquals(expected.getRealmId(), actual.getRealmId());
Assert.assertEquals(expected.getOperationType(), actual.getOperationType());
Assert.assertThat(actual.getResourcePath(), resourcePath); Assert.assertThat(actual.getResourcePath(), resourcePath);
Assert.assertEquals(expected.getOperationType(), actual.getOperationType());
Assert.assertTrue(ObjectUtil.isEqualOrBothNull(expected.getError(), actual.getError())); Assert.assertTrue(ObjectUtil.isEqualOrBothNull(expected.getError(), actual.getError()));