Repository: ambari Updated Branches: refs/heads/branch-2.4 e22e2cbbe -> e7b852607
AMBARI-16851. Cluster operator and cluster admin not allowed to install ambari agent (rlevas) Project: http://git-wip-us.apache.org/repos/asf/ambari/repo Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/e7b85260 Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/e7b85260 Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/e7b85260 Branch: refs/heads/branch-2.4 Commit: e7b852607fec810eb3bc4c0dc0cfedccdff395f4 Parents: e22e2cb Author: Robert Levas <[email protected]> Authored: Fri May 27 13:47:35 2016 -0400 Committer: Robert Levas <[email protected]> Committed: Fri May 27 13:47:35 2016 -0400 ---------------------------------------------------------------------- .../internal/RequestResourceProvider.java | 31 ++++++- .../server/customactions/ActionDefinition.java | 16 +++- .../customactions/ActionDefinitionManager.java | 37 ++++++++- .../customactions/ActionDefinitionSpec.java | 10 +++ .../AmbariAuthorizationFilter.java | 87 +++++++++++--------- .../server/upgrade/UpgradeCatalog240.java | 13 +++ .../main/resources/Ambari-DDL-Derby-CREATE.sql | 1 + .../main/resources/Ambari-DDL-MySQL-CREATE.sql | 1 + .../main/resources/Ambari-DDL-Oracle-CREATE.sql | 1 + .../resources/Ambari-DDL-Postgres-CREATE.sql | 1 + .../Ambari-DDL-Postgres-EMBEDDED-CREATE.sql | 1 + .../resources/Ambari-DDL-SQLAnywhere-CREATE.sql | 1 + .../resources/Ambari-DDL-SQLServer-CREATE.sql | 1 + .../system_action_definitions.xml | 1 + .../AmbariManagementControllerTest.java | 18 ++-- .../internal/ActionResourceProviderTest.java | 8 +- .../internal/RequestResourceProviderTest.java | 74 ++++++++++++++--- .../ActionDefinitionManagerTest.java | 29 ++++++- .../security/TestAuthenticationFactory.java | 57 +++++++++++++ .../server/upgrade/UpgradeCatalog240Test.java | 3 + .../cust_action_definitions1.xml | 9 ++ .../cust_action_definitions_invalid.xml | 33 ++++++++ 22 files changed, 366 insertions(+), 67 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ambari/blob/e7b85260/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/RequestResourceProvider.java ---------------------------------------------------------------------- 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 5b318af..d38234f 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 @@ -56,6 +56,7 @@ import org.apache.ambari.server.controller.spi.SystemException; import org.apache.ambari.server.controller.spi.UnsupportedPropertyException; import org.apache.ambari.server.controller.utilities.PredicateBuilder; import org.apache.ambari.server.controller.utilities.PropertyHelper; +import org.apache.ambari.server.customactions.ActionDefinition; import org.apache.ambari.server.orm.dao.HostRoleCommandDAO; import org.apache.ambari.server.orm.dao.HostRoleCommandStatusSummaryDTO; import org.apache.ambari.server.orm.dao.RequestDAO; @@ -71,6 +72,7 @@ import org.apache.ambari.server.topology.TopologyManager; import com.google.common.collect.Sets; import com.google.inject.Inject; +import org.apache.commons.lang.StringUtils; /** * Resource provider for request resources. @@ -185,8 +187,33 @@ public class RequestResourceProvider extends AbstractControllerResourceProvider String clusterName = actionRequest.getClusterName(); if(clusterName == null) { - // This must be an administrative action? - // TODO: Perform authorization check for this? + String actionName = actionRequest.getActionName(); + + // Ensure that the actionName is not null or empty. A null actionName will result in + // a NPE at when getting the action definition. The string "_unknown_action_" should not + // result in a valid action definition and should be easy to understand in any error message + // that gets displayed or logged due to an authorization issue. + if(StringUtils.isEmpty(actionName)) { + actionName = "_unknown_action_"; + } + + ActionDefinition actionDefinition = getManagementController().getAmbariMetaInfo().getActionDefinition(actionName); + Set<RoleAuthorization> permissions = (actionDefinition == null) ? null : actionDefinition.getPermissions(); + + if(permissions == null) { + if (!AuthorizationHelper.isAuthorized(ResourceType.AMBARI, null, RoleAuthorization.SERVICE_RUN_CUSTOM_COMMAND)) { + throw new AuthorizationException(String.format("The authenticated user is not authorized to execute the '%s'command.", actionName)); + } + } + else { + // Since we cannot tell whether the action is to be exectued for the system or a + // non-disclosed cluster, specify that the resource is a CLUSTER with no resource id. + // This should ensure that a user with a role for any cluster with the appropriate + // permissions or an Ambari administrator can execute the command. + if (!AuthorizationHelper.isAuthorized(ResourceType.CLUSTER, null, permissions)) { + throw new AuthorizationException(String.format("The authenticated user is not authorized to execute the '%s'command.", actionName)); + } + } } else if(actionRequest.isCommand()) { if (!AuthorizationHelper.isAuthorized(ResourceType.CLUSTER, http://git-wip-us.apache.org/repos/asf/ambari/blob/e7b85260/ambari-server/src/main/java/org/apache/ambari/server/customactions/ActionDefinition.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/customactions/ActionDefinition.java b/ambari-server/src/main/java/org/apache/ambari/server/customactions/ActionDefinition.java index 1f189a3..02c469f 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/customactions/ActionDefinition.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/customactions/ActionDefinition.java @@ -21,6 +21,9 @@ package org.apache.ambari.server.customactions; import org.apache.ambari.server.actionmanager.ActionType; import org.apache.ambari.server.actionmanager.TargetHostType; import org.apache.ambari.server.controller.ActionResponse; +import org.apache.ambari.server.security.authorization.RoleAuthorization; + +import java.util.Set; /** * The resource describing the definition of an action @@ -34,6 +37,7 @@ public class ActionDefinition { private String description; private TargetHostType targetType; private Short defaultTimeout; + private Set<RoleAuthorization> permissions; /** * Create an instance of ActionDefinition @@ -46,10 +50,11 @@ public class ActionDefinition { * @param description Short description of the action * @param targetType Selection criteria for target hosts * @param defaultTimeout The timeout value for this action when executed + * @param permissions A set of permissions to use when verifiying authorization to execute this action */ public ActionDefinition(String actionName, ActionType actionType, String inputs, String targetService, String targetComponent, String description, - TargetHostType targetType, Short defaultTimeout) { + TargetHostType targetType, Short defaultTimeout, Set<RoleAuthorization> permissions) { setActionName(actionName); setActionType(actionType); setInputs(inputs); @@ -58,6 +63,7 @@ public class ActionDefinition { setDescription(description); setTargetType(targetType); setDefaultTimeout(defaultTimeout); + setPermissions(permissions); } public String getActionName() { @@ -124,6 +130,14 @@ public class ActionDefinition { this.defaultTimeout = defaultTimeout; } + public void setPermissions(Set<RoleAuthorization> permissions) { + this.permissions = permissions; + } + + public Set<RoleAuthorization> getPermissions() { + return permissions; + } + public ActionResponse convertToResponse() { return new ActionResponse(getActionName(), getActionType().name(), getInputs(), getTargetService(), getTargetComponent(), getDescription(), getTargetType().name(), http://git-wip-us.apache.org/repos/asf/ambari/blob/e7b85260/ambari-server/src/main/java/org/apache/ambari/server/customactions/ActionDefinitionManager.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/customactions/ActionDefinitionManager.java b/ambari-server/src/main/java/org/apache/ambari/server/customactions/ActionDefinitionManager.java index 97aa8a0..637471f 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/customactions/ActionDefinitionManager.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/customactions/ActionDefinitionManager.java @@ -21,6 +21,8 @@ import org.apache.ambari.server.AmbariException; import org.apache.ambari.server.actionmanager.ActionType; import org.apache.ambari.server.actionmanager.TargetHostType; import org.apache.ambari.server.api.services.AmbariMetaInfo; +import org.apache.ambari.server.security.authorization.RoleAuthorization; +import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -30,9 +32,12 @@ import javax.xml.bind.UnmarshalException; import javax.xml.bind.Unmarshaller; import java.io.File; import java.util.ArrayList; +import java.util.EnumSet; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Set; /** * Manages Action definitions read from XML files @@ -120,7 +125,8 @@ public class ActionDefinitionManager { } actionDefinitionMap.put(ad.getActionName(), new ActionDefinition(ad.getActionName(), actionType, - ad.getInputs(), ad.getTargetService(), ad.getTargetComponent(), ad.getDescription(), targetType, defaultTimeout)); + ad.getInputs(), ad.getTargetService(), ad.getTargetComponent(), ad.getDescription(), targetType, defaultTimeout, + translatePermissions(ad.getPermissions()))); LOG.info("Added custom action definition for " + ad.getActionName()); } else { LOG.warn(errorReason.toString()); @@ -199,4 +205,33 @@ public class ActionDefinitionManager { } return true; } + + /** + * Given a comma-delimited list of permission names, translates into a {@link Set} of + * {@link RoleAuthorization}s. + * <p> + * <code>null</code> is returned if the permission string is null or empty, or if none of the + * permissions in the string translate to a {@link RoleAuthorization}. Permissions that do not + * translate to a {@link RoleAuthorization} will yield a {@link IllegalArgumentException}. + * + * @param permissions a comma-delimited string of permission names + * @return a set of {@link RoleAuthorization}s; or null if no permissions are specified + */ + private Set<RoleAuthorization> translatePermissions(String permissions) { + if (StringUtils.isEmpty(permissions)) { + return null; + } else { + Set<RoleAuthorization> authorizations = new HashSet<RoleAuthorization>(); + String[] parts = permissions.split(","); + + for (String permission : parts) { + RoleAuthorization authorization = RoleAuthorization.translate(permission); + if (authorization != null) { + authorizations.add(authorization); + } + } + + return (authorizations.isEmpty()) ? null : EnumSet.copyOf(authorizations); + } + } } http://git-wip-us.apache.org/repos/asf/ambari/blob/e7b85260/ambari-server/src/main/java/org/apache/ambari/server/customactions/ActionDefinitionSpec.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/customactions/ActionDefinitionSpec.java b/ambari-server/src/main/java/org/apache/ambari/server/customactions/ActionDefinitionSpec.java index 2dfa1f2..f789691 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/customactions/ActionDefinitionSpec.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/customactions/ActionDefinitionSpec.java @@ -27,6 +27,7 @@ public class ActionDefinitionSpec { private String description; private String targetType; private String defaultTimeout; + private String permissions; public String getTargetComponent() { return targetComponent; @@ -92,6 +93,14 @@ public class ActionDefinitionSpec { this.targetService = targetService; } + public String getPermissions() { + return permissions; + } + + public void setPermissions(String permissions) { + this.permissions = permissions; + } + @Override public int hashCode() { final int prime = 31; @@ -134,6 +143,7 @@ public class ActionDefinitionSpec { .append(" targetComponent: ").append(targetComponent) .append(" defaultTimeout: ").append(defaultTimeout) .append(" targetType: ").append(targetType) + .append(" permissions: ").append(permissions) .toString(); } } http://git-wip-us.apache.org/repos/asf/ambari/blob/e7b85260/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 5c74f07..eeb1a8b 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 @@ -47,6 +47,7 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.security.Principal; +import java.util.EnumSet; import java.util.regex.Pattern; public class AmbariAuthorizationFilter implements Filter { @@ -77,9 +78,12 @@ public class AmbariAuthorizationFilter implements Filter { private static final String API_CLUSTER_SERVICES_ALL_PATTERN = API_VERSION_PREFIX + "/clusters/.*?/services.*"; private static final String API_CLUSTER_ALERT_ALL_PATTERN = API_VERSION_PREFIX + "/clusters/.*?/alert.*"; private static final String API_CLUSTER_HOSTS_ALL_PATTERN = API_VERSION_PREFIX + "/clusters/.*?/hosts.*"; + private static final String API_CLUSTER_HOST_COMPONENTS_ALL_PATTERN = API_VERSION_PREFIX + "/clusters/.*?/host_components.*"; private static final String API_STACK_VERSIONS_PATTERN = API_VERSION_PREFIX + "/stacks/.*?/versions/.*"; private static final String API_HOSTS_ALL_PATTERN = API_VERSION_PREFIX + "/hosts.*"; private static final String API_ALERT_TARGETS_ALL_PATTERN = API_VERSION_PREFIX + "/alert_targets.*"; + private static final String API_BOOTSTRAP_PATTERN_ALL = API_VERSION_PREFIX + "/bootstrap.*"; + private static final String API_REQUESTS_ALL_PATTERN = API_VERSION_PREFIX + "/requests.*"; protected static final String LOGIN_REDIRECT_BASE = "/#/login?targetURI="; @@ -161,55 +165,62 @@ public class AmbariAuthorizationFilter implements Filter { } else if (!authorizationPerformedInternally(requestURI)) { boolean authorized = false; - for (GrantedAuthority grantedAuthority : authentication.getAuthorities()) { - if (grantedAuthority instanceof AmbariGrantedAuthority) { - - AmbariGrantedAuthority ambariGrantedAuthority = (AmbariGrantedAuthority) grantedAuthority; + if (requestURI.matches(API_BOOTSTRAP_PATTERN_ALL)) { + authorized = AuthorizationHelper.isAuthorized(authentication, + ResourceType.CLUSTER, + null, + EnumSet.of(RoleAuthorization.HOST_ADD_DELETE_HOSTS)); + } + else { + for (GrantedAuthority grantedAuthority : authentication.getAuthorities()) { + if (grantedAuthority instanceof AmbariGrantedAuthority) { - PrivilegeEntity privilegeEntity = ambariGrantedAuthority.getPrivilegeEntity(); - Integer permissionId = privilegeEntity.getPermission().getId(); + AmbariGrantedAuthority ambariGrantedAuthority = (AmbariGrantedAuthority) grantedAuthority; - // admin has full access - if (permissionId.equals(PermissionEntity.AMBARI_ADMINISTRATOR_PERMISSION)) { - authorized = true; - break; - } + PrivilegeEntity privilegeEntity = ambariGrantedAuthority.getPrivilegeEntity(); + Integer permissionId = privilegeEntity.getPermission().getId(); - // clusters require permission - if (!"GET".equalsIgnoreCase(httpRequest.getMethod()) && requestURI.matches(API_CREDENTIALS_AMBARI_PATTERN)) { - // Only the administrator can operate on credentials where the alias starts with "ambari." + // admin has full access if (permissionId.equals(PermissionEntity.AMBARI_ADMINISTRATOR_PERMISSION)) { authorized = true; break; } - } else if (requestURI.matches(API_CLUSTERS_ALL_PATTERN)) { - if (permissionId.equals(PermissionEntity.CLUSTER_USER_PERMISSION) || - permissionId.equals(PermissionEntity.CLUSTER_ADMINISTRATOR_PERMISSION)) { - authorized = true; - break; - } - } else if (STACK_ADVISOR_REGEX.matcher(requestURI).matches()) { - //TODO permissions model doesn't manage stacks api, but we need access to stack advisor to save configs - if (permissionId.equals(PermissionEntity.CLUSTER_USER_PERMISSION) || - permissionId.equals(PermissionEntity.CLUSTER_ADMINISTRATOR_PERMISSION)) { - authorized = true; - break; - } - } else if (requestURI.matches(API_VIEWS_ALL_PATTERN)) { - // views require permission - if (permissionId.equals(PermissionEntity.VIEW_USER_PERMISSION)) { - authorized = true; - break; + + // clusters require permission + if (!"GET".equalsIgnoreCase(httpRequest.getMethod()) && requestURI.matches(API_CREDENTIALS_AMBARI_PATTERN)) { + // Only the administrator can operate on credentials where the alias starts with "ambari." + if (permissionId.equals(PermissionEntity.AMBARI_ADMINISTRATOR_PERMISSION)) { + authorized = true; + break; + } + } else if (requestURI.matches(API_CLUSTERS_ALL_PATTERN)) { + if (permissionId.equals(PermissionEntity.CLUSTER_USER_PERMISSION) || + permissionId.equals(PermissionEntity.CLUSTER_ADMINISTRATOR_PERMISSION)) { + authorized = true; + break; + } + } else if (STACK_ADVISOR_REGEX.matcher(requestURI).matches()) { + //TODO permissions model doesn't manage stacks api, but we need access to stack advisor to save configs + if (permissionId.equals(PermissionEntity.CLUSTER_USER_PERMISSION) || + permissionId.equals(PermissionEntity.CLUSTER_ADMINISTRATOR_PERMISSION)) { + authorized = true; + break; + } + } else if (requestURI.matches(API_VIEWS_ALL_PATTERN)) { + // views require permission + if (permissionId.equals(PermissionEntity.VIEW_USER_PERMISSION)) { + authorized = true; + break; + } } } } - } - // allow GET for everything except /views, /api/v1/users, /api/v1/groups, /api/v1/ldap_sync_events - if (!authorized && - (!httpRequest.getMethod().equals("GET") - || requestURI.matches(API_LDAP_SYNC_EVENTS_ALL_PATTERN))) { + // Allow all GETs that are not LDAP sync events... + authorized = authorized || (httpRequest.getMethod().equals("GET") && !requestURI.matches(API_LDAP_SYNC_EVENTS_ALL_PATTERN)); + } + if (!authorized) { if(auditLogger.isEnabled()) { auditEvent = AccessUnauthorizedAuditEvent.builder() .withHttpMethodName(httpRequest.getMethod()) @@ -283,6 +294,7 @@ public class AmbariAuthorizationFilter implements Filter { */ private boolean authorizationPerformedInternally(String requestURI) { return requestURI.matches(API_USERS_ALL_PATTERN) || + requestURI.matches(API_REQUESTS_ALL_PATTERN) || requestURI.matches(API_GROUPS_ALL_PATTERN) || requestURI.matches(API_CREDENTIALS_ALL_PATTERN) || requestURI.matches(API_PRIVILEGES_ALL_PATTERN) || @@ -295,6 +307,7 @@ public class AmbariAuthorizationFilter implements Filter { requestURI.matches(VIEWS_CONTEXT_PATH_PATTERN) || requestURI.matches(API_WIDGET_LAYOUTS_PATTERN) || requestURI.matches(API_CLUSTER_HOSTS_ALL_PATTERN) || + requestURI.matches(API_CLUSTER_HOST_COMPONENTS_ALL_PATTERN) || requestURI.matches(API_HOSTS_ALL_PATTERN) || requestURI.matches(API_ALERT_TARGETS_ALL_PATTERN) || requestURI.matches(API_PRIVILEGES_ALL_PATTERN) || http://git-wip-us.apache.org/repos/asf/ambari/blob/e7b85260/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog240.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog240.java b/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog240.java index ecd8ff1..db6d73a9 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog240.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog240.java @@ -329,6 +329,7 @@ public class UpgradeCatalog240 extends AbstractUpgradeCatalog { setRoleSortOrder(); addSettingPermission(); addManageUserPersistedDataPermission(); + allowClusterOperatorToManageCredentials(); updateHDFSConfigs(); updateHIVEConfigs(); updateAMSConfigs(); @@ -513,6 +514,18 @@ public class UpgradeCatalog240 extends AbstractUpgradeCatalog { } + /** + * Adds <code>CLUSTER.MANAGE_CREDENTIALS</code> to the set of authorizations a <code>CLUSTER.OPERATOR</code> can perform. + * + * @throws SQLException + */ + protected void allowClusterOperatorToManageCredentials() throws SQLException { + String permissionId = permissionDAO.findPermissionByNameAndType("CLUSTER.OPERATOR", + resourceTypeDAO.findByName("CLUSTER")).getId().toString(); + dbAccessor.insertRowIfMissing("permission_roleauthorization", new String[]{"permission_id", "authorization_id" }, + new String[]{"'" + permissionId + "'", "'CLUSTER.MANAGE_CREDENTIALS'" }, false); + } + protected void removeHiveOozieDBConnectionConfigs() throws AmbariException { AmbariManagementController ambariManagementController = injector.getInstance(AmbariManagementController.class); Map<String, Cluster> clusterMap = getCheckedClusterMap(ambariManagementController.getClusters()); http://git-wip-us.apache.org/repos/asf/ambari/blob/e7b85260/ambari-server/src/main/resources/Ambari-DDL-Derby-CREATE.sql ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/resources/Ambari-DDL-Derby-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-Derby-CREATE.sql index 2c2d743..e6d1e16 100644 --- a/ambari-server/src/main/resources/Ambari-DDL-Derby-CREATE.sql +++ b/ambari-server/src/main/resources/Ambari-DDL-Derby-CREATE.sql @@ -1341,6 +1341,7 @@ INSERT INTO permission_roleauthorization(permission_id, authorization_id) SELECT permission_id, 'CLUSTER.VIEW_STACK_DETAILS' FROM adminpermission WHERE permission_name='CLUSTER.OPERATOR' UNION ALL SELECT permission_id, 'CLUSTER.MANAGE_CONFIG_GROUPS' FROM adminpermission WHERE permission_name='CLUSTER.OPERATOR' UNION ALL SELECT permission_id, 'CLUSTER.VIEW_ALERTS' FROM adminpermission WHERE permission_name='CLUSTER.OPERATOR' UNION ALL + SELECT permission_id, 'CLUSTER.MANAGE_CREDENTIALS' FROM adminpermission WHERE permission_name='CLUSTER.OPERATOR' UNION ALL SELECT permission_id, 'CLUSTER.MANAGE_USER_PERSISTED_DATA' FROM adminpermission WHERE permission_name='CLUSTER.OPERATOR'; -- Set authorizations for Cluster Administrator role http://git-wip-us.apache.org/repos/asf/ambari/blob/e7b85260/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql index ee87cc5..38300b0 100644 --- a/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql +++ b/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql @@ -1274,6 +1274,7 @@ INSERT INTO permission_roleauthorization(permission_id, authorization_id) SELECT permission_id, 'CLUSTER.VIEW_STACK_DETAILS' FROM adminpermission WHERE permission_name='CLUSTER.OPERATOR' UNION ALL SELECT permission_id, 'CLUSTER.MANAGE_CONFIG_GROUPS' FROM adminpermission WHERE permission_name='CLUSTER.OPERATOR' UNION ALL SELECT permission_id, 'CLUSTER.VIEW_ALERTS' FROM adminpermission WHERE permission_name='CLUSTER.OPERATOR' UNION ALL + SELECT permission_id, 'CLUSTER.MANAGE_CREDENTIALS' FROM adminpermission WHERE permission_name='CLUSTER.OPERATOR' UNION ALL SELECT permission_id, 'CLUSTER.MANAGE_USER_PERSISTED_DATA' FROM adminpermission WHERE permission_name='CLUSTER.OPERATOR'; -- Set authorizations for Cluster Administrator role http://git-wip-us.apache.org/repos/asf/ambari/blob/e7b85260/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql index edc46f7..a017388 100644 --- a/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql +++ b/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql @@ -1293,6 +1293,7 @@ INSERT INTO permission_roleauthorization(permission_id, authorization_id) SELECT permission_id, 'CLUSTER.VIEW_STACK_DETAILS' FROM adminpermission WHERE permission_name='CLUSTER.OPERATOR' UNION ALL SELECT permission_id, 'CLUSTER.MANAGE_CONFIG_GROUPS' FROM adminpermission WHERE permission_name='CLUSTER.OPERATOR' UNION ALL SELECT permission_id, 'CLUSTER.VIEW_ALERTS' FROM adminpermission WHERE permission_name='CLUSTER.OPERATOR' UNION ALL + SELECT permission_id, 'CLUSTER.MANAGE_CREDENTIALS' FROM adminpermission WHERE permission_name='CLUSTER.OPERATOR' UNION ALL SELECT permission_id, 'CLUSTER.MANAGE_USER_PERSISTED_DATA' FROM adminpermission WHERE permission_name='CLUSTER.OPERATOR'; -- Set authorizations for Cluster Administrator role http://git-wip-us.apache.org/repos/asf/ambari/blob/e7b85260/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql index 6f38ec8..7667a6b 100644 --- a/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql +++ b/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql @@ -1265,6 +1265,7 @@ INSERT INTO permission_roleauthorization(permission_id, authorization_id) SELECT permission_id, 'CLUSTER.VIEW_STACK_DETAILS' FROM adminpermission WHERE permission_name='CLUSTER.OPERATOR' UNION ALL SELECT permission_id, 'CLUSTER.MANAGE_CONFIG_GROUPS' FROM adminpermission WHERE permission_name='CLUSTER.OPERATOR' UNION ALL SELECT permission_id, 'CLUSTER.VIEW_ALERTS' FROM adminpermission WHERE permission_name='CLUSTER.OPERATOR' UNION ALL + SELECT permission_id, 'CLUSTER.MANAGE_CREDENTIALS' FROM adminpermission WHERE permission_name='CLUSTER.OPERATOR' UNION ALL SELECT permission_id, 'CLUSTER.MANAGE_USER_PERSISTED_DATA' FROM adminpermission WHERE permission_name='CLUSTER.OPERATOR'; -- Set authorizations for Cluster Administrator role http://git-wip-us.apache.org/repos/asf/ambari/blob/e7b85260/ambari-server/src/main/resources/Ambari-DDL-Postgres-EMBEDDED-CREATE.sql ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/resources/Ambari-DDL-Postgres-EMBEDDED-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-Postgres-EMBEDDED-CREATE.sql index ca57de5..9663d56 100644 --- a/ambari-server/src/main/resources/Ambari-DDL-Postgres-EMBEDDED-CREATE.sql +++ b/ambari-server/src/main/resources/Ambari-DDL-Postgres-EMBEDDED-CREATE.sql @@ -1427,6 +1427,7 @@ INSERT INTO ambari.permission_roleauthorization(permission_id, authorization_id) SELECT permission_id, 'CLUSTER.VIEW_STACK_DETAILS' FROM ambari.adminpermission WHERE permission_name='CLUSTER.OPERATOR' UNION ALL SELECT permission_id, 'CLUSTER.MANAGE_CONFIG_GROUPS' FROM ambari.adminpermission WHERE permission_name='CLUSTER.OPERATOR' UNION ALL SELECT permission_id, 'CLUSTER.VIEW_ALERTS' FROM ambari.adminpermission WHERE permission_name='CLUSTER.OPERATOR' UNION ALL + SELECT permission_id, 'CLUSTER.MANAGE_CREDENTIALS' FROM ambari.adminpermission WHERE permission_name='CLUSTER.OPERATOR' UNION ALL SELECT permission_id, 'CLUSTER.MANAGE_USER_PERSISTED_DATA' FROM ambari.adminpermission WHERE permission_name='CLUSTER.OPERATOR'; -- Set authorizations for Cluster Administrator role http://git-wip-us.apache.org/repos/asf/ambari/blob/e7b85260/ambari-server/src/main/resources/Ambari-DDL-SQLAnywhere-CREATE.sql ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/resources/Ambari-DDL-SQLAnywhere-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-SQLAnywhere-CREATE.sql index 61aadf0..d35dab3 100644 --- a/ambari-server/src/main/resources/Ambari-DDL-SQLAnywhere-CREATE.sql +++ b/ambari-server/src/main/resources/Ambari-DDL-SQLAnywhere-CREATE.sql @@ -1290,6 +1290,7 @@ insert into adminpermission(permission_id, permission_name, resource_type_id, pe SELECT permission_id, 'CLUSTER.VIEW_STACK_DETAILS' FROM adminpermission WHERE permission_name='CLUSTER.OPERATOR' UNION ALL SELECT permission_id, 'CLUSTER.MANAGE_CONFIG_GROUPS' FROM adminpermission WHERE permission_name='CLUSTER.OPERATOR' UNION ALL SELECT permission_id, 'CLUSTER.VIEW_ALERTS' FROM adminpermission WHERE permission_name='CLUSTER.OPERATOR' UNION ALL + SELECT permission_id, 'CLUSTER.MANAGE_CREDENTIALS' FROM adminpermission WHERE permission_name='CLUSTER.OPERATOR' UNION ALL SELECT permission_id, 'CLUSTER.MANAGE_USER_PERSISTED_DATA' FROM adminpermission WHERE permission_name='CLUSTER.OPERATOR'; -- Set authorizations for Cluster Administrator role http://git-wip-us.apache.org/repos/asf/ambari/blob/e7b85260/ambari-server/src/main/resources/Ambari-DDL-SQLServer-CREATE.sql ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/resources/Ambari-DDL-SQLServer-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-SQLServer-CREATE.sql index 9269b13..23ba2db 100644 --- a/ambari-server/src/main/resources/Ambari-DDL-SQLServer-CREATE.sql +++ b/ambari-server/src/main/resources/Ambari-DDL-SQLServer-CREATE.sql @@ -1293,6 +1293,7 @@ BEGIN TRANSACTION SELECT permission_id, 'CLUSTER.VIEW_STACK_DETAILS' FROM adminpermission WHERE permission_name='CLUSTER.OPERATOR' UNION ALL SELECT permission_id, 'CLUSTER.MANAGE_CONFIG_GROUPS' FROM adminpermission WHERE permission_name='CLUSTER.OPERATOR' UNION ALL SELECT permission_id, 'CLUSTER.VIEW_ALERTS' FROM adminpermission WHERE permission_name='CLUSTER.OPERATOR' UNION ALL + SELECT permission_id, 'CLUSTER.MANAGE_CREDENTIALS' FROM adminpermission WHERE permission_name='CLUSTER.OPERATOR' UNION ALL SELECT permission_id, 'CLUSTER.MANAGE_USER_PERSISTED_DATA' FROM adminpermission WHERE permission_name='CLUSTER.OPERATOR'; -- Set authorizations for Cluster Administrator role http://git-wip-us.apache.org/repos/asf/ambari/blob/e7b85260/ambari-server/src/main/resources/custom_action_definitions/system_action_definitions.xml ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/resources/custom_action_definitions/system_action_definitions.xml b/ambari-server/src/main/resources/custom_action_definitions/system_action_definitions.xml index 6304baf..bc1c271 100644 --- a/ambari-server/src/main/resources/custom_action_definitions/system_action_definitions.xml +++ b/ambari-server/src/main/resources/custom_action_definitions/system_action_definitions.xml @@ -28,6 +28,7 @@ <defaultTimeout>60</defaultTimeout> <description>General check for host</description> <targetType>ANY</targetType> + <permissions>HOST.ADD_DELETE_HOSTS</permissions> </actionDefinition> <actionDefinition> <actionName>update_repo</actionName> http://git-wip-us.apache.org/repos/asf/ambari/blob/e7b85260/ambari-server/src/test/java/org/apache/ambari/server/controller/AmbariManagementControllerTest.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/test/java/org/apache/ambari/server/controller/AmbariManagementControllerTest.java b/ambari-server/src/test/java/org/apache/ambari/server/controller/AmbariManagementControllerTest.java index 3ec9cb3..42d62c8 100644 --- a/ambari-server/src/test/java/org/apache/ambari/server/controller/AmbariManagementControllerTest.java +++ b/ambari-server/src/test/java/org/apache/ambari/server/controller/AmbariManagementControllerTest.java @@ -4314,11 +4314,11 @@ public class AmbariManagementControllerTest { ActionDefinition a1 = new ActionDefinition(actionDef1, ActionType.SYSTEM, - "test,[optional1]", "", "", "Does file exist", TargetHostType.SPECIFIC, Short.valueOf("100")); + "test,[optional1]", "", "", "Does file exist", TargetHostType.SPECIFIC, Short.valueOf("100"), null); controller.getAmbariMetaInfo().addActionDefinition(a1); controller.getAmbariMetaInfo().addActionDefinition(new ActionDefinition( actionDef2, ActionType.SYSTEM, "", "HDFS", "DATANODE", "Does file exist", - TargetHostType.ALL, Short.valueOf("1000"))); + TargetHostType.ALL, Short.valueOf("1000"), null)); Map<String, String> params = new HashMap<String, String>() {{ put("test", "test"); @@ -4700,23 +4700,23 @@ public class AmbariManagementControllerTest { controller.getAmbariMetaInfo().addActionDefinition(new ActionDefinition( actionDef1, ActionType.SYSTEM, "test,dirName", "", "", "Does file exist", - TargetHostType.SPECIFIC, Short.valueOf("100"))); + TargetHostType.SPECIFIC, Short.valueOf("100"), null)); controller.getAmbariMetaInfo().addActionDefinition(new ActionDefinition( actionDef2, ActionType.SYSTEM, "", "HDFS", "DATANODE", "Does file exist", - TargetHostType.ANY, Short.valueOf("100"))); + TargetHostType.ANY, Short.valueOf("100"), null)); controller.getAmbariMetaInfo().addActionDefinition(new ActionDefinition( "update_repo", ActionType.SYSTEM, "", "HDFS", "DATANODE", "Does file exist", - TargetHostType.ANY, Short.valueOf("100"))); + TargetHostType.ANY, Short.valueOf("100"), null)); controller.getAmbariMetaInfo().addActionDefinition(new ActionDefinition( actionDef3, ActionType.SYSTEM, "", "MAPREDUCE", "MAPREDUCE_CLIENT", "Does file exist", - TargetHostType.ANY, Short.valueOf("100"))); + TargetHostType.ANY, Short.valueOf("100"), null)); controller.getAmbariMetaInfo().addActionDefinition(new ActionDefinition( actionDef4, ActionType.SYSTEM, "", "HIVE", "", "Does file exist", - TargetHostType.ANY, Short.valueOf("100"))); + TargetHostType.ANY, Short.valueOf("100"), null)); actionRequest = new ExecuteActionRequest(cluster1, null, actionDef1, null, null, null, false); expectActionCreationErrorWithMessage(actionRequest, requestProperties, @@ -6560,7 +6560,7 @@ public class AmbariManagementControllerTest { controller.getAmbariMetaInfo().addActionDefinition(new ActionDefinition( action1, ActionType.SYSTEM, "", "HDFS", "", "Some custom action.", - TargetHostType.ALL, Short.valueOf("10010"))); + TargetHostType.ALL, Short.valueOf("10010"), null)); Map<String, String> params = new HashMap<String, String>() {{ put("test", "test"); @@ -10601,7 +10601,7 @@ public class AmbariManagementControllerTest { ambariMetaInfo.addActionDefinition(new ActionDefinition(action1, ActionType.SYSTEM, "", "", "", "action def description", TargetHostType.ANY, - Short.valueOf("60"))); + Short.valueOf("60"), null)); Map<String, String> requestProperties = new HashMap<String, String>(); requestProperties.put(REQUEST_CONTEXT_PROPERTY, "Called from a test"); http://git-wip-us.apache.org/repos/asf/ambari/blob/e7b85260/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/ActionResourceProviderTest.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/ActionResourceProviderTest.java b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/ActionResourceProviderTest.java index 96995b4..c581ff4 100644 --- a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/ActionResourceProviderTest.java +++ b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/ActionResourceProviderTest.java @@ -97,13 +97,13 @@ public class ActionResourceProviderTest { List<ActionDefinition> allDefinition = new ArrayList<ActionDefinition>(); allDefinition.add(new ActionDefinition( "a1", ActionType.SYSTEM, "fileName", "HDFS", "DATANODE", "Does file exist", TargetHostType.ANY, - Short.valueOf("100"))); + Short.valueOf("100"), null)); allDefinition.add(new ActionDefinition( "a2", ActionType.SYSTEM, "fileName", "HDFS", "DATANODE", "Does file exist", TargetHostType.ANY, - Short.valueOf("100"))); + Short.valueOf("100"), null)); allDefinition.add(new ActionDefinition( "a3", ActionType.SYSTEM, "fileName", "HDFS", "DATANODE", "Does file exist", TargetHostType.ANY, - Short.valueOf("100"))); + Short.valueOf("100"), null)); Set<ActionResponse> allResponse = new HashSet<ActionResponse>(); for (ActionDefinition definition : allDefinition) { @@ -112,7 +112,7 @@ public class ActionResourceProviderTest { ActionDefinition namedDefinition = new ActionDefinition( "a1", ActionType.SYSTEM, "fileName", "HDFS", "DATANODE", "Does file exist", TargetHostType.ANY, - Short.valueOf("100")); + Short.valueOf("100"), null); Set<ActionResponse> nameResponse = new HashSet<ActionResponse>(); nameResponse.add(namedDefinition.convertToResponse()); http://git-wip-us.apache.org/repos/asf/ambari/blob/e7b85260/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/RequestResourceProviderTest.java ---------------------------------------------------------------------- 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 65efc63..4444714 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 @@ -22,19 +22,20 @@ package org.apache.ambari.server.controller.internal; import static org.apache.ambari.server.controller.internal.HostComponentResourceProvider.HOST_COMPONENT_STALE_CONFIGS_PROPERTY_ID; import static org.easymock.EasyMock.anyObject; import static org.easymock.EasyMock.capture; -import static org.easymock.EasyMock.createMock; -import static org.easymock.EasyMock.createNiceMock; -import static org.easymock.EasyMock.eq; import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.eq; import static org.easymock.EasyMock.newCapture; -import static org.easymock.EasyMock.replay; -import static org.easymock.EasyMock.reset; -import static org.easymock.EasyMock.verify; +import static org.powermock.api.easymock.PowerMock.createMock; +import static org.powermock.api.easymock.PowerMock.createNiceMock; +import static org.powermock.api.easymock.PowerMock.replay; +import static org.powermock.api.easymock.PowerMock.reset; +import static org.powermock.api.easymock.PowerMock.verify; import java.lang.reflect.Field; import java.util.Arrays; import java.util.Collection; import java.util.Collections; +import java.util.EnumSet; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashMap; @@ -49,6 +50,7 @@ import org.apache.ambari.server.actionmanager.ActionManager; import org.apache.ambari.server.actionmanager.HostRoleCommand; import org.apache.ambari.server.actionmanager.HostRoleStatus; import org.apache.ambari.server.actionmanager.Stage; +import org.apache.ambari.server.api.services.AmbariMetaInfo; import org.apache.ambari.server.api.services.BaseRequest; import org.apache.ambari.server.controller.AmbariManagementController; import org.apache.ambari.server.controller.AmbariServer; @@ -63,6 +65,7 @@ import org.apache.ambari.server.controller.utilities.ClusterControllerHelper; import org.apache.ambari.server.controller.utilities.PredicateBuilder; import org.apache.ambari.server.controller.utilities.PredicateHelper; import org.apache.ambari.server.controller.utilities.PropertyHelper; +import org.apache.ambari.server.customactions.ActionDefinition; import org.apache.ambari.server.orm.dao.HostRoleCommandDAO; import org.apache.ambari.server.orm.dao.HostRoleCommandStatusSummaryDTO; import org.apache.ambari.server.orm.dao.RequestDAO; @@ -70,6 +73,7 @@ import org.apache.ambari.server.orm.entities.RequestEntity; import org.apache.ambari.server.security.TestAuthenticationFactory; import org.apache.ambari.server.security.authorization.AuthorizationException; import org.apache.ambari.server.security.authorization.AuthorizationHelperInitializer; +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.topology.ClusterTopology; @@ -1307,21 +1311,69 @@ public class RequestResourceProviderTest { } @Test - public void testCreateResourcesForNonCluster() throws Exception { + public void testCreateResourcesCheckHostForNonClusterAsAdministrator() throws Exception { + testCreateResourcesForNonCluster(TestAuthenticationFactory.createAdministrator(), "check_host", + EnumSet.of(RoleAuthorization.HOST_ADD_DELETE_HOSTS)); + } + + @Test + public void testCreateResourcesCheckHostForNonClusterAsClusterAdministrator() throws Exception { + testCreateResourcesForNonCluster(TestAuthenticationFactory.createClusterAdministrator(), "check_host", + EnumSet.of(RoleAuthorization.HOST_ADD_DELETE_HOSTS)); + } + + @Test + public void testCreateResourcesCheckHostForNonClusterAsClusterOperator() throws Exception { + testCreateResourcesForNonCluster(TestAuthenticationFactory.createClusterOperator(), "check_host", + EnumSet.of(RoleAuthorization.HOST_ADD_DELETE_HOSTS)); + } + + @Test(expected = AuthorizationException.class) + public void testCreateResourcesCheckHostForNonClusterAsServiceAdministrator() throws Exception { + testCreateResourcesForNonCluster(TestAuthenticationFactory.createServiceAdministrator(), "check_host", + EnumSet.of(RoleAuthorization.HOST_ADD_DELETE_HOSTS)); + } + + @Test + public void testCreateResourcesCheckJavaForNonClusterAsAdministrator() throws Exception { + testCreateResourcesForNonCluster(TestAuthenticationFactory.createAdministrator(), "check_java", null); + } + + @Test(expected = AuthorizationException.class) + public void testCreateResourcesCheckJavaForNonClusterAsClusterAdministrator() throws Exception { + testCreateResourcesForNonCluster(TestAuthenticationFactory.createClusterAdministrator(), "check_java", null); + } + + @Test(expected = AuthorizationException.class) + public void testCreateResourcesCheckJavaForNonClusterAsClusterOperator() throws Exception { + testCreateResourcesForNonCluster(TestAuthenticationFactory.createClusterOperator(), "check_java", null); + } + + @Test(expected = AuthorizationException.class) + public void testCreateResourcesForNonClusterAsServiceAdministrator() throws Exception { + testCreateResourcesForNonCluster(TestAuthenticationFactory.createServiceAdministrator(), "check_java", null); + } + + private void testCreateResourcesForNonCluster(Authentication authentication, String actionName, Set<RoleAuthorization> permissions) throws Exception { Resource.Type type = Resource.Type.Request; Capture<ExecuteActionRequest> actionRequest = newCapture(); Capture<HashMap<String, String>> propertyMap = newCapture(); AmbariManagementController managementController = createMock(AmbariManagementController.class); + AmbariMetaInfo metaInfo = createMock(AmbariMetaInfo.class); + ActionDefinition actionDefinition = createMock(ActionDefinition.class); RequestStatusResponse response = createNiceMock(RequestStatusResponse.class); expect(managementController.createAction(capture(actionRequest), capture(propertyMap))) .andReturn(response).anyTimes(); + expect(managementController.getAmbariMetaInfo()).andReturn(metaInfo).anyTimes(); + expect(metaInfo.getActionDefinition(actionName)).andReturn(actionDefinition).anyTimes(); + expect(actionDefinition.getPermissions()).andReturn(permissions).anyTimes(); expect(response.getMessage()).andReturn("Message").anyTimes(); // replay - replay(managementController, response); + replay(managementController, metaInfo, actionDefinition, response); // add the property map to a set for the request. add more maps for multiple creates Set<Map<String, Object>> propertySet = new LinkedHashSet<Map<String, Object>>(); @@ -1338,7 +1390,9 @@ public class RequestResourceProviderTest { propertySet.add(properties); Map<String, String> requestInfoProperties = new HashMap<String, String>(); - requestInfoProperties.put(RequestResourceProvider.ACTION_ID, "check_java"); + requestInfoProperties.put(RequestResourceProvider.ACTION_ID, actionName); + + SecurityContextHolder.getContext().setAuthentication(authentication); // create the request Request request = PropertyHelper.getCreateRequest(propertySet, requestInfoProperties); @@ -1352,7 +1406,7 @@ public class RequestResourceProviderTest { Assert.assertTrue(actionRequest.hasCaptured()); Assert.assertFalse("expected an action", capturedRequest.isCommand()); - Assert.assertEquals("check_java", capturedRequest.getActionName()); + Assert.assertEquals(actionName, capturedRequest.getActionName()); Assert.assertEquals(null, capturedRequest.getCommandName()); Assert.assertNotNull(capturedRequest.getResourceFilters()); Assert.assertEquals(1, capturedRequest.getResourceFilters().size()); http://git-wip-us.apache.org/repos/asf/ambari/blob/e7b85260/ambari-server/src/test/java/org/apache/ambari/server/customactions/ActionDefinitionManagerTest.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/test/java/org/apache/ambari/server/customactions/ActionDefinitionManagerTest.java b/ambari-server/src/test/java/org/apache/ambari/server/customactions/ActionDefinitionManagerTest.java index ec84922..f7808d1 100644 --- a/ambari-server/src/test/java/org/apache/ambari/server/customactions/ActionDefinitionManagerTest.java +++ b/ambari-server/src/test/java/org/apache/ambari/server/customactions/ActionDefinitionManagerTest.java @@ -19,22 +19,25 @@ package org.apache.ambari.server.customactions; import java.io.File; +import java.util.EnumSet; import junit.framework.Assert; import org.apache.ambari.server.actionmanager.ActionType; import org.apache.ambari.server.actionmanager.TargetHostType; +import org.apache.ambari.server.security.authorization.RoleAuthorization; import org.junit.Test; public class ActionDefinitionManagerTest { - private final String customActionDefinitionRoot = "./src/test/resources/custom_action_definitions/"; + private static final String CUSTOM_ACTION_DEFINITION_ROOT = "./src/test/resources/custom_action_definitions/"; + private static final String CUSTOM_ACTION_DEFINITION_INVALID_ROOT = "./src/test/resources/custom_action_definitions_invalid/"; @Test public void testReadCustomActionDefinitions() throws Exception { ActionDefinitionManager manager = new ActionDefinitionManager(); - manager.readCustomActionDefinitions(new File(customActionDefinitionRoot)); + manager.readCustomActionDefinitions(new File(CUSTOM_ACTION_DEFINITION_ROOT)); - Assert.assertEquals(2, manager.getAllActionDefinition().size()); + Assert.assertEquals(3, manager.getAllActionDefinition().size()); ActionDefinition ad = manager.getActionDefinition("customAction1"); Assert.assertNotNull(ad); Assert.assertEquals("customAction1", ad.getActionName()); @@ -45,6 +48,7 @@ public class ActionDefinitionManagerTest { Assert.assertEquals(60, (int)ad.getDefaultTimeout()); Assert.assertEquals(TargetHostType.ALL, ad.getTargetType()); Assert.assertEquals(ActionType.USER, ad.getActionType()); + Assert.assertEquals(EnumSet.of(RoleAuthorization.HOST_ADD_DELETE_COMPONENTS, RoleAuthorization.HOST_ADD_DELETE_HOSTS), ad.getPermissions()); ad = manager.getActionDefinition("customAction2"); Assert.assertNotNull(ad); @@ -56,6 +60,25 @@ public class ActionDefinitionManagerTest { Assert.assertEquals(60, (int)ad.getDefaultTimeout()); Assert.assertEquals(null, ad.getTargetType()); Assert.assertEquals(ActionType.USER, ad.getActionType()); + Assert.assertEquals(EnumSet.of(RoleAuthorization.HOST_ADD_DELETE_COMPONENTS, RoleAuthorization.HOST_ADD_DELETE_HOSTS), ad.getPermissions()); + + ad = manager.getActionDefinition("customAction3"); + Assert.assertNotNull(ad); + Assert.assertEquals("customAction3", ad.getActionName()); + Assert.assertEquals("A random test", ad.getDescription()); + Assert.assertEquals(null, ad.getInputs()); + Assert.assertEquals("TASKTRACKER", ad.getTargetComponent()); + Assert.assertEquals("MAPREDUCE", ad.getTargetService()); + Assert.assertEquals(60, (int)ad.getDefaultTimeout()); + Assert.assertEquals(null, ad.getTargetType()); + Assert.assertEquals(ActionType.USER, ad.getActionType()); + Assert.assertNull(ad.getPermissions()); + } + + @Test(expected = IllegalArgumentException.class) + public void testReadInvalidCustomActionDefinitions() throws Exception { + ActionDefinitionManager manager = new ActionDefinitionManager(); + manager.readCustomActionDefinitions(new File(CUSTOM_ACTION_DEFINITION_INVALID_ROOT)); } } http://git-wip-us.apache.org/repos/asf/ambari/blob/e7b85260/ambari-server/src/test/java/org/apache/ambari/server/security/TestAuthenticationFactory.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/test/java/org/apache/ambari/server/security/TestAuthenticationFactory.java b/ambari-server/src/test/java/org/apache/ambari/server/security/TestAuthenticationFactory.java index 69b4b08..4301bf8 100644 --- a/ambari-server/src/test/java/org/apache/ambari/server/security/TestAuthenticationFactory.java +++ b/ambari-server/src/test/java/org/apache/ambari/server/security/TestAuthenticationFactory.java @@ -48,10 +48,18 @@ public class TestAuthenticationFactory { return createClusterAdministrator("clusterAdmin", 4L); } + public static Authentication createClusterOperator() { + return createClusterOperator("clusterOp", 4L); + } + public static Authentication createClusterAdministrator(String name, Long clusterResourceId) { return new TestAuthorization(name, Collections.singleton(createClusterAdministratorGrantedAuthority(clusterResourceId))); } + public static Authentication createClusterOperator(String name, Long clusterResourceId) { + return new TestAuthorization(name, Collections.singleton(createClusterOperatorGrantedAuthority(clusterResourceId))); + } + public static Authentication createServiceAdministrator() { return createServiceAdministrator("serviceAdmin", 4L); } @@ -92,6 +100,10 @@ public class TestAuthenticationFactory { return new AmbariGrantedAuthority(createClusterAdministratorPrivilegeEntity(clusterResourceId)); } + private static GrantedAuthority createClusterOperatorGrantedAuthority(Long clusterResourceId) { + return new AmbariGrantedAuthority(createClusterOperatorPrivilegeEntity(clusterResourceId)); + } + private static GrantedAuthority createServiceAdministratorGrantedAuthority(Long clusterResourceId) { return new AmbariGrantedAuthority(createServiceAdministratorPrivilegeEntity(clusterResourceId)); } @@ -122,6 +134,13 @@ public class TestAuthenticationFactory { return privilegeEntity; } + private static PrivilegeEntity createClusterOperatorPrivilegeEntity(Long clusterResourceId) { + PrivilegeEntity privilegeEntity = new PrivilegeEntity(); + privilegeEntity.setResource(createClusterResourceEntity(clusterResourceId)); + privilegeEntity.setPermission(createClusterOperatorPermission()); + return privilegeEntity; + } + private static PrivilegeEntity createServiceAdministratorPrivilegeEntity(Long clusterResourceId) { PrivilegeEntity privilegeEntity = new PrivilegeEntity(); privilegeEntity.setResource(createClusterResourceEntity(clusterResourceId)); @@ -200,6 +219,44 @@ public class TestAuthenticationFactory { return permissionEntity; } + private static PermissionEntity createClusterOperatorPermission() { + PermissionEntity permissionEntity = new PermissionEntity(); + permissionEntity.setId(5); + permissionEntity.setResourceType(createResourceTypeEntity(ResourceType.CLUSTER)); + permissionEntity.setAuthorizations(createAuthorizations(EnumSet.of( + RoleAuthorization.HOST_VIEW_CONFIGS, + RoleAuthorization.HOST_ADD_DELETE_COMPONENTS, + RoleAuthorization.HOST_VIEW_METRICS, + RoleAuthorization.SERVICE_DECOMMISSION_RECOMMISSION, + RoleAuthorization.CLUSTER_VIEW_CONFIGS, + RoleAuthorization.SERVICE_MANAGE_ALERTS, + RoleAuthorization.SERVICE_ENABLE_HA, + RoleAuthorization.SERVICE_VIEW_METRICS, + RoleAuthorization.SERVICE_RUN_CUSTOM_COMMAND, + RoleAuthorization.HOST_VIEW_STATUS_INFO, + RoleAuthorization.CLUSTER_VIEW_METRICS, + RoleAuthorization.SERVICE_VIEW_STATUS_INFO, + RoleAuthorization.CLUSTER_VIEW_STACK_DETAILS, + RoleAuthorization.SERVICE_COMPARE_CONFIGS, + RoleAuthorization.SERVICE_VIEW_ALERTS, + RoleAuthorization.CLUSTER_MANAGE_CONFIG_GROUPS, + RoleAuthorization.SERVICE_TOGGLE_ALERTS, + RoleAuthorization.SERVICE_MOVE, + RoleAuthorization.SERVICE_RUN_SERVICE_CHECK, + RoleAuthorization.SERVICE_MODIFY_CONFIGS, + RoleAuthorization.CLUSTER_VIEW_STATUS_INFO, + RoleAuthorization.SERVICE_VIEW_CONFIGS, + RoleAuthorization.HOST_ADD_DELETE_HOSTS, + RoleAuthorization.SERVICE_START_STOP, + RoleAuthorization.CLUSTER_VIEW_ALERTS, + RoleAuthorization.HOST_TOGGLE_MAINTENANCE, + RoleAuthorization.SERVICE_TOGGLE_MAINTENANCE, + RoleAuthorization.SERVICE_MANAGE_CONFIG_GROUPS, + RoleAuthorization.CLUSTER_MANAGE_USER_PERSISTED_DATA, + RoleAuthorization.CLUSTER_MANAGE_CREDENTIALS))); + return permissionEntity; + } + private static PermissionEntity createServiceAdministratorPermission() { PermissionEntity permissionEntity = new PermissionEntity(); permissionEntity.setId(5); http://git-wip-us.apache.org/repos/asf/ambari/blob/e7b85260/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog240Test.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog240Test.java b/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog240Test.java index 4dedc98..2490851 100644 --- a/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog240Test.java +++ b/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog240Test.java @@ -464,6 +464,7 @@ public class UpgradeCatalog240Test { Method addNewConfigurationsFromXml = AbstractUpgradeCatalog.class.getDeclaredMethod("addNewConfigurationsFromXml"); Method updateAlerts = UpgradeCatalog240.class.getDeclaredMethod("updateAlerts"); Method addManageUserPersistedDataPermission = UpgradeCatalog240.class.getDeclaredMethod("addManageUserPersistedDataPermission"); + Method allowClusterOperatorToManageCredentials = UpgradeCatalog240.class.getDeclaredMethod("allowClusterOperatorToManageCredentials"); Method addSettingPermission = UpgradeCatalog240.class.getDeclaredMethod("addSettingPermission"); Method updateHDFSConfigs = UpgradeCatalog240.class.getDeclaredMethod("updateHDFSConfigs"); Method updateHIVEConfigs = UpgradeCatalog240.class.getDeclaredMethod("updateHIVEConfigs"); @@ -495,6 +496,7 @@ public class UpgradeCatalog240Test { .addMockedMethod(updateAlerts) .addMockedMethod(addSettingPermission) .addMockedMethod(addManageUserPersistedDataPermission) + .addMockedMethod(allowClusterOperatorToManageCredentials) .addMockedMethod(updateHDFSConfigs) .addMockedMethod(updateHIVEConfigs) .addMockedMethod(updateAmsConfigs) @@ -520,6 +522,7 @@ public class UpgradeCatalog240Test { upgradeCatalog240.updateAlerts(); upgradeCatalog240.addSettingPermission(); upgradeCatalog240.addManageUserPersistedDataPermission(); + upgradeCatalog240.allowClusterOperatorToManageCredentials(); upgradeCatalog240.updateHDFSConfigs(); upgradeCatalog240.updateHIVEConfigs(); upgradeCatalog240.updateAMSConfigs(); http://git-wip-us.apache.org/repos/asf/ambari/blob/e7b85260/ambari-server/src/test/resources/custom_action_definitions/cust_action_definitions1.xml ---------------------------------------------------------------------- diff --git a/ambari-server/src/test/resources/custom_action_definitions/cust_action_definitions1.xml b/ambari-server/src/test/resources/custom_action_definitions/cust_action_definitions1.xml index 9cee575..e8e6bc8 100644 --- a/ambari-server/src/test/resources/custom_action_definitions/cust_action_definitions1.xml +++ b/ambari-server/src/test/resources/custom_action_definitions/cust_action_definitions1.xml @@ -27,6 +27,7 @@ <targetComponent>TASKTRACKER</targetComponent> <description>A random test</description> <targetType>ALL</targetType> + <permissions>HOST.ADD_DELETE_HOSTS,HOST.ADD_DELETE_COMPONENTS</permissions> </actionDefinition> <actionDefinition> <actionName>customAction2</actionName> @@ -34,9 +35,17 @@ <targetService>MAPREDUCE</targetService> <targetComponent>TASKTRACKER</targetComponent> <description>A random test</description> + <permissions> HOST.ADD_DELETE_HOSTS , HOST.ADD_DELETE_COMPONENTS </permissions> <!-- Note the spaces --> </actionDefinition> <actionDefinition> <actionName>customAction3</actionName> + <actionType>USER</actionType> + <targetService>MAPREDUCE</targetService> + <targetComponent>TASKTRACKER</targetComponent> + <description>A random test</description> + </actionDefinition> + <actionDefinition> + <actionName>customAction4</actionName> <actionType>USERS_OWN</actionType> <targetService>MAPREDUCE</targetService> <targetComponent>TASKTRACKER</targetComponent> http://git-wip-us.apache.org/repos/asf/ambari/blob/e7b85260/ambari-server/src/test/resources/custom_action_definitions_invalid/cust_action_definitions_invalid.xml ---------------------------------------------------------------------- diff --git a/ambari-server/src/test/resources/custom_action_definitions_invalid/cust_action_definitions_invalid.xml b/ambari-server/src/test/resources/custom_action_definitions_invalid/cust_action_definitions_invalid.xml new file mode 100644 index 0000000..a6fd71e --- /dev/null +++ b/ambari-server/src/test/resources/custom_action_definitions_invalid/cust_action_definitions_invalid.xml @@ -0,0 +1,33 @@ +<?xml version="1.0"?> +<?xml-stylesheet type="text/xsl" href="action_definition.xsl"?> + +<!-- + ~ 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. + --> + +<actionDefinitions> + <actionDefinition> + <actionName>invalidCustomAction1</actionName> + <actionType>USER</actionType> + <inputs>threshold</inputs> + <targetService>MAPREDUCE</targetService> + <targetComponent>TASKTRACKER</targetComponent> + <description>A random test</description> + <targetType>ALL</targetType> + <permissions>NOT.A.PERMISSION</permissions> + </actionDefinition> +</actionDefinitions> \ No newline at end of file
