[ Tutorial ] Apache ZooKeeper – Setting ACL in ZooKeeper Client

Now let’s talk about setting the ACL of a znode in ZooKeeper. Before getting into the details, let’s talk more about the scheme and ID.

1. Scheme and ID

ID, as name suggests, is an identifier comprised of a username and password. By default, when the znode has an ACL set accessible by a specific group of users or an individual, the <username>:<password> is first hashed using an SHA-1 hashing algorithm, and then it (hex-string) is base-64 encoded.

As mentioned in earlier blog entries, scheme is like a group of users that are authorized to access a certain znode with a scheme-and-id-specific ACL set.

1.1. World Scheme

World scheme has one ID (anyone). This represents any user in the world.

For example, we type in the following command to set the znode accessible by anyone.

setAcl /newznode world:anyone:crdwa

By doing it correctly, You should get something like this in return:

world_acl_valid

1.2. Auth Scheme

Auth scheme represents a "manually" set group of authenticated users. According to the ZooKeeper documentation (http://zookeeper.apache.org/doc/r3.1.2/zookeeperProgrammers.html), auth does not utilize any ID. Unless I am mistaken, this seems not to be the case. Because if you try to set ACL on a znode using auth scheme and not provide any ID, it tells you that is not a valid ID, or some form of ID is needed. Below is a (bad) example:

setAcl /newznode auth:crdwa

as seen above, I did not provide any form of ID. This is what I get:

invalid_acl

A correct way to use this scheme would be as follows:

setAcl /newznode auth:username:password:crdwa

Using auth scheme allows us to have multiple authorized users to access a single znode with the different username and password combination. Say we have 3 users:

username : password
user_123 : pwd_123
user_456 : pwd_456
user_789 : pwd_789

We can use the same syntax above by replacing username with user_123, user_456, or user_789 and password with pwd_123, pwd_456, or pwd_789 respectively.

1.2.1 addauth Command

One important thing to note is you must use the addauth command before proceeding to set the ACL of a znode using the auth scheme. If you try to set the ACL before executing the addauth command, you will get an error as below:

invalid_acl2

Correct way to do is to execute addauth command first, and then execute the setAcl command. Below is the syntax of command execution for addauth:

addauth /<node-name> digest <username>:<password>

By adding the authenticator and setting ACL accordingly, you can ensure that you set the ACL correctly.

valid_acl

Repeat the steps for additional username and password combo, and the ACL for that newznode looks like this:

valid_acl2

1.3. Digest Scheme

Digest scheme represents an individual user with authentication. This uses username:password string that is hashed using the SHA-1 hashing algorithm, and that hashed string is in turn base64 encoded. According to the ZooKeeper website, it is stated that the MD5 hash of <username>:<password> is used as an ACL ID identity. Unless I am mistaken, that seems not to be the case. Instead, what I found was that <username>:<Base64 encoded SHA-1 hash of username:password> is used as an ACL ID (Please see above pictures under the Auth section).

What’s really funny is that if I authenticate an individual user on a znode using digest scheme on ZooKeeper client, instead of storing the username and encoded hash string of <username:password> like it should, it stores a clear, human-readable text of <username:password> as an ID. Executing the addauth command before setting the ACL with digest scheme does not work either. Below is the picture that illustrates my point:

acl_digest

Unless it is easy to work backwards – decoding the user_abc:pwd_abc, and then take that decoded string and undo the SHA-1 hashing part, it turns out setting ACL using digest scheme on a znode in ZooKeeper client is pointless.

Good thing is that if you setAcl a znode using digest scheme via client, you can delete it.

1.4. Host Scheme

Host scheme represents anyone within the same hosting server. I have not done enough with the host scheme yet, but I will come back to this with more details.

1.5. IP Scheme

IP scheme represents any user within the same IP address. Easiest example to use in this case would be 127.0.0.1, which represents the user of that any local machine, since any local machine will have 127.0.0.1 point to the localhost. Below is the syntax of setAcl using IP scheme:

setAcl /<node-name> ip:<IPv4-address>:<permission-set>

Using the syntax above, below is an example using the 127.0.0.1 IP address:

setAcl /newnode ip:127.0.0.1:crdwa

If done correctly, you should get the znode stat like the picture below:

acl_ip

That is it for now. On my next blog post, I will briefly talk about how to access them in Java; furthermore, I will talk more in detail about how username and password are stored. Thanks for reading as usual, and happy zookeeping!

[ Tutorial ] Apache ZooKeeper ACL (Access Control List) Getting Permission Sets

Today, I will talk about the basics of ACL in ZooKeeper and getting the permission sets of ACL.

1. What is ACL?

ACL (Access Control List) is basically an authentication mechanism implemented in ZooKeeper. It makes znodes accessible to users, depending on how it is set. For example, if its scheme is set to world and ID set to anyone, then it is accessible by anyone in the world, thus the world scheme and anyone ID. However, if the scheme is anything other than the world, then it’s a different story. Let’s talk about the basics and its attributes first.

A typical permission set of a znode looks something like this: crdwa. This is actually an acronym (can be in any order) that stands for: Create, Read, Delete, Write, and Admin.

1.1. Getting the ACL of a Znode

To get the ACL of a particular znode, we execute the getAcl command in the ZooKeeper client.

It will return that znode’s ACL in this format:

'[ scheme ],'[ id ]
: [ permission-set ]

Syntax of the getAcl command is: getAcl Path

Example: getAcl /getmyacl

Think of the scheme as more like a specific group of users. The world scheme would represent everyone in the world, literally. There are also different schemes in ZooKeeper, which are digest (individual user with unique username and password), ip, which is an individual or group of users within the same IP address, and host, which is a group of users within the same host.

ID I believe is self-explanatory; should the scheme be world, then ID always has to be anyone. There is no point to restrict specific users if it is meant to be viewed by anyone.

Here, I have an example of getting the ACL of the getmyacl znode. By typing in the command getAcl /getmyacl, you will get something like this:

acl-1

1.2. More About Permission Set

Notice how the permission set says crdwa. If you were trying to get the permission set of a znode in Java, you would get an integer value in return.

First off, you would call getPerms method to get the permission set of a znode in Java. As mentioned earlier, it returns an integer value. In this case, with this znode having a permission set of crdwa, in Java it returns 31, meaning that the user is authorized to create a child znode, read data of that znode, delete that znode, overwrite (or set data) the znode, and has administrative rights of that znode.

Each permission (create, read, delete, write, admin) is actually a bit, either 0 or 1, where 0 represents not allowed, and 1 represents allowed. So, if you convert that 31 into a binary number, you would get 11111. Refer to the following bullet points:

  • Read – 2^0
  • Write – 2^1
  • Create – 2^2
  • Delete – 2^3
  • Admin – 2^4

Say we have a getmyaccl znode. Create, read, and admin are allowed, but delete and write are not. According to my little bullet points above, in Java it would return 21 for the permission set. Convert that to binary, we get 10101 ( (2^4 = 16) + (2^2 = 4) + (2^0 = 1) ) = 21

Let’s try to change its permission set to cwa (create, write, admin) and see what integer value is returned in Java.

This time it returned 22, or 10110 ( (2^4 = 16) + (2^2 = 4) + (2^1 = 2) ) = 22

To get the permission set of a znode, we need to import ACL class (from ZooKeeper package) and ArrayList. First, we need to create an instance of ArrayList that can store ACL object, and create a new instance of ACL object, assign that to the first element of the ArrayList. What’s interesting is that ArrayList contains only one element. Following is the code snippet on how to get the permission set of a znode:

List acl = new ArrayList(); // create new instance of ArrayList to store ACL object
acl = zk.getACL("/getmyacl", stat); 
ACL aclElement = acl.get(0);
System.out.println(aclElement.getPerms()); // for printing the permission set on the screen.  
                                    // this is also how I get 21 and 22 earlier for the permission set.  

When creating a znode the simplest way, any user is authorized the full crdwa permission set. I will talk more about setting the permission set in 2 different blog entries: First one will be the easy; where any user can access the znode. Second one will be tricky (also to talk about and explain), which involves an individual’s username and password, group of users within the same host or the IP address.

This sums up how to get the permission set of a znode. As usual, thanks for reading, and happy zookeeping!