org.apache.sentry.cli.tools.TestPermissionsMigrationToolSolr.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.sentry.cli.tools.TestPermissionsMigrationToolSolr.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.cli.tools;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.assertFalse;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import org.apache.commons.io.FileUtils;
import org.apache.sentry.core.common.exception.SentryUserException;
import org.apache.sentry.provider.common.ProviderBackendContext;
import org.apache.sentry.api.generic.thrift.SentryGenericServiceIntegrationBase;
import org.apache.sentry.api.generic.thrift.TAuthorizable;
import org.apache.sentry.api.generic.thrift.TSentryPrivilege;
import org.apache.sentry.api.generic.thrift.TSentryRole;
import org.apache.sentry.api.tools.GenericPrivilegeConverter;
import org.apache.sentry.provider.file.PolicyFile;
import org.apache.sentry.provider.file.SimpleFileProviderBackend;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import com.google.common.collect.Sets;
import com.google.common.collect.Table;
import com.google.common.io.Files;

public class TestPermissionsMigrationToolSolr extends SentryGenericServiceIntegrationBase {
    private File confDir;
    private File confPath;
    private String requestorName = "";
    private String service = "service1";

    @Before
    public void prepareForTest() throws Exception {
        confDir = Files.createTempDir();
        confPath = new File(confDir, "sentry-site.xml");
        if (confPath.createNewFile()) {
            FileOutputStream to = new FileOutputStream(confPath);
            conf.writeXml(to);
            to.close();
        }
        requestorName = clientUgi.getShortUserName();//System.getProperty("user.name", "");
        Set<String> requestorUserGroupNames = Sets.newHashSet(ADMIN_GROUP);
        setLocalGroupMapping(requestorName, requestorUserGroupNames);
        // add ADMIN_USER for the after() in SentryServiceIntegrationBase
        setLocalGroupMapping(ADMIN_USER, requestorUserGroupNames);
        setLocalGroupMapping("dev", Sets.newHashSet("dev_group"));
        setLocalGroupMapping("user", Sets.newHashSet("user_group"));
        writePolicyFile();
    }

    @After
    public void clearTestData() throws Exception {
        FileUtils.deleteQuietly(confDir);

        // clear roles and privileges
        Set<TSentryRole> tRoles = client.listAllRoles(requestorName, SOLR);
        for (TSentryRole tRole : tRoles) {
            String role = tRole.getRoleName();
            Set<TSentryPrivilege> privileges = client.listAllPrivilegesByRoleName(requestorName, role, SOLR,
                    service);
            for (TSentryPrivilege privilege : privileges) {
                client.revokePrivilege(requestorName, role, SOLR, privilege);
            }
            client.dropRole(requestorName, role, SOLR);
        }
    }

    @Test
    public void testPermissionsMigrationFromSentrySvc_v1() throws Exception {
        initializeSentryService();

        String[] args = { "-s", "1.8.0", "-c", confPath.getAbsolutePath() };
        PermissionsMigrationToolSolr sentryTool = new PermissionsMigrationToolSolr();
        sentryTool.executeConfigTool(args);

        Map<String, Set<String>> groupMapping = new HashMap<String, Set<String>>();
        groupMapping.put("admin_role", Sets.newHashSet("admin_group"));
        groupMapping.put("dev_role", Sets.newHashSet("dev_group"));
        groupMapping.put("user_role", Sets.newHashSet("user_group"));

        Map<String, Set<String>> privilegeMapping = new HashMap<String, Set<String>>();
        privilegeMapping.put("admin_role", Sets.newHashSet("admin=collections->action=*", "admin=cores->action=*"));
        privilegeMapping.put("dev_role",
                Sets.newHashSet("collection=*->action=*", "admin=collections->action=*", "admin=cores->action=*"));
        privilegeMapping.put("user_role", Sets.newHashSet("collection=foo->action=*"));

        verifySentryServiceState(groupMapping, privilegeMapping);
    }

    @Test
    public void testPermissionsMigrationFromSentryPolicyFile_v1() throws Exception {
        Path policyFilePath = initializeSentryPolicyFile();
        Path outputFilePath = Paths.get(confDir.getAbsolutePath(), "sentry-provider_migrated.ini");

        String[] args = { "-s", "1.8.0", "-p", policyFilePath.toFile().getAbsolutePath(), "-o",
                outputFilePath.toFile().getAbsolutePath() };
        PermissionsMigrationToolSolr sentryTool = new PermissionsMigrationToolSolr();
        assertTrue(sentryTool.executeConfigTool(args));

        Set<String> groups = new HashSet<>();
        groups.add("admin_group");
        groups.add("dev_group");
        groups.add("user_group");

        Map<String, Set<String>> privilegeMapping = new HashMap<String, Set<String>>();
        privilegeMapping.put("admin_role", Sets.newHashSet("admin=collections->action=*", "admin=cores->action=*"));
        privilegeMapping.put("dev_role",
                Sets.newHashSet("collection=*->action=*", "admin=collections->action=*", "admin=cores->action=*"));
        privilegeMapping.put("user_role", Sets.newHashSet("collection=foo->action=*"));

        verifySentryPolicyFile(groups, privilegeMapping, outputFilePath);
    }

    @Test
    // For permissions created with Sentry 2.x, no migration necessary
    public void testPermissionsMigrationFromSentrySvc_v2() throws Exception {
        initializeSentryService();

        String[] args = { "-s", "2.0.0", "-c", confPath.getAbsolutePath() };
        PermissionsMigrationToolSolr sentryTool = new PermissionsMigrationToolSolr();
        sentryTool.executeConfigTool(args);

        Map<String, Set<String>> groupMapping = new HashMap<String, Set<String>>();
        groupMapping.put("admin_role", Sets.newHashSet("admin_group"));
        groupMapping.put("dev_role", Sets.newHashSet("dev_group"));
        groupMapping.put("user_role", Sets.newHashSet("user_group"));

        Map<String, Set<String>> privilegeMapping = new HashMap<String, Set<String>>();
        privilegeMapping.put("admin_role", Sets.newHashSet("collection=admin->action=*"));
        privilegeMapping.put("dev_role", Sets.newHashSet("collection=*->action=*"));
        privilegeMapping.put("user_role", Sets.newHashSet("collection=foo->action=*"));

        verifySentryServiceState(groupMapping, privilegeMapping);
    }

    @Test
    // For permissions created with Sentry 2.x, no migration necessary
    public void testPermissionsMigrationFromSentryPolicyFile_v2() throws Exception {
        Path policyFilePath = initializeSentryPolicyFile();
        Path outputFilePath = Paths.get(confDir.getAbsolutePath(), "sentry-provider_migrated.ini");

        String[] args = { "-s", "2.0.0", "-p", policyFilePath.toFile().getAbsolutePath(), "-o",
                outputFilePath.toFile().getAbsolutePath() };
        PermissionsMigrationToolSolr sentryTool = new PermissionsMigrationToolSolr();
        assertTrue(sentryTool.executeConfigTool(args));

        Set<String> groups = new HashSet<>();
        groups.add("admin_group");
        groups.add("dev_group");
        groups.add("user_group");

        Map<String, Set<String>> privilegeMapping = new HashMap<String, Set<String>>();
        privilegeMapping.put("admin_role", Sets.newHashSet("collection=admin->action=*"));
        privilegeMapping.put("dev_role", Sets.newHashSet("collection=*->action=*"));
        privilegeMapping.put("user_role", Sets.newHashSet("collection=foo->action=*"));

        verifySentryPolicyFile(groups, privilegeMapping, outputFilePath);
    }

    @Test
    public void testDryRunOption() throws Exception {
        initializeSentryService();

        String[] args = { "-s", "1.8.0", "-c", confPath.getAbsolutePath(), "--dry_run" };
        PermissionsMigrationToolSolr sentryTool = new PermissionsMigrationToolSolr();
        sentryTool.executeConfigTool(args);

        Map<String, Set<String>> groupMapping = new HashMap<String, Set<String>>();
        groupMapping.put("admin_role", Sets.newHashSet("admin_group"));
        groupMapping.put("dev_role", Sets.newHashSet("dev_group"));
        groupMapping.put("user_role", Sets.newHashSet("user_group"));

        // No change in the privileges
        Map<String, Set<String>> privilegeMapping = new HashMap<String, Set<String>>();
        privilegeMapping.put("admin_role", Sets.newHashSet("collection=admin->action=*"));
        privilegeMapping.put("dev_role", Sets.newHashSet("collection=*->action=*"));
        privilegeMapping.put("user_role", Sets.newHashSet("collection=foo->action=*"));

        verifySentryServiceState(groupMapping, privilegeMapping);
    }

    @Test
    public void testInvalidToolArguments() throws Exception {
        PermissionsMigrationToolSolr sentryTool = new PermissionsMigrationToolSolr();

        {
            String[] args = { "-c", confPath.getAbsolutePath() };
            assertFalse("The execution should have failed due to missing source version",
                    sentryTool.executeConfigTool(args));
        }

        {
            String[] args = { "-s", "1.8.0" };
            sentryTool.executeConfigTool(args);
            assertFalse(
                    "The execution should have failed due to missing Sentry config file" + " (or policy file) path",
                    sentryTool.executeConfigTool(args));
        }

        {
            String[] args = { "-s", "1.8.0", "-p", "/test/path" };
            sentryTool.executeConfigTool(args);
            assertFalse("The execution should have failed due to missing Sentry config output file path",
                    sentryTool.executeConfigTool(args));
        }

        {
            String[] args = { "-s", "1.8.0", "-c", "/test/path1", "-p", "/test/path2" };
            sentryTool.executeConfigTool(args);
            assertFalse("The execution should have failed due to providing both Sentry config file"
                    + " as well as policy file params", sentryTool.executeConfigTool(args));
        }
    }

    private void initializeSentryService() throws SentryUserException {
        // Define an admin role
        client.createRoleIfNotExist(requestorName, "admin_role", SOLR);
        client.grantRoleToGroups(requestorName, "admin_role", SOLR, Sets.newHashSet("admin_group"));

        // Define a developer role
        client.createRoleIfNotExist(requestorName, "dev_role", SOLR);
        client.grantRoleToGroups(requestorName, "dev_role", SOLR, Sets.newHashSet("dev_group"));

        // Define a user role
        client.createRoleIfNotExist(requestorName, "user_role", SOLR);
        client.grantRoleToGroups(requestorName, "user_role", SOLR, Sets.newHashSet("user_group"));

        // Grant permissions
        client.grantPrivilege(requestorName, "admin_role", SOLR, new TSentryPrivilege(SOLR, "service1",
                Arrays.asList(new TAuthorizable("collection", "admin")), "*"));
        client.grantPrivilege(requestorName, "dev_role", SOLR,
                new TSentryPrivilege(SOLR, "service1", Arrays.asList(new TAuthorizable("collection", "*")), "*"));
        client.grantPrivilege(requestorName, "user_role", SOLR,
                new TSentryPrivilege(SOLR, "service1", Arrays.asList(new TAuthorizable("collection", "foo")), "*"));
    }

    private void verifySentryServiceState(Map<String, Set<String>> groupMapping,
            Map<String, Set<String>> privilegeMapping) throws SentryUserException {
        // check roles
        Set<TSentryRole> tRoles = client.listAllRoles(requestorName, SOLR);
        assertEquals("Unexpected number of roles", groupMapping.keySet().size(), tRoles.size());
        Set<String> roles = new HashSet<String>();
        for (TSentryRole tRole : tRoles) {
            roles.add(tRole.getRoleName());
        }

        for (String expectedRole : groupMapping.keySet()) {
            assertTrue("Didn't find expected role: " + expectedRole, roles.contains(expectedRole));
        }

        // check groups
        for (TSentryRole tRole : tRoles) {
            Set<String> expectedGroups = groupMapping.get(tRole.getRoleName());
            assertEquals("Group size doesn't match for role: " + tRole.getRoleName(), expectedGroups.size(),
                    tRole.getGroups().size());
            assertTrue("Group does not contain all expected members for role: " + tRole.getRoleName(),
                    tRole.getGroups().containsAll(expectedGroups));
        }

        // check privileges
        GenericPrivilegeConverter convert = new GenericPrivilegeConverter(SOLR, service);
        for (String role : roles) {
            Set<TSentryPrivilege> privileges = client.listAllPrivilegesByRoleName(requestorName, role, SOLR,
                    service);
            Set<String> expectedPrivileges = privilegeMapping.get(role);
            assertEquals(
                    "Privilege set size doesn't match for role: " + role + " Actual permissions : " + privileges,
                    expectedPrivileges.size(), privileges.size());

            Set<String> privilegeStrs = new HashSet<String>();
            for (TSentryPrivilege privilege : privileges) {
                privilegeStrs.add(convert.toString(privilege).toLowerCase());
            }

            for (String expectedPrivilege : expectedPrivileges) {
                assertTrue("Did not find expected privilege: " + expectedPrivilege + " in " + privilegeStrs,
                        privilegeStrs.contains(expectedPrivilege));
            }
        }
    }

    private Path initializeSentryPolicyFile() throws Exception {
        PolicyFile file = new PolicyFile();

        file.addRolesToGroup("admin_group", "admin_role");
        file.addRolesToGroup("dev_group", "dev_role");
        file.addRolesToGroup("user_group", "user_role");

        file.addPermissionsToRole("admin_role", "collection=admin->action=*");
        file.addPermissionsToRole("dev_role", "collection=*->action=*");
        file.addPermissionsToRole("user_role", "collection=foo->action=*");

        Path policyFilePath = Paths.get(confDir.getAbsolutePath(), "sentry-provider.ini");
        file.write(policyFilePath.toFile());

        return policyFilePath;
    }

    private void verifySentryPolicyFile(Set<String> groups, Map<String, Set<String>> privilegeMapping,
            Path policyFilePath) throws IOException {
        SimpleFileProviderBackend policyFileBackend = new SimpleFileProviderBackend(conf,
                new org.apache.hadoop.fs.Path(policyFilePath.toUri()));
        policyFileBackend.initialize(new ProviderBackendContext());
        Table<String, String, Set<String>> groupRolePrivilegeTable = policyFileBackend.getGroupRolePrivilegeTable();

        assertEquals(groups, groupRolePrivilegeTable.rowKeySet());
        assertEquals(privilegeMapping.keySet(), groupRolePrivilegeTable.columnKeySet());

        for (String groupName : groupRolePrivilegeTable.rowKeySet()) {
            for (String roleName : groupRolePrivilegeTable.columnKeySet()) {
                if (groupRolePrivilegeTable.contains(groupName, roleName)) {
                    Set<String> privileges = groupRolePrivilegeTable.get(groupName, roleName);
                    assertEquals(privilegeMapping.get(roleName), privileges);
                }
            }
        }
    }
}