SAF Consideration

Beginning with version 5.1.21 a lot of additional checks against a System authorization facility (SAF) can be activated. These SAF support gives for example an RACF administrator on z/OS the possibility to activate different security policies and control a lot of resources used by FLAM.

The complete SAF setup is documented in the corresponding install.txt and can be simply extended on user request. For z/OS with RACF we recommend at minimum the definitions below (be careful with this example, we are no RACF specialists):

    //S01      EXEC PGM=IKJEFT01,DYNAMNBR=75,TIME=100,REGION=6M
    //SYSPRINT DD SYSOUT=*
    //SYSTSPRT DD SYSOUT=*
    //SYSTERM  DD DUMMY
    //SYSUADS  DD DSN=SYS1.UADS,DISP=SHR
    //SYSLBC   DD DSN=SYS1.BRODCAST,DISP=SHR
    //SYSTSIN  DD *
    RDEFINE CDT +
            $FLAM +
            CDTINFO(CASE(ASIS)        /* mixed case profile names */ +
                    DEFAULTRC(4)      /* default                  */ +
                    DEFAULTUACC(NONE) /* default                  */ +
                    FIRST(ALPHA)      /* profile name first char  */ +
                    GENERIC(ALLOWED)  /* default                  */ +
                    KEYQUALIFIERS(0)  /* default                  */ +
                    MAXLENGTH(246)    /* maximum prof name length */ +
                    OPERATIONS(NO)    /* default                  */ +
                    OTHER(ALPHA,      /* prof name allows A-Z,a-z */ +
                          NUMERIC,    /*                  0-9     */ +
                          NATIONAL,   /*                  #,@,$   */ +
                          SPECIAL)    /* all except blank ( ) , ; */ +
                    POSIT(202)        /* in user range 128-527    */ +
                    RACLIST(ALLOWED)  /* setr raclist allowed     */ +
                    SECLABELSREQUIRED(NO) /* default              */ +
                    SIGNAL(NO)        /* default (no ENF signals) */ +
                   )
    SETROPTS CLASSACT(CDT)
    SETROPTS RACLIST(CDT)
    SETROPTS RACLIST(CDT) REFRESH
    //S02      EXEC PGM=IKJEFT01,DYNAMNBR=75,TIME=100,REGION=6M
    //SYSPRINT DD SYSOUT=*
    //SYSTSPRT DD SYSOUT=*
    //SYSTERM  DD DUMMY
    //SYSUADS  DD DSN=SYS1.UADS,DISP=SHR
    //SYSLBC   DD DSN=SYS1.BRODCAST,DISP=SHR
    //SYSTSIN  DD *
    PERMIT $FLAM CLASS(CDT) RESET     /* clear permit list        */
    RALTER CDT   $FLAM OWNER(SYS1)    /* change ownership         */
    SETROPTS RACLIST(CDT) REFRESH
    //S03      EXEC PGM=IKJEFT01,DYNAMNBR=75,TIME=100,REGION=6M
    //SYSPRINT DD SYSOUT=*
    //SYSTSPRT DD SYSOUT=*
    //SYSTERM  DD DUMMY
    //SYSUADS  DD DSN=SYS1.UADS,DISP=SHR
    //SYSLBC   DD DSN=SYS1.BRODCAST,DISP=SHR
    //SYSTSIN  DD *
    SETROPTS GENERIC($FLAM)
    RDEFINE $FLAM +
            **                        /* cover all entities       */ +
            OWNER(SYS1) UACC(NONE)
    RDEFINE $FLAM GLOBAL.MUSTDEF OWNER(SYS1) UACC(NONE)
    RDEFINE $FLAM GLOBAL.POLICIES OWNER(SYS1) UACC(NONE)
    RDEFINE $FLAM GLOBAL.SMF.LOGGING OWNER(SYS1) UACC(NONE)
    RDEFINE $FLAM GLOBAL.CLP.CONTROL OWNER(SYS1) UACC(NONE)
    RDEFINE $FLAM GLOBAL.CMD.CONTROL OWNER(SYS1) UACC(NONE)
    RDEFINE $FLAM GLOBAL.AVE.CONTROL OWNER(SYS1) UACC(NONE)
    RDEFINE $FLAM GLOBAL.CPE.CONTROL OWNER(SYS1) UACC(NONE)
    RDEFINE $FLAM GLOBAL.KME.CONTROL OWNER(SYS1) UACC(NONE)
    RDEFINE $FLAM GLOBAL.SGU.CONTROL OWNER(SYS1) UACC(NONE)
    RDEFINE $FLAM GLOBAL.OBU.CONTROL OWNER(SYS1) UACC(NONE)
    RDEFINE $FLAM GLOBAL.EDC.CONTROL OWNER(SYS1) UACC(NONE)
    RDEFINE $FLAM GLOBAL.FIO.CONTROL OWNER(SYS1) UACC(NONE)
    RDEFINE $FLAM GLOBAL.FL4.CONTROL OWNER(SYS1) UACC(NONE)
    RDEFINE $FLAM GLOBAL.ARC.CONTROL OWNER(SYS1) UACC(NONE)
    RDEFINE $FLAM GLOBAL.SSH.CONNECT OWNER(SYS1) UACC(NONE)
    RDEFINE $FLAM GLOBAL.RST.CONNECT OWNER(SYS1) UACC(NONE)
    RDEFINE $FLAM GLOBAL.PGP.KEYMNGM OWNER(SYS1) UACC(NONE)
    RDEFINE $FLAM GLOBAL.PGP.USERID OWNER(SYS1) UACC(NONE)
    RDEFINE $FLAM GLOBAL.PGP.KEYID OWNER(SYS1) UACC(NONE)

    RDEFINE $FLAM POLICY.LOW.ENTROPY OWNER(SYS1) UACC(NONE)
    RDEFINE $FLAM POLICY.LOG.INPUT OWNER(SYS1) UACC(NONE)
    RDEFINE $FLAM POLICY.SSH.AUTH.*.ALLOWED OWNER(SYS1) UACC(NONE)
    RDEFINE $FLAM POLICY.SSH.PCAP.ALLOWED OWNER(SYS1) UACC(NONE)
    RDEFINE $FLAM POLICY.SSH.WEAK.HOSTKEY.CHECK.ALLOWED OWNER(SYS1) UACC(NONE)
    RDEFINE $FLAM POLICY.SSH.CUSTOM.HOSTKEY.ALLOWED OWNER(SYS1) UACC(NONE)
    RDEFINE $FLAM POLICY.SSH.CUSTOM.KNOWN.HOST.FILE.ALLOWED OWNER(SYS1) UACC(NONE)
    RDEFINE $FLAM POLICY.SSH.CUSTOM.CONFIG.FILE.ALLOWED OWNER(SYS1) UACC(NONE)
    RDEFINE $FLAM POLICY.KEY.GENERATE.PGP.EXPIRD.REQIRED OWNER(SYS1) UACC(NONE)
    RDEFINE $FLAM POLICY.KEY.GENERATE.PGP.ALGO.RSA.KEYLEN OWNER(SYS1) UACC(NONE)
    RDEFINE $FLAM POLICY.KEY.GENERATE.PGP.ALGO.DSA.ALLOWED OWNER(SYS1) UACC(NONE)
    RDEFINE $FLAM POLICY.KEY.IMPORT.PGP.KIDVER OWNER(SYS1) UACC(NONE)
    RDEFINE $FLAM POLICY.KEY.IMPORT.PGP.DOUBLE.KIDS OWNER(SYS1) UACC(NONE)
    RDEFINE $FLAM POLICY.PGP.PWD OWNER(SYS1) UACC(NONE)
    RDEFINE $FLAM POLICY.PGP.PWD.LEN.ENC OWNER(SYS1) UACC(NONE)
    RDEFINE $FLAM POLICY.PGP.PWD.LEN.DEC OWNER(SYS1) UACC(NONE)
    RDEFINE $FLAM POLICY.PGP.ENFORCE.ENCRYPTION OWNER(SYS1) UACC(NONE)
    RDEFINE $FLAM POLICY.PGP.ENFORCE.INTEGRITY OWNER(SYS1) UACC(NONE)
    RDEFINE $FLAM POLICY.PGP.ENFORCE.SIGNING OWNER(SYS1) UACC(NONE)
    RDEFINE $FLAM POLICY.EDC.PARM.FILE.ALLOWED OWNER(SYS1) UACC(NONE)
    RDEFINE $FLAM POLICY.EDC.KEY.PRINT.ALLOWED OWNER(SYS1) UACC(NONE)
    RDEFINE $FLAM POLICY.EDC.KEY.INVERSE.ALLOWED OWNER(SYS1) UACC(NONE)
    RDEFINE $FLAM POLICY.EDC.NO.HEADER.ALLOWED OWNER(SYS1) UACC(NONE)
    RDEFINE $FLAM POLICY.EDC.NO.SALT.ALLOWED OWNER(SYS1) UACC(NONE)
    RDEFINE $FLAM POLICY.SYM.KEY.LEN.ENC OWNER(SYS1) UACC(NONE)
    RDEFINE $FLAM POLICY.SYM.KEY.LEN.DEC OWNER(SYS1) UACC(NONE)
    RDEFINE $FLAM POLICY.SYM.PWD.LEN.ENC OWNER(SYS1) UACC(NONE)
    RDEFINE $FLAM POLICY.SYM.PWD.LEN.DEC OWNER(SYS1) UACC(NONE)
    RDEFINE $FLAM POLICY.ARC.ENCRYPT OWNER(SYS1) UACC(NONE)
    RDEFINE $FLAM POLICY.ARC.PROTECT OWNER(SYS1) UACC(NONE)
    RDEFINE $FLAM POLICY.ARC.PGP OWNER(SYS1) UACC(NONE)
    RDEFINE $FLAM POLICY.ARC.PWD OWNER(SYS1) UACC(NONE)
    RDEFINE $FLAM POLICY.ARC.DEF.PWD OWNER(SYS1) UACC(NONE)
    RDEFINE $FLAM POLICY.ARC.PWD.LEN.ENC OWNER(SYS1) UACC(NONE)
    RDEFINE $FLAM POLICY.ARC.PWD.LEN.DEC OWNER(SYS1) UACC(NONE)

    RDEFINE $FLAM FAVELIB.libfave OWNER(SYS1) UACC(NONE)
    RDEFINE $FLAM FAVEFUC.CLAMAVC OWNER(SYS1) UACC(NONE)
    RDEFINE $FLAM FAVEPAR.clamd.limes.de:3310 OWNER(SYS1) UACC(NONE)
    RDEFINE $FLAM FAVEIPH.clamd.limes.de OWNER(SYS1) UACC(NONE)
    RDEFINE $FLAM FAVEIPS.3310 OWNER(SYS1) UACC(NONE)

    RDEFINE $FLAM FSEGLIB.LIBFSEG OWNER(SYS1) UACC(NONE)
    RDEFINE $FLAM FSEGFUC.FSEGUSR OWNER(SYS1) UACC(NONE)
    RDEFINE $FLAM FOBJLIB.LIBFOBJ OWNER(SYS1) UACC(NONE)
    RDEFINE $FLAM FOBJFUC.FOBJUSR OWNER(SYS1) UACC(NONE)

    PERMIT  **   CLASS($FLAM) RESET   /* clear permit list (optional)*/
    PERMIT  GLOBAL.MUSTDEF CLASS($FLAM) ID(*) ACC(CONTROL)
/*  PERMIT  GLOBAL.POLICIES CLASS($FLAM) ID(*) ACC(NONE)      ACTIVE */
    PERMIT  GLOBAL.SMF.LOGGING CLASS($FLAM) ID(*) ACC(ALTER)/*INACTIV*/
    PERMIT  GLOBAL.CLP.CONTROL CLASS($FLAM) ID(*) ACC(ALTER)/*INACTIV*/
    PERMIT  GLOBAL.CMD.CONTROL CLASS($FLAM) ID(*) ACC(ALTER)/*INACTIV*/
/*  PERMIT  GLOBAL.AVE.CONTROL CLASS($FLAM) ID(*) ACC(NONE)   ACTIVE */
    PERMIT  GLOBAL.CPE.CONTROL CLASS($FLAM) ID(*) ACC(ALTER)/*INACTIV*/
    PERMIT  GLOBAL.KME.CONTROL CLASS($FLAM) ID(*) ACC(ALTER)/*INACTIV*/
    PERMIT  GLOBAL.SGU.CONTROL CLASS($FLAM) ID(*) ACC(ALTER)/*INACTIV*/
    PERMIT  GLOBAL.OBU.CONTROL CLASS($FLAM) ID(*) ACC(ALTER)/*INACTIV*/
    PERMIT  GLOBAL.EDC.CONTROL CLASS($FLAM) ID(*) ACC(ALTER)/*INACTIV*/
    PERMIT  GLOBAL.FIO.CONTROL CLASS($FLAM) ID(*) ACC(ALTER)/*INACTIV*/
/*  PERMIT  GLOBAL.FL4.CONTROL CLASS($FLAM) ID(*) ACC(ALTER)  ACTIVE */
/*  PERMIT  GLOBAL.ARC.CONTROL CLASS($FLAM) ID(*) ACC(ALTER)  ACTIVE */
    PERMIT  GLOBAL.SSH.CONNECT CLASS($FLAM) ID(*) ACC(ALTER)/*INACTIV*/
    PERMIT  GLOBAL.RST.CONNECT CLASS($FLAM) ID(*) ACC(ALTER)/*INACTIV*/
    PERMIT  GLOBAL.PGP.KEYMNGM CLASS($FLAM) ID(*) ACC(ALTER)/*INACTIV*/
    PERMIT  GLOBAL.PGP.USERID CLASS($FLAM) ID(*) ACC(ALTER) /*INACTIV*/
    PERMIT  GLOBAL.PGP.KEYID CLASS($FLAM) ID(*) ACC(ALTER)  /*INACTIV*/

    PERMIT  POLICY.SSH.AUTH.PUBLICKEY CLASS($FLAM) ID(*) ACC(READ)
    PERMIT  POLICY.SSH.AUTH.PASSWORD CLASS($FLAM) ID(*) ACC(UPDATE)
/*  PERMIT  POLICY.SSH.PCAP.ALLOWED CLASS($FLAM) ID(*) ACC(NONE)*/
    PERMIT  POLICY.SSH.WEAK.HOSTKEY.CHECK.ALLOWED CLASS($FLAM) ID(*) ACC(UPDATE)
    PERMIT  POLICY.SSH.CUSTOM.HOSTKEY.ALLOWED CLASS($FLAM) ID(*) ACC(UPDATE)
    PERMIT  POLICY.SSH.CUSTOM.KNOWN.HOST.FILE.ALLOWED CLASS($FLAM) ID(*) ACC(CONTRL)
    PERMIT  POLICY.SSH.CUSTOM.CONFIG.FILE.ALLOWED CLASS($FLAM) ID(*) ACC(UPDATE)
    PERMIT  POLICY.KEY.GENERATE.PGP.EXPIRD.REQIRED CLASS($FLAM) ID(*) ACC(UPDATE)
    PERMIT  POLICY.KEY.GENERATE.PGP.ALGO.RSA.KEYLEN CLASS($FLAM) ID(*) ACC(UPDATE)
/*  PERMIT  POLICY.KEY.GENERATE.PGP.ALGO.DSA.ALLOWED CLASS($FLAM) ID(*) ACC(NONE)*/
    PERMIT  POLICY.KEY.IMPORT.PGP.KIDVER CLASS($FLAM) ID(*) ACC(UPDATE)
/*  PERMIT  POLICY.KEY.IMPORT.PGP.DOUBLE.KIDS CLASS($FLAM) ID(*) ACC(READ)*/
    PERMIT  POLICY.PGP.PWD CLASS($FLAM) ID(*) ACC(ALTER)
    PERMIT  POLICY.PGP.PWD.LEN.ENC CLASS($FLAM) ID(*) ACC(CONTRL)
    PERMIT  POLICY.PGP.PWD.LEN.DEC CLASS($FLAM) ID(*) ACC(ALTER)
/*  PERMIT  POLICY.PGP.ENFORCE.ENCRYPTION CLASS($FLAM) ID(*) ACC(NONE)*/
/*  PERMIT  POLICY.PGP.ENFORCE.INTEGRITY CLASS($FLAM) ID(*) ACC(NONE)*/
    PERMIT  POLICY.PGP.ENFORCE.SIGNING CLASS($FLAM) ID(*) ACC(ALTER)
    PERMIT  POLICY.EDC.PARM.FILE.ALLOWED CLASS($FLAM) ID(*) ACC(UPDATE)
    PERMIT  POLICY.EDC.KEY.PRINT.ALLOWED CLASS($FLAM) ID(*) ACC(UPDATE)
/*  PERMIT  POLICY.EDC.KEY.INVERSE.ALLOWED CLASS($FLAM) ID(*) ACC(NONE)*/
    PERMIT  POLICY.EDC.NO.HEADER.ALLOWED CLASS($FLAM) ID(*) ACC(UPDATE)
    PERMIT  POLICY.EDC.NO.SALT.ALLOWED CLASS($FLAM) ID(*) ACC(READ)
    PERMIT  POLICY.EDC.STATIC.KEY.ALLOWED CLASS($FLAM) ID(*) ACC(ALTER)
    PERMIT  POLICY.EDC.STATIC.IV.ALLOWED CLASS($FLAM) ID(*) ACC(UPDATE)
    PERMIT  POLICY.SYM.KEY.LEN.ENC CLASS($FLAM) ID(*) ACC(UPDATE)
    PERMIT  POLICY.SYM.KEY.LEN.DEC CLASS($FLAM) ID(*) ACC(UPDATE)
    PERMIT  POLICY.SYM.PWD.LEN.ENC CLASS($FLAM) ID(*) ACC(CONTRL)
    PERMIT  POLICY.SYM.PWD.LEN.DEC CLASS($FLAM) ID(*) ACC(ALTER)
    PERMIT  POLICY.ARC.ENCRYPT CLASS($FLAM) ID(*) ACC(CONTROL)
    PERMIT  POLICY.ARC.PROTECT CLASS($FLAM) ID(*) ACC(UPDATE)
    PERMIT  POLICY.ARC.PGP CLASS($FLAM) ID(*) ACC(ALTER)
    PERMIT  POLICY.ARC.PWD CLASS($FLAM) ID(*) ACC(ALTER)
    PERMIT  POLICY.ARC.DEF.PWD CLASS($FLAM) ID(*) ACC(NONE)
    PERMIT  POLICY.ARC.PWD.LEN.ENC CLASS($FLAM) ID(*) ACC(CONTRL)
    PERMIT  POLICY.ARC.PWD.LEN.DEC CLASS($FLAM) ID(*) ACC(ALTER)

    PERMIT  FAVELIB.libfave CLASS($FLAM) ID(*) ACC(READ)
    PERMIT  FAVEFUC.CLAMAVC CLASS($FLAM) ID(*) ACC(READ)
    PERMIT  FAVEPAR.clamd.limes.de:3310 CLASS($FLAM) ID(*) ACC(READ)
    PERMIT  FAVEIPH.clamd.limes.de CLASS($FLAM) ID(*) ACC(READ)
    PERMIT  FAVEIPS.3310 CLASS($FLAM) ID(*) ACC(READ)

    PERMIT  FSEGLIB.LIBFSEG CLASS($FLAM) ID(*) ACC(READ)
    PERMIT  FSEGFUC.FSEGUSR CLASS($FLAM) ID(*) ACC(READ)
    PERMIT  FOBJLIB.LIBFOBJ CLASS($FLAM) ID(*) ACC(READ)
    PERMIT  FOBJFUC.FOBJUSR CLASS($FLAM) ID(*) ACC(READ)

/* REST/HTTP resource access control (active when GLOBAL.RST.CONNECT    */
/* has no ALTER permit -- see above). Resource entity is the URL.       */
/* Use specific URL profiles (e.g. RST.GET.https://s3.example.com/**)   */
/* instead of ** wildcards for production environments.                 */
    PERMIT  RST.CONNECT.** CLASS($FLAM) ID(*) ACC(CONTROL)
/* The same resource gates a Cloud Data Access provider, because the      */
/* question is the same one -- may this caller reach that place. CDA does  */
/* not run through the REST layer, so the entity is not a URL:             */
/*   RST.CONNECT.ibmcda://<provider>                                       */
/* The ** profile above already covers it. To decide per provider instead: */
/*   PERMIT RST.CONNECT.ibmcda://** CLASS($FLAM) ID(*) ACC(NONE)           */
/*   PERMIT RST.CONNECT.ibmcda://COSPROD CLASS($FLAM) ID(archiver)         */
/*          ACC(CONTROL)                                                   */
/* The bucket is not part of the entity: what a user id may do inside a    */
/* provider follows from the credential in its CDA key file, which RACF    */
/* governs through CSFKEYS.                                                */
/*  PERMIT  RST.NOVERIFY.** CLASS($FLAM) ID(*) ACC(NONE) (forbid TLS bypass) */
/* The TLS floor. A LADDER, inverted on purpose: the weakest level costs   */
/* the highest access, and RACF access is hierarchical, so the permitted   */
/* level IS the floor. UPDATE is the recommended setting -- TLS 1.2 and    */
/* above. Grant ALTER only on the one endpoint that needs TLS 1.0:         */
/*   PERMIT RST.TLSVSN.https://legacy.example.com CLASS($FLAM)             */
/*          ID(flam_users) ACC(ALTER)                                      */
/* With no permit at any level no TLS version is offered and the           */
/* connection fails. There is no environment variable for this: the        */
/* permit is the configuration.                                           */
    PERMIT  RST.TLSVSN.** CLASS($FLAM) ID(*) ACC(UPDATE)
/* The cipher list, checked only when FL_HWTHTTP_CIPHERS names one. The    */
/* level asked for is what the WEAKEST suite in the list demands, so a     */
/* list of modern suites needs only READ. ALTER buys RSA with SHA-1.       */
    PERMIT  RST.CIPHER.** CLASS($FLAM) ID(*) ACC(READ)
/* Substituting the trust anchor. Checked whether the value comes from the  */
/* CABUNDLE parameter of store.s3()/store.azure() or from FL_CA_BUNDLE --   */
/* the act is the same act and the source does not change it.               */
/* UPDATE and not ALTER: on z/OS a key ring is required for TLS at all, so */
/* ALTER here would make the secure path the harder one.                   */
    PERMIT  RST.CABUNDLE.** CLASS($FLAM) ID(*) ACC(UPDATE)
/* The backend trace. FL_HWTHTTP_VERBOSE at level 2 (UNREDACTED) writes the */
/* Authorization header into the trace -- an S3 SigV4 signature, and for    */
/* Azure or anything reached through CDA the account key itself -- so it    */
/* lands in a data set or in the job spool that operations can read.        */
/* Level 1 redacts the header but still records endpoints, the certificate  */
/* chain and timings, and FL_HWTHTTP_SSLTRACE names the key ring.           */
/*                                                                          */
/*   READ     a redacted trace, and the System SSL trace                    */
/*   CONTROL  UNREDACTED -- writing a credential out                        */
/*                                                                          */
/* A refusal DOWNGRADES and never fails the run: UNREDACTED without CONTROL */
/* falls back to the redacted trace, and that to no trace. So a site with   */
/* no profile keeps working and simply gets no trace.                       */
/* Grant CONTROL temporarily and on one endpoint when IBM support asks for  */
/* an unredacted trace, and take it back afterwards:                        */
/*   PERMIT RST.TRACE.https://s3.example.com CLASS($FLAM)                   */
/*          ID(support_user) ACC(CONTROL)                                   */
    PERMIT  RST.TRACE.** CLASS($FLAM) ID(*) ACC(READ)
    PERMIT  RST.GET.** CLASS($FLAM) ID(*) ACC(READ)
    PERMIT  RST.HEAD.** CLASS($FLAM) ID(*) ACC(READ)
    PERMIT  RST.PUT.** CLASS($FLAM) ID(*) ACC(UPDATE)
    PERMIT  RST.POST.** CLASS($FLAM) ID(*) ACC(UPDATE)
    PERMIT  RST.DELETE.** CLASS($FLAM) ID(*) ACC(CONTROL)
/* NOTE: Azure OAuth2 and MSI auth modes require RST.CONNECT and        */
/* RST.POST permits for the token acquisition endpoints:                */
/*   OAuth2: https://login.microsoftonline.com (RST.CONNECT + RST.POST) */
/*   MSI:    http://169.254.169.254            (RST.CONNECT + RST.GET)  */
/* The RST.CONNECT.** and RST.POST.**/RST.GET.** wildcards above cover  */
/* these endpoints. For restrictive environments add explicit permits:  */
/*  PERMIT RST.CONNECT.https://login.microsoftonline.com CLASS($FLAM)   */
/*         ID(flam_users) ACC(CONTROL)                                  */
/*  PERMIT RST.POST.https://login.microsoftonline.com CLASS($FLAM)      */
/*         ID(flam_users) ACC(UPDATE)                                   */
/*  PERMIT RST.CONNECT.http://169.254.169.254 CLASS($FLAM)              */
/*         ID(flam_users) ACC(CONTROL)                                  */

    SETROPTS CLASSACT($FLAM)
    SETROPTS RACLIST($FLAM)
    SETROPTS RACLIST($FLAM) REFRESH

First (in step 1 and 2) the general resource class $FLAM must be setup. The last step defines the rights for the certain entities. The recommendation defines all the policies and enable anti virus scanning only with the defined ClamAV daemon (DSN must be adjusted).

The entities for command execution or parameter string can include whitespace or one of the other 4 invalid characters '(),;'. If such an invalid character is encountered in an entity string, it is replaced by an underscore '_' before the SAF check. For example the PDS(E) 'HLQ.PO(HUGO)' results in the resource name 'FIOURL.HLQ.PO_HUGO_'. The global pre-write pre-processing command 'ls -l' results in the resource name 'CMD.PRE.WRITE.GLOBAL.ls_-l'.