/**
* 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.falcon.regression.security;
import org.apache.falcon.regression.core.bundle.Bundle;
import org.apache.falcon.regression.core.enumsAndConstants.MerlinConstants;
import org.apache.falcon.regression.core.helpers.ColoHelper;
import org.apache.falcon.regression.core.helpers.entity.AbstractEntityHelper;
import org.apache.falcon.regression.core.response.ServiceResponse;
import org.apache.falcon.regression.core.util.AssertUtil;
import org.apache.falcon.regression.core.util.BundleUtil;
import org.apache.falcon.regression.core.util.HadoopUtil;
import org.apache.falcon.regression.core.util.MatrixUtil;
import org.apache.falcon.regression.core.util.OSUtil;
import org.apache.falcon.regression.testHelper.BaseTestClass;
import org.apache.hadoop.fs.FileSystem;
import org.testng.Assert;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
/**
* Tests ACL of cluster with different operations.
*/
@Test(groups = "authorization")
public class ClusterAclTest extends BaseTestClass {
private ColoHelper cluster = servers.get(0);
private FileSystem clusterFS = serverFS.get(0);
private String baseTestDir = cleanAndGetTestDir();
private String aggregateWorkflowDir = baseTestDir + "/aggregator";
private String feedInputPath = baseTestDir + "/input" + MINUTE_DATE_PATTERN;
private final AbstractEntityHelper clusterHelper = prism.getClusterHelper();
private String clusterString;
@BeforeClass(alwaysRun = true)
public void uploadWorkflow() throws Exception {
HadoopUtil.uploadDir(clusterFS, aggregateWorkflowDir, OSUtil.RESOURCES_OOZIE);
}
@BeforeMethod(alwaysRun = true)
public void setup() throws Exception {
Bundle bundle = BundleUtil.readELBundle();
bundles[0] = new Bundle(bundle, cluster);
bundles[0].generateUniqueBundle(this);
bundles[0].setInputFeedDataPath(feedInputPath);
bundles[0].setProcessWorkflow(aggregateWorkflowDir);
bundles[0].setCLusterACL(MerlinConstants.CURRENT_USER_NAME,
MerlinConstants.CURRENT_USER_GROUP, "*");
clusterString = bundles[0].getClusters().get(0);
}
/**
* Test cluster read operations by different users.
* @param user the user that would perform operation
* @param op the operation that user would perform
* @param isAllowed is the user allowed that operation
* @throws Exception
*/
@Test(dataProvider = "generateUserReadOpsPermissions")
public void othersReadCluster(final String user, EntityOp op, final boolean isAllowed)
throws Exception {
bundles[0].submitClusters(prism);
bundles[0].submitFeeds(prism);
final boolean executeRes = op.executeAs(user, clusterHelper, clusterString);
Assert.assertEquals(executeRes, isAllowed, "Unexpected result user " + user
+ " performing: " + op);
}
@DataProvider(name = "generateUserReadOpsPermissions")
public Object[][] generateUserReadOpsPermissions() {
final Object[][] allowedCombinations = MatrixUtil.crossProduct(
new String[]{
MerlinConstants.FALCON_SUPER_USER_NAME,
MerlinConstants.FALCON_SUPER_USER2_NAME,
MerlinConstants.USER2_NAME,
},
new EntityOp[]{
EntityOp.dependency,
EntityOp.listing,
EntityOp.definition,
},
new Boolean[]{true}
);
final Object[][] notAllowedCombinations = MatrixUtil.crossProduct(
new String[]{MerlinConstants.DIFFERENT_USER_NAME},
new EntityOp[]{EntityOp.dependency, EntityOp.listing, EntityOp.definition},
new Boolean[]{false}
);
return MatrixUtil.append(allowedCombinations, notAllowedCombinations);
}
/**
* Test cluster deletion by different users.
* @param deleteUser the user that would attempt to delete
* @param deleteAllowed is delete expected to go through
* @throws Exception
*/
@Test(dataProvider = "generateUserAndDeletePermission")
public void othersDeleteCluster(final String deleteUser, final boolean deleteAllowed)
throws Exception {
bundles[0].submitClusters(prism);
final ServiceResponse response = clusterHelper.delete(clusterString, deleteUser);
if (deleteAllowed) {
AssertUtil.assertSucceeded(response);
} else {
AssertUtil.assertFailedWith403(response);
}
}
@DataProvider(name = "generateUserAndDeletePermission")
public Object[][] generateUserAndDeletePermission() {
return new Object[][] {
//first element is username, second element indicates if deletion is allowed
{MerlinConstants.FALCON_SUPER_USER_NAME, true},
{MerlinConstants.FALCON_SUPER_USER2_NAME, true},
{MerlinConstants.USER2_NAME, true},
{"root", false},
};
}
@AfterMethod(alwaysRun = true)
public void tearDown() {
removeTestClassEntities();
}
}