curator-user mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Robert Kanter <rkan...@cloudera.com>
Subject Re: Help with ACLProvider + Kerberos
Date Tue, 05 Nov 2013 21:58:57 GMT
I created the below test class using JUnit.  It starts a TestingServer and
connects to it; then it creates a path directly to verify that the custom
ACLProvider is being applied.  Then it tries to do the same with an
InterProcessReadWriteLock and fails the test because its using the default
ACLs.  I used “ip” instead of “sasl” to keep things simpler.

I did take a quick look at the Curator code and it seemed to be using the
ACLProvider through the CuratorFramework when using locks, but perhaps I
missed something (and I’m not super familiar with the codebase).

Please take a look; thanks!
- Robert


import java.util.Collections;
import java.util.List;
import junit.framework.TestCase;
import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.api.ACLProvider;
import org.apache.curator.framework.recipes.locks.InterProcessMutex;
import org.apache.curator.framework.recipes.locks.InterProcessReadWriteLock;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.apache.curator.test.TestingServer;
import org.apache.zookeeper.ZooDefs;
import org.apache.zookeeper.data.ACL;
import org.apache.zookeeper.data.Id;

public class TestLockACLs extends TestCase {
    private TestingServer zkServer;
    private CuratorFramework client;
    private final List<ACL> acls = Collections.singletonList(new
ACL(ZooDefs.Perms.ALL, new Id("ip", "127.0.0.1")));

    @Override
    protected void setUp() throws Exception {
        super.setUp();
        zkServer = new TestingServer();
        createClient();
    }

    @Override
    protected void tearDown() throws Exception {
        super.tearDown();
        client.close();
        zkServer.stop();
        zkServer.close();
    }

    private void createClient() throws Exception {
        RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);
        String zkConnectionString = zkServer.getConnectString();
        String zkNamespace = "ns";
        client = CuratorFrameworkFactory.builder()
                                            .namespace(zkNamespace)

.connectString(zkConnectionString)
                                            .retryPolicy(retryPolicy)
                                            .aclProvider(new
MyACLProvider())
                                            .build();
        client.start();
    }

    public void testLockACLs() throws Exception {
        // Create a path directly and verify that MyACLProvider is being
used
        client.create().forPath("/foo");
        assertNotNull(client.checkExists().forPath("/foo"));
        assertEquals(ZooDefs.Perms.ALL,
client.getACL().forPath("/foo").get(0).getPerms());
        assertEquals("ip",
client.getACL().forPath("/foo").get(0).getId().getScheme());
        assertEquals("127.0.0.1",
client.getACL().forPath("/foo").get(0).getId().getId());

        // Now try creating a lock and we'll see that it incorrectly has
the default world ACLs
        // and doesn't seem to be using MyACLProvider
        InterProcessReadWriteLock lock = new
InterProcessReadWriteLock(client, "/bar");
        InterProcessMutex writeLock = lock.writeLock();
        writeLock.acquire();
        assertNotNull(client.checkExists().forPath("/bar"));
        assertEquals(ZooDefs.Perms.ALL,
client.getACL().forPath("/bar").get(0).getPerms());
        assertEquals("ip",
client.getACL().forPath("/bar").get(0).getId().getScheme());
        assertEquals("127.0.0.1",
client.getACL().forPath("/bar").get(0).getId().getId());
    }

    public class MyACLProvider implements ACLProvider {

        @Override
        public List<ACL> getDefaultAcl() {
            return acls;
        }

        @Override
        public List<ACL> getAclForPath(String path) {
            return acls;
        }
    }
}


On Mon, Nov 4, 2013 at 6:10 PM, Jordan Zimmerman <jordan@jordanzimmerman.com
> wrote:

> The ACLProvider should be called for every node created. It’s not getting
> called? Can you produce a test that shows this?
>
> -Jordan
>
> On Nov 4, 2013, at 5:57 PM, Robert Kanter <rkanter@cloudera.com> wrote:
>
> I have everything working now except for one thing:
> The ACLProvider doesn’t seem to be used for the locks (Curator’s
> InterProcessReadWriteLock); they are always created with the default
> fully open ACLs.  I know the ACLProvider is correct now because the
> service discovery is using it and znodes created by it have the correct
> ACLs.  InterProcessReadWriteLock’s constructor takes in the
> CuratorFramework object, which has the ACLProvider set.
>
> Any ideas?
> This sounds like it could be a Curator bug :(
> I’m not familiar with Curator’s codebase, but I’ll try to take a look and
> see if I can figure it out.
>
> thanks
> - Robert
>
>
>
> On Mon, Nov 4, 2013 at 1:09 PM, Robert Kanter <rkanter@cloudera.com>wrote:
>
>> I don’t have it 100% working yet, but I’ve figured out a lot more, so I
>> thought I’d share in case anyone else runs into this:
>>
>> The ZooDefs.Ids.CREATOR_ALL_ACL predefined ACL that I was trying to use
>> is for the “auth” scheme.  For SASL/Kerberos, we want “sasl”.  The
>> javadoc for the predefined one wasn’t very clear on that; I had to look at
>> the code.  Using this is working:
>> Collections.singletonList(new ACL(Perms.ALL, new Id("sasl", principal)));
>>
>> I was also able to find answers to the three questions I asked:
>> 1) Yes; looking through the code, its definitely grabbing the
>> ACLProvider and using it.
>> 2) Yes; I think the only way to do this is to recursively travel through
>> the znodes under /oozie and apply the ACL on starting up Oozie.  We
>> should only have to do this if previously it was setup without security and
>> has since been reconfigured to use security; so we should only have to do
>> this once.  I can probably have a znode as a flag that states if
>> everything has ACLs or not to make it more efficient
>> 3) It doesn’t look like it; I’ll have to get the ZK client and do it
>> from outside Curator
>>
>>
>> - Robert
>>
>>
>> On Mon, Oct 28, 2013 at 5:47 PM, Jordan Zimmerman <
>> jordan@jordanzimmerman.com> wrote:
>>
>>> I don’t have any experience with this. Curator doesn’t do much - it sets
>>> up the ACL as the CLI options dictate. I do know that you also have to do
>>> work on the server side to make this work.
>>>
>>> -JZ
>>>
>>> On Oct 24, 2013, at 4:58 PM, Robert Kanter <rkanter@cloudera.com> wrote:
>>>
>>> Hi,
>>>
>>> Is there any documentation on using an ACLProvider and/or Kerberos?
>>>
>>> From what I gathered at various sites, to use Kerberos, all I have to do
>>> is set the following properties before building the CuratorFramework client:
>>> System.setProperty("java.security.auth.login.config",
>>> "/path/to/jaasConfFile");
>>>
>>> System.setProperty("zookeeper.authProvider.1","org.apache.zookeeper.server.auth.SASLAuthenticationProvider");
>>> System.setProperty(ZooKeeperSaslClient.LOGIN_CONTEXT_NAME_KEY, "Client");
>>> Looking at the logs for the client and server, this appears to be
>>> working properly and my program is connecting to ZooKeeper using Kerberos.
>>>
>>> The problem I'm having is with the ACLs.
>>>
>>> I'd like to set the ACLs so that only the Kerberos user running the
>>> program can do anything.  From what I can tell, if I specify an
>>> ACLProvider, then Curator will automatically use it for setting ACLs on
>>> all paths.  So, an ACLProvider like the following should do what I want:
>>> public class CreatorACLProvider implements ACLProvider {
>>>    @Override
>>>     public List<ACL> getDefaultAcl() {
>>>         return ZooDefs.Ids.CREATOR_ALL_ACL;
>>>    }
>>>    @Override
>>>     public List<ACL> getAclForPath(String path) {
>>>         return ZooDefs.Ids.CREATOR_ALL_ACL;
>>>    }
>>> }
>>> Then I would just do this:
>>> client = CuratorFrameworkFactory.builder()
>>>                                 .namespace(zkNamespace)
>>>                                 .connectString(zkConnectionString)
>>>                                 .retryPolicy(retryPolicy)
>>>                                 .aclProvider(new CreatorACLProvider())
>>>                                 .build();
>>> client.start();
>>>
>>> However, this doesn't seem to be working.  The zkcli returns this (on a
>>> newly created znode):
>>> [zk: localhost:2181(CONNECTED) 8] getAcl
>>> /oozie/locks/0000000-131024162150146-oozie-oozi-W
>>> 'world,'anyone
>>> : Cdr.
>>> Is there something that I missed?
>>>
>>> A few other questions:
>>> 1) Will the ACLProvider cause the ACLs to be applied to znodes created
>>> by the Curator recipes?  (e.g. InterProcessReadWriteLock,
>>> ServiceDiscovery, etc).  If not, then how should I go about setting the
>>> ACLs for these znodes?
>>> 2) I'm guessing that the ACLProvider is only applied when creating the
>>> znode, right; so existing znodes from before I added the ACLProviderwon't have
the ACLs I want, right?  What would be the best way to apply the
>>> ACLs to any existing znodes that don't have it set?  (My goal is to have
>>> all znodes under /oozie have the CREATOR_ALL_ACL)
>>> 3) Is there a way to set the ACLs on the namespace itself (i.e. /oozie)?
>>>  The methods that take a path (and automatically prepend the namespace)
>>> don't allow simply "/", so it seems like I'd have to use the ZooKeeper
>>> client directly to set ACLs manually on the namespace.  Or would simply
>>> passing an empty string "" work?
>>>
>>> thanks
>>> - Robert
>>>
>>>
>>>
>>
>
>

Mime
View raw message