All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.graylog.security.entities.EntityDependencyPermissionChecker Maven / Gradle / Ivy

There is a newer version: 6.1.4
Show newest version
/*
 * Copyright (C) 2020 Graylog, Inc.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the Server Side Public License, version 1,
 * as published by MongoDB, Inc.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * Server Side Public License for more details.
 *
 * You should have received a copy of the Server Side Public License
 * along with this program. If not, see
 * .
 */
package org.graylog.security.entities;

import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.ImmutableSet;
import org.graylog.grn.GRN;
import org.graylog.security.BuiltinCapabilities;
import org.graylog.security.Capability;
import org.graylog.security.CapabilityDescriptor;
import org.graylog.security.GranteeAuthorizer;

import javax.inject.Inject;
import java.util.Collections;
import java.util.Optional;
import java.util.Set;

public class EntityDependencyPermissionChecker {
    private final GranteeAuthorizer.Factory granteeAuthorizerFactory;
    private final BuiltinCapabilities builtinCapabilities;

    @Inject
    public EntityDependencyPermissionChecker(GranteeAuthorizer.Factory granteeAuthorizerFactory,
                                             BuiltinCapabilities builtinCapabilities) {
        this.granteeAuthorizerFactory = granteeAuthorizerFactory;
        this.builtinCapabilities = builtinCapabilities;
    }

    /**
     * Runs permission checks for the given dependencies for every selected grantee and returns the entities that
     * grantees cannot access.
     *
     * @param sharingUser      the sharing user
     * @param dependencies     the dependencies to check
     * @param selectedGrantees the selected grantees
     * @return dependencies that grantees cannot access, grouped by grantee
     */
    public ImmutableMultimap check(GRN sharingUser,
                                                          ImmutableSet dependencies,
                                                          Set selectedGrantees) {
        final ImmutableMultimap.Builder deniedDependencies = ImmutableMultimap.builder();
        final GranteeAuthorizer sharerAuthorizer = granteeAuthorizerFactory.create(sharingUser);

        for (final GRN grantee : selectedGrantees) {
            // We only check for existing grants for the actual grantee. If the grantee is a team, we only check if
            // the team has a grant, not if any users in the team can access the dependency via other grants.
            // The same for the "everyone" grantee, we only check if  the "everyone" grantee has access to a dependency.
            final GranteeAuthorizer granteeAuthorizer = granteeAuthorizerFactory.create(grantee);

            for (final EntityDescriptor dependency : dependencies) {
                // We can only expose missing dependencies that the sharing user can read to avoid
                // leaking information to the sharing user.
                if (cannotView(sharerAuthorizer, dependency)) {
                    continue;
                }

                if (cannotView(granteeAuthorizer, dependency)) {
                    deniedDependencies.put(grantee, dependency);
                }
            }
        }

        return deniedDependencies.build();
    }

    private boolean cannotView(GranteeAuthorizer authorizer, EntityDescriptor dependency) {
        final Optional capabilityDescriptor = builtinCapabilities.get(Capability.VIEW);

        // TODO: This only looks at grants permissions, but should also check for permissions through roles
        return capabilityDescriptor.map(CapabilityDescriptor::permissions)
                .orElse(Collections.emptySet())
                .stream()
                .filter(permission -> dependency.id().isPermissionApplicable(permission))
                .noneMatch(permission -> authorizer.isPermitted(permission, dependency.id()));
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy