/******************************************************************************* * Cloud Foundry * Copyright (c) [2009-2016] Pivotal Software, Inc. All Rights Reserved. * * This product is licensed to you under the Apache License, Version 2.0 (the "License"). * You may not use this product except in compliance with the License. * * This product includes a number of subcomponents with * separate copyright notices and license terms. Your use of these * subcomponents is subject to the terms and conditions of the * subcomponent's license, as noted in the LICENSE file. *******************************************************************************/ package org.cloudfoundry.identity.uaa.audit; import org.cloudfoundry.identity.uaa.util.TimeService; import org.cloudfoundry.identity.uaa.util.TimeServiceImpl; import org.springframework.jdbc.core.JdbcTemplate; import java.sql.Timestamp; import java.util.concurrent.atomic.AtomicLong; /** * An audit service that subscribes to audit events but only saves enough data * to answer queries about consecutive * failed logins. */ public class JdbcFailedLoginCountingAuditService extends JdbcAuditService { private int saveDataPeriodMillis = 24 * 3600 * 1000; // 24hr private long timeBetweenDeleteMillis = 1000*30; private AtomicLong lastDelete = new AtomicLong(0); private TimeService timeService = new TimeServiceImpl(); public JdbcFailedLoginCountingAuditService(JdbcTemplate template) { super(template); } /** * @param saveDataPeriodMillis the period in milliseconds to set */ public void setSaveDataPeriodMillis(int saveDataPeriodMillis) { this.saveDataPeriodMillis = saveDataPeriodMillis; } public void setTimeService(TimeService timeService) { this.timeService = timeService; } @Override public void log(AuditEvent auditEvent) { switch (auditEvent.getType()) { case UserAuthenticationSuccess: case PasswordChangeSuccess: case UserAccountUnlockedEvent: getJdbcTemplate().update("delete from sec_audit where principal_id=?", auditEvent.getPrincipalId()); break; case UserAuthenticationFailure: periodicDelete(); super.log(auditEvent); break; default: break; } } protected void periodicDelete() { long now = timeService.getCurrentTimeMillis(); long lastCheck = lastDelete.get(); if (now - lastCheck > timeBetweenDeleteMillis && lastDelete.compareAndSet(lastCheck, now)) { getJdbcTemplate().update("delete from sec_audit where created < ?", new Timestamp(System.currentTimeMillis() - saveDataPeriodMillis)); } } }