One of the key capabilities of the IBM Application Gateway (IAG) is being able to apply authorization policies to requests, controlling who is able to access your protected resources.
The authorization policy is made up of a collection of rules. There are a couple of main elements which are important to understand when constructing the authorization policy:
A rule will be evaluated for matching resources only. There are three elements which are used to match a resource:
|Paths||A rule is matched on the path, as found in the request line of the resource request. Each path may contain the '*' or '?' pattern matching characters.|
|Host||A rule can be matched on the host header found in the resource request. If no host header is specified the rule will match all hosts.|
|Methods||A rule can be matched on one or more HTTP methods from the resource request. If no method is specified the rule will match any method.|
In other words, a rule will be considered a match for a resource request if the path, host header and HTTP method matches the request.
A rule is a logical expression which is used to compare the user attributes, as obtained during the authentication processing, against required values.
The following operators can be used when constructing the rule:
|and||Performs a logical AND of the two operands.||
|or||Performs a logical OR of the two operands.||
|not||Performs a logical NOT of the operand.||
|any||The operation must match at least one of the values of the specified user attribute.||
|all||The operation must match all of the values of the specified user attribute.||
|=||The value of the left operand must equal the value of the right operand.||
|!=||The value of the left operand must not equal the value of the right operand.||
|matches||The value of the left operand must match the regular expression specified in the right operand.||
|>||The value of the left operand must be greater than the value of the right operand.||
|>=||The value of the left operand must be greater than or equal to the value of the right operand.||
|<||The value of the left operand must be less than the value of the right operand.||
|<=||The value of the left operand must be less than or equal to the value of the right operand.||
|exists||The user attribute, specified by the left operand, must exist.||
A 'simple' rule usually consists of three elements:
- A user attribute name;
- A relational operator;
- A literal value (literal values are always enclosed in double or single quotes).
name = "alice"
A 'complex' rule consists of a number of 'simple' rules, separated by logical operators. Parenthesis should be used to control the evaluation order of the simple rules.
(not ((name = "scott") or (name = "alice"))) and (any groupIds = "admin")
The above rule will evaluate to true if the user is not 'scott' or 'alice', and they are a member of the 'admin' group.
The following pre-defined rules can also be used:
|anyuser||Matches any user, whether they are authenticated or not.|
|anyauth||Matches any authenticated user.|
A rule will evaluate to either true or false. If a rule evaluates to 'true' the configured rule action will then be used to determine the overall authorization decision. The possible actions include:
|permit||The user is granted access to the resource.|
|deny||The user is denied access to the resource. If the user is not yet authenticated they will be redirected to the identity provider for authentication. If the user is already authenticated they will be denied access to the resource and a 403 Forbidden response will be returned.|
|obligate||The user is redirected to the identity provider for authentication or re-authentication, using the parameters defined in the obligation.|
If no action is specified the default is 'permit'.
If the rule action is 'obligate', the obligation node defines additional parameters about the authentication or re-authentication that should take place. Depending on the configured identity source, the format of the obligation data can look different.
For OIDC scenarios, the obligation data is a map of string values. The parameter and values are appended to the authorization request when authentication or re-authentication takes place. See Authentication Requirements for further information.
obligation: oidc: <parameter>: <value>
The authorization policy comprises of an ordered sequence of authorization rules. When making an authorization decision each rule will be examined in turn. If the rule matches the request it will be evaluated. If the rule evaluates to 'true' the result of the authorization decision is determined from the corresponding rule action. Each rule will be examined in order until a matching rule evaluates to 'true'. The default rule, which will be used if the end of the list of configured rules is reached, is to grant access to any authenticated user.
The following diagram illustrates the logic which is used:
An example authorization policy is defined below:
policies: authorization: # Alice has left the team and is no longer allowed # access to any data. - name: alice paths: - /* rule: "(user = 'alice')" action: deny # Allow unauthenticated access to /public. - name: unauth paths: - /public/* methods: - GET rule: anyuser action: permit # Allow any authenticated user to retrieve their # account information. - name: account paths: - /account/* methods: - GET rule: anyauth action: permit # Updates to account information can only be completed # after the user has completed stronger authentication. - name: account_update paths: - /account/* methods: - POST rule: "(acr = 'urn:ibm:security:policy:id:2')" action: permit # We can use and obligation to trigger a re-authentication # to prompt the client to complete strong authentication. - name: account_update_obligation paths: - /account/* methods: - POST rule: "(acr != 'urn:ibm:security:policy:id:2')" action: obligate obligation: oidc: acr_values: urn:ibm:security:policy:id:2 # In order to be able to manage accounts you must be # an administrator. - name: manage paths: - /account/* rule: (any groupIds = "admin") action: permit # We want to deny access to every other resource. - name: deny_all paths: - /* rule: anyuser action: deny
The authorization rules are configured as authorization polices on the server. Information on how to define the authorization policy is available in the Defining the Authorization Policy page.
It is absolutely critical that the authorization policy is authored correctly for the environment. This can potentially be a complex task, and as such it is relatively easy to make mistakes.
There are two mechanisms which can be used to help validate and debug the authorization policy:
The in-built credential viewer application can be used to display the user attributes contained within an active session. This is useful in determining which attributes are available when defining the authorization rules. For information on enabling the in-built credential viewer application refer to the Cred Viewer YAML reference page.
Tracing can be enabled within the authorization logic to help debug the actual rules that have been created, and to also debug the logic which was followed to reach a decision. The trace component name for the authorization logic is: 'iag.azn'.
The configured trace level will control the amount of trace information generated. As a general guide:
|3||Rule parsing errors are displayed.|
|7||The authorization decision itself is traced.|
|8||The authorization decision, along with some of the decision logic is traced.|
|9||Full tracing, which includes all of the decision logic.|
Further information on managing tracing within IAG is available in the Enabling Tracing page.