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.CertificateFactory;
33 import java.util.ArrayList;
34 import java.util.List;
35 import java.util.stream.Collectors;
36 import org.bouncycastle.jce.provider.BouncyCastleProvider;
37 import org.bouncycastle.openssl.jcajce.JcaMiscPEMGenerator;
38 import org.bouncycastle.util.io.pem.PemObjectGenerator;
39 import org.bouncycastle.util.io.pem.PemWriter;
40 import org.onap.oom.certservice.postprocessor.common.FileTools;
41 import org.onap.oom.certservice.postprocessor.merger.exception.MissingTruststoreException;
42 import org.onap.oom.certservice.postprocessor.merger.exception.TruststoreDataOperationException;
43 import org.onap.oom.certservice.postprocessor.merger.exception.WriteTruststoreFileException;
44 import org.onap.oom.certservice.postprocessor.merger.model.certificate.CertificateWithAlias;
45 import org.onap.oom.certservice.postprocessor.merger.model.certificate.CertificateWithAliasFactory;
46 import org.slf4j.Logger;
47 import org.slf4j.LoggerFactory;
49 public class PemTruststore extends Truststore {
51 private static final Logger LOGGER = LoggerFactory.getLogger(PemTruststore.class);
53 private static final boolean APPEND_TO_FILE = true;
55 private final CertificateWithAliasFactory factory = new CertificateWithAliasFactory();
56 private final List<CertificateWithAlias> certificatesToBeSaved = new ArrayList<>();
58 public PemTruststore(File storeFile) {
59 super(storeFile, new FileTools());
62 public List<CertificateWithAlias> getCertificates()
63 throws TruststoreDataOperationException, MissingTruststoreException {
64 LOGGER.debug("Attempt to read certificates from file: {}", storeFile.getPath());
65 if (isFileWithoutPemCertificate()) {
66 throw new MissingTruststoreException("File does not contain any certificate");
68 List<Certificate> extractedCertificate = extractCertificatesFromFile();
69 return wrapCertificates(extractedCertificate);
72 public void addCertificates(List<CertificateWithAlias> certificates)
73 throws TruststoreDataOperationException, MissingTruststoreException {
74 LOGGER.debug("Attempt to add certificates for saving to file");
75 if (isFileWithoutPemCertificate()) {
76 LOGGER.error("File does not contain any certificate. File path: {} ", storeFile.getPath());
77 throw new MissingTruststoreException("File does not contain any certificate");
79 certificatesToBeSaved.addAll(certificates);
82 public void saveFile() throws WriteTruststoreFileException, TruststoreDataOperationException {
83 LOGGER.debug("Attempt to save file: {}", storeFile.getPath());
84 List<Certificate> certificates = certificatesToBeSaved.stream()
85 .map(CertificateWithAlias::getCertificate)
86 .collect(Collectors.toList());
87 String certificatesAsString = transformToStringInPemFormat(certificates);
88 appendToFile(certificatesAsString);
91 boolean isFileWithoutPemCertificate() throws TruststoreDataOperationException {
92 List<Certificate> certificateList = extractCertificatesFromFile();
93 return certificateList.isEmpty();
96 String transformToStringInPemFormat(List<Certificate> certificates) throws TruststoreDataOperationException {
97 StringWriter sw = new StringWriter();
98 List<PemObjectGenerator> generators = transformToPemGenerators(certificates);
99 try (PemWriter pemWriter = new PemWriter(sw)) {
100 for (PemObjectGenerator generator : generators) {
101 pemWriter.writeObject(generator);
103 } catch (IOException e) {
104 LOGGER.error("Cannot convert certificates to PEM format");
105 throw new TruststoreDataOperationException(e);
107 return sw.toString();
110 private List<Certificate> extractCertificatesFromFile() throws TruststoreDataOperationException {
111 try (FileInputStream inputStream = new FileInputStream(storeFile)) {
112 Security.addProvider(new BouncyCastleProvider());
113 CertificateFactory certFactory = CertificateFactory.getInstance(X_509_CERTIFICATE, BOUNCY_CASTLE_PROVIDER);
114 return new ArrayList<>(certFactory.generateCertificates(inputStream));
115 } catch (Exception e) {
116 LOGGER.error("Cannot read certificates from file: {}", storeFile.getPath());
117 throw new TruststoreDataOperationException(e);
121 private List<PemObjectGenerator> transformToPemGenerators(List<Certificate> certificates)
122 throws TruststoreDataOperationException {
123 List<PemObjectGenerator> generators = new ArrayList<>();
124 for (Certificate certificate : certificates) {
125 PemObjectGenerator generator = createPemGenerator(certificate);
126 generators.add(generator);
131 private JcaMiscPEMGenerator createPemGenerator(Certificate certificate)
132 throws TruststoreDataOperationException {
134 return new JcaMiscPEMGenerator(certificate);
135 } catch (IOException e) {
136 LOGGER.error("Cannot convert Certificate Object to PemGenerator Object");
137 throw new TruststoreDataOperationException(e);
141 private List<CertificateWithAlias> wrapCertificates(List<Certificate> rawCertificates) {
142 return rawCertificates.stream()
143 .map(factory::createPemCertificate)
144 .collect(Collectors.toList());
147 private void appendToFile(String certificatesAsString) throws WriteTruststoreFileException {
148 try (FileOutputStream fileOutputStream = new FileOutputStream(storeFile, APPEND_TO_FILE)) {
149 fileOutputStream.write(certificatesAsString.getBytes());
150 } catch (Exception e) {
151 LOGGER.error("Cannot write certificates to file");
152 throw new WriteTruststoreFileException(e);