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