/*
 * 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.guacamole.vault.ksm.secret;

import com.google.inject.Inject;
import com.google.inject.Singleton;
import com.keepersecurity.secretsManager.core.KeeperRecord;
import com.keepersecurity.secretsManager.core.SecretsManagerOptions;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.Future;

import javax.annotation.Nonnull;

import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.net.auth.Connectable;
import org.apache.guacamole.net.auth.Connection;
import org.apache.guacamole.net.auth.ConnectionGroup;
import org.apache.guacamole.net.auth.Directory;
import org.apache.guacamole.net.auth.UserContext;
import org.apache.guacamole.protocol.GuacamoleConfiguration;
import org.apache.guacamole.token.TokenFilter;
import org.apache.guacamole.vault.ksm.conf.KsmAttributeService;
import org.apache.guacamole.vault.ksm.conf.KsmConfigurationService;
import org.apache.guacamole.vault.secret.VaultSecretService;
import org.apache.guacamole.vault.secret.WindowsUsername;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Service which retrieves secrets from Keeper Secrets Manager.
 * The configuration used to connect to KSM can be set at a global
 * level using guacamole.properties, or using a connection group
 * attribute.
 */
@Singleton
public class KsmSecretService implements VaultSecretService {

    /**
     * Logger for this class.
     */
    private static final Logger logger = LoggerFactory.getLogger(VaultSecretService.class);

    /**
     * Service for retrieving data from records.
     */
    @Inject
    private KsmRecordService recordService;

    /**
     * Service for retrieving configuration information.
     */
    @Inject
    private KsmConfigurationService confService;

    /**
     * Factory for creating KSM client instances.
     */
    @Inject
    private KsmClientFactory ksmClientFactory;

    /**
     * A map of base-64 encoded JSON KSM config blobs to associated KSM client instances.
     * A distinct KSM client will exist for every KSM config.
     */
    private final ConcurrentMap<String, KsmClient> ksmClientMap = new ConcurrentHashMap<>();

    /**
     * Create and return a KSM client for the provided KSM config if not already
     * present in the client map, otherwise return the existing client entry.
     *
     * @param ksmConfig
     *     The base-64 encoded JSON KSM config blob associated with the client entry.
     *     If an associated entry does not already exist, it will be created using
     *     this configuration.
     *
     * @return
     *     A KSM client for the provided KSM config if not already present in the
     *     client map, otherwise the existing client entry.
     *
     * @throws GuacamoleException
     *     If an error occurs while creating the KSM client.
     */
    private KsmClient getClient(@Nonnull String ksmConfig)
            throws GuacamoleException {

        // If a client already exists for the provided config, use it
        KsmClient ksmClient = ksmClientMap.get(ksmConfig);
        if (ksmClient != null)
            return ksmClient;

        // Create and store a new KSM client instance for the provided KSM config blob
        SecretsManagerOptions options = confService.getSecretsManagerOptions(ksmConfig);
        ksmClient = ksmClientFactory.create(options);
        KsmClient prevClient = ksmClientMap.putIfAbsent(ksmConfig, ksmClient);

        // If the client was already set before this thread got there, use the existing one
        return prevClient != null ? prevClient : ksmClient;
    }

    @Override
    public String canonicalize(String nameComponent) {
        try {

            // As Keeper notation is essentially a URL, encode all components
            // using standard URL escaping
            return URLEncoder.encode(nameComponent, "UTF-8");

        }
        catch (UnsupportedEncodingException e) {
            throw new UnsupportedOperationException("Unexpected lack of UTF-8 support.", e);
        }
    }

    @Override
    public Future<String> getValue(UserContext userContext, Connectable connectable,
            String name) throws GuacamoleException {

        // Attempt to find a KSM config for this connection or group
        String ksmConfig = getConnectionGroupKsmConfig(userContext, connectable);

        return getClient(ksmConfig).getSecret(name);
    }

    @Override
    public Future<String> getValue(String name) throws GuacamoleException {

        // Use the default KSM configuration from guacamole.properties
        return getClient(confService.getKsmConfig()).getSecret(name);
    }

    /**
     * Adds contextual parameter tokens for the secrets in the given record to
     * the given map of existing tokens. The values of each token are
     * determined from secrets within the record. Depending on the record, this
     * will be a subset of the username, password, private key, and passphrase.
     *
     * @param tokens
     *     The map of parameter tokens that any new tokens should be added to.
     *
     * @param prefix
     *     The prefix that should be prepended to each added token.
     *
     * @param record
     *     The record to retrieve secrets from when generating tokens. This may
     *     be null.
     *
     * @throws GuacamoleException
     *     If configuration details in guacamole.properties cannot be parsed.
     */
    private void addRecordTokens(Map<String, Future<String>> tokens, String prefix,
            KeeperRecord record) throws GuacamoleException {

        if (record == null)
            return;

        // Domain of server-related record
        String domain = recordService.getDomain(record);
        if (domain != null)
            tokens.put(prefix + "DOMAIN", CompletableFuture.completedFuture(domain));

        // Username of server-related record
        String username = recordService.getUsername(record);
        if (username != null) {

            // If the record had no directly defined domain, but there is a
            // username, and the configuration is enabled to split Windows
            // domains out of usernames, attempt to split the domain out now
            if (domain == null && confService.getSplitWindowsUsernames()) {
                WindowsUsername usernameAndDomain =
                        WindowsUsername.splitWindowsUsernameFromDomain(username);

                // Always store the username token
                tokens.put(prefix + "USERNAME", CompletableFuture.completedFuture(
                        usernameAndDomain.getUsername()));

                // Only store the domain if one is detected
                if (usernameAndDomain.hasDomain())
                    tokens.put(prefix + "DOMAIN", CompletableFuture.completedFuture(
                        usernameAndDomain.getDomain()));

            }

            // If splitting is not enabled, store the whole value in the USERNAME token
            else {
                tokens.put(prefix + "USERNAME", CompletableFuture.completedFuture(username));
            }
        }

        // Password of server-related record
        String password = recordService.getPassword(record);
        if (password != null)
            tokens.put(prefix + "PASSWORD", CompletableFuture.completedFuture(password));

        // Key passphrase of server-related record
        String passphrase = recordService.getPassphrase(record);
        if (passphrase != null)
            tokens.put(prefix + "PASSPHRASE", CompletableFuture.completedFuture(passphrase));

        // Private key of server-related record
        Future<String> privateKey = recordService.getPrivateKey(record);
        tokens.put(prefix + "KEY", privateKey);

    }

    /**
     * Search for a KSM configuration attribute, recursing up the connection group tree
     * until a connection group with the appropriate attribute is found. If the KSM config
     * is found, it will be returned. If not, the default value from the config file will
     * be returned.
     *
     * @param userContext
     *     The userContext associated with the connection or connection group.
     *
     * @param connectable
     *     A connection or connection group for which the tokens are being replaced.
     *
     * @return
     *     The value of the KSM configuration attribute if found in the tree, the default
     *     KSM config blob defined in guacamole.properties otherwise.
     *
     * @throws GuacamoleException
     *     If an error occurs while attempting to retrieve the KSM config attribute, or if
     *     no KSM config is found in the connection group tree, and the value is also not
     *     defined in the config file.
     */
    private String getConnectionGroupKsmConfig(
            UserContext userContext, Connectable connectable) throws GuacamoleException {

        // Check to make sure it's a usable type before proceeding
        if (
                !(connectable instanceof Connection)
                && !(connectable instanceof ConnectionGroup)) {
            logger.warn(
                    "Unsupported Connectable type: {}; skipping KSM config lookup.",
                    connectable.getClass());

            // Use the default value if searching is impossible
            return confService.getKsmConfig();
        }

        // For connections, start searching the parent group for the KSM config
        // For connection groups, start searching the group directly
        String parentIdentifier = (connectable instanceof Connection)
                ? ((Connection) connectable).getParentIdentifier()
                : ((ConnectionGroup) connectable).getIdentifier();

        Directory<ConnectionGroup> connectionGroupDirectory = userContext.getConnectionGroupDirectory();
        while (true) {

            // Fetch the parent group, if one exists
            ConnectionGroup group = connectionGroupDirectory.get(parentIdentifier);
            if (group == null)
                break;

            // If the current connection group has the KSM configuration attribute, return immediately
            String ksmConfig = group.getAttributes().get(KsmAttributeService.KSM_CONFIGURATION_ATTRIBUTE);
            if (ksmConfig != null)
                return ksmConfig;

            // Otherwise, keep searching up the tree until an appropriate configuration is found
            parentIdentifier = group.getParentIdentifier();
        }

        // If no KSM configuration was ever found, use the default value
        return confService.getKsmConfig();
    }

    @Override
    public Map<String, Future<String>> getTokens(UserContext userContext, Connectable connectable,
            GuacamoleConfiguration config, TokenFilter filter) throws GuacamoleException {

        Map<String, Future<String>> tokens = new HashMap<>();
        Map<String, String> parameters = config.getParameters();

        // Attempt to find a KSM config for this connection or group
        String ksmConfig = getConnectionGroupKsmConfig(userContext, connectable);

        // Get a client instance for this KSM config
        KsmClient ksm = getClient(ksmConfig);

        // Retrieve and define server-specific tokens, if any
        String hostname = parameters.get("hostname");
        if (hostname != null && !hostname.isEmpty())
            addRecordTokens(tokens, "KEEPER_SERVER_",
                    ksm.getRecordByHost(filter.filter(hostname)));

        // Retrieve and define user-specific tokens, if any
        String username = parameters.get("username");
        if (username != null && !username.isEmpty())
            addRecordTokens(tokens, "KEEPER_USER_",
                    ksm.getRecordByLogin(filter.filter(username)));

        // Tokens specific to RDP
        if ("rdp".equals(config.getProtocol())) {

            // Retrieve and define gateway server-specific tokens, if any
            String gatewayHostname = parameters.get("gateway-hostname");
            if (gatewayHostname != null && !gatewayHostname.isEmpty())
                addRecordTokens(tokens, "KEEPER_GATEWAY_",
                        ksm.getRecordByHost(filter.filter(gatewayHostname)));

            // Retrieve and define gateway user-specific tokens, if any
            String gatewayUsername = parameters.get("gateway-username");
            if (gatewayUsername != null && !gatewayUsername.isEmpty())
                addRecordTokens(tokens, "KEEPER_GATEWAY_USER_",
                        ksm.getRecordByLogin(filter.filter(gatewayUsername)));

        }

        return tokens;

    }

}
