You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by jo...@apache.org on 2014/09/29 14:14:23 UTC

[11/16] git commit: AMBARI-7530. Admin: /users and /groups resources should only be accessible from AMBARI.ADMIN.

AMBARI-7530. Admin: /users and /groups resources should only be accessible from AMBARI.ADMIN.


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/f92ad8f5
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/f92ad8f5
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/f92ad8f5

Branch: refs/heads/branch-alerts-dev
Commit: f92ad8f520b230feaf6c0bc7d8c7248448566e0b
Parents: 1ea0f47
Author: Siddharth Wagle <sw...@hortonworks.com>
Authored: Fri Sep 26 17:15:55 2014 -0700
Committer: Siddharth Wagle <sw...@hortonworks.com>
Committed: Fri Sep 26 17:15:55 2014 -0700

----------------------------------------------------------------------
 .../server/orm/entities/ViewInstanceEntity.java |  34 +--
 .../AmbariAuthorizationFilter.java              |  81 +++++-
 .../server/security/authorization/Users.java    |   3 +-
 .../orm/entities/ViewInstanceEntityTest.java    |  19 +-
 .../AmbariAuthorizationFilterTest.java          | 266 ++++++++++++++++++-
 .../security/authorization/TestUsers.java       |   1 +
 6 files changed, 335 insertions(+), 69 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/f92ad8f5/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ViewInstanceEntity.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ViewInstanceEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ViewInstanceEntity.java
index f84be60..8f8712c 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ViewInstanceEntity.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ViewInstanceEntity.java
@@ -23,9 +23,6 @@ import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Map;
 import java.util.Set;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
 import javax.persistence.Basic;
 import javax.persistence.CascadeType;
 import javax.persistence.Column;
@@ -47,6 +44,7 @@ import javax.persistence.UniqueConstraint;
 import org.apache.ambari.server.controller.spi.Resource;
 import org.apache.ambari.server.security.SecurityHelper;
 import org.apache.ambari.server.security.SecurityHelperImpl;
+import org.apache.ambari.server.security.authorization.AmbariAuthorizationFilter;
 import org.apache.ambari.server.view.configuration.InstanceConfig;
 import org.apache.ambari.view.ResourceProvider;
 import org.apache.ambari.view.ViewDefinition;
@@ -70,15 +68,6 @@ import org.apache.ambari.view.ViewInstanceDefinition;
 )
 @Entity
 public class ViewInstanceEntity implements ViewInstanceDefinition {
-  /**
-   * The prefix for every view instance context path.
-   */
-  public static final String VIEWS_CONTEXT_PATH_PREFIX = "/views/";
-
-  /**
-   * The pattern for matching view instance context path.
-   */
-  public static final String VIEWS_CONTEXT_PATH_PATTERN = "" + VIEWS_CONTEXT_PATH_PREFIX + "([^/]+)/([^/]+)/([^/]+)(.*)";
 
   @Id
   @Column(name = "view_instance_id", nullable = false)
@@ -680,26 +669,7 @@ public class ViewInstanceEntity implements ViewInstanceDefinition {
    * @return the context path
    */
   public static String getContextPath(String viewName, String version, String viewInstanceName) {
-    return VIEWS_CONTEXT_PATH_PREFIX + viewName + "/" + version + "/" + viewInstanceName;
-  }
-
-  /**
-   * Parses context path into view name, version and instance name
-   *
-   * @param contextPath the context path
-   * @return null if context path doesn't match correct pattern
-   */
-  public static ViewInstanceVersionDTO parseContextPath(String contextPath) {
-    final Pattern pattern = Pattern.compile(VIEWS_CONTEXT_PATH_PATTERN);
-    Matcher matcher = pattern.matcher(contextPath);
-    if (!matcher.matches()) {
-      return null;
-    } else {
-      final String viewName = matcher.group(1);
-      final String version = matcher.group(2);
-      final String instanceName = matcher.group(3);
-      return new ViewInstanceVersionDTO(viewName, version, instanceName);
-    }
+    return AmbariAuthorizationFilter.VIEWS_CONTEXT_PATH_PREFIX + viewName + "/" + version + "/" + viewInstanceName;
   }
 
   /**

http://git-wip-us.apache.org/repos/asf/ambari/blob/f92ad8f5/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/AmbariAuthorizationFilter.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/AmbariAuthorizationFilter.java b/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/AmbariAuthorizationFilter.java
index 658fc80..f1c2a26 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/AmbariAuthorizationFilter.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/AmbariAuthorizationFilter.java
@@ -32,7 +32,6 @@ import javax.servlet.http.HttpServletResponse;
 
 import org.apache.ambari.server.orm.entities.PermissionEntity;
 import org.apache.ambari.server.orm.entities.PrivilegeEntity;
-import org.apache.ambari.server.orm.entities.ViewInstanceEntity;
 import org.apache.ambari.server.orm.entities.ViewInstanceEntity.ViewInstanceVersionDTO;
 import org.apache.ambari.server.security.authorization.internal.InternalAuthenticationToken;
 import org.apache.ambari.server.view.ViewRegistry;
@@ -50,6 +49,19 @@ public class AmbariAuthorizationFilter implements Filter {
 
   private static final Pattern STACK_ADVISOR_REGEX = Pattern.compile("/api/v[0-9]+/stacks/[^/]+/versions/[^/]+/validations.*");
 
+  public static final String API_VERSION_PREFIX        = "/api/v[0-9]+";
+  public static final String VIEWS_CONTEXT_PATH_PREFIX = "/views/";
+
+  private static final String VIEWS_CONTEXT_PATH_PATTERN       = VIEWS_CONTEXT_PATH_PREFIX + "([^/]+)/([^/]+)/([^/]+)(.*)";
+  private static final String VIEWS_CONTEXT_ALL_PATTERN        = VIEWS_CONTEXT_PATH_PREFIX + ".*";
+  private static final String API_USERS_USERNAME_PATTERN       = API_VERSION_PREFIX + "/users/([^/?]+)(.*)";
+  private static final String API_USERS_ALL_PATTERN            = API_VERSION_PREFIX + "/users.*";
+  private static final String API_GROUPS_ALL_PATTERN           = API_VERSION_PREFIX + "/groups.*";
+  private static final String API_CLUSTERS_ALL_PATTERN         = API_VERSION_PREFIX + "/clusters.*";
+  private static final String API_VIEWS_ALL_PATTERN            = API_VERSION_PREFIX + "/views.*";
+  private static final String API_PERSIST_ALL_PATTERN          = API_VERSION_PREFIX + "/persist.*";
+  private static final String API_LDAP_SYNC_EVENTS_ALL_PATTERN = API_VERSION_PREFIX + "/ldap_sync_events.*";
+
   /**
    * The realm to use for the basic http auth
    */
@@ -92,8 +104,8 @@ public class AmbariAuthorizationFilter implements Filter {
             break;
           }
 
-          if (requestURI.matches("/api/v[0-9]+/clusters.*")) {
             // clusters require permission
+	  if (requestURI.matches(API_CLUSTERS_ALL_PATTERN)) {
             if (permissionId.equals(PermissionEntity.CLUSTER_READ_PERMISSION) ||
                 permissionId.equals(PermissionEntity.CLUSTER_OPERATE_PERMISSION)) {
               authorized = true;
@@ -105,13 +117,13 @@ public class AmbariAuthorizationFilter implements Filter {
               authorized = true;
               break;
             }
-          } else if (requestURI.matches("/api/v[0-9]+/views.*")) {
+	  } else if (requestURI.matches(API_VIEWS_ALL_PATTERN)) {
             // views require permission
             if (permissionId.equals(PermissionEntity.VIEW_USE_PERMISSION)) {
               authorized = true;
               break;
             }
-          } else if (requestURI.matches("/api/v[0-9]+/persist.*")) {
+          } else if (requestURI.matches(API_PERSIST_ALL_PATTERN)) {
             if (permissionId.equals(PermissionEntity.CLUSTER_OPERATE_PERMISSION)) {
               authorized = true;
               break;
@@ -120,14 +132,26 @@ public class AmbariAuthorizationFilter implements Filter {
         }
       }
 
-      if (!authorized && requestURI.matches(ViewInstanceEntity.VIEWS_CONTEXT_PATH_PATTERN)) {
-        final ViewInstanceVersionDTO dto = ViewInstanceEntity.parseContextPath(requestURI);
-        authorized = ViewRegistry.getInstance().checkPermission(dto.getViewName(), dto.getVersion(), dto.getInstanceName(), true);
+      if (!authorized && requestURI.matches(VIEWS_CONTEXT_PATH_PATTERN)) {
+        final ViewInstanceVersionDTO dto = parseViewInstanceInfo(requestURI);
+        authorized = getViewRegistry().checkPermission(dto.getViewName(), dto.getVersion(), dto.getInstanceName(), true);
       }
 
-      // allow GET for everything except views
+      // allow all types of requests for /users/{current_user}
+      if (!authorized && requestURI.matches(API_USERS_USERNAME_PATTERN)) {
+        final SecurityContext securityContext = getSecurityContext();
+        final String currentUserName = securityContext.getAuthentication().getName();
+        final String urlUserName = parseUserName(requestURI);
+        authorized = currentUserName.equalsIgnoreCase(urlUserName);
+      }
+
+      // allow GET for everything except /views, /api/v1/users, /api/v1/groups, /api/v1/ldap_sync_events
       if (!authorized &&
-          (!httpRequest.getMethod().equals("GET") || requestURI.matches("/views.*"))) {
+          (!httpRequest.getMethod().equals("GET")
+              || requestURI.matches(VIEWS_CONTEXT_ALL_PATTERN)
+              || requestURI.matches(API_USERS_ALL_PATTERN)
+              || requestURI.matches(API_GROUPS_ALL_PATTERN)
+              || requestURI.matches(API_LDAP_SYNC_EVENTS_ALL_PATTERN))) {
 
         httpResponse.setHeader("WWW-Authenticate", "Basic realm=\"" + realm + "\"");
         httpResponse.sendError(HttpServletResponse.SC_FORBIDDEN, "You do not have permissions to access this resource.");
@@ -166,7 +190,46 @@ public class AmbariAuthorizationFilter implements Filter {
     return value == null || value.length() == 0 ? defaultValue : value;
   }
 
+  /**
+   * Parses context path into view name, version and instance name
+   *
+   * @param contextPath the context path
+   * @return null if context path doesn't match correct pattern
+   */
+  static ViewInstanceVersionDTO parseViewInstanceInfo(String contextPath) {
+    final Pattern pattern = Pattern.compile(VIEWS_CONTEXT_PATH_PATTERN);
+    final Matcher matcher = pattern.matcher(contextPath);
+    if (!matcher.matches()) {
+      return null;
+    } else {
+      final String viewName = matcher.group(1);
+      final String version = matcher.group(2);
+      final String instanceName = matcher.group(3);
+      return new ViewInstanceVersionDTO(viewName, version, instanceName);
+    }
+  }
+
+  /**
+   * Parses url to get user name.
+   *
+   * @param url the url
+   * @return null if url doesn't match correct pattern
+   */
+  static String parseUserName(String url) {
+    final Pattern pattern = Pattern.compile(API_USERS_USERNAME_PATTERN);
+    final Matcher matcher = pattern.matcher(url);
+    if (!matcher.matches()) {
+      return null;
+    } else {
+      return matcher.group(1);
+    }
+  }
+
   SecurityContext getSecurityContext() {
     return SecurityContextHolder.getContext();
   }
+
+  ViewRegistry getViewRegistry() {
+    return ViewRegistry.getInstance();
+  }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/f92ad8f5/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/Users.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/Users.java b/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/Users.java
index 26daa1b..1cd3fc8 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/Users.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/Users.java
@@ -24,7 +24,6 @@ import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
-
 import javax.persistence.EntityManager;
 
 import org.apache.ambari.server.AmbariException;
@@ -66,7 +65,7 @@ import com.google.inject.persist.Transactional;
 @Singleton
 public class Users {
 
-  private final static Logger LOG = LoggerFactory.getLogger(Users.class);
+  private static final Logger LOG = LoggerFactory.getLogger(Users.class);
 
   @Inject
   Provider<EntityManager> entityManagerProvider;

http://git-wip-us.apache.org/repos/asf/ambari/blob/f92ad8f5/ambari-server/src/test/java/org/apache/ambari/server/orm/entities/ViewInstanceEntityTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/orm/entities/ViewInstanceEntityTest.java b/ambari-server/src/test/java/org/apache/ambari/server/orm/entities/ViewInstanceEntityTest.java
index c0545da..08aea6e 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/orm/entities/ViewInstanceEntityTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/orm/entities/ViewInstanceEntityTest.java
@@ -20,8 +20,8 @@ package org.apache.ambari.server.orm.entities;
 
 import org.apache.ambari.server.configuration.Configuration;
 import org.apache.ambari.server.controller.spi.Resource;
-import org.apache.ambari.server.orm.entities.ViewInstanceEntity.ViewInstanceVersionDTO;
 import org.apache.ambari.server.security.SecurityHelper;
+import org.apache.ambari.server.security.authorization.AmbariAuthorizationFilter;
 import org.apache.ambari.server.view.ViewRegistryTest;
 import org.apache.ambari.server.view.configuration.InstanceConfig;
 import org.apache.ambari.server.view.configuration.InstanceConfigTest;
@@ -295,26 +295,11 @@ public class ViewInstanceEntityTest {
   public void testContextPath() throws Exception {
     ViewInstanceEntity viewInstanceDefinition = getViewInstanceEntity();
 
-    Assert.assertEquals(ViewInstanceEntity.VIEWS_CONTEXT_PATH_PREFIX + "MY_VIEW/1.0.0/INSTANCE1",
+    Assert.assertEquals(AmbariAuthorizationFilter.VIEWS_CONTEXT_PATH_PREFIX + "MY_VIEW/1.0.0/INSTANCE1",
         viewInstanceDefinition.getContextPath());
   }
 
   @Test
-  public void testParseContextPath() throws Exception {
-    final String[] pathesToTest = {
-        ViewInstanceEntity.VIEWS_CONTEXT_PATH_PREFIX + "MY_VIEW/1.0.0/INSTANCE1",
-        ViewInstanceEntity.VIEWS_CONTEXT_PATH_PREFIX + "MY_VIEW/1.0.0/INSTANCE1/index.html",
-        ViewInstanceEntity.VIEWS_CONTEXT_PATH_PREFIX + "MY_VIEW/1.0.0/INSTANCE1/api/test"
-    };
-    for (String contextPath: pathesToTest) {
-      final ViewInstanceVersionDTO dto = ViewInstanceEntity.parseContextPath(contextPath);
-      Assert.assertEquals("INSTANCE1", dto.getInstanceName());
-      Assert.assertEquals("MY_VIEW", dto.getViewName());
-      Assert.assertEquals("1.0.0", dto.getVersion());
-    }
-  }
-
-  @Test
   public void testInstanceData() throws Exception {
     TestSecurityHelper securityHelper = new TestSecurityHelper("user1");
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/f92ad8f5/ambari-server/src/test/java/org/apache/ambari/server/security/authorization/AmbariAuthorizationFilterTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/security/authorization/AmbariAuthorizationFilterTest.java b/ambari-server/src/test/java/org/apache/ambari/server/security/authorization/AmbariAuthorizationFilterTest.java
index a950eb6..116b6ec 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/security/authorization/AmbariAuthorizationFilterTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/security/authorization/AmbariAuthorizationFilterTest.java
@@ -18,23 +18,40 @@
 
 package org.apache.ambari.server.security.authorization;
 
+import static org.easymock.EasyMock.createMockBuilder;
+import static org.easymock.EasyMock.createNiceMock;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
+import static org.easymock.EasyMock.verify;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import junit.framework.Assert;
+
 import org.apache.ambari.server.orm.entities.PermissionEntity;
 import org.apache.ambari.server.orm.entities.PrivilegeEntity;
+import org.apache.ambari.server.orm.entities.ViewInstanceEntity.ViewInstanceVersionDTO;
+import org.apache.ambari.server.view.ViewRegistry;
 import org.easymock.EasyMock;
-import org.junit.BeforeClass;
+import org.easymock.IAnswer;
 import org.junit.Test;
 import org.springframework.security.core.Authentication;
 import org.springframework.security.core.GrantedAuthority;
 import org.springframework.security.core.context.SecurityContext;
 
-import javax.servlet.FilterChain;
-import javax.servlet.FilterConfig;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import java.util.Collection;
-import java.util.Collections;
-
-import static org.easymock.EasyMock.*;
+import com.google.common.collect.HashBasedTable;
+import com.google.common.collect.Table;
+import com.google.common.collect.Table.Cell;
 
 public class AmbariAuthorizationFilterTest {
 
@@ -121,4 +138,235 @@ public class AmbariAuthorizationFilterTest {
     verify(request, response, chain, filter, securityContext, authentication, authority,
         privilegeEntity, permission, filterConfig);
   }
+
+  @Test
+  public void testDoFilter_adminAccess() throws Exception {
+    final Table<String, String, Boolean> urlTests = HashBasedTable.create();
+    urlTests.put("/api/v1/clusters/cluster", "GET",  true);
+    urlTests.put("/api/v1/clusters/cluster", "POST",  true);
+    urlTests.put("/api/v1/views", "GET", true);
+    urlTests.put("/api/v1/views", "POST", true);
+    urlTests.put("/api/v1/persist/SomeValue", "GET", true);
+    urlTests.put("/api/v1/persist/SomeValue", "POST", true);
+    urlTests.put("/views/AllowedView/SomeVersion/SomeInstance", "GET", true);
+    urlTests.put("/views/AllowedView/SomeVersion/SomeInstance", "POST", true);
+    urlTests.put("/views/DeniedView/AnotherVersion/AnotherInstance", "GET", true);
+    urlTests.put("/views/DeniedView/AnotherVersion/AnotherInstance", "POST", true);
+    urlTests.put("/api/v1/users/user1", "GET", true);
+    urlTests.put("/api/v1/users/user1", "POST", true);
+    urlTests.put("/api/v1/users/user2", "GET", true);
+    urlTests.put("/api/v1/users/user2", "POST", true);
+    urlTests.put("/api/v1/groups", "GET", true);
+    urlTests.put("/api/v1/ldap_sync_events", "GET", true);
+    urlTests.put("/any/other/URL", "GET", true);
+    urlTests.put("/any/other/URL", "POST", true);
+
+    performGeneralDoFilterTest("admin", new int[] {PermissionEntity.AMBARI_ADMIN_PERMISSION}, urlTests);
+  }
+
+  @Test
+  public void testDoFilter_clusterViewerAccess() throws Exception {
+    final Table<String, String, Boolean> urlTests = HashBasedTable.create();
+    urlTests.put("/api/v1/clusters/cluster", "GET",  true);
+    urlTests.put("/api/v1/clusters/cluster", "POST",  true);
+    urlTests.put("/api/v1/views", "GET", true);
+    urlTests.put("/api/v1/views", "POST", false);
+    urlTests.put("/api/v1/persist/SomeValue", "GET", true);
+    urlTests.put("/api/v1/persist/SomeValue", "POST", false);
+    urlTests.put("/views/AllowedView/SomeVersion/SomeInstance", "GET", false);
+    urlTests.put("/views/AllowedView/SomeVersion/SomeInstance", "POST", false);
+    urlTests.put("/views/DeniedView/AnotherVersion/AnotherInstance", "GET", false);
+    urlTests.put("/views/DeniedView/AnotherVersion/AnotherInstance", "POST", false);
+    urlTests.put("/api/v1/users/user1", "GET", true);
+    urlTests.put("/api/v1/users/user1", "POST", true);
+    urlTests.put("/api/v1/users/user2", "GET", false);
+    urlTests.put("/api/v1/users/user2", "POST", false);
+    urlTests.put("/api/v1/groups", "GET", false);
+    urlTests.put("/api/v1/ldap_sync_events", "GET", false);
+    urlTests.put("/any/other/URL", "GET", true);
+    urlTests.put("/any/other/URL", "POST", false);
+
+    performGeneralDoFilterTest("user1", new int[] {PermissionEntity.CLUSTER_READ_PERMISSION}, urlTests);
+  }
+
+  @Test
+  public void testDoFilter_clusterOperatorAccess() throws Exception {
+    final Table<String, String, Boolean> urlTests = HashBasedTable.create();
+    urlTests.put("/api/v1/clusters/cluster", "GET",  true);
+    urlTests.put("/api/v1/clusters/cluster", "POST",  true);
+    urlTests.put("/api/v1/views", "GET", true);
+    urlTests.put("/api/v1/views", "POST", false);
+    urlTests.put("/api/v1/persist/SomeValue", "GET", true);
+    urlTests.put("/api/v1/persist/SomeValue", "POST", true);
+    urlTests.put("/views/AllowedView/SomeVersion/SomeInstance", "GET", false);
+    urlTests.put("/views/AllowedView/SomeVersion/SomeInstance", "POST", false);
+    urlTests.put("/views/DeniedView/AnotherVersion/AnotherInstance", "GET", false);
+    urlTests.put("/views/DeniedView/AnotherVersion/AnotherInstance", "POST", false);
+    urlTests.put("/api/v1/users/user1", "GET", true);
+    urlTests.put("/api/v1/users/user1", "POST", true);
+    urlTests.put("/api/v1/users/user2", "GET", false);
+    urlTests.put("/api/v1/users/user2", "POST", false);
+    urlTests.put("/api/v1/groups", "GET", false);
+    urlTests.put("/api/v1/ldap_sync_events", "GET", false);
+    urlTests.put("/any/other/URL", "GET", true);
+    urlTests.put("/any/other/URL", "POST", false);
+
+    performGeneralDoFilterTest("user1", new int[] {PermissionEntity.CLUSTER_OPERATE_PERMISSION}, urlTests);
+  }
+
+  @Test
+  public void testDoFilter_viewUserAccess() throws Exception {
+    final Table<String, String, Boolean> urlTests = HashBasedTable.create();
+    urlTests.put("/api/v1/clusters/cluster", "GET",  true);
+    urlTests.put("/api/v1/clusters/cluster", "POST",  false);
+    urlTests.put("/api/v1/views", "GET", true);
+    urlTests.put("/api/v1/views", "POST", true);
+    urlTests.put("/api/v1/persist/SomeValue", "GET", true);
+    urlTests.put("/api/v1/persist/SomeValue", "POST", false);
+    urlTests.put("/views/AllowedView/SomeVersion/SomeInstance", "GET", true);
+    urlTests.put("/views/AllowedView/SomeVersion/SomeInstance", "POST", true);
+    urlTests.put("/views/DeniedView/AnotherVersion/AnotherInstance", "GET", false);
+    urlTests.put("/views/DeniedView/AnotherVersion/AnotherInstance", "POST", false);
+    urlTests.put("/api/v1/users/user1", "GET", true);
+    urlTests.put("/api/v1/users/user1", "POST", true);
+    urlTests.put("/api/v1/users/user2", "GET", false);
+    urlTests.put("/api/v1/users/user2", "POST", false);
+    urlTests.put("/api/v1/groups", "GET", false);
+    urlTests.put("/api/v1/ldap_sync_events", "GET", false);
+    urlTests.put("/any/other/URL", "GET", true);
+    urlTests.put("/any/other/URL", "POST", false);
+
+    performGeneralDoFilterTest("user1", new int[] {PermissionEntity.VIEW_USE_PERMISSION}, urlTests);
+  }
+
+  @Test
+  public void testDoFilter_userNoPermissionsAccess() throws Exception {
+    final Table<String, String, Boolean> urlTests = HashBasedTable.create();
+    urlTests.put("/api/v1/clusters/cluster", "GET",  true);
+    urlTests.put("/api/v1/clusters/cluster", "POST",  false);
+    urlTests.put("/api/v1/views", "GET", true);
+    urlTests.put("/api/v1/views", "POST", false);
+    urlTests.put("/api/v1/persist/SomeValue", "GET", true);
+    urlTests.put("/api/v1/persist/SomeValue", "POST", false);
+    urlTests.put("/views/AllowedView/SomeVersion/SomeInstance", "GET", false);
+    urlTests.put("/views/AllowedView/SomeVersion/SomeInstance", "POST", false);
+    urlTests.put("/views/DeniedView/AnotherVersion/AnotherInstance", "GET", false);
+    urlTests.put("/views/DeniedView/AnotherVersion/AnotherInstance", "POST", false);
+    urlTests.put("/api/v1/users/user1", "GET", false);
+    urlTests.put("/api/v1/users/user1", "POST", false);
+    urlTests.put("/api/v1/users/user2", "GET", true);
+    urlTests.put("/api/v1/users/user2", "POST", true);
+    urlTests.put("/any/other/URL", "GET", true);
+    urlTests.put("/any/other/URL", "POST", false);
+
+    performGeneralDoFilterTest("user2", new int[0], urlTests);
+  }
+
+  /**
+   * Creates mocks with given permissions and performs all given url tests.
+   *
+   * @param username user name
+   * @param permissionsGranted array of user permissions
+   * @param urlTests map of triples: url - http method - is allowed
+   * @throws Exception
+   */
+  private void performGeneralDoFilterTest(String username, final int[] permissionsGranted, Table<String, String, Boolean> urlTests) throws Exception {
+    final SecurityContext securityContext = createNiceMock(SecurityContext.class);
+    final Authentication authentication = createNiceMock(Authentication.class);
+    final FilterConfig filterConfig = createNiceMock(FilterConfig.class);
+    final AmbariAuthorizationFilter filter = createMockBuilder(AmbariAuthorizationFilter.class)
+        .addMockedMethod("getSecurityContext").addMockedMethod("getViewRegistry").withConstructor().createMock();
+    final List<AmbariGrantedAuthority> authorities = new ArrayList<AmbariGrantedAuthority>();
+    final ViewRegistry viewRegistry = createNiceMock(ViewRegistry.class);
+
+    for (int permissionGranted: permissionsGranted) {
+      final AmbariGrantedAuthority authority = createNiceMock(AmbariGrantedAuthority.class);
+      final PrivilegeEntity privilegeEntity = createNiceMock(PrivilegeEntity.class);
+      final PermissionEntity permission = createNiceMock(PermissionEntity.class);
+
+      expect(authority.getPrivilegeEntity()).andReturn(privilegeEntity).anyTimes();
+      expect(privilegeEntity.getPermission()).andReturn(permission).anyTimes();
+      expect(permission.getId()).andReturn(permissionGranted).anyTimes();
+
+      replay(authority, privilegeEntity, permission);
+      authorities.add(authority);
+    }
+
+    EasyMock.<Collection<? extends GrantedAuthority>>expect(authentication.getAuthorities()).andReturn(authorities).anyTimes();
+    expect(filterConfig.getInitParameter("realm")).andReturn("AuthFilter").anyTimes();
+    expect(authentication.isAuthenticated()).andReturn(true).anyTimes();
+    expect(authentication.getName()).andReturn(username).anyTimes();
+    expect(filter.getSecurityContext()).andReturn(securityContext).anyTimes();
+    expect(filter.getViewRegistry()).andReturn(viewRegistry).anyTimes();
+    expect(securityContext.getAuthentication()).andReturn(authentication).anyTimes();
+    expect(viewRegistry.checkPermission(EasyMock.eq("AllowedView"), EasyMock.<String>anyObject(), EasyMock.<String>anyObject(), EasyMock.anyBoolean())).andAnswer(new IAnswer<Boolean>() {
+      @Override
+      public Boolean answer() throws Throwable {
+        for (int permissionGranted: permissionsGranted) {
+          if (permissionGranted == PermissionEntity.VIEW_USE_PERMISSION) {
+            return true;
+          }
+        }
+        return false;
+      }
+    }).anyTimes();
+    expect(viewRegistry.checkPermission(EasyMock.eq("DeniedView"), EasyMock.<String>anyObject(), EasyMock.<String>anyObject(), EasyMock.anyBoolean())).andReturn(false).anyTimes();
+
+    replay(authentication, filterConfig, filter, securityContext, viewRegistry);
+
+    for (final Cell<String, String, Boolean> urlTest: urlTests.cellSet()) {
+      final FilterChain chain = EasyMock.createStrictMock(FilterChain.class);
+      final HttpServletRequest request = createNiceMock(HttpServletRequest.class);
+      final HttpServletResponse response = createNiceMock(HttpServletResponse.class);
+
+      expect(request.getRequestURI()).andReturn(urlTest.getRowKey()).anyTimes();
+      expect(request.getMethod()).andReturn(urlTest.getColumnKey()).anyTimes();
+      if (urlTest.getValue()) {
+        chain.doFilter(EasyMock.<ServletRequest>anyObject(), EasyMock.<ServletResponse>anyObject());
+        EasyMock.expectLastCall().once();
+      }
+
+      replay(request, response, chain);
+
+      try {
+        filter.doFilter(request, response, chain);
+      } catch (AssertionError error) {
+        throw new Exception("doFilter() should not be chained on " + urlTest.getColumnKey() + " " + urlTest.getRowKey(), error);
+      }
+
+      try {
+        verify(chain);
+      } catch (AssertionError error) {
+        throw new Exception("verify( failed on " + urlTest.getColumnKey() + " " + urlTest.getRowKey(), error);
+      }
+    }
+  }
+
+  @Test
+  public void testParseUserName() throws Exception {
+    final String[] pathesToTest = {
+        "/api/v1/users/user",
+        "/api/v1/users/user?fields=*",
+        "/api/v22/users/user?fields=*"
+    };
+    for (String contextPath: pathesToTest) {
+      final String username = AmbariAuthorizationFilter.parseUserName(contextPath);
+      Assert.assertEquals("user", username);
+    }
+  }
+
+  @Test
+  public void testParseViewContextPath() throws Exception {
+    final String[] pathesToTest = {
+        AmbariAuthorizationFilter.VIEWS_CONTEXT_PATH_PREFIX + "MY_VIEW/1.0.0/INSTANCE1",
+        AmbariAuthorizationFilter.VIEWS_CONTEXT_PATH_PREFIX + "MY_VIEW/1.0.0/INSTANCE1/index.html",
+        AmbariAuthorizationFilter.VIEWS_CONTEXT_PATH_PREFIX + "MY_VIEW/1.0.0/INSTANCE1/api/test"
+    };
+    for (String contextPath: pathesToTest) {
+      final ViewInstanceVersionDTO dto = AmbariAuthorizationFilter.parseViewInstanceInfo(contextPath);
+      Assert.assertEquals("INSTANCE1", dto.getInstanceName());
+      Assert.assertEquals("MY_VIEW", dto.getViewName());
+      Assert.assertEquals("1.0.0", dto.getVersion());
+    }
+  }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/f92ad8f5/ambari-server/src/test/java/org/apache/ambari/server/security/authorization/TestUsers.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/security/authorization/TestUsers.java b/ambari-server/src/test/java/org/apache/ambari/server/security/authorization/TestUsers.java
index 5487db8..dbdb469 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/security/authorization/TestUsers.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/security/authorization/TestUsers.java
@@ -313,4 +313,5 @@ public class TestUsers {
 
     userDAO.merge(ldapUser);
   }
+
 }