Allow clearing audit events through admin console, and added timer to clear expired events
This commit is contained in:
parent
9bc0bd452d
commit
7f0cf3eda8
18 changed files with 279 additions and 8 deletions
|
@ -1028,10 +1028,6 @@ module.controller('RealmAuditCtrl', function($scope, auditConfig, RealmAudit, Re
|
|||
$scope.auditConfig = auditConfig;
|
||||
|
||||
$scope.auditConfig.expirationUnit = TimeUnit.autoUnit(auditConfig.auditExpiration);
|
||||
if ($scope.auditConfig.expirationUnit) {
|
||||
$scope.auditConfig.expirationUnit = 'Hours';
|
||||
}
|
||||
|
||||
$scope.auditConfig.auditExpiration = TimeUnit.toUnit(auditConfig.auditExpiration, $scope.auditConfig.expirationUnit);
|
||||
$scope.$watch('auditConfig.expirationUnit', function(to, from) {
|
||||
if ($scope.auditConfig.auditExpiration) {
|
||||
|
|
|
@ -696,6 +696,10 @@ module.factory('TimeUnit', function() {
|
|||
var t = {};
|
||||
|
||||
t.autoUnit = function(time) {
|
||||
if (!time) {
|
||||
return 'Hours';
|
||||
}
|
||||
|
||||
var unit = 'Seconds';
|
||||
if (time % 60 == 0) {
|
||||
unit = 'Minutes';
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
</div>
|
||||
<div class="col-sm-2 select-kc">
|
||||
<select name="expirationUnit" data-ng-model="auditConfig.expirationUnit" >
|
||||
<option>Minutes</option>
|
||||
<option>Hours</option>
|
||||
<option>Days</option>
|
||||
</select>
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package org.keycloak.models;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
|
||||
|
@ -12,7 +13,9 @@ public class Config {
|
|||
|
||||
public static final String MODEL_PROVIDER_KEY = "keycloak.model";
|
||||
|
||||
public static final String MODEL_AUDIT_KEY = "keycloak.audit";
|
||||
public static final String AUDIT_KEY = "keycloak.audit";
|
||||
public static final String AUDIT_EXPIRATION_SCHEDULE_KEY = "keycloak.audit.expirationSchedule";
|
||||
public static final String AUDIT_EXPIRATION_SCHEDULE_DEFAULT = String.valueOf(TimeUnit.MINUTES.toMillis(15));
|
||||
|
||||
public static final String THEME_BASE_KEY = "keycloak.theme.base";
|
||||
public static final String THEME_BASE_DEFAULT = "base";
|
||||
|
@ -21,6 +24,9 @@ public class Config {
|
|||
public static final String THEME_DIR_KEY = "keycloak.theme.dir";
|
||||
public static final String JBOSS_SERVER_CONFIG_DIR_KEY = "jboss.server.config.dir";
|
||||
|
||||
public static final String TIMER_PROVIDER_KEY = "keycloak.timer";
|
||||
public static final String TIMER_PROVIDER_DEFAULT = "basic";
|
||||
|
||||
public static String getAdminRealm() {
|
||||
return System.getProperty(ADMIN_REALM_KEY, ADMIN_REALM_DEFAULT);
|
||||
}
|
||||
|
@ -30,13 +36,21 @@ public class Config {
|
|||
}
|
||||
|
||||
public static String getAuditProvider() {
|
||||
return System.getProperty(MODEL_PROVIDER_KEY, "jpa");
|
||||
return System.getProperty(AUDIT_KEY);
|
||||
}
|
||||
|
||||
public static void setAuditProvider(String provider) {
|
||||
System.setProperty(MODEL_PROVIDER_KEY, provider);
|
||||
}
|
||||
|
||||
public static String getAuditExpirationSchedule() {
|
||||
return System.getProperty(AUDIT_EXPIRATION_SCHEDULE_KEY, AUDIT_EXPIRATION_SCHEDULE_DEFAULT);
|
||||
}
|
||||
|
||||
public static void setAuditExpirationSchedule(String schedule) {
|
||||
System.setProperty(AUDIT_EXPIRATION_SCHEDULE_KEY, schedule);
|
||||
}
|
||||
|
||||
public static String getModelProvider() {
|
||||
return System.getProperty(MODEL_PROVIDER_KEY);
|
||||
}
|
||||
|
@ -45,6 +59,14 @@ public class Config {
|
|||
System.setProperty(MODEL_PROVIDER_KEY, provider);
|
||||
}
|
||||
|
||||
public static String getTimerProvider() {
|
||||
return System.getProperty(TIMER_PROVIDER_KEY, TIMER_PROVIDER_DEFAULT);
|
||||
}
|
||||
|
||||
public static void setTimerProvider(String provider) {
|
||||
System.setProperty(TIMER_PROVIDER_KEY, provider);
|
||||
}
|
||||
|
||||
public static String getThemeDir() {
|
||||
String themeDir = System.getProperty(THEME_DIR_KEY);
|
||||
if (themeDir == null && System.getProperties().containsKey(JBOSS_SERVER_CONFIG_DIR_KEY)) {
|
||||
|
|
1
pom.xml
1
pom.xml
|
@ -98,6 +98,7 @@
|
|||
<module>testsuite</module>
|
||||
<module>server</module>
|
||||
<module>spi</module>
|
||||
<module>timer</module>
|
||||
</modules>
|
||||
|
||||
<dependencyManagement>
|
||||
|
|
|
@ -142,6 +142,18 @@
|
|||
<artifactId>keycloak-authentication-picketlink</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-timer-api</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-timer-basic</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
|
|
|
@ -69,6 +69,18 @@
|
|||
<version>${project.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-timer-api</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-timer-basic</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-authentication-spi</artifactId>
|
||||
|
|
|
@ -170,7 +170,7 @@ public class RealmManager {
|
|||
|
||||
public void updateRealmAudit(RealmAuditRepresentation rep, RealmModel realm) {
|
||||
realm.setAuditEnabled(rep.isAuditEnabled());
|
||||
realm.setAuditExpiration(rep.getAuditExpiration());
|
||||
realm.setAuditExpiration(rep.getAuditExpiration() != null ? rep.getAuditExpiration() : 0);
|
||||
if (rep.getAuditListeners() != null) {
|
||||
realm.setAuditListeners(new HashSet<String>(rep.getAuditListeners()));
|
||||
}
|
||||
|
|
|
@ -7,11 +7,16 @@ import org.keycloak.audit.AuditListenerFactory;
|
|||
import org.keycloak.audit.AuditProvider;
|
||||
import org.keycloak.audit.AuditProviderFactory;
|
||||
import org.keycloak.models.Config;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.KeycloakSessionFactory;
|
||||
import org.keycloak.models.ModelProvider;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.provider.ProviderFactory;
|
||||
import org.keycloak.provider.ProviderFactoryLoader;
|
||||
import org.keycloak.services.DefaultProviderSessionFactory;
|
||||
import org.keycloak.services.ProviderSessionFactory;
|
||||
import org.keycloak.timer.TimerProvider;
|
||||
import org.keycloak.timer.TimerProviderFactory;
|
||||
import org.keycloak.util.KeycloakRegistry;
|
||||
import org.keycloak.services.managers.ApplianceBootstrap;
|
||||
import org.keycloak.services.managers.SocialRequestManager;
|
||||
|
@ -24,6 +29,7 @@ import javax.ws.rs.core.Application;
|
|||
import javax.ws.rs.core.Context;
|
||||
import javax.ws.rs.core.UriInfo;
|
||||
import java.net.URI;
|
||||
import java.util.Date;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
|
@ -49,7 +55,9 @@ public class KeycloakApplication extends Application {
|
|||
context.setAttribute(KeycloakRegistry.class.getName(), registry);
|
||||
//classes.add(KeycloakSessionCleanupFilter.class);
|
||||
|
||||
context.setAttribute(ProviderSessionFactory.class.getName(), createProviderSessionFactory());
|
||||
DefaultProviderSessionFactory providerSessionFactory = createProviderSessionFactory();
|
||||
|
||||
context.setAttribute(ProviderSessionFactory.class.getName(), providerSessionFactory);
|
||||
|
||||
TokenManager tokenManager = new TokenManager();
|
||||
SocialRequestManager socialRequestManager = new SocialRequestManager();
|
||||
|
@ -62,6 +70,8 @@ public class KeycloakApplication extends Application {
|
|||
classes.add(ThemeResource.class);
|
||||
|
||||
setupDefaultRealm(context.getContextPath());
|
||||
|
||||
setupScheduledTasks(providerSessionFactory, factory);
|
||||
}
|
||||
|
||||
public String getContextPath() {
|
||||
|
@ -99,10 +109,45 @@ public class KeycloakApplication extends Application {
|
|||
|
||||
factory.registerLoader(AuditProvider.class, ProviderFactoryLoader.create(AuditProviderFactory.class), Config.getAuditProvider());
|
||||
factory.registerLoader(AuditListener.class, ProviderFactoryLoader.create(AuditListenerFactory.class));
|
||||
factory.registerLoader(TimerProvider.class, ProviderFactoryLoader.create(TimerProviderFactory.class), Config.getTimerProvider());
|
||||
|
||||
return factory;
|
||||
}
|
||||
|
||||
public static void setupScheduledTasks(final ProviderSessionFactory providerSessionFactory, final KeycloakSessionFactory keycloakSessionFactory) {
|
||||
ProviderFactory<TimerProvider> timerFactory = providerSessionFactory.getProviderFactory(TimerProvider.class);
|
||||
if (timerFactory == null) {
|
||||
log.error("Can't setup schedule tasks, no timer provider found");
|
||||
return;
|
||||
}
|
||||
TimerProvider timer = timerFactory.create();
|
||||
|
||||
final ProviderFactory<AuditProvider> auditFactory = providerSessionFactory.getProviderFactory(AuditProvider.class);
|
||||
if (auditFactory != null) {
|
||||
timer.schedule(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
KeycloakSession keycloakSession = keycloakSessionFactory.createSession();
|
||||
AuditProvider audit = providerSessionFactory.getProviderFactory(AuditProvider.class).create();
|
||||
try {
|
||||
for (RealmModel realm : keycloakSession.getRealms()) {
|
||||
if (realm.isAuditEnabled() && realm.getAuditExpiration() > 0) {
|
||||
long olderThan = System.currentTimeMillis() - realm.getAuditExpiration() * 1000;
|
||||
log.info("Expiring audit events for " + realm.getName() + " older than " + new Date(olderThan));
|
||||
audit.clear(realm.getId(), olderThan);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
keycloakSession.close();
|
||||
audit.close();
|
||||
}
|
||||
}
|
||||
}, Config.getAuditExpirationSchedule());
|
||||
} else {
|
||||
log.info("Not scheduling audit expiration, no audit provider found");
|
||||
}
|
||||
}
|
||||
|
||||
public KeycloakSessionFactory getFactory() {
|
||||
return factory;
|
||||
}
|
||||
|
|
|
@ -72,6 +72,16 @@
|
|||
<artifactId>keycloak-model-jpa</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-timer-api</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-timer-basic</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-js-adapter</artifactId>
|
||||
|
|
22
timer/api/pom.xml
Executable file
22
timer/api/pom.xml
Executable file
|
@ -0,0 +1,22 @@
|
|||
<?xml version="1.0"?>
|
||||
<project>
|
||||
<parent>
|
||||
<artifactId>keycloak-timer-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>1.0-beta-1-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>keycloak-timer-api</artifactId>
|
||||
<name>Keycloak Timer API</name>
|
||||
<description/>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-core</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
|
@ -0,0 +1,12 @@
|
|||
package org.keycloak.timer;
|
||||
|
||||
import org.keycloak.provider.Provider;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
|
||||
*/
|
||||
public interface TimerProvider extends Provider {
|
||||
|
||||
public void schedule(Runnable runnable, String config);
|
||||
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
package org.keycloak.timer;
|
||||
|
||||
import org.keycloak.provider.ProviderFactory;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
|
||||
*/
|
||||
public interface TimerProviderFactory extends ProviderFactory<TimerProvider> {
|
||||
}
|
23
timer/basic/pom.xml
Executable file
23
timer/basic/pom.xml
Executable file
|
@ -0,0 +1,23 @@
|
|||
<?xml version="1.0"?>
|
||||
<project>
|
||||
<parent>
|
||||
<artifactId>keycloak-timer-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>1.0-beta-1-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>keycloak-timer-basic</artifactId>
|
||||
<name>Keycloak Timer Basic Provider</name>
|
||||
<description/>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-timer-api</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
|
@ -0,0 +1,39 @@
|
|||
package org.keycloak.timer.basic;
|
||||
|
||||
import org.keycloak.timer.TimerProvider;
|
||||
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
|
||||
*/
|
||||
public class BasicTimerProvider implements TimerProvider {
|
||||
|
||||
private Timer timer;
|
||||
|
||||
public BasicTimerProvider(Timer timer) {
|
||||
|
||||
this.timer = timer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void schedule(final Runnable runnable, String config) {
|
||||
long interval = Long.parseLong(config);
|
||||
|
||||
TimerTask task = new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
runnable.run();
|
||||
}
|
||||
};
|
||||
|
||||
timer.schedule(task, interval, interval);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
package org.keycloak.timer.basic;
|
||||
|
||||
import org.keycloak.timer.TimerProvider;
|
||||
import org.keycloak.timer.TimerProviderFactory;
|
||||
|
||||
import java.util.Timer;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
|
||||
*/
|
||||
public class BasicTimerProviderFactory implements TimerProviderFactory {
|
||||
|
||||
private Timer timer;
|
||||
|
||||
@Override
|
||||
public TimerProvider create() {
|
||||
return new BasicTimerProvider(timer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
timer = new Timer();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
timer.cancel();
|
||||
timer = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return "basic";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean lazyLoad() {
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
org.keycloak.timer.basic.BasicTimerProviderFactory
|
22
timer/pom.xml
Executable file
22
timer/pom.xml
Executable file
|
@ -0,0 +1,22 @@
|
|||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>1.0-beta-1-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<name>Keycloak Timer Parent</name>
|
||||
<description/>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-timer-parent</artifactId>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<modules>
|
||||
<module>api</module>
|
||||
<module>basic</module>
|
||||
</modules>
|
||||
</project>
|
Loading…
Reference in a new issue