May
08
2018 Posted by James Gill

DB2 Native REST API – 11 – DB2 RACF Access Control Exit DSNXRXAC

Introduction

Many customers make use of the RACF Access Control sample exit (DSNXRXAC) to pass security control within DB2 to their security teams. This puts access to DB2 objects and resources under the control of RACF (other security products are available) in a set of classes and profiles. The benefits of this approach are:

  • Data security is in the hands of the security team, rather than the DBAs
  • RACF classes can support generic profiles, allowing very efficient development security
  • Security can be put in place before objects are created
  • Security profiles are retained when objects are dropped, reducing the impact of DBA changes

It does make things a little trickier in terms of DBA diagnosis, unless the security team are happy for them to have AUDIT (allows listing of classes and profiles).

There is an extensive manual produced to cover this (V11 and V12), and arguably it warrants a whole sequence of blog posts all on its own, but suffice to say, for our interests from the point of view of the REST API, the challenge is that the IBM supplied RACF classes are defined with upper case resource names (CASE=UPPER). This means that if we are stuck with using them, we can only profile our mixed case REST service names generically – e.g.

  • Service = https://s0w1.zpdt.local:2055/services/GILLJSRV/GetDepartments
  • Package = GILLJSRV.GetDepartments
  • Profile = GILLJSRV.G%%D%%%%%%%%%%

This is not enormously secure, as a large number of services could potentially be covered by this profile.

The other option is to make all of the collections and service names upper case, but this is not generally acceptable either, and makes DB2 look a bit shouty to the architecture team!

In the rest of this blog, we’ll look at how the RACF classes used by the exit all hang together, and what we need to do to create our own mixed case classes and how to use them with DSNXRXAC.

RACF Classes

To use a class in RACF, it needs to be defined in the Class Descriptor Table (CDT). This is defined using:

  • Static CDT:
    • ICHRRCDX module, which contains the IBM supplied classes
    • ICHRRCDE module, which is built by the installation using the ICHERCDE macro
  • Dynamic CDT:
    • Through the CDT RACF class

Changes to the static CDT require an IPL to implement, whereas the dynamic CDT is controlled by the RACF TSO commands RDEFINE / RALTER and SETROPTS RACLIST, and can be made on demand.

The simplest way to review the current state of the CDT is to use the LISTCDT tool. This can be downloaded from IBM:

ftp://public.dhe.ibm.com/eserver/zseries/zos/racf/listcdt/

The main item of interest is the XMIT unload of the LISTCDT load library. To use this, binary download the listcdt.xmitbin item, then binary copy (FTP or IND$FILE) to your z/OS as RECFM=FB, LRECL=80,BLKSIZE=27920. Once there, use the TSO RECEIVE command to restore it – e.g.

TSO RECEIVE INDS(‘GILLJ.LISTCDT.XMITBIN’)

You can run it in batch like this:

The report is quite wide, and contains a lot of information, but the fields that we’re most interested in are:

  • Class name
  • Maximum entity length – i.e. what’s the longest the profile name can be?
  • RACLIST anchor – can we RACLIST it?
  • POSIT VALUE – required when defining a class – more on this below

CASE – as this is the one that’s causing us a problem

The POSIT value identifies a set of options that apply to the class. Classes with the same POSIT number will have the same effective options in place. Similarly, if you update the options on one class, all of the other classes with the same POSIT will be updated as well. The options covered are:

  • The class is active
  • Auditing is active
  • Statistics gathering is active
  • Generic profile checking is active
  • Generic command processing is active
  • Global access checking is active
  • RACLISTing is active

The upshot of all of this is that you need to be really careful how you assign a new class a POSIT number, as there is a danger that you will not get the behaviour you’re looking for if it is already in use elsewhere!

POSIT values are assigned in ranges:

  • 0 – 18                   IBM use
  • 19 – 56                 available for use
  • 57 – 127                IBM use
  • 128 – 527              available for use
  • 528 – 1023            IBM use

In the example used later on in this blog, we used a POSIT value of 201, as this was not in use (verified in LISTCDT output).

RACF Access Control Exit

The DSNXRXAC exit makes use of two sorts of classes:

  • Member classes (prefixed with ‘M’) which have a single profile which covers the resource, e.g.
    • Class MDB2XPK1 with profile DB01.GILLJSRV.GetDepartments.EXECUTE
      Covers execute authority on subsystem DB01 for package GetDepartments in collection GILLJSRV
  • Grouping classes (prefixed with ‘G’) which group several profiles under one name, e.g.
    • Class GDB2XPK1 with name PHPKEXEC with the following profiles (using ADDMEM):
      • GILLJSRV.GetDepartments.EXECUTE
      • GILLJSRV.GetEmployeesByDepartment.EXECUTE

Class names are controlled by values configured in the top of the exit source code (…SDSNSAMP(DSNXRXAC)):

The values shown here are the defaults and use classes defined in the static CDT (IBM supplied). Class names are formed as follows:

&CLASSOPT = 1

Admin: <ssid>ADM<&CHAROPT>
Member classes: M<ssid><TT><&CHAROPT>
Grouping classes: G<ssid><TT><&CHAROPT>

&CLASSOPT = 2

Admin: <&CLASSNMT>ADM<&CHAROPT>
Member classes: M<&CLASSNMT><TT><&CHAROPT>
Grouping classes: G<&CLASSNMT><TT><&CHAROPT>

The value of <TT> determines the type of object being protected. The list of two character type mappings is in the manual (V11 and V12), Chapter 5 Protecting DB2 Objects, DB2 Object Types – see Table 4 (DB2 Object abbreviations).

Note that when &CLASSNMT = ‘DSN’ (i.e. the default value) &CHAROPT is ignored, so whilst the default values are in use, as above, the member package class would be MDSNPK, rather than MDSNPK1.

Most customers find &CLASSOPT = 2 the best way to manage their service as it limits the number of classes (one set shared across all subsystems / data sharing groups), with the separation provided by the profile names (prefixed by subsystem / group name).

Example Mixed Case REST Solution

For the purposes of this blog, we’re just going to focus on the RACF member class for packages (M prefix and PK for the type), as the REST runtime is only interested in the package execute authority.

Our starting point is DB2 for z/OS V11 at RSU 1803, with a few simple REST services defined (see previous blogs):

We are running the standard (i.e. DSNSRXAC) disabled RACF Access Control exit.

We want to:

  • Enable the RACF Access Control exit
  • Coverage should be just the REST services
    • i.e. package execute authority
  • The class used MUST support and work with mixed case profiles
  • Use &CLASSNMT=DB2X, and &CHAROPT=1 – so the class name will be MDB2XPK1

Process

The process we used is as follows:

  1. Define the new class in the dynamic CDT
  2. Modify the sample exit and build it
  3. Restart DB2 to deploy the new exit
  4. Verify operation

Each of these is covered in more detail, below:

Define the New Class – MDB2XPK1

This was done using the TSO RACF commands below:

  1. Define the class in the dynamic CDT class CDT:
    1. RDEFINE CDT (MDB2XPK1) +
      1. CDTINFO(CASE(ASIS) +
        1. DEFAULTUACC(NONE) +
        2. FIRST(ALPHA,NUMERIC,NATIONAL,SPECIAL) +
        3. OTHER(ALPHA,NUMERIC,NATIONAL,SPECIAL) +
        4. MAXLENGTH(100) +
        5. POSIT(201) +
        6. GENERIC(ALLOWED) +
        7. RACLIST(ALLOWED)) +
      2. OWNER(SYS1)
      3. Notes:

        1. This is modelled on the IBM supplied MDSNPK class, but with CASE(ASIS), i.e. mixed case resource names
        2. MAXLENGTH(100) is the same as the IBM supplied MDSNPK
        3. POSIT(201) was selected as an unused value from the LISTCDT report
  1. Refresh the dynamic CDT class:

SETROPTS RACLIST(CDT) REFRESH

  1. Set the options for the new class:

SETROPTS GLOBAL(MDB2XPK1)
SETROPTS GENCMD(MDB2XPK1)
SETROPTS GENERIC(MDB2XPK1)

Modify the Sample Exit and Built It

The source code for the sample exit is delivered in the SDSNSAMP  target library by SMP/E. Take a copy of this (DSNXRXAC) to a separate (working) PDS to support making the required changes:

  1. Copy DSNB10.SDSNSAMP(DSNXRXAC) to GILLJ.SOURCE(DSNXRXAC)
  1. Edit the copy of the sample exit (GILLJ.SOURCE(DSNXRXAC)):
    1. Change the value of &CLASSNMT from ‘DSN’ to ‘DB2X’

 

  1. Create a build job for the exit:
    1. Take a copy of the installation job DSNTIJEX (used to build all of the exits)
      1. SDB00.DB01.DSNTID00.SDSNSAMP(DSNTIJEX) -> GILLJ.SYSTEM.JCL
    1. Edit the copy and make the following changes:
      1. Update ASMPROC SYSIN DD statement to point at the PDS with the modified copy of the exit source code (GILLJ.SOURCE)
      2. After ASMPROC PEND, remove steps JEX0001 (DSN3@SGN) and JEX0002 (DSN3@ATH)
      3. Update step JEX0003 changing the MEM parm to DSNXRXAC
      4. Remove step JEX0004 (DSNACICS)
    1. Submit the job to build the exit into SDSNEXIT

Restart DB2 to Activate the Exit

  1. Stop DB2
    -DB01 STOP DB2
  1. -DB01 STOP DB2
    -DB01 START DB2

This produced the following output:

We forgot to activate the class, and so the exit was unable to find anything to work with and deactivated itself. It’s worth noting that the exit will only work with classes that are available when DB2 starts – activating the class after restart will have no effect until DB2 is stopped and started again. This is probably worth remembering if you are migrating to make full use of this exit.
It is also worth noting that the message detail above mostly appears in the SYSLOG, and not in the MSTR JESMSGLG.

  1. Stop DB2 again and activate class MDB2XPK1
    -DB01 STOP DB2
    TSO CLASSACT(MDB2XPK1)
    TSO RACLIST(MDB2XPK1) REFRESH
  1. Restart DB2
    -DB01 START DB2
    This produced the following output:

The exit is now active and it is working with our new class.

Verify Operation

At the start of this, we have an active RACF class with no profiles, but we do have supporting GRANTs for user ADCDA, so our initial test execution of the service (using CURL) works:

So if we REVOKE EXECUTE authority from ADCDA so that we just have the RACF cover (the profile for which isn’t currently defined), we get SQLCODE = -551, as expected:

Now define the RACF profile to provide execute authority on collection GILLJSRV package GetDepartments (case sensitive), using the TSO commands:

Verify that this has given us the mixed case profile that we were looking for using the RLIST TSO command:

Note that we’ve set UACC(NONE) – i.e. the default is no access to the profile – so now we need to permit user ADCD access:

Because we defined our class as RACLIST allowed, and made it RACLISTed, the addition of the new profile is made available to DB2 by refreshing the RACLISTed class, rather than requiring DB2 to restart to pick up the change.

When we retest ADCD using this mixed case service:

Everything works as expected.

Conclusions

Testing mixed case support in the DB2 for z/OS RACF Access Control Exit has shown that this works well and is able to provide support for mixed case REST service names implemented in DB2 for z/OS.

The flexibility of the RACF solution and the benefits that it provides in terms of role separation (DBA and security admin), as well as the generic profile and grouping support make this an attractive feature of DB2 for z/OS.

 

Access all of James Gill’s Native REST API blogs here.

 

« | »
Have a Question?

Get in touch with our expert team and see how we can help with your IT project, call us on +44(0) 870 2411 550 or use our contact form…