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