I recently came across an unusual behaviour of record level security, that I don’t think has been documented before, so I thought I would share it with you.

The situation here is that there is an employee with emplId=”RLS”, and there is a user group configured with record level security which will allow members to view every employee except “RLS”.Now a user which is a member of this group runs a report, and the fetch() method of the report looks like this:

public boolean fetch()
{
    boolean ret = true;
    EmplTable emplTable;
    ;
    //emplTable.recordLevelSecurity(false);

    select firstonly emplTable where emplTable.EmplId == 'RLS';

    return ret;
}

What should be the result - Does the emplTable buffer get populated? Record level security (RLS) isn’t enforced in code, right? Wrong!

Whilst it is true most of the time that RLS isn’t enforced in code, there are a couple of exceptions to that rule: reportRun.fetch(), reportRun.send() and lookup() on form controls.

What happens in the AX kernel is that before the kernel triggers these methods it enables RLS for the whole current X++ stream and then disables it again when the method returns. This has the effect that any code in one of these methods, or any code called out to from one of these methods will have RLS enabled by default.

In the above code if we uncomment the line emplTable.recordLevelSecurity(false) then it will allow the buffer to bypass RLS and get populated successfully.

There are a couple of other noticeable quirks of this – if you print the value used from the emplTable.recordLevelSecurity() method it will show that RLS is not enabled for that buffer – this is because it is actually enabled at a higher level for the whole X++ stream and the buffer’s property isn’t directly set.

The other quirk is that if you enable tracing from the user options -> development tab -> database trace option then you’ll see that RLS is enabled for the calls made to tables in this scenario – this is correct as the tracing picks up whether RLS was actually used when accessing the table in the data layer of the kernel – and it was!

Moving forward in AX2012 this no longer applies – the security framework and reports are re-worked.

--author:  Tariq Bell
--editor: Tariq Bell
--date: 24/05/2011