You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by sm...@apache.org on 2018/08/31 08:01:29 UTC

[ambari] branch trunk updated: AMBARI-24546. Only authenticated users with proper AMBARI/CLUSTER authorization roles can query Ambari Request related information (#2198)

This is an automated email from the ASF dual-hosted git repository.

smolnar pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/ambari.git


The following commit(s) were added to refs/heads/trunk by this push:
     new 8a79291  AMBARI-24546. Only authenticated users with proper AMBARI/CLUSTER authorization roles can query Ambari Request related information (#2198)
8a79291 is described below

commit 8a79291ff36b23014a14261c703658437db9acc3
Author: Sandor Molnar <sm...@apache.org>
AuthorDate: Fri Aug 31 10:01:25 2018 +0200

    AMBARI-24546. Only authenticated users with proper AMBARI/CLUSTER authorization roles can query Ambari Request related information (#2198)
---
 .../internal/RequestResourceProvider.java          | 26 +++++++++++-
 .../security/authorization/RoleAuthorization.java  |  1 +
 .../ambari/server/upgrade/UpgradeCatalog272.java   |  7 ++++
 .../internal/RequestResourceProviderTest.java      | 47 ++++++++++++++++++++++
 .../server/upgrade/UpgradeCatalog272Test.java      | 10 ++++-
 5 files changed, 88 insertions(+), 3 deletions(-)

diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/RequestResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/RequestResourceProvider.java
index 0b9bce0..d5222d2 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/RequestResourceProvider.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/RequestResourceProvider.java
@@ -21,6 +21,10 @@ import static org.apache.ambari.server.controller.internal.HostComponentResource
 import static org.apache.ambari.server.controller.internal.HostComponentResourceProvider.COMPONENT_NAME;
 import static org.apache.ambari.server.controller.internal.HostComponentResourceProvider.HOST_NAME;
 import static org.apache.ambari.server.controller.internal.HostComponentResourceProvider.SERVICE_NAME;
+import static org.apache.ambari.server.security.authorization.RoleAuthorization.AMBARI_VIEW_STATUS_INFO;
+import static org.apache.ambari.server.security.authorization.RoleAuthorization.CLUSTER_VIEW_STATUS_INFO;
+import static org.apache.ambari.server.security.authorization.RoleAuthorization.HOST_VIEW_STATUS_INFO;
+import static org.apache.ambari.server.security.authorization.RoleAuthorization.SERVICE_VIEW_STATUS_INFO;
 
 import java.util.ArrayList;
 import java.util.Collection;
@@ -295,9 +299,9 @@ public class RequestResourceProvider extends AbstractControllerResourceProvider
     Boolean ascOrder = (ascOrderRaw == null ? null : Boolean.parseBoolean(ascOrderRaw));
 
     if (null == predicate) {
+      authorizeGetResources(null);
       // the no-arg call to /requests is here
-      resources.addAll(
-          getRequestResources(null, null, null, maxResults, ascOrder, requestedIds));
+      resources.addAll(getRequestResources(null, null, null, maxResults, ascOrder, requestedIds));
     } else {
       // process /requests with a predicate
       // process /clusters/[cluster]/requests
@@ -316,6 +320,7 @@ public class RequestResourceProvider extends AbstractControllerResourceProvider
           requestStatus = (String) properties.get(REQUEST_STATUS_PROPERTY_ID);
         }
 
+        authorizeGetResources(clusterName);
         resources.addAll(getRequestResources(clusterName, requestId, requestStatus, maxResults,
             ascOrder, requestedIds));
       }
@@ -324,6 +329,23 @@ public class RequestResourceProvider extends AbstractControllerResourceProvider
     return resources;
   }
 
+  private void authorizeGetResources(String clusterName) throws NoSuchParentResourceException, AuthorizationException {
+    final boolean ambariLevelRequest = StringUtils.isBlank(clusterName);
+    final ResourceType resourceType = ambariLevelRequest ? ResourceType.AMBARI : ResourceType.CLUSTER;
+    Long resourceId;
+    try {
+      resourceId = ambariLevelRequest ? null : getClusterResourceId(clusterName);
+    } catch (AmbariException e) {
+      throw new NoSuchParentResourceException("Error while fetching cluster resource ID", e);
+    }
+    final Set<RoleAuthorization> requiredAuthorizations = ambariLevelRequest ? Sets.newHashSet(AMBARI_VIEW_STATUS_INFO)
+        : Sets.newHashSet(CLUSTER_VIEW_STATUS_INFO, HOST_VIEW_STATUS_INFO, SERVICE_VIEW_STATUS_INFO);
+
+    if (!AuthorizationHelper.isAuthorized(resourceType, resourceId, requiredAuthorizations)) {
+      throw new AuthorizationException(String.format("The authenticated user is not authorized to fetch request related information."));
+    }
+  }
+
   @Override
   public RequestStatus updateResources(Request requestInfo, Predicate predicate)
           throws SystemException, UnsupportedPropertyException,
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/RoleAuthorization.java b/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/RoleAuthorization.java
index 3c50628..a079db1 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/RoleAuthorization.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/RoleAuthorization.java
@@ -40,6 +40,7 @@ public enum RoleAuthorization {
   AMBARI_RENAME_CLUSTER("AMBARI.RENAME_CLUSTER"),
   AMBARI_RUN_CUSTOM_COMMAND("AMBARI.RUN_CUSTOM_COMMAND"),
   AMBARI_MANAGE_CONFIGURATION("AMBARI.MANAGE_CONFIGURATION"),
+  AMBARI_VIEW_STATUS_INFO("AMBARI.VIEW_STATUS_INFO"),
   CLUSTER_MANAGE_CREDENTIALS("CLUSTER.MANAGE_CREDENTIALS"),
   CLUSTER_MODIFY_CONFIGS("CLUSTER.MODIFY_CONFIGS"),
   CLUSTER_MANAGE_CONFIG_GROUPS("CLUSTER.MANAGE_CONFIG_GROUPS"),
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog272.java b/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog272.java
index d76e40d..32b8043 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog272.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog272.java
@@ -18,11 +18,13 @@
 package org.apache.ambari.server.upgrade;
 
 import static org.apache.ambari.server.configuration.AmbariServerConfigurationCategory.LDAP_CONFIGURATION;
+import static org.apache.ambari.server.security.authorization.RoleAuthorization.AMBARI_VIEW_STATUS_INFO;
 import static org.apache.ambari.server.upgrade.UpgradeCatalog270.AMBARI_CONFIGURATION_CATEGORY_NAME_COLUMN;
 import static org.apache.ambari.server.upgrade.UpgradeCatalog270.AMBARI_CONFIGURATION_PROPERTY_NAME_COLUMN;
 import static org.apache.ambari.server.upgrade.UpgradeCatalog270.AMBARI_CONFIGURATION_TABLE;
 
 import java.sql.SQLException;
+import java.util.Collections;
 
 import org.apache.ambari.server.AmbariException;
 import org.slf4j.Logger;
@@ -72,6 +74,7 @@ public class UpgradeCatalog272 extends AbstractUpgradeCatalog {
   @Override
   protected void executeDMLUpdates() throws AmbariException, SQLException {
     renameLdapSynchCollisionBehaviorValue();
+    createRoleAuthorizations();
   }
 
   protected int renameLdapSynchCollisionBehaviorValue() throws SQLException {
@@ -86,4 +89,8 @@ public class UpgradeCatalog272 extends AbstractUpgradeCatalog {
     return numberOfRecordsRenamed;
   }
 
+  protected void createRoleAuthorizations() throws SQLException {
+    addRoleAuthorization(AMBARI_VIEW_STATUS_INFO.getId(), "View status information", Collections.singleton("AMBARI.ADMINISTRATOR:AMBARI"));
+    LOG.info("Added new role authorization {}", AMBARI_VIEW_STATUS_INFO.getId());
+  }
 }
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/RequestResourceProviderTest.java b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/RequestResourceProviderTest.java
index c014692..04dceea 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/RequestResourceProviderTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/RequestResourceProviderTest.java
@@ -20,6 +20,8 @@ package org.apache.ambari.server.controller.internal;
 
 
 import static org.apache.ambari.server.controller.internal.HostComponentResourceProvider.STALE_CONFIGS;
+import static org.apache.ambari.server.security.TestAuthenticationFactory.createAdministrator;
+import static org.apache.ambari.server.security.TestAuthenticationFactory.createViewUser;
 import static org.easymock.EasyMock.anyObject;
 import static org.easymock.EasyMock.capture;
 import static org.easymock.EasyMock.eq;
@@ -212,6 +214,8 @@ public class RequestResourceProviderTest {
 
     expect(requestDAO.findByPks(Collections.emptyList(), true)).andReturn(Collections.emptyList()).anyTimes();
 
+    prepareGetAuthorizationExpectations();
+
     ActionManager actionManager = createNiceMock(ActionManager.class);
 
     Cluster cluster = createNiceMock(Cluster.class);
@@ -267,6 +271,14 @@ public class RequestResourceProviderTest {
     verify(requestDAO);
   }
 
+  private void prepareGetAuthorizationExpectations() {
+    prepareGetAuthorizationExpectations(true);
+  }
+
+  private void prepareGetAuthorizationExpectations(boolean allowedToAuthorize) {
+    SecurityContextHolder.getContext().setAuthentication(allowedToAuthorize ? createAdministrator() : createViewUser(1L));
+  }
+
   @Test
   public void testGetResources() throws Exception {
     Resource.Type type = Resource.Type.Request;
@@ -313,6 +325,8 @@ public class RequestResourceProviderTest {
       put(1L, HostRoleCommandStatusSummaryDTO.create().inProgress(1));
     }}).anyTimes();
 
+    prepareGetAuthorizationExpectations();
+
     // replay
     replay(managementController, actionManager, requestDAO, hrcDAO, requestMock);
 
@@ -363,6 +377,8 @@ public class RequestResourceProviderTest {
       put(1L, HostRoleCommandStatusSummaryDTO.create().inProgress(1));
     }}).anyTimes();
 
+    prepareGetAuthorizationExpectations();
+
     // replay
     replay(managementController, actionManager, requestDAO, hrcDAO, requestMock);
 
@@ -414,6 +430,8 @@ public class RequestResourceProviderTest {
       put(1L, HostRoleCommandStatusSummaryDTO.create().inProgress(1));
     }}).anyTimes();
 
+    prepareGetAuthorizationExpectations();
+
     // replay
     replay(managementController, actionManager, requestMock, requestDAO, hrcDAO);
 
@@ -472,6 +490,7 @@ public class RequestResourceProviderTest {
       put(1L, HostRoleCommandStatusSummaryDTO.create().inProgress(1));
     }}).anyTimes();
 
+    prepareGetAuthorizationExpectations();
 
     // replay
     replay(managementController, actionManager, clusters, cluster, requestMock, requestDAO, hrcDAO);
@@ -538,6 +557,8 @@ public class RequestResourceProviderTest {
       put(1L, HostRoleCommandStatusSummaryDTO.create().inProgress(1));
     }}).anyTimes();
 
+    prepareGetAuthorizationExpectations();
+
     // replay
     replay(managementController, actionManager, requestMock, requestMock1, requestDAO, hrcDAO);
 
@@ -590,6 +611,8 @@ public class RequestResourceProviderTest {
       put(1L, HostRoleCommandStatusSummaryDTO.create().completed(2));
     }}).anyTimes();
 
+    prepareGetAuthorizationExpectations();
+
     // replay
     replay(managementController, actionManager, requestMock0, requestMock1, requestDAO, hrcDAO);
 
@@ -659,6 +682,8 @@ public class RequestResourceProviderTest {
       put(1L, HostRoleCommandStatusSummaryDTO.create().inProgress(1).queued(1));
     }}).once();
 
+    prepareGetAuthorizationExpectations();
+
     // replay
     replay(managementController, actionManager, requestMock0, requestMock1, requestDAO, hrcDAO);
 
@@ -737,6 +762,7 @@ public class RequestResourceProviderTest {
       put(1L, HostRoleCommandStatusSummaryDTO.create().aborted(1).timedout(1));
     }}).once();
 
+    prepareGetAuthorizationExpectations();
 
     // replay
     replay(managementController, actionManager, requestMock0, requestMock1, requestDAO, hrcDAO);
@@ -785,6 +811,20 @@ public class RequestResourceProviderTest {
     verify(managementController, actionManager, requestMock0, requestMock1, requestDAO, hrcDAO);
   }
 
+  @Test(expected = AuthorizationException.class)
+  public void shouldThrowAuthorizationErrorInCaseTheAuthenticatedUserDoesNotHaveTheAppropriatePermissions() throws Exception {
+    // Given
+    prepareGetAuthorizationExpectations(false);
+    final ResourceProvider provider = AbstractControllerResourceProvider.getResourceProvider(Resource.Type.Request, createMock(AmbariManagementController.class));
+    final Request request = PropertyHelper.getUpdateRequest(new LinkedHashMap<>(), null);
+    final Predicate predicate = new PredicateBuilder().property(RequestResourceProvider.REQUEST_ID_PROPERTY_ID).equals("100").toPredicate();
+
+    // When
+    provider.getResources(request, predicate);
+
+    // Then: see expected exception
+  }
+
   @Test
   public void testUpdateResources_CancelRequest() throws Exception {
     Resource.Type type = Resource.Type.Request;
@@ -818,6 +858,8 @@ public class RequestResourceProviderTest {
 
     RequestStatusResponse response = createNiceMock(RequestStatusResponse.class);
 
+    prepareGetAuthorizationExpectations();
+
     // replay
     replay(managementController, actionManager, hostRoleCommand, clusters, requestMock, response, stage);
 
@@ -1559,6 +1601,7 @@ public class RequestResourceProviderTest {
       put(1L, HostRoleCommandStatusSummaryDTO.create().inProgress(1));
     }}).anyTimes();
 
+    prepareGetAuthorizationExpectations();
 
     // replay
     replay(managementController, actionManager, clusters, requestMock, requestDAO, hrcDAO);
@@ -1612,6 +1655,8 @@ public class RequestResourceProviderTest {
     expect(hrcDAO.findAggregateCounts((Long) anyObject())).andReturn(
       Collections.emptyMap()).anyTimes();
 
+    prepareGetAuthorizationExpectations();
+
     // replay
     replay(managementController, actionManager, clusters, requestMock, requestDAO, hrcDAO);
 
@@ -1707,6 +1752,8 @@ public class RequestResourceProviderTest {
         : Optional.<String>absent();
       expect(logicalRequest.getFailureReason()).andReturn(failureReason).anyTimes();
 
+      prepareGetAuthorizationExpectations();
+
       replayAll();
 
       Resource.Type type = Resource.Type.Request;
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog272Test.java b/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog272Test.java
index d303861..0c7fb02 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog272Test.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog272Test.java
@@ -21,6 +21,7 @@ import static org.apache.ambari.server.upgrade.UpgradeCatalog270.AMBARI_CONFIGUR
 import static org.apache.ambari.server.upgrade.UpgradeCatalog272.RENAME_COLLISION_BEHAVIOR_PROPERTY_SQL;
 import static org.easymock.EasyMock.createMockBuilder;
 import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.expectLastCall;
 import static org.easymock.EasyMock.replay;
 import static org.easymock.EasyMock.verify;
 import static org.junit.Assert.assertEquals;
@@ -49,11 +50,16 @@ public class UpgradeCatalog272Test {
   @Test
   public void testExecuteDMLUpdates() throws Exception {
     final Method renameLdapSynchCollisionBehaviorValue = UpgradeCatalog272.class.getDeclaredMethod("renameLdapSynchCollisionBehaviorValue");
+    final Method createRoleAuthorizations = UpgradeCatalog272.class.getDeclaredMethod("createRoleAuthorizations");
 
-    final UpgradeCatalog272 upgradeCatalog272 = createMockBuilder(UpgradeCatalog272.class).addMockedMethod(renameLdapSynchCollisionBehaviorValue).createMock();
+    final UpgradeCatalog272 upgradeCatalog272 = createMockBuilder(UpgradeCatalog272.class).addMockedMethod(renameLdapSynchCollisionBehaviorValue)
+        .addMockedMethod(createRoleAuthorizations).createMock();
 
     expect(upgradeCatalog272.renameLdapSynchCollisionBehaviorValue()).andReturn(0).once();
 
+    upgradeCatalog272.createRoleAuthorizations();
+    expectLastCall().once();
+
     replay(upgradeCatalog272);
 
     upgradeCatalog272.executeDMLUpdates();
@@ -83,5 +89,7 @@ public class UpgradeCatalog272Test {
     assertEquals(expectedResult, upgradeCatalog272.renameLdapSynchCollisionBehaviorValue());
     verify(dbAccessor);
   }
+  
+  
 
 }