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

org.apache.nifi.toolkit.tls.manager.BaseTlsManager Maven / Gradle / Ivy

There is a newer version: 1.28.1
Show newest version
/*
 * 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.toolkit.tls.manager;

import org.apache.nifi.security.util.KeyStoreUtils;
import org.apache.nifi.toolkit.tls.configuration.TlsConfig;
import org.apache.nifi.toolkit.tls.manager.writer.ConfigurationWriter;
import org.apache.nifi.toolkit.tls.util.InputStreamFactory;
import org.apache.nifi.toolkit.tls.util.OutputStreamFactory;
import org.apache.nifi.toolkit.tls.util.PasswordUtil;
import org.apache.nifi.toolkit.tls.util.TlsHelper;
import org.apache.nifi.util.StringUtils;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.GeneralSecurityException;
import java.security.KeyPair;
import java.security.KeyStore;
import java.security.cert.Certificate;
import java.util.ArrayList;
import java.util.List;

/**
 * Base class for managing KeyStores and Certificates
 */
public class BaseTlsManager {
    private final TlsConfig tlsConfig;
    private final PasswordUtil passwordUtil;
    private final InputStreamFactory inputStreamFactory;
    private final KeyStore keyStore;
    private final List> configurationWriters;
    private boolean differentKeyAndKeyStorePassword = false;
    private boolean keyStorePasswordGenerated = false;

    public BaseTlsManager(TlsConfig tlsConfig) throws GeneralSecurityException, IOException {
        this(tlsConfig, new PasswordUtil(), FileInputStream::new);
    }

    public BaseTlsManager(TlsConfig tlsConfig, PasswordUtil passwordUtil, InputStreamFactory inputStreamFactory) throws GeneralSecurityException, IOException {
        this.tlsConfig = tlsConfig;
        this.passwordUtil = passwordUtil;
        this.inputStreamFactory = inputStreamFactory;
        this.keyStore = loadKeystore(tlsConfig.getKeyStore(), tlsConfig.getKeyStoreType(), getKeyStorePassword());
        this.configurationWriters = new ArrayList<>();
    }

    /**
     * Returns the KeyStore
     *
     * @return the KeyStore
     */
    public KeyStore getKeyStore() {
        return keyStore;
    }

    /**
     * Returns an entry from the KeyStore with the given alias
     *
     * @param alias the alias
     * @return an entry from the KeyStore with the given alias
     * @throws GeneralSecurityException if there is a problem retrieving the entry
     */
    public KeyStore.Entry getEntry(String alias) throws GeneralSecurityException {
        String keyPassword = getKeyPassword();
        return keyStore.getEntry(alias, new KeyStore.PasswordProtection(keyPassword == null ? null : keyPassword.toCharArray()));
    }

    /**
     * Adds the private key of the KeyPair to the KeyStore and returns the entry
     *
     * @param keyPair the KeyPair
     * @param alias the alias
     * @param certificates the certificate chain
     * @return the entry
     * @throws GeneralSecurityException if there is a problem performing the operation
     */
    public KeyStore.Entry addPrivateKeyToKeyStore(KeyPair keyPair, String alias, Certificate... certificates) throws GeneralSecurityException {
        String passphrase = getKeyPassword();
        keyStore.setKeyEntry(alias, keyPair.getPrivate(), passphrase == null ? null : passphrase.toCharArray(), certificates);
        return getEntry(alias);
    }

    /**
     * Sets a flag indicating whether to use a different key and keystore password
     *
     * @param differentKeyAndKeyStorePassword a flag indicating whether to use a different key and keystore password
     */
    public void setDifferentKeyAndKeyStorePassword(boolean differentKeyAndKeyStorePassword) {
        this.differentKeyAndKeyStorePassword = differentKeyAndKeyStorePassword;
    }

    private String getKeyPassword() {
        String result = tlsConfig.getKeyPassword();
        if (StringUtils.isEmpty(result)) {
            if (differentKeyAndKeyStorePassword) {
                result = passwordUtil.generatePassword();
            } else {
                result = getKeyStorePassword();
            }
            tlsConfig.setKeyPassword(result);
        }
        return result;
    }

    private String getKeyStorePassword() {
        String result = tlsConfig.getKeyStorePassword();
        if (StringUtils.isEmpty(result)) {
            result = passwordUtil.generatePassword();
            keyStorePasswordGenerated = true;
            tlsConfig.setKeyStorePassword(result);
        }
        return result;
    }

    protected KeyStore loadKeystore(String keyStore, String keyStoreType, String keyStorePassword) throws GeneralSecurityException, IOException {
        KeyStore result = KeyStoreUtils.getKeyStore(keyStoreType);
        File file = new File(keyStore);
        if (file.exists()) {
            try (InputStream stream = inputStreamFactory.create(file)) {
                result.load(stream, keyStorePassword.toCharArray());
            }
            return result;
        }
        result.load(null, null);
        return result;
    }

    /**
     * Writes the KeyStore and configuration information
     *
     * @param outputStreamFactory factory interface for creating output streams
     * @throws IOException if there is an IO problem while writing
     * @throws GeneralSecurityException if there is a security problem while writing
     */
    public void write(OutputStreamFactory outputStreamFactory) throws IOException, GeneralSecurityException {
        String keyStorePassword = getKeyStorePassword();
        tlsConfig.setKeyStorePassword(TlsHelper.writeKeyStore(keyStore, outputStreamFactory, new File(tlsConfig.getKeyStore()), keyStorePassword, keyStorePasswordGenerated));

        for (ConfigurationWriter configurationWriter : configurationWriters) {
            configurationWriter.write(tlsConfig, outputStreamFactory);
        }
    }

    protected PasswordUtil getPasswordUtil() {
        return passwordUtil;
    }

    /**
     * Adds a ConfigurationWriter which will have an opportunity to write configuration information
     *
     * @param configurationWriter a ConfigurationWriter which will have an opportunity to write configuration information
     */
    public void addConfigurationWriter(ConfigurationWriter configurationWriter) {
        configurationWriters.add(configurationWriter);
    }

    protected TlsConfig getTlsConfig() {
        return tlsConfig;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy