001/* 002 * The contents of this file are subject to the terms of the Common Development and 003 * Distribution License (the License). You may not use this file except in compliance with the 004 * License. 005 * 006 * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the 007 * specific language governing permission and limitations under the License. 008 * 009 * When distributing Covered Software, include this CDDL Header Notice in each file and include 010 * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL 011 * Header, with the fields enclosed by brackets [] replaced by your own identifying 012 * information: "Portions copyright [year] [name of copyright owner]". 013 * 014 * Copyright 2015-2016 ForgeRock AS. 015 */ 016 017package org.forgerock.audit; 018 019import static org.forgerock.audit.AuditServiceBuilder.newAuditService; 020import static org.forgerock.audit.json.AuditJsonConfig.getJson; 021import static org.forgerock.audit.json.AuditJsonConfig.registerHandlerToService; 022import static org.forgerock.http.routing.RouteMatchers.requestUriMatcher; 023 024import java.io.IOException; 025import java.io.InputStream; 026 027import org.forgerock.audit.events.handlers.buffering.BatchPublisherFactory; 028import org.forgerock.audit.events.handlers.buffering.BatchPublisherFactoryImpl; 029import org.forgerock.audit.json.AuditJsonConfig; 030import org.forgerock.http.Client; 031import org.forgerock.http.Handler; 032import org.forgerock.http.HttpApplication; 033import org.forgerock.http.HttpApplicationException; 034import org.forgerock.http.handler.HttpClientHandler; 035import org.forgerock.http.io.Buffer; 036import org.forgerock.http.routing.Router; 037import org.forgerock.http.routing.RoutingMode; 038import org.forgerock.json.JsonValue; 039import org.forgerock.json.resource.Resources; 040import org.forgerock.json.resource.ServiceUnavailableException; 041import org.forgerock.json.resource.http.CrestHttp; 042import org.forgerock.util.Factory; 043import org.slf4j.Logger; 044import org.slf4j.LoggerFactory; 045 046/** 047 * Crest Application that instantiates the AuditService on the crest router. 048 */ 049public final class AuditHttpApplication implements HttpApplication { 050 051 private static final Logger logger = LoggerFactory.getLogger(AuditHttpApplication.class); 052 /** Audit event handlers config location. */ 053 public static final String AUDIT_EVENT_HANDLERS_CONFIG = "/conf/audit-event-handlers.json"; 054 /** Event handlers key. */ 055 public static final String EVENT_HANDLERS = "eventHandlers"; 056 /** Root path for audit endpoints. */ 057 public static final String AUDIT_ROOT_PATH = "/audit"; 058 059 private AuditService auditService; 060 061 @Override 062 public Handler start() throws HttpApplicationException { 063 final Router router = new Router(); 064 final AuditServiceConfiguration auditServiceConfiguration = loadAuditServiceConfiguration(); 065 066 AuditServiceBuilder auditServiceBuilder = newAuditService(); 067 auditServiceBuilder.withDependencyProvider(setupDependencies()); 068 auditServiceBuilder.withConfiguration(auditServiceConfiguration); 069 070 try (final InputStream eventHandlersConfig = this.getClass().getResourceAsStream(AUDIT_EVENT_HANDLERS_CONFIG)) { 071 JsonValue auditEventHandlers = getJson(eventHandlersConfig).get(EVENT_HANDLERS); 072 for (final JsonValue handlerConfig : auditEventHandlers) { 073 try { 074 registerHandlerToService(handlerConfig, auditServiceBuilder, this.getClass().getClassLoader()); 075 } catch (Exception ex) { 076 logger.error("Unable to register handler defined by config: " + handlerConfig, ex); 077 } 078 } 079 } catch (AuditException | IOException e) { 080 logger.error("Failed to read audit event handler configurations", e); 081 throw new HttpApplicationException(e); 082 } 083 084 auditService = auditServiceBuilder.build(); 085 try { 086 auditService.startup(); 087 } catch (ServiceUnavailableException e) { 088 logger.error("Unable to start audit service", e); 089 throw new HttpApplicationException(e); 090 } 091 router.addRoute(requestUriMatcher(RoutingMode.STARTS_WITH, AUDIT_ROOT_PATH), 092 CrestHttp.newHttpHandler(Resources.newInternalConnectionFactory(auditService))); 093 return router; 094 } 095 096 @Override 097 public Factory<Buffer> getBufferFactory() { 098 return null; 099 } 100 101 @Override 102 public void stop() { 103 if (auditService != null) { 104 auditService.shutdown(); 105 } 106 } 107 108 private DependencyProvider setupDependencies() throws HttpApplicationException { 109 DependencyProviderBase dependencyProvider = new DependencyProviderBase(); 110 dependencyProvider.register(Client.class, new Client(new HttpClientHandler())); 111 dependencyProvider.register(BatchPublisherFactory.class, new BatchPublisherFactoryImpl()); 112 return dependencyProvider; 113 } 114 115 /** Loads the audit service configuration from JSON. */ 116 private static AuditServiceConfiguration loadAuditServiceConfiguration() { 117 try (InputStream inputStream = getResourceAsStream("/conf/audit-service.json")) { 118 return AuditJsonConfig.parseAuditServiceConfiguration(inputStream); 119 } catch (AuditException | IOException e) { 120 final RuntimeException exception = new RuntimeException("Error while configuring the audit service", e); 121 logger.error(exception.getMessage(), e); 122 throw exception; 123 } 124 } 125 126 private static InputStream getResourceAsStream(String path) { 127 return AuditHttpApplication.class.getResourceAsStream(path); 128 } 129}