Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Updated for general readability and to reflect significant changes to 0.16 C++ broker ACL handling.

v2 ACL file format for brokers

This new ACL implementation The v2 ACL file format has been designed for implementation and interoperability on all Qpid brokers. It is currently supported in the following brokers:

Broker

Version

C++

M4 onward

Java

M5 onward

This document is updated for release 0.16.

Contents

Table of Contents
minLevel2

Anchor
specification
specification

Specification

...

Comments

  • A line starting with the character '#' will be character is considered a comment , and are ignored.Since the '#' char (and and is ignored.
  • Embedded comments and trailing comments are not allowed.
    • The '#' character is commonly
    others that are commonly used for comments) are commonly
    • found in routing keys and other AMQP literals
    , it is simpler (for now) to hold off on allowing trailing comments (ie comments in which everything following a '#' is considered a comment). This could be reviewed later once the rest of the format is finalized.
    • and occur naturally in ACL rule specifications.
    • By disallowing embedded and trailing comments there is less confusion in writing ACL rules that work correctly.

White Space

  • Blank lines Empty lines ("") and lines that contain only whitespace (any combination of ' ', '\f', '\n', '\r', '\t', '\v') are ignored.
  • All tokens are case sensitive. "name1" != "Name1" and "create" != "CREATE".
  • Group lists may be extended to the following line by terminating the line with the '\' character. However, this may only occur after the group name or any of the names following the group name. Empty extension lines (ie just a '\' character) are not permitted. Code Block # Examples of extending group lists using a trailing '\' character group group1 name1 name2 \ name3 name4 \ name5 group group2 \ group1 \ name6 # The following are illegal: # '\' must be after group name group
  • Additional whitespace between and after tokens is ignored.
  • Group and acl definition lines must start with "group" or "acl" respectively and with no preceding whitespace.

Character Set

  • ACL files use are constrained to 7-bit ASCII characters.
  • Group names may contain only
    • a-z
    • A-Z
    • 0-9
    • '-' hyphen
    • '_' underscore
  • Individual user names may contain only
    • a-z
    • A-Z
    • 0-9
    • '-' hyphen
    • '_' underscore
    • '.' period
    • '@' ampersand
    • '/' slash

Case Sensitivity

  • All tokens are case sensitive.
  • "name1" is not equal to "Name1"
  • "create" is not equal to "CREATE".

Line Continuation

  • Group name lists may be extended to the following line by terminating the current line with the '\' character. No other ACL file lines may be continued.
  • Group specification lines may be continued only after the group name or any of the names following the group name. See the example below.
  • Lines consisting solely of a '\' continuation character are not permitted.
  • The '\' continuation character is recognized only if it is the last character in the line. Any characters after the '\' are not permitted.
Code Block

# Examples of extending group lists using a trailing '\' character

group group1 name1 name2 \
      

...

 

...

 

...

 

...

 

...

 

...

 

...

 

...

name3 

...

name4 \
             name5

group group2 \
             group1 \
             

...

name6

# The following are illegal:

# '\' must be after group name
group \
      group3 name7 name8

# No empty extension lines
group group4 name9 \
                   \
             name10

Line Length

  • ACL file lines are limited to 1024 characters.

The all keyword

  • The keyword "all" is reserved and may be used in ACL rules to match all individuals and groups, all actions, or all objects.
    • acl allow all all
    • acl deny all all
    • acl deny user1 all
    • acl allow fred@QPID create all

ACL File Syntax

Code Block

user = username[/domain[@realm]]
user-list = user1 user2 user3 ...
group-name-list = group1 group2 group3 ...

group <group-name> = [user-list] [group-name-list]

permission = [allow|allow-log|deny|deny-log]
action = [consume|publish|create|access|bind|unbind|delete|purge|update]
object = [virtualhost|queue|exchange|broker|link|route|method]
property = [name|durable|owner|routingkey|passive|autodelete|exclusive|type|alternate|queuename|
            policytype|schemapackage|schemaclass|
            queuemaxsizelowerlimit|queuemaxsizeupperlimit|
            queuemaxcountlowerlimit|queuemaxcountupperlimit]

acl permission {<group-name>|<user-name>|"all"} {action|"all"} [object|"all" [property=<property-value>]]
  • ACL rules must have the following tokens in order on a single line:
    • The string literal "acl"
    • The permission
    • The name of a single group or of an individual, or the keyword "all"
    • The name of an action, or the keyword "all"
    • Optionally, a single object name, or the keyword "all"
      • If the object is present, then optionally one or more property name-value pairs in the form 'property=value'.

File Processing Overview

  • ACL files are processed line by line from the top of the file down.
  • Group membership must be established before the group name is used in an ACL rule.
Deny Mode vs. Allow Mode
  • By default ACL files are in 'Deny Mode' and deny all actions by all users. That is, there is an implicit "acl deny all all" rule appended to the ACL rule list. In 'Deny Mode' any action by any actor is denied unless some other rule in the ACL file explicitly allows it.
  • Administrators may change an ACL file to 'Allow Mode' by ending the ACL file with "acl allow all all". When this rule is present at then end of the ACL file then any action by any actor is allowed unless some other rule in the ACL file explictly denys it.
  • C++ Brokers prior to release 0.16 had an optimization based on the Allow Mode or Deny Mode.
    • In a Deny Mode ACL file all 'deny' or 'deny-log' rules are discarded.
    • Similarly in an Allow Mode ACL file all 'allow' or 'allow-log' rules are discarded.
    • This characteristic made specification of certain ACL rules difficult and confusing.
  • C++ Brokers after release 0.16 do not optimize the rules based on Allow Mode or Deny Mode.
    • All rules are kept and processed in the order specified my the ACL file.
    • Allow rules may be mixed with Deny rules and if a rule is matched then an allow or deny decision is rendered.
Code Block

# Example of C++ Broker Allow Mode processing behavior

group admins bob@QPID joe@QPID
acl allow bob@QPID create queue
acl deny  admins   create queue
acl allow all      all

# Prior to release 0.16 bob is denied permission to create a queue because the
# 'allow bob@QPID create queue' rule in an Allow Mode file is discarded.
# Since release 0.16 bob is allowed permission to create a queue because no
# rules in the file are discarded and the first allow rule controls the decision.

Rule Processing Details

  • Rules are interpreted from the top of the file down until a matching rule is obtained. The matching rule then controls the allow or deny decision.

Rule Matching Details

  • The minimum matching criteria for all ACL rules are:
    • An actor (individually named or group member)
    • An action
    • An object
  • If a rule does not match the minimum criteria then that rule does not control the ACL decision.
  • ACL rules optionally specify object names and property values:
    • If an object is named and/or property values are specified in an ACL rule then all of them must match to cause the rule to match.
Code Block

# Example of rule matching
#
# Using this ACL file content:

(1)  acl deny bob create exchange name=test durable=true passive=true
(2)  acl deny bob create exchange name=myEx type=direct
(3)  acl allow all all

#
# Lookup 1. id:bob action:create objectType:exchange name=test {durable=false passive=false type=direct alternate=}
#
# ACL Match Processing:
#  1. Rule 1 passes minimum criteria with user bob, action create, and object exchange.
#  2. Rule 1 matches name=test.
#  3. Rule 1 does not match the rule's durable=false with the requested lookup of durable=true.
#  4. Rule 1 does not control the decision and processing continues to Rule 2.
#  5. Rule 2 passes minimum criteria with user bob, action create, and object exchange.
#  6. Rule 2 does not match the rule's name=myEx with the requested lookup of name=test.
#  7. Rule 2 does not control the decision and processing continues to Rule 3.
#  8. Rule 3 matches everything and the decision is 'allow'.
#
# Lookup 2. id:bob action:create objectType:exchange name=myEx {durable=true passive=true type=direct alternate=}
#
# ACL Match Processing:
#  1. Rule 1 passes minimum criteria with user bob, action create, and object exchange.
#  6. Rule 1 does not match the rule's name=test with the requested lookup of name=myEx.
#  4. Rule 1 does not control the decision and processing continues to Rule 2.
#  5. Rule 2 passes minimum criteria with user bob, action create, and object exchange.
#  2. Rule 2 matches name=myEx.
#  3. Rule 2 matches the rule's type=direct with the requested lookup of type=direct.
#  8. Rule 2 matches everything and the decision is 'deny'.
#
  • C++ Broker release 0.16 introduces new rule matching criteria.
    • Certain rule properties are introduced that constrain settings from exceeding ACL minimums or maximums.
    • When specified in an ACL allow rule these properties do not affect that rule's match determination. Rather, when the constraint is exceeded then the allow rule which is otherwise matched is converted into a deny rule.
    • The new rule properties have no effect in deny rules.
    • The new rule properties are:
      • queuemaxsizelowerlimit
      • queuemaxsizeupperlimit (alias: maxqueuesize)
      • queuemaxcountlowerlimit
      • queuemaxcountupperlimit (alias: maxqueuecount)
Code Block

# Example of ACL specifying queue size constraints
# Note: for legibility this acl line has been split into multiple lines.

acl allow bob@QPID create queue name=q6 queuemaxsizelowerlimit=50 
                                        queuemaxsizeupperlimit=100 
                                        queuemaxcountlowerlimit=200 
                                        queuemaxcountupperlimit=300

#
# These limits come into play when a queue is created as illustrated here:

            queue_options = {}
            queue_options["qpid.max_count"] = 101
            queue_options["qpid.max_size"] = 100
            session.queue_declare(queue="q6", arguments=queue_options)

#
# When the ACL rule is processed the actor, action, object, and object name all match
# and so this allow rule matches for the allow or deny decision. However, the ACL rule
# is further constrained to limit 50 <= max_size <= 100 and 200 <= max_count <= 300.
# Since the queue_option max_count is 101 then the size limit is violated and the
# allow rule is returned with a deny decision.

Validation

Note: In the 0.16 C++ Broker only the following validation is performed on ACL rule files:

  • Files are correctly formatted with respect to character sets, white space, continuation, and line length.
  • Permissions, Actions and Objects are correctly named.
  • Sufficient tokens are presented for each ACL rule.
  • Any validation error is fatal and the broker is shut down.
  • Every line in an ACL file is validated before the broker is shut down due to a validation failure

...

  • The string literal "acl";
  • The permission;
  • The name of a single group or individual or the keyword "all";
  • The name of an action or the keyword "all";
  • Optionally, a single object name or the keyword "all";
  • If the object is present, then optionally one or more property name-value pair(s) (in the form property=value).
Code Block

user = username[/domain[@realm]]
user-list = user1 user2 user3 ...
group-name-list = group1 group2 group3 ...

group <group-name> = [user-list] [group-name-list]


permission = [allow|allow-log|deny|deny-log]
action = [consume|publish|create|access|bind|unbind|delete|purge|update]
object = [virtualhost|queue|exchange|broker|link|route|method]
property = [name|durable|owner|routingkey|passive|autodelete|exclusive|type|alternate|queuename|schemapackage|schemaclass]

acl permission {<group-name>|<user-name>|"all"} {action|"all"} [object|"all"] [property=<property-value>]

Validation

The new ACL file format needs to perform validation on the acl rules. The validation should be performed depending on the set value:

strict-acl-validation=none
The default setting should be 'warn'

On validation of this acl the following checks would be expected:

Code Block

acl allow client publish routingkey=exampleQueue exchange=amq.direct
  1. The If the user 'client' cannot be found, if the authentication mechanism cannot be queried then a 'user' value should be added to the file.
  2. There is an exchange called 'amq.direct'
  3. There is a queue bound to 'exampleQueue' on 'amq.direct'

Each of these checks that fail will result in a log statement being generated.

...

  • .

Example file:

Code Block

# Some groups
group admin ted@QPID martin@QPID
group user-consume martin@QPID ted@QPID
group group2 kim@QPID user-consume rob@QPID
group publisher group2 \
                tom@QPID andrew@QPID debbie@QPID

# Some rules
acl allow carlt@QPID create exchange name=carl.*
acl deny rob@QPID create queue
acl allow guest@QPID bind exchange name=amq.topic routingkey=stocks.ibm.#  owner=self
acl allow user-consume create queue name=tmp.*

acl allow publisher publish all durable=false
acl allow publisher create queue name=RequestQueue
acl allow consumer consume queue durable=true
acl allow fred@QPID create all
acl allow bob@QPID all queue
acl allow admin all
acl deny kim@QPID all
acl allow all consume queue owner=self
acl allow all bind exchange owner=self

# Last (default) rule
acl deny all all

...

Mapping of ACL traps to action and type

  • The C++ broker maps the ACL traps in the follow way for AMQP 0-10

...

  • .
  • The Java broker currently only performs ACLs on the AMQP connection not on management functions

...

  • .
  • This table also shows which property values are allowed to be specified for each Object-Action pair.

Object

Action

Properties

Trap C++

Trap Java

Exchange

Create

name type alternate passive durable

ExchangeHandlerImpl::declare

ExchangeDeclareHandler

Exchange

Delete

name

ExchangeHandlerImpl::delete

ExchangeDeleteHandler

Exchange

Access

name

ExchangeHandlerImpl::query

Exchange

Bind

name routingkey queuename owner

ExchangeHandlerImpl::bind

QueueBindHandler

Exchange

Unbind

name routingkey

ExchangeHandlerImpl::unbind

ExchangeUnbindHandler

Exchange

Access

name queuename routingkey

ExchangeHandlerImpl::bound

Exchange

Publish

name routingKey

SemanticState::route

BasicPublishMethodHandler

Queue

Access

name

QueueHandlerImpl::query

Queue

Create

name alternate passive durable exclusive autodelete policytype queuemaxsizelowerlimit queuemaxsizeupperlimit queuemaxcountlowerlimit queuemaxcountupperlimit

QueueHandlerImpl::declare

QueueDeclareHandler

Queue

Purge

name

QueueHandlerImpl::purge

QueuePurgeHandler

Queue

Purge

name

Management::Queue::purge

Queue

Delete

name

QueueHandlerImpl::delete

QueueDeleteHandler

Queue

Consume

name (possibly add in future?)

MessageHandlerImpl::subscribe

BasicConsumeMethodHandler
BasicGetMethodHandler

<Object>

Update

 

ManagementProperty::set

<Object>

Access

 

ManagementProperty::read

Link

Create

 

Management::connect

Route

Create

 

Management:: -createFederationRoute-

Route

Delete

 

Management:: -deleteFederationRoute-

Virtualhost

Access

name

TBD

ConnectionOpenMethodHandler

...

The file gets read top down and rule get passed based on the first match. In the following example the first rule is a dead rule. I.e. the unnecessary. The second rule is wider than the first rule . DON'T do this, it will force extra analysis, worst case if the parser does not kill the dead rule you might get a false denyand the same result would be achieved if the first rule was removed.

Code Block
acl allow peter@QPID create queue name=tmp <-- deadunnecessary rule!!
 causes extra work.
acl allow peter@QPID create queue
acl deny all all

By default files end with

Code Block
acl deny all all

the mode of the ACL engine can be swapped to be allow based by putting the following at the end of the file

Code Block
acl allow all all

Note that 'allow' based file will be a LOT faster for message transfer. This is because the AMQP specification does not allow for creating subscribes on publish, so the ACL is executed on every message transfer. Also, ACL 's rules using less fewer properties on publish will in general be faster.

...

In order to get log messages from ACL actions use allow-log and deny-log for example

Code Block
acl allow-log john@QPID all all
acl deny-log guest@QPID all all

...