zookeeper访问控制列表(ACL)

原文地址:https://zookeeper.apache.org/doc/r3.5.5/zookeeperProgrammers.html#sc_ZooKeeperAccessControl

 

1.简介

ZooKeeper使用ACL来控制对其znode(ZooKeeper数据树的数据节点)的访问。

ACL实现与UNIX文件访问权限非常相似:它使用权限位来允许/禁止针对节点的各种操作以及位应用的范围。

与标准UNIX权限不同,ZooKeeper节点不受用户(文件所有者),组和世界(其他)的三个标准范围的限制。

ZooKeeper没有znode所有者的概念。 相反,ACL指定ID与这些ID关联的权限集。

另请注意,ACL仅适用于特定的znode。特别是父节点的ACL不适用于子节点。

例如,如果/ app只能通过ip读取:172.16.16.1和/ app / status是世界可读的,那么任何人都可以读取/ app / status; ACL不是递归的。

ZooKeeper支持可插拔的身份验证方案。使用表单scheme:expression指定ID,其中scheme是id对应的认证方案。有效表达式集由方案定义。

例如,ip:172.16.16.1是使用ip方案的地址为172.16.16.1的主机的id,而digest:bob:password是使用摘要方案的名称为bob的用户的id。

当客户端连接到ZooKeeper并对其自身进行身份验证时,ZooKeeper会将与客户端对应的所有ID与客户端连接相关联。

当客户端尝试访问节点时,将根据znode的ACL检查这些ID。

ACL由(scheme:expression,perms)对组成。表达式的格式特定于该方案。

例如,该对(ip:19.22.0.0/16,READ)为任何IP地址以19.22开头的客户端提供READ权限。

 

2.ACL权限

ZooKeeper支持以下权限:

  • CREATE:您可以创建子节点
  • READ:您可以从节点获取数据并列出其子节点。
  • WRITE:您可以为节点设置数据
  • DELETE:您可以删除子节点
  • ADMIN:您可以设置权限

CREATE和DELETE权限已从WRITE权限中删除,以获得更精细的访问控制。

CREATE和DELETE的情况如下:

您希望A能够在ZooKeeper节点上执行设置数据,但无法创建或删除子节点。

CREATE without DELETE:客户端通过在父目录中创建ZooKeeper节点来创建请求。您希望所有客户端都能够添加,但只有请求处理器才能删除。 (这有点像文件的APPEND权限。)

此外,由于ZooKeeper没有文件所有者的概念,因此存在ADMIN权限。在某种意义上,ADMIN权限将实体指定为所有者。 ZooKeeper不支持LOOKUP权限(对目录执行权限位以允许您进行LOOKUP,即使您无法列出目录)。每个人都隐含地拥有LOOKUP权限。这允许您统计节点,但仅此而已。 (问题是,如果要在不存在的节点上调用zoo_exists(),则无权检查。)

ADMIN权限在ACL方面也有一个特殊的作用:为了检索znode的ACL,用户必须具有READ或ADMIN权限,但没有ADMIN权限,摘要哈希值将被屏蔽掉。

 

2.1内置ACL方案


ZooKeeeper具有以下内置方案:

  • world:一个id,任何人,代表任何人。
  • auth:是一种特殊方案,它忽略任何提供的表达式,而是使用当前用户,凭据和方案。在持久化ACL时,ZooKeeper服务器会忽略所提供的任何表达式(无论是使用SASL身份验证还是用户:密码,如使用DIGEST身份验证)。但是,仍必须在ACL中提供表达式,因为ACL必须与表单scheme:expression:perms匹配。提供此方案是为了方便,因为它是用户创建znode然后将该znode的访问权限仅限于该用户的常见用例。如果没有经过身份验证的用户,则使用auth方案设置ACL将失败。
  • digest:使用username:password字符串生成MD5哈希,然后将其用作ACL ID标识。通过以明文形式发送用户名:密码来完成身份验证。在ACL中使用时,表达式将是用户名:base64编码的SHA1密码摘要。
  • ip:使用客户端主机IP作为ACL ID标识。 ACL表达式的形式为addr / bits,其中addr的最高有效位与客户端主机IP的最高有效位匹配。
  • x509:使用客户端X500 Principal作为ACL ID标识。 ACL表达式是客户端的确切X500主体名称。使用安全端口时,会自动对客户端进行身份验证,并设置x509方案的身份验证信息。

 

2.2ZooKeeper 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


以下是标准ACL ID:

struct Id ZOO_ANYONE_ID_UNSAFE; //(“世界”,”人”)
struct Id ZOO_AUTH_IDS; //('auth','')
ZOO_AUTH_IDS空标识字符串应解释为“创建者的标识”。

 

ZooKeeper客户端带有三个标准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向节点的创建者授予所有权限。创建者必须已经过服务器验证(例如,使用“_digest_”方案)才能使用此ACL创建节点。

 

以下ZooKeeper操作处理ACL:

 

int zoo_add_auth(zhandle_t * zh,_const_ char * scheme,_const_ char * cert,int certLen,void_completion_t completion,const void * data);
应用程序使用zoo_add_auth函数向服务器验证自身。如果应用程序想要使用不同的方案和/或身份进行身份验证,则可以多次调用该函数。

 

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权限位。

 

int zoo_get_acl(zhandle_t * zh,const char * path,_struct_ ACL_vector * acl,struct Stat * stat);
此操作返回节点的ACL信息。该节点必须具有READ或ADMIN权限集。如果没有ADMIN权限,摘要哈希值将被屏蔽掉。

 

int zoo_set_acl(zhandle_t * zh,const char * path,int version,_const_ struct ACL_vector * acl);
此函数用新的ACL替换节点的ACL列表。该节点必须具有ADMIN权限集。

示例:

#include <string.h>
#include <errno.h>

#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; }

/** 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");
  }

  #设置debug日志级别  
  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};

  #创建节点
  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;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值