/* * Copyright (C) 2015 Red Hat, inc., and individual contributors * as indicated by the @author tags. See the copyright.txt file in the * distribution for a full listing of individual contributors. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA */ package org.jboss.as.controller.audit; import static org.jboss.as.controller.audit.AuditLogItemFormatter.TYPE_JMX; import static org.jboss.as.controller.audit.JsonAuditLogItemFormatter.AS_VERSION; import static org.jboss.as.controller.audit.JsonAuditLogItemFormatter.ERROR; import static org.jboss.as.controller.audit.JsonAuditLogItemFormatter.METHOD_NAME; import static org.jboss.as.controller.audit.JsonAuditLogItemFormatter.METHOD_PARAMETERS; import static org.jboss.as.controller.audit.JsonAuditLogItemFormatter.METHOD_SIGNATURE; import static org.jboss.as.controller.audit.JsonAuditLogItemFormatter.REMOTE_ADDRESS; import static org.jboss.as.controller.audit.JsonAuditLogItemFormatter.TYPE; import static org.jboss.as.controller.audit.JsonAuditLogItemFormatter.USER_ID; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.ACCESS_MECHANISM; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.DOMAIN_UUID; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.FAILED; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.OPERATIONS; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.OUTCOME; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.READ_ONLY; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.SUCCESS; import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.List; import org.jboss.as.controller.OperationContext; import org.jboss.dmr.ModelNode; /** * * @author <a href="mailto:ehugonne@redhat.com">Emmanuel Hugonnet</a> (c) 2015 Red Hat, inc. */ public final class InMemoryAuditLogHander extends AuditLogHandler { public static final String OPERATION_DATE = "operation-date"; private static final ModelNode UNDEFINED = new ModelNode(); static { UNDEFINED.protect(); } private static final String IN_MEMORY_FORMATTER_NAME = "in-memory-formatter"; private final List<ModelNode> items; private int maxHistory; private final AuditLogItemFormatter myFormatter = new InMemoryFormatter(); public InMemoryAuditLogHander(String name, int maxHistory) { super(name, IN_MEMORY_FORMATTER_NAME, maxHistory); this.items = new ArrayList<>(maxHistory); this.maxHistory = maxHistory; setFormatter(myFormatter); } @Override public List<ModelNode> listLastEntries() { return Collections.unmodifiableList(items); } public void setMaxHistory(int maxHistory) { this.maxHistory = maxHistory; while (maxHistory < items.size()) { items.remove(0); } } @Override void setFormatter(AuditLogItemFormatter formatter) { super.setFormatter(myFormatter); } public AuditLogItemFormatter getFormatter() { return myFormatter; } @Override boolean isDifferent(AuditLogHandler other) { if (other instanceof InMemoryAuditLogHander == false) { return true; } return getName().equals(other.getName()); } private void addItem(ModelNode item) { if (items.size() == maxHistory) { items.remove(0); } items.add(item); } @Override void initialize() { } @Override void stop() { items.clear(); } @Override void writeLogItem(String formattedItem) throws IOException { } private class InMemoryFormatter extends AuditLogItemFormatter { public static final String BOOTING = "booting"; public InMemoryFormatter() { super(IN_MEMORY_FORMATTER_NAME, true, "", "yyyy-MM-dd hh:mm:ss"); } @Override String formatAuditLogItem(AuditLogItem.ModelControllerAuditLogItem item) { ModelNode entry = new ModelNode().setEmptyObject(); entry.get(TYPE).set(TYPE_CORE); addCommonFields(entry, item); entry.get(OUTCOME).set(item.getResultAction() == OperationContext.ResultAction.KEEP ? SUCCESS : FAILED); if (item.getOperations() != null && !item.getOperations().isEmpty()) { ModelNode operations = entry.get(OPERATIONS).setEmptyList(); item.getOperations().stream().forEach((op) -> { operations.add(op); }); } addItem(entry); return entry.asString(); } @Override String formatAuditLogItem(AuditLogItem.JmxAccessAuditLogItem item) { ModelNode entry = new ModelNode(); entry.get(TYPE).set(TYPE_JMX); addCommonFields(entry, item); entry.get(METHOD_NAME).set(item.getMethodName()); entry.get(METHOD_SIGNATURE); for (String sig : item.getMethodSignature()) { entry.get(METHOD_SIGNATURE).add(sig); } entry.get(METHOD_PARAMETERS); for (Object param : item.getMethodParams()) { //TODO handle arrays better entry.get(METHOD_PARAMETERS).add(param == null ? UNDEFINED : new ModelNode(param.toString())); } final Throwable throwable = item.getError(); if (throwable != null) { //TODO include stack trace? entry.get(ERROR).set(throwable.getMessage()); } addItem(entry); return entry.asString(); } private void addCommonFields(ModelNode entry, AuditLogItem item) { StringBuilder buffer = new StringBuilder(20); appendDate(buffer, item); entry.get(OPERATION_DATE).set(buffer.toString()); entry.get(READ_ONLY).set(item.isReadOnly()); entry.get(BOOTING).set(item.isBooting()); entry.get(AS_VERSION).set(item.getAsVersion()); if (item.getUserId() != null) { entry.get(USER_ID).set(item.getUserId()); } if (item.getDomainUUID() != null) { entry.get(DOMAIN_UUID).set(item.getDomainUUID()); } if (item.getAccessMechanism() != null) { entry.get(ACCESS_MECHANISM).set(item.getAccessMechanism().toString()); } if (item.getRemoteAddress() != null) { entry.get(REMOTE_ADDRESS).set(item.getRemoteAddress().toString()); } } } }