/* * Licensed to Elasticsearch under one or more contributor * license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright * ownership. Elasticsearch 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.elasticsearch.common.logging; import org.apache.logging.log4j.Level; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.core.Appender; import org.apache.logging.log4j.core.LoggerContext; import org.apache.logging.log4j.core.config.Configuration; import org.apache.logging.log4j.core.config.Configurator; import org.apache.logging.log4j.core.config.LoggerConfig; import org.elasticsearch.cli.UserException; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.env.Environment; import org.elasticsearch.test.ESTestCase; import java.io.IOException; import java.nio.file.Path; import java.util.Map; import static org.hamcrest.CoreMatchers.containsString; import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.Matchers.hasKey; import static org.hamcrest.Matchers.hasToString; import static org.hamcrest.Matchers.notNullValue; public class EvilLoggerConfigurationTests extends ESTestCase { @Override public void setUp() throws Exception { super.setUp(); LogConfigurator.registerErrorListener(); } @Override public void tearDown() throws Exception { LoggerContext context = (LoggerContext) LogManager.getContext(false); Configurator.shutdown(context); super.tearDown(); } public void testResolveMultipleConfigs() throws Exception { final Level level = ESLoggerFactory.getLogger("test").getLevel(); try { final Path configDir = getDataPath("config"); final Settings settings = Settings.builder() .put(Environment.PATH_CONF_SETTING.getKey(), configDir.toAbsolutePath()) .put(Environment.PATH_HOME_SETTING.getKey(), createTempDir().toString()) .build(); final Environment environment = new Environment(settings); LogConfigurator.configure(environment); { final LoggerContext ctx = (LoggerContext) LogManager.getContext(false); final Configuration config = ctx.getConfiguration(); final LoggerConfig loggerConfig = config.getLoggerConfig("test"); final Appender appender = loggerConfig.getAppenders().get("console"); assertThat(appender, notNullValue()); } { final LoggerContext ctx = (LoggerContext) LogManager.getContext(false); final Configuration config = ctx.getConfiguration(); final LoggerConfig loggerConfig = config.getLoggerConfig("second"); final Appender appender = loggerConfig.getAppenders().get("console2"); assertThat(appender, notNullValue()); } { final LoggerContext ctx = (LoggerContext) LogManager.getContext(false); final Configuration config = ctx.getConfiguration(); final LoggerConfig loggerConfig = config.getLoggerConfig("third"); final Appender appender = loggerConfig.getAppenders().get("console3"); assertThat(appender, notNullValue()); } } finally { Configurator.setLevel("test", level); } } public void testDefaults() throws IOException, UserException { final Path configDir = getDataPath("config"); final String level = randomFrom(Level.TRACE, Level.DEBUG, Level.INFO, Level.WARN, Level.ERROR).toString(); final Settings settings = Settings.builder() .put(Environment.PATH_CONF_SETTING.getKey(), configDir.toAbsolutePath()) .put(Environment.PATH_HOME_SETTING.getKey(), createTempDir().toString()) .put("logger.level", level) .build(); final Environment environment = new Environment(settings); LogConfigurator.configure(environment); final String loggerName = "test"; final Logger logger = ESLoggerFactory.getLogger(loggerName); assertThat(logger.getLevel().toString(), equalTo(level)); } // tests that custom settings are not overwritten by settings in the config file public void testResolveOrder() throws Exception { final Path configDir = getDataPath("config"); final Settings settings = Settings.builder() .put(Environment.PATH_CONF_SETTING.getKey(), configDir.toAbsolutePath()) .put(Environment.PATH_HOME_SETTING.getKey(), createTempDir().toString()) .put("logger.test_resolve_order", "TRACE") .build(); final Environment environment = new Environment(settings); LogConfigurator.configure(environment); // args should overwrite whatever is in the config final String loggerName = "test_resolve_order"; final Logger logger = ESLoggerFactory.getLogger(loggerName); assertTrue(logger.isTraceEnabled()); } public void testHierarchy() throws Exception { final Path configDir = getDataPath("hierarchy"); final Settings settings = Settings.builder() .put(Environment.PATH_CONF_SETTING.getKey(), configDir.toAbsolutePath()) .put(Environment.PATH_HOME_SETTING.getKey(), createTempDir().toString()) .build(); final Environment environment = new Environment(settings); LogConfigurator.configure(environment); assertThat(ESLoggerFactory.getLogger("x").getLevel(), equalTo(Level.TRACE)); assertThat(ESLoggerFactory.getLogger("x.y").getLevel(), equalTo(Level.DEBUG)); final Level level = randomFrom(Level.TRACE, Level.DEBUG, Level.INFO, Level.WARN, Level.ERROR); Loggers.setLevel(ESLoggerFactory.getLogger("x"), level); assertThat(ESLoggerFactory.getLogger("x").getLevel(), equalTo(level)); assertThat(ESLoggerFactory.getLogger("x.y").getLevel(), equalTo(level)); } public void testMissingConfigFile() { final Path configDir = getDataPath("does_not_exist"); final Settings settings = Settings.builder() .put(Environment.PATH_CONF_SETTING.getKey(), configDir.toAbsolutePath()) .put(Environment.PATH_HOME_SETTING.getKey(), createTempDir().toString()) .build(); final Environment environment = new Environment(settings); UserException e = expectThrows(UserException.class, () -> LogConfigurator.configure(environment)); assertThat(e, hasToString(containsString("no log4j2.properties found; tried"))); } public void testLoggingLevelsFromSettings() throws IOException, UserException { final Level rootLevel = randomFrom(Level.TRACE, Level.DEBUG, Level.INFO, Level.WARN, Level.ERROR); final Level fooLevel = randomFrom(Level.TRACE, Level.DEBUG, Level.INFO, Level.WARN, Level.ERROR); final Level barLevel = randomFrom(Level.TRACE, Level.DEBUG, Level.INFO, Level.WARN, Level.ERROR); final Path configDir = getDataPath("minimal"); final Settings settings = Settings.builder() .put(Environment.PATH_CONF_SETTING.getKey(), configDir.toAbsolutePath()) .put(Environment.PATH_HOME_SETTING.getKey(), createTempDir().toString()) .put("logger.level", rootLevel.name()) .put("logger.foo", fooLevel.name()) .put("logger.bar", barLevel.name()) .build(); final Environment environment = new Environment(settings); LogConfigurator.configure(environment); final LoggerContext ctx = (LoggerContext) LogManager.getContext(false); final Configuration config = ctx.getConfiguration(); final Map<String, LoggerConfig> loggerConfigs = config.getLoggers(); assertThat(loggerConfigs.size(), equalTo(3)); assertThat(loggerConfigs, hasKey("")); assertThat(loggerConfigs.get("").getLevel(), equalTo(rootLevel)); assertThat(loggerConfigs, hasKey("foo")); assertThat(loggerConfigs.get("foo").getLevel(), equalTo(fooLevel)); assertThat(loggerConfigs, hasKey("bar")); assertThat(loggerConfigs.get("bar").getLevel(), equalTo(barLevel)); assertThat(ctx.getLogger(randomAlphaOfLength(16)).getLevel(), equalTo(rootLevel)); } }