Java tutorial
/** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you 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. */ package org.apache.hadoop.gateway; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.IsNull.notNullValue; import static org.hamcrest.core.IsNull.nullValue; import static org.junit.Assert.fail; import java.io.IOException; import java.net.URI; import java.net.URISyntaxException; import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.hadoop.gateway.audit.api.Action; import org.apache.hadoop.gateway.audit.api.ActionOutcome; import org.apache.hadoop.gateway.audit.api.AuditContext; import org.apache.hadoop.gateway.audit.api.AuditServiceFactory; import org.apache.hadoop.gateway.audit.api.CorrelationContext; import org.apache.hadoop.gateway.audit.api.ResourceType; import org.apache.hadoop.gateway.audit.log4j.audit.AuditConstants; import org.apache.hadoop.gateway.audit.log4j.audit.Log4jAuditService; import org.apache.hadoop.gateway.audit.log4j.correlation.Log4jCorrelationService; import org.apache.hadoop.gateway.config.GatewayConfig; import org.apache.hadoop.gateway.dispatch.DefaultDispatch; import org.apache.hadoop.gateway.i18n.resources.ResourcesFactory; import org.apache.hadoop.test.log.CollectAppender; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.log4j.spi.LoggingEvent; import org.easymock.EasyMock; import org.junit.After; import org.junit.Before; import org.junit.Test; public class AuditLoggingTest { private static final String METHOD = "GET"; private static final String PATH = "path"; private static final String CONTEXT_PATH = "contextPath/"; private static final String ADDRESS = "address"; private static final String HOST = "host"; private static final GatewayResources RES = ResourcesFactory.get(GatewayResources.class); @Before public void loggingSetup() { AuditServiceFactory.getAuditService().createContext(); CollectAppender.queue.clear(); } @After public void reset() { AuditServiceFactory.getAuditService().detachContext(); } @Test /** * Empty filter chain. Two events with same correlation ID are expected: * * action=access request_type=uri outcome=unavailable * action=access request_type=uri outcome=success message=Response status: 404 */ public void testNoFiltersAudit() throws ServletException, IOException { FilterConfig config = EasyMock.createNiceMock(FilterConfig.class); EasyMock.replay(config); HttpServletRequest request = EasyMock.createNiceMock(HttpServletRequest.class); ServletContext context = EasyMock.createNiceMock(ServletContext.class); GatewayConfig gatewayConfig = EasyMock.createNiceMock(GatewayConfig.class); EasyMock.expect(request.getMethod()).andReturn(METHOD).anyTimes(); EasyMock.expect(request.getPathInfo()).andReturn(PATH).anyTimes(); EasyMock.expect(request.getContextPath()).andReturn(CONTEXT_PATH).anyTimes(); EasyMock.expect(request.getRemoteAddr()).andReturn(ADDRESS).anyTimes(); EasyMock.expect(request.getRemoteHost()).andReturn(HOST).anyTimes(); EasyMock.expect(request.getServletContext()).andReturn(context).anyTimes(); EasyMock.expect(context.getAttribute(GatewayConfig.GATEWAY_CONFIG_ATTRIBUTE)).andReturn(gatewayConfig) .anyTimes(); EasyMock.expect(gatewayConfig.getHeaderNameForRemoteAddress()).andReturn("Custom-Forwarded-For").anyTimes(); EasyMock.replay(request); EasyMock.replay(context); EasyMock.replay(gatewayConfig); HttpServletResponse response = EasyMock.createNiceMock(HttpServletResponse.class); EasyMock.replay(response); FilterChain chain = EasyMock.createNiceMock(FilterChain.class); EasyMock.replay(chain); GatewayFilter gateway = new GatewayFilter(); gateway.init(config); gateway.doFilter(request, response, chain); gateway.destroy(); assertThat(CollectAppender.queue.size(), is(1)); Iterator<LoggingEvent> iterator = CollectAppender.queue.iterator(); LoggingEvent accessEvent = iterator.next(); verifyAuditEvent(accessEvent, CONTEXT_PATH + PATH, ResourceType.URI, Action.ACCESS, ActionOutcome.UNAVAILABLE, null, "Request method: GET"); } @Test /** * One NoOp filter in chain. Single audit event with same with specified request URI is expected: * * action=access request_type=uri outcome=unavailable */ public void testNoopFilter() throws ServletException, IOException, URISyntaxException { FilterConfig config = EasyMock.createNiceMock(FilterConfig.class); EasyMock.replay(config); HttpServletRequest request = EasyMock.createNiceMock(HttpServletRequest.class); ServletContext context = EasyMock.createNiceMock(ServletContext.class); GatewayConfig gatewayConfig = EasyMock.createNiceMock(GatewayConfig.class); EasyMock.expect(request.getMethod()).andReturn(METHOD).anyTimes(); EasyMock.expect(request.getPathInfo()).andReturn(PATH).anyTimes(); EasyMock.expect(request.getContextPath()).andReturn(CONTEXT_PATH).anyTimes(); EasyMock.expect(request.getRemoteAddr()).andReturn(ADDRESS).anyTimes(); EasyMock.expect(request.getRemoteHost()).andReturn(HOST).anyTimes(); EasyMock.expect(request.getServletContext()).andReturn(context).anyTimes(); EasyMock.expect(context.getAttribute(GatewayConfig.GATEWAY_CONFIG_ATTRIBUTE)).andReturn(gatewayConfig) .anyTimes(); EasyMock.expect(gatewayConfig.getHeaderNameForRemoteAddress()).andReturn("Custom-Forwarded-For").anyTimes(); EasyMock.replay(request); EasyMock.replay(context); EasyMock.replay(gatewayConfig); HttpServletResponse response = EasyMock.createNiceMock(HttpServletResponse.class); EasyMock.replay(response); FilterChain chain = EasyMock.createNiceMock(FilterChain.class); EasyMock.replay(chain); Filter filter = EasyMock.createNiceMock(Filter.class); EasyMock.replay(filter); GatewayFilter gateway = new GatewayFilter(); gateway.addFilter("path", "filter", filter, null, null); gateway.init(config); gateway.doFilter(request, response, chain); gateway.destroy(); assertThat(CollectAppender.queue.size(), is(1)); Iterator<LoggingEvent> iterator = CollectAppender.queue.iterator(); LoggingEvent accessEvent = iterator.next(); verifyAuditEvent(accessEvent, CONTEXT_PATH + PATH, ResourceType.URI, Action.ACCESS, ActionOutcome.UNAVAILABLE, null, "Request method: GET"); } @Test /** * Dispatching outbound request. Remote host is unreachable. Two log events is expected: * * action=dispatch request_type=uri outcome=FAILED * action=dispatch request_type=uri outcome=unavailable */ public void testHttpClientOutboundException() throws IOException, URISyntaxException { String uri = "http://outbound-host:port/path"; HttpServletRequest inboundRequest = EasyMock.createNiceMock(HttpServletRequest.class); EasyMock.expect(inboundRequest.getHeaderNames()).andReturn(Collections.enumeration(new ArrayList<String>())) .anyTimes(); EasyMock.replay(inboundRequest); HttpServletResponse outboundResponse = EasyMock.createNiceMock(HttpServletResponse.class); EasyMock.replay(outboundResponse); DefaultDispatch dispatch = new DefaultDispatch(); dispatch.setHttpClient(new DefaultHttpClient()); try { dispatch.doGet(new URI(uri), inboundRequest, outboundResponse); fail("Expected exception while accessing to unreachable host"); } catch (IOException e) { Iterator<LoggingEvent> iterator = CollectAppender.queue.iterator(); LoggingEvent unavailableEvent = iterator.next(); verifyValue((String) unavailableEvent.getMDC(AuditConstants.MDC_RESOURCE_NAME_KEY), uri); verifyValue((String) unavailableEvent.getMDC(AuditConstants.MDC_RESOURCE_TYPE_KEY), ResourceType.URI); verifyValue((String) unavailableEvent.getMDC(AuditConstants.MDC_ACTION_KEY), Action.DISPATCH); verifyValue((String) unavailableEvent.getMDC(AuditConstants.MDC_OUTCOME_KEY), ActionOutcome.UNAVAILABLE); LoggingEvent failureEvent = iterator.next(); verifyValue((String) failureEvent.getMDC(AuditConstants.MDC_RESOURCE_NAME_KEY), uri); verifyValue((String) failureEvent.getMDC(AuditConstants.MDC_RESOURCE_TYPE_KEY), ResourceType.URI); verifyValue((String) failureEvent.getMDC(AuditConstants.MDC_ACTION_KEY), Action.DISPATCH); verifyValue((String) failureEvent.getMDC(AuditConstants.MDC_OUTCOME_KEY), ActionOutcome.FAILURE); } } private void verifyAuditEvent(LoggingEvent event, String resourceName, String resourceType, String action, String outcome, String targetService, String message) { event.getMDCCopy(); CorrelationContext cc = (CorrelationContext) event .getMDC(Log4jCorrelationService.MDC_CORRELATION_CONTEXT_KEY); assertThat(cc, notNullValue()); assertThat(cc.getRequestId(), is(notNullValue())); AuditContext ac = (AuditContext) event.getMDC(Log4jAuditService.MDC_AUDIT_CONTEXT_KEY); assertThat(ac, notNullValue()); assertThat(ac.getRemoteIp(), is(ADDRESS)); assertThat(ac.getRemoteHostname(), is(HOST)); assertThat((String) event.getMDC(AuditConstants.MDC_SERVICE_KEY), is(AuditConstants.KNOX_SERVICE_NAME)); assertThat((String) event.getMDC(AuditConstants.MDC_COMPONENT_KEY), is(AuditConstants.KNOX_COMPONENT_NAME)); assertThat((String) event.getLoggerName(), is(AuditConstants.DEFAULT_AUDITOR_NAME)); verifyValue((String) event.getMDC(AuditConstants.MDC_RESOURCE_NAME_KEY), resourceName); verifyValue((String) event.getMDC(AuditConstants.MDC_RESOURCE_TYPE_KEY), resourceType); verifyValue((String) event.getMDC(AuditConstants.MDC_ACTION_KEY), action); verifyValue((String) event.getMDC(AuditConstants.MDC_OUTCOME_KEY), outcome); verifyValue(ac.getTargetServiceName(), targetService); verifyValue(event.getRenderedMessage(), message); } private void verifyValue(String actual, String expected) { if (expected == null) { assertThat(actual, nullValue()); } else { assertThat(actual, is(expected)); } } private String getRequestId(LoggingEvent event) { CorrelationContext cc = (CorrelationContext) event .getMDC(Log4jCorrelationService.MDC_CORRELATION_CONTEXT_KEY); return cc == null ? null : cc.getRequestId(); } }