| //// |
| Licensed to the Apache Software Foundation (ASF) under one |
| or more contributor license agreements. See the NOTICE file |
| distributed with this work for additional information |
| regarding copyright ownership. The ASF licenses this file |
| to you under the Apache License, Version 2.0 (the |
| "License"); you may not use this file except in compliance |
| with the License. You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, |
| software distributed under the License is distributed on an |
| "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| KIND, either express or implied. See the License for the |
| specific language governing permissions and limitations |
| under the License |
| //// |
| |
| [id='policy'] |
| = Policy |
| |
| The Policy module is an optional authorization mechanism enforcing |
| user connection restrictions and AMQP resource access control. |
| |
| Policy is assigned when a connection is created. The connection |
| properties *AMQP virtual host*, *authenticated user name*, and *connection |
| remote host* are passed to the policy engine for a connection |
| allow/deny decision. If the connection is allowed then the user is |
| assigned to a group that names a set of AMQP resource limits that are |
| enforced for the lifetime of the connection. |
| |
| [NOTE] |
| ==== |
| Policy limits are applied only to incoming user network connections. |
| Policy limits are not applied to interrouter connections nor are they |
| applied to router connections outbound to waypoints. |
| ==== |
| |
| == Definitions |
| |
| === vhost |
| |
| A _vhost_ is typically the name of the host to which the client AMQP |
| connection is directed. For example, suppose a client application opens |
| connection URL: |
| |
| [options="nowrap"] |
| ---- |
| amqp://bigbroker.example.com:5672/favorite_subject |
| ---- |
| |
| The client will signal virtual host name _bigbroker.example.com_ to |
| the router during AMQP connection startup. Router Policy intercepts |
| the virtual host _bigbroker.example.com_ and applies a vhost policy |
| with that name to the connection. |
| |
| == Policy Features |
| |
| === Total Connection Limit |
| |
| A router may be configured with a total connection limit. This limit |
| controls the maximum number of simultaneous incoming user connections |
| that are allowed at any time. It protects the router from file |
| descriptor resource exhaustion in the face of many incoming client |
| connections. This limit is specified and enforced independently of |
| any other Policy settings. |
| |
| === Vhost Policy |
| |
| Vhost policy defines users and assigns them to user groups. Each |
| user group defines the remote hosts from which the members may connect |
| to the router network, and what resources in the router network the |
| group members are allowed to access. |
| |
| Vhost policy also defines connection count limits to control the |
| number of users that may be simultaneously connected to the vhost. |
| |
| [NOTE] |
| ==== |
| A vhost user may be assigned to one user group only. |
| ==== |
| |
| === Default Vhost |
| |
| A default vhost may be defined. The default vhost policy is used for |
| connections whose vhost is otherwise not defined in the policy database. |
| |
| xref:example2[Example 2] illustrates how the default vhost feature can |
| be used to apply a single vhost policy set of restrictions to any |
| number of vhost connections. |
| |
| === Vhost Patterns |
| |
| Policy vhost names may be interpreted as literal host names or |
| as host name patterns. Vhost name patterns are a convenience |
| for letting a single policy rule cover a wide range of vhosts. |
| |
| Host name patterns consist of a series of host and domain name |
| labels and one or more tokens all concatenated with periods or dots. |
| A token can be one of the following: |
| |
| [options="header"] |
| |==== |
| | Token character | Match rule |
| | asterisk * | matches a single hostname label |
| | hash # | matches zero or more hostname labels |
| |==== |
| |
| Some simple examples show how given policy name patterns match |
| incoming connection vhost names. |
| |
| [options="header"] |
| |==== |
| | Policy pattern | Connection vhost | Policy match |
| | *.example.com | example.com | no |
| | *.example.com | www.example.com | yes |
| | *.example.com | srv2.www.example.com | no |
| | #.example.com | example.com | yes |
| | #.example.com | www.example.com | yes |
| | #.example.com | a.b.c.d.example.com | yes |
| | #.example.com | bighost.com | no |
| | www.*.test.example.com | www.test.example.com | no |
| | www.*.test.example.com | www.a.test.example.com | yes |
| | www.*.test.example.com | www.a.b.c.test.example.com | no |
| | www.#.test.example.com | www.test.example.com | yes |
| | www.#.test.example.com | www.a.test.example.com | yes |
| | www.#.test.example.com | www.a.b.c.test.example.com | yes |
| |==== |
| |
| Pattern matching applies the following precedence rules. |
| |
| [options="header"] |
| |==== |
| | Policy pattern | Precedence |
| | exact match | high |
| | asterisk * | medium |
| | hash # | low |
| |==== |
| |
| Policy vhost name patterns are optimised before they are used |
| in connection vhost name matching. As a result of this |
| optimisation the names stored for pattern match lookups are |
| not necessarily the same as the patterns specified in the |
| vhost policy hostname. The policy agent disallows vhost |
| name patterns that reduce to the same pattern as an existing name |
| pattern. For instance, name pattern _pass:[#.#.#.#.com]_ is reduced to _pass:[#.com]_. |
| Attempts to create a vhost name pattern whose optimised |
| name conflicts with an existing optimised name will be denied. |
| |
| == Policy Schema |
| |
| Policy configuration is specified in two schema objects. |
| |
| [options="nowrap"] |
| ---- |
| policy = { |
| <global settings> |
| } |
| |
| vhost = { |
| id: vhost-name |
| <connection limits> |
| groups: { |
| group-name: { |
| <user group settings> |
| } |
| } |
| } |
| ---- |
| |
| The _policy_ object is a singleton. Multiple _vhost_ objects may be |
| created as needed. |
| |
| === Global Policy |
| |
| [options="header", cols="35,15,50"] |
| |==== |
| | attribute | default | description |
| | maxConnections | 65535 | Global maximum number of concurrent client connections allowed. This limit is always enforced even if no other policy settings have been defined. This limit is applied to all incoming connections regardless of remote host, authenticated user, or targeted vhost. |
| | enableVhostPolicy | false | Enable vhost policy connection denial, and resource limit enforcement. |
| | policyDir | "" | Absolute path to a directory that holds vhost definition .json files. All vhost definitions in all .json files in this directory are processed. |
| | defaultVhost | "$default" | Vhost rule set name to use for connections with a vhost that is otherwise not defined. Default vhost processing may be disabled either by erasing the definition of _defaultVhost_ or by not defining a _vhost_ object named _$default_. |
| | enableVhostNamePatterns | false | Enable vhost name patterns. When false vhost hostnames are treated as literal strings. When true vhost hostnames are treated as match patterns. |
| |==== |
| |
| === Vhost Policy |
| |
| [options="header", cols="35,15,50"] |
| |==== |
| | attribute | default | description |
| | id | | Vhost name must be unique. |
| | maxConnections | 65535 | Maximum number of concurrent client connections allowed. |
| | maxConnectionsPerUser | 65535 | Maximum number of concurrent client connections allowed for any user. |
| | maxConnectionsPerRemoteHost | 65535 | Maximum number of concurrent client connections allowed for any remote host. |
| | allowUnknownUser | false | Allow unknown users who are not members of a defined user group. Unknown users are assigned to the '$default' user group and receive '$default' settings. |
| | groups | | A map where each key is a user group name and the value is a Vhost User Group Settings map. |
| |==== |
| |
| === Vhost User Group Settings Map |
| |
| This object is the data value contained in entries in the policy/groups map. |
| |
| [options="header", cols="35,15,50"] |
| |==== |
| | Section/Attribute | default | description |
| | *Group Membership* | | |
| | users | "" | Comma separated list of authenticated users in this group. |
| | *Connection Restrictions* | | |
| | remoteHosts | "" | List of remote hosts from which the users may connect. List values may be host names, numeric IP addresses, numeric IP address ranges, or the wildcard '*'. An empty list denies all access. |
| | *AMQP Connection Open Limits* | | |
| | maxFrameSize | 2^31-1 | Largest frame that may be sent on this connection. (AMQP Open, max-frame-size) |
| | maxSessions | 65535 | Maximum number of sessions that may be created on this connection. (AMQP Open, channel-max) |
| | *AMQP Session Begin Limits* | | |
| | maxSessionWindow | 2^31-1 |Incoming capacity for new sessions measured in octets. AMQP Begin, incoming-window measured in AMQP frames is calculated by (maxSessionWindow / maxFrameSize). (AMQP Begin, incoming-window) |
| | *AMQP Link Attach* | | |
| | maxMessageSize | 0 | Largest message size supported by links created on this connection. If this field is zero there is no maximum size imposed by the link endpoint. (AMQP Attach, max-message-size) |
| | maxSenders | 2^31-1 | Maximum number of sending links that may be created on this connection. |
| | maxReceivers | 2^31-1 | Maximum number of receiving links that may be created on this connection. |
| | allowDynamicSource | false | This connection is allowed to create receiving links using the Dynamic Link Source feature. |
| | allowAnonymousSender | false | This connection is allowed to create sending links using the Anonymous Sender feature. |
| | allowUserIdProxy | false | This connection is allowed to send messages with a user_id property that differs from the connection's authenticated user id. |
| | sources | "" | List of Source addresses allowed when creating receiving links. This list may be expressed as a CSV string or as a list of strings. An empty list denies all access. |
| | targets | "" | List of Target addresses allowed when creating sending links. This list may be expressed as a CSV string or as a list of strings. An empty list denies all access. |
| | sourcePattern | "" | List of Source address patterns allowed when creating receiving links. This list must be expressed as a CSV string. An empty string denies all access. |
| | targetPattern | "" | List of Target address patterns allowed when creating sending links. This list must be expressed as a CSV string. An empty string denies all access. |
| |==== |
| |
| == Policy Wildcard and User Name Substitution |
| |
| Policy provides several conventions to make writing rules easier. |
| |
| === Remote Host Wildcard |
| |
| Remote host rules may consist of a single asterisk character to |
| specify all hosts. |
| |
| [options="nowrap"] |
| ---- |
| remoteHosts: * |
| ---- |
| |
| The asterisk must stand alone and cannot be appended to a host name |
| or to an IP address fragment. |
| |
| === AMQP Source and Target User Name Substitution |
| |
| The rule definitions for `sources`, `targets`, `sourcePattern`, and |
| `targetPattern` may include the username |
| substitution token |
| |
| [options="nowrap"] |
| ---- |
| ${user} |
| ---- |
| |
| The username substitution token is replaced with the authenticated user name for |
| the connection. Using this token, an administrator may allow access to |
| some resources specific to each user without having to name each user |
| individually. This token is substituted once for the leftmost |
| occurrence in the link name. |
| |
| === AMQP Source and Target Link Name Match Wildcard |
| |
| The rule definitions for `sources` and `targets` may contain a trailing |
| asterisk character. |
| The asterisk is recognized only if it is the last character in the |
| link name. |
| |
| [options="nowrap"] |
| ---- |
| sources: tmp_${user}, temp*, ${user}-home-* |
| ---- |
| |
| The rule definitions for `sourcePattern` and `targetPattern` use the same |
| patterns defined for router addresses and link routes. The patterns consist of one or more |
| tokens separated by a forward slash /. A token can be one of the following: |
| a * character, a # character, or a sequence of characters that do not |
| include /, *, or #. The * token matches any single token. The # token |
| matches zero or more tokens. |
| |
| The user name substitution token may be used in a sourcePattern or in a |
| targetPattern subject to the following restrictions: |
| |
| * The user name substitution token must be the first or last token in the rule clause. |
| * The user name substitution token must stand alone within its delimited field. |
| It may not be concatenated with literal text prefixes or suffixes. |
| |
| For each rule definition multiple patterns may be specified in a comma |
| separated list. |
| |
| [options="nowrap"] |
| ---- |
| sourcePattern: tmp.${user}, temp/#, ${user}.home/* |
| ---- |
| |
| [NOTE] |
| ==== |
| A rule definition may contain `sources` or `sourcePattern` but not both. |
| A rule definition may contain `targets` or `targetPattern` but not both. |
| ==== |
| |
| |
| |
| == Composing Policies |
| |
| This section shows policy examples designed to illustrate some common use cases. |
| |
| === Example 1. User Policy Disabled |
| |
| Policy is disabled when no policy configuation objects are defined. |
| Any number of connections are allowed and all users have |
| access to all AMQP resources in the network. |
| |
| [id='example2'] |
| === Example 2. All Users Have Simple Connection Limits |
| |
| This example shows how to keep users from overwhelming the router with |
| connections. Any user can create up to ten connections and the router |
| will limit the aggregated user connection count to 100 connections |
| total. No other restrictions apply. |
| |
| This example also shows how to use a default vhost policy effectively. |
| Only one vhost policy is defined and all user connections regardless |
| of the requested vhost use that policy. |
| |
| [options="nowrap"] |
| ---- |
| policy { |
| maxConnections: 100 <1> |
| } |
| |
| vhost { |
| name: $default <2> |
| maxConnectionsPerUser: 10 <3> |
| allowUnknownUser: true <4> |
| groups: { |
| $default: { |
| remoteHosts: * <5> |
| sources: * <6> |
| targets: * <6> |
| } |
| } |
| } |
| ---- |
| |
| <1> The global maxConnections limit of 100 is enforced. |
| <2> No normal vhost names are defined; user is assigned to default vhost '$default'. |
| <3> The vhost maxConnectionsPerUser limit of 10 is enforced. |
| <4> No groups are defined to have any users but allowUnknownUser is true so all users are assigned to group $default. |
| <5> The user is allowed to connect from any remote host. |
| <6> The user is allowed to connect to any source or target in the AMQP network. Router system-wide values are used for the other AMQP settings that are unspecified in the vhost rules. |
| |
| === Example 3. Admins Must Connect From Localhost |
| |
| This example shows how an admin group may be created and restricted |
| to accessing a vhost only from localhost. The admin users are allowed |
| to connect to any AMQP resources while normal users are restricted. |
| |
| In this example a user connects to vhost 'example.com'. |
| |
| [options="nowrap"] |
| ---- |
| vhost { |
| name: example.com <1> |
| allowUnknownUser: true <3> |
| groups: { |
| admin: { |
| users: alice, bob <2> |
| remoteHosts: 127.0.0.1, ::1 <4> |
| sources: * <5> |
| targets: * <5> |
| }, |
| $default: { |
| remoteHosts: * <6> |
| sources: news*, sports*, chat* <7> |
| targets: chat* <7> |
| } |
| } |
| } |
| ---- |
| |
| <1> A connection to vhost 'example.com' locates this vhost rule set. |
| <2> If one of users _alice_ or _bob_ is connecting then she or he is assigned to the 'admin' user group. |
| <3> Any other user is not defined by a user group. However, since the _allowUnknownUser_ setting is true then this user is assigned to the '$default' user group. |
| <4> Users in the 'admin' user group must connect from localhost. Connections for an 'admin' user from other hosts on the network are denied. |
| <5> Users in the 'admin' user group are allowed to access any resource offered by the vhost service. |
| <6> Other users are allowed to connect from any host. |
| <7> Other users have source and target name lists that restrict the resources they are allowed to access. |
| |
| === Example 4. Limiting Possible Memory Consumption |
| |
| Policy provides a mechanism to control how much system buffer memory a |
| user connection can potentially consume. The formula for computing |
| buffer memory consumption for each session is |
| set directly by _maxSessionWindow_. |
| |
| By adjusting _maxSessions_, and _maxSessionWindow_ an |
| administrator can prevent a user from consuming too much memory by |
| buffering messages in flight. |
| |
| [NOTE] |
| ==== |
| The settings passed into the AMQP protocol connection and session |
| negotiations. Normal AMQP session flow control limits buffer |
| consumption in due course with no processing cycles required by the |
| router. |
| ==== |
| |
| In this example normal users, the traders, are given smaller buffer |
| allocations while high-capacity, automated data feeds are given a |
| higher buffer allocation. This example skips the details of settings |
| unrelated to buffer allocation. |
| |
| [options="nowrap"] |
| ---- |
| vhost { |
| name: traders.com <1> |
| groups: { |
| traders: { |
| users: trader-1, trader-2, ... <2> |
| maxFrameSize: 10000 <3> |
| maxSessionWindow: 5000000 <3> |
| maxSessions: 1 <4> |
| ... |
| }, |
| feeds: { |
| users: nyse-feed, nasdaq-feed <5> |
| maxFrameSize: 60000 <6> |
| maxSessionWindow: 1200000000 <6> |
| maxSessions: 3 <7> |
| ... |
| } |
| } |
| } |
| ---- |
| |
| <1> These rules are for vhost traders.com. |
| <2> The 'traders' group includes trader-1, trader-2, and any other user defined in the list. |
| <3> _maxFrameSize_ and _maxSessionWindow_ allow for at most 5,000,000 bytes of data to be in flight on each session. |
| <4> Only one session per connection is allowed. |
| <5> In the 'feeds' group two users are defined. |
| <6> _maxFrameSize_ and _maxSessionWindow_ allow for at most 1,200,000,000 bytes of data to be in flight on each session. |
| <7> Up to three sessions per connection are allowed. |
| |
| //// |
| |
| - Should we used signed ints for limits to allow for magic values? |
| |
| - In example 3, alice and bob cannot connect from an outside server and |
| get the $default settings. |
| |
| - Limits are enforced per router, so a vhost policy of maxConnections |
| 10 across 10 routers will allow 100 connections to that vhost. |
| |
| //// |