aabe79a73073d47b8748f33e1080eead2f0ac037
[netconf.git] / plugins / netconf-client-mdsal / src / test / java / org / opendaylight / netconf / client / mdsal / impl / DefaultSslHandlerFactoryProviderTest.java
1 /*
2  * Copyright (c) 2018 ZTE Corporation. 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.netconf.client.mdsal.impl;
9
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.doReturn;
16 import static org.mockito.Mockito.mock;
17
18 import java.security.KeyStoreException;
19 import java.util.ArrayList;
20 import java.util.List;
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.Registration;
39 import org.w3c.dom.Document;
40 import org.w3c.dom.Element;
41 import org.w3c.dom.Node;
42 import org.w3c.dom.NodeList;
43
44 @RunWith(MockitoJUnitRunner.StrictStubs.class)
45 public class DefaultSslHandlerFactoryProviderTest {
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";
52
53     @Mock
54     private DataBroker dataBroker;
55     @Mock
56     private Registration listenerRegistration;
57
58     @Before
59     public void setUp() {
60         doReturn(listenerRegistration).when(dataBroker)
61             .registerTreeChangeListener(any(DataTreeIdentifier.class), any(DefaultSslHandlerFactoryProvider.class));
62     }
63
64     @Test
65     public void testKeystoreAdapterInit() throws Exception {
66         final DefaultSslHandlerFactoryProvider keystoreAdapter = new DefaultSslHandlerFactoryProvider(dataBroker);
67         final var ex = assertThrows(KeyStoreException.class, keystoreAdapter::getJavaKeyStore);
68         assertThat(ex.getMessage(), startsWith("No keystore private key found"));
69     }
70
71     @SuppressWarnings("unchecked")
72     @Test
73     public void testWritePrivateKey() throws Exception {
74         DataTreeModification<Keystore> dataTreeModification = mock(DataTreeModification.class);
75         DataObjectModification<Keystore> keystoreObjectModification = mock(DataObjectModification.class);
76         doReturn(keystoreObjectModification).when(dataTreeModification).getRootNode();
77
78         DataObjectModification<?> childObjectModification = mock(DataObjectModification.class);
79         doReturn(List.of(childObjectModification)).when(keystoreObjectModification).modifiedChildren();
80         doReturn(PrivateKey.class).when(childObjectModification).dataType();
81
82         doReturn(DataObjectModification.ModificationType.WRITE).when(childObjectModification).modificationType();
83
84         final var privateKey = getPrivateKey();
85         doReturn(privateKey).when(childObjectModification).dataAfter();
86
87         final var keystoreAdapter = new DefaultSslHandlerFactoryProvider(dataBroker);
88         keystoreAdapter.onDataTreeChanged(List.of(dataTreeModification));
89
90         final var keyStore = keystoreAdapter.getJavaKeyStore();
91         assertTrue(keyStore.containsAlias(privateKey.getName()));
92     }
93
94     @SuppressWarnings("unchecked")
95     @Test
96     public void testWritePrivateKeyAndTrustedCertificate() throws Exception {
97         // Prepare PrivateKey configuration
98         DataTreeModification<Keystore> dataTreeModification1 = mock(DataTreeModification.class);
99         DataObjectModification<Keystore> keystoreObjectModification1 = mock(DataObjectModification.class);
100         doReturn(keystoreObjectModification1).when(dataTreeModification1).getRootNode();
101
102         DataObjectModification<?> childObjectModification1 = mock(DataObjectModification.class);
103         doReturn(List.of(childObjectModification1)).when(keystoreObjectModification1).modifiedChildren();
104         doReturn(PrivateKey.class).when(childObjectModification1).dataType();
105
106         doReturn(DataObjectModification.ModificationType.WRITE).when(childObjectModification1).modificationType();
107
108         final var privateKey = getPrivateKey();
109         doReturn(privateKey).when(childObjectModification1).dataAfter();
110
111         // Prepare TrustedCertificate configuration
112         DataTreeModification<Keystore> dataTreeModification2 = mock(DataTreeModification.class);
113         DataObjectModification<Keystore> keystoreObjectModification2 = mock(DataObjectModification.class);
114         doReturn(keystoreObjectModification2).when(dataTreeModification2).getRootNode();
115
116         DataObjectModification<?> childObjectModification2 = mock(DataObjectModification.class);
117         doReturn(List.of(childObjectModification2)).when(keystoreObjectModification2).modifiedChildren();
118         doReturn(TrustedCertificate.class).when(childObjectModification2).dataType();
119
120         doReturn(DataObjectModification.ModificationType.WRITE)
121             .when(childObjectModification2).modificationType();
122
123         final var trustedCertificate = geTrustedCertificate();
124         doReturn(trustedCertificate).when(childObjectModification2).dataAfter();
125
126         // Apply configurations
127         final var keystoreAdapter = new DefaultSslHandlerFactoryProvider(dataBroker);
128         keystoreAdapter.onDataTreeChanged(List.of(dataTreeModification1, dataTreeModification2));
129
130         // Check result
131         final var keyStore = keystoreAdapter.getJavaKeyStore();
132         assertTrue(keyStore.containsAlias(privateKey.getName()));
133         assertTrue(keyStore.containsAlias(trustedCertificate.getName()));
134     }
135
136     private PrivateKey getPrivateKey() throws Exception {
137         final List<PrivateKey> privateKeys = new ArrayList<>();
138         final Document document = readKeystoreXML();
139         final NodeList nodeList = document.getElementsByTagName(XML_ELEMENT_PRIVATE_KEY);
140         for (int i = 0; i < nodeList.getLength(); i++) {
141             final Node node = nodeList.item(i);
142             if (node.getNodeType() != Node.ELEMENT_NODE) {
143                 continue;
144             }
145             final Element element = (Element)node;
146             final String keyName = element.getElementsByTagName(XML_ELEMENT_NAME).item(0).getTextContent();
147             final String keyData = element.getElementsByTagName(XML_ELEMENT_DATA).item(0).getTextContent();
148             final NodeList certNodes = element.getElementsByTagName(XML_ELEMENT_CERT_CHAIN);
149             final List<String> certChain = new ArrayList<>();
150             for (int j = 0; j < certNodes.getLength(); j++) {
151                 final Node certNode = certNodes.item(j);
152                 if (certNode.getNodeType() != Node.ELEMENT_NODE) {
153                     continue;
154                 }
155                 certChain.add(certNode.getTextContent());
156             }
157
158             final PrivateKey privateKey = new PrivateKeyBuilder()
159                     .withKey(new PrivateKeyKey(keyName))
160                     .setName(keyName)
161                     .setData(keyData)
162                     .setCertificateChain(certChain)
163                     .build();
164             privateKeys.add(privateKey);
165         }
166
167         return privateKeys.get(0);
168     }
169
170     private TrustedCertificate geTrustedCertificate() throws Exception {
171         final List<TrustedCertificate> trustedCertificates = new ArrayList<>();
172         final Document document = readKeystoreXML();
173         final NodeList nodeList = document.getElementsByTagName(XML_ELEMENT_TRUSTED_CERT);
174         for (int i = 0; i < nodeList.getLength(); i++) {
175             final Node node = nodeList.item(i);
176             if (node.getNodeType() != Node.ELEMENT_NODE) {
177                 continue;
178             }
179             final Element element = (Element)node;
180             final String certName = element.getElementsByTagName(XML_ELEMENT_NAME).item(0).getTextContent();
181             final String certData = element.getElementsByTagName(XML_ELEMENT_CERT).item(0).getTextContent();
182
183             final TrustedCertificate certificate = new TrustedCertificateBuilder()
184                     .withKey(new TrustedCertificateKey(certName))
185                     .setName(certName)
186                     .setCertificate(certData)
187                     .build();
188             trustedCertificates.add(certificate);
189         }
190
191         return trustedCertificates.get(0);
192     }
193
194     private Document readKeystoreXML() throws Exception {
195         return XmlUtil.readXmlToDocument(getClass().getResourceAsStream("/netconf-keystore.xml"));
196     }
197 }