Hi Adam. You might think that you could use "look up" to compare fields in RACF profiles with an external file. Like using key:$connect.$user.$group in your second newlist.
The point is, a lookup has a key field and only one record is retained for each value of said key. That means, if your MY.DATASET contains several groups for 1 user id, the LOOKUP only remembers the first:
ADAM SYS1
ADAM DEV
ADAM ADAMSGRP
a lookup from ADAM to $GROUP always and only returns SYS1. This is reported in SYSPRINT with a message
CKR1142 00 Duplicate and conflicting entry for key=ADAM in lookup $CONNECT.$USER.$GROUP
Value "SYS1" retained, value "DEV" from record 2 ignored.
Alternative methods, like writing the connect info to an external file, and processing this external file together with MY.DATASET, fail for the same reason. And COMPAREOPT, the method to see where lines are different, is not supported for DEFTYPE newlists.
I had a similar challenge when I built the alert configuration whitelists in C2PCUST members SENSREAD, SENSUPDT etc. In each member, I wanted to support multiple resources for the same user id. I ended up reading the member using a CARLa program and converting the whole member into a single EXCLUDE command. The code to do this conversion is in SCKRSLIB(C2PSDFSE). It is fairly complex.
Also, if we want to single out individual connect entries, it is easier to use RACF_ACCESS as the newlist type, where you can use SELECT to identity one connect, as opposed to SUBSELECT in RACF newlists. The group name is in the PROFILE field and the user id is in ID. The following JCL would do the job, I think.
//JCLLIB JCLLIB ORDER=(CKR231.CKRPARM,
// CKR231.SCKRPROC)
//*
//STEP1 EXEC C2RC
//CKR2PASS DD DISP=(NEW,PASS),DSN=&&CKR2PASS,SPACE=(CYL,(5,5))
//SYSIN DD *
Deftype type=$CONNECT
Alloc type=$CONNECT dsn=MY.DATASET
Define type=$CONNECT $USER(8) as word(record,1)
Define type=$CONNECT $GROUP(8) as word(record,2)
Newlist type=$CONNECT nopage dd=ckr2pass
define once(nd) boolean where $user==$user
sum once count(nd) "define found_connect('Match',5) boolean where",
"((complex<<>>complex,"
sum ")) or (id=" | $user(0) | " profile=(,",
* $group(0) | "," count(nd)
sum once count(nd) "))"
/*
//STEP2 EXEC C2RC
//CKR2PASS DD DISP=(OLD,PASS),DSN=&&CKR2PASS,SPACE=(CYL,(5,5))
//SYSIN DD *
alloc type=RACF active
Deftype type=$CONNECT
Alloc type=$CONNECT dsn=MY.DATASET
Define type=$CONNECT $USER(8) as word(record,1)
Define type=$CONNECT $GROUP(8) as word(record,2)
Newlist type=$CONNECT retain pl=0
summary $USER('User') $GROUP('Group') Count(nondisplay)
newlist type=RACF_ACCESS pl=0
imbed dd=ckr2pass
select class=group exists(id:$connect.$user.$user)
sortlist id(8,"User") profile(8,"Group") found_connect
//
The first step generates a DEFINE command that is evaluated for each RACF_ACCESS entry:
define found_connect('Match',5) boolean where ((complex<<>>complex,
)) or (id=ADAM profile=(,
ADAMGRP,
DEV,
SYS1,
))
Don't think too much about the COMPLEX<<>>COMPLEX clause, it is needed to generate balancing parentheses. An alternative method is described in the Wiki (while it lasts).
------------------------------
Rob van Hoboken
------------------------------