使用访问控制服务进行 Service Bus 身份验证和授权
Windows Azure Service Bus操作的授权(即决定是否在当前用户的安全上下文中执行某项操作的行为),由 Windows Azure Active Directory 访问控制(也称为访问控制服务或 ACS)与 Service Bus 共同完成。
Windows Azure 访问控制
访问控制为身份验证提供便利,即它确定调用方的标识。访问控制通过两种方式确定调用方的标识。它或者根据服务标识(或帐户)的命名空间范围列表,使用传统用户名和密码方案来确定标识,或者将确定标识的任务委派给外部标识提供者,如 Active Directory 联合身份验证服务 (ADFS)、Windows Live ID、Facebook、Google ID、Yahoo ID 或 OpenID。
确定标识后,访问控制就有了(或会收到)有关标识的多个“声明”。这些声明将做出有关人员(或非人帐户)的陈述,并由发布它们的标识提供者进行数字签名,目的是向访问控制保证这些声明是正确的,或者至少符合颁发者的管理规则。换言之,如果一组声明指出其代表的标识为“Bill Gates,Microsoft Corporation 总裁”且这些声明由 Microsoft ADFS 网关发布,则最为可信,但由第三方发布时则不太可信。在所有标识提供者之间始终有效并可用于访问控制内置服务标识的声明属于提供者声明(标识提供者自身)和“nameidentifier”声明,对于给定标识来说,后者是特定于提供者且为提供者所独有的标识符。
其次,访问控制允许将标识提供者发布的声明映射到“信赖方”所理解的声明,因此可为授权提供便利。Service Bus 就是这样的信赖方,也就是说,它依赖访问控制处理身份验证和授权。对声明进行映射有两个用途:一方面,它将众多不同的声明“用语”标准化为一组可由服务理解的声明;另一方面,映射可作为一个授权规则集。如果给定标识无法映射到一组可由服务理解的声明,该标识将无法访问服务。
身份验证和授权始终会流经客户端,客户端是唯一需要向各方提供直接网络可见性的组件。例如,可以将未在企业防火墙外面公开的 ADFS 服务与访问控制结合使用,因为访问控制与 ADFS 绝不会彼此通信。尝试对受保护的资源执行某个操作(例如向 Service Bus 队列发送消息)时,客户端需要获得相关证据,证明自己已获得执行该操作的授权。它以令牌的形式从访问控制那里获得该证据。令牌只是用于放置一组声明的容器,由颁发者进行数字签名。如果将访问控制配置为使用外部标识提供者(如 ADFS)建立标识,则至少要用到两个令牌。第一个令牌将由标识提供者(如 ADFS)提供,可将用户标识的许多种证据之一作为输入。然后,可将该令牌传送给访问控制,由后者对其进行评估,然后运行规则,并向信赖方发出该令牌。
Service Bus 和访问控制
Service Bus 与访问控制之间存在一种特殊的关系,因为每个 Service Bus服务命名空间将与匹配的、带“–sb”后缀的同名访问控制服务命名空间配对。之所以存在这种特殊关系,是因为 Service Bus 和访问控制就是以这样的方式管理它们相互之间的信任关系以及关联的加密机密。
Service Bus 可以与访问控制 V1 及访问控制 V2 联合。所有在 2011 年 9 月版 Service Bus 之前创建的服务命名空间将与访问控制 V1 联合,所有在服务升级之后创建的服务命名空间将与访问控制 V2 联合。本主题仅介绍访问控制 V2,它是访问控制服务的最新版本。
在“-sb”访问控制服务命名空间(可以通过选择 Service Bus 服务命名空间,然后单击功能区上的“访问控制”图标,从 Windows Azure 门户进行浏览)中,是一个紧跟在“信赖方应用”导航后面的“ServiceBus”信赖方定义。信赖方定义有一个映射(使用“http”方案)到匹配的 Service Bus 服务命名空间根的“领域”值,该定义将令牌类型设置为“SWT”,将令牌过期时间设置为 1200 秒。此外,无法通过门户或 API 管理或访问签名密钥。
与“ServiceBus”信赖方定义关联的是“Service Bus 的默认规则组”,其中包含的基本映射允许服务命名空间的“所有者”在服务命名空间上充当超级用户。默认情况下,该规则组包含三项简单规则,这些规则将“所有者”服务标识的输入“nameidentifier”声明映射到 Service Bus 所理解的三个权限声明:用于所有发送操作的“Send”、用于打开侦听程序或接收消息的“Listen”,以及用于观察或管理 Service Bus 租户状态的“Manage”。Service Bus 将忽略发布给它的令牌包含的所有其他声明。“所有者”服务标识是访问控制服务命名空间中的一个常规服务标识。您可以创建更多标识,而且我们建议您这样做。实际上,“所有者”标识的使用应该仅限于执行管理任务。
信赖方定义和作用域
例如,当客户端请求获得授权令牌,以便向位于 https://tenant.servicebus.windows.net/my/test 上的队列发送消息时,令牌请求将包含目标地址的标准化形式,并将其作为所需的目标领域。此“标准化”在所有协议之间直接使用常用的 URI 方案。因此,如果要请求一个令牌,以便与 https://tenant.servicebus.windows.net/my/test 或 sb://tenant.servicebus.windows.net/my/test 上的 Service Bus 实体进行交互,则不妨通过一个使用“http”方案 http://tenant.servicebus.windows.net/foo/bar 的领域 URI 来完成。因此,所有信赖方定义还必须使用领域 URI 的“标准化”URI 方案“http”。
当该请求到达访问控制时,访问控制将通过“最长前缀匹配”将领域 URI 与信赖方定义进行匹配,即选择并运行信赖方(其“领域 URI”地址为请求令牌的地址的最长可用前缀)、信赖方定义及其关联的规则定义。默认“ServiceBus”信赖方定义的作用范围是与之对应的整个 Service Bus 服务命名空间,也就是说,它的与 Service Bus 服务命名空间根地址相对应的领域 URI 是 Service Bus 服务命名空间上所有可能地址的前缀。同样,在此信赖方定义上启用的规则定义将授予整个 Service Bus 服务命名空间的完全访问权限。
例如,为 https://tenant.servicebus.windows.net/my/test 上的队列创建一组有作用域的授权规则时,其方法是通过访问控制门户或访问控制管理 API 创建新的信赖方定义(提供队列地址或该地址的前缀作为新定义的领域 URI)。在门户上,其步骤为:
-
在“信赖方应用”下单击“添加”。
-
输入某个显示名称,例如 MyTest。
-
输入 http://tenant.servicebus.windows.net/my/test 作为作用域的领域 URI。
-
选择“SWT”作为令牌格式。
-
将“加密策略”设置为“无”。
-
将“令牌生存期”设置为 1200 秒。
-
单击“保存”。
最终将创建一个此地址独有的信赖方定义。由于其领域 URI 为内置“ServiceBus”信赖方定义的后缀,因此,该定义将自动继承正确的签名密钥,使得 Service Bus 信任基于新定义发布的令牌。不过,由于新的信赖方定义没有关联的规则,因此到现在为止,任何人都无法访问队列,“所有者”也不例外,因为即使信赖方定义形成了层次结构,它们之间也没有自动隐式继承规则。
创建新定义后,访问控制门户的“规则组”部分将显示“<displayname> 的默认规则组”。默认情况下,此新组为空。若要允许访问队列,需要向该组添加规则,这一内容将在下一部分介绍。此外,还可以为信赖方定义启用包含规则的已存在规则组。可以将每个规则组看作是可以在信赖方层次结构的任何位置启用的独立访问控制列表。例如,若要启用文件系统之类的继承来继承 Service Bus 服务命名空间根的默认规则,只需在信赖方定义上启用相应的“ServiceBus 的默认规则组”及任何其他规则组即可,即需要在门户上选中信赖方定义的“规则组”部分中的右方框。如果需要将一组常用访问规则应用于大量资源,例如,将常用规则应用于一组并行资源(如 http://tenant.servicebus.windows.net/my/test 和 http://tenant.servicebus.windows.net/my/zoo 上的同级队列),则还可将信赖方定义作用于共享服务命名空间分支,如 http://tenant.servicebus.windows.net/my。
在其他情况下,方案可能需要以不同方式管理同一 Service Bus 实体各方面的访问控制,如向主题的不同订阅授予不同的权限。在这些情况下,可以创建一个作用域为特定订阅名称(如 http://tenant.servicebus.windows.net/my/test/subscriptions/sub1/)的信赖方定义,并由该定义保存仅应用于特定已命名订阅的规则。
定义规则
规则在规则组中定义,并通常会将输入声明映射到输出声明。组中的所有规则将生成一个组合结果,因此,如果给定的输入声明集有三项匹配的规则,这三项规则可以生成三个不同的输出声明,则发布的授权令牌将包含所有三个声明。对于 Service Bus,这三个权限声明是:用于所有发送操作的“Send”、用于打开侦听程序或接收消息的“Listen”,以及用于观察或管理 Service Bus 租户状态的“Manage”。准确地说,“Send”、“Listen”和“Manage”为声明类型“net.windows.servicebus.action”的允许值。为 Service Bus 创建规则需要将输入声明(如服务标识的 nameidentifier)映射到所需权限声明。因此,若要授予服务标识“contoso”在队列上进行“Send”的权限,需要在规则定义中将颁发者的 nameidentifier 声明以及值“contoso”映射到值为“Send”、类型为“net.windows.servicebus.action”的自定义输出声明。向服务标识授予所有三个权限声明需要三个不同的规则。仅提供三个权限声明的目的,是为了降低规则定义的复杂程度。下表显示了如何将权限声明映射到 Service Bus 实体上的具体操作中:
| 操作 | 所需声明 | 声明作用域 |
|---|---|---|
|
服务注册表 |
|
|
|
枚举隐私策略 |
管理 |
任何服务命名空间地址 |
|
中继 |
|
|
|
在服务命名空间上开始侦听 |
侦听 |
任何服务命名空间地址 |
|
向服务命名空间上的侦听程序发送消息 |
发送 |
任何服务命名空间地址 |
|
队列 |
|
|
|
创建队列 |
管理 |
任何服务命名空间地址 |
|
删除队列 |
管理 |
任何有效的队列地址 |
|
枚举队列 |
管理 |
/$Resources/Queues |
|
获取队列描述 |
管理、侦听或发送 |
任何有效的队列地址 |
|
发送到队列 |
发送 |
任何有效的队列地址 |
|
接收来自队列的消息 |
侦听 |
任何有效的队列地址 |
|
在扫视-锁定模式下接收消息后放弃或完成消息 |
侦听 |
任何有效的队列地址 |
|
推迟消息以便稍后检索 |
侦听 |
任何有效的队列地址 |
|
使消息成为死信 |
侦听 |
任何有效的队列地址 |
|
获取与消息队列会话相关联的状态 |
侦听 |
任何有效的队列地址 |
|
设置与消息队列会话相关联的状态 |
侦听 |
任何有效的队列地址 |
|
主题 |
|
|
|
创建主题 |
管理 |
任何服务命名空间地址 |
|
删除主题 |
管理 |
任何有效的主题地址 |
|
枚举主题 |
管理 |
/$Resources/Topics |
|
获取主题描述 |
管理或发送 |
任何有效的主题地址 |
|
发送到主题 |
发送 |
任何有效的主题地址 |
|
订阅 |
|
|
|
创建订阅 |
管理 |
任何服务命名空间地址 |
|
删除订阅 |
管理 |
../myTopic/Subscriptions/mySubscription |
|
枚举订阅 |
管理 |
../myTopic/Subscriptions |
|
获取订阅描述 |
管理或侦听 |
../myTopic/Subscriptions/mySubscription |
|
在扫视-锁定模式下接收消息后放弃或完成消息 |
侦听 |
../myTopic/Subscriptions/mySubscription |
|
推迟消息以便稍后检索 |
侦听 |
../myTopic/Subscriptions/mySubscription |
|
使消息成为死信 |
侦听 |
../myTopic/Subscriptions/mySubscription |
|
获取与主题会话相关联的状态 |
侦听 |
../myTopic/Subscriptions/mySubscription |
|
设置与主题会话相关联的状态 |
侦听 |
../myTopic/Subscriptions/mySubscription |
|
规则 |
|
|
|
创建规则 |
管理 |
../myTopic/Subscriptions/mySubscription |
|
删除规则 |
管理 |
../myTopic/Subscriptions/mySubscription |
|
枚举规则 |
管理或侦听 |
../myTopic/Subscriptions/mySubscription/Rules |
使用令牌提供程序
令牌提供程序是Service Bus .NET 托管 API 中的一个泛型构造,可用于将某种形式的凭据转换为由访问控制服务发布的授权令牌。然后,可将其传递到Service Bus 以执行所需的操作。TokenProvider 是一个包含三个具体实现的抽象基类,通过大多数基本方案的工厂方法可以访问这些实施:
-
共享机密 – 允许在服务标识(已在访问控制的 Service Bus 服务命名空间“-sb”好友命名空间中定义)以及与该标识关联的共享密钥的基础上获取令牌。在创建服务命名空间时创建的预配服务标识称为“所有者”,其共享机密可通过管理门户进行访问。
-
简单 Web 令牌 (SWT) – 允许在此前获得的 SWT 令牌(已通过令牌提供程序传递到访问控制)的基础上获取令牌。令牌将使用 WS 信任/WS 联合身份验证 RST/RSTR 请求以二进制令牌的形式传递到访问控制。有关如何配置 WS 联合身份验提供者的信息,请参阅访问控制文档。
-
SAML – 允许在此前获得的 SAML 令牌(已通过令牌提供程序传递到访问控制)的基础上获取令牌。令牌将使用 WS 信任/WS 联合身份验证 RST/RSTR 请求传递到访问控制。有关如何配置 WS 联合身份验提供者的信息,请参阅访问控制文档。
Service Bus MessagingFactory、NamespaceManager 和 TransportClientEndpointBehavior API 接受 TokenProvider 实例。在需要令牌的情况下,尤其是在现有令牌的到期时间(默认为 1200 秒)已过而需要获得新令牌以维持长效连接的情况下,将调用令牌提供程序。需要用户交互的联合身份验证方案确实需要实现自定义的令牌提供程序。
例如,如果自定义令牌提供程序要启用特定 Facebook 用户向特定队列发送消息,则需要通过访问控制显示该用户,同时使用相应的 Facebook UI 建立 Facebook 标识,通过访问控制进行重定向将 Facebook 令牌转换为适用于 Service Bus 的访问控制令牌,然后在请求重定向到本地应用程序时提取该访问控制令牌。Service Bus Codeplex 站点将提供一个适用于自定义的、不断扩展的令牌提供程序示例集合。