SecurityAuditManager.java 6.9 KB
Newer Older
1 2 3 4
/**
 * $Revision$
 * $Date$
 *
5
 * Copyright (C) 2005-2008 Jive Software. All rights reserved.
6
 *
7 8 9 10 11 12 13 14 15 16 17
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
18 19 20 21
 */
package org.jivesoftware.openfire.security;

import java.util.Date;
22 23 24 25 26 27 28 29 30
import java.util.List;
import java.util.Map;

import org.jivesoftware.util.ClassUtils;
import org.jivesoftware.util.JiveGlobals;
import org.jivesoftware.util.PropertyEventDispatcher;
import org.jivesoftware.util.PropertyEventListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
31 32 33 34 35 36

/**
 * The SecurityAuditManager manages the SecurityAuditProvider configured for this server, and provides
 * a proper conduit for making security log entries and looking them up.  Ideally there is no reason
 * for outside classes to interact directly with a provider.
 *
37 38 39 40 41
 * The provider can be specified in system properties by adding:
 *
 * <ul>
 * <li><tt>provider.securityAudit.className = my.security.audit.provider</tt></li>
 * </ul>
42 43 44 45 46
 *
 * @author Daniel Henninger
 */
public class SecurityAuditManager {

47 48
	private static final Logger Log = LoggerFactory.getLogger(SecurityAuditManager.class);

49
    // Wrap this guy up so we can mock out the SecurityAuditManager class.
50 51
    private static class SecurityAuditManagerContainer {
        private static SecurityAuditManager instance = new SecurityAuditManager();
52 53 54 55 56 57 58 59 60 61 62
    }

    /**
     * Returns the currently-installed SecurityAuditProvider. <b>Warning:</b> in virtually all
     * cases the security audit provider should not be used directly. Instead, the appropriate
     * methods in SecurityAuditManager should be called. Direct access to the security audit
     * provider is only provided for special-case logic.
     *
     * @return the current SecurityAuditProvider.
     */
    public static SecurityAuditProvider getSecurityAuditProvider() {
63
        return SecurityAuditManagerContainer.instance.provider;
64 65 66 67 68 69 70 71 72 73 74
    }

    /**
     * Returns a singleton instance of SecurityAuditManager.
     *
     * @return a SecurityAuditManager instance.
     */
    public static SecurityAuditManager getInstance() {
        return SecurityAuditManagerContainer.instance;
    }

75
    private SecurityAuditProvider provider;
76 77 78 79 80 81 82 83 84 85 86

    /**
     * Constructs a SecurityAuditManager, setting up the provider, and a listener.
     */
    private SecurityAuditManager() {
        // Load an security audit provider.
        initProvider();

        // Detect when a new security audit provider class is set
        PropertyEventListener propListener = new PropertyEventListener() {
            public void propertySet(String property, Map params) {
87 88 89
                if ("provider.securityAudit.className".equals(property)) {
                    initProvider();
                }
90 91 92 93 94 95 96
            }

            public void propertyDeleted(String property, Map params) {
                //Ignore
            }

            public void xmlPropertySet(String property, Map params) {
97
                //Ignore
98 99 100 101 102 103 104 105 106 107 108 109 110
            }

            public void xmlPropertyDeleted(String property, Map params) {
                //Ignore
            }
        };
        PropertyEventDispatcher.addListener(propListener);
    }

    /**
     * Initializes the server's security audit provider, based on configuration and defaults to
     * DefaultSecurityAuditProvider if the specified provider is not valid or not specified.
     */
111
    private void initProvider() {
112 113 114 115
        // Convert XML based provider setup to Database based
        JiveGlobals.migrateProperty("provider.securityAudit.className");

        String className = JiveGlobals.getProperty("provider.securityAudit.className",
116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178
                "org.jivesoftware.openfire.security.DefaultSecurityAuditProvider");
        // Check if we need to reset the provider class
        if (provider == null || !className.equals(provider.getClass().getName())) {
            try {
                Class c = ClassUtils.forName(className);
                provider = (SecurityAuditProvider) c.newInstance();
            }
            catch (Exception e) {
                Log.error("Error loading security audit provider: " + className, e);
                provider = new DefaultSecurityAuditProvider();
            }
        }
    }

    /**
     * Records a security event in the audit logs.
     *
     * @param username Username of user who performed the security event.
     * @param summary Short description of the event, similar to a subject.
     * @param details Detailed description of the event, can be null if not desired.
     */
    public void logEvent(String username, String summary, String details) {
        provider.logEvent(username, summary, details);
    }

    /**
     * Retrieves security events that have occurred, filtered by the parameters passed.
     * The events will be in order of most recent to least recent.
     *
     * Any parameters that are left null are to be ignored.  In other words, if username is null,
     * then no specific username is being searched for.
     *
     * @param username Username of user to look up.  Can be null for no username filtering.
     * @param skipEvents Number of events to skip past (typically for paging).  Can be null for first page.
     * @param numEvents Number of events to retrieve.  Can be null for "all" events.
     * @param startTime Oldest date of range of events to retrieve.  Can be null for forever.
     * @param endTime Most recent date of range of events to retrieve.  Can be null for "now".
     * @return Array of security events.
     * @throws AuditWriteOnlyException if provider can not be read from.
     */
    public List<SecurityAuditEvent> getEvents(String username, Integer skipEvents, Integer numEvents, Date startTime, Date endTime) throws AuditWriteOnlyException {
        if (provider.isWriteOnly()) {
            throw new AuditWriteOnlyException();
        }
        return provider.getEvents(username, skipEvents, numEvents, startTime, endTime);
    }

    /**
     * Retrieves a specific event by ID in the form of a SecurityAuditEvent.
     *
     * @param msgID ID number of event to retrieve.
     * @return SecurityAuditEvent object with information from retrieved event.
     * @throws EventNotFoundException if event was not found.
     * @throws AuditWriteOnlyException if provider can not be read from.
     */
    public SecurityAuditEvent getEvent(Integer msgID) throws EventNotFoundException, AuditWriteOnlyException {
        if (provider.isWriteOnly()) {
            throw new AuditWriteOnlyException();
        }
        return provider.getEvent(msgID);
    }

}