Added RBAC for REST APIs.

- admin role required for POST, PUT, DELETE & PATCH
- viewer role required for all other requests
- cleaned up all web.xml files for consistency and correctness

Change-Id: I33bad5cec0fb0f4285eed84173025b0a107b5aec
This commit is contained in:
Thomas Vachuska 2018-07-17 11:51:54 -07:00
parent 3933295cd0
commit 67484d9008
38 changed files with 330 additions and 12 deletions

View File

@ -31,11 +31,13 @@
</web-resource-collection>
<auth-constraint>
<role-name>admin</role-name>
<role-name>viewer</role-name>
</auth-constraint>
</security-constraint>
<security-role>
<role-name>admin</role-name>
<role-name>viewer</role-name>
</security-role>
<login-config>

View File

@ -28,11 +28,13 @@
</web-resource-collection>
<auth-constraint>
<role-name>admin</role-name>
<role-name>viewer</role-name>
</auth-constraint>
</security-constraint>
<security-role>
<role-name>admin</role-name>
<role-name>viewer</role-name>
</security-role>
<login-config>

View File

@ -28,11 +28,13 @@
</web-resource-collection>
<auth-constraint>
<role-name>admin</role-name>
<role-name>viewer</role-name>
</auth-constraint>
</security-constraint>
<security-role>
<role-name>admin</role-name>
<role-name>viewer</role-name>
</security-role>
<login-config>

View File

@ -28,11 +28,13 @@
</web-resource-collection>
<auth-constraint>
<role-name>admin</role-name>
<role-name>viewer</role-name>
</auth-constraint>
</security-constraint>
<security-role>
<role-name>admin</role-name>
<role-name>viewer</role-name>
</security-role>
<login-config>

View File

@ -28,11 +28,13 @@
</web-resource-collection>
<auth-constraint>
<role-name>admin</role-name>
<role-name>viewer</role-name>
</auth-constraint>
</security-constraint>
<security-role>
<role-name>admin</role-name>
<role-name>viewer</role-name>
</security-role>
<login-config>

View File

@ -28,11 +28,13 @@
</web-resource-collection>
<auth-constraint>
<role-name>admin</role-name>
<role-name>viewer</role-name>
</auth-constraint>
</security-constraint>
<security-role>
<role-name>admin</role-name>
<role-name>viewer</role-name>
</security-role>
<login-config>

View File

@ -20,6 +20,27 @@
id="ONOS" version="2.5">
<display-name>FM2 REST API v1.0</display-name>
<security-constraint>
<web-resource-collection>
<web-resource-name>Secured</web-resource-name>
<url-pattern>/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>admin</role-name>
<role-name>viewer</role-name>
</auth-constraint>
</security-constraint>
<security-role>
<role-name>admin</role-name>
<role-name>viewer</role-name>
</security-role>
<login-config>
<auth-method>BASIC</auth-method>
<realm-name>karaf</realm-name>
</login-config>
<servlet>
<servlet-name>JAX-RS Service</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>

View File

@ -28,11 +28,13 @@
</web-resource-collection>
<auth-constraint>
<role-name>admin</role-name>
<role-name>viewer</role-name>
</auth-constraint>
</security-constraint>
<security-role>
<role-name>admin</role-name>
<role-name>viewer</role-name>
</security-role>
<login-config>

View File

@ -20,6 +20,27 @@
id="ONOS" version="2.5">
<display-name>Event Exporter REST API</display-name>
<security-constraint>
<web-resource-collection>
<web-resource-name>Secured</web-resource-name>
<url-pattern>/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>admin</role-name>
<role-name>viewer</role-name>
</auth-constraint>
</security-constraint>
<security-role>
<role-name>admin</role-name>
<role-name>viewer</role-name>
</security-role>
<login-config>
<auth-method>BASIC</auth-method>
<realm-name>karaf</realm-name>
</login-config>
<servlet>
<servlet-name>JAX-RS Service</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>

View File

@ -27,11 +27,13 @@
</web-resource-collection>
<auth-constraint>
<role-name>admin</role-name>
<role-name>viewer</role-name>
</auth-constraint>
</security-constraint>
<security-role>
<role-name>admin</role-name>
<role-name>viewer</role-name>
</security-role>
<login-config>

View File

@ -27,11 +27,13 @@
</web-resource-collection>
<auth-constraint>
<role-name>admin</role-name>
<role-name>viewer</role-name>
</auth-constraint>
</security-constraint>
<security-role>
<role-name>admin</role-name>
<role-name>viewer</role-name>
</security-role>
<login-config>

View File

@ -20,6 +20,27 @@
id="ONOS" version="2.5">
<display-name>ONOS APP MFWD</display-name>
<security-constraint>
<web-resource-collection>
<web-resource-name>Secured</web-resource-name>
<url-pattern>/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>admin</role-name>
<role-name>viewer</role-name>
</auth-constraint>
</security-constraint>
<security-role>
<role-name>admin</role-name>
<role-name>viewer</role-name>
</security-role>
<login-config>
<auth-method>BASIC</auth-method>
<realm-name>karaf</realm-name>
</login-config>
<servlet>
<servlet-name>JAX-RS Service</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>

View File

@ -28,11 +28,13 @@
</web-resource-collection>
<auth-constraint>
<role-name>admin</role-name>
<role-name>viewer</role-name>
</auth-constraint>
</security-constraint>
<security-role>
<role-name>admin</role-name>
<role-name>viewer</role-name>
</security-role>
<login-config>

View File

@ -27,11 +27,13 @@
</web-resource-collection>
<auth-constraint>
<role-name>admin</role-name>
<role-name>viewer</role-name>
</auth-constraint>
</security-constraint>
<security-role>
<role-name>admin</role-name>
<role-name>viewer</role-name>
</security-role>
<login-config>

View File

@ -20,6 +20,27 @@
id="ONOS" version="2.5">
<display-name>SONA GUI REST API v1.0</display-name>
<security-constraint>
<web-resource-collection>
<web-resource-name>Secured</web-resource-name>
<url-pattern>/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>admin</role-name>
<role-name>viewer</role-name>
</auth-constraint>
</security-constraint>
<security-role>
<role-name>admin</role-name>
<role-name>viewer</role-name>
</security-role>
<login-config>
<auth-method>BASIC</auth-method>
<realm-name>karaf</realm-name>
</login-config>
<servlet>
<servlet-name>JAX-RS Service</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>

View File

@ -28,11 +28,13 @@
</web-resource-collection>
<auth-constraint>
<role-name>admin</role-name>
<role-name>viewer</role-name>
</auth-constraint>
</security-constraint>
<security-role>
<role-name>admin</role-name>
<role-name>viewer</role-name>
</security-role>
<login-config>

View File

@ -27,11 +27,13 @@
</web-resource-collection>
<auth-constraint>
<role-name>admin</role-name>
<role-name>viewer</role-name>
</auth-constraint>
</security-constraint>
<security-role>
<role-name>admin</role-name>
<role-name>viewer</role-name>
</security-role>
<login-config>

View File

@ -27,11 +27,13 @@
</web-resource-collection>
<auth-constraint>
<role-name>admin</role-name>
<role-name>viewer</role-name>
</auth-constraint>
</security-constraint>
<security-role>
<role-name>admin</role-name>
<role-name>viewer</role-name>
</security-role>
<login-config>

View File

@ -28,11 +28,13 @@
</web-resource-collection>
<auth-constraint>
<role-name>admin</role-name>
<role-name>viewer</role-name>
</auth-constraint>
</security-constraint>
<security-role>
<role-name>admin</role-name>
<role-name>viewer</role-name>
</security-role>
<login-config>

View File

@ -96,7 +96,18 @@
<artifactId>onos-apps-pce-app</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.onosproject</groupId>
<artifactId>onos-rest</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.onosproject</groupId>
<artifactId>onos-rest</artifactId>
<version>${project.version}</version>
<scope>test</scope>
<classifier>tests</classifier>
</dependency>
</dependencies>
<build>
<plugins>

View File

@ -20,6 +20,27 @@
id="ONOS" version="2.5">
<display-name>PCE REST API v1.0</display-name>
<security-constraint>
<web-resource-collection>
<web-resource-name>Secured</web-resource-name>
<url-pattern>/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>admin</role-name>
<role-name>viewer</role-name>
</auth-constraint>
</security-constraint>
<security-role>
<role-name>admin</role-name>
<role-name>viewer</role-name>
</security-role>
<login-config>
<auth-method>BASIC</auth-method>
<realm-name>karaf</realm-name>
</login-config>
<servlet>
<servlet-name>JAX-RS Service</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>

View File

@ -18,6 +18,7 @@ package org.onosproject.pcerest;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.test.JerseyTest;
import org.glassfish.jersey.test.TestProperties;
import org.onlab.rest.AuthorizationFilter;
/**
* Base class for pce rest api tests. Performs common configuration operations.
@ -29,6 +30,7 @@ public class PceResourceTest extends JerseyTest {
*/
public PceResourceTest() {
super(ResourceConfig.forApplicationClass(PceWebApplication.class));
AuthorizationFilter.disableForTests();
set(TestProperties.CONTAINER_PORT, 0);
}
}

View File

@ -28,11 +28,13 @@
</web-resource-collection>
<auth-constraint>
<role-name>admin</role-name>
<role-name>viewer</role-name>
</auth-constraint>
</security-constraint>
<security-role>
<role-name>admin</role-name>
<role-name>viewer</role-name>
</security-role>
<login-config>

View File

@ -28,11 +28,13 @@
</web-resource-collection>
<auth-constraint>
<role-name>admin</role-name>
<role-name>viewer</role-name>
</auth-constraint>
</security-constraint>
<security-role>
<role-name>admin</role-name>
<role-name>viewer</role-name>
</security-role>
<login-config>

View File

@ -28,11 +28,13 @@
</web-resource-collection>
<auth-constraint>
<role-name>admin</role-name>
<role-name>viewer</role-name>
</auth-constraint>
</security-constraint>
<security-role>
<role-name>admin</role-name>
<role-name>viewer</role-name>
</security-role>
<login-config>

View File

@ -27,11 +27,13 @@
</web-resource-collection>
<auth-constraint>
<role-name>admin</role-name>
<role-name>viewer</role-name>
</auth-constraint>
</security-constraint>
<security-role>
<role-name>admin</role-name>
<role-name>viewer</role-name>
</security-role>
<login-config>

View File

@ -28,11 +28,13 @@
</web-resource-collection>
<auth-constraint>
<role-name>admin</role-name>
<role-name>viewer</role-name>
</auth-constraint>
</security-constraint>
<security-role>
<role-name>admin</role-name>
<role-name>viewer</role-name>
</security-role>
<login-config>

View File

@ -20,6 +20,27 @@
id="ONOS" version="2.5">
<display-name>ONOS DEMO APP API v1.0</display-name>
<security-constraint>
<web-resource-collection>
<web-resource-name>Secured</web-resource-name>
<url-pattern>/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>admin</role-name>
<role-name>viewer</role-name>
</auth-constraint>
</security-constraint>
<security-role>
<role-name>admin</role-name>
<role-name>viewer</role-name>
</security-role>
<login-config>
<auth-method>BASIC</auth-method>
<realm-name>karaf</realm-name>
</login-config>
<servlet>
<servlet-name>JAX-RS Service</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>

View File

@ -20,6 +20,27 @@
id="ONOS" version="2.5">
<display-name>ONOS Virtual BNG APP REST API</display-name>
<security-constraint>
<web-resource-collection>
<web-resource-name>Secured</web-resource-name>
<url-pattern>/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>admin</role-name>
<role-name>viewer</role-name>
</auth-constraint>
</security-constraint>
<security-role>
<role-name>admin</role-name>
<role-name>viewer</role-name>
</security-role>
<login-config>
<auth-method>BASIC</auth-method>
<realm-name>karaf</realm-name>
</login-config>
<servlet>
<servlet-name>JAX-RS Service</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>

View File

@ -20,7 +20,6 @@
id="ONOS" version="2.5">
<display-name>VTNRSC REST API v1.0</display-name>
<!-- TODO: this should be uncommented
<security-constraint>
<web-resource-collection>
<web-resource-name>Secured</web-resource-name>
@ -28,18 +27,19 @@
</web-resource-collection>
<auth-constraint>
<role-name>admin</role-name>
<role-name>viewer</role-name>
</auth-constraint>
</security-constraint>
<security-role>
<role-name>admin</role-name>
<role-name>viewer</role-name>
</security-role>
<login-config>
<auth-method>BASIC</auth-method>
<realm-name>karaf</realm-name>
</login-config>
-->
<servlet>
<servlet-name>JAX-RS Service</servlet-name>

View File

@ -15,19 +15,38 @@
~ limitations under the License.
-->
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
id="ONOS" version="2.5">
<display-name>YANG LIVE COMPILER REST API v1.0</display-name>
<display-name>YANG Live Compiler REST API v1.0</display-name>
<security-constraint>
<web-resource-collection>
<web-resource-name>Secured</web-resource-name>
<url-pattern>/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>admin</role-name>
<role-name>viewer</role-name>
</auth-constraint>
</security-constraint>
<security-role>
<role-name>admin</role-name>
<role-name>viewer</role-name>
</security-role>
<login-config>
<auth-method>BASIC</auth-method>
<realm-name>karaf</realm-name>
</login-config>
<servlet>
<servlet-name>JAX-RS Service</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer
</servlet-class>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>javax.ws.rs.Application</param-name>
<param-value>org.onosproject.yang.web.YangWebApplication
</param-value>
<param-value>org.onosproject.yang.web.YangWebApplication</param-value>
</init-param>
<init-param>
<param-name>jersey.config.server.provider.classnames</param-name>

View File

@ -28,11 +28,13 @@
</web-resource-collection>
<auth-constraint>
<role-name>admin</role-name>
<role-name>viewer</role-name>
</auth-constraint>
</security-constraint>
<security-role>
<role-name>admin</role-name>
<role-name>viewer</role-name>
</security-role>
<login-config>

View File

@ -1,5 +1,4 @@
#!/bin/bash
#
# Copyright 2015-present Open Networking Foundation
#
@ -44,4 +43,4 @@ fi
file=$(basename $yang)
modelId="$(echo $file | sed -E 's/(.zip|.jar|.yang)$//g')"
curl $URL?modelId=$modelId -F"file=@$yang"
$curl $URL?modelId=$modelId -F"file=@$yang"

View File

@ -19,6 +19,7 @@ package org.onlab.rest;
import com.google.common.collect.ImmutableSet;
import org.onlab.rest.exceptions.BadRequestMapper;
import org.onlab.rest.exceptions.EntityNotFoundMapper;
import org.onlab.rest.exceptions.ForbiddenMapper;
import org.onlab.rest.exceptions.IllegalArgumentExceptionMapper;
import org.onlab.rest.exceptions.IllegalStateExceptionMapper;
import org.onlab.rest.exceptions.NotFoundMapper;
@ -43,7 +44,9 @@ public abstract class AbstractWebApplication extends Application {
*/
protected Set<Class<?>> getClasses(Class<?>... classes) {
ImmutableSet.Builder<Class<?>> builder = ImmutableSet.builder();
builder.add(ServiceNotFoundMapper.class,
builder.add(AuthorizationFilter.class,
ForbiddenMapper.class,
ServiceNotFoundMapper.class,
EntityNotFoundMapper.class,
NotFoundMapper.class,
ServerErrorMapper.class,

View File

@ -0,0 +1,59 @@
/*
* Copyright 2018-present Open Networking Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onlab.rest;
import com.google.common.collect.ImmutableSet;
import javax.ws.rs.ForbiddenException;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerRequestFilter;
import java.io.IOException;
import java.util.Set;
/**
* Filter that performs authorization checks on all incoming REST API requests.
* Methods with modify semantics require 'admin' role; all others require 'viewer' role.
*/
public class AuthorizationFilter implements ContainerRequestFilter {
private static final String ADMIN = "admin";
private static final String VIEWER = "viewer";
private static final String FORBIDDEN_MSG =
"User has insufficient privilege for this request";
private static final Set<String> PRIVILEGED_METHODS =
ImmutableSet.of("POST", "PUT", "DELETE", "PATCH");
private static boolean disableForTests = false;
@Override
public void filter(ContainerRequestContext requestContext) throws IOException {
if (disableForTests) {
return;
}
if ((PRIVILEGED_METHODS.contains(requestContext.getMethod()) &&
!requestContext.getSecurityContext().isUserInRole(ADMIN)) ||
!requestContext.getSecurityContext().isUserInRole(VIEWER)) {
throw new ForbiddenException(FORBIDDEN_MSG);
}
}
public static void disableForTests() {
disableForTests = true;
}
}

View File

@ -0,0 +1,32 @@
/*
* Copyright 2018-present Open Networking Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onlab.rest.exceptions;
import javax.ws.rs.ForbiddenException;
import javax.ws.rs.core.Response;
import javax.ws.rs.ext.Provider;
/**
* Mapper for service not found exceptions to the NOT_FOUND response code.
*/
@Provider
public class ForbiddenMapper extends AbstractMapper<ForbiddenException> {
@Override
protected Response.Status responseStatus() {
return Response.Status.FORBIDDEN;
}
}

View File

@ -29,11 +29,13 @@
</web-resource-collection>
<auth-constraint>
<role-name>admin</role-name>
<role-name>viewer</role-name>
</auth-constraint>
</security-constraint>
<security-role>
<role-name>admin</role-name>
<role-name>viewer</role-name>
</security-role>
<login-config>

View File

@ -23,6 +23,7 @@ import org.glassfish.jersey.test.spi.TestContainerException;
import org.glassfish.jersey.test.spi.TestContainerFactory;
import org.onlab.junit.TestUtils;
import org.onlab.osgi.ServiceDirectory;
import org.onlab.rest.AuthorizationFilter;
import org.onlab.rest.BaseResource;
/**
@ -49,6 +50,7 @@ public class ResourceTest extends JerseyTest {
private void configureProperties() {
set(TestProperties.CONTAINER_PORT, 0);
AuthorizationFilter.disableForTests();
}
/**