Package org.elasticsearch.river.ldap

Source Code of org.elasticsearch.river.ldap.LdapRiver$LdapReader

package org.elasticsearch.river.ldap;

import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import javax.naming.Context;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.Attribute;
import javax.naming.directory.Attributes;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;

import org.elasticsearch.ExceptionsHelper;
import org.elasticsearch.action.bulk.BulkRequestBuilder;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.client.Client;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.util.concurrent.EsExecutors;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.support.XContentMapValues;
import org.elasticsearch.indices.IndexAlreadyExistsException;
import org.elasticsearch.river.AbstractRiverComponent;
import org.elasticsearch.river.River;
import org.elasticsearch.river.RiverIndexName;
import org.elasticsearch.river.RiverName;
import org.elasticsearch.river.RiverSettings;

/*
* Licensed to ElasticSearch and Shay Banon under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. ElasticSearch 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.
*/
public class LdapRiver extends AbstractRiverComponent implements River {

    private final Client client;

    @RiverIndexName
    private String riverIndexName;

    private final String userDn;
    private final String credentials;
    private final String host;
    private final int port;
    private final boolean ssl;

    private final String filter;
    private final String baseDn;
    private final String[] attributes;
    private final List<String> attributesList;
    private final String[] fields;
    private final String scope;

    private final TimeValue poll;

    private final String indexName;
    private final String typeName;

    private final int bulkSize;
    private final TimeValue bulkTimeout;

    private volatile boolean closed = false;

    private volatile Thread thread;

    @SuppressWarnings("unchecked")
    @Inject
    protected LdapRiver(RiverName riverName, RiverSettings settings, Client client) {
        super(riverName, settings);
        this.client = client;

        if (settings.settings().containsKey("ldap")) {
            Map<String, Object> ldapSettings = (Map<String, Object>) settings.settings().get("ldap");

            userDn = XContentMapValues.nodeStringValue(ldapSettings.get("userDn"), null);
            credentials = XContentMapValues.nodeStringValue(ldapSettings.get("credentials"), null);
            host = XContentMapValues.nodeStringValue(ldapSettings.get("host"), null);
            port = XContentMapValues.nodeIntegerValue(ldapSettings.get("port"), 389);
            ssl = XContentMapValues.nodeBooleanValue(ldapSettings.get("ssl"), false);
            filter = XContentMapValues.nodeStringValue(ldapSettings.get("filter"), null);
            baseDn = XContentMapValues.nodeStringValue(ldapSettings.get("baseDn"), null);
            scope = XContentMapValues.nodeStringValue(ldapSettings.get("scope"), null);

            if(XContentMapValues.isArray(ldapSettings.get("attributes"))) {
                List<Object> values = (List<Object>) ldapSettings.get("attributes");
                attributes = new String[values.size()];
                attributesList = new ArrayList<String>(values.size());
                for (int i = 0; i < attributes.length; i++) {
                    attributes[i] = values.get(i).toString();
                    attributesList.add(attributes[i]);
                }
            } else {
                attributes = null;
                attributesList = new ArrayList<String>();
            }
            if(XContentMapValues.isArray(ldapSettings.get("fields"))) {
                List<Object> values = (List<Object>) ldapSettings.get("fields");
                fields = new String[values.size()];
                for (int i = 0; i < fields.length; i++) {
                    fields[i] = values.get(i).toString();
                }
            } else {
                fields = null;
            }
            poll = XContentMapValues.nodeTimeValue(ldapSettings.get("poll"), TimeValue.timeValueMinutes(60));

        } else {
            userDn = null;
            credentials = null;
            host = null;
            port = 389;
            ssl = false;
            filter = null;
            baseDn = null;
            attributes = null;
            attributesList = new ArrayList<String>();
            fields = null;
            scope = null;
            poll = TimeValue.timeValueMinutes(60);
        }
        if (settings.settings().containsKey("index")) {
            Map<String, Object> indexSettings = (Map<String, Object>) settings.settings().get("index");
            indexName = XContentMapValues.nodeStringValue(indexSettings.get("index"), "ldap");
            typeName = XContentMapValues.nodeStringValue(indexSettings.get("type"), "ldap");
            bulkSize = XContentMapValues.nodeIntegerValue(indexSettings.get("bulk_size"), 100);
            if (indexSettings.containsKey("bulk_timeout")) {
                bulkTimeout = TimeValue.parseTimeValue(XContentMapValues.nodeStringValue(indexSettings.get("bulk_timeout"), "60s"),
                                                       TimeValue.timeValueMillis(60000));
            } else {
                bulkTimeout = TimeValue.timeValueMillis(60000);
            }
        } else {
            indexName = "ldap";
            typeName = "ldap";
            bulkSize = 100;
            bulkTimeout = TimeValue.timeValueMillis(60000);
        }
    }

    public void start() {
        logger.info("starting ldap river [{}]: host [{}], port [{}], ssl [{}], username [{}], filter [{}], search [{}], indexing to [{}]/[{}], poll [{}]",
                    riverIndexName, host, port, ssl, userDn, filter, baseDn, indexName, typeName, poll);
        try {
            client.admin().indices().prepareCreate(indexName).execute().actionGet();
        } catch (Exception e) {
            if (ExceptionsHelper.unwrapCause(e) instanceof IndexAlreadyExistsException) {
                logger.debug("ldap river index [{}] already exists", e, indexName);
            } else {
                logger.warn("failed to create index [{}], disabling river...", e, indexName);
                return;
            }
        }
        thread = EsExecutors.daemonThreadFactory(settings.globalSettings(), "ldap_river").newThread(new LdapReader());
        thread.start();
    }

    public void close() {
        if (closed) {
            return;
        }
        logger.info("closing Ldap river");
        if (thread != null) {
            thread.interrupt();
        }
        closed = true;
    }

    private class LdapReader implements Runnable {

        public void run() {
           
            BulkRequestBuilder bulkRequest = client.prepareBulk();
           
            while (true) {
                if (closed) {
                    return;
                }

                DirContext ctx = null;
                Properties environment = new Properties();

                try {
                    environment.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
          if (userDn != null && !"".equals(userDn)) {
                        environment.put(Context.SECURITY_AUTHENTICATION, "simple");
                        environment.put(Context.SECURITY_PRINCIPAL, userDn);
                        environment.put(Context.SECURITY_CREDENTIALS, credentials);
                    } else {
                        environment.put(Context.SECURITY_AUTHENTICATION, "none");
                    }

                    if (ssl) {
                        environment.put(Context.PROVIDER_URL, "ldaps://" + host + ":" + port);
                        environment.put(Context.SECURITY_PROTOCOL, "ssl");
                    } else {
                        environment.put(Context.PROVIDER_URL, "ldap://" + host + ":" + port);
                    }

                    ctx = new InitialDirContext(environment);
                    int count = 0;

                    SearchControls constraints = new SearchControls();
                    if ("object".equalsIgnoreCase(scope)) {
                        constraints.setSearchScope(SearchControls.OBJECT_SCOPE);
                    } else if ("onelevel".equalsIgnoreCase(scope)) {
                        constraints.setSearchScope(SearchControls.ONELEVEL_SCOPE);
                    } else {
                        constraints.setSearchScope(SearchControls.SUBTREE_SCOPE);
                    }
                   
                    if (attributes != null && attributes.length > 0) {
                        constraints.setReturningAttributes(attributes);
                    }
                   
                    long start = System.currentTimeMillis();
                    NamingEnumeration<SearchResult> results = ctx.search(baseDn, filter, constraints);
                    logger.debug("LDAP search executed in {} ms", System.currentTimeMillis() - start);
                   
                    while (results != null && results.hasMore()) {
                       
                        SearchResult sr = (SearchResult) results.next();
                       
                        IndexRequest indexRequest = new IndexRequest(indexName);
                       
                        XContentBuilder builder = jsonBuilder();
                        builder.startObject();
                       
                        String dn = sr.getName();
                        logger.debug("Reading ldap object dn [{}]", dn);
                       
                        Attributes ldapAttributes = sr.getAttributes();
                        NamingEnumeration<String> ldapAttributesIds = ldapAttributes.getIDs();
                        while (ldapAttributesIds.hasMoreElements()) {
                            String id = ldapAttributesIds.next();
                            logger.debug("\treading attribute id [{}]", id);
                           
                            List<String> fieldValues = new ArrayList<String>();
                            Attribute attribute = ldapAttributes.get(id);
                            NamingEnumeration<?> values = attribute.getAll();
                            while (values.hasMoreElements()) {
                                Object value = values.next();
                                logger.debug("\t\tvalue: [{}]", value.toString());
                                fieldValues.add(value.toString());
                            }
                            String fieldName = resolveFieldName(id);
                            if(fieldValues.size() > 1){
                                builder.array(fieldName, fieldValues.toArray());
                            } else {
                                if (!"_id".equals(fieldName)) {
                                    builder.field(fieldName, fieldValues.get(0));
                                } else {
                                    indexRequest.id(fieldValues.get(0));
                                }
                            }
                        }

                        builder.endObject();
                       
                        indexRequest.type(typeName).source(builder);
                        bulkRequest.add(indexRequest);
                        count++;
                       
                        if((count % bulkSize) == 0){
                            BulkResponse bulkResponse = bulkRequest.execute().actionGet(bulkTimeout);
                            logger.info("{} objects indexed with ", count, bulkResponse.hasFailures()? "errors" : "success");
                        }                       
                    }
                   
                    if(bulkRequest.numberOfActions() > 0){
                        BulkResponse bulkResponse = bulkRequest.setRefresh(true).execute().actionGet(bulkTimeout);
                        logger.info("{} objects indexed with ", count, bulkResponse.hasFailures()? "errors" : "success");
                    }

                } catch (Exception e) {
                    logger.error("Exception when accessing to LDAP server", e);
                } finally {
                    try {
                        ctx.close();
                    } catch (NamingException e) {
                        logger.error("Exception when closing LDAP context", e);
                    }
                }
               
                if (poll.millis() > 0L) {
                    logger.info("now, ldap river {} waiting for {} ms", riverIndexName, poll);
                    try {
                        Thread.sleep(poll.millis());
                    } catch (InterruptedException e) {
                        logger.error("Exception on Thread.sleep()", e);
                    }
                }
            }
        }
       
        private String resolveFieldName(String id) {
            if ((fields != null) && (fields.length > 0)) {
                int i = attributesList.indexOf(id);
                if ((i >= 0) && (i < fields.length)) {
                    return fields[i];
                }
            }
            return id;
        }
    }
}
TOP

Related Classes of org.elasticsearch.river.ldap.LdapRiver$LdapReader

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.