org.apache.sentry.core.common.utils.PolicyFile.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.sentry.core.common.utils.PolicyFile.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.sentry.core.common.utils;

import static org.apache.sentry.core.common.utils.PolicyFileConstants.DATABASES;
import static org.apache.sentry.core.common.utils.PolicyFileConstants.GROUPS;
import static org.apache.sentry.core.common.utils.PolicyFileConstants.ROLES;
import static org.apache.sentry.core.common.utils.PolicyFileConstants.USERS;

import java.io.File;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Charsets;
import com.google.common.base.Joiner;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multimap;
import com.google.common.io.Files;

/**
 * PolicyFile creator. Written specifically to be used with tests. Specifically
 * due to the fact that methods that would typically return true or false to
 * indicate success or failure these methods throw an unchecked exception.
 * This is because in a test if you mean to remove a user from the policy file,
 * the user should absolutely be there. If not, the test is mis-behaving.
 */
@VisibleForTesting
public class PolicyFile {

    private static final Logger LOGGER = LoggerFactory.getLogger(PolicyFile.class);

    private static final String NL = System.getProperty("line.separator", "\n");

    private final Map<String, String> databasesToPolicyFiles = Maps.newHashMap();
    private final Multimap<String, String> usersToGroups = ArrayListMultimap.create();
    private final Multimap<String, String> groupsToRoles = ArrayListMultimap.create();
    private final Multimap<String, String> rolesToPermissions = ArrayListMultimap.create();

    public Multimap<String, String> getGroupsToRoles() {
        return groupsToRoles;
    }

    public Multimap<String, String> getRolesToPermissions() {
        return rolesToPermissions;
    }

    public PolicyFile addRolesToGroup(String groupName, String... roleNames) throws Exception {
        return addRolesToGroup(groupName, false, roleNames);
    }

    public PolicyFile addRolesToGroup(String groupName, boolean allowDuplicates, String... roleNames) {
        return add(groupsToRoles.get(groupName), allowDuplicates, roleNames);
    }

    public PolicyFile addPermissionsToRole(String roleName, String... permissionNames) {
        return addPermissionsToRole(roleName, false, permissionNames);
    }

    public PolicyFile addPermissionsToRole(String roleName, boolean allowDuplicates, String... permissionNames) {
        return add(rolesToPermissions.get(roleName), allowDuplicates, permissionNames);
    }

    public PolicyFile addGroupsToUser(String userName, String... groupNames) {
        LOGGER.warn("Static user:group mapping is not being used");
        return addGroupsToUser(userName, false, groupNames);
    }

    public PolicyFile addGroupsToUser(String userName, boolean allowDuplicates, String... groupNames) {
        LOGGER.warn("Static user:group mapping is not being used");
        return add(usersToGroups.get(userName), allowDuplicates, groupNames);
    }

    public PolicyFile setUserGroupMapping(Map<String, String> mapping) {
        for (Entry<String, String> entry : mapping.entrySet()) {
            usersToGroups.put(entry.getKey(), entry.getValue());
        }
        return this;
    }

    public PolicyFile addDatabase(String databaseName, String path) {
        String oldPath = databasesToPolicyFiles.put(databaseName, path);
        if (oldPath != null) {
            throw new IllegalStateException("Database " + databaseName + " already existed in "
                    + databasesToPolicyFiles + " with value of " + oldPath);
        }
        databasesToPolicyFiles.put(databaseName, path);
        return this;
    }

    public PolicyFile removeRolesFromGroup(String groupName, String... roleNames) {
        return remove(groupsToRoles.get(groupName), roleNames);
    }

    public PolicyFile removePermissionsFromRole(String roleName, String... permissionNames) {
        return remove(rolesToPermissions.get(roleName), permissionNames);
    }

    public PolicyFile removeGroupsFromUser(String userName, String... groupNames) {
        LOGGER.warn("Static user:group mapping is not being used");
        return remove(usersToGroups.get(userName), groupNames);
    }

    public PolicyFile removeDatabase(String databaseName) {
        if (databasesToPolicyFiles.remove(databaseName) == null) {
            throw new IllegalStateException(
                    "Database " + databaseName + " did not exist in " + databasesToPolicyFiles);
        }
        return this;
    }

    public PolicyFile copy() {
        PolicyFile other = new PolicyFile();
        other.databasesToPolicyFiles.putAll(databasesToPolicyFiles);
        other.usersToGroups.putAll(usersToGroups);
        other.groupsToRoles.putAll(groupsToRoles);
        other.rolesToPermissions.putAll(rolesToPermissions);
        return other;
    }

    public void write(File clientFile, File serverFile) throws Exception {
        write(clientFile);
        write(serverFile);
    }

    public void write(File file) throws Exception {
        if (file.exists() && !file.delete()) {
            throw new IllegalStateException("Unable to delete " + file);
        }
        String contents = Joiner.on(NL).join(getSection(DATABASES, databasesToPolicyFiles),
                getSection(USERS, usersToGroups), getSection(GROUPS, groupsToRoles),
                getSection(ROLES, rolesToPermissions), "");
        LOGGER.info("Writing policy file to " + file + ":\n" + contents);
        Files.write(contents, file, Charsets.UTF_8);
    }

    private String getSection(String name, Map<String, String> mapping) {
        if (mapping.isEmpty()) {
            return "";
        }
        Joiner kvJoiner = Joiner.on(" = ");
        List<String> lines = Lists.newArrayList();
        lines.add("[" + name + "]");
        for (Entry<String, String> entry : mapping.entrySet()) {
            lines.add(kvJoiner.join(entry.getKey(), entry.getValue()));
        }
        return Joiner.on(NL).join(lines);
    }

    private String getSection(String name, Multimap<String, String> mapping) {
        if (mapping.isEmpty()) {
            return "";
        }
        Joiner kvJoiner = Joiner.on(" = ");
        Joiner itemJoiner = Joiner.on(" , ");
        List<String> lines = Lists.newArrayList();
        lines.add("[" + name + "]");
        for (String key : mapping.keySet()) {
            lines.add(kvJoiner.join(key, itemJoiner.join(mapping.get(key))));
        }
        return Joiner.on(NL).join(lines);
    }

    private PolicyFile remove(Collection<String> exitingItems, String[] newItems) {
        for (String newItem : newItems) {
            if (!exitingItems.remove(newItem)) {
                throw new IllegalStateException("Item " + newItem + " did not exist in " + exitingItems);
            }
        }
        return this;
    }

    private PolicyFile add(Collection<String> exitingItems, boolean allowDuplicates, String[] newItems) {
        for (String newItem : newItems) {
            if (exitingItems.contains(newItem) && !allowDuplicates) {
                throw new IllegalStateException("Item " + newItem + " already exists in " + exitingItems);
            }
            exitingItems.add(newItem);
        }
        return this;
    }

    //User:Group mapping for the admin user needs to be set separately
    public static PolicyFile setAdminOnServer1(String admin) throws Exception {
        return new PolicyFile().addRolesToGroup(admin, "admin_role").addPermissionsToRole("admin_role",
                "server=server1");
    }
}