2 * Copyright (c) 2018 ZTE Corporation. and others. All rights reserved.
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
8 package org.opendaylight.netconf.sal.connect.netconf.sal;
10 import static org.junit.Assert.assertTrue;
11 import static org.mockito.ArgumentMatchers.any;
12 import static org.mockito.Mockito.doReturn;
13 import static org.mockito.Mockito.mock;
15 import java.security.KeyStoreException;
16 import java.util.ArrayList;
17 import java.util.Arrays;
18 import java.util.Collections;
19 import java.util.List;
20 import org.junit.Assert;
21 import org.junit.Before;
22 import org.junit.Test;
23 import org.junit.runner.RunWith;
24 import org.mockito.Mock;
25 import org.mockito.junit.MockitoJUnitRunner;
26 import org.opendaylight.mdsal.binding.api.DataBroker;
27 import org.opendaylight.mdsal.binding.api.DataObjectModification;
28 import org.opendaylight.mdsal.binding.api.DataTreeIdentifier;
29 import org.opendaylight.mdsal.binding.api.DataTreeModification;
30 import org.opendaylight.netconf.api.xml.XmlUtil;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.keystore.rev171017.Keystore;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.keystore.rev171017._private.keys.PrivateKey;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.keystore.rev171017._private.keys.PrivateKeyBuilder;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.keystore.rev171017._private.keys.PrivateKeyKey;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.keystore.rev171017.trusted.certificates.TrustedCertificate;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.keystore.rev171017.trusted.certificates.TrustedCertificateBuilder;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.keystore.rev171017.trusted.certificates.TrustedCertificateKey;
38 import org.opendaylight.yangtools.concepts.ListenerRegistration;
39 import org.w3c.dom.Document;
40 import org.w3c.dom.Element;
41 import org.w3c.dom.Node;
42 import org.w3c.dom.NodeList;
44 @RunWith(MockitoJUnitRunner.StrictStubs.class)
45 public class NetconfKeystoreAdapterTest {
46 private static final String XML_ELEMENT_PRIVATE_KEY = "private-key";
47 private static final String XML_ELEMENT_NAME = "name";
48 private static final String XML_ELEMENT_DATA = "data";
49 private static final String XML_ELEMENT_CERT_CHAIN = "certificate-chain";
50 private static final String XML_ELEMENT_TRUSTED_CERT = "trusted-certificate";
51 private static final String XML_ELEMENT_CERT = "certificate";
54 private DataBroker dataBroker;
56 private ListenerRegistration listenerRegistration;
60 doReturn(listenerRegistration).when(dataBroker).registerDataTreeChangeListener(
61 any(DataTreeIdentifier.class), any(NetconfKeystoreAdapter.class));
65 public void testKeystoreAdapterInit() throws Exception {
66 NetconfKeystoreAdapter keystoreAdapter = new NetconfKeystoreAdapter(dataBroker);
69 keystoreAdapter.getJavaKeyStore();
70 Assert.fail(IllegalStateException.class + "exception expected");
71 } catch (KeyStoreException e) {
72 assertTrue(e.getMessage().startsWith("No keystore private key found"));
76 @SuppressWarnings("unchecked")
78 public void testWritePrivateKey() throws Exception {
79 DataTreeModification<Keystore> dataTreeModification = mock(DataTreeModification.class);
80 DataObjectModification<Keystore> keystoreObjectModification = mock(DataObjectModification.class);
81 doReturn(keystoreObjectModification).when(dataTreeModification).getRootNode();
83 DataObjectModification<?> childObjectModification = mock(DataObjectModification.class);
84 doReturn(Collections.singletonList(childObjectModification))
85 .when(keystoreObjectModification).getModifiedChildren();
86 doReturn(PrivateKey.class).when(childObjectModification).getDataType();
88 doReturn(DataObjectModification.ModificationType.WRITE)
89 .when(childObjectModification).getModificationType();
91 PrivateKey privateKey = getPrivateKey();
92 doReturn(privateKey).when(childObjectModification).getDataAfter();
94 NetconfKeystoreAdapter keystoreAdapter = new NetconfKeystoreAdapter(dataBroker);
95 keystoreAdapter.onDataTreeChanged(Collections.singletonList(dataTreeModification));
97 java.security.KeyStore keyStore = keystoreAdapter.getJavaKeyStore();
98 assertTrue(keyStore.containsAlias(privateKey.getName()));
101 @SuppressWarnings("unchecked")
103 public void testWritePrivateKeyAndTrustedCertificate() throws Exception {
104 // Prepare PrivateKey configuration
105 DataTreeModification<Keystore> dataTreeModification1 = mock(DataTreeModification.class);
106 DataObjectModification<Keystore> keystoreObjectModification1 = mock(DataObjectModification.class);
107 doReturn(keystoreObjectModification1).when(dataTreeModification1).getRootNode();
109 DataObjectModification<?> childObjectModification1 = mock(DataObjectModification.class);
110 doReturn(Collections.singletonList(childObjectModification1))
111 .when(keystoreObjectModification1).getModifiedChildren();
112 doReturn(PrivateKey.class).when(childObjectModification1).getDataType();
114 doReturn(DataObjectModification.ModificationType.WRITE)
115 .when(childObjectModification1).getModificationType();
117 PrivateKey privateKey = getPrivateKey();
118 doReturn(privateKey).when(childObjectModification1).getDataAfter();
120 // Prepare TrustedCertificate configuration
121 DataTreeModification<Keystore> dataTreeModification2 = mock(DataTreeModification.class);
122 DataObjectModification<Keystore> keystoreObjectModification2 = mock(DataObjectModification.class);
123 doReturn(keystoreObjectModification2).when(dataTreeModification2).getRootNode();
125 DataObjectModification<?> childObjectModification2 = mock(DataObjectModification.class);
126 doReturn(Collections.singletonList(childObjectModification2))
127 .when(keystoreObjectModification2).getModifiedChildren();
128 doReturn(TrustedCertificate.class).when(childObjectModification2).getDataType();
130 doReturn(DataObjectModification.ModificationType.WRITE)
131 .when(childObjectModification2).getModificationType();
133 TrustedCertificate trustedCertificate = geTrustedCertificate();
134 doReturn(trustedCertificate).when(childObjectModification2).getDataAfter();
136 // Apply configurations
137 NetconfKeystoreAdapter keystoreAdapter = new NetconfKeystoreAdapter(dataBroker);
138 keystoreAdapter.onDataTreeChanged(Arrays.asList(dataTreeModification1, dataTreeModification2));
141 java.security.KeyStore keyStore = keystoreAdapter.getJavaKeyStore();
142 assertTrue(keyStore.containsAlias(privateKey.getName()));
143 assertTrue(keyStore.containsAlias(trustedCertificate.getName()));
146 private PrivateKey getPrivateKey() throws Exception {
147 final List<PrivateKey> privateKeys = new ArrayList<>();
148 final Document document = readKeystoreXML();
149 final NodeList nodeList = document.getElementsByTagName(XML_ELEMENT_PRIVATE_KEY);
150 for (int i = 0; i < nodeList.getLength(); i++) {
151 final Node node = nodeList.item(i);
152 if (node.getNodeType() != Node.ELEMENT_NODE) {
155 final Element element = (Element)node;
156 final String keyName = element.getElementsByTagName(XML_ELEMENT_NAME).item(0).getTextContent();
157 final String keyData = element.getElementsByTagName(XML_ELEMENT_DATA).item(0).getTextContent();
158 final NodeList certNodes = element.getElementsByTagName(XML_ELEMENT_CERT_CHAIN);
159 final List<String> certChain = new ArrayList<>();
160 for (int j = 0; j < certNodes.getLength(); j++) {
161 final Node certNode = certNodes.item(j);
162 if (certNode.getNodeType() != Node.ELEMENT_NODE) {
165 certChain.add(certNode.getTextContent());
168 final PrivateKey privateKey = new PrivateKeyBuilder()
169 .withKey(new PrivateKeyKey(keyName))
172 .setCertificateChain(certChain)
174 privateKeys.add(privateKey);
177 return privateKeys.get(0);
180 private TrustedCertificate geTrustedCertificate() throws Exception {
181 final List<TrustedCertificate> trustedCertificates = new ArrayList<>();
182 final Document document = readKeystoreXML();
183 final NodeList nodeList = document.getElementsByTagName(XML_ELEMENT_TRUSTED_CERT);
184 for (int i = 0; i < nodeList.getLength(); i++) {
185 final Node node = nodeList.item(i);
186 if (node.getNodeType() != Node.ELEMENT_NODE) {
189 final Element element = (Element)node;
190 final String certName = element.getElementsByTagName(XML_ELEMENT_NAME).item(0).getTextContent();
191 final String certData = element.getElementsByTagName(XML_ELEMENT_CERT).item(0).getTextContent();
193 final TrustedCertificate certificate = new TrustedCertificateBuilder()
194 .withKey(new TrustedCertificateKey(certName))
196 .setCertificate(certData)
198 trustedCertificates.add(certificate);
201 return trustedCertificates.get(0);
204 private Document readKeystoreXML() throws Exception {
205 return XmlUtil.readXmlToDocument(getClass().getResourceAsStream("/netconf-keystore.xml"));