From af9729aac43f1dd32b77076d757e3052d7a8e87b Mon Sep 17 00:00:00 2001 From: Sapan Shah Date: Wed, 8 May 2013 18:20:30 -0700 Subject: [PATCH] Authorization fixes for Northbound bundles Signed-off-by: Sapan Shah --- opendaylight/northbound/commons/pom.xml | 3 + .../commons/utils/NorthboundUtils.java | 60 ++ .../northbound/flowprogrammer/pom.xml | 5 +- .../northbound/FlowProgrammerNorthbound.java | 202 ++-- opendaylight/northbound/hosttracker/pom.xml | 5 +- .../northbound/HostTrackerNorthbound.java | 189 ++-- opendaylight/northbound/staticrouting/pom.xml | 5 +- .../northbound/StaticRoutingNorthbound.java | 47 +- opendaylight/northbound/statistics/pom.xml | 3 + .../northbound/StatisticsNorthbound.java | 147 ++- opendaylight/northbound/subnets/pom.xml | 5 +- .../northbound/SubnetsNorthboundJAXRS.java | 238 +++-- opendaylight/northbound/switchmanager/pom.xml | 5 +- .../northbound/SwitchNorthbound.java | 890 ++++++++++-------- opendaylight/northbound/topology/pom.xml | 7 +- .../northbound/TopologyNorthboundJAXRS.java | 285 +++--- 16 files changed, 1335 insertions(+), 761 deletions(-) create mode 100644 opendaylight/northbound/commons/src/main/java/org/opendaylight/controller/northbound/commons/utils/NorthboundUtils.java diff --git a/opendaylight/northbound/commons/pom.xml b/opendaylight/northbound/commons/pom.xml index d80d669edf..3756e3d51d 100644 --- a/opendaylight/northbound/commons/pom.xml +++ b/opendaylight/northbound/commons/pom.xml @@ -24,12 +24,15 @@ org.opendaylight.controller.northbound.commons.exception, + org.opendaylight.controller.northbound.commons.utils, org.opendaylight.controller.northbound.commons javax.ws.rs, javax.ws.rs.core, org.opendaylight.controller.sal.utils, + org.opendaylight.controller.sal.authorization, + org.opendaylight.controller.containermanager, org.opendaylight.controller.usermanager, javax.servlet.http, org.slf4j, diff --git a/opendaylight/northbound/commons/src/main/java/org/opendaylight/controller/northbound/commons/utils/NorthboundUtils.java b/opendaylight/northbound/commons/src/main/java/org/opendaylight/controller/northbound/commons/utils/NorthboundUtils.java new file mode 100644 index 0000000000..7069ff041f --- /dev/null +++ b/opendaylight/northbound/commons/src/main/java/org/opendaylight/controller/northbound/commons/utils/NorthboundUtils.java @@ -0,0 +1,60 @@ +package org.opendaylight.controller.northbound.commons.utils; + +import org.opendaylight.controller.containermanager.IContainerAuthorization; +import org.opendaylight.controller.sal.authorization.Privilege; +import org.opendaylight.controller.sal.authorization.UserLevel; +import org.opendaylight.controller.sal.utils.GlobalConstants; +import org.opendaylight.controller.sal.utils.ServiceHelper; +import org.opendaylight.controller.usermanager.IUserManager; + +public class NorthboundUtils { + + + /** + * Returns whether the current user has the required privilege on the + * specified container + * + * @param userName + * The user name + * @param containerName + * The container name + * @param required + * Operation to be performed - READ/WRITE + * @param bundle + * Class from where the function is invoked + * @return The Status of the request, either Success or Unauthorized + */ + public static boolean isAuthorized(String userName, String containerName, + Privilege required,Object bundle) { + + if (containerName.equals(GlobalConstants.DEFAULT.toString())) { + IUserManager auth = (IUserManager) ServiceHelper.getGlobalInstance( + IUserManager.class, bundle); + + switch (required) { + case WRITE: + return (auth.getUserLevel(userName).ordinal() <= UserLevel.NETWORKADMIN.ordinal()); + case READ: + return (auth.getUserLevel(userName).ordinal() <= UserLevel.NETWORKOPERATOR.ordinal()); + default: + return false; + } + + } else { + IContainerAuthorization auth = (IContainerAuthorization) ServiceHelper + .getGlobalInstance(IContainerAuthorization.class, bundle); + + if (auth == null) { + return false; + } + + Privilege current = auth.getResourcePrivilege(userName, + containerName); + if (required.ordinal() > current.ordinal()) { + return false; + } + } + return true; + } + +} diff --git a/opendaylight/northbound/flowprogrammer/pom.xml b/opendaylight/northbound/flowprogrammer/pom.xml index a4ebfa2b64..e28454ffc1 100644 --- a/opendaylight/northbound/flowprogrammer/pom.xml +++ b/opendaylight/northbound/flowprogrammer/pom.xml @@ -41,7 +41,10 @@ org.opendaylight.controller.switchmanager, org.opendaylight.controller.northbound.commons, org.opendaylight.controller.northbound.commons.exception, - com.sun.jersey.spi.container.servlet, + org.opendaylight.controller.northbound.commons.utils, + org.opendaylight.controller.sal.authorization, + org.opendaylight.controller.usermanager, + com.sun.jersey.spi.container.servlet, javax.ws.rs, javax.ws.rs.core, javax.xml.bind.annotation, diff --git a/opendaylight/northbound/flowprogrammer/src/main/java/org/opendaylight/controller/flowprogrammer/northbound/FlowProgrammerNorthbound.java b/opendaylight/northbound/flowprogrammer/src/main/java/org/opendaylight/controller/flowprogrammer/northbound/FlowProgrammerNorthbound.java index ed3abde0ab..99452b4b21 100644 --- a/opendaylight/northbound/flowprogrammer/src/main/java/org/opendaylight/controller/flowprogrammer/northbound/FlowProgrammerNorthbound.java +++ b/opendaylight/northbound/flowprogrammer/src/main/java/org/opendaylight/controller/flowprogrammer/northbound/FlowProgrammerNorthbound.java @@ -1,4 +1,3 @@ - /* * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. * @@ -20,8 +19,10 @@ import javax.ws.rs.PUT; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; +import javax.ws.rs.core.Context; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; +import javax.ws.rs.core.SecurityContext; import javax.xml.bind.JAXBElement; import org.codehaus.enunciate.jaxrs.ResponseCode; @@ -36,6 +37,9 @@ import org.opendaylight.controller.northbound.commons.exception.NotAcceptableExc import org.opendaylight.controller.northbound.commons.exception.ResourceConflictException; import org.opendaylight.controller.northbound.commons.exception.ResourceNotFoundException; import org.opendaylight.controller.northbound.commons.exception.ServiceUnavailableException; +import org.opendaylight.controller.northbound.commons.exception.UnauthorizedException; +import org.opendaylight.controller.northbound.commons.utils.NorthboundUtils; +import org.opendaylight.controller.sal.authorization.Privilege; import org.opendaylight.controller.sal.core.Node; import org.opendaylight.controller.sal.utils.GlobalConstants; import org.opendaylight.controller.sal.utils.ServiceHelper; @@ -44,20 +48,34 @@ import org.opendaylight.controller.switchmanager.ISwitchManager; /** * Flow Configuration Northbound API - * - *

+ * + *
+ *
* Authentication scheme : HTTP Basic
* Authentication realm : opendaylight
* Transport : HTTP and HTTPS
*
- * HTTPS Authentication is disabled by default. Administrator can enable it in tomcat-server.xml after adding - * a proper keystore / SSL certificate from a trusted authority.
- * More info : http://tomcat.apache.org/tomcat-7.0-doc/ssl-howto.html#Configuration - * + * HTTPS Authentication is disabled by default. Administrator can enable it in + * tomcat-server.xml after adding a proper keystore / SSL certificate from a + * trusted authority.
+ * More info : + * http://tomcat.apache.org/tomcat-7.0-doc/ssl-howto.html#Configuration + * */ @Path("/") public class FlowProgrammerNorthbound { + private String username; + + @Context + public void setSecurityContext(SecurityContext context) { + username = context.getUserPrincipal().getName(); + } + + protected String getUserName() { + return username; + } + private IForwardingRulesManager getForwardingRulesManagerService( String containerName) { IContainerManager containerManager = (IContainerManager) ServiceHelper @@ -129,38 +147,51 @@ public class FlowProgrammerNorthbound { /** * Returns a list of Flows configured on the given container - * - * @param containerName Name of the Container. The Container name for the base controller is "default". + * + * @param containerName + * Name of the Container. The Container name for the base + * controller is "default". * @return List of configured flows configured on a given container */ @Path("/{containerName}") @GET - @Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) + @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) @TypeHint(FlowConfigs.class) - @StatusCodes( { + @StatusCodes({ @ResponseCode(code = 200, condition = "Operation successful"), @ResponseCode(code = 404, condition = "The containerName is not found"), @ResponseCode(code = 503, condition = "One or more of Controller Services are unavailable") }) public FlowConfigs getStaticFlows( @PathParam("containerName") String containerName) { - List flowConfigs = getStaticFlowsInternal(containerName, null); + if (!NorthboundUtils.isAuthorized( + getUserName(), containerName, Privilege.READ, this)) { + throw new UnauthorizedException( + "User is not authorized to perform this operation on container " + + containerName); + } + + List flowConfigs = getStaticFlowsInternal(containerName, + null); return new FlowConfigs(flowConfigs); } /** * Returns a list of Flows configured on a Node in a given container - * - * @param containerName Name of the Container. The Container name - * for the base controller is "default". - * @param nodeType Type of the node being programmed - * @param nodeId Node Identifier + * + * @param containerName + * Name of the Container. The Container name for the base + * controller is "default". + * @param nodeType + * Type of the node being programmed + * @param nodeId + * Node Identifier * @return List of configured flows configured on a Node in a container */ @Path("/{containerName}/{nodeType}/{nodeId}") @GET - @Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) + @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) @TypeHint(FlowConfigs.class) - @StatusCodes( { + @StatusCodes({ @ResponseCode(code = 200, condition = "Operation successful"), @ResponseCode(code = 404, condition = "The containerName or nodeId is not found"), @ResponseCode(code = 503, condition = "One or more of Controller Services are unavailable") }) @@ -168,6 +199,12 @@ public class FlowProgrammerNorthbound { @PathParam("containerName") String containerName, @PathParam("nodeType") String nodeType, @PathParam("nodeId") String nodeId) { + if (!NorthboundUtils.isAuthorized( + getUserName(), containerName, Privilege.READ, this)) { + throw new UnauthorizedException( + "User is not authorized to perform this operation on container " + + containerName); + } Node node = Node.fromString(nodeType, nodeId); if (node == null) { throw new ResourceNotFoundException(nodeId + " : " @@ -178,29 +215,38 @@ public class FlowProgrammerNorthbound { } /** - * Returns the flow configuration matching a human-readable name and nodeId on a - * given Container. - * - * @param containerName Name of the Container. The Container name - * for the base controller is "default". - * @param nodeType Type of the node being programmed - * @param nodeId Node Identifier - * @param name Human-readable name for the configured flow. + * Returns the flow configuration matching a human-readable name and nodeId + * on a given Container. + * + * @param containerName + * Name of the Container. The Container name for the base + * controller is "default". + * @param nodeType + * Type of the node being programmed + * @param nodeId + * Node Identifier + * @param name + * Human-readable name for the configured flow. * @return Flow configuration matching the name and nodeId on a Container */ @Path("/{containerName}/{nodeType}/{nodeId}/{name}") @GET - @Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) + @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) @TypeHint(FlowConfig.class) - @StatusCodes( { + @StatusCodes({ @ResponseCode(code = 200, condition = "Operation successful"), @ResponseCode(code = 404, condition = "The containerName or NodeId or Configuration name is not found"), @ResponseCode(code = 503, condition = "One or more of Controller Services are unavailable") }) public FlowConfig getStaticFlow( @PathParam("containerName") String containerName, @PathParam("nodeType") String nodeType, - @PathParam("nodeId") String nodeId, - @PathParam("name") String name) { + @PathParam("nodeId") String nodeId, @PathParam("name") String name) { + if (!NorthboundUtils.isAuthorized( + getUserName(), containerName, Privilege.READ, this)) { + throw new UnauthorizedException( + "User is not authorized to perform this operation on container " + + containerName); + } IForwardingRulesManager frm = getForwardingRulesManagerService(containerName); if (frm == null) { @@ -220,20 +266,25 @@ public class FlowProgrammerNorthbound { /** * Add a flow configuration - * - * @param containerName Name of the Container. The Container name - * for the base controller is "default". - * @param nodeType Type of the node being programmed - * @param nodeId Node Identifier - * @param name Name of the Static Flow configuration - * @param FlowConfig Flow Configuration in JSON or XML format + * + * @param containerName + * Name of the Container. The Container name for the base + * controller is "default". + * @param nodeType + * Type of the node being programmed + * @param nodeId + * Node Identifier + * @param name + * Name of the Static Flow configuration + * @param FlowConfig + * Flow Configuration in JSON or XML format * @return Response as dictated by the HTTP Response Status code */ @Path("/{containerName}/{nodeType}/{nodeId}/{name}") @POST - @Consumes( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) - @StatusCodes( { + @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) + @StatusCodes({ @ResponseCode(code = 201, condition = "Flow Config processed successfully"), @ResponseCode(code = 404, condition = "The Container Name or nodeId or configuration name is not found"), @ResponseCode(code = 406, condition = "Cannot operate on Default Container when other Containers are active"), @@ -247,6 +298,12 @@ public class FlowProgrammerNorthbound { @PathParam(value = "nodeId") String nodeId, @TypeHint(FlowConfig.class) JAXBElement flowConfig) { + if (!NorthboundUtils.isAuthorized( + getUserName(), containerName, Privilege.WRITE, this)) { + throw new UnauthorizedException( + "User is not authorized to perform this operation on container " + + containerName); + } handleDefaultDisabled(containerName); IForwardingRulesManager frm = getForwardingRulesManagerService(containerName); @@ -273,21 +330,25 @@ public class FlowProgrammerNorthbound { /** * Delete a Flow configuration - * + * * DELETE /flows/{containerName}/{nodeType}/{nodeId}/{name} - * - * @param containerName Name of the Container. The Container name - * for the base controller is "default". - * @param nodeType Type of the node being programmed - * @param nodeId Node Identifier - * @param name Name of the Static Flow configuration + * + * @param containerName + * Name of the Container. The Container name for the base + * controller is "default". + * @param nodeType + * Type of the node being programmed + * @param nodeId + * Node Identifier + * @param name + * Name of the Static Flow configuration * @return Response as dictated by the HTTP Response code */ @Path("/{containerName}/{nodeType}/{nodeId}/{name}") @DELETE - @Consumes( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) - @StatusCodes( { + @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) + @StatusCodes({ @ResponseCode(code = 200, condition = "Flow Config deleted successfully"), @ResponseCode(code = 404, condition = "The Container Name or Node-id or Flow Name passed is not found"), @ResponseCode(code = 406, condition = "Cannot operate on Default Container when other Containers are active"), @@ -299,6 +360,12 @@ public class FlowProgrammerNorthbound { @PathParam("nodeType") String nodeType, @PathParam(value = "nodeId") String nodeId) { + if (!NorthboundUtils.isAuthorized( + getUserName(), containerName, Privilege.WRITE, this)) { + throw new UnauthorizedException( + "User is not authorized to perform this operation on container " + + containerName); + } handleDefaultDisabled(containerName); IForwardingRulesManager frm = getForwardingRulesManagerService(containerName); @@ -325,19 +392,23 @@ public class FlowProgrammerNorthbound { /** * Toggle a Flow configuration - * - * @param containerName Name of the Container. The Container name - * for the base controller is "default". - * @param nodeType Type of the node being programmed - * @param nodeId Node Identifier - * @param name Name of the Static Flow configuration + * + * @param containerName + * Name of the Container. The Container name for the base + * controller is "default". + * @param nodeType + * Type of the node being programmed + * @param nodeId + * Node Identifier + * @param name + * Name of the Static Flow configuration * @return Response as dictated by the HTTP Response code */ @Path("/{containerName}/{nodeType}/{nodeId}/{name}") @PUT - @Consumes( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) - @StatusCodes( { + @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) + @StatusCodes({ @ResponseCode(code = 200, condition = "Flow Config deleted successfully"), @ResponseCode(code = 404, condition = "The Container Name or Node-id or Flow Name passed is not found"), @ResponseCode(code = 406, condition = "Cannot operate on Default Container when other Containers are active"), @@ -349,6 +420,13 @@ public class FlowProgrammerNorthbound { @PathParam(value = "nodeId") String nodeId, @PathParam(value = "name") String name) { + if (!NorthboundUtils.isAuthorized( + getUserName(), containerName, Privilege.WRITE, this)) { + throw new UnauthorizedException( + "User is not authorized to perform this operation on container " + + containerName); + } + handleDefaultDisabled(containerName); IForwardingRulesManager frm = getForwardingRulesManagerService(containerName); @@ -374,7 +452,7 @@ public class FlowProgrammerNorthbound { } private Node handleNodeAvailability(String containerName, String nodeType, - String nodeId) { + String nodeId) { Node node = Node.fromString(nodeType, nodeId); if (node == null) { @@ -401,13 +479,13 @@ public class FlowProgrammerNorthbound { IContainerManager containerManager = (IContainerManager) ServiceHelper .getGlobalInstance(IContainerManager.class, this); if (containerManager == null) { - throw new InternalServerErrorException(RestMessages.INTERNALERROR - .toString()); + throw new InternalServerErrorException( + RestMessages.INTERNALERROR.toString()); } if (containerName.equals(GlobalConstants.DEFAULT.toString()) && containerManager.hasNonDefaultContainer()) { - throw new NotAcceptableException(RestMessages.DEFAULTDISABLED - .toString()); + throw new NotAcceptableException( + RestMessages.DEFAULTDISABLED.toString()); } } diff --git a/opendaylight/northbound/hosttracker/pom.xml b/opendaylight/northbound/hosttracker/pom.xml index 5ddab37ff3..374b98418f 100644 --- a/opendaylight/northbound/hosttracker/pom.xml +++ b/opendaylight/northbound/hosttracker/pom.xml @@ -40,11 +40,14 @@ org.opendaylight.controller.sal.utils, org.opendaylight.controller.containermanager, org.opendaylight.controller.switchmanager, + org.opendaylight.controller.usermanager, org.apache.commons.logging, com.sun.jersey.spi.container.servlet, org.opendaylight.controller.northbound.commons, org.opendaylight.controller.northbound.commons.exception, - javax.ws.rs, + org.opendaylight.controller.northbound.commons.utils, + org.opendaylight.controller.sal.authorization, + javax.ws.rs, javax.ws.rs.core, javax.xml.bind.annotation, javax.xml.bind, diff --git a/opendaylight/northbound/hosttracker/src/main/java/org/opendaylight/controller/hosttracker/northbound/HostTrackerNorthbound.java b/opendaylight/northbound/hosttracker/src/main/java/org/opendaylight/controller/hosttracker/northbound/HostTrackerNorthbound.java index 2275ee98da..a9f210e0ec 100644 --- a/opendaylight/northbound/hosttracker/src/main/java/org/opendaylight/controller/hosttracker/northbound/HostTrackerNorthbound.java +++ b/opendaylight/northbound/hosttracker/src/main/java/org/opendaylight/controller/hosttracker/northbound/HostTrackerNorthbound.java @@ -1,4 +1,3 @@ - /* * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. * @@ -11,10 +10,8 @@ package org.opendaylight.controller.hosttracker.northbound; import java.net.InetAddress; import java.net.UnknownHostException; +import java.security.Principal; import java.util.List; -import java.util.Set; - -import javax.servlet.http.HttpServletRequest; import javax.ws.rs.Consumes; import javax.ws.rs.DELETE; import javax.ws.rs.DefaultValue; @@ -24,8 +21,10 @@ import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; +import javax.ws.rs.core.Context; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; +import javax.ws.rs.core.SecurityContext; import org.codehaus.enunciate.jaxrs.ResponseCode; import org.codehaus.enunciate.jaxrs.StatusCodes; @@ -38,7 +37,9 @@ import org.opendaylight.controller.northbound.commons.exception.InternalServerEr import org.opendaylight.controller.northbound.commons.exception.ResourceConflictException; import org.opendaylight.controller.northbound.commons.exception.ResourceNotFoundException; import org.opendaylight.controller.northbound.commons.exception.ServiceUnavailableException; +import org.opendaylight.controller.northbound.commons.exception.UnauthorizedException; import org.opendaylight.controller.northbound.commons.exception.UnsupportedMediaTypeException; +import org.opendaylight.controller.northbound.commons.utils.NorthboundUtils; import org.opendaylight.controller.sal.core.Node; import org.opendaylight.controller.sal.core.NodeConnector; import org.opendaylight.controller.sal.utils.GlobalConstants; @@ -47,26 +48,43 @@ import org.opendaylight.controller.sal.utils.Status; import org.opendaylight.controller.sal.utils.StatusCode; import org.opendaylight.controller.switchmanager.ISwitchManager; +import org.opendaylight.controller.sal.authorization.Privilege; + /** * Host Tracker Northbound REST APIs.
- * This class provides REST APIs to track host location in a network. Host Location is represented by Host node connector - * which is essentially a logical entity that represents a Switch/Port. A host is represented by it's IP-address - * and mac-address. - * - *

+ * This class provides REST APIs to track host location in a network. Host + * Location is represented by Host node connector which is essentially a logical + * entity that represents a Switch/Port. A host is represented by it's + * IP-address and mac-address. + * + *
+ *
* Authentication scheme : HTTP Basic
* Authentication realm : opendaylight
* Transport : HTTP and HTTPS
*
- * HTTPS Authentication is disabled by default. Administrator can enable it in tomcat-server.xml after adding - * a proper keystore / SSL certificate from a trusted authority.
- * More info : http://tomcat.apache.org/tomcat-7.0-doc/ssl-howto.html#Configuration - * + * HTTPS Authentication is disabled by default. Administrator can enable it in + * tomcat-server.xml after adding a proper keystore / SSL certificate from a + * trusted authority.
+ * More info : + * http://tomcat.apache.org/tomcat-7.0-doc/ssl-howto.html#Configuration + * */ @Path("/") public class HostTrackerNorthbound { + private String username; + + @Context + public void setSecurityContext(SecurityContext context) { + username = context.getUserPrincipal().getName(); + } + + protected String getUserName() { + return username; + } + private IfIptoHost getIfIpToHostService(String containerName) { IContainerManager containerManager = (IContainerManager) ServiceHelper .getGlobalInstance(IContainerManager.class, this); @@ -100,21 +118,30 @@ public class HostTrackerNorthbound { } /** - * Returns a list of all Hosts : both configured via PUT API and dynamically learnt on the network. - * - * @param containerName Name of the Container. The Container name for the base controller is "default". + * Returns a list of all Hosts : both configured via PUT API and dynamically + * learnt on the network. + * + * @param containerName + * Name of the Container. The Container name for the base + * controller is "default". * @return List of Active Hosts. */ @Path("/{containerName}") @GET - @Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) + @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) @TypeHint(Hosts.class) - @StatusCodes( { + @StatusCodes({ @ResponseCode(code = 200, condition = "Operation successful"), @ResponseCode(code = 404, condition = "The containerName is not found"), @ResponseCode(code = 503, condition = "One or more of Controller Services are unavailable") }) - public Hosts getActiveHosts( - @PathParam("containerName") String containerName) { + public Hosts getActiveHosts(@PathParam("containerName") String containerName) { + + if (!NorthboundUtils.isAuthorized( + getUserName(), containerName, Privilege.READ, this)) { + throw new UnauthorizedException( + "User is not authorized to perform this operation on container " + + containerName); + } IfIptoHost hostTracker = getIfIpToHostService(containerName); if (hostTracker == null) { throw new ServiceUnavailableException("Host Tracker " @@ -125,21 +152,30 @@ public class HostTrackerNorthbound { } /** - * Returns a list of Hosts that are statically configured and are connected to a NodeConnector that is down. - * - * @param containerName Name of the Container. The Container name for the base controller is "default". + * Returns a list of Hosts that are statically configured and are connected + * to a NodeConnector that is down. + * + * @param containerName + * Name of the Container. The Container name for the base + * controller is "default". * @return List of inactive Hosts. */ @Path("/{containerName}/inactive") @GET - @Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) + @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) @TypeHint(Hosts.class) - @StatusCodes( { + @StatusCodes({ @ResponseCode(code = 200, condition = "Operation successful"), @ResponseCode(code = 404, condition = "The containerName is not found"), @ResponseCode(code = 503, condition = "One or more of Controller Services are unavailable") }) public Hosts getInactiveHosts( @PathParam("containerName") String containerName) { + if (!NorthboundUtils.isAuthorized( + getUserName(), containerName, Privilege.READ, this)) { + throw new UnauthorizedException( + "User is not authorized to perform this operation on container " + + containerName); + } IfIptoHost hostTracker = getIfIpToHostService(containerName); if (hostTracker == null) { throw new ServiceUnavailableException("Host Tracker " @@ -151,16 +187,19 @@ public class HostTrackerNorthbound { /** * Returns a host that matches the IP Address value passed as parameter. - * - * @param containerName Name of the Container. The Container name for the base controller is "default". - * @param networkAddress IP Address being looked up + * + * @param containerName + * Name of the Container. The Container name for the base + * controller is "default". + * @param networkAddress + * IP Address being looked up * @return host that matches the IP Address */ @Path("/{containerName}/{networkAddress}") @GET - @Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) + @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) @TypeHint(HostNodeConnector.class) - @StatusCodes( { + @StatusCodes({ @ResponseCode(code = 200, condition = "Operation successful"), @ResponseCode(code = 404, condition = "The containerName is not found"), @ResponseCode(code = 415, condition = "Invalid IP Address passed in networkAddress parameter"), @@ -168,6 +207,12 @@ public class HostTrackerNorthbound { public HostNodeConnector getHostDetails( @PathParam("containerName") String containerName, @PathParam("networkAddress") String networkAddress) { + if (!NorthboundUtils.isAuthorized( + getUserName(), containerName, Privilege.READ, this)) { + throw new UnauthorizedException( + "User is not authorized to perform this operation on container " + + containerName); + } IfIptoHost hostTracker = getIfIpToHostService(containerName); if (hostTracker == null) { throw new ServiceUnavailableException("Host Tracker " @@ -191,22 +236,31 @@ public class HostTrackerNorthbound { /** * Add a Static Host configuration - * - * @param containerName Name of the Container. The Container name for the base controller is "default". - * @param networkAddress Host IP Address - * @param dataLayerAddress Host L2 data-layer address. - * @param nodeType Node Type as specifid by Node class - * @param nodeId Node Identifier as specifid by Node class - * @param nodeConnectorType Port Type as specified by NodeConnector class - * @param nodeConnectorId Port Identifier as specified by NodeConnector class - * @param vlan Vlan number + * + * @param containerName + * Name of the Container. The Container name for the base + * controller is "default". + * @param networkAddress + * Host IP Address + * @param dataLayerAddress + * Host L2 data-layer address. + * @param nodeType + * Node Type as specifid by Node class + * @param nodeId + * Node Identifier as specifid by Node class + * @param nodeConnectorType + * Port Type as specified by NodeConnector class + * @param nodeConnectorId + * Port Identifier as specified by NodeConnector class + * @param vlan + * Vlan number * @return Response as dictated by the HTTP Response Status code */ @Path("/{containerName}/{networkAddress}") @POST - @Consumes( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) - @StatusCodes( { + @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) + @StatusCodes({ @ResponseCode(code = 201, condition = "Flow Config processed successfully"), @ResponseCode(code = 404, condition = "The Container Name or nodeId or configuration name is not found"), @ResponseCode(code = 406, condition = "Cannot operate on Default Container when other Containers are active"), @@ -222,6 +276,12 @@ public class HostTrackerNorthbound { @QueryParam("nodeConnectorId") String nodeConnectorId, @DefaultValue("0") @QueryParam("vlan") String vlan) { + if (!NorthboundUtils.isAuthorized( + getUserName(), containerName, Privilege.WRITE, this)) { + throw new UnauthorizedException( + "User is not authorized to perform this operation on container " + + containerName); + } handleDefaultDisabled(containerName); IfIptoHost hostTracker = getIfIpToHostService(containerName); @@ -232,8 +292,8 @@ public class HostTrackerNorthbound { Node node = handleNodeAvailability(containerName, nodeType, nodeId); if (node == null) { - throw new InternalServerErrorException(RestMessages.NONODE. - toString()); + throw new InternalServerErrorException( + RestMessages.NONODE.toString()); } try { @@ -242,15 +302,14 @@ public class HostTrackerNorthbound { throw new UnsupportedMediaTypeException(networkAddress + " " + RestMessages.INVALIDADDRESS.toString()); } - NodeConnector nc = NodeConnector.fromStringNoNode(nodeConnectorType, nodeConnectorId, - node); + NodeConnector nc = NodeConnector.fromStringNoNode(nodeConnectorType, + nodeConnectorId, node); if (nc == null) { - throw new ResourceNotFoundException(nodeConnectorType+"|"+nodeConnectorId + " : " - + RestMessages.NONODE.toString()); + throw new ResourceNotFoundException(nodeConnectorType + "|" + + nodeConnectorId + " : " + RestMessages.NONODE.toString()); } Status status = hostTracker.addStaticHost(networkAddress, - dataLayerAddress, - nc, vlan); + dataLayerAddress, nc, vlan); if (status.isSuccess()) { return Response.status(Response.Status.CREATED).build(); } else if (status.getCode().equals(StatusCode.BADREQUEST)) { @@ -261,16 +320,19 @@ public class HostTrackerNorthbound { /** * Delete a Static Host configuration - * - * @param containerName Name of the Container. The Container name for the base controller is "default". - * @param networkAddress IP Address + * + * @param containerName + * Name of the Container. The Container name for the base + * controller is "default". + * @param networkAddress + * IP Address * @return Response as dictated by the HTTP Response code. */ @Path("/{containerName}/{networkAddress}") @DELETE - @Consumes( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) - @StatusCodes( { + @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) + @StatusCodes({ @ResponseCode(code = 200, condition = "Flow Config deleted successfully"), @ResponseCode(code = 404, condition = "The Container Name or Node-id or Flow Name passed is not found"), @ResponseCode(code = 406, condition = "Cannot operate on Default Container when other Containers are active"), @@ -280,7 +342,13 @@ public class HostTrackerNorthbound { public Response deleteFlow( @PathParam(value = "containerName") String containerName, @PathParam(value = "networkAddress") String networkAddress) { - + + if (!NorthboundUtils.isAuthorized( + getUserName(), containerName, Privilege.WRITE, this)) { + throw new UnauthorizedException( + "User is not authorized to perform this operation on container " + + containerName); + } handleDefaultDisabled(containerName); IfIptoHost hostTracker = getIfIpToHostService(containerName); if (hostTracker == null) { @@ -307,18 +375,18 @@ public class HostTrackerNorthbound { IContainerManager containerManager = (IContainerManager) ServiceHelper .getGlobalInstance(IContainerManager.class, this); if (containerManager == null) { - throw new InternalServerErrorException(RestMessages.INTERNALERROR - .toString()); + throw new InternalServerErrorException( + RestMessages.INTERNALERROR.toString()); } if (containerName.equals(GlobalConstants.DEFAULT.toString()) && containerManager.hasNonDefaultContainer()) { - throw new ResourceConflictException(RestMessages.DEFAULTDISABLED - .toString()); + throw new ResourceConflictException( + RestMessages.DEFAULTDISABLED.toString()); } } private Node handleNodeAvailability(String containerName, String nodeType, - String nodeId) { + String nodeId) { Node node = Node.fromString(nodeType, nodeId); if (node == null) { @@ -340,4 +408,5 @@ public class HostTrackerNorthbound { } return node; } + } diff --git a/opendaylight/northbound/staticrouting/pom.xml b/opendaylight/northbound/staticrouting/pom.xml index f0fd323710..3e76e0637f 100644 --- a/opendaylight/northbound/staticrouting/pom.xml +++ b/opendaylight/northbound/staticrouting/pom.xml @@ -40,10 +40,13 @@ org.opendaylight.controller.sal.core, org.opendaylight.controller.sal.utils, org.opendaylight.controller.containermanager, + org.opendaylight.controller.usermanager, com.sun.jersey.spi.container.servlet, org.opendaylight.controller.northbound.commons, org.opendaylight.controller.northbound.commons.exception, - org.slf4j, + org.opendaylight.controller.northbound.commons.utils, + org.opendaylight.controller.sal.authorization, + org.slf4j, javax.ws.rs, javax.ws.rs.core, javax.xml.bind.annotation, diff --git a/opendaylight/northbound/staticrouting/src/main/java/org/opendaylight/controller/forwarding/staticrouting/northbound/StaticRoutingNorthbound.java b/opendaylight/northbound/staticrouting/src/main/java/org/opendaylight/controller/forwarding/staticrouting/northbound/StaticRoutingNorthbound.java index f04c9023b0..c48d7ec026 100644 --- a/opendaylight/northbound/staticrouting/src/main/java/org/opendaylight/controller/forwarding/staticrouting/northbound/StaticRoutingNorthbound.java +++ b/opendaylight/northbound/staticrouting/src/main/java/org/opendaylight/controller/forwarding/staticrouting/northbound/StaticRoutingNorthbound.java @@ -19,8 +19,10 @@ import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; +import javax.ws.rs.core.Context; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; +import javax.ws.rs.core.SecurityContext; import javax.xml.bind.JAXBElement; import org.codehaus.enunciate.jaxrs.ResponseCode; @@ -34,6 +36,9 @@ import org.opendaylight.controller.northbound.commons.exception.InternalServerEr import org.opendaylight.controller.northbound.commons.exception.NotAcceptableException; import org.opendaylight.controller.northbound.commons.exception.ResourceConflictException; import org.opendaylight.controller.northbound.commons.exception.ResourceNotFoundException; +import org.opendaylight.controller.northbound.commons.exception.UnauthorizedException; +import org.opendaylight.controller.northbound.commons.utils.NorthboundUtils; +import org.opendaylight.controller.sal.authorization.Privilege; import org.opendaylight.controller.sal.utils.GlobalConstants; import org.opendaylight.controller.sal.utils.ServiceHelper; import org.opendaylight.controller.sal.utils.Status; @@ -53,6 +58,19 @@ import org.opendaylight.controller.sal.utils.Status; @Path("/") public class StaticRoutingNorthbound { + + private String username; + + @Context + public void setSecurityContext(SecurityContext context) { + username = context.getUserPrincipal().getName(); + } + protected String getUserName() { + return username; + } + + + private List getStaticRoutesInternal(String containerName) { IForwardingStaticRouting staticRouting = (IForwardingStaticRouting) ServiceHelper @@ -90,6 +108,13 @@ public class StaticRoutingNorthbound { @ResponseCode(code = 404, condition = "The containerName passed was not found") }) public StaticRoutes getStaticRoutes( @PathParam("containerName") String containerName) { + + if(!NorthboundUtils.isAuthorized(getUserName(), containerName, + Privilege.WRITE, this)){ + throw new + UnauthorizedException("User is not authorized to perform this operation on container " + + containerName); + } return new StaticRoutes(getStaticRoutesInternal(containerName)); } @@ -110,6 +135,13 @@ public class StaticRoutingNorthbound { public StaticRoute getStaticRoute( @PathParam("containerName") String containerName, @PathParam("name") String name) { + + if(!NorthboundUtils.isAuthorized(getUserName(), containerName, + Privilege.WRITE, this)){ + throw new + UnauthorizedException("User is not authorized to perform this operation on container " + + containerName); + } List routes = this.getStaticRoutesInternal(containerName); for (StaticRoute route : routes) { if (route.getName().equalsIgnoreCase(name)) { @@ -142,6 +174,13 @@ public class StaticRoutingNorthbound { @PathParam(value = "name") String name, @TypeHint(StaticRoute.class) JAXBElement staticRouteData) { + + if(!NorthboundUtils.isAuthorized(getUserName(), containerName, + Privilege.WRITE, this)){ + throw new + UnauthorizedException("User is not authorized to perform this operation on container " + + containerName); + } handleDefaultDisabled(containerName); IForwardingStaticRouting staticRouting = (IForwardingStaticRouting) ServiceHelper @@ -182,7 +221,13 @@ public class StaticRoutingNorthbound { public Response removeStaticRoute( @PathParam(value = "containerName") String containerName, @PathParam(value = "name") String name) { - + + if(!NorthboundUtils.isAuthorized(getUserName(), containerName, + Privilege.WRITE, this)){ + throw new + UnauthorizedException("User is not authorized to perform this operation on container " + + containerName); + } handleDefaultDisabled(containerName); IForwardingStaticRouting staticRouting = (IForwardingStaticRouting) ServiceHelper diff --git a/opendaylight/northbound/statistics/pom.xml b/opendaylight/northbound/statistics/pom.xml index 84c4020369..326c9324fb 100644 --- a/opendaylight/northbound/statistics/pom.xml +++ b/opendaylight/northbound/statistics/pom.xml @@ -46,11 +46,14 @@ org.opendaylight.controller.sal.utils, org.opendaylight.controller.containermanager, org.opendaylight.controller.statisticsmanager, + org.opendaylight.controller.usermanager, org.opendaylight.controller.switchmanager, + org.opendaylight.controller.sal.authorization, org.apache.commons.logging, com.sun.jersey.spi.container.servlet, org.opendaylight.controller.northbound.commons, org.opendaylight.controller.northbound.commons.exception, + org.opendaylight.controller.northbound.commons.utils, javax.ws.rs, javax.ws.rs.core, javax.xml.bind.annotation, diff --git a/opendaylight/northbound/statistics/src/main/java/org/opendaylight/controller/statistics/northbound/StatisticsNorthbound.java b/opendaylight/northbound/statistics/src/main/java/org/opendaylight/controller/statistics/northbound/StatisticsNorthbound.java index 651cb2dad3..5cddc663c6 100644 --- a/opendaylight/northbound/statistics/src/main/java/org/opendaylight/controller/statistics/northbound/StatisticsNorthbound.java +++ b/opendaylight/northbound/statistics/src/main/java/org/opendaylight/controller/statistics/northbound/StatisticsNorthbound.java @@ -15,7 +15,9 @@ import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; +import javax.ws.rs.core.Context; import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.SecurityContext; import org.codehaus.enunciate.jaxrs.ResponseCode; import org.codehaus.enunciate.jaxrs.StatusCodes; @@ -23,10 +25,9 @@ import org.codehaus.enunciate.jaxrs.TypeHint; import org.opendaylight.controller.containermanager.IContainerManager; import org.opendaylight.controller.northbound.commons.RestMessages; -import org.opendaylight.controller.northbound.commons.exception.InternalServerErrorException; -import org.opendaylight.controller.northbound.commons.exception.ResourceConflictException; -import org.opendaylight.controller.northbound.commons.exception.ResourceNotFoundException; -import org.opendaylight.controller.northbound.commons.exception.ServiceUnavailableException; +import org.opendaylight.controller.northbound.commons.exception.*; +import org.opendaylight.controller.northbound.commons.utils.NorthboundUtils; +import org.opendaylight.controller.sal.authorization.Privilege; import org.opendaylight.controller.sal.core.Node; import org.opendaylight.controller.sal.reader.FlowOnNode; import org.opendaylight.controller.sal.reader.NodeConnectorStatistics; @@ -36,21 +37,36 @@ import org.opendaylight.controller.statisticsmanager.IStatisticsManager; import org.opendaylight.controller.switchmanager.ISwitchManager; /** - * Northbound APIs that returns various Statistics exposed by the Southbound plugins such as Openflow. + * Northbound APIs that returns various Statistics exposed by the Southbound + * plugins such as Openflow. * - *

+ *
+ *
* Authentication scheme : HTTP Basic
* Authentication realm : opendaylight
* Transport : HTTP and HTTPS
*
- * HTTPS Authentication is disabled by default. Administrator can enable it in tomcat-server.xml after adding - * a proper keystore / SSL certificate from a trusted authority.
- * More info : http://tomcat.apache.org/tomcat-7.0-doc/ssl-howto.html#Configuration - * + * HTTPS Authentication is disabled by default. Administrator can enable it in + * tomcat-server.xml after adding a proper keystore / SSL certificate from a + * trusted authority.
+ * More info : + * http://tomcat.apache.org/tomcat-7.0-doc/ssl-howto.html#Configuration + * */ @Path("/") public class StatisticsNorthbound { + private String username; + + @Context + public void setSecurityContext(SecurityContext context) { + username = context.getUserPrincipal().getName(); + } + + protected String getUserName() { + return username; + } + private IStatisticsManager getStatisticsService(String containerName) { IContainerManager containerManager = (IContainerManager) ServiceHelper .getGlobalInstance(IContainerManager.class, this); @@ -85,21 +101,29 @@ public class StatisticsNorthbound { /** * Returns a list of all Flow Statistics from all the Nodes. - * - * @param containerName Name of the Container. The Container name for the base controller is "default". + * + * @param containerName + * Name of the Container. The Container name for the base + * controller is "default". * @return List of FlowStatistics from all the Nodes */ @Path("/{containerName}/flowstats") @GET - @Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) + @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) @TypeHint(AllFlowStatistics.class) - @StatusCodes( { + @StatusCodes({ @ResponseCode(code = 200, condition = "Operation successful"), @ResponseCode(code = 404, condition = "The containerName is not found"), @ResponseCode(code = 503, condition = "One or more of Controller Services are unavailable") }) public AllFlowStatistics getFlowStatistics( @PathParam("containerName") String containerName) { + if (!NorthboundUtils.isAuthorized( + getUserName(), containerName, Privilege.READ, this)) { + throw new UnauthorizedException( + "User is not authorized to perform this operation on container " + + containerName); + } IStatisticsManager statisticsManager = getStatisticsService(containerName); if (statisticsManager == null) { throw new ServiceUnavailableException("Statistics " @@ -121,8 +145,7 @@ public class StatisticsNorthbound { for (FlowOnNode flowOnSwitch : flows) { flowStats.add(flowOnSwitch); } - FlowStatistics stat = new FlowStatistics(node, - flowStats); + FlowStatistics stat = new FlowStatistics(node, flowStats); statistics.add(stat); } return new AllFlowStatistics(statistics); @@ -130,18 +153,21 @@ public class StatisticsNorthbound { /** * Returns a list of Flow Statistics for a given Node. - * - * @param containerName Name of the Container. The Container name - * for the base controller is "default". - * @param nodeType Node Type as specifid by Node class - * @param nodeId Node Identifier + * + * @param containerName + * Name of the Container. The Container name for the base + * controller is "default". + * @param nodeType + * Node Type as specifid by Node class + * @param nodeId + * Node Identifier * @return List of Flow Statistics for a given Node. */ @Path("/{containerName}/flowstats/{nodeType}/{nodeId}") @GET - @Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) + @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) @TypeHint(FlowStatistics.class) - @StatusCodes( { + @StatusCodes({ @ResponseCode(code = 200, condition = "Operation successful"), @ResponseCode(code = 404, condition = "The containerName is not found"), @ResponseCode(code = 503, condition = "One or more of Controller Services are unavailable") }) @@ -149,7 +175,12 @@ public class StatisticsNorthbound { @PathParam("containerName") String containerName, @PathParam("nodeType") String nodeType, @PathParam("nodeId") String nodeId) { - + if (!NorthboundUtils.isAuthorized( + getUserName(), containerName, Privilege.READ, this)) { + throw new UnauthorizedException( + "User is not authorized to perform this operation on container " + + containerName); + } handleDefaultDisabled(containerName); IStatisticsManager statisticsManager = getStatisticsService(containerName); @@ -170,23 +201,33 @@ public class StatisticsNorthbound { } /** - * Returns a list of all the Port Statistics across all the NodeConnectors on all the Nodes. - * - * @param containerName Name of the Container. The Container name for the base controller is "default". - * @return List of all the Port Statistics across all the NodeConnectors on all the Nodes. + * Returns a list of all the Port Statistics across all the NodeConnectors + * on all the Nodes. + * + * @param containerName + * Name of the Container. The Container name for the base + * controller is "default". + * @return List of all the Port Statistics across all the NodeConnectors on + * all the Nodes. */ @Path("/{containerName}/portstats") @GET - @Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) + @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) @TypeHint(AllPortStatistics.class) - @StatusCodes( { + @StatusCodes({ @ResponseCode(code = 200, condition = "Operation successful"), @ResponseCode(code = 404, condition = "The containerName is not found"), @ResponseCode(code = 503, condition = "One or more of Controller Services are unavailable") }) public AllPortStatistics getPortStatistics( @PathParam("containerName") String containerName) { + if (!NorthboundUtils.isAuthorized( + getUserName(), containerName, Privilege.READ, this)) { + throw new UnauthorizedException( + "User is not authorized to perform this operation on container " + + containerName); + } IStatisticsManager statisticsManager = getStatisticsService(containerName); if (statisticsManager == null) { throw new ServiceUnavailableException("Statistics " @@ -211,19 +252,24 @@ public class StatisticsNorthbound { } /** - * Returns a list of all the Port Statistics across all the NodeConnectors in a given Node. - * - * @param containerName Name of the Container. The Container name - * for the base controller is "default". - * @param nodeType Node Type as specifid by Node class - * @param Node Identifier - * @return Returns a list of all the Port Statistics across all the NodeConnectors in a given Node. + * Returns a list of all the Port Statistics across all the NodeConnectors + * in a given Node. + * + * @param containerName + * Name of the Container. The Container name for the base + * controller is "default". + * @param nodeType + * Node Type as specifid by Node class + * @param Node + * Identifier + * @return Returns a list of all the Port Statistics across all the + * NodeConnectors in a given Node. */ @Path("/{containerName}/portstats/{nodeType}/{nodeId}") @GET - @Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) + @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) @TypeHint(PortStatistics.class) - @StatusCodes( { + @StatusCodes({ @ResponseCode(code = 200, condition = "Operation successful"), @ResponseCode(code = 404, condition = "The containerName is not found"), @ResponseCode(code = 503, condition = "One or more of Controller Services are unavailable") }) @@ -232,6 +278,12 @@ public class StatisticsNorthbound { @PathParam("nodeType") String nodeType, @PathParam("nodeId") String nodeId) { + if (!NorthboundUtils.isAuthorized( + getUserName(), containerName, Privilege.READ, this)) { + throw new UnauthorizedException( + "User is not authorized to perform this operation on container " + + containerName); + } handleDefaultDisabled(containerName); IStatisticsManager statisticsManager = getStatisticsService(containerName); @@ -247,28 +299,27 @@ public class StatisticsNorthbound { + RestMessages.SERVICEUNAVAILABLE.toString()); } - Node node = handleNodeAvailability(containerName, - nodeType, nodeId); - return new PortStatistics(node, statisticsManager - .getNodeConnectorStatistics(node)); + Node node = handleNodeAvailability(containerName, nodeType, nodeId); + return new PortStatistics(node, + statisticsManager.getNodeConnectorStatistics(node)); } private void handleDefaultDisabled(String containerName) { IContainerManager containerManager = (IContainerManager) ServiceHelper .getGlobalInstance(IContainerManager.class, this); if (containerManager == null) { - throw new InternalServerErrorException(RestMessages.INTERNALERROR - .toString()); + throw new InternalServerErrorException( + RestMessages.INTERNALERROR.toString()); } if (containerName.equals(GlobalConstants.DEFAULT.toString()) && containerManager.hasNonDefaultContainer()) { - throw new ResourceConflictException(RestMessages.DEFAULTDISABLED - .toString()); + throw new ResourceConflictException( + RestMessages.DEFAULTDISABLED.toString()); } } private Node handleNodeAvailability(String containerName, String nodeType, - String nodeId) { + String nodeId) { Node node = Node.fromString(nodeType, nodeId); if (node == null) { diff --git a/opendaylight/northbound/subnets/pom.xml b/opendaylight/northbound/subnets/pom.xml index 22c9a97458..3abb1be9c6 100644 --- a/opendaylight/northbound/subnets/pom.xml +++ b/opendaylight/northbound/subnets/pom.xml @@ -57,8 +57,11 @@ org.opendaylight.controller.switchmanager, org.opendaylight.controller.northbound.commons, org.opendaylight.controller.northbound.commons.exception, + org.opendaylight.controller.northbound.commons.utils, com.sun.jersey.spi.container.servlet, - javax.ws.rs, + org.opendaylight.controller.sal.authorization, + org.opendaylight.controller.usermanager, + javax.ws.rs, javax.ws.rs.core, javax.xml.bind.annotation, org.slf4j, diff --git a/opendaylight/northbound/subnets/src/main/java/org/opendaylight/controller/subnets/northbound/SubnetsNorthboundJAXRS.java b/opendaylight/northbound/subnets/src/main/java/org/opendaylight/controller/subnets/northbound/SubnetsNorthboundJAXRS.java index 1e5336257d..05bb5b1dd9 100644 --- a/opendaylight/northbound/subnets/src/main/java/org/opendaylight/controller/subnets/northbound/SubnetsNorthboundJAXRS.java +++ b/opendaylight/northbound/subnets/src/main/java/org/opendaylight/controller/subnets/northbound/SubnetsNorthboundJAXRS.java @@ -8,7 +8,6 @@ package org.opendaylight.controller.subnets.northbound; import java.util.ArrayList; -import java.util.List; import javax.ws.rs.DELETE; import javax.ws.rs.GET; @@ -17,8 +16,10 @@ import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; +import javax.ws.rs.core.Context; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; +import javax.ws.rs.core.SecurityContext; import org.codehaus.enunciate.jaxrs.ResponseCode; import org.codehaus.enunciate.jaxrs.StatusCodes; @@ -26,6 +27,9 @@ import org.codehaus.enunciate.jaxrs.TypeHint; import org.opendaylight.controller.northbound.commons.RestMessages; import org.opendaylight.controller.northbound.commons.exception.InternalServerErrorException; import org.opendaylight.controller.northbound.commons.exception.ResourceNotFoundException; +import org.opendaylight.controller.northbound.commons.exception.UnauthorizedException; +import org.opendaylight.controller.northbound.commons.utils.NorthboundUtils; +import org.opendaylight.controller.sal.authorization.Privilege; import org.opendaylight.controller.sal.utils.ServiceHelper; import org.opendaylight.controller.sal.utils.Status; import org.opendaylight.controller.switchmanager.ISwitchManager; @@ -38,60 +42,86 @@ public class SubnetsNorthboundJAXRS { protected static final Logger logger = LoggerFactory .getLogger(SubnetsNorthboundJAXRS.class); + private String username; + + @Context + public void setSecurityContext(SecurityContext context) { + username = context.getUserPrincipal().getName(); + } + + protected String getUserName() { + return username; + } + /** * List all the subnets in a given container - * - * @param containerName container in which we want to query the subnets - * + * + * @param containerName + * container in which we want to query the subnets + * * @return a List of SubnetConfig */ @Path("/{containerName}") @GET - @Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) - @StatusCodes( { @ResponseCode(code = 404, condition = "The containerName passed was not found") }) + @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) + @StatusCodes({ @ResponseCode(code = 404, condition = "The containerName passed was not found") }) @TypeHint(SubnetConfigs.class) public SubnetConfigs listSubnets( @PathParam("containerName") String containerName) { + if (!NorthboundUtils.isAuthorized( + getUserName(), containerName, Privilege.READ, this)) { + throw new UnauthorizedException( + "User is not authorized to perform this operation on container " + + containerName); + } ISwitchManager switchManager = null; switchManager = (ISwitchManager) ServiceHelper.getInstance( ISwitchManager.class, containerName, this); if (switchManager == null) { - throw new ResourceNotFoundException(RestMessages.NOCONTAINER - .toString()); + throw new ResourceNotFoundException( + RestMessages.NOCONTAINER.toString()); } return new SubnetConfigs(switchManager.getSubnetsConfigList()); } /** * List the configuration of a subnet in a given container - * - * @param containerName container in which we want to query the - * subnet - * @param subnetName of the subnet being queried - * + * + * @param containerName + * container in which we want to query the subnet + * @param subnetName + * of the subnet being queried + * * @return a SubnetConfig */ @Path("/{containerName}/{subnetName}") @GET - @Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) - @StatusCodes( { + @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) + @StatusCodes({ @ResponseCode(code = 404, condition = "The containerName passed was not found"), @ResponseCode(code = 404, condition = "Subnet does not exist") }) @TypeHint(SubnetConfig.class) public SubnetConfig listSubnet( @PathParam("containerName") String containerName, @PathParam("subnetName") String subnetName) { + + if (!NorthboundUtils.isAuthorized( + getUserName(), containerName, Privilege.READ, this)) { + throw new UnauthorizedException( + "User is not authorized to perform this operation on container " + + containerName); + } ISwitchManager switchManager = null; switchManager = (ISwitchManager) ServiceHelper.getInstance( ISwitchManager.class, containerName, this); if (switchManager == null) { - throw new ResourceNotFoundException(RestMessages.NOCONTAINER - .toString()); + throw new ResourceNotFoundException( + RestMessages.NOCONTAINER.toString()); } SubnetConfig res = switchManager.getSubnetConfig(subnetName); if (res == null) { - throw new ResourceNotFoundException(RestMessages.NOSUBNET - .toString()); + throw new ResourceNotFoundException( + RestMessages.NOSUBNET.toString()); } else { return res; } @@ -99,17 +129,19 @@ public class SubnetsNorthboundJAXRS { /** * Add/Update a subnet to a container - * - * @param containerName container in which we want to add/update the - * subnet - * @param subnetName that has to be added - * @param subnet pair default gateway IP/mask that identify the - * subnet being added modified - * + * + * @param containerName + * container in which we want to add/update the subnet + * @param subnetName + * that has to be added + * @param subnet + * pair default gateway IP/mask that identify the subnet being + * added modified + * */ @Path("/{containerName}/{subnetName}") @POST - @StatusCodes( { + @StatusCodes({ @ResponseCode(code = 404, condition = "The containerName passed was not found"), @ResponseCode(code = 404, condition = "Invalid Data passed"), @ResponseCode(code = 201, condition = "Subnet added/modified"), @@ -117,17 +149,27 @@ public class SubnetsNorthboundJAXRS { public Response addSubnet(@PathParam("containerName") String containerName, @PathParam("subnetName") String subnetName, @QueryParam("subnet") String subnet) { + + if (!NorthboundUtils.isAuthorized( + getUserName(), containerName, Privilege.WRITE, this)) { + throw new UnauthorizedException( + "User is not authorized to perform this operation on container " + + containerName); + } if (subnetName == null) { - throw new ResourceNotFoundException(RestMessages.INVALIDDATA.toString()); + throw new ResourceNotFoundException( + RestMessages.INVALIDDATA.toString()); } if (subnet == null) { - throw new ResourceNotFoundException(RestMessages.INVALIDDATA.toString()); + throw new ResourceNotFoundException( + RestMessages.INVALIDDATA.toString()); } ISwitchManager switchManager = null; switchManager = (ISwitchManager) ServiceHelper.getInstance( ISwitchManager.class, containerName, this); if (switchManager == null) { - throw new ResourceNotFoundException(RestMessages.NOCONTAINER.toString()); + throw new ResourceNotFoundException( + RestMessages.NOCONTAINER.toString()); } SubnetConfig cfgObject = new SubnetConfig(subnetName, subnet, @@ -141,30 +183,39 @@ public class SubnetsNorthboundJAXRS { /** * Delete a subnet from a container - * - * @param containerName container in which we want to delete the - * subnet by name - * @param subnetName of the subnet to be remove. - * + * + * @param containerName + * container in which we want to delete the subnet by name + * @param subnetName + * of the subnet to be remove. + * */ @Path("/{containerName}/{subnetName}") @DELETE - @StatusCodes( { + @StatusCodes({ @ResponseCode(code = 404, condition = "The containerName passed was not found"), @ResponseCode(code = 500, condition = "Removal of subnet failed") }) public Response removeSubnet( @PathParam("containerName") String containerName, @PathParam("subnetName") String subnetName) { if (subnetName == null) { - throw new ResourceNotFoundException(RestMessages.INVALIDDATA - .toString()); + throw new ResourceNotFoundException( + RestMessages.INVALIDDATA.toString()); } + + if (!NorthboundUtils.isAuthorized( + getUserName(), containerName, Privilege.WRITE, this)) { + throw new UnauthorizedException( + "User is not authorized to perform this operation on container " + + containerName); + } + ISwitchManager switchManager = null; switchManager = (ISwitchManager) ServiceHelper.getInstance( ISwitchManager.class, containerName, this); if (switchManager == null) { - throw new ResourceNotFoundException(RestMessages.NOCONTAINER - .toString()); + throw new ResourceNotFoundException( + RestMessages.NOCONTAINER.toString()); } Status status = switchManager.removeSubnet(subnetName); if (status.isSuccess()) { @@ -173,58 +224,57 @@ public class SubnetsNorthboundJAXRS { throw new InternalServerErrorException(status.getDescription()); } - /* /\** */ - /* * */ - /* * Add or remove switch ports to a subnet */ - /* * */ - /* * POST subnets/green/sw */ - /* * */ - /* * @param model */ - /* * @param containerName */ - /* * @param name */ - /* * @param subnet: the subnet name name */ - /* * @param switchports: datapath ID/port list => xx:xx:xx:xx:xx:xx:xx:xx/a,b,c-m,r-t,y */ - /* * @return */ - /* *\/ */ - /* @RequestMapping(value = "/{containerName}/{name}", method = RequestMethod.POST) */ - /* public View addSwitchports(Map model, */ - /* @PathVariable(value = "containerName") String containerName, */ - /* @PathVariable(value = "name") String name, */ - /* @RequestParam(value = "nodeports") String nodePorts, */ - /* @RequestParam(value = "action") String action) { */ - - /* checkDefaultDisabled(containerName); */ - - /* ISwitchManager switchManager = null; */ - /* try { */ - /* BundleContext bCtx = FrameworkUtil.getBundle(this.getClass()) */ - /* .getBundleContext(); */ - - /* ServiceReference[] services = bCtx.getServiceReferences( */ - /* ISwitchManager.class.getName(), "(containerName=" */ - /* + containerName + ")"); */ - - /* if (services != null) { */ - /* switchManager = (ISwitchManager) bCtx.getService(services[0]); */ - /* logger.debug("Switch manager reference is:" + switchManager); */ - /* } */ - /* } catch (Exception e) { */ - /* logger.error("Switch Manager reference is NULL"); */ - /* } */ - - /* checkContainerExists(switchManager); */ - - /* String ret; */ - /* if (action.equals("add")) { */ - /* ret = switchManager.addPortsToSubnet(name, nodePorts); */ - /* } else if (action.equals("remove")) { */ - /* ret = switchManager.removePortsFromSubnet(name, nodePorts); */ - /* } else { */ - /* throw new UnsupportedMediaTypeException(RestMessages.UNKNOWNACTION */ - /* .toString() */ - /* + ": " + action); */ - /* } */ - - /* return returnViewOrThrowConflicEx(model, ret); */ - /* } */ + /* + * + * Add or remove switch ports to a subnet POST subnets/green/sw + * + * @param model + * + * @param containerName + * + * @param name + * + * @param subnet: the subnet name name + * + * @param switchports: datapath ID/port list => + * xx:xx:xx:xx:xx:xx:xx:xx/a,b,c-m,r-t,y + * + * @return + * + * @RequestMapping(value = "/{containerName}/{name}", method = + * RequestMethod.POST) + * + * public View addSwitchports(Map model, + * + * @PathVariable(value = "containerName") String containerName, + * + * @PathVariable(value = "name") String name, + * + * @RequestParam(value = "nodeports") String nodePorts, + * + * @RequestParam(value = "action") String action) { + * + * checkDefaultDisabled(containerName); ISwitchManager switchManager = null; + * try { BundleContext bCtx = FrameworkUtil.getBundle(this.getClass()) + * .getBundleContext(); + * + * ServiceReference[] services = bCtx.getServiceReferences( + * ISwitchManager.class.getName(), "(containerName=" + containerName + ")"); + * + * if (services != null) { switchManager = (ISwitchManager) + * bCtx.getService(services[0]); logger.debug("Switch manager reference is:" + * + switchManager); } } catch (Exception e) { + * logger.error("Switch Manager reference is NULL"); } + * + * checkContainerExists(switchManager); + * + * String ret; if (action.equals("add")) { ret = + * switchManager.addPortsToSubnet(name, nodePorts); } else if + * (action.equals("remove")) { ret = + * switchManager.removePortsFromSubnet(name, nodePorts); } else { throw new + * UnsupportedMediaTypeException(RestMessages.UNKNOWNACTION .toString() + + * ": " + action); } + * + * return returnViewOrThrowConflicEx(model, ret); } + */ } diff --git a/opendaylight/northbound/switchmanager/pom.xml b/opendaylight/northbound/switchmanager/pom.xml index 25757e66c4..7a97e176d5 100644 --- a/opendaylight/northbound/switchmanager/pom.xml +++ b/opendaylight/northbound/switchmanager/pom.xml @@ -39,12 +39,15 @@ org.opendaylight.controller.sal.utils, org.opendaylight.controller.containermanager, org.opendaylight.controller.switchmanager, + org.opendaylight.controller.usermanager, org.apache.commons.lang3.tuple, org.apache.commons.logging, com.sun.jersey.spi.container.servlet, org.opendaylight.controller.northbound.commons, org.opendaylight.controller.northbound.commons.exception, - javax.ws.rs, + org.opendaylight.controller.northbound.commons.utils, + org.opendaylight.controller.sal.authorization, + javax.ws.rs, javax.ws.rs.core, javax.xml.bind.annotation, javax.xml.bind, diff --git a/opendaylight/northbound/switchmanager/src/main/java/org/opendaylight/controller/switchmanager/northbound/SwitchNorthbound.java b/opendaylight/northbound/switchmanager/src/main/java/org/opendaylight/controller/switchmanager/northbound/SwitchNorthbound.java index c26d4f26d4..7bdd3f322b 100644 --- a/opendaylight/northbound/switchmanager/src/main/java/org/opendaylight/controller/switchmanager/northbound/SwitchNorthbound.java +++ b/opendaylight/northbound/switchmanager/src/main/java/org/opendaylight/controller/switchmanager/northbound/SwitchNorthbound.java @@ -1,4 +1,3 @@ - /* * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. * @@ -23,8 +22,11 @@ import javax.ws.rs.PUT; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; +import javax.ws.rs.core.Context; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; +import javax.ws.rs.core.SecurityContext; + import org.codehaus.enunciate.jaxrs.ResponseCode; import org.codehaus.enunciate.jaxrs.StatusCodes; import org.codehaus.enunciate.jaxrs.TypeHint; @@ -34,6 +36,9 @@ import org.opendaylight.controller.northbound.commons.exception.InternalServerEr import org.opendaylight.controller.northbound.commons.exception.ResourceConflictException; import org.opendaylight.controller.northbound.commons.exception.ResourceNotFoundException; import org.opendaylight.controller.northbound.commons.exception.ServiceUnavailableException; +import org.opendaylight.controller.northbound.commons.exception.UnauthorizedException; +import org.opendaylight.controller.northbound.commons.utils.NorthboundUtils; +import org.opendaylight.controller.sal.authorization.Privilege; import org.opendaylight.controller.sal.core.MacAddress; import org.opendaylight.controller.sal.core.Node; import org.opendaylight.controller.sal.core.NodeConnector; @@ -52,168 +57,219 @@ import org.opendaylight.controller.switchmanager.ISwitchManager; @Path("/") public class SwitchNorthbound { - private ISwitchManager getIfSwitchManagerService(String containerName) { - IContainerManager containerManager = (IContainerManager) ServiceHelper - .getGlobalInstance(IContainerManager.class, this); - if (containerManager == null) { - throw new ServiceUnavailableException("Container " - + RestMessages.SERVICEUNAVAILABLE.toString()); - } - - boolean found = false; - List containerNames = containerManager.getContainerNames(); - for (String cName : containerNames) { - if (cName.trim().equalsIgnoreCase(containerName.trim())) { - found = true; - } - } - - if (found == false) { - throw new ResourceNotFoundException(containerName + " " - + RestMessages.NOCONTAINER.toString()); - } - - ISwitchManager switchManager = (ISwitchManager) ServiceHelper.getInstance( - ISwitchManager.class, containerName, this); - - if (switchManager == null) { - throw new ServiceUnavailableException("Switch Manager " - + RestMessages.SERVICEUNAVAILABLE.toString()); - } - - return switchManager; - } - - /** - * - * Retrieve a list of all the nodes and their properties in the network - * - * @param containerName The container for which we want to retrieve the list - * @return A list of Pair each pair represents a - * {@link org.opendaylight.controller.sal.core.Node} and Set of - * {@link org.opendaylight.controller.sal.core.Property} attached to - * it. - */ - @Path("/{containerName}/nodes") - @GET - @Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) - @TypeHint(Nodes.class) - @StatusCodes( { - @ResponseCode(code = 200, condition = "Operation successful"), - @ResponseCode(code = 404, condition = "The containerName is not found"), - @ResponseCode(code = 503, condition = "One or more of Controller Services are unavailable") }) - public Nodes getNodes( - @PathParam("containerName") String containerName) { - ISwitchManager switchManager = (ISwitchManager) getIfSwitchManagerService(containerName); - if (switchManager == null) { - throw new ServiceUnavailableException("Switch Manager " - + RestMessages.SERVICEUNAVAILABLE.toString()); - } - - List res = new ArrayList(); - Set nodes = switchManager.getNodes(); - if (nodes == null) { - return null; - } - - byte[] controllerMac = switchManager.getControllerMAC(); - for (Node node : nodes) { - Map propMap = switchManager.getNodeProps(node); - if (propMap == null) { - continue; - } - Set props = new HashSet(propMap.values()); - - byte[] nodeMac = switchManager.getNodeMAC(node); - Property macAddr = new MacAddress(controllerMac, nodeMac); - props.add(macAddr); - - NodeProperties nodeProps = new NodeProperties(node, props); - res.add(nodeProps); - } - - return new Nodes(res); - } + private String username; + + @Context + public void setSecurityContext(SecurityContext context) { + username = context.getUserPrincipal().getName(); + } + + protected String getUserName() { + return username; + } + + private ISwitchManager getIfSwitchManagerService(String containerName) { + IContainerManager containerManager = (IContainerManager) ServiceHelper + .getGlobalInstance(IContainerManager.class, this); + if (containerManager == null) { + throw new ServiceUnavailableException("Container " + + RestMessages.SERVICEUNAVAILABLE.toString()); + } + + boolean found = false; + List containerNames = containerManager.getContainerNames(); + for (String cName : containerNames) { + if (cName.trim().equalsIgnoreCase(containerName.trim())) { + found = true; + break; + } + } + + if (found == false) { + throw new ResourceNotFoundException(containerName + " " + + RestMessages.NOCONTAINER.toString()); + } + + ISwitchManager switchManager = (ISwitchManager) ServiceHelper + .getInstance(ISwitchManager.class, containerName, this); + + if (switchManager == null) { + throw new ServiceUnavailableException("Switch Manager " + + RestMessages.SERVICEUNAVAILABLE.toString()); + } + + return switchManager; + } + + /** + * + * Retrieve a list of all the nodes and their properties in the network + * + * @param containerName + * The container for which we want to retrieve the list + * @return A list of Pair each pair represents a + * {@link org.opendaylight.controller.sal.core.Node} and Set of + * {@link org.opendaylight.controller.sal.core.Property} attached to + * it. + */ + @Path("/{containerName}/nodes") + @GET + @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) + @TypeHint(Nodes.class) + @StatusCodes({ + @ResponseCode(code = 200, condition = "Operation successful"), + @ResponseCode(code = 404, condition = "The containerName is not found"), + @ResponseCode(code = 503, condition = "One or more of Controller Services are unavailable") }) + public Nodes getNodes(@PathParam("containerName") String containerName) { + + if (!NorthboundUtils.isAuthorized( + getUserName(), containerName, Privilege.READ, this)) { + throw new UnauthorizedException( + "User is not authorized to perform this operation on container " + + containerName); + } + + ISwitchManager switchManager = (ISwitchManager) getIfSwitchManagerService(containerName); + if (switchManager == null) { + throw new ServiceUnavailableException("Switch Manager " + + RestMessages.SERVICEUNAVAILABLE.toString()); + } + + List res = new ArrayList(); + Set nodes = switchManager.getNodes(); + if (nodes == null) { + return null; + } + + byte[] controllerMac = switchManager.getControllerMAC(); + for (Node node : nodes) { + Map propMap = switchManager.getNodeProps(node); + if (propMap == null) { + continue; + } + Set props = new HashSet(propMap.values()); + + byte[] nodeMac = switchManager.getNodeMAC(node); + Property macAddr = new MacAddress(controllerMac, nodeMac); + props.add(macAddr); + + NodeProperties nodeProps = new NodeProperties(node, props); + res.add(nodeProps); + } + + return new Nodes(res); + } /** * Add a Name/Tier property to a node - * - * @param containerName Name of the Container - * @param nodeType Type of the node being programmed - * @param nodeId Node Identifier as specified by {@link org.opendaylight.controller.sal.core.Node} - * @param propName Name of the Property specified by {@link org.opendaylight.controller.sal.core.Property} and its extended classes - * @param propValue Value of the Property specified by {@link org.opendaylight.controller.sal.core.Property} and its extended classes + * + * @param containerName + * Name of the Container + * @param nodeType + * Type of the node being programmed + * @param nodeId + * Node Identifier as specified by + * {@link org.opendaylight.controller.sal.core.Node} + * @param propName + * Name of the Property specified by + * {@link org.opendaylight.controller.sal.core.Property} and its + * extended classes + * @param propValue + * Value of the Property specified by + * {@link org.opendaylight.controller.sal.core.Property} and its + * extended classes * @return Response as dictated by the HTTP Response Status code */ @Path("/{containerName}/node/{nodeType}/{nodeId}/property/{propName}/{propValue}") @PUT - @Consumes( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) + @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) @TypeHint(Response.class) - @StatusCodes( { - @ResponseCode(code = 200, condition = "Operation successful"), + @StatusCodes({ + @ResponseCode(code = 200, condition = "Operation successful"), @ResponseCode(code = 404, condition = "The Container Name or nodeId or configuration name is not found"), @ResponseCode(code = 503, condition = "One or more of Controller services are unavailable") }) - public Response addNodeProperty(@PathParam("containerName") String containerName, + public Response addNodeProperty( + @PathParam("containerName") String containerName, @PathParam("nodeType") String nodeType, @PathParam("nodeId") String nodeId, @PathParam("propName") String propName, @PathParam("propValue") String propValue) { + if (!NorthboundUtils.isAuthorized( + getUserName(), containerName, Privilege.WRITE, this)) { + throw new UnauthorizedException( + "User is not authorized to perform this operation on container " + + containerName); + } handleDefaultDisabled(containerName); - ISwitchManager switchManager = (ISwitchManager) getIfSwitchManagerService(containerName); - if (switchManager == null) { - throw new ServiceUnavailableException("Switch Manager " - + RestMessages.SERVICEUNAVAILABLE.toString()); - } + ISwitchManager switchManager = (ISwitchManager) getIfSwitchManagerService(containerName); + if (switchManager == null) { + throw new ServiceUnavailableException("Switch Manager " + + RestMessages.SERVICEUNAVAILABLE.toString()); + } handleNodeAvailability(containerName, nodeType, nodeId); - Node node = Node.fromString(nodeId); - - Property prop = switchManager.createProperty(propName, propValue); - if (prop == null) { - throw new ResourceNotFoundException( - RestMessages.INVALIDDATA.toString()); - } - + Node node = Node.fromString(nodeId); + + Property prop = switchManager.createProperty(propName, propValue); + if (prop == null) { + throw new ResourceNotFoundException( + RestMessages.INVALIDDATA.toString()); + } + switchManager.setNodeProp(node, prop); return Response.status(Response.Status.CREATED).build(); } /** * Delete a property of a node - * - * @param containerName Name of the Container - * @param nodeType Type of the node being programmed - * @param nodeId Node Identifier as specified by {@link org.opendaylight.controller.sal.core.Node} - * @param propertyName Name of the Property specified by {@link org.opendaylight.controller.sal.core.Property} and its extended classes + * + * @param containerName + * Name of the Container + * @param nodeType + * Type of the node being programmed + * @param nodeId + * Node Identifier as specified by + * {@link org.opendaylight.controller.sal.core.Node} + * @param propertyName + * Name of the Property specified by + * {@link org.opendaylight.controller.sal.core.Property} and its + * extended classes * @return Response as dictated by the HTTP Response Status code */ @Path("/{containerName}/node/{nodeType}/{nodeId}/property/{propertyName}") @DELETE - @Consumes( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) - @StatusCodes( { - @ResponseCode(code = 200, condition = "Operation successful"), + @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) + @StatusCodes({ + @ResponseCode(code = 200, condition = "Operation successful"), @ResponseCode(code = 404, condition = "The Container Name or nodeId or configuration name is not found"), @ResponseCode(code = 503, condition = "One or more of Controller services are unavailable") }) - public Response deleteNodeProperty(@PathParam("containerName") String containerName, + public Response deleteNodeProperty( + @PathParam("containerName") String containerName, @PathParam("nodeType") String nodeType, @PathParam("nodeId") String nodeId, @PathParam("propertyName") String propertyName) { + if (!NorthboundUtils.isAuthorized( + getUserName(), containerName, Privilege.WRITE, this)) { + throw new UnauthorizedException( + "User is not authorized to perform this operation on container " + + containerName); + } handleDefaultDisabled(containerName); - ISwitchManager switchManager = (ISwitchManager) getIfSwitchManagerService(containerName); - if (switchManager == null) { - throw new ServiceUnavailableException("Switch Manager " - + RestMessages.SERVICEUNAVAILABLE.toString()); - } + ISwitchManager switchManager = (ISwitchManager) getIfSwitchManagerService(containerName); + if (switchManager == null) { + throw new ServiceUnavailableException("Switch Manager " + + RestMessages.SERVICEUNAVAILABLE.toString()); + } handleNodeAvailability(containerName, nodeType, nodeId); - Node node = Node.fromString(nodeId); - + Node node = Node.fromString(nodeId); + Status ret = switchManager.removeNodeProp(node, propertyName); if (ret.isSuccess()) { return Response.ok().build(); @@ -221,80 +277,109 @@ public class SwitchNorthbound { throw new ResourceNotFoundException(ret.getDescription()); } - /** - * - * Retrieve a list of all the node connectors and their properties in a given node - * - * @param containerName The container for which we want to retrieve the list - * @param nodeType Type of the node being programmed - * @param nodeId Node Identifier as specified by {@link org.opendaylight.controller.sal.core.Node} - * @return A List of Pair each pair represents a - * {@link org.opendaylight.controller.sal.core.NodeConnector} and - * its corresponding - * {@link org.opendaylight.controller.sal.core.Property} attached to - * it. - */ - @Path("/{containerName}/node/{nodeType}/{nodeId}") - @GET - @Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) - @TypeHint(NodeConnectors.class) - @StatusCodes( { - @ResponseCode(code = 200, condition = "Operation successful"), - @ResponseCode(code = 404, condition = "The containerName is not found"), - @ResponseCode(code = 503, condition = "One or more of Controller Services are unavailable") }) - public NodeConnectors getNodeConnectors( - @PathParam("containerName") String containerName, - @PathParam("nodeType") String nodeType, - @PathParam("nodeId") String nodeId) { - ISwitchManager switchManager = (ISwitchManager) getIfSwitchManagerService(containerName); - if (switchManager == null) { - throw new ServiceUnavailableException("Switch Manager " - + RestMessages.SERVICEUNAVAILABLE.toString()); - } - - handleNodeAvailability(containerName, nodeType,nodeId); - Node node = Node.fromString(nodeId); - - List res = new ArrayList(); - Set ncs = switchManager.getNodeConnectors(node); - if (ncs == null) { - return null; - } - - for (NodeConnector nc : ncs) { - Map propMap = switchManager.getNodeConnectorProps(nc); - if (propMap == null) { - continue; - } - Set props = new HashSet(propMap.values()); - NodeConnectorProperties ncProps = new NodeConnectorProperties(nc, props); - res.add(ncProps); - } - - return new NodeConnectors(res); - } + /** + * + * Retrieve a list of all the node connectors and their properties in a + * given node + * + * @param containerName + * The container for which we want to retrieve the list + * @param nodeType + * Type of the node being programmed + * @param nodeId + * Node Identifier as specified by + * {@link org.opendaylight.controller.sal.core.Node} + * @return A List of Pair each pair represents a + * {@link org.opendaylight.controller.sal.core.NodeConnector} and + * its corresponding + * {@link org.opendaylight.controller.sal.core.Property} attached to + * it. + */ + @Path("/{containerName}/node/{nodeType}/{nodeId}") + @GET + @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) + @TypeHint(NodeConnectors.class) + @StatusCodes({ + @ResponseCode(code = 200, condition = "Operation successful"), + @ResponseCode(code = 404, condition = "The containerName is not found"), + @ResponseCode(code = 503, condition = "One or more of Controller Services are unavailable") }) + public NodeConnectors getNodeConnectors( + @PathParam("containerName") String containerName, + @PathParam("nodeType") String nodeType, + @PathParam("nodeId") String nodeId) { + + if (!NorthboundUtils.isAuthorized( + getUserName(), containerName, Privilege.READ, this)) { + throw new UnauthorizedException( + "User is not authorized to perform this operation on container " + + containerName); + } + + ISwitchManager switchManager = (ISwitchManager) getIfSwitchManagerService(containerName); + if (switchManager == null) { + throw new ServiceUnavailableException("Switch Manager " + + RestMessages.SERVICEUNAVAILABLE.toString()); + } + + handleNodeAvailability(containerName, nodeType, nodeId); + Node node = Node.fromString(nodeId); + + List res = new ArrayList(); + Set ncs = switchManager.getNodeConnectors(node); + if (ncs == null) { + return null; + } + + for (NodeConnector nc : ncs) { + Map propMap = switchManager + .getNodeConnectorProps(nc); + if (propMap == null) { + continue; + } + Set props = new HashSet(propMap.values()); + NodeConnectorProperties ncProps = new NodeConnectorProperties(nc, + props); + res.add(ncProps); + } + + return new NodeConnectors(res); + } /** * Add a Name/Bandwidth property to a node connector - * - * @param containerName Name of the Container - * @param nodeType Type of the node being programmed - * @param nodeId Node Identifier as specified by {@link org.opendaylight.controller.sal.core.Node} - * @param nodeConnectorType Type of the node connector being programmed - * @param nodeConnectorId NodeConnector Identifier as specified by {@link org.opendaylight.controller.sal.core.NodeConnector} - * @param propName Name of the Property specified by {@link org.opendaylight.controller.sal.core.Property} and its extended classes - * @param propValue Value of the Property specified by {@link org.opendaylight.controller.sal.core.Property} and its extended classes + * + * @param containerName + * Name of the Container + * @param nodeType + * Type of the node being programmed + * @param nodeId + * Node Identifier as specified by + * {@link org.opendaylight.controller.sal.core.Node} + * @param nodeConnectorType + * Type of the node connector being programmed + * @param nodeConnectorId + * NodeConnector Identifier as specified by + * {@link org.opendaylight.controller.sal.core.NodeConnector} + * @param propName + * Name of the Property specified by + * {@link org.opendaylight.controller.sal.core.Property} and its + * extended classes + * @param propValue + * Value of the Property specified by + * {@link org.opendaylight.controller.sal.core.Property} and its + * extended classes * @return Response as dictated by the HTTP Response Status code */ @Path("/{containerName}/nodeconnector/{nodeType}/{nodeId}/{nodeConnectorType}/{nodeConnectorId}/property/{propName}/{propValue}") @PUT - @Consumes( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) - @StatusCodes( { - @ResponseCode(code = 200, condition = "Operation successful"), + @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) + @StatusCodes({ + @ResponseCode(code = 200, condition = "Operation successful"), @ResponseCode(code = 404, condition = "The Container Name or nodeId or configuration name is not found"), @ResponseCode(code = 503, condition = "One or more of Controller services are unavailable") }) - public Response addNodeConnectorProperty(@PathParam("containerName") String containerName, + public Response addNodeConnectorProperty( + @PathParam("containerName") String containerName, @PathParam("nodeType") String nodeType, @PathParam("nodeId") String nodeId, @PathParam("nodeConnectorType") String nodeConnectorType, @@ -302,27 +387,36 @@ public class SwitchNorthbound { @PathParam("propName") String propName, @PathParam("propValue") String propValue) { + if (!NorthboundUtils.isAuthorized( + getUserName(), containerName, Privilege.WRITE, this)) { + throw new UnauthorizedException( + "User is not authorized to perform this operation on container " + + containerName); + } + handleDefaultDisabled(containerName); - ISwitchManager switchManager = (ISwitchManager) getIfSwitchManagerService(containerName); - if (switchManager == null) { - throw new ServiceUnavailableException("Switch Manager " - + RestMessages.SERVICEUNAVAILABLE.toString()); - } - - handleNodeAvailability(containerName, nodeType, nodeId); - Node node = Node.fromString(nodeId); - - handleNodeConnectorAvailability(containerName, node, nodeConnectorType, nodeConnectorId); - NodeConnector nc = NodeConnector.fromStringNoNode(nodeConnectorId, node); - - Property prop = switchManager.createProperty(propName, propValue); - if (prop == null) { - throw new ResourceNotFoundException( - RestMessages.INVALIDDATA.toString()); - } - - Status ret = switchManager.addNodeConnectorProp(nc, prop); + ISwitchManager switchManager = (ISwitchManager) getIfSwitchManagerService(containerName); + if (switchManager == null) { + throw new ServiceUnavailableException("Switch Manager " + + RestMessages.SERVICEUNAVAILABLE.toString()); + } + + handleNodeAvailability(containerName, nodeType, nodeId); + Node node = Node.fromString(nodeId); + + handleNodeConnectorAvailability(containerName, node, nodeConnectorType, + nodeConnectorId); + NodeConnector nc = NodeConnector + .fromStringNoNode(nodeConnectorId, node); + + Property prop = switchManager.createProperty(propName, propValue); + if (prop == null) { + throw new ResourceNotFoundException( + RestMessages.INVALIDDATA.toString()); + } + + Status ret = switchManager.addNodeConnectorProp(nc, prop); if (ret.isSuccess()) { return Response.status(Response.Status.CREATED).build(); } @@ -331,44 +425,64 @@ public class SwitchNorthbound { /** * Delete a property of a node connector - * - * @param containerName Name of the Container - * @param nodeType Type of the node being programmed - * @param nodeId Node Identifier as specified by {@link org.opendaylight.controller.sal.core.Node} - * @param nodeConnectorType Type of the node connector being programmed - * @param nodeConnectorId NodeConnector Identifier as specified by {@link org.opendaylight.controller.sal.core.NodeConnector} - * @param propertyName Name of the Property specified by {@link org.opendaylight.controller.sal.core.Property} and its extended classes + * + * @param containerName + * Name of the Container + * @param nodeType + * Type of the node being programmed + * @param nodeId + * Node Identifier as specified by + * {@link org.opendaylight.controller.sal.core.Node} + * @param nodeConnectorType + * Type of the node connector being programmed + * @param nodeConnectorId + * NodeConnector Identifier as specified by + * {@link org.opendaylight.controller.sal.core.NodeConnector} + * @param propertyName + * Name of the Property specified by + * {@link org.opendaylight.controller.sal.core.Property} and its + * extended classes * @return Response as dictated by the HTTP Response Status code */ @Path("/{containerName}/nodeconnector/{nodeType}/{nodeId}/{nodeConnectorType}/{nodeConnectorId}/property/{propertyName}") @DELETE - @Consumes( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) - @StatusCodes( { - @ResponseCode(code = 200, condition = "Operation successful"), + @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) + @StatusCodes({ + @ResponseCode(code = 200, condition = "Operation successful"), @ResponseCode(code = 404, condition = "The Container Name or nodeId or configuration name is not found"), @ResponseCode(code = 503, condition = "One or more of Controller services are unavailable") }) - public Response deleteNodeConnectorProperty(@PathParam("containerName") String containerName, + public Response deleteNodeConnectorProperty( + @PathParam("containerName") String containerName, @PathParam("nodeType") String nodeType, @PathParam("nodeId") String nodeId, @PathParam("nodeConnectorType") String nodeConnectorType, @PathParam("nodeConnectorId") String nodeConnectorId, @PathParam("propertyName") String propertyName) { + if (!NorthboundUtils.isAuthorized( + getUserName(), containerName, Privilege.WRITE, this)) { + throw new UnauthorizedException( + "User is not authorized to perform this operation on container " + + containerName); + } + handleDefaultDisabled(containerName); - ISwitchManager switchManager = (ISwitchManager) getIfSwitchManagerService(containerName); - if (switchManager == null) { - throw new ServiceUnavailableException("Switch Manager " - + RestMessages.SERVICEUNAVAILABLE.toString()); - } - - handleNodeAvailability(containerName, nodeType, nodeId); - Node node = Node.fromString(nodeId); - - handleNodeConnectorAvailability(containerName, node, nodeConnectorType, nodeConnectorId); - NodeConnector nc = NodeConnector.fromStringNoNode(nodeConnectorId, node); - + ISwitchManager switchManager = (ISwitchManager) getIfSwitchManagerService(containerName); + if (switchManager == null) { + throw new ServiceUnavailableException("Switch Manager " + + RestMessages.SERVICEUNAVAILABLE.toString()); + } + + handleNodeAvailability(containerName, nodeType, nodeId); + Node node = Node.fromString(nodeId); + + handleNodeConnectorAvailability(containerName, node, nodeConnectorType, + nodeConnectorId); + NodeConnector nc = NodeConnector + .fromStringNoNode(nodeConnectorId, node); + Status ret = switchManager.removeNodeConnectorProp(nc, propertyName); if (ret.isSuccess()) { return Response.ok().build(); @@ -376,174 +490,208 @@ public class SwitchNorthbound { throw new ResourceNotFoundException(ret.getDescription()); } -/* *//** + /* *//** * Retrieve a list of Span ports that were configured previously. - * - * @param containerName Name of the Container - * @return list of {@link org.opendaylight.controller.switchmanager.SpanConfig} resources - *//* - @Path("/span-config/{containerName}") - @GET - @Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) - @StatusCodes( { - @ResponseCode(code = 200, condition = "Operation successful"), - @ResponseCode(code = 404, condition = "The containerName is not found"), - @ResponseCode(code = 503, condition = "One or more of Controller Services are unavailable") }) - public List getSpanConfigList(@PathParam("containerName") String containerName) { - ISwitchManager switchManager = (ISwitchManager) getIfSwitchManagerService(containerName); - if (switchManager == null) { - throw new ServiceUnavailableException("Switch Manager " - + RestMessages.SERVICEUNAVAILABLE.toString()); - } - - return switchManager.getSpanConfigList(); - } - - *//** + * + * @param containerName + * Name of the Container + * @return list of + * {@link org.opendaylight.controller.switchmanager.SpanConfig} + * resources + */ + /* + * @Path("/span-config/{containerName}") + * + * @GET + * + * @Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) + * + * @StatusCodes( { + * + * @ResponseCode(code = 200, condition = "Operation successful"), + * + * @ResponseCode(code = 404, condition = "The containerName is not found"), + * + * @ResponseCode(code = 503, condition = + * "One or more of Controller Services are unavailable") }) public + * List getSpanConfigList(@PathParam("containerName") String + * containerName) { ISwitchManager switchManager = (ISwitchManager) + * getIfSwitchManagerService(containerName); if (switchManager == null) { + * throw new ServiceUnavailableException("Switch Manager " + + * RestMessages.SERVICEUNAVAILABLE.toString()); } + * + * return switchManager.getSpanConfigList(); } + *//** * Add a span configuration - * - * @param containerName Name of the Container - * @param config {@link org.opendaylight.controller.switchmanager.SpanConfig} in JSON or XML format + * + * @param containerName + * Name of the Container + * @param config + * {@link org.opendaylight.controller.switchmanager.SpanConfig} + * in JSON or XML format * @return Response as dictated by the HTTP Response Status code - *//* - @Path("/span-config/{containerName}") - @PUT - @Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) - @StatusCodes( { - @ResponseCode(code = 200, condition = "Operation successful"), - @ResponseCode(code = 404, condition = "The containerName is not found"), - @ResponseCode(code = 503, condition = "One or more of Controller Services are unavailable") }) - public Response addSpanConfig(@PathParam("containerName") String containerName, - @TypeHint(SubnetConfig.class) JAXBElement config) { - ISwitchManager switchManager = (ISwitchManager) getIfSwitchManagerService(containerName); - if (switchManager == null) { - throw new ServiceUnavailableException("Switch Manager " - + RestMessages.SERVICEUNAVAILABLE.toString()); - } - - String ret = switchManager.addSpanConfig(config.getValue()); - if (ret.equals(ReturnString.SUCCESS.toString())) { - return Response.status(Response.Status.CREATED).build(); - } - throw new InternalServerErrorException(ret); - } - - *//** + */ + /* + * @Path("/span-config/{containerName}") + * + * @PUT + * + * @Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) + * + * @StatusCodes( { + * + * @ResponseCode(code = 200, condition = "Operation successful"), + * + * @ResponseCode(code = 404, condition = "The containerName is not found"), + * + * @ResponseCode(code = 503, condition = + * "One or more of Controller Services are unavailable") }) public Response + * addSpanConfig(@PathParam("containerName") String containerName, + * + * @TypeHint(SubnetConfig.class) JAXBElement config) { + * ISwitchManager switchManager = (ISwitchManager) + * getIfSwitchManagerService(containerName); if (switchManager == null) { + * throw new ServiceUnavailableException("Switch Manager " + + * RestMessages.SERVICEUNAVAILABLE.toString()); } + * + * String ret = switchManager.addSpanConfig(config.getValue()); if + * (ret.equals(ReturnString.SUCCESS.toString())) { return + * Response.status(Response.Status.CREATED).build(); } throw new + * InternalServerErrorException(ret); } + *//** * Delete a span configuration - * - * @param containerName Name of the Container - * @param config {@link org.opendaylight.controller.switchmanager.SpanConfig} in JSON or XML format + * + * @param containerName + * Name of the Container + * @param config + * {@link org.opendaylight.controller.switchmanager.SpanConfig} + * in JSON or XML format * @return Response as dictated by the HTTP Response Status code - *//* - @Path("/span-config/{containerName}") - @DELETE - @Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) - @StatusCodes( { - @ResponseCode(code = 200, condition = "Operation successful"), - @ResponseCode(code = 404, condition = "The containerName is not found"), - @ResponseCode(code = 503, condition = "One or more of Controller Services are unavailable") }) - public Response deleteSpanConfig(@PathParam("containerName") String containerName, - @TypeHint(SubnetConfig.class) JAXBElement config) { - ISwitchManager switchManager = (ISwitchManager) getIfSwitchManagerService(containerName); - if (switchManager == null) { - throw new ServiceUnavailableException("Switch Manager " - + RestMessages.SERVICEUNAVAILABLE.toString()); - } - - String ret = switchManager.removeSpanConfig(config.getValue()); - if (ret.equals(ReturnString.SUCCESS.toString())) { - return Response.ok().build(); - } - throw new ResourceNotFoundException(ret); - } -*/ - + */ + /* + * @Path("/span-config/{containerName}") + * + * @DELETE + * + * @Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) + * + * @StatusCodes( { + * + * @ResponseCode(code = 200, condition = "Operation successful"), + * + * @ResponseCode(code = 404, condition = "The containerName is not found"), + * + * @ResponseCode(code = 503, condition = + * "One or more of Controller Services are unavailable") }) public Response + * deleteSpanConfig(@PathParam("containerName") String containerName, + * + * @TypeHint(SubnetConfig.class) JAXBElement config) { + * ISwitchManager switchManager = (ISwitchManager) + * getIfSwitchManagerService(containerName); if (switchManager == null) { + * throw new ServiceUnavailableException("Switch Manager " + + * RestMessages.SERVICEUNAVAILABLE.toString()); } + * + * String ret = switchManager.removeSpanConfig(config.getValue()); if + * (ret.equals(ReturnString.SUCCESS.toString())) { return + * Response.ok().build(); } throw new ResourceNotFoundException(ret); } + */ + /** * Save the current switch configurations - * - * @param containerName Name of the Container + * + * @param containerName + * Name of the Container * @return Response as dictated by the HTTP Response Status code */ - @Path("/{containerName}/switch-config") - @POST - @Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) - @StatusCodes( { - @ResponseCode(code = 200, condition = "Operation successful"), - @ResponseCode(code = 404, condition = "The containerName is not found"), - @ResponseCode(code = 503, condition = "One or more of Controller Services are unavailable") }) - public Response saveSwitchConfig(@PathParam("containerName") String containerName) { - ISwitchManager switchManager = (ISwitchManager) getIfSwitchManagerService(containerName); - if (switchManager == null) { - throw new ServiceUnavailableException("Switch Manager " - + RestMessages.SERVICEUNAVAILABLE.toString()); - } - - Status ret = switchManager.saveSwitchConfig(); + @Path("/{containerName}/switch-config") + @POST + @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) + @StatusCodes({ + @ResponseCode(code = 200, condition = "Operation successful"), + @ResponseCode(code = 404, condition = "The containerName is not found"), + @ResponseCode(code = 503, condition = "One or more of Controller Services are unavailable") }) + public Response saveSwitchConfig( + @PathParam("containerName") String containerName) { + + if (!NorthboundUtils.isAuthorized( + getUserName(), containerName, Privilege.WRITE, this)) { + throw new UnauthorizedException( + "User is not authorized to perform this operation on container " + + containerName); + } + ISwitchManager switchManager = (ISwitchManager) getIfSwitchManagerService(containerName); + if (switchManager == null) { + throw new ServiceUnavailableException("Switch Manager " + + RestMessages.SERVICEUNAVAILABLE.toString()); + } + + Status ret = switchManager.saveSwitchConfig(); if (ret.isSuccess()) { return Response.ok().build(); } throw new InternalServerErrorException(ret.getDescription()); - } + } private void handleDefaultDisabled(String containerName) { IContainerManager containerManager = (IContainerManager) ServiceHelper .getGlobalInstance(IContainerManager.class, this); if (containerManager == null) { - throw new InternalServerErrorException(RestMessages.INTERNALERROR - .toString()); + throw new InternalServerErrorException( + RestMessages.INTERNALERROR.toString()); } if (containerName.equals(GlobalConstants.DEFAULT.toString()) && containerManager.hasNonDefaultContainer()) { - throw new ResourceConflictException(RestMessages.DEFAULTDISABLED - .toString()); + throw new ResourceConflictException( + RestMessages.DEFAULTDISABLED.toString()); } } private Node handleNodeAvailability(String containerName, String nodeType, - String nodeId) { - - Node node = Node.fromString(nodeType, nodeId); - if (node == null) { - throw new ResourceNotFoundException(nodeId + " : " - + RestMessages.NONODE.toString()); - } - - ISwitchManager sm = (ISwitchManager) ServiceHelper.getInstance( - ISwitchManager.class, containerName, this); - - if (sm == null) { - throw new ServiceUnavailableException("Switch Manager " - + RestMessages.SERVICEUNAVAILABLE.toString()); - } - - if (!sm.getNodes().contains(node)) { - throw new ResourceNotFoundException(node.toString() + " : " - + RestMessages.NONODE.toString()); - } - return node; + String nodeId) { + + Node node = Node.fromString(nodeType, nodeId); + if (node == null) { + throw new ResourceNotFoundException(nodeId + " : " + + RestMessages.NONODE.toString()); + } + + ISwitchManager sm = (ISwitchManager) ServiceHelper.getInstance( + ISwitchManager.class, containerName, this); + + if (sm == null) { + throw new ServiceUnavailableException("Switch Manager " + + RestMessages.SERVICEUNAVAILABLE.toString()); + } + + if (!sm.getNodes().contains(node)) { + throw new ResourceNotFoundException(node.toString() + " : " + + RestMessages.NONODE.toString()); + } + return node; + } + + private void handleNodeConnectorAvailability(String containerName, + Node node, String nodeConnectorType, String nodeConnectorId) { + + NodeConnector nc = NodeConnector.fromStringNoNode(nodeConnectorType, + nodeConnectorId, node); + if (nc == null) { + throw new ResourceNotFoundException(nc + " : " + + RestMessages.NORESOURCE.toString()); + } + + ISwitchManager sm = (ISwitchManager) ServiceHelper.getInstance( + ISwitchManager.class, containerName, this); + + if (sm == null) { + throw new ServiceUnavailableException("Switch Manager " + + RestMessages.SERVICEUNAVAILABLE.toString()); + } + + if (!sm.getNodeConnectors(node).contains(nc)) { + throw new ResourceNotFoundException(nc.toString() + " : " + + RestMessages.NORESOURCE.toString()); + } } - private void handleNodeConnectorAvailability(String containerName, - Node node, String nodeConnectorType, String nodeConnectorId) { - - NodeConnector nc = NodeConnector.fromStringNoNode(nodeConnectorType, - nodeConnectorId, node); - if (nc == null) { - throw new ResourceNotFoundException(nc + " : " - + RestMessages.NORESOURCE.toString()); - } - - ISwitchManager sm = (ISwitchManager) ServiceHelper.getInstance( - ISwitchManager.class, containerName, this); - - if (sm == null) { - throw new ServiceUnavailableException("Switch Manager " - + RestMessages.SERVICEUNAVAILABLE.toString()); - } - - if (!sm.getNodeConnectors(node).contains(nc)) { - throw new ResourceNotFoundException(nc.toString() + " : " - + RestMessages.NORESOURCE.toString()); - } - } } diff --git a/opendaylight/northbound/topology/pom.xml b/opendaylight/northbound/topology/pom.xml index 0cfa487f1c..b8eebe4a0f 100644 --- a/opendaylight/northbound/topology/pom.xml +++ b/opendaylight/northbound/topology/pom.xml @@ -40,14 +40,17 @@ org.opendaylight.controller.containermanager, org.opendaylight.controller.northbound.commons, org.opendaylight.controller.northbound.commons.exception, + org.opendaylight.controller.northbound.commons.utils, org.opendaylight.controller.sal.core, org.opendaylight.controller.sal.packet, - org.opendaylight.controller.sal.packet.address, + org.opendaylight.controller.sal.authorization, + org.opendaylight.controller.sal.packet.address, org.opendaylight.controller.sal.utils, org.opendaylight.controller.switchmanager, + org.opendaylight.controller.usermanager, org.opendaylight.controller.topologymanager, com.sun.jersey.spi.container.servlet, - javax.ws.rs, + javax.ws.rs, javax.ws.rs.core, javax.xml.bind, javax.xml.bind.annotation, diff --git a/opendaylight/northbound/topology/src/main/java/org/opendaylight/controller/topology/northbound/TopologyNorthboundJAXRS.java b/opendaylight/northbound/topology/src/main/java/org/opendaylight/controller/topology/northbound/TopologyNorthboundJAXRS.java index 5f1933b9b1..10480bc4ec 100644 --- a/opendaylight/northbound/topology/src/main/java/org/opendaylight/controller/topology/northbound/TopologyNorthboundJAXRS.java +++ b/opendaylight/northbound/topology/src/main/java/org/opendaylight/controller/topology/northbound/TopologyNorthboundJAXRS.java @@ -1,4 +1,3 @@ - /* * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. * @@ -22,8 +21,10 @@ import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; +import javax.ws.rs.core.Context; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; +import javax.ws.rs.core.SecurityContext; import javax.xml.bind.JAXBElement; import org.codehaus.enunciate.jaxrs.ResponseCode; @@ -32,61 +33,82 @@ import org.codehaus.enunciate.jaxrs.TypeHint; import org.opendaylight.controller.northbound.commons.RestMessages; import org.opendaylight.controller.northbound.commons.exception.InternalServerErrorException; import org.opendaylight.controller.northbound.commons.exception.ResourceNotFoundException; +import org.opendaylight.controller.northbound.commons.exception.UnauthorizedException; +import org.opendaylight.controller.northbound.commons.utils.NorthboundUtils; +import org.opendaylight.controller.sal.authorization.Privilege; import org.opendaylight.controller.sal.core.Edge; import org.opendaylight.controller.sal.core.Property; import org.opendaylight.controller.sal.utils.ServiceHelper; import org.opendaylight.controller.sal.utils.Status; import org.opendaylight.controller.topologymanager.ITopologyManager; import org.opendaylight.controller.topologymanager.TopologyUserLinkConfig; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; /** * Topology Northbound REST API * - *

+ *
+ *
* Authentication scheme : HTTP Basic
* Authentication realm : opendaylight
* Transport : HTTP and HTTPS
*
- * HTTPS Authentication is disabled by default. Administrator can enable it in tomcat-server.xml after adding - * a proper keystore / SSL certificate from a trusted authority.
- * More info : http://tomcat.apache.org/tomcat-7.0-doc/ssl-howto.html#Configuration + * HTTPS Authentication is disabled by default. Administrator can enable it in + * tomcat-server.xml after adding a proper keystore / SSL certificate from a + * trusted authority.
+ * More info : + * http://tomcat.apache.org/tomcat-7.0-doc/ssl-howto.html#Configuration */ @Path("/") public class TopologyNorthboundJAXRS { - private static Logger logger = LoggerFactory - .getLogger(TopologyNorthboundJAXRS.class); + + private String username; + + @Context + public void setSecurityContext(SecurityContext context) { + username = context.getUserPrincipal().getName(); + } + + protected String getUserName() { + return username; + } /** - * + * * Retrieve the Topology - * - * @param containerName The container for which we want to retrieve the topology - * - * @return A List of EdgeProps each EdgeProp represent an Edge of - * the grap with the corresponding properties attached to it. + * + * @param containerName + * The container for which we want to retrieve the topology + * + * @return A List of EdgeProps each EdgeProp represent an Edge of the grap + * with the corresponding properties attached to it. */ @Path("/{containerName}") @GET - @Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) + @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) @TypeHint(Topology.class) - @StatusCodes( { @ResponseCode(code = 404, condition = "The Container Name passed was not found") }) - public Topology getTopology( - @PathParam("containerName") String containerName) { + @StatusCodes({ @ResponseCode(code = 404, condition = "The Container Name passed was not found") }) + public Topology getTopology(@PathParam("containerName") String containerName) { + + if (!NorthboundUtils.isAuthorized( + getUserName(), containerName, Privilege.READ, this)) { + throw new UnauthorizedException( + "User is not authorized to perform this operation on container " + + containerName); + } ITopologyManager topologyManager = (ITopologyManager) ServiceHelper .getInstance(ITopologyManager.class, containerName, this); if (topologyManager == null) { - throw new ResourceNotFoundException(RestMessages.NOCONTAINER - .toString()); + throw new ResourceNotFoundException( + RestMessages.NOCONTAINER.toString()); } Map> topo = topologyManager.getEdges(); if (topo != null) { List res = new ArrayList(); for (Map.Entry> entry : topo.entrySet()) { - EdgeProperties el = new EdgeProperties(entry.getKey(), entry.getValue()); + EdgeProperties el = new EdgeProperties(entry.getKey(), + entry.getValue()); res.add(el); } return new Topology(res); @@ -96,100 +118,127 @@ public class TopologyNorthboundJAXRS { } /** - * Retrieve the user configured links - * - * @param containerName The container for which we want to retrieve the user links - * - * @return A List of user configured links - */ - @Path("/{containerName}/userLink") - @GET - @Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) - @TypeHint(TopologyUserLinks.class) - @StatusCodes( { @ResponseCode(code = 404, condition = "The Container Name passed was not found") }) - public TopologyUserLinks getUserLinks( - @PathParam("containerName") String containerName) { - ITopologyManager topologyManager = (ITopologyManager) ServiceHelper - .getInstance(ITopologyManager.class, containerName, this); - if (topologyManager == null) { - throw new ResourceNotFoundException(RestMessages.NOCONTAINER - .toString()); - } - - ConcurrentMap userLinks = topologyManager.getUserLinks(); - if ((userLinks != null) && (userLinks.values() != null)) { - List res = new ArrayList(userLinks.values()); - return new TopologyUserLinks(res); - } - - return null; - } - - /** - * Add an User Link - * - * @param containerName Name of the Container. The base Container is "default". - * @param TopologyUserLinkConfig in JSON or XML format - * @return Response as dictated by the HTTP Response Status code - */ - - @Path("/{containerName}/userLink") - @POST - @Consumes( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) - @StatusCodes( { - @ResponseCode(code = 201, condition = "User Link added successfully"), - @ResponseCode(code = 404, condition = "The Container Name passed was not found"), - @ResponseCode(code = 409, condition = "Failed to add User Link due to Conflicting Name"), - @ResponseCode(code = 500, condition = "Failed to add User Link. Failure Reason included in HTTP Error response"), - @ResponseCode(code = 503, condition = "One or more of Controller services are unavailable") }) - public Response addUserLink( - @PathParam(value = "containerName") String containerName, - @TypeHint(TopologyUserLinkConfig.class) JAXBElement userLinkConfig) { - - ITopologyManager topologyManager = (ITopologyManager) ServiceHelper - .getInstance(ITopologyManager.class, containerName, this); - if (topologyManager == null) { - throw new ResourceNotFoundException(RestMessages.NOCONTAINER - .toString()); - } - - Status status = topologyManager.addUserLink(userLinkConfig.getValue()); - if (status.isSuccess()) { - return Response.status(Response.Status.CREATED).build(); - } - throw new InternalServerErrorException(status.getDescription()); - } - - /** - * Delete an User Link - * - * @param containerName Name of the Container. The base Container is "default". - * @param name Name of the Link Configuration - * @return Response as dictated by the HTTP Response Status code - */ - - @Path("/{containerName}/userLink/{name}") - @DELETE - @Consumes( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) - @StatusCodes( { - @ResponseCode(code = 200, condition = "Operation successful"), - @ResponseCode(code = 404, condition = "The Container Name or Link Configuration Name was not found"), - @ResponseCode(code = 503, condition = "One or more of Controller services are unavailable") }) - public Response deleteUserLink( - @PathParam("containerName") String containerName, - @PathParam("name") String name) { - - ITopologyManager topologyManager = (ITopologyManager) ServiceHelper - .getInstance(ITopologyManager.class, containerName, this); - if (topologyManager == null) { - throw new ResourceNotFoundException(RestMessages.NOCONTAINER - .toString()); - } - - Status ret = topologyManager.deleteUserLink(name); - if (ret.isSuccess()) { - return Response.ok().build(); - } - throw new ResourceNotFoundException(ret.getDescription()); - } + * Retrieve the user configured links + * + * @param containerName + * The container for which we want to retrieve the user links + * + * @return A List of user configured links + */ + @Path("/{containerName}/userLink") + @GET + @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) + @TypeHint(TopologyUserLinks.class) + @StatusCodes({ @ResponseCode(code = 404, condition = "The Container Name passed was not found") }) + public TopologyUserLinks getUserLinks( + @PathParam("containerName") String containerName) { + + if (!NorthboundUtils.isAuthorized( + getUserName(), containerName, Privilege.READ, this)) { + throw new UnauthorizedException( + "User is not authorized to perform this operation on container " + + containerName); + } + ITopologyManager topologyManager = (ITopologyManager) ServiceHelper + .getInstance(ITopologyManager.class, containerName, this); + if (topologyManager == null) { + throw new ResourceNotFoundException( + RestMessages.NOCONTAINER.toString()); + } + + ConcurrentMap userLinks = topologyManager + .getUserLinks(); + if ((userLinks != null) && (userLinks.values() != null)) { + List res = new ArrayList( + userLinks.values()); + return new TopologyUserLinks(res); + } + + return null; + } + + /** + * Add an User Link + * + * @param containerName + * Name of the Container. The base Container is "default". + * @param TopologyUserLinkConfig + * in JSON or XML format + * @return Response as dictated by the HTTP Response Status code + */ + + @Path("/{containerName}/userLink") + @POST + @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) + @StatusCodes({ + @ResponseCode(code = 201, condition = "User Link added successfully"), + @ResponseCode(code = 404, condition = "The Container Name passed was not found"), + @ResponseCode(code = 409, condition = "Failed to add User Link due to Conflicting Name"), + @ResponseCode(code = 500, condition = "Failed to add User Link. Failure Reason included in HTTP Error response"), + @ResponseCode(code = 503, condition = "One or more of Controller services are unavailable") }) + public Response addUserLink( + @PathParam(value = "containerName") String containerName, + @TypeHint(TopologyUserLinkConfig.class) JAXBElement userLinkConfig) { + + if (!NorthboundUtils.isAuthorized( + getUserName(), containerName, Privilege.WRITE, this)) { + throw new UnauthorizedException( + "User is not authorized to perform this operation on container " + + containerName); + } + ITopologyManager topologyManager = (ITopologyManager) ServiceHelper + .getInstance(ITopologyManager.class, containerName, this); + if (topologyManager == null) { + throw new ResourceNotFoundException( + RestMessages.NOCONTAINER.toString()); + } + + Status status = topologyManager.addUserLink(userLinkConfig.getValue()); + if (status.isSuccess()) { + return Response.status(Response.Status.CREATED).build(); + } + throw new InternalServerErrorException(status.getDescription()); + } + + /** + * Delete an User Link + * + * @param containerName + * Name of the Container. The base Container is "default". + * @param name + * Name of the Link Configuration + * @return Response as dictated by the HTTP Response Status code + */ + + @Path("/{containerName}/userLink/{name}") + @DELETE + @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) + @StatusCodes({ + @ResponseCode(code = 200, condition = "Operation successful"), + @ResponseCode(code = 404, condition = "The Container Name or Link Configuration Name was not found"), + @ResponseCode(code = 503, condition = "One or more of Controller services are unavailable") }) + public Response deleteUserLink( + @PathParam("containerName") String containerName, + @PathParam("name") String name) { + + if (!NorthboundUtils.isAuthorized( + getUserName(), containerName, Privilege.WRITE, this)) { + throw new UnauthorizedException( + "User is not authorized to perform this operation on container " + + containerName); + } + ITopologyManager topologyManager = (ITopologyManager) ServiceHelper + .getInstance(ITopologyManager.class, containerName, this); + if (topologyManager == null) { + throw new ResourceNotFoundException( + RestMessages.NOCONTAINER.toString()); + } + + Status ret = topologyManager.deleteUserLink(name); + if (ret.isSuccess()) { + return Response.ok().build(); + } + throw new ResourceNotFoundException(ret.getDescription()); + } + } -- 2.36.6