This is an internal documentation. There is a good chance you’re looking for something else. See Disclaimer.
Security¶
Note
This is mostly a direct copy from an old package-info.java
file from the ch.tocco.nice2.security.api
package. Feel free to
rewrite or expand this documentation.
The Policy¶
The policy can be thought of as a table of security rules. Each row denotes one rule. An example:
Selector |
Action |
Permission |
Subject |
Condition |
---|---|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
For each secured action, this table will be processed top-down, resulting in a conclusion: deny or grant. It first assumes deny, then changes to the specified action for each rule where all conditions are met. A rule may be declared final, in which case processing stops if that rule applies, further rules will be ignored.
The selector defines the general type of the object affected by the action. The permission the exact permission, that’s asked for. The currently logged in user is the principal, and finally, there may be some generic condition.
Table Reduction¶
Because the full table for all possible principals and all possible objects may get very big for a full-scale application, this table will be reduced whenever possible. There are two points, where some important facts get known that allow to filter out rules that won’t apply anyway:
After login, the exact principal is known. At this point, a new policy will be generated for that user that doesn’t contain any rules anymore that don’t affect that principal.
When a guard is needed, the exact object is known. At this point, all rules that don’t affect this object will be filtered out using the selector.
Therefore, in practice, the policy for a concrete object will finally be relatively compact.
The Access Control Language (ACL)¶
The define the policy, a language called ACL is introduced. The top-level structural element of this language is the section. A section defines the selector for the following rules, until a new section is started. The section header looks like this:
entityManager(MyEntity):
// the rules
So, each rule starts with the keyword grant
or deny
, optionally followed by a list
of permissions, optionally followed by the keyword to
and a list of subjects (role
name or '&'
+ principal name), optionally followed by the keyword if
and a condition
(or unless
and a condition, which is a shortcut for if not (...)
). It is finally
terminated by a semicolon.
Optionally, a rule may end with and stop
, which declares a rule final. If a final
rule applies, processing of rules stops at this point.
This is the table above written as ACL:
entityManager(myEntity):
grant create
to someGroup, anotherGroup;
deny create
to group3;
entity(myEntity):
grant access(read|write, *)
if principal.key == owner;
deny access(write, *)
to anonymous;
Keywords¶
The following words are ACL keywords: grant
, deny
, include
, to
, if
, unless
,
principal
, null
, true
, false
, or
, and
, not
, role
. Also, the
keyword permission
is currently reserved, but unused.
Selectors and Permissions¶
Selectors and permissions are written very similarily: identifier [(arguments)]
.
The identifier is the one as contributed to the security system:
@Bean
public SecurityDomainContribution infoboxSecurityDomainContribution(MyDomain domain) {
SecurityDomainContribution contribution = new SecurityDomainContribution();
contribution.setName("myDomain");
contribution.setImplementation(domain);
return contribution;
}
@Bean
public PermissionContribution infoboxDisplayPermission() {
PermissionContribution contribution = new PermissionContribution();
contribution.setDomain("myDomain");
contribution.setName("myPermission");
contribution.setId("myPermission");
contribution.setPermissionClass(my.pkg.MyPermission.class);
return contribution;
}
This defines the domain myDomain
as provided by the service MyDomain
, and assigns the
permission myPermission
imlemented by the class my.pkg.MyPermission
to this domain.
The argument list will be mapped to method signatures for domains and constructors for permissions. See the documentation of SecurityDomain#getSelectorFactory() and permissions. See the documentation of Permission for more information.
Method and Constructor Matching¶
- Primitive Types
Numeric types are matched straight-forward. All Java rules apply for Integers and Doubles. Supported primitive types are: Integer, Long, Short, Byte, Double and Boolean, all in their primitive and wrapped version.
- Strings
Strings may be written in three ways:
myString
,'myString'
and"myString"
. The two quoted variants support all Java escapes, the unquoted variant must follow Java’s rules for identifiers. If a string matches a keyword, it must be quoted.
- Enumerations
Enumeration types are written just like strings, however, these Strings are converted: All letters to upper case, ‘-’ will be replaced by ‘_’, i.e
'my-enum-value'
refers to the enumeration valueMY_ENUM_VALUE
.
- Arrays of Enumerations
Arrays of enumerations can be written by separating the enum values with ‘|’. A typical example is read/write access:
read|write
.
- Varargs
If the last argument of a method or constructor is an array, it will be interpreted as Varargs. If no varargs or the wildcard are passed, the method will be called with
null
for the array. Enumeration types are never treated as varargs. For all other types, arrays are only allowed as the last argument.
- Wildcards
Wildcards are written as ‘*’ and result in
null
being passed to the method. They’re allowed both for arrays of enumerations or varargs.
Conditions¶
Conditions are simple boolean critera and logical operations (and, or, not, you know
that stuff). Supported operators are ==
, !=
, <
, <=
, >
, >=
and ~=
.
Identifiers and paths thereof (a.b.c
is a path) will be resolved depending on the
object being checked. For example, in entities, relations and fields will be used.
The special identifier principal
may only occur as the first path element and
refers to the principal of the current security context. The second path element will
be resolved using the Principal’s attributes, except name
(the Principal’s username)
and key
(the Principal’s primary key). All further path elements will be resolved
using the bean introspection.
Date Conditions¶
The keyword now
specifies the current date/time. It’s fields are actually operators
which operate on that object. These can be combined freely, e.g. now.yesterday.date
means yesterday at 0:00.
The following “path elements” (operators) are available:
- date
Keep the date as-is, set the time to 0:00.
- time
Keep the time as-is, set the date to January 1st, 1970
- tomorrow
Plus one day.
- yesterday
Minus one day.
Includes¶
ACL files may include other ACL files. The syntax for this is:
include 'another-resource.acl';
Important: An include
statement will end the current section! This is an error:
entity(*):
grant access(*, *);
include 'another-resource.acl';
deny access(write) to anonymous; // ERROR: No section header