/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.ambari.server.controller.internal; import java.util.EnumSet; import java.util.Set; import org.apache.ambari.server.orm.entities.AlertCurrentEntity; import org.apache.ambari.server.orm.entities.AlertDefinitionEntity; import org.apache.ambari.server.orm.entities.AlertGroupEntity; import org.apache.ambari.server.orm.entities.AlertHistoryEntity; import org.apache.ambari.server.orm.entities.ClusterEntity; import org.apache.ambari.server.orm.entities.ResourceEntity; 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.commons.lang.StringUtils; /** * AlertResourceProviderUtils provides utility methods used to help perform tasks within alert-specific * resource providers. */ public class AlertResourceProviderUtils { /** * A set of RoleAuthorizations where one is required in order to be authorized to view * cluster-level alerts */ private static final Set<RoleAuthorization> AUTHORIZATIONS_VIEW_CLUSTER_ALERTS = EnumSet.of( RoleAuthorization.CLUSTER_VIEW_ALERTS, RoleAuthorization.CLUSTER_TOGGLE_ALERTS, RoleAuthorization.CLUSTER_MANAGE_ALERTS); /** * A set of RoleAuthorizations where one is required in order to be authorized to view * service-level alerts */ private static final Set<RoleAuthorization> AUTHORIZATIONS_VIEW_SERVICE_ALERTS = EnumSet.of( RoleAuthorization.CLUSTER_VIEW_ALERTS, RoleAuthorization.CLUSTER_TOGGLE_ALERTS, RoleAuthorization.CLUSTER_MANAGE_ALERTS, RoleAuthorization.SERVICE_VIEW_ALERTS, RoleAuthorization.SERVICE_TOGGLE_ALERTS, RoleAuthorization.SERVICE_MANAGE_ALERTS); /** * A set of RoleAuthorizations where one is required in order to be authorized to execute * cluster-level alerts */ private static final Set<RoleAuthorization> AUTHORIZATIONS_EXECUTE_CLUSTER_ALERTS = AUTHORIZATIONS_VIEW_CLUSTER_ALERTS; /** * A set of RoleAuthorizations where one is required in order to be authorized to execute * service-level alerts */ private static final Set<RoleAuthorization> AUTHORIZATIONS_EXECUTE_SERVICE_ALERTS = AUTHORIZATIONS_VIEW_SERVICE_ALERTS; /** * A set of RoleAuthorizations where one is required in order to be authorized to toggle * cluster-level alerts */ private static final Set<RoleAuthorization> AUTHORIZATIONS_TOGGLE_CLUSTER_ALERTS = EnumSet.of( RoleAuthorization.CLUSTER_TOGGLE_ALERTS, RoleAuthorization.CLUSTER_MANAGE_ALERTS); /** * A set of RoleAuthorizations where one is required in order to be authorized to toggle * service-level alerts */ private static final Set<RoleAuthorization> AUTHORIZATIONS_TOGGLE_SERVICE_ALERTS = EnumSet.of( RoleAuthorization.CLUSTER_TOGGLE_ALERTS, RoleAuthorization.CLUSTER_MANAGE_ALERTS, RoleAuthorization.SERVICE_TOGGLE_ALERTS, RoleAuthorization.SERVICE_MANAGE_ALERTS); /** * A set of RoleAuthorizations where one is required in order to be authorized to create, update, * and delete cluster-level alerts */ private static final Set<RoleAuthorization> AUTHORIZATIONS_MANAGE_CLUSTER_ALERTS = EnumSet.of( RoleAuthorization.CLUSTER_MANAGE_ALERTS); /** * A set of RoleAuthorizations where one is required in order to be authorized to create, update, * and delete service-level alerts */ private static final Set<RoleAuthorization> AUTHORIZATIONS_MANAGE_SERVICE_ALERTS = EnumSet.of( RoleAuthorization.CLUSTER_MANAGE_ALERTS, RoleAuthorization.SERVICE_MANAGE_ALERTS); /* ------------------------------------------------------------------------------------------ * Checks for VIEWING Alerts * ------------------------------------------------------------------------------------------ */ /** * Tests if the authenticated user is authorized to view the requested alert data * * @param entity an AlertGroupEntity * @param clusterResourceId the resource id of the relevant cluster * @return true if the authenticated user is authorized; otherwise false */ public static boolean hasViewAuthorization(AlertGroupEntity entity, Long clusterResourceId) { return (null != entity) && hasViewAuthorization(entity.getServiceName(), clusterResourceId); } /** * Tests if the authenticated user is authorized to view service- or cluster-level alert data * * @param serviceName the name of the relevant service - null or empty indicates a cluster-level alert * @param clusterResourceId the resource id of the relevant cluster * @return true if the authenticated user is authorized; otherwise false */ public static boolean hasViewAuthorization(String serviceName, Long clusterResourceId) { return hasAuthorization(serviceName, clusterResourceId, AUTHORIZATIONS_VIEW_CLUSTER_ALERTS, AUTHORIZATIONS_VIEW_SERVICE_ALERTS); } /** * Tests if the authenticated user is authorized to view service- or cluster-level alert data. * An authorization failure results in a thrown {@link AuthorizationException}. * * @param entity an AlertCurrentEntity * @throws AuthorizationException if the authenticated user is not authorized */ public static void verifyViewAuthorization(AlertCurrentEntity entity) throws AuthorizationException { if (entity != null) { verifyViewAuthorization(entity.getAlertHistory()); } } /** * Tests if the authenticated user is authorized to view service- or cluster-level alert data. * An authorization failure results in a thrown {@link AuthorizationException}. * * @param entity an AlertHistoryEntity * @throws AuthorizationException if the authenticated user is not authorized */ public static void verifyViewAuthorization(AlertHistoryEntity entity) throws AuthorizationException { if (entity != null) { verifyViewAuthorization(entity.getAlertDefinition()); } } /** * Tests if the authenticated user is authorized to view service- or cluster-level alert data. * An authorization failure results in a thrown {@link AuthorizationException}. * * @param entity an AlertGroupEntity * @param clusterResourceId the resource id of the relevant cluster * @throws AuthorizationException if the authenticated user is not authorized */ public static void verifyViewAuthorization(AlertGroupEntity entity, Long clusterResourceId) throws AuthorizationException { if (entity != null) { verifyViewAuthorization(entity.getServiceName(), clusterResourceId); } } /** * Tests if the authenticated user is authorized to view service- or cluster-level alert data. * An authorization failure results in a thrown {@link AuthorizationException}. * * @param entity an AlertDefinitionEntity * @throws AuthorizationException if the authenticated user is not authorized */ public static void verifyViewAuthorization(AlertDefinitionEntity entity) throws AuthorizationException { verifyAuthorization(entity, AUTHORIZATIONS_VIEW_CLUSTER_ALERTS, AUTHORIZATIONS_VIEW_SERVICE_ALERTS, "view"); } /** * Tests if the authenticated user is authorized to view service- or cluster-level alert data. * An authorization failure results in a thrown {@link AuthorizationException}. * * @param serviceName the name of the relevant service - null or empty indicates a cluster-level alert * @param clusterResourceId the resource id of the relevant cluster * @throws AuthorizationException if the authenticated user is not authorized */ public static void verifyViewAuthorization(String serviceName, Long clusterResourceId) throws AuthorizationException { verifyAuthorization(serviceName, clusterResourceId, AUTHORIZATIONS_VIEW_CLUSTER_ALERTS, AUTHORIZATIONS_VIEW_SERVICE_ALERTS, "view"); } /* ------------------------------------------------------------------------------------------ * Checks for EXECUTING Alerts * ------------------------------------------------------------------------------------------ */ /** * Tests if the authenticated user is authorized to execute service- or cluster-level alert data. * An authorization failure results in a thrown {@link AuthorizationException}. * * @param entity an AlertDefinitionEntity * @throws AuthorizationException if the authenticated user is not authorized */ public static void verifyExecuteAuthorization(AlertDefinitionEntity entity) throws AuthorizationException { verifyAuthorization(entity, AUTHORIZATIONS_EXECUTE_CLUSTER_ALERTS, AUTHORIZATIONS_EXECUTE_SERVICE_ALERTS, "execute"); } /** * Tests if the authenticated user is authorized to execute service- or cluster-level alert data. * An authorization failure results in a thrown {@link AuthorizationException}. * * @param serviceName the name of the relevant service - null or empty indicates a cluster-level alert * @param clusterResourceId the resource id of the relevant cluster * @throws AuthorizationException if the authenticated user is not authorized */ public static void verifyExecuteAuthorization(String serviceName, Long clusterResourceId) throws AuthorizationException { verifyAuthorization(serviceName, clusterResourceId, AUTHORIZATIONS_EXECUTE_CLUSTER_ALERTS, AUTHORIZATIONS_EXECUTE_SERVICE_ALERTS, "execute"); } /* ------------------------------------------------------------------------------------------ * Checks for TOGGLING Alerts * ------------------------------------------------------------------------------------------ */ /** * Tests if the authenticated user is authorized to toggle service- or cluster-level alert data. * An authorization failure results in a thrown {@link AuthorizationException}. * * @param entity an AlertDefinitionEntity * @throws AuthorizationException if the authenticated user is not authorized */ public static void verifyToggleAuthorization(AlertDefinitionEntity entity) throws AuthorizationException { verifyAuthorization(entity, AUTHORIZATIONS_TOGGLE_CLUSTER_ALERTS, AUTHORIZATIONS_TOGGLE_SERVICE_ALERTS, "execute"); } /** * Tests if the authenticated user is authorized to toggle service- or cluster-level alert data. * An authorization failure results in a thrown {@link AuthorizationException}. * * @param serviceName the name of the relevant service - null or empty indicates a cluster-level alert * @param clusterResourceId the resource id of the relevant cluster * @throws AuthorizationException if the authenticated user is not authorized */ public static void verifyToggleAuthorization(String serviceName, Long clusterResourceId) throws AuthorizationException { verifyAuthorization(serviceName, clusterResourceId, AUTHORIZATIONS_TOGGLE_CLUSTER_ALERTS, AUTHORIZATIONS_TOGGLE_SERVICE_ALERTS, "execute"); } /* ------------------------------------------------------------------------------------------ * Checks for MANAGING Alerts * ------------------------------------------------------------------------------------------ */ /** * Tests if the authenticated user is authorized to manage service- or cluster-level alert data. * An authorization failure results in a thrown {@link AuthorizationException}. * * @param entity an AlertGroupEntity * @param clusterResourceId the resource id of the relevant cluster * @throws AuthorizationException if the authenticated user is not authorized */ public static void verifyManageAuthorization(AlertGroupEntity entity, Long clusterResourceId) throws AuthorizationException { if (entity != null) { verifyManageAuthorization(entity.getServiceName(), clusterResourceId); } } /** * Tests if the authenticated user is authorized to manage service- or cluster-level alert data. * An authorization failure results in a thrown {@link AuthorizationException}. * * @param entity an AlertDefinitionEntity * @throws AuthorizationException if the authenticated user is not authorized */ public static void verifyManageAuthorization(AlertDefinitionEntity entity) throws AuthorizationException { verifyAuthorization(entity, AUTHORIZATIONS_MANAGE_CLUSTER_ALERTS, AUTHORIZATIONS_MANAGE_SERVICE_ALERTS, "manage"); } /** * Tests if the authenticated user is authorized to manage service- or cluster-level alert data. * An authorization failure results in a thrown {@link AuthorizationException}. * * @param serviceName the name of the relevant service - null or empty indicates a cluster-level alert * @param clusterResourceId the resource id of the relevant cluster * @throws AuthorizationException if the authenticated user is not authorized */ public static void verifyManageAuthorization(String serviceName, Long clusterResourceId) throws AuthorizationException { verifyAuthorization(serviceName, clusterResourceId, AUTHORIZATIONS_MANAGE_CLUSTER_ALERTS, AUTHORIZATIONS_MANAGE_SERVICE_ALERTS, "manage"); } /* ------------------------------------------------------------------------------------------ * Generic checks * ------------------------------------------------------------------------------------------ */ /** * Tests if the authenticated user is authorized to for either service- or cluster-level access to * alert data. * <p/> * If the service name is null or empty, the alert is considered to be a cluster-level alert, * else it is considered to be a service-level alert. * <p/> * If the clusterResourceId is null, no cluster is assume and the alert is considered to be an * Ambari-level alert. * * @param serviceName the name of the relevant service - null or empty indicates a cluster-level alert * @param clusterResourceId the resource id of the relevant cluster * @param clusterLevelAuthorizations the set of cluster-level authorizations to check for * @param serviceLevelAuthorizations the set of service-level authorizations to check for * @return true if the authenticated user is authorized; otherwise false */ public static boolean hasAuthorization(String serviceName, Long clusterResourceId, Set<RoleAuthorization> clusterLevelAuthorizations, Set<RoleAuthorization> serviceLevelAuthorizations) { if (null == clusterResourceId) { // Do not let clusterResourceId be null because that indicates we don't care about which cluster // we are checking authorization for, but we do. Setting this to -1 ensures that no cluster // will match will will give only Ambari administrators access to this. clusterResourceId = -1L; } return AuthorizationHelper.isAuthorized(ResourceType.CLUSTER, clusterResourceId, (StringUtils.isEmpty(serviceName) || "AMBARI".equals(serviceName)) ? clusterLevelAuthorizations : serviceLevelAuthorizations); } /** * Tests if the authenticated user is authorized to for either service- or cluster-level access to * alert data. An authorization failure results in a thrown {@link AuthorizationException}. * <p/> * If the service name from the AlertDefinitionEntity is null or empty, the alert is considered to * be a cluster-level alert, else it is considered to be a service-level alert. * * @param entity an AlertDefinitionEntity * @param clusterLevelAuthorizations the set of cluster-level authorizations to check for * @param serviceLevelAuthorizations the set of service-level authorizations to check for * @param operation the name of the operation being tested for (used in error and logging messages) * @throws AuthorizationException if the authenticated user is not authorized * @see #verifyAuthorization(String, Long, Set, Set, String) */ public static void verifyAuthorization(AlertDefinitionEntity entity, Set<RoleAuthorization> clusterLevelAuthorizations, Set<RoleAuthorization> serviceLevelAuthorizations, String operation) throws AuthorizationException { ClusterEntity clusterEntity = (null == entity) ? null : entity.getCluster(); ResourceEntity resourceEntity = (null == clusterEntity) ? null : clusterEntity.getResource(); Long resourceId = (null == resourceEntity) ? null : resourceEntity.getId(); verifyAuthorization((null == entity) ? null : entity.getServiceName(), resourceId, clusterLevelAuthorizations, serviceLevelAuthorizations, operation); } /** * Tests if the authenticated user is authorized to for either service- or cluster-level access to * alert data. An authorization failure results in a thrown {@link AuthorizationException}. * <p/> * If the service name from the AlertDefinitionEntity is null or empty, the alert is considered to * be a cluster-level alert, else it is considered to be a service-level alert. * * @param serviceName the name of the relevant service - null or empty indicates a cluster-level alert * @param clusterResourceId the resource id of the relevant cluster * @param clusterLevelAuthorizations the set of cluster-level authorizations to check for * @param serviceLevelAuthorizations the set of service-level authorizations to check for * @param operation the name of the operation being tested for (used in error and logging messages) * @throws AuthorizationException if the authenticated user is not authorized */ public static void verifyAuthorization(String serviceName, Long clusterResourceId, Set<RoleAuthorization> clusterLevelAuthorizations, Set<RoleAuthorization> serviceLevelAuthorizations, String operation) throws AuthorizationException { if (null == clusterResourceId) { // Do not let clusterResourceId be null because that indicates we don't care about which cluster // we are checking authorization for, but we do. Setting this to -1 ensures that no cluster // will match will will give only Ambari administrators access to this. clusterResourceId = -1L; } // If the service name is AMBARI, than the alert is for the cluster if (StringUtils.isEmpty(serviceName) || "AMBARI".equals(serviceName)) { if (!AuthorizationHelper.isAuthorized(ResourceType.CLUSTER, clusterResourceId, clusterLevelAuthorizations)) { throw new AuthorizationException(String.format("The authenticated user is not authorized to %s cluster-level alerts", operation)); } } else { if (!AuthorizationHelper.isAuthorized(ResourceType.CLUSTER, clusterResourceId, serviceLevelAuthorizations)) { throw new AuthorizationException(String.format("The authenticated user is not authorized to %s service-level alerts", operation)); } } } }