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 2015/12/10 16:42:19 UTC
[2/2] ambari git commit: AMBARI-14193. Enforce granular role-based
access control for host functions (rlevas)
AMBARI-14193. Enforce granular role-based access control for host functions (rlevas)
Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/5de1d054
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/5de1d054
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/5de1d054
Branch: refs/heads/trunk
Commit: 5de1d0547c087a863fb488778c38b781ee7c33e1
Parents: 8750537
Author: Robert Levas <rl...@hortonworks.com>
Authored: Thu Dec 10 10:42:08 2015 -0500
Committer: Robert Levas <rl...@hortonworks.com>
Committed: Thu Dec 10 10:42:08 2015 -0500
----------------------------------------------------------------------
.../internal/HostResourceProvider.java | 80 +-
.../AmbariAuthorizationFilter.java | 2 +
.../internal/HostResourceProviderTest.java | 916 +++++++++++--------
3 files changed, 579 insertions(+), 419 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ambari/blob/5de1d054/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/HostResourceProvider.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/HostResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/HostResourceProvider.java
index 39d4040..8f00321 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/HostResourceProvider.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/HostResourceProvider.java
@@ -20,6 +20,7 @@ package org.apache.ambari.server.controller.internal;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collections;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.HashSet;
@@ -49,6 +50,10 @@ import org.apache.ambari.server.controller.spi.ResourceAlreadyExistsException;
import org.apache.ambari.server.controller.spi.SystemException;
import org.apache.ambari.server.controller.spi.UnsupportedPropertyException;
import org.apache.ambari.server.controller.utilities.PropertyHelper;
+import org.apache.ambari.server.security.authorization.AuthorizationException;
+import org.apache.ambari.server.security.authorization.AuthorizationHelper;
+import org.apache.ambari.server.security.authorization.ResourceType;
+import org.apache.ambari.server.security.authorization.RoleAuthorization;
import org.apache.ambari.server.state.Cluster;
import org.apache.ambari.server.state.Clusters;
import org.apache.ambari.server.state.Config;
@@ -62,7 +67,6 @@ import org.apache.ambari.server.state.stack.OsFamily;
import org.apache.ambari.server.topology.InvalidTopologyException;
import org.apache.ambari.server.topology.InvalidTopologyTemplateException;
import org.apache.ambari.server.topology.TopologyManager;
-import org.apache.ambari.server.topology.TopologyRequest;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -167,12 +171,19 @@ public class HostResourceProvider extends AbstractControllerResourceProvider {
@Assisted Map<Resource.Type, String> keyPropertyIds,
@Assisted AmbariManagementController managementController) {
super(propertyIds, keyPropertyIds, managementController);
+
+ Set<RoleAuthorization> authorizationsAddDelete = EnumSet.of(RoleAuthorization.HOST_ADD_DELETE_HOSTS);
+
+ setRequiredCreateAuthorizations(authorizationsAddDelete);
+ setRequiredDeleteAuthorizations(authorizationsAddDelete);
+ setRequiredGetAuthorizations(RoleAuthorization.AUTHORIZATIONS_VIEW_CLUSTER);
+ setRequiredUpdateAuthorizations(RoleAuthorization.AUTHORIZATIONS_UPDATE_CLUSTER);
}
// ----- ResourceProvider ------------------------------------------------
@Override
- public RequestStatus createResources(final Request request)
+ protected RequestStatus createResourcesAuthorized(final Request request)
throws SystemException,
UnsupportedPropertyException,
ResourceAlreadyExistsException,
@@ -196,7 +207,7 @@ public class HostResourceProvider extends AbstractControllerResourceProvider {
}
@Override
- public Set<Resource> getResources(Request request, Predicate predicate)
+ protected Set<Resource> getResourcesAuthorized(Request request, Predicate predicate)
throws SystemException, UnsupportedPropertyException, NoSuchResourceException, NoSuchParentResourceException {
final Set<HostRequest> requests = new HashSet<HostRequest>();
@@ -289,7 +300,7 @@ public class HostResourceProvider extends AbstractControllerResourceProvider {
}
@Override
- public RequestStatus updateResources(final Request request, Predicate predicate)
+ protected RequestStatus updateResourcesAuthorized(final Request request, Predicate predicate)
throws SystemException, UnsupportedPropertyException, NoSuchResourceException, NoSuchParentResourceException {
final Set<HostRequest> requests = new HashSet<HostRequest>();
@@ -299,7 +310,7 @@ public class HostResourceProvider extends AbstractControllerResourceProvider {
modifyResources(new Command<Void>() {
@Override
- public Void invoke() throws AmbariException {
+ public Void invoke() throws AmbariException, AuthorizationException {
updateHosts(requests);
return null;
}
@@ -311,7 +322,7 @@ public class HostResourceProvider extends AbstractControllerResourceProvider {
}
@Override
- public RequestStatus deleteResources(Predicate predicate)
+ protected RequestStatus deleteResourcesAuthorized(Predicate predicate)
throws SystemException, UnsupportedPropertyException, NoSuchResourceException, NoSuchParentResourceException {
final Set<HostRequest> requests = new HashSet<HostRequest>();
@@ -647,7 +658,7 @@ public class HostResourceProvider extends AbstractControllerResourceProvider {
return response;
}
- protected synchronized void updateHosts(Set<HostRequest> requests) throws AmbariException {
+ protected synchronized void updateHosts(Set<HostRequest> requests) throws AmbariException, AuthorizationException {
if (requests.isEmpty()) {
LOG.warn("Received an empty requests set");
@@ -673,6 +684,8 @@ public class HostResourceProvider extends AbstractControllerResourceProvider {
Host host = clusters.getHost(request.getHostname());
String clusterName = request.getClusterName();
+ Cluster cluster = clusters.getCluster(clusterName);
+ Long clusterId = cluster.getClusterId();
try {
// The below method call throws an exception when trying to create a duplicate mapping in the clusterhostmapping
@@ -683,6 +696,9 @@ public class HostResourceProvider extends AbstractControllerResourceProvider {
}
if (null != request.getHostAttributes()) {
+ if(!AuthorizationHelper.isAuthorized(ResourceType.CLUSTER, clusterId, RoleAuthorization.HOST_ADD_DELETE_HOSTS)) {
+ throw new AuthorizationException("The authenticated user is not authorized to update host attributes");
+ }
host.setHostAttributes(request.getHostAttributes());
}
@@ -691,35 +707,64 @@ public class HostResourceProvider extends AbstractControllerResourceProvider {
boolean rackChange = requestRackInfo != null && !requestRackInfo.equals(rackInfo);
if (rackChange) {
+ if(!AuthorizationHelper.isAuthorized(ResourceType.CLUSTER, clusterId, RoleAuthorization.HOST_ADD_DELETE_HOSTS)) {
+ throw new AuthorizationException("The authenticated user is not authorized to update host rack information");
+ }
host.setRackInfo(requestRackInfo);
}
if (null != request.getPublicHostName()) {
+ if(!AuthorizationHelper.isAuthorized(ResourceType.CLUSTER, clusterId, RoleAuthorization.HOST_ADD_DELETE_HOSTS)) {
+ throw new AuthorizationException("The authenticated user is not authorized to update host attributes");
+ }
host.setPublicHostName(request.getPublicHostName());
}
if (null != clusterName && null != request.getMaintenanceState()) {
- Cluster c = clusters.getCluster(clusterName);
+ if(!AuthorizationHelper.isAuthorized(ResourceType.CLUSTER, clusterId, RoleAuthorization.HOST_TOGGLE_MAINTENANCE)) {
+ throw new AuthorizationException("The authenticated user is not authorized to update host maintenance state");
+ }
MaintenanceState newState = MaintenanceState.valueOf(request.getMaintenanceState());
- MaintenanceState oldState = host.getMaintenanceState(c.getClusterId());
+ MaintenanceState oldState = host.getMaintenanceState(clusterId);
if (!newState.equals(oldState)) {
if (newState.equals(MaintenanceState.IMPLIED_FROM_HOST)
|| newState.equals(MaintenanceState.IMPLIED_FROM_SERVICE)) {
throw new IllegalArgumentException("Invalid arguments, can only set " +
"maintenance state to one of " + EnumSet.of(MaintenanceState.OFF, MaintenanceState.ON));
} else {
- host.setMaintenanceState(c.getClusterId(), newState);
+ host.setMaintenanceState(clusterId, newState);
}
}
}
// Create configurations
if (null != clusterName && null != request.getDesiredConfigs()) {
- Cluster c = clusters.getCluster(clusterName);
-
if (clusters.getHostsForCluster(clusterName).containsKey(host.getHostName())) {
for (ConfigurationRequest cr : request.getDesiredConfigs()) {
+ String configType = cr.getType();
+
+ // If the config type is for a service, then allow a user with SERVICE_MODIFY_CONFIGS to
+ // update, else ensure the user has CLUSTER_MODIFY_CONFIGS
+ String service = null;
+
+ try {
+ service = cluster.getServiceForConfigTypes(Collections.singleton(configType));
+ } catch (IllegalArgumentException e) {
+ // Ignore this since we may have hit a config type that spans multiple services. This may
+ // happen in unit test cases but should not happen with later versions of stacks.
+ }
+
+ if(StringUtils.isEmpty(service)) {
+ if (!AuthorizationHelper.isAuthorized(ResourceType.CLUSTER, cluster.getClusterId(), EnumSet.of(RoleAuthorization.CLUSTER_MODIFY_CONFIGS))) {
+ throw new AuthorizationException("The authenticated user does not have authorization to modify cluster configurations");
+ }
+ }
+ else {
+ if (!AuthorizationHelper.isAuthorized(ResourceType.CLUSTER, cluster.getClusterId(), EnumSet.of(RoleAuthorization.SERVICE_MODIFY_CONFIGS))) {
+ throw new AuthorizationException("The authenticated user does not have authorization to modify service configurations");
+ }
+ }
if (null != cr.getProperties() && cr.getProperties().size() > 0) {
LOG.info(MessageFormat.format("Applying configuration with tag ''{0}'' to host ''{1}'' in cluster ''{2}''",
@@ -727,18 +772,18 @@ public class HostResourceProvider extends AbstractControllerResourceProvider {
request.getHostname(),
clusterName));
- cr.setClusterName(c.getClusterName());
+ cr.setClusterName(cluster.getClusterName());
controller.createConfiguration(cr);
}
- Config baseConfig = c.getConfig(cr.getType(), cr.getVersionTag());
+ Config baseConfig = cluster.getConfig(cr.getType(), cr.getVersionTag());
if (null != baseConfig) {
String authName = controller.getAuthName();
- DesiredConfig oldConfig = host.getDesiredConfigs(c.getClusterId()).get(cr.getType());
+ DesiredConfig oldConfig = host.getDesiredConfigs(clusterId).get(cr.getType());
- if (host.addDesiredConfig(c.getClusterId(), cr.isSelected(), authName, baseConfig)) {
+ if (host.addDesiredConfig(clusterId, cr.isSelected(), authName, baseConfig)) {
Logger logger = LoggerFactory.getLogger("configchange");
- logger.info("cluster '" + c.getClusterName() + "', "
+ logger.info("cluster '" + cluster.getClusterName() + "', "
+ "host '" + host.getHostName() + "' "
+ "changed by: '" + authName + "'; "
+ "type='" + baseConfig.getType() + "' "
@@ -754,6 +799,7 @@ public class HostResourceProvider extends AbstractControllerResourceProvider {
if (clusterName != null && !clusterName.isEmpty()) {
clusters.getCluster(clusterName).recalculateAllClusterVersionStates();
if (rackChange) {
+ // Authorization check for this update was performed before we got to this point.
controller.registerRackChange(clusterName);
}
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/5de1d054/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 21745b4..5146cca 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
@@ -76,6 +76,7 @@ public class AmbariAuthorizationFilter implements Filter {
private static final String API_CLUSTER_SERVICES_ALL_PATTERN = API_VERSION_PREFIX + "/clusters/.*?/services.*";
private static final String API_HOSTS_ALL_PATTERN = API_VERSION_PREFIX + "/clusters/.*?/hosts.*";
private static final String API_STACK_VERSIONS_PATTERN = API_VERSION_PREFIX + "/stacks/.*?/versions/.*";
+ private static final String API_HOSTS_ALL = API_VERSION_PREFIX + "/hosts.*";
protected static final String LOGIN_REDIRECT_BASE = "/#/login?targetURI=";
@@ -265,6 +266,7 @@ public class AmbariAuthorizationFilter implements Filter {
requestURI.matches(API_STACK_VERSIONS_PATTERN) ||
requestURI.matches(API_WIDGET_LAYOUTS_PATTERN) ||
requestURI.matches(API_HOSTS_ALL_PATTERN) ||
+ requestURI.matches(API_HOSTS_ALL) ||
requestURI.matches(API_PRIVILEGES_ALL_PATTERN);
}