/** * 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.layout.AuditLayout; 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.text.SimpleDateFormat; import java.util.Date; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.MatcherAssert.assertThat; public class AuditLayoutTest { private static AuditService auditService = AuditServiceFactory.getAuditService(); private static CorrelationService correlationService = CorrelationServiceFactory.getCorrelationService(); private static Auditor auditor = auditService.getAuditor( "audit.forward", AuditConstants.KNOX_COMPONENT_NAME, AuditConstants.KNOX_SERVICE_NAME ); private static AuditLayout layout = new AuditLayout(); private static final String USERNAME = "username"; private static final String PROXYUSERNAME = "proxy_username"; private static final String SYSTEMUSERNAME = "system_username"; private static final String HOST_NAME = "hostname"; private static final String HOST_ADDRESS = "hostaddress"; private static final String ACTION = "action"; private static final String OUTCOME = "outcome"; private static final String RESOURCE_NAME = "resource_name"; private static final String RESOURCE_TYPE = "resource_type"; private static final String TARGET_SERVICE = "WEBHDFS"; private static final String MESSAGE = "message"; private static final String ROOT_REQUEST_ID = "1"; private static final String PARENT_REQUEST_ID = "2"; private static final String REQUEST_ID = "3"; private static final String EMPTY = ""; private static final String RECORD_PATTERN = "%s %s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s%s"; static { layout.activateOptions(); } @Before public void setup() { cleanup(); } @After public void cleanup() { CollectAppender.queue.clear(); auditService.detachContext(); correlationService.detachContext(); 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 testFullyFilledAuditEvent() { AuditContext auditContext = auditService.createContext(); auditContext.setProxyUsername( PROXYUSERNAME ); auditContext.setSystemUsername( SYSTEMUSERNAME ); auditContext.setUsername( USERNAME ); auditContext.setRemoteHostname( HOST_NAME ); auditContext.setRemoteIp( HOST_ADDRESS ); auditContext.setTargetServiceName( TARGET_SERVICE ); CorrelationContext correlationContext = correlationService.createContext(); correlationContext.setRequestId( REQUEST_ID ); correlationContext.setParentRequestId( PARENT_REQUEST_ID ); correlationContext.setRootRequestId( ROOT_REQUEST_ID ); auditor.audit( ACTION, RESOURCE_NAME, RESOURCE_TYPE, OUTCOME, MESSAGE ); assertThat( CollectAppender.queue.size(), is( 1 ) ); LoggingEvent event = CollectAppender.queue.iterator().next(); SimpleDateFormat format = new SimpleDateFormat( "yy/MM/dd HH:mm:ss" ); String formatedDate = format.format( new Date( event.getTimeStamp() ) ); //14/01/24 12:40:24 1|2|3|audit.forward|hostaddress|WEBHDFS|username|proxy_username|system_username|action|resource_type|resource_name|outcome|message String expectedOutput = String.format( RECORD_PATTERN, formatedDate, ROOT_REQUEST_ID, PARENT_REQUEST_ID, REQUEST_ID, "audit.forward", HOST_ADDRESS, TARGET_SERVICE, USERNAME, PROXYUSERNAME, SYSTEMUSERNAME, ACTION, RESOURCE_TYPE, RESOURCE_NAME, OUTCOME, MESSAGE, AuditLayout.LINE_SEP ); String auditOutput = layout.format( event ); assertThat( auditOutput, is( expectedOutput ) ); } @Test public void testAuditEventWithoutContexts() { auditor.audit( ACTION, RESOURCE_NAME, RESOURCE_TYPE, OUTCOME, MESSAGE ); assertThat( CollectAppender.queue.size(), is( 1 ) ); LoggingEvent event = CollectAppender.queue.iterator().next(); SimpleDateFormat format = new SimpleDateFormat( "yy/MM/dd HH:mm:ss" ); String formatedDate = format.format( new Date( event.getTimeStamp() ) ); //14/01/24 12:41:47 |||audit.forward|||||action|resource_type|resource_name|outcome|message String expectedOutput = String.format( RECORD_PATTERN, formatedDate, EMPTY, EMPTY, EMPTY, "audit.forward", EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, ACTION, RESOURCE_TYPE, RESOURCE_NAME, OUTCOME, MESSAGE, AuditLayout.LINE_SEP ); String auditOutput = layout.format( event ); assertThat( auditOutput, is( expectedOutput ) ); } @Test public void testAuditEventWithoutMessage() { auditor.audit( ACTION, RESOURCE_NAME, RESOURCE_TYPE, OUTCOME ); assertThat( CollectAppender.queue.size(), is( 1 ) ); LoggingEvent event = CollectAppender.queue.iterator().next(); SimpleDateFormat format = new SimpleDateFormat( "yy/MM/dd HH:mm:ss" ); String formatedDate = format.format( new Date( event.getTimeStamp() ) ); //14/01/24 12:41:47 |||audit.forward|||||action|resource_type|resource_name|outcome| String expectedOutput = String.format( RECORD_PATTERN, formatedDate, EMPTY, EMPTY, EMPTY, "audit.forward", EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, ACTION, RESOURCE_TYPE, RESOURCE_NAME, OUTCOME, EMPTY, AuditLayout.LINE_SEP ); String auditOutput = layout.format( event ); assertThat( auditOutput, is( expectedOutput ) ); } }