You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@falcon.apache.org by ve...@apache.org on 2014/08/08 19:43:42 UTC
[3/9] git commit: FALCON-463 Validate Feed ACL only if authorization
is enabled. Contributed by Venkatesh Seetharam
FALCON-463 Validate Feed ACL only if authorization is enabled. Contributed by Venkatesh Seetharam
Project: http://git-wip-us.apache.org/repos/asf/incubator-falcon/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-falcon/commit/a3c1ffe8
Tree: http://git-wip-us.apache.org/repos/asf/incubator-falcon/tree/a3c1ffe8
Diff: http://git-wip-us.apache.org/repos/asf/incubator-falcon/diff/a3c1ffe8
Branch: refs/heads/master
Commit: a3c1ffe844d1c8214ab9289e33e7a1312c9949f1
Parents: 909888f
Author: Venkatesh Seetharam <ve...@apache.org>
Authored: Fri Aug 8 10:13:43 2014 -0700
Committer: Venkatesh Seetharam <ve...@apache.org>
Committed: Fri Aug 8 10:13:43 2014 -0700
----------------------------------------------------------------------
client/src/main/resources/jaxb-binding.xjb | 4 +
.../apache/falcon/entity/FileSystemStorage.java | 8 +-
.../falcon/entity/parser/FeedEntityParser.java | 28 +--
.../falcon/entity/FileSystemStorageTest.java | 6 +-
.../entity/parser/FeedEntityParserTest.java | 179 +++++++++++++++++++
5 files changed, 204 insertions(+), 21 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-falcon/blob/a3c1ffe8/client/src/main/resources/jaxb-binding.xjb
----------------------------------------------------------------------
diff --git a/client/src/main/resources/jaxb-binding.xjb b/client/src/main/resources/jaxb-binding.xjb
index b7d5359..f644f40 100644
--- a/client/src/main/resources/jaxb-binding.xjb
+++ b/client/src/main/resources/jaxb-binding.xjb
@@ -36,6 +36,10 @@
<inheritance:extends>org.apache.falcon.entity.v0.Entity</inheritance:extends>
</jaxb:bindings>
+ <jaxb:bindings schemaLocation="feed-0.1.xsd" node="//xs:complexType[@name='ACL']">
+ <inheritance:extends>org.apache.falcon.entity.v0.AccessControlList</inheritance:extends>
+ </jaxb:bindings>
+
<jaxb:bindings schemaLocation="process-0.1.xsd" node="//xs:complexType[@name='process']">
<inheritance:extends>org.apache.falcon.entity.v0.Entity</inheritance:extends>
</jaxb:bindings>
http://git-wip-us.apache.org/repos/asf/incubator-falcon/blob/a3c1ffe8/common/src/main/java/org/apache/falcon/entity/FileSystemStorage.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/falcon/entity/FileSystemStorage.java b/common/src/main/java/org/apache/falcon/entity/FileSystemStorage.java
index 0d17f3d..326fccd 100644
--- a/common/src/main/java/org/apache/falcon/entity/FileSystemStorage.java
+++ b/common/src/main/java/org/apache/falcon/entity/FileSystemStorage.java
@@ -247,10 +247,10 @@ public class FileSystemStorage implements Storage {
if (fileSystem.exists(path)) {
FileStatus fileStatus = fileSystem.getFileStatus(path);
if (!fileStatus.getOwner().equals(owner)) {
- LOG.error("Feed ACL owner {} doesn't match the actual file owner {}",
- owner, fileStatus.getOwner());
- throw new FalconException("Feed ACL owner " + owner + " doesn't match the actual file owner "
- + fileStatus.getOwner());
+ LOG.error("Feed ACL owner {} doesn't match the actual owner {} for file {}",
+ owner, fileStatus.getOwner(), path);
+ throw new FalconException("Feed ACL owner " + owner
+ + " doesn't match the actual file owner " + fileStatus.getOwner());
}
}
}
http://git-wip-us.apache.org/repos/asf/incubator-falcon/blob/a3c1ffe8/common/src/main/java/org/apache/falcon/entity/parser/FeedEntityParser.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/falcon/entity/parser/FeedEntityParser.java b/common/src/main/java/org/apache/falcon/entity/parser/FeedEntityParser.java
index e517e39..0bc5c8f 100644
--- a/common/src/main/java/org/apache/falcon/entity/parser/FeedEntityParser.java
+++ b/common/src/main/java/org/apache/falcon/entity/parser/FeedEntityParser.java
@@ -40,7 +40,6 @@ import org.apache.falcon.entity.v0.process.Process;
import org.apache.falcon.expression.ExpressionHelper;
import org.apache.falcon.group.FeedGroup;
import org.apache.falcon.group.FeedGroupMap;
-import org.apache.falcon.security.CurrentUser;
import org.apache.falcon.security.SecurityUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -68,7 +67,7 @@ public class FeedEntityParser extends EntityParser<Feed> {
}
if (feed.getClusters() == null) {
- throw new ValidationException("Feed should have atleast one cluster");
+ throw new ValidationException("Feed should have at least one cluster");
}
for (Cluster cluster : feed.getClusters().getClusters()) {
@@ -82,7 +81,7 @@ public class FeedEntityParser extends EntityParser<Feed> {
validateFeedStorage(feed);
validateFeedPartitionExpression(feed);
validateFeedGroups(feed);
- validateUser(feed);
+ validateACL(feed);
// Seems like a good enough entity object for a new one
// But is this an update ?
@@ -105,14 +104,6 @@ public class FeedEntityParser extends EntityParser<Feed> {
ensureValidityFor(feed, processes);
}
- protected void validateUser(Feed feed) throws ValidationException {
- String owner = feed.getACL().getOwner();
- if (!owner.equals(CurrentUser.getUser())) {
- throw new ValidationException("Entity's owner " + owner + " is not same as current user "
- + CurrentUser.getUser());
- }
- }
-
private Set<Process> findProcesses(Set<Entity> referenced) {
Set<Process> processes = new HashSet<Process>();
for (Entity entity : referenced) {
@@ -314,9 +305,6 @@ public class FeedEntityParser extends EntityParser<Feed> {
* Does not matter for FileSystem storage.
*/
private void validateFeedStorage(Feed feed) throws FalconException {
- validateUser(feed);
- validateACL(feed);
-
final Storage.TYPE baseFeedStorageType = FeedHelper.getStorageType(feed);
validateMultipleSourcesExist(feed, baseFeedStorageType);
validateUniformStorageType(feed, baseFeedStorageType);
@@ -409,7 +397,19 @@ public class FeedEntityParser extends EntityParser<Feed> {
}
}
+ /**
+ * Validate ACL if authorization is enabled.
+ *
+ * @param feed Feed entity
+ * @throws ValidationException
+ */
private void validateACL(Feed feed) throws FalconException {
+ if (!isAuthorizationEnabled()) {
+ return;
+ }
+
+ validateOwner(feed.getACL().getOwner());
+
for (Cluster cluster : feed.getClusters().getClusters()) {
org.apache.falcon.entity.v0.cluster.Cluster clusterEntity =
EntityUtil.getEntity(EntityType.CLUSTER, cluster.getName());
http://git-wip-us.apache.org/repos/asf/incubator-falcon/blob/a3c1ffe8/common/src/test/java/org/apache/falcon/entity/FileSystemStorageTest.java
----------------------------------------------------------------------
diff --git a/common/src/test/java/org/apache/falcon/entity/FileSystemStorageTest.java b/common/src/test/java/org/apache/falcon/entity/FileSystemStorageTest.java
index 06f660d..47f63bc 100644
--- a/common/src/test/java/org/apache/falcon/entity/FileSystemStorageTest.java
+++ b/common/src/test/java/org/apache/falcon/entity/FileSystemStorageTest.java
@@ -167,11 +167,11 @@ public class FileSystemStorageTest {
fs.mkdirs(path);
FileSystemStorage storage = new FileSystemStorage(cluster.getConf().get("fs.default.name"), locations);
- storage.validateACL(user, user, "rrr");
+ storage.validateACL(user, user, "0x755");
//-ve case
try {
- storage.validateACL("random", user, "rrr");
+ storage.validateACL("random", user, "0x755");
Assert.fail("Validation should have failed");
} catch(FalconException e) {
//expected exception
@@ -183,7 +183,7 @@ public class FileSystemStorageTest {
//-ve case
try {
- storage.validateACL("random", user, "rrr");
+ storage.validateACL("random", user, "0x755");
Assert.fail("Validation should have failed");
} catch(FalconException e) {
//expected exception
http://git-wip-us.apache.org/repos/asf/incubator-falcon/blob/a3c1ffe8/common/src/test/java/org/apache/falcon/entity/parser/FeedEntityParserTest.java
----------------------------------------------------------------------
diff --git a/common/src/test/java/org/apache/falcon/entity/parser/FeedEntityParserTest.java b/common/src/test/java/org/apache/falcon/entity/parser/FeedEntityParserTest.java
index e2da982..e669f44 100644
--- a/common/src/test/java/org/apache/falcon/entity/parser/FeedEntityParserTest.java
+++ b/common/src/test/java/org/apache/falcon/entity/parser/FeedEntityParserTest.java
@@ -19,6 +19,7 @@
package org.apache.falcon.entity.parser;
import org.apache.falcon.FalconException;
+import org.apache.falcon.cluster.util.EmbeddedCluster;
import org.apache.falcon.entity.AbstractTestBase;
import org.apache.falcon.entity.ClusterHelper;
import org.apache.falcon.entity.EntityUtil;
@@ -32,6 +33,8 @@ import org.apache.falcon.entity.v0.cluster.Interfacetype;
import org.apache.falcon.entity.v0.feed.*;
import org.apache.falcon.group.FeedGroupMapTest;
import org.apache.falcon.security.CurrentUser;
+import org.apache.falcon.util.StartupProperties;
+import org.apache.hadoop.fs.Path;
import org.testng.Assert;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
@@ -50,6 +53,8 @@ import static org.testng.AssertJUnit.assertEquals;
*/
public class FeedEntityParserTest extends AbstractTestBase {
+ public static final String USER = System.getProperty("user.name");
+
private final FeedEntityParser parser = (FeedEntityParser) EntityParserFactory
.getParser(EntityType.FEED);
@@ -60,6 +65,9 @@ public class FeedEntityParserTest extends AbstractTestBase {
cleanupStore();
ConfigurationStore store = ConfigurationStore.get();
+ this.dfsCluster = EmbeddedCluster.newCluster("testCluster");
+ this.conf = dfsCluster.getConf();
+
Unmarshaller unmarshaller = EntityType.CLUSTER.getUnmarshaller();
Cluster cluster = (Cluster) unmarshaller.unmarshal(this.getClass()
.getResourceAsStream(CLUSTER_XML));
@@ -85,10 +93,14 @@ public class FeedEntityParserTest extends AbstractTestBase {
@Test(expectedExceptions = ValidationException.class)
public void testValidateUser() throws Exception {
CurrentUser.authenticate("unknown");
+ StartupProperties.get().setProperty("falcon.security.authorization.enabled", "true");
+ Assert.assertTrue(Boolean.valueOf(
+ StartupProperties.get().getProperty("falcon.security.authorization.enabled")));
try {
parser.parseAndValidate(this.getClass().getResourceAsStream(FEED_XML));
} finally {
CurrentUser.authenticate("testuser");
+ StartupProperties.get().setProperty("falcon.security.authorization.enabled", "false");
}
}
@@ -535,4 +547,171 @@ public class FeedEntityParserTest extends AbstractTestBase {
Assert.fail("An exception should have been thrown: Cluster should have registry interface defined with table"
+ " storage");
}
+
+ @Test
+ public void testValidateACLWithACLAndAuthorizationDisabled() throws Exception {
+ InputStream stream = this.getClass().getResourceAsStream(FEED_XML);
+
+ Feed feed = parser.parse(stream);
+ Assert.assertNotNull(feed);
+ Assert.assertNotNull(feed.getACL());
+ Assert.assertNotNull(feed.getACL().getOwner());
+ Assert.assertNotNull(feed.getACL().getGroup());
+ Assert.assertNotNull(feed.getACL().getPermission());
+
+ parser.validate(feed);
+ }
+
+ @Test
+ public void testValidateACLAndOwner() throws Exception {
+ CurrentUser.authenticate("testuser");
+ StartupProperties.get().setProperty("falcon.security.authorization.enabled", "true");
+ Assert.assertTrue(Boolean.valueOf(
+ StartupProperties.get().getProperty("falcon.security.authorization.enabled")));
+
+ try {
+ InputStream stream = this.getClass().getResourceAsStream(FEED_XML);
+
+ Feed feed = parser.parseAndValidate(stream);
+ Assert.assertNotNull(feed);
+ Assert.assertNotNull(feed.getACL());
+ Assert.assertNotNull(feed.getACL().getOwner());
+ Assert.assertNotNull(feed.getACL().getGroup());
+ Assert.assertNotNull(feed.getACL().getPermission());
+ } finally {
+ StartupProperties.get().setProperty("falcon.security.authorization.enabled", "false");
+ }
+ }
+
+ @Test (expectedExceptions = ValidationException.class)
+ public void testValidateACLBadOwner() throws Exception {
+ StartupProperties.get().setProperty("falcon.security.authorization.enabled", "true");
+ Assert.assertTrue(Boolean.valueOf(
+ StartupProperties.get().getProperty("falcon.security.authorization.enabled")));
+ CurrentUser.authenticate("blah");
+
+ try {
+ InputStream stream = this.getClass().getResourceAsStream(FEED_XML);
+
+ // need a new parser since it caches authorization enabled flag
+ FeedEntityParser feedEntityParser =
+ (FeedEntityParser) EntityParserFactory.getParser(EntityType.FEED);
+ Feed feed = feedEntityParser.parse(stream);
+
+ Assert.assertNotNull(feed);
+ Assert.assertNotNull(feed.getACL());
+ Assert.assertNotNull(feed.getACL().getOwner());
+ Assert.assertNotNull(feed.getACL().getGroup());
+ Assert.assertNotNull(feed.getACL().getPermission());
+
+ feedEntityParser.validate(feed);
+ Assert.fail("Validation exception should have been thrown for invalid owner");
+ } finally {
+ StartupProperties.get().setProperty("falcon.security.authorization.enabled", "false");
+ }
+ }
+
+ @Test (expectedExceptions = ValidationException.class)
+ public void testValidateACLBadOwnerAndGroup() throws Exception {
+ StartupProperties.get().setProperty("falcon.security.authorization.enabled", "true");
+ Assert.assertTrue(Boolean.valueOf(
+ StartupProperties.get().getProperty("falcon.security.authorization.enabled")));
+ CurrentUser.authenticate("blah");
+
+ try {
+ InputStream stream = this.getClass().getResourceAsStream(FEED_XML);
+
+ Feed feed = parser.parse(stream);
+
+ Assert.assertNotNull(feed);
+ Assert.assertNotNull(feed.getACL());
+ Assert.assertNotNull(feed.getACL().getOwner());
+ Assert.assertNotNull(feed.getACL().getGroup());
+ Assert.assertNotNull(feed.getACL().getPermission());
+
+ parser.validate(feed);
+ Assert.fail("Validation exception should have been thrown for invalid owner");
+ } finally {
+ CurrentUser.authenticate("testuser");
+ StartupProperties.get().setProperty("falcon.security.authorization.enabled", "false");
+ }
+ }
+
+ @Test (expectedExceptions = ValidationException.class)
+ public void testValidateACLAndStorageBadOwner() throws Exception {
+ CurrentUser.authenticate("testuser");
+ StartupProperties.get().setProperty("falcon.security.authorization.enabled", "true");
+ Assert.assertTrue(Boolean.valueOf(
+ StartupProperties.get().getProperty("falcon.security.authorization.enabled")));
+
+ Feed feed = null;
+ try {
+ InputStream stream = this.getClass().getResourceAsStream(FEED_XML);
+
+ feed = parser.parse(stream);
+ Assert.assertNotNull(feed);
+ Assert.assertNotNull(feed.getACL());
+ Assert.assertNotNull(feed.getACL().getOwner());
+ Assert.assertNotNull(feed.getACL().getGroup());
+ Assert.assertNotNull(feed.getACL().getPermission());
+
+ // create locations
+ createLocations(feed);
+ parser.validate(feed);
+ } finally {
+ if (feed != null) {
+ deleteLocations(feed);
+ }
+ StartupProperties.get().setProperty("falcon.security.authorization.enabled", "false");
+ }
+ }
+
+ @Test
+ public void testValidateACLAndStorage() throws Exception {
+ CurrentUser.authenticate(USER);
+ StartupProperties.get().setProperty("falcon.security.authorization.enabled", "true");
+ Assert.assertTrue(Boolean.valueOf(
+ StartupProperties.get().getProperty("falcon.security.authorization.enabled")));
+
+ Feed feed = null;
+ try {
+ InputStream stream = this.getClass().getResourceAsStream(FEED_XML);
+
+ feed = parser.parse(stream);
+ Assert.assertNotNull(feed);
+ Assert.assertNotNull(feed.getACL());
+ Assert.assertNotNull(feed.getACL().getOwner());
+ Assert.assertNotNull(feed.getACL().getGroup());
+ Assert.assertNotNull(feed.getACL().getPermission());
+
+ feed.getACL().setOwner(USER);
+
+ // create locations
+ createLocations(feed);
+ parser.validate(feed);
+ } finally {
+ if (feed != null) {
+ deleteLocations(feed);
+ }
+ StartupProperties.get().setProperty("falcon.security.authorization.enabled", "false");
+ }
+ }
+
+ private void createLocations(Feed feed) throws IOException {
+ for (Location location : feed.getLocations().getLocations()) {
+ if (location.getType() == LocationType.DATA) {
+ dfsCluster.getFileSystem().create(new Path(location.getPath()));
+ break;
+ }
+ }
+ }
+
+ private void deleteLocations(Feed feed) throws IOException {
+ for (Location location : feed.getLocations().getLocations()) {
+ if (location.getType() == LocationType.DATA) {
+ dfsCluster.getFileSystem().delete(new Path(location.getPath()), true);
+ break;
+ }
+ }
+ }
}