643d0286b3008771f775864a9b9f51c32d15068c
[vfc/nfvo/driver/vnfm/svnfm.git] / nokiav2 / driver / src / main / java / org / onap / vfc / nfvo / driver / vnfm / svnfm / nokia / util / StoreLoader.java
1 /*
2  * Copyright 2016-2017, Nokia Corporation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 package org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.util;
18
19 import org.apache.commons.codec.binary.Base64;
20
21 import java.io.ByteArrayInputStream;
22 import java.io.InputStream;
23 import java.security.KeyFactory;
24 import java.security.KeyStore;
25 import java.security.KeyStore.TrustedCertificateEntry;
26 import java.security.PrivateKey;
27 import java.security.cert.Certificate;
28 import java.security.cert.CertificateFactory;
29 import java.security.spec.PKCS8EncodedKeySpec;
30 import java.util.Collection;
31 import java.util.HashSet;
32 import java.util.Optional;
33 import java.util.Set;
34
35 import static java.util.Optional.empty;
36 import static java.util.Optional.of;
37 import static org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.util.CbamUtils.buildFatalFailure;
38 import static org.slf4j.LoggerFactory.getLogger;
39
40 /**
41  * Create Truststore from the given certificates and keys
42  */
43 public final class StoreLoader {
44
45     public static final String PASS_ALIAS = "password";
46     private static final String RSA = "RSA";
47     private static final String X_509 = "X.509";
48     private static final String SUN = "SUN";
49     private static final String JKS = "JKS";
50     private static final String RSA_PRIVATE_KEY = "RSA PRIVATE KEY";
51     private static final String CERTIFICATE = "CERTIFICATE";
52     private static org.slf4j.Logger logger = getLogger(StoreLoader.class);
53
54     private StoreLoader() {
55     }
56
57     private static String getScope(String content, String scope) {
58         int rindex = content.indexOf(begin(scope));
59         int lindex = content.indexOf(end(scope));
60         if (rindex == -1 || lindex == -1) {
61             return "";
62         }
63         return content.substring(rindex, lindex) + end(scope);
64     }
65
66     /**
67      * @param content the content of the PEM ( a PEM may contain multiple certificates)
68      * @return the collection of certificates in the PEM
69      */
70     public static Set<String> getCertifacates(String content) {
71         String lastCertificate = "";
72         Set<String> certificates = new HashSet<>();
73         do {
74             lastCertificate = getScope(content, CERTIFICATE);
75             content = content.replace(lastCertificate, "");
76             if (!"".equals(lastCertificate)) {
77                 certificates.add(lastCertificate);
78             }
79         } while (!"".equals(lastCertificate));
80         return certificates;
81     }
82
83     private static byte[] toDer(String pem, String scope) {
84         return Base64.decodeBase64(pem
85                 .replace(begin(scope), "")
86                 .replace(end(scope), "")
87                 .replaceAll("\\s", ""));
88     }
89
90     private static String begin(String scope) {
91         return "-----BEGIN " + scope + "-----";
92     }
93
94     private static String end(String scope) {
95         return "-----END " + scope + "-----";
96     }
97
98     /**
99      * Create new truststore from the given certificate
100      *
101      * @param pem           the certificate which used to create the store
102      * @param storePassword the password to protect the store
103      * @param keyPassword   the password to protect the key
104      * @return the created key store
105      */
106     public static KeyStore loadStore(String pem, String storePassword, String keyPassword) {
107         Optional<PrivateKey> privateKey = generatePrivateKey(pem);
108         Optional<Certificate[]> certs = createCertificates(pem);
109         try {
110             KeyStore ks = KeyStore.getInstance(JKS, SUN);
111             ks.load(null, storePassword.toCharArray());
112             if (privateKey.isPresent()) {
113                 ks.setKeyEntry(PASS_ALIAS, privateKey.get(), keyPassword.toCharArray(), certs.orElse(null));
114             } else if (certs.isPresent()) {
115                 int index = 0;
116                 for (Certificate cert : certs.get()) {
117                     TrustedCertificateEntry ts = new TrustedCertificateEntry(cert);
118                     ks.setEntry(PASS_ALIAS + index, ts, null);
119                     index++;
120                 }
121             }
122             return ks;
123         } catch (Exception e) {
124             throw new UserInvisibleError("Unable to create keystore", e);
125         }
126     }
127
128     private static Optional<Certificate[]> createCertificates(String pem) {
129         Set<Certificate> certificates = new HashSet<>();
130         try {
131             for (String certificate : getCertifacates(pem)) {
132                 CertificateFactory certFactory = CertificateFactory.getInstance(X_509);
133
134                 InputStream is = new ByteArrayInputStream(toDer(certificate, CERTIFICATE));
135                 Collection<? extends Certificate> c = certFactory.generateCertificates(is);
136                 certificates.addAll(c);
137             }
138         } catch (Exception e) {
139             throw buildFatalFailure(logger, "Unable to load certificates", e);
140         }
141
142         if (!certificates.isEmpty()) {
143             return of(certificates.toArray(new Certificate[certificates.size()]));
144         } else {
145             return empty();
146         }
147     }
148
149     private static Optional<PrivateKey> generatePrivateKey(String pem) {
150         try {
151             String key = getScope(pem, RSA_PRIVATE_KEY);
152             if (!key.isEmpty()) {
153                 KeyFactory keyFactory = KeyFactory.getInstance(RSA);
154                 PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(toDer(key, RSA_PRIVATE_KEY));
155                 return of(keyFactory.generatePrivate(keySpec));
156             }
157             return empty();
158         } catch (Exception e) {
159             throw buildFatalFailure(logger, "Unable to load key", e);
160         }
161     }
162
163 }