/*
 * 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.cassandra.auth.jmx;

import java.lang.reflect.*;
import java.security.AccessControlContext;
import java.security.AccessController;
import java.security.Principal;
import java.util.Set;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import javax.management.MBeanServer;
import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;
import javax.management.remote.MBeanServerForwarder;
import javax.security.auth.Subject;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableSet;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.apache.cassandra.auth.*;
import org.apache.cassandra.config.DatabaseDescriptor;
import org.apache.cassandra.exceptions.ConfigurationException;
import org.apache.cassandra.service.StorageService;
import org.apache.cassandra.utils.FBUtilities;

/**
 * Provides a proxy interface to the platform's MBeanServer instance to perform
 * role-based authorization on method invocation.
 *
 * When used in conjunction with a suitable JMXAuthenticator, which attaches a CassandraPrincipal
 * to authenticated Subjects, this class uses the configured IAuthorizer to verify that the
 * subject has the required permissions to execute methods on the MBeanServer and the MBeans it
 * manages.
 *
 * Because an ObjectName may contain wildcards, meaning it represents a set of individual MBeans,
 * JMX resources don't fit well with the hierarchical approach modelled by other IResource
 * implementations and utilised by ClientState::ensureHasPermission etc. To enable grants to use
 * pattern-type ObjectNames, this class performs its own custom matching and filtering of resources
 * rather than pushing that down to the configured IAuthorizer. To that end, during authorization
 * it pulls back all permissions for the active subject, filtering them to retain only grants on
 * JMXResources. It then uses ObjectName::apply to assert whether the target MBeans are wholly
 * represented by the resources with permissions. This means that it cannot use the PermissionsCache
 * as IAuthorizer can, so it manages its own cache locally.
 *
 * Methods are split into 2 categories; those which are to be invoked on the MBeanServer itself
 * and those which apply to MBean instances. Actually, this is somewhat of a construct as in fact
 * *all* invocations are performed on the MBeanServer instance, the distinction is made here on
 * those methods which take an ObjectName as their first argument and those which do not.
 * Invoking a method of the former type, e.g. MBeanServer::getAttribute(ObjectName name, String attribute),
 * implies that the caller is concerned with a specific MBean. Conversely, invoking a method such as
 * MBeanServer::getDomains is primarily a function of the MBeanServer itself. This class makes
 * such a distinction in order to identify which JMXResource the subject requires permissions on.
 *
 * Certain operations are never allowed for users and these are recorded in a blacklist so that we
 * can short circuit authorization process if one is attempted by a remote subject.
 *
 */
public class AuthorizationProxy implements InvocationHandler
{
    private static final Logger logger = LoggerFactory.getLogger(AuthorizationProxy.class);

    /*
     A whitelist of permitted methods on the MBeanServer interface which *do not* take an ObjectName
     as their first argument. These methods can be thought of as relating to the MBeanServer itself,
     rather than to the MBeans it manages. All of the whitelisted methods are essentially descriptive,
     hence they require the Subject to have the DESCRIBE permission on the root JMX resource.
     */
    private static final Set<String> MBEAN_SERVER_METHOD_WHITELIST = ImmutableSet.of("getDefaultDomain",
                                                                                     "getDomains",
                                                                                     "getMBeanCount",
                                                                                     "hashCode",
                                                                                     "queryMBeans",
                                                                                     "queryNames",
                                                                                     "toString");

    /*
     A blacklist of method names which are never permitted to be executed by a remote user,
     regardless of privileges they may be granted.
     */
    private static final Set<String> METHOD_BLACKLIST = ImmutableSet.of("createMBean",
                                                                        "deserialize",
                                                                        "getClassLoader",
                                                                        "getClassLoaderFor",
                                                                        "instantiate",
                                                                        "registerMBean",
                                                                        "unregisterMBean");

    private static final JMXPermissionsCache permissionsCache = new JMXPermissionsCache();
    private MBeanServer mbs;

    /*
     Used to check whether the Role associated with the authenticated Subject has superuser
     status. By default, just delegates to Roles::hasSuperuserStatus, but can be overridden for testing.
     */
    protected Function<RoleResource, Boolean> isSuperuser = Roles::hasSuperuserStatus;

    /*
     Used to retrieve the set of all permissions granted to a given role. By default, this fetches
     the permissions from the local cache, which in turn loads them from the configured IAuthorizer
     but can be overridden for testing.
     */
    protected Function<RoleResource, Set<PermissionDetails>> getPermissions = permissionsCache::get;

    /*
     Used to decide whether authorization is enabled or not, usually this depends on the configured
     IAuthorizer, but can be overridden for testing.
     */
    protected Supplier<Boolean> isAuthzRequired = () -> DatabaseDescriptor.getAuthorizer().requireAuthorization();

    /*
     Used to find matching MBeans when the invocation target is a pattern type ObjectName.
     Defaults to querying the MBeanServer but can be overridden for testing. See checkPattern for usage.
     */
    protected Function<ObjectName, Set<ObjectName>> queryNames = (name) -> mbs.queryNames(name, null);

    /*
     Used to determine whether auth setup has completed so we know whether the expect the IAuthorizer
     to be ready. Can be overridden for testing.
     */
    protected Supplier<Boolean> isAuthSetupComplete = () -> StorageService.instance.isAuthSetupComplete();

    @Override
    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable
    {
        String methodName = method.getName();

        if ("getMBeanServer".equals(methodName))
            throw new SecurityException("Access denied");

        // Retrieve Subject from current AccessControlContext
        AccessControlContext acc = AccessController.getContext();
        Subject subject = Subject.getSubject(acc);

        // Allow setMBeanServer iff performed on behalf of the connector server itself
        if (("setMBeanServer").equals(methodName))
        {
            if (subject != null)
                throw new SecurityException("Access denied");

            if (args[0] == null)
                throw new IllegalArgumentException("Null MBeanServer");

            if (mbs != null)
                throw new IllegalArgumentException("MBeanServer already initialized");

            mbs = (MBeanServer) args[0];
            return null;
        }

        if (authorize(subject, methodName, args))
            return invoke(method, args);

        throw new SecurityException("Access Denied");
    }

    /**
     * Performs the actual authorization of an identified subject to execute a remote method invocation.
     * @param subject The principal making the execution request. A null value represents a local invocation
     *                from the JMX connector itself
     * @param methodName Name of the method being invoked
     * @param args Array containing invocation argument. If the first element is an ObjectName instance, for
     *             authz purposes we consider this an invocation of an MBean method, otherwise it is treated
     *             as an invocation of a method on the MBeanServer.
     */
    @VisibleForTesting
    boolean authorize(Subject subject, String methodName, Object[] args)
    {
        logger.trace("Authorizing JMX method invocation {} for {}",
                     methodName,
                     subject == null ? "" :subject.toString().replaceAll("\\n", " "));

        if (!isAuthSetupComplete.get())
        {
            logger.trace("Auth setup is not complete, refusing access");
            return false;
        }

        // Permissive authorization is enabled
        if (!isAuthzRequired.get())
            return true;

        // Allow operations performed locally on behalf of the connector server itself
        if (subject == null)
            return true;

        // Restrict access to certain methods by any remote user
        if (METHOD_BLACKLIST.contains(methodName))
        {
            logger.trace("Access denied to blacklisted method {}", methodName);
            return false;
        }

        // Reject if the user has not authenticated
        Set<Principal> principals = subject.getPrincipals();
        if (principals == null || principals.isEmpty())
            return false;

        // Currently, we assume that the first Principal returned from the Subject
        // is the one to use for authorization. It would be good to make this more
        // robust, but we have no control over which Principals a given LoginModule
        // might choose to associate with the Subject following successful authentication
        RoleResource userResource = RoleResource.role(principals.iterator().next().getName());
        // A role with superuser status can do anything
        if (isSuperuser.apply(userResource))
            return true;

        // The method being invoked may be a method on an MBean, or it could belong
        // to the MBeanServer itself
        if (args != null && args[0] instanceof ObjectName)
            return authorizeMBeanMethod(userResource, methodName, args);
        else
            return authorizeMBeanServerMethod(userResource, methodName);
    }

    /**
     * Authorize execution of a method on the MBeanServer which does not take an MBean ObjectName
     * as its first argument. The whitelisted methods that match this criteria are generally
     * descriptive methods concerned with the MBeanServer itself, rather than with any particular
     * set of MBeans managed by the server and so we check the DESCRIBE permission on the root
     * JMXResource (representing the MBeanServer)
     *
     * @param subject
     * @param methodName
     * @return the result of the method invocation, if authorized
     * @throws Throwable
     * @throws SecurityException if authorization fails
     */
    private boolean authorizeMBeanServerMethod(RoleResource subject, String methodName)
    {
        logger.trace("JMX invocation of {} on MBeanServer requires permission {}", methodName, Permission.DESCRIBE);
        return (MBEAN_SERVER_METHOD_WHITELIST.contains(methodName) &&
            hasPermission(subject, Permission.DESCRIBE, JMXResource.root()));
    }

    /**
     * Authorize execution of a method on an MBean (or set of MBeans) which may be
     * managed by the MBeanServer. Note that this also includes the queryMBeans and queryNames
     * methods of MBeanServer as those both take an ObjectName (possibly a pattern containing
     * wildcards) as their first argument. They both of those methods also accept null arguments,
     * in which case they will be handled by authorizedMBeanServerMethod
     *
     * @param role
     * @param methodName
     * @param args
     * @return the result of the method invocation, if authorized
     * @throws Throwable
     * @throws SecurityException if authorization fails
     */
    private boolean authorizeMBeanMethod(RoleResource role, String methodName, Object[] args)
    {
        ObjectName targetBean = (ObjectName)args[0];

        // work out which permission we need to execute the method being called on the mbean
        Permission requiredPermission = getRequiredPermission(methodName);
        if (null == requiredPermission)
            return false;

        logger.trace("JMX invocation of {} on {} requires permission {}", methodName, targetBean, requiredPermission);

        // find any JMXResources upon which the authenticated subject has been granted the
        // reqired permission. We'll do ObjectName-specific filtering & matching of resources later
        Set<JMXResource> permittedResources = getPermittedResources(role, requiredPermission);

        if (permittedResources.isEmpty())
            return false;

        // finally, check the JMXResource from the grants to see if we have either
        // an exact match or a wildcard match for the target resource, whichever is
        // applicable
        return targetBean.isPattern()
                ? checkPattern(targetBean, permittedResources)
                : checkExact(targetBean, permittedResources);
    }

    /**
     * Get any grants of the required permission for the authenticated subject, regardless
     * of the resource the permission applies to as we'll do the filtering & matching in
     * the calling method
     * @param subject
     * @param required
     * @return the set of JMXResources upon which the subject has been granted the required permission
     */
    private Set<JMXResource> getPermittedResources(RoleResource subject, Permission required)
    {
        return getPermissions.apply(subject)
               .stream()
               .filter(details -> details.permission == required)
               .map(details -> (JMXResource)details.resource)
               .collect(Collectors.toSet());
    }

    /**
     * Check whether a required permission has been granted to the authenticated subject on a specific resource
     * @param subject
     * @param permission
     * @param resource
     * @return true if the Subject has been granted the required permission on the specified resource; false otherwise
     */
    private boolean hasPermission(RoleResource subject, Permission permission, JMXResource resource)
    {
        return getPermissions.apply(subject)
               .stream()
               .anyMatch(details -> details.permission == permission && details.resource.equals(resource));
    }

    /**
     * Given a set of JMXResources upon which the Subject has been granted a particular permission,
     * check whether any match the pattern-type ObjectName representing the target of the method
     * invocation. At this point, we are sure that whatever the required permission, the Subject
     * has definitely been granted it against this set of JMXResources. The job of this method is
     * only to verify that the target of the invocation is covered by the members of the set.
     *
     * @param target
     * @param permittedResources
     * @return true if all registered beans which match the target can also be matched by the
     *         JMXResources the subject has been granted permissions on; false otherwise
     */
    private boolean checkPattern(ObjectName target, Set<JMXResource> permittedResources)
    {
        // if the required permission was granted on the root JMX resource, then we're done
        if (permittedResources.contains(JMXResource.root()))
            return true;

        // Get the full set of beans which match the target pattern
        Set<ObjectName> targetNames = queryNames.apply(target);

        // Iterate over the resources the permission has been granted on. Some of these may
        // be patterns, so query the server to retrieve the full list of matching names and
        // remove those from the target set. Once the target set is empty (i.e. all required
        // matches have been satisfied), the requirement is met.
        // If there are still unsatisfied targets after all the JMXResources have been processed,
        // there are insufficient grants to permit the operation.
        for (JMXResource resource : permittedResources)
        {
            try
            {
                Set<ObjectName> matchingNames = queryNames.apply(ObjectName.getInstance(resource.getObjectName()));
                targetNames.removeAll(matchingNames);
                if (targetNames.isEmpty())
                    return true;
            }
            catch (MalformedObjectNameException e)
            {
                logger.warn("Permissions for JMX resource contains invalid ObjectName {}", resource.getObjectName());
            }
        }

        logger.trace("Subject does not have sufficient permissions on all MBeans matching the target pattern {}", target);
        return false;
    }

    /**
     * Given a set of JMXResources upon which the Subject has been granted a particular permission,
     * check whether any match the ObjectName representing the target of the method invocation.
     * At this point, we are sure that whatever the required permission, the Subject has definitely
     * been granted it against this set of JMXResources. The job of this method is only to verify
     * that the target of the invocation is matched by a member of the set.
     *
     * @param target
     * @param permittedResources
     * @return true if at least one of the permitted resources matches the target; false otherwise
     */
    private boolean checkExact(ObjectName target, Set<JMXResource> permittedResources)
    {
        // if the required permission was granted on the root JMX resource, then we're done
        if (permittedResources.contains(JMXResource.root()))
            return true;

        for (JMXResource resource : permittedResources)
        {
            try
            {
                if (ObjectName.getInstance(resource.getObjectName()).apply(target))
                    return true;
            }
            catch (MalformedObjectNameException e)
            {
                logger.warn("Permissions for JMX resource contains invalid ObjectName {}", resource.getObjectName());
            }
        }

        logger.trace("Subject does not have sufficient permissions on target MBean {}", target);
        return false;
    }

    /**
     * Mapping between method names and the permission required to invoke them. Note, these
     * names refer to methods on MBean instances invoked via the MBeanServer.
     * @param methodName
     * @return
     */
    private static Permission getRequiredPermission(String methodName)
    {
        switch (methodName)
        {
            case "getAttribute":
            case "getAttributes":
                return Permission.SELECT;
            case "setAttribute":
            case "setAttributes":
                return Permission.MODIFY;
            case "invoke":
                return Permission.EXECUTE;
            case "getInstanceOf":
            case "getMBeanInfo":
            case "hashCode":
            case "isInstanceOf":
            case "isRegistered":
            case "queryMBeans":
            case "queryNames":
                return Permission.DESCRIBE;
            default:
                logger.debug("Access denied, method name {} does not map to any defined permission", methodName);
                return null;
        }
    }

    /**
     * Invoke a method on the MBeanServer instance. This is called when authorization is not required (because
     * AllowAllAuthorizer is configured, or because the invocation is being performed by the JMXConnector
     * itself rather than by a connected client), and also when a call from an authenticated subject
     * has been successfully authorized
     *
     * @param method
     * @param args
     * @return
     * @throws Throwable
     */
    private Object invoke(Method method, Object[] args) throws Throwable
    {
        try
        {
            return method.invoke(mbs, args);
        }
        catch (InvocationTargetException e) //Catch any exception that might have been thrown by the mbeans
        {
            Throwable t = e.getCause(); //Throw the exception that nodetool etc expects
            throw t;
        }
    }

    /**
     * Query the configured IAuthorizer for the set of all permissions granted on JMXResources to a specific subject
     * @param subject
     * @return All permissions granted to the specfied subject (including those transitively inherited from
     *         any roles the subject has been granted), filtered to include only permissions granted on
     *         JMXResources
     */
    private static Set<PermissionDetails> loadPermissions(RoleResource subject)
    {
        // get all permissions for the specified subject. We'll cache them as it's likely
        // we'll receive multiple lookups for the same subject (but for different resources
        // and permissions) in quick succession
        return DatabaseDescriptor.getAuthorizer().list(AuthenticatedUser.SYSTEM_USER, Permission.ALL, null, subject)
                                                 .stream()
                                                 .filter(details -> details.resource instanceof JMXResource)
                                                 .collect(Collectors.toSet());
    }

    private static final class JMXPermissionsCache extends AuthCache<RoleResource, Set<PermissionDetails>>
    {
        protected JMXPermissionsCache()
        {
            super("JMXPermissionsCache",
                  DatabaseDescriptor::setPermissionsValidity,
                  DatabaseDescriptor::getPermissionsValidity,
                  DatabaseDescriptor::setPermissionsUpdateInterval,
                  DatabaseDescriptor::getPermissionsUpdateInterval,
                  DatabaseDescriptor::setPermissionsCacheMaxEntries,
                  DatabaseDescriptor::getPermissionsCacheMaxEntries,
                  AuthorizationProxy::loadPermissions,
                  () -> true);
        }

        public Set<PermissionDetails> get(RoleResource roleResource)
        {
            try
            {
                return super.get(roleResource);
            }
            catch (Exception e)
            {
                // because the outer class uses this method as Function<RoleResource, Set<PermissionDetails>>,
                // which can be overridden for testing, it cannot throw checked exceptions. So here we simply
                // use guava's propagation helper.
                throw Throwables.propagate(e);
            }
        }
    }
}
