Repository: logging-log4j2 Updated Branches: refs/heads/master 5b2df230d -> 9d32793b1
[LOG4J2-1699] Configurable Log File Permissions with PosixFilePermission. Apply patch. Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo Commit: http://git-wip-us.apache.org/repos/asf/logging-log4j2/commit/9d32793b Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/9d32793b Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/9d32793b Branch: refs/heads/master Commit: 9d32793b12e2fe9b7a77519e59f5027942db4917 Parents: 5b2df23 Author: Pierrick HYMBERT <[email protected]> Authored: Thu Jun 22 21:51:30 2017 -0700 Committer: Gary Gregory <[email protected]> Committed: Thu Jun 22 21:51:30 2017 -0700 ---------------------------------------------------------------------- .../rolling/DefaultRolloverStrategy.java | 20 +- .../rolling/DirectWriteRolloverStrategy.java | 20 +- .../action/PosixViewAttributeAction.java | 216 ++++++++++++---- .../logging/log4j/core/util/FileUtils.java | 9 + .../appender/FileAppenderPermissionsTest.java | 211 ++++++++++++++++ .../FileAppenderPermissionsXmlConfigTest.java | 66 +++++ .../core/appender/FilePermissionsTest.java | 244 ------------------- ...lingAppenderSizeCompressPermissionsTest.java | 9 +- 8 files changed, 492 insertions(+), 303 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/9d32793b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/DefaultRolloverStrategy.java ---------------------------------------------------------------------- diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/DefaultRolloverStrategy.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/DefaultRolloverStrategy.java index a91a453..4141195 100644 --- a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/DefaultRolloverStrategy.java +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/DefaultRolloverStrategy.java @@ -356,14 +356,18 @@ public class DefaultRolloverStrategy extends AbstractRolloverStrategy { if (manager.isPosixSupported()) { // Propagate posix attribute view to rolled/compressed file - Action posixAttributeViewAction = new PosixViewAttributeAction(compressedName, - false, - 1, - new PathCondition[0], - getStrSubstitutor(), - manager.getFilePermissions(), - manager.getFileOwner(), - manager.getFileGroup()); + // @formatter:off + Action posixAttributeViewAction = PosixViewAttributeAction.newBuilder() + .withBasePath(compressedName) + .withFollowLinks(false) + .withMaxDepth(1) + .withPathConditions(new PathCondition[0]) + .withSubst(getStrSubstitutor()) + .withFilePermissions(manager.getFilePermissions()) + .withFileOwner(manager.getFileOwner()) + .withFileGroup(manager.getFileGroup()) + .build(); + // @formatter:on if (compressAction == null) { compressAction = posixAttributeViewAction; } else { http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/9d32793b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/DirectWriteRolloverStrategy.java ---------------------------------------------------------------------- diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/DirectWriteRolloverStrategy.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/DirectWriteRolloverStrategy.java index feff516..6ce58d8 100644 --- a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/DirectWriteRolloverStrategy.java +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/DirectWriteRolloverStrategy.java @@ -197,14 +197,18 @@ public class DirectWriteRolloverStrategy extends AbstractRolloverStrategy implem if (manager.isPosixSupported()) { // Propagate posix attribute view to rolled/compressed file - Action posixAttributeViewAction = new PosixViewAttributeAction(compressedName, - false, - 1, - new PathCondition[0], - getStrSubstitutor(), - manager.getFilePermissions(), - manager.getFileOwner(), - manager.getFileGroup()); + // @formatter:off + Action posixAttributeViewAction = PosixViewAttributeAction.newBuilder() + .withBasePath(compressedName) + .withFollowLinks(false) + .withMaxDepth(1) + .withPathConditions(new PathCondition[0]) + .withSubst(getStrSubstitutor()) + .withFilePermissions(manager.getFilePermissions()) + .withFileOwner(manager.getFileOwner()) + .withFileGroup(manager.getFileGroup()) + .build(); + // @formatter:on if (compressAction == null) { compressAction = posixAttributeViewAction; } else { http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/9d32793b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/action/PosixViewAttributeAction.java ---------------------------------------------------------------------- diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/action/PosixViewAttributeAction.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/action/PosixViewAttributeAction.java index 7603e75..d74fcbd 100644 --- a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/action/PosixViewAttributeAction.java +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/action/PosixViewAttributeAction.java @@ -32,15 +32,19 @@ import java.util.Set; import org.apache.logging.log4j.core.Core; import org.apache.logging.log4j.core.config.Configuration; import org.apache.logging.log4j.core.config.plugins.Plugin; -import org.apache.logging.log4j.core.config.plugins.PluginAttribute; +import org.apache.logging.log4j.core.config.plugins.PluginBuilderAttribute; +import org.apache.logging.log4j.core.config.plugins.PluginBuilderFactory; import org.apache.logging.log4j.core.config.plugins.PluginConfiguration; import org.apache.logging.log4j.core.config.plugins.PluginElement; -import org.apache.logging.log4j.core.config.plugins.PluginFactory; +import org.apache.logging.log4j.core.config.plugins.validation.constraints.Required; import org.apache.logging.log4j.core.lookup.StrSubstitutor; import org.apache.logging.log4j.core.util.FileUtils; +import org.apache.logging.log4j.util.Strings; /** - * File posix attribute action. + * File posix attribute view action. + * + * Allow to define file permissions, user and group for log files on posix supported OS. */ @Plugin(name = "PosixViewAttribute", category = Core.CATEGORY_NAME, printObject = true) public class PosixViewAttributeAction extends AbstractPathAction { @@ -60,19 +64,7 @@ public class PosixViewAttributeAction extends AbstractPathAction { */ private final String fileGroup; - /** - * Constructor of the posix view attribute action. - * - * @param basePath {@link AbstractPathAction#getBasePath()} - * @param followSymbolicLinks {@link AbstractPathAction#isFollowSymbolicLinks()} - * @param pathConditions {@link AbstractPathAction#getPathConditions()} - * @param subst {@link AbstractPathAction#getStrSubstitutor()} - * @param filePermissions Permissions to apply - * @param fileOwner File owner - * @param fileGroup File group - * @param followSymbolicLinks - */ - public PosixViewAttributeAction(final String basePath, final boolean followSymbolicLinks, + private PosixViewAttributeAction(final String basePath, final boolean followSymbolicLinks, final int maxDepth, final PathCondition[] pathConditions, final StrSubstitutor subst, final Set<PosixFilePermission> filePermissions, final String fileOwner, final String fileGroup) { @@ -82,35 +74,177 @@ public class PosixViewAttributeAction extends AbstractPathAction { this.fileGroup = fileGroup; } + @PluginBuilderFactory + public static Builder newBuilder() { + return new Builder(); + } + /** - * Creates a PosixViewAttributeAction action that defined posix attribute view on a file. - * - * @param basePath {@link AbstractPathAction#getBasePath()} - * @param followSymbolicLinks {@link AbstractPathAction#isFollowSymbolicLinks()} - * @param pathConditions {@link AbstractPathAction#getPathConditions()} - * @param subst {@link AbstractPathAction#getStrSubstitutor()} - * @param filePermissions File permissions - * @param fileOwner File owner - * @param fileGroup File group - * @return PosixViewAttribute action + * Builder for the posix view attribute action. */ - @PluginFactory - public static PosixViewAttributeAction createNameCondition( - // @formatter:off - @PluginAttribute("basePath") final String basePath, // - @PluginAttribute(value = "followLinks") final boolean followLinks, - @PluginAttribute(value = "maxDepth", defaultInt = 1) final int maxDepth, - @PluginElement("PathConditions") final PathCondition[] pathConditions, - @PluginAttribute("filePermissions") final String filePermissions, - @PluginAttribute("fileOwner") final String fileOwner, - @PluginAttribute("fileGroup") final String fileGroup, - @PluginConfiguration final Configuration config) { - // @formatter:on - return new PosixViewAttributeAction(basePath, followLinks, maxDepth, - pathConditions, config.getStrSubstitutor(), - filePermissions != null ? PosixFilePermissions.fromString(filePermissions) : null, + public static class Builder implements org.apache.logging.log4j.core.util.Builder<PosixViewAttributeAction> { + + @PluginConfiguration + private Configuration configuration; + + private StrSubstitutor subst; + + @PluginBuilderAttribute + @Required(message = "No base path provided") + private String basePath; + + @PluginBuilderAttribute + private boolean followLinks = false; + + @PluginBuilderAttribute + private int maxDepth = 1; + + @PluginElement("PathConditions") + private PathCondition[] pathConditions; + + @PluginBuilderAttribute(value = "filePermissions") + private String filePermissionsString; + + private Set<PosixFilePermission> filePermissions; + + @PluginBuilderAttribute + private String fileOwner; + + @PluginBuilderAttribute + private String fileGroup; + + @Override + public PosixViewAttributeAction build() { + if (Strings.isEmpty(basePath)) { + LOGGER.error("Posix file attribute view action not valid because base path is empty."); + return null; + } + + if (filePermissions == null && Strings.isEmpty(filePermissionsString) + && Strings.isEmpty(fileOwner) && Strings.isEmpty(fileGroup)) { + LOGGER.error("Posix file attribute view not valid because nor permissions, user and group defined."); + return null; + } + + if (!FileUtils.isFilePosixAttributeViewSupported()) { + LOGGER.warn("Posix file attribute view defined but it is not supported by this file system."); +// return null; // FIXME Should we avoid operations not permitted or unsupported exception ? + } + + return new PosixViewAttributeAction(basePath, followLinks, maxDepth, pathConditions, + subst != null ? subst : configuration.getStrSubstitutor(), + filePermissions != null ? filePermissions : + filePermissionsString != null ? PosixFilePermissions.fromString(filePermissionsString) : null, fileOwner, fileGroup); + } + + /** + * Define required configuration, used to retrieve string substituter. + * + * @param configuration {@link AbstractPathAction#getStrSubstitutor()} + * @return This builder + */ + public Builder withConfiguration(Configuration configuration) { + this.configuration = configuration; + return this; + } + + /** + * Define string substituter. + * + * @param subst {@link AbstractPathAction#getStrSubstitutor()} + * @return This builder + */ + public Builder withSubst(StrSubstitutor subst) { + this.subst = subst; + return this; + } + + /** + * Define base path to apply condition before execute posix file attribute action. + * @param basePath {@link AbstractPathAction#getBasePath()} + * @return This builder + */ + public Builder withBasePath(String basePath) { + this.basePath = basePath; + return this; + } + + /** + * True to allow synonyms links during search of eligible files. + * @param followLinks Follow synonyms links + * @return This builder + */ + public Builder withFollowLinks(boolean followLinks) { + this.followLinks = followLinks; + return this; + } + + /** + * Define max folder depth to search for eligible files to apply posix attribute view. + * @param maxDepth Max search depth + * @return This builder + */ + public Builder withMaxDepth(int maxDepth) { + this.maxDepth = maxDepth; + return this; + } + + /** + * Define path conditions to filter files in {@link PosixViewAttributeAction#getBasePath()}. + * + * @param pathConditions {@link AbstractPathAction#getPathConditions()} + * @return This builder + */ + public Builder withPathConditions(PathCondition[] pathConditions) { + this.pathConditions = pathConditions; + return this; + } + + /** + * Define file permissions in posix format to apply during action execution eligible files. + * + * Example: + * <p>rw-rw-rw + * <p>r--r--r-- + * @param filePermissionsString Permissions to apply + * @return This builder + */ + public Builder withFilePermissionsString(String filePermissionsString) { + this.filePermissionsString = filePermissionsString; + return this; + } + + /** + * Define file permissions to apply during action execution eligible files. + * @param filePermissions Permissions to apply + * @return This builder + */ + public Builder withFilePermissions(Set<PosixFilePermission> filePermissions) { + this.filePermissions = filePermissions; + return this; + } + + /** + * Define file owner to apply during action execution eligible files. + * @param fileOwner File owner + * @return This builder + */ + public Builder withFileOwner(String fileOwner) { + this.fileOwner = fileOwner; + return this; + } + + /** + * Define file group to apply during action execution eligible files. + * @param fileGroup File group + * @return This builder + */ + public Builder withFileGroup(String fileGroup) { + this.fileGroup = fileGroup; + return this; + } } @Override http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/9d32793b/log4j-core/src/main/java/org/apache/logging/log4j/core/util/FileUtils.java ---------------------------------------------------------------------- diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/util/FileUtils.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/util/FileUtils.java index f82e738..c486d64 100644 --- a/log4j-core/src/main/java/org/apache/logging/log4j/core/util/FileUtils.java +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/util/FileUtils.java @@ -186,4 +186,13 @@ public final class FileUtils { } } } + + /** + * Check if posix file attribute view is supported on the default FileSystem. + * + * @return true if posix file attribute view supported, false otherwise + */ + public static boolean isFilePosixAttributeViewSupported() { + return FileSystems.getDefault().supportedFileAttributeViews().contains("posix"); + } } http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/9d32793b/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/FileAppenderPermissionsTest.java ---------------------------------------------------------------------- diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/FileAppenderPermissionsTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/FileAppenderPermissionsTest.java new file mode 100644 index 0000000..ec12e00 --- /dev/null +++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/FileAppenderPermissionsTest.java @@ -0,0 +1,211 @@ +/* + * 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.logging.log4j.core.appender; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.nio.charset.Charset; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.attribute.PosixFileAttributes; +import java.nio.file.attribute.PosixFilePermissions; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; + +import org.apache.logging.log4j.Level; +import org.apache.logging.log4j.core.Layout; +import org.apache.logging.log4j.core.LogEvent; +import org.apache.logging.log4j.core.impl.Log4jLogEvent; +import org.apache.logging.log4j.core.layout.PatternLayout; +import org.apache.logging.log4j.core.util.FileUtils; +import org.apache.logging.log4j.message.SimpleMessage; +import org.junit.Assert; +import org.junit.Assume; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +/** + * Tests {@link FileAppender}. + */ +@RunWith(Parameterized.class) +public class FileAppenderPermissionsTest { + + private static final String DIR = "target/permissions1"; + + @Parameterized.Parameters(name = "{0} {1} {2}") + public static Collection<Object[]> data() throws IOException { + return Arrays.asList(new Object[][] { // + // @formatter:off + {"rwxrwxrwx", true, 2}, + {"rw-r--r--", false, 3}, + {"rw-------", true, 4}, + {"rw-rw----", false, 5}, + }); + // @formatter:on + } + + private final boolean createOnDemand; + private final String filePermissions; + private final int fileIndex; + + public FileAppenderPermissionsTest(final String filePermissions, final boolean createOnDemand, final int fileIndex) { + this.filePermissions = filePermissions; + this.createOnDemand = createOnDemand; + this.fileIndex = fileIndex; + } + + @BeforeClass + public static void beforeClass() { + Assume.assumeTrue(FileUtils.isFilePosixAttributeViewSupported()); + } + + @Test + public void testFilePermissionsAPI() throws Exception { + final File file = new File(DIR, "AppenderTest-" + fileIndex + ".log"); + final Path path = file.toPath(); + final Layout<String> layout = PatternLayout.newBuilder().withPattern(PatternLayout.SIMPLE_CONVERSION_PATTERN) + .build(); + // @formatter:off + final FileAppender appender = FileAppender.newBuilder() + .withFileName(file.getAbsolutePath()) + .withName("test") + .withImmediateFlush(false) + .withIgnoreExceptions(false) + .withBufferedIo(false) + .withBufferSize(1) + .withLayout(layout) + .withCreateOnDemand(createOnDemand) + .withFilePermissions(filePermissions) + .build(); + // @formatter:on + try { + appender.start(); + assertTrue("Appender did not start", appender.isStarted()); + Assert.assertNotEquals(createOnDemand, Files.exists(path)); + long curLen = file.length(); + long prevLen = curLen; + assertTrue("File length: " + curLen, curLen == 0); + for (int i = 0; i < 100; ++i) { + final LogEvent event = Log4jLogEvent.newBuilder().setLoggerName("TestLogger") // + .setLoggerFqcn(FileAppenderPermissionsTest.class.getName()).setLevel(Level.INFO) // + .setMessage(new SimpleMessage("Test")).setThreadName(this.getClass().getSimpleName()) // + .setTimeMillis(System.currentTimeMillis()).build(); + try { + appender.append(event); + curLen = file.length(); + assertTrue("File length: " + curLen, curLen > prevLen); + // Give up control long enough for another thread/process to occasionally do something. + Thread.sleep(25); + } catch (final Exception ex) { + throw ex; + } + prevLen = curLen; + } + assertEquals(filePermissions, PosixFilePermissions.toString(Files.getPosixFilePermissions(path))); + } finally { + appender.stop(); + } + assertFalse("Appender did not stop", appender.isStarted()); + } + + @Test + public void testFileUserGroupAPI() throws Exception { + final File file = new File(DIR, "AppenderTest-" + (1000 + fileIndex) + ".log"); + final Path path = file.toPath(); + String user = findAUser(); + assertNotNull(user); + String group = findAGroup(user); + assertNotNull(group); + + final Layout<String> layout = PatternLayout.newBuilder().withPattern(PatternLayout.SIMPLE_CONVERSION_PATTERN) + .build(); + // @formatter:off + final FileAppender appender = FileAppender.newBuilder() + .withFileName(file.getAbsolutePath()) + .withName("test") + .withImmediateFlush(true) + .withIgnoreExceptions(false) + .withBufferedIo(false) + .withBufferSize(1) + .withLayout(layout) + .withFilePermissions(filePermissions) + .withFileOwner(user) + .withFileGroup(group) + .build(); + // @formatter:on + try { + appender.start(); + assertTrue("Appender did not start", appender.isStarted()); + long curLen = file.length(); + long prevLen = curLen; + assertTrue(file + " File length: " + curLen, curLen == 0); + for (int i = 0; i < 100; ++i) { + final LogEvent event = Log4jLogEvent.newBuilder().setLoggerName("TestLogger") // + .setLoggerFqcn(FileAppenderPermissionsTest.class.getName()).setLevel(Level.INFO) // + .setMessage(new SimpleMessage("Test")).setThreadName(this.getClass().getSimpleName()) // + .setTimeMillis(System.currentTimeMillis()).build(); + try { + appender.append(event); + curLen = file.length(); + assertTrue("File length: " + curLen, curLen > prevLen); + // Give up control long enough for another thread/process to occasionally do something. + Thread.sleep(25); + } catch (final Exception ex) { + throw ex; + } + prevLen = curLen; + } + assertEquals(filePermissions, PosixFilePermissions.toString(Files.getPosixFilePermissions(path))); + assertEquals(user, Files.getOwner(path).getName()); + assertEquals(group, Files.readAttributes(path, PosixFileAttributes.class).group().getName()); + } finally { + appender.stop(); + } + assertFalse("Appender did not stop", appender.isStarted()); + } + + public static String findAGroup(String user) throws IOException { + String group = user; + try (FileInputStream fis = new FileInputStream("/etc/group")) { + List<String> groups = org.apache.commons.io.IOUtils.readLines(fis, Charset.defaultCharset()); + for (int i = 0; i < groups.size(); i++) { + String aGroup = groups.get(i); + if (!aGroup.startsWith(user) && aGroup.contains(user)) { + group = aGroup.split(":")[0]; + break; + } + } + } + return group; + } + + private static String findAUser() throws IOException { + // On jenkins build within ubuntu, it is not possible to chmod to another user + return System.getProperty("user.name"); + } + + +} http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/9d32793b/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/FileAppenderPermissionsXmlConfigTest.java ---------------------------------------------------------------------- diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/FileAppenderPermissionsXmlConfigTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/FileAppenderPermissionsXmlConfigTest.java new file mode 100644 index 0000000..941e785 --- /dev/null +++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/FileAppenderPermissionsXmlConfigTest.java @@ -0,0 +1,66 @@ +/* + * 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.logging.log4j.core.appender; + +import static org.junit.Assert.assertEquals; + +import java.nio.file.Files; +import java.nio.file.Paths; +import java.nio.file.attribute.PosixFilePermissions; + +import org.apache.logging.log4j.Logger; +import org.apache.logging.log4j.core.util.FileUtils; +import org.apache.logging.log4j.junit.LoggerContextRule; +import org.junit.Assume; +import org.junit.BeforeClass; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.RuleChain; + +/** + * Tests {@link FileAppender}. + */ +public class FileAppenderPermissionsXmlConfigTest { + + private static final String DIR = "target/permissions1"; + + private static final String CONFIG = "log4j-posix.xml"; + + public static LoggerContextRule loggerContextRule = LoggerContextRule.createShutdownTimeoutLoggerContextRule(CONFIG); + + @Rule + public RuleChain chain = loggerContextRule.withCleanFoldersRule(DIR); + + @BeforeClass + public static void beforeClass() { + Assume.assumeTrue(FileUtils.isFilePosixAttributeViewSupported()); + } + + @Test + public void testFilePermissions() throws Exception { + Logger logger = loggerContextRule.getLogger(FileAppenderPermissionsTest.class); + for (int i = 0; i < 1000; ++i) { + String message = "This is test message number " + i; + logger.debug(message); + } + assertEquals("rw-------", PosixFilePermissions.toString( + Files.getPosixFilePermissions(Paths.get("target/permissions1/AppenderTest-1.log")))); + } + + +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/9d32793b/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/FilePermissionsTest.java ---------------------------------------------------------------------- diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/FilePermissionsTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/FilePermissionsTest.java deleted file mode 100644 index 40c4e7b..0000000 --- a/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/FilePermissionsTest.java +++ /dev/null @@ -1,244 +0,0 @@ -/* - * 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.logging.log4j.core.appender; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; - -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.nio.charset.Charset; -import java.nio.file.FileSystems; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.nio.file.attribute.PosixFileAttributes; -import java.nio.file.attribute.PosixFilePermissions; -import java.util.Arrays; -import java.util.Collection; -import java.util.List; - -import org.apache.logging.log4j.Level; -import org.apache.logging.log4j.Logger; -import org.apache.logging.log4j.core.Layout; -import org.apache.logging.log4j.core.LogEvent; -import org.apache.logging.log4j.core.impl.Log4jLogEvent; -import org.apache.logging.log4j.core.layout.PatternLayout; -import org.apache.logging.log4j.junit.LoggerContextRule; -import org.apache.logging.log4j.message.SimpleMessage; -import org.junit.Assert; -import org.junit.Assume; -import org.junit.BeforeClass; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.RuleChain; -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; - -/** - * Tests {@link FileAppender}. - */ -public class FilePermissionsTest { - - private static final String DIR = "target/permissions1"; - - @RunWith(Parameterized.class) - public static final class TestParameterized { - - @Parameterized.Parameters(name = "{0} {1} {2}") - public static Collection<Object[]> data() throws IOException { - return Arrays.asList(new Object[][] { // - // @formatter:off - {"rwxrwxrwx", true, 2}, - {"rw-r--r--", false, 3}, - {"rw-------", true, 4}, - {"rw-rw----", false, 5}, - }); - // @formatter:on - } - - private final boolean createOnDemand; - private final String filePermissions; - private final int fileIndex; - - public TestParameterized(final String filePermissions, final boolean createOnDemand, final int fileIndex) { - this.filePermissions = filePermissions; - this.createOnDemand = createOnDemand; - this.fileIndex = fileIndex; - } - - @BeforeClass - public static void beforeClass() { - Assume.assumeTrue(FileSystems.getDefault().supportedFileAttributeViews().contains("posix")); - } - - @Test - public void testFilePermissionsAPI() throws Exception { - final File file = new File(DIR, "AppenderTest-" + fileIndex + ".log"); - final Path path = file.toPath(); - final Layout<String> layout = PatternLayout.newBuilder().withPattern(PatternLayout.SIMPLE_CONVERSION_PATTERN) - .build(); - // @formatter:off - final FileAppender appender = FileAppender.newBuilder() - .withFileName(file.getAbsolutePath()) - .withName("test") - .withImmediateFlush(false) - .withIgnoreExceptions(false) - .withBufferedIo(false) - .withBufferSize(1) - .withLayout(layout) - .withCreateOnDemand(createOnDemand) - .withFilePermissions(filePermissions) - .build(); - // @formatter:on - try { - appender.start(); - assertTrue("Appender did not start", appender.isStarted()); - Assert.assertNotEquals(createOnDemand, Files.exists(path)); - long curLen = file.length(); - long prevLen = curLen; - assertTrue("File length: " + curLen, curLen == 0); - for (int i = 0; i < 100; ++i) { - final LogEvent event = Log4jLogEvent.newBuilder().setLoggerName("TestLogger") // - .setLoggerFqcn(FilePermissionsTest.class.getName()).setLevel(Level.INFO) // - .setMessage(new SimpleMessage("Test")).setThreadName(this.getClass().getSimpleName()) // - .setTimeMillis(System.currentTimeMillis()).build(); - try { - appender.append(event); - curLen = file.length(); - assertTrue("File length: " + curLen, curLen > prevLen); - // Give up control long enough for another thread/process to occasionally do something. - Thread.sleep(25); - } catch (final Exception ex) { - throw ex; - } - prevLen = curLen; - } - assertEquals(filePermissions, PosixFilePermissions.toString(Files.getPosixFilePermissions(path))); - } finally { - appender.stop(); - } - assertFalse("Appender did not stop", appender.isStarted()); - } - - } - - public static class TestNotParameterized { - private static final String CONFIG = "log4j-posix.xml"; - - public static LoggerContextRule loggerContextRule = LoggerContextRule.createShutdownTimeoutLoggerContextRule(CONFIG); - - @Rule - public RuleChain chain = loggerContextRule.withCleanFoldersRule(DIR); - - @BeforeClass - public static void beforeClass() { - Assume.assumeTrue(FileSystems.getDefault().supportedFileAttributeViews().contains("posix")); - } - - @Test - public void testFilePermissions() throws Exception { - Logger logger = loggerContextRule.getLogger(FilePermissionsTest.class); - for (int i = 0; i < 1000; ++i) { - String message = "This is test message number " + i; - logger.debug(message); - } - assertEquals("rw-------", PosixFilePermissions.toString( - Files.getPosixFilePermissions(Paths.get("target/permissions1/AppenderTest-1.log")))); - } - - @Test - public void testFileUserGroupAPI() throws Exception { - final File file = new File(DIR, "AppenderTest-0.log"); - final Path path = file.toPath(); - String user = findAUser(); - assertNotNull(user); - String group = findAGroup(user); - assertNotNull(group); - String filePermissions = "rw-rw-rw-"; - - final Layout<String> layout = PatternLayout.newBuilder().withPattern(PatternLayout.SIMPLE_CONVERSION_PATTERN) - .build(); - // @formatter:off - final FileAppender appender = FileAppender.newBuilder() - .withFileName(file.getAbsolutePath()) - .withName("test") - .withImmediateFlush(true) - .withIgnoreExceptions(false) - .withBufferedIo(false) - .withBufferSize(1) - .withLayout(layout) - .withFilePermissions(filePermissions) - .withFileOwner(user) - .withFileGroup(group) - .build(); - // @formatter:on - try { - appender.start(); - assertTrue("Appender did not start", appender.isStarted()); - long curLen = file.length(); - long prevLen = curLen; - assertTrue("File length: " + curLen, curLen == 0); - for (int i = 0; i < 100; ++i) { - final LogEvent event = Log4jLogEvent.newBuilder().setLoggerName("TestLogger") // - .setLoggerFqcn(FilePermissionsTest.class.getName()).setLevel(Level.INFO) // - .setMessage(new SimpleMessage("Test")).setThreadName(this.getClass().getSimpleName()) // - .setTimeMillis(System.currentTimeMillis()).build(); - try { - appender.append(event); - curLen = file.length(); - assertTrue("File length: " + curLen, curLen > prevLen); - // Give up control long enough for another thread/process to occasionally do something. - Thread.sleep(25); - } catch (final Exception ex) { - throw ex; - } - prevLen = curLen; - } - assertEquals(filePermissions, PosixFilePermissions.toString(Files.getPosixFilePermissions(path))); - assertEquals(user, Files.getOwner(path).getName()); - assertEquals(group, Files.readAttributes(path, PosixFileAttributes.class).group().getName()); - } finally { - appender.stop(); - } - assertFalse("Appender did not stop", appender.isStarted()); - } - - public static String findAGroup(String user) throws IOException { - String group = null; - try (FileInputStream fis = new FileInputStream("/etc/group")) { - List<String> groups = org.apache.commons.io.IOUtils.readLines(fis, Charset.defaultCharset()); - for (int i = 0; i < groups.size(); i++) { - String aGroup = groups.get(i); - if (!aGroup.startsWith(user) && aGroup.contains(user)) { - group = aGroup.split(":")[0]; - break; - } - } - } - return group; - } - - private static String findAUser() throws IOException { - // On jenkins build within ubuntu, it is not possible to chmod to another user - return System.getProperty("user.name"); - } - } -} http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/9d32793b/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/rolling/RollingAppenderSizeCompressPermissionsTest.java ---------------------------------------------------------------------- diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/rolling/RollingAppenderSizeCompressPermissionsTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/rolling/RollingAppenderSizeCompressPermissionsTest.java index c57705b..0ea11f7 100644 --- a/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/rolling/RollingAppenderSizeCompressPermissionsTest.java +++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/rolling/RollingAppenderSizeCompressPermissionsTest.java @@ -19,15 +19,16 @@ import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import java.io.File; -import java.nio.file.FileSystems; import java.nio.file.Files; import java.nio.file.attribute.PosixFilePermissions; import java.util.concurrent.TimeUnit; import org.apache.logging.log4j.Logger; +import org.apache.logging.log4j.core.util.FileUtils; import org.apache.logging.log4j.junit.LoggerContextRule; import org.junit.Assume; import org.junit.Before; +import org.junit.BeforeClass; import org.junit.Rule; import org.junit.Test; import org.junit.rules.RuleChain; @@ -49,6 +50,11 @@ public class RollingAppenderSizeCompressPermissionsTest { private Logger logger; + @BeforeClass + public static void beforeClass() { + Assume.assumeTrue(FileUtils.isFilePosixAttributeViewSupported()); + } + @Before public void setUp() throws Exception { this.logger = loggerContextRule.getLogger(RollingAppenderSizeCompressPermissionsTest.class.getName()); @@ -56,7 +62,6 @@ public class RollingAppenderSizeCompressPermissionsTest { @Test public void testAppenderCompressPermissions() throws Exception { - Assume.assumeTrue(FileSystems.getDefault().supportedFileAttributeViews().contains("posix")); for (int i = 0; i < 500; ++i) { String message = "This is test message number " + i; logger.debug(message);
