《Zookeeper官方指南》zookeeper 使用 acl 进行访问控制-博客-云栖社区-阿里云 price of bitcoin

原文链接 译者:thor liu

ZooKeeper 使用 ACL 进行访问控制

ZooKeeper使用ACL来控制访问其znode(zookeeper的数据树的数据节点)。ACL的实现方式非常类似于UNIX文件的访问权限:它采用访问权限位 允许/禁止 对节点的各种操作以及能进行操作的范围。不同于UNIX权限的是,zookeeper的节点不局限于 用户(文件的拥有者),组和其他人(其它)这三个标准范围。zookeeper不具有znode的拥有者的概念。相反,acl指定id集以及与之对应的权限。

还要注意的是一条ACL仅针对于一个特定的节点。尤其不适用于子节点。例如,如果/app 只对IP:172.16.16.1可读 而 / APP/status 是对任何人可读的,ACL不是递归的。

ZooKeeper支持可插拔的身份验证方案。 id使用如下形式 scheme:id,其中 scheme 是 id 所对应一个认证方案。例如,IP:172.16.16.1,id为主机的地址 172.16.16.1。

当客户端连接到ZooKeeper验证自己时,zookeeper将有关该客户端的所有id与客户连接关联。客户端试图访问一个节点时,这些id与该znodes的acl验证。 ACL是由(scheme:expression, perms)对构成。其中expression的格式指定为scheme。例如,(IP:19.22.0.0/16,READ)表示对所有起始IP为19.22的客户端具有读权限。

ACL 权限

ZooKeeper 支持以下权限:

• CREATE: 能创建子节点

• READ:能获取节点数据和列出其子节点

• WRITE: 能设置节点数据

• DELETE: 能删除子节点

• ADMIN: 能设置权限

CREATE权限和DELETE权限从WRITE权限中分离出来,是为了获得更好的访问控制。使用CREATE和DELETE权限的场景如下:

the price of bitcoin

你想让A用户能够设置节点数据,但不允许创建或删除子节点。

有CREATE但无DELETE权限:客户端发出一个在父目录下创建节点的请求。你想让所有客户端能够添加,但是只有创建者能够删除。(这类似于文件的APPEND权限)。

内置的 ACL schemes

ZooKeeper有如下内置的schemes

• world 有个唯一的id, anyone ,代表所有人。

• auth 不使用任何id,代表任何已认证的用户。

• digest 用 username:password 字符串来产生一个MD5串,然后该串被用来作为ACL ID。认证是通过明文发送 username:password 来进行的,当用在ACL时,表达式为 username:base64 ,base64是password的sha1摘要的编码。

• ip 使用客户端的主机IP作为ACL ID 。这个ACL表达式的格式为 addr/bits ,此时addr中的有效位与客户端addr中的有效位进行比对。

ZooKeeper C 客户端 API

如下的常量是由ZooKeeper C语言库中提供的:

• const int ZOO PERM READ; //能读节点的值及列出其子节点

• const int ZOO PERM WRITE; //能设置节点的值

• const int ZOO PERM CREATE; //能创建子节点

• const int ZOO PERM DELETE; // 能删除子节点

• const int ZOO PERM ADMIN; //能执行set acl()

• const int ZOO PERM ALL; // 上面所有值的OR

• struct id ZOO ANYONE ID UNSAFE; //(‘world’,’anyone’)

• struct id ZOO AUTH IDS;// (‘auth’,’’)

ZOO AUTH IDS 为空时,应被理解成“创建者的id”

the price of bitcoin

ZooKeeper 客户端有3种标准的ACL:

• struct ACL vector ZOO OPEN ACL UNSAFE; //(ZOO PERM ALL,ZOO ANYONE ID UNSAFE)

• struct ACL vector ZOO READ ACL UNSAFE;// (ZOO PERM READ, ZOO ANYONE ID UNSAFE)

• struct ACL vector ZOO CREATOR ALL ACL; //(ZOO PERM ALL,ZOO AUTH IDS)

ZOO OPEN ACL UNSAFE使所有ACL都“开放”了:任何应用程序在节点上可进行任何操作,能创建、列出和删除它的子节点。对任何应用程序,ZOO READ ACL UNSAFE是只读的。CREATE ALL ACL赋予了节点的创建者所有的权限,在创建者采用此ACL创建节点之前,已经被服务器所认证(例如,采用 “ digest”方案)。

以下ZooKeeper方法处理ACL:

• int zoo add auth (zhandle t *zh, const char* scheme, const char* cert, int certlen, void completion t completion, const void *data);

The application uses the zoo add auth function to authenticate itself to the server. The function can be called multiple times if the application wants to authenticate using different schemes and/or identities.

应用程序使用zoo add auth方法来向服务器认证自己,如果想用不同的方案来认证,这个方法可以被调用多次。

the price of bitcoin

• int zoo create (zhandle t *zh, const char *path, const char *value, int valuelen, const struct ACL vector *acl, int flags, char *realpath, int max realpath len);

Zoo create(…)方法创建一个新节点。acl 参数是一个与这个节点关联的ACL列表,父节点权限项的CREATE位已被设(set,即由权限)。

• int zoo get acl (zhandle t *zh, const char *path, struct ACL vector *acl, struct stat *stat);

这个方法返回这个节点的ACL信息。

• int zoo set acl (zhandle t *zh, const char *path, int version, const struct ACL vector *acl);

这个方法用新的节点的ACL列表替换老的,这个节点的ADMIN位必须被设置(set,即具有ADMIN权限)。

这有一个使用上面API的例子,采用”foo”方案认证,创建一个“/xyz”的暂态节点,设置其为”只创建“权限。

这是一个非常简单的例子,它的目的是展示如何与zookeeper ACL交换。C客户端的实现,参考…/trunk/src/c/src/cli.C .

#include

#include “zookeeper.H”

Static zhandle t *zh;

/**

* in this example this method gets the cert for your

* environment — you must provide

*/

Char *foo get cert once(char* id) { return 0; }

the price of bitcoin

/** watcher function — empty for this example, not something you should

* do in real code */

Void watcher(zhandle t *zzh, int type, int state, const char *path,

Void *watcherctx) {}

Int main(int argc, char argv) {

Char buffer[512];

Char p[2048];

Char *cert=0;

Char appid[64];

Strcpy(appid, “example.Foo test”);

Cert = foo get cert once(appid);

If(cert!=0) {

Fprintf(stderr,

“certificate for appid [%s] is [%s]\n”,appid,cert);

Strncpy(p,cert, sizeof(p)-1);

Free(cert);

} else {

Fprintf(stderr, “certificate for appid [%s] not found\n”,appid);

Strcpy(p, “dummy”);

}

Zoo set debug level(ZOO LOG LEVEL DEBUG);

Zh = zookeeper init(“localhost:3181″, watcher, 10000, 0, 0, 0);

If (!Zh) {

Return errno;

}

If(zoo add auth(zh,”foo”,p,strlen(p),0,0)!=ZOK)

Return 2;

Struct ACL CREATE ONLY ACL[] = {{ZOO PERM CREATE, ZOO AUTH IDS}};

Struct ACL vector CREATE ONLY = {1, CREATE ONLY ACL};

the price of bitcoin

Int rc = zoo create(zh,”/xyz”,”value”, 5, CREATE ONLY, ZOO EPHEMERAL,

Buffer, sizeof(buffer)-1);

/** this operation will fail with a ZNOAUTH error */

Int buflen= sizeof(buffer);

Struct stat stat;

Rc = zoo get(zh, “/xyz”, 0, buffer, buflen, stat);

If (rc) {

Fprintf(stderr, “error %d for %s\n”, rc, LINE );

}

Zookeeper close(zh);

Return 0;

}