/*******************************************************************************
* 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 java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.jmx.export.annotation.ManagedMetric;
import org.springframework.jmx.export.annotation.ManagedResource;
import org.springframework.jmx.support.MetricType;
/**
* Audit service implementation which just outputs the relevant information
* through the logger.
* <p>
* Also accumulates count data for exposure through /varz
*
* @author Luke Taylor
* @author Dave Syer
*/
@ManagedResource
public class LoggingAuditService implements UaaAuditService {
private final Log logger = LogFactory.getLog("UAA.Audit");
private AtomicInteger userAuthenticationCount = new AtomicInteger();
private AtomicInteger userAuthenticationFailureCount = new AtomicInteger();
private AtomicInteger clientAuthenticationCount = new AtomicInteger();
private AtomicInteger clientAuthenticationFailureCount = new AtomicInteger();
private AtomicInteger principalAuthenticationFailureCount = new AtomicInteger();
private AtomicInteger userNotFoundCount = new AtomicInteger();
private AtomicInteger principalNotFoundCount = new AtomicInteger();
private AtomicInteger passwordChanges = new AtomicInteger();
private AtomicInteger passwordFailures = new AtomicInteger();
@ManagedMetric(metricType = MetricType.COUNTER, displayName = "User Not Found Count")
public int getUserNotFoundCount() {
return userNotFoundCount.get();
}
@ManagedMetric(metricType = MetricType.COUNTER, displayName = "User Successful Authentication Count")
public int getUserAuthenticationCount() {
return userAuthenticationCount.get();
}
@ManagedMetric(metricType = MetricType.COUNTER, displayName = "User Authentication Failure Count")
public int getUserAuthenticationFailureCount() {
return userAuthenticationFailureCount.get();
}
@ManagedMetric(metricType = MetricType.COUNTER, displayName = "Client Successful Authentication Count")
public int getClientAuthenticationCount() {
return clientAuthenticationCount.get();
}
@ManagedMetric(metricType = MetricType.COUNTER, displayName = "Client Authentication Failure Count")
public int getClientAuthenticationFailureCount() {
return clientAuthenticationFailureCount.get();
}
@ManagedMetric(metricType = MetricType.COUNTER, displayName = "Principal (non-user) Authentication Failure Count")
public int getPrincipalAuthenticationFailureCount() {
return principalAuthenticationFailureCount.get();
}
@ManagedMetric(metricType = MetricType.COUNTER, displayName = "Principal (non-user) Not Found Count")
public int getPrincipalNotFoundCount() {
return principalNotFoundCount.get();
}
@ManagedMetric(metricType = MetricType.COUNTER, displayName = "User Password Change Count (Since Startup)")
public int getUserPasswordChanges() {
return passwordChanges.get();
}
@ManagedMetric(metricType = MetricType.COUNTER, displayName = "User Password Change Failure Count (Since Startup)")
public int getUserPasswordFailures() {
return passwordFailures.get();
}
@Override
public List<AuditEvent> find(String principal, long after) {
throw new UnsupportedOperationException("This implementation does not store data");
}
@Override
public void log(AuditEvent auditEvent) {
updateCounters(auditEvent);
log(String.format("%s ('%s'): principal=%s, origin=[%s], identityZoneId=[%s]", auditEvent.getType().name(), auditEvent.getData(),
auditEvent.getPrincipalId(), auditEvent.getOrigin(), auditEvent.getIdentityZoneId()));
}
private void updateCounters(AuditEvent auditEvent) {
switch (auditEvent.getType()) {
case PasswordChangeSuccess:
passwordChanges.incrementAndGet();
break;
case PasswordChangeFailure:
passwordFailures.incrementAndGet();
break;
case UserAuthenticationSuccess:
userAuthenticationCount.incrementAndGet();
break;
case UserAuthenticationFailure:
userAuthenticationFailureCount.incrementAndGet();
break;
case ClientAuthenticationSuccess:
clientAuthenticationCount.incrementAndGet();
break;
case ClientAuthenticationFailure:
clientAuthenticationFailureCount.incrementAndGet();
break;
case UserNotFound:
userNotFoundCount.incrementAndGet();
break;
case PrincipalAuthenticationFailure:
principalAuthenticationFailureCount.incrementAndGet();
break;
case PrincipalNotFound:
principalNotFoundCount.incrementAndGet();
break;
default:
break;
}
}
private void log(String msg) {
if (logger.isTraceEnabled()) {
StringBuilder output = new StringBuilder(256);
output.append("\n************************************************************\n");
output.append(msg);
output.append("\n\n************************************************************\n");
logger.trace(output.toString());
}
else {
logger.info(msg);
}
}
}