Reports Security IDL Configuration
The new Report Security functionality is primarily configured through the addition of XML attributes to elements in the Fieldmapper XML file, fm_IDL.xml. These new attributes fall into three categories:
-
Field value redaction
-
Core class row restriction
-
Joined class row restriction
These attributes, explained below, are defined within a new XML namespace with the URI http://open-ils.org/spec/opensrf/IDL/reporter/v1/security
, and the common namespace prefix of repsec
. An accompanying XSD is provided to confirm that the locations and values of the attributes, when supplied, do not fall outside their defined scope and that the fm_IDL.xml file remains both well-formed and valid.
Field value redaction
Fields used in the SELECT and ORDER BY SQL clauses can be redacted, either outputting NULL or, optionally, a data type compatible alternate literal value. This is configured through the addition of several XML attributes to the fields to which redaction should be applied.
XML Attributes involved:
-
repsec:redact
andrepsec:redact_default
-
Type: XML Schema boolean
-
Valid values: true or false
-
-
repsec:redact_with
andrepsec:redact_with_default
-
Type: string
-
Valid values: any string literal that can be cast to the same datatype as the field naturally holds
-
-
repsec:redact_skip_function
andrepsec:redact_skip_function_default
-
Type: string
-
Valid values: a fully-qualified database function that returns a boolean value. When the function returns TRUE the redaction of the field will not be performed, otherwise the field will be redacted.
-
-
repsec:redact_skip_function_parameters
andrepsec:redact_skip_function_parameters_default
-
Type: string
-
Valid values: a colon-separated list of parameters to pass to the function named in the
repsec:redact_skip_function
. Each parameter in the list can have one of the following three forms-
The string
$runner
, which will cause the id of the staff user that scheduled the run of the report to be passed to the function. -
The name of a field defined for the class, which will cause the value of that field from the row being tested for field redaction to be passed to the function.
-
Any other string that does not contain a colon (:) character, which will be passed as a dollar-quoted literal to the function. There is no provision for escaping an embedded colon, so special consideration must be given to the string literals that need to be passed into the function, and function may need to perform text manipulation in order to interpret some other string as a colon before operating on the string as passed.
-
-
Field values can be marked for redaction in one of two ways: adding the repsec:redact
attribute with a boolean value of TRUE
directly to the <field>
element of an IDL class; or by adding a repsec:redact_default
attribute of TRUE
to the <fields>
container element for all fields of an IDL class.
Any default set on the <fields>
element by applying a repsec:redact_default
attribute can be overridden on individual <field>
elements by applying the repsec:redact
attribute. If not supplied at all, the default is to NOT redact a field. When generating SQL, redaction settings are only tested at the field level, so each field will have its own "calculated redact attribute" which will be truthy or falsy.
If the "calculated redact attribute" is falsy, all other redaction-related attributes are ignored for the field.
A repsec:redact_skip_function
attribute on the <field>
element, or repsec:redact_skip_function_default
on the <fields>
element, is not required for redaction. The contents of the repsec:redact_skip_function_default
on the <fields>
element is used as the default for all fields that do not carry their own repsec:redact_skip_function
attribute.
The repsec:redact_skip_function_parameters
and repsec:redact_skip_function_parameters_default
values are interpreted as described above, and are used to pass row level, reporting staff, and global contextual information to the function used to decide if the redaction request should be skipped or completed for each marked field.
Finally, all fields are redacted with an SQL NULL
value by default. Supplying a repsec:redact_with
attribute on the <field>
element, or a repsec:redact_with_default
on the <fields>
container element, allows the administrator to supply a non- NULL
replacement value for the database column contents. This value must be a string literal that, when cast, is type-compatible with the column’s natural data type. For instance, an INT column cannot be redacted with a string that does not consist entirely of numeric characters, and once cast to an INT must not over- or under-flow the INT data type’s boundaries.
Two new, stock functions are supplied for use as redact_skip_function
values:
-
evergreen.direct_opt_in_check
-
Purpose: confirm that the patron either has a home library at which the staff has at least one of the permissions from the Required Permission List, or that the patron has opted in at of those libraries.
-
Parameters
-
Patron ID
-
Staff ID
-
Required Permission List
-
-
Returns TRUE if the patron is opt-in visible to the staff member, and FALSE otherwise.
-
Example:
<class id="au" ...> <fields ... repsec:redact_default="true" repsec:redact_skip_function_default="evergreen.direct_opt_in_check" repsec:redact_skip_function_parameters_default="id:$runner:{VIEW_USER}"> <field name="id" ... repsec:redact="false"/> ... </fields> </class>
-
-
evergreen.hint_opt_in_check
-
Purpose: Indirectly confirm that a patron related to a row from another linked table either has a home library at which the staff has at least one of the permissions from the Required Permission List, or that the patron has opted in at of those libraries.
-
Parameters
-
Patron ID
-
Staff ID
-
Required Permission List
-
-
Applicable classes:
-
aua (table:
actor.usr_address
) -
auact (table:
actor.usr_activity
) -
aus (table:
actor.usr_setting
) -
actscecm (table:
actor.stat_cat_entry_usr_map
) -
ateo (table:
action_trigger.event_output
)
-
-
Returns TRUE if the patron is opt-in visible to the staff member, and FALSE otherwise.
-
Example:
<class id="ateo" ...> <fields ... repsec:redact_skip_function_default="evergreen.hint_opt_in_check" repsec:redact_skip_function_parameters_default="ateo:id:$runner:{VIEW_USER}"> <field name="data" ... repsec:redact="true"/> ... </fields> </class>
-
In addition to these new functions, the preexisting stock permission test functions, such as permission.usr_has_perm
and permission.usr_has_work_perm
can be used as redact_skip_function
values. These can be used in this way:
<class id="circ" ...>
<fields ...
repsec:redact_skip_function_default="permission.usr_has_work_perm"
repsec:redact_skip_function_parameters_default="$runner:VIEW_CIRCULATIONS:circ_lib">
<field name="due_date" ... repsec:redact="true"/>
...
</fields>
</class>
Core class row restriction
Two new attributes are available for defining row-level restrictions on the core class of a report template:
-
repsec:restriction_function
-
repsec:restriction_function_parameters
From a configuration perspective, these work in exactly the same way as the repsec:redact_skip_function
and repsec:redact_skip_function_parameters
attributes described above, but are applied to the <class>
element instead of <field>
. Indeed, the two stock functions described above, evergreen.direct_opt_in_check
and evergreen.hint_opt_in_check
, can be used as restriction functions.
When added, these functions generate a WHERE-clause condition that, when TRUE, allow a tested row to be included in the report output, all else being equal. This attribute pair is only applicable to the core class of a report.
For example:
<class id="au" ...
repsec:restriction_function="evergreen.direct_opt_in_check"
repsec:restriction_function_parameters="id:$runner:{VIEW_USER}">
will cause any report that uses the au class as the core source to add a WHERE-clause condition that restricts the inclusion of rows from actor.usr in the final report output by applying the evergreen.direct_opt_in_check
function.
Joined class row restriction
Two additional new attributes are available to define JOIN-clause restrictions that should be applied to each row in order to include the tested table row in the final report output:
-
repsec:projection_function
-
repsec:projection_function_parameters
As with the core class restrictions, the above-described functions can be used for this purpose.
There are two locations for these attributes, and where they are attached defines whether they will be applied to the relevant underlying table when it is on the left side of a join, or the right side.
Put another way, an administrator can decide if restrictions are added when a table is joined from, joined to, or both.
To restrict access to rows of a table being joined to — that is, when a "child relation" is joined into a report — the attributes are applied to the <class>
element. For example:
<class id="actscecm" ...
repsec:projection_function="evergreen.direct_opt_in_check"
repsec:projection_function_parameters="target_usr:$runner:{VIEW_USER}">
will cause any report that links from the au
class to the actscecm
class to restrict the visibility of rows from actscecm
by applying the evergreen.direct_opt_in_check
function.
If the projection function attributes are instead applied to the <link>
element, the restriction will be applied only if the link is followed in the report. This allows a report creator to build a template that does not limit output when it does not link through to tables that should be restricted, while enforcing the desired visibility limits when a joined table should be restricted due to relationship with the linking table, even if that joined table is not itself restricted at the <class>
level. This may be the case when a table contains classifying data that is useful and safe when queried by itself in aggregate, but provides a channel for leaking personal information when joined to, within a report, from another user-centered table.
For a somewhat contrived example, consider this configuration that allows core and linked use of ancihu (Non-cataloged In House Use) while redacting the staff
field based on the VIEW_USER
permission, but restricts rows based on the opt-in visibility of the staff that recorded the in-house use based on the VIEW_CIRC
permission of the report-running staff member if that field is linked in the template:
<class id="ancihu" ...>
...
<field
name="staff"
repsec:redact="true"
repsec:redact_skip_function="evergreen.direct_opt_in_check"
repsec:redact_skip_function_parameters="staff:$runner:{VIEW_USER}"/>
...
<link ...
field="staff"
repsec:projection_function="evergreen.direct_opt_in_check"
repsec:projection_function_parameters="staff:$runner:{VIEW_CIRC}"/>
Any <class> -level restrictions on the linked table, in this case the actor.usr table, will also be enforced.
|
As with Field Value Redaction described above, the existing stock permission functions can be used in all cases for both Core class and Join class row restriction if there is a relevant Org Unit column available.