falcon-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From venkat...@apache.org
Subject [3/9] git commit: FALCON-463 Validate Feed ACL only if authorization is enabled. Contributed by Venkatesh Seetharam
Date Fri, 08 Aug 2014 17:43:42 GMT
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 <venkatesh@apache.org>
Authored: Fri Aug 8 10:13:43 2014 -0700
Committer: Venkatesh Seetharam <venkatesh@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;
+            }
+        }
+    }
 }


Mime
View raw message