diff options
author | Tomasz Wrobel <tomasz.wrobel@nokia.com> | 2020-08-19 10:38:43 +0200 |
---|---|---|
committer | Tomasz Wrobel <tomasz.wrobel@nokia.com> | 2020-08-27 15:02:07 +0200 |
commit | 2512d60868bf25f91e4aa4b857d4ba373579f0fd (patch) | |
tree | e46d4010b6fc873facbf0222225eb822d3284dac /trustStoreMerger/src/main | |
parent | a1def56303f42c197156ed3862f733df32001bb7 (diff) |
Add Certification merge logic
Issue-ID: DCAEGEN2-2253
Signed-off-by: Tomasz Wrobel <tomasz.wrobel@nokia.com>
Change-Id: I4157ce71373b41d9f7ee03b76d407ec7a2b17ec3
Diffstat (limited to 'trustStoreMerger/src/main')
32 files changed, 1002 insertions, 190 deletions
diff --git a/trustStoreMerger/src/main/java/org/onap/oom/truststoremerger/TrustStoreMerger.java b/trustStoreMerger/src/main/java/org/onap/oom/truststoremerger/TrustStoreMerger.java index 98c67ba8..c8cc84df 100644 --- a/trustStoreMerger/src/main/java/org/onap/oom/truststoremerger/TrustStoreMerger.java +++ b/trustStoreMerger/src/main/java/org/onap/oom/truststoremerger/TrustStoreMerger.java @@ -21,11 +21,12 @@ package org.onap.oom.truststoremerger; import org.onap.oom.truststoremerger.api.ExitStatus; import org.onap.oom.truststoremerger.api.ExitableException; -import org.onap.oom.truststoremerger.certification.file.TruststoreFile; +import org.onap.oom.truststoremerger.certification.file.provider.entry.CertificateWithAlias; +import org.onap.oom.truststoremerger.certification.file.model.Truststore; import org.onap.oom.truststoremerger.certification.file.provider.FileManager; import org.onap.oom.truststoremerger.certification.file.provider.PasswordReader; -import org.onap.oom.truststoremerger.certification.file.provider.TruststoreFileFactory; -import org.onap.oom.truststoremerger.certification.file.provider.TruststoreFilesListProvider; +import org.onap.oom.truststoremerger.certification.file.TruststoreFileFactory; +import org.onap.oom.truststoremerger.certification.file.TruststoreFilesListProvider; import org.onap.oom.truststoremerger.certification.path.EnvProvider; import org.onap.oom.truststoremerger.certification.path.TruststoresPathsProvider; import org.onap.oom.truststoremerger.configuration.MergerConfiguration; @@ -33,9 +34,15 @@ import org.onap.oom.truststoremerger.configuration.MergerConfigurationFactory; import org.onap.oom.truststoremerger.certification.path.PathValidator; import java.util.List; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; class TrustStoreMerger { + private static final Logger LOGGER = LoggerFactory.getLogger(TrustStoreMerger.class); + private static final int FIRST_TRUSTSTORE_INDEX = 0; + private static final int SECOND_TRUSTSTORE_INDEX = 1; + private final AppExitHandler appExitHandler; TrustStoreMerger(AppExitHandler appExitHandler) { @@ -47,28 +54,42 @@ class TrustStoreMerger { mergeTruststores(); appExitHandler.exit(ExitStatus.SUCCESS); } catch (ExitableException e) { + LOGGER.error("Truststore Merger fails in execution: ", e); appExitHandler.exit(e.applicationExitStatus()); } } private void mergeTruststores() throws ExitableException { MergerConfiguration configuration = loadConfiguration(); - List<TruststoreFile> truststoreFilesList = getTruststoreFilesList(configuration); + List<Truststore> truststoreFilesList = getTruststoreFilesList(configuration); + + Truststore baseFile = truststoreFilesList.get(FIRST_TRUSTSTORE_INDEX); + baseFile.createBackup(); + + for (int i = SECOND_TRUSTSTORE_INDEX; i < truststoreFilesList.size(); i++) { + List<CertificateWithAlias> certificateWrappers = truststoreFilesList.get(i).getCertificates(); + baseFile.addCertificate(certificateWrappers); + } + + baseFile.saveFile(); } private MergerConfiguration loadConfiguration() throws ExitableException { - TruststoresPathsProvider truststoresPathsProvider = new TruststoresPathsProvider(new EnvProvider(), new PathValidator()); + TruststoresPathsProvider truststoresPathsProvider = new TruststoresPathsProvider(new EnvProvider(), + new PathValidator()); MergerConfigurationFactory factory = new MergerConfigurationFactory(truststoresPathsProvider); return factory.createConfiguration(); } - private List<TruststoreFile> getTruststoreFilesList(MergerConfiguration configuration) throws ExitableException { - TruststoreFileFactory truststoreFileFactory = new TruststoreFileFactory(new FileManager(), new PasswordReader()); - TruststoreFilesListProvider truststoreFilesListProvider = new TruststoreFilesListProvider(truststoreFileFactory); + private List<Truststore> getTruststoreFilesList(MergerConfiguration configuration) throws ExitableException { + TruststoreFileFactory truststoreFileFactory = new TruststoreFileFactory(new FileManager(), + new PasswordReader()); + TruststoreFilesListProvider truststoreFilesListProvider = new TruststoreFilesListProvider( + truststoreFileFactory); return truststoreFilesListProvider - .getTruststoreFilesList( - configuration.getTruststoreFilePaths(), - configuration.getTruststoreFilePasswordPaths() - ); + .getTruststoreFilesList( + configuration.getTruststoreFilePaths(), + configuration.getTruststoreFilePasswordPaths() + ); } } diff --git a/trustStoreMerger/src/main/java/org/onap/oom/truststoremerger/api/CertificateConstants.java b/trustStoreMerger/src/main/java/org/onap/oom/truststoremerger/api/CertificateConstants.java new file mode 100644 index 00000000..68c5d13c --- /dev/null +++ b/trustStoreMerger/src/main/java/org/onap/oom/truststoremerger/api/CertificateConstants.java @@ -0,0 +1,29 @@ +/*============LICENSE_START======================================================= + * oom-truststore-merger + * ================================================================================ + * Copyright (C) 2020 Nokia. All rights reserved. + * ================================================================================ + * Licensed 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.oom.truststoremerger.api; + +public class CertificateConstants { + + public static final String JKS_INSTANCE = "JKS"; + public static final String PKCS12_INSTANCE = "PKCS12"; + public static final String X_509_CERTIFICATE = "X.509"; + public static final String BOUNCY_CASTLE_PROVIDER = "BC"; + +} diff --git a/trustStoreMerger/src/main/java/org/onap/oom/truststoremerger/api/ConfigurationEnvs.java b/trustStoreMerger/src/main/java/org/onap/oom/truststoremerger/api/ConfigurationEnvs.java index 13c8c726..f6f8bbba 100644 --- a/trustStoreMerger/src/main/java/org/onap/oom/truststoremerger/api/ConfigurationEnvs.java +++ b/trustStoreMerger/src/main/java/org/onap/oom/truststoremerger/api/ConfigurationEnvs.java @@ -21,6 +21,6 @@ package org.onap.oom.truststoremerger.api; public class ConfigurationEnvs { - public static final String TRUSTSTORES_ENV = "TRUSTSTORES"; - public static final String TRUSTSTORES_PASSWORDS_ENV = "TRUSTSTORES_PASSWORDS"; + public static final String TRUSTSTORES_PATHS_ENV = "TRUSTSTORES_PATHS"; + public static final String TRUSTSTORES_PASSWORDS_PATHS_ENV = "TRUSTSTORES_PASSWORDS_PATHS"; } diff --git a/trustStoreMerger/src/main/java/org/onap/oom/truststoremerger/api/ExitStatus.java b/trustStoreMerger/src/main/java/org/onap/oom/truststoremerger/api/ExitStatus.java index d0c3b2f0..b9111bf9 100644 --- a/trustStoreMerger/src/main/java/org/onap/oom/truststoremerger/api/ExitStatus.java +++ b/trustStoreMerger/src/main/java/org/onap/oom/truststoremerger/api/ExitStatus.java @@ -25,7 +25,15 @@ public enum ExitStatus { TRUSTSTORES_PATHS_PROVIDER_EXCEPTION(1, "Invalid paths in environment variables"), MERGER_CONFIGURATION_EXCEPTION(2, "Invalid merger configuration"), TRUSTSTORE_FILE_FACTORY_EXCEPTION(3, "Invalid truststore file-password pair"), - PASSWORD_READER_EXCEPTION(4, "Cannot read password from file"); + PASSWORD_READER_EXCEPTION(4, "Cannot read password from file"), + CREATE_BACKUP_EXCEPTION(5, "Cannot create backup file"), + KEYSTORE_INSTANCE_EXCEPTION(6, "Cannot initialize keystore instance"), + TRUSTSTORE_LOAD_FILE_EXCEPTION(7, "Cannot load truststore file"), + TRUSTSTORE_DATA_OPERATION_EXCEPTION(8, "Cannot operate on truststore data"), + MISSING_TRUSTSTORE_EXCEPTION(9, "Missing truststore certificates in provided file"), + ALIAS_CONFLICT_EXCEPTION(10, "Alias conflict detected"), + WRITE_TRUSTSTORE_FILE_EXCEPTION(11, "Cannot save truststore file"); + private final int value; private final String message; diff --git a/trustStoreMerger/src/main/java/org/onap/oom/truststoremerger/api/ExitableException.java b/trustStoreMerger/src/main/java/org/onap/oom/truststoremerger/api/ExitableException.java index 3cc46730..ec28d466 100644 --- a/trustStoreMerger/src/main/java/org/onap/oom/truststoremerger/api/ExitableException.java +++ b/trustStoreMerger/src/main/java/org/onap/oom/truststoremerger/api/ExitableException.java @@ -35,5 +35,6 @@ public class ExitableException extends Exception { public ExitStatus applicationExitStatus() { return exitStatus; - }; + } + } diff --git a/trustStoreMerger/src/main/java/org/onap/oom/truststoremerger/certification/file/TruststoreFileFactory.java b/trustStoreMerger/src/main/java/org/onap/oom/truststoremerger/certification/file/TruststoreFileFactory.java new file mode 100644 index 00000000..d93409b6 --- /dev/null +++ b/trustStoreMerger/src/main/java/org/onap/oom/truststoremerger/certification/file/TruststoreFileFactory.java @@ -0,0 +1,99 @@ +/*============LICENSE_START======================================================= + * oom-truststore-merger + * ================================================================================ + * Copyright (C) 2020 Nokia. All rights reserved. + * ================================================================================ + * Licensed 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.oom.truststoremerger.certification.file; + +import org.onap.oom.truststoremerger.certification.file.model.JavaTruststore; +import org.onap.oom.truststoremerger.certification.file.model.PemTruststore; +import org.onap.oom.truststoremerger.certification.file.model.Truststore; + +import java.io.File; +import org.onap.oom.truststoremerger.certification.file.exception.KeystoreInstanceException; +import org.onap.oom.truststoremerger.certification.file.exception.LoadTruststoreException; +import org.onap.oom.truststoremerger.certification.file.exception.PasswordReaderException; +import org.onap.oom.truststoremerger.certification.file.exception.TruststoreFileFactoryException; +import org.onap.oom.truststoremerger.certification.file.provider.CertificateStoreControllerFactory; +import org.onap.oom.truststoremerger.certification.file.provider.FileManager; +import org.onap.oom.truststoremerger.certification.file.provider.JavaCertificateStoreController; +import org.onap.oom.truststoremerger.certification.file.provider.PasswordReader; +import org.onap.oom.truststoremerger.certification.file.provider.PemCertificateController; + +public class TruststoreFileFactory { + + private static final String JKS_EXTENSION = ".jks"; + private static final String P12_EXTENSION = ".p12"; + private static final String PEM_EXTENSION = ".pem"; + private static final String FILE_DOES_NOT_EXIST_MSG_TEMPLATE = "File: %s does not exist"; + private static final String UNKNOWN_TRUSTSTORE_TYPE_MSG_TEMPLATE = "Unknown truststore extension type: %s"; + + private final FileManager fileManager; + private final PasswordReader passwordReader; + private final CertificateStoreControllerFactory certificateStoreControllerFactory = + new CertificateStoreControllerFactory(); + + public TruststoreFileFactory(FileManager fileManager, PasswordReader passwordReader) { + this.fileManager = fileManager; + this.passwordReader = passwordReader; + } + + public Truststore create(String truststoreFilePath, String truststorePasswordPath) + throws TruststoreFileFactoryException, PasswordReaderException, KeystoreInstanceException, LoadTruststoreException { + File truststoreFile = new File(truststoreFilePath); + if (!fileManager.checkIfFileExists(truststoreFile)) { + throw new TruststoreFileFactoryException(String.format(FILE_DOES_NOT_EXIST_MSG_TEMPLATE, truststoreFile)); + } + return createTypedTruststore(truststoreFile, truststorePasswordPath); + } + + private Truststore createTypedTruststore(File truststoreFile, String truststorePasswordPath) + throws KeystoreInstanceException, PasswordReaderException, LoadTruststoreException, TruststoreFileFactoryException { + String extension = fileManager.getExtension(truststoreFile); + switch (extension) { + case JKS_EXTENSION: + return createJksTruststore(truststoreFile, truststorePasswordPath); + case P12_EXTENSION: + return createP12Truststore(truststoreFile, truststorePasswordPath); + case PEM_EXTENSION: + return createPemTruststore(truststoreFile); + default: + throw new TruststoreFileFactoryException( + String.format(UNKNOWN_TRUSTSTORE_TYPE_MSG_TEMPLATE, extension)); + } + } + + private JavaTruststore createJksTruststore(File truststoreFile, String truststorePasswordPath) + throws PasswordReaderException, LoadTruststoreException, KeystoreInstanceException { + String password = passwordReader.readPassword(new File(truststorePasswordPath)); + JavaCertificateStoreController storeController = certificateStoreControllerFactory + .createLoadedJksCertificateStoreController(truststoreFile, password); + return new JavaTruststore(truststoreFile, storeController); + } + + private JavaTruststore createP12Truststore(File truststoreFile, String truststorePasswordPath) + throws LoadTruststoreException, KeystoreInstanceException, PasswordReaderException { + String password = passwordReader.readPassword(new File(truststorePasswordPath)); + JavaCertificateStoreController storeController = certificateStoreControllerFactory + .createLoadedPkcs12CertificateStoreController(truststoreFile, password); + return new JavaTruststore(truststoreFile, storeController); + } + + private PemTruststore createPemTruststore(File truststoreFile) { + return new PemTruststore(truststoreFile, new PemCertificateController(truststoreFile)); + } +} diff --git a/trustStoreMerger/src/main/java/org/onap/oom/truststoremerger/certification/file/provider/TruststoreFilesListProvider.java b/trustStoreMerger/src/main/java/org/onap/oom/truststoremerger/certification/file/TruststoreFilesListProvider.java index 2f5356d5..92e3c2a8 100644 --- a/trustStoreMerger/src/main/java/org/onap/oom/truststoremerger/certification/file/provider/TruststoreFilesListProvider.java +++ b/trustStoreMerger/src/main/java/org/onap/oom/truststoremerger/certification/file/TruststoreFilesListProvider.java @@ -17,13 +17,16 @@ * ============LICENSE_END========================================================= */ -package org.onap.oom.truststoremerger.certification.file.provider; +package org.onap.oom.truststoremerger.certification.file; -import org.onap.oom.truststoremerger.certification.file.TruststoreFile; +import org.onap.oom.truststoremerger.certification.file.model.Truststore; import java.util.ArrayList; -import java.util.Iterator; import java.util.List; +import org.onap.oom.truststoremerger.certification.file.exception.KeystoreInstanceException; +import org.onap.oom.truststoremerger.certification.file.exception.LoadTruststoreException; +import org.onap.oom.truststoremerger.certification.file.exception.PasswordReaderException; +import org.onap.oom.truststoremerger.certification.file.exception.TruststoreFileFactoryException; public class TruststoreFilesListProvider { @@ -33,16 +36,16 @@ public class TruststoreFilesListProvider { this.truststoreFileFactory = truststoreFileFactory; } - public List<TruststoreFile> getTruststoreFilesList(List<String> truststoreFilePaths, - List<String> truststoreFilePasswordPaths) - throws PasswordReaderException, TruststoreFileFactoryException { - List<TruststoreFile> truststoreFilesList = new ArrayList<>(); + public List<Truststore> getTruststoreFilesList(List<String> truststoreFilePaths, + List<String> truststoreFilePasswordPaths) + throws LoadTruststoreException, PasswordReaderException, TruststoreFileFactoryException, KeystoreInstanceException { + List<Truststore> truststoreFilesList = new ArrayList<>(); for (int i = 0; i < truststoreFilePaths.size(); i++) { String truststorePath = truststoreFilePaths.get(i); String passwordPath = truststoreFilePasswordPaths.get(i); - TruststoreFile truststoreFile = truststoreFileFactory.create(truststorePath, passwordPath); - truststoreFilesList.add(truststoreFile); + Truststore truststore = truststoreFileFactory.create(truststorePath, passwordPath); + truststoreFilesList.add(truststore); } return truststoreFilesList; diff --git a/trustStoreMerger/src/main/java/org/onap/oom/truststoremerger/certification/file/TruststoreFileWithPassword.java b/trustStoreMerger/src/main/java/org/onap/oom/truststoremerger/certification/file/exception/AliasConflictException.java index 484f2d4f..a4102d9f 100644 --- a/trustStoreMerger/src/main/java/org/onap/oom/truststoremerger/certification/file/TruststoreFileWithPassword.java +++ b/trustStoreMerger/src/main/java/org/onap/oom/truststoremerger/certification/file/exception/AliasConflictException.java @@ -17,19 +17,15 @@ * ============LICENSE_END========================================================= */ -package org.onap.oom.truststoremerger.certification.file; +package org.onap.oom.truststoremerger.certification.file.exception; -import java.io.File; +import org.onap.oom.truststoremerger.api.ExitStatus; +import org.onap.oom.truststoremerger.api.ExitableException; -public abstract class TruststoreFileWithPassword extends TruststoreFile { - private String password; +public class AliasConflictException extends ExitableException { - TruststoreFileWithPassword(File truststoreFile, String password) { - super(truststoreFile); - this.password = password; + public AliasConflictException(String message) { + super(message, ExitStatus.ALIAS_CONFLICT_EXCEPTION); } - public String getPassword(){ - return password; - }; } diff --git a/trustStoreMerger/src/main/java/org/onap/oom/truststoremerger/certification/file/exception/CreateBackupException.java b/trustStoreMerger/src/main/java/org/onap/oom/truststoremerger/certification/file/exception/CreateBackupException.java new file mode 100644 index 00000000..a21f7013 --- /dev/null +++ b/trustStoreMerger/src/main/java/org/onap/oom/truststoremerger/certification/file/exception/CreateBackupException.java @@ -0,0 +1,30 @@ +/*============LICENSE_START======================================================= + * oom-truststore-merger + * ================================================================================ + * Copyright (C) 2020 Nokia. All rights reserved. + * ================================================================================ + * Licensed 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.oom.truststoremerger.certification.file.exception; + +import org.onap.oom.truststoremerger.api.ExitStatus; +import org.onap.oom.truststoremerger.api.ExitableException; + +public class CreateBackupException extends ExitableException { + + public CreateBackupException(Exception e) { + super(e, ExitStatus.CREATE_BACKUP_EXCEPTION); + } +} diff --git a/trustStoreMerger/src/main/java/org/onap/oom/truststoremerger/certification/file/exception/KeystoreInstanceException.java b/trustStoreMerger/src/main/java/org/onap/oom/truststoremerger/certification/file/exception/KeystoreInstanceException.java new file mode 100644 index 00000000..c5bcc3ca --- /dev/null +++ b/trustStoreMerger/src/main/java/org/onap/oom/truststoremerger/certification/file/exception/KeystoreInstanceException.java @@ -0,0 +1,30 @@ +/*============LICENSE_START======================================================= + * oom-truststore-merger + * ================================================================================ + * Copyright (C) 2020 Nokia. All rights reserved. + * ================================================================================ + * Licensed 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.oom.truststoremerger.certification.file.exception; + +import org.onap.oom.truststoremerger.api.ExitStatus; +import org.onap.oom.truststoremerger.api.ExitableException; + +public class KeystoreInstanceException extends ExitableException { + + public KeystoreInstanceException(Throwable e) { + super(e, ExitStatus.KEYSTORE_INSTANCE_EXCEPTION); + } +} diff --git a/trustStoreMerger/src/main/java/org/onap/oom/truststoremerger/certification/file/PemTruststore.java b/trustStoreMerger/src/main/java/org/onap/oom/truststoremerger/certification/file/exception/LoadTruststoreException.java index ca2ac85d..b8bb53fa 100644 --- a/trustStoreMerger/src/main/java/org/onap/oom/truststoremerger/certification/file/PemTruststore.java +++ b/trustStoreMerger/src/main/java/org/onap/oom/truststoremerger/certification/file/exception/LoadTruststoreException.java @@ -17,21 +17,14 @@ * ============LICENSE_END========================================================= */ -package org.onap.oom.truststoremerger.certification.file; +package org.onap.oom.truststoremerger.certification.file.exception; -import java.io.File; -import java.security.cert.Certificate; -import java.util.Collections; -import java.util.List; +import org.onap.oom.truststoremerger.api.ExitStatus; +import org.onap.oom.truststoremerger.api.ExitableException; -public class PemTruststore extends TruststoreFile { +public class LoadTruststoreException extends ExitableException { - public PemTruststore(File truststoreFile) { - super(truststoreFile); - } - - @Override - public List<Certificate> getCertificates() { - return Collections.emptyList(); + public LoadTruststoreException(Throwable e) { + super(e, ExitStatus.TRUSTSTORE_LOAD_FILE_EXCEPTION); } } diff --git a/trustStoreMerger/src/main/java/org/onap/oom/truststoremerger/certification/file/TruststoreFile.java b/trustStoreMerger/src/main/java/org/onap/oom/truststoremerger/certification/file/exception/MissingTruststoreException.java index 88b1b5a8..c502d6b6 100644 --- a/trustStoreMerger/src/main/java/org/onap/oom/truststoremerger/certification/file/TruststoreFile.java +++ b/trustStoreMerger/src/main/java/org/onap/oom/truststoremerger/certification/file/exception/MissingTruststoreException.java @@ -17,22 +17,14 @@ * ============LICENSE_END========================================================= */ -package org.onap.oom.truststoremerger.certification.file; +package org.onap.oom.truststoremerger.certification.file.exception; -import java.io.File; -import java.security.cert.Certificate; -import java.util.List; +import org.onap.oom.truststoremerger.api.ExitStatus; +import org.onap.oom.truststoremerger.api.ExitableException; -public abstract class TruststoreFile { - private File truststoreFile; +public class MissingTruststoreException extends ExitableException { - TruststoreFile(File truststoreFile) { - this.truststoreFile = truststoreFile; + public MissingTruststoreException(String message) { + super(message, ExitStatus.MISSING_TRUSTSTORE_EXCEPTION); } - - public abstract List<Certificate> getCertificates(); - - public File getTruststoreFile() { - return truststoreFile; - }; } diff --git a/trustStoreMerger/src/main/java/org/onap/oom/truststoremerger/certification/file/provider/PasswordReaderException.java b/trustStoreMerger/src/main/java/org/onap/oom/truststoremerger/certification/file/exception/PasswordReaderException.java index 2928f0c5..d601d229 100644 --- a/trustStoreMerger/src/main/java/org/onap/oom/truststoremerger/certification/file/provider/PasswordReaderException.java +++ b/trustStoreMerger/src/main/java/org/onap/oom/truststoremerger/certification/file/exception/PasswordReaderException.java @@ -17,13 +17,13 @@ * ============LICENSE_END========================================================= */ -package org.onap.oom.truststoremerger.certification.file.provider; +package org.onap.oom.truststoremerger.certification.file.exception; import org.onap.oom.truststoremerger.api.ExitStatus; import org.onap.oom.truststoremerger.api.ExitableException; -class PasswordReaderException extends ExitableException { - PasswordReaderException(String message) { +public class PasswordReaderException extends ExitableException { + public PasswordReaderException(String message) { super(message, ExitStatus.PASSWORD_READER_EXCEPTION); } } diff --git a/trustStoreMerger/src/main/java/org/onap/oom/truststoremerger/certification/file/exception/TruststoreDataOperationException.java b/trustStoreMerger/src/main/java/org/onap/oom/truststoremerger/certification/file/exception/TruststoreDataOperationException.java new file mode 100644 index 00000000..cf848f79 --- /dev/null +++ b/trustStoreMerger/src/main/java/org/onap/oom/truststoremerger/certification/file/exception/TruststoreDataOperationException.java @@ -0,0 +1,30 @@ +/*============LICENSE_START======================================================= + * oom-truststore-merger + * ================================================================================ + * Copyright (C) 2020 Nokia. All rights reserved. + * ================================================================================ + * Licensed 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.oom.truststoremerger.certification.file.exception; + +import org.onap.oom.truststoremerger.api.ExitStatus; +import org.onap.oom.truststoremerger.api.ExitableException; + +public class TruststoreDataOperationException extends ExitableException { + + public TruststoreDataOperationException(Exception e) { + super(e, ExitStatus.TRUSTSTORE_DATA_OPERATION_EXCEPTION); + } +} diff --git a/trustStoreMerger/src/main/java/org/onap/oom/truststoremerger/certification/file/provider/TruststoreFileFactoryException.java b/trustStoreMerger/src/main/java/org/onap/oom/truststoremerger/certification/file/exception/TruststoreFileFactoryException.java index 43342c83..18349fd4 100644 --- a/trustStoreMerger/src/main/java/org/onap/oom/truststoremerger/certification/file/provider/TruststoreFileFactoryException.java +++ b/trustStoreMerger/src/main/java/org/onap/oom/truststoremerger/certification/file/exception/TruststoreFileFactoryException.java @@ -17,13 +17,13 @@ * ============LICENSE_END========================================================= */ -package org.onap.oom.truststoremerger.certification.file.provider; +package org.onap.oom.truststoremerger.certification.file.exception; import org.onap.oom.truststoremerger.api.ExitStatus; import org.onap.oom.truststoremerger.api.ExitableException; -class TruststoreFileFactoryException extends ExitableException { - TruststoreFileFactoryException(String message) { +public class TruststoreFileFactoryException extends ExitableException { + public TruststoreFileFactoryException(String message) { super(message, ExitStatus.TRUSTSTORE_FILE_FACTORY_EXCEPTION); } diff --git a/trustStoreMerger/src/main/java/org/onap/oom/truststoremerger/certification/file/exception/WriteTruststoreFileException.java b/trustStoreMerger/src/main/java/org/onap/oom/truststoremerger/certification/file/exception/WriteTruststoreFileException.java new file mode 100644 index 00000000..a5e02b3c --- /dev/null +++ b/trustStoreMerger/src/main/java/org/onap/oom/truststoremerger/certification/file/exception/WriteTruststoreFileException.java @@ -0,0 +1,31 @@ +/*============LICENSE_START======================================================= + * oom-truststore-merger + * ================================================================================ + * Copyright (C) 2020 Nokia. All rights reserved. + * ================================================================================ + * Licensed 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. + * ============LICENSE_END========================================================= + */ + + +package org.onap.oom.truststoremerger.certification.file.exception; + +import org.onap.oom.truststoremerger.api.ExitStatus; +import org.onap.oom.truststoremerger.api.ExitableException; + +public class WriteTruststoreFileException extends ExitableException { + + public WriteTruststoreFileException(Exception e) { + super(e, ExitStatus.WRITE_TRUSTSTORE_FILE_EXCEPTION); + } +} diff --git a/trustStoreMerger/src/main/java/org/onap/oom/truststoremerger/certification/file/model/JavaTruststore.java b/trustStoreMerger/src/main/java/org/onap/oom/truststoremerger/certification/file/model/JavaTruststore.java new file mode 100644 index 00000000..d46fba1e --- /dev/null +++ b/trustStoreMerger/src/main/java/org/onap/oom/truststoremerger/certification/file/model/JavaTruststore.java @@ -0,0 +1,58 @@ +/*============LICENSE_START======================================================= + * oom-truststore-merger + * ================================================================================ + * Copyright (C) 2020 Nokia. All rights reserved. + * ================================================================================ + * Licensed 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.oom.truststoremerger.certification.file.model; + +import java.io.File; +import java.util.List; +import org.onap.oom.truststoremerger.api.ExitableException; +import org.onap.oom.truststoremerger.certification.file.provider.entry.CertificateWithAlias; +import org.onap.oom.truststoremerger.certification.file.exception.WriteTruststoreFileException; +import org.onap.oom.truststoremerger.certification.file.provider.JavaCertificateStoreController; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class JavaTruststore extends Truststore { + + private static final Logger LOGGER = LoggerFactory.getLogger(JavaTruststore.class); + private final JavaCertificateStoreController storeController; + + public JavaTruststore(File truststoreFile, JavaCertificateStoreController storeController) { + super(truststoreFile); + this.storeController = storeController; + } + + @Override + public List<CertificateWithAlias> getCertificates() throws ExitableException { + LOGGER.debug("Attempt ro read certificates from file: {} ", this.getFile().getPath()); + return storeController.getNotEmptyCertificateList(); + } + + @Override + public void addCertificate(List<CertificateWithAlias> certificates) throws ExitableException { + LOGGER.debug("Attempt to add certificates for saving to file"); + storeController.addCertificates(certificates); + } + + @Override + public void saveFile() throws WriteTruststoreFileException { + LOGGER.debug("Attempt to save file: {}", this.getFile().getPath()); + storeController.saveFile(); + } +} diff --git a/trustStoreMerger/src/main/java/org/onap/oom/truststoremerger/certification/file/model/PemTruststore.java b/trustStoreMerger/src/main/java/org/onap/oom/truststoremerger/certification/file/model/PemTruststore.java new file mode 100644 index 00000000..36195267 --- /dev/null +++ b/trustStoreMerger/src/main/java/org/onap/oom/truststoremerger/certification/file/model/PemTruststore.java @@ -0,0 +1,58 @@ +/*============LICENSE_START======================================================= + * oom-truststore-merger + * ================================================================================ + * Copyright (C) 2020 Nokia. All rights reserved. + * ================================================================================ + * Licensed 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.oom.truststoremerger.certification.file.model; + +import java.io.File; +import java.util.List; +import org.onap.oom.truststoremerger.api.ExitableException; +import org.onap.oom.truststoremerger.certification.file.provider.entry.CertificateWithAlias; +import org.onap.oom.truststoremerger.certification.file.provider.PemCertificateController; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class PemTruststore extends Truststore { + + private static final Logger LOGGER = LoggerFactory.getLogger(PemTruststore.class); + private final PemCertificateController pemCertificateController; + + public PemTruststore(File truststoreFile, PemCertificateController pemCertificateController) { + super(truststoreFile); + this.pemCertificateController = pemCertificateController; + } + + @Override + public List<CertificateWithAlias> getCertificates() throws ExitableException { + LOGGER.debug("Attempt ro read certificates from file: {}", this.getFile().getPath()); + return pemCertificateController.getNotEmptyCertificateList(); + } + + @Override + public void addCertificate(List<CertificateWithAlias> certificates) throws ExitableException { + LOGGER.debug("Attempt to add certificates for saving to file"); + pemCertificateController.addCertificates(certificates); + } + + @Override + public void saveFile() throws ExitableException { + LOGGER.debug("Attempt to save file: {}", this.getFile().getPath()); + pemCertificateController.saveFile(); + } + +} diff --git a/trustStoreMerger/src/main/java/org/onap/oom/truststoremerger/certification/file/model/Truststore.java b/trustStoreMerger/src/main/java/org/onap/oom/truststoremerger/certification/file/model/Truststore.java new file mode 100644 index 00000000..153805a7 --- /dev/null +++ b/trustStoreMerger/src/main/java/org/onap/oom/truststoremerger/certification/file/model/Truststore.java @@ -0,0 +1,62 @@ +/*============LICENSE_START======================================================= + * oom-truststore-merger + * ================================================================================ + * Copyright (C) 2020 Nokia. All rights reserved. + * ================================================================================ + * Licensed 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.oom.truststoremerger.certification.file.model; + +import java.io.File; +import java.io.FileOutputStream; +import java.nio.file.Files; +import java.util.List; +import org.onap.oom.truststoremerger.api.ExitableException; +import org.onap.oom.truststoremerger.certification.file.provider.entry.CertificateWithAlias; +import org.onap.oom.truststoremerger.certification.file.exception.CreateBackupException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public abstract class Truststore { + + private static final Logger LOGGER = LoggerFactory.getLogger(Truststore.class); + private static final String BACKUP_EXTENSION = ".bak"; + private final File file; + + Truststore(File file) { + this.file = file; + } + + public abstract List<CertificateWithAlias> getCertificates() throws ExitableException; + + public abstract void addCertificate(List<CertificateWithAlias> certificates) throws ExitableException; + + public abstract void saveFile() throws ExitableException; + + public File getFile() { + return file; + } + + public void createBackup() throws CreateBackupException { + LOGGER.debug("Create backup of file: {}", file.getPath()); + String backupFilePath = file.getAbsolutePath() + BACKUP_EXTENSION; + try (FileOutputStream fileOutputStream = new FileOutputStream(backupFilePath)) { + Files.copy(file.toPath(), fileOutputStream); + } catch (Exception e) { + LOGGER.error("Cannot create backup of file: {} ", getFile().getPath()); + throw new CreateBackupException(e); + } + } +} diff --git a/trustStoreMerger/src/main/java/org/onap/oom/truststoremerger/certification/file/provider/CertificateController.java b/trustStoreMerger/src/main/java/org/onap/oom/truststoremerger/certification/file/provider/CertificateController.java new file mode 100644 index 00000000..f2ed2c45 --- /dev/null +++ b/trustStoreMerger/src/main/java/org/onap/oom/truststoremerger/certification/file/provider/CertificateController.java @@ -0,0 +1,33 @@ +/*============LICENSE_START======================================================= + * oom-truststore-merger + * ================================================================================ + * Copyright (C) 2020 Nokia. All rights reserved. + * ================================================================================ + * Licensed 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.oom.truststoremerger.certification.file.provider; + +import java.util.List; +import org.onap.oom.truststoremerger.api.ExitableException; +import org.onap.oom.truststoremerger.certification.file.provider.entry.CertificateWithAlias; + +public interface CertificateController { + + List<CertificateWithAlias> getNotEmptyCertificateList() throws ExitableException; + + void addCertificates(List<CertificateWithAlias> certificates) throws ExitableException; + + void saveFile() throws ExitableException; +} diff --git a/trustStoreMerger/src/main/java/org/onap/oom/truststoremerger/certification/file/provider/CertificateStoreControllerFactory.java b/trustStoreMerger/src/main/java/org/onap/oom/truststoremerger/certification/file/provider/CertificateStoreControllerFactory.java new file mode 100644 index 00000000..66e2aed2 --- /dev/null +++ b/trustStoreMerger/src/main/java/org/onap/oom/truststoremerger/certification/file/provider/CertificateStoreControllerFactory.java @@ -0,0 +1,61 @@ +/*============LICENSE_START======================================================= + * oom-truststore-merger + * ================================================================================ + * Copyright (C) 2020 Nokia. All rights reserved. + * ================================================================================ + * Licensed 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.oom.truststoremerger.certification.file.provider; + +import static org.onap.oom.truststoremerger.api.CertificateConstants.JKS_INSTANCE; +import static org.onap.oom.truststoremerger.api.CertificateConstants.PKCS12_INSTANCE; + +import java.io.File; +import java.security.KeyStore; +import java.security.KeyStoreException; +import org.onap.oom.truststoremerger.certification.file.exception.KeystoreInstanceException; +import org.onap.oom.truststoremerger.certification.file.exception.LoadTruststoreException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class CertificateStoreControllerFactory { + + private static final Logger LOGGER = LoggerFactory.getLogger(CertificateStoreControllerFactory.class); + + public JavaCertificateStoreController createLoadedJksCertificateStoreController(File certFile, String certPassword) + throws LoadTruststoreException, KeystoreInstanceException { + return createLoadedCertificateStoreController(certFile, certPassword, JKS_INSTANCE); + } + + public JavaCertificateStoreController createLoadedPkcs12CertificateStoreController(File certFile, String certPassword) + throws KeystoreInstanceException, LoadTruststoreException { + return createLoadedCertificateStoreController(certFile, certPassword, PKCS12_INSTANCE); + } + + private JavaCertificateStoreController createLoadedCertificateStoreController(File certFile, String certPassword, + String instanceType) + throws LoadTruststoreException, KeystoreInstanceException { + try { + JavaCertificateStoreController javaCertificateStoreController = new JavaCertificateStoreController( + KeyStore.getInstance(instanceType), certFile, certPassword); + javaCertificateStoreController.loadFile(); + return javaCertificateStoreController; + } catch (KeyStoreException e) { + LOGGER.error("Cannot initialize Java Keystore instance"); + throw new KeystoreInstanceException(e); + } + } +} + diff --git a/trustStoreMerger/src/main/java/org/onap/oom/truststoremerger/certification/file/provider/FileManager.java b/trustStoreMerger/src/main/java/org/onap/oom/truststoremerger/certification/file/provider/FileManager.java index 901c13ab..12029ade 100644 --- a/trustStoreMerger/src/main/java/org/onap/oom/truststoremerger/certification/file/provider/FileManager.java +++ b/trustStoreMerger/src/main/java/org/onap/oom/truststoremerger/certification/file/provider/FileManager.java @@ -22,17 +22,18 @@ package org.onap.oom.truststoremerger.certification.file.provider; import java.io.File; public class FileManager { - private static final int NOT_FOUND_INDEX=-1; - String getExtension(File file) { + private static final int INDEX_NOT_FOUND = -1; + + public String getExtension(File file) { int extStartIndex = file.getName().lastIndexOf("."); - if (extStartIndex == NOT_FOUND_INDEX) { + if (extStartIndex == INDEX_NOT_FOUND) { return ""; } - return file.getName().substring(extStartIndex); + return file.getName().substring(extStartIndex).toLowerCase(); } - boolean checkIfFileExists(File file){ + public boolean checkIfFileExists(File file) { return file.exists(); } diff --git a/trustStoreMerger/src/main/java/org/onap/oom/truststoremerger/certification/file/provider/JavaCertificateStoreController.java b/trustStoreMerger/src/main/java/org/onap/oom/truststoremerger/certification/file/provider/JavaCertificateStoreController.java new file mode 100644 index 00000000..1c20fd38 --- /dev/null +++ b/trustStoreMerger/src/main/java/org/onap/oom/truststoremerger/certification/file/provider/JavaCertificateStoreController.java @@ -0,0 +1,156 @@ +/*============LICENSE_START======================================================= + * oom-truststore-merger + * ================================================================================ + * Copyright (C) 2020 Nokia. All rights reserved. + * ================================================================================ + * Licensed 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.oom.truststoremerger.certification.file.provider; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import org.onap.oom.truststoremerger.api.ExitableException; +import org.onap.oom.truststoremerger.certification.file.provider.entry.CertificateWithAlias; +import org.onap.oom.truststoremerger.certification.file.provider.entry.CertificateWithAliasFactory; +import org.onap.oom.truststoremerger.certification.file.exception.AliasConflictException; +import org.onap.oom.truststoremerger.certification.file.exception.TruststoreDataOperationException; +import org.onap.oom.truststoremerger.certification.file.exception.LoadTruststoreException; +import org.onap.oom.truststoremerger.certification.file.exception.MissingTruststoreException; +import org.onap.oom.truststoremerger.certification.file.exception.WriteTruststoreFileException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class JavaCertificateStoreController implements CertificateController { + + private static final Logger LOGGER = LoggerFactory.getLogger(JavaCertificateStoreController.class); + + private final CertificateWithAliasFactory factory = new CertificateWithAliasFactory(); + private final KeyStore keyStore; + private final File storeFile; + private final String password; + + + public JavaCertificateStoreController(KeyStore keyStore, File storeFile, String password) { + this.keyStore = keyStore; + this.storeFile = storeFile; + this.password = password; + } + + public List<CertificateWithAlias> getNotEmptyCertificateList() throws ExitableException { + List<String> aliases = getTruststoreAliasesList(); + if (aliases.isEmpty()) { + throw new MissingTruststoreException("Missing certificate aliases in file: " + storeFile.getPath()); + } + return getWrappedCertificates(aliases); + } + + public void addCertificates(List<CertificateWithAlias> certificatesWithAliases) + throws ExitableException { + if (getTruststoreAliasesList().isEmpty()){ + throw new MissingTruststoreException("Missing certificate aliases in file: " + storeFile.getPath()); + } + for (CertificateWithAlias certificate : certificatesWithAliases) { + addCertificate(certificate); + } + } + + public void saveFile() throws WriteTruststoreFileException { + try (FileOutputStream outputStream = new FileOutputStream(this.storeFile)) { + keyStore.store(outputStream, this.password.toCharArray()); + } catch (Exception e) { + LOGGER.error("Cannot write truststore file"); + throw new WriteTruststoreFileException(e); + } + } + + public void loadFile() throws LoadTruststoreException { + try { + keyStore.load(new FileInputStream(this.storeFile), this.password.toCharArray()); + } catch (Exception e) { + LOGGER.error("Cannot load file: {}", this.storeFile.getPath()); + throw new LoadTruststoreException(e); + } + } + + private void addCertificate(CertificateWithAlias certificate) + throws TruststoreDataOperationException, AliasConflictException { + if (hasAliasConflict(certificate)) { + LOGGER.error("Alias conflict detected"); + throw new AliasConflictException("Alias conflict detected. Alias conflicted: " + certificate.getAlias()); + } + try { + keyStore.setCertificateEntry(certificate.getAlias(), certificate.getCertificate()); + } catch (KeyStoreException e) { + LOGGER.error("Cannot merge certificate with alias: {}", certificate.getAlias()); + throw new TruststoreDataOperationException(e); + } + } + + private boolean hasAliasConflict(CertificateWithAlias certificate) throws TruststoreDataOperationException { + try { + return keyStore.containsAlias(certificate.getAlias()); + } catch (KeyStoreException e) { + LOGGER.error("Cannot check alias conflict"); + throw new TruststoreDataOperationException(e); + } + } + + private List<CertificateWithAlias> getWrappedCertificates(List<String> aliases) + throws TruststoreDataOperationException { + + List<CertificateWithAlias> certificateWrapped = new ArrayList<>(); + + for (String alias : aliases) { + certificateWrapped.add(createWrappedCertificate(alias)); + } + return certificateWrapped; + } + + private CertificateWithAlias createWrappedCertificate(String alias) throws TruststoreDataOperationException { + try { + return factory.createCertificateWithAlias(keyStore.getCertificate(alias), alias); + } catch (KeyStoreException e) { + LOGGER.warn("Cannot get certificate with alias: {} ", alias); + throw new TruststoreDataOperationException(e); + } + } + + private List<String> getTruststoreAliasesList() throws TruststoreDataOperationException { + try { + List<String> aliases = Collections.list(keyStore.aliases()); + return getFilteredAlias(aliases); + } catch (KeyStoreException e) { + LOGGER.warn("Cannot read truststore aliases"); + throw new TruststoreDataOperationException(e); + } + } + + private List<String> getFilteredAlias(List<String> aliases) throws KeyStoreException { + List<String> filteredAlias = new ArrayList<>(); + for (String alias : aliases) { + if (keyStore.isCertificateEntry(alias)) { + filteredAlias.add(alias); + } + } + return filteredAlias; + } + +} diff --git a/trustStoreMerger/src/main/java/org/onap/oom/truststoremerger/certification/file/provider/PasswordReader.java b/trustStoreMerger/src/main/java/org/onap/oom/truststoremerger/certification/file/provider/PasswordReader.java index db42f3bd..d7da53b0 100644 --- a/trustStoreMerger/src/main/java/org/onap/oom/truststoremerger/certification/file/provider/PasswordReader.java +++ b/trustStoreMerger/src/main/java/org/onap/oom/truststoremerger/certification/file/provider/PasswordReader.java @@ -22,11 +22,12 @@ package org.onap.oom.truststoremerger.certification.file.provider; import java.io.File; import java.io.IOException; import java.nio.file.Files; +import org.onap.oom.truststoremerger.certification.file.exception.PasswordReaderException; public class PasswordReader { private static final String COULD_NOT_READ_PASSWORD_FROM_FILE_MSG_TEMPLATE = "Could not read password from file: %s"; - String readPassword(File file) throws PasswordReaderException { + public String readPassword(File file) throws PasswordReaderException { try { return Files.readString(file.toPath()); } catch (IOException e) { diff --git a/trustStoreMerger/src/main/java/org/onap/oom/truststoremerger/certification/file/provider/PemCertificateController.java b/trustStoreMerger/src/main/java/org/onap/oom/truststoremerger/certification/file/provider/PemCertificateController.java new file mode 100644 index 00000000..9ff42b87 --- /dev/null +++ b/trustStoreMerger/src/main/java/org/onap/oom/truststoremerger/certification/file/provider/PemCertificateController.java @@ -0,0 +1,155 @@ +/*============LICENSE_START======================================================= + * oom-truststore-merger + * ================================================================================ + * Copyright (C) 2020 Nokia. All rights reserved. + * ================================================================================ + * Licensed 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.oom.truststoremerger.certification.file.provider; + +import static org.onap.oom.truststoremerger.api.CertificateConstants.BOUNCY_CASTLE_PROVIDER; +import static org.onap.oom.truststoremerger.api.CertificateConstants.X_509_CERTIFICATE; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.StringWriter; +import java.security.Security; +import java.security.cert.Certificate; +import java.security.cert.CertificateFactory; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; +import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.bouncycastle.openssl.jcajce.JcaMiscPEMGenerator; +import org.bouncycastle.util.io.pem.PemObjectGenerator; +import org.bouncycastle.util.io.pem.PemWriter; +import org.onap.oom.truststoremerger.certification.file.provider.entry.CertificateWithAlias; +import org.onap.oom.truststoremerger.certification.file.provider.entry.CertificateWithAliasFactory; +import org.onap.oom.truststoremerger.certification.file.exception.MissingTruststoreException; +import org.onap.oom.truststoremerger.certification.file.exception.TruststoreDataOperationException; +import org.onap.oom.truststoremerger.certification.file.exception.WriteTruststoreFileException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class PemCertificateController implements CertificateController { + + private static final Logger LOGGER = LoggerFactory.getLogger(PemCertificateController.class); + + private static final boolean APPEND_TO_FILE = true; + + private final CertificateWithAliasFactory factory = new CertificateWithAliasFactory(); + private final List<CertificateWithAlias> certificatesToBeSaved = new ArrayList<>(); + private final File file; + + public PemCertificateController(File file) { + this.file = file; + } + + public List<CertificateWithAlias> getNotEmptyCertificateList() + throws TruststoreDataOperationException, MissingTruststoreException { + if (isFileWithoutPemCertificate()) { + throw new MissingTruststoreException("File does not contain any certificate"); + } + List<Certificate> extractedCertificate = extractCertificatesFromFile(); + return wrapCertificates(extractedCertificate); + } + + public void addCertificates(List<CertificateWithAlias> certificates) + throws TruststoreDataOperationException, MissingTruststoreException { + if (isFileWithoutPemCertificate()) { + LOGGER.error("File does not contain any certificate. File path: {} ", this.file.getPath()); + throw new MissingTruststoreException("File does not contain any certificate"); + } + certificatesToBeSaved.addAll(certificates); + } + + public void saveFile() throws WriteTruststoreFileException, TruststoreDataOperationException { + List<Certificate> certificates = certificatesToBeSaved.stream() + .map(CertificateWithAlias::getCertificate) + .collect(Collectors.toList()); + String certificatesAsString = transformToStringInPemFormat(certificates); + appendToFile(certificatesAsString); + } + + boolean isFileWithoutPemCertificate() throws TruststoreDataOperationException { + List<Certificate> certificateList = extractCertificatesFromFile(); + return certificateList.isEmpty(); + } + + String transformToStringInPemFormat(List<Certificate> certificates) throws TruststoreDataOperationException { + StringWriter sw = new StringWriter(); + List<PemObjectGenerator> generators = transformToPemGenerators(certificates); + try (PemWriter pemWriter = new PemWriter(sw)) { + for (PemObjectGenerator generator : generators) { + pemWriter.writeObject(generator); + } + } catch (IOException e) { + LOGGER.error("Cannot convert certificates to PEM format"); + throw new TruststoreDataOperationException(e); + } + return sw.toString(); + } + + + private List<Certificate> extractCertificatesFromFile() throws TruststoreDataOperationException { + try (FileInputStream inputStream = new FileInputStream(this.file)) { + Security.addProvider(new BouncyCastleProvider()); + CertificateFactory factory = CertificateFactory.getInstance(X_509_CERTIFICATE, BOUNCY_CASTLE_PROVIDER); + return new ArrayList<>(factory.generateCertificates(inputStream)); + } catch (Exception e) { + LOGGER.error("Cannot read certificates from file: {}", this.file.getPath()); + throw new TruststoreDataOperationException(e); + } + } + + + private List<PemObjectGenerator> transformToPemGenerators(List<Certificate> certificates) + throws TruststoreDataOperationException { + List<PemObjectGenerator> generators = new ArrayList<>(); + for (Certificate certificate : certificates) { + PemObjectGenerator generator = createPemGenerator(certificate); + generators.add(generator); + } + return generators; + } + + private JcaMiscPEMGenerator createPemGenerator(Certificate certificate) + throws TruststoreDataOperationException { + try { + return new JcaMiscPEMGenerator(certificate); + } catch (IOException e) { + LOGGER.error("Cannot convert Certificate Object to PemGenerator Object"); + throw new TruststoreDataOperationException(e); + } + } + + private List<CertificateWithAlias> wrapCertificates(List<Certificate> rawCertificates) { + return rawCertificates.stream() + .map(factory::createPemCertificate) + .collect(Collectors.toList()); + } + + private void appendToFile(String certificatesAsString) throws WriteTruststoreFileException { + try { + FileOutputStream fileOutputStream = new FileOutputStream(this.file, APPEND_TO_FILE); + fileOutputStream.write(certificatesAsString.getBytes()); + } catch (Exception e) { + LOGGER.error("Cannot write certificates to file"); + throw new WriteTruststoreFileException(e); + } + } +} diff --git a/trustStoreMerger/src/main/java/org/onap/oom/truststoremerger/certification/file/provider/TruststoreFileFactory.java b/trustStoreMerger/src/main/java/org/onap/oom/truststoremerger/certification/file/provider/TruststoreFileFactory.java deleted file mode 100644 index e63e7c33..00000000 --- a/trustStoreMerger/src/main/java/org/onap/oom/truststoremerger/certification/file/provider/TruststoreFileFactory.java +++ /dev/null @@ -1,84 +0,0 @@ -/*============LICENSE_START======================================================= - * oom-truststore-merger - * ================================================================================ - * Copyright (C) 2020 Nokia. All rights reserved. - * ================================================================================ - * Licensed 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. - * ============LICENSE_END========================================================= - */ - -package org.onap.oom.truststoremerger.certification.file.provider; - -import org.onap.oom.truststoremerger.certification.file.JksTruststore; -import org.onap.oom.truststoremerger.certification.file.P12Truststore; -import org.onap.oom.truststoremerger.certification.file.PemTruststore; -import org.onap.oom.truststoremerger.certification.file.TruststoreFile; - -import java.io.File; - -public class TruststoreFileFactory { - - private static final String JKS_EXTENSION = ".jks"; - private static final String P12_EXTENSION = ".p12"; - private static final String PEM_EXTENSION = ".pem"; - private static final String FILE_DOES_NOT_EXIST_MSG_TEMPLATE = "File: %s does not exist"; - private static final String UNKNOWN_TRUSTSTORE_TYPE_MSG_TEMPLATE = "Unknown truststore extension type: %s"; - - private final FileManager fileManager; - private final PasswordReader passwordReader; - - public TruststoreFileFactory(FileManager fileManager, PasswordReader passwordReader) { - this.fileManager = fileManager; - this.passwordReader = passwordReader; - } - - TruststoreFile create(String truststoreFilePath, String truststorePasswordPath) - throws TruststoreFileFactoryException, PasswordReaderException { - File truststoreFile = new File(truststoreFilePath); - if (!fileManager.checkIfFileExists(truststoreFile)) { - throw new TruststoreFileFactoryException(String.format(FILE_DOES_NOT_EXIST_MSG_TEMPLATE, truststoreFile)); - } - return createTypedTruststore(truststoreFile, truststorePasswordPath); - } - - private TruststoreFile createTypedTruststore(File truststoreFile, String truststorePasswordPath) - throws PasswordReaderException, TruststoreFileFactoryException { - String extension = fileManager.getExtension(truststoreFile); - switch (extension) { - case JKS_EXTENSION: - return createJksTruststore(truststoreFile, truststorePasswordPath); - case P12_EXTENSION: - return createP12Truststore(truststoreFile, truststorePasswordPath); - case PEM_EXTENSION: - return createPemTruststore(truststoreFile); - default: - throw new TruststoreFileFactoryException(String.format(UNKNOWN_TRUSTSTORE_TYPE_MSG_TEMPLATE, extension)); - } - } - - private JksTruststore createJksTruststore(File truststoreFile, String truststorePasswordPath) - throws PasswordReaderException { - String password = passwordReader.readPassword(new File(truststorePasswordPath)); - return new JksTruststore(truststoreFile, password); - } - - private P12Truststore createP12Truststore(File truststoreFile, String truststorePasswordPath) - throws PasswordReaderException { - String password = passwordReader.readPassword(new File(truststorePasswordPath)); - return new P12Truststore(truststoreFile, password); - } - - private PemTruststore createPemTruststore(File truststoreFile) { - return new PemTruststore(truststoreFile); - } -} diff --git a/trustStoreMerger/src/main/java/org/onap/oom/truststoremerger/certification/file/P12Truststore.java b/trustStoreMerger/src/main/java/org/onap/oom/truststoremerger/certification/file/provider/entry/CertificateWithAlias.java index 8527cce5..decc3977 100644 --- a/trustStoreMerger/src/main/java/org/onap/oom/truststoremerger/certification/file/P12Truststore.java +++ b/trustStoreMerger/src/main/java/org/onap/oom/truststoremerger/certification/file/provider/entry/CertificateWithAlias.java @@ -17,22 +17,25 @@ * ============LICENSE_END========================================================= */ -package org.onap.oom.truststoremerger.certification.file; +package org.onap.oom.truststoremerger.certification.file.provider.entry; -import java.io.File; import java.security.cert.Certificate; -import java.util.Collections; -import java.util.List; -public class P12Truststore extends TruststoreFileWithPassword { +public class CertificateWithAlias { - public P12Truststore(File truststoreFile, String password) { - super(truststoreFile, password); + private final Certificate certificate; + private final String alias; + + public CertificateWithAlias(Certificate certificate, String alias) { + this.certificate = certificate; + this.alias = alias; } - @Override - public List<Certificate> getCertificates() { - return Collections.emptyList(); + public String getAlias() { + return this.alias; } + public Certificate getCertificate() { + return this.certificate; + } } diff --git a/trustStoreMerger/src/main/java/org/onap/oom/truststoremerger/certification/file/JksTruststore.java b/trustStoreMerger/src/main/java/org/onap/oom/truststoremerger/certification/file/provider/entry/CertificateWithAliasFactory.java index b977daee..0889650e 100644 --- a/trustStoreMerger/src/main/java/org/onap/oom/truststoremerger/certification/file/JksTruststore.java +++ b/trustStoreMerger/src/main/java/org/onap/oom/truststoremerger/certification/file/provider/entry/CertificateWithAliasFactory.java @@ -17,21 +17,17 @@ * ============LICENSE_END========================================================= */ -package org.onap.oom.truststoremerger.certification.file; +package org.onap.oom.truststoremerger.certification.file.provider.entry; -import java.io.File; import java.security.cert.Certificate; -import java.util.Collections; -import java.util.List; -public class JksTruststore extends TruststoreFileWithPassword { +public class CertificateWithAliasFactory { - public JksTruststore(File truststoreFile, String password) { - super(truststoreFile, password); + public CertificateWithAlias createCertificateWithAlias(Certificate certificate, String alias) { + return new CertificateWithAlias(certificate, alias); } - @Override - public List<Certificate> getCertificates() { - return Collections.emptyList(); + public CertificateWithAlias createPemCertificate(Certificate certificate) { + return new CertificateWithAlias(certificate, PemAliasGenerator.getInstance().getAlias()); } } diff --git a/trustStoreMerger/src/main/java/org/onap/oom/truststoremerger/certification/file/provider/entry/PemAliasGenerator.java b/trustStoreMerger/src/main/java/org/onap/oom/truststoremerger/certification/file/provider/entry/PemAliasGenerator.java new file mode 100644 index 00000000..56faa1f6 --- /dev/null +++ b/trustStoreMerger/src/main/java/org/onap/oom/truststoremerger/certification/file/provider/entry/PemAliasGenerator.java @@ -0,0 +1,42 @@ +/*============LICENSE_START======================================================= + * oom-truststore-merger + * ================================================================================ + * Copyright (C) 2020 Nokia. All rights reserved. + * ================================================================================ + * Licensed 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.oom.truststoremerger.certification.file.provider.entry; + + +import java.util.concurrent.atomic.AtomicInteger; + +public class PemAliasGenerator { + + private static final String PREFIX_ALIAS_NAME = "pem-trusted-certificate-"; + private static final PemAliasGenerator INSTANCE = new PemAliasGenerator(); + private static AtomicInteger counter = new AtomicInteger(0); + + private PemAliasGenerator() { + } + + public static PemAliasGenerator getInstance() { + return INSTANCE; + } + + public String getAlias() { + + return PREFIX_ALIAS_NAME + counter.getAndIncrement(); + } +} diff --git a/trustStoreMerger/src/main/java/org/onap/oom/truststoremerger/certification/path/EnvProvider.java b/trustStoreMerger/src/main/java/org/onap/oom/truststoremerger/certification/path/EnvProvider.java index 4bb763da..a1998b86 100644 --- a/trustStoreMerger/src/main/java/org/onap/oom/truststoremerger/certification/path/EnvProvider.java +++ b/trustStoreMerger/src/main/java/org/onap/oom/truststoremerger/certification/path/EnvProvider.java @@ -21,9 +21,16 @@ package org.onap.oom.truststoremerger.certification.path; import java.util.Optional; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + public class EnvProvider { + private static final Logger LOGGER = LoggerFactory.getLogger(EnvProvider.class); + Optional<String> getEnv(String name) { + String value = System.getenv(name); + LOGGER.info("Read variable: {} , value: {}", name, value); return Optional.ofNullable(System.getenv(name)); } } diff --git a/trustStoreMerger/src/main/java/org/onap/oom/truststoremerger/certification/path/TruststoresPathsProvider.java b/trustStoreMerger/src/main/java/org/onap/oom/truststoremerger/certification/path/TruststoresPathsProvider.java index f8e85d49..9d86a8b9 100644 --- a/trustStoreMerger/src/main/java/org/onap/oom/truststoremerger/certification/path/TruststoresPathsProvider.java +++ b/trustStoreMerger/src/main/java/org/onap/oom/truststoremerger/certification/path/TruststoresPathsProvider.java @@ -19,8 +19,8 @@ package org.onap.oom.truststoremerger.certification.path; -import static org.onap.oom.truststoremerger.api.ConfigurationEnvs.TRUSTSTORES_ENV; -import static org.onap.oom.truststoremerger.api.ConfigurationEnvs.TRUSTSTORES_PASSWORDS_ENV; +import static org.onap.oom.truststoremerger.api.ConfigurationEnvs.TRUSTSTORES_PATHS_ENV; +import static org.onap.oom.truststoremerger.api.ConfigurationEnvs.TRUSTSTORES_PASSWORDS_PATHS_ENV; import java.util.Arrays; import java.util.List; @@ -31,8 +31,8 @@ public class TruststoresPathsProvider { private static final String DELIMITER = ":"; private static final int NEGATIVE_SPLIT_LIMIT = -1; - private EnvProvider envProvider; - private PathValidator pathValidator; + private final EnvProvider envProvider; + private final PathValidator pathValidator; public TruststoresPathsProvider(EnvProvider envProvider, PathValidator pathValidator) { this.envProvider = envProvider; @@ -40,20 +40,20 @@ public class TruststoresPathsProvider { } public List<String> getTruststores() throws TruststoresPathsProviderException { - return envProvider.getEnv(TRUSTSTORES_ENV) + return envProvider.getEnv(TRUSTSTORES_PATHS_ENV) .filter(Predicate.not(String::isEmpty)) .map(this::splitToList) .filter(this::validateTruststores) .orElseThrow(() -> new TruststoresPathsProviderException( - TRUSTSTORES_ENV + " environment variable does not contain valid truststores paths")); + TRUSTSTORES_PATHS_ENV + " environment variable does not contain valid truststores paths")); } public List<String> getTruststoresPasswords() throws TruststoresPathsProviderException { - return envProvider.getEnv(TRUSTSTORES_PASSWORDS_ENV) + return envProvider.getEnv(TRUSTSTORES_PASSWORDS_PATHS_ENV) .map(this::splitToList) .filter(this::validateTruststoresPasswords) .orElseThrow(() -> new TruststoresPathsProviderException( - TRUSTSTORES_PASSWORDS_ENV + " environment variable does not contain valid passwords paths")); + TRUSTSTORES_PASSWORDS_PATHS_ENV + " environment variable does not contain valid passwords paths")); } private boolean validateTruststores(List<String> truststores) { diff --git a/trustStoreMerger/src/main/java/org/onap/oom/truststoremerger/configuration/MergerConfigurationFactory.java b/trustStoreMerger/src/main/java/org/onap/oom/truststoremerger/configuration/MergerConfigurationFactory.java index 7a2fdc10..acd9a840 100644 --- a/trustStoreMerger/src/main/java/org/onap/oom/truststoremerger/configuration/MergerConfigurationFactory.java +++ b/trustStoreMerger/src/main/java/org/onap/oom/truststoremerger/configuration/MergerConfigurationFactory.java @@ -22,8 +22,8 @@ package org.onap.oom.truststoremerger.configuration; import org.onap.oom.truststoremerger.certification.path.TruststoresPathsProvider; import org.onap.oom.truststoremerger.certification.path.TruststoresPathsProviderException; -import static org.onap.oom.truststoremerger.api.ConfigurationEnvs.TRUSTSTORES_ENV; -import static org.onap.oom.truststoremerger.api.ConfigurationEnvs.TRUSTSTORES_PASSWORDS_ENV; +import static org.onap.oom.truststoremerger.api.ConfigurationEnvs.TRUSTSTORES_PATHS_ENV; +import static org.onap.oom.truststoremerger.api.ConfigurationEnvs.TRUSTSTORES_PASSWORDS_PATHS_ENV; import java.util.List; @@ -42,8 +42,8 @@ public class MergerConfigurationFactory { if (truststores.size() != truststoresPasswords.size()) { throw new MergerConfigurationException( - "Size of " + TRUSTSTORES_ENV - + " does not match size of " + TRUSTSTORES_PASSWORDS_ENV + " environment variables"); + "Size of " + TRUSTSTORES_PATHS_ENV + + " does not match size of " + TRUSTSTORES_PASSWORDS_PATHS_ENV + " environment variables"); } return new MergerConfiguration(truststores, truststoresPasswords); |