Use {Key,Trust}ManagerFactory.getDefaultAlgorithm()
[aaa.git] / aaa-cert / src / main / java / org / opendaylight / aaa / cert / impl / CertificateManagerService.java
1 /*
2  * Copyright (c) 2016, 2017 Inocybe Technologies. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.aaa.cert.impl;
9
10 import java.io.File;
11 import java.io.IOException;
12 import java.security.KeyManagementException;
13 import java.security.KeyStore;
14 import java.security.KeyStoreException;
15 import java.security.NoSuchAlgorithmException;
16 import java.security.UnrecoverableKeyException;
17 import javax.net.ssl.KeyManagerFactory;
18 import javax.net.ssl.SSLContext;
19 import javax.net.ssl.TrustManagerFactory;
20 import javax.xml.parsers.DocumentBuilder;
21 import javax.xml.parsers.DocumentBuilderFactory;
22 import javax.xml.parsers.ParserConfigurationException;
23 import javax.xml.transform.Transformer;
24 import javax.xml.transform.TransformerException;
25 import javax.xml.transform.TransformerFactory;
26 import javax.xml.transform.dom.DOMSource;
27 import javax.xml.transform.stream.StreamResult;
28 import org.apache.commons.lang3.RandomStringUtils;
29 import org.opendaylight.aaa.cert.api.IAaaCertProvider;
30 import org.opendaylight.aaa.cert.api.ICertificateManager;
31 import org.opendaylight.aaa.encrypt.AAAEncryptionService;
32 import org.opendaylight.mdsal.binding.api.DataBroker;
33 import org.opendaylight.mdsal.binding.api.RpcProviderService;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.yang.aaa.cert.rev151126.AaaCertServiceConfig;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.yang.aaa.cert.rev151126.AaaCertServiceConfigBuilder;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.yang.aaa.cert.rev151126.aaa.cert.service.config.CtlKeystore;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.yang.aaa.cert.rev151126.aaa.cert.service.config.CtlKeystoreBuilder;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.yang.aaa.cert.rev151126.aaa.cert.service.config.TrustKeystore;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.yang.aaa.cert.rev151126.aaa.cert.service.config.TrustKeystoreBuilder;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.yang.aaa.cert.rpc.rev151215.AaaCertRpcService;
41 import org.opendaylight.yangtools.concepts.Registration;
42 import org.slf4j.Logger;
43 import org.slf4j.LoggerFactory;
44 import org.w3c.dom.Document;
45 import org.w3c.dom.Node;
46 import org.w3c.dom.NodeList;
47 import org.xml.sax.SAXException;
48
49 /**
50  * CertificateManagerService implements ICertificateManager and work as adapter
51  * to which AaaCertProvider is used.
52  *
53  * @author mserngawy
54  */
55 public class CertificateManagerService implements ICertificateManager, AutoCloseable {
56     private static final Logger LOG = LoggerFactory.getLogger(CertificateManagerService.class);
57     private static final String DEFAULT_CONFIG_FILE_PATH = "etc" + File.separator + "opendaylight" + File.separator
58             + "datastore" + File.separator + "initial" + File.separator + "config" + File.separator
59             + "aaa-cert-config.xml";
60     private static final int PWD_LENGTH = 12;
61
62     private final IAaaCertProvider aaaCertProvider;
63     private final Registration reg;
64
65     public CertificateManagerService(final RpcProviderService rpcProviderService, final DataBroker dataBroker,
66             final AAAEncryptionService encryptionSrv, AaaCertServiceConfig aaaCertServiceConfig) {
67         if (aaaCertServiceConfig == null) {
68             throw new IllegalArgumentException("Certificate Manager service configuration is null");
69         }
70         if (aaaCertServiceConfig.getUseConfig()) {
71             if (aaaCertServiceConfig.getCtlKeystore() != null
72                     && aaaCertServiceConfig.getCtlKeystore().getStorePassword() != null
73                     && aaaCertServiceConfig.getCtlKeystore().getStorePassword().isEmpty()) {
74                 LOG.debug("Set keystores password");
75                 final String ctlPwd = RandomStringUtils.random(PWD_LENGTH, true, true);
76                 final String trustPwd = RandomStringUtils.random(PWD_LENGTH, true, true);
77                 updateCertManagerSrvConfig(ctlPwd, trustPwd);
78                 final CtlKeystore ctlKeystore = new CtlKeystoreBuilder(aaaCertServiceConfig.getCtlKeystore())
79                         .setStorePassword(ctlPwd).build();
80                 final TrustKeystore trustKeystore = new TrustKeystoreBuilder(aaaCertServiceConfig.getTrustKeystore())
81                         .setStorePassword(trustPwd).build();
82                 aaaCertServiceConfig = new AaaCertServiceConfigBuilder(aaaCertServiceConfig).setCtlKeystore(ctlKeystore)
83                         .setTrustKeystore(trustKeystore).build();
84             }
85             if (aaaCertServiceConfig.getUseMdsal()) {
86                 aaaCertProvider = new DefaultMdsalSslData(new AaaCertMdsalProvider(dataBroker, encryptionSrv),
87                         aaaCertServiceConfig.getBundleName(), aaaCertServiceConfig.getCtlKeystore(),
88                         aaaCertServiceConfig.getTrustKeystore());
89                 LOG.debug("Using default mdsal SslData as aaaCertProvider");
90             } else {
91                 aaaCertProvider = new AaaCertProvider(aaaCertServiceConfig.getCtlKeystore(),
92                         aaaCertServiceConfig.getTrustKeystore());
93                 LOG.debug("Using default keystore files as aaaCertProvider");
94             }
95             aaaCertProvider.createKeyStores();
96             LOG.info("Certificate Manager service has been initialized");
97             reg = rpcProviderService.registerRpcImplementation(AaaCertRpcService.class,
98                 new AaaCertRpcServiceImpl(aaaCertProvider));
99             LOG.info("AaaCert Rpc Service has been initialized");
100         } else {
101             aaaCertProvider = null;
102             reg = null;
103             LOG.info("Certificate Manager service has not been initialized, change the initial aaa-cert-config data "
104                 + "and restart Opendaylight");
105         }
106     }
107
108     @Override
109     public void close() {
110         if (reg != null) {
111             reg.close();
112         }
113     }
114
115     @Override
116     public KeyStore getODLKeyStore() {
117         return aaaCertProvider.getODLKeyStore();
118     }
119
120     @Override
121     public KeyStore getTrustKeyStore() {
122         return aaaCertProvider.getTrustKeyStore();
123     }
124
125     @Override
126     public String[] getCipherSuites() {
127         return aaaCertProvider.getCipherSuites();
128     }
129
130     @Override
131     public String getCertificateTrustStore(final String storePasswd, final String alias, final boolean withTag) {
132         return aaaCertProvider.getCertificateTrustStore(storePasswd, alias, withTag);
133     }
134
135     @Override
136     public String getODLKeyStoreCertificate(final String storePasswd, final boolean withTag) {
137         return aaaCertProvider.getODLKeyStoreCertificate(storePasswd, withTag);
138     }
139
140     @Override
141     public String genODLKeyStoreCertificateReq(final String storePasswd, final boolean withTag) {
142         return aaaCertProvider.genODLKeyStoreCertificateReq(storePasswd, withTag);
143     }
144
145     @Override
146     public SSLContext getServerContext() {
147         SSLContext serverContext = null;
148         try {
149             KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
150             kmf.init(aaaCertProvider.getODLKeyStore(),
151                     aaaCertProvider.getOdlKeyStoreInfo().getStorePassword().toCharArray());
152             TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
153             tmf.init(aaaCertProvider.getTrustKeyStore());
154
155             serverContext = SSLContext.getInstance("TLS");
156             serverContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
157         } catch (final NoSuchAlgorithmException | UnrecoverableKeyException | KeyStoreException
158                 | KeyManagementException e) {
159             LOG.error("Error while creating SSLContext ", e);
160         }
161         return serverContext;
162     }
163
164     @Override
165     public String[] getTlsProtocols() {
166         return aaaCertProvider.getTlsProtocols();
167     }
168
169     @Override
170     public boolean importSslDataKeystores(final String odlKeystoreName, final String odlKeystorePwd,
171             final String odlKeystoreAlias, final String trustKeystoreName, final String trustKeystorePwd,
172             final String[] cipherSuites, final String tlsProtocols) {
173         DefaultMdsalSslData mdsalCertProvider = (DefaultMdsalSslData) aaaCertProvider;
174         if (mdsalCertProvider == null) {
175             LOG.debug("aaaCertProvider is not MD-Sal Certificate Provider");
176             return false;
177         }
178         return mdsalCertProvider.importSslDataKeystores(odlKeystoreName, odlKeystorePwd, odlKeystoreAlias,
179                 trustKeystoreName, trustKeystorePwd, cipherSuites, tlsProtocols);
180     }
181
182     @Override
183     public void exportSslDataKeystores() {
184         DefaultMdsalSslData mdsalCertProvider = (DefaultMdsalSslData) aaaCertProvider;
185         if (mdsalCertProvider == null) {
186             LOG.debug("aaaCertProvider is not MD-Sal Certificate Provider");
187             return;
188         }
189         mdsalCertProvider.exportSslDataKeystores();
190     }
191
192     private static void updateCertManagerSrvConfig(final String ctlPwd, final String trustPwd) {
193         try {
194             LOG.debug("Update Certificate manager service config file");
195             final File configFile = new File(DEFAULT_CONFIG_FILE_PATH);
196             if (configFile.exists()) {
197                 final String storePwdTag = "store-password";
198                 final String ctlStoreTag = "ctlKeystore";
199                 final String trustStoreTag = "trustKeystore";
200                 final DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
201                 final DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
202                 final Document doc = docBuilder.parse(configFile);
203                 final NodeList ndList = doc.getElementsByTagName(storePwdTag);
204                 for (int i = 0; i < ndList.getLength(); i++) {
205                     final Node nd = ndList.item(i);
206                     if (nd.getParentNode() != null && nd.getParentNode().getNodeName().equals(ctlStoreTag)) {
207                         nd.setTextContent(ctlPwd);
208                     } else if (nd.getParentNode() != null && nd.getParentNode().getNodeName().equals(trustStoreTag)) {
209                         nd.setTextContent(trustPwd);
210                     }
211                 }
212                 final TransformerFactory transformerFactory = TransformerFactory.newInstance();
213                 final Transformer transformer = transformerFactory.newTransformer();
214                 final DOMSource source = new DOMSource(doc);
215                 final StreamResult result = new StreamResult(new File(DEFAULT_CONFIG_FILE_PATH));
216                 transformer.transform(source, result);
217             } else {
218                 LOG.warn("The Certificate manager service config file does not exist {}", DEFAULT_CONFIG_FILE_PATH);
219             }
220         } catch (ParserConfigurationException | TransformerException | SAXException | IOException e) {
221             LOG.error("Error while updating Certificate manager service config file", e);
222         }
223     }
224 }