[KEYCLOAK-392] - Admin audit events

This commit is contained in:
girirajsharma authored and Stian Thorgersen committed 2015-03-30 14:06:01 +02:00
1 parent f8b25cad7f
commit 962b623b4a
57 files changed
+797 -144

No files matched your search

@@ -26,6 +26,7 @@ import org.jboss.resteasy.client.core.executors.ApacheHttpClient4Executor;
import org.keycloak.OAuth2Constants;
import org.keycloak.events.Details;
import org.keycloak.events.EventBuilder;
import org.keycloak.events.EventGroup;
import org.keycloak.events.EventType;
import org.keycloak.models.ApplicationModel;
import org.keycloak.models.ClientSessionModel;
@@ -185,7 +186,7 @@ public class OIDCLoginProtocol implements LoginProtocol {
public Response finishLogout(UserSessionModel userSession) {
String redirectUri = userSession.getNote(OIDCLoginProtocol.LOGOUT_REDIRECT_URI);
String state = userSession.getNote(OIDCLoginProtocol.LOGOUT_STATE_PARAM);
event.event(EventType.LOGOUT);
event.eventGroup(EventGroup.USER).event(EventType.LOGOUT);
if (redirectUri != null) {
event.detail(Details.REDIRECT_URI, redirectUri);
}
@@ -1,18 +1,10 @@
package org.keycloak.protocol.oidc;
import org.jboss.logging.Logger;
import org.jboss.resteasy.annotations.cache.NoCache;
import org.jboss.resteasy.spi.HttpRequest;
import org.jboss.resteasy.spi.HttpResponse;
import org.jboss.resteasy.spi.ResteasyProviderFactory;
import org.keycloak.ClientConnection;
import org.keycloak.OAuth2Constants;
import org.keycloak.OAuthErrorException;
import org.keycloak.RSATokenVerifier;
import org.keycloak.events.Details;
import org.keycloak.events.Errors;
import org.keycloak.events.EventBuilder;
import org.keycloak.events.EventType;
import org.keycloak.events.EventGroup;
import org.keycloak.jose.jwk.JWK;
import org.keycloak.jose.jwk.JWKBuilder;
import org.keycloak.login.LoginFormsProvider;
@@ -25,8 +17,6 @@ import org.keycloak.protocol.oidc.endpoints.TokenEndpoint;
import org.keycloak.protocol.oidc.endpoints.UserInfoEndpoint;
import org.keycloak.protocol.oidc.endpoints.ValidateTokenEndpoint;
import org.keycloak.protocol.oidc.representations.JSONWebKeySet;
import org.keycloak.representations.AccessToken;
import org.keycloak.services.ErrorResponseException;
import org.keycloak.services.managers.AuthenticationManager;
import org.keycloak.services.resources.RealmsResource;
import org.keycloak.services.resources.flows.Flows;
@@ -39,12 +29,8 @@ import javax.ws.rs.core.Context;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.SecurityContext;
import javax.ws.rs.core.UriBuilder;
import javax.ws.rs.core.UriInfo;
import javax.ws.rs.ext.Providers;
import java.util.HashMap;
import java.util.Map;
/**
* Resource class for the oauth/openid connect token service
@@ -73,7 +59,7 @@ public class OIDCLoginProtocolService {
public OIDCLoginProtocolService(RealmModel realm, EventBuilder event, AuthenticationManager authManager) {
this.realm = realm;
this.tokenManager = new TokenManager();
this.event = event;
this.event = event.eventGroup(EventGroup.USER);
this.authManager = authManager;
}
@@ -9,6 +9,7 @@ import org.keycloak.constants.AdapterConstants;
import org.keycloak.events.Details;
import org.keycloak.events.Errors;
import org.keycloak.events.EventBuilder;
import org.keycloak.events.EventGroup;
import org.keycloak.events.EventType;
import org.keycloak.login.LoginFormsProvider;
import org.keycloak.models.ApplicationModel;
@@ -35,6 +36,7 @@ import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import java.util.List;
/**
@@ -88,7 +90,7 @@ public class AuthorizationEndpoint {
this.authManager = authManager;
this.realm = realm;
this.event = event;
event.event(EventType.LOGIN);
event.eventGroup(EventGroup.USER).event(EventType.LOGIN);
}
@GET
@@ -9,6 +9,7 @@ import org.keycloak.OAuthErrorException;
import org.keycloak.events.Details;
import org.keycloak.events.Errors;
import org.keycloak.events.EventBuilder;
import org.keycloak.events.EventGroup;
import org.keycloak.events.EventType;
import org.keycloak.models.ApplicationModel;
import org.keycloak.models.ClientModel;
@@ -70,7 +71,7 @@ public class LogoutEndpoint {
this.tokenManager = tokenManager;
this.authManager = authManager;
this.realm = realm;
this.event = event;
this.event = event.eventGroup(EventGroup.USER);
}
/**
@@ -9,6 +9,7 @@ import org.keycloak.constants.AdapterConstants;
import org.keycloak.events.Details;
import org.keycloak.events.Errors;
import org.keycloak.events.EventBuilder;
import org.keycloak.events.EventGroup;
import org.keycloak.events.EventType;
import org.keycloak.models.ApplicationModel;
import org.keycloak.models.ClientModel;
@@ -40,6 +41,7 @@ import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import java.util.Map;
/**
@@ -85,7 +87,7 @@ public class TokenEndpoint {
this.tokenManager = tokenManager;
this.authManager = authManager;
this.realm = realm;
this.event = event;
this.event = event.eventGroup(EventGroup.USER);
}
@POST
@@ -26,6 +26,7 @@ import org.keycloak.OAuthErrorException;
import org.keycloak.RSATokenVerifier;
import org.keycloak.events.Details;
import org.keycloak.events.EventBuilder;
import org.keycloak.events.EventGroup;
import org.keycloak.events.EventType;
import org.keycloak.models.ClientModel;
import org.keycloak.models.KeycloakSession;
@@ -54,6 +55,7 @@ import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import javax.ws.rs.core.UriInfo;
import java.util.HashMap;
import java.util.Map;
@@ -114,6 +116,7 @@ public class UserInfoEndpoint {
private Response issueUserInfo(String tokenString) {
EventBuilder event = new EventsManager(realm, session, clientConnection).createEventBuilder()
.eventGroup(EventGroup.USER)
.event(EventType.USER_INFO_REQUEST)
.detail(Details.AUTH_METHOD, Details.VALIDATE_ACCESS_TOKEN);
@@ -9,6 +9,7 @@ import org.keycloak.RSATokenVerifier;
import org.keycloak.events.Details;
import org.keycloak.events.Errors;
import org.keycloak.events.EventBuilder;
import org.keycloak.events.EventGroup;
import org.keycloak.events.EventType;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
@@ -22,6 +23,7 @@ import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.*;
import java.util.HashMap;
import java.util.Map;
@@ -51,7 +53,7 @@ public class ValidateTokenEndpoint {
public ValidateTokenEndpoint(TokenManager tokenManager, RealmModel realm, EventBuilder event) {
this.tokenManager = tokenManager;
this.realm = realm;
this.event = event;
this.event = event.eventGroup(EventGroup.USER);
}
/**
@@ -9,6 +9,7 @@ import org.keycloak.VerificationException;
import org.keycloak.broker.provider.IdentityProvider;
import org.keycloak.events.Details;
import org.keycloak.events.EventBuilder;
import org.keycloak.events.EventGroup;
import org.keycloak.events.EventType;
import org.keycloak.jose.jws.JWSBuilder;
import org.keycloak.login.LoginFormsProvider;
@@ -43,6 +44,7 @@ import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.NewCookie;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import java.net.URI;
import java.util.HashSet;
import java.util.LinkedList;
@@ -374,7 +376,7 @@ public class AuthenticationManager {
logger.debugv("processAccessCode: go to oauth page?: {0}",
!isResource);
event.detail(Details.CODE_ID, clientSession.getId());
event.eventGroup(EventGroup.USER).detail(Details.CODE_ID, clientSession.getId());
Set<UserModel.RequiredAction> requiredActions = user.getRequiredActions();
if (!requiredActions.isEmpty()) {
@@ -5,11 +5,14 @@ import org.keycloak.ClientConnection;
import org.keycloak.events.EventBuilder;
import org.keycloak.events.EventListenerProvider;
import org.keycloak.events.EventStoreProvider;
import org.keycloak.events.EventType;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
@@ -50,8 +53,13 @@ public class EventsManager {
}
}
}
Set<EventType> enabledEventTypes = new HashSet<EventType>();
for(String type : realm.getEnabledEventTypes()) {
enabledEventTypes.add(EventType.valueOf(type));
}
return new EventBuilder(listeners, realm, clientConnection.getRemoteAddr());
return new EventBuilder(listeners, enabledEventTypes, realm, clientConnection.getRemoteAddr());
}
}
@@ -25,6 +25,7 @@ import org.keycloak.timer.TimerProvider;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
/**
@@ -161,6 +162,9 @@ public class RealmManager {
if (rep.getEventsListeners() != null) {
realm.setEventsListeners(new HashSet<String>(rep.getEventsListeners()));
}
if(rep.getEnabledEventTypes() != null) {
realm.setEnabledEventTypes(new HashSet<String>(rep.getEnabledEventTypes()));
}
}
// Should be RealmManager moved to model/api instead of referencing methods this way?
@@ -31,6 +31,7 @@ import org.keycloak.account.AccountProvider;
import org.keycloak.events.Details;
import org.keycloak.events.Event;
import org.keycloak.events.EventBuilder;
import org.keycloak.events.EventGroup;
import org.keycloak.events.EventStoreProvider;
import org.keycloak.events.EventType;
import org.keycloak.models.*;
@@ -71,6 +72,7 @@ import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriBuilder;
import javax.ws.rs.core.UriInfo;
import javax.ws.rs.core.Variant;
import java.lang.reflect.Method;
import java.net.URI;
import java.util.HashSet;
@@ -141,7 +143,7 @@ public class AccountService {
public AccountService(RealmModel realm, ApplicationModel application, EventBuilder event) {
this.realm = realm;
this.application = application;
this.event = event;
this.event = event.eventGroup(EventGroup.USER);
this.authManager = new AppAuthManager();
}
@@ -29,6 +29,7 @@ import org.keycloak.broker.provider.IdentityProviderFactory;
import org.keycloak.events.Details;
import org.keycloak.events.Errors;
import org.keycloak.events.EventBuilder;
import org.keycloak.events.EventGroup;
import org.keycloak.events.EventType;
import org.keycloak.models.ClientModel;
import org.keycloak.models.ClientSessionModel;
@@ -61,6 +62,7 @@ import javax.ws.rs.PathParam;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.*;
import javax.ws.rs.core.Response.Status;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@@ -109,7 +111,7 @@ public class IdentityBrokerService implements IdentityProvider.AuthenticationCal
}
public void init() {
this.event = new EventsManager(this.realmModel, this.session, this.clientConnection).createEventBuilder().event(EventType.IDENTITY_PROVIDER_LOGIN);
this.event = new EventsManager(this.realmModel, this.session, this.clientConnection).createEventBuilder().event(EventType.IDENTITY_PROVIDER_LOGIN).eventGroup(EventGroup.USER);
}
@GET
@@ -29,6 +29,7 @@ import org.keycloak.email.EmailProvider;
import org.keycloak.events.Details;
import org.keycloak.events.Errors;
import org.keycloak.events.EventBuilder;
import org.keycloak.events.EventGroup;
import org.keycloak.events.EventType;
import org.keycloak.jose.jws.JWSBuilder;
import org.keycloak.login.LoginFormsProvider;
@@ -63,6 +64,7 @@ import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriBuilder;
import javax.ws.rs.core.UriInfo;
import javax.ws.rs.ext.Providers;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.TimeUnit;
@@ -132,7 +134,7 @@ public class LoginActionsService {
public LoginActionsService(RealmModel realm, AuthenticationManager authManager, EventBuilder event) {
this.realm = realm;
this.authManager = authManager;
this.event = event;
this.event = event.eventGroup(EventGroup.USER);
}
private boolean checkSsl() {
@@ -5,6 +5,7 @@ import org.jboss.resteasy.spi.NotFoundException;
import org.jboss.resteasy.spi.ResteasyProviderFactory;
import org.keycloak.ClientConnection;
import org.keycloak.events.EventBuilder;
import org.keycloak.events.EventGroup;
import org.keycloak.models.ApplicationModel;
import org.keycloak.models.Constants;
import org.keycloak.models.KeycloakSession;
@@ -130,6 +131,7 @@ public class RealmsResource {
RealmManager realmManager = new RealmManager(session);
RealmModel realm = locateRealm(name, realmManager);
EventBuilder event = new EventsManager(realm, session, clientConnection).createEventBuilder();
event.eventGroup(EventGroup.USER);
AuthenticationManager authManager = new AuthenticationManager(protector);
LoginActionsService service = new LoginActionsService(realm, authManager, event);
ResteasyProviderFactory.getInstance().injectProperties(service);
@@ -143,6 +145,7 @@ public class RealmsResource {
RealmManager realmManager = new RealmManager(session);
RealmModel realm = locateRealm(name, realmManager);
EventBuilder event = new EventsManager(realm, session, clientConnection).createEventBuilder();
event.eventGroup(EventGroup.USER);
ClientsManagementService service = new ClientsManagementService(realm, event);
ResteasyProviderFactory.getInstance().injectProperties(service);
return service;
@@ -169,6 +172,7 @@ public class RealmsResource {
}
EventBuilder event = new EventsManager(realm, session, clientConnection).createEventBuilder();
event.eventGroup(EventGroup.USER);
AccountService accountService = new AccountService(realm, application, event);
ResteasyProviderFactory.getInstance().injectProperties(accountService);
//resourceContext.initResource(accountService);
@@ -6,9 +6,11 @@ import org.jboss.resteasy.annotations.cache.NoCache;
import org.jboss.resteasy.spi.HttpRequest;
import org.jboss.resteasy.spi.HttpResponse;
import org.jboss.resteasy.spi.NotFoundException;
import org.keycloak.ClientConnection;
import org.keycloak.Config;
import org.keycloak.Version;
import org.keycloak.ClientConnection;
import org.keycloak.Version;
import org.keycloak.events.Details;
import org.keycloak.events.EventBuilder;
import org.keycloak.events.EventType;
import org.keycloak.freemarker.BrowserSecurityHeaderSetup;
import org.keycloak.freemarker.FreeMarkerException;
import org.keycloak.freemarker.FreeMarkerUtil;
@@ -28,21 +30,18 @@ import org.keycloak.services.managers.AuthenticationManager;
import org.keycloak.services.managers.RealmManager;
import org.keycloak.services.resources.KeycloakApplication;
import org.keycloak.services.resources.flows.Urls;
import org.keycloak.util.MimeTypeUtil;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.CacheControl;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import javax.ws.rs.ext.Providers;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.HashMap;
@@ -86,9 +85,11 @@ public class AdminConsole {
protected AppAuthManager authManager;
protected RealmModel realm;
private EventBuilder event;
public AdminConsole(RealmModel realm) {
public AdminConsole(RealmModel realm, EventBuilder event) {
this.realm = realm;
this.event = event.detail(Details.REALM_NAME, realm.getName());
this.authManager = new AppAuthManager();
}
@@ -168,6 +169,12 @@ public class AdminConsole {
if (consoleApp == null) {
throw new NotFoundException("Could not find admin console application");
}
event.event(EventType.SET_REALM_ADAPTER_CONFIGURATION)
.client(consoleApp)
.detail(Details.REALM_REQUIRED_SSL, realm.getSslRequired().name().toLowerCase())
.success();
return new ApplicationManager().toInstallationRepresentation(realm, consoleApp, keycloak.getBaseUri(uriInfo));
}
@@ -212,6 +219,8 @@ public class AdminConsole {
logger.debug("setting up realm access for a realm user");
addRealmAccess(realm, user, realmAccess);
}
event.event(EventType.SET_REALM_USER_PERMISSIONS).user(user).success();
return Response.ok(new WhoAmI(user.getId(), realm.getName(), displayName, createRealm, realmAccess)).build();
}
@@ -255,12 +264,14 @@ public class AdminConsole {
@NoCache
public Response logout() {
URI redirect = AdminRoot.adminConsoleUrl(uriInfo).build(realm.getName());
event.event(EventType.LOGOUT).detail(Details.REDIRECT_URI, redirect.toString()).success();
return Response.status(302).location(
OIDCLoginProtocolService.logoutUrl(uriInfo).queryParam("redirect_uri", redirect.toString()).build(realm.getName())
).build();
}
protected RealmModel getAdminstrationRealm(RealmManager realmManager) {
return realmManager.getKeycloakAdminstrationRealm();
}
@@ -8,6 +8,9 @@ import org.jboss.resteasy.spi.NotFoundException;
import org.jboss.resteasy.spi.ResteasyProviderFactory;
import org.jboss.resteasy.spi.UnauthorizedException;
import org.keycloak.ClientConnection;
import org.keycloak.events.Details;
import org.keycloak.events.EventBuilder;
import org.keycloak.events.EventGroup;
import org.keycloak.jose.jws.JWSInput;
import org.keycloak.models.ClientModel;
import org.keycloak.models.KeycloakSession;
@@ -16,6 +19,7 @@ import org.keycloak.protocol.oidc.TokenManager;
import org.keycloak.representations.AccessToken;
import org.keycloak.services.managers.AppAuthManager;
import org.keycloak.services.managers.AuthenticationManager;
import org.keycloak.services.managers.EventsManager;
import org.keycloak.services.managers.RealmManager;
import org.keycloak.services.resources.Cors;
@@ -27,6 +31,7 @@ import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriBuilder;
import javax.ws.rs.core.UriInfo;
import java.io.IOException;
/**
@@ -70,9 +75,6 @@ public class AdminRoot {
return base.path(AdminRoot.class);
}
/**
* Convenience path to master realm admin console
*
@@ -124,7 +126,9 @@ public class AdminRoot {
public AdminConsole getAdminConsole(final @PathParam("realm") String name) {
RealmManager realmManager = new RealmManager(session);
RealmModel realm = locateRealm(name, realmManager);
AdminConsole service = new AdminConsole(realm);
EventBuilder event = new EventsManager(realm, session, clientConnection).createEventBuilder();
event.eventGroup(EventGroup.ADMIN).detail(Details.REALM_NAME, realm.getName());
AdminConsole service = new AdminConsole(realm, event);
ResteasyProviderFactory.getInstance().injectProperties(service);
return service;
}
@@ -187,7 +191,9 @@ public class AdminRoot {
Cors.add(request).allowedOrigins(auth.getToken()).allowedMethods("GET", "PUT", "POST", "DELETE").auth().build(response);
RealmsAdminResource adminResource = new RealmsAdminResource(auth, tokenManager);
EventBuilder event = new EventsManager(auth.getRealm(), session, clientConnection).createEventBuilder();
event.eventGroup(EventGroup.ADMIN);
RealmsAdminResource adminResource = new RealmsAdminResource(auth, tokenManager, event);
ResteasyProviderFactory.getInstance().injectProperties(adminResource);
//resourceContext.initResource(adminResource);
return adminResource;
@@ -208,8 +214,10 @@ public class AdminRoot {
logger.debug("authenticated admin access for: " + auth.getUser().getUsername());
}
Cors.add(request).allowedOrigins(auth.getToken()).allowedMethods("GET", "PUT", "POST", "DELETE").auth().build(response);
ServerInfoAdminResource adminResource = new ServerInfoAdminResource();
EventBuilder event = new EventsManager(auth.getRealm(), session, clientConnection).createEventBuilder();
event.eventGroup(EventGroup.ADMIN);
ServerInfoAdminResource adminResource = new ServerInfoAdminResource(event);
ResteasyProviderFactory.getInstance().injectProperties(adminResource);
//resourceContext.initResource(adminResource);
return adminResource;
@@ -5,6 +5,9 @@ import org.jboss.resteasy.annotations.cache.NoCache;
import org.jboss.resteasy.spi.BadRequestException;
import org.jboss.resteasy.spi.NotFoundException;
import org.jboss.resteasy.spi.ResteasyProviderFactory;
import org.keycloak.events.Details;
import org.keycloak.events.EventBuilder;
import org.keycloak.events.EventType;
import org.keycloak.models.ApplicationModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.ModelDuplicateException;
@@ -40,6 +43,7 @@ import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
@@ -57,8 +61,10 @@ public class ApplicationResource {
protected static final Logger logger = Logger.getLogger(ApplicationResource.class);
protected RealmModel realm;
private RealmAuth auth;
private EventBuilder event;
protected ApplicationModel application;
protected KeycloakSession session;
@Context
protected UriInfo uriInfo;
@@ -69,12 +75,13 @@ public class ApplicationResource {
return (KeycloakApplication)keycloak;
}
public ApplicationResource(RealmModel realm, RealmAuth auth, ApplicationModel applicationModel, KeycloakSession session) {
public ApplicationResource(RealmModel realm, RealmAuth auth, ApplicationModel applicationModel, KeycloakSession session, EventBuilder event) {
this.realm = realm;
this.auth = auth;
this.application = applicationModel;
this.session = session;
this.event = event;
auth.init(RealmAuth.Resource.APPLICATION);
}
@@ -98,6 +105,9 @@ public class ApplicationResource {
try {
RepresentationToModel.updateApplication(rep, application);
event.event(EventType.UPDATE_APPLICATION).client(application).success();
return Response.noContent().build();
} catch (ModelDuplicateException e) {
return Flows.errors().exists("Application " + rep.getName() + " already exists");
@@ -115,6 +125,8 @@ public class ApplicationResource {
@Produces(MediaType.APPLICATION_JSON)
public ApplicationRepresentation getApplication() {
auth.requireView();
event.event(EventType.VIEW_APPLICATION).client(application).success();
return ModelToRepresentation.toRepresentation(application);
}
@@ -126,7 +138,7 @@ public class ApplicationResource {
*/
@Path("certificates/{attr}")
public ClientAttributeCertificateResource getCertficateResource(@PathParam("attr") String attributePrefix) {
return new ClientAttributeCertificateResource(realm, auth, application, session, attributePrefix);
return new ClientAttributeCertificateResource(realm, auth, application, session, attributePrefix, event);
}
@@ -175,6 +187,8 @@ public class ApplicationResource {
@NoCache
public void deleteApplication() {
auth.requireManage();
event.event(EventType.DELETE_APPLICATION).client(application).success();
new ApplicationManager(new RealmManager(session)).removeApplication(realm, application);
}
@@ -228,7 +242,7 @@ public class ApplicationResource {
@Path("roles")
public RoleContainerResource getRoleContainerResource() {
return new RoleContainerResource(realm, auth, application);
return new RoleContainerResource(realm, auth, application, event);
}
/**
@@ -331,6 +345,9 @@ public class ApplicationResource {
UserSessionRepresentation rep = ModelToRepresentation.toRepresentation(userSession);
sessions.add(rep);
}
event.event(EventType.VIEW_APPLICATION_USER_SESSIONS).client(application).success();
return sessions;
}
@@ -342,6 +359,9 @@ public class ApplicationResource {
@POST
public GlobalRequestResult logoutAll() {
auth.requireManage();
event.event(EventType.INVALIDATE_APPLICATION_USER_SESSIONS).client(application).success();
return new ResourceAdminManager().logoutApplication(uriInfo.getRequestUri(), realm, application);
}
@@ -357,6 +377,8 @@ public class ApplicationResource {
if (user == null) {
throw new NotFoundException("User not found");
}
event.event(EventType.INVALIDATE_APPLICATION_USER_SESSION).client(application).user(user).success();
new ResourceAdminManager().logoutUserFromApplication(uriInfo.getRequestUri(), realm, application, user, session);
}
@@ -378,6 +400,10 @@ public class ApplicationResource {
}
if (logger.isDebugEnabled()) logger.debug("Register node: " + node);
application.registerNode(node, Time.currentTime());
event.event(EventType.REGISTER_APPLICATION_CLUSTER_NODE).client(application)
.detail(Details.APPLICATION_CLUSTER_NODE, node)
.success();
}
/**
@@ -398,6 +424,10 @@ public class ApplicationResource {
}
application.unregisterNode(node);
event.event(EventType.UNREGISTER_APPLICATION_CLUSTER_NODE).client(application)
.detail(Details.APPLICATION_CLUSTER_NODE, node)
.success();
}
/**
@@ -1,5 +1,6 @@
package org.keycloak.services.resources.admin;
import org.keycloak.events.EventBuilder;
import org.keycloak.models.ApplicationModel;
import org.keycloak.models.RealmModel;
@@ -8,8 +9,8 @@ import org.keycloak.models.RealmModel;
* @version $Revision: 1 $
*/
public class ApplicationsByIdResource extends ApplicationsResource {
public ApplicationsByIdResource(RealmModel realm, RealmAuth auth) {
super(realm, auth);
public ApplicationsByIdResource(RealmModel realm, RealmAuth auth, EventBuilder event) {
super(realm, auth, event);
}
@Override
@@ -4,6 +4,9 @@ import org.jboss.logging.Logger;
import org.jboss.resteasy.annotations.cache.NoCache;
import org.jboss.resteasy.spi.NotFoundException;
import org.jboss.resteasy.spi.ResteasyProviderFactory;
import org.keycloak.events.Details;
import org.keycloak.events.EventBuilder;
import org.keycloak.events.EventType;
import org.keycloak.models.ApplicationModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.ModelDuplicateException;
@@ -23,6 +26,7 @@ import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import java.util.ArrayList;
import java.util.List;
@@ -36,14 +40,16 @@ public class ApplicationsResource {
protected static final Logger logger = Logger.getLogger(RealmAdminResource.class);
protected RealmModel realm;
private RealmAuth auth;
private EventBuilder event;
@Context
protected KeycloakSession session;
public ApplicationsResource(RealmModel realm, RealmAuth auth) {
public ApplicationsResource(RealmModel realm, RealmAuth auth, EventBuilder event) {
this.realm = realm;
this.auth = auth;
this.event = event;
auth.init(RealmAuth.Resource.APPLICATION);
}
@@ -71,6 +77,9 @@ public class ApplicationsResource {
rep.add(app);
}
}
event.event(EventType.VIEW_REALM_APPLICATIONS).success();
return rep;
}
@@ -85,13 +94,16 @@ public class ApplicationsResource {
@Consumes(MediaType.APPLICATION_JSON)
public Response createApplication(final @Context UriInfo uriInfo, final ApplicationRepresentation rep) {
auth.requireManage();
try {
ApplicationModel applicationModel = RepresentationToModel.createApplication(session, realm, rep, true);
event.event(EventType.CREATE_APPLICATION).client(applicationModel).success();
return Response.created(uriInfo.getAbsolutePathBuilder().path(getApplicationPath(applicationModel)).build()).build();
} catch (ModelDuplicateException e) {
return Flows.errors().exists("Application " + rep.getName() + " already exists");
}
}
protected String getApplicationPath(ApplicationModel applicationModel) {
@@ -110,7 +122,7 @@ public class ApplicationsResource {
if (applicationModel == null) {
throw new NotFoundException("Could not find application: " + name);
}
ApplicationResource applicationResource = new ApplicationResource(realm, auth, applicationModel, session);
ApplicationResource applicationResource = new ApplicationResource(realm, auth, applicationModel, session, event);
ResteasyProviderFactory.getInstance().injectProperties(applicationResource);
//resourceContext.initResource(applicationResource);
return applicationResource;
@@ -6,6 +6,9 @@ import org.jboss.resteasy.plugins.providers.multipart.MultipartFormDataInput;
import org.jboss.resteasy.spi.BadRequestException;
import org.jboss.resteasy.spi.NotAcceptableException;
import org.jboss.resteasy.spi.NotFoundException;
import org.keycloak.events.Details;
import org.keycloak.events.EventBuilder;
import org.keycloak.events.EventType;
import org.keycloak.models.ClientModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
@@ -21,6 +24,7 @@ import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.UriInfo;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
@@ -39,18 +43,20 @@ import java.util.Map;
* @version $Revision: 1 $
*/
public class ClientAttributeCertificateResource {
public static final String PRIVATE_KEY = "private.key";
public static final String X509CERTIFICATE = "certificate";
protected RealmModel realm;
private RealmAuth auth;
private EventBuilder event;
protected ClientModel client;
protected KeycloakSession session;
protected String attributePrefix;
protected String privateAttribute;
protected String certificateAttribute;
public ClientAttributeCertificateResource(RealmModel realm, RealmAuth auth, ClientModel client, KeycloakSession session, String attributePrefix) {
public ClientAttributeCertificateResource(RealmModel realm, RealmAuth auth, ClientModel client, KeycloakSession session, String attributePrefix, EventBuilder event) {
this.realm = realm;
this.auth = auth;
this.client = client;
@@ -58,6 +64,7 @@ public class ClientAttributeCertificateResource {
this.attributePrefix = attributePrefix;
this.privateAttribute = attributePrefix + "." + PRIVATE_KEY;
this.certificateAttribute = attributePrefix + "." + X509CERTIFICATE;
this.event = event;
}
public static class ClientKeyPairInfo {
@@ -93,6 +100,9 @@ public class ClientAttributeCertificateResource {
ClientKeyPairInfo info = new ClientKeyPairInfo();
info.setCertificate(client.getAttribute(certificateAttribute));
info.setPrivateKey(client.getAttribute(privateAttribute));
event.event(EventType.VIEW_CLIENT_CERTIFICATE).client(client).success();
return info;
}
@@ -131,6 +141,9 @@ public class ClientAttributeCertificateResource {
ClientKeyPairInfo info = new ClientKeyPairInfo();
info.setCertificate(client.getAttribute(certificateAttribute));
info.setPrivateKey(client.getAttribute(privateAttribute));
event.event(EventType.GENERATE_CLIENT_CERTIFICATE).client(client).success();
return info;
}
@@ -187,8 +200,9 @@ public class ClientAttributeCertificateResource {
client.setAttribute(certificateAttribute, certPem);
info.setCertificate(certPem);
}
event.event(EventType.UPLOAD_CLIENT_CERTIFICATE).client(client).success();
return info;
}
@@ -314,6 +328,9 @@ public class ClientAttributeCertificateResource {
stream.flush();
stream.close();
byte[] rtn = stream.toByteArray();
event.event(EventType.DOWNLOAD_CLIENT_CERTIFICATE).client(client).success();
return rtn;
} catch (Exception e) {
throw new RuntimeException(e);
@@ -4,6 +4,9 @@ import org.jboss.logging.Logger;
import org.jboss.resteasy.annotations.cache.NoCache;
import org.keycloak.broker.provider.IdentityProvider;
import org.keycloak.broker.provider.IdentityProviderFactory;
import org.keycloak.events.Details;
import org.keycloak.events.EventBuilder;
import org.keycloak.events.EventType;
import org.keycloak.models.ClientIdentityProviderMappingModel;
import org.keycloak.models.ClientModel;
import org.keycloak.models.FederatedIdentityModel;
@@ -29,6 +32,7 @@ import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import java.util.ArrayList;
import java.util.List;
@@ -43,18 +47,26 @@ public class IdentityProviderResource {
private final RealmModel realm;
private final KeycloakSession session;
private final IdentityProviderModel identityProviderModel;
private EventBuilder event;
public IdentityProviderResource(RealmAuth auth, RealmModel realm, KeycloakSession session, IdentityProviderModel identityProviderModel) {
public IdentityProviderResource(RealmAuth auth, RealmModel realm, KeycloakSession session, IdentityProviderModel identityProviderModel, EventBuilder event) {
this.realm = realm;
this.session = session;
this.identityProviderModel = identityProviderModel;
this.auth = auth;
this.event = event;
}
@GET
@NoCache
@Produces("application/json")
public IdentityProviderRepresentation getIdentityProvider() {
event.event(EventType.VIEW_IDENTITY_PROVIDER)
.detail(Details.IDENTITY_PROVIDER, identityProviderModel.getProviderId())
.detail(Details.IDENTITY_PROVIDER_ALIAS, identityProviderModel.getAlias())
.success();
return ModelToRepresentation.toRepresentation(this.identityProviderModel);
}
@@ -64,7 +76,14 @@ public class IdentityProviderResource {
this.auth.requireManage();
removeClientIdentityProviders(this.realm.getApplications(), this.identityProviderModel);
removeClientIdentityProviders(this.realm.getOAuthClients(), this.identityProviderModel);
this.realm.removeIdentityProviderByAlias(this.identityProviderModel.getAlias());
this.realm.removeIdentityProviderByAlias(this.identityProviderModel.getAlias());
event.event(EventType.DELETE_IDENTITY_PROVIDER)
.detail(Details.IDENTITY_PROVIDER, identityProviderModel.getProviderId())
.detail(Details.IDENTITY_PROVIDER_ALIAS, identityProviderModel.getAlias())
.success();
return Response.noContent().build();
}
@@ -89,6 +108,11 @@ public class IdentityProviderResource {
updateClientsAfterProviderAliasChange(this.realm.getOAuthClients(), oldProviderId, newProviderId);
updateUsersAfterProviderAliasChange(this.session.users().getUsers(this.realm), oldProviderId, newProviderId);
}
event.event(EventType.UPDATE_IDENTITY_PROVIDER)
.detail(Details.IDENTITY_PROVIDER, identityProviderModel.getProviderId())
.detail(Details.IDENTITY_PROVIDER_ALIAS, identityProviderModel.getAlias())
.success();
return Response.noContent().build();
} catch (ModelDuplicateException e) {
@@ -8,8 +8,9 @@ import org.jboss.resteasy.spi.NotFoundException;
import org.jboss.resteasy.spi.ResteasyProviderFactory;
import org.keycloak.broker.provider.IdentityProvider;
import org.keycloak.broker.provider.IdentityProviderFactory;
import org.keycloak.models.ClientIdentityProviderMappingModel;
import org.keycloak.models.ClientModel;
import org.keycloak.events.Details;
import org.keycloak.events.EventBuilder;
import org.keycloak.events.EventType;
import org.keycloak.models.IdentityProviderModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.ModelDuplicateException;
@@ -32,6 +33,7 @@ import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
@@ -48,11 +50,13 @@ public class IdentityProvidersResource {
private final RealmModel realm;
private final KeycloakSession session;
private RealmAuth auth;
private EventBuilder event;
public IdentityProvidersResource(RealmModel realm, KeycloakSession session, RealmAuth auth) {
public IdentityProvidersResource(RealmModel realm, KeycloakSession session, RealmAuth auth, EventBuilder event) {
this.realm = realm;
this.session = session;
this.auth = auth;
this.event = event;
this.auth.init(RealmAuth.Resource.IDENTITY_PROVIDER);
}
@@ -65,6 +69,11 @@ public class IdentityProvidersResource {
IdentityProviderFactory providerFactory = getProviderFactorytById(providerId);
if (providerFactory != null) {
event.event(EventType.VIEW_IDENTITY_PROVIDERS)
.detail(Details.IDENTITY_PROVIDER_FACTORY, providerFactory.getId())
.detail(Details.IDENTITY_PROVIDER_FACTORY_IDENTITY, providerFactory.getName())
.success();
return Response.ok(providerFactory).build();
}
@@ -83,6 +92,12 @@ public class IdentityProvidersResource {
InputStream inputStream = file.getBody(InputStream.class, null);
IdentityProviderFactory providerFactory = getProviderFactorytById(providerId);
Map<String, String> config = providerFactory.parseConfig(inputStream);
event.event(EventType.IMPORT_IDENTITY_PROVIDER_CONFIG)
.detail(Details.IDENTITY_PROVIDER_FACTORY, providerFactory.getId())
.detail(Details.IDENTITY_PROVIDER_FACTORY_IDENTITY, providerFactory.getName())
.success();
return config;
}
@@ -104,6 +119,12 @@ public class IdentityProvidersResource {
}
IdentityProviderFactory providerFactory = getProviderFactorytById(providerId);
Map<String, String> config = providerFactory.parseConfig(inputStream);
event.event(EventType.IMPORT_IDENTITY_PROVIDER_CONFIG)
.detail(Details.IDENTITY_PROVIDER_FACTORY, providerFactory.getId())
.detail(Details.IDENTITY_PROVIDER_FACTORY_IDENTITY, providerFactory.getName())
.success();
return config;
}
@@ -119,6 +140,8 @@ public class IdentityProvidersResource {
for (IdentityProviderModel identityProviderModel : realm.getIdentityProviders()) {
representations.add(ModelToRepresentation.toRepresentation(identityProviderModel));
}
event.event(EventType.VIEW_IDENTITY_PROVIDERS).success();
return representations;
}
@@ -131,7 +154,12 @@ public class IdentityProvidersResource {
try {
this.realm.addIdentityProvider(RepresentationToModel.toModel(representation));
event.event(EventType.CREATE_IDENTITY_PROVIDER)
.detail(Details.IDENTITY_PROVIDER, representation.getProviderId())
.detail(Details.IDENTITY_PROVIDER_ALIAS, representation.getAlias())
.success();
return Response.created(uriInfo.getAbsolutePathBuilder().path(representation.getProviderId()).build()).build();
} catch (ModelDuplicateException e) {
return Flows.errors().exists("Identity Provider " + representation.getAlias() + " already exists");
@@ -153,9 +181,14 @@ public class IdentityProvidersResource {
if (identityProviderModel == null) {
throw new NotFoundException("Could not find identity provider: " + alias);
}
IdentityProviderResource identityProviderResource = new IdentityProviderResource(this.auth, realm, session, identityProviderModel);
IdentityProviderResource identityProviderResource = new IdentityProviderResource(this.auth, realm, session, identityProviderModel, event);
ResteasyProviderFactory.getInstance().injectProperties(identityProviderResource);
event.event(EventType.VIEW_IDENTITY_PROVIDER)
.detail(Details.IDENTITY_PROVIDER, identityProviderModel.getProviderId())
.detail(Details.IDENTITY_PROVIDER_ALIAS, identityProviderModel.getAlias())
.success();
return identityProviderResource;
}
@@ -180,4 +213,4 @@ public class IdentityProvidersResource {
return allProviders;
}
}
}
@@ -4,6 +4,9 @@ import org.jboss.logging.Logger;
import org.jboss.resteasy.annotations.cache.NoCache;
import org.jboss.resteasy.spi.NotFoundException;
import org.jboss.resteasy.spi.ResteasyProviderFactory;
import org.keycloak.events.Details;
import org.keycloak.events.EventBuilder;
import org.keycloak.events.EventType;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.ModelDuplicateException;
import org.keycloak.models.OAuthClientModel;
@@ -31,6 +34,7 @@ import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import java.io.IOException;
/**
@@ -43,6 +47,7 @@ public class OAuthClientResource {
protected static final Logger logger = Logger.getLogger(RealmAdminResource.class);
protected RealmModel realm;
private RealmAuth auth;
private EventBuilder event;
protected OAuthClientModel oauthClient;
protected KeycloakSession session;
@Context
@@ -55,11 +60,12 @@ public class OAuthClientResource {
return (KeycloakApplication)application;
}
public OAuthClientResource(RealmModel realm, RealmAuth auth, OAuthClientModel oauthClient, KeycloakSession session) {
public OAuthClientResource(RealmModel realm, RealmAuth auth, OAuthClientModel oauthClient, KeycloakSession session, EventBuilder event) {
this.realm = realm;
this.auth = auth;
this.oauthClient = oauthClient;
this.session = session;
this.event = event;
auth.init(RealmAuth.Resource.CLIENT);
}
@@ -84,7 +90,7 @@ public class OAuthClientResource {
*/
@Path("certificates/{attr}")
public ClientAttributeCertificateResource getCertficateResource(@PathParam("attr") String attributePrefix) {
return new ClientAttributeCertificateResource(realm, auth, oauthClient, session, attributePrefix);
return new ClientAttributeCertificateResource(realm, auth, oauthClient, session, attributePrefix, event);
}
@@ -102,6 +108,8 @@ public class OAuthClientResource {
try {
RepresentationToModel.updateOAuthClient(session, rep, oauthClient);
event.event(EventType.UPDATE_OAUTH_CLIENT).client(oauthClient).success();
return Response.noContent().build();
} catch (ModelDuplicateException e) {
return Flows.errors().exists("Client " + rep.getName() + " already exists");
@@ -118,7 +126,9 @@ public class OAuthClientResource {
@Produces(MediaType.APPLICATION_JSON)
public OAuthClientRepresentation getOAuthClient() {
auth.requireView();
event.event(EventType.VIEW_OAUTH_CLIENT).client(oauthClient).success();
return ModelToRepresentation.toRepresentation(oauthClient);
}
@@ -150,7 +160,9 @@ public class OAuthClientResource {
@NoCache
public void deleteOAuthClient() {
auth.requireManage();
event.event(EventType.DELETE_OAUTH_CLIENT).client(oauthClient).success();
new OAuthClientManager(new RealmManager(session)).removeClient(realm, oauthClient);
}
@@ -1,38 +1,17 @@
package org.keycloak.services.resources.admin;
import org.jboss.logging.Logger;
import org.jboss.resteasy.annotations.cache.NoCache;
import org.jboss.resteasy.spi.NotFoundException;
import org.jboss.resteasy.spi.ResteasyProviderFactory;
import org.keycloak.events.EventBuilder;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.ModelDuplicateException;
import org.keycloak.models.OAuthClientModel;
import org.keycloak.models.RealmModel;
import org.keycloak.models.utils.ModelToRepresentation;
import org.keycloak.models.utils.RepresentationToModel;
import org.keycloak.representations.idm.OAuthClientRepresentation;
import org.keycloak.services.resources.flows.Flows;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import java.util.ArrayList;
import java.util.List;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class OAuthClientsByIdResource extends OAuthClientsResource {
public OAuthClientsByIdResource(RealmModel realm, RealmAuth auth, KeycloakSession session) {
super(realm, auth, session);
public OAuthClientsByIdResource(RealmModel realm, RealmAuth auth, KeycloakSession session, EventBuilder event) {
super(realm, auth, session, event);
}
@Override
@@ -4,6 +4,9 @@ import org.jboss.logging.Logger;
import org.jboss.resteasy.annotations.cache.NoCache;
import org.jboss.resteasy.spi.NotFoundException;
import org.jboss.resteasy.spi.ResteasyProviderFactory;
import org.keycloak.events.Details;
import org.keycloak.events.EventBuilder;
import org.keycloak.events.EventType;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.ModelDuplicateException;
import org.keycloak.models.OAuthClientModel;
@@ -23,6 +26,7 @@ import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import java.util.ArrayList;
import java.util.List;
@@ -33,9 +37,9 @@ import java.util.List;
public class OAuthClientsResource {
protected static final Logger logger = Logger.getLogger(RealmAdminResource.class);
protected RealmModel realm;
private EventBuilder event;
protected KeycloakSession session;
/*
@Context
protected ResourceContext resourceContext;
@@ -43,11 +47,12 @@ public class OAuthClientsResource {
*/
private RealmAuth auth;
public OAuthClientsResource(RealmModel realm, RealmAuth auth, KeycloakSession session) {
public OAuthClientsResource(RealmModel realm, RealmAuth auth, KeycloakSession session, EventBuilder event) {
this.auth = auth;
this.realm = realm;
this.session = session;
this.event = event;
auth.init(RealmAuth.Resource.CLIENT);
}
@@ -73,6 +78,9 @@ public class OAuthClientsResource {
rep.add(client);
}
}
event.event(EventType.VIEW_OAUTH_CLIENTS).success();
return rep;
}
@@ -90,10 +98,13 @@ public class OAuthClientsResource {
try {
OAuthClientModel oauth = RepresentationToModel.createOAuthClient(session, rep, realm);
event.event(EventType.CREATE_OAUTH_CLIENT).client(oauth).success();
return Response.created(uriInfo.getAbsolutePathBuilder().path(getClientPath(oauth)).build()).build();
} catch (ModelDuplicateException e) {
return Flows.errors().exists("Client " + rep.getName() + " already exists");
}
}
protected String getClientPath(OAuthClientModel oauth) {
@@ -114,7 +125,7 @@ public class OAuthClientsResource {
if (oauth == null) {
throw new NotFoundException("OAuth Client not found");
}
OAuthClientResource oAuthClientResource = new OAuthClientResource(realm, auth, oauth, session);
OAuthClientResource oAuthClientResource = new OAuthClientResource(realm, auth, oauth, session, event);
ResteasyProviderFactory.getInstance().injectProperties(oAuthClientResource);
//resourceContext.initResource(oAuthClientResource);
return oAuthClientResource;
@@ -26,6 +26,7 @@ import org.jboss.resteasy.spi.NotFoundException;
import org.jboss.resteasy.spi.ResteasyProviderFactory;
import org.keycloak.ClientConnection;
import org.keycloak.events.Event;
import org.keycloak.events.EventBuilder;
import org.keycloak.events.EventQuery;
import org.keycloak.events.EventStoreProvider;
import org.keycloak.events.EventType;
@@ -63,6 +64,7 @@ public class RealmAdminResource {
protected RealmAuth auth;
protected RealmModel realm;
private TokenManager tokenManager;
private EventBuilder event;
@Context
protected KeycloakSession session;
@@ -75,12 +77,13 @@ public class RealmAdminResource {
@Context
protected HttpHeaders headers;
public RealmAdminResource(RealmAuth auth, RealmModel realm, TokenManager tokenManager) {
public RealmAdminResource(RealmAuth auth, RealmModel realm, TokenManager tokenManager, EventBuilder event) {
this.auth = auth;
this.realm = realm;
this.tokenManager = tokenManager;
this.event = event;
auth.init(RealmAuth.Resource.REALM);
}
@@ -102,7 +105,7 @@ public class RealmAdminResource {
*/
@Path("applications")
public ApplicationsResource getApplications() {
ApplicationsResource applicationsResource = new ApplicationsResource(realm, auth);
ApplicationsResource applicationsResource = new ApplicationsResource(realm, auth, event);
ResteasyProviderFactory.getInstance().injectProperties(applicationsResource);
//resourceContext.initResource(applicationsResource);
return applicationsResource;
@@ -115,7 +118,7 @@ public class RealmAdminResource {
*/
@Path("applications-by-id")
public ApplicationsByIdResource getApplicationsById() {
ApplicationsByIdResource applicationsResource = new ApplicationsByIdResource(realm, auth);
ApplicationsByIdResource applicationsResource = new ApplicationsByIdResource(realm, auth, event);
ResteasyProviderFactory.getInstance().injectProperties(applicationsResource);
//resourceContext.initResource(applicationsResource);
return applicationsResource;
@@ -128,7 +131,7 @@ public class RealmAdminResource {
*/
@Path("oauth-clients")
public OAuthClientsResource getOAuthClients() {
OAuthClientsResource oauth = new OAuthClientsResource(realm, auth, session);
OAuthClientsResource oauth = new OAuthClientsResource(realm, auth, session, event);
ResteasyProviderFactory.getInstance().injectProperties(oauth);
//resourceContext.initResource(oauth);
return oauth;
@@ -141,7 +144,7 @@ public class RealmAdminResource {
*/
@Path("oauth-clients-by-id")
public OAuthClientsByIdResource getOAuthClientsById() {
OAuthClientsByIdResource oauth = new OAuthClientsByIdResource(realm, auth, session);
OAuthClientsByIdResource oauth = new OAuthClientsByIdResource(realm, auth, session, event);
ResteasyProviderFactory.getInstance().injectProperties(oauth);
//resourceContext.initResource(oauth);
return oauth;
@@ -154,7 +157,7 @@ public class RealmAdminResource {
*/
@Path("roles")
public RoleContainerResource getRoleContainerResource() {
return new RoleContainerResource(realm, auth, realm);
return new RoleContainerResource(realm, auth, realm, event);
}
/**
@@ -177,13 +180,18 @@ public class RealmAdminResource {
CacheUserProvider cache = (CacheUserProvider)session.userStorage();
rep.setUserCacheEnabled(cache.isEnabled());
}
event.event(EventType.VIEW_REALM).success();
return rep;
} else {
auth.requireAny();
RealmRepresentation rep = new RealmRepresentation();
rep.setRealm(realm.getName());
event.event(EventType.VIEW_REALM).success();
return rep;
}
}
@@ -218,7 +226,9 @@ public class RealmAdminResource {
for (final UserFederationProviderModel fedProvider : federationProviders) {
usersSyncManager.refreshPeriodicSyncForProvider(session.getKeycloakSessionFactory(), session.getProvider(TimerProvider.class), fedProvider, realm.getId());
}
event.event(EventType.UPDATE_REALM).success();
return Response.noContent().build();
} catch (ModelDuplicateException e) {
return Flows.errors().exists("Realm " + rep.getRealm() + " already exists");
@@ -236,6 +246,8 @@ public class RealmAdminResource {
if (!new RealmManager(session).removeRealm(realm)) {
throw new NotFoundException("Realm doesn't exist");
}
event.event(EventType.DELETE_REALM).success();
}
/**
@@ -245,7 +257,7 @@ public class RealmAdminResource {
*/
@Path("users")
public UsersResource users() {
UsersResource users = new UsersResource(realm, auth, tokenManager);
UsersResource users = new UsersResource(realm, auth, tokenManager, event);
ResteasyProviderFactory.getInstance().injectProperties(users);
//resourceContext.initResource(users);
return users;
@@ -253,7 +265,7 @@ public class RealmAdminResource {
@Path("user-federation")
public UserFederationResource userFederation() {
UserFederationResource fed = new UserFederationResource(realm, auth);
UserFederationResource fed = new UserFederationResource(realm, auth, event);
ResteasyProviderFactory.getInstance().injectProperties(fed);
//resourceContext.initResource(fed);
return fed;
@@ -266,7 +278,7 @@ public class RealmAdminResource {
*/
@Path("roles-by-id")
public RoleByIdResource rolesById() {
RoleByIdResource resource = new RoleByIdResource(realm, auth);
RoleByIdResource resource = new RoleByIdResource(realm, auth, event);
ResteasyProviderFactory.getInstance().injectProperties(resource);
//resourceContext.initResource(resource);
return resource;
@@ -473,6 +485,6 @@ public class RealmAdminResource {
@Path("identity-provider")
public IdentityProvidersResource getIdentityProviderResource() {
return new IdentityProvidersResource(realm, session, this.auth);
return new IdentityProvidersResource(realm, session, this.auth, event);
}
}
@@ -6,6 +6,10 @@ import org.jboss.resteasy.plugins.providers.multipart.InputPart;
import org.jboss.resteasy.plugins.providers.multipart.MultipartFormDataInput;
import org.jboss.resteasy.spi.NotFoundException;
import org.jboss.resteasy.spi.ResteasyProviderFactory;
import org.keycloak.events.Details;
import org.keycloak.events.EventBuilder;
import org.keycloak.events.EventGroup;
import org.keycloak.events.EventType;
import org.keycloak.models.AdminRoles;
import org.keycloak.models.ApplicationModel;
import org.keycloak.models.KeycloakSession;
@@ -33,6 +37,7 @@ import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import java.io.IOException;
import java.net.URI;
import java.util.ArrayList;
@@ -49,10 +54,12 @@ public class RealmsAdminResource {
protected static final Logger logger = Logger.getLogger(RealmsAdminResource.class);
protected AdminAuth auth;
protected TokenManager tokenManager;
private EventBuilder event;
public RealmsAdminResource(AdminAuth auth, TokenManager tokenManager) {
public RealmsAdminResource(AdminAuth auth, TokenManager tokenManager, EventBuilder event) {
this.auth = auth;
this.tokenManager = tokenManager;
this.event = event;
}
public static final CacheControl noCache = new CacheControl();
@@ -72,7 +79,6 @@ public class RealmsAdminResource {
@Context
protected KeycloakApplication keycloak;
/**
* Returns a list of realms. This list is filtered based on what realms the caller is allowed to view.
*
@@ -135,6 +141,9 @@ public class RealmsAdminResource {
URI location = AdminRoot.realmsUrl(uriInfo).path(realm.getName()).build();
logger.debugv("imported realm success, sending back: {0}", location.toString());
event.event(EventType.IMPORT_REALM).detail(Details.REALM_NAME, realm.getName()).success();
return Response.created(location).build();
} catch (ModelDuplicateException e) {
return Flows.errors().exists("Realm " + rep.getRealm() + " already exists");
@@ -181,8 +190,10 @@ public class RealmsAdminResource {
URI location = AdminRoot.realmsUrl(uriInfo).path(realm.getName()).build();
return Response.created(location).build();
}
event.event(EventType.UPLOAD_REALM).detail(Details.REALM_NAME, realm.getName()).success();
}
return Response.noContent().build();
}
@@ -224,8 +235,9 @@ public class RealmsAdminResource {
} else {
realmAuth = new RealmAuth(auth, realm.getApplicationByName(realmManager.getRealmAdminApplicationName(auth.getRealm())));
}
RealmAdminResource adminResource = new RealmAdminResource(realmAuth, realm, tokenManager);
event.detail(Details.REALM_NAME, realm.getName());
RealmAdminResource adminResource = new RealmAdminResource(realmAuth, realm, tokenManager, event);
ResteasyProviderFactory.getInstance().injectProperties(adminResource);
//resourceContext.initResource(adminResource);
return adminResource;
@@ -3,7 +3,11 @@ package org.keycloak.services.resources.admin;
import org.jboss.logging.Logger;
import org.jboss.resteasy.annotations.cache.NoCache;
import org.jboss.resteasy.spi.NotFoundException;
import org.keycloak.events.Details;
import org.keycloak.events.EventBuilder;
import org.keycloak.events.EventType;
import org.keycloak.models.ApplicationModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.OAuthClientModel;
import org.keycloak.models.RealmModel;
import org.keycloak.models.RoleModel;
@@ -18,6 +22,8 @@ import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import java.util.List;
import java.util.Set;
@@ -31,12 +37,17 @@ public class RoleByIdResource extends RoleResource {
protected static final Logger logger = Logger.getLogger(RoleByIdResource.class);
private final RealmModel realm;
private final RealmAuth auth;
private EventBuilder event;
public RoleByIdResource(RealmModel realm, RealmAuth auth) {
@Context
protected KeycloakSession session;
public RoleByIdResource(RealmModel realm, RealmAuth auth, EventBuilder event) {
super(realm);
this.realm = realm;
this.auth = auth;
this.event = event;
}
/**
@@ -52,6 +63,12 @@ public class RoleByIdResource extends RoleResource {
public RoleRepresentation getRole(final @PathParam("role-id") String id) {
RoleModel roleModel = getRoleModel(id);
auth.requireView();
event.event(EventType.VIEW_ROLE)
.detail(Details.ROLE_ID, roleModel.getId())
.detail(Details.ROLE_NAME, roleModel.getName())
.success();
return getRole(roleModel);
}
@@ -88,6 +105,11 @@ public class RoleByIdResource extends RoleResource {
RoleModel role = getRoleModel(id);
auth.requireManage();
deleteRole(role);
event.event(EventType.DELETE_ROLE)
.detail(Details.ROLE_ID, role.getId())
.detail(Details.ROLE_NAME, role.getName())
.success();
}
/**
@@ -103,6 +125,11 @@ public class RoleByIdResource extends RoleResource {
RoleModel role = getRoleModel(id);
auth.requireManage();
updateRole(rep, role);
event.event(EventType.UPDATE_ROLE)
.detail(Details.ROLE_ID, role.getId())
.detail(Details.ROLE_NAME, role.getName())
.success();
}
/**
@@ -118,6 +145,11 @@ public class RoleByIdResource extends RoleResource {
RoleModel role = getRoleModel(id);
auth.requireManage();
addComposites(roles, role);
event.event(EventType.MAKE_ROLE_COMPOSITE)
.detail(Details.ROLE_ID, role.getId())
.detail(Details.ROLE_NAME, role.getName())
.success();
}
/**
@@ -2,6 +2,9 @@ package org.keycloak.services.resources.admin;
import org.jboss.resteasy.annotations.cache.NoCache;
import org.jboss.resteasy.spi.NotFoundException;
import org.keycloak.events.Details;
import org.keycloak.events.EventBuilder;
import org.keycloak.events.EventType;
import org.keycloak.models.ApplicationModel;
import org.keycloak.models.ModelDuplicateException;
import org.keycloak.models.RealmModel;
@@ -22,6 +25,7 @@ import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
@@ -34,12 +38,14 @@ public class RoleContainerResource extends RoleResource {
private final RealmModel realm;
private final RealmAuth auth;
protected RoleContainerModel roleContainer;
private EventBuilder event;
public RoleContainerResource(RealmModel realm, RealmAuth auth, RoleContainerModel roleContainer) {
public RoleContainerResource(RealmModel realm, RealmAuth auth, RoleContainerModel roleContainer, EventBuilder event) {
super(realm);
this.realm = realm;
this.auth = auth;
this.roleContainer = roleContainer;
this.event = event;
}
/**
@@ -58,6 +64,9 @@ public class RoleContainerResource extends RoleResource {
for (RoleModel roleModel : roleModels) {
roles.add(ModelToRepresentation.toRepresentation(roleModel));
}
event.event(EventType.VIEW_ROLES).success();
return roles;
}
@@ -76,6 +85,12 @@ public class RoleContainerResource extends RoleResource {
try {
RoleModel role = roleContainer.addRole(rep.getName());
role.setDescription(rep.getDescription());
event.event(EventType.CREATE_ROLE)
.detail(Details.ROLE_ID, role.getId())
.detail(Details.ROLE_NAME, role.getName())
.success();
return Response.created(uriInfo.getAbsolutePathBuilder().path(role.getName()).build()).build();
} catch (ModelDuplicateException e) {
return Flows.errors().exists("Role with name " + rep.getName() + " already exists");
@@ -99,6 +114,12 @@ public class RoleContainerResource extends RoleResource {
if (roleModel == null) {
throw new NotFoundException("Could not find role: " + roleName);
}
event.event(EventType.VIEW_ROLE)
.detail(Details.ROLE_ID, roleModel.getId())
.detail(Details.ROLE_NAME, roleModel.getName())
.success();
return getRole(roleModel);
}
@@ -118,6 +139,11 @@ public class RoleContainerResource extends RoleResource {
throw new NotFoundException("Could not find role: " + roleName);
}
deleteRole(role);
event.event(EventType.DELETE_ROLE)
.detail(Details.ROLE_ID, role.getId())
.detail(Details.ROLE_NAME, role.getName())
.success();
}
/**
@@ -139,6 +165,12 @@ public class RoleContainerResource extends RoleResource {
}
try {
updateRole(rep, role);
event.event(EventType.UPDATE_ROLE)
.detail(Details.ROLE_ID, role.getId())
.detail(Details.ROLE_NAME, role.getName())
.success();
return Response.noContent().build();
} catch (ModelDuplicateException e) {
return Flows.errors().exists("Role with name " + rep.getName() + " already exists");
@@ -3,7 +3,10 @@ package org.keycloak.services.resources.admin;
import org.keycloak.Version;
import org.keycloak.broker.provider.IdentityProvider;
import org.keycloak.broker.provider.IdentityProviderFactory;
import org.keycloak.events.Details;
import org.keycloak.events.EventBuilder;
import org.keycloak.events.EventListenerProvider;
import org.keycloak.events.EventType;
import org.keycloak.exportimport.ApplicationImporter;
import org.keycloak.exportimport.ApplicationImporterFactory;
import org.keycloak.freemarker.Theme;
@@ -23,6 +26,7 @@ import org.keycloak.social.SocialIdentityProvider;
import javax.ws.rs.GET;
import javax.ws.rs.core.Context;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
@@ -40,7 +44,13 @@ public class ServerInfoAdminResource {
@Context
private KeycloakSession session;
private EventBuilder event;
public ServerInfoAdminResource(EventBuilder event) {
this.event = event;
}
/**
* Returns a list of themes, social providers, auth providers, and event listeners available on this server
*
@@ -60,6 +70,12 @@ public class ServerInfoAdminResource {
setProviders(info);
setProtocolMapperTypes(info);
setBuiltinProtocolMappers(info);
event.event(EventType.VIEW_SERVER_INFO)
.detail(Details.SERVER_VERSION, info.version)
.detail(Details.SERVER_TIME, info.serverTime)
.success();
return info;
}
@@ -11,6 +11,9 @@ import org.keycloak.models.UserFederationProvider;
import org.keycloak.models.UserFederationProviderFactory;
import org.keycloak.models.UserFederationProviderModel;
import org.keycloak.constants.KerberosConstants;
import org.keycloak.events.Details;
import org.keycloak.events.EventBuilder;
import org.keycloak.events.EventType;
import org.keycloak.models.utils.ModelToRepresentation;
import org.keycloak.provider.ProviderFactory;
import org.keycloak.representations.idm.UserFederationProviderFactoryRepresentation;
@@ -30,6 +33,7 @@ import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import java.util.LinkedList;
import java.util.List;
@@ -45,16 +49,19 @@ public class UserFederationResource {
protected RealmModel realm;
protected RealmAuth auth;
private EventBuilder event;
@Context
protected UriInfo uriInfo;
@Context
protected KeycloakSession session;
public UserFederationResource(RealmModel realm, RealmAuth auth) {
public UserFederationResource(RealmModel realm, RealmAuth auth, EventBuilder event) {
this.auth = auth;
this.realm = realm;
this.event = event;
auth.init(RealmAuth.Resource.USER);
}
@@ -77,11 +84,14 @@ public class UserFederationResource {
rep.setOptions(((UserFederationProviderFactory)factory).getConfigurationOptions());
providers.add(rep);
}
event.event(EventType.VIEW_PROVIDER_FACTORIES).success();
return providers;
}
/**
* Get List of available provider factories
* Get a provider
*
* @return
*/
@@ -98,6 +108,9 @@ public class UserFederationResource {
UserFederationProviderFactoryRepresentation rep = new UserFederationProviderFactoryRepresentation();
rep.setId(factory.getId());
rep.setOptions(((UserFederationProviderFactory)factory).getConfigurationOptions());
event.event(EventType.VIEW_PROVIDER).detail(Details.PROVIDER_ID, rep.getId()).success();
return rep;
}
throw new NotFoundException("Could not find provider");
@@ -122,7 +135,12 @@ public class UserFederationResource {
rep.getFullSyncPeriod(), rep.getChangedSyncPeriod(), rep.getLastSync());
new UsersSyncManager().refreshPeriodicSyncForProvider(session.getKeycloakSessionFactory(), session.getProvider(TimerProvider.class), model, realm.getId());
checkKerberosCredential(model);
event.event(EventType.CREATE_PROVIDER)
.detail(Details.PROVIDER_ID, model.getId())
.detail(Details.PROVIDER_NAME, model.getProviderName())
.success();
return Response.created(uriInfo.getAbsolutePathBuilder().path(model.getId()).build()).build();
}
@@ -146,6 +164,11 @@ public class UserFederationResource {
realm.updateUserFederationProvider(model);
new UsersSyncManager().refreshPeriodicSyncForProvider(session.getKeycloakSessionFactory(), session.getProvider(TimerProvider.class), model, realm.getId());
checkKerberosCredential(model);
event.event(EventType.UPDATE_PROVIDER)
.detail(Details.PROVIDER_ID, model.getId())
.detail(Details.PROVIDER_NAME, model.getProviderName())
.success();
}
/**
@@ -161,9 +184,16 @@ public class UserFederationResource {
auth.requireView();
for (UserFederationProviderModel model : realm.getUserFederationProviders()) {
if (model.getId().equals(id)) {
event.event(EventType.VIEW_PROVIDER)
.detail(Details.PROVIDER_ID, model.getId())
.detail(Details.PROVIDER_NAME, model.getProviderName())
.success();
return ModelToRepresentation.toRepresentation(model);
}
}
throw new NotFoundException("could not find provider");
}
@@ -179,6 +209,11 @@ public class UserFederationResource {
UserFederationProviderModel model = new UserFederationProviderModel(id, null, null, -1, null, -1, -1, 0);
realm.removeUserFederationProvider(model);
new UsersSyncManager().removePeriodicSyncForProvider(session.getProvider(TimerProvider.class), model);
event.event(EventType.DELETE_PROVIDER)
.detail(Details.PROVIDER_ID, model.getId())
.detail(Details.PROVIDER_NAME, model.getProviderName())
.success();
}
@@ -7,6 +7,9 @@ import org.jboss.resteasy.spi.NotFoundException;
import org.keycloak.ClientConnection;
import org.keycloak.email.EmailException;
import org.keycloak.email.EmailProvider;
import org.keycloak.events.Details;
import org.keycloak.events.EventBuilder;
import org.keycloak.events.EventType;
import org.keycloak.models.ApplicationModel;
import org.keycloak.models.ClientModel;
import org.keycloak.models.ClientSessionModel;
@@ -24,7 +27,6 @@ import org.keycloak.models.UserSessionModel;
import org.keycloak.models.utils.ModelToRepresentation;
import org.keycloak.models.utils.RepresentationToModel;
import org.keycloak.protocol.oidc.OIDCLoginProtocol;
import org.keycloak.protocol.oidc.OIDCLoginProtocolService;
import org.keycloak.protocol.oidc.TokenManager;
import org.keycloak.protocol.oidc.utils.RedirectUtils;
import org.keycloak.representations.idm.ApplicationMappingsRepresentation;
@@ -57,6 +59,7 @@ import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriBuilder;
import javax.ws.rs.core.UriInfo;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
@@ -79,6 +82,8 @@ public class UsersResource {
private RealmAuth auth;
private TokenManager tokenManager;
private EventBuilder event;
@Context
protected ClientConnection clientConnection;
@@ -91,11 +96,12 @@ public class UsersResource {
@Context
protected HttpHeaders headers;
public UsersResource(RealmModel realm, RealmAuth auth, TokenManager tokenManager) {
public UsersResource(RealmModel realm, RealmAuth auth, TokenManager tokenManager, EventBuilder event) {
this.auth = auth;
this.realm = realm;
this.tokenManager = tokenManager;
this.event = event;
auth.init(RealmAuth.Resource.USER);
}
@@ -120,10 +126,15 @@ public class UsersResource {
}
updateUserFromRep(user, rep);
event.event(EventType.UPDATE_USER)
.user(user)
.detail(Details.USERNAME, user.getUsername())
.success();
if (session.getTransaction().isActive()) {
session.getTransaction().commit();
}
return Response.noContent().build();
} catch (ModelDuplicateException e) {
return Flows.errors().exists("User exists with same username or email");
@@ -155,11 +166,16 @@ public class UsersResource {
try {
UserModel user = session.users().addUser(realm, rep.getUsername());
updateUserFromRep(user, rep);
event.event(EventType.CREATE_USER)
.user(user)
.detail(Details.USERNAME, user.getUsername())
.success();
if (session.getTransaction().isActive()) {
session.getTransaction().commit();
}
return Response.created(uriInfo.getAbsolutePathBuilder().path(user.getUsername()).build()).build();
} catch (ModelDuplicateException e) {
if (session.getTransaction().isActive()) {
@@ -220,6 +236,12 @@ public class UsersResource {
if (user == null) {
throw new NotFoundException("User not found");
}
event.event(EventType.VIEW_USER)
.user(user)
.detail(Details.USERNAME, user.getUsername())
.success();
return ModelToRepresentation.toRepresentation(user);
}
@@ -245,6 +267,12 @@ public class UsersResource {
UserSessionRepresentation rep = ModelToRepresentation.toRepresentation(session);
reps.add(rep);
}
event.event(EventType.VIEW_USER_SESSIONS)
.user(user)
.detail(Details.USERNAME, user.getUsername())
.success();
return reps;
}
@@ -276,6 +304,12 @@ public class UsersResource {
}
}
}
event.event(EventType.VIEW_USER_SOCIAL_LOGINS)
.user(user)
.detail(Details.USERNAME, user.getUsername())
.success();
return result;
}
@@ -326,10 +360,16 @@ public class UsersResource {
if (user == null) {
throw new NotFoundException("User not found");
}
List<UserSessionModel> userSessions = session.sessions().getUserSessions(realm, user);
for (UserSessionModel userSession : userSessions) {
AuthenticationManager.backchannelLogout(session, realm, userSession, uriInfo, clientConnection, headers);
}
event.event(EventType.INVALIDATE_USER_SESSIONS)
.user(user)
.detail(Details.USERNAME, user.getUsername())
.success();
}
/**
@@ -350,6 +390,12 @@ public class UsersResource {
boolean removed = new UserManager(session).removeUser(realm, user);
if (removed) {
event.event(EventType.DELETE_USER)
.user(user)
.detail(Details.USERNAME, user.getUsername())
.success();
return Response.noContent().build();
} else {
return Flows.errors().error("User couldn't be deleted", Response.Status.BAD_REQUEST);