diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-jetty/src/main/java/org/apache/nifi/web/server/connector/FrameworkServerConnectorFactory.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-jetty/src/main/java/org/apache/nifi/web/server/connector/FrameworkServerConnectorFactory.java index c434010f3d..829a5578f6 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-jetty/src/main/java/org/apache/nifi/web/server/connector/FrameworkServerConnectorFactory.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-jetty/src/main/java/org/apache/nifi/web/server/connector/FrameworkServerConnectorFactory.java @@ -27,10 +27,9 @@ import org.apache.nifi.security.util.TlsException; import org.apache.nifi.security.util.TlsPlatform; import org.apache.nifi.util.FormatUtils; import org.apache.nifi.util.NiFiProperties; -import org.apache.nifi.web.server.util.TrustStoreScanner; +import org.apache.nifi.web.server.util.StoreScanner; import org.eclipse.jetty.server.HttpConfiguration; import org.eclipse.jetty.server.Server; -import org.eclipse.jetty.util.ssl.KeyStoreScanner; import org.eclipse.jetty.util.ssl.SslContextFactory; import javax.net.ssl.SSLContext; @@ -149,12 +148,12 @@ public class FrameworkServerConnectorFactory extends StandardServerConnectorFact if (storeScanInterval != null) { sslContextFactory.setKeyStorePath(tlsConfiguration.getKeystorePath()); - final KeyStoreScanner keyStoreScanner = new KeyStoreScanner(sslContextFactory); + final StoreScanner keyStoreScanner = new StoreScanner(sslContextFactory, tlsConfiguration, sslContextFactory.getKeyStoreResource()); keyStoreScanner.setScanInterval(storeScanInterval); getServer().addBean(keyStoreScanner); sslContextFactory.setTrustStorePath(tlsConfiguration.getTruststorePath()); - final TrustStoreScanner trustStoreScanner = new TrustStoreScanner(sslContextFactory); + final StoreScanner trustStoreScanner = new StoreScanner(sslContextFactory, tlsConfiguration, sslContextFactory.getTrustStoreResource()); trustStoreScanner.setScanInterval(storeScanInterval); getServer().addBean(trustStoreScanner); } diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-jetty/src/main/java/org/apache/nifi/web/server/util/StoreScanner.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-jetty/src/main/java/org/apache/nifi/web/server/util/StoreScanner.java new file mode 100644 index 0000000000..daf7c02db4 --- /dev/null +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-jetty/src/main/java/org/apache/nifi/web/server/util/StoreScanner.java @@ -0,0 +1,158 @@ +/* + * 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.web.server.util; + +import org.apache.nifi.security.util.TlsConfiguration; +import org.apache.nifi.security.util.TlsException; +import org.eclipse.jetty.util.Scanner; +import org.eclipse.jetty.util.annotation.ManagedAttribute; +import org.eclipse.jetty.util.annotation.ManagedOperation; +import org.eclipse.jetty.util.component.ContainerLifeCycle; +import org.eclipse.jetty.util.log.Log; +import org.eclipse.jetty.util.log.Logger; +import org.eclipse.jetty.util.resource.Resource; +import org.eclipse.jetty.util.ssl.SslContextFactory; + +import javax.net.ssl.SSLContext; +import java.io.File; +import java.io.IOException; +import java.util.Collections; + +import static org.apache.nifi.security.util.SslContextFactory.createSslContext; + +/** + * File Scanner for Keystore or Truststore reloading using provided TLS Configuration + */ +public class StoreScanner extends ContainerLifeCycle implements Scanner.DiscreteListener { + private static final Logger LOG = Log.getLogger(StoreScanner.class); + + private final SslContextFactory sslContextFactory; + private final TlsConfiguration tlsConfiguration; + private final File file; + private final Scanner scanner; + private final String resourceName; + + public StoreScanner(final SslContextFactory sslContextFactory, + final TlsConfiguration tlsConfiguration, + final Resource resource) { + this.sslContextFactory = sslContextFactory; + this.tlsConfiguration = tlsConfiguration; + this.resourceName = resource.getName(); + try { + File monitoredFile = resource.getFile(); + if (monitoredFile == null || !monitoredFile.exists()) { + throw new IllegalArgumentException(String.format("%s file does not exist", resourceName)); + } + if (monitoredFile.isDirectory()) { + throw new IllegalArgumentException(String.format("expected %s file not directory", resourceName)); + } + + if (resource.getAlias() != null) { + // this resource has an alias, use the alias, as that's what's returned in the Scanner + monitoredFile = new File(resource.getAlias()); + } + + file = monitoredFile; + if (LOG.isDebugEnabled()) { + LOG.debug("File monitoring started {} [{}]", resourceName, monitoredFile); + } + } catch (final IOException e) { + throw new IllegalArgumentException(String.format("could not obtain %s file", resourceName), e); + } + + File parentFile = file.getParentFile(); + if (!parentFile.exists() || !parentFile.isDirectory()) { + throw new IllegalArgumentException(String.format("error obtaining %s dir", resourceName)); + } + + scanner = new Scanner(); + scanner.setScanDirs(Collections.singletonList(parentFile)); + scanner.setScanInterval(1); + scanner.setReportDirs(false); + scanner.setReportExistingFilesOnStartup(false); + scanner.setScanDepth(1); + scanner.addListener(this); + addBean(scanner); + } + + @Override + public void fileAdded(final String filename) { + LOG.debug("Resource [{}] File [{}] added", resourceName, filename); + reloadMatched(filename); + } + + @Override + public void fileChanged(final String filename) { + LOG.debug("Resource [{}] File [{}] changed", resourceName, filename); + reloadMatched(filename); + } + + @Override + public void fileRemoved(final String filename) { + LOG.debug("Resource [{}] File [{}] removed", resourceName, filename); + reloadMatched(filename); + } + + @ManagedOperation( + value = "Scan for changes in the SSL Keystore/Truststore", + impact = "ACTION" + ) + public void scan() { + LOG.debug("Resource [{}] scanning started", resourceName); + + this.scanner.scan(); + this.scanner.scan(); + } + + @ManagedOperation( + value = "Reload the SSL Keystore/Truststore", + impact = "ACTION" + ) + public void reload() { + LOG.debug("File [{}] reload started", file); + + try { + this.sslContextFactory.reload(contextFactory -> contextFactory.setSslContext(createContext())); + LOG.info("File [{}] reload completed", file); + } catch (final Throwable t) { + LOG.warn("File [{}] reload failed", file, t); + } + } + + @ManagedAttribute("scanning interval to detect changes which need reloaded") + public int getScanInterval() { + return this.scanner.getScanInterval(); + } + + public void setScanInterval(int scanInterval) { + this.scanner.setScanInterval(scanInterval); + } + + private void reloadMatched(final String filename) { + if (file.toPath().toString().equals(filename)) { + reload(); + } + } + + private SSLContext createContext() { + try { + return createSslContext(tlsConfiguration); + } catch (final TlsException e) { + throw new IllegalArgumentException("Failed to create SSL context with the TLS configuration", e); + } + } +} diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-jetty/src/main/java/org/apache/nifi/web/server/util/TrustStoreScanner.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-jetty/src/main/java/org/apache/nifi/web/server/util/TrustStoreScanner.java deleted file mode 100644 index 22913ed811..0000000000 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-jetty/src/main/java/org/apache/nifi/web/server/util/TrustStoreScanner.java +++ /dev/null @@ -1,151 +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.nifi.web.server.util; - -import org.eclipse.jetty.util.Scanner; -import org.eclipse.jetty.util.annotation.ManagedAttribute; -import org.eclipse.jetty.util.annotation.ManagedOperation; -import org.eclipse.jetty.util.component.ContainerLifeCycle; -import org.eclipse.jetty.util.log.Log; -import org.eclipse.jetty.util.log.Logger; -import org.eclipse.jetty.util.resource.Resource; -import org.eclipse.jetty.util.ssl.SslContextFactory; - -import java.io.File; -import java.io.IOException; -import java.util.Collections; - -/** - *

The {@link TrustStoreScanner} is used to monitor the TrustStore file used by the {@link SslContextFactory}. - * It will reload the {@link SslContextFactory} if it detects that the TrustStore file has been modified.

- *

- * Though it would have been more ideal to simply extend KeyStoreScanner and override the keystore resource - * with the truststore resource, KeyStoreScanner's constructor was written in a way that doesn't make this possible. - */ -public class TrustStoreScanner extends ContainerLifeCycle implements Scanner.DiscreteListener { - private static final Logger LOG = Log.getLogger(TrustStoreScanner.class); - - private final SslContextFactory sslContextFactory; - private final File truststoreFile; - private final Scanner _scanner; - - public TrustStoreScanner(SslContextFactory sslContextFactory) { - this.sslContextFactory = sslContextFactory; - try { - Resource truststoreResource = sslContextFactory.getTrustStoreResource(); - File monitoredFile = truststoreResource.getFile(); - if (monitoredFile == null || !monitoredFile.exists()) { - throw new IllegalArgumentException("truststore file does not exist"); - } - if (monitoredFile.isDirectory()) { - throw new IllegalArgumentException("expected truststore file not directory"); - } - - if (truststoreResource.getAlias() != null) { - // this resource has an alias, use the alias, as that's what's returned in the Scanner - monitoredFile = new File(truststoreResource.getAlias()); - } - - truststoreFile = monitoredFile; - if (LOG.isDebugEnabled()) { - LOG.debug("Monitored Truststore File: {}", monitoredFile); - } - } catch (IOException e) { - throw new IllegalArgumentException("could not obtain truststore file", e); - } - - File parentFile = truststoreFile.getParentFile(); - if (!parentFile.exists() || !parentFile.isDirectory()) { - throw new IllegalArgumentException("error obtaining truststore dir"); - } - - _scanner = new Scanner(); - _scanner.setScanDirs(Collections.singletonList(parentFile)); - _scanner.setScanInterval(1); - _scanner.setReportDirs(false); - _scanner.setReportExistingFilesOnStartup(false); - _scanner.setScanDepth(1); - _scanner.addListener(this); - addBean(_scanner); - } - - @Override - public void fileAdded(String filename) { - if (LOG.isDebugEnabled()) { - LOG.debug("added {}", filename); - } - - if (truststoreFile.toPath().toString().equals(filename)) { - reload(); - } - } - - @Override - public void fileChanged(String filename) { - if (LOG.isDebugEnabled()) { - LOG.debug("changed {}", filename); - } - - if (truststoreFile.toPath().toString().equals(filename)) { - reload(); - } - } - - @Override - public void fileRemoved(String filename) { - if (LOG.isDebugEnabled()) { - LOG.debug("removed {}", filename); - } - - if (truststoreFile.toPath().toString().equals(filename)) { - reload(); - } - } - - @ManagedOperation(value = "Scan for changes in the SSL Truststore", impact = "ACTION") - public void scan() { - if (LOG.isDebugEnabled()) { - LOG.debug("scanning"); - } - - _scanner.scan(); - _scanner.scan(); - } - - @ManagedOperation(value = "Reload the SSL Truststore", impact = "ACTION") - public void reload() { - if (LOG.isDebugEnabled()) { - LOG.debug("reloading truststore file {}", truststoreFile); - } - - try { - sslContextFactory.reload(scf -> { - }); - } catch (Throwable t) { - LOG.warn("Truststore Reload Failed", t); - } - } - - @ManagedAttribute("scanning interval to detect changes which need reloaded") - public int getScanInterval() { - return _scanner.getScanInterval(); - } - - public void setScanInterval(int scanInterval) { - _scanner.setScanInterval(scanInterval); - } -} \ No newline at end of file diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-jetty/src/test/java/org/apache/nifi/web/server/connector/FrameworkServerConnectorFactoryTest.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-jetty/src/test/java/org/apache/nifi/web/server/connector/FrameworkServerConnectorFactoryTest.java index e997f25ac6..f4119f76aa 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-jetty/src/test/java/org/apache/nifi/web/server/connector/FrameworkServerConnectorFactoryTest.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-jetty/src/test/java/org/apache/nifi/web/server/connector/FrameworkServerConnectorFactoryTest.java @@ -20,17 +20,17 @@ import org.apache.nifi.jetty.configuration.connector.alpn.ALPNServerConnectionFa import org.apache.nifi.security.util.TemporaryKeyStoreBuilder; import org.apache.nifi.security.util.TlsConfiguration; import org.apache.nifi.util.NiFiProperties; -import org.apache.nifi.web.server.util.TrustStoreScanner; +import org.apache.nifi.web.server.util.StoreScanner; import org.eclipse.jetty.http2.server.HTTP2ServerConnectionFactory; import org.eclipse.jetty.server.HttpConnectionFactory; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.ServerConnector; import org.eclipse.jetty.server.SslConnectionFactory; -import org.eclipse.jetty.util.ssl.KeyStoreScanner; import org.eclipse.jetty.util.ssl.SslContextFactory; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; +import java.util.Collection; import java.util.Properties; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -182,11 +182,8 @@ class FrameworkServerConnectorFactoryTest { private void assertAutoReloadEnabled(final ServerConnector serverConnector) { final Server server = serverConnector.getServer(); - final KeyStoreScanner keyStoreScanner = server.getBean(KeyStoreScanner.class); - assertNotNull(keyStoreScanner); - - final TrustStoreScanner trustStoreScanner = server.getBean(TrustStoreScanner.class); - assertNotNull(trustStoreScanner); + final Collection scanners = server.getBeans(StoreScanner.class); + assertEquals(2, scanners.size()); } private NiFiProperties getProperties(final Properties serverProperties) { diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-jetty/src/test/java/org/apache/nifi/web/server/util/StoreScannerTest.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-jetty/src/test/java/org/apache/nifi/web/server/util/StoreScannerTest.java new file mode 100644 index 0000000000..35c971c144 --- /dev/null +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-jetty/src/test/java/org/apache/nifi/web/server/util/StoreScannerTest.java @@ -0,0 +1,143 @@ +/* + * 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.web.server.util; + +import org.apache.nifi.security.util.TemporaryKeyStoreBuilder; +import org.apache.nifi.security.util.TlsConfiguration; +import org.eclipse.jetty.util.resource.Resource; +import org.eclipse.jetty.util.ssl.SslContextFactory; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.ArgumentCaptor; +import org.mockito.ArgumentMatchers; +import org.mockito.Captor; +import org.mockito.junit.jupiter.MockitoExtension; + +import javax.net.ssl.SSLContext; +import java.io.File; +import java.io.IOException; +import java.nio.file.Paths; +import java.util.HashMap; +import java.util.Map; +import java.util.function.Consumer; + +import static org.mockito.Mockito.clearInvocations; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +@ExtendWith(MockitoExtension.class) +public class StoreScannerTest { + private SslContextFactory sslContextFactory; + private static TlsConfiguration tlsConfiguration; + private static File keyStoreFile; + private static File trustStoreFile; + private static Map filesToScannerMap; + + @Captor + private ArgumentCaptor> consumerArgumentCaptor; + + @BeforeAll + public static void initClass() { + tlsConfiguration = new TemporaryKeyStoreBuilder().build(); + keyStoreFile = Paths.get(tlsConfiguration.getKeystorePath()).toFile(); + trustStoreFile = Paths.get(tlsConfiguration.getTruststorePath()).toFile(); + } + + @BeforeEach + public void init() throws IOException { + sslContextFactory = mock(SslContextFactory.class); + Resource keyStoreResource = mock(Resource.class); + when(keyStoreResource.getFile()).thenReturn(keyStoreFile); + when(sslContextFactory.getKeyStoreResource()).thenReturn(keyStoreResource); + + Resource trustStoreResource = mock(Resource.class); + when(trustStoreResource.getFile()).thenReturn(trustStoreFile); + when(sslContextFactory.getTrustStoreResource()).thenReturn(trustStoreResource); + + final StoreScanner keyStoreScanner = new StoreScanner(sslContextFactory, tlsConfiguration, sslContextFactory.getKeyStoreResource()); + final StoreScanner trustStoreScanner = new StoreScanner(sslContextFactory, tlsConfiguration, sslContextFactory.getTrustStoreResource()); + filesToScannerMap = new HashMap<>(); + filesToScannerMap.put(keyStoreFile, keyStoreScanner); + filesToScannerMap.put(trustStoreFile, trustStoreScanner); + } + + @Test + public void testFileAdded() throws Exception { + for (final Map.Entry entry : filesToScannerMap.entrySet()) { + final File file = entry.getKey(); + final StoreScanner scanner = entry.getValue(); + scanner.fileAdded(file.getAbsolutePath()); + + verify(sslContextFactory).reload(consumerArgumentCaptor.capture()); + + final Consumer consumer = consumerArgumentCaptor.getValue(); + consumer.accept(sslContextFactory); + verify(sslContextFactory).setSslContext(ArgumentMatchers.any(SSLContext.class)); + clearInvocations(sslContextFactory); + } + } + + @Test + public void testFileChanged() throws Exception { + for (final Map.Entry entry : filesToScannerMap.entrySet()) { + final File file = entry.getKey(); + final StoreScanner scanner = entry.getValue(); + scanner.fileChanged(file.getAbsolutePath()); + + verify(sslContextFactory).reload(consumerArgumentCaptor.capture()); + + final Consumer consumer = consumerArgumentCaptor.getValue(); + consumer.accept(sslContextFactory); + verify(sslContextFactory).setSslContext(ArgumentMatchers.any(SSLContext.class)); + clearInvocations(sslContextFactory); + } + } + + @Test + public void testFileRemoved() throws Exception { + for (final Map.Entry entry : filesToScannerMap.entrySet()) { + final File file = entry.getKey(); + final StoreScanner scanner = entry.getValue(); + scanner.fileRemoved(file.getAbsolutePath()); + + verify(sslContextFactory).reload(consumerArgumentCaptor.capture()); + + final Consumer consumer = consumerArgumentCaptor.getValue(); + consumer.accept(sslContextFactory); + verify(sslContextFactory).setSslContext(ArgumentMatchers.any(SSLContext.class)); + clearInvocations(sslContextFactory); + } + } + + @Test + public void testReload() throws Exception { + for (final Map.Entry entry : filesToScannerMap.entrySet()) { + final StoreScanner scanner = entry.getValue(); + scanner.reload(); + + verify(sslContextFactory).reload(consumerArgumentCaptor.capture()); + + final Consumer consumer = consumerArgumentCaptor.getValue(); + consumer.accept(sslContextFactory); + verify(sslContextFactory).setSslContext(ArgumentMatchers.any(SSLContext.class)); + clearInvocations(sslContextFactory); + } + } +} diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-jetty/src/test/java/org/apache/nifi/web/server/util/TrustStoreScannerTest.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-jetty/src/test/java/org/apache/nifi/web/server/util/TrustStoreScannerTest.java deleted file mode 100644 index e5ee7df072..0000000000 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-jetty/src/test/java/org/apache/nifi/web/server/util/TrustStoreScannerTest.java +++ /dev/null @@ -1,85 +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.nifi.web.server.util; - -import org.apache.nifi.security.util.TemporaryKeyStoreBuilder; -import org.apache.nifi.security.util.TlsConfiguration; -import org.eclipse.jetty.util.resource.Resource; -import org.eclipse.jetty.util.ssl.SslContextFactory; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.mockito.ArgumentMatchers; -import org.mockito.Mockito; - -import java.io.File; -import java.io.IOException; -import java.nio.file.Paths; -import java.util.function.Consumer; - -public class TrustStoreScannerTest { - - private TrustStoreScanner scanner; - private SslContextFactory sslContextFactory; - private static File keyStoreFile; - private static File trustStoreFile; - - @BeforeAll - public static void initClass() { - TlsConfiguration tlsConfiguration = new TemporaryKeyStoreBuilder().build(); - keyStoreFile = Paths.get(tlsConfiguration.getKeystorePath()).toFile(); - trustStoreFile = Paths.get(tlsConfiguration.getTruststorePath()).toFile(); - } - - @BeforeEach - public void init() throws IOException { - sslContextFactory = Mockito.mock(SslContextFactory.class); - Resource trustStoreResource = Mockito.mock(Resource.class); - Mockito.when(trustStoreResource.getFile()).thenReturn(trustStoreFile); - Mockito.when(sslContextFactory.getTrustStoreResource()).thenReturn(trustStoreResource); - - scanner = new TrustStoreScanner(sslContextFactory); - } - - @Test - public void fileAdded() throws Exception { - scanner.fileAdded(trustStoreFile.getAbsolutePath()); - - Mockito.verify(sslContextFactory).reload(ArgumentMatchers.any(Consumer.class)); - } - - @Test - public void fileChanged() throws Exception { - scanner.fileChanged(trustStoreFile.getAbsolutePath()); - - Mockito.verify(sslContextFactory).reload(ArgumentMatchers.any(Consumer.class)); - } - - @Test - public void fileRemoved() throws Exception { - scanner.fileRemoved(trustStoreFile.getAbsolutePath()); - - Mockito.verify(sslContextFactory).reload(ArgumentMatchers.any(Consumer.class)); - } - - @Test - public void reload() throws Exception { - scanner.reload(); - - Mockito.verify(sslContextFactory).reload(ArgumentMatchers.any(Consumer.class)); - } -}