blob: f0e93ef59c10c674981bf86858ece9e38122610f [file] [log] [blame]
Ari Saha89831742015-06-26 10:31:48 -07001/*
Brian O'Connor4e33be22017-08-03 22:45:46 -07002 * Copyright 2015-present Open Networking Foundation
Ari Saha89831742015-06-26 10:31:48 -07003 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
Matteo Scandolocf847b82019-04-26 15:00:00 -070016package org.opencord.aaa.impl;
Ari Saha89831742015-06-26 10:31:48 -070017
18import org.junit.After;
19import org.junit.Before;
20import org.junit.Test;
Matteo Scandolobbc1ffb2020-10-16 15:56:20 -070021import org.junit.runner.RunWith;
22import org.junit.runners.Parameterized;
Jonathan Hart5db44532018-07-12 18:13:54 -070023import org.onlab.junit.TestUtils;
Ray Milkey967776a2015-10-07 14:37:17 -070024import org.onlab.packet.BasePacket;
Ray Milkeyea366452015-09-30 10:56:43 -070025import org.onlab.packet.DeserializationException;
26import org.onlab.packet.EAP;
Ray Milkeyea366452015-09-30 10:56:43 -070027import org.onlab.packet.Ethernet;
Ray Milkeyea366452015-09-30 10:56:43 -070028import org.onlab.packet.IpAddress;
Ray Milkeyea366452015-09-30 10:56:43 -070029import org.onlab.packet.RADIUS;
30import org.onlab.packet.RADIUSAttribute;
Jonathan Hartc41227c2020-01-28 16:56:49 -080031import org.onosproject.cluster.ClusterServiceAdapter;
32import org.onosproject.cluster.LeadershipServiceAdapter;
33import org.onosproject.cluster.NodeId;
Ray Milkeyea366452015-09-30 10:56:43 -070034import org.onosproject.core.CoreServiceAdapter;
Jonathan Hart5db44532018-07-12 18:13:54 -070035import org.onosproject.event.DefaultEventSinkRegistry;
36import org.onosproject.event.Event;
37import org.onosproject.event.EventDeliveryService;
38import org.onosproject.event.EventSink;
Ray Milkeyfcb623d2015-10-01 16:48:18 -070039import org.onosproject.net.config.Config;
40import org.onosproject.net.config.NetworkConfigRegistryAdapter;
Amit Ghoshc9ac1e52017-07-28 12:31:18 +010041import org.onosproject.net.packet.InboundPacket;
Jonathan Hartc41227c2020-01-28 16:56:49 -080042import org.onosproject.store.cluster.messaging.ClusterCommunicationServiceAdapter;
Jonathan Hart9d1ce802020-01-28 10:45:08 -080043import org.onosproject.store.service.TestStorageService;
Matteo Scandolocf847b82019-04-26 15:00:00 -070044import org.opencord.aaa.AaaConfig;
Matteo Scandolo9510e5d2020-09-24 17:31:52 -070045import org.slf4j.Logger;
Ray Milkeyea366452015-09-30 10:56:43 -070046
Jonathan Hart092dfb22015-11-16 23:05:21 -080047import java.net.InetAddress;
48import java.net.UnknownHostException;
Matteo Scandolo9510e5d2020-09-24 17:31:52 -070049import java.util.concurrent.atomic.AtomicReference;
Ray Milkeyea366452015-09-30 10:56:43 -070050
Jonathan Hart5db44532018-07-12 18:13:54 -070051import static com.google.common.base.Preconditions.checkState;
Ray Milkeyea366452015-09-30 10:56:43 -070052import static org.hamcrest.Matchers.is;
53import static org.hamcrest.Matchers.notNullValue;
Jonathan Hart612651f2019-11-25 09:21:43 -080054import static org.hamcrest.Matchers.nullValue;
Ray Milkeyea366452015-09-30 10:56:43 -070055import static org.junit.Assert.assertThat;
Matteo Scandolo9510e5d2020-09-24 17:31:52 -070056import static org.junit.Assert.fail;
57import static org.onosproject.net.intent.TestTools.assertAfter;
58import static org.slf4j.LoggerFactory.getLogger;
Ari Saha89831742015-06-26 10:31:48 -070059
60/**
61 * Set of tests of the ONOS application component.
62 */
Matteo Scandolobbc1ffb2020-10-16 15:56:20 -070063@RunWith(Parameterized.class)
Jonathan Hart092dfb22015-11-16 23:05:21 -080064public class AaaManagerTest extends AaaTestBase {
Ari Saha89831742015-06-26 10:31:48 -070065
Matteo Scandolobbc1ffb2020-10-16 15:56:20 -070066 // Change this to have more run with mvn
67 @Parameterized.Parameters
68 public static Object[][] data() {
69 return new Object[1][0];
70 }
71
Ray Milkey967776a2015-10-07 14:37:17 -070072 static final String BAD_IP_ADDRESS = "198.51.100.0";
Ari Saha89831742015-06-26 10:31:48 -070073
Matteo Scandolo9510e5d2020-09-24 17:31:52 -070074 private final Logger log = getLogger(getClass());
75
Jonathan Hart092dfb22015-11-16 23:05:21 -080076 private AaaManager aaaManager;
kartikey dubeye1545422019-05-22 12:53:45 +000077 private AaaStatisticsManager aaaStatisticsManager;
Ray Milkeyea366452015-09-30 10:56:43 -070078
Jonathan Hart092dfb22015-11-16 23:05:21 -080079 class AaaManagerWithoutRadiusServer extends AaaManager {
Amit Ghoshc9ac1e52017-07-28 12:31:18 +010080 protected void sendRadiusPacket(RADIUS radiusPacket, InboundPacket inPkt) {
Ray Milkey967776a2015-10-07 14:37:17 -070081 savePacket(radiusPacket);
82 }
Ray Milkeyea366452015-09-30 10:56:43 -070083 }
Ray Milkeyea366452015-09-30 10:56:43 -070084 /**
Ray Milkey967776a2015-10-07 14:37:17 -070085 * Mocks the AAAConfig class to force usage of an unroutable address for the
86 * RADIUS server.
Ray Milkeyea366452015-09-30 10:56:43 -070087 */
Jonathan Hart092dfb22015-11-16 23:05:21 -080088 static class MockAaaConfig extends AaaConfig {
Ray Milkeyea366452015-09-30 10:56:43 -070089 @Override
Ray Milkey967776a2015-10-07 14:37:17 -070090 public InetAddress radiusIp() {
Ray Milkeyea366452015-09-30 10:56:43 -070091 try {
Ray Milkey967776a2015-10-07 14:37:17 -070092 return InetAddress.getByName(BAD_IP_ADDRESS);
93 } catch (UnknownHostException ex) {
94 // can't happen
95 throw new IllegalStateException(ex);
Ray Milkeyea366452015-09-30 10:56:43 -070096 }
97 }
98 }
99
Jonathan Hartc41227c2020-01-28 16:56:49 -0800100 static final class TestLeadershipService extends LeadershipServiceAdapter {
101 @Override
102 public NodeId getLeader(String path) {
103 return new ClusterServiceAdapter().getLocalNode().id();
104 }
105 }
106
Ray Milkeyea366452015-09-30 10:56:43 -0700107 /**
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700108 * Mocks the network config registry.
109 */
Matteo Scandolo120d40b2020-11-25 15:49:22 -0800110 @SuppressWarnings({"unchecked", "TypeParameterUnusedInFormals"})
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700111 private static final class TestNetworkConfigRegistry
112 extends NetworkConfigRegistryAdapter {
113 @Override
114 public <S, C extends Config<S>> C getConfig(S subject, Class<C> configClass) {
Jonathan Hart092dfb22015-11-16 23:05:21 -0800115 AaaConfig aaaConfig = new MockAaaConfig();
Ray Milkey967776a2015-10-07 14:37:17 -0700116 return (C) aaaConfig;
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700117 }
118 }
119
Jonathan Hart5db44532018-07-12 18:13:54 -0700120 public static class TestEventDispatcher extends DefaultEventSinkRegistry
121 implements EventDeliveryService {
Jonathan Hart5db44532018-07-12 18:13:54 -0700122 @Override
123 @SuppressWarnings("unchecked")
124 public synchronized void post(Event event) {
125 EventSink sink = getSink(event.getClass());
126 checkState(sink != null, "No sink for event %s", event);
127 sink.process(event);
128 }
129
130 @Override
131 public void setDispatchTimeLimit(long millis) {
132 }
133
134 @Override
135 public long getDispatchTimeLimit() {
136 return 0;
137 }
138 }
139
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700140 /**
Ray Milkeyea366452015-09-30 10:56:43 -0700141 * Sets up the services required by the AAA application.
142 */
Ari Saha89831742015-06-26 10:31:48 -0700143 @Before
144 public void setUp() {
Jonathan Hart092dfb22015-11-16 23:05:21 -0800145 aaaManager = new AaaManagerWithoutRadiusServer();
146 aaaManager.netCfgService = new TestNetworkConfigRegistry();
147 aaaManager.coreService = new CoreServiceAdapter();
148 aaaManager.packetService = new MockPacketService();
Amit Ghoshf739be52017-09-21 15:49:37 +0100149 aaaManager.deviceService = new TestDeviceService();
Gamze Abaka1cfdb192018-10-25 11:39:19 +0000150 aaaManager.sadisService = new MockSadisService();
kartikey dubeye1545422019-05-22 12:53:45 +0000151 aaaManager.cfgService = new MockCfgService();
Jonathan Hart9d1ce802020-01-28 10:45:08 -0800152 aaaManager.storageService = new TestStorageService();
kartikey dubeye1545422019-05-22 12:53:45 +0000153 aaaStatisticsManager = new AaaStatisticsManager();
Jonathan Hartc41227c2020-01-28 16:56:49 -0800154 aaaStatisticsManager.storageService = new TestStorageService();
155 aaaStatisticsManager.clusterService = new ClusterServiceAdapter();
156 aaaStatisticsManager.leadershipService = new TestLeadershipService();
157 aaaStatisticsManager.clusterCommunicationService = new ClusterCommunicationServiceAdapter();
Shubham Sharma4900ce62019-06-19 14:18:50 +0000158 aaaManager.radiusOperationalStatusService = new RadiusOperationalStatusManager();
kartikey dubeye1545422019-05-22 12:53:45 +0000159 TestUtils.setField(aaaStatisticsManager, "eventDispatcher", new TestEventDispatcher());
Jonathan Hartc41227c2020-01-28 16:56:49 -0800160 aaaStatisticsManager.activate(new MockComponentContext());
kartikey dubeye1545422019-05-22 12:53:45 +0000161 aaaManager.aaaStatisticsManager = this.aaaStatisticsManager;
Jonathan Hart5db44532018-07-12 18:13:54 -0700162 TestUtils.setField(aaaManager, "eventDispatcher", new TestEventDispatcher());
Matteo Scandolo9510e5d2020-09-24 17:31:52 -0700163
164
kartikey dubeye1545422019-05-22 12:53:45 +0000165 aaaManager.activate(new AaaTestBase.MockComponentContext());
Ari Saha89831742015-06-26 10:31:48 -0700166 }
167
Ray Milkeyea366452015-09-30 10:56:43 -0700168 /**
169 * Tears down the AAA application.
170 */
Ari Saha89831742015-06-26 10:31:48 -0700171 @After
172 public void tearDown() {
kartikey dubeye1545422019-05-22 12:53:45 +0000173 aaaManager.deactivate(new AaaTestBase.MockComponentContext());
Ari Saha89831742015-06-26 10:31:48 -0700174 }
175
Ray Milkeyea366452015-09-30 10:56:43 -0700176 /**
177 * Extracts the RADIUS packet from a packet sent by the supplicant.
178 *
Ray Milkey967776a2015-10-07 14:37:17 -0700179 * @param radius RADIUS packet sent by the supplicant
Ray Milkeyea366452015-09-30 10:56:43 -0700180 * @throws DeserializationException if deserialization of the packet contents
181 * fails.
182 */
Jonathan Hart092dfb22015-11-16 23:05:21 -0800183 private void checkRadiusPacketFromSupplicant(RADIUS radius)
Ray Milkeyea366452015-09-30 10:56:43 -0700184 throws DeserializationException {
Ray Milkeyea366452015-09-30 10:56:43 -0700185 assertThat(radius, notNullValue());
Ray Milkeyea366452015-09-30 10:56:43 -0700186
Ray Milkey967776a2015-10-07 14:37:17 -0700187 EAP eap = radius.decapsulateMessage();
Ray Milkeyea366452015-09-30 10:56:43 -0700188 assertThat(eap, notNullValue());
Ray Milkeyea366452015-09-30 10:56:43 -0700189 }
190
191 /**
192 * Fetches the sent packet at the given index. The requested packet
193 * must be the last packet on the list.
194 *
195 * @param index index into sent packets array
196 * @return packet
197 */
Ray Milkey967776a2015-10-07 14:37:17 -0700198 private BasePacket fetchPacket(int index) {
199 BasePacket packet = savedPackets.get(index);
200 assertThat(packet, notNullValue());
201 return packet;
Ray Milkeyea366452015-09-30 10:56:43 -0700202 }
203
204 /**
205 * Tests the authentication path through the AAA application.
206 *
207 * @throws DeserializationException if packed deserialization fails.
208 */
Ari Saha89831742015-06-26 10:31:48 -0700209 @Test
Jonathan Hart612651f2019-11-25 09:21:43 -0800210 public void testAuthentication() throws Exception {
Ray Milkeyea366452015-09-30 10:56:43 -0700211
212 // (1) Supplicant start up
213
214 Ethernet startPacket = constructSupplicantStartPacket();
215 sendPacket(startPacket);
Matteo Scandolo9510e5d2020-09-24 17:31:52 -0700216 assertAfter(ASSERTION_DELAY, ASSERTION_LENGTH, () -> {
Andrea Campanellac4781e62020-10-08 12:58:45 +0200217 Ethernet responsePacket = (Ethernet) fetchPacket(0);
218 checkRadiusPacket(aaaManager, responsePacket, EAP.ATTR_IDENTITY);
219
220 // (2) Supplicant identify
221
222 Ethernet identifyPacket = null;
223 try {
224 identifyPacket = constructSupplicantIdentifyPacket(null,
225 EAP.ATTR_IDENTITY, (byte) 3, null);
226 } catch (Exception e) {
227 log.error(e.getMessage());
228 fail();
229 }
230 sendPacket(identifyPacket);
231 });
232 assertAfter(ASSERTION_DELAY, ASSERTION_LENGTH, () -> {
233 RADIUS radiusIdentifyPacket = (RADIUS) fetchPacket(1);
234 AtomicReference<Byte> reqId = new AtomicReference<>(radiusIdentifyPacket.getIdentifier());
235
236 try {
237 checkRadiusPacketFromSupplicant(radiusIdentifyPacket);
238 } catch (DeserializationException e) {
239 log.error(e.getMessage());
240 fail();
241 }
242
243 assertThat(radiusIdentifyPacket.getCode(), is(RADIUS.RADIUS_CODE_ACCESS_REQUEST));
244 assertThat(new String(radiusIdentifyPacket.getAttribute(RADIUSAttribute.RADIUS_ATTR_USERNAME).getValue()),
245 is("testuser"));
246
247 IpAddress nasIp =
248 IpAddress.valueOf(IpAddress.Version.INET,
249 radiusIdentifyPacket.getAttribute(RADIUSAttribute.RADIUS_ATTR_NAS_IP)
250 .getValue());
251 assertThat(nasIp.toString(), is(aaaManager.nasIpAddress.getHostAddress()));
252
253 // (3) RADIUS MD5 challenge
254
255 RADIUS radiusCodeAccessChallengePacket =
256 constructRadiusCodeAccessChallengePacket(RADIUS.RADIUS_CODE_ACCESS_CHALLENGE, EAP.ATTR_MD5,
257 reqId.get(), aaaManager.radiusSecret.getBytes());
258 aaaManager.handleRadiusPacket(radiusCodeAccessChallengePacket);
259 });
260 assertAfter(ASSERTION_DELAY, ASSERTION_LENGTH, () -> {
261
262 // State machine should have been created by now
263
264 StateMachine stateMachine = aaaManager.getStateMachine(SESSION_ID);
265 assertThat(stateMachine, notNullValue());
266 assertThat(stateMachine.state(), is(StateMachine.STATE_PENDING));
267
Matteo Scandolo9510e5d2020-09-24 17:31:52 -0700268 Ethernet radiusChallengeMD5Packet = (Ethernet) fetchPacket(2);
269 checkRadiusPacket(aaaManager, radiusChallengeMD5Packet, EAP.ATTR_MD5);
Ray Milkeyea366452015-09-30 10:56:43 -0700270
Matteo Scandolo9510e5d2020-09-24 17:31:52 -0700271 // (4) Supplicant MD5 response
272 try {
273 Ethernet md5RadiusPacket =
274 constructSupplicantIdentifyPacket(stateMachine,
275 EAP.ATTR_MD5,
276 stateMachine.challengeIdentifier(),
277 radiusChallengeMD5Packet);
278 sendPacket(md5RadiusPacket);
279 } catch (Exception e) {
280 log.error(e.getMessage());
281 fail();
282 }
283 });
Andrea Campanellac4781e62020-10-08 12:58:45 +0200284
285 // State machine should have been created by now
286
287 StateMachine stateMachine = aaaManager.getStateMachine(SESSION_ID);
288
Matteo Scandolo9510e5d2020-09-24 17:31:52 -0700289 assertAfter(ASSERTION_DELAY, ASSERTION_LENGTH, () -> {
Andrea Campanellac4781e62020-10-08 12:58:45 +0200290
291
Matteo Scandolo9510e5d2020-09-24 17:31:52 -0700292 RADIUS responseMd5RadiusPacket = (RADIUS) fetchPacket(3);
293 try {
294 checkRadiusPacketFromSupplicant(responseMd5RadiusPacket);
295 } catch (Exception e) {
296 log.error(e.getMessage());
297 fail();
298 }
299 //assertThat(responseMd5RadiusPacket.getIdentifier(), is((byte) 9));
Andrea Campanellac4781e62020-10-08 12:58:45 +0200300 AtomicReference<Byte> reqId = new AtomicReference<>(responseMd5RadiusPacket.getIdentifier());
Matteo Scandolo9510e5d2020-09-24 17:31:52 -0700301 assertThat(responseMd5RadiusPacket.getCode(), is(RADIUS.RADIUS_CODE_ACCESS_REQUEST));
Ray Milkeyea366452015-09-30 10:56:43 -0700302
Matteo Scandolo9510e5d2020-09-24 17:31:52 -0700303 // State machine should be in pending state
Ray Milkey967776a2015-10-07 14:37:17 -0700304
Matteo Scandolo9510e5d2020-09-24 17:31:52 -0700305 assertThat(stateMachine, notNullValue());
306 assertThat(stateMachine.state(), is(StateMachine.STATE_PENDING));
Ray Milkey967776a2015-10-07 14:37:17 -0700307
Matteo Scandolo9510e5d2020-09-24 17:31:52 -0700308 // (5) RADIUS Success
Ray Milkeyea366452015-09-30 10:56:43 -0700309
Matteo Scandolo9510e5d2020-09-24 17:31:52 -0700310 RADIUS successPacket =
311 constructRadiusCodeAccessChallengePacket(RADIUS.RADIUS_CODE_ACCESS_ACCEPT,
312 EAP.SUCCESS, reqId.get(),
313 aaaManager.radiusSecret.getBytes());
314 aaaManager.handleRadiusPacket((successPacket));
315 });
316 assertAfter(ASSERTION_DELAY, ASSERTION_LENGTH, () -> {
317 Ethernet supplicantSuccessPacket = (Ethernet) fetchPacket(4);
Ray Milkeyea366452015-09-30 10:56:43 -0700318
Matteo Scandolo9510e5d2020-09-24 17:31:52 -0700319 checkRadiusPacket(aaaManager, supplicantSuccessPacket, EAP.SUCCESS);
Ray Milkeyea366452015-09-30 10:56:43 -0700320
Matteo Scandolo9510e5d2020-09-24 17:31:52 -0700321 // State machine should be in authorized state
Ray Milkeyea366452015-09-30 10:56:43 -0700322
Matteo Scandolo9510e5d2020-09-24 17:31:52 -0700323 assertThat(stateMachine, notNullValue());
324 assertThat(stateMachine.state(), is(StateMachine.STATE_AUTHORIZED));
325 });
Jonathan Hart612651f2019-11-25 09:21:43 -0800326 }
Ray Milkey967776a2015-10-07 14:37:17 -0700327
Jonathan Hart612651f2019-11-25 09:21:43 -0800328 @Test
329 public void testRemoveAuthentication() {
330 Ethernet startPacket = constructSupplicantStartPacket();
331 sendPacket(startPacket);
Andrea Campanellac4781e62020-10-08 12:58:45 +0200332 assertAfter(ASSERTION_DELAY, ASSERTION_LENGTH, () -> {
333 StateMachine stateMachine = aaaManager.getStateMachine(SESSION_ID);
Jonathan Hart612651f2019-11-25 09:21:43 -0800334
Andrea Campanellac4781e62020-10-08 12:58:45 +0200335 assertThat(stateMachine, notNullValue());
336 assertThat(stateMachine.state(), is(StateMachine.STATE_STARTED));
Jonathan Hart612651f2019-11-25 09:21:43 -0800337
Andrea Campanellac4781e62020-10-08 12:58:45 +0200338 aaaManager.removeAuthenticationStateByMac(stateMachine.supplicantAddress());
Jonathan Hart612651f2019-11-25 09:21:43 -0800339
Andrea Campanellac4781e62020-10-08 12:58:45 +0200340 assertThat(aaaManager.getStateMachine(SESSION_ID), nullValue());
341 });
Ari Saha89831742015-06-26 10:31:48 -0700342 }
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700343
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700344 /**
345 * Tests the default configuration.
346 */
347 @Test
348 public void testConfig() {
Jonathan Hart092dfb22015-11-16 23:05:21 -0800349 assertThat(aaaManager.nasIpAddress.getHostAddress(), is(AaaConfig.DEFAULT_NAS_IP));
350 assertThat(aaaManager.nasMacAddress, is(AaaConfig.DEFAULT_NAS_MAC));
351 assertThat(aaaManager.radiusIpAddress.getHostAddress(), is(BAD_IP_ADDRESS));
352 assertThat(aaaManager.radiusMacAddress, is(AaaConfig.DEFAULT_RADIUS_MAC));
Ray Milkeyfcb623d2015-10-01 16:48:18 -0700353 }
Ari Saha89831742015-06-26 10:31:48 -0700354}