1 /*============LICENSE_START=======================================================
2 * oom-truststore-merger
3 * ================================================================================
4 * Copyright (C) 2020-2021 Nokia. All rights reserved.
5 * ================================================================================
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 * ============LICENSE_END=========================================================
20 package org.onap.oom.certservice.postprocessor.merger.model;
22 import static org.onap.oom.certservice.postprocessor.api.CertificateConstants.BOUNCY_CASTLE_PROVIDER;
23 import static org.onap.oom.certservice.postprocessor.api.CertificateConstants.X_509_CERTIFICATE;
26 import java.io.FileInputStream;
27 import java.io.FileOutputStream;
28 import java.io.IOException;
29 import java.io.StringWriter;
30 import java.security.Security;
31 import java.security.cert.Certificate;
32 import java.security.cert.CertificateException;
33 import java.security.cert.CertificateFactory;
34 import java.util.ArrayList;
35 import java.util.List;
36 import java.util.stream.Collectors;
37 import org.bouncycastle.jce.provider.BouncyCastleProvider;
38 import org.bouncycastle.openssl.jcajce.JcaMiscPEMGenerator;
39 import org.bouncycastle.util.io.pem.PemObjectGenerator;
40 import org.bouncycastle.util.io.pem.PemWriter;
41 import org.onap.oom.certservice.postprocessor.common.FileTools;
42 import org.onap.oom.certservice.postprocessor.merger.exception.MissingTruststoreException;
43 import org.onap.oom.certservice.postprocessor.merger.exception.TruststoreDataOperationException;
44 import org.onap.oom.certservice.postprocessor.merger.exception.WriteTruststoreFileException;
45 import org.onap.oom.certservice.postprocessor.merger.model.certificate.CertificateWithAlias;
46 import org.onap.oom.certservice.postprocessor.merger.model.certificate.CertificateWithAliasFactory;
47 import org.slf4j.Logger;
48 import org.slf4j.LoggerFactory;
50 public class PemTruststore extends Truststore {
52 private static final Logger LOGGER = LoggerFactory.getLogger(PemTruststore.class);
54 private static final boolean APPEND_TO_FILE = true;
56 private final CertificateWithAliasFactory factory = new CertificateWithAliasFactory();
57 private final List<CertificateWithAlias> certificatesToBeSaved = new ArrayList<>();
59 public PemTruststore(File storeFile) {
60 super(storeFile, new FileTools());
63 public List<CertificateWithAlias> getCertificates()
64 throws TruststoreDataOperationException, MissingTruststoreException {
65 LOGGER.debug("Attempt to read certificates from file: {}", storeFile.getPath());
66 if (isFileWithoutPemCertificate()) {
67 throw new MissingTruststoreException("File does not contain any certificate");
69 List<Certificate> extractedCertificate = extractCertificatesFromFile();
70 return wrapCertificates(extractedCertificate);
73 public void addCertificates(List<CertificateWithAlias> certificates)
74 throws TruststoreDataOperationException, MissingTruststoreException {
75 LOGGER.debug("Attempt to add certificates for saving to file");
76 if (isFileWithoutPemCertificate()) {
77 LOGGER.error("File does not contain any certificate. File path: {} ", storeFile.getPath());
78 throw new MissingTruststoreException("File does not contain any certificate");
80 certificatesToBeSaved.addAll(certificates);
83 public void saveFile() throws WriteTruststoreFileException, TruststoreDataOperationException {
84 LOGGER.debug("Attempt to save file: {}", storeFile.getPath());
85 List<Certificate> certificates = certificatesToBeSaved.stream()
86 .map(CertificateWithAlias::getCertificate)
87 .collect(Collectors.toList());
88 String certificatesAsString = transformToStringInPemFormat(certificates);
89 appendToFile(certificatesAsString);
92 boolean isFileWithoutPemCertificate() throws TruststoreDataOperationException {
94 List<Certificate> certificateList = extractCertificatesFromFile();
95 return certificateList.isEmpty();
96 } catch (TruststoreDataOperationException e) {
97 LOGGER.error("Cannot extract certificates from file: {}", storeFile.getPath());
102 String transformToStringInPemFormat(List<Certificate> certificates) throws TruststoreDataOperationException {
103 StringWriter sw = new StringWriter();
104 List<PemObjectGenerator> generators = transformToPemGenerators(certificates);
105 try (PemWriter pemWriter = new PemWriter(sw)) {
106 for (PemObjectGenerator generator : generators) {
107 pemWriter.writeObject(generator);
109 } catch (IOException e) {
110 LOGGER.error("Cannot convert certificates to PEM format");
111 throw new TruststoreDataOperationException(e);
113 return sw.toString();
116 private List<Certificate> extractCertificatesFromFile() throws TruststoreDataOperationException {
117 try (FileInputStream inputStream = new FileInputStream(storeFile)) {
118 Security.addProvider(new BouncyCastleProvider());
119 CertificateFactory certFactory = CertificateFactory.getInstance(X_509_CERTIFICATE, BOUNCY_CASTLE_PROVIDER);
120 return new ArrayList<>(certFactory.generateCertificates(inputStream));
122 catch (CertificateException e) {
123 LOGGER.error("Cannot read certificates from file: {}", storeFile.getPath());
124 throw new TruststoreDataOperationException(e);
126 catch (Exception e) {
127 LOGGER.error("Cannot read certificates from file: {}", storeFile.getPath());
128 throw new TruststoreDataOperationException(e);
132 private List<PemObjectGenerator> transformToPemGenerators(List<Certificate> certificates)
133 throws TruststoreDataOperationException {
134 List<PemObjectGenerator> generators = new ArrayList<>();
135 for (Certificate certificate : certificates) {
136 PemObjectGenerator generator = createPemGenerator(certificate);
137 generators.add(generator);
142 private JcaMiscPEMGenerator createPemGenerator(Certificate certificate)
143 throws TruststoreDataOperationException {
145 return new JcaMiscPEMGenerator(certificate);
146 } catch (IOException e) {
147 LOGGER.error("Cannot convert Certificate Object to PemGenerator Object");
148 throw new TruststoreDataOperationException(e);
152 private List<CertificateWithAlias> wrapCertificates(List<Certificate> rawCertificates) {
153 return rawCertificates.stream()
154 .map(factory::createPemCertificate)
155 .collect(Collectors.toList());
158 private void appendToFile(String certificatesAsString) throws WriteTruststoreFileException {
159 try (FileOutputStream fileOutputStream = new FileOutputStream(storeFile, APPEND_TO_FILE)) {
160 fileOutputStream.write(certificatesAsString.getBytes());
161 } catch (Exception e) {
162 LOGGER.error("Cannot write certificates to file");
163 throw new WriteTruststoreFileException(e);