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 <[email protected]>
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);
}
+
+
}