Code development platform for open source projects from the European Union institutions

Skip to content
Snippets Groups Projects
Commit 726195bf authored by Joze RIHTARSIC's avatar Joze RIHTARSIC
Browse files

[EDELIVERY-13125] update keystore keys handling

parent 80ff7f6e
No related branches found
No related tags found
No related merge requests found
Pipeline #159271 passed with warnings
......@@ -51,7 +51,7 @@ cleanExternalImageResources() {
}
composeBuildImage() {
echo "Build ${IMAGE_NAME_DOMIBUS_SOAPUI} image..."
echo "Build ${IMAGE_SMP_WEBLOGIC122} image..."
docker compose -f docker-compose.build.yml build
}
......
......@@ -51,7 +51,7 @@ cleanExternalImageResources() {
}
composeBuildImage() {
echo "Build ${IMAGE_NAME_DOMIBUS_SOAPUI} image..."
echo "Build ${IMAGE_SMP_WEBLOGIC141} image..."
docker compose -f docker-compose.build.yml build
}
......
......@@ -8,9 +8,9 @@
* versions of the EUPL (the "Licence");
* You may not use this work except in compliance with the Licence.
* You may obtain a copy of the Licence at:
*
*
* [PROJECT_HOME]\license\eupl-1.2\license.txt or https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
*
*
* Unless required by applicable law or agreed to in writing, software distributed under the Licence is
* distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the Licence for the specific language governing permissions and limitations under the Licence.
......@@ -32,7 +32,11 @@ import org.springframework.stereotype.Service;
import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import java.io.*;
import javax.net.ssl.X509KeyManager;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.security.*;
import java.security.cert.Certificate;
......@@ -62,7 +66,7 @@ public class UIKeystoreService extends BasicKeystoreService {
this.configurationService = configurationService;
}
private final Map<String, Key> keystoreKeys = new HashMap<>();
private final List<String> keystoreKeys = new ArrayList<>(); // list of aliases with private keys
private final Map<String, X509Certificate> keystoreCertificates = new HashMap<>();
private final List<CertificateRO> certificateROList = new ArrayList<>();
......@@ -97,19 +101,20 @@ public class UIKeystoreService extends BasicKeystoreService {
KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
kmf.init(keyStore, keystoreSecToken.toCharArray());
keyManagersTemp = kmf.getKeyManagers();
} catch (KeyStoreException | NoSuchAlgorithmException | UnrecoverableKeyException exception) {
} catch (KeyStoreException | NoSuchAlgorithmException |
UnrecoverableKeyException exception) {
LOG.error("Error occurred while initialize keyManagers : "
+ keystoreFile.getAbsolutePath() + " Error: " + ExceptionUtils.getRootCauseMessage(exception), exception);
return;
}
// load keys for signature
Map<String, Key> hmKeys = new HashMap<>();
List<String> keyList = new ArrayList<>();
Map<String, X509Certificate> hmCertificates = new HashMap<>();
try {
List<String> aliases = list(keyStore.aliases());
for (String alias : aliases) {
loadKeyAndCert(keyStore, alias, keystoreSecToken, hmKeys, hmCertificates);
loadKeyAndCert(keyStore, alias, keyList, hmCertificates);
}
} catch (Exception exception) {
LOG.error("Could not load signing certificate amd private keys Error: " + ExceptionUtils.getRootCauseMessage(exception), exception);
......@@ -123,7 +128,7 @@ public class UIKeystoreService extends BasicKeystoreService {
keystoreKeys.clear();
keystoreCertificates.clear();
keystoreKeys.putAll(hmKeys);
keystoreKeys.addAll(keyList);
keystoreCertificates.putAll(hmCertificates);
// add last file date
lastUpdateKeystoreFileTime = keystoreFile.lastModified();
......@@ -172,15 +177,17 @@ public class UIKeystoreService extends BasicKeystoreService {
return keyStore;
}
private void loadKeyAndCert(KeyStore keyStore, String alias, String keySecurityToken, Map<String, Key> hmKeys, Map<String, X509Certificate> hmCertificates) throws KeyStoreException, NoSuchAlgorithmException, UnrecoverableKeyException {
Key key = keyStore.getKey(alias, keySecurityToken.toCharArray());
private void loadKeyAndCert(KeyStore keyStore, String alias, List<String> keyList, Map<String, X509Certificate> hmCertificates) throws KeyStoreException {
Certificate certificate = keyStore.getCertificate(alias);
if (!(certificate instanceof X509Certificate)) {
LOG.warn("Wrong certificate type found in keystore, entry alias: [{}]. Entry is ignored", alias);
return;
}
// add to cache
hmKeys.put(alias, key);
if (keyStore.isKeyEntry(alias)) {
keyList.add(alias);
}
hmCertificates.put(alias, (X509Certificate) certificate);
}
......@@ -196,7 +203,7 @@ public class UIKeystoreService extends BasicKeystoreService {
CertificateRO certificateRO = convertToRo(cert);
basicCertificateValidation(cert, certificateRO);
certificateRO.setAlias(alias);
certificateRO.setContainingKey(keystoreKeys.get(alias) != null);
certificateRO.setContainingKey(keystoreKeys.contains(alias));
certificateROList.add(certificateRO);
});
}
......@@ -208,30 +215,52 @@ public class UIKeystoreService extends BasicKeystoreService {
return conversionService.convert(d, CertificateRO.class);
}
/**
* Get key from keystore by the alias from the registered keyManagers
*
* @param keyAlias alias of the key or null for the only key in the keystore
* @return key from keystore
* @throws SMPRuntimeException if the key for alias is not found in the keystore
*/
public Key getKey(String keyAlias) {
if (isKeyStoreChanged()) {
refreshData();
}
if (keystoreKeys.isEmpty()) {
throw new SMPRuntimeException(ErrorCode.CONFIGURATION_ERROR, "Could not retrieve key: [" + keyAlias + "] from empty keystore: [" + configurationService.getKeystoreFile() +"]!");
if (keystoreKeys.isEmpty() || keyManagers == null || keyManagers.length < 1) {
throw new SMPRuntimeException(ErrorCode.CONFIGURATION_ERROR, "Could not retrieve key: [" + keyAlias + "] from empty keystore: [" + configurationService.getKeystoreFile() + "]!");
}
final String searchAlias = getKeyAlias(keyAlias);
// get all X509KeyManager
return Arrays.stream(keyManagers)
.filter(X509KeyManager.class::isInstance)
.map(X509KeyManager.class::cast)
.map(km -> km.getPrivateKey(searchAlias))
.findFirst()
.orElseThrow(() -> new SMPRuntimeException(ErrorCode.CONFIGURATION_ERROR,
"Could not retrieve key: [" + keyAlias + "] from empty keystore: [" + configurationService.getKeystoreFile() + "]!"));
}
if (keystoreKeys.size() == 1) {
// for backward compatibility...
// don't care about configured alias in single-domain setup
// and return the only key
LOG.warn("Returning the only key in keystore regardless the configuration");
return keystoreKeys.values().iterator().next();
/**
* Get key from keystore by the alias from the registered keyManagers.
* Legacy behaviour: If the alias is not provided and there is only one key in the keystore, the key is returned.
*
* @param keyAlias alias of the key or null
* @return non null key alias
* @throws SMPRuntimeException if the keyAlias is not found in the keystore
*/
private String getKeyAlias(String keyAlias) {
String trimAlias = StringUtils.trim(keyAlias);
if (StringUtils.isBlank(trimAlias) && keystoreKeys.size() == 1) {
trimAlias = keystoreKeys.get(0);
}
if (isBlank(keyAlias) || !keystoreKeys.containsKey(keyAlias)) {
if (isBlank(trimAlias) || !keystoreKeys.contains(trimAlias)) {
throw new SMPRuntimeException(ErrorCode.CONFIGURATION_ERROR, "Wrong configuration, missing key pair from keystore or wrong alias: " + keyAlias);
}
return keystoreKeys.get(keyAlias);
return trimAlias;
}
public X509Certificate getCert(String certAlias) {
......@@ -256,7 +285,7 @@ public class UIKeystoreService extends BasicKeystoreService {
/**
* Import keys smp keystore
*
* @param newKeystore new keystore file to import
* @param newKeystore new keystore file to import
* @param password password for new keystore file
*/
public List<CertificateRO> importKeys(KeyStore newKeystore, String password) throws UnrecoverableKeyException, NoSuchAlgorithmException, KeyStoreException, IOException, CertificateException {
......@@ -276,7 +305,7 @@ public class UIKeystoreService extends BasicKeystoreService {
/**
* Returns entries having certificates that are already present in the current keystore.
*
* @param newKeystore new keystore file to import
* @param newKeystore new keystore file to import
* @return the set of duplicate certificates
* @throws KeyStoreException when not able to read the keystore aliases
*/
......@@ -312,10 +341,10 @@ public class UIKeystoreService extends BasicKeystoreService {
* Store keystore
*
* @param keyStore to store
* @throws IOException if the keystore can not be persisted
* @throws CertificateException if keystore cannot be stored
* @throws IOException if the keystore can not be persisted
* @throws CertificateException if keystore cannot be stored
* @throws NoSuchAlgorithmException if keystore type algorithm is not supported
* @throws KeyStoreException if keystore cannot be stored
* @throws KeyStoreException if keystore cannot be stored
*/
private void storeKeystore(KeyStore keyStore) throws IOException, CertificateException, NoSuchAlgorithmException, KeyStoreException {
File keystoreFilePath = configurationService.getKeystoreFile();
......
......@@ -45,11 +45,13 @@ import java.util.UUID;
import static eu.europa.ec.edelivery.smp.testutil.TestConstants.SIMPLE_EXTENSION_XML;
public class TestDBUtils {
// valid key alias for testing from the keystore
public static final String TEST_KEY_ALIAS = "single_domain_key";
public static DBDomain createDBDomain(String domainCode) {
DBDomain domain = new DBDomain();
domain.setDomainCode(domainCode);
domain.setSignatureKeyAlias(anyString());
domain.setSignatureKeyAlias(TEST_KEY_ALIAS);
domain.setSmlClientKeyAlias(anyString());
domain.setSmlSubdomain(anyString());
domain.setSmlSmpId(anyString());
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment