mirror of https://github.com/apache/nifi.git
NIFI-9374 Added Deprecation Logger
- Added nifi-deprecation-log module with interface and implementation using SLF4J - Updated standard logback.xml with nifi-deprecation.log appender - Updated NiFiLegacyCipherProvider with deprecation logging - Set Size, Time Policy, and Total Size Limit for Deprecation Log This closes #6300 Signed-off-by: Paul Grey <greyp@apache.org>
This commit is contained in:
parent
ca991a6805
commit
fa85a05a2b
|
@ -0,0 +1,37 @@
|
|||
<?xml version="1.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.
|
||||
-->
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>org.apache.nifi</groupId>
|
||||
<artifactId>nifi-commons</artifactId>
|
||||
<version>1.18.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>nifi-deprecation-log</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-inline</artifactId>
|
||||
<version>${mockito.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* 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.nifi.deprecation.log;
|
||||
|
||||
/**
|
||||
* Deprecation Exception provides stack traces referencing deprecated features or capabilities
|
||||
*/
|
||||
class DeprecationException extends RuntimeException {
|
||||
/**
|
||||
* Deprecation Exception package-private constructor for internal usage within Standard Deprecation Logger
|
||||
*
|
||||
* @param referenceClass Reference Class
|
||||
*/
|
||||
DeprecationException(final Class<?> referenceClass) {
|
||||
super(getMessage(referenceClass));
|
||||
}
|
||||
|
||||
private static String getMessage(final Class<?> referenceClass) {
|
||||
final ClassLoader classLoader = referenceClass.getClassLoader();
|
||||
return String.format("Reference Class [%s] ClassLoader [%s]", referenceClass.getName(), classLoader);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* 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.nifi.deprecation.log;
|
||||
|
||||
/**
|
||||
* Logger interface to indicate use of deprecated components or features
|
||||
*/
|
||||
public interface DeprecationLogger {
|
||||
/**
|
||||
* Log deprecation warning with optional arguments for message placeholders
|
||||
*
|
||||
* @param message Message required
|
||||
* @param arguments Variable array of arguments to populate message placeholders
|
||||
*/
|
||||
void warn(String message, Object... arguments);
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* 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.nifi.deprecation.log;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Logger Factory provides concrete instances of Deprecation Loggers
|
||||
*/
|
||||
public class DeprecationLoggerFactory {
|
||||
/**
|
||||
* Get Deprecation Logger for Reference Class
|
||||
*
|
||||
* @param referenceClass Reference Class for deriving Logger
|
||||
* @return Deprecation Logger
|
||||
*/
|
||||
public static DeprecationLogger getLogger(final Class<?> referenceClass) {
|
||||
Objects.requireNonNull(referenceClass, "Reference Class required");
|
||||
return new StandardDeprecationLogger(referenceClass);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
* 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.nifi.deprecation.log;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Standard implementation of Deprecation Logger based on SLF4J
|
||||
*/
|
||||
class StandardDeprecationLogger implements DeprecationLogger {
|
||||
private static final String LOGGER_NAME_FORMAT = "deprecation.%s";
|
||||
|
||||
private final Class<?> referenceClass;
|
||||
|
||||
private final Logger logger;
|
||||
|
||||
/**
|
||||
* Standard Deprecation Logger constructor with reference class for deriving logger
|
||||
*
|
||||
* @param referenceClass Reference Class
|
||||
*/
|
||||
StandardDeprecationLogger(final Class<?> referenceClass) {
|
||||
this.referenceClass = Objects.requireNonNull(referenceClass, "Reference Class required");
|
||||
this.logger = LoggerFactory.getLogger(String.format(LOGGER_NAME_FORMAT, referenceClass.getName()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Log deprecation warning with optional arguments for message placeholders and Deprecation Exception for tracking
|
||||
*
|
||||
* @param message Message required
|
||||
* @param arguments Variable array of arguments to populate message placeholders
|
||||
*/
|
||||
@Override
|
||||
public void warn(final String message, final Object... arguments) {
|
||||
Objects.requireNonNull(message, "Message required");
|
||||
final Object[] extendedArguments = getExtendedArguments(arguments);
|
||||
logger.warn(message, extendedArguments);
|
||||
}
|
||||
|
||||
private Object[] getExtendedArguments(final Object... arguments) {
|
||||
final Object[] messageArguments = arguments == null ? new Object[0] : arguments;
|
||||
final int messageArgumentsLength = messageArguments.length;
|
||||
|
||||
final Object[] extendedArguments = Arrays.copyOf(messageArguments, messageArgumentsLength + 1);
|
||||
extendedArguments[messageArgumentsLength] = new DeprecationException(referenceClass);
|
||||
|
||||
return extendedArguments;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* 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.nifi.deprecation.log;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class DeprecationExceptionTest {
|
||||
private static final Class<?> REFERENCE_CLASS = DeprecationExceptionTest.class;
|
||||
|
||||
@Test
|
||||
void testGetMessageReferenceClassFound() {
|
||||
final DeprecationException deprecationException = new DeprecationException(REFERENCE_CLASS);
|
||||
|
||||
final String message = deprecationException.getMessage();
|
||||
|
||||
assertTrue(message.contains(REFERENCE_CLASS.getName()));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* 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.nifi.deprecation.log;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
class DeprecationLoggerFactoryTest {
|
||||
|
||||
@Test
|
||||
void testGetLogger() {
|
||||
final DeprecationLogger deprecationLogger = DeprecationLoggerFactory.getLogger(DeprecationLoggerFactoryTest.class);
|
||||
|
||||
assertNotNull(deprecationLogger);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetLoggerClassRequired() {
|
||||
assertThrows(NullPointerException.class, () -> DeprecationLoggerFactory.getLogger(null));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
/*
|
||||
* 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.nifi.deprecation.log;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.ArgumentMatchers;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockedStatic;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.mockStatic;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class StandardDeprecationLoggerTest {
|
||||
private static final Class<?> REFERENCE_CLASS = StandardDeprecationLoggerTest.class;
|
||||
|
||||
private static final String LOGGER_NAME = String.format("deprecation.%s", REFERENCE_CLASS.getName());
|
||||
|
||||
private static final String MESSAGE = "Feature not used";
|
||||
|
||||
private static final String MESSAGE_PLACEHOLDER = "Feature not used [{}]";
|
||||
|
||||
private static final String PLACEHOLDER = "PLACEHOLDER";
|
||||
|
||||
@Mock
|
||||
Logger logger;
|
||||
|
||||
@Test
|
||||
void testWarn() {
|
||||
try (final MockedStatic<LoggerFactory> ignored = mockStatic(LoggerFactory.class)) {
|
||||
when(LoggerFactory.getLogger(eq(LOGGER_NAME))).thenReturn(logger);
|
||||
|
||||
final DeprecationLogger deprecationLogger = new StandardDeprecationLogger(REFERENCE_CLASS);
|
||||
|
||||
deprecationLogger.warn(MESSAGE);
|
||||
|
||||
verify(logger).warn(eq(MESSAGE), ArgumentMatchers.<Object[]>any());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testWarnArguments() {
|
||||
try (final MockedStatic<LoggerFactory> ignored = mockStatic(LoggerFactory.class)) {
|
||||
when(LoggerFactory.getLogger(eq(LOGGER_NAME))).thenReturn(logger);
|
||||
|
||||
final DeprecationLogger deprecationLogger = new StandardDeprecationLogger(REFERENCE_CLASS);
|
||||
|
||||
deprecationLogger.warn(MESSAGE_PLACEHOLDER, PLACEHOLDER);
|
||||
|
||||
verify(logger).warn(eq(MESSAGE_PLACEHOLDER), ArgumentMatchers.<Object[]>any());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -37,6 +37,11 @@
|
|||
<artifactId>nifi-utils</artifactId>
|
||||
<version>1.18.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.nifi</groupId>
|
||||
<artifactId>nifi-deprecation-log</artifactId>
|
||||
<version>1.18.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.nifi</groupId>
|
||||
<artifactId>nifi-security-utils-api</artifactId>
|
||||
|
|
|
@ -21,6 +21,9 @@ import java.io.InputStream;
|
|||
import java.io.OutputStream;
|
||||
import java.security.SecureRandom;
|
||||
import javax.crypto.Cipher;
|
||||
|
||||
import org.apache.nifi.deprecation.log.DeprecationLogger;
|
||||
import org.apache.nifi.deprecation.log.DeprecationLoggerFactory;
|
||||
import org.apache.nifi.processor.exception.ProcessException;
|
||||
import org.apache.nifi.security.util.EncryptionMethod;
|
||||
import org.apache.nifi.stream.io.StreamUtils;
|
||||
|
@ -40,9 +43,12 @@ import org.slf4j.LoggerFactory;
|
|||
public class NiFiLegacyCipherProvider extends OpenSSLPKCS5CipherProvider implements PBECipherProvider {
|
||||
private static final Logger logger = LoggerFactory.getLogger(NiFiLegacyCipherProvider.class);
|
||||
|
||||
private static final DeprecationLogger deprecationLogger = DeprecationLoggerFactory.getLogger(NiFiLegacyCipherProvider.class);
|
||||
|
||||
// Legacy magic number value
|
||||
private static final int ITERATION_COUNT = 1000;
|
||||
|
||||
|
||||
/**
|
||||
* Returns an initialized cipher for the specified algorithm. The key (and IV if necessary) are derived using the NiFi legacy code, based on @see org.apache.nifi.crypto
|
||||
* .OpenSSLPKCS5CipherProvider#getCipher(java.lang.String, java.lang.String, java.lang.String, byte[], boolean) [essentially {@code MD5(password || salt) * 1000 }].
|
||||
|
@ -57,6 +63,7 @@ public class NiFiLegacyCipherProvider extends OpenSSLPKCS5CipherProvider impleme
|
|||
*/
|
||||
@Override
|
||||
public Cipher getCipher(EncryptionMethod encryptionMethod, String password, byte[] salt, int keyLength, boolean encryptMode) throws Exception {
|
||||
deprecationLogger.warn("Insecure Cipher Provider Algorithm [{}] cipher requested", encryptionMethod.getAlgorithm());
|
||||
try {
|
||||
// This method is defined in the OpenSSL implementation and just uses a locally-overridden iteration count
|
||||
return getInitializedCipher(encryptionMethod, password, salt, encryptMode);
|
||||
|
@ -68,6 +75,7 @@ public class NiFiLegacyCipherProvider extends OpenSSLPKCS5CipherProvider impleme
|
|||
}
|
||||
|
||||
public byte[] generateSalt(EncryptionMethod encryptionMethod) {
|
||||
deprecationLogger.warn("Insecure Cipher Provider Algorithm [{}] generate salt requested", encryptionMethod.getAlgorithm());
|
||||
byte[] salt = new byte[calculateSaltLength(encryptionMethod)];
|
||||
new SecureRandom().nextBytes(salt);
|
||||
return salt;
|
||||
|
@ -106,6 +114,7 @@ public class NiFiLegacyCipherProvider extends OpenSSLPKCS5CipherProvider impleme
|
|||
* @return the salt
|
||||
*/
|
||||
public byte[] readSalt(EncryptionMethod encryptionMethod, InputStream in) throws IOException {
|
||||
deprecationLogger.warn("Insecure Cipher Provider Algorithm [{}] read salt requested", encryptionMethod.getAlgorithm());
|
||||
if (in == null) {
|
||||
throw new IllegalArgumentException("Cannot read salt from null InputStream");
|
||||
}
|
||||
|
@ -122,6 +131,7 @@ public class NiFiLegacyCipherProvider extends OpenSSLPKCS5CipherProvider impleme
|
|||
|
||||
@Override
|
||||
public void writeSalt(byte[] salt, OutputStream out) throws IOException {
|
||||
deprecationLogger.warn("Insecure Cipher Provider write salt requested");
|
||||
if (out == null) {
|
||||
throw new IllegalArgumentException("Cannot write salt to null OutputStream");
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
<module>nifi-bootstrap-utils</module>
|
||||
<module>nifi-build</module>
|
||||
<module>nifi-data-provenance-utils</module>
|
||||
<module>nifi-deprecation-log</module>
|
||||
<module>nifi-expression-language</module>
|
||||
<module>nifi-external-resource-utils</module>
|
||||
<module>nifi-flowfile-packager</module>
|
||||
|
|
|
@ -88,6 +88,19 @@
|
|||
</encoder>
|
||||
</appender>
|
||||
|
||||
<appender name="DEPRECATION_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
<file>${org.apache.nifi.bootstrap.config.log.dir}/nifi-deprecation.log</file>
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
|
||||
<fileNamePattern>${org.apache.nifi.bootstrap.config.log.dir}/nifi-deprecation_%d.%i.log</fileNamePattern>
|
||||
<maxFileSize>10MB</maxFileSize>
|
||||
<maxHistory>10</maxHistory>
|
||||
<totalSizeCap>100MB</totalSizeCap>
|
||||
</rollingPolicy>
|
||||
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
|
||||
<pattern>%date %level [%thread] %logger %msg%n</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
|
||||
<pattern>%date %level [%thread] %logger{40} %msg%n</pattern>
|
||||
|
@ -96,6 +109,11 @@
|
|||
|
||||
<!-- valid logging levels: TRACE, DEBUG, INFO, WARN, ERROR -->
|
||||
|
||||
<!-- Deprecation Log -->
|
||||
<logger name="deprecation" level="WARN" additivity="false">
|
||||
<appender-ref ref="DEPRECATION_FILE"/>
|
||||
</logger>
|
||||
|
||||
<logger name="org.apache.nifi" level="INFO"/>
|
||||
<logger name="org.apache.nifi.processors" level="WARN"/>
|
||||
<logger name="org.apache.nifi.processors.standard.LogAttribute" level="INFO"/>
|
||||
|
|
Loading…
Reference in New Issue