/*
 * 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.ranger.services.nifi.client;

import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.WebResource;
import com.sun.jersey.api.client.config.ClientConfig;
import com.sun.jersey.api.client.config.DefaultClientConfig;
import com.sun.jersey.client.urlconnection.HTTPSProperties;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.ranger.plugin.client.BaseClient;
import org.apache.ranger.plugin.service.ResourceLookupContext;
import org.codehaus.jackson.JsonNode;
import org.codehaus.jackson.map.ObjectMapper;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLPeerUnverifiedException;
import javax.net.ssl.SSLSession;
import javax.ws.rs.core.Response;
import java.security.cert.Certificate;
import java.security.cert.CertificateParsingException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;

/**
 * Client to communicate with NiFi and retrieve available resources.
 */
public class NiFiClient {

    private static final Log LOG = LogFactory.getLog(NiFiClient.class);

    static final String SUCCESS_MSG = "ConnectionTest Successful";
    static final String FAILURE_MSG = "Unable to retrieve any resources using given parameters. ";

    private final String url;
    private final SSLContext sslContext;
    private final HostnameVerifier hostnameVerifier;
    private final ObjectMapper mapper = new ObjectMapper();

    public NiFiClient(final String url, final SSLContext sslContext) {
        this.url = url;
        this.sslContext = sslContext;
        this.hostnameVerifier = new NiFiHostnameVerifier();
    }

    public HashMap<String, Object> connectionTest() {
        String errMsg = "";
        boolean connectivityStatus;
        HashMap<String, Object> responseData = new HashMap<>();

        try {
            final WebResource resource = getWebResource();
            final ClientResponse response = getResponse(resource, "application/json");

            if (LOG.isDebugEnabled()) {
                LOG.debug("Got response from NiFi with status code " + response.getStatus());
            }

            if (Response.Status.OK.getStatusCode() == response.getStatus()) {
                connectivityStatus = true;
            } else {
                connectivityStatus = false;
                errMsg = "Status Code = " + response.getStatus();
            }

        } catch (Exception e) {
            LOG.error("Connection to NiFi failed due to " + e.getMessage(), e);
            connectivityStatus = false;
            errMsg = e.getMessage();
        }

        if (connectivityStatus) {
            BaseClient.generateResponseDataMap(connectivityStatus, SUCCESS_MSG, SUCCESS_MSG, null, null, responseData);
        } else {
            BaseClient.generateResponseDataMap(connectivityStatus, FAILURE_MSG, FAILURE_MSG + errMsg, null, null, responseData);
        }

        if (LOG.isDebugEnabled()) {
            LOG.debug("Response Data - " + responseData);
        }

        return responseData;
    }

    public List<String> getResources(ResourceLookupContext context) throws Exception {
        final WebResource resource = getWebResource();
        final ClientResponse response = getResponse(resource, "application/json");

        if (Response.Status.OK.getStatusCode() != response.getStatus()) {
            String errorMsg = IOUtils.toString(response.getEntityInputStream());
            throw new Exception("Unable to retrieve resources from NiFi due to: " + errorMsg);
        }

        JsonNode rootNode = mapper.readTree(response.getEntityInputStream());
        if (rootNode == null) {
            throw new Exception("Unable to retrieve resources from NiFi");
        }

        JsonNode resourcesNode = rootNode.findValue("resources");
        List<String> identifiers = resourcesNode.findValuesAsText("identifier");

        final String userInput = context.getUserInput();
        if (StringUtils.isBlank(userInput)) {
            return identifiers;
        } else {
            List<String> filteredIdentifiers = new ArrayList<>();

            for (String identifier : identifiers) {
                if (identifier.contains(userInput)) {
                    filteredIdentifiers.add(identifier);
                }
            }

            return filteredIdentifiers;
        }
    }

    protected WebResource getWebResource() {
        final ClientConfig config = new DefaultClientConfig();
        if (sslContext != null) {
            config.getProperties().put(HTTPSProperties.PROPERTY_HTTPS_PROPERTIES,
                    new HTTPSProperties(hostnameVerifier, sslContext));
        }

        final Client client = Client.create(config);
        return client.resource(url);
    }

    protected ClientResponse getResponse(WebResource resource, String accept) {
        return resource.accept(accept).get(ClientResponse.class);
    }

    public String getUrl() {
        return url;
    }

    public SSLContext getSslContext() {
        return sslContext;
    }

    public HostnameVerifier getHostnameVerifier() {
        return hostnameVerifier;
    }

    /**
     * Custom hostname verifier that checks subject alternative names against the hostname of the URI.
     */
    private static class NiFiHostnameVerifier implements HostnameVerifier {

        @Override
        public boolean verify(final String hostname, final SSLSession ssls) {
            try {
                for (final Certificate peerCertificate : ssls.getPeerCertificates()) {
                    if (peerCertificate instanceof X509Certificate) {
                        final X509Certificate x509Cert = (X509Certificate) peerCertificate;
                        final List<String> subjectAltNames = getSubjectAlternativeNames(x509Cert);
                        if (subjectAltNames.contains(hostname.toLowerCase())) {
                            return true;
                        }
                    }
                }
            } catch (final SSLPeerUnverifiedException | CertificateParsingException ex) {
                LOG.warn("Hostname Verification encountered exception verifying hostname due to: " + ex, ex);
            }

            return false;
        }

        private List<String> getSubjectAlternativeNames(final X509Certificate certificate) throws CertificateParsingException {
            final Collection<List<?>> altNames = certificate.getSubjectAlternativeNames();
            if (altNames == null) {
                return new ArrayList<>();
            }

            final List<String> result = new ArrayList<>();
            for (final List<?> generalName : altNames) {
                /**
                 * generalName has the name type as the first element a String or byte array for the second element. We return any general names that are String types.
                 *
                 * We don't inspect the numeric name type because some certificates incorrectly put IPs and DNS names under the wrong name types.
                 */
                final Object value = generalName.get(1);
                if (value instanceof String) {
                    result.add(((String) value).toLowerCase());
                }

            }

            return result;
        }
    }

}
