你是谁?RabbitMQ 2.3.1 中的身份验证和授权
RabbitMQ 2.3.1 引入了几个新的插件机制,让您可以更全面地控制用户如何向 Rabbit 进行身份验证,以及我们如何确定他们被授权执行哪些操作。这里有三个问题值得关注:
- 客户端如何在传输过程中证明其身份?
- 用户和身份验证信息(例如密码哈希)存储在哪里?
- 权限信息存储在哪里?
对于 AMQP,第一个问题通过 SASL 来解答——这是一个嵌入在 AMQP(以及其他各种协议)中的可插拔身份验证机制的简单协议。SASL 允许客户端和服务器协商并使用身份验证机制,而无需“外部”协议了解身份验证的工作细节。
SASL 提供了许多“机制”。从一开始,RabbitMQ 就支持 PLAIN 机制,它基本上是在传输过程中以明文形式发送用户名和密码(当然,整个连接可能由 SSL 保护)。它也支持 AMQPLAIN 机制(概念上与 PLAIN 相同,但如果您有一个 AMQP 编解码器,实现起来会更容易)。RabbitMQ 2.3.1 添加了一个插件系统,允许您添加或配置更多机制,我们编写了一个实现 SASL EXTERNAL 机制的示例插件。
SASL EXTERNAL 机制基本上就是说“通过协议上下文之外的某种机制来确定用户的身份”。在 rabbitmq-auth-mechanism-ssl 中,我们将其理解为 SSL。当此插件安装并启用后,如果客户端使用 SSL 连接并提供服务器 CA 信任的客户端证书,则无需提供用户名和密码即可连接。在这种情况下,我们将用户名视为所提供证书的通用名称 (Common Name)。只要该用户名存在,就可以允许其登录。
但是该用户名存在吗?并且针对它记录了哪些权限?这就引出了我们的第二(即身份验证)和第三(即授权)个问题。
同样,从一开始,RabbitMQ 就包含一个内部用户和权限数据库,通过 rabbitmqctl 进行管理,最近又通过 管理插件 进行管理。同样,RabbitMQ 2.3.1 添加了一个插件系统,允许您增强或替换此数据库。
而且,我们编写了一个插件来做一些有趣的事情。rabbitmq-auth-backend-ldap 允许您通过 LDAP 数据库对用户进行身份验证并检查授权。这可以完全替代内置数据库,也可以仅仅对其进行增强。配置此插件进行身份验证(相对而言)很简单,一旦您的 LDAP 服务器启动并运行;您为所有用户提供一个模板专有名称 (Distinguished Name),例如,登录名为“guest”的用户可能具有 DN“cn=guest,ou=People,dc=example,dc=com”,插件将尝试绑定到 LDAP 服务器以检查他们是否能够登录。很简单!
但是,配置插件进行授权则很困难。嗯,很复杂。问题在于 LDAP 对 AMQP 代理中的权限应该如何工作没有概念(这是个可怕的疏忽!),因此我们需要自己制定一些规则。README-authorisation 详细介绍了这一点,但简而言之,它有一个简单的分层查询机制,允许您构建针对 LDAP 数据库的查询。例如:
{vhost_access_query, {exists, "ou=${vhost},ou=vhosts,dc=example,dc=com"}}
是一个简单的查询,它根据 LDAP 中是否存在相应的组织单位 (Organisational Unit) 来确定 LDAP 用户是否可以查看虚拟主机,而
{resource_access_query,
{for, [{resource, exchange,
{for, [{permission, configure,
{ in_group, "cn=wheel,ou=groups,dc=example,dc=com" } },
{permission, write, {constant, true}},
{permission, read, {constant, true}}
]}},
{resource, queue, {constant, true}} ]}}
是一个更复杂的查询,它允许“wheel”组的成员声明和删除交换器,并允许所有用户执行其他所有操作。
那么,您怎么看?这对您有用吗?如何改进?