Skip to content

Commit 7cd2eb0

Browse files
Logging Architecture Updates (JAVA)
Updating the Logging implementation for Java to match the SLF4J class structures.
1 parent 4461aa7 commit 7cd2eb0

File tree

7 files changed

+494
-52
lines changed

7 files changed

+494
-52
lines changed
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/**
2+
* OWASP Enterprise Security API (ESAPI)
3+
*
4+
* This file is part of the Open Web Application Security Project (OWASP)
5+
* Enterprise Security API (ESAPI) project. For details, please see
6+
* <a href="http://www.owasp.org/index.php/ESAPI">http://www.owasp.org/index.php/ESAPI</a>.
7+
*
8+
* Copyright (c) 2007 - The OWASP Foundation
9+
*
10+
* The ESAPI is published by OWASP under the BSD license. You should read and accept the
11+
* LICENSE before you use, modify, and/or redistribute this software.
12+
*
13+
* @created 2018
14+
*/
15+
package org.owasp.esapi.logging.java;
16+
17+
import java.util.logging.Logger;
18+
19+
import org.owasp.esapi.Logger.EventType;
20+
21+
/**
22+
* Contract for translating an ESAPI log event into an Java log event.
23+
*
24+
*/
25+
public interface JavaLogBridge {
26+
/**
27+
* Translation for the provided ESAPI level, type, and message to the specified Java Logger.
28+
* @param logger Logger to receive the translated message.
29+
* @param esapiLevel ESAPI level of event.
30+
* @param type ESAPI event type
31+
* @param message ESAPI event message content.
32+
*/
33+
void log(Logger logger, int esapiLevel, EventType type, String message) ;
34+
/**
35+
* Translation for the provided ESAPI level, type, message, and Throwable to the specified Java Logger.
36+
* @param logger Logger to receive the translated message.
37+
* @param esapiLevel ESAPI level of event.
38+
* @param type ESAPI event type
39+
* @param message ESAPI event message content.
40+
* @param throwable ESAPI event Throwable content
41+
*/
42+
void log(Logger logger, int esapiLevel, EventType type, String message, Throwable throwable) ;
43+
44+
}
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
/**
2+
* OWASP Enterprise Security API (ESAPI)
3+
*
4+
* This file is part of the Open Web Application Security Project (OWASP)
5+
* Enterprise Security API (ESAPI) project. For details, please see
6+
* <a href="http://www.owasp.org/index.php/ESAPI">http://www.owasp.org/index.php/ESAPI</a>.
7+
*
8+
* Copyright (c) 2007 - The OWASP Foundation
9+
*
10+
* The ESAPI is published by OWASP under the BSD license. You should read and accept the
11+
* LICENSE before you use, modify, and/or redistribute this software.
12+
*
13+
* @created 2018
14+
*/
15+
16+
package org.owasp.esapi.logging.java;
17+
18+
import java.util.HashMap;
19+
import java.util.Map;
20+
import java.util.logging.Logger;
21+
22+
import org.owasp.esapi.Logger.EventType;
23+
import org.owasp.esapi.logging.appender.LogAppender;
24+
import org.owasp.esapi.logging.cleaning.LogScrubber;
25+
26+
/**
27+
* Implementation which is intended to bridge the ESAPI Logging API into Java supported Object structures.
28+
*
29+
*/
30+
public class JavaLogBridgeImpl implements JavaLogBridge {
31+
/** Configuration providing associations between esapi log levels and Java levels.*/
32+
private final Map<Integer,JavaLogLevelHandler> esapiJavaLevelMap;
33+
/** Cleaner used for log content.*/
34+
private final LogScrubber scrubber;
35+
/** Appender used for assembling default message content for all logs.*/
36+
private final LogAppender appender;
37+
38+
/**
39+
* Constructor.
40+
* @param logScrubber Log message cleaner.
41+
* @param esapiJavaHandlerMap Map identifying ESAPI -> Java log level associations.
42+
*/
43+
public JavaLogBridgeImpl(LogAppender messageAppender, LogScrubber logScrubber, Map<Integer, JavaLogLevelHandler> esapiJavaHandlerMap) {
44+
//Defensive copy to prevent external mutations.
45+
this.esapiJavaLevelMap = new HashMap<>(esapiJavaHandlerMap);
46+
this.scrubber = logScrubber;
47+
this.appender = messageAppender;
48+
}
49+
@Override
50+
public void log(Logger logger, int esapiLevel, EventType type, String message) {
51+
JavaLogLevelHandler handler = esapiJavaLevelMap.get(esapiLevel);
52+
if (handler == null) {
53+
throw new IllegalArgumentException("Unable to lookup Java level mapping for esapi value of " + esapiLevel);
54+
}
55+
if (handler.isEnabled(logger)) {
56+
String fullMessage = appender.appendTo(logger.getName(), type, message);
57+
String cleanString = scrubber.cleanMessage(fullMessage);
58+
59+
handler.log(logger, cleanString);
60+
}
61+
}
62+
@Override
63+
public void log(Logger logger, int esapiLevel, EventType type, String message, Throwable throwable) {
64+
JavaLogLevelHandler handler = esapiJavaLevelMap.get(esapiLevel);
65+
if (handler == null) {
66+
throw new IllegalArgumentException("Unable to lookup Java level mapping for esapi value of " + esapiLevel);
67+
}
68+
if (handler.isEnabled(logger)) {
69+
String fullMessage = appender.appendTo(logger.getName(), type, message);
70+
String cleanString = scrubber.cleanMessage(fullMessage);
71+
72+
handler.log(logger, cleanString, throwable);
73+
}
74+
}
75+
}
Lines changed: 98 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,69 +1,115 @@
1+
/**
2+
* OWASP Enterprise Security API (ESAPI)
3+
*
4+
* This file is part of the Open Web Application Security Project (OWASP)
5+
* Enterprise Security API (ESAPI) project. For details, please see
6+
* <a href="http://www.owasp.org/index.php/ESAPI">http://www.owasp.org/index.php/ESAPI</a>.
7+
*
8+
* Copyright (c) 2007 - The OWASP Foundation
9+
*
10+
* The ESAPI is published by OWASP under the BSD license. You should read and accept the
11+
* LICENSE before you use, modify, and/or redistribute this software.
12+
*
13+
* @created 2018
14+
*/
115
package org.owasp.esapi.logging.java;
216

3-
import java.io.Serializable;
17+
import java.util.ArrayList;
418
import java.util.HashMap;
19+
import java.util.List;
20+
import java.util.Map;
521

22+
import org.owasp.esapi.ESAPI;
623
import org.owasp.esapi.LogFactory;
724
import org.owasp.esapi.Logger;
8-
25+
import org.owasp.esapi.codecs.HTMLEntityCodec;
26+
import org.owasp.esapi.logging.appender.LogAppender;
27+
import org.owasp.esapi.logging.appender.LogPrefixAppender;
28+
import org.owasp.esapi.logging.cleaning.CodecLogScrubber;
29+
import org.owasp.esapi.logging.cleaning.CompositeLogScrubber;
30+
import org.owasp.esapi.logging.cleaning.LogScrubber;
31+
import org.owasp.esapi.logging.cleaning.NewlineLogScrubber;
32+
import org.owasp.esapi.reference.DefaultSecurityConfiguration;
933
/**
10-
* Reference implementation of the LogFactory and Logger interfaces. This implementation uses the Java logging package, and marks each
11-
* log message with the currently logged in user and the word "SECURITY" for security related events. See the
12-
* <a href="JavaLogFactory.JavaLogger.html">JavaLogFactory.JavaLogger</a> Javadocs for the details on the JavaLogger reference implementation.
13-
*
14-
* @author Mike Fauzy ([email protected]) <a href="http://www.aspectsecurity.com">Aspect Security</a>
15-
* @author Jeff Williams (jeff.williams .at. aspectsecurity.com) <a href="http://www.aspectsecurity.com">Aspect Security</a>
16-
* @since June 1, 2007
17-
* @see org.owasp.esapi.LogFactory
18-
* @see org.owasp.esapi.logging.java.JavaLogFactory.JavaLogger
34+
* LogFactory implementation which creates JAVA supporting Loggers.
35+
*
1936
*/
2037
public class JavaLogFactory implements LogFactory {
21-
private static volatile LogFactory singletonInstance;
22-
23-
public static LogFactory getInstance() {
24-
if ( singletonInstance == null ) {
25-
synchronized ( JavaLogFactory.class ) {
26-
if ( singletonInstance == null ) {
27-
singletonInstance = new JavaLogFactory();
28-
}
29-
}
30-
}
31-
return singletonInstance;
38+
/** Immune characters for the codec log scrubber for JAVA context.*/
39+
private static final char[] IMMUNE_JAVA_HTML = {',', '.', '-', '_', ' ' };
40+
/** Codec being used to clean messages for logging.*/
41+
private static final HTMLEntityCodec HTML_CODEC = new HTMLEntityCodec();
42+
/** Log appender instance.*/
43+
private static LogAppender JAVA_LOG_APPENDER;
44+
/** Log cleaner instance.*/
45+
private static LogScrubber JAVA_LOG_SCRUBBER;
46+
/** Bridge class for mapping esapi -> java log levels.*/
47+
private static JavaLogBridge LOG_BRIDGE;
48+
49+
static {
50+
boolean encodeLog = ESAPI.securityConfiguration().getBooleanProp(DefaultSecurityConfiguration.LOG_ENCODING_REQUIRED);
51+
JAVA_LOG_SCRUBBER = createLogScrubber(encodeLog);
52+
53+
boolean logClientInfo = true;
54+
boolean logApplicationName = ESAPI.securityConfiguration().getBooleanProp(DefaultSecurityConfiguration.LOG_APPLICATION_NAME);
55+
String appName = ESAPI.securityConfiguration().getStringProp(DefaultSecurityConfiguration.APPLICATION_NAME);
56+
boolean logServerIp = ESAPI.securityConfiguration().getBooleanProp(DefaultSecurityConfiguration.LOG_SERVER_IP);
57+
JAVA_LOG_APPENDER = createLogAppender(logClientInfo, logServerIp, logApplicationName, appName);
58+
59+
Map<Integer, JavaLogLevelHandler> levelLookup = new HashMap<>();
60+
levelLookup.put(Logger.ALL, JavaLogLevelHandlers.ALL);
61+
levelLookup.put(Logger.TRACE, JavaLogLevelHandlers.FINEST);
62+
levelLookup.put(Logger.DEBUG, JavaLogLevelHandlers.FINE);
63+
levelLookup.put(Logger.INFO, JavaLogLevelHandlers.INFO);
64+
levelLookup.put(Logger.ERROR, JavaLogLevelHandlers.ERROR);
65+
levelLookup.put(Logger.WARNING, JavaLogLevelHandlers.WARNING);
66+
levelLookup.put(Logger.FATAL, JavaLogLevelHandlers.SEVERE);
67+
//LEVEL.OFF not used. If it's off why would we try to log it?
68+
69+
LOG_BRIDGE = new JavaLogBridgeImpl(JAVA_LOG_APPENDER, JAVA_LOG_SCRUBBER, levelLookup);
3270
}
33-
34-
private HashMap<Serializable, Logger> loggersMap = new HashMap<Serializable, Logger>();
35-
36-
/**
37-
* Null argument constructor for this implementation of the LogFactory interface
38-
* needed for dynamic configuration.
39-
*/
40-
public JavaLogFactory() {}
41-
42-
/**
43-
* {@inheritDoc}
44-
*/
45-
public Logger getLogger(Class clazz) {
46-
return getLogger(clazz.getName());
71+
72+
/**
73+
* Populates the default log scrubber for use in factory-created loggers.
74+
* @param requiresEncoding {@code true} if encoding is required for log content.
75+
* @return LogScrubber instance.
76+
*/
77+
/*package*/ static LogScrubber createLogScrubber(boolean requiresEncoding) {
78+
List<LogScrubber> messageScrubber = new ArrayList<>();
79+
messageScrubber.add(new NewlineLogScrubber());
80+
81+
if (requiresEncoding) {
82+
messageScrubber.add(new CodecLogScrubber(HTML_CODEC, IMMUNE_JAVA_HTML));
83+
}
84+
85+
return new CompositeLogScrubber(messageScrubber);
86+
4787
}
48-
88+
4989
/**
50-
* {@inheritDoc}
51-
*/
90+
* Populates the default log appender for use in factory-created loggers.
91+
* @param appName
92+
* @param logApplicationName
93+
* @param logServerIp
94+
* @param logClientInfo
95+
*
96+
* @return LogAppender instance.
97+
*/
98+
/*package*/ static LogAppender createLogAppender(boolean logClientInfo, boolean logServerIp, boolean logApplicationName, String appName) {
99+
return new LogPrefixAppender(logClientInfo, logServerIp, logApplicationName, appName);
100+
}
101+
102+
103+
@Override
52104
public Logger getLogger(String moduleName) {
53-
54-
synchronized (loggersMap) {
55-
// If a logger for this module already exists, we return the same one, otherwise we create a new one.
56-
Logger moduleLogger = loggersMap.get(moduleName);
57-
58-
if (moduleLogger == null) {
59-
moduleLogger = new JavaLogger(moduleName);
60-
loggersMap.put(moduleName, moduleLogger);
61-
}
62-
return moduleLogger;
63-
}
105+
java.util.logging.Logger javaLogger = java.util.logging.Logger.getLogger(moduleName);
106+
return new JavaLogger(javaLogger, LOG_BRIDGE, Logger.ALL);
64107
}
65108

66-
67-
109+
@Override
110+
public Logger getLogger(@SuppressWarnings("rawtypes") Class clazz) {
111+
java.util.logging.Logger javaLogger = java.util.logging.Logger.getLogger(clazz.getName());
112+
return new JavaLogger(javaLogger, LOG_BRIDGE, Logger.ALL);
113+
}
68114

69115
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/**
2+
* OWASP Enterprise Security API (ESAPI)
3+
*
4+
* This file is part of the Open Web Application Security Project (OWASP)
5+
* Enterprise Security API (ESAPI) project. For details, please see
6+
* <a href="http://www.owasp.org/index.php/ESAPI">http://www.owasp.org/index.php/ESAPI</a>.
7+
*
8+
* Copyright (c) 2007 - The OWASP Foundation
9+
*
10+
* The ESAPI is published by OWASP under the BSD license. You should read and accept the
11+
* LICENSE before you use, modify, and/or redistribute this software.
12+
*
13+
* @created 2018
14+
*/
15+
package org.owasp.esapi.logging.java;
16+
17+
import java.util.logging.Logger;
18+
19+
/**
20+
* Contract used to isolate translations for each Java Logging Level.
21+
*
22+
* @see JavaLogLevelHandlers
23+
* @see JavaLogBridgeImpl
24+
*
25+
*/
26+
interface JavaLogLevelHandler {
27+
/** Check if the logging level is enabled for the specified logger.*/
28+
boolean isEnabled(Logger logger);
29+
/**
30+
* Calls the appropriate log level event on the specified logger.
31+
* @param logger Logger to invoke.
32+
* @param msg Message to log.
33+
*/
34+
void log(Logger logger, String msg);
35+
/**
36+
* Calls the appropriate log level event on the specified logger.
37+
* @param logger Logger to invoke
38+
* @param msg Message to log
39+
* @param th Throwable to log.
40+
*/
41+
void log(Logger logger, String msg, Throwable th);
42+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package org.owasp.esapi.logging.java;
2+
3+
import java.util.logging.Level;
4+
import java.util.logging.Logger;
5+
6+
public enum JavaLogLevelHandlers implements JavaLogLevelHandler {
7+
8+
SEVERE(Level.SEVERE),
9+
WARNING(Level.WARNING),
10+
INFO(Level.INFO),
11+
CONFIG(Level.CONFIG),
12+
FINE(Level.FINE),
13+
FINER(Level.FINER),
14+
FINEST(Level.FINEST),
15+
ALL(Level.ALL),
16+
ERROR(JavaLoggerLevel.ERROR_LEVEL);
17+
18+
private final Level level;
19+
20+
private JavaLogLevelHandlers(Level lvl) {
21+
this.level = lvl;
22+
}
23+
24+
@Override
25+
public boolean isEnabled(Logger logger) {
26+
return logger.isLoggable(level);
27+
}
28+
29+
@Override
30+
public void log(Logger logger, String msg) {
31+
logger.log(level, msg);
32+
}
33+
34+
@Override
35+
public void log(Logger logger, String msg, Throwable th) {
36+
logger.log(level, msg, th);
37+
}
38+
}

0 commit comments

Comments
 (0)