You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by rl...@apache.org on 2016/06/08 15:52:08 UTC
ambari git commit: AMBARI-16247. Authorizations given to role-based
principals must be dereferenced upon user login (rlevas)
Repository: ambari
Updated Branches:
refs/heads/trunk 671f3bde8 -> 8c1564e08
AMBARI-16247. Authorizations given to role-based principals must be dereferenced upon user login (rlevas)
Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/8c1564e0
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/8c1564e0
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/8c1564e0
Branch: refs/heads/trunk
Commit: 8c1564e083169196cf53b8c1a570bcf3c5f65e68
Parents: 671f3bd
Author: Robert Levas <rl...@hortonworks.com>
Authored: Wed Jun 8 11:52:01 2016 -0400
Committer: Robert Levas <rl...@hortonworks.com>
Committed: Wed Jun 8 11:52:01 2016 -0400
----------------------------------------------------------------------
.../server/security/authorization/Users.java | 46 +++++-
.../security/authorization/UsersTest.java | 145 +++++++++++++++++++
2 files changed, 188 insertions(+), 3 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ambari/blob/8c1564e0/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 545095d..f1abb90 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
@@ -44,7 +44,6 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
-import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.password.PasswordEncoder;
@@ -447,7 +446,7 @@ public class Users {
/**
* Grants AMBARI.ADMINISTRATOR privilege to provided user.
*
- * @param user user
+ * @param userId user id
*/
public synchronized void grantAdminPrivilege(Integer userId) {
final UserEntity user = userDAO.findByPK(userId);
@@ -466,7 +465,7 @@ public class Users {
/**
* Revokes AMBARI.ADMINISTRATOR privilege from provided user.
*
- * @param user user
+ * @param userId user id
*/
public synchronized void revokeAdminPrivilege(Integer userId) {
final UserEntity user = userDAO.findByPK(userId);
@@ -711,6 +710,23 @@ public class Users {
entityManagerProvider.get().getEntityManagerFactory().getCache().evictAll();
}
+ /**
+ * Gets the explicit and implicit authorities for the given user.
+ * <p>
+ * The explicit authorities are the authorities that have be explicitly set by assigning roles to
+ * a user. For example the Cluster Operator role on a given cluster gives that the ability to
+ * start and stop services in that cluster, among other privileges for that particular cluster.
+ * <p>
+ * The implicit authorities are the authorities that have been given to the roles themselves which
+ * in turn are granted to the users that have been assigned those roles. For example if the
+ * Cluster User role for a given cluster has been given View User access on a specified File View
+ * instance, then all users who have the Cluster User role for that cluster will implicitly be
+ * granted View User access on that File View instance.
+ *
+ * @param userName the username for the relevant user
+ * @param userType the user type for the relevant user
+ * @return the users collection of implicit and explicit granted authorities
+ */
public Collection<AmbariGrantedAuthority> getUserAuthorities(String userName, UserType userType) {
UserEntity userEntity = userDAO.findUserByNameAndType(userName, userType);
if (userEntity == null) {
@@ -730,12 +746,36 @@ public class Users {
List<PrivilegeEntity> privilegeEntities = privilegeDAO.findAllByPrincipal(principalEntities);
+ // A list of principals representing roles/permissions. This collection of roles will be used to
+ // find additional authorizations inherited by the authenticated user based on the assigned roles.
+ // For example a File View instance may be set to be accessible to all authenticated user with
+ // the Cluster User role.
+ List<PrincipalEntity> rolePrincipals = new ArrayList<PrincipalEntity>();
+
Set<AmbariGrantedAuthority> authorities = new HashSet<>(privilegeEntities.size());
for (PrivilegeEntity privilegeEntity : privilegeEntities) {
+ // Add the principal representing the role associated with this PrivilegeEntity to the collection
+ // of roles for the authenticated user.
+ PrincipalEntity rolePrincipal = privilegeEntity.getPermission().getPrincipal();
+ if(rolePrincipal != null) {
+ rolePrincipals.add(rolePrincipal);
+ }
+
authorities.add(new AmbariGrantedAuthority(privilegeEntity));
}
+ // If the collections of assigned roles is not empty find the inherited authorizations that are
+ // give to the roles and add them to the collection of (Granted) authorities for the user.
+ if(!rolePrincipals.isEmpty()) {
+ // For each "role" see if any privileges have been granted...
+ List<PrivilegeEntity> rolePrivilegeEntities = privilegeDAO.findAllByPrincipal(rolePrincipals);
+
+ for (PrivilegeEntity privilegeEntity : rolePrivilegeEntities) {
+ authorities.add(new AmbariGrantedAuthority(privilegeEntity));
+ }
+ }
+
return authorities;
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/8c1564e0/ambari-server/src/test/java/org/apache/ambari/server/security/authorization/UsersTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/security/authorization/UsersTest.java b/ambari-server/src/test/java/org/apache/ambari/server/security/authorization/UsersTest.java
new file mode 100644
index 0000000..f059abc
--- /dev/null
+++ b/ambari-server/src/test/java/org/apache/ambari/server/security/authorization/UsersTest.java
@@ -0,0 +1,145 @@
+/*
+ * 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.ambari.server.security.authorization;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+import junit.framework.Assert;
+import org.apache.ambari.server.orm.DBAccessor;
+import org.apache.ambari.server.orm.dao.MemberDAO;
+import org.apache.ambari.server.orm.dao.PrivilegeDAO;
+import org.apache.ambari.server.orm.dao.UserDAO;
+import org.apache.ambari.server.orm.entities.GroupEntity;
+import org.apache.ambari.server.orm.entities.MemberEntity;
+import org.apache.ambari.server.orm.entities.PermissionEntity;
+import org.apache.ambari.server.orm.entities.PrincipalEntity;
+import org.apache.ambari.server.orm.entities.PrivilegeEntity;
+import org.apache.ambari.server.orm.entities.UserEntity;
+import org.apache.ambari.server.state.stack.OsFamily;
+import org.easymock.Capture;
+import org.easymock.CaptureType;
+import org.easymock.EasyMockSupport;
+import org.junit.Test;
+import org.springframework.security.crypto.password.PasswordEncoder;
+
+import javax.persistence.EntityManager;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+import static org.easymock.EasyMock.capture;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.newCapture;
+
+public class UsersTest extends EasyMockSupport {
+ @Test
+ public void testGetUserAuthorities() throws Exception {
+ Injector injector = getInjector();
+
+ PrincipalEntity userPrincipalEntity = createMock(PrincipalEntity.class);
+
+ UserEntity userEntity = createMock(UserEntity.class);
+ expect(userEntity.getPrincipal()).andReturn(userPrincipalEntity).times(1);
+
+ UserDAO userDAO = injector.getInstance(UserDAO.class);
+ expect(userDAO.findUserByNameAndType("user1", UserType.LOCAL)).andReturn(userEntity).times(1);
+
+ PrincipalEntity groupPrincipalEntity = createMock(PrincipalEntity.class);
+
+ GroupEntity groupEntity = createMock(GroupEntity.class);
+ expect(groupEntity.getPrincipal()).andReturn(groupPrincipalEntity).times(1);
+
+ MemberEntity memberEntity = createMock(MemberEntity.class);
+ expect(memberEntity.getGroup()).andReturn(groupEntity).times(1);
+
+ MemberDAO memberDAO = injector.getInstance(MemberDAO.class);
+ expect(memberDAO.findAllMembersByUser(userEntity)).andReturn(Collections.singletonList(memberEntity)).times(1);
+
+ PrincipalEntity clusterUserPrivilegePermissionPrincipalEntity = createMock(PrincipalEntity.class);
+
+ PermissionEntity clusterUserPrivilegePermissionEntity = createMock(PermissionEntity.class);
+ expect(clusterUserPrivilegePermissionEntity.getPrincipal()).andReturn(clusterUserPrivilegePermissionPrincipalEntity).times(1);
+
+ PrivilegeEntity clusterUserPrivilegeEntity = createMock(PrivilegeEntity.class);
+ expect(clusterUserPrivilegeEntity.getPermission()).andReturn(clusterUserPrivilegePermissionEntity).times(1);
+
+ PrincipalEntity clusterOperatorPrivilegePermissionPrincipalEntity = createMock(PrincipalEntity.class);
+
+ PermissionEntity clusterOperatorPrivilegePermissionEntity = createMock(PermissionEntity.class);
+ expect(clusterOperatorPrivilegePermissionEntity.getPrincipal()).andReturn(clusterOperatorPrivilegePermissionPrincipalEntity).times(1);
+
+ PrivilegeEntity clusterOperatorPrivilegeEntity = createMock(PrivilegeEntity.class);
+ expect(clusterOperatorPrivilegeEntity.getPermission()).andReturn(clusterOperatorPrivilegePermissionEntity).times(1);
+
+ List<PrivilegeEntity> privilegeEntities = new ArrayList<PrivilegeEntity>();
+ privilegeEntities.add(clusterUserPrivilegeEntity);
+ privilegeEntities.add(clusterOperatorPrivilegeEntity);
+
+ PrivilegeEntity clusterUserViewUserPrivilegeEntity = createMock(PrivilegeEntity.class);
+
+ List<PrivilegeEntity> rolePrivilegeEntities = new ArrayList<PrivilegeEntity>();
+ rolePrivilegeEntities.add(clusterUserViewUserPrivilegeEntity);
+
+ Capture<? extends List<PrincipalEntity>> principalEntitiesCapture = newCapture();
+ Capture<? extends List<PrincipalEntity>> rolePrincipalEntitiesCapture = newCapture();
+
+ PrivilegeDAO privilegeDAO = injector.getInstance(PrivilegeDAO.class);
+ expect(privilegeDAO.findAllByPrincipal(capture(principalEntitiesCapture))).andReturn(privilegeEntities).times(1);
+ expect(privilegeDAO.findAllByPrincipal(capture(rolePrincipalEntitiesCapture))).andReturn(rolePrivilegeEntities).times(1);
+
+ replayAll();
+
+ Users user = injector.getInstance(Users.class);
+ Collection<AmbariGrantedAuthority> authorities = user.getUserAuthorities("user1", UserType.LOCAL);
+
+ verifyAll();
+
+ Assert.assertEquals(2, principalEntitiesCapture.getValue().size());
+ Assert.assertTrue(principalEntitiesCapture.getValue().contains(userPrincipalEntity));
+ Assert.assertTrue(principalEntitiesCapture.getValue().contains(groupPrincipalEntity));
+
+ Assert.assertEquals(2, rolePrincipalEntitiesCapture.getValue().size());
+ Assert.assertTrue(rolePrincipalEntitiesCapture.getValue().contains(clusterUserPrivilegePermissionPrincipalEntity));
+ Assert.assertTrue(rolePrincipalEntitiesCapture.getValue().contains(clusterOperatorPrivilegePermissionPrincipalEntity));
+
+
+ Assert.assertEquals(3, authorities.size());
+ Assert.assertTrue(authorities.contains(new AmbariGrantedAuthority(clusterUserPrivilegeEntity)));
+ Assert.assertTrue(authorities.contains(new AmbariGrantedAuthority(clusterOperatorPrivilegeEntity)));
+ Assert.assertTrue(authorities.contains(new AmbariGrantedAuthority(clusterUserViewUserPrivilegeEntity)));
+ }
+
+ private Injector getInjector() {
+ return Guice.createInjector(new AbstractModule() {
+ @Override
+ protected void configure() {
+ bind(EntityManager.class).toInstance(createMock(EntityManager.class));
+ bind(DBAccessor.class).toInstance(createMock(DBAccessor.class));
+ bind(OsFamily.class).toInstance(createNiceMock(OsFamily.class));
+ bind(UserDAO.class).toInstance(createMock(UserDAO.class));
+ bind(MemberDAO.class).toInstance(createMock(MemberDAO.class));
+ bind(PrivilegeDAO.class).toInstance(createMock(PrivilegeDAO.class));
+ bind(PasswordEncoder.class).toInstance(createMock(PasswordEncoder.class));
+ }
+ });
+ }
+}
\ No newline at end of file