Refactor NetconfKeystoreAdapter
[netconf.git] / apps / netconf-topology-impl / src / test / java / org / opendaylight / netconf / topology / impl / NetconfTopologyImplTest.java
1 /*
2  * Copyright (c) 2016 Cisco Systems, Inc. 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.topology.impl;
9
10 import static org.junit.Assert.assertEquals;
11 import static org.junit.Assert.assertFalse;
12 import static org.junit.Assert.assertNotNull;
13 import static org.junit.Assert.assertNull;
14 import static org.junit.Assert.assertTrue;
15 import static org.mockito.Mockito.doReturn;
16 import static org.mockito.Mockito.mock;
17 import static org.mockito.Mockito.spy;
18 import static org.mockito.Mockito.times;
19 import static org.mockito.Mockito.verify;
20 import static org.mockito.Mockito.when;
21
22 import com.google.common.util.concurrent.Futures;
23 import com.google.common.util.concurrent.ListenableFuture;
24 import com.google.common.util.concurrent.MoreExecutors;
25 import io.netty.util.concurrent.EventExecutor;
26 import java.util.Collection;
27 import java.util.HashSet;
28 import org.junit.Before;
29 import org.junit.Test;
30 import org.junit.runner.RunWith;
31 import org.mockito.Mock;
32 import org.mockito.junit.MockitoJUnitRunner;
33 import org.opendaylight.aaa.encrypt.AAAEncryptionService;
34 import org.opendaylight.controller.config.threadpool.ScheduledThreadPool;
35 import org.opendaylight.controller.config.threadpool.ThreadPool;
36 import org.opendaylight.mdsal.binding.api.DataBroker;
37 import org.opendaylight.mdsal.binding.api.DataObjectModification;
38 import org.opendaylight.mdsal.binding.api.DataTreeModification;
39 import org.opendaylight.mdsal.binding.api.RpcProviderService;
40 import org.opendaylight.mdsal.binding.api.WriteTransaction;
41 import org.opendaylight.mdsal.common.api.CommitInfo;
42 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
43 import org.opendaylight.mdsal.dom.api.DOMMountPointService;
44 import org.opendaylight.netconf.client.NetconfClientDispatcher;
45 import org.opendaylight.netconf.client.NetconfClientSessionListener;
46 import org.opendaylight.netconf.client.conf.NetconfClientConfiguration;
47 import org.opendaylight.netconf.client.conf.NetconfReconnectingClientConfiguration;
48 import org.opendaylight.netconf.client.mdsal.api.BaseNetconfSchemas;
49 import org.opendaylight.netconf.client.mdsal.api.NetconfKeystoreAdapter;
50 import org.opendaylight.netconf.client.mdsal.api.SchemaResourceManager;
51 import org.opendaylight.netconf.client.mdsal.impl.DefaultBaseNetconfSchemas;
52 import org.opendaylight.netconf.topology.spi.AbstractNetconfTopology;
53 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Host;
54 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
55 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
56 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.PortNumber;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.device.rev230430.connection.parameters.Protocol.Name;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.device.rev230430.connection.parameters.ProtocolBuilder;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.device.rev230430.credentials.credentials.LoginPasswordBuilder;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev221225.NetconfNodeBuilder;
61 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
62 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
63 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
64 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
65 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyBuilder;
66 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
67 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
68 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeBuilder;
69 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
70 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
71 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.IdentifiableItem;
72 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument;
73 import org.opendaylight.yangtools.yang.common.Decimal64;
74 import org.opendaylight.yangtools.yang.common.Empty;
75 import org.opendaylight.yangtools.yang.common.Uint16;
76 import org.opendaylight.yangtools.yang.common.Uint32;
77 import org.opendaylight.yangtools.yang.parser.api.YangParserException;
78 import org.opendaylight.yangtools.yang.parser.impl.DefaultYangParserFactory;
79
80 @RunWith(MockitoJUnitRunner.StrictStubs.class)
81 public class NetconfTopologyImplTest {
82     private static final NodeId NODE_ID = new NodeId("testing-node");
83     private static final String TOPOLOGY_ID = "testing-topology";
84
85     @Mock
86     private NetconfClientDispatcher mockedClientDispatcher;
87     @Mock
88     private EventExecutor mockedEventExecutor;
89     @Mock
90     private ScheduledThreadPool mockedKeepaliveExecutor;
91     @Mock
92     private ThreadPool mockedProcessingExecutor;
93     @Mock
94     private SchemaResourceManager mockedResourceManager;
95     @Mock
96     private DataBroker dataBroker;
97     @Mock
98     private DOMMountPointService mountPointService;
99     @Mock
100     private AAAEncryptionService encryptionService;
101     @Mock
102     private RpcProviderService rpcProviderService;
103     @Mock
104     private NetconfKeystoreAdapter keystoreAdapter;
105     @Mock
106     private WriteTransaction wtx;
107
108     private TestingNetconfTopologyImpl topology;
109     private TestingNetconfTopologyImpl spyTopology;
110
111     @Before
112     public void setUp() {
113         doReturn(MoreExecutors.newDirectExecutorService()).when(mockedProcessingExecutor).getExecutor();
114         doReturn(wtx).when(dataBroker).newWriteOnlyTransaction();
115         doReturn(CommitInfo.emptyFluentFuture()).when(wtx).commit();
116
117         topology = new TestingNetconfTopologyImpl(TOPOLOGY_ID, mockedClientDispatcher, mockedEventExecutor,
118             mockedKeepaliveExecutor, mockedProcessingExecutor, mockedResourceManager, dataBroker, mountPointService,
119             encryptionService, rpcProviderService, keystoreAdapter);
120         //verify initialization of topology
121         verify(wtx).merge(LogicalDatastoreType.OPERATIONAL, InstanceIdentifier.builder(NetworkTopology.class)
122                 .child(Topology.class, new TopologyKey(new TopologyId(TOPOLOGY_ID))).build(),
123                 new TopologyBuilder().setTopologyId(new TopologyId(TOPOLOGY_ID)).build());
124
125         spyTopology = spy(topology);
126     }
127
128     @Test
129     public void testOnDataTreeChange() {
130         final DataObjectModification<Node> newNode = mock(DataObjectModification.class);
131         when(newNode.getModificationType()).thenReturn(DataObjectModification.ModificationType.WRITE);
132
133         NodeKey key = new NodeKey(NODE_ID);
134         PathArgument pa = IdentifiableItem.of(Node.class, key);
135         when(newNode.getIdentifier()).thenReturn(pa);
136
137         final NodeBuilder nn = new NodeBuilder()
138                 .withKey(key)
139                 .addAugmentation(new NetconfNodeBuilder()
140                     .setHost(new Host(new IpAddress(new Ipv4Address("127.0.0.1"))))
141                     .setPort(new PortNumber(Uint16.valueOf(9999)))
142                     .setReconnectOnChangedSchema(true)
143                     .setDefaultRequestTimeoutMillis(Uint32.valueOf(1000))
144                     .setBetweenAttemptsTimeoutMillis(Uint16.valueOf(100))
145                     .setKeepaliveDelay(Uint32.valueOf(1000))
146                     .setTcpOnly(true)
147                     .setCredentials(new LoginPasswordBuilder()
148                         .setUsername("testuser")
149                         .setPassword("testpassword")
150                         .build())
151                     .build());
152
153         when(newNode.getDataAfter()).thenReturn(nn.build());
154
155         final Collection<DataTreeModification<Node>> changes = new HashSet<>();
156         final DataTreeModification<Node> ch = mock(DataTreeModification.class);
157         when(ch.getRootNode()).thenReturn(newNode);
158         changes.add(ch);
159         spyTopology.onDataTreeChanged(changes);
160         verify(spyTopology).connectNode(NetconfTopologyImpl.getNodeId(pa), nn.build());
161
162         when(newNode.getModificationType()).thenReturn(DataObjectModification.ModificationType.DELETE);
163         spyTopology.onDataTreeChanged(changes);
164         verify(spyTopology).disconnectNode(NetconfTopologyImpl.getNodeId(pa));
165
166         when(newNode.getModificationType()).thenReturn(DataObjectModification.ModificationType.SUBTREE_MODIFIED);
167         spyTopology.onDataTreeChanged(changes);
168
169         //one in previous creating and deleting node and one in updating
170         verify(spyTopology, times(2)).disconnectNode(NetconfTopologyImpl.getNodeId(pa));
171         verify(spyTopology, times(2)).connectNode(NetconfTopologyImpl.getNodeId(pa), nn.build());
172     }
173
174     @Test
175     public void testGetClientConfig() {
176         final NetconfClientSessionListener sessionListener = mock(NetconfClientSessionListener.class);
177         final NetconfNodeBuilder nodeBuilder = new NetconfNodeBuilder()
178                 .setHost(new Host(new IpAddress(new Ipv4Address("127.0.0.1"))))
179                 .setPort(new PortNumber(Uint16.valueOf(9999)))
180                 .setReconnectOnChangedSchema(true)
181                 .setDefaultRequestTimeoutMillis(Uint32.valueOf(1000))
182                 .setBetweenAttemptsTimeoutMillis(Uint16.valueOf(100))
183                 .setKeepaliveDelay(Uint32.valueOf(1000))
184                 .setCredentials(new LoginPasswordBuilder().setUsername("testuser").setPassword("testpassword").build())
185                 .setMaxConnectionAttempts(Uint32.ZERO)
186                 .setSleepFactor(Decimal64.valueOf("1.5"))
187                 .setConnectionTimeoutMillis(Uint32.valueOf(20000));
188
189         final NetconfReconnectingClientConfiguration configuration =
190                 spyTopology.getClientConfig(sessionListener, nodeBuilder.setTcpOnly(true).build(), NODE_ID);
191         assertEquals(NetconfClientConfiguration.NetconfClientProtocol.TCP, configuration.getProtocol());
192         assertNotNull(configuration.getAuthHandler());
193         assertNull(configuration.getSslHandlerFactory());
194
195         final NetconfReconnectingClientConfiguration configuration2 =
196                 spyTopology.getClientConfig(sessionListener, nodeBuilder.setTcpOnly(false).build(), NODE_ID);
197         assertEquals(NetconfClientConfiguration.NetconfClientProtocol.SSH, configuration2.getProtocol());
198         assertNotNull(configuration2.getAuthHandler());
199         assertNull(configuration2.getSslHandlerFactory());
200
201         final NetconfReconnectingClientConfiguration configuration3 =
202                 spyTopology.getClientConfig(sessionListener, nodeBuilder
203                         .setProtocol(new ProtocolBuilder().setName(Name.SSH).build()).build(), NODE_ID);
204         assertEquals(NetconfClientConfiguration.NetconfClientProtocol.SSH, configuration3.getProtocol());
205         assertNotNull(configuration3.getAuthHandler());
206         assertNull(configuration3.getSslHandlerFactory());
207
208         final NetconfReconnectingClientConfiguration configuration4 =
209                 spyTopology.getClientConfig(sessionListener, nodeBuilder
210                         .setProtocol(new ProtocolBuilder().setName(Name.TLS).build()).build(), NODE_ID);
211         assertEquals(NetconfClientConfiguration.NetconfClientProtocol.TLS, configuration4.getProtocol());
212         assertNull(configuration4.getAuthHandler());
213         assertNotNull(configuration4.getSslHandlerFactory());
214     }
215
216     public static class TestingNetconfTopologyImpl extends NetconfTopologyImpl {
217         private static final BaseNetconfSchemas BASE_SCHEMAS;
218
219         static {
220             try {
221                 BASE_SCHEMAS = new DefaultBaseNetconfSchemas(new DefaultYangParserFactory());
222             } catch (YangParserException e) {
223                 throw new ExceptionInInitializerError(e);
224             }
225         }
226
227         public TestingNetconfTopologyImpl(final String topologyId, final NetconfClientDispatcher clientDispatcher,
228                                           final EventExecutor eventExecutor,
229                                           final ScheduledThreadPool keepaliveExecutor,
230                                           final ThreadPool processingExecutor,
231                                           final SchemaResourceManager schemaRepositoryProvider,
232                                           final DataBroker dataBroker, final DOMMountPointService mountPointService,
233                                           final AAAEncryptionService encryptionService,
234                                           final RpcProviderService rpcProviderService,
235                                           final NetconfKeystoreAdapter keystoreAdapter) {
236             super(topologyId, clientDispatcher, eventExecutor, keepaliveExecutor, processingExecutor,
237                 schemaRepositoryProvider, dataBroker, mountPointService, encryptionService, rpcProviderService,
238                 BASE_SCHEMAS, keystoreAdapter, null);
239         }
240
241         @Override
242         public ListenableFuture<Empty> connectNode(final NodeId nodeId, final Node configNode) {
243             return Futures.immediateFuture(Empty.value());
244         }
245
246         @Override
247         public ListenableFuture<Empty> disconnectNode(final NodeId nodeId) {
248             return Futures.immediateFuture(Empty.value());
249         }
250     }
251
252     @Test
253     public void hideCredentialsTest() {
254         final String userName = "admin";
255         final String password = "pa$$word";
256         final Node node = new NodeBuilder()
257                 .addAugmentation(new NetconfNodeBuilder()
258                     .setHost(new Host(new IpAddress(new Ipv4Address("127.0.0.1"))))
259                     .setPort(new PortNumber(Uint16.valueOf(9999)))
260                     .setReconnectOnChangedSchema(true)
261                     .setDefaultRequestTimeoutMillis(Uint32.valueOf(1000))
262                     .setBetweenAttemptsTimeoutMillis(Uint16.valueOf(100))
263                     .setKeepaliveDelay(Uint32.valueOf(1000))
264                     .setTcpOnly(false)
265                     .setProtocol(new ProtocolBuilder().setName(Name.TLS).build())
266                     .setCredentials(new LoginPasswordBuilder()
267                         .setUsername(userName)
268                         .setPassword(password)
269                         .build())
270                     .build())
271                 .setNodeId(NodeId.getDefaultInstance("junos"))
272                 .build();
273         final String transformedNetconfNode = AbstractNetconfTopology.hideCredentials(node);
274         assertTrue(transformedNetconfNode.contains("credentials=***"));
275         assertFalse(transformedNetconfNode.contains(userName));
276         assertFalse(transformedNetconfNode.contains(password));
277     }
278 }