Making zSecure and STIGs work for you
The US Defense Information Systems Agency (DISA) needed a reference for the security configuration of information systems in the US Department of Defense (DoD). DISA supports the intrusion avoidance program of DoD by publishing Security Technical Implementation Guides (STIGs) for IT products used by DoD or systems that store information relevant to DoD. The STIGs can be composed and maintained by DISA, or by the vendor of the IT product.
The STIGs provide a reasonably consistent framework for IT security across many platforms and products, so many organizations, even outside the US, have turned to STIGs for their own IT systems. Also, there is a myriad of tools available to scan systems and report on compliance related to STIGs. However, considerations like GDPR, CCPA and in-house security policy present different challenges to organizations, so installations that simply borrow from STIGs and have no intention to be fully STIG compliant will need a way to deviate from the formal tests in automated STIG evaluations.
zSecure Audit provides a compliance reporting framework and an extensive set of STIG evaluation tests. The ISPF interface offers a Rule-based compliance interface (AU.R) and batch jobs to generate reports. It uses some 550 members with CARLa code to test a variety of data types and covers approx. 350 STIGs for z/OS, RACF, and z/OS components and products. z/OS systems with ACF2 and TopSecret can also be evaluated, albeit with fewer STIGs.
This paper shows how to gain benefit from the automated STIG tests in zSecure Audit, while retaining flexibility to verify more relevant controls.
Getting your zSecure definitions ready for STIGs
There are two versions of zSecure compliance reporting framework available:
- zSecure 2.4.0 with PTF UJ04502 and UJ04557 applied, optionally UJ04502 for ACF2 support, referred to as 2020 Q4 SSE. This version adds support for long entries in config members through CKACUSV, and ships empty allowlist[1] and config members in target libraries SCKACUST and SCKACUSV. The CKACUST data set only has to contain customized members, the empty members can be removed. Installation batch job CKAZCUST is redundant. See https://www.ibm.com/support/pages/node/6352999
- Older zSecure versions and zSecure 2.4.0 without these PTFs applied. These versions must have all possible allowlist members in the CKACUST data set, maintained with installation batch job CKAZCUST after each applicable PTF.
For the older zSecure versions you should allocate a CKACUST partitioned data set (RECFM=FB,LRECL=80) preferably with DSTYPE=LIBRARY. Initialize the data set using job CKAZCUST (from the CKRINST or SCKRSAMP library).
With the 2020 Q4 SSE installed, you should have a CKACUST (RECFM=FB,LRECL=80) and a CKACUSV data set (RECFM=VB,LRECL=32756), both PDS(E). Initially, these data sets can be empty because the initial members are found in SCKACUST or SCKACUSV, resp. If you re-use an existing CKACUST from an older zSecure version, you could delete all the members that you never changed.
Job CKAZSITE in SCKRSAMP or CKRJOBS is available to allocate site or user specific libraries with allowlist members.
If you intend to use STIG verification on LPARs with different naming conventions, or with different user IDs, you could define a third PDS(E) that contains the CARLa programs the are identical between the LPARs, and use the CKACUST data set only for (LPAR specific) allow lists. If this is your intended use of zSecure, allocate a CARLA PDS(E) too (RECFM=FB,LRECL=80).
DSLIST - Data Sets Matching MYCOSEC.STIG Row 1 of 3
Command - Enter "/" to select action Dsorg Recfm Lrecl Blksz
-------------------------------------------------------------------------------
MYCOSEC.STIG.CARLA PO-E FB 80 32720
MYCOSEC.STIG.CKACUST PO-E FB 80 32720
MYCOSEC.STIG.CKACUSV PO-E VB 32756 32760
***************************** End of Data Set list ****************************
If you plan to share these data sets with all zSecure users in your installation, as site defined CKACUST/CKACUSV, you should add these names in the active CKRPARM member, like so:
EDIT ZSECURE.SHARED.CKRPARM(C2R$PARM) - 01.02 Columns 00001 00072
000033 //* Parameters only used for zSecure Audit AU.R Compliance
000034 // SET CKACUST='ZSECURE.SHARED.CKACUST'
000035 // SET CKACUSV='ZSECURE.SHARED.CKACUSV'
These data sets show up with Status value “site” in SE.8. There is no “site” CKRCARLA data set option, so you should add a similar line in SE.8 as shown below for the MYCOSEC.STIG.CARLA data set. Alternatively, you can use SCKRCARL instead of CARLA as the last qualifier and set the WPREFIX symbol in C2R$PARM to MYCOSEC.STIG.
If you only plan to work on the STIGs with a small team, you can do without updating CKRPARM and simply define these data sets to zSecure using option SE.8:
zSecure Suite - Setup - Command files Row 1 of 7
Select Command library or work with a library (S, U, E, R, I, D)
Command library Type Status
_ DD:CKRCARLA CKRCARLA
_ DD:CKRCMD CKRCMD
_ 'MYCOSEC.STIG.CARLA' CKRCARLA selected
_ 'MYCOSEC.STIG.CKACUST' CKACUST user
_ 'MYCOSEC.STIG.CKACUSV' CKACUSV user
******************************* Bottom of data ********************************
Run a STIG evaluation
To run a STIG evaluation, you should select a snapshot of the system from option SE.1, containing a CKFREEZE data set and a security database (active RACF, backup ACF2 database or an UNLOAD). If you specify a COMPLEX name, make sure all selected data sets have the same COMPLEX value specified.
If the input data sets describe a relatively small system, go to option AU.R.E (Run standard evaluation) and enter a / in front of STIG. Leave all other fields empty and press Enter.
If the snapshot contains large data set, you might use AU.R.S to run subsets of the STIG. This uses less CPU and storage, with a better response time. In AU.R.S you select STIG with a S line command, then enter an A line command in front of a Category like ACP, RACF or ACF.
The result of your evaluation shows 3 reports:
Name Summary Records Title
STDRULES 1 57 Standard rule set compliance summary
STDTYPES 1 10 Standard object type compliance summary
STDTESTS 1 11076 Standard compliance test
******************************* Bottom of Data ********************************
The first is an overview of the compliance levels in the system, showing (only) how many tests in each rule set are compliant, non-compliant or unknown. These numbers can be much higher than actual users, data sets or options in the system.
The third report refers to objects (data sets, RACF permits and profiles, user IDs, Logon IDs) and their compliance state. This produces numbers closer to actual things you can list in the system. More importantly, the third report allows you to drill down to see the objects, and the tests that determine their compliance status.
Standard compliance test
Complex Ver Pr Standards NonComp Unknown Exm Sup
ZTEC 0 30 1 1 1 1
Standard Pr Rule sets NonComp Unknown Exm Sup Version
RACF_STIG 30 352 173 52 89 6.47
Rule set Pr Objects NonComp Unknown Exm Sup Caption
AAMV0010 1 1 Change Management Process
AAMV0012 1 1 Supported system software
AAMV0014 1 1 Upgrade OS plan
AAMV0018 1 1 Software Patches
AAMV0030 20 1 1 LNKAUTH=APFTAB
AAMV0040 10 1652 15 APF libraries exist
AAMV0050 16 APF libraries unique
AAMV0060 124 124 Review AC=1 modules
AAMV0160 20 105 26 PPT programs exist
AAMV0325 1 Accessible LPA libraries
AAMV0350 1 Accessible LINKLIST libs
AAMV0370 20 5 5 SMF data collection
AAMV0380 222 SMF record (sub)types
AAMV0400 1 1 Collect and retain SMF
AAMV0410 20 1 1 RACF database recovery
AAMV0420 20 1 1 RACF database backup
AAMV0430 1 1 System DASD backups
AAMV0440 1 PASSWORD data set
AAMV0450 1 1 System programs
AAMV0500 1 1 Protect shared sens ds
ACP00010 30 34 34 Master PARMLIBs protected
ACP00020 20 9 9 SYS1.LINKLIB protected
ACP00030 30 9 9 SYS1.SVCLIB protected
ACP00040 30 9 9 SYS1.IMAGELIB protected
ACP00050 30 9 9 SYS1.LPALIB protected
ACP00060 30 1725 1725 APF libraries protected
Looking at Rule set AAMV0040 we surmise there are 1652 APF data sets defined, but 15 of these are somehow non-compliant. Selecting the Rule set, we see the names of the faulty entries:
Standard compliance test
Complex Ver Pr Standards NonComp Unknown Exm Sup
ZTEC 0 30 1 1 1 1
Standard Pr Rule sets NonComp Unknown Exm Sup Version
RACF_STIG 30 352 173 52 89 6.47
Rule set Pr Objects NonComp Unknown Exm Sup Caption
AAMV0040 10 1652 15 APF libraries exist
Non Unk Exm Class System Type VolSer Resource
Non Dataset ZS14 PP010P ABC.V1R5M5.LINKLIB
Non Dataset ZS14 PP010P ABC.V1R6M0.LINKLIB
Non Dataset ZS14 MIGRAT ZSECURE.CKR230.GA.SB8RLNK
Non Dataset ZS14 MIGRAT ZSECURE.CKR231.GA.SB8RLNK
Non Dataset ZS14 MIGRAT ZSECURE.CQT221.GA.SCQTLOAD
Non Dataset ZS14 MIGRAT ZSECURE.CQT230.GA.SCQTLOAD
Non Dataset ZS14 MIGRAT ZSECURE.CQT240.GA.SCQTLOAD
Non Dataset ZS14 MIGRAT ZSECURE.C4R221.GA.SC4RLNK
Non Dataset ZS14 R00871 IBMBTST.X.NONEXIST.APF
Non Dataset ZS14 R00872 IBMBTST.X.SHORT
Dataset ZS14 ABC001 ABC.LOADE
Dataset ZS14 COMN01 CONCAT.LOAD
Dataset ZS14 COMN01 ECHO.LPAESA.LINKLIB
Dataset ZS14 COMN01 ECHO.PRODESA.LINKLIB
Selecting a Dataset entry, we see an indication why it is non-compliant:
Standard compliance test
Complex Ver Pr Standards NonComp Unknown Exm Sup
ZTEC 0 30 1 1 1 1
Standard Pr Rule sets NonComp Unknown Exm Sup Version
RACF_STIG 30 352 173 52 89 6.47
Rule set Pr Objects NonComp Unknown Exm Sup Caption
AAMV0040 10 1652 15 APF libraries exist
Non Unk Exm Class System Type VolSer Resource
Non Dataset ZS14 PP010P ABC.V1R6M0.LINKLIB
Cmp Non Unk Exm Test name MembTest Test description
Non b.1.APF_present C2RGM040 Data set in APF list acces
******************************* Bottom of Data ********************************
Test b.1.APF_present determines if the data set was found on any online volume, and this dsname was not present. Details can be reviewed by typing an S line command in front of the test.
In your installation, APF definitions in PARMLIB members may be managed centrally, putting program products into APF list, even when the program product is not actually installed. STIG considers this a security exposure, whereas your installation considers it an acceptable risk. How to proceed?
Manually modifying STIG test results
zSecure provides the O line command in the ISPF interface to override individual test results. Before you can use the O and A (assert) line command, you must allocate an ASSERT type output data set using option SE.1. Insert a set with an entry like this:
zSecure Suite - Setup - Input files Row 1 of 1
Description . . . . Asserts
Complex . . . . . . Version . . . .
Enter data set names and types. Type END or press F3 when complete.
Enter dsname with .* to get a list Type SAVE to save set, CANCEL to quit.
Valid line commands: E L I R D Type REFRESH to submit unload job.
Data set name or DSNPREF=, or Unix file name Type or ? NJE node
DSNPREF=MYCOSEC.ASSERT SAVE POSTPONE ASSERT
******************************* Bottom of data ********************************
The width of the data set name prefix (DSNPREF) is limited to 14 characters. The COMPLEX and VERSION fields are ignored. Your user ID must be permitted to create new data sets starting with this prefix. Each time you run AU.R.E, and use the O or A line command, a new ASSERT data set is allocated.
The next time you run AU.R.E, all matching ASSERT data sets are read and used to modify test results according to your previous override or assert decision.
You can select additional ASSERT type data sets in SE.1, containing input from colleagues or from previous projects, but only one entry should have the SAVE and POSTPONE keywords.
Going back to our APF data set finding, from Rule set AAMV0040, you could issue an O line command in front of each Test result, for each dsname. Each line command results in 1 record in the ASSERT output data set, specifying the dsname actioned. You can review previous actions using option AU.R.H (history).
The A line commands are used to assert the existence of organizational processes, or system parameters that cannot (currently) be measured by zSecure Audit. The corresponding test commands in the CARLa members have the ASSERT keyword, indicating they can ONLY be answered by an ASSERT action. Unanswered tests show up with a status of Unknown.
There are currently no documented mechanisms to combine ASSERT data sets, or to remove expired actions from them. At best you can use ISPF 3.4 to delete individual data sets based on the date, time, and user ID of the creator.
Remember to unselect the ASSERT set of input files with the SAVE option when you stop using the A and O line commands!
Programmatically modifying STIG tests
If your installation security policy has different ideas than implemented in the STIGs, you can selectively modify the CARLa commands that evaluate your installation. If you modify the CARLa commands, you should no longer claim compliance with DISA STIGs.
Although the STIG evaluation code is available in members C%%G%%%% in SCKRCARL, you should never modify these members directly. They are (frequently) replaced by PTFs or new releases of zSecure. Also, creating an identically named member in your CKACUST or CARLA data set is inefficient, because updates to the (original) members in SCKRCARL would become inaccessible.
It is much easier and less dangerous to selectively override TEST commands, using the CARLA OVERRIDE command. This process relies on carefully specifying the name of the TEST command and the RULE command from the test results, and using these in an OVERRIDE command. If a PTF or new release of zSecure changes either of these names, you will have to amend your OVERRIDE commands accordingly.
First identify a CARLa member that zSecure executes in every STIG evaluation. This member is C2RG@IDF in the CKACUST data set. Although primarily meant to specify Installation specific DEFTYPE statements, more CARLa commands are allowed. However, we do not want to clutter this member, so we only add an IMBED command for a member that starts with your (installation specific) prefix MYCO.
MYCOSEC.STIG.CKACUST(C2RG@IDF) - 01.00 Columns 00001 00072
***************************** Top of Data ******************************
/* This member is used for site customization for addition */
/* of AU.R population members in the STIG standard. */
/* Insert here DEFTYPE statements. */
/* This member is NOT the place to add rules. */
/* Use C%%%@INS members for that. */
/* See also: SCKRCARL(C2RG@DEF) (STIG DEFTYPEs) */
/* CKACUST(C%%G@INS) (Customization members) */
IMBED M=MYCO@OVR /* Load OVERRIDE statements from CARLA lib */
**************************** Bottom of Data ****************************
By omitting the DD= parameter on the IMBED command, zSecure first searches your selected CARLA library, then your user CKACUST, then your site CKACUST.
Lets add member MYCO@OVR in my CARLA library:
MYCOSEC.STIG.CARLA(MYCO@OVR) - 01.00 Columns 00001 00072
***************************** Top of Data ******************************
/* Override AAMV0040 APF data set not found finding */
override rule(AAMV0040) test(b.1.APF_present),
version(1) as(compliant),
by("Rob van Hoboken") enddate(2023-12-31),
Comment("program product can be uninstalled on LPARs")
**************************** Bottom of Data ****************************
Note: if you still have a set of input files selected with TYPE=ASSERT SAVE POSTPONE, any OVERRIDE (and ASSERT) commands cause a new ASSERT data set to be created. Unselect this set first!
Running the whole STIG, or selectively using AU.R.S, selecting Category AAMV with S and rule AAMV0060 using the R line command, the offending data sets are no longer non-compliant but now exempted.
Standard compliance test
Complex Ver Pr Standards NonComp Unknown Exm Sup
ZTEC 0 1 1
Standard Pr Rule sets NonComp Unknown Exm Sup Version
RACF_STIG 1 1 "1.00"
Rule set Pr Objects NonComp Unknown Exm Sup Caption
AAMV0040 1652 15 APF libraries exist
Non Unk Exm Class System Type VolSer Resource
Exm Dataset ZS14 PP010P ABC.V1R5M5.LINKLIB
Exm Dataset ZS14 PP010P ABC.V1R6M0.LINKLIB
Exm Dataset ZS14 R00871 IBMBTST.X.NONEXIST.APF
Exm Dataset ZS14 R00872 IBMBTST.X.SHORT
******************************* Bottom of Data ********************************
The test details show the User ID running the evaluation, the end date, name and comment of the override:
Standard compliance test b.1.APF_present
AAMV0040 APF libraries exist
Rule set description
No inaccessible APF libraries in APF list.
Rule description
No inaccessible APF libraries in APF list.
Test description
Data set in APF list accessible.
Class Resource
Dataset ABC.V1R5M5.LINKLIB
Assert/override
Object asserted as compliant
Test that requires assertion No Override that changes finding Yes
Assertion recorded by user IBMBROB End assertion validity 31Dec23
Last assertion timestamp
Person asserting test result Rob van Hoboken
Comment explaining assertion program product can be uninstalled on LPARs
Test result
Test value is compliant Yes Test is true No
Non-compliant audit finding No Relative audit priority
Lookup against
Actual value of test field NoAPFnoDsn
Test definition
Test name b.1.APF_present
Test lookup base field name
Test field name SENSITIVITY
Relational operator <>
Compliance comparison value NOAPF
Test type n/a,(non-)compliant compliant
Rule
Rule name AAMV0040
Rule non-compliance severity Low Site overruling rule severity
Do not confuse Rule name and Rule set name, even though they can be identical. We use Rule name in our OVERRIDE commands because this unique name identifies the statements in the IBM supplied SCKRCARL members. The Rules set name is used to tie the IBM supplied rules and any installation defined rules together in summaries.
The optional parameter RESOURCE can be used in the OVERRIDE command to provide granularity: allow some data sets to be missing. For each dsname you must specify 1 OVERRIDE command; the RESOURCE value must match exactly, generic matching is not supported. Here is the syntax of the OVERRIDE command:
OVERRIDE [TEST(name)] [RULE_SET(name)] [RULE(name)] [STANDARD(name)]
VERSION(version) [COMPLEX(name)] [SYSTEM(name)] [CLASS(class)]
[RESOURCE(resource)] [PROFTYPE(proftype)] [VOLSER_KEY(volser)]
AS({COMPLIANT|NONCOMPLIANT|RETRACTED}) [BY(name|quotedstring))]
[ENDDATE(date)] [COMMENT(quotedstring)]
Replace STIG tests with other tests
The OVERRIDE AS(COMPLIANT) command can be used to blot out false-positive test results. For some Rule sets an alternative test should be inserted. Take the password interval test. In RACF systems this is RACF0440:
Standard compliance test
Complex Ver Pr Standards NonComp Unknown Exm Sup
ZTEC 0 20 1 1
Standard Pr Rule sets NonComp Unknown Exm Sup Version
RACF_STIG 20 1 1 "1.00"
Rule set Pr Objects NonComp Unknown Exm Sup Caption
RACF0440 20 1 1 SETROPTS PASSW INT(60)
Non Unk Exm Class System Type VolSer Resource
Non System ZS14 ZS14
Cmp Non Unk Exm Test name MembTest Test description
Non b.1b.PWDInterval60 CKAGR440 PASSWORD(INTERVAL) must be
Cmp b.1a.PWDIntervalNO CKAGR440 PASSWORD(INTERVAL) should
******************************* Bottom of Data ********************************
Some installations like to switch the interval to 90 days. We first OVERRIDE the test:
MYCOSEC.STIG.CARLA(MYCO@OVR) - 01.00 Member MYCO@OVR saved
***************************** Top of Data ******************************
/* Override AAMV0040 APF data set not found finding */
override rule(AAMV0040) test(b.1.APF_present),
version(1) as(compliant),
by("Rob van Hoboken") enddate(2023-12-31),
Comment("program product can be uninstalled on LPARs")
/* Override RACF0440 Password interval 60 days */
override rule(RACF0440) test(b.1b.PWDInterval60),
version(1) as(compliant),
by("Rob van Hoboken"),
Comment("Local standard SETROPTS PASSWORD(INTERVAL(90))")
**************************** Bottom of Data ****************************
As a result, b.1b.PWDInterval60 is now Compliant, Exempted from the Test:
Standard compliance test
Complex Ver Pr Standards NonComp Unknown Exm Sup
ZTEC 0 1 1
Standard Pr Rule sets NonComp Unknown Exm Sup Version
RACF_STIG 1 1 "1.00"
Rule set Pr Objects NonComp Unknown Exm Sup Caption
RACF0440 1 1 SETROPTS PASSW INT(60)
Non Unk Exm Class System Type VolSer Resource
Exm System ZS14 ZS14
Cmp Non Unk Exm Test name MembTest Test description
Cmp b.1a.PWDIntervalNO CKAGR440 PASSWORD(INTERVAL) should
Cmp Exm b.1b.PWDInterval60 CKAGR440 PASSWORD(INTERVAL) must be
******************************* Bottom of Data ********************************
Using the S line command to select one of the Tests we check the test details. At the end of the details you find the CARLa member for this Rule, CKAGR440, where you can you use a line command to view it. Then we write an alternative test member, using the CARLa code in SCKRCARL(CKAGR440) as an example:
MYCOSEC.STIG.CARLA(MYCOR440) - 01.00 Member MYCOR440 saved
***************************** Top of Data ******************************
imbed m=ckagr440 nodup
RULE MYCO_RACF0440 domain(System_options),
SET(RACF0440),
DESC("The PASSWORD(INTERVAL) value must be set to 90 days or less."),
CAPTION("SETROPTS PASSW INT(90)") SEV(2)
TEST b.1b.PWDInterval90 system(pwdinterval<=90),
DESC("PASSWORD(INTERVAL) must be set to 90 days or less.")
ENDRULE
**************************** Bottom of Data ****************************
First we get the original CARLa code included, unless it was included by STIGs before. This allows us to test the new member separately, using AU.R.T (Test member).
Then we build a new Rule, with a unique name produced by prefixing the original rule with your own prefix. The new rule is added into the existing Rule set that you can see in the previous screen shot.
In the new Rule, we can use the same Test name or make the Test name more specific for the value we test. After all, Test names only have to be unique within the RULE command context. You only have to write TEST commands for Tests that are different from the original, the original tests in member CKAGR440 are still used.
We test this new rule member using AU.R.T:
zSecure Suite - Audit - Test rule 0.0 s CPU, RC=0
Action and name for CKACUST rule member
1 1. Evaluate 2. Configure 3. Browse 4. View 5. Edit
Test member . . . . . . MYCOR440
Specify for single rule evaluation or configuration:
Standard . . . . . . . MYOWNSTD (prefixed by the OS name)
ESM . . . . . . . . . . / RACF ACF2 TSS
Compliance result selection
Compliant Non-compliant Overridden
Assertions due in (number of days)
Output/run options
Show differences
Print format Send as e-mail
Background run Include test details Narrow print
The results indicate that our installation meets the 90 day Test, as well as the old, exempted, 60 day Test:
Standard compliance test
Complex Ver Pr Standards NonComp Unknown Exm Sup
ZTEC 0 1 1
Standard Pr Rule sets NonComp Unknown Exm Sup Version
ZOS_MYOWNSTD 1 1 0
Rule set Pr Objects NonComp Unknown Exm Sup Caption
RACF0440 1 1 SETROPTS PASSW INT(60)
Non Unk Exm Class System Type VolSer Resource
Exm System ZS14 ZS14
Cmp Non Unk Exm Test name MembTest Test description
Cmp b.1a.PWDIntervalNO CKAGR440 PASSWORD(INTERVAL) should
Cmp b.1b.PWDInterval90 MYCOR440 PASSWORD(INTERVAL) must be
Cmp Exm b.1b.PWDInterval60 CKAGR440 PASSWORD(INTERVAL) must be
******************************* Bottom of Data ********************************
The MembTest column shows us the standard tests (CKAGR440) and the modified tests (MYCOR440).
But this new rule member is not going to be included in the standard AU.R.E STIG evaluation, until we add it as an installation defined rule, in CKACUST member CKAG@INS for RACF system, or C2AG@INS for ACF2 system.
MYCOSEC.STIG.CKACUST(CKAG@INS) - 01.00 Columns 00001 00072
***************************** Top of Data ******************************
/* This member is used for site customization for addition */
/* of rules to the RACF STIG. */
/* You can add new rule sets or extend existing rule sets */
/* (for instance to declare the set N/A for some specific */
/* reason), or replace a rule by adding a SUPPRESS for */
/* the standard RULE and add a new RULE with a slightly */
/* different name (suggest suffix "_site") and add it to */
/* the existing rule set with the SET() keyword. */
/* This member is included from the RACF STIG standard. */
/* See also: C2RG@IDF (DEFTYPEs) */
/* C2AG@INS (ACF2), CKTG@INS (TSS) */
IMBED M=MYCO@INS /* Load IMBED statements from CARLA lib */
**************************** Bottom of Data ****************************
Which imbeds the (still short) list of installation defined rule members:
MYCOSEC.STIG.CARLA(MYCO@INS) - 01.00 Columns 00001 00072
***************************** Top of Data ******************************
/* Installation defined rules for MY CO */
IMBED M=MYCOR440
**************************** Bottom of Data ****************************
Note: a future fix will change member CKAGR440: both the Rule name and the Test name are changing. After each PTF you will have to verify that all overrides that you built are still accepted. The ASSERT and OVERRIDE commands do not issue a warning when there is no matching Rule, Rule set or Test. The same applies to asserts and overrides in ASSERT data sets, created using A and O line commands.
Assertions
The ASSERT command can be used, like OVERRIDE, to programmatically set the outcome of TEST ASSERT commands. Initially, these Tests return a status of Unknown, however, you can build a member with ASSERT commands and imbed this from C2RG@IDF:
MYCOSEC.STIG.CKACUST(C2RG@IDF) - 01.00 Columns 00001 00072
***************************** Top of Data ******************************
/* This member is used for site customization for addition */
/* of AU.R population members in the STIG standard. */
/* Insert here DEFTYPE statements. */
/* This member is NOT the place to add rules. */
/* Use C%%%@INS members for that. */
/* See also: SCKRCARL(C2RG@DEF) (STIG DEFTYPEs) */
/* CKACUST(C%%G@INS) (Customization members) */
IMBED M=MYCO@OVR /* Load OVERRIDE statements from CARLA lib */
IMBED M=MYCO@ASS /* Load ASSERT statements from CARLA lib */
**************************** Bottom of Data ****************************
And maintain these manually:
MYCOSEC.STIG.CARLA(MYCO@ASS) - 01.00 Columns 00001 00072
***************************** Top of Data ******************************
ASSERT RULE_SET(AAMV0010), /* Change Management Process */
VERSION(1) AS(COMPLIANT),
COMMENT(“Manual entry of findings.”)
ASSERT RULE_SET(AAMV0012), /* Supported system software */
SYSTEM(ZS14),
VERSION(1) AS(COMPLIANT),
COMMENT(“Manual entry of findings.”)
**************************** Bottom of Data ****************************
Syntax of the ASSERT command shows that only the VERSION and AS parameters are required:
ASSERT [TEST(name)] [RULE_SET(name)] [RULE(name)] [STANDARD(name)]
VERSION(version) [COMPLEX(name)] [SYSTEM(name)] [CLASS(class)]
RESOURCE(resource)][PROFTYPE(proftype)] [VOLSER_KEY(volser)]
AS({RETRACTED| COMPLIANT | NONCOMPLIANT}) [BY(name|quotedstring)]
[ENDDATE(date)] [COMMENT(quotedstring)]
You can remove all unresolved assertion results from the compliance test overview (not from the rule set compliance summary) by manually adding to your CARLa code:
define type=compliance compliance_exclude boolean where,
test_assert missing(test_assert_as)
or by selecting (only) the first 3 report elements in AU.R.E, leaving Assertions unselected:
Compliance result selection
/ Compliant / Non-compliant / Overridden
Assertions due in (number of days)
Increase granularity for job functions in ACP tests
STIG ACP00060 prescribes that (RACF, ACF2) rules for APF libraries should restrict update access to only system programming personnel. zSecure implements this rule by testing that IDs with UPDATE or more on the access control list (ACL) of profiles for APF data sets are in one of these allowlist members in CKACUST[2]:
SYSPAUDT system programming personnel
TSTCAUDT trusted started tasks
If the ID permitted on a relevant dataset profile is NOT in either of these members, the permit is flagged as non-compliant by test 3.access_other.
Consequently, you start by adding into SYSPAUDT user IDs belonging to persons in the system programming team and connect groups used for system programming roles, that were reported in the RESOURCE value for non-compliant tests. Change management started task IDs and groups would be added to TSTCAUDT.
Using AU.R.C “Configure” using the “Configuration of user and group IDs in domain allowlist members” checkbox, you can see where else these allow lists act (only first 10 lines shown):
Line 1 of 133
Configuration of user and group IDs in domain allowlist members
16 Mar 2021 07:20
DomAllow Standards Description
SYSPAUDT 2 Systems Programmers or Systems Administrators
Standard Version of standard Rule sets
RACF_STIG 6.47 133
Rule set Rule set caption
ACP00010 Master PARMLIBs protected
ACP00020 SYS1.LINKLIB protected
ACP00030 SYS1.SVCLIB protected
ACP00040 SYS1.IMAGELIB protected
ACP00050 SYS1.LPALIB protected
ACP00060 APF libraries protected
ACP00062 System REXX lib protected
ACP00070 LPA libraries protected
ACP00080 SYS1.NUCLEUS protected
ACP00100 PPT libraries protected
Many installations have segregated control of APF libraries, and do not want middleware teams to have the same (wide) access as core-z/OS teams. Adding all the user IDs to SYSPAUDT does not represent the team responsibilities in their installation.
Let’s compose an installation-specific rule member to match team responsibilities. But first we disable the generic failure in ACP00060:
MYCOSEC.STIG.CARLA(MYCO@OVR) - 01.08 Columns 00001 00072
***************************** Top of Data ******************************
- - - - - - - - - - - - - - - - 18 Line(s) not Displayed
/* Override ACP00060 function names */
override rule(ACP00060_permit) test(3.access_other),
version(1) as(compliant),
by("Rob van Hoboken"),
Comment("additional jobroles verified in MYCOC060")
- - - - - - - - - - - - - - - - 6 Line(s) not Displayed
**************************** Bottom of Data ****************************
Next we go to the test details of an ACP00060 finding and browse the Rule set CARLa member CKAGC060. Copy the DOMAIN APF_PERMITS command and the RULE ACP00060_permit block into a new member MYCOC060:
***************************** Top of Data ******************************
imbed m=ckagc060 nodup
DOMAIN APF_PERMITS,
SELECT(racf_access(access=(UPDATE,CONTROL,ALTER),
class=DATASET,
priv_senstype=:APF,
id<>('-UACC-'c,'*'c,'- any -'c))),
ALLOWLIST(SYSPAUDT,TSTCAUDT)
RULE ACP00060_permit domain(APF_PERMITS),
SET(ACP00060),
DESC("The ACP data set rules for APF restrict UPDATE or greater access
to only z/OS systems programming personnel or trusted started tasks.")
TEST 3.access_sysp,
racf_access(id:populate_stig_syspaudt.id.id<>' '),
DESCRIPTION("Systems programming personnel."),
OTHERWISE(,
TEST 3.access_tstc,
racf_access(id:populate_stig_tstcaudt.id.id<>' '),
DESCRIPTION("Trusted started tasks."),
OTHERWISE(,
TEST 3.access_other,
racf_access(id<>" ") noncompliant,
DESC("Update or higher access must be restricted to only system pro
gramming personnel (SYSPAUDT) or trusted started tasks (TSTCAUDT).")))
ENDRULE
**************************** Bottom of Data ****************************
Suppose we have only two teams: BASE and MIDWARE. First put our company acronym MYCO in front of the RULE label, then do a block repeat of the DOMAIN and RULE blocks. Delete the first DOMAIN command block, because that is already defined in CKAGC060. For now, put comment markers around the 2nd half.
Find TEST 3.access_other and insert a TEST above, that finds all profiles protecting only the data sets belonging to the MIDWARE team and skips 3.access_other for those data set names. Note, for each TEST added, also add a closing parenthesis right before the ENDRULE command.
The new test looks at all resources (dsnames) protected by the current profile. If none of the dsnames has a value other than MIDWARE.xxxxx or USER.yyyyy, the profile should be verified as a MIDWARE profile.
This is the result:
MYCOSEC.STIG.CARLA(MYCOC060) - 01.04 Columns 00001 00072
***************************** Top of Data ******************************
imbed m=ckagc060 nodup
RULE MYCO_ACP00060_permit domain(APF_PERMITS),
SET(ACP00060),
DESC("The ACP data set rules for APF restrict UPDATE or greater access
to only z/OS systems programming personnel or trusted started tasks.")
TEST 3.access_sysp,
racf_access(id:populate_stig_syspaudt.id.id<>' '),
DESCRIPTION("Systems programming personnel."),
OTHERWISE(,
TEST 3.access_tstc,
racf_access(id:populate_stig_tstcaudt.id.id<>' '),
DESCRIPTION("Trusted started tasks."),
OTHERWISE(,
TEST 3.MIDWARE_Libraries,
racf_access(not(resource<>(,
MIDWARE.**,
USER.**,
))),
DESCRIPTION("Middleware maintenance monitored in separate rule."),
OTHERWISE(,
TEST 3.access_other,
racf_access(id<>" ") noncompliant,
DESC("Update or higher access must be restricted to only system pro
gramming personnel (SYSPAUDT) or trusted started tasks (TSTCAUDT)."))))
ENDRULE
/*
DOMAIN APF_PERMITS,
SELECT(racf_access(access=(UPDATE,CONTROL,ALTER),
class=DATASET,
priv_senstype=:APF,
id<>('-UACC-'c,'*'c,'- any -'c))),
ALLOWLIST(SYSPAUDT,TSTCAUDT)
RULE MYCO_ACP00060_permit domain(APF_PERMITS),
SET(ACP00060),
DESC("The ACP data set rules for APF restrict UPDATE or greater access
to only z/OS systems programming personnel or trusted started tasks.")
TEST 3.access_sysp,
racf_access(id:populate_stig_syspaudt.id.id<>' '),
DESCRIPTION("Systems programming personnel."),
OTHERWISE(,
TEST 3.access_tstc,
racf_access(id:populate_stig_tstcaudt.id.id<>' '),
DESCRIPTION("Trusted started tasks."),
OTHERWISE(,
TEST 3.access_other,
racf_access(id<>" ") noncompliant,
DESC("Update or higher access must be restricted to only system pro
gramming personnel (SYSPAUDT) or trusted started tasks (TSTCAUDT).")))
ENDRULE
*/
**************************** Bottom of Data ****************************
You can save this member and test it using AU.R.T. For data sets matching the patterns you should now see the exempted test from CKAGC060 and a compliant test from MYCOC060:
Standard compliance test
Complex Ver Pr Standards NonComp Unknown Exm Sup
ZTEC 0 30 1 1 1
Standard Pr Rule sets NonComp Unknown Exm Sup Version
ZOS_MYOWNSTD 30 1 1 1 0
Rule set Pr Objects NonComp Unknown Exm Sup Caption
ACP00060 30 1890 1880 44 APF libraries protected
Non Unk Exm Class System Type VolSer Resource
Exm DATASET GENERIC ADMIN ALTER USER.*.**
Cmp Non Unk Exm Test name MembTest Test description
Cmp 3.MIDWARE_Libraries MYCOC060 Middleware maintenance mon
Cmp Exm 3.access_other CKAGC060 Update or higher access mu
******************************* Bottom of Data ********************************
Next we verify that these data sets have appropriate access controls. Remove the comment markers that we added 2 pages back.
Give the DOMAIN a label that refers to the team name, APF_MIDWARE_PERMITS, in the DOMAIN command and in the RULE command.
Change the RULE label into MYCO_ACP00060_MIDWARE_permit and change the DESC strings accordingly.
Copy the resource selection list into the DOMAIN command.
As a shortcut we’re hardcoding the list of groups and user IDs, but you should consider using an installation maintained allowlist member. Until you have such a member, remove the ALLOWLIST parameter in the DOMAIN.
DOMAIN APF_MIDWARE_PERMITS,
SELECT(racf_access(access=(UPDATE,CONTROL,ALTER),
class=DATASET,
priv_senstype=:APF,
resource=(,
MIDWARE.**,
USER.**,
),
id<>('-UACC-'c,'*'c,'- any -'c)))
RULE MYCO_ACP00060_MIDWARE_permit domain(APF_MIDWARE_PERMITS),
SET(ACP00060),
DESC("The ACP data set rules for middleware restrict UPDATE or greater
access to the MIDDLEWARE team.")
TEST 3.access_MIDWARE,
racf_access(id=(,
ADMIN,
APPL,
SUPPORT)),
DESCRIPTION("Middleware maintenance team."),
OTHERWISE(,
TEST 3.access_other,
racf_access(id<>" ") noncompliant,
DESC("Update or higher access must be restricted to the appropriate
Middleware maintenance team."))
ENDRULE
**************************** Bottom of Data ****************************
When you test this member, you will now see that any remaining system programmers in the ACL are now flagged as non-compliant. This can be fixed by re-inserting TEST 3.access_sysp, or a similar member.
You could also centralize your list of data set patterns in a new member MYCO@DEF, and include this from C2RG@IDF.
MYCOSEC.STIG.CARLA(MYCO@DEF) - 01.01 Columns 00001 00072
***************************** Top of Data ******************************
define type=racf_access only_MIDWARE boolean where not(resource<>(,
MIDWARE.**,
USER.**,
))
**************************** Bottom of Data ****************************
Next, replace the list of patterns with the name of this defined field:
MYCOSEC.STIG.CARLA(MYCOC060) - 01.06 Columns 00001 00072
***************************** Top of Data ******************************
imbed m=ckagc060 nodup
RULE MYCO_ACP00060_permit domain(APF_PERMITS),
SET(ACP00060),
DESC("The ACP data set rules for APF restrict UPDATE or greater access
to only z/OS systems programming personnel or trusted started tasks.")
TEST 3.access_sysp,
racf_access(id:populate_stig_syspaudt.id.id<>' '),
DESCRIPTION("Systems programming personnel."),
OTHERWISE(,
TEST 3.access_tstc,
racf_access(id:populate_stig_tstcaudt.id.id<>' '),
DESCRIPTION("Trusted started tasks."),
OTHERWISE(,
TEST 3.MIDWARE_Libraries,
racf_access(only_MIDWARE),
DESCRIPTION("Middleware maintenance monitored in separate rule."),
OTHERWISE(,
TEST 3.access_other,
racf_access(id<>" ") noncompliant,
DESC("Update or higher access must be restricted to only system pro
gramming personnel (SYSPAUDT) or trusted started tasks (TSTCAUDT)."))))
ENDRULE
DOMAIN APF_MIDWARE_PERMITS,
SELECT(racf_access(access=(UPDATE,CONTROL,ALTER),
class=DATASET,
priv_senstype=:APF,
resource=(only_MIDWARE),
id<>('-UACC-'c,'*'c,'- any -'c)))
RULE MYCO_ACP00060_MIDWARE_permit domain(APF_MIDWARE_PERMITS),
SET(ACP00060),
DESC("The ACP data set rules for middleware restrict UPDATE or greater
access to the MIDDLEWARE team.")
TEST 3.access_MIDWARE,
racf_access(id=(,
ADMIN,
APPL,
SUPPORT)),
DESCRIPTION("Middleware maintenance team."),
OTHERWISE(,
TEST 3.access_other,
racf_access(id<>" ") noncompliant,
DESC("Update or higher access must be restricted to the appropriate
Middleware maintenance team."))
ENDRULE
**************************** Bottom of Data ****************************
To create an allowlist member, create a member, e.g., $MIDWARE, in CKACUST. To prevent future conflicts, start the member name with a national character. Add user IDs and group names related to this team, one entry per line.
Edit member C2RG@IDF in CKACUST, add a line
MYCOSEC.STIG.CKACUST(C2RG@IDF) - 01.04 Columns 00001 00072
***************************** Top of Data ******************************
/* This member is used for site customization for addition */
/* of AU.R population members in the STIG standard. */
/* Insert here DEFTYPE statements. */
/* This member is NOT the place to add rules. */
/* Use C%%%@INS members for that. */
/* See also: SCKRCARL(C2RG@DEF) (STIG DEFTYPEs) */
/* CKACUST(C%%G@INS) (Customization members) */
IMBED M=MYCO@OVR /* Load OVERRIDE statements from CARLA lib */
IMBED M=MYCO@IDF /* Load DEFTYPE statements from CARLA lib */
IMBED M=MYCO@DEF /* DEFINE commands for local patterns */
**************************** Bottom of Data ****************************
Then add the newly named member in STIG.CARLA
MYCOSEC.STIG.CARLA(MYCO@IDF) - 01.00 Columns 00001 00072
***************************** Top of Data ******************************
DEFTYPE TYPE=POPULATE_MYCO_$MIDWARE NOWARN COL1COM='*'
ALLOC TYPE=POPULATE_MYCO_$MIDWARE DD=CKA@CUST($MIDWARE)
DEFINE TYPE=POPULATE_MYCO_$MIDWARE ID AS SUBSTR(RECORD,1,8)
**************************** Bottom of Data ****************************
Finally, replace the user ID test in MYCOC060 with a lookup:
TEST 3.access_MIDWARE,
racf_access(id:populate_MYCO_$MIDWARE.id.id<>' '),
DESCRIPTION("Middleware maintenance team."),
OTHERWISE(……)
To separate out the applications into multiple teams, a DOMAIN and a RULE command must be built for each team. Remember to add a similar <> test in the first RULE block too.
Data set name patterns cannot be stored in allow lists, they are only recognized in CARLa commands.
Finally, do not copy code segments from this paper, but find the relevant rule member from your SCKRCARL library. This contains the current CARLa statements with maintenance updates that may be missing from the paper.
[1] Allowlist members, or allow lists, contain user IDs, logon IDs and group names. Config lookup members contain other values, including long values like global access table entries and certificate related information. These members can be listed using option AU.R.C.
[2] You can edit the CKACUST data set directly, or use AU.R.C “Configure”, selecting the checkbox for
Configuration of user and group IDs in domain allowlist members.