All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.elasticsearch.xpack.core.ssl.X509KeyPairSettings Maven / Gradle / Ivy

There is a newer version: 8.13.2
Show newest version
/*
 * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
 * or more contributor license agreements. Licensed under the Elastic License
 * 2.0; you may not use this file except in compliance with the Elastic License
 * 2.0.
 */
package org.elasticsearch.xpack.core.ssl;

import org.elasticsearch.common.settings.SecureSetting;
import org.elasticsearch.common.settings.SecureString;
import org.elasticsearch.common.settings.Setting;
import org.elasticsearch.common.util.CollectionUtils;

import javax.net.ssl.KeyManagerFactory;
import java.security.KeyStore;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * An encapsulation of the configuration options for X.509 Key Pair support in X-Pack security.
 * The most common use is as the private key and associated certificate for SSL/TLS support, but it can also be used for providing
 * signing or encryption keys (if they are X.509 based).
 * This class supports using a {@link java.security.KeyStore} (with configurable {@link KeyStore#getType() type}) or PEM based files.
 */
public class X509KeyPairSettings {

    static final Function>> KEYSTORE_PATH_TEMPLATE = key -> new Setting<>(key, s -> null,
            Optional::ofNullable, Setting.Property.NodeScope, Setting.Property.Filtered);

    static final Function> LEGACY_KEYSTORE_PASSWORD_TEMPLATE = key -> new Setting<>(key, "",
            SecureString::new, Setting.Property.Deprecated, Setting.Property.Filtered, Setting.Property.NodeScope);
    static final Function> KEYSTORE_PASSWORD_TEMPLATE = key -> SecureSetting.secureString(key,
            LEGACY_KEYSTORE_PASSWORD_TEMPLATE.apply(key.replace("keystore.secure_password", "keystore.password")));

    static final Function> KEY_STORE_ALGORITHM_TEMPLATE = key ->
            new Setting<>(key, s -> KeyManagerFactory.getDefaultAlgorithm(),
                    Function.identity(), Setting.Property.NodeScope, Setting.Property.Filtered);

    static final Function>> KEY_STORE_TYPE_TEMPLATE = key ->
            new Setting<>(key, s -> null, Optional::ofNullable, Setting.Property.NodeScope, Setting.Property.Filtered);

    static final Function> LEGACY_KEYSTORE_KEY_PASSWORD_TEMPLATE = key -> new Setting<>(key, "",
            SecureString::new, Setting.Property.Deprecated, Setting.Property.Filtered, Setting.Property.NodeScope);
    static final Function> KEYSTORE_KEY_PASSWORD_TEMPLATE = key ->
            SecureSetting.secureString(key, LEGACY_KEYSTORE_KEY_PASSWORD_TEMPLATE.apply(key.replace("keystore.secure_key_password",
                    "keystore.key_password")));

    static final Function>> KEY_PATH_TEMPLATE = key -> new Setting<>(key, s -> null,
            Optional::ofNullable, Setting.Property.NodeScope, Setting.Property.Filtered);

    static final Function>> CERT_TEMPLATE = key -> new Setting<>(key, s -> null,
            Optional::ofNullable, Setting.Property.NodeScope, Setting.Property.Filtered);

    static final Function> LEGACY_KEY_PASSWORD_TEMPLATE = key -> new Setting<>(key, "",
            SecureString::new, Setting.Property.Deprecated, Setting.Property.Filtered, Setting.Property.NodeScope);
    static final Function> KEY_PASSWORD_TEMPLATE = key ->
            SecureSetting.secureString(key, LEGACY_KEY_PASSWORD_TEMPLATE.apply(key.replace("secure_key_passphrase",
                    "key_passphrase")));


    // Specify private cert/key pair via keystore
    final Setting> keystorePath;
    final Setting keystorePassword;
    final Setting keystoreAlgorithm;
    final Setting> keystoreType;
    final Setting keystoreKeyPassword;

    // Specify private cert/key pair via key and certificate files
    final Setting> keyPath;
    final Setting keyPassword;
    final Setting> certificatePath;

    // Optional support for legacy (non secure) passwords
    // pkg private for tests
    final Setting legacyKeystorePassword;
    final Setting legacyKeystoreKeyPassword;
    final Setting legacyKeyPassword;

    private final List> allSettings;

    private interface SettingFactory {
         Setting apply(String keyPart, Function> template);
    }

    private X509KeyPairSettings(boolean acceptNonSecurePasswords, SettingFactory factory) {
        keystorePath = factory.apply("keystore.path", KEYSTORE_PATH_TEMPLATE);
        keystorePassword = factory.apply("keystore.secure_password", KEYSTORE_PASSWORD_TEMPLATE);
        keystoreAlgorithm = factory.apply("keystore.algorithm", KEY_STORE_ALGORITHM_TEMPLATE);
        keystoreType = factory.apply("keystore.type", KEY_STORE_TYPE_TEMPLATE);
        keystoreKeyPassword = factory.apply("keystore.secure_key_password", KEYSTORE_KEY_PASSWORD_TEMPLATE);

        keyPath = factory.apply("key", KEY_PATH_TEMPLATE);
        keyPassword = factory.apply("secure_key_passphrase", KEY_PASSWORD_TEMPLATE);
        certificatePath = factory.apply("certificate", CERT_TEMPLATE);

        legacyKeystorePassword = factory.apply("keystore.password", LEGACY_KEYSTORE_PASSWORD_TEMPLATE);
        legacyKeystoreKeyPassword = factory.apply("keystore.key_password", LEGACY_KEYSTORE_KEY_PASSWORD_TEMPLATE);
        legacyKeyPassword = factory.apply("key_passphrase", LEGACY_KEY_PASSWORD_TEMPLATE);

        final List> settings = CollectionUtils.arrayAsArrayList(
                keystorePath, keystorePassword, keystoreAlgorithm, keystoreType, keystoreKeyPassword,
                keyPath, keyPassword, certificatePath);
        if (acceptNonSecurePasswords) {
            settings.add(legacyKeystorePassword);
            settings.add(legacyKeystoreKeyPassword);
            settings.add(legacyKeyPassword);
        }
        allSettings = Collections.unmodifiableList(settings);
    }

    public static X509KeyPairSettings withPrefix(String prefix, boolean acceptNonSecurePasswords) {
        return new X509KeyPairSettings(acceptNonSecurePasswords, new SettingFactory() {
            @Override
            public  Setting apply(String key, Function> template) {
                return template.apply(prefix + key);
            }
        });
    }

    public static Collection> affix(String prefix, String suffixPart, boolean acceptNonSecurePasswords) {
        final X509KeyPairSettings settings = new X509KeyPairSettings(acceptNonSecurePasswords, new SettingFactory() {
            @Override
            public  Setting apply(String keyPart, Function> template) {
                return Setting.affixKeySetting(prefix, suffixPart + keyPart, template);
            }
        });
        return settings.getAllSettings().stream().map(s -> (Setting.AffixSetting) s).collect(Collectors.toList());
    }

    public Collection> getAllSettings() {
        return allSettings;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy