This is an automated email from the ASF dual-hosted git repository.

sijie pushed a commit to branch branch-2.1
in repository https://gitbox.apache.org/repos/asf/incubator-pulsar.git


The following commit(s) were added to refs/heads/branch-2.1 by this push:
     new d3261ed  Enable authentication and authorization for some admin APIs 
(#2046)
d3261ed is described below

commit d3261ed4dc86f4cdf5ad6a246c532212f064967a
Author: massakam <[email protected]>
AuthorDate: Fri Jun 29 01:21:02 2018 +0900

    Enable authentication and authorization for some admin APIs (#2046)
    
    ### Motivation
    
    Currently, it seems to that users who are not admin can send POST requests 
to the REST APIs for configuring retention policy and persistence policies.
    ```
    POST /admin/namespaces/{tenant}/{namespace}/retention
    POST /admin/persistent/{tenant}/{namespace}/persistence
    ```
    I think that only administrators should be able to change these settings.
    
    ### Modifications
    
    Fixed these APIs to authenticate and authorize users by calling the 
`validateAdminAccessForTenant()` method.
    
    ### Result
    
    Only the administrators of the tenant will be able to change these settings.
---
 .../pulsar/broker/admin/impl/NamespacesBase.java   |  2 +
 .../apache/pulsar/broker/admin/NamespacesTest.java | 73 +++++++++++++++++-----
 2 files changed, 59 insertions(+), 16 deletions(-)

diff --git 
a/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/impl/NamespacesBase.java
 
b/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/impl/NamespacesBase.java
index b8a4c53..553f53a 100644
--- 
a/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/impl/NamespacesBase.java
+++ 
b/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/impl/NamespacesBase.java
@@ -767,6 +767,7 @@ public abstract class NamespacesBase extends AdminResource {
     }
 
     protected void internalSetRetention(RetentionPolicies retention) {
+        validateAdminAccessForTenant(namespaceName.getTenant());
         validatePoliciesReadOnlyAccess();
 
         try {
@@ -804,6 +805,7 @@ public abstract class NamespacesBase extends AdminResource {
     }
 
     protected void internalSetPersistence(PersistencePolicies persistence) {
+        validateAdminAccessForTenant(namespaceName.getTenant());
         validatePoliciesReadOnlyAccess();
         validatePersistencePolicies(persistence);
 
diff --git 
a/pulsar-broker/src/test/java/org/apache/pulsar/broker/admin/NamespacesTest.java
 
b/pulsar-broker/src/test/java/org/apache/pulsar/broker/admin/NamespacesTest.java
index 305c887..f24aad5 100644
--- 
a/pulsar-broker/src/test/java/org/apache/pulsar/broker/admin/NamespacesTest.java
+++ 
b/pulsar-broker/src/test/java/org/apache/pulsar/broker/admin/NamespacesTest.java
@@ -64,6 +64,7 @@ import org.apache.pulsar.common.naming.TopicName;
 import org.apache.pulsar.common.policies.data.AuthAction;
 import org.apache.pulsar.common.policies.data.BundlesData;
 import org.apache.pulsar.common.policies.data.ClusterData;
+import org.apache.pulsar.common.policies.data.PersistencePolicies;
 import org.apache.pulsar.common.policies.data.Policies;
 import org.apache.pulsar.common.policies.data.TenantInfo;
 import org.apache.pulsar.common.policies.data.RetentionPolicies;
@@ -90,6 +91,7 @@ public class NamespacesTest extends 
MockedPulsarServiceBaseTest {
     private List<NamespaceName> testLocalNamespaces;
     private List<NamespaceName> testGlobalNamespaces;
     private final String testTenant = "my-tenant";
+    private final String testOtherTenant = "other-tenant";
     private final String testLocalCluster = "use";
     private final String testOtherCluster = "usc";
 
@@ -110,6 +112,7 @@ public class NamespacesTest extends 
MockedPulsarServiceBaseTest {
         testLocalNamespaces.add(NamespaceName.get(this.testTenant, 
this.testLocalCluster, "test-namespace-1"));
         testLocalNamespaces.add(NamespaceName.get(this.testTenant, 
this.testLocalCluster, "test-namespace-2"));
         testLocalNamespaces.add(NamespaceName.get(this.testTenant, 
this.testOtherCluster, "test-other-namespace-1"));
+        testLocalNamespaces.add(NamespaceName.get(this.testOtherTenant, 
this.testLocalCluster, "test-namespace-1"));
 
         testGlobalNamespaces.add(NamespaceName.get(this.testTenant, "global", 
"test-global-ns1"));
 
@@ -133,8 +136,8 @@ public class NamespacesTest extends 
MockedPulsarServiceBaseTest {
         doReturn(false).when(namespaces).isRequestHttps();
         doReturn("test").when(namespaces).clientAppId();
         doReturn(Sets.newTreeSet(Lists.newArrayList("use", "usw", "usc", 
"global"))).when(namespaces).clusters();
-        doNothing().when(namespaces).validateAdminAccessForTenant("my-tenant");
-        
doNothing().when(namespaces).validateAdminAccessForTenant("other-tenant");
+        
doNothing().when(namespaces).validateAdminAccessForTenant(this.testTenant);
+        
doNothing().when(namespaces).validateAdminAccessForTenant("non-existing-tenant");
         
doNothing().when(namespaces).validateAdminAccessForTenant("new-property");
 
         admin.clusters().createCluster("use", new 
ClusterData("http://broker-use.com:"; + BROKER_WEBSERVICE_PORT));
@@ -142,11 +145,16 @@ public class NamespacesTest extends 
MockedPulsarServiceBaseTest {
         admin.clusters().createCluster("usc", new 
ClusterData("http://broker-usc.com:"; + BROKER_WEBSERVICE_PORT));
         admin.tenants().createTenant(this.testTenant,
                 new TenantInfo(Sets.newHashSet("role1", "role2"), 
Sets.newHashSet("use", "usc", "usw")));
+        admin.tenants().createTenant(this.testOtherTenant,
+                new TenantInfo(Sets.newHashSet("role3", "role4"), 
Sets.newHashSet("use", "usc", "usw")));
 
-        createTestNamespaces(this.testTenant, this.testLocalNamespaces, new 
BundlesData());
+        createTestNamespaces(this.testLocalNamespaces, new BundlesData());
         createGlobalTestNamespaces(this.testTenant, 
this.testGlobalNamespaces.get(0).getLocalName(),
                 new BundlesData());
 
+        doThrow(new RestException(Status.UNAUTHORIZED, 
"unauthorized")).when(namespaces)
+                .validateAdminAccessForTenant(this.testOtherTenant);
+
         nsSvc = pulsar.getNamespaceService();
     }
 
@@ -159,34 +167,34 @@ public class NamespacesTest extends 
MockedPulsarServiceBaseTest {
     @Test
     public void testCreateNamespaces() throws Exception {
         try {
-            namespaces.createNamespace("my-tenant", "other-colo", 
"my-namespace", new BundlesData());
+            namespaces.createNamespace(this.testTenant, "other-colo", 
"my-namespace", new BundlesData());
             fail("should have failed");
         } catch (RestException e) {
             // Ok, cluster doesn't exist
         }
 
         List<NamespaceName> nsnames = Lists.newArrayList();
-        nsnames.add(NamespaceName.get("my-tenant", "use", 
"create-namespace-1"));
-        nsnames.add(NamespaceName.get("my-tenant", "use", 
"create-namespace-2"));
-        nsnames.add(NamespaceName.get("my-tenant", "usc", 
"create-other-namespace-1"));
-        createTestNamespaces("my-tenant", nsnames, new BundlesData());
+        nsnames.add(NamespaceName.get(this.testTenant, "use", 
"create-namespace-1"));
+        nsnames.add(NamespaceName.get(this.testTenant, "use", 
"create-namespace-2"));
+        nsnames.add(NamespaceName.get(this.testTenant, "usc", 
"create-other-namespace-1"));
+        createTestNamespaces(nsnames, new BundlesData());
 
         try {
-            namespaces.createNamespace("my-tenant", "use", 
"create-namespace-1", new BundlesData());
+            namespaces.createNamespace(this.testTenant, "use", 
"create-namespace-1", new BundlesData());
             fail("should have failed");
         } catch (RestException e) {
             // Ok, namespace already exists
         }
 
         try {
-            namespaces.createNamespace("other-tenant", "use", 
"create-namespace-1", new BundlesData());
+            namespaces.createNamespace("non-existing-tenant", "use", 
"create-namespace-1", new BundlesData());
             fail("should have failed");
         } catch (RestException e) {
-            // Ok, property doesn't exist
+            // Ok, tenant doesn't exist
         }
 
         try {
-            namespaces.createNamespace("my-tenant", "use", 
"create-namespace-#", new BundlesData());
+            namespaces.createNamespace(this.testTenant, "use", 
"create-namespace-#", new BundlesData());
             fail("should have failed");
         } catch (RestException e) {
             // Ok, invalid namespace name
@@ -195,7 +203,7 @@ public class NamespacesTest extends 
MockedPulsarServiceBaseTest {
 
         mockZookKeeper.failNow(Code.SESSIONEXPIRED);
         try {
-            namespaces.createNamespace("my-tenant", "use", "my-namespace-3", 
new BundlesData());
+            namespaces.createNamespace(this.testTenant, "use", 
"my-namespace-3", new BundlesData());
             fail("should have failed");
         } catch (RestException e) {
             // Ok
@@ -215,7 +223,7 @@ public class NamespacesTest extends 
MockedPulsarServiceBaseTest {
         assertEquals(namespaces.getTenantNamespaces(this.testTenant), 
expectedList);
 
         try {
-            namespaces.getTenantNamespaces("other-tenant");
+            namespaces.getTenantNamespaces("non-existing-tenant");
             fail("should have failed");
         } catch (RestException e) {
             // Ok, does not exist
@@ -971,8 +979,7 @@ public class NamespacesTest extends 
MockedPulsarServiceBaseTest {
         namespaces.createNamespace(property, "global", namespace, bundle);
     }
 
-    private void createTestNamespaces(String property, List<NamespaceName> 
nsnames, BundlesData bundle)
-            throws Exception {
+    private void createTestNamespaces(List<NamespaceName> nsnames, BundlesData 
bundle) throws Exception {
         for (NamespaceName nsName : nsnames) {
             namespaces.createNamespace(nsName.getTenant(), 
nsName.getCluster(), nsName.getLocalName(), bundle);
         }
@@ -1047,6 +1054,40 @@ public class NamespacesTest extends 
MockedPulsarServiceBaseTest {
     }
 
     @Test
+    public void testRetentionUnauthorized() throws Exception {
+        try {
+            NamespaceName testNs = this.testLocalNamespaces.get(3);
+            RetentionPolicies retention = new RetentionPolicies(10, 10);
+            namespaces.setRetention(testNs.getTenant(), testNs.getCluster(), 
testNs.getLocalName(), retention);
+            fail("Should fail");
+        } catch (RestException e) {
+            assertEquals(e.getResponse().getStatus(), 
Status.UNAUTHORIZED.getStatusCode());
+        }
+    }
+
+    @Test
+    public void testPersistence() throws Exception {
+        NamespaceName testNs = this.testLocalNamespaces.get(0);
+        PersistencePolicies persistence1 = new PersistencePolicies(3, 2, 1, 
0.0);
+        namespaces.setPersistence(testNs.getTenant(), testNs.getCluster(), 
testNs.getLocalName(), persistence1);
+        PersistencePolicies persistence2 = 
namespaces.getPersistence(testNs.getTenant(), testNs.getCluster(),
+                testNs.getLocalName());
+        assertEquals(persistence2, persistence1);
+    }
+
+    @Test
+    public void testPersistenceUnauthorized() throws Exception {
+        try {
+            NamespaceName testNs = this.testLocalNamespaces.get(3);
+            PersistencePolicies persistence = new PersistencePolicies(3, 2, 1, 
0.0);
+            namespaces.setPersistence(testNs.getTenant(), testNs.getCluster(), 
testNs.getLocalName(), persistence);
+            fail("Should fail");
+        } catch (RestException e) {
+            assertEquals(e.getResponse().getStatus(), 
Status.UNAUTHORIZED.getStatusCode());
+        }
+    }
+
+    @Test
     public void testValidateTopicOwnership() throws Exception {
         try {
             URL localWebServiceUrl = new URL(pulsar.getWebServiceAddress());

Reply via email to