blob: 10f992590a746945a020dc388ad155658d16a91d [file] [log] [blame]
/*
* 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.authorization.kylin.authorizer;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang.RandomStringUtils;
import org.apache.kylin.common.KylinConfig;
import org.apache.kylin.metadata.project.ProjectInstance;
import org.apache.kylin.metadata.project.ProjectManager;
import org.apache.kylin.metadata.project.RealizationEntry;
import org.apache.kylin.rest.util.AclEvaluate;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.FixMethodOrder;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.MethodSorters;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationCredentialsNotFoundException;
import org.springframework.security.test.context.support.WithMockUser;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.util.ReflectionTestUtils;
/**
*
* Here we plug the Ranger RangerKylinAuthorizer into Kylin.
*
* A custom RangerAdminClient is plugged into Ranger in turn, which loads security policies from a local file.
* These policies were generated in the Ranger Admin UI for a kylin service called "kylinTest":
*
* a) A user "kylin" can do all permissions(contains "ADMIN", "MANAGEMENT", "OPERATION", "QUERY")
* on all kylin projects;
* b) A user "zhangqiang" can do a "ADMIN" on the project "test_project",
* and do a "OPERATION" on the project "kylin_project";
* c) A user "yuwen" can do a "ADMIN" on the project "test_project",
* and do a "OPERATION" on the project "kylin_project";
* d) A user "admin" has role "ROLE_ADMIN",
* and the others have role "ROLE_USER" by mock for test.
*
*/
@Ignore
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath*:applicationContext.xml", "classpath*:kylinSecurity.xml" })
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class RangerKylinAuthorizerTest {
private static final Map<String, ProjectInstance> uuid2Projects = new HashMap<>();
private static final Map<String, ProjectInstance> name2Projects = new HashMap<>();
private static final String ADMIN = "admin";
private static final String KYLIN = "kylin";
private static final String ZHANGQIANG = "zhangqiang";
private static final String YUWEN = "yuwen";
private static final String LEARN_PROJECT = "learn_project";
private static final String TEST_PROJECT = "test_project";
private static final String KYLIN_PROJECT = "kylin_project";
private static final String[] PROJECTNAMES = new String[] { LEARN_PROJECT, TEST_PROJECT, KYLIN_PROJECT };
private static final String ROLE_ADMIN = "ADMIN";
private static final String ROLE_USER = "USER";
@Autowired
private AclEvaluate aclEvaluate;
@BeforeClass
public static void setup() throws Exception {
// set kylin conf path
System.setProperty(KylinConfig.KYLIN_CONF, "src/test/resources");
// init kylin projects
initKylinProjects();
// mock kylin projects, to match projectUuid and projectName for kylin
mockKylinProjects();
}
@AfterClass
public static void cleanup() throws Exception {
// do nothing
}
/**
* Help function: init kylin projects
*/
private static void initKylinProjects() {
for (String projectName : PROJECTNAMES) {
ProjectInstance projectInstance = getProjectInstance(projectName);
name2Projects.put(projectName, projectInstance);
uuid2Projects.put(projectInstance.getUuid(), projectInstance);
}
}
/**
* Help function: mock kylin projects, to match projectUuid and projectName
*/
private static void mockKylinProjects() {
KylinConfig kylinConfig = KylinConfig.getInstanceFromEnv();
ProjectManager projectManager = mock(ProjectManager.class);
@SuppressWarnings({ "rawtypes", "unchecked" })
Map<Class, Object> managersCache = (Map<Class, Object>) ReflectionTestUtils.getField(kylinConfig,
"managersCache");
managersCache.put(ProjectManager.class, projectManager);
Answer<ProjectInstance> answer = new Answer<ProjectInstance>() {
@Override
public ProjectInstance answer(InvocationOnMock invocation) throws Throwable {
Object[] args = invocation.getArguments();
if (args == null || args.length == 0) {
return null;
}
String uuid = (String) args[0];
return uuid2Projects.get(uuid);
}
};
when(projectManager.getPrjByUuid(anyString())).thenAnswer(answer);
}
/**
* Help function: get random project instance for test
*/
private static ProjectInstance getRandomProjectInstance() {
String name = RandomStringUtils.randomAlphanumeric(10) + "-project";
return getProjectInstance(name);
}
/**
* Help function: get specific project instance for test
*/
private static ProjectInstance getProjectInstance(String name) {
String owner = null;
String description = null;
LinkedHashMap<String, String> overrideProps = null;
List<RealizationEntry> realizationEntries = null;
List<String> models = null;
return ProjectInstance.create(name, owner, description, overrideProps, realizationEntries, models);
}
// No.1 hasProjectReadPermission test start
/**
* no credentials read any project failed
*/
@Test(expected = AuthenticationCredentialsNotFoundException.class)
public void readProjectAnyWithoutCredentials() {
ProjectInstance project = getRandomProjectInstance();
aclEvaluate.hasProjectReadPermission(project);
}
/**
* admin read all projects sueecss
*/
@Test
@WithMockUser(username = ADMIN, roles = { ROLE_ADMIN })
public void readProjectAllAsRoleAdmin() {
for (ProjectInstance project : uuid2Projects.values()) {
boolean result = aclEvaluate.hasProjectReadPermission(project);
Assert.assertTrue(result);
}
}
/**
* kylin read all projects success
*/
@Test
@WithMockUser(username = KYLIN, roles = { ROLE_USER })
public void readProjectAllWithAdminPermission() {
for (ProjectInstance project : uuid2Projects.values()) {
boolean result = aclEvaluate.hasProjectReadPermission(project);
Assert.assertTrue(result);
}
}
/**
* zhangqiang read test_project success
*/
@Test
@WithMockUser(username = ZHANGQIANG, roles = { ROLE_USER })
public void readProjectTestWithAdminPermission() {
ProjectInstance project = name2Projects.get(TEST_PROJECT);
boolean result = aclEvaluate.hasProjectReadPermission(project);
Assert.assertTrue(result);
}
/**
* zhangqiang read kylin_project success
*/
@Test
@WithMockUser(username = ZHANGQIANG, roles = { ROLE_USER })
public void readProjectKylinWithOperationPermission() {
ProjectInstance project = name2Projects.get(KYLIN_PROJECT);
boolean result = aclEvaluate.hasProjectReadPermission(project);
Assert.assertTrue(result);
}
/**
* yuwen read test_project success
*/
@Test
@WithMockUser(username = YUWEN, roles = { ROLE_USER })
public void readProjectTestWithManagementPermission() {
ProjectInstance project = name2Projects.get(TEST_PROJECT);
boolean result = aclEvaluate.hasProjectReadPermission(project);
Assert.assertTrue(result);
}
/**
* yuwen read kylin_project success
*/
@Test
@WithMockUser(username = YUWEN, roles = { ROLE_USER })
public void readProjectKylinWithQueryPermission() {
ProjectInstance project = name2Projects.get(KYLIN_PROJECT);
boolean result = aclEvaluate.hasProjectReadPermission(project);
Assert.assertTrue(result);
}
/**
* yuwen read learn_project failed
*/
@Test
@WithMockUser(username = YUWEN, roles = { ROLE_USER })
public void readProjectLearnWithoutPermission() {
ProjectInstance project = name2Projects.get(LEARN_PROJECT);
boolean result = aclEvaluate.hasProjectReadPermission(project);
Assert.assertFalse(result);
}
// No.1 hasProjectReadPermission test end
// No.2 hasProjectOperationPermission test start
/**
* no credentials operation any project failed
*/
@Test(expected = AuthenticationCredentialsNotFoundException.class)
public void operationProjectAnyWithoutCredentials() {
ProjectInstance project = getRandomProjectInstance();
aclEvaluate.hasProjectOperationPermission(project);
}
/**
* admin operation all projects sueecss
*/
@Test
@WithMockUser(username = ADMIN, roles = { ROLE_ADMIN })
public void operationProjectAllAsRoleAdmin() {
for (ProjectInstance project : uuid2Projects.values()) {
boolean result = aclEvaluate.hasProjectOperationPermission(project);
Assert.assertTrue(result);
}
}
/**
* kylin operation all projects success
*/
@Test
@WithMockUser(username = KYLIN, roles = { ROLE_USER })
public void operationProjectAllWithAdminPermission() {
for (ProjectInstance project : uuid2Projects.values()) {
boolean result = aclEvaluate.hasProjectOperationPermission(project);
Assert.assertTrue(result);
}
}
/**
* zhangqiang operation test_project success
*/
@Test
@WithMockUser(username = ZHANGQIANG, roles = { ROLE_USER })
public void operationProjectTestWithAdminPermission() {
ProjectInstance project = name2Projects.get(TEST_PROJECT);
boolean result = aclEvaluate.hasProjectOperationPermission(project);
Assert.assertTrue(result);
}
/**
* zhangqiang operation kylin_project success
*/
@Test
@WithMockUser(username = ZHANGQIANG, roles = { ROLE_USER })
public void operationProjectKylinWithOperationPermission() {
ProjectInstance project = name2Projects.get(KYLIN_PROJECT);
boolean result = aclEvaluate.hasProjectOperationPermission(project);
Assert.assertTrue(result);
}
/**
* yuwen operation test_project success
*/
@Test
@WithMockUser(username = YUWEN, roles = { ROLE_USER })
public void operationProjectTestWithManagementPermission() {
ProjectInstance project = name2Projects.get(TEST_PROJECT);
boolean result = aclEvaluate.hasProjectOperationPermission(project);
Assert.assertTrue(result);
}
/**
* yuwen operation kylin_project failed
*/
@Test
@WithMockUser(username = YUWEN, roles = { ROLE_USER })
public void operationProjectKylinWithoutPermission() {
ProjectInstance project = name2Projects.get(KYLIN_PROJECT);
boolean result = aclEvaluate.hasProjectOperationPermission(project);
Assert.assertFalse(result);
}
/**
* yuwen operation learn_project failed
*/
@Test
@WithMockUser(username = YUWEN, roles = { ROLE_USER })
public void operationProjectLearnWithoutPermission() {
ProjectInstance project = name2Projects.get(LEARN_PROJECT);
boolean result = aclEvaluate.hasProjectOperationPermission(project);
Assert.assertFalse(result);
}
// No.2 hasProjectOperationPermission test end
// No.3 hasProjectWritePermission test start
/**
* no credentials write any project failed
*/
@Test(expected = AuthenticationCredentialsNotFoundException.class)
public void writeProjectAnyWithoutCredentials() {
ProjectInstance project = getRandomProjectInstance();
aclEvaluate.hasProjectWritePermission(project);
}
/**
* admin write all projects sueecss
*/
@Test
@WithMockUser(username = ADMIN, roles = { ROLE_ADMIN })
public void writeProjectAllAsRoleAdmin() {
for (ProjectInstance project : uuid2Projects.values()) {
boolean result = aclEvaluate.hasProjectWritePermission(project);
Assert.assertTrue(result);
}
}
/**
* kylin write all projects success
*/
@Test
@WithMockUser(username = KYLIN, roles = { ROLE_USER })
public void writeProjectAllWithAdminPermission() {
for (ProjectInstance project : uuid2Projects.values()) {
boolean result = aclEvaluate.hasProjectWritePermission(project);
Assert.assertTrue(result);
}
}
/**
* zhangqiang write test_project success
*/
@Test
@WithMockUser(username = ZHANGQIANG, roles = { ROLE_USER })
public void writeProjectTestWithAdminPermission() {
ProjectInstance project = name2Projects.get(TEST_PROJECT);
boolean result = aclEvaluate.hasProjectWritePermission(project);
Assert.assertTrue(result);
}
/**
* zhangqiang write kylin_project failed
*/
@Test
@WithMockUser(username = ZHANGQIANG, roles = { ROLE_USER })
public void writeProjectKylinWithoutPermission() {
ProjectInstance project = name2Projects.get(KYLIN_PROJECT);
boolean result = aclEvaluate.hasProjectWritePermission(project);
Assert.assertFalse(result);
}
/**
* yuwen write test_project success
*/
@Test
@WithMockUser(username = YUWEN, roles = { ROLE_USER })
public void writeProjectTestWithManagementPermission() {
ProjectInstance project = name2Projects.get(TEST_PROJECT);
boolean result = aclEvaluate.hasProjectWritePermission(project);
Assert.assertTrue(result);
}
/**
* yuwen write kylin_project failed
*/
@Test
@WithMockUser(username = YUWEN, roles = { ROLE_USER })
public void writeProjectKylinWithoutPermission2() {
ProjectInstance project = name2Projects.get(KYLIN_PROJECT);
boolean result = aclEvaluate.hasProjectWritePermission(project);
Assert.assertFalse(result);
}
/**
* yuwen write learn_project failed
*/
@Test
@WithMockUser(username = YUWEN, roles = { ROLE_USER })
public void writeProjectLearnWithoutPermission() {
ProjectInstance project = name2Projects.get(LEARN_PROJECT);
boolean result = aclEvaluate.hasProjectWritePermission(project);
Assert.assertFalse(result);
}
// No.3 hasProjectWritePermission test end
// No.4 hasProjectAdminPermission test start
/**
* no credentials admin any project failed
*/
@Test(expected = AuthenticationCredentialsNotFoundException.class)
public void adminProjectAnyWithoutCredentials() {
ProjectInstance project = getRandomProjectInstance();
aclEvaluate.hasProjectAdminPermission(project);
}
/**
* admin admin all projects sueecss
*/
@Test
@WithMockUser(username = ADMIN, roles = { ROLE_ADMIN })
public void adminProjectAllAsRoleAdmin() {
for (ProjectInstance project : uuid2Projects.values()) {
boolean result = aclEvaluate.hasProjectAdminPermission(project);
Assert.assertTrue(result);
}
}
/**
* kylin admin all projects success
*/
@Test
@WithMockUser(username = KYLIN, roles = { ROLE_USER })
public void adminProjectAllWithAdminPermission() {
for (ProjectInstance project : uuid2Projects.values()) {
boolean result = aclEvaluate.hasProjectAdminPermission(project);
Assert.assertTrue(result);
}
}
/**
* zhangqiang admin test_project success
*/
@Test
@WithMockUser(username = ZHANGQIANG, roles = { ROLE_USER })
public void adminProjectTestWithAdminPermission() {
ProjectInstance project = name2Projects.get(TEST_PROJECT);
boolean result = aclEvaluate.hasProjectAdminPermission(project);
Assert.assertTrue(result);
}
/**
* zhangqiang admin kylin_project failed
*/
@Test
@WithMockUser(username = ZHANGQIANG, roles = { ROLE_USER })
public void adminProjectKylinWithoutPermission() {
ProjectInstance project = name2Projects.get(KYLIN_PROJECT);
boolean result = aclEvaluate.hasProjectAdminPermission(project);
Assert.assertFalse(result);
}
/**
* yuwen admin test_project failed
*/
@Test
@WithMockUser(username = YUWEN, roles = { ROLE_USER })
public void adminProjectTestWithoutPermission() {
ProjectInstance project = name2Projects.get(TEST_PROJECT);
boolean result = aclEvaluate.hasProjectAdminPermission(project);
Assert.assertFalse(result);
}
/**
* yuwen admin kylin_project failed
*/
@Test
@WithMockUser(username = YUWEN, roles = { ROLE_USER })
public void adminProjectKylinWithoutPermission2() {
ProjectInstance project = name2Projects.get(KYLIN_PROJECT);
boolean result = aclEvaluate.hasProjectAdminPermission(project);
Assert.assertFalse(result);
}
/**
* yuwen admin learn_project failed
*/
@Test
@WithMockUser(username = YUWEN, roles = { ROLE_USER })
public void adminProjectLearnWithoutPermission() {
ProjectInstance project = name2Projects.get(LEARN_PROJECT);
boolean result = aclEvaluate.hasProjectAdminPermission(project);
Assert.assertFalse(result);
}
// No.4 hasProjectAdminPermission test end
}