Split out keystore-legacy
[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.doAnswer;
16 import static org.mockito.Mockito.doReturn;
17
18 import java.security.KeyStoreException;
19 import java.util.ArrayList;
20 import java.util.List;
21 import org.junit.jupiter.api.BeforeEach;
22 import org.junit.jupiter.api.Test;
23 import org.junit.jupiter.api.extension.ExtendWith;
24 import org.mockito.Mock;
25 import org.mockito.junit.jupiter.MockitoExtension;
26 import org.opendaylight.mdsal.binding.api.DataBroker;
27 import org.opendaylight.mdsal.binding.api.DataObjectModification;
28 import org.opendaylight.mdsal.binding.api.DataTreeChangeListener;
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
42 @ExtendWith(MockitoExtension.class)
43 class DefaultSslHandlerFactoryProviderTest {
44     private static final String XML_ELEMENT_PRIVATE_KEY = "private-key";
45     private static final String XML_ELEMENT_NAME = "name";
46     private static final String XML_ELEMENT_DATA = "data";
47     private static final String XML_ELEMENT_CERT_CHAIN = "certificate-chain";
48     private static final String XML_ELEMENT_TRUSTED_CERT = "trusted-certificate";
49     private static final String XML_ELEMENT_CERT = "certificate";
50
51     @Mock
52     private DataBroker dataBroker;
53     @Mock
54     private Registration listenerRegistration;
55     @Mock
56     private DataTreeModification<Keystore> dataTreeModification1;
57     @Mock
58     private DataTreeModification<Keystore> dataTreeModification2;
59     @Mock
60     private DataObjectModification<Keystore> keystoreObjectModification1;
61     @Mock
62     private DataObjectModification<Keystore> keystoreObjectModification2;
63     @Mock
64     private DataObjectModification<PrivateKey> privateKeyModification;
65     @Mock
66     private DataObjectModification<TrustedCertificate> trustedCertificateModification;
67
68     private DataTreeChangeListener<Keystore> listener;
69
70     @BeforeEach
71     void beforeEach() {
72         doAnswer(inv -> {
73             listener = inv.getArgument(1);
74             return listenerRegistration;
75         }).when(dataBroker).registerTreeChangeListener(any(), any());
76     }
77
78     @Test
79     void testKeystoreAdapterInit() throws Exception {
80         try (var keystoreAdapter = new DefaultSslHandlerFactoryProvider(dataBroker)) {
81             final var ex = assertThrows(KeyStoreException.class, keystoreAdapter::getJavaKeyStore);
82             assertThat(ex.getMessage(), startsWith("No keystore private key found"));
83         }
84     }
85
86     @Test
87     void testWritePrivateKey() throws Exception {
88         doReturn(keystoreObjectModification1).when(dataTreeModification1).getRootNode();
89         doReturn(List.of(privateKeyModification)).when(keystoreObjectModification1)
90             .getModifiedChildren(PrivateKey.class);
91         doReturn(DataObjectModification.ModificationType.WRITE).when(privateKeyModification).modificationType();
92
93         final var privateKey = getPrivateKey();
94         doReturn(privateKey).when(privateKeyModification).dataAfter();
95
96         try (var keystoreAdapter = new DefaultSslHandlerFactoryProvider(dataBroker)) {
97             listener.onDataTreeChanged(List.of(dataTreeModification1));
98
99             final var keyStore = keystoreAdapter.getJavaKeyStore();
100             assertTrue(keyStore.containsAlias(privateKey.getName()));
101         }
102     }
103
104     @Test
105     void testWritePrivateKeyAndTrustedCertificate() throws Exception {
106         // Prepare PrivateKey configuration
107         doReturn(keystoreObjectModification1).when(dataTreeModification1).getRootNode();
108
109         doReturn(List.of(privateKeyModification)).when(keystoreObjectModification1)
110             .getModifiedChildren(PrivateKey.class);
111         doReturn(DataObjectModification.ModificationType.WRITE).when(privateKeyModification).modificationType();
112
113         final var privateKey = getPrivateKey();
114         doReturn(privateKey).when(privateKeyModification).dataAfter();
115
116         // Prepare TrustedCertificate configuration
117         doReturn(keystoreObjectModification2).when(dataTreeModification2).getRootNode();
118
119         doReturn(List.of()).when(keystoreObjectModification2).getModifiedChildren(PrivateKey.class);
120         doReturn(List.of(trustedCertificateModification)).when(keystoreObjectModification2)
121             .getModifiedChildren(TrustedCertificate.class);
122         doReturn(DataObjectModification.ModificationType.WRITE).when(trustedCertificateModification).modificationType();
123
124         final var trustedCertificate = getTrustedCertificate();
125         doReturn(trustedCertificate).when(trustedCertificateModification).dataAfter();
126
127         try (var keystoreAdapter = new DefaultSslHandlerFactoryProvider(dataBroker)) {
128             // Apply configurations
129             listener.onDataTreeChanged(List.of(dataTreeModification1, dataTreeModification2));
130
131             // Check result
132             final var keyStore = keystoreAdapter.getJavaKeyStore();
133             assertTrue(keyStore.containsAlias(privateKey.getName()));
134             assertTrue(keyStore.containsAlias(trustedCertificate.getName()));
135         }
136     }
137
138     private static PrivateKey getPrivateKey() throws Exception {
139         final var privateKeys = new ArrayList<PrivateKey>();
140         final var document = readKeystoreXML();
141         final var nodeList = document.getElementsByTagName(XML_ELEMENT_PRIVATE_KEY);
142         for (int i = 0; i < nodeList.getLength(); i++) {
143             if (nodeList.item(i) instanceof Element element) {
144                 final var keyName = element.getElementsByTagName(XML_ELEMENT_NAME).item(0).getTextContent();
145                 final var keyData = element.getElementsByTagName(XML_ELEMENT_DATA).item(0).getTextContent();
146                 final var certNodes = element.getElementsByTagName(XML_ELEMENT_CERT_CHAIN);
147                 final var certChain = new ArrayList<String>();
148                 for (int j = 0; j < certNodes.getLength(); j++) {
149                     if (certNodes.item(j) instanceof Element certNode) {
150                         certChain.add(certNode.getTextContent());
151                     }
152                 }
153
154                 privateKeys.add(new PrivateKeyBuilder()
155                     .withKey(new PrivateKeyKey(keyName))
156                     .setName(keyName)
157                     .setData(keyData)
158                     .setCertificateChain(certChain)
159                     .build());
160             }
161         }
162
163         return privateKeys.get(0);
164     }
165
166     private static TrustedCertificate getTrustedCertificate() throws Exception {
167         final var trustedCertificates = new ArrayList<TrustedCertificate>();
168         final var document = readKeystoreXML();
169         final var nodeList = document.getElementsByTagName(XML_ELEMENT_TRUSTED_CERT);
170         for (int i = 0; i < nodeList.getLength(); i++) {
171             if (nodeList.item(i) instanceof Element element) {
172                 final var certName = element.getElementsByTagName(XML_ELEMENT_NAME).item(0).getTextContent();
173                 final var certData = element.getElementsByTagName(XML_ELEMENT_CERT).item(0).getTextContent();
174
175                 trustedCertificates.add(new TrustedCertificateBuilder()
176                     .withKey(new TrustedCertificateKey(certName))
177                     .setName(certName)
178                     .setCertificate(certData)
179                     .build());
180             }
181         }
182
183         return trustedCertificates.get(0);
184     }
185
186     private static Document readKeystoreXML() throws Exception {
187         return XmlUtil.readXmlToDocument(
188             DefaultSslHandlerFactoryProviderTest.class.getResourceAsStream("/netconf-keystore.xml"));
189     }
190 }