Repository: zeppelin Updated Branches: refs/heads/master 767a50b41 -> d45d878a1
[ZEPPELIN-2913] Support for both user and role for AuthorizationFilter Currently, Zeppelin only supports roles for AuthorizationFilter, but there can be a condition as described in https://issues.apache.org/jira/browse/ZEPPELIN-2913 where Zeppelin's user does not belong to a group/role, and the administrator wants to have control using user only. [Feature] * [x] - Add documentation * https://issues.apache.org/jira/browse/ZEPPELIN-2913 add the following in shiro.ini: ``` [main] ... anyofroles = org.apache.zeppelin.utils.AnyOfRolesUserAuthorizationFilter [urls] ... /api/interpreter/** = authc, anyofroles[admin, user1] /api/configurations/** = authc, roles[admin] /api/credential/** = authc, roles[admin] ``` With the above config both user (user1) and users the belong to role admin will have access to interpreter setting page. Author: Prabhjyot Singh <prabhjyotsi...@gmail.com> Closes #3004 from prabhjyotsingh/ZEPPELIN-2913 and squashes the following commits: e05d72a9f [Prabhjyot Singh] rename AnyOfRolesAuthorizationFilter to AnyOfRolesUserAuthorizationFilter 724192ff4 [Prabhjyot Singh] add doc 53c0c034a [Prabhjyot Singh] [ZEPPELIN-2913] support for both user and role Change-Id: I63cdebf66d76a67cfca0054283c7d1c65a9b5805 Project: http://git-wip-us.apache.org/repos/asf/zeppelin/repo Commit: http://git-wip-us.apache.org/repos/asf/zeppelin/commit/d45d878a Tree: http://git-wip-us.apache.org/repos/asf/zeppelin/tree/d45d878a Diff: http://git-wip-us.apache.org/repos/asf/zeppelin/diff/d45d878a Branch: refs/heads/master Commit: d45d878a162d1012900f2de90314603a33323c5d Parents: 767a50b Author: Prabhjyot Singh <prabhjyotsi...@gmail.com> Authored: Wed Jun 6 09:11:52 2018 +0530 Committer: Prabhjyot Singh <prabhjyotsi...@gmail.com> Committed: Thu Jun 7 15:10:10 2018 +0530 ---------------------------------------------------------------------- docs/setup/security/shiro_authentication.md | 8 +-- .../zeppelin/integration/AuthenticationIT.java | 8 +-- .../utils/AnyOfRolesAuthorizationFilter.java | 52 -------------------- .../AnyOfRolesUserAuthorizationFilter.java | 50 +++++++++++++++++++ 4 files changed, 59 insertions(+), 59 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/zeppelin/blob/d45d878a/docs/setup/security/shiro_authentication.md ---------------------------------------------------------------------- diff --git a/docs/setup/security/shiro_authentication.md b/docs/setup/security/shiro_authentication.md index a51f77e..49b06c1 100644 --- a/docs/setup/security/shiro_authentication.md +++ b/docs/setup/security/shiro_authentication.md @@ -273,14 +273,16 @@ By default, Shiro will allow access to a URL if only user is part of "**all the /api/interpreter/** = authc, roles[admin, role1] ``` -If there is a need that user with "**any of the defined roles**" should be allowed, then following Shiro configuration can be used: +### Apply multiple roles or user in Shiro configuration +If there is a need that user with "**any of the defined roles or user itself**" should be allowed, then following Shiro configuration can be used: + ``` [main] -anyofroles = org.apache.zeppelin.utils.AnyOfRolesAuthorizationFilter +anyofrolesuser = org.apache.zeppelin.utils.AnyOfRolesUserAuthorizationFilter [urls] -/api/interpreter/** = authc, anyofroles[admin, role1] +/api/interpreter/** = authc, anyofrolesuser[admin, user1] /api/configurations/** = authc, roles[admin] /api/credential/** = authc, roles[admin] ``` http://git-wip-us.apache.org/repos/asf/zeppelin/blob/d45d878a/zeppelin-integration/src/test/java/org/apache/zeppelin/integration/AuthenticationIT.java ---------------------------------------------------------------------- diff --git a/zeppelin-integration/src/test/java/org/apache/zeppelin/integration/AuthenticationIT.java b/zeppelin-integration/src/test/java/org/apache/zeppelin/integration/AuthenticationIT.java index 4c194f3..ea6ad69 100644 --- a/zeppelin-integration/src/test/java/org/apache/zeppelin/integration/AuthenticationIT.java +++ b/zeppelin-integration/src/test/java/org/apache/zeppelin/integration/AuthenticationIT.java @@ -63,14 +63,14 @@ public class AuthenticationIT extends AbstractZeppelinIT { "securityManager.sessionManager = $sessionManager\n" + "securityManager.sessionManager.globalSessionTimeout = 86400000\n" + "shiro.loginUrl = /api/login\n" + - "anyofroles = org.apache.zeppelin.utils.AnyOfRolesAuthorizationFilter\n" + + "anyofrolesuser = org.apache.zeppelin.utils.AnyOfRolesUserAuthorizationFilter\n" + "[roles]\n" + "admin = *\n" + "hr = *\n" + "finance = *\n" + "[urls]\n" + "/api/version = anon\n" + - "/api/interpreter/** = authc, anyofroles[admin, finance]\n" + + "/api/interpreter/** = authc, anyofrolesuser[admin, finance]\n" + "/** = authc"; static String originalShiro = ""; @@ -172,7 +172,7 @@ public class AuthenticationIT extends AbstractZeppelinIT { } @Test - public void testAnyOfRoles() throws Exception { + public void testAnyOfRolesUser() throws Exception { try { AuthenticationIT authenticationIT = new AuthenticationIT(); authenticationIT.authenticationUser("admin", "password1"); @@ -220,7 +220,7 @@ public class AuthenticationIT extends AbstractZeppelinIT { authenticationIT.logoutUser("hr1"); } catch (Exception e) { - handleException("Exception in AuthenticationIT while testAnyOfRoles ", e); + handleException("Exception in AuthenticationIT while testAnyOfRolesUser ", e); } } http://git-wip-us.apache.org/repos/asf/zeppelin/blob/d45d878a/zeppelin-server/src/main/java/org/apache/zeppelin/utils/AnyOfRolesAuthorizationFilter.java ---------------------------------------------------------------------- diff --git a/zeppelin-server/src/main/java/org/apache/zeppelin/utils/AnyOfRolesAuthorizationFilter.java b/zeppelin-server/src/main/java/org/apache/zeppelin/utils/AnyOfRolesAuthorizationFilter.java deleted file mode 100644 index 61fa0b5..0000000 --- a/zeppelin-server/src/main/java/org/apache/zeppelin/utils/AnyOfRolesAuthorizationFilter.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You 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.apache.zeppelin.utils; - -import org.apache.shiro.subject.Subject; -import org.apache.shiro.web.filter.authz.RolesAuthorizationFilter; - -import java.io.IOException; - -import javax.servlet.ServletRequest; -import javax.servlet.ServletResponse; - -/** - * Allows access if current user has at least one role of the specified list. - * <p> - * Basically, it's the same as {@link RolesAuthorizationFilter} but using {@literal OR} instead - * of {@literal AND} on the specified roles. - */ -public class AnyOfRolesAuthorizationFilter extends RolesAuthorizationFilter { - @Override - public boolean isAccessAllowed(ServletRequest request, ServletResponse response, - Object mappedValue) throws IOException { - final Subject subject = getSubject(request, response); - final String[] rolesArray = (String[]) mappedValue; - - if (rolesArray == null || rolesArray.length == 0) { - //no roles specified, so nothing to check - allow access. - return true; - } - - for (String roleName : rolesArray) { - if (subject.hasRole(roleName)) { - return true; - } - } - return false; - } -} http://git-wip-us.apache.org/repos/asf/zeppelin/blob/d45d878a/zeppelin-server/src/main/java/org/apache/zeppelin/utils/AnyOfRolesUserAuthorizationFilter.java ---------------------------------------------------------------------- diff --git a/zeppelin-server/src/main/java/org/apache/zeppelin/utils/AnyOfRolesUserAuthorizationFilter.java b/zeppelin-server/src/main/java/org/apache/zeppelin/utils/AnyOfRolesUserAuthorizationFilter.java new file mode 100644 index 0000000..e345dd6 --- /dev/null +++ b/zeppelin-server/src/main/java/org/apache/zeppelin/utils/AnyOfRolesUserAuthorizationFilter.java @@ -0,0 +1,50 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.zeppelin.utils; + +import java.io.IOException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import org.apache.shiro.subject.Subject; +import org.apache.shiro.web.filter.authz.RolesAuthorizationFilter; + +/** + * Allows access if current user has at least one role of the specified list. + * <p> + * Basically, it's the same as {@link RolesAuthorizationFilter} but using {@literal OR} instead + * of {@literal AND} on the specified roles or user. + */ +public class AnyOfRolesUserAuthorizationFilter extends RolesAuthorizationFilter { + @Override + public boolean isAccessAllowed(ServletRequest request, ServletResponse response, + Object mappedValue) throws IOException { + final Subject subject = getSubject(request, response); + final String[] rolesArray = (String[]) mappedValue; + + if (rolesArray == null || rolesArray.length == 0) { + //no roles specified, so nothing to check - allow access. + return true; + } + + for (String roleName : rolesArray) { + if (subject.hasRole(roleName) || subject.getPrincipal().equals(roleName)) { + return true; + } + } + return false; + } +}