BUG-1422 Introduce Call-Home functionality for the NETCONF Topology.
[netconf.git] / netconf / callhome-protocol / src / test / java / org / opendaylight / netconf / callhome / protocol / NetconfCallHomeServerTest.java
1 /*
2  * Copyright (c) 2016 Brocade Communication Systems 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
9 package org.opendaylight.netconf.callhome.protocol;
10
11 import static org.junit.Assert.assertFalse;
12 import static org.mockito.Matchers.any;
13 import static org.mockito.Mockito.mock;
14 import static org.mockito.Mockito.times;
15 import static org.mockito.Mockito.verify;
16
17 import java.io.IOException;
18 import java.net.InetSocketAddress;
19 import java.net.SocketAddress;
20 import java.security.PublicKey;
21 import java.util.HashMap;
22 import java.util.Map;
23 import org.apache.sshd.ClientSession;
24 import org.apache.sshd.SshClient;
25 import org.apache.sshd.client.future.AuthFuture;
26 import org.apache.sshd.client.session.ClientSessionImpl;
27 import org.apache.sshd.common.Session;
28 import org.apache.sshd.common.SessionListener;
29 import org.apache.sshd.common.future.SshFutureListener;
30 import org.apache.sshd.common.io.IoAcceptor;
31 import org.apache.sshd.common.io.IoHandler;
32 import org.apache.sshd.common.io.IoServiceFactory;
33 import org.junit.Before;
34 import org.junit.Ignore;
35 import org.junit.Test;
36 import org.mockito.Mockito;
37 import org.slf4j.Logger;
38 import org.slf4j.LoggerFactory;
39
40 public class NetconfCallHomeServerTest {
41
42     SshClient mockSshClient;
43     CallHomeAuthorizationProvider mockCallHomeAuthProv;
44     CallHomeAuthorization mockAuth;
45     CallHomeSessionContext.Factory mockFactory;
46     InetSocketAddress mockAddress;
47     ClientSession mockSession;
48
49     NetconfCallHomeServer instance;
50
51     @Before
52     public void setup() {
53         mockSshClient = Mockito.spy(SshClient.setUpDefaultClient());
54         mockCallHomeAuthProv = mock(CallHomeAuthorizationProvider.class);
55         mockAuth = mock(CallHomeAuthorization.class);
56         mockFactory = mock(CallHomeSessionContext.Factory.class);
57         mockAddress = InetSocketAddress.createUnresolved("1.2.3.4", 123);
58         mockSession = mock(ClientSession.class);
59
60         Map<String,String> props = new HashMap<>();
61         props.put("nio-workers", "1");
62         Mockito.doReturn(props).when(mockSshClient).getProperties();
63         Mockito.doReturn("test").when(mockSession).toString();
64         instance = new NetconfCallHomeServer(mockSshClient, mockCallHomeAuthProv, mockFactory, mockAddress);
65     }
66
67     @Test
68     public void sessionListenerShouldHandleEventsOfKeyEstablishedAndAuthenticated () throws IOException {
69         // Weird - IJ was ok but command line compile failed using the usual array initializer syntax ????
70         SessionListener.Event[] evt = new SessionListener.Event[2];
71         evt[0] = SessionListener.Event.KeyEstablished;
72         evt[1] = SessionListener.Event.Authenticated;
73
74         int[] hitOpen = new int[2];
75         hitOpen[0] = 0;
76         hitOpen[1] = 1;
77
78         int[] hitAuth = new int[2];
79         hitAuth[0] = 1;
80         hitAuth[1] = 0;
81
82         for (int pass = 0; pass < evt.length; pass++)
83         {
84             // given
85             AuthFuture mockAuthFuture = mock(AuthFuture.class);
86             Mockito.doReturn(null).when(mockAuthFuture).addListener(any(SshFutureListener.class));
87             CallHomeSessionContext mockContext = mock(CallHomeSessionContext.class);
88             Mockito.doNothing().when(mockContext).openNetconfChannel();
89             Mockito.doReturn(mockContext).when(mockSession).getAttribute(any(Session.AttributeKey.class));
90             SessionListener listener = instance.createSessionListener();
91             Mockito.doReturn(mockAuthFuture).when(mockContext).authorize();
92             // when
93             listener.sessionEvent(mockSession, evt[pass]);
94             // then
95             verify(mockContext, times(hitOpen[pass])).openNetconfChannel();
96             verify(mockContext, times(hitAuth[pass])).authorize();
97         }
98     }
99
100     @Test
101     public void verificationOfTheServerKeyShouldBeSuccessfulForServerIsAllowed () {
102         // given
103
104         ClientSessionImpl mockClientSession = mock(ClientSessionImpl.class);
105         Mockito.doReturn("test").when(mockClientSession).toString();
106         SocketAddress mockSocketAddr = mock(SocketAddress.class);
107         Mockito.doReturn("testAddr").when(mockSocketAddr).toString();
108         PublicKey mockPublicKey = mock(PublicKey.class);
109
110         CallHomeAuthorization mockAuth = mock(CallHomeAuthorization.class);
111         Mockito.doReturn("test").when(mockAuth).toString();
112         Mockito.doReturn(true).when(mockAuth).isServerAllowed();
113         Mockito.doReturn("some-session-name").when(mockAuth).getSessionName();
114
115         Mockito.doReturn(mockAuth).when(mockCallHomeAuthProv).provideAuth(mockSocketAddr,mockPublicKey);
116
117         Mockito.doReturn(null).when(mockFactory).createIfNotExists(mockClientSession, mockAuth, mockSocketAddr);
118
119         // expect
120         instance.verifyServerKey(mockClientSession, mockSocketAddr, mockPublicKey);
121     }
122
123     @Test
124     public void verificationOfTheServerKeyShouldFailIfTheServerIsNotAllowed () {
125         // given
126
127         ClientSessionImpl mockClientSession = mock(ClientSessionImpl.class);
128         SocketAddress mockSocketAddr = mock(SocketAddress.class);
129         PublicKey mockPublicKey = mock(PublicKey.class);
130
131         Mockito.doReturn(false).when(mockAuth).isServerAllowed();
132         Mockito.doReturn(mockAuth).when(mockCallHomeAuthProv).provideAuth(mockSocketAddr, mockPublicKey);
133         Mockito.doReturn("").when(mockClientSession).toString();
134
135         // expect
136         assertFalse(instance.verifyServerKey(mockClientSession, mockSocketAddr, mockPublicKey));
137     }
138
139     static class TestableCallHomeServer extends NetconfCallHomeServer
140     {
141         static IoServiceFactory minaServiceFactory;
142         static SshClient factoryHook (SshClient client, IoServiceFactory minaFactory)
143         {
144             minaServiceFactory = minaFactory;
145             return client;
146         }
147
148         SshClient client;
149
150         TestableCallHomeServer(SshClient sshClient, CallHomeAuthorizationProvider authProvider,
151                                    CallHomeSessionContext.Factory factory, InetSocketAddress socketAddress,
152                                    IoServiceFactory minaFactory) {
153             super(factoryHook(sshClient, minaFactory), authProvider, factory, socketAddress);
154             client = sshClient;
155         }
156
157         @Override
158         protected IoServiceFactory createMinaServiceFactory(SshClient sshClient)
159         {
160             return minaServiceFactory;
161         }
162     }
163
164     @Test
165     public void bindShouldStartTheClientAndBindTheAddress () throws IOException {
166         // given
167         IoAcceptor mockAcceptor = mock(IoAcceptor.class);
168         IoServiceFactory mockMinaFactory = mock(IoServiceFactory.class);
169
170         Mockito.doReturn(mockAcceptor).when(mockMinaFactory).createAcceptor(any(IoHandler.class));
171         Mockito.doReturn(mockAcceptor).when(mockMinaFactory).createAcceptor(any(IoHandler.class));
172         Mockito.doNothing().when(mockAcceptor).bind(mockAddress);
173         instance = new TestableCallHomeServer(mockSshClient, mockCallHomeAuthProv, mockFactory, mockAddress, mockMinaFactory);
174         // when
175         instance.bind();
176         // then
177         verify(mockSshClient, times(1)).start();
178         verify(mockAcceptor, times(1)).bind(mockAddress);
179     }
180
181 }