Contents:
The item level security functionality allows restricting access
on selected items at the database and/or dataset level, depending
on the access privileges of a database account.
This allows to enhance the security of existing applications
with no or minimal code changes.
A typical use would be to limit access on items with sensitive
information, such as credit card numbers, social security numbers
or salary figures to those database users that are member of a
dedicated security group, whereas all other users only get to
see empty or masked values when reading the respective item
contents.
The rules for item level access control are configured with dbutil
script commands and stored inside the database catalog.
Item access rules may be configured for selected datasets or for the
whole database or both. Rules at the dataset level take precedence
over rules at the database level.
Item access rules may also either be general or specific to
database security groups. General rules apply to all users. Group
specific rules apply to users which are member of those groups.
Group specific rules take precedence over general rules.
If a user is member of multiple groups for which access rules are
configured, the "most restrictive" access is granted, unless an
"allow" rule overrides this.
Item access rules use a set of keywords to define the desired
access rights: MASKED, NOUPDATE, ALLOWED.
-
The MASKED keyword changes the DBGET behavior to return a modified
copy of the item content to the application; one of several different
functions for "masking" the item content may be specified with the
MASKED keyword, the default is to return an empty field, blanks
for string items and (unsigned) zero for numeric items.
The MASKED keyword also changes the DBUPDATE behavior to silently
ignore the modified value returned by DBGET, if the application
passes the masked value back to the server as part of a subsequent
DBUPDATE call. This is intended to avoid accidental modification
of the data while still allowing update of the item.
For array items this is evaluated for each element separately.
-
The NOUPDATE keyword changes the DBUPDATE behavior to (silently)
discard all changes to the specified item. No error is returned,
the update just keeps the previous item value in the database.
The NOUPDATE option is typically used in conjunction with MASKED.
-
The ALLOWED keyword specifies unrestricted item access for DBGET
and DBUPDATE operations. It is useful for defining access rules
that take precedence over other existing rules (e.g. set specific
rule overriding database-wide rule).
The following "mask functions" are available with MASKED and
string items:
-
cover(x,m,n) keeps the leading m and trailing n characters of the
item contents visible (m >= 0, n >= 0) and replaces each character
in between with character x. The item is considered left-justified
and trailing blanks are ignored.
For example: cover(X,1,2) on 123456 results in 1XXX56
-
part(x,m,n) keeps the leading m and trailing n characters of the
item content visible (m >= 0, n >= 0) and replaces the characters
in between with a sinngle character x. The item is considered
left-justified and trailing blanks are ignored.
For example: part(*,1,2) on 123456 results in 1*56
-
left(x,n) keeps the leading part of the item content. If n is
positive, the n leftmost characters are kept. If n is negative,
all but the trailing n characters are kept. The item is
considered left-justified and trailing blanks are ignored.
For example:
left(*,2) on 123456 results in 12*
left(*,-2) on 123456 results in 1234*
-
right(x,n) keeps the trailing part of the item content. If n is
positive, the n rightmost characters are kept. If n is negative,
all but the leading n characters are kept. The item is
considered left-justified and trailing blanks are ignored.
For example:
right(*,2) on 123456 results in *56
right(*,-2) on 123456 results in *3456
-
set(text) shows the string "text" if the item content is non-blank.
The text is truncated as necessary if it exceeds the item size.
For example:
set(PRESENT) on 123456 results in PRESENT
set(PRESENT) on an empty field results in an empty field
If none of the above functions is specified with the MASKED keyword,
string item contents are changed to blanks, numeric items to zero.
Configuring and using item access rules requires an internal database
catalog table "sysitemproperty" that did not exist in previous versions
of Eloquence. For databases created on older Eloquence versions, it is
necessary to upgrade the catalog tables with the "upgrade database"
command in dbutil before configuring any item access rules is possible.
After upgrading the database catalog tables, such databases may no
longer be fully compatible with older Eloquence versions. Using the
database volume files with an older Eloquence version or transferring
such a database to an older Eloquence version with dbstore/dbrestore
results in the item access rules being "ignored" by the older server
version (and potentially corrupting the item access rules if the
database structure is changed with an older server version).
Furthermore, the old dbdumpcat and dbutil programs may not be able to
work with those databases in all cases.
Please note that there is no "downgrade database" command in dbutil.
All commands below are only valid inside a database context:
DATABASE "example";
The following command upgrades the database catalog for databases
created on older Eloquence versions (see "Compatibility" above):
UPGRADE DATABASE;
The following commands may be used to maintain item access rules:
SET ITEM ACCESS ON ItemName [ IN SetName ]
TO MASKED [ MaskFunction ] [,NOUPDATE] [ FOR GroupList ] ;
SET ITEM ACCESS ON ItemName [ IN SetName ]
TO ALLOWED [,NOUPDATE] [ FOR GroupList ] ;
UNSET ITEM ACCESS ON ItemName [ IN SetName ]
[ FOR { GroupList | ALL } ] ;
Where
- ItemName specifies the item name (optionally enclosed in quotes)
- SetName specifies the set name (optionally enclosed in quotes)
- MaskFunction is one of
- "cover(x,m,n)" with m >=0 and n >= 0 and x = some character (e.g. *)
- "part(x,m,n)" with m >=0 and n >= 0 and x = some character
- "left(x,n)" with x = some character
- "right(x,n)" with x = some character
- "set(text)" with text = some string (e.g. -is set-)
- GroupList is a list of quoted group names, separated by a comma
If a SetName is specified, the item access rule is specific
to this data set. If not specified, it applies as a default
to all data sets that use this item.
Examples:
set item access on salary
to masked, noupdate;
set item access on salary
to allowed for "supervisor";
set item access on salary in payroll-info
to masked, noupdate;
set item access on salary in payroll-info
to allowed for "supervisor";
set item access on "ccard#"
to masked "set(available)", noupdate;
set item access on "ccard#"
to masked "cover(X,0,4)"
for "agents";
set item access on "ccard#"
to allowed
for "billing";
set item access on "ccard#" in customers
to masked "set(available)", noupdate;
set item access on "ccard#" in customers
to "cover(X,0,4)"
for "agents";
set item access on "ccard#" in customers
to allowed
for "billing";
unset item access on zipcode;
unset item access on zipcode for all;
unset item access on zipcode in customers for "group";
The item access rules configured with dbutil script commands are
maintained in the catalog table "sysitemproperty" for the respective
database. They may be reviewed with dbdumpcat as needed (e.g. to
help troubleshooting).
For example:
$ dbdumpcat -t 12 sampledb
-------------------------------------------------------
#12 sysitemproperty (5 entries)
-------------------------------------------------------
|gid |tableid|colid|type|flags |data |
-------------------------------------------------------
|0 |0 |74 |1 |06000000|set(available) |
|3 |0 |74 |1 |02000000|cover(X,0,4) |
|4 |0 |74 |1 |00000000| |
|5 |101 |65 |1 |00000000| |
|6 |101 |65 |1 |02000000| |
-------------------------------------------------------
The catalog tables "sysgroup", "systables" and "syscolumns" contain
additional details on the values of the "gid", "tableid", and "colid"
columns, for example the textual names of the respective entities.
Note that gid=0 denotes access rules not specific to a group and
that tableid=0 denotes access rules not specific to a data set.
Below is an example for using the enhanced item level security.
Consider you have a database containing a sensitive item called
credit-card-no in several datasets and you want to restrict the
access in the following way: members of the billing department
should have full access, members of the "agents" group should
be able to only see the rightmost 4 characters of the item and
also be able change the item to a new value with DBUPDATE. All
other users should only see the word "available", if the item
contains a non-blank value, and should not be able to change it
to a new value with dbupdate.
The following dbutil commands configure the above behavior:
DATABASE "sampledb";
SET ITEM ACCESS ON credit-card-no
TO MASKED "set(available)", NOUPDATE;
SET ITEM ACCESS ON credit-card-no
TO MASKED "cover(*,0,4)" FOR "agents";
SET ITEM ACCESS ON credit-card-no
TO ALLOWED FOR "billing";
The example above assumes that (only) the users of the billing department
are configured as members of the database security group "billing".
Members of the "agents" group are unable to view the unmasked item contents,
but are allowed to change it to a new value with DBUPDATE (with the single
exception that they will not be able to change it to the masked value itself).
To further refine the access rules for a specific data set called "payment-log"
so not even the agents or billing users are able to change the item value with
DBUPDATE a data set specific rule may be used.
The following dbutil commands configure these additional rules:
DATABASE "sampledb";
SET ITEM ACCESS ON credit-card-no IN payment-log
TO MASKED "set(available)", NOUPDATE;
SET ITEM ACCESS ON credit-card-no IN payment-log
TO MASKED "cover(*,0,4)", NOUPDATE FOR "agents";
SET ITEM ACCESS ON credit-card-no IN payment-log
TO ALLOWED, NOUPDATE for "billing";
Please note that the NOUPDATE option only applies to item content changes
performed with a DBUPDATE call. It does not prevent changes resulting from a
sequence of DBDELETE and DBPUT calls.
When preparing to use item level access rules in production,
we recommend to carefully check that your configuration works
as intended and that the applications are compatible with the
access rules.
The following paragraphs discuss a number of potential pitfalls
that you might encounter when implementing item access rules.
By configuring a MASKED rule for an item, you do not only limit
the read access for the users that the rule applies to. You also
change the dbupdate behavior, even if NOUPDATE is not specified.
This is to prevent an application from overwriting an entry with
the masked item value by accident when using a dbupdate after a
dbget that returned masked item contents to the client buffer.
For example, if an access rule is effective for a user in such
a way that the user only gets blanked (or zeroed) item contents
from the database server, then this user will not be able to
change the item value to all blanks (or zeros) with a subsequent
dbupdate.
Note, however, that preventing the accidental write-back of the
masked value into the database ONLY works for the DBUPDATE call.
If your application uses a sequence of DBDELETE and DBPUT calls
to update existing database records, there is no such protection
and the use of MASKED items would silently damage your database
contents. Check your application behavior very carefully before
using MASKED items in productive environments.
When configuring item access rules for specific groups, keep in
mind whether your database has users with membership in multiple
groups or not.
If a user is member of more than one security group, the most
restrictive access rule will apply, unless there is an "allow"
rule that overrides the other access rules.
The following table shows the access rules sorted by precedence:
- ALLOWED
- MASKED,NOUPDATE
- MASKED
- NOUPDATE
Please keep in mind that data set specific rules still override unspecific rules.
If you have multiple competing MASKED (or MASKED,NOUPDATE) rules
for a given user because the user is member of multiple groups,
the associated masking functions (if any are specified) have no
influence on the selection of the effective access rule.
When configuring MASKED rules for items that are used as a key in
master sets and/or search items in detail sets, you should pay special
attention to testing the compatibility of your tools and applications.
While DBGET (mode 7) and DBFIND behave "as usual" when passing the
(unmasked) item value as argument, the application might not be prepared
to handle the masked item value returned by the DBGET (mode 7) or
subsequent DBGET calls (mode 5 or 6) following the DBFIND.
One such example is the FIND command in query3k, which does not work
properly when used with MASKED key or search items as part of the
selection criteria (no matter if the masked or unmasked item values are
specified with the FIND command).
As mentioned in the section "Compatibility", the item level access
rules are stored in a database catalog table "sysitemproperty" that did
not exist in Eloquence versions before B.08.10.
When attempting to use a database using item level access rules with
an older version of the Eloquence database server, the item level access
rules are not applied. When restructuring the database, the item access rules
in the database structure might be corrupted, which could result in unexpected
behavior when restored to a newer server release that supports item access rules.
The incompatible database catalog version might also potentially cause issues
when using tools like dbdumpcat or dbutil that could complain about the
unkown "sysitemproperty" catalog table.
It is recommended to remove all item access rules before restoring a database
to an Eloquence version before B.08.10. These rules are not effective with older
Eloquence database versions and stale access rules are not be a problem when
upgrading to B.08.10 subsequently.
A reasonable efficient supported procedure for downgrading a database to an
older Eloquence version is thus to save the schema with prschema and to binary
export the data with dbbexp. The resulting files are then used on the old Eloquence
version to create the database from the schema file and import each dataset with
dbctl bimport.
|