图片解析应用
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

175 lines
4.7 KiB

  1. """Kazoo Security"""
  2. from base64 import b64encode
  3. from collections import namedtuple
  4. import hashlib
  5. # Represents a Zookeeper ID and ACL object
  6. Id = namedtuple("Id", "scheme id")
  7. class ACL(namedtuple("ACL", "perms id")):
  8. """An ACL for a Zookeeper Node
  9. An ACL object is created by using an :class:`Id` object along with
  10. a :class:`Permissions` setting. For convenience,
  11. :meth:`make_digest_acl` should be used to create an ACL object with
  12. the desired scheme, id, and permissions.
  13. """
  14. @property
  15. def acl_list(self):
  16. perms = []
  17. if self.perms & Permissions.ALL == Permissions.ALL:
  18. perms.append("ALL")
  19. return perms
  20. if self.perms & Permissions.READ == Permissions.READ:
  21. perms.append("READ")
  22. if self.perms & Permissions.WRITE == Permissions.WRITE:
  23. perms.append("WRITE")
  24. if self.perms & Permissions.CREATE == Permissions.CREATE:
  25. perms.append("CREATE")
  26. if self.perms & Permissions.DELETE == Permissions.DELETE:
  27. perms.append("DELETE")
  28. if self.perms & Permissions.ADMIN == Permissions.ADMIN:
  29. perms.append("ADMIN")
  30. return perms
  31. def __repr__(self):
  32. return "ACL(perms=%r, acl_list=%s, id=%r)" % (
  33. self.perms,
  34. self.acl_list,
  35. self.id,
  36. )
  37. class Permissions(object):
  38. READ = 1
  39. WRITE = 2
  40. CREATE = 4
  41. DELETE = 8
  42. ADMIN = 16
  43. ALL = 31
  44. # Shortcuts for common Ids
  45. ANYONE_ID_UNSAFE = Id("world", "anyone")
  46. AUTH_IDS = Id("auth", "")
  47. # Shortcuts for common ACLs
  48. OPEN_ACL_UNSAFE = [ACL(Permissions.ALL, ANYONE_ID_UNSAFE)]
  49. CREATOR_ALL_ACL = [ACL(Permissions.ALL, AUTH_IDS)]
  50. READ_ACL_UNSAFE = [ACL(Permissions.READ, ANYONE_ID_UNSAFE)]
  51. def make_digest_acl_credential(username, password):
  52. """Create a SHA1 digest credential.
  53. .. note::
  54. This function uses UTF-8 to encode non-ASCII codepoints,
  55. whereas ZooKeeper uses the "default locale" for decoding. It
  56. may be a good idea to start the JVM with `-Dfile.encoding=UTF-8`
  57. in non-UTF-8 locales.
  58. See: https://github.com/python-zk/kazoo/pull/584
  59. """
  60. credential = username.encode("utf-8") + b":" + password.encode("utf-8")
  61. cred_hash = b64encode(hashlib.sha1(credential).digest()).strip()
  62. return username + ":" + cred_hash.decode("utf-8")
  63. def make_acl(
  64. scheme,
  65. credential,
  66. read=False,
  67. write=False,
  68. create=False,
  69. delete=False,
  70. admin=False,
  71. all=False,
  72. ):
  73. """Given a scheme and credential, return an :class:`ACL` object
  74. appropriate for use with Kazoo.
  75. :param scheme: The scheme to use. I.e. `digest`.
  76. :param credential:
  77. A colon separated username, password. The password should be
  78. hashed with the `scheme` specified. The
  79. :meth:`make_digest_acl_credential` method will create and
  80. return a credential appropriate for use with the `digest`
  81. scheme.
  82. :param write: Write permission.
  83. :type write: bool
  84. :param create: Create permission.
  85. :type create: bool
  86. :param delete: Delete permission.
  87. :type delete: bool
  88. :param admin: Admin permission.
  89. :type admin: bool
  90. :param all: All permissions.
  91. :type all: bool
  92. :rtype: :class:`ACL`
  93. """
  94. if all:
  95. permissions = Permissions.ALL
  96. else:
  97. permissions = 0
  98. if read:
  99. permissions |= Permissions.READ
  100. if write:
  101. permissions |= Permissions.WRITE
  102. if create:
  103. permissions |= Permissions.CREATE
  104. if delete:
  105. permissions |= Permissions.DELETE
  106. if admin:
  107. permissions |= Permissions.ADMIN
  108. return ACL(permissions, Id(scheme, credential))
  109. def make_digest_acl(
  110. username,
  111. password,
  112. read=False,
  113. write=False,
  114. create=False,
  115. delete=False,
  116. admin=False,
  117. all=False,
  118. ):
  119. """Create a digest ACL for Zookeeper with the given permissions
  120. This method combines :meth:`make_digest_acl_credential` and
  121. :meth:`make_acl` to create an :class:`ACL` object appropriate for
  122. use with Kazoo's ACL methods.
  123. :param username: Username to use for the ACL.
  124. :param password: A plain-text password to hash.
  125. :param write: Write permission.
  126. :type write: bool
  127. :param create: Create permission.
  128. :type create: bool
  129. :param delete: Delete permission.
  130. :type delete: bool
  131. :param admin: Admin permission.
  132. :type admin: bool
  133. :param all: All permissions.
  134. :type all: bool
  135. :rtype: :class:`ACL`
  136. """
  137. cred = make_digest_acl_credential(username, password)
  138. return make_acl(
  139. "digest",
  140. cred,
  141. read=read,
  142. write=write,
  143. create=create,
  144. delete=delete,
  145. admin=admin,
  146. all=all,
  147. )