org.apache.ranger.unixusersync.process.FileSourceUserGroupBuilder.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.ranger.unixusersync.process.FileSourceUserGroupBuilder.java

Source

/*
 * 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.ranger.unixusersync.process;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVParser;
import org.apache.commons.csv.CSVRecord;
import org.apache.log4j.Logger;
import org.apache.ranger.unixusersync.config.UserGroupSyncConfig;
import org.apache.ranger.usergroupsync.AbstractUserGroupSource;
import org.apache.ranger.usergroupsync.UserGroupSink;
import org.apache.ranger.usergroupsync.UserGroupSource;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.stream.JsonReader;

public class FileSourceUserGroupBuilder extends AbstractUserGroupSource {
    private static final Logger LOG = Logger.getLogger(FileSourceUserGroupBuilder.class);

    private Map<String, List<String>> user2GroupListMap = new HashMap<String, List<String>>();
    private String userGroupFilename = null;
    private long usergroupFileModified = 0;

    private boolean isUpdateSinkSucc = true;

    public static void main(String[] args) throws Throwable {
        FileSourceUserGroupBuilder filesourceUGBuilder = new FileSourceUserGroupBuilder();

        if (args.length > 0) {
            filesourceUGBuilder.setUserGroupFilename(args[0]);
        }

        filesourceUGBuilder.init();

        UserGroupSink ugSink = UserGroupSyncConfig.getInstance().getUserGroupSink();
        LOG.info("initializing sink: " + ugSink.getClass().getName());
        ugSink.init();

        filesourceUGBuilder.updateSink(ugSink);

        if (LOG.isDebugEnabled()) {
            filesourceUGBuilder.print();
        }
    }

    public FileSourceUserGroupBuilder() {
        super();
    }

    @Override
    public void init() throws Throwable {
        if (userGroupFilename == null) {
            userGroupFilename = config.getUserSyncFileSource();
        }

        buildUserGroupInfo();
    }

    @Override
    public boolean isChanged() {
        // If previous update to Ranger admin fails, 
        // we want to retry the sync process even if there are no changes to the sync files
        if (!isUpdateSinkSucc) {
            LOG.info("Previous updateSink failed and hence retry!!");
            return true;
        }

        long TempUserGroupFileModifedAt = new File(userGroupFilename).lastModified();
        if (usergroupFileModified != TempUserGroupFileModifedAt) {
            return true;
        }
        return false;
    }

    @Override
    public void updateSink(UserGroupSink sink) throws Throwable {
        isUpdateSinkSucc = true;
        buildUserGroupInfo();
        String user = null;
        List<String> groups = null;
        for (Map.Entry<String, List<String>> entry : user2GroupListMap.entrySet()) {
            user = entry.getKey();
            try {
                if (userNameRegExInst != null) {
                    user = userNameRegExInst.transform(user);
                }
                groups = entry.getValue();
                if (groupNameRegExInst != null) {
                    List<String> mappedGroups = new ArrayList<>();
                    for (String group : groups) {
                        mappedGroups.add(groupNameRegExInst.transform(group));
                    }
                    groups = mappedGroups;
                }
                sink.addOrUpdateUser(user, groups);
            } catch (Throwable t) {
                LOG.error("sink.addOrUpdateUser failed with exception: " + t.getMessage() + ", for user: " + user
                        + ", groups: " + groups);
                isUpdateSinkSucc = false;
            }
        }
    }

    private void setUserGroupFilename(String filename) {
        userGroupFilename = filename;
    }

    private void print() {
        for (String user : user2GroupListMap.keySet()) {
            LOG.debug("USER:" + user);
            List<String> groups = user2GroupListMap.get(user);
            if (groups != null) {
                for (String group : groups) {
                    LOG.debug("\tGROUP: " + group);
                }
            }
        }
    }

    public void buildUserGroupInfo() throws Throwable {
        buildUserGroupList();
        if (LOG.isDebugEnabled()) {
            print();
        }
    }

    public void buildUserGroupList() throws Throwable {
        if (userGroupFilename == null) {
            throw new Exception(
                    "User Group Source File is not Configured. Please maintain in unixauthservice.properties or pass it as command line argument for org.apache.ranger.unixusersync.process.FileSourceUserGroupBuilder");
        }

        File f = new File(userGroupFilename);

        if (f.exists() && f.canRead()) {
            Map<String, List<String>> tmpUser2GroupListMap = null;

            if (isJsonFile(userGroupFilename)) {
                tmpUser2GroupListMap = readJSONfile(f);
            } else {
                tmpUser2GroupListMap = readTextFile(f);
            }

            if (tmpUser2GroupListMap != null) {
                user2GroupListMap = tmpUser2GroupListMap;

                usergroupFileModified = f.lastModified();
            } else {
                LOG.info("No new UserGroup to sync at this time");
            }
        } else {
            throw new Exception("User Group Source File " + userGroupFilename + "doesn't not exist or readable");
        }
    }

    public boolean isJsonFile(String userGroupFilename) {
        boolean ret = false;

        if (userGroupFilename.toLowerCase().endsWith(".json")) {
            ret = true;
        }

        return ret;
    }

    public Map<String, List<String>> readJSONfile(File jsonFile) throws Exception {
        Map<String, List<String>> ret = new HashMap<String, List<String>>();

        JsonReader jsonReader = new JsonReader(new BufferedReader(new FileReader(jsonFile)));

        Gson gson = new GsonBuilder().create();

        ret = gson.fromJson(jsonReader, ret.getClass());

        return ret;

    }

    public Map<String, List<String>> readTextFile(File textFile) throws Exception {

        Map<String, List<String>> ret = new HashMap<String, List<String>>();

        String delimiter = config.getUserSyncFileSourceDelimiter();

        CSVFormat csvFormat = CSVFormat.newFormat(delimiter.charAt(0));

        CSVParser csvParser = new CSVParser(new BufferedReader(new FileReader(textFile)), csvFormat);

        List<CSVRecord> csvRecordList = csvParser.getRecords();

        if (csvRecordList != null) {
            for (CSVRecord csvRecord : csvRecordList) {
                List<String> groups = new ArrayList<String>();
                String user = csvRecord.get(0);

                user = user.replaceAll("^\"|\"$", "");

                int i = csvRecord.size();

                for (int j = 1; j < i; j++) {
                    String group = csvRecord.get(j);
                    if (group != null && !group.isEmpty()) {
                        group = group.replaceAll("^\"|\"$", "");
                        groups.add(group);
                    }
                }
                ret.put(user, groups);
            }
        }

        csvParser.close();

        return ret;
    }

}