-<configuration scan="true">
+ <configuration scan="true">
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<maxHistory>1</maxHistory>
</rollingPolicy>
+ <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
+ <maxFileSize>10MB</maxFileSize>
+ </triggeringPolicy>
+
<encoder>
<pattern>%date{"yyyy-MM-dd HH:mm:ss.SSS z"} [%thread] %-5level %logger{35} - %msg%n</pattern>
</encoder>
</appender>
-
+ <appender name="audit-file" class="ch.qos.logback.core.FileAppender">
+ <file>logs/audit.log</file>
+ <append>true</append>
+ <encoder>
+ <pattern>%date{"yyyy-MM-dd HH:mm:ss.SSS z"} %msg %n</pattern>
+ </encoder>
+ </appender>
<root level="error">
<appender-ref ref="STDOUT" />
<appender-ref ref="opendaylight.log" />
</root>
<!-- Base log level -->
- <logger name="org.opendaylight" level="INFO"/>
+ <logger name="org.opendaylight.controller" level="INFO"/>
<!-- OSGi logging bridge -->
<logger name="org.opendaylight.controller.logging.bridge" level="WARN"/>
<logger name="org.opendaylight.controller.usermanager" level="INFO"/>
<!-- Web modules -->
<logger name="org.opendaylight.controller.web" level="INFO"/>
-</configuration>
+ <!-- additivity=false ensures analytics data only goes to the analytics log -->
+ <logger name="audit" level="INFO" additivity="false">
+ <appender-ref ref="audit-file"/>
+ </logger>
+</configuration>
\ No newline at end of file
import org.opendaylight.controller.sal.utils.Status;
import org.opendaylight.controller.sal.utils.StatusCode;
import org.opendaylight.controller.usermanager.IUserManager;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
public class NorthboundUtils {
}
};
+ private static final String AUDIT = "audit";
+
+ private static final Logger logger = LoggerFactory.getLogger(AUDIT);
+
// Suppress default constructor for noninstantiability
private NorthboundUtils() {
}
return true;
}
+ public static void auditlog(String moduleName, String user, String action, String resource,
+ String containerName) {
+ String auditMsg = "";
+ String mode = "REST";
+ if (containerName != null) {
+ auditMsg = "Mode: " + mode + " User " + user + " " + action + " " + moduleName + " " + resource + " in container "
+ + containerName;
+ } else {
+ auditMsg = "Mode: " + mode + " User " + user + " " + action + " " + moduleName + " " + resource;
+ }
+ logger.info(auditMsg);
+ }
+
+ public static void auditlog(String moduleName, String user, String action, String resource) {
+ auditlog(moduleName, user, action, resource, null);
+ }
}
}
Status status = frm.addStaticFlow(flowConfig.getValue());
+
if (status.isSuccess()) {
+ NorthboundUtils.auditlog("Flow", username, "added", name, containerName);
return Response.status(Response.Status.CREATED).build();
}
throw new InternalServerErrorException(status.getDescription());
Status status = frm.removeStaticFlow(name, node);
if (status.isSuccess()) {
+ NorthboundUtils.auditlog("Flow", username, "removed", name, containerName);
return Response.ok().build();
}
throw new InternalServerErrorException(status.getDescription());
Status status = frm.toggleStaticFlowStatus(staticFlow);
if (status.isSuccess()) {
+ NorthboundUtils.auditlog("Flow", username, "toggled", name, containerName);
return Response.ok().build();
}
throw new InternalServerErrorException(status.getDescription());
Status status = hostTracker.addStaticHost(networkAddress,
dataLayerAddress, nc, vlan);
if (status.isSuccess()) {
+ NorthboundUtils.auditlog("Static Host", username, "added", networkAddress, containerName);
return Response.status(Response.Status.CREATED).build();
} else if (status.getCode().equals(StatusCode.BADREQUEST)) {
throw new UnsupportedMediaTypeException(status.getDescription());
Status status = hostTracker.removeStaticHost(networkAddress);
if (status.isSuccess()) {
+ NorthboundUtils.auditlog("Static Host", username, "removed", networkAddress, containerName);
return Response.ok().build();
}
throw new InternalServerErrorException(status.getDescription());
@Path("/")
public class StaticRoutingNorthbound {
-
- private String username;
+ private String username;
@Context
public void setSecurityContext(SecurityContext context) {
sRoute.getPrefix(), sRoute.getNextHop());
Status response = staticRouting.addStaticRoute(cfgObject);
if (response.isSuccess()) {
+ NorthboundUtils.auditlog("Static Route", username, "added", name, containerName);
return Response.status(Response.Status.CREATED).build();
}
throw new ResourceConflictException(response.getDescription());
Status status = staticRouting.removeStaticRoute(name);
if (status.isSuccess()) {
+ NorthboundUtils.auditlog("Static Route", username, "removed", name, containerName);
return Response.ok().build();
}
throw new ResourceNotFoundException(status.getDescription());
SubnetConfig cfgObject = new SubnetConfig(subnetName, subnet, new HashSet<String>(0));
Status status = switchManager.addSubnet(cfgObject);
if (status.isSuccess()) {
+ NorthboundUtils.auditlog("Subnet Gateway", username, "added", subnetName, containerName);
return Response.status(Response.Status.CREATED).build();
}
throw new InternalServerErrorException(status.getDescription());
}
Status status = switchManager.removeSubnet(subnetName);
if (status.isSuccess()) {
+ NorthboundUtils.auditlog("Subnet Gateway", username, "removed", subnetName, containerName);
return Response.status(Response.Status.OK).build();
}
throw new InternalServerErrorException(status.getDescription());
for (String s : newPorts) {
Status st = switchManager.addPortsToSubnet(name, s);
successful = successful && st.isSuccess();
+ if(successful){
+ NorthboundUtils.auditlog("Subnet Gateway", username, "added", s +" to "+name, containerName);
+ }
}
}
for (String port : ports) {
st = switchManager.addPortsToSubnet(name, port);
successful = successful && st.isSuccess();
+ if(successful){
+ NorthboundUtils.auditlog("Subnet Gateway", username, "added", st +" to "+name, containerName);
+ }
}
} else if (action.equals("delete")) {
// delete existing ports
for (String port : ports) {
st = switchManager.removePortsFromSubnet(name, port);
successful = successful && st.isSuccess();
+ if(successful){
+ NorthboundUtils.auditlog("Subnet Gateway", username, "removed", st +" from "+name, containerName);
+ }
}
} else {
return Response.status(Response.Status.BAD_REQUEST).build();
nodeProperties.remove(propertyName.toLowerCase());
SwitchConfig newSwitchConfig = new SwitchConfig(node.toString(), nodeProperties);
status = switchManager.updateNodeConfig(newSwitchConfig);
+ if(status.isSuccess()){
+ NorthboundUtils.auditlog("Static Route", username, "updated", nodeId, containerName);
+ }
}
}
return NorthboundUtils.getResponse(status);
.fromStringNoNode(nodeConnectorType, nodeConnectorId, node);
Status ret = switchManager.removeNodeConnectorProp(nc, propertyName);
if (ret.isSuccess()) {
+ NorthboundUtils.auditlog("Node Connector Property", username, "removed", nc + " from " + nodeConnectorId, containerName);
return Response.ok().build();
}
throw new ResourceNotFoundException(ret.getDescription());
Status status = topologyManager.addUserLink(userLinkConfig.getValue());
if (status.isSuccess()) {
+ NorthboundUtils.auditlog("User Link", username, "added", userLinkConfig.getValue().getName(), containerName);
return Response.status(Response.Status.CREATED).build();
}
throw new InternalServerErrorException(status.getDescription());
Status ret = topologyManager.deleteUserLink(name);
if (ret.isSuccess()) {
+ NorthboundUtils.auditlog("User Link", username, "removed", name, containerName);
return Response.ok().build();
}
throw new ResourceNotFoundException(ret.getDescription());
} else {
resultBean.setStatus(true);
resultBean.setMessage("Updated node information successfully");
+ DaylightWebUtil.auditlog("Node", userName, "updated", nodeId + " to "+ nodeName, containerName);
}
} catch (Exception e) {
resultBean.setStatus(false);
if (addStaticRouteResult.isSuccess()) {
result.setStatus(true);
result.setMessage("Static Route saved successfully");
+ DaylightWebUtil.auditlog("Static Route", userName, "added", routeName, containerName);
} else {
result.setStatus(false);
result.setMessage(addStaticRouteResult.getDescription());
resultBean.setMessage(result.getDescription());
break;
}
+ DaylightWebUtil.auditlog("Static Route", userName, "removed", route, containerName);
}
} catch (Exception e) {
resultBean.setStatus(false);
if (result.isSuccess()) {
resultBean.setStatus(true);
resultBean.setMessage("Added gateway address successfully");
+ DaylightWebUtil.auditlog("Subnet Gateway", userName, "added", gatewayName, containerName);
} else {
resultBean.setStatus(false);
resultBean.setMessage(result.getDescription());
resultBean.setMessage(result.getDescription());
break;
}
+ DaylightWebUtil.auditlog("Subnet Gateway", userName, "removed", subnet, containerName);
}
} catch (Exception e) {
resultBean.setStatus(false);
resultBean.setStatus(true);
resultBean
.setMessage("Added ports to subnet gateway address successfully");
+ DaylightWebUtil.auditlog("Ports to Subnet Gateway", userName, "added",nodeId+"/"+ ports, containerName);
} else {
resultBean.setStatus(false);
resultBean.setMessage(result.getDescription());
resultBean.setStatus(true);
resultBean
.setMessage("Deleted port from subnet gateway address successfully");
+ DaylightWebUtil.auditlog("Ports from Subnet Gateway", userName, "removed", nodePort, containerName);
} else {
resultBean.setStatus(false);
resultBean.setMessage(result.getDescription());
if (result.isSuccess()) {
resultBean.setStatus(true);
resultBean.setMessage("SPAN Port added successfully");
+ DaylightWebUtil.auditlog("SPAN Port", userName, "added", cfgObject.getNodeId(), containerName);
} else {
resultBean.setStatus(false);
resultBean.setMessage(result.getDescription());
resultBean.setMessage(result.getDescription());
break;
}
+ DaylightWebUtil.auditlog("SPAN Port", userName, "removed", cfgObject.getNodeId(), containerName);
}
}
} catch (Exception e) {
public class Flows implements IDaylightWeb {
private static final UserLevel AUTH_LEVEL = UserLevel.CONTAINERUSER;
private static final String WEB_NAME = "Flows";
+
private static final String WEB_ID = "flows";
private static final short WEB_ORDER = 2;
Status result = new Status(StatusCode.BADREQUEST, "Invalid request");
if (action.equals("add")) {
result = frm.addStaticFlow(flow);
+ DaylightWebUtil.auditlog("Flow", userName, "added", flow.getName(), containerName);
}
return (result.isSuccess()) ? StatusCode.SUCCESS.toString() : result
}
if (action.equals("remove")) {
result = frm.removeStaticFlow(name, node);
+ if(result.isSuccess()) {
+ DaylightWebUtil.auditlog("Flow", userName, "removed", name, containerName);
+ }
} else if (action.equals("toggle")) {
result = frm.toggleStaticFlowStatus(name, node);
+ if(result.isSuccess()) {
+ DaylightWebUtil.auditlog("Flow", userName, "toggled", name, containerName);
+ }
} else {
result = new Status(StatusCode.BADREQUEST, "Unknown action");
}
@Controller
@RequestMapping("/admin")
public class DaylightWebAdmin {
+
+
+
@RequestMapping("/users")
@ResponseBody
public List<UserConfig> getUsers() {
Status result = (action.equals("add")) ? userManager
.addLocalUser(config) : userManager.removeLocalUser(config);
-
+ if(result.getCode().equals(StatusCode.SUCCESS)) {
+ String userAction=(action.equals("add")) ? "added":"removed";
+ DaylightWebUtil.auditlog("User", request.getUserPrincipal().getName(), userAction, config.getUser());
+ return "Success";
+ }
return result.getDescription();
}
return "Operation not permitted";
}
- return userManager.removeLocalUser(userName).getDescription();
+ Status result = userManager.removeLocalUser(userName);
+ if(result.getCode().equals(StatusCode.SUCCESS)) {
+ DaylightWebUtil.auditlog("User", request.getUserPrincipal().getName(), "removed", userName);
+ return "Success";
+ }
+ return result.getDescription();
}
@RequestMapping(value = "/users/password/{username}", method = RequestMethod.POST)
}
Status status = userManager.changeLocalUserPassword(username, currentPassword, newPassword);
-
+ if(status.isSuccess()){
+ DaylightWebUtil.auditlog("User", request.getUserPrincipal().getName(), "changed password for", username);
+ }
return status;
}
import org.opendaylight.controller.sal.utils.GlobalConstants;
import org.opendaylight.controller.sal.utils.ServiceHelper;
import org.opendaylight.controller.usermanager.IUserManager;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
public class DaylightWebUtil {
+ private static final String AUDIT = "audit";
+ private static final Logger logger = LoggerFactory.getLogger(AUDIT);
+
/**
* Returns the access privilege the user has on the specified container
*
return Privilege.NONE;
}
+
+ public static void auditlog(String moduleName, String user, String action, String resource,
+ String containerName) {
+ String auditMsg = "";
+ String mode = "WEB";
+ if (containerName != null) {
+ auditMsg = "Mode: " + mode + " User " + user + " " + action + " " + moduleName + " " + resource + " in container "
+ + containerName;
+ } else {
+ auditMsg = "Mode: " + mode + " User " + user + " " + action + " " + moduleName + " " + resource;
+ }
+ logger.info(auditMsg);
+ }
+
+ public static void auditlog(String moduleName, String user, String action, String resource) {
+ auditlog(moduleName, user, action, resource, null);
+ }
}
\ No newline at end of file