Dynamic ACL Binding Technical Reference¶
Available Dynamic ACL Types¶
Some of the previously described access modes have a corresponding dynamic ACL type associated with them. Because dynamic ACLs are for data-dependent access, they have more restrictive applicability:
Type | Mode | Implies | Supported Resources |
---|---|---|---|
owner | Write data | insert, update, delete, select | table, column, reference |
insert | Insert data | reference | |
update | Modify data | table, column, reference | |
delete | Delete data | table, column | |
select | View data | table, column |
Table and column-level dynamic ACLs are only applicable to access requests against existing database content. Insertion of new rows can only be granted by a static policy. However, reference-level dynamic ACLs can grant or deny the ability to specify specific foreign keys even during row insertion.
Dynamic data rights do not imply model access. Model access must be determined in a data-independent manner in order to even pose an access request which might be granted by dynamic access rights.
Dynamic ACL Binding Representation¶
The data-dependent ACL bindings are encoded in an "acl_bindings"
sub-resource of the governed resource. This is a hash-map keyed by ACL
binding name. For example, a table resource has a canonical
representation as in the following example:
{
"schema_name": "My Schema",
"table_name": "My Table",
"kind": "table",
"comment": "The purpose of My Table is...",
"annotations": ...,
"column_definitions": ...,
"keys": ...,
"foreign_keys": ...,
"acls": {
"write": ["some/curator/URI"]
},
"acl_bindings": {
"My Binding": {
"types": ["owner"],
"projection": "Managed By",
"projection_type": "acl",
"scope_acl": ["registered-users-group"]
}
}
}
This example has an explicitly set, data-independent curator group who
can modify all rows in the table, while other data-independent ACLs
are inherited from the enclosing schema. A dynamic ACL binding called
My Row Owners
specifies that an ACL stored in the Managed By
column of the table grants owner
dynamic access type for individual
rows. The representation uses an array for the type
so that multiple
access modes can be more easily configured without having to repeat
the same projection many times. This binding has a scoping ACL such
that only members of the registered-users-group
can acquire these
row-level rights.
Inheritence and False Binding¶
As a convenience, columns effectively inherit the ACL bindings of
their table. A column whose "acl_bindings"
document is empty will
permit all operations that the table would allow for each row. To
grant fewer writes, the column-level "acl_bindings"
MUST override
the named bindings inherited from the table.
- Replacement: the column MAY provide a different binding document under the same binding name.
- Suppression: the column MAY provide a literal
false
value instead of a binding document.
Projection Document¶
The "projection"
field of the ACL binding is a document representing
a parsed abstract syntax tree for an attribute query fragment. The
general form of the ACL document is an array of path elements:
[
element,
…,
column]
This corresponds to the serialized query fragment element/.../column
to project ACL content from an implicit base entity context using the
ERMrest /attribute/base
API. The final column MUST be a string
literal naming a column in the effective entity-path context. Each
anterior element MAY use one of the following sub-document
structures:
{ "context":
leftalias,
direction:
fkeyname, "alias":
rightalias}
- Links a new table instance to the existing path via inner join
- The left-hand path context is the table instance named by leftalias or the immediately preceding path context if leftalias is
null
or absent.- The alias
"base"
is implicitly bound to the base table to which this ACL is bound.
- The alias
- The joining condition is determined by the named foreign key constraint fkeyname where one end is tied to the left-hand path context and the other to the newly added table instance.
- The direction of the joining condition is
"inbound"
or"outbound"
and MUST be specified. - The rightalias string literal is bound to the new table instance unless it is
null
or absent.- The alias
"base"
is reserved and cannot be bound as a rightalias.
- The alias
{ "and": [
filter,
…], "negate":
negate}
- A logical conjunction of multiple filter clauses is applied to the query to constrain matching rows.
- The logical result is negated only if negate is
true
. - Each filter clause may be a terminal filter element, conjunction, or disjunction.
{ "or": [
filter,
…], "negate":
negate}
- A logical disjunction of multiple filter clauses is applied to the query to constrain matching rows.
- The logical result is negated only if negate is
true
. - Each filter clause may be a terminal filter element, conjunction, or disjunction.
{ "filter": [
leftalias,
column], "operand":
value, "operator":
operator, "negate":
negate}
- An individual filter element is applied to the query or individual filter clauses participate in a conjunction or disjunction.
- The filter constrains a named column in the table named by leftalias or the current path context if leftalias is
null
. - The operator specifies the constraint operator via one of the valid operator names in the ERMrest REST API.
- The value specifies the constant operand for a binary constraint operator.
- The logical result of the constraint is negated only if negate is
true
.
Many fields may be omitted from the above structures to allow concise projection documents:
- Many
null
or absent values have a default semantics defined:- leftalias is omitted to get a default path-based entity context
- rightalias is omitted if no alias binding is required
- negate is omitted for normal (non-negated) logical decisions
- operator is omitted for regular
"="
equality comparisons - value is omitted when the unary
"::null::"
operator is used
- A few fields are required to be present with a non-null value
- direction and fkeyname MUST always be present in link documents.
- filter MUST always be present in conjunction and disjunction documents.
- column MUST always be present in filter clauses.
- value MUST always be present with each binary operator including the default
"="
- Two syntactic short-hands are allowed for bare column names:
- An single-element projection
[
column]
MAY omit the array and specify just the string literal column. - An unqualified filter column
[ null,
column]
MAY omit the array and specify just the string literal column.
- An single-element projection
Effective ACL Projection Query¶
The projection document assumes that a base
row query similar to /ermrest/catalog/N/attribute/Base/key=X/
will
be formulated by the system, and the projection document describes the
suffix necessary to turn this into an ACL projection query. E.g. in
the dynamic ACL example above,
the projection string "Managed%20By"
names a column Managed By
could be appended to a base-row URL to form a complete ACL projection
query URL:
/ermrest/catalog/N/attribute/My%20Schema:My20Table/key=X/Managed%20By
For more complicated projection documents, there is a similar mechanical transformation which can produce an effective ACL projection query. The supported projection language covers a subset of all possible query URLs.
Projection Types¶
Zero or one rows MAY be returned as the query result. Several projected column types are supported, and more than one projection type is supported. See the following matrix:
Projected Column Type | Supported "projection_type" |
Description |
---|---|---|
text[] |
acl (default) |
The projected array is interpreted as ACL content. |
text |
acl (default) |
The projected text is interpreted as if it were an array containing the single value. |
any | nonnull |
A non-null projected value is interpreted as a true authorization decision. |
The nonnull
projection type is supported by all column types. The
acl
projection type is only supported for the projected column types
shown above.
Scoping ACLs¶
The "scope_acl"
field of each ACL binding document restricts the set
of clients for whom the data-dependent privileges may be granted. If a
client’s attributes do not match this scoping ACL, the effective
permissions for the client are the same as if this ACL binding were
absent from the system.
If "scope_acl"
is omitted during binding creation, a default scoping
ACL value of ["*"]
is configured. This provides backwards
compatibility with older policies used in earlier versions of ERMrest,
where all ACL bindings were evaluated for all clients.