There are a couple of security definitions which are required for the EKMF Web Liberty server. You need to define started tasks for the Liberty server itself and the Angel server. In addition, you must authorize the WebShere Liberty server to access these services:
See Configuring security for z/OS Connect and Enabling z/OS authorized services on Liberty for z/OS for details.
You must define a STARTED class profile for the Liberty server so that the server is started as a z/OS started task.
The example has the following assumptions:
EKMFSVR procedure starts the serverLIBSRV is the user ID for the Liberty serverRDEFINE STARTED EKMFSVR.* OWNER('<owner>') UACC(NONE) STDATA(USER(LIBSRV) +
GROUP(LIBSRVGP) PRIVILEGED(NO) TRUSTED(NO) TRACE(YES))
SETROPTS RACLIST(STARTED) GENERIC(STARTED) REFRESH
The server user ID must also have write access to files in the $WLP_USER_DIR directory.
You must define a STARTED class profile for the Liberty Angel process so that the process is started as a z/OS started task.
The example has the following assumptions:
BBGZANGL procedure starts the serverLIBSRV is the user ID for the Liberty server RDEFINE STARTED BBGZANGL.* OWNER('<owner>') UACC(NONE) STDATA(USER(LIBSRV) +
GROUP(LIBSRVGP) PRIVILEGED(NO) TRUSTED(NO) TRACE(NO))
SETROPTS RACLIST(STARTED) GENERIC(STARTED) REFRESH
RDEFINE SERVER BBG.ANGEL OWNER('<owner>') UACC(NONE)
PERMIT BBG.ANGEL CLASS(SERVER) ACCESS(READ) ID(LIBSRV)
RDEFINE SERVER BBG.AUTHMOD.BBGZSAFM OWNER('<owner>') UACC(NONE)
PERMIT BBG.AUTHMOD.BBGZSAFM CLASS(SERVER) ACCESS(READ) ID(LIBSRV)
RDEFINE SERVER BBG.AUTHMOD.BBGZSAFM.SAFCRED OWNER('<owner>') UACC(NONE)
PERMIT BBG.AUTHMOD.BBGZSAFM.SAFCRED CLASS(SERVER) ACCESS(READ) ID(LIBSRV)
RDEFINE SERVER BBG.AUTHMOD.BBGZSAFM.ZOSWLM UACC(NONE)
PERMIT BBG.AUTHMOD.BBGZSAFM.ZOSWLM CLASS(SERVER) ACCESS(READ) ID(LIBSRV)
RDEFINE SERVER BBG.AUTHMOD.BBGZSAFM.TXRRS UACC(NONE)
PERMIT BBG.AUTHMOD.BBGZSAFM.TXRRS CLASS(SERVER) ACCESS(READ) ID(LIBSRV)
RDEFINE SERVER BBG.AUTHMOD.BBGZSAFM.ZOSDUMP UACC(NONE)
PERMIT BBG.AUTHMOD.BBGZSAFM.ZOSDUMP CLASS(SERVER) ACCESS(READ) ID(LIBSRV)
RDEFINE SERVER BBG.AUTHMOD.BBGZSAFM.LOCALCOM UACC(NONE)
PERMIT BBG.AUTHMOD.BBGZSAFM.LOCALCOM CLASS(SERVER) ACCESS(READ) ID(LIBSRV)
RDEFINE SERVER BBG.AUTHMOD.BBGZSAFM.WOLA UACC(NONE)
PERMIT BBG.AUTHMOD.BBGZSAFM.WOLA CLASS(SERVER)ACCESS(READ) ID(LIBSRV)
RDEFINE SERVER BBG.AUTHMOD.BBGZSAFM.PRODMGR UACC(NONE)
PERMIT BBG.AUTHMOD.BBGZSAFM.PRODMGR CLASS(SERVER) ACCESS(READ) ID(LIBSRV)
RDEFINE SERVER BBG.AUTHMOD.BBGZSAFM.ZOSAIO UACC(NONE)
PERMIT BBG.AUTHMOD.BBGZSAFM.ZOSAIO CLASS(SERVER) ACCESS(READ) ID(LIBSRV)
RDEFINE SERVER BBG.AUTHMOD.BBGZSCFM.WOLA UACC(NONE)
PERMIT BBG.AUTHMOD.BBGZSCFM.WOLA CLASS(SERVER) ACCESS(READ) ID(LIBSRV)
SETROPTS RACLIST(SERVER) REFRESH
The user ID for the Liberty server must have READ access to the EKMF Web prefix.
RDEFINE SERVER BBG.SECPFX.EKMFWEB OWNER('<owner>') UACC(NONE)
PERMIT BBG.SECPFX.EKMFWEB CLASS(SERVER) ACCESS(READ) ID(LIBSRV)
SETROPTS RACLIST(SERVER) REFRESH
The unauthenticated user ID for the Liberty server (WSGUEST by default) requires READ access to the EKMFWEB application id in the APPL class:
ADDUSER WSGUEST RESTRICTED NOPASSWORD NOOIDCARD +
NAME('WAS DEFAULT USER ') +
OWNER(WSCLGP) +
OMVS( autouid +
HOME('/local/WebSphere/home/WSCLGP') +
PROGRAM('/bin/sh') +
) +
DFLTGRP(WSCLGP)
CONNECT WSGUEST GROUP(WSCLGP) OWNER(WSCLGP) AUTH(USE) UACC(NONE)
RDEFINE APPL EKMFWEB UACC(NONE)
PERMIT EKMFWEB CLASS(APPL) ACCESS(READ) ID(WSGUEST)
SETROPTS REFRESH RACLIST(APPL)
In a similar way, you must grant READ access to the EKMFWEB application id in the APPL class for all users who need to use EKMF Web.
You should define a generic application profile in the EJBROLE class with UACC(NONE) and no users in the access list. This is to ensure that future upgrades to the application will not accidentally grant users access to new
roles until the resources have specifically been defined in RACF. For authentication purposes, two additional profiles in the EJBROLE class need to be defined and all users should have READ access to these last two resources.
RDEFINE EJBROLE EKMFWEB.*.* OWNER('<owner>') UACC(NONE)
RDEFINE EJBROLE EKMFWEB.ekmf-rest-api.authenticated OWNER('<owner>') UACC(NONE)
RDEFINE EJBROLE EKMFWEB.com.ibm.ws.security.oauth20.* OWNER('<owner>') UACC(NONE)
PERMIT EKMFWEB.ekmf-rest-api.authenticated CLASS(EJBROLE) ACCESS(READ) ID(*)
PERMIT EKMFWEB.com.ibm.ws.security.oauth20.* CLASS(EJBROLE) ACCESS(READ) ID(*)
SETROPTS REFRESH RACLIST(EJBROLE)
The Liberty server user ID must have READ access to list SAF key rings.
RDEFINE FACILITY IRR.DIGTCERT.LISTRING OWNER('<owner>') UACC(NONE)
PERMIT IRR.DIGTCERT.LISTRING CLASS(FACILITY) ACCESS(READ) +
ID(LIBSRV)
SETROPTS RACLIST(FACILITY) REFRESH
EKMF Web uses SSL/TLS for all communication.
Use the RACDCERT GENCERT command to create server certificates. The following example assumes that the WebSphere Liberty server user ID is LIBSRV. Change www.example.com to match the server to which you want to
deploy EKMF Web.
SETROPTS CLASSACT(DIGTCERT)
RACDCERT CERTAUTH GENCERT +
SUBJECTSDN(CN('EKMF Web CA') OU('Liberty') O('IBM')) +
WITHLABEL('EkmfWebLibertyCA') +
NOTAFTER(DATE(2028-12-31) TIME(23:59:59)) +
RSA SIZE(2048)
RACDCERT ID(LIBSRV) GENCERT +
SUBJECTSDN(CN('www.example.com') OU('Liberty') O('IBM')) +
WITHLABEL('EkmfWebLibertyServer') +
SIGNWITH(CERTAUTH LABEL('EkmfWebLibertyCA')) +
NOTAFTER(DATE(2023-12-31) TIME(23:59:59)) +
RSA SIZE(2048)
RACDCERT ID(LIBSRV) GENCERT +
SUBJECTSDN(CN('EkmfWebLibertyOpenID') OU('Liberty') O('IBM')) +
WITHLABEL('EkmfWebLibertyOpenID') +
SIGNWITH(CERTAUTH LABEL('EkmfWebLibertyCA')) +
NOTAFTER(DATE(2023-12-31) TIME(23:59:59)) +
RSA SIZE(2048)
SETROPTS RACLIST(DIGTCERT) REFRESH
Add the server certificates to a SAF key ring.
SETROPTS CLASSACT(DIGTRING)
RACDCERT ID(LIBSRV) ADDRING(EkmfKeyRing)
RACDCERT ID(LIBSRV) CONNECT(LABEL('EkmfWebLibertyServer') +
RING (EkmfKeyRing) DEFAULT USAGE(PERSONAL))
RACDCERT ID(LIBSRV) CONNECT(LABEL('EkmfWebLibertyOpenID') +
RING (EkmfKeyRing) USAGE(PERSONAL))
RACDCERT ID(LIBSRV) CONNECT(CERTAUTH LABEL('EkmfWebLibertyCA') +
RING(EkmfKeyRing) USAGE(CERTAUTH))
SETROPTS RACLIST(DIGTRING) REFRESH
Create a data set for the CA certificate and export it for installation into a client browser or application truststore. Alternatively use your browser on logon to EKMF Web to download the certificate via the security icon. Change HLQ into
your high-level qualifier.
RACDCERT CERTAUTH EXPORT (LABEL('EkmfWebLibertyCA')) +
DSN ('HLQ.LIBSRV.CERT') FORMAT(CERTDER)
Enable the Liberty user to use the key ring:
RDEFINE RDATALIB LIBSRV.EKMFKEYRING.LST OWNER('<owner>') UACC(NONE)
PERMIT LIBSRV.EKMFKEYRING.LST CLASS(RDATALIB) +
ACCESS(READ) ID(LIBSRV)
SETROPTS RACLIST(RDATALIB) REFRESH
For cloud keystore connections we need to add the CA certificates to RACF. Upload the certificate to a VB LRECL=84 dataset and add to RACF. In the command below we assume the dataset name is '<HLQ>.CA.CERT'.
To obtain the root certificates for cloud vendors:
At the time of writing these instructions, the certificates for IBM and Microsoft were provided by DigiCert.
SETROPTS CLASSACT(DIGTCERT)
RACDCERT CERTAUTH ADD('<HLQ>.CA.CERT') +
WITHLABEL('DIGICERT-ROOT-CA') TRUST
SETROPTS RACLIST(DIGTCERT) REFRESH
The z/OS user ID (LIBSRV) that is associated with the EKMF Web server must be authorized to ICSF services. For detailed information about ICSF authorization, see the following page: Cryptographic Support Downloads for IBM z/OS.
For a full description of the ICSF functions and ACPS, refer to the ICSF and ACP Reference.
The z/OS user ID (LIBSRV) needs access to the following profiles in the CSFSERV class:
It is recommended that you establish a generic profile to protect all the CSFSERV resources that are not in use. If this has not been done yet, you could use for example the following command
RDEFINE CSFSERV ** OWNER(<owner>) UACC(NONE)
After that, you need to grant access to each required ICSF resource. For example, to grant access to the CSFDSG service:
RDEFINE CSFSERV CSFDSG OWNER(<owner>) UACC(NONE)
PERMIT CSFDSG CLASS(CSFSERV) ACCESS(READ) ID(LIBSERV)
This has to be repeated for all required ICSF resources. At the end, issue a REFRESH command:
SETROPTS RACLIST(CSFSERV) REFRESH
In addition, the following Access Control Points must be enabled in the crypto card:
Depending on the naming standards of the key labels in use, the user ID for the Liberty server must have permission for CONTROL access to CSFKEYS class profiles. This level of access enables the Liberty Server user ID to administer
the keys. The actual commands depend on existing profiles in the CSFKEYS class. The following example shows how to define a CSFKEYS profile. This example profile limits this user ID to administering key labels that begin
with the letter 'T' only. (The actual users of the 'T' key labels most likely need only READ access.)
RDEFINE CSFKEYS T* OWNER('<owner>') UACC(NONE) ICSF(SYMCPACFWRAP(YES),SYMCPACFRET(YES))
PERMIT T* CLASS(CSFKEYS) ACCESS(CONTROL) ID(LIBSRV)
SETROPTS RACLIST(CSFKEYS) REFRESH
If ICSF keystore policy checking is active and the CSF.PKDS.TOKEN.CHECK.DEFAULT.LABEL resource in XFACILIT class is defined, the CSF-PKDS-DEFAULT resource in CSFKEYS class must also be defined and
the user ID for the Liberty server must have READ access.