[OOM-CERT-SERVICE] Fix vulnerabilities for Kohn
[oom/platform/cert-service.git] / certServicePostProcessor / src / main / java / org / onap / oom / certservice / postprocessor / merger / model / PemTruststore.java
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
9  *
10  *      http://www.apache.org/licenses/LICENSE-2.0
11  *
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=========================================================
18  */
19
20 package org.onap.oom.certservice.postprocessor.merger.model;
21
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;
24
25 import java.io.File;
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;
49
50 public class PemTruststore extends Truststore {
51
52     private static final Logger LOGGER = LoggerFactory.getLogger(PemTruststore.class);
53
54     private static final boolean APPEND_TO_FILE = true;
55
56     private final CertificateWithAliasFactory factory = new CertificateWithAliasFactory();
57     private final List<CertificateWithAlias> certificatesToBeSaved = new ArrayList<>();
58
59     public PemTruststore(File storeFile) {
60         super(storeFile, new FileTools());
61     }
62
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");
68         }
69         List<Certificate> extractedCertificate = extractCertificatesFromFile();
70         return wrapCertificates(extractedCertificate);
71     }
72
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");
79         }
80         certificatesToBeSaved.addAll(certificates);
81     }
82
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);
90     }
91
92     boolean isFileWithoutPemCertificate() throws TruststoreDataOperationException {
93         try {
94             List<Certificate> certificateList = extractCertificatesFromFile();
95             return certificateList.isEmpty();
96         } catch (TruststoreDataOperationException e) {
97             LOGGER.error("Cannot extract certificates from file: {}", storeFile.getPath());
98         }
99         return true;
100     }
101
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);
108             }
109         } catch (IOException e) {
110             LOGGER.error("Cannot convert certificates to PEM format");
111             throw new TruststoreDataOperationException(e);
112         }
113         return sw.toString();
114     }
115
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));
121         }
122         catch (CertificateException e) {
123             LOGGER.error("Cannot read certificates from file: {}", storeFile.getPath());
124             throw new TruststoreDataOperationException(e);
125         }
126         catch (Exception e) {
127             LOGGER.error("Cannot read certificates from file: {}", storeFile.getPath());
128             throw new TruststoreDataOperationException(e);
129         }
130     }
131
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);
138         }
139         return generators;
140     }
141
142     private JcaMiscPEMGenerator createPemGenerator(Certificate certificate)
143         throws TruststoreDataOperationException {
144         try {
145             return new JcaMiscPEMGenerator(certificate);
146         } catch (IOException e) {
147             LOGGER.error("Cannot convert Certificate Object to PemGenerator Object");
148             throw new TruststoreDataOperationException(e);
149         }
150     }
151
152     private List<CertificateWithAlias> wrapCertificates(List<Certificate> rawCertificates) {
153         return rawCertificates.stream()
154             .map(factory::createPemCertificate)
155             .collect(Collectors.toList());
156     }
157
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);
164         }
165     }
166 }