org.elasticsearch.plugin.readonlyrest.acl.blocks.rules.impl.LdapAuthAsyncRule.java Source code

Java tutorial

Introduction

Here is the source code for org.elasticsearch.plugin.readonlyrest.acl.blocks.rules.impl.LdapAuthAsyncRule.java

Source

/*
 *    This file is part of ReadonlyREST.
 *
 *    ReadonlyREST is free software: you can redistribute it and/or modify
 *    it under the terms of the GNU General Public License as published by
 *    the Free Software Foundation, either version 3 of the License, or
 *    (at your option) any later version.
 *
 *    ReadonlyREST 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
 *    GNU General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with ReadonlyREST.  If not, see http://www.gnu.org/licenses/
 */

package org.elasticsearch.plugin.readonlyrest.acl.blocks.rules.impl;

import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.plugin.readonlyrest.acl.blocks.rules.ConfigMalformedException;
import org.elasticsearch.plugin.readonlyrest.ldap.LdapClient;
import org.elasticsearch.plugin.readonlyrest.ldap.LdapCredentials;
import org.elasticsearch.plugin.readonlyrest.ldap.LdapGroup;
import org.elasticsearch.plugin.readonlyrest.ldap.LdapUser;
import org.elasticsearch.plugin.readonlyrest.utils.FuturesSequencer;

import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;

public class LdapAuthAsyncRule extends GeneralAuthKeyAsyncRule {

    private static final String RULE_NAME = "ldap_auth";
    private static final String LDAP_NAME = "name";
    private static final String LDAP_GROUP_NAMES = "groups";

    private final List<LdapAuthDefinition> ldapAuthDefinitions;

    private LdapAuthAsyncRule(List<LdapAuthDefinition> ldapAuthDefinitions) {
        this.ldapAuthDefinitions = ldapAuthDefinitions;
    }

    public static Optional<LdapAuthAsyncRule> fromSettings(Settings s, List<LdapConfig> ldapConfigs)
            throws ConfigMalformedException {
        Map<String, Settings> ldapAuths = s.getGroups(RULE_NAME);
        if (ldapAuths.isEmpty())
            return Optional.empty();

        Map<String, LdapClient> ldapClientsByName = ldapConfigs.stream()
                .collect(Collectors.toMap(LdapConfig::getName, LdapConfig::getClient));

        List<LdapAuthDefinition> authDefinitions = ldapAuths.values().stream().map(ldapAuthDefSettings -> {
            String name = ldapAuthDefSettings.get(LDAP_NAME);
            if (name == null)
                throw new ConfigMalformedException("No [" + LDAP_NAME + "] attribute defined");
            Set<String> groups = Sets.newHashSet(ldapAuthDefSettings.getAsArray(LDAP_GROUP_NAMES));
            if (!ldapClientsByName.containsKey(name)) {
                throw new ConfigMalformedException("LDAP with name [" + name + "] wasn't defined.");
            }
            return new LdapAuthDefinition(ldapClientsByName.get(name), groups);
        }).collect(Collectors.toList());
        return Optional.of(new LdapAuthAsyncRule(authDefinitions));
    }

    @Override
    protected CompletableFuture<Boolean> authenticate(String user, String password) {
        LdapCredentials credentials = new LdapCredentials(user, password);
        return FuturesSequencer.runInSeqUntilConditionIsUndone(ldapAuthDefinitions.iterator(),
                authDefinition -> authDefinition.client.authenticate(credentials),
                (authDefinition, ldapUser) -> ldapUser.isPresent()
                        && checkIfUserHasAccess(ldapUser.get(), authDefinition),
                noMatterWhat -> true, noMatterWhat -> false);
    }

    private boolean checkIfUserHasAccess(LdapUser user, LdapAuthDefinition authDefinition) {
        return authDefinition.accessGroups.isEmpty() || !Sets.intersection(authDefinition.accessGroups,
                user.getGroups().stream().map(LdapGroup::getName).collect(Collectors.toSet())).isEmpty();
    }

    @Override
    public String getKey() {
        return RULE_NAME;
    }

    private static class LdapAuthDefinition {
        private final LdapClient client;
        private final ImmutableSet<String> accessGroups;

        LdapAuthDefinition(LdapClient client, Set<String> accessGroups) {
            this.client = client;
            this.accessGroups = ImmutableSet.copyOf(accessGroups);
        }
    }
}