/** * 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.audit; import org.apache.hadoop.gateway.audit.api.AuditContext; import org.apache.hadoop.gateway.audit.api.AuditService; import org.apache.hadoop.gateway.audit.api.AuditServiceFactory; import org.apache.hadoop.gateway.audit.api.Auditor; import org.apache.hadoop.gateway.audit.api.CorrelationContext; import org.apache.hadoop.gateway.audit.api.CorrelationService; import org.apache.hadoop.gateway.audit.api.CorrelationServiceFactory; 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.test.log.CollectAppender; import org.apache.log4j.LogManager; import org.apache.log4j.PropertyConfigurator; import org.apache.log4j.spi.LoggingEvent; import org.junit.After; import org.junit.Before; import org.junit.Test; import java.io.File; import java.util.Iterator; import java.util.UUID; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.IsNull.nullValue; public class AuditServiceTest { private static AuditService auditService = AuditServiceFactory.getAuditService(); private static CorrelationService correlationService = CorrelationServiceFactory.getCorrelationService(); private static Auditor auditor = AuditServiceFactory.getAuditService().getAuditor( "audit.forward", AuditConstants.KNOX_COMPONENT_NAME, AuditConstants.KNOX_SERVICE_NAME ); private String username = "user"; private String proxyUsername = "proxyuser"; private String remoteIp = "127.0.0.1"; private String remoteHostname = "localhost"; private String targetServiceName = "service"; @Before public void setup() { cleanup(); } @After public void cleanup() { CollectAppender.queue.clear(); LogManager.shutdown(); String absolutePath = "target/audit"; File db = new File( absolutePath + ".db" ); if( db.exists() ) { assertThat( "Failed to delete audit store db file.", db.delete(), is( true ) ); } File lg = new File( absolutePath + ".lg" ); if( lg.exists() ) { assertThat( "Failed to delete audit store lg file.", lg.delete(), is( true ) ); } PropertyConfigurator.configure( ClassLoader.getSystemResourceAsStream( "audit-log4j.properties" ) ); } @Test public void testMultipleRequestEvents() { int iterations = 1000; AuditContext ac = auditService.createContext(); ac.setUsername( username ); ac.setProxyUsername( proxyUsername ); ac.setRemoteIp( remoteIp ); ac.setRemoteHostname( remoteHostname ); ac.setTargetServiceName( targetServiceName ); CorrelationContext cc = correlationService.createContext(); cc.setRequestId( UUID.randomUUID().toString() ); cc.setParentRequestId( UUID.randomUUID().toString() ); cc.setRootRequestId( UUID.randomUUID().toString() ); CollectAppender.queue.clear(); for( int i = 0; i < iterations; i++ ) { auditor.audit( "action" + i, "resource" + i, "resource type" + i, "outcome" + i, "message" + i ); } auditService.detachContext(); correlationService.detachContext(); assertThat( CollectAppender.queue.size(), is( iterations ) ); //Verify events number and audit/correlation parameters in each event Iterator<LoggingEvent> iterator = CollectAppender.queue.iterator(); int counter = 0; while(iterator.hasNext()) { LoggingEvent event = iterator.next(); checkLogEventContexts( event, cc, ac ); assertThat( (String)event.getMDC( AuditConstants.MDC_ACTION_KEY ), is( "action" + counter ) ); assertThat( (String)event.getMDC( AuditConstants.MDC_RESOURCE_NAME_KEY ), is( "resource" + counter ) ); assertThat( (String)event.getMDC( AuditConstants.MDC_RESOURCE_TYPE_KEY ), is( "resource type" + counter ) ); assertThat( (String)event.getMDC( AuditConstants.MDC_OUTCOME_KEY ), is( "outcome" + counter ) ); 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.getRenderedMessage(), is( "message" + counter ) ); counter++; } assertThat( auditService.getContext(), nullValue() ); assertThat( correlationService.getContext(), nullValue() ); } @Test public void testSequentialRequests() { AuditContext ac = auditService.createContext(); ac.setUsername( username ); ac.setProxyUsername( proxyUsername ); ac.setRemoteIp( remoteIp ); ac.setRemoteHostname( remoteHostname ); ac.setTargetServiceName( targetServiceName ); CorrelationContext cc = correlationService.createContext(); cc.setRequestId( UUID.randomUUID().toString() ); cc.setParentRequestId( UUID.randomUUID().toString() ); cc.setRootRequestId( UUID.randomUUID().toString() ); auditor.audit( "action", "resource", "resource type", "outcome", "message" ); auditService.detachContext(); correlationService.detachContext(); assertThat( CollectAppender.queue.size(), is( 1 ) ); LoggingEvent event = CollectAppender.queue.iterator().next(); checkLogEventContexts( event, cc, ac ); CollectAppender.queue.clear(); ac = auditService.createContext(); ac.setUsername( username + "1" ); ac.setProxyUsername( proxyUsername + "1" ); ac.setRemoteIp( remoteIp + "1" ); ac.setRemoteHostname( remoteHostname + "1" ); ac.setTargetServiceName( targetServiceName + "1" ); cc = correlationService.createContext(); cc.setRequestId( UUID.randomUUID().toString() ); cc.setParentRequestId( UUID.randomUUID().toString() ); cc.setRootRequestId( UUID.randomUUID().toString() ); auditor.audit( "action", "resource", "resource type", "outcome", "message" ); auditService.detachContext(); correlationService.detachContext(); assertThat( CollectAppender.queue.size(), is( 1 ) ); event = CollectAppender.queue.iterator().next(); checkLogEventContexts( event, cc, ac ); } private void checkLogEventContexts( LoggingEvent event, CorrelationContext expectedCorrelationContext, AuditContext expectedAuditContext ) { AuditContext context = (AuditContext) event.getMDC( Log4jAuditService.MDC_AUDIT_CONTEXT_KEY ); assertThat( context.getUsername(), is( expectedAuditContext.getUsername() ) ); assertThat( context.getProxyUsername(), is( expectedAuditContext.getProxyUsername() ) ); assertThat( context.getSystemUsername(), is( expectedAuditContext.getSystemUsername() ) ); assertThat( context.getRemoteIp(), is( expectedAuditContext.getRemoteIp() ) ); assertThat( context.getRemoteHostname(), is( expectedAuditContext.getRemoteHostname() ) ); assertThat( context.getTargetServiceName(), is( expectedAuditContext.getTargetServiceName() ) ); CorrelationContext correlationContext = (CorrelationContext)event.getMDC( Log4jCorrelationService.MDC_CORRELATION_CONTEXT_KEY ); assertThat( correlationContext.getRequestId(), is( expectedCorrelationContext.getRequestId() ) ); assertThat( correlationContext.getRootRequestId(), is( expectedCorrelationContext.getRootRequestId() ) ); assertThat( correlationContext.getParentRequestId(), is( expectedCorrelationContext.getParentRequestId() ) ); } }