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.client.mdsal.impl;
10 import static org.hamcrest.CoreMatchers.startsWith;
11 import static org.hamcrest.MatcherAssert.assertThat;
12 import static org.junit.Assert.assertThrows;
13 import static org.junit.Assert.assertTrue;
14 import static org.mockito.ArgumentMatchers.any;
15 import static org.mockito.Mockito.doAnswer;
16 import static org.mockito.Mockito.doReturn;
18 import java.security.KeyStoreException;
19 import java.util.ArrayList;
20 import java.util.List;
22 import org.junit.jupiter.api.BeforeEach;
23 import org.junit.jupiter.api.Test;
24 import org.junit.jupiter.api.extension.ExtendWith;
25 import org.mockito.Mock;
26 import org.mockito.junit.jupiter.MockitoExtension;
27 import org.opendaylight.mdsal.binding.api.DataBroker;
28 import org.opendaylight.mdsal.binding.api.DataObjectModification;
29 import org.opendaylight.mdsal.binding.api.DataTreeChangeListener;
30 import org.opendaylight.mdsal.binding.api.DataTreeModification;
31 import org.opendaylight.netconf.api.xml.XmlUtil;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.keystore.rev171017.Keystore;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.keystore.rev171017._private.keys.PrivateKey;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.keystore.rev171017._private.keys.PrivateKeyBuilder;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.keystore.rev171017._private.keys.PrivateKeyKey;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.keystore.rev171017.trusted.certificates.TrustedCertificate;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.keystore.rev171017.trusted.certificates.TrustedCertificateBuilder;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.keystore.rev171017.trusted.certificates.TrustedCertificateKey;
39 import org.opendaylight.yangtools.concepts.Registration;
40 import org.w3c.dom.Document;
41 import org.w3c.dom.Element;
43 @ExtendWith(MockitoExtension.class)
44 class DefaultSslHandlerFactoryProviderTest {
45 private static final String XML_ELEMENT_PRIVATE_KEY = "private-key";
46 private static final String XML_ELEMENT_NAME = "name";
47 private static final String XML_ELEMENT_DATA = "data";
48 private static final String XML_ELEMENT_CERT_CHAIN = "certificate-chain";
49 private static final String XML_ELEMENT_TRUSTED_CERT = "trusted-certificate";
50 private static final String XML_ELEMENT_CERT = "certificate";
53 private DataBroker dataBroker;
55 private Registration listenerRegistration;
57 private DataTreeModification<Keystore> dataTreeModification1;
59 private DataTreeModification<Keystore> dataTreeModification2;
61 private DataObjectModification<Keystore> keystoreObjectModification1;
63 private DataObjectModification<Keystore> keystoreObjectModification2;
65 private DataObjectModification<PrivateKey> privateKeyModification;
67 private DataObjectModification<TrustedCertificate> trustedCertificateModification;
69 private DataTreeChangeListener<Keystore> listener;
74 listener = inv.getArgument(1);
75 return listenerRegistration;
76 }).when(dataBroker).registerTreeChangeListener(any(), any());
80 void testKeystoreAdapterInit() throws Exception {
81 try (var keystoreAdapter = new DefaultSslHandlerFactoryProvider(dataBroker)) {
82 final var ex = assertThrows(KeyStoreException.class, () -> keystoreAdapter.getJavaKeyStore(Set.of()));
83 assertThat(ex.getMessage(), startsWith("No keystore private key found"));
88 void testWritePrivateKey() throws Exception {
89 doReturn(keystoreObjectModification1).when(dataTreeModification1).getRootNode();
90 doReturn(List.of(privateKeyModification)).when(keystoreObjectModification1)
91 .getModifiedChildren(PrivateKey.class);
92 doReturn(DataObjectModification.ModificationType.WRITE).when(privateKeyModification).modificationType();
94 final var privateKey = getPrivateKey();
95 doReturn(privateKey).when(privateKeyModification).dataAfter();
97 try (var keystoreAdapter = new DefaultSslHandlerFactoryProvider(dataBroker)) {
98 listener.onDataTreeChanged(List.of(dataTreeModification1));
100 final var keyStore = keystoreAdapter.getJavaKeyStore(Set.of());
101 assertTrue(keyStore.containsAlias(privateKey.getName()));
106 void testWritePrivateKeyAndTrustedCertificate() throws Exception {
107 // Prepare PrivateKey configuration
108 doReturn(keystoreObjectModification1).when(dataTreeModification1).getRootNode();
110 doReturn(List.of(privateKeyModification)).when(keystoreObjectModification1)
111 .getModifiedChildren(PrivateKey.class);
112 doReturn(DataObjectModification.ModificationType.WRITE).when(privateKeyModification).modificationType();
114 final var privateKey = getPrivateKey();
115 doReturn(privateKey).when(privateKeyModification).dataAfter();
117 // Prepare TrustedCertificate configuration
118 doReturn(keystoreObjectModification2).when(dataTreeModification2).getRootNode();
120 doReturn(List.of()).when(keystoreObjectModification2).getModifiedChildren(PrivateKey.class);
121 doReturn(List.of(trustedCertificateModification)).when(keystoreObjectModification2)
122 .getModifiedChildren(TrustedCertificate.class);
123 doReturn(DataObjectModification.ModificationType.WRITE).when(trustedCertificateModification).modificationType();
125 final var trustedCertificate = getTrustedCertificate();
126 doReturn(trustedCertificate).when(trustedCertificateModification).dataAfter();
128 try (var keystoreAdapter = new DefaultSslHandlerFactoryProvider(dataBroker)) {
129 // Apply configurations
130 listener.onDataTreeChanged(List.of(dataTreeModification1, dataTreeModification2));
133 final var keyStore = keystoreAdapter.getJavaKeyStore(Set.of());
134 assertTrue(keyStore.containsAlias(privateKey.getName()));
135 assertTrue(keyStore.containsAlias(trustedCertificate.getName()));
139 private static PrivateKey getPrivateKey() throws Exception {
140 final var privateKeys = new ArrayList<PrivateKey>();
141 final var document = readKeystoreXML();
142 final var nodeList = document.getElementsByTagName(XML_ELEMENT_PRIVATE_KEY);
143 for (int i = 0; i < nodeList.getLength(); i++) {
144 if (nodeList.item(i) instanceof Element element) {
145 final var keyName = element.getElementsByTagName(XML_ELEMENT_NAME).item(0).getTextContent();
146 final var keyData = element.getElementsByTagName(XML_ELEMENT_DATA).item(0).getTextContent();
147 final var certNodes = element.getElementsByTagName(XML_ELEMENT_CERT_CHAIN);
148 final var certChain = new ArrayList<String>();
149 for (int j = 0; j < certNodes.getLength(); j++) {
150 if (certNodes.item(j) instanceof Element certNode) {
151 certChain.add(certNode.getTextContent());
155 privateKeys.add(new PrivateKeyBuilder()
156 .withKey(new PrivateKeyKey(keyName))
159 .setCertificateChain(certChain)
164 return privateKeys.get(0);
167 private static TrustedCertificate getTrustedCertificate() throws Exception {
168 final var trustedCertificates = new ArrayList<TrustedCertificate>();
169 final var document = readKeystoreXML();
170 final var nodeList = document.getElementsByTagName(XML_ELEMENT_TRUSTED_CERT);
171 for (int i = 0; i < nodeList.getLength(); i++) {
172 if (nodeList.item(i) instanceof Element element) {
173 final var certName = element.getElementsByTagName(XML_ELEMENT_NAME).item(0).getTextContent();
174 final var certData = element.getElementsByTagName(XML_ELEMENT_CERT).item(0).getTextContent();
176 trustedCertificates.add(new TrustedCertificateBuilder()
177 .withKey(new TrustedCertificateKey(certName))
179 .setCertificate(certData)
184 return trustedCertificates.get(0);
187 private static Document readKeystoreXML() throws Exception {
188 return XmlUtil.readXmlToDocument(
189 DefaultSslHandlerFactoryProviderTest.class.getResourceAsStream("/netconf-keystore.xml"));