We were recently asked about the impact on existing RPG programs of the new Row and Column Access Control (RCAC) DB2 support in V7.2. For those who haven't yet heard about RCAC, the simplest explanation is that it allows you to control access to data by row (aka record) and by column (aka field). The column control masks specific data from people who don't need (or shouldn't be able) to see it. Think seeing masked data for salary, credit card numbers, etc. The row control simply omits access to the entire row for unauthorized users, much as a select/omit LF with specific user authorizations could do--only it's probably a bit easier to implement.
We haven't fully thought through some of the implications of row control yet. Clearly there is a difference between "These are all the rows that satisfy your query" and "These are all the rows that satisfy your query that you are allowed to see." But how much that matters and its impact on our application design we need to muse on for a while. There appears to be no feedback to tell you that your result set was constrained so we can foresee some interesting debug problems when a user reports that they only received X rows and your tests show Y but I guess we'll get used to it.
Column control is a little different in that you will receive a value--just not the real one. Because you can supply masking values for columns that have limited access rights, this is not much of a problem in handling character fields. We're all used to seeing things like XXXX-XXX-XXX-1057 for a credit card number in an email or report. Character columns can normally be masked with characters that could never otherwise occur in them, and if you wished, these could be standardized for all columns in the shop. As a result testing for a masked column is not that difficult a feature to add to an existing program that processes the table.
Dealing with numeric columns, however, could be a bit more of a problem. While most columns will have some limit (e.g., this column can never contain zero, another can never exceed 50,000, another can never be negative, etc.) they will rarely fit into a single pattern and so a standardized approach won't be possible. In some cases we might need to mask to a negative value, in others to all 9s, etc.
One thing is for sure, you cannot simply apply RCAC to an existing table and program combination and just "let it fly"--particularly if math is involved on the column in question. You need to think through the impact on your code and possibly make adjustments in the logic to accommodate the new situation.
We find ourselves thinking it would be nice if the database returned a status of some kind with each row/set to indicate that some data is "missing" due to RCAC considerations. After all, we've been increasingly using null capable columns to handle situations where a special value in a column just doesn't work. Having to go back to using special values makes it feel as if we have taken two steps forward and one step back, at least from a programmer's perspective.
While this new support is both important and useful, we do feel that the lack of any standardized way to readily detect "lost" data may be problematic. But maybe we just worry too much. What do you think?
There is also an other problem:
if you still use RPG for native I/O on a file with a MASK, the RPG receive masked data (XXXX-XXX-XXX-1057) and when updating the record, that's this masked value (XXXX-XXX-XXX-1057) that will be put back in the record (even if you use %FIELDS() bif to protect this column, i made a test)
So impossible to use a MASK on a file when there is RPG "around", except using a trigger to correct the column.
Posted by: Christian Massé | July 02, 2014 at 02:05 AM
No i don't think you worry too much. Better too much than too little, especially this kind of stuff. I read about RCAC, which is a necessary feature IMO, but i didn't really delve into it and didn't know about the masking approach. Setting a mask on a column should be done very carefully, thinking about the impact of it and the effect it has when processing data. For example, like you said, when doing calculations. If the credit limit of a client is based on his salary, and the salary is always 999,999,999.99 you may have a huge problem. Masking is a nice and easy way to implement it, without needing to change the software, but only applied very carefully. But it shouldn't be the only option. So yes, i believe there should be an API to explicitly check that a value is not a "real" value but an imaginary one.
Posted by: John Erps | July 02, 2014 at 04:13 AM
Not sure what's going on with %Fields function. However, there is new DB2 support so that the application doesn't have to use the %Fields function to prevent accidental updates with masked values.
A check constraint can be created with the new ON UPDATE clause to prevent masked values from overwriting the card number value.
CONSTRAINT masked_card_check
CHECK( SUBSTR( card_num , 1 , 13 ) <> 'XXXX-XXX-XXX-' )
ON UPDATE VIOLATION PRESERVE card_num
No error is signalled to the application, the masked value in the buffer is ignored and the original card number value is preserved.
Posted by: Kent Milligan | July 02, 2014 at 09:43 AM