/*
 * 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

import org.apache.log4j.AppenderSkeleton
import org.apache.log4j.spi.LoggingEvent
import org.apache.nifi.bundle.Bundle
import org.apache.nifi.nar.ExtensionManagerHolder
import org.apache.nifi.nar.ExtensionMapping
import org.apache.nifi.nar.SystemBundle
import org.apache.nifi.processor.DataUnit
import org.apache.nifi.remote.io.socket.NetworkUtils
import org.apache.nifi.security.util.StandardTlsConfiguration
import org.apache.nifi.security.util.TlsConfiguration
import org.apache.nifi.security.util.TlsPlatform
import org.apache.nifi.util.NiFiProperties
import org.bouncycastle.jce.provider.BouncyCastleProvider
import org.eclipse.jetty.server.Connector
import org.eclipse.jetty.server.HttpConfiguration
import org.eclipse.jetty.server.Server
import org.eclipse.jetty.server.ServerConnector
import org.eclipse.jetty.server.SslConnectionFactory
import org.eclipse.jetty.servlet.FilterHolder
import org.eclipse.jetty.util.ssl.SslContextFactory
import org.eclipse.jetty.webapp.WebAppContext
import org.junit.After
import org.junit.Assume
import org.junit.BeforeClass
import org.junit.Rule
import org.junit.Test
import org.junit.contrib.java.lang.system.Assertion
import org.junit.contrib.java.lang.system.ExpectedSystemExit
import org.junit.contrib.java.lang.system.SystemErrRule
import org.junit.contrib.java.lang.system.SystemOutRule
import org.junit.runner.RunWith
import org.junit.runners.JUnit4
import org.mockito.ArgumentMatchers
import org.mockito.Mockito
import org.mockito.invocation.InvocationOnMock
import org.mockito.stubbing.Answer
import org.slf4j.Logger
import org.slf4j.LoggerFactory

import javax.net.ssl.SSLContext
import javax.net.ssl.SSLSocket
import javax.net.ssl.SSLSocketFactory
import javax.servlet.DispatcherType
import java.nio.charset.StandardCharsets
import java.security.Security

@RunWith(JUnit4.class)
class JettyServerGroovyTest extends GroovyTestCase {
    private static final Logger logger = LoggerFactory.getLogger(JettyServerGroovyTest.class)

    @Rule
    public final ExpectedSystemExit exit = ExpectedSystemExit.none()

    @Rule
    public final SystemOutRule systemOutRule = new SystemOutRule().enableLog()

    @Rule
    public final SystemErrRule systemErrRule = new SystemErrRule().enableLog()

    private static final int DEFAULT_HTTP_PORT = 8080
    private static final int DEFAULT_HTTPS_PORT = 8443

    private static final int HTTPS_PORT = NetworkUtils.getAvailableTcpPort()
    private static final String HTTPS_HOSTNAME = "localhost"

    private static final String KEYSTORE_PATH = "src/test/resources/keystore.jks"
    private static final String TRUSTSTORE_PATH = "src/test/resources/truststore.jks"
    private static final String STORE_PASSWORD = "passwordpassword"
    private static final String STORE_TYPE = "JKS"

    private static final String TLS_1_3_PROTOCOL = "TLSv1.3"
    private static final List<String> TLS_1_3_CIPHER_SUITES = ["TLS_AES_128_GCM_SHA256"]

    // These protocol versions should not ever be supported
    static private final List<String> LEGACY_TLS_PROTOCOLS = ["TLS", "TLSv1", "TLSv1.1", "SSL", "SSLv2", "SSLv2Hello", "SSLv3"]

    NiFiProperties httpsProps = new NiFiProperties(new Properties([
            (NiFiProperties.WEB_HTTPS_PORT)            : HTTPS_PORT as String,
            (NiFiProperties.WEB_HTTPS_HOST)            : HTTPS_HOSTNAME,
            (NiFiProperties.SECURITY_KEYSTORE)         : KEYSTORE_PATH,
            (NiFiProperties.SECURITY_KEYSTORE_PASSWD)  : STORE_PASSWORD,
            (NiFiProperties.SECURITY_KEYSTORE_TYPE)    : STORE_TYPE,
            (NiFiProperties.SECURITY_TRUSTSTORE)       : TRUSTSTORE_PATH,
            (NiFiProperties.SECURITY_TRUSTSTORE_PASSWD): STORE_PASSWORD,
            (NiFiProperties.SECURITY_TRUSTSTORE_TYPE)  : STORE_TYPE,
    ]))

    @BeforeClass
    static void setUpOnce() throws Exception {
        Security.addProvider(new BouncyCastleProvider())

        logger.metaClass.methodMissing = { String name, args ->
            logger.info("[${name?.toUpperCase()}] ${(args as List).join(" ")}")
        }

        TestAppender.reset()
    }

    @After
    void tearDown() throws Exception {
        // Cleans up the EMH so it can be reinitialized when a new Jetty server starts
        ExtensionManagerHolder.INSTANCE = null
        TestAppender.reset()
    }

    @Test
    void testShouldDetectHttpAndHttpsConfigurationsBothPresent() {
        // Arrange
        Map badProps = [
                (NiFiProperties.WEB_HTTP_HOST) : "localhost",
                (NiFiProperties.WEB_HTTPS_HOST): "secure.host.com",
                (NiFiProperties.WEB_THREADS)   : NiFiProperties.DEFAULT_WEB_THREADS
        ]
        NiFiProperties mockProps = Mockito.mock(NiFiProperties.class)
        Mockito.when(mockProps.getPort()).thenReturn(DEFAULT_HTTP_PORT)
        Mockito.when(mockProps.getSslPort()).thenReturn(DEFAULT_HTTPS_PORT)

        Mockito.when(mockProps.getProperty(ArgumentMatchers.anyString())).thenAnswer(new Answer<Object>() {
            @Override
            Object answer(InvocationOnMock invocation) throws Throwable {
                badProps[(String) invocation.getArgument(0)] ?: "no_value"
            }
        })

        // Act
        boolean bothConfigsPresent = JettyServer.bothHttpAndHttpsConnectorsConfigured(mockProps)
        logger.info("Both configs present: ${bothConfigsPresent}")
        def log = TestAppender.getLogLines()

        // Assert
        assert bothConfigsPresent
        assert !log.isEmpty()
        assert log.first() =~ "Both the HTTP and HTTPS connectors are configured in nifi.properties. Only one of these connectors should be configured. See the NiFi Admin Guide for more details"
    }

    @Test
    void testDetectHttpAndHttpsConfigurationsShouldAllowEither() {
        // Arrange
        Map httpMap = [
                (NiFiProperties.WEB_HTTP_HOST) : "localhost",
                (NiFiProperties.WEB_HTTPS_HOST): null,
        ]
        NiFiProperties httpProps = [
                getPort    : { -> DEFAULT_HTTP_PORT },
                getSslPort : { -> null },
                getProperty: { String prop ->
                    String value = httpMap[prop] ?: "no_value"
                    logger.mock("getProperty(${prop}) -> ${value}")
                    value
                },
        ] as NiFiProperties

        Map httpsMap = [
                (NiFiProperties.WEB_HTTP_HOST) : null,
                (NiFiProperties.WEB_HTTPS_HOST): "secure.host.com",
        ]
        NiFiProperties httpsProps = [
                getPort    : { -> null },
                getSslPort : { -> DEFAULT_HTTPS_PORT },
                getProperty: { String prop ->
                    String value = httpsMap[prop] ?: "no_value"
                    logger.mock("getProperty(${prop}) -> ${value}")
                    value
                },
        ] as NiFiProperties

        // Act
        boolean bothConfigsPresentForHttp = JettyServer.bothHttpAndHttpsConnectorsConfigured(httpProps)
        logger.info("Both configs present for HTTP properties: ${bothConfigsPresentForHttp}")

        boolean bothConfigsPresentForHttps = JettyServer.bothHttpAndHttpsConnectorsConfigured(httpsProps)
        logger.info("Both configs present for HTTPS properties: ${bothConfigsPresentForHttps}")
        def log = TestAppender.getLogLines()

        // Assert
        assert !bothConfigsPresentForHttp
        assert !bothConfigsPresentForHttps

        // Verifies that the warning was not logged (messages are duplicated because of log4j.properties settings)
        assert log.size() == 4
        assert log.every { it =~ "Both configs present for HTTPS? properties: false" }
    }

    @Test
    void testShouldFailToStartWithHttpAndHttpsConfigurationsBothPresent() {
        // Arrange
        Map badProps = [
                (NiFiProperties.WEB_HTTP_HOST) : "localhost",
                (NiFiProperties.WEB_HTTPS_HOST): "secure.host.com",
        ]
        NiFiProperties mockProps = [
                getPort            : { -> DEFAULT_HTTP_PORT },
                getSslPort         : { -> DEFAULT_HTTPS_PORT },
                getProperty        : { String prop ->
                    String value = badProps[prop] ?: "no_value"
                    logger.mock("getProperty(${prop}) -> ${value}")
                    value
                },
                getWebThreads      : { -> NiFiProperties.DEFAULT_WEB_THREADS },
                getWebMaxHeaderSize: { -> NiFiProperties.DEFAULT_WEB_MAX_HEADER_SIZE },
                isHTTPSConfigured  : { -> true }
        ] as NiFiProperties

        // The web server should fail to start and exit Java
        exit.expectSystemExitWithStatus(1)
        exit.checkAssertionAfterwards(new Assertion() {
            void checkAssertion() {
                final String standardErr = systemErrRule.getLog()
                List<String> errLines = standardErr.split("\n")

                assert errLines.any { it =~ "Failed to start web server: " }
                assert errLines.any { it =~ "Shutting down..." }
            }
        })

        // Act
        JettyServer jettyServer = new JettyServer()
        jettyServer.initialize(mockProps, null, [] as Set<Bundle>, null)
        
        // Assert

        // Assertions defined above
    }

    /**
     * Regression test added after NiFi 1.12.0 because Jetty upgrade to 9.4.26 no longer works
     * with multiple certificate keystores.
     */
    @Test
    void testShouldStartWithMultipleCertificatePKCS12Keystore() {
        // Arrange
        final String externalHostname = "localhost"

        NiFiProperties httpsProps = new NiFiProperties(new Properties([
                (NiFiProperties.WEB_HTTPS_PORT): HTTPS_PORT as String,
                (NiFiProperties.WEB_HTTPS_HOST): externalHostname,
                (NiFiProperties.SECURITY_KEYSTORE): "src/test/resources/multiple_cert_keystore.p12",
                (NiFiProperties.SECURITY_KEYSTORE_PASSWD): "passwordpassword",
                (NiFiProperties.SECURITY_KEYSTORE_TYPE): "PKCS12",
                (NiFiProperties.NAR_LIBRARY_DIRECTORY): "target/"
        ]))

        JettyServer jetty = createJettyServer(httpsProps)
        Server internalServer = jetty.server
        List<Connector> connectors = Arrays.asList(internalServer.connectors)

        // Act
        jetty.start()

        // Assert
        assertServerConnector(connectors, externalHostname, HTTPS_PORT)

        // Clean up
        jetty.stop()
    }

    /**
     * Regression test added after NiFi 1.12.0 because Jetty upgrade to 9.4.26 no longer works
     * with multiple certificate keystores.
     */
    @Test
    void testShouldStartWithMultipleCertificateJKSKeystore() {
        // Arrange
        final String externalHostname = "localhost"

        NiFiProperties httpsProps = new NiFiProperties(new Properties([
                (NiFiProperties.WEB_HTTPS_PORT): HTTPS_PORT as String,
                (NiFiProperties.WEB_HTTPS_HOST): externalHostname,
                (NiFiProperties.SECURITY_KEYSTORE): "src/test/resources/multiple_cert_keystore.jks",
                (NiFiProperties.SECURITY_KEYSTORE_PASSWD): "passwordpassword",
                (NiFiProperties.SECURITY_KEYSTORE_TYPE): "JKS",
                (NiFiProperties.NAR_LIBRARY_DIRECTORY): "target/"
        ]))

        JettyServer jetty = createJettyServer(httpsProps)
        Server internalServer = jetty.server
        List<Connector> connectors = Arrays.asList(internalServer.connectors)

        // Act
        jetty.start()

        // Assert
        assertServerConnector(connectors, externalHostname, HTTPS_PORT)

        // Clean up
        jetty.stop()
    }

    private static JettyServer createJettyServer(NiFiProperties httpsProps) {
        Server internalServer = new Server()
        JettyServer jetty = new JettyServer(internalServer, httpsProps)
        jetty.systemBundle = SystemBundle.create(httpsProps)
        jetty.bundles = [] as Set<Bundle>
        jetty.extensionMapping = [size: { -> 0 }] as ExtensionMapping
        jetty.configureHttpsConnector(internalServer, new HttpConfiguration())
        jetty
    }

    @Test
    void testShouldConfigureHTTPSConnector() {
        // Arrange
        final String externalHostname = "localhost"

        NiFiProperties httpsProps = new NiFiProperties(new Properties([
                (NiFiProperties.WEB_HTTPS_PORT): HTTPS_PORT as String,
                (NiFiProperties.WEB_HTTPS_HOST): externalHostname,
        ]))

        Server internalServer = new Server()
        JettyServer jetty = new JettyServer(internalServer, httpsProps)

        // Act
        jetty.configureHttpsConnector(internalServer, new HttpConfiguration())
        List<Connector> connectors = Arrays.asList(internalServer.connectors)

        // Assert
        assertServerConnector(connectors, externalHostname, HTTPS_PORT)
    }

    @Test
    void testShouldSupportTLSv1_3WhenProtocolFound() {
        // Arrange
        String[] defaultProtocols = SSLContext.getDefault().defaultSSLParameters.protocols
        Assume.assumeTrue("This test should only run when TLSv1.3 is found in the set of default protocols", defaultProtocols.contains(TLS_1_3_PROTOCOL))

        Server internalServer = new Server()
        JettyServer jetty = new JettyServer(internalServer, httpsProps)

        jetty.configureConnectors(internalServer)
        List<Connector> connectors = Arrays.asList(internalServer.connectors)
        internalServer.start()

        // Create a (client) socket which only supports TLSv1.3
        TlsConfiguration tls13ClientConf = StandardTlsConfiguration.fromNiFiProperties(httpsProps)
        SSLSocketFactory socketFactory = org.apache.nifi.security.util.SslContextFactory.createSSLSocketFactory(tls13ClientConf)

        SSLSocket socket = (SSLSocket) socketFactory.createSocket(HTTPS_HOSTNAME, HTTPS_PORT)
        socket.setEnabledProtocols([TLS_1_3_PROTOCOL] as String[])
        socket.setEnabledCipherSuites(TLS_1_3_CIPHER_SUITES as String[])

        // Act
        String response = makeTLSRequest(socket, "This is a TLS 1.3 request")

        // Assert
        assert response =~ "HTTP/1.1 400"

        assertServerConnector(connectors)

        // Clean up
        internalServer.stop()
    }

    @Test
    void testShouldNotSupportTLSv1_3WhenProtocolNotFound() {
        // Arrange
        Assume.assumeTrue("This test should only run when TLSv1.3 is not found in the set of default protocols", !TlsPlatform.supportedProtocols.contains(TLS_1_3_PROTOCOL))

        Server internalServer = new Server()
        JettyServer jetty = new JettyServer(internalServer, httpsProps)

        jetty.configureConnectors(internalServer)
        List<Connector> connectors = Arrays.asList(internalServer.connectors)
        internalServer.start()

        TlsConfiguration tlsConfiguration = StandardTlsConfiguration.fromNiFiProperties(httpsProps)

        // Create a "default" (client) socket (which supports TLSv1.2)
        SSLSocketFactory defaultSocketFactory = org.apache.nifi.security.util.SslContextFactory.createSSLSocketFactory(tlsConfiguration)
        SSLSocket defaultSocket = (SSLSocket) defaultSocketFactory.createSocket(HTTPS_HOSTNAME, HTTPS_PORT)

        // Act
        String tls12Response = makeTLSRequest(defaultSocket, "This is a default socket request")

        def msg = shouldFail() {
            // Create a (client) socket which only supports TLSv1.3
            SSLSocketFactory tls13SocketFactory = org.apache.nifi.security.util.SslContextFactory.createSSLSocketFactory(tlsConfiguration)

            SSLSocket tls13Socket = (SSLSocket) tls13SocketFactory.createSocket(HTTPS_HOSTNAME, HTTPS_PORT)
            tls13Socket.setEnabledProtocols([TLS_1_3_PROTOCOL] as String[])
            tls13Socket.setEnabledCipherSuites(TLS_1_3_CIPHER_SUITES as String[])

            makeTLSRequest(tls13Socket, "This is a TLSv1.3 socket request")
        }
        logger.expected(msg)

        // Assert
        assert tls12Response =~ "HTTP"

        assertServerConnector(connectors)

        // Clean up
        internalServer.stop()
    }

    /**
     * Returns the server's response body as a String. Closes the socket connection.
     *
     * @param socket
     * @param requestMessage
     * @return
     */
    private static String makeTLSRequest(Socket socket, String requestMessage) {
        InputStream socketInputStream = new BufferedInputStream(socket.getInputStream())
        OutputStream socketOutputStream = new BufferedOutputStream(socket.getOutputStream())

        socketOutputStream.write(requestMessage.getBytes())
        socketOutputStream.flush()

        byte[] data = new byte[2048]
        int len = socketInputStream.read(data)
        if (len <= 0) {
            throw new IOException("no data received")
        }
        final String trimmedResponse = new String(data, 0, len, StandardCharsets.UTF_8)
        logger.info("Client received ${len} bytes from server: \n${trimmedResponse}\n----End of response----")
        socket.close()
        trimmedResponse
    }

    private static void assertServerConnector(List<Connector> connectors,
                                              String EXPECTED_HOSTNAME = HTTPS_HOSTNAME,
                                              int EXPECTED_PORT = HTTPS_PORT) {
        // Assert the server connector is correct
        assert connectors.size() == 1
        ServerConnector connector = connectors.first() as ServerConnector
        assert connector.host == EXPECTED_HOSTNAME
        assert connector.port == EXPECTED_PORT
        assert connector.getProtocols() == ['ssl', 'http/1.1']

        SslConnectionFactory connectionFactory = connector.getConnectionFactory("ssl") as SslConnectionFactory
        SslContextFactory sslContextFactory = connectionFactory.getSslContextFactory()
        assert (sslContextFactory.getExcludeProtocols() as List<String>).containsAll(LEGACY_TLS_PROTOCOLS)
    }

    @Test
    void testShouldEnableContentLengthFilterIfWebMaxContentSizeSet() {
        // Arrange
        Map defaultProps = [
                (NiFiProperties.WEB_HTTP_PORT)       : DEFAULT_HTTP_PORT as String,
                (NiFiProperties.WEB_HTTP_HOST)       : "localhost",
                (NiFiProperties.WEB_MAX_CONTENT_SIZE): "1 MB",
        ]
        NiFiProperties mockProps = new NiFiProperties(new Properties(defaultProps))

        List<FilterHolder> filters = []
        def mockWebContext = [
                addFilter: { FilterHolder fh, String path, EnumSet<DispatcherType> d ->
                    logger.mock("Called addFilter(${fh.name}, ${path}, ${d})")
                    filters.add(fh)
                    fh
                }] as WebAppContext

        JettyServer jettyServer = new JettyServer(new Server(), mockProps)
        logger.info("Created JettyServer: ${jettyServer.dump()}")

        final int MAX_CONTENT_LENGTH_BYTES = DataUnit.parseDataSize(defaultProps[NiFiProperties.WEB_MAX_CONTENT_SIZE], DataUnit.B).intValue()

        // Act
        jettyServer.addDenialOfServiceFilters(mockWebContext, mockProps)

        // Assert
        assert filters.size() == 2
        def filterNames = filters*.name
        logger.info("Web API Context has ${filters.size()} filters: ${filterNames.join(", ")}".toString())
        assert filterNames.contains("DoSFilter")
        assert filterNames.contains("ContentLengthFilter")

        FilterHolder clfHolder = filters.find { it.name == "ContentLengthFilter" }
        String maxContentLength = clfHolder.getInitParameter("maxContentLength")
        assert maxContentLength == MAX_CONTENT_LENGTH_BYTES as String

        // Filter is not instantiated just by adding it
//        ContentLengthFilter clf = filters?.find { it.className == "ContentLengthFilter" }?.filter as ContentLengthFilter
//        assert clf.getMaxContentLength() == MAX_CONTENT_LENGTH_BYTES
    }

    @Test
    void testShouldNotEnableContentLengthFilterIfWebMaxContentSizeEmpty() {
        // Arrange
        Map defaultProps = [
                (NiFiProperties.WEB_HTTP_PORT): DEFAULT_HTTP_PORT as String,
                (NiFiProperties.WEB_HTTP_HOST): "localhost",
        ]
        NiFiProperties mockProps = new NiFiProperties(new Properties(defaultProps))

        List<FilterHolder> filters = []
        def mockWebContext = [
                addFilter: { FilterHolder fh, String path, EnumSet<DispatcherType> d ->
                    logger.mock("Called addFilter(${fh.name}, ${path}, ${d})")
                    filters.add(fh)
                    fh
                }] as WebAppContext

        JettyServer jettyServer = new JettyServer(new Server(), mockProps)
        logger.info("Created JettyServer: ${jettyServer.dump()}")

        // Act
        jettyServer.addDenialOfServiceFilters(mockWebContext, mockProps)

        // Assert
        assert filters.size() == 1
        def filterNames = filters*.name
        logger.info("Web API Context has ${filters.size()} filters: ${filterNames.join(", ")}".toString())
        assert filterNames.contains("DoSFilter")
        assert !filterNames.contains("ContentLengthFilter")
    }
}

class TestAppender extends AppenderSkeleton {
    static final List<LoggingEvent> events = new ArrayList<>()

    @Override
    protected void append(LoggingEvent e) {
        synchronized (events) {
            events.add(e)
        }
    }

    static void reset() {
        synchronized (events) {
            events.clear()
        }
    }

    @Override
    void close() {
    }

    @Override
    boolean requiresLayout() {
        return false
    }

    static List<String> getLogLines() {
        synchronized (events) {
            events.collect { LoggingEvent le -> le.getRenderedMessage() }
        }
    }
}
