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

org.openremote.manager.security.KeyStoreServiceImpl Maven / Gradle / Ivy

/*
 * Copyright 2024, OpenRemote Inc.
 *
 * See the CONTRIBUTORS.txt file in the distribution for a
 * full listing of individual contributors.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see .
 */

package org.openremote.manager.security;

import org.openremote.agent.protocol.mqtt.CustomKeyManagerFactory;
import org.openremote.agent.protocol.mqtt.CustomX509TrustManagerFactory;
import org.openremote.container.persistence.PersistenceService;
import org.openremote.model.Container;
import org.openremote.model.security.KeyStoreService;

import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.TrustManagerFactory;
import java.io.*;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.KeyStore;
import java.util.logging.Logger;
import java.util.Optional;

import static org.openremote.container.util.MapAccess.getString;

/**
 * 

* This service is used for retrieving, creating, or editing KeyStore (and TrustStore) files. *

* Currently the KeyStores are stored in the Storage directory of OpenRemote, which is usually volumed and persisted. *

* Each realm is allocated 2 KeyStores; A Client KeyStore, which is used for storing key-pairs that are used by * clients (be that as an Agent or as a plain client), and a TrustStore, which contains trusted certificates, usually SSL * certificates. To ensure both security and extensibility, both the default and predefined TrustStores are used to find * the correct certificates. *

*/ public class KeyStoreServiceImpl implements KeyStoreService { protected PersistenceService persistenceService; protected ManagerIdentityService identityService; private KeyStore keyStore = null; private KeyStore trustStore = null; private static final String OR_SSL_CLIENT_KEYSTORE_FILE = "OR_SSL_CLIENT_KEYSTORE_FILE"; private static final String OR_SSL_CLIENT_TRUSTSTORE_FILE = "OR_SSL_CLIENT_TRUSTSTORE_FILE"; private static final String OR_SSL_CLIENT_KEYSTORE_PASSWORD = "OR_SSL_CLIENT_KEYSTORE_PASSWORD"; private static final String OR_SSL_CLIENT_TRUSTSTORE_PASSWORD = "OR_SSL_CLIENT_TRUSTSTORE_PASSWORD"; private static final String OR_KEYSTORE_PASSWORD = "OR_KEYSTORE_PASSWORD"; protected Path keyStorePath; protected Path trustStorePath; private String keyStorePassword; @Override public int getPriority() { return ManagerIdentityService.PRIORITY + 10; } @Override public void init(Container container) throws Exception { persistenceService = container.getService(PersistenceService.class); identityService = container.getService(ManagerIdentityService.class); String defaultPassword = getString(container.getConfig(), "OR_ADMIN_PASSWORD", "secret"); keyStorePassword = getString(container.getConfig(), OR_KEYSTORE_PASSWORD, defaultPassword); } @Override public void start(Container container) throws Exception { String keyStoreEnv = getString(container.getConfig(), OR_SSL_CLIENT_KEYSTORE_FILE, null); String trustStoreEnv = getString(container.getConfig(), OR_SSL_CLIENT_TRUSTSTORE_FILE, null); Optional keyStorePath = keyStoreEnv != null ? Optional.of(Paths.get(keyStoreEnv)) : Optional.empty(); Optional trustStorePath = trustStoreEnv != null ? Optional.of(Paths.get(trustStoreEnv)) : Optional.empty(); String keyStorePassword = getString(container.getConfig(), OR_SSL_CLIENT_KEYSTORE_PASSWORD, String.valueOf(getKeyStorePassword())); String trustStorePassword = getString(container.getConfig(), OR_SSL_CLIENT_TRUSTSTORE_PASSWORD, String.valueOf(getKeyStorePassword())); if (keyStorePath.isPresent()) { this.keyStore = KeyStore.getInstance(keyStorePath.get().toFile(), keyStorePassword.toCharArray()); } else { Path defaultKeyStorePath = persistenceService.resolvePath(Paths.get("keystores").resolve("client_keystore.p12")); if (new File(defaultKeyStorePath.toUri()).exists()) { this.keyStorePath = defaultKeyStorePath; this.keyStore = KeyStore.getInstance(new File(defaultKeyStorePath.toUri()), getKeyStorePassword()); } else { this.keyStore = createKeyStore(defaultKeyStorePath); } this.keyStorePath = defaultKeyStorePath; } if (trustStorePath.isPresent()) { this.trustStore = KeyStore.getInstance(trustStorePath.get().toFile(), trustStorePassword.toCharArray()); } else { Path defaultTrustStorePath = persistenceService.resolvePath(Paths.get("keystores").resolve("client_truststore.p12")); if (new File(defaultTrustStorePath.toUri()).exists()) { this.trustStorePath = defaultTrustStorePath; this.trustStore = KeyStore.getInstance(new File(defaultTrustStorePath.toUri()), getKeyStorePassword()); } else { this.trustStore = createKeyStore(defaultTrustStorePath); } this.trustStorePath = defaultTrustStorePath; } } private KeyStore getKeyStore() { try { return KeyStore.getInstance(this.keyStorePath.toAbsolutePath().toFile(), getKeyStorePassword()); } catch (Exception e) { throw new RuntimeException(e); } } private KeyStore getTrustStore() { try { return KeyStore.getInstance(this.trustStorePath.toAbsolutePath().toFile(), getKeyStorePassword()); } catch (Exception e) { throw new RuntimeException(e); } } private void storeKeyStore(KeyStore keystore) { try { this.keyStore = keystore; keystore.store(new FileOutputStream(this.keyStorePath.toFile()), getKeyStorePassword()); } catch (Exception saveException) { getLogger().severe("Couldn't store KeyStore to Storage! " + saveException.getMessage()); } } private void storeTrustStore(KeyStore truststore) { try { this.trustStore = truststore; truststore.store(new FileOutputStream(this.trustStorePath.toFile()), getKeyStorePassword()); } catch (Exception saveException) { getLogger().severe("Couldn't store TrustStore to Storage! " + saveException.getMessage()); } } private char[] getKeyStorePassword() { return this.keyStorePassword.toCharArray(); } @Override public KeyManagerFactory getKeyManagerFactory(String alias) throws Exception { KeyManagerFactory keyManagerFactory = new CustomKeyManagerFactory(alias); try { keyManagerFactory.init(this.keyStore, getKeyStorePassword()); } catch (Exception e) { throw new Exception("Could not retrieve KeyManagerFactory: " + e.getMessage()); } return keyManagerFactory; } @Override public TrustManagerFactory getTrustManagerFactory() throws Exception { CustomX509TrustManagerFactory tmf = new CustomX509TrustManagerFactory(this.trustStore, (KeyStore) null); try { tmf.init((KeyStore) null); } catch (Exception e) { throw new Exception("Could not retrieve KeyManagerFactory: " + e.getMessage()); } return tmf; } protected KeyStore createKeyStore(Path path) throws Exception { KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType()); keystore.load(null, getKeyStorePassword()); File keyStoreFile = path.toAbsolutePath().toFile(); if (keyStoreFile.getParentFile() != null && !keyStoreFile.getParentFile().exists()) { keyStoreFile.getParentFile().mkdirs(); } keyStoreFile.createNewFile(); // Save the newly created KeyStore try (OutputStream os = new FileOutputStream(keyStoreFile)) { keystore.store(os, getKeyStorePassword()); } catch (Exception saveException) { getLogger().severe("Couldn't store KeyStore to Storage! " + saveException.getMessage()); throw saveException; } return keystore; } @Override public void stop(Container container) throws Exception { } private Logger getLogger() { return LOG; } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy