SEBA-75: AAA app exposes authentication state machine events.
Change-Id: I9a1fbc0c28579f6b347322d6f7fc58635c1a9c8a
diff --git a/src/main/java/org/opencord/aaa/AaaManager.java b/src/main/java/org/opencord/aaa/AaaManager.java
index c9fddc0..120f14f 100755
--- a/src/main/java/org/opencord/aaa/AaaManager.java
+++ b/src/main/java/org/opencord/aaa/AaaManager.java
@@ -20,6 +20,7 @@
import org.apache.felix.scr.annotations.Deactivate;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
+import org.apache.felix.scr.annotations.Service;
import org.onlab.packet.DeserializationException;
import org.onlab.packet.EAP;
import org.onlab.packet.EAPOL;
@@ -30,6 +31,7 @@
import org.onlab.packet.RADIUSAttribute;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreService;
+import org.onosproject.event.AbstractListenerManager;
import org.onosproject.mastership.MastershipService;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DeviceId;
@@ -63,20 +65,19 @@
/**
* AAA application for ONOS.
*/
+@Service
@Component(immediate = true)
-public class
-AaaManager {
+public class AaaManager
+ extends AbstractListenerManager<AuthenticationEvent, AuthenticationEventListener>
+ implements AuthenticationService {
+
private static final String APP_NAME = "org.opencord.aaa";
- // for verbose output
private final Logger log = getLogger(getClass());
- // a list of our dependencies :
- // to register with ONOS as an application - described next
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected CoreService coreService;
- // to receive Packet-in events that we'll respond to
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected PacketService packetService;
@@ -98,7 +99,7 @@
protected InetAddress nasIpAddress;
// self MAC address
- protected static String nasMacAddress;
+ protected String nasMacAddress;
// Parsed RADIUS server addresses
protected InetAddress radiusIpAddress;
@@ -109,9 +110,6 @@
// RADIUS server secret
protected String radiusSecret;
- // NAS Identifier
- protected String nasId;
-
// bindings
protected CustomizationInfo customInfo;
@@ -131,7 +129,7 @@
// "socket" or "packet_out"
private String radiusConnectionType;
- // Object for the spcific type of communication with the RADIUS
+ // Object for the specific type of communication with the RADIUS
// server, socket based or packet_out based
RadiusCommunicator impl = null;
@@ -152,6 +150,8 @@
// Listener for config changes
private final InternalConfigListener cfgListener = new InternalConfigListener();
+ private StateMachineDelegate delegate = new InternalStateMachineDelegate();
+
/**
* Builds an EAPOL packet based on the given parameters.
*
@@ -189,6 +189,7 @@
@Activate
public void activate() {
appId = coreService.registerApplication(APP_NAME);
+ eventDispatcher.addSink(AuthenticationEvent.class, listenerRegistry);
netCfgService.addListener(cfgListener);
netCfgService.registerConfigFactory(factory);
customInfo = new CustomizationInfo(subsService, deviceService);
@@ -202,6 +203,7 @@
StateMachine.initializeMaps();
+ StateMachine.setDelegate(delegate);
impl.initializeLocalState(newCfg);
@@ -216,13 +218,13 @@
@Deactivate
public void deactivate() {
impl.withdrawIntercepts();
- // de-register and null our handler
packetService.removeProcessor(processor);
- processor = null;
netCfgService.removeListener(cfgListener);
+ StateMachine.unsetDelegate(delegate);
StateMachine.destroyMaps();
impl.deactivate();
deviceService.removeListener(deviceListener);
+ eventDispatcher.removeSink(AuthenticationEvent.class);
log.info("Stopped");
}
@@ -441,8 +443,8 @@
switch (eapol.getEapolType()) {
case EAPOL.EAPOL_START:
log.debug("EAP packet: EAPOL_START");
- stateMachine.start();
stateMachine.setSupplicantConnectpoint(inPacket.receivedFrom());
+ stateMachine.start();
//send an EAP Request/Identify to the supplicant
EAP eapPayload = new EAP(EAP.REQUEST, stateMachine.identifier(), EAP.ATTR_IDENTITY, null);
@@ -542,6 +544,19 @@
}
/**
+ * Delegate allowing the StateMachine to notify us of events.
+ */
+ private class InternalStateMachineDelegate implements StateMachineDelegate {
+
+ @Override
+ public void notify(AuthenticationEvent authenticationEvent) {
+ log.info("Auth event {} for {}",
+ authenticationEvent.type(), authenticationEvent.subject());
+ post(authenticationEvent);
+ }
+ }
+
+ /**
* Configuration Listener, handles change in configuration.
*/
private class InternalConfigListener implements NetworkConfigListener {
diff --git a/src/main/java/org/opencord/aaa/AaaResetDeviceCommand.java b/src/main/java/org/opencord/aaa/AaaResetDeviceCommand.java
index f5b4e43..6655fec 100644
--- a/src/main/java/org/opencord/aaa/AaaResetDeviceCommand.java
+++ b/src/main/java/org/opencord/aaa/AaaResetDeviceCommand.java
@@ -20,6 +20,9 @@
import org.onosproject.cli.AbstractShellCommand;
import org.onlab.packet.MacAddress;
+/**
+ * Removes a AAA state machine.
+ */
@Command(scope = "onos", name = "aaa-reset-device",
description = "Resets the authentication state machine for a given device")
public class AaaResetDeviceCommand extends AbstractShellCommand {
diff --git a/src/main/java/org/opencord/aaa/AuthenticationEvent.java b/src/main/java/org/opencord/aaa/AuthenticationEvent.java
new file mode 100644
index 0000000..da02ec2
--- /dev/null
+++ b/src/main/java/org/opencord/aaa/AuthenticationEvent.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2018-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.opencord.aaa;
+
+import org.onosproject.event.AbstractEvent;
+import org.onosproject.net.ConnectPoint;
+
+/**
+ * Event indicating the authentication state of a port has changed.
+ */
+public class AuthenticationEvent extends
+ AbstractEvent<AuthenticationEvent.Type, ConnectPoint> {
+
+ /**
+ * Authentication event type.
+ */
+ public enum Type {
+ /**
+ * Supplicant has started authentication on a port.
+ */
+ STARTED,
+
+ /**
+ * Supplicant has requested authentication on a port.
+ */
+ REQUESTED,
+
+ /**
+ * Authentication request was approved.
+ */
+ APPROVED,
+
+ /**
+ * Authentication request was denied.
+ */
+ DENIED
+ }
+
+ /**
+ * Creates a new authentication event.
+ *
+ * @param type event type
+ * @param connectPoint port
+ */
+ public AuthenticationEvent(Type type, ConnectPoint connectPoint) {
+ super(type, connectPoint);
+ }
+
+}
diff --git a/src/main/java/org/opencord/aaa/AuthenticationEventListener.java b/src/main/java/org/opencord/aaa/AuthenticationEventListener.java
new file mode 100644
index 0000000..87d2e4a
--- /dev/null
+++ b/src/main/java/org/opencord/aaa/AuthenticationEventListener.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2018-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.opencord.aaa;
+
+import org.onosproject.event.EventListener;
+
+/**
+ * Listener for authentication events.
+ */
+public interface AuthenticationEventListener extends
+ EventListener<AuthenticationEvent> {
+}
diff --git a/src/main/java/org/opencord/aaa/AuthenticationService.java b/src/main/java/org/opencord/aaa/AuthenticationService.java
new file mode 100644
index 0000000..82aabbd
--- /dev/null
+++ b/src/main/java/org/opencord/aaa/AuthenticationService.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2018-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.opencord.aaa;
+
+import org.onosproject.event.ListenerService;
+
+/**
+ * Service for interacting with authentication module.
+ */
+public interface AuthenticationService extends
+ ListenerService<AuthenticationEvent, AuthenticationEventListener> {
+}
diff --git a/src/main/java/org/opencord/aaa/StateMachine.java b/src/main/java/org/opencord/aaa/StateMachine.java
index e2a24bc..d888c98 100644
--- a/src/main/java/org/opencord/aaa/StateMachine.java
+++ b/src/main/java/org/opencord/aaa/StateMachine.java
@@ -109,6 +109,8 @@
private static Map<String, StateMachine> sessionIdMap;
private static Map<Integer, StateMachine> identifierMap;
+ private static StateMachineDelegate delegate;
+
public static void initializeMaps() {
sessionIdMap = Maps.newConcurrentMap();
identifierMap = Maps.newConcurrentMap();
@@ -120,6 +122,16 @@
identifierMap = null;
}
+ public static void setDelegate(StateMachineDelegate delagate) {
+ StateMachine.delegate = delagate;
+ }
+
+ public static void unsetDelegate(StateMachineDelegate delegate) {
+ if (StateMachine.delegate == delegate) {
+ StateMachine.delegate = null;
+ }
+ }
+
public static Map<String, StateMachine> sessionIdMap() {
return sessionIdMap;
}
@@ -366,6 +378,10 @@
*/
public void start() throws StateMachineException {
states[currentState].start();
+
+ delegate.notify(new AuthenticationEvent(
+ AuthenticationEvent.Type.STARTED, supplicantConnectpoint));
+
//move to the next state
next(TRANSITION_START);
identifier = this.identifier();
@@ -379,6 +395,10 @@
*/
public void requestAccess() throws StateMachineException {
states[currentState].requestAccess();
+
+ delegate.notify(new AuthenticationEvent(
+ AuthenticationEvent.Type.REQUESTED, supplicantConnectpoint));
+
//move to the next state
next(TRANSITION_REQUEST_ACCESS);
}
@@ -394,7 +414,8 @@
//move to the next state
next(TRANSITION_AUTHORIZE_ACCESS);
- // TODO send state machine change event
+ delegate.notify(new AuthenticationEvent(
+ AuthenticationEvent.Type.APPROVED, supplicantConnectpoint));
// Clear mapping
deleteStateMachineMapping(this);
@@ -410,6 +431,10 @@
states[currentState].radiusDenied();
//move to the next state
next(TRANSITION_DENY_ACCESS);
+
+ delegate.notify(new AuthenticationEvent(
+ AuthenticationEvent.Type.DENIED, supplicantConnectpoint));
+
// Clear mappings
deleteStateMachineMapping(this);
}
diff --git a/src/main/java/org/opencord/aaa/StateMachineDelegate.java b/src/main/java/org/opencord/aaa/StateMachineDelegate.java
new file mode 100644
index 0000000..6546d74
--- /dev/null
+++ b/src/main/java/org/opencord/aaa/StateMachineDelegate.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2018-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.opencord.aaa;
+
+import org.onosproject.store.StoreDelegate;
+
+/**
+ * Delegate for authentication state machine.
+ */
+public interface StateMachineDelegate extends StoreDelegate<AuthenticationEvent> {
+}