From 42f689fa9ff3e513b2c5ed4236ca36cedfdc7e70 Mon Sep 17 00:00:00 2001 From: Vit Tomica Date: Wed, 19 Feb 2020 13:52:05 +0100 Subject: [PATCH 01/37] keyring support using keytool utility Signed-off-by: Vit Tomica --- bin/apiml_cm.sh | 187 +++++++++++++++++++++++--------- bin/zowe-setup-certificates.env | 3 + bin/zowe-setup-certificates.sh | 70 +++++++++--- 3 files changed, 193 insertions(+), 67 deletions(-) diff --git a/bin/apiml_cm.sh b/bin/apiml_cm.sh index 471ceffbcf..b3f679a1bf 100644 --- a/bin/apiml_cm.sh +++ b/bin/apiml_cm.sh @@ -59,11 +59,14 @@ EXTERNAL_CERTIFICATE= EXTERNAL_CERTIFICATE_ALIAS= ZOSMF_CERTIFICATE= +ZOWE_USERID=ZWESVUSR +ZOWE_KEYRING=ZWERING + ALIAS="alias" CERTIFICATE="no-certificate-specified" if [ -z ${TEMP_DIR+x} ]; then - TEMP_DIR=/tmp + TEMP_DIR=${TMPDIR:-/tmp} fi function pkeytool { @@ -90,16 +93,26 @@ function clean_service { } function create_certificate_authority { - echo "Generate keystore with the local CA private key and local CA public certificate:" - pkeytool -genkeypair $V -alias ${LOCAL_CA_ALIAS} -keyalg RSA -keysize 2048 -keystore ${LOCAL_CA_FILENAME}.keystore.p12 \ - -dname "${LOCAL_CA_DNAME}" -keypass ${LOCAL_CA_PASSWORD} -storepass ${LOCAL_CA_PASSWORD} -storetype PKCS12 -validity ${LOCAL_CA_VALIDITY} \ - -ext KeyUsage="keyCertSign" -ext BasicConstraints:"critical=ca:true" - chmod 600 ${LOCAL_CA_FILENAME}.keystore.p12 - - echo "Export local CA public certificate:" - pkeytool -export $V -alias ${LOCAL_CA_ALIAS} -file ${LOCAL_CA_FILENAME}.cer -keystore ${LOCAL_CA_FILENAME}.keystore.p12 -rfc \ - -keypass ${LOCAL_CA_PASSWORD} -storepass ${LOCAL_CA_PASSWORD} -storetype PKCS12 - + if [[ "${SERVICE_STORETYPE}" == "JCERACFKS" ]]; then + echo "Generate keyring with the local CA private key and local CA public certificate:" + pkeytool -genkeypair $V -alias ${LOCAL_CA_ALIAS} -keyalg RSA -keysize 2048 -keystore safkeyring://${ZOWE_USERID}/${ZOWE_KEYRING} \ + -dname "${LOCAL_CA_DNAME}" -storetype ${SERVICE_STORETYPE} -validity ${LOCAL_CA_VALIDITY} \ + -ext KeyUsage="keyCertSign" -ext BasicConstraints:"critical=ca:true" -J-Djava.protocol.handler.pkgs=com.ibm.crypto.provider + + echo "Export local CA public certificate:" + pkeytool -export $V -alias ${LOCAL_CA_ALIAS} -file ${LOCAL_CA_FILENAME}.cer -keystore safkeyring://${ZOWE_USERID}/${ZOWE_KEYRING} -rfc \ + -storetype ${SERVICE_STORETYPE} -J-Djava.protocol.handler.pkgs=com.ibm.crypto.provider + else + echo "Generate keystore with the local CA private key and local CA public certificate:" + pkeytool -genkeypair $V -alias ${LOCAL_CA_ALIAS} -keyalg RSA -keysize 2048 -keystore ${LOCAL_CA_FILENAME}.keystore.p12 \ + -dname "${LOCAL_CA_DNAME}" -keypass ${LOCAL_CA_PASSWORD} -storepass ${LOCAL_CA_PASSWORD} -storetype ${SERVICE_STORETYPE} -validity ${LOCAL_CA_VALIDITY} \ + -ext KeyUsage="keyCertSign" -ext BasicConstraints:"critical=ca:true" + chmod 600 ${LOCAL_CA_FILENAME}.keystore.p12 + + echo "Export local CA public certificate:" + pkeytool -export $V -alias ${LOCAL_CA_ALIAS} -file ${LOCAL_CA_FILENAME}.cer -keystore ${LOCAL_CA_FILENAME}.keystore.p12 -rfc \ + -keypass ${LOCAL_CA_PASSWORD} -storepass ${LOCAL_CA_PASSWORD} -storetype ${SERVICE_STORETYPE} + fi if [ `uname` = "OS/390" ]; then iconv -f ISO8859-1 -t IBM-1047 ${LOCAL_CA_FILENAME}.cer > ${LOCAL_CA_FILENAME}.cer-ebcdic fi @@ -122,15 +135,25 @@ function add_external_ca { } function create_service_certificate_and_csr { - if [ ! -e "${SERVICE_KEYSTORE}.p12" ]; - then - echo "Generate service private key and service:" - pkeytool -genkeypair $V -alias ${SERVICE_ALIAS} -keyalg RSA -keysize 2048 -keystore ${SERVICE_KEYSTORE}.p12 -keypass ${SERVICE_PASSWORD} -storepass ${SERVICE_PASSWORD} \ - -storetype PKCS12 -dname "${SERVICE_DNAME}" -validity ${SERVICE_VALIDITY} - - echo "Generate CSR for the the service certificate:" - pkeytool -certreq $V -alias ${SERVICE_ALIAS} -keystore ${SERVICE_KEYSTORE}.p12 -storepass ${SERVICE_PASSWORD} -file ${SERVICE_KEYSTORE}.csr \ - -keyalg RSA -storetype PKCS12 -dname "${SERVICE_DNAME}" -validity ${SERVICE_VALIDITY} + if [[ "${SERVICE_STORETYPE}" == "JCERACFKS" ]]; then + echo "Generate service private key and service into the keyring:" + pkeytool -genkeypair $V -alias ${SERVICE_ALIAS} -keyalg RSA -keysize 2048 -keystore safkeyring://${ZOWE_USERID}/${ZOWE_KEYRING} \ + -storetype ${SERVICE_STORETYPE} -dname "${SERVICE_DNAME}" -validity ${SERVICE_VALIDITY} -J-Djava.protocol.handler.pkgs=com.ibm.crypto.provider + + echo "Generate CSR for the service certificate in the keyring:" + pkeytool -certreq $V -alias ${SERVICE_ALIAS} -keystore safkeyring://${ZOWE_USERID}/${ZOWE_KEYRING} -file ${SERVICE_KEYSTORE}.csr \ + -keyalg RSA -storetype ${SERVICE_STORETYPE} -dname "${SERVICE_DNAME}" -validity ${SERVICE_VALIDITY} -J-Djava.protocol.handler.pkgs=com.ibm.crypto.provider + else + if [ ! -e "${SERVICE_KEYSTORE}.p12" ]; + then + echo "Generate service private key and service:" + pkeytool -genkeypair $V -alias ${SERVICE_ALIAS} -keyalg RSA -keysize 2048 -keystore ${SERVICE_KEYSTORE}.p12 -keypass ${SERVICE_PASSWORD} -storepass ${SERVICE_PASSWORD} \ + -storetype ${SERVICE_STORETYPE} -dname "${SERVICE_DNAME}" -validity ${SERVICE_VALIDITY} + + echo "Generate CSR for the the service certificate:" + pkeytool -certreq $V -alias ${SERVICE_ALIAS} -keystore ${SERVICE_KEYSTORE}.p12 -storepass ${SERVICE_PASSWORD} -file ${SERVICE_KEYSTORE}.csr \ + -keyalg RSA -storetype ${SERVICE_STORETYPE} -dname "${SERVICE_DNAME}" -validity ${SERVICE_VALIDITY} + fi fi } @@ -145,16 +168,25 @@ function create_self_signed_service { } function sign_csr_using_local_ca { - echo "Sign the CSR using the Certificate Authority:" - pkeytool -gencert $V -infile ${SERVICE_KEYSTORE}.csr -outfile ${SERVICE_KEYSTORE}_signed.cer -keystore ${LOCAL_CA_FILENAME}.keystore.p12 \ - -alias ${LOCAL_CA_ALIAS} -keypass ${LOCAL_CA_PASSWORD} -storepass ${LOCAL_CA_PASSWORD} -storetype PKCS12 \ - -ext ${SERVICE_EXT} -ext KeyUsage:critical=keyEncipherment,digitalSignature,nonRepudiation,dataEncipherment -ext ExtendedKeyUsage=clientAuth,serverAuth -rfc \ - -validity ${SERVICE_VALIDITY} + echo "Sign the CSR using the Certificate Authority:" + if [[ "${SERVICE_STORETYPE}" == "JCERACFKS" ]]; then + pkeytool -gencert $V -infile ${SERVICE_KEYSTORE}.csr -outfile ${SERVICE_KEYSTORE}_signed.cer -keystore safkeyring://${ZOWE_USERID}/${ZOWE_KEYRING} \ + -alias ${LOCAL_CA_ALIAS} -storetype ${SERVICE_STORETYPE} \ + -ext ${SERVICE_EXT} -ext KeyUsage:critical=keyEncipherment,digitalSignature,nonRepudiation,dataEncipherment -ext ExtendedKeyUsage=clientAuth,serverAuth -rfc \ + -validity ${SERVICE_VALIDITY} -J-Djava.protocol.handler.pkgs=com.ibm.crypto.provider + else + pkeytool -gencert $V -infile ${SERVICE_KEYSTORE}.csr -outfile ${SERVICE_KEYSTORE}_signed.cer -keystore ${LOCAL_CA_FILENAME}.keystore.p12 \ + -alias ${LOCAL_CA_ALIAS} -keypass ${LOCAL_CA_PASSWORD} -storepass ${LOCAL_CA_PASSWORD} -storetype ${SERVICE_STORETYPE} \ + -ext ${SERVICE_EXT} -ext KeyUsage:critical=keyEncipherment,digitalSignature,nonRepudiation,dataEncipherment -ext ExtendedKeyUsage=clientAuth,serverAuth -rfc \ + -validity ${SERVICE_VALIDITY} + fi } function import_local_ca_certificate { - echo "Import the local Certificate Authority to the truststore:" - pkeytool -importcert $V -trustcacerts -noprompt -file ${LOCAL_CA_FILENAME}.cer -alias ${LOCAL_CA_ALIAS} -keystore ${SERVICE_TRUSTSTORE}.p12 -storepass ${SERVICE_PASSWORD} -storetype PKCS12 + if [[ "${SERVICE_STORETYPE}" == "PKCS12" ]]; then + echo "Import the local Certificate Authority to the truststore:" + pkeytool -importcert $V -trustcacerts -noprompt -file ${LOCAL_CA_FILENAME}.cer -alias ${LOCAL_CA_ALIAS} -keystore ${SERVICE_TRUSTSTORE}.p12 -storepass ${SERVICE_PASSWORD} -storetype ${SERVICE_STORETYPE} + fi } function import_external_ca_certificates { @@ -170,11 +202,17 @@ function import_external_ca_certificates { } function import_signed_certificate { - echo "Import the Certificate Authority to the keystore:" - pkeytool -importcert $V -trustcacerts -noprompt -file ${LOCAL_CA_FILENAME}.cer -alias ${LOCAL_CA_ALIAS} -keystore ${SERVICE_KEYSTORE}.p12 -storepass ${SERVICE_PASSWORD} -storetype PKCS12 + if [[ "${SERVICE_STORETYPE}" == "JCERACFKS" ]]; then + echo "Import the signed CSR to the keystore:" + pkeytool -importcert $V -trustcacerts -noprompt -file ${SERVICE_KEYSTORE}_signed.cer -alias ${SERVICE_ALIAS} -keystore safkeyring://${ZOWE_USERID}/${ZOWE_KEYRING} -storetype ${SERVICE_STORETYPE} \ + -J-Djava.protocol.handler.pkgs=com.ibm.crypto.provider + else + echo "Import the Certificate Authority to the keystore:" + pkeytool -importcert $V -trustcacerts -noprompt -file ${LOCAL_CA_FILENAME}.cer -alias ${LOCAL_CA_ALIAS} -keystore ${SERVICE_KEYSTORE}.p12 -storepass ${SERVICE_PASSWORD} -storetype ${SERVICE_STORETYPE} - echo "Import the signed CSR to the keystore:" - pkeytool -importcert $V -trustcacerts -noprompt -file ${SERVICE_KEYSTORE}_signed.cer -alias ${SERVICE_ALIAS} -keystore ${SERVICE_KEYSTORE}.p12 -storepass ${SERVICE_PASSWORD} -storetype PKCS12 + echo "Import the signed CSR to the keystore:" + pkeytool -importcert $V -trustcacerts -noprompt -file ${SERVICE_KEYSTORE}_signed.cer -alias ${SERVICE_ALIAS} -keystore ${SERVICE_KEYSTORE}.p12 -storepass ${SERVICE_PASSWORD} -storetype ${SERVICE_STORETYPE} + fi } function import_external_certificate { @@ -189,15 +227,27 @@ function import_external_certificate { fi if [ -n "${EXTERNAL_CERTIFICATE}" ]; then - echo "Import the signed certificate and its private key to the keystore:" - pkeytool -importkeystore $V -deststorepass ${SERVICE_PASSWORD} -destkeypass ${SERVICE_PASSWORD} -destkeystore ${SERVICE_KEYSTORE}.p12 -deststoretype PKCS12 -destalias ${SERVICE_ALIAS} \ - -srckeystore ${EXTERNAL_CERTIFICATE} -srcstoretype PKCS12 -srcstorepass ${SERVICE_PASSWORD} -keypass ${SERVICE_PASSWORD} -srcalias ${EXTERNAL_CERTIFICATE_ALIAS} + if [[ "${SERVICE_STORETYPE}" == "JCERACFKS" ]]; then + echo "Import the signed certificate and its private key to the keyring:" + pkeytool -importkeystore $V -destkeystore safkeyring://${ZOWE_USERID}/${ZOWE_KEYRING} -deststoretype ${SERVICE_STORETYPE} -destalias ${SERVICE_ALIAS} \ + -srckeystore ${EXTERNAL_CERTIFICATE} -srcstoretype PKCS12 -srcstorepass ${SERVICE_PASSWORD} -srcalias ${EXTERNAL_CERTIFICATE_ALIAS} \ + -J-Djava.protocol.handler.pkgs=com.ibm.crypto.provider + else + echo "Import the signed certificate and its private key to the keystore:" + pkeytool -importkeystore $V -deststorepass ${SERVICE_PASSWORD} -destkeypass ${SERVICE_PASSWORD} -destkeystore ${SERVICE_KEYSTORE}.p12 -deststoretype ${SERVICE_STORETYPE} -destalias ${SERVICE_ALIAS} \ + -srckeystore ${EXTERNAL_CERTIFICATE} -srcstoretype PKCS12 -srcstorepass ${SERVICE_PASSWORD} -keypass ${SERVICE_PASSWORD} -srcalias ${EXTERNAL_CERTIFICATE_ALIAS} + fi fi } function export_service_certificate { echo "Export service certificate to the PEM format" - pkeytool -exportcert -alias ${SERVICE_ALIAS} -keystore ${SERVICE_KEYSTORE}.p12 -storetype PKCS12 -storepass ${SERVICE_PASSWORD} -rfc -file ${SERVICE_KEYSTORE}.cer + if [[ "${SERVICE_STORETYPE}" == "JCERACFKS" ]]; then + pkeytool -exportcert -alias ${SERVICE_ALIAS} -keystore safkeyring://${ZOWE_USERID}/${ZOWE_KEYRING} -storetype ${SERVICE_STORETYPE} -rfc -file ${SERVICE_KEYSTORE}.cer \ + -J-Djava.protocol.handler.pkgs=com.ibm.crypto.provider + else + pkeytool -exportcert -alias ${SERVICE_ALIAS} -keystore ${SERVICE_KEYSTORE}.p12 -storetype ${SERVICE_STORETYPE} -storepass ${SERVICE_PASSWORD} -rfc -file ${SERVICE_KEYSTORE}.cer + fi if [ `uname` = "OS/390" ]; then iconv -f ISO8859-1 -t IBM-1047 ${SERVICE_KEYSTORE}.cer > ${SERVICE_KEYSTORE}.cer-ebcdic @@ -215,9 +265,10 @@ import java.io.FileWriter; import java.security.Key; import java.security.KeyStore; import java.util.Base64; +import com.ibm.crypto.provider.RACFInputStream; public class ExportPrivateKey { - private File keystoreFile; + private String keystoreName; private String keyStoreType; private char[] keyStorePassword; private char[] keyPassword; @@ -226,7 +277,13 @@ public class ExportPrivateKey { public void export() throws Exception { KeyStore keystore = KeyStore.getInstance(keyStoreType); - keystore.load(new FileInputStream(keystoreFile), keyStorePassword); + if ("JCERACFKS".equalsIgnoreCase(keyStoreType)) { + String splits[] = keystoreName.replaceFirst("safkeyring://", "").split("/"); + keystore.load(new RACFInputStream(splits[0], splits[1], keyStorePassword), keyStorePassword); + + } else { + keystore.load(new FileInputStream(new File(keystoreName)), keyStorePassword); + } Key key = keystore.getKey(alias, keyPassword); String encoded = Base64.getEncoder().encodeToString(key.getEncoded()); FileWriter fw = new FileWriter(exportedFile); @@ -244,7 +301,7 @@ public class ExportPrivateKey { public static void main(String args[]) throws Exception { ExportPrivateKey export = new ExportPrivateKey(); - export.keystoreFile = new File(args[0]); + export.keystoreName = args[0]; export.keyStoreType = args[1]; export.keyStorePassword = args[2].toCharArray(); export.alias = args[3]; @@ -257,12 +314,17 @@ EOF echo "cat returned $?" javac ${TEMP_DIR}/ExportPrivateKey.java echo "javac returned $?" - java -cp ${TEMP_DIR} ExportPrivateKey ${SERVICE_KEYSTORE}.p12 PKCS12 ${SERVICE_PASSWORD} ${SERVICE_ALIAS} ${SERVICE_PASSWORD} ${SERVICE_KEYSTORE}.key + if [[ "${SERVICE_STORETYPE}" == "JCERACFKS" ]]; then + java -Djava.protocol.handler.pkgs=com.ibm.crypto.provider \ + -cp ${TEMP_DIR} ExportPrivateKey safkeyring://${ZOWE_USERID}/${ZOWE_KEYRING} ${SERVICE_STORETYPE} "" ${SERVICE_ALIAS} "" ${SERVICE_KEYSTORE}.key + else + java -cp ${TEMP_DIR} ExportPrivateKey ${SERVICE_KEYSTORE}.p12 ${SERVICE_STORETYPE} ${SERVICE_PASSWORD} ${SERVICE_ALIAS} ${SERVICE_PASSWORD} ${SERVICE_KEYSTORE}.key + fi echo "java returned $?" rm ${TEMP_DIR}/ExportPrivateKey.java ${TEMP_DIR}/ExportPrivateKey.class } -function get_service_certificate_form_url { +function get_service_certificate_from_url { echo "Exporting service certificate" echo "TEMP_DIR=$TEMP_DIR" cat <$TEMP_DIR/GetCertificate.java @@ -361,15 +423,27 @@ function new_self_signed_service { function trust { echo "Import a certificate to the truststore:" - pkeytool -importcert $V -trustcacerts -noprompt -file ${CERTIFICATE} -alias "${ALIAS}" -keystore ${SERVICE_TRUSTSTORE}.p12 -storepass ${SERVICE_PASSWORD} -storetype PKCS12 + if [[ "${SERVICE_STORETYPE}" == "JCERACFKS" ]]; then + pkeytool -importcert $V -trustcacerts -noprompt -file ${CERTIFICATE} -alias "${ALIAS}" -keystore safkeyring://${ZOWE_USERID}/${ZOWE_KEYRING} -storetype ${SERVICE_STORETYPE} \ + -J-Djava.protocol.handler.pkgs=com.ibm.crypto.provider + else + pkeytool -importcert $V -trustcacerts -noprompt -file ${CERTIFICATE} -alias "${ALIAS}" -keystore ${SERVICE_TRUSTSTORE}.p12 -storepass ${SERVICE_PASSWORD} -storetype ${SERVICE_STORETYPE} + fi } function jwt_key_gen_and_export { echo "Generates key pair for JWT token secret and exports the public key" - pkeytool -genkeypair $V -alias ${JWT_ALIAS} -keyalg RSA -keysize 2048 -keystore ${SERVICE_KEYSTORE}.p12 \ - -dname "${SERVICE_DNAME}" -keypass ${SERVICE_PASSWORD} -storepass ${SERVICE_PASSWORD} -storetype ${SERVICE_STORETYPE} -validity ${SERVICE_VALIDITY} - pkeytool -export -rfc -alias ${JWT_ALIAS} -keystore ${SERVICE_KEYSTORE}.p12 -storepass ${SERVICE_PASSWORD} -keypass ${SERVICE_PASSWORD} -storetype ${SERVICE_STORETYPE} \ - -file ${SERVICE_KEYSTORE}.${JWT_ALIAS}.pem + if [[ "${SERVICE_STORETYPE}" == "JCERACFKS" ]]; then + pkeytool -genkeypair $V -alias ${JWT_ALIAS} -keyalg RSA -keysize 2048 -keystore safkeyring://${ZOWE_USERID}/${ZOWE_KEYRING} \ + -dname "${SERVICE_DNAME}" -storetype ${SERVICE_STORETYPE} -validity ${SERVICE_VALIDITY} -J-Djava.protocol.handler.pkgs=com.ibm.crypto.provider + pkeytool -export -rfc -alias ${JWT_ALIAS} -keystore safkeyring://${ZOWE_USERID}/${ZOWE_KEYRING} -storetype ${SERVICE_STORETYPE} \ + -file ${SERVICE_KEYSTORE}.${JWT_ALIAS}.pem -J-Djava.protocol.handler.pkgs=com.ibm.crypto.provider + else + pkeytool -genkeypair $V -alias ${JWT_ALIAS} -keyalg RSA -keysize 2048 -keystore ${SERVICE_KEYSTORE}.p12 \ + -dname "${SERVICE_DNAME}" -keypass ${SERVICE_PASSWORD} -storepass ${SERVICE_PASSWORD} -storetype ${SERVICE_STORETYPE} -validity ${SERVICE_VALIDITY} + pkeytool -export -rfc -alias ${JWT_ALIAS} -keystore ${SERVICE_KEYSTORE}.p12 -storepass ${SERVICE_PASSWORD} -keypass ${SERVICE_PASSWORD} -storetype ${SERVICE_STORETYPE} \ + -file ${SERVICE_KEYSTORE}.${JWT_ALIAS}.pem + fi } function trust_zosmf { @@ -379,10 +453,15 @@ function trust_zosmf { CER_DIR=`dirname ${SERVICE_TRUSTSTORE}/temp` mkdir -p $CER_DIR ALIAS="zosmf" - get_service_certificate_form_url + get_service_certificate_from_url for entry in "${CER_DIR}"/*; do - echo "z/OSMF certificate fingerprint:" >&5 - cat ${entry} | openssl x509 -sha1 -noout -fingerprint -subject >&5 + if [[ "$LOG" != "" ]]; then + echo "z/OSMF certificate fingerprint:" >&5 + cat ${entry} | openssl x509 -sha1 -noout -fingerprint -subject >&5 + else + echo "z/OSMF certificate fingerprint:" + cat ${entry} | openssl x509 -sha1 -noout -fingerprint -subject + fi CERTIFICATE=${entry} entry=${entry##*/} ALIAS=${entry%.cer} @@ -400,6 +479,10 @@ function trust_zosmf { fi } +function toUpperCase { + echo $1 | tr '[:lower:]' '[:upper:]' +} + while [ "$1" != "" ]; do case $1 in -a | --action ) shift @@ -445,7 +528,7 @@ while [ "$1" != "" ]; do SERVICE_TRUSTSTORE=$1 ;; --service-storetype ) shift - SERVICE_STORETYPE=$1 + SERVICE_STORETYPE=`toUpperCase $1` ;; --service-dname ) shift SERVICE_DNAME=$1 @@ -471,6 +554,12 @@ while [ "$1" != "" ]; do --zosmf-certificate ) shift ZOSMF_CERTIFICATE=$1 ;; + --zowe-keyring ) shift + ZOWE_KEYRING=$1 + ;; + --zowe-userid ) shift + ZOWE_USERID=$1 + ;; --certificate ) shift CERTIFICATE=$1 ;; diff --git a/bin/zowe-setup-certificates.env b/bin/zowe-setup-certificates.env index f006041b31..20bba2f4d8 100644 --- a/bin/zowe-setup-certificates.env +++ b/bin/zowe-setup-certificates.env @@ -26,3 +26,6 @@ KEYSTORE_ALIAS=localhost ZOWE_USER_ID=ZWESVUSR # Specify zowe user id to set up ownership of the generated certificates ZOWE_GROUP_ID=ZWEADMIN +# Specify zowe keyring that keeps zowe certificates, if not specified USS keystore +# files will be created. +ZOWE_KEYRING=ZWERING diff --git a/bin/zowe-setup-certificates.sh b/bin/zowe-setup-certificates.sh index 4c6ef06edd..24b89f7150 100644 --- a/bin/zowe-setup-certificates.sh +++ b/bin/zowe-setup-certificates.sh @@ -13,6 +13,8 @@ # - KEYSTORE_PASSWORD - a password that is used to secure EXTERNAL_CERTIFICATE keystore and # that will be also used to secure newly generated keystores for API Mediation. # - ZOWE_USER_ID - zowe user id to set up ownership of the generated certificates +# - ZOWE_KEYRING - specify zowe keyring that keeps zowe certificates, if not specified USS keystore +# files will be created. # Set up logging @@ -104,8 +106,13 @@ SAN="SAN=dns:${ZOWE_EXPLORER_HOST},ip:${ZOWE_IP_ADDRESS},dns:localhost.localdoma if [[ -z "${EXTERNAL_CERTIFICATE}" ]] || [[ -z "${EXTERNAL_CERTIFICATE_ALIAS}" ]] || [[ -z "${EXTERNAL_CERTIFICATE_AUTHORITIES}" ]]; then if [[ -z "${EXTERNAL_CERTIFICATE}" ]] && [[ -z "${EXTERNAL_CERTIFICATE_ALIAS}" ]] && [[ -z "${EXTERNAL_CERTIFICATE_AUTHORITIES}" ]]; then - ${ZOWE_ROOT_DIR}/bin/apiml_cm.sh --verbose --log $LOG_FILE --action setup --service-ext ${SAN} --service-password ${KEYSTORE_PASSWORD} \ - --service-alias ${KEYSTORE_ALIAS} --service-keystore ${KEYSTORE_PREFIX} --service-truststore ${TRUSTSTORE_PREFIX} --local-ca-filename ${LOCAL_CA_PREFIX} + if [[ -z "${ZOWE_KEYRING}" ]]; then + ${ZOWE_ROOT_DIR}/bin/apiml_cm.sh --verbose --log $LOG_FILE --action setup --service-ext ${SAN} --service-password ${KEYSTORE_PASSWORD} \ + --service-alias ${KEYSTORE_ALIAS} --service-keystore ${KEYSTORE_PREFIX} --service-truststore ${TRUSTSTORE_PREFIX} --local-ca-filename ${LOCAL_CA_PREFIX} + else + ${ZOWE_ROOT_DIR}/bin/apiml_cm.sh --verbose --log $LOG_FILE --action setup --service-ext ${SAN} --service-keystore ${KEYSTORE_PREFIX} \ + --service-alias ${KEYSTORE_ALIAS} --zowe-userid ${ZOWE_USER_ID} --zowe-keyring ${ZOWE_KEYRING} --service-storetype "JCERACFKS" --local-ca-filename ${LOCAL_CA_PREFIX} + fi RC=$? echo "apiml_cm.sh --action setup returned: $RC" >> $LOG_FILE else @@ -121,10 +128,16 @@ else EXT_CA_PARM="${EXT_CA_PARM} --external-ca ${CA} " done - ${ZOWE_ROOT_DIR}/bin/apiml_cm.sh --verbose --log $LOG_FILE --action setup --service-ext ${SAN} --service-password ${KEYSTORE_PASSWORD} \ - --external-certificate ${EXTERNAL_CERTIFICATE} --external-certificate-alias ${EXTERNAL_CERTIFICATE_ALIAS} ${EXT_CA_PARM} \ - --service-alias ${KEYSTORE_ALIAS} --service-keystore ${KEYSTORE_PREFIX} --service-truststore ${TRUSTSTORE_PREFIX} --local-ca-filename ${LOCAL_CA_PREFIX} \ - --external-ca-filename ${EXTERNAL_CA_PREFIX} + if [[ -z "${ZOWE_KEYRING}" ]]; then + ${ZOWE_ROOT_DIR}/bin/apiml_cm.sh --verbose --log $LOG_FILE --action setup --service-ext ${SAN} --service-password ${KEYSTORE_PASSWORD} \ + --external-certificate ${EXTERNAL_CERTIFICATE} --external-certificate-alias ${EXTERNAL_CERTIFICATE_ALIAS} ${EXT_CA_PARM} \ + --service-alias ${KEYSTORE_ALIAS} --service-keystore ${KEYSTORE_PREFIX} --service-truststore ${TRUSTSTORE_PREFIX} --local-ca-filename ${LOCAL_CA_PREFIX} \ + --external-ca-filename ${EXTERNAL_CA_PREFIX} + else + ${ZOWE_ROOT_DIR}/bin/apiml_cm.sh --verbose --log $LOG_FILE --action setup --service-ext ${SAN} --zowe-userid ${ZOWE_USER_ID} --zowe-keyring ${ZOWE_KEYRING} \ + --service-storetype "JCERACFKS" --external-certificate ${EXTERNAL_CERTIFICATE} --external-certificate-alias ${EXTERNAL_CERTIFICATE_ALIAS} \ + --service-alias ${KEYSTORE_ALIAS} --service-keystore ${KEYSTORE_PREFIX} --local-ca-filename ${LOCAL_CA_PREFIX} + fi RC=$? echo "apiml_cm.sh --action setup returned: $RC" >> $LOG_FILE @@ -137,9 +150,15 @@ if [ "$RC" -ne "0" ]; then fi if [[ "${VERIFY_CERTIFICATES}" == "true" ]]; then - ${ZOWE_ROOT_DIR}/bin/apiml_cm.sh --verbose --log $LOG_FILE --action trust-zosmf \ - --service-password ${KEYSTORE_PASSWORD} --service-truststore ${TRUSTSTORE_PREFIX} --zosmf-certificate "${ZOSMF_CERTIFICATE}" - RC=$? + if [[ -z "${ZOWE_KEYRING}" ]]; then + ${ZOWE_ROOT_DIR}/bin/apiml_cm.sh --verbose --log $LOG_FILE --action trust-zosmf \ + --service-password ${KEYSTORE_PASSWORD} --service-truststore ${TRUSTSTORE_PREFIX} --zosmf-certificate "${ZOSMF_CERTIFICATE}" + RC=$? + else + echo "Zosmf trust action for keyrings not supported yet." + RC=4 + fi + echo "apiml_cm.sh --action trust-zosmf returned: $RC" >> $LOG_FILE if [ "$RC" -ne "0" ]; then @@ -153,16 +172,31 @@ echo "Creating certificates and keystores... DONE" ZOWE_CERTIFICATES_ENV=${KEYSTORE_DIRECTORY}/${ZOWE_CERT_ENV_NAME} rm ${ZOWE_CERTIFICATES_ENV} 2> /dev/null -cat >${KEYSTORE_DIRECTORY}/${ZOWE_CERT_ENV_NAME} <${KEYSTORE_DIRECTORY}/${ZOWE_CERT_ENV_NAME} <${KEYSTORE_DIRECTORY}/${ZOWE_CERT_ENV_NAME} < Date: Fri, 21 Feb 2020 15:58:26 +0100 Subject: [PATCH 02/37] do not make keyring as default yet Signed-off-by: Vit Tomica --- bin/zowe-setup-certificates.env | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/zowe-setup-certificates.env b/bin/zowe-setup-certificates.env index 20bba2f4d8..ca6fb068cb 100644 --- a/bin/zowe-setup-certificates.env +++ b/bin/zowe-setup-certificates.env @@ -28,4 +28,4 @@ ZOWE_USER_ID=ZWESVUSR ZOWE_GROUP_ID=ZWEADMIN # Specify zowe keyring that keeps zowe certificates, if not specified USS keystore # files will be created. -ZOWE_KEYRING=ZWERING +ZOWE_KEYRING= From 4e816719a20d52c94704e3eb85c89718f7aa182b Mon Sep 17 00:00:00 2001 From: Vit Tomica Date: Tue, 3 Mar 2020 15:45:55 +0100 Subject: [PATCH 03/37] added keyring-util function for keyring operations Signed-off-by: Vit Tomica --- bin/utils/keyring-util/README.md | 46 +++++++ bin/utils/keyring-util/build.sh | 1 + bin/utils/keyring-util/keyring-util.c | 174 ++++++++++++++++++++++++++ bin/utils/keyring-util/keyring-util.h | 70 +++++++++++ 4 files changed, 291 insertions(+) create mode 100644 bin/utils/keyring-util/README.md create mode 100644 bin/utils/keyring-util/build.sh create mode 100644 bin/utils/keyring-util/keyring-util.c create mode 100644 bin/utils/keyring-util/keyring-util.h diff --git a/bin/utils/keyring-util/README.md b/bin/utils/keyring-util/README.md new file mode 100644 index 0000000000..82b1970921 --- /dev/null +++ b/bin/utils/keyring-util/README.md @@ -0,0 +1,46 @@ +# keyring-util + +The keyring-util program leverages +[R_datalib callable service](https://www.ibm.com/support/knowledgecenter/SSLTBW_2.4.0/com.ibm.zos.v2r4.ichd100/datalib.htm) +to perform various operations on digital certificates and RACF key rings. + +## Syntax +```bash +keyring-util function userid keyring label +``` +**Parametres:** + 1. `function` see [Functions](##Functions) section below + 2. `userid` - an owner of the `keyring` and `label` certificate + 3. `keyring` - a name of the keyring + 4. `label` - a label of the certificate + +## Functions + + * `NEWRING` - creates a keyring + * Example: `keyring-util NEWRING USER01 ZOWERING` + + * `DELRING` - deletes a keyring + * Example: `keyring-util DELRING USER01 ZOWERING` + + * `DELCERT` - remove a certificate from a keyring or deletes a certificate from RACF database + + **Current Limitation:** The `DELCERT` function can only manipulate a certificate that is owned by the `userid`, i.e. it can't + work with certificates owned by the CERTAUTH, SITE or different userid. + + The following example removes `localhost` certificate owned by the `USER01` from the `ZOWERING` keyring owner by the `USER01` userid + * Example: `keyring-util DELCERT USER01 ZOWERING localhost` + + The following example removes `localhost` certificate owned by the `USER01` from the RACF database. + * Example: `keyring-util DELCERT USER01 '*' localhost` + + * `REFRESH` - refreshes DIGTCERT class + * Example: `keyring-util REFRESH` + +## Further development +There is room for improvement: + * command line argument processing and syntax + * an extension of functionality of the current functions + * implementation of new [functions](https://www.ibm.com/support/knowledgecenter/SSLTBW_2.4.0/com.ibm.zos.v2r4.ichd100/ich2d100226.htm) + +Work with the following resource if you want to implement a new R_datalib function [Data areas for R_datalib callable service](https://www.ibm.com/support/knowledgecenter/SSLTBW_2.4.0/com.ibm.zos.v2r4.ichc400/comx.htm) + diff --git a/bin/utils/keyring-util/build.sh b/bin/utils/keyring-util/build.sh new file mode 100644 index 0000000000..798e388dd2 --- /dev/null +++ b/bin/utils/keyring-util/build.sh @@ -0,0 +1 @@ +xlc -q64 -o keyring-util keyring-util.c diff --git a/bin/utils/keyring-util/keyring-util.c b/bin/utils/keyring-util/keyring-util.c new file mode 100644 index 0000000000..e6f3d1dbd9 --- /dev/null +++ b/bin/utils/keyring-util/keyring-util.c @@ -0,0 +1,174 @@ +#include +#include +#include + +#ifdef _LP64 + #pragma linkage(IRRSDL64, OS) +#else + #error "31-bit not supported yet." +#endif + +#include "keyring-util.h" + +int debug = 0; + +int main(int argc, char **argv) +{ + int i; + + if (getenv("KEYRING_UTIL_DEBUG") != NULL && ! strcmp(getenv("KEYRING_UTIL_DEBUG"), "YES")) { + debug = 1; + } + Command_line_parms parms; + memset(&parms, 0, sizeof(Command_line_parms)); + + R_datalib_data_remove rem_parm; + memset(&rem_parm, 0x00, sizeof(R_datalib_data_remove)); + + R_datalib_parm_list_64 p; + + process_cmdline_parms(&parms, argc, argv); + + R_datalib_function function_table[] = { + {"NEWRING", NEWRING_CODE, 0x00000000, 0, NULL, simple_action}, + {"DELCERT", DELCERT_CODE, 0x00000000, 0, &rem_parm, delcert_action}, + {"DELRING", DELRING_CODE, 0x00000000, 0, NULL, simple_action}, + {"REFRESH", REFRESH_CODE, 0x00000000, 0, NULL, simple_action}, + {"HELP", HELP_CODE, 0x00000000, 0, NULL, print_help}, + {"NOTSUPPORTED", NOTSUPPORTED_CODE, 0x00000000, 0, NULL, print_help} + }; + + R_datalib_function function; + for (i = 0; i < sizeof(function_table)/sizeof(R_datalib_function); i++) { + if (strncasecmp(function_table[i].name, parms.function, sizeof(parms.function)) == 0) { + function = function_table[i]; + break; + } + function = function_table[sizeof(function_table)/sizeof(R_datalib_function) - 1]; + } + if (debug) { + printf("Selected function is %s with code of %.2X\n", function.name, function.code); + } + function.action(&p, &function, &parms); + + return 0; +} + +void simple_action(R_datalib_parm_list_64* rdatalib_parms, void * function, Command_line_parms* parms) { + R_datalib_function *func = function; + if (debug) { + printf("%s action\n", func->name); + } + set_up_R_datalib_parameters(rdatalib_parms, function, parms->userid, parms->keyring); + invoke_R_datalib(rdatalib_parms); + check_return_code(rdatalib_parms); +} + +void delcert_action(R_datalib_parm_list_64* rdatalib_parms, void * function, Command_line_parms* parms) { + R_datalib_function *func = function; + R_datalib_data_remove *rem_parm = func->parmlist; + + if (debug) { + printf("%s action\n", func->name); + } + rem_parm->label_len = strlen(parms->label); + rem_parm->label_addr = parms->label; + rem_parm->CERT_userid_len = 0x00; + + set_up_R_datalib_parameters(rdatalib_parms, func, parms->userid, parms->keyring); + invoke_R_datalib(rdatalib_parms); + check_return_code(rdatalib_parms); + // refresh DIGTCERT class if required + if (rdatalib_parms->return_code == 4 && rdatalib_parms->RACF_return_code == 4 && rdatalib_parms->RACF_reason_code == 12) { + func->code = REFRESH_CODE; + set_up_R_datalib_parameters(rdatalib_parms, func, "", ""); + invoke_R_datalib(rdatalib_parms); + check_return_code(rdatalib_parms); + printf("DIGTCERT class refreshed."); + } +} + +void validate_and_set_parm(char * parm, char * cmd_parm, int maxlen) { + if (strlen(cmd_parm) <= maxlen) { + strcpy(parm, cmd_parm); + } else { + printf("ERROR: %s parm too long and will not be set.\n", cmd_parm); + } +} + +void check_return_code(R_datalib_parm_list_64* p) { + if (p->return_code != 0 || p->RACF_return_code != 0 || p->RACF_reason_code != 0) { + printf("Function code: %.2X, SAF rc: %d, RACF rc: %d, RACF rsn: %d\n", + p->function_code, p->return_code, p->RACF_return_code, p->RACF_reason_code); + } +} + +void process_cmdline_parms(Command_line_parms* parms, int argc, char** argv) { + int i; + for (i = 1; i < argc; i++) { + if (debug) { + printf("%d. parameter: %s\n", i, argv[i]); + } + switch(i) { + case 1: + validate_and_set_parm(parms->function, argv[i], MAX_FUNCTION_LEN); + break; + case 2: + validate_and_set_parm(parms->userid, argv[i], MAX_USERID_LEN); + break; + case 3: + validate_and_set_parm(parms->keyring, argv[i], MAX_KEYRING_LEN); + break; + case 4: + validate_and_set_parm(parms->label, argv[i], MAX_LABEL_LEN); + break; + default: + printf("WARNING: %i. parameter - %s - is currently not supported and will be ignored.\n", i, argv[i]); + } + } +} + +void invoke_R_datalib(R_datalib_parm_list_64 * p) { + + IRRSDL64( + &p->num_parms, + &p->workarea, + &p->saf_rc_ALET, &p->return_code, + &p->racf_rc_ALET, &p->RACF_return_code, + &p->racf_rsn_ALET, &p->RACF_reason_code, + &p->function_code, + &p->attributes, + &p->RACF_userid_len, + &p->ring_name_len, + &p->parm_list_version, + p->parmlist + ); +} + +void set_up_R_datalib_parameters(R_datalib_parm_list_64 * p, R_datalib_function * function, char * userid, char * keyring) { + memset(p, 0, sizeof(R_datalib_parm_list_64)); + p->num_parms = 14; + p->saf_rc_ALET = 0; + p->racf_rc_ALET = 0; + p->racf_rsn_ALET = 0; + p->function_code = function->code; + p->attributes = function->default_attributes; + memset(&p->RACF_userid_len, strlen(userid), 1); + memcpy(p->RACF_userid, userid, strlen(userid)); + memset(&p->ring_name_len, strlen(keyring), 1); + memcpy(p->ring_name, keyring, strlen(keyring)); + p->parm_list_version = function->parm_list_version; + p->parmlist = function->parmlist; +} + +void print_help(R_datalib_parm_list_64* rdatalib_parms, void * function, Command_line_parms* parms) { + printf("----------------------------------------------------\n"); + printf("Usage: keyring-util function userid keyring label\n"); + printf("----------------------------------------------------\n"); + printf("function:\n"); + printf("NEWRING - creates a new keyring.\n"); + printf("DELRING - deletes a keyring\n"); + printf("DELCERT - disconnects a certificate (label) from a keyring or deletes a certificate from RACF database\n"); + printf("REFRESH - refreshes DIGTCERT class\n"); + printf("HELP - prints this help\n"); +} diff --git a/bin/utils/keyring-util/keyring-util.h b/bin/utils/keyring-util/keyring-util.h new file mode 100644 index 0000000000..85f261e7cb --- /dev/null +++ b/bin/utils/keyring-util/keyring-util.h @@ -0,0 +1,70 @@ +#ifndef _keyring_util +#define _keyring_util + +#define MAX_FUNCTION_LEN 16 +#define MAX_USERID_LEN 8 +#define MAX_KEYRING_LEN 236 +#define MAX_LABEL_LEN 32 + +#define NEWRING_CODE 0x07 +#define DELCERT_CODE 0x09 +#define DELRING_CODE 0x0A +#define REFRESH_CODE 0x0B +#define HELP_CODE 0x00 +#define NOTSUPPORTED_CODE 0x00 + + +typedef struct _Command_line_params { + char function[MAX_FUNCTION_LEN]; + char userid[MAX_USERID_LEN + 1]; + char keyring[MAX_KEYRING_LEN + 1]; + char label[MAX_LABEL_LEN + 1]; + +} Command_line_parms; + +typedef struct _R_datalib_parm_list_64 { + int num_parms; + double workarea[128]; // double word aligned, 1024 bytes long workarea + int saf_rc_ALET, return_code; + int racf_rc_ALET, RACF_return_code; + int racf_rsn_ALET, RACF_reason_code; + char function_code; + int attributes; + char RACF_userid_len; // DO NOT change position of this field + char RACF_userid[MAX_USERID_LEN]; // DO NOT change position of this field + char ring_name_len; // DO NOT change position of this field + char ring_name[MAX_KEYRING_LEN]; // DO NOT change position of this field + int parm_list_version; + void *parmlist; +} R_datalib_parm_list_64; + +typedef void (*function_action)(R_datalib_parm_list_64*, void*, Command_line_parms*); + +typedef struct _R_datalib_function { + char name[MAX_FUNCTION_LEN]; + char code; + int default_attributes; + int parm_list_version; + void *parmlist; + function_action action; +} R_datalib_function; + +typedef _Packed struct _R_datalib_data_remove { + int label_len; + int reserve_1; + char *label_addr; + char CERT_userid_len; // DO NOT change position of this field + char CERT_userid[MAX_USERID_LEN]; // DO NOT change position of this field + char reserved_2[3]; +} R_datalib_data_remove; + +void invoke_R_datalib(R_datalib_parm_list_64*); +void set_up_R_datalib_parameters(R_datalib_parm_list_64* , R_datalib_function* , char* ,char* ); +void simple_action(R_datalib_parm_list_64*, void*, Command_line_parms*); +void delcert_action(R_datalib_parm_list_64*, void*, Command_line_parms*); +void print_help(R_datalib_parm_list_64*, void*, Command_line_parms*); +void process_cmdline_parms(Command_line_parms*, int , char**); +void validate_and_set_parm(char*, char*, int); +void check_return_code(R_datalib_parm_list_64*); + +#endif From c0e71a1c262437c165b15a1aac57a06e47cb5a2e Mon Sep 17 00:00:00 2001 From: Vit Tomica Date: Tue, 3 Mar 2020 18:49:05 +0100 Subject: [PATCH 04/37] add informational message Signed-off-by: Vit Tomica --- bin/utils/keyring-util/keyring-util.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/bin/utils/keyring-util/keyring-util.c b/bin/utils/keyring-util/keyring-util.c index e6f3d1dbd9..cce9786864 100644 --- a/bin/utils/keyring-util/keyring-util.c +++ b/bin/utils/keyring-util/keyring-util.c @@ -80,11 +80,12 @@ void delcert_action(R_datalib_parm_list_64* rdatalib_parms, void * function, Com check_return_code(rdatalib_parms); // refresh DIGTCERT class if required if (rdatalib_parms->return_code == 4 && rdatalib_parms->RACF_return_code == 4 && rdatalib_parms->RACF_reason_code == 12) { + printf("DIGTCERT class has to refreshed.\n"); func->code = REFRESH_CODE; set_up_R_datalib_parameters(rdatalib_parms, func, "", ""); invoke_R_datalib(rdatalib_parms); check_return_code(rdatalib_parms); - printf("DIGTCERT class refreshed."); + printf("DIGTCERT class refreshed.\n"); } } From a111842942929b936606fae5e230e09d80882a88 Mon Sep 17 00:00:00 2001 From: Vit Tomica Date: Wed, 4 Mar 2020 18:33:21 +0100 Subject: [PATCH 05/37] keyring cleanup; zosmf trust Signed-off-by: Vit Tomica --- bin/apiml_cm.sh | 36 ++++++++++++++++++++++++++++++-- bin/utils/keyring-util/README.md | 4 +++- bin/zowe-setup-certificates.sh | 15 ++++++++++--- 3 files changed, 49 insertions(+), 6 deletions(-) diff --git a/bin/apiml_cm.sh b/bin/apiml_cm.sh index 051f605d5a..74a4e40f66 100644 --- a/bin/apiml_cm.sh +++ b/bin/apiml_cm.sh @@ -84,12 +84,38 @@ function pkeytool { fi } +function clean_keyring { + if [[ "${SERVICE_STORETYPE}" == "JCERACFKS" ]]; then + KEYRING_UTIL=`dirname ${LOCAL_CA_FILENAME}`/../keyring-util + echo "Removing ${ZOWE_USERID}/${ZOWE_KEYRING} keyring" + $KEYRING_UTIL delring ${ZOWE_USERID} ${ZOWE_KEYRING} + fi +} + function clean_local_ca { rm -f ${LOCAL_CA_FILENAME}.keystore.p12 ${LOCAL_CA_FILENAME}.cer + if [[ "${SERVICE_STORETYPE}" == "JCERACFKS" ]]; then + KEYRING_UTIL=`dirname ${LOCAL_CA_FILENAME}`/../keyring-util + echo "Disconnecting ${LOCAL_CA_ALIAS} certificate from the ${ZOWE_KEYRING} keyring" + $KEYRING_UTIL delcert ${ZOWE_USERID} ${ZOWE_KEYRING} ${LOCAL_CA_ALIAS} + echo "Removing ${LOCAL_CA_ALIAS} certificate from RACF database" + $KEYRING_UTIL delcert ${ZOWE_USERID} "*" ${LOCAL_CA_ALIAS} + fi } function clean_service { rm -f ${SERVICE_KEYSTORE}.p12 ${SERVICE_KEYSTORE}.csr ${SERVICE_KEYSTORE}_signed.cer ${SERVICE_TRUSTSTORE}.p12 + if [[ "${SERVICE_STORETYPE}" == "JCERACFKS" ]]; then + KEYRING_UTIL=`dirname ${SERVICE_KEYSTORE}`/../keyring-util + echo "Disconnecting ${SERVICE_ALIAS} certificate from the ${ZOWE_KEYRING} keyring" + $KEYRING_UTIL delcert ${ZOWE_USERID} ${ZOWE_KEYRING} ${SERVICE_ALIAS} + echo "Disconnecting ${JWT_ALIAS} certificate from the ${ZOWE_KEYRING} keyring" + $KEYRING_UTIL delcert ${ZOWE_USERID} ${ZOWE_KEYRING} ${JWT_ALIAS} + echo "Removing ${SERVICE_ALIAS} certificate from RACF database" + $KEYRING_UTIL delcert ${ZOWE_USERID} "*" ${SERVICE_ALIAS} + echo "Removing ${JWT_ALIAS} certificate from RACF database" + $KEYRING_UTIL delcert ${ZOWE_USERID} "*" ${JWT_ALIAS} + fi } function create_certificate_authority { @@ -336,7 +362,9 @@ function new_service_csr { clean_service create_service_certificate_and_csr echo "Listing generated files for service:" - ls -l ${SERVICE_KEYSTORE}* ${SERVICE_TRUSTSTORE}* + if [[ "${SERVICE_STORETYPE}" != "JCERACFKS" ]]; then + ls -l ${SERVICE_KEYSTORE}* ${SERVICE_TRUSTSTORE}* + fi } function new_service { @@ -353,7 +381,9 @@ function new_service { export_service_certificate export_service_private_key echo "Listing generated files for service:" - ls -l ${SERVICE_KEYSTORE}* ${SERVICE_TRUSTSTORE}* + if [[ "${SERVICE_STORETYPE}" != "JCERACFKS" ]]; then + ls -l ${SERVICE_KEYSTORE}* ${SERVICE_TRUSTSTORE}* + fi } function new_self_signed_service { @@ -550,10 +580,12 @@ done case $ACTION in clean) + clean_keyring clean_local_ca clean_service ;; setup) + clean_keyring setup_local_ca new_service jwt_key_gen_and_export diff --git a/bin/utils/keyring-util/README.md b/bin/utils/keyring-util/README.md index 82b1970921..bd8da25a78 100644 --- a/bin/utils/keyring-util/README.md +++ b/bin/utils/keyring-util/README.md @@ -35,10 +35,12 @@ keyring-util function userid keyring label * `REFRESH` - refreshes DIGTCERT class * Example: `keyring-util REFRESH` + +For any return and reason codes, check [R_datalib return and reason codes](https://www.ibm.com/support/knowledgecenter/SSLTBW_2.4.0/com.ibm.zos.v2r4.ichd100/ich2d100238.htm) ## Further development There is room for improvement: - * command line argument processing and syntax + * command line argument processing and syntax (perhaps using the argp library from [ambitus project](https://github.com/ambitus/glibc/tree/zos/2.28/master/argp)) * an extension of functionality of the current functions * implementation of new [functions](https://www.ibm.com/support/knowledgecenter/SSLTBW_2.4.0/com.ibm.zos.v2r4.ichd100/ich2d100226.htm) diff --git a/bin/zowe-setup-certificates.sh b/bin/zowe-setup-certificates.sh index b365b534e8..0ff0c40b40 100644 --- a/bin/zowe-setup-certificates.sh +++ b/bin/zowe-setup-certificates.sh @@ -92,6 +92,13 @@ if [ ! -d ${KEYSTORE_DIRECTORY}/${KEYSTORE_ALIAS} ]; then fi fi +# build keyring-util program +if [[ -n "${ZOWE_KEYRING}" ]]; then + xlc -q64 -o ${KEYSTORE_DIRECTORY}/keyring-util ${ZOWE_ROOT_DIR}/bin/utils/keyring-util/keyring-util.c >> $LOG_FILE + #c89 -W"c,lp64,langlv(STDC99)" -Wl,lp64 -o ${KEYSTORE_DIRECTORY}/keyring-util ${ZOWE_ROOT_DIR}/bin/utils/keyring-util/keyring-util.c 2>> $LOG_FILE + rm ${KEYSTORE_DIRECTORY}/keyring-util.o 2> /dev/null +fi + echo "Creating certificates and keystores... STARTED" # set up parameters for apiml_cm.sh script KEYSTORE_PREFIX="${KEYSTORE_DIRECTORY}/${KEYSTORE_ALIAS}/${KEYSTORE_ALIAS}.keystore" @@ -120,6 +127,7 @@ if [[ -z "${EXTERNAL_CERTIFICATE}" ]] || [[ -z "${EXTERNAL_CERTIFICATE_ALIAS}" ] (>&2 echo "Some external apiml certificate fields are supplied...Fields must be filled out in full or left completely blank.") (>&2 echo "See $LOG_FILE for more details.") echo "" >> $LOG_FILE + rm ${KEYSTORE_PREFIX}* ${TRUSTSTORE_PREFIX}* ${EXTERNAL_CA_PREFIX}* ${LOCAL_CA_PREFIX}* 2> /dev/null exit 1 fi else @@ -146,6 +154,7 @@ fi if [ "$RC" -ne "0" ]; then (>&2 echo "apiml_cm.sh --action setup has failed. See $LOG_FILE for more details") echo "" >> $LOG_FILE + rm ${KEYSTORE_PREFIX}* ${TRUSTSTORE_PREFIX}* ${EXTERNAL_CA_PREFIX}* ${LOCAL_CA_PREFIX}* 2> /dev/null exit 1 fi @@ -155,11 +164,10 @@ if [[ "${VERIFY_CERTIFICATES}" == "true" ]]; then --service-password ${KEYSTORE_PASSWORD} --service-truststore ${TRUSTSTORE_PREFIX} --zosmf-certificate "${ZOSMF_CERTIFICATE}" RC=$? else - echo "Zosmf trust action for keyrings not supported yet." - RC=4 + ${ZOWE_ROOT_DIR}/bin/apiml_cm.sh --verbose --log $LOG_FILE --action trust-zosmf --zowe-userid ${ZOWE_USER_ID} \ + --zowe-keyring ${ZOWE_KEYRING} --service-storetype "JCERACFKS" --zosmf-certificate "${ZOSMF_CERTIFICATE}" fi - echo "apiml_cm.sh --action trust-zosmf returned: $RC" >> $LOG_FILE if [ "$RC" -ne "0" ]; then (>&2 echo "apiml_cm.sh --action trust-zosmf has failed. See $LOG_FILE for more details") @@ -167,6 +175,7 @@ if [[ "${VERIFY_CERTIFICATES}" == "true" ]]; then (>&2 echo "ZOWE_ZOSMF_HOST=${ZOWE_ZOSMF_HOST} ZOWE_ZOSMF_PORT=${ZOWE_ZOSMF_PORT}") (>&2 echo "You can also specify z/OSMF certificate explicitly in the ZOSMF_CERTIFICATE environmental variable in the zowe-setup-certificates.env file.") echo "" >> $LOG_FILE + rm ${KEYSTORE_PREFIX}* ${TRUSTSTORE_PREFIX}* ${EXTERNAL_CA_PREFIX}* ${LOCAL_CA_PREFIX}* 2> /dev/null exit 1 fi fi From 67ec8d64ee66fce9c8cecfc6edbe7a322b973cbc Mon Sep 17 00:00:00 2001 From: Vit Tomica Date: Wed, 4 Mar 2020 18:48:58 +0100 Subject: [PATCH 06/37] zosmf trust Signed-off-by: Vit Tomica --- bin/apiml_cm.sh | 2 +- bin/zowe-setup-certificates.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bin/apiml_cm.sh b/bin/apiml_cm.sh index 74a4e40f66..89f93b6946 100644 --- a/bin/apiml_cm.sh +++ b/bin/apiml_cm.sh @@ -399,7 +399,7 @@ function new_self_signed_service { function trust { echo "Import a certificate to the truststore:" if [[ "${SERVICE_STORETYPE}" == "JCERACFKS" ]]; then - pkeytool -importcert $V -trustcacerts -noprompt -file ${CERTIFICATE} -alias "${ALIAS}" -keystore safkeyring://${ZOWE_USERID}/${ZOWE_KEYRING} -storetype ${SERVICE_STORETYPE} \ + keytool -importcert $V -trustcacerts -noprompt -file ${CERTIFICATE} -alias "${ALIAS}" -keystore safkeyring://${ZOWE_USERID}/${ZOWE_KEYRING} -storetype ${SERVICE_STORETYPE} \ -J-Djava.protocol.handler.pkgs=com.ibm.crypto.provider else pkeytool -importcert $V -trustcacerts -noprompt -file ${CERTIFICATE} -alias "${ALIAS}" -keystore ${SERVICE_TRUSTSTORE}.p12 -storepass ${SERVICE_PASSWORD} -storetype ${SERVICE_STORETYPE} diff --git a/bin/zowe-setup-certificates.sh b/bin/zowe-setup-certificates.sh index 0ff0c40b40..d398f60532 100644 --- a/bin/zowe-setup-certificates.sh +++ b/bin/zowe-setup-certificates.sh @@ -162,11 +162,11 @@ if [[ "${VERIFY_CERTIFICATES}" == "true" ]]; then if [[ -z "${ZOWE_KEYRING}" ]]; then ${ZOWE_ROOT_DIR}/bin/apiml_cm.sh --verbose --log $LOG_FILE --action trust-zosmf \ --service-password ${KEYSTORE_PASSWORD} --service-truststore ${TRUSTSTORE_PREFIX} --zosmf-certificate "${ZOSMF_CERTIFICATE}" - RC=$? else ${ZOWE_ROOT_DIR}/bin/apiml_cm.sh --verbose --log $LOG_FILE --action trust-zosmf --zowe-userid ${ZOWE_USER_ID} \ --zowe-keyring ${ZOWE_KEYRING} --service-storetype "JCERACFKS" --zosmf-certificate "${ZOSMF_CERTIFICATE}" fi + RC=$? echo "apiml_cm.sh --action trust-zosmf returned: $RC" >> $LOG_FILE if [ "$RC" -ne "0" ]; then From f55ea2a6723b4e5622fd43406a310fdb3d2e0af0 Mon Sep 17 00:00:00 2001 From: Vit Tomica Date: Thu, 5 Mar 2020 13:59:11 +0100 Subject: [PATCH 07/37] adding umask in zowe-setup-certificates.sh; minor changes Signed-off-by: Vit Tomica --- bin/apiml_cm.sh | 2 +- bin/utils/keyring-util/README.md | 11 ++++++----- bin/zowe-setup-certificates.sh | 3 ++- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/bin/apiml_cm.sh b/bin/apiml_cm.sh index 89f93b6946..56345bb38c 100644 --- a/bin/apiml_cm.sh +++ b/bin/apiml_cm.sh @@ -86,7 +86,7 @@ function pkeytool { function clean_keyring { if [[ "${SERVICE_STORETYPE}" == "JCERACFKS" ]]; then - KEYRING_UTIL=`dirname ${LOCAL_CA_FILENAME}`/../keyring-util + KEYRING_UTIL=`dirname ${SERVICE_KEYSTORE}`/../keyring-util echo "Removing ${ZOWE_USERID}/${ZOWE_KEYRING} keyring" $KEYRING_UTIL delring ${ZOWE_USERID} ${ZOWE_KEYRING} fi diff --git a/bin/utils/keyring-util/README.md b/bin/utils/keyring-util/README.md index bd8da25a78..1f863f877a 100644 --- a/bin/utils/keyring-util/README.md +++ b/bin/utils/keyring-util/README.md @@ -27,10 +27,11 @@ keyring-util function userid keyring label **Current Limitation:** The `DELCERT` function can only manipulate a certificate that is owned by the `userid`, i.e. it can't work with certificates owned by the CERTAUTH, SITE or different userid. - The following example removes `localhost` certificate owned by the `USER01` from the `ZOWERING` keyring owner by the `USER01` userid + The following example removes `localhost` certificate owned by the `USER01` from the `ZOWERING` keyring owned by the `USER01` userid * Example: `keyring-util DELCERT USER01 ZOWERING localhost` - The following example removes `localhost` certificate owned by the `USER01` from the RACF database. + The following example removes `localhost` certificate owned by the `USER01` from the RACF database. The command fails if the certificate + is still connected to some keyring. * Example: `keyring-util DELCERT USER01 '*' localhost` * `REFRESH` - refreshes DIGTCERT class @@ -41,8 +42,8 @@ For any return and reason codes, check [R_datalib return and reason codes](https ## Further development There is room for improvement: * command line argument processing and syntax (perhaps using the argp library from [ambitus project](https://github.com/ambitus/glibc/tree/zos/2.28/master/argp)) - * an extension of functionality of the current functions - * implementation of new [functions](https://www.ibm.com/support/knowledgecenter/SSLTBW_2.4.0/com.ibm.zos.v2r4.ichd100/ich2d100226.htm) + * an extension of functionality of the current R_datalib functions + * adding support for other [R_datalib functions](https://www.ibm.com/support/knowledgecenter/SSLTBW_2.4.0/com.ibm.zos.v2r4.ichd100/ich2d100226.htm) -Work with the following resource if you want to implement a new R_datalib function [Data areas for R_datalib callable service](https://www.ibm.com/support/knowledgecenter/SSLTBW_2.4.0/com.ibm.zos.v2r4.ichc400/comx.htm) +Work with the following resource if you want to add support for other R_datalib functions [Data areas for R_datalib callable service](https://www.ibm.com/support/knowledgecenter/SSLTBW_2.4.0/com.ibm.zos.v2r4.ichc400/comx.htm) diff --git a/bin/zowe-setup-certificates.sh b/bin/zowe-setup-certificates.sh index d398f60532..ba9d424a2d 100644 --- a/bin/zowe-setup-certificates.sh +++ b/bin/zowe-setup-certificates.sh @@ -44,6 +44,8 @@ while getopts "p:" opt; do done shift "$(($OPTIND-1))" +umask 0027 + if [[ -z ${ZOWE_ROOT_DIR} ]] then export ZOWE_ROOT_DIR=$(cd $(dirname $0)/../;pwd) @@ -95,7 +97,6 @@ fi # build keyring-util program if [[ -n "${ZOWE_KEYRING}" ]]; then xlc -q64 -o ${KEYSTORE_DIRECTORY}/keyring-util ${ZOWE_ROOT_DIR}/bin/utils/keyring-util/keyring-util.c >> $LOG_FILE - #c89 -W"c,lp64,langlv(STDC99)" -Wl,lp64 -o ${KEYSTORE_DIRECTORY}/keyring-util ${ZOWE_ROOT_DIR}/bin/utils/keyring-util/keyring-util.c 2>> $LOG_FILE rm ${KEYSTORE_DIRECTORY}/keyring-util.o 2> /dev/null fi From 990380e3e37d1f8b7927a07a4427c9d0fabfebfe Mon Sep 17 00:00:00 2001 From: Vit Tomica Date: Fri, 6 Mar 2020 14:31:15 +0100 Subject: [PATCH 08/37] typo Signed-off-by: Vit Tomica --- bin/zowe-setup-certificates.env | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/zowe-setup-certificates.env b/bin/zowe-setup-certificates.env index ccdbde5e8f..4993ef804b 100644 --- a/bin/zowe-setup-certificates.env +++ b/bin/zowe-setup-certificates.env @@ -31,7 +31,7 @@ KEYSTORE_DIRECTORY=/global/zowe/keystore KEYSTORE_ALIAS=localhost # Specify zowe user id to set up ownership of the generated certificates ZOWE_USER_ID=ZWESVUSR -# Specify zowe user id to set up ownership of the generated certificates +# Specify zowe group id to set up ownership of the generated certificates ZOWE_GROUP_ID=ZWEADMIN # Specify zowe keyring that keeps zowe certificates, if not specified USS keystore # files will be created. From 01699ce41a8fd8cbdb372893bc242081531213cc Mon Sep 17 00:00:00 2001 From: Vit Tomica Date: Mon, 4 May 2020 16:27:52 +0200 Subject: [PATCH 09/37] use four slashes so java components can directly consume the value Signed-off-by: Vit Tomica --- bin/zowe-setup-certificates.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bin/zowe-setup-certificates.sh b/bin/zowe-setup-certificates.sh index 943c7ce8bd..f4ff8958c5 100644 --- a/bin/zowe-setup-certificates.sh +++ b/bin/zowe-setup-certificates.sh @@ -194,9 +194,9 @@ else cat >${KEYSTORE_DIRECTORY}/${ZOWE_CERT_ENV_NAME} < Date: Wed, 6 May 2020 13:40:21 +0200 Subject: [PATCH 10/37] added JCL that configures certificates and SAF keyrings Signed-off-by: Vit Tomica --- files/jcl/ZWEKRING.jcl | 376 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 376 insertions(+) create mode 100644 files/jcl/ZWEKRING.jcl diff --git a/files/jcl/ZWEKRING.jcl b/files/jcl/ZWEKRING.jcl new file mode 100644 index 0000000000..d9ee84e23d --- /dev/null +++ b/files/jcl/ZWEKRING.jcl @@ -0,0 +1,376 @@ +//ZWEKRING JOB +//* +//* This program and the accompanying materials are made available +//* under the terms of the Eclipse Public License v2.0 which +//* accompanies this distribution, and is available at +//* https://www.eclipse.org/legal/epl-v20.html +//* +//* SPDX-License-Identifier: EPL-2.0 +//* +//* Copyright Contributors to the Zowe Project. 2018, 2020 +//* +//********************************************************************* +//* +//* Zowe Open Source Project +//* This JCL can be used to define key ring and certificates for Zowe +//* +//* +//* CAUTION: This is neither a JCL procedure nor a complete job. +//* Before using this JCL, you will have to make the following +//* modifications: +//* +//* 1) Add job name and job parameters to the JOB statement, to +//* meet your system requirements. +//* +//* 2) Update the SET PRODUCT= statement to match your security +//* product. +//* +//* 3) Update the SET ZOWEUSER= statement to match the desired +//* user ID for the ZOWE started task. +//* +//* 4) Update the SET ZOWERING= statement to match the desired +//* name of the keyring owned by the ZOWEUSER. +//* +//* 5) Update the SET LABEL= statement with the name of the Zowe +//* certificate that will be added to the RACF database or that +//* is already stored in the RACF database. +//* +//* 6) Update the SET DSNAME= statement if you plan to import the Zowe +//* certificate from a data set in PKCS12 format. +//* +//* 7) Update the SET PKCSPASS= statement to match the password for +//* the PKCS12 data set. +//* +//* 8) Specify the distinguished name of the Zowe's local CA by +//* updating the SET statements CN=, OU=, O=, L=, SP= and C=. +//* +//* 9) Customize the commands in the DD statement that matches your +//* security product so that they meet your system requirements. +//* +//* Note(s): +//* +//* 1. THE USER ID THAT RUNS THIS JOB MUST HAVE SUFFICIENT AUTHORITY +//* TO ALTER SECURITY DEFINITIONS +//* +//* 2. Assumption: signing CAs of the Zowe external certificate are +//* added to RACF database under the CERTAUTH userid. +//* +//* 3. If the Zowe certificate is imported from a data set then +//* the certificate has to be in PKCS12 format and has to +//* contain Zowe certificate's signing CA chain and private key. +//* +//* 4. This job WILL complete with return code 0. +//* The results of each command must be verified after completion. +//* +//********************************************************************* +// EXPORT SYMLIST=* +//* +// SET PRODUCT=RACF * RACF, ACF2, or TSS +//* 12345678 +// SET ZOWEUSER=ZWESVUSR * userid for Zowe started task +//* 12345678 +//* +//* * Keyring for the Zowe userid +// SET ZOWERING='ZoweKeyring' +//* * Zowe's certificate label +// SET LABEL= '' +//* * Name of the data set containing Zowe's certificate (PKCS12) +// SET DSNAME= +//* * Password for the PKCS12 data set +// SET PKCSPASS= +//* * Zowe's local CA common name +// SET CN='Zowe Development Instances' +//* * Zowe's local CA organizational unit +// SET OU='API Mediation Layer' +//* * Zowe's local CA organization +// SET O='Zowe Sample' +//* * Zowe's local CA city/locality +// SET L='Prague' +//* * Zowe's local CA state/province +// SET SP='Prague' +//* * Zowe's local CA country +// SET C='CZ' +//* +//********************************************************************* +//* +//* EXECUTE COMMANDS FOR SELECTED SECURITY PRODUCT +//* +//RUN EXEC PGM=IKJEFT01,REGION=0M +//SYSTSPRT DD SYSOUT=* +//SYSTSIN DD DDNAME=&PRODUCT +//* +//********************************************************************* +//* +//* RACF ONLY, customize to meet your system requirements +//* +//RACF DD DATA,DLM=$$,SYMBOLS=JCLONLY + +/* Create the keyring .............................................. */ + RACDCERT ADDRING(&ZOWERING.) ID(&ZOWEUSER.) + SETROPTS RACLIST(DIGTRING) REFRESH + +/* Create Zowe's local CA authority .................................*/ + RACDCERT GENCERT CERTAUTH + + SUBJECTSDN( + + CN('&CN. CA') + + OU('&OU.') + + O('&O.') + + L('&L.') + + SP('&SP.') + + C('&C.')) + + SIZE(2048) + + NOTAFTER(DATE(2030-05-01)) + + WITHLABEL('localca') + + KEYUSAGE(CERTSIGN) + SETROPTS RACLIST(DIGTCERT) REFRESH + +/* Connect Zowe's local CA authority to the keyring ................ */ + RACDCERT CONNECT(CERTAUTH LABEL('localca') + + RING(&ZOWERING.)) + + ID(&ZOWEUSER.) + +/* ***************************************************************** */ +/* ATTENTION! */ +/* Configure certificate for Zowe .................................. */ +/* Select one of three options which is the most suitable for your */ +/* environment and follow the appropriate action */ +/* */ +/* Options: */ +/* 1. Zowe's certificate is already loaded in RACF database */ +/* (assuming under &ZOWEUSER ACID) */ +/* ACTION: No action required */ +/* */ +/* 2. Import external Zowe's certificate from a data set in PKCS12 */ +/* format */ +/* ACTION: Uncomment the "Option 1" block below */ +/* */ +/* 3. Generate Zowe's certificate that will be signed by the */ +/* Zowe's local CA */ +/* ACTION: Uncomment the "Option 2" block below */ +/* */ +/* ***************************************************************** */ +/* */ +/* Option 1 - BEGINNING ............................................ */ +/* Import external certificate from data set ....................... */ +/* RACDCERT ADD('&DSNAME.') + +/* ID(&ZOWEUSER.) + +/* WITHLABEL('&LABEL.') + +/* PASSWORD('&PKCSPASS.') + +/* TRUST +/* SETROPTS RACLIST(DIGTCERT, DIGTRING) REFRESH + +/* Option 1 - END .................................................. */ +/* ................................................................. */ +/* Option 2 - BEGINNING ............................................ */ +/* Create a certificate signed by local zowe's CA .................. */ +/* RACDCERT GENCERT ID(&ZOWEUSER.) + +/* SUBJECTSDN( + +/* CN('&CN. certificate') + +/* OU('&OU.') + +/* O('&O.') + +/* L('&L.') + +/* SP('&SP.') + +/* C('&C.')) + +/* SIZE(2048) + +/* NOTAFTER(DATE(2030-05-01)) + +/* WITHLABEL('&LABEL.') + +/* KEYUSAGE(HANDSHAKE,DATAENCRYPT,DOCSIGN) + +/* ALTNAME(IP(127.0.0.1) + +/* DOMAIN('localhost')) + +/* SIGNWITH(CERTAUTH LABEL('localca')) +/* SETROPTS RACLIST(DIGTCERT) REFRESH + +/* Option 2 - END .................................................. */ + +/* Connect a Zowe's certificate with the keyring ................... */ + RACDCERT CONNECT(ID(&ZOWEUSER.) LABEL('&LABEL.') + + RING(&ZOWERING.) USAGE(PERSONAL) DEFAULT) + + ID(&ZOWEUSER.) + +/* Connect all CAs of the Zowe certificate's signing chain with the */ +/* keyring ......................................................... */ +/* Add or remove the command(s) according to your requirements ..... */ + RACDCERT CONNECT(CERTAUTH + + LABEL('>>>provide label of root CA<<<') + + RING(&ZOWERING.)) + + ID(&ZOWEUSER.) + RACDCERT CONNECT(CERTAUTH + + LABEL('>>>provide label of intermediate CA<<<') + + RING(&ZOWERING.)) + + ID(&ZOWEUSER.) + +/* Connect root CA that signs z/OSMF certificate with the keyring .. */ + RACDCERT CONNECT(CERTAUTH + + LABEL('>>>provide label of zosmf's root CA<<<') + + RING(&ZOWERING.)) + + ID(&ZOWEUSER.) + +/* Create jwtsecret .................................................*/ + RACDCERT GENCERT ID(&ZOWEUSER.) + + SUBJECTSDN( + + CN('&CN. JWT') + + OU('&OU.') + + O('&O.') + + L('&L.') + + SP('&SP.') + + C('&C.')) + + SIZE(2048) + + NOTAFTER(DATE(2030-05-01)) + + WITHLABEL('jwtsecret') + SETROPTS RACLIST(DIGTCERT) REFRESH + +/* Connect jwtsecret to the keyring ................................ */ + RACDCERT CONNECT(ID(&ZOWEUSER.) LABEL('jwtsecret') + + RING(&ZOWERING.) USAGE(PERSONAL)) + + ID(&ZOWEUSER.) + +/* Allow ZOWEUSER to access keyring ................................ */ + PERMIT IRR.DIGTCERT.LISTRING CLASS(FACILITY) ID(&ZOWEUSER.) + + ACCESS(READ) + + SETROPTS RACLIST(FACILITY) REFRESH + +/* List the keyring ................................................ */ + RACDCERT LISTRING(&ZOWERING.) ID(&ZOWEUSER.) + +/* ................................................................. */ +/* only the last RC is returned, this command ensures it is a 0 */ +PROFILE +$$ +//* +//********************************************************************* +//* +//* ACF2 ONLY, customize to meet your system requirements +//* +//ACF2 DD DATA,DLM=$$,SYMBOLS=JCLONLY +ACF +//* TODO +$$ +//* +//********************************************************************* +//* +//* Top Secret ONLY, customize to meet your system requirements +//* +//TSS DD DATA,DLM=$$,SYMBOLS=JCLONLY + +/* Create the keyring .............................................. */ + TSS ADD(&ZOWEUSER.) KEYRING(ZOWERING) LABLRING(&ZOWERING.) + +/* Create Zowe's local CA authority .................................*/ + TSS GENCERT(CERTAUTH) + + DIGICERT(ZOWECA) + + SUBJECTN( + + 'CN="&CN. CA" + + OU="&OU." + + O="&O." + + L="&L." + + SP="&SP." + + C="&C." ') + + KEYSIZE(2048) + + NADATE(05/01/30) + + LABLCERT(localca) + + KEYUSAGE('CERTSIGN') + +/* Connect Zowe's local CA authority to the keyring ................ */ + TSS ADD(&ZOWEUSER.) KEYRING(ZOWERING) LABLRING(&ZOWERING.) + + RINGDATA(CERTAUTH,ZOWECA) + +/* ***************************************************************** */ +/* ATTENTION! */ +/* Configure certificate for Zowe .................................. */ +/* Select one of three options which is the most suitable for your */ +/* environment and follow the appropriate action */ +/* */ +/* Options: */ +/* 1. Zowe's certificate is already loaded in RACF database */ +/* (assuming under &ZOWEUSER ACID) */ +/* ACTION: No action required */ +/* */ +/* 2. Import external Zowe's certificate from a data set in PKCS12 */ +/* format */ +/* ACTION: Uncomment the "Option 1" block below */ +/* */ +/* 3. Generate Zowe's certificate that will be signed by the */ +/* Zowe's local CA */ +/* ACTION: Uncomment the "Option 2" block below */ +/* */ +/* ***************************************************************** */ +/* */ +/* Option 1 - BEGINNING ............................................ */ +/* Import external certificate from data set ....................... */ +/* TSS ADD(&ZOWEUSER.) + +/* DIGICERT(ZOWECERT) + +/* DCDSN(&DSNAME.) + +/* LABLCERT(&LABEL.) + +/* PKCSPASS('&PKCSPASS.') + +/* TRUST + +/* Option 1 - END .................................................. */ +/* ................................................................. */ +/* Option 2 - BEGINNING ............................................ */ +/* Create a certificate signed by local zowe's CA .................. */ +/* TSS GENCERT(&ZOWEUSER.) + +/* DIGICERT(ZOWECERT) + +/* SUBJECTN( + +/* 'CN="&CN. certificate" + +/* OU="&OU." + +/* O="&O." + +/* L="&L." + +/* SP="&SP." + +/* C="&C." ') + +/* KEYSIZE(2048) + +/* NADATE(05/01/30) + +/* LABLCERT(&LABEL.) + +/* KEYUSAGE('HANDSHAKE DATAENCRYPT DOCSIGN') + +/* ALTNAME('DOMAIN=localhost') + +/* SIGNWITH(CERTAUTH,ZOWECA) + +/* Option 2 - END .................................................. */ + +/* Connect a Zowe's certificate with the keyring ................... */ + TSS ADD(&ZOWEUSER.) KEYRING(ZOWERING) LABLRING(&ZOWERING.) + + RINGDATA(&ZOWEUSER.,ZOWECERT) USAGE(PERSONAL) DEFAULT + +/* Connect all CAs of the Zowe certificate's signing chain with the */ +/* keyring ......................................................... */ +/* Add or remove the command(s) according to your requirements ..... */ + TSS ADD(&ZOWEUSER.) KEYRING(ZOWERING) LABLRING(&ZOWERING.) + + RINGDATA(CERTAUTH,>>>set DIGICERT name of root CA<<<) + + TSS ADD(&ZOWEUSER.) KEYRING(ZOWERING) LABLRING(&ZOWERING.) + + RINGDATA(CERTAUTH,>>>set DIGICERT name of intermediate CA<<<) + +/* Connect root CA that signs z/OSMF certificate with the keyring .. */ + TSS ADD(&ZOWEUSER.) KEYRING(ZOWERING) LABLRING(&ZOWERING.) + + RINGDATA(CERTAUTH,>>>set DIGICERT name of zosmf's root CA<<<) + +/* Create jwtsecret .................................................*/ + TSS GENCERT(&ZOWEUSER.) + + DIGICERT(ZOWEJWT) + + SUBJECTN( + + 'CN="&CN. JWT" + + OU="&OU." + + O="&O." + + L="&L." + + SP="&SP." + + C="&C." ') + + KEYSIZE(2048) + + NADATE(05/01/30) + + LABLCERT(jwtsecret) + +/* Connect jwtsecret to the keyring ................................ */ + TSS ADD(&ZOWEUSER.) KEYRING(ZOWERING) LABLRING(&ZOWERING.) + + RINGDATA(&ZOWEUSER.,ZOWEJWT) USAGE(PERSONAL) + +/* Allow ZOWEUSER to access keyring ................................ */ + TSS PERMIT(&ZOWEUSER.) IBMFAC(IRR.DIGTCERT.LISTRING) ACCESS(READ) + +/* List the keyring ................................................ */ + TSS LIST(&ZOWEUSER.) KEYRING(ZOWERING) LABLRING(&ZOWERING.) + +/* ................................................................. */ +/* only the last RC is returned, this command ensures it is a 0 */ +PROFILE +$$ +//* + From 3eb14233f04ac26713021f28d118c7e52fb66ef7 Mon Sep 17 00:00:00 2001 From: Vit Tomica Date: Wed, 6 May 2020 15:45:51 +0200 Subject: [PATCH 11/37] Added ZWEKRING element to SMPE build Signed-off-by: Vit Tomica --- scripts/zowe-install-MVS.sh | 2 +- smpe/bld/SMPMCS.txt | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/scripts/zowe-install-MVS.sh b/scripts/zowe-install-MVS.sh index 22ebaba337..32a0951f57 100644 --- a/scripts/zowe-install-MVS.sh +++ b/scripts/zowe-install-MVS.sh @@ -12,7 +12,7 @@ sizeAUTH='space(30,15) tracks' sizeSAMP='space(15,15) tracks' -members='ZWESVSTC.jcl ZWESECUR.jcl ZWENOSEC.jcl' +members='ZWESVSTC.jcl ZWESECUR.jcl ZWENOSEC.jcl ZWEKRING.jcl' # info: construct ${variable%%.*} keeps up to first . (exclusive) diff --git a/smpe/bld/SMPMCS.txt b/smpe/bld/SMPMCS.txt index 36112b724c..3d03dc912b 100755 --- a/smpe/bld/SMPMCS.txt +++ b/smpe/bld/SMPMCS.txt @@ -27,6 +27,7 @@ ++SAMP(ZWESASTC) SYSLIB(SZWESAMP) DISTLIB(AZWESAMP) RELFILE(2) . ++SAMP(ZWENOSEC) SYSLIB(SZWESAMP) DISTLIB(AZWESAMP) RELFILE(2) . ++SAMP(ZWESECUR) SYSLIB(SZWESAMP) DISTLIB(AZWESAMP) RELFILE(2) . +++SAMP(ZWEKRING) SYSLIB(SZWESAMP) DISTLIB(AZWESAMP) RELFILE(2) . ++SAMP(ZWESIPRG) SYSLIB(SZWESAMP) DISTLIB(AZWESAMP) RELFILE(2) . ++SAMP(ZWESIP00) SYSLIB(SZWESAMP) DISTLIB(AZWESAMP) RELFILE(2) . ++SAMP(ZWESISCH) SYSLIB(SZWESAMP) DISTLIB(AZWESAMP) RELFILE(2) . @@ -71,4 +72,4 @@ ++HFS(ZWEWRF01) SYSLIB(SZWEZFS ) DISTLIB(AZWEZFS ) RELFILE(4) TEXT PARM(PATHMODE(0,7,5,5)) . ++HFS(ZWEYML01) SYSLIB(SZWEZFS ) DISTLIB(AZWEZFS ) RELFILE(4) - TEXT PARM(PATHMODE(0,7,5,5)) . \ No newline at end of file + TEXT PARM(PATHMODE(0,7,5,5)) . From 31119027488b22177fbe1fbefd060d79dd746166 Mon Sep 17 00:00:00 2001 From: Vit Tomica Date: Thu, 7 May 2020 12:53:54 +0200 Subject: [PATCH 12/37] Do not build keyring-util program. Ship pre-built binaries instead. Signed-off-by: Vit Tomica --- bin/apiml_cm.sh | 6 +- bin/utils/keyring-util/README.md | 66 ++++++---- bin/utils/keyring-util/build.sh | 1 - bin/utils/keyring-util/keyring-util | Bin 0 -> 65536 bytes bin/utils/keyring-util/keyring-util.c | 175 -------------------------- bin/utils/keyring-util/keyring-util.h | 70 ----------- bin/zowe-setup-certificates.sh | 6 - 7 files changed, 46 insertions(+), 278 deletions(-) delete mode 100644 bin/utils/keyring-util/build.sh create mode 100644 bin/utils/keyring-util/keyring-util delete mode 100644 bin/utils/keyring-util/keyring-util.c delete mode 100644 bin/utils/keyring-util/keyring-util.h diff --git a/bin/apiml_cm.sh b/bin/apiml_cm.sh index b24ccaf31c..d0443c5c4f 100644 --- a/bin/apiml_cm.sh +++ b/bin/apiml_cm.sh @@ -86,7 +86,7 @@ function pkeytool { function clean_keyring { if [[ "${SERVICE_STORETYPE}" == "JCERACFKS" ]]; then - KEYRING_UTIL=`dirname ${SERVICE_KEYSTORE}`/../keyring-util + KEYRING_UTIL=${BASE_DIR}/utils/keyring-util/keyring-util echo "Removing ${ZOWE_USERID}/${ZOWE_KEYRING} keyring" $KEYRING_UTIL delring ${ZOWE_USERID} ${ZOWE_KEYRING} fi @@ -95,7 +95,7 @@ function clean_keyring { function clean_local_ca { rm -f ${LOCAL_CA_FILENAME}.keystore.p12 ${LOCAL_CA_FILENAME}.cer if [[ "${SERVICE_STORETYPE}" == "JCERACFKS" ]]; then - KEYRING_UTIL=`dirname ${LOCAL_CA_FILENAME}`/../keyring-util + KEYRING_UTIL=${BASE_DIR}/utils/keyring-util/keyring-util echo "Disconnecting ${LOCAL_CA_ALIAS} certificate from the ${ZOWE_KEYRING} keyring" $KEYRING_UTIL delcert ${ZOWE_USERID} ${ZOWE_KEYRING} ${LOCAL_CA_ALIAS} echo "Removing ${LOCAL_CA_ALIAS} certificate from RACF database" @@ -106,7 +106,7 @@ function clean_local_ca { function clean_service { rm -f ${SERVICE_KEYSTORE}.p12 ${SERVICE_KEYSTORE}.csr ${SERVICE_KEYSTORE}_signed.cer ${SERVICE_TRUSTSTORE}.p12 if [[ "${SERVICE_STORETYPE}" == "JCERACFKS" ]]; then - KEYRING_UTIL=`dirname ${SERVICE_KEYSTORE}`/../keyring-util + KEYRING_UTIL=${BASE_DIR}/utils/keyring-util/keyring-util echo "Disconnecting ${SERVICE_ALIAS} certificate from the ${ZOWE_KEYRING} keyring" $KEYRING_UTIL delcert ${ZOWE_USERID} ${ZOWE_KEYRING} ${SERVICE_ALIAS} echo "Disconnecting ${JWT_ALIAS} certificate from the ${ZOWE_KEYRING} keyring" diff --git a/bin/utils/keyring-util/README.md b/bin/utils/keyring-util/README.md index 1f863f877a..15f78d8300 100644 --- a/bin/utils/keyring-util/README.md +++ b/bin/utils/keyring-util/README.md @@ -1,49 +1,69 @@ -# keyring-util +The keyring-util's source code can be found in the +https://github.com/zowe/keyring-utilities -The keyring-util program leverages -[R_datalib callable service](https://www.ibm.com/support/knowledgecenter/SSLTBW_2.4.0/com.ibm.zos.v2r4.ichd100/datalib.htm) +# keyring-util + +The keyring-util program leverages +[R_datalib callable service](https://www.ibm.com/support/knowledgecenter/SSLTBW_2.4.0/com.ibm.zos.v2r4.ichd100/datalib.htm) to perform various operations on digital certificates and RACF key rings. -## Syntax +## Build +Execute the `build.sh` script + +## Syntax ```bash keyring-util function userid keyring label ``` **Parametres:** 1. `function` see [Functions](##Functions) section below - 2. `userid` - an owner of the `keyring` and `label` certificate + 2. `userid` - an owner of the `keyring` and `label` certificate 3. `keyring` - a name of the keyring - 4. `label` - a label of the certificate + 4. `label` - a label of the certificate + 5. `extra-parm-1` - specific to a used function + 6. `extra-parm-2` - specific to a used function ## Functions - + * `NEWRING` - creates a keyring - * Example: `keyring-util NEWRING USER01 ZOWERING` - + * Example: `keyring-util NEWRING USER01 RING02` + * `DELRING` - deletes a keyring - * Example: `keyring-util DELRING USER01 ZOWERING` - + * Example: `keyring-util DELRING USER01 RING02` + * `DELCERT` - remove a certificate from a keyring or deletes a certificate from RACF database - - **Current Limitation:** The `DELCERT` function can only manipulate a certificate that is owned by the `userid`, i.e. it can't + + **Current Limitation:** The `DELCERT` function can only manipulate a certificate that is owned by the `userid`, i.e. it can't work with certificates owned by the CERTAUTH, SITE or different userid. - - The following example removes `localhost` certificate owned by the `USER01` from the `ZOWERING` keyring owned by the `USER01` userid - * Example: `keyring-util DELCERT USER01 ZOWERING localhost` + + The following example removes `CERT03` certificate owned by the `USER01` from the `RING02` keyring owned by the `USER01` userid + * Example: `keyring-util DELCERT USER01 RING02 CERT03` + + The following example removes `CERT03` certificate owned by the `USER01` from the RACF database. The command fails if the certificate + is still connected to some keyring. + * Example: `keyring-util DELCERT USER01 '*' CERT03` + + * `EXPORT` - exports a certificate in PEM format. The file is created in a `pwd` directory with a name of `.pem` + * Example: `keyring-util EXPORT USER01 RING02 CERT03` + + Creates a file CERT03.pem. + + * `IMPORT` - imports a certificate from the PKCS12 format. - The following example removes `localhost` certificate owned by the `USER01` from the RACF database. The command fails if the certificate - is still connected to some keyring. - * Example: `keyring-util DELCERT USER01 '*' localhost` + **Warning:** The scenario where a private key is also imported currently works only with RACF. + * Example: `keyring-util IMPORT USER01 RING02 CERT03 /path/to/file.p12 pkcs12_password` + * `REFRESH` - refreshes DIGTCERT class * Example: `keyring-util REFRESH` - + For any return and reason codes, check [R_datalib return and reason codes](https://www.ibm.com/support/knowledgecenter/SSLTBW_2.4.0/com.ibm.zos.v2r4.ichd100/ich2d100238.htm) ## Further development -There is room for improvement: +There is room for improvement: * command line argument processing and syntax (perhaps using the argp library from [ambitus project](https://github.com/ambitus/glibc/tree/zos/2.28/master/argp)) * an extension of functionality of the current R_datalib functions - * adding support for other [R_datalib functions](https://www.ibm.com/support/knowledgecenter/SSLTBW_2.4.0/com.ibm.zos.v2r4.ichd100/ich2d100226.htm) - + * adding support for other [R_datalib functions](https://www.ibm.com/support/knowledgecenter/SSLTBW_2.4.0/com.ibm.zos.v2r4.ichd100/ich2d100226.htm) + Work with the following resource if you want to add support for other R_datalib functions [Data areas for R_datalib callable service](https://www.ibm.com/support/knowledgecenter/SSLTBW_2.4.0/com.ibm.zos.v2r4.ichc400/comx.htm) + diff --git a/bin/utils/keyring-util/build.sh b/bin/utils/keyring-util/build.sh deleted file mode 100644 index 798e388dd2..0000000000 --- a/bin/utils/keyring-util/build.sh +++ /dev/null @@ -1 +0,0 @@ -xlc -q64 -o keyring-util keyring-util.c diff --git a/bin/utils/keyring-util/keyring-util b/bin/utils/keyring-util/keyring-util new file mode 100644 index 0000000000000000000000000000000000000000..675de00fe922bc61d78103c4f4b3f4252d300706 GIT binary patch literal 65536 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 vV}2UH -#include -#include - -#ifdef _LP64 - #pragma linkage(IRRSDL64, OS) -#else - #error "31-bit not supported yet." -#endif - -#include "keyring-util.h" - -int debug = 0; - -int main(int argc, char **argv) -{ - int i; - - if (getenv("KEYRING_UTIL_DEBUG") != NULL && ! strcmp(getenv("KEYRING_UTIL_DEBUG"), "YES")) { - debug = 1; - } - Command_line_parms parms; - memset(&parms, 0, sizeof(Command_line_parms)); - - R_datalib_data_remove rem_parm; - memset(&rem_parm, 0x00, sizeof(R_datalib_data_remove)); - - R_datalib_parm_list_64 p; - - process_cmdline_parms(&parms, argc, argv); - - R_datalib_function function_table[] = { - {"NEWRING", NEWRING_CODE, 0x00000000, 0, NULL, simple_action}, - {"DELCERT", DELCERT_CODE, 0x00000000, 0, &rem_parm, delcert_action}, - {"DELRING", DELRING_CODE, 0x00000000, 0, NULL, simple_action}, - {"REFRESH", REFRESH_CODE, 0x00000000, 0, NULL, simple_action}, - {"HELP", HELP_CODE, 0x00000000, 0, NULL, print_help}, - {"NOTSUPPORTED", NOTSUPPORTED_CODE, 0x00000000, 0, NULL, print_help} - }; - - R_datalib_function function; - for (i = 0; i < sizeof(function_table)/sizeof(R_datalib_function); i++) { - if (strncasecmp(function_table[i].name, parms.function, sizeof(parms.function)) == 0) { - function = function_table[i]; - break; - } - function = function_table[sizeof(function_table)/sizeof(R_datalib_function) - 1]; - } - if (debug) { - printf("Selected function is %s with code of %.2X\n", function.name, function.code); - } - function.action(&p, &function, &parms); - - return 0; -} - -void simple_action(R_datalib_parm_list_64* rdatalib_parms, void * function, Command_line_parms* parms) { - R_datalib_function *func = function; - if (debug) { - printf("%s action\n", func->name); - } - set_up_R_datalib_parameters(rdatalib_parms, function, parms->userid, parms->keyring); - invoke_R_datalib(rdatalib_parms); - check_return_code(rdatalib_parms); -} - -void delcert_action(R_datalib_parm_list_64* rdatalib_parms, void * function, Command_line_parms* parms) { - R_datalib_function *func = function; - R_datalib_data_remove *rem_parm = func->parmlist; - - if (debug) { - printf("%s action\n", func->name); - } - rem_parm->label_len = strlen(parms->label); - rem_parm->label_addr = parms->label; - rem_parm->CERT_userid_len = 0x00; - - set_up_R_datalib_parameters(rdatalib_parms, func, parms->userid, parms->keyring); - invoke_R_datalib(rdatalib_parms); - check_return_code(rdatalib_parms); - // refresh DIGTCERT class if required - if (rdatalib_parms->return_code == 4 && rdatalib_parms->RACF_return_code == 4 && rdatalib_parms->RACF_reason_code == 12) { - printf("DIGTCERT class has to refreshed.\n"); - func->code = REFRESH_CODE; - set_up_R_datalib_parameters(rdatalib_parms, func, "", ""); - invoke_R_datalib(rdatalib_parms); - check_return_code(rdatalib_parms); - printf("DIGTCERT class refreshed.\n"); - } -} - -void validate_and_set_parm(char * parm, char * cmd_parm, int maxlen) { - if (strlen(cmd_parm) <= maxlen) { - strcpy(parm, cmd_parm); - } else { - printf("ERROR: %s parm too long and will not be set.\n", cmd_parm); - } -} - -void check_return_code(R_datalib_parm_list_64* p) { - if (p->return_code != 0 || p->RACF_return_code != 0 || p->RACF_reason_code != 0) { - printf("Function code: %.2X, SAF rc: %d, RACF rc: %d, RACF rsn: %d\n", - p->function_code, p->return_code, p->RACF_return_code, p->RACF_reason_code); - } -} - -void process_cmdline_parms(Command_line_parms* parms, int argc, char** argv) { - int i; - for (i = 1; i < argc; i++) { - if (debug) { - printf("%d. parameter: %s\n", i, argv[i]); - } - switch(i) { - case 1: - validate_and_set_parm(parms->function, argv[i], MAX_FUNCTION_LEN); - break; - case 2: - validate_and_set_parm(parms->userid, argv[i], MAX_USERID_LEN); - break; - case 3: - validate_and_set_parm(parms->keyring, argv[i], MAX_KEYRING_LEN); - break; - case 4: - validate_and_set_parm(parms->label, argv[i], MAX_LABEL_LEN); - break; - default: - printf("WARNING: %i. parameter - %s - is currently not supported and will be ignored.\n", i, argv[i]); - } - } -} - -void invoke_R_datalib(R_datalib_parm_list_64 * p) { - - IRRSDL64( - &p->num_parms, - &p->workarea, - &p->saf_rc_ALET, &p->return_code, - &p->racf_rc_ALET, &p->RACF_return_code, - &p->racf_rsn_ALET, &p->RACF_reason_code, - &p->function_code, - &p->attributes, - &p->RACF_userid_len, - &p->ring_name_len, - &p->parm_list_version, - p->parmlist - ); -} - -void set_up_R_datalib_parameters(R_datalib_parm_list_64 * p, R_datalib_function * function, char * userid, char * keyring) { - memset(p, 0, sizeof(R_datalib_parm_list_64)); - p->num_parms = 14; - p->saf_rc_ALET = 0; - p->racf_rc_ALET = 0; - p->racf_rsn_ALET = 0; - p->function_code = function->code; - p->attributes = function->default_attributes; - memset(&p->RACF_userid_len, strlen(userid), 1); - memcpy(p->RACF_userid, userid, strlen(userid)); - memset(&p->ring_name_len, strlen(keyring), 1); - memcpy(p->ring_name, keyring, strlen(keyring)); - p->parm_list_version = function->parm_list_version; - p->parmlist = function->parmlist; -} - -void print_help(R_datalib_parm_list_64* rdatalib_parms, void * function, Command_line_parms* parms) { - printf("----------------------------------------------------\n"); - printf("Usage: keyring-util function userid keyring label\n"); - printf("----------------------------------------------------\n"); - printf("function:\n"); - printf("NEWRING - creates a new keyring.\n"); - printf("DELRING - deletes a keyring\n"); - printf("DELCERT - disconnects a certificate (label) from a keyring or deletes a certificate from RACF database\n"); - printf("REFRESH - refreshes DIGTCERT class\n"); - printf("HELP - prints this help\n"); -} diff --git a/bin/utils/keyring-util/keyring-util.h b/bin/utils/keyring-util/keyring-util.h deleted file mode 100644 index 85f261e7cb..0000000000 --- a/bin/utils/keyring-util/keyring-util.h +++ /dev/null @@ -1,70 +0,0 @@ -#ifndef _keyring_util -#define _keyring_util - -#define MAX_FUNCTION_LEN 16 -#define MAX_USERID_LEN 8 -#define MAX_KEYRING_LEN 236 -#define MAX_LABEL_LEN 32 - -#define NEWRING_CODE 0x07 -#define DELCERT_CODE 0x09 -#define DELRING_CODE 0x0A -#define REFRESH_CODE 0x0B -#define HELP_CODE 0x00 -#define NOTSUPPORTED_CODE 0x00 - - -typedef struct _Command_line_params { - char function[MAX_FUNCTION_LEN]; - char userid[MAX_USERID_LEN + 1]; - char keyring[MAX_KEYRING_LEN + 1]; - char label[MAX_LABEL_LEN + 1]; - -} Command_line_parms; - -typedef struct _R_datalib_parm_list_64 { - int num_parms; - double workarea[128]; // double word aligned, 1024 bytes long workarea - int saf_rc_ALET, return_code; - int racf_rc_ALET, RACF_return_code; - int racf_rsn_ALET, RACF_reason_code; - char function_code; - int attributes; - char RACF_userid_len; // DO NOT change position of this field - char RACF_userid[MAX_USERID_LEN]; // DO NOT change position of this field - char ring_name_len; // DO NOT change position of this field - char ring_name[MAX_KEYRING_LEN]; // DO NOT change position of this field - int parm_list_version; - void *parmlist; -} R_datalib_parm_list_64; - -typedef void (*function_action)(R_datalib_parm_list_64*, void*, Command_line_parms*); - -typedef struct _R_datalib_function { - char name[MAX_FUNCTION_LEN]; - char code; - int default_attributes; - int parm_list_version; - void *parmlist; - function_action action; -} R_datalib_function; - -typedef _Packed struct _R_datalib_data_remove { - int label_len; - int reserve_1; - char *label_addr; - char CERT_userid_len; // DO NOT change position of this field - char CERT_userid[MAX_USERID_LEN]; // DO NOT change position of this field - char reserved_2[3]; -} R_datalib_data_remove; - -void invoke_R_datalib(R_datalib_parm_list_64*); -void set_up_R_datalib_parameters(R_datalib_parm_list_64* , R_datalib_function* , char* ,char* ); -void simple_action(R_datalib_parm_list_64*, void*, Command_line_parms*); -void delcert_action(R_datalib_parm_list_64*, void*, Command_line_parms*); -void print_help(R_datalib_parm_list_64*, void*, Command_line_parms*); -void process_cmdline_parms(Command_line_parms*, int , char**); -void validate_and_set_parm(char*, char*, int); -void check_return_code(R_datalib_parm_list_64*); - -#endif diff --git a/bin/zowe-setup-certificates.sh b/bin/zowe-setup-certificates.sh index f4ff8958c5..9a8bb9403e 100644 --- a/bin/zowe-setup-certificates.sh +++ b/bin/zowe-setup-certificates.sh @@ -84,12 +84,6 @@ if [ ! -d ${KEYSTORE_DIRECTORY}/${KEYSTORE_ALIAS} ]; then fi fi -# build keyring-util program -if [[ -n "${ZOWE_KEYRING}" ]]; then - xlc -q64 -o ${KEYSTORE_DIRECTORY}/keyring-util ${ZOWE_ROOT_DIR}/bin/utils/keyring-util/keyring-util.c >> $LOG_FILE - rm ${KEYSTORE_DIRECTORY}/keyring-util.o 2> /dev/null -fi - echo "Creating certificates and keystores... STARTED" # set up parameters for apiml_cm.sh script KEYSTORE_PREFIX="${KEYSTORE_DIRECTORY}/${KEYSTORE_ALIAS}/${KEYSTORE_ALIAS}.keystore" From 024520a98fa72e344d7924a777057e0eb2f6033b Mon Sep 17 00:00:00 2001 From: Vit Tomica Date: Thu, 7 May 2020 13:20:07 +0200 Subject: [PATCH 13/37] Do not export private key and cert when using a keyring Signed-off-by: Vit Tomica --- bin/apiml_cm.sh | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/bin/apiml_cm.sh b/bin/apiml_cm.sh index d0443c5c4f..8d66812eb9 100644 --- a/bin/apiml_cm.sh +++ b/bin/apiml_cm.sh @@ -268,10 +268,7 @@ function import_external_certificate { function export_service_certificate { echo "Export service certificate to the PEM format" - if [[ "${SERVICE_STORETYPE}" == "JCERACFKS" ]]; then - pkeytool -exportcert -alias ${SERVICE_ALIAS} -keystore safkeyring://${ZOWE_USERID}/${ZOWE_KEYRING} -storetype ${SERVICE_STORETYPE} -rfc -file ${SERVICE_KEYSTORE}.cer \ - -J-Djava.protocol.handler.pkgs=com.ibm.crypto.provider - else + if [[ "${SERVICE_STORETYPE}" == "PKCS12" ]]; then pkeytool -exportcert -alias ${SERVICE_ALIAS} -keystore ${SERVICE_KEYSTORE}.p12 -storetype ${SERVICE_STORETYPE} -storepass ${SERVICE_PASSWORD} -rfc -file ${SERVICE_KEYSTORE}.cer fi @@ -340,10 +337,7 @@ EOF echo "cat returned $?" javac ${TEMP_DIR}/ExportPrivateKey.java echo "javac returned $?" - if [[ "${SERVICE_STORETYPE}" == "JCERACFKS" ]]; then - java -Djava.protocol.handler.pkgs=com.ibm.crypto.provider \ - -cp ${TEMP_DIR} ExportPrivateKey safkeyring://${ZOWE_USERID}/${ZOWE_KEYRING} ${SERVICE_STORETYPE} "" ${SERVICE_ALIAS} "" ${SERVICE_KEYSTORE}.key - else + if [[ "${SERVICE_STORETYPE}" == "PKCS12" ]]; then java -cp ${TEMP_DIR} ExportPrivateKey ${SERVICE_KEYSTORE}.p12 ${SERVICE_STORETYPE} ${SERVICE_PASSWORD} ${SERVICE_ALIAS} ${SERVICE_PASSWORD} ${SERVICE_KEYSTORE}.key fi echo "java returned $?" From 26d77f66b966387791651122a0ea05a02935e51d Mon Sep 17 00:00:00 2001 From: Vit Tomica Date: Thu, 7 May 2020 15:08:12 +0200 Subject: [PATCH 14/37] Do not generate certificates for keyring if ZWEKRING jcl already did Signed-off-by: Vit Tomica --- bin/apiml_cm.sh | 6 +++++- bin/zowe-setup-certificates.env | 3 +++ bin/zowe-setup-certificates.sh | 24 +++++++++++++++++------- 3 files changed, 25 insertions(+), 8 deletions(-) diff --git a/bin/apiml_cm.sh b/bin/apiml_cm.sh index 8d66812eb9..6ed58a6569 100644 --- a/bin/apiml_cm.sh +++ b/bin/apiml_cm.sh @@ -619,7 +619,11 @@ case $ACTION in trust ;; trust-zosmf) - trust_zosmf + if [[ "${SERVICE_STORETYPE}" == "JCERACFKS" ]] && [[ "${GENERATE_CERTS_FOR_KEYRING}" == "false" ]]; then + echo "Trust z/OSMF action is skipped for keyring setup." + else + trust_zosmf + fi zosmf_jwt_public_key ;; cert-key-export) diff --git a/bin/zowe-setup-certificates.env b/bin/zowe-setup-certificates.env index 12a772b26b..c97f5b8929 100644 --- a/bin/zowe-setup-certificates.env +++ b/bin/zowe-setup-certificates.env @@ -39,3 +39,6 @@ ZOWE_GROUP_ID=ZWEADMIN # Specify zowe keyring that keeps zowe certificates, if not specified USS keystore # files will be created. ZOWE_KEYRING= +# If you used ZWEKRING jcl to configure certificates and the keyring +# then set this variable to false (defaults to false) +GENERATE_CERTS_FOR_KEYRING=false diff --git a/bin/zowe-setup-certificates.sh b/bin/zowe-setup-certificates.sh index 9a8bb9403e..adf5e4ee6d 100644 --- a/bin/zowe-setup-certificates.sh +++ b/bin/zowe-setup-certificates.sh @@ -15,6 +15,8 @@ # - ZOWE_USER_ID - zowe user id to set up ownership of the generated certificates # - ZOWE_KEYRING - specify zowe keyring that keeps zowe certificates, if not specified USS keystore # files will be created. +# - GENERATE_CERTS_FOR_KEYRING - If you used ZWEKRING jcl to configure certificates and the keyring +# then set this variable to false (defaults to false) # process input parameters. while getopts "l:p:" opt; do @@ -101,12 +103,16 @@ if [[ -z "${EXTERNAL_CERTIFICATE}" ]] || [[ -z "${EXTERNAL_CERTIFICATE_ALIAS}" ] if [[ -z "${ZOWE_KEYRING}" ]]; then ${ZOWE_ROOT_DIR}/bin/apiml_cm.sh --verbose --log $LOG_FILE --action setup --service-ext ${SAN} --service-password ${KEYSTORE_PASSWORD} \ --service-alias ${KEYSTORE_ALIAS} --service-keystore ${KEYSTORE_PREFIX} --service-truststore ${TRUSTSTORE_PREFIX} --local-ca-filename ${LOCAL_CA_PREFIX} - else + RC=$? + echo "apiml_cm.sh --action setup returned: $RC" >> $LOG_FILE + elif [[ "${GENERATE_CERTS_FOR_KEYRING}" != "false" ]]; then ${ZOWE_ROOT_DIR}/bin/apiml_cm.sh --verbose --log $LOG_FILE --action setup --service-ext ${SAN} --service-keystore ${KEYSTORE_PREFIX} \ --service-alias ${KEYSTORE_ALIAS} --zowe-userid ${ZOWE_USER_ID} --zowe-keyring ${ZOWE_KEYRING} --service-storetype "JCERACFKS" --local-ca-filename ${LOCAL_CA_PREFIX} + RC=$? + echo "apiml_cm.sh --action setup returned: $RC" >> $LOG_FILE + else + echo "Generating certificates for the keyring is skipped." fi - RC=$? - echo "apiml_cm.sh --action setup returned: $RC" >> $LOG_FILE else (>&2 echo "Zowe Install setup configuration is invalid; check your zowe-setup-certificates.env file.") (>&2 echo "Some external apiml certificate fields are supplied...Fields must be filled out in full or left completely blank.") @@ -126,14 +132,17 @@ else --external-certificate ${EXTERNAL_CERTIFICATE} --external-certificate-alias ${EXTERNAL_CERTIFICATE_ALIAS} ${EXT_CA_PARM} \ --service-alias ${KEYSTORE_ALIAS} --service-keystore ${KEYSTORE_PREFIX} --service-truststore ${TRUSTSTORE_PREFIX} --local-ca-filename ${LOCAL_CA_PREFIX} \ --external-ca-filename ${EXTERNAL_CA_PREFIX} - else + RC=$? + echo "apiml_cm.sh --action setup returned: $RC" >> $LOG_FILE + elif [[ "${GENERATE_CERTS_FOR_KEYRING}" != "false" ]]; then ${ZOWE_ROOT_DIR}/bin/apiml_cm.sh --verbose --log $LOG_FILE --action setup --service-ext ${SAN} --zowe-userid ${ZOWE_USER_ID} --zowe-keyring ${ZOWE_KEYRING} \ --service-storetype "JCERACFKS" --external-certificate ${EXTERNAL_CERTIFICATE} --external-certificate-alias ${EXTERNAL_CERTIFICATE_ALIAS} \ --service-alias ${KEYSTORE_ALIAS} --service-keystore ${KEYSTORE_PREFIX} --local-ca-filename ${LOCAL_CA_PREFIX} + RC=$? + echo "apiml_cm.sh --action setup returned: $RC" >> $LOG_FILE + else + echo "Generating certificates for the keyring is skipped." fi - RC=$? - - echo "apiml_cm.sh --action setup returned: $RC" >> $LOG_FILE fi if [ "$RC" -ne "0" ]; then @@ -149,6 +158,7 @@ if [[ "${VERIFY_CERTIFICATES}" == "true" ]]; then --service-password ${KEYSTORE_PASSWORD} --service-truststore ${TRUSTSTORE_PREFIX} --zosmf-certificate "${ZOSMF_CERTIFICATE}" \ --service-keystore ${KEYSTORE_PREFIX} else + export GENERATE_CERTS_FOR_KEYRING; ${ZOWE_ROOT_DIR}/bin/apiml_cm.sh --verbose --log $LOG_FILE --action trust-zosmf --zowe-userid ${ZOWE_USER_ID} \ --zowe-keyring ${ZOWE_KEYRING} --service-storetype "JCERACFKS" --zosmf-certificate "${ZOSMF_CERTIFICATE}" \ --service-keystore ${KEYSTORE_PREFIX} From 04a975e40604f76ac65263adeda974c2ad05b217 Mon Sep 17 00:00:00 2001 From: Vit Tomica Date: Thu, 7 May 2020 17:52:14 +0200 Subject: [PATCH 15/37] Remove KEYSTORE_KEY,KEYSTORE_CERTIFICATE,KEYSTORE_CERTIFICATE_AUTHORITY variables when using keyring Signed-off-by: Vit Tomica --- bin/zowe-setup-certificates.sh | 3 --- 1 file changed, 3 deletions(-) diff --git a/bin/zowe-setup-certificates.sh b/bin/zowe-setup-certificates.sh index adf5e4ee6d..6123ceadd8 100644 --- a/bin/zowe-setup-certificates.sh +++ b/bin/zowe-setup-certificates.sh @@ -201,9 +201,6 @@ else KEYSTORE="safkeyring:////${ZOWE_USER_ID}/${ZOWE_KEYRING}" KEYSTORE_TYPE="JCERACFKS" TRUSTSTORE="safkeyring:////${ZOWE_USER_ID}/${ZOWE_KEYRING}" - KEYSTORE_KEY=${KEYSTORE_PREFIX}.key - KEYSTORE_CERTIFICATE=${KEYSTORE_PREFIX}.cer-ebcdic - KEYSTORE_CERTIFICATE_AUTHORITY=${LOCAL_CA_PREFIX}.cer-ebcdic ZOWE_APIM_VERIFY_CERTIFICATES=${VERIFY_CERTIFICATES} EOF fi From 7164302b41b10219286590c88ba7644a05df811e Mon Sep 17 00:00:00 2001 From: Vit Tomica Date: Thu, 7 May 2020 18:15:37 +0200 Subject: [PATCH 16/37] added 'chmod +x' for keyring_util; fix iconv Signed-off-by: Vit Tomica --- bin/apiml_cm.sh | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/bin/apiml_cm.sh b/bin/apiml_cm.sh index 6ed58a6569..673db135a8 100644 --- a/bin/apiml_cm.sh +++ b/bin/apiml_cm.sh @@ -87,6 +87,7 @@ function pkeytool { function clean_keyring { if [[ "${SERVICE_STORETYPE}" == "JCERACFKS" ]]; then KEYRING_UTIL=${BASE_DIR}/utils/keyring-util/keyring-util + chmod +x $KEYRING_UTIL echo "Removing ${ZOWE_USERID}/${ZOWE_KEYRING} keyring" $KEYRING_UTIL delring ${ZOWE_USERID} ${ZOWE_KEYRING} fi @@ -96,6 +97,7 @@ function clean_local_ca { rm -f ${LOCAL_CA_FILENAME}.keystore.p12 ${LOCAL_CA_FILENAME}.cer if [[ "${SERVICE_STORETYPE}" == "JCERACFKS" ]]; then KEYRING_UTIL=${BASE_DIR}/utils/keyring-util/keyring-util + chmod +x $KEYRING_UTIL echo "Disconnecting ${LOCAL_CA_ALIAS} certificate from the ${ZOWE_KEYRING} keyring" $KEYRING_UTIL delcert ${ZOWE_USERID} ${ZOWE_KEYRING} ${LOCAL_CA_ALIAS} echo "Removing ${LOCAL_CA_ALIAS} certificate from RACF database" @@ -107,6 +109,7 @@ function clean_service { rm -f ${SERVICE_KEYSTORE}.p12 ${SERVICE_KEYSTORE}.csr ${SERVICE_KEYSTORE}_signed.cer ${SERVICE_TRUSTSTORE}.p12 if [[ "${SERVICE_STORETYPE}" == "JCERACFKS" ]]; then KEYRING_UTIL=${BASE_DIR}/utils/keyring-util/keyring-util + chmod +x $KEYRING_UTIL echo "Disconnecting ${SERVICE_ALIAS} certificate from the ${ZOWE_KEYRING} keyring" $KEYRING_UTIL delcert ${ZOWE_USERID} ${ZOWE_KEYRING} ${SERVICE_ALIAS} echo "Disconnecting ${JWT_ALIAS} certificate from the ${ZOWE_KEYRING} keyring" @@ -270,10 +273,9 @@ function export_service_certificate { echo "Export service certificate to the PEM format" if [[ "${SERVICE_STORETYPE}" == "PKCS12" ]]; then pkeytool -exportcert -alias ${SERVICE_ALIAS} -keystore ${SERVICE_KEYSTORE}.p12 -storetype ${SERVICE_STORETYPE} -storepass ${SERVICE_PASSWORD} -rfc -file ${SERVICE_KEYSTORE}.cer - fi - - if [ `uname` = "OS/390" ]; then - iconv -f ISO8859-1 -t IBM-1047 ${SERVICE_KEYSTORE}.cer > ${SERVICE_KEYSTORE}.cer-ebcdic + if [ `uname` = "OS/390" ]; then + iconv -f ISO8859-1 -t IBM-1047 ${SERVICE_KEYSTORE}.cer > ${SERVICE_KEYSTORE}.cer-ebcdic + fi fi } From 11315da31802446fda720768c5b63b96b8c352dd Mon Sep 17 00:00:00 2001 From: Vit Tomica Date: Tue, 12 May 2020 14:23:11 +0200 Subject: [PATCH 17/37] add descriptions Signed-off-by: Vit Tomica --- bin/zowe-setup-certificates.env | 29 ++++++++++++++++++----------- files/jcl/ZWEKRING.jcl | 6 +++++- 2 files changed, 23 insertions(+), 12 deletions(-) diff --git a/bin/zowe-setup-certificates.env b/bin/zowe-setup-certificates.env index c97f5b8929..78498c4139 100644 --- a/bin/zowe-setup-certificates.env +++ b/bin/zowe-setup-certificates.env @@ -1,7 +1,7 @@ # Zowe development: if you edit this file, please make sure to update the # ../workflows/ZWEWRF05.xml file accordingly. -# The hostname of the system running API Mediation. If the hostname is +# The hostname of the system running API Mediation. If the hostname is # omitted, the configuration script attempts to calculate the value on # its own. HOSTNAME= @@ -13,32 +13,39 @@ IPADDRESS= VERIFY_CERTIFICATES=true # optional - Path to a PKCS12 keystore with a server certificate for API -# Mediaton Layer (APIML) +# Mediaton Layer (APIML). Ignore if you used the ZWEKRING jcl EXTERNAL_CERTIFICATE= -# optional - Alias of the certificate in the keystore +# optional - Alias of the certificate in the keystore. Ignore if you used +# the ZWEKRING jcl EXTERNAL_CERTIFICATE_ALIAS= # optional - Public certificates of trusted CAs - multiple certificates # delimitad with space has to be enclosed with quotes ("cer1 cer2") +# Ignore if you used the ZWEKRING jcl EXTERNAL_CERTIFICATE_AUTHORITIES= # optional - Public certificates of z/OSMF - multiple certificates # delimited with space has to be enclosed with quotes ("cer1 cer2") +# Ignore if you used the ZWEKRING jcl ZOSMF_CERTIFICATE= - # Select a password that is used to secure EXTERNAL_CERTIFICATE keystore # and that will be also used to secure newly generated keystores for API -# Mediation +# Mediation. Ignore if you used the ZWEKRING jcl KEYSTORE_PASSWORD=password -# Location for generated certificates +# Location for generated certificates and/or JWT token KEYSTORE_DIRECTORY=/global/zowe/keystore -# Select an alias for the certificate in the generated keystore +# Select an alias for the certificate in the generated keystore. +# If you used the ZWEKRING jcl, then this variable has to be set to the +# Zowe certificate's LABEL specified in the JCL. KEYSTORE_ALIAS=localhost -# Specify zowe user id to set up ownership of the generated certificates +# Specify zowe user id to set up ownership of the generated certificates. +# This variable is also used for keyring configuration. If you used +# the ZWEKRING jcl, set the variable to the same user id as in the jcl. ZOWE_USER_ID=ZWESVUSR # Specify zowe group id to set up ownership of the generated certificates ZOWE_GROUP_ID=ZWEADMIN -# Specify zowe keyring that keeps zowe certificates, if not specified USS keystore -# files will be created. +# Specify zowe keyring that keeps zowe certificates, if not specified then +# USS keystore files will be created. If you used the ZWEKRING jcl, set +# the variable to the same keyring that you used in the jcl. ZOWE_KEYRING= -# If you used ZWEKRING jcl to configure certificates and the keyring +# If you used ZWEKRING jcl to configure the certificates for the keyring # then set this variable to false (defaults to false) GENERATE_CERTS_FOR_KEYRING=false diff --git a/files/jcl/ZWEKRING.jcl b/files/jcl/ZWEKRING.jcl index d9ee84e23d..7a6aa7a3bb 100644 --- a/files/jcl/ZWEKRING.jcl +++ b/files/jcl/ZWEKRING.jcl @@ -45,7 +45,11 @@ //* updating the SET statements CN=, OU=, O=, L=, SP= and C=. //* //* 9) Customize the commands in the DD statement that matches your -//* security product so that they meet your system requirements. +//* security product so that they meet your system requirements. +//* Especially focus on the part that is adding all certificates +//* of the CA chain of the Zowe certificate to the key ring. +//* Similarly, add the root CA of the z/OSMF certificate to the +//* keyring. //* //* Note(s): //* From 38779cb33e1564ed55a3afdd024b044dcd97ec22 Mon Sep 17 00:00:00 2001 From: Vit Tomica Date: Thu, 14 May 2020 16:25:39 +0200 Subject: [PATCH 18/37] Always set up trust with zosmf because of retrieving JWT token from zosmf Signed-off-by: Vit Tomica --- bin/apiml_cm.sh | 12 ++++-------- bin/zowe-setup-certificates.sh | 3 ++- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/bin/apiml_cm.sh b/bin/apiml_cm.sh index 673db135a8..4d65317ea5 100644 --- a/bin/apiml_cm.sh +++ b/bin/apiml_cm.sh @@ -394,11 +394,11 @@ function new_self_signed_service { function trust { echo "Import a certificate to the truststore:" - if [[ "${SERVICE_STORETYPE}" == "JCERACFKS" ]]; then + pkeytool -importcert $V -trustcacerts -noprompt -file ${CERTIFICATE} -alias "${ALIAS}" -keystore ${SERVICE_TRUSTSTORE}.p12 -storepass ${SERVICE_PASSWORD} -storetype PKCS12 + + if [[ "${SERVICE_STORETYPE}" == "JCERACFKS" ]] && [[ "${GENERATE_CERTS_FOR_KEYRING}" != "false" ]]; then keytool -importcert $V -trustcacerts -noprompt -file ${CERTIFICATE} -alias "${ALIAS}" -keystore safkeyring://${ZOWE_USERID}/${ZOWE_KEYRING} -storetype ${SERVICE_STORETYPE} \ -J-Djava.protocol.handler.pkgs=com.ibm.crypto.provider - else - pkeytool -importcert $V -trustcacerts -noprompt -file ${CERTIFICATE} -alias "${ALIAS}" -keystore ${SERVICE_TRUSTSTORE}.p12 -storepass ${SERVICE_PASSWORD} -storetype ${SERVICE_STORETYPE} fi } @@ -621,11 +621,7 @@ case $ACTION in trust ;; trust-zosmf) - if [[ "${SERVICE_STORETYPE}" == "JCERACFKS" ]] && [[ "${GENERATE_CERTS_FOR_KEYRING}" == "false" ]]; then - echo "Trust z/OSMF action is skipped for keyring setup." - else - trust_zosmf - fi + trust_zosmf zosmf_jwt_public_key ;; cert-key-export) diff --git a/bin/zowe-setup-certificates.sh b/bin/zowe-setup-certificates.sh index 5cda04bcbd..48c4bb6696 100644 --- a/bin/zowe-setup-certificates.sh +++ b/bin/zowe-setup-certificates.sh @@ -163,7 +163,8 @@ if [[ "${VERIFY_CERTIFICATES}" == "true" ]]; then export GENERATE_CERTS_FOR_KEYRING; ${ZOWE_ROOT_DIR}/bin/apiml_cm.sh --verbose --log $LOG_FILE --action trust-zosmf --zowe-userid ${ZOWE_USER_ID} \ --zowe-keyring ${ZOWE_KEYRING} --service-storetype "JCERACFKS" --zosmf-certificate "${ZOSMF_CERTIFICATE}" \ - --service-keystore ${KEYSTORE_PREFIX} + --service-keystore ${KEYSTORE_PREFIX} --service-password ${KEYSTORE_PASSWORD} \ + --service-truststore ${TRUSTSTORE_PREFIX} fi RC=$? From 31c25178d6231c4e01b84f70358c35643c91c712 Mon Sep 17 00:00:00 2001 From: Vit Tomica Date: Fri, 15 May 2020 12:56:59 +0200 Subject: [PATCH 19/37] ZWEKRING - remove blank between SET LABEL= and a value Signed-off-by: Vit Tomica --- files/jcl/ZWEKRING.jcl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/files/jcl/ZWEKRING.jcl b/files/jcl/ZWEKRING.jcl index 7a6aa7a3bb..d965805f7c 100644 --- a/files/jcl/ZWEKRING.jcl +++ b/files/jcl/ZWEKRING.jcl @@ -77,7 +77,7 @@ //* * Keyring for the Zowe userid // SET ZOWERING='ZoweKeyring' //* * Zowe's certificate label -// SET LABEL= '' +// SET LABEL='' //* * Name of the data set containing Zowe's certificate (PKCS12) // SET DSNAME= //* * Password for the PKCS12 data set From 61fa7a755cc9897fc00b30440b61716454eeceaf Mon Sep 17 00:00:00 2001 From: Vit Tomica Date: Tue, 19 May 2020 10:53:03 +0200 Subject: [PATCH 20/37] create SET variables for signing CA's Signed-off-by: Vit Tomica --- files/jcl/ZWEKRING.jcl | 46 +++++++++++++++++++++++++----------------- 1 file changed, 28 insertions(+), 18 deletions(-) diff --git a/files/jcl/ZWEKRING.jcl b/files/jcl/ZWEKRING.jcl index d965805f7c..09165a8d4b 100644 --- a/files/jcl/ZWEKRING.jcl +++ b/files/jcl/ZWEKRING.jcl @@ -46,17 +46,13 @@ //* //* 9) Customize the commands in the DD statement that matches your //* security product so that they meet your system requirements. -//* Especially focus on the part that is adding all certificates -//* of the CA chain of the Zowe certificate to the key ring. -//* Similarly, add the root CA of the z/OSMF certificate to the -//* keyring. //* //* Note(s): //* //* 1. THE USER ID THAT RUNS THIS JOB MUST HAVE SUFFICIENT AUTHORITY //* TO ALTER SECURITY DEFINITIONS //* -//* 2. Assumption: signing CAs of the Zowe external certificate are +//* 2. Assumption: signing CA chain of the Zowe external certificate is //* added to RACF database under the CERTAUTH userid. //* //* 3. If the Zowe certificate is imported from a data set then @@ -82,6 +78,14 @@ // SET DSNAME= //* * Password for the PKCS12 data set // SET PKCSPASS= +//* * Name/Label of the intermediate CA of the Zowe certificate +//* * Ignore if not applicable +// SET ITRMZWCA= +//* * Name/Label of the root CA of the Zowe certificate +//* * Ignore if not applicable +// SET ROOTZWCA= +//* * Name/Label of the root CA of the z/OSMF certificate +// SET ROOTZFCA= //* * Zowe's local CA common name // SET CN='Zowe Development Instances' //* * Zowe's local CA organizational unit @@ -193,20 +197,23 @@ /* Connect all CAs of the Zowe certificate's signing chain with the */ /* keyring ......................................................... */ -/* Add or remove the command(s) according to your requirements ..... */ +/* Add or remove commands according to the Zowe certificate's */ +/* signing CA chain ................................................ */ RACDCERT CONNECT(CERTAUTH + - LABEL('>>>provide label of root CA<<<') + - RING(&ZOWERING.)) + + LABEL('&ITRMZWCA.') + + RING(&ZOWERING.) USAGE(CERTAUTH)) + ID(&ZOWEUSER.) RACDCERT CONNECT(CERTAUTH + - LABEL('>>>provide label of intermediate CA<<<') + - RING(&ZOWERING.)) + + LABEL('&ROOTZWCA.') + + RING(&ZOWERING.) USAGE(CERTAUTH)) + ID(&ZOWEUSER.) -/* Connect root CA that signs z/OSMF certificate with the keyring .. */ +/* Connect root CA that signed z/OSMF certificate with the keyring. */ +/* If z/OSMF is using self-signed certificate then specify directly */ +/* the z/OSMF certificate to be connected with the keyring. */ RACDCERT CONNECT(CERTAUTH + - LABEL('>>>provide label of zosmf's root CA<<<') + - RING(&ZOWERING.)) + + LABEL('&ROOTZFCA.') + + RING(&ZOWERING.) USAGE(CERTAUTH)) + ID(&ZOWEUSER.) /* Create jwtsecret .................................................*/ @@ -337,16 +344,19 @@ $$ /* Connect all CAs of the Zowe certificate's signing chain with the */ /* keyring ......................................................... */ -/* Add or remove the command(s) according to your requirements ..... */ +/* Add or remove commands according to the Zowe certificate's */ +/* signing CA chain ................................................ */ TSS ADD(&ZOWEUSER.) KEYRING(ZOWERING) LABLRING(&ZOWERING.) + - RINGDATA(CERTAUTH,>>>set DIGICERT name of root CA<<<) + RINGDATA(CERTAUTH,&ITRMZWCA.) USAGE(CERTAUTH) TSS ADD(&ZOWEUSER.) KEYRING(ZOWERING) LABLRING(&ZOWERING.) + - RINGDATA(CERTAUTH,>>>set DIGICERT name of intermediate CA<<<) + RINGDATA(CERTAUTH,&ROOTZWCA.) USAGE(CERTAUTH) -/* Connect root CA that signs z/OSMF certificate with the keyring .. */ +/* Connect root CA that signed z/OSMF certificate with the keyring. */ +/* If z/OSMF is using self-signed certificate then specify directly */ +/* the z/OSMF certificate to be connected with the keyring. */ TSS ADD(&ZOWEUSER.) KEYRING(ZOWERING) LABLRING(&ZOWERING.) + - RINGDATA(CERTAUTH,>>>set DIGICERT name of zosmf's root CA<<<) + RINGDATA(CERTAUTH,&ROOTZFCA.) USAGE(CERTAUTH) /* Create jwtsecret .................................................*/ TSS GENCERT(&ZOWEUSER.) + From 49d6369975d22904e16133871d70ed5c9b6ef70b Mon Sep 17 00:00:00 2001 From: Vit Tomica Date: Fri, 22 May 2020 17:00:26 +0200 Subject: [PATCH 21/37] Added ACF2 commands Signed-off-by: Vit Tomica --- files/jcl/ZWEKRING.jcl | 143 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 138 insertions(+), 5 deletions(-) diff --git a/files/jcl/ZWEKRING.jcl b/files/jcl/ZWEKRING.jcl index 09165a8d4b..af47e97221 100644 --- a/files/jcl/ZWEKRING.jcl +++ b/files/jcl/ZWEKRING.jcl @@ -99,6 +99,13 @@ //* * Zowe's local CA country // SET C='CZ' //* +//* ACF2 ONLY - - - - - - - - - - - - - - - - - +//* 12345678 +// SET STCGRP= * group for Zowe started tasks +//* 12345678 +//* +//* end ACF2 ONLY - - - - - - - - - - - - - - - - +//* //********************************************************************* //* //* EXECUTE COMMANDS FOR SELECTED SECURITY PRODUCT @@ -145,8 +152,8 @@ /* */ /* Options: */ /* 1. Zowe's certificate is already loaded in RACF database */ -/* (assuming under &ZOWEUSER ACID) */ -/* ACTION: No action required */ +/* ACTION: Modify the CONNECT(ID(&ZOWEUSER.) ...) keyword */ +/* below to match the owner of the desired certificate */ /* */ /* 2. Import external Zowe's certificate from a data set in PKCS12 */ /* format */ @@ -255,7 +262,133 @@ $$ //* //ACF2 DD DATA,DLM=$$,SYMBOLS=JCLONLY ACF -//* TODO +// +* Create the keyring + SET PROFILE(USER) DIVISION(KEYRING) + INSERT &ZOWEUSER..ZOWERING RINGNAME(&ZOWERING.) + F ACF2,REBUILD(USR),CLASS(P),DIVISION(KEYRING) + +* Create Zowe's local CA authority + SET PROFILE(USER) DIVISION(CERTDATA) + GENCERT CERTAUTH.ZOWECA LABEL(localca) SIZE(2048) + + SUBJSDN(CN='&CN. CA' + + OU='&OU.' + + O='&O.' + + L='&L.' + + SP='&SP.' + + C='&C.') + + EXPIRE(05/01/30) + + KEYUSAGE(CERTSIGN) +* +* Connect Zowe's local CA authority to the keyring ................ */ + SET PROFILE(USER) DIVISION(CERTDATA) + CONNECT CERTDATA(CERTAUTH.ZOWECA) RINGNAME(&ZOWERING.) + + KEYRING(&ZOWEUSER..ZOWERING) USAGE(CERTAUTH) + CHKCERT CERTAUTH.ZOWECA + +* ATTENTION! */ +* Configure certificate for Zowe .................................. */ +* Select one of three options which is the most suitable for your */ +* environment and follow the appropriate action */ +* */ +* Options: */ +* 1. Zowe's certificate is already loaded in RACF database */ +* ACTION: Modify the CERTDATA(&ZOWEUSER..ZOWECERT) keyword */ +* below to match the desired certificate for Zowe */ +* */ +* 2. Import external Zowe's certificate from a data set in PKCS12 */ +* format */ +* ACTION: Uncomment the "Option 1" block below */ +* */ +* 3. Generate Zowe's certificate that will be signed by the */ +* Zowe's local CA */ +* ACTION: Uncomment the "Option 2" block below */ +* */ +* ***************************************************************** */ +* */ +* Option 1 - BEGINNING ............................................ */ +* Import external certificate from data set ....................... */ + +* SET PROFILE(USER) DIV(CERTDATA) +* INSERT &ZOWEUSER..ZOWECERT + +* DSNAME('&DSNAME.') + +* LABEL(&LABEL.) + +* PASSWORD('&PKCSPASS.') + +* TRUST + +* Option 1 - END .................................................. */ +* ................................................................. */ +* Option 2 - BEGINNING ............................................ */ +* Create a certificate signed by local zowe's CA .................. */ +* SET PROFILE(USER) DIV(CERTDATA) +* GENCERT &ZOWEUSER..ZOWECERT + +* SUBJSDN(CN='&CN. certificate' + +* OU='&OU.' + +* O='&O.' + +* L='&L.' + +* SP='&SP.' + +* C='&C.') + +* SIZE(2048) + +* EXPIRE(05/01/30) + +* LABEL('&LABEL.') + +* KEYUSAGE(HANDSHAKE,DATAENCRYPT,DOCSIGN) + +* ALTNAME(IP='127.0.0.1' DOMAIN='localhost') + +* SIGNWITH(CERTAUTH.ZOWECA) + +* Option 2 - END ................................................... */ + +* Connect a Zowe's certificate with the keyring .................... */ + SET PROFILE(USER) DIVISION(CERTDATA) + CONNECT CERTDATA(&ZOWEUSER..ZOWECERT) RINGNAME(&ZOWERING.) + + KEYRING(&ZOWEUSER..ZOWERING) USAGE(PERSONAL) DEFAULT + CHKCERT &ZOWEUSER..ZOWECERT + +* Connect all CAs of the Zowe certificate's signing chain with the */ +* keyring .......................................................... */ +* Add or remove commands according to the Zowe certificate's */ +* signing CA chain ................................................. */ + SET PROFILE(USER) DIVISION(CERTDATA) + CONNECT CERTDATA(CERTAUTH.&ITRMZWCA.) RINGNAME(&ZOWERING.) + + KEYRING(&ZOWEUSER..ZOWERING) USAGE(CERTAUTH) + + CONNECT CERTDATA(CERTAUTH.&ROOTZWCA.) RINGNAME(&ZOWERING.) + + KEYRING(&ZOWEUSER..ZOWERING) USAGE(CERTAUTH) + +* Connect root CA that signed z/OSMF certificate with the keyring. */ +* If z/OSMF is using self-signed certificate then specify directly */ +* the z/OSMF certificate to be connected with the keyring. */ + SET PROFILE(USER) DIVISION(CERTDATA) + CONNECT CERTDATA(CERTAUTH.&ROOTZFCA.) RINGNAME(&ZOWERING.) + + KEYRING(&ZOWEUSER..ZOWERING) USAGE(CERTAUTH) + +* Create jwtsecret + SET PROFILE(USER) DIVISION(CERTDATA) + GENCERT &ZOWEUSER..ZOWEJWT + + SUBJSDN(CN='&CN. JWT' + + OU='&OU.' + + O='&O.' + + L='&L.' + + SP='&SP.' + + C='&C.') + + SIZE(2048) + + LABEL(jwtsecret) + + EXPIRE(05/01/30) + +* Connect jwtsecret to the keyring ................................ + SET PROFILE(USER) DIVISION(CERTDATA) + CONNECT CERTDATA(&ZOWEUSER..ZOWEJWT) RINGNAME(&ZOWERING.) + + KEYRING(&ZOWEUSER..ZOWERING) USAGE(PERSONAL) + CHKCERT &ZOWEUSER..ZOWEJWT + +* Allow ZOWEUSER to access keyring ................................ + SET RESOURCE(FAC) + RECKEY IRR ADD(DIGTCERT.LISTRING ROLE(&STCGRP) + + SERVICE(READ) ALLOW) + F ACF2,REBUILD(FAC) + +* List the keyring ................................................ + SET PROFILE(USER) DIVISION(KEYRING) + LIST &ZOWEUSER..ZOWERING $$ //* //********************************************************************* @@ -294,8 +427,8 @@ $$ /* */ /* Options: */ /* 1. Zowe's certificate is already loaded in RACF database */ -/* (assuming under &ZOWEUSER ACID) */ -/* ACTION: No action required */ +/* ACTION: Modify the RINGDATA(&ZOWEUSER.,ZOWECERT) keyword */ +/* below to match the desired certificate for Zowe */ /* */ /* 2. Import external Zowe's certificate from a data set in PKCS12 */ /* format */ From ab3b7304565f65cd30d87f0f6744f3968858aaef Mon Sep 17 00:00:00 2001 From: Vit Tomica Date: Mon, 25 May 2020 12:51:53 +0200 Subject: [PATCH 22/37] ACF2 fixes Signed-off-by: Vit Tomica --- files/jcl/ZWEKRING.jcl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/files/jcl/ZWEKRING.jcl b/files/jcl/ZWEKRING.jcl index af47e97221..ea1ae6ee99 100644 --- a/files/jcl/ZWEKRING.jcl +++ b/files/jcl/ZWEKRING.jcl @@ -77,7 +77,7 @@ //* * Name of the data set containing Zowe's certificate (PKCS12) // SET DSNAME= //* * Password for the PKCS12 data set -// SET PKCSPASS= +// SET PKCSPASS='' //* * Name/Label of the intermediate CA of the Zowe certificate //* * Ignore if not applicable // SET ITRMZWCA= @@ -330,9 +330,9 @@ ACF * C='&C.') + * SIZE(2048) + * EXPIRE(05/01/30) + -* LABEL('&LABEL.') + -* KEYUSAGE(HANDSHAKE,DATAENCRYPT,DOCSIGN) + -* ALTNAME(IP='127.0.0.1' DOMAIN='localhost') + +* LABEL(&LABEL.) + +* KEYUSAGE(HANDSHAKE DATAENCRYPT DOCSIGN) + +* ALTNAME(IP=127.0.0.1 DOMAIN='localhost') + * SIGNWITH(CERTAUTH.ZOWECA) * Option 2 - END ................................................... */ From 45723c7aab3813ce7853e8af682d80877a8a48cd Mon Sep 17 00:00:00 2001 From: Vit Tomica Date: Mon, 25 May 2020 16:27:28 +0200 Subject: [PATCH 23/37] Allow Zowe to use certificate owned by SITE acid Signed-off-by: Vit Tomica --- files/jcl/ZWEKRING.jcl | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/files/jcl/ZWEKRING.jcl b/files/jcl/ZWEKRING.jcl index ea1ae6ee99..634d19e5db 100644 --- a/files/jcl/ZWEKRING.jcl +++ b/files/jcl/ZWEKRING.jcl @@ -246,6 +246,10 @@ PERMIT IRR.DIGTCERT.LISTRING CLASS(FACILITY) ID(&ZOWEUSER.) + ACCESS(READ) +/* Uncomment this command if SITE acid owns the Zowe certificate */ +/* PERMIT IRR.DIGTCERT.GENCERT CLASS(FACILITY) ID(&ZOWEUSER.) + +/* ACCESS(CONTROL) + SETROPTS RACLIST(FACILITY) REFRESH /* List the keyring ................................................ */ @@ -384,6 +388,11 @@ ACF SET RESOURCE(FAC) RECKEY IRR ADD(DIGTCERT.LISTRING ROLE(&STCGRP) + SERVICE(READ) ALLOW) + +* Uncomment this command if SITE acid owns the Zowe certificate +* RECKEY IRR ADD(DIGTCERT.GENCERT ROLE(&STCGRP) + +* SERVICE(CONTROL) ALLOW) + F ACF2,REBUILD(FAC) * List the keyring ................................................ @@ -512,6 +521,10 @@ $$ /* Allow ZOWEUSER to access keyring ................................ */ TSS PERMIT(&ZOWEUSER.) IBMFAC(IRR.DIGTCERT.LISTRING) ACCESS(READ) +/* Uncomment this command if SITE acid owns the Zowe certificate */ +/* TSS PERMIT(&ZOWEUSER.) IBMFAC(IRR.DIGTCERT.GENCERT) ACCESS(CONTROL) + + /* List the keyring ................................................ */ TSS LIST(&ZOWEUSER.) KEYRING(ZOWERING) LABLRING(&ZOWERING.) From 3d1032eaa6415ba52ad793d79211c367b0d00171 Mon Sep 17 00:00:00 2001 From: Vit Tomica Date: Tue, 26 May 2020 12:24:13 +0200 Subject: [PATCH 24/37] Add KEYRING_OWNER and KEYRING_NAME variables to the zowe-certificates.env Signed-off-by: Vit Tomica --- bin/zowe-setup-certificates.sh | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/bin/zowe-setup-certificates.sh b/bin/zowe-setup-certificates.sh index 48c4bb6696..d622fe3391 100644 --- a/bin/zowe-setup-certificates.sh +++ b/bin/zowe-setup-certificates.sh @@ -228,9 +228,11 @@ else cat >${KEYSTORE_DIRECTORY}/${ZOWE_CERT_ENV_NAME} < Date: Thu, 28 May 2020 12:29:20 +0200 Subject: [PATCH 25/37] minor change Signed-off-by: Vit Tomica --- files/jcl/ZWEKRING.jcl | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/files/jcl/ZWEKRING.jcl b/files/jcl/ZWEKRING.jcl index 634d19e5db..6e0a21e672 100644 --- a/files/jcl/ZWEKRING.jcl +++ b/files/jcl/ZWEKRING.jcl @@ -152,8 +152,9 @@ /* */ /* Options: */ /* 1. Zowe's certificate is already loaded in RACF database */ -/* ACTION: Modify the CONNECT(ID(&ZOWEUSER.) ...) keyword */ -/* below to match the owner of the desired certificate */ +/* ACTION: Modify the CONNECT(ID(&ZOWEUSER.) LABEL('&LABEL.') */ +/* command below to match the owner of the desired */ +/* certificate */ /* */ /* 2. Import external Zowe's certificate from a data set in PKCS12 */ /* format */ From 6be227732b406957616ac3773b4faee8881d4c5d Mon Sep 17 00:00:00 2001 From: Vit Tomica Date: Thu, 4 Jun 2020 16:39:17 +0200 Subject: [PATCH 26/37] escape dollar sign Signed-off-by: Vit Tomica --- bin/zowe-setup-certificates.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bin/zowe-setup-certificates.sh b/bin/zowe-setup-certificates.sh index d622fe3391..776355582a 100644 --- a/bin/zowe-setup-certificates.sh +++ b/bin/zowe-setup-certificates.sh @@ -230,9 +230,9 @@ else KEYSTORE_PASSWORD="" KEYRING_OWNER="${ZOWE_USER_ID}" KEYRING_NAME="${ZOWE_KEYRING}" - KEYSTORE="safkeyring:////${KEYRING_OWNER}/${KEYRING_NAME}" + KEYSTORE="safkeyring:////\${KEYRING_OWNER}/\${KEYRING_NAME}" KEYSTORE_TYPE="JCERACFKS" - TRUSTSTORE="safkeyring:////${KEYRING_OWNER}/${KEYRING_NAME}" + TRUSTSTORE="safkeyring:////\${KEYRING_OWNER}/\${KEYRING_NAME}" ZOWE_APIM_VERIFY_CERTIFICATES=${VERIFY_CERTIFICATES} SETUP_APIML_SSO=${SETUP_APIML_SSO} SSO_FALLBACK_TO_NATIVE_AUTH=${SSO_FALLBACK_TO_NATIVE_AUTH} From e4413cb5699ac7577ebe994abb582f390bc3356a Mon Sep 17 00:00:00 2001 From: Vit Tomica Date: Fri, 5 Jun 2020 10:50:24 +0200 Subject: [PATCH 27/37] Use only handshake key usage for generated certificate Signed-off-by: Vit Tomica --- files/jcl/ZWEKRING.jcl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/files/jcl/ZWEKRING.jcl b/files/jcl/ZWEKRING.jcl index 6e0a21e672..e62c18ee48 100644 --- a/files/jcl/ZWEKRING.jcl +++ b/files/jcl/ZWEKRING.jcl @@ -190,7 +190,7 @@ /* SIZE(2048) + /* NOTAFTER(DATE(2030-05-01)) + /* WITHLABEL('&LABEL.') + -/* KEYUSAGE(HANDSHAKE,DATAENCRYPT,DOCSIGN) + +/* KEYUSAGE(HANDSHAKE) + /* ALTNAME(IP(127.0.0.1) + /* DOMAIN('localhost')) + /* SIGNWITH(CERTAUTH LABEL('localca')) @@ -336,7 +336,7 @@ ACF * SIZE(2048) + * EXPIRE(05/01/30) + * LABEL(&LABEL.) + -* KEYUSAGE(HANDSHAKE DATAENCRYPT DOCSIGN) + +* KEYUSAGE(HANDSHAKE) + * ALTNAME(IP=127.0.0.1 DOMAIN='localhost') + * SIGNWITH(CERTAUTH.ZOWECA) @@ -475,7 +475,7 @@ $$ /* KEYSIZE(2048) + /* NADATE(05/01/30) + /* LABLCERT(&LABEL.) + -/* KEYUSAGE('HANDSHAKE DATAENCRYPT DOCSIGN') + +/* KEYUSAGE('HANDSHAKE') + /* ALTNAME('DOMAIN=localhost') + /* SIGNWITH(CERTAUTH,ZOWECA) From 2bae8d20bc9db2afc14d71475b21d7d5a65d5c53 Mon Sep 17 00:00:00 2001 From: Vit Tomica Date: Mon, 8 Jun 2020 17:37:50 +0200 Subject: [PATCH 28/37] Export a zowe generated jwt public key from a keyring Signed-off-by: Vit Tomica --- bin/apiml_cm.sh | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/bin/apiml_cm.sh b/bin/apiml_cm.sh index 4d65317ea5..129ff25822 100644 --- a/bin/apiml_cm.sh +++ b/bin/apiml_cm.sh @@ -407,8 +407,7 @@ function jwt_key_gen_and_export { if [[ "${SERVICE_STORETYPE}" == "JCERACFKS" ]]; then pkeytool -genkeypair $V -alias ${JWT_ALIAS} -keyalg RSA -keysize 2048 -keystore safkeyring://${ZOWE_USERID}/${ZOWE_KEYRING} \ -dname "${SERVICE_DNAME}" -storetype ${SERVICE_STORETYPE} -validity ${SERVICE_VALIDITY} -J-Djava.protocol.handler.pkgs=com.ibm.crypto.provider - pkeytool -export -rfc -alias ${JWT_ALIAS} -keystore safkeyring://${ZOWE_USERID}/${ZOWE_KEYRING} -storetype ${SERVICE_STORETYPE} \ - -file ${SERVICE_KEYSTORE}.${JWT_ALIAS}.pem -J-Djava.protocol.handler.pkgs=com.ibm.crypto.provider + export_jwt_from_keyring else pkeytool -genkeypair $V -alias ${JWT_ALIAS} -keyalg RSA -keysize 2048 -keystore ${SERVICE_KEYSTORE}.p12 \ -dname "${SERVICE_DNAME}" -keypass ${SERVICE_PASSWORD} -storepass ${SERVICE_PASSWORD} -storetype ${SERVICE_STORETYPE} -validity ${SERVICE_VALIDITY} @@ -417,6 +416,11 @@ function jwt_key_gen_and_export { fi } +function export_jwt_from_keyring { + pkeytool -export -rfc -alias ${JWT_ALIAS} -keystore safkeyring://${ZOWE_USERID}/${ZOWE_KEYRING} -storetype ${SERVICE_STORETYPE} \ + -file ${SERVICE_KEYSTORE}.${JWT_ALIAS}.pem -J-Djava.protocol.handler.pkgs=com.ibm.crypto.provider +} + function zosmf_jwt_public_key { echo "Retrieves z/OSMF JWT public key and stores it to ${SERVICE_KEYSTORE}.${JWT_ALIAS}.pem" java -Xms16m -Xmx32m -Xquickstart \ @@ -622,6 +626,9 @@ case $ACTION in ;; trust-zosmf) trust_zosmf + if [[ "${SERVICE_STORETYPE}" == "JCERACFKS" ]] && [[ "${GENERATE_CERTS_FOR_KEYRING}" == "false" ]]; then + export_jwt_from_keyring + fi zosmf_jwt_public_key ;; cert-key-export) From 412d1d4e1a8c6b597d8ca4434e8181457163bba7 Mon Sep 17 00:00:00 2001 From: Vit Tomica Date: Tue, 9 Jun 2020 16:10:26 +0200 Subject: [PATCH 29/37] Hardcode the password value otherwise JVM fails reading the keyring Signed-off-by: Vit Tomica --- bin/zowe-setup-certificates.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/zowe-setup-certificates.sh b/bin/zowe-setup-certificates.sh index 776355582a..b1146c5d05 100644 --- a/bin/zowe-setup-certificates.sh +++ b/bin/zowe-setup-certificates.sh @@ -227,7 +227,7 @@ EOF else cat >${KEYSTORE_DIRECTORY}/${ZOWE_CERT_ENV_NAME} < Date: Fri, 19 Jun 2020 16:02:15 +0200 Subject: [PATCH 30/37] increase zlux version Signed-off-by: Vit Tomica --- manifest.json.template | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/manifest.json.template b/manifest.json.template index 4c7e87e4a1..62c9ba21a2 100644 --- a/manifest.json.template +++ b/manifest.json.template @@ -12,47 +12,47 @@ }, "binaryDependencies": { "org.zowe.zlux.zlux-core": { - "version": "~1.12.0-STAGING", + "version": "~1.13.0-STAGING", "artifact": "*.pax" }, "org.zowe.zlux.zss-auth": { - "version": "~1.12.0-STAGING", + "version": "~1.13.0-STAGING", "artifact": "*.pax" }, "org.zowe.zlux.sample-angular-app": { - "version": "~1.12.0-STAGING", + "version": "~1.13.0-STAGING", "artifact": "*.pax" }, "org.zowe.zlux.sample-iframe-app": { - "version": "~1.12.0-STAGING", + "version": "~1.13.0-STAGING", "artifact": "*.pax" }, "org.zowe.zlux.sample-react-app": { - "version": "~1.12.0-STAGING", + "version": "~1.13.0-STAGING", "artifact": "*.pax" }, "org.zowe.zlux.tn3270-ng2": { - "version": "~1.12.0-STAGING", + "version": "~1.13.0-STAGING", "artifact": "*.pax" }, "org.zowe.zlux.vt-ng2": { - "version": "~1.12.0-STAGING", + "version": "~1.13.0-STAGING", "artifact": "*.pax" }, "org.zowe.zlux.zlux-editor": { - "version": "~1.12.0-STAGING", + "version": "~1.13.0-STAGING", "artifact": "*.pax" }, "org.zowe.zlux.zlux-workflow": { - "version": "~1.12.0-STAGING", + "version": "~1.13.0-STAGING", "artifact": "*.pax" }, "org.zowe.zlux.zosmf-auth": { - "version": "~1.12.0-STAGING", + "version": "~1.13.0-STAGING", "artifact": "*.pax" }, "org.zowe.zss": { - "version": "~1.12.0-STAGING", + "version": "~1.13.0-STAGING", "artifact": "*.pax" }, "org.zowe.explorer.jobs": { From 5d3cc8ed110e1a4baa0635917a8f69780f2bdca6 Mon Sep 17 00:00:00 2001 From: Vit Tomica Date: Mon, 22 Jun 2020 16:53:46 +0200 Subject: [PATCH 31/37] remove apostrophes from ALTNAME keyword for ACF2 Signed-off-by: Vit Tomica --- files/jcl/ZWEKRING.jcl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/files/jcl/ZWEKRING.jcl b/files/jcl/ZWEKRING.jcl index e62c18ee48..b4f89ac636 100644 --- a/files/jcl/ZWEKRING.jcl +++ b/files/jcl/ZWEKRING.jcl @@ -337,7 +337,7 @@ ACF * EXPIRE(05/01/30) + * LABEL(&LABEL.) + * KEYUSAGE(HANDSHAKE) + -* ALTNAME(IP=127.0.0.1 DOMAIN='localhost') + +* ALTNAME(IP=127.0.0.1 DOMAIN=localhost) + * SIGNWITH(CERTAUTH.ZOWECA) * Option 2 - END ................................................... */ @@ -391,7 +391,7 @@ ACF SERVICE(READ) ALLOW) * Uncomment this command if SITE acid owns the Zowe certificate -* RECKEY IRR ADD(DIGTCERT.GENCERT ROLE(&STCGRP) + +* RECKEY IRR ADD(DIGTCERT.GENCERT ROLE(&`STCGRP`) + * SERVICE(CONTROL) ALLOW) F ACF2,REBUILD(FAC) From 382bf746fdfa98a0c133c58a210125a8ef6efd20 Mon Sep 17 00:00:00 2001 From: Vit Tomica Date: Mon, 22 Jun 2020 17:43:54 +0200 Subject: [PATCH 32/37] Detect root CA for a certificate in a key ring Signed-off-by: Vit Tomica --- bin/zowe-setup-certificates.sh | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/bin/zowe-setup-certificates.sh b/bin/zowe-setup-certificates.sh index 0e1e0e727e..1b6eea8294 100644 --- a/bin/zowe-setup-certificates.sh +++ b/bin/zowe-setup-certificates.sh @@ -19,6 +19,8 @@ # then set this variable to false (defaults to false) function detectExternalRootCA { + echo "Detecting external root CA... STARTED" + if [[ -z "${ZOWE_KEYRING}" ]]; then for file in ${KEYSTORE_DIRECTORY}/${LOCAL_KEYSTORE_SUBDIR}/extca.*.cer-ebcdic; do if [[ ! -f $file ]]; then break; @@ -30,6 +32,24 @@ function detectExternalRootCA { break; fi done + else + # Assumption: External certificate contains its chain of trust. The root certificate is the last one in the list + # that we get using the commands just below: + var_keytool_cmd="keytool -list -storetype JCERACFKS -keystore safkeyring://${ZOWE_USER_ID}/${ZOWE_KEYRING} \ + -J-Djava.protocol.handler.pkgs=com.ibm.crypto.provider" + var_CA_chain_length=`$var_keytool_cmd -alias $KEYSTORE_ALIAS -v | grep -c -e Owner:` + if [[ $var_CA_chain_length -lt 2 ]]; then + echo "The $KEYSTORE_ALIAS certificate is self-signed or does not contain its CA chain. If the certificate is externally signed \ +and its root CA is connected to the same keyring then you can manually set the EXTERNAL_ROOT_CA env variable with the \ +root CA label in the ${KEYSTORE_DIRECTORY}/${ZOWE_CERT_ENV_NAME} file." + else + var_root_CA_DN=`$var_keytool_cmd -alias $KEYSTORE_ALIAS -v | grep -e Issuer: | tail -n 1 | cut -d ":" -f 2-` + var_root_CA_alias=`$var_keytool_cmd -v | grep -e "Owner:$var_root_CA_DN" -P 5 | grep -e "Alias name:" | cut -d ":" -f 2-` + EXTERNAL_ROOT_CA=`echo ${var_root_CA_alias} | tr -d '[:space:]'` + echo "A label of the external root CA in the keyring: $EXTERNAL_ROOT_CA" + fi + fi + echo "Detecting external root CA... DONE" } # process input parameters. From bda18ea2fb6483791066a2209a299cfbaa4b7a97 Mon Sep 17 00:00:00 2001 From: Mark Ackert <35308966+MarkAckert@users.noreply.github.com> Date: Wed, 24 Jun 2020 05:05:55 -0400 Subject: [PATCH 33/37] add keyring to artifactory build (#1453) * add keyring to artifactory build Signed-off-by: MarkAckert * fix keyring version Signed-off-by: MarkAckert * fix keyring manifest, add gitignore Signed-off-by: MarkAckert * setup keyring-util as binary Signed-off-by: MarkAckert * fix keyring during prepare-workspace, chmod in pre-package Signed-off-by: MarkAckert * fix dir Signed-off-by: MarkAckert * set keyring version to 1.0.1 Signed-off-by: MarkAckert --- .pax/pre-packaging.sh | 3 +++ .pax/prepare-workspace.sh | 12 +++++++++++- Jenkinsfile | 2 +- bin/utils/keyring-util/README.md | 2 ++ bin/utils/keyring-util/keyring-util | Bin 65536 -> 0 bytes manifest.json.template | 19 ++++++++++++++++++- 6 files changed, 35 insertions(+), 3 deletions(-) delete mode 100644 bin/utils/keyring-util/keyring-util diff --git a/.pax/pre-packaging.sh b/.pax/pre-packaging.sh index c54e0f1f7b..9faba057f0 100755 --- a/.pax/pre-packaging.sh +++ b/.pax/pre-packaging.sh @@ -174,6 +174,9 @@ chmod +x content/zowe-$ZOWE_VERSION/scripts/ocopyshr.clist chmod +x content/zowe-$ZOWE_VERSION/install/*.sh chmod +x content/templates/*.rex +echo "[$SCRIPT_NAME] change keyring-util to be executable ..." +chmod +x content/zowe-$ZOWE_VERSION/bin/utils/keyring-util/keyring-util + # prepare for SMPE echo "[$SCRIPT_NAME] smpe is not part of zowe.pax, moving it out ..." mv ./content/smpe . diff --git a/.pax/prepare-workspace.sh b/.pax/prepare-workspace.sh index 3c27041876..fd7ad2f282 100755 --- a/.pax/prepare-workspace.sh +++ b/.pax/prepare-workspace.sh @@ -23,6 +23,7 @@ set -x # expected workspace layout: # ./.pax/mediation/ +# ./.pax/keyring-util/ # ./bin/ # ./files/ # ./install/ @@ -152,6 +153,15 @@ mv ${ASCII_DIR}/files/scripts/jobs-api*.sh \ mv ${ASCII_DIR}/files/scripts/files-api*.sh \ ${CONTENT_DIR}/files/scripts/ +# move keyring-util to bin/utils/keyring-util +KEYRING_UTIL_SRC="${PAX_WORKSPACE_DIR}/keyring-util" +KEYRING_UTIL_DEST="${CONTENT_DIR}/bin/utils/keyring-util" +mkdir -p "$KEYRING_UTIL_DEST" +cp "$KEYRING_UTIL_SRC/keyring-util" "$KEYRING_UTIL_DEST/keyring-util" + +# cleanup working files +rm -rf "$KEYRING_UTIL_SRC" + # move licenses mkdir -p "${CONTENT_DIR}/licenses" mv "${CONTENT_DIR}/files/zowe_licenses_full.zip" \ @@ -199,5 +209,5 @@ echo "[$SCRIPT_NAME] done" # ${PAX_WORKSPACE_DIR}/ascii/zowe-${ZOWE_VERSION}/ # ${PAX_WORKSPACE_DIR}/content/zowe-${ZOWE_VERSION}/ # ${PAX_WORKSPACE_DIR}/mediation/ # already present - +# ${PAX_WORKSPACE_DIR}/keyring-util/ # already present # ascii/* will move into content/, translated to ebcdic diff --git a/Jenkinsfile b/Jenkinsfile index e46bcfab43..90f0fb180a 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -84,7 +84,7 @@ sed -e 's#{BUILD_BRANCH}#${env.BRANCH_NAME}#g' \ // download components pipeline.artifactory.download( spec : 'artifactory-download-spec.json', - expected : 18 + expected : 19 ) // we want build log pulled in for SMP/e build diff --git a/bin/utils/keyring-util/README.md b/bin/utils/keyring-util/README.md index 15f78d8300..bdb63f4299 100644 --- a/bin/utils/keyring-util/README.md +++ b/bin/utils/keyring-util/README.md @@ -1,6 +1,8 @@ The keyring-util's source code can be found in the https://github.com/zowe/keyring-utilities +The binary will be placed here by artifactory during build process. + # keyring-util The keyring-util program leverages diff --git a/bin/utils/keyring-util/keyring-util b/bin/utils/keyring-util/keyring-util deleted file mode 100644 index 675de00fe922bc61d78103c4f4b3f4252d300706..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 65536 zcmeHw4R{>YdG6UCNo!lS*R~8I{H=)yf*4r97$tVnS>b?$Y_kvo4i~rU;3N)M$vPp4 zL%3mtv_@)aA}mX`0&NvZ#7;`@byK%7x#_*DKU>N*AoOdsv{kh>ICXNnGRDX)LHGU6 zoS8W@J7XC^jM9sA6jbH4Yy=R4o|oiih;ujh@?!J%G-F}Bl>3-i#01;l+P!UfFB z)1JXKpZR!rAFj1b%Me1inB`Eqr;M?@VwOwcKpgQP%cF1*zGMqn;eLV0bzuawk{Eji ztlaHR9B8gNDnyAopjBuf@g&kge$>6?pF4)m=IY)-D3_`b~?`GB+d_KhM}r$;F3Adz3amzhBFHQDOdZ zEp%gY(E%-V!-p0f)IuwJ7YW=A#}}owv~XZ?Qb_w3i@YoQ7msUcj4eK;g>H=d*8A5| z*!PTo?ez5D_xjf79n<1@$EK%`m-yD_^S1LnlmFuM^x&rIjrmhrUdF1wtA~q9sy8mw zlaa26uj#FRWnn-UR4>xQD-SS&_(Tud40}A}RT;Y_?rn!Xg5GY*<3l^GO!|s&o${?C zsc$RU#s_QNvd6cFvD->~`w;H-LC4!leXz)?S|9YkZM_dR0cMD?ThIDX+uOGLe#KK@ zq1DU}=G&h1L$h1<`16sH?++p6PyHwhDaA-BB)i=9H-3eup!C&6{!K_Z>PNc)6GKYa z{}@vK(Z7?YJb{$8{(7XG_d~Z^Ui3q^)n$I@R^stPH>4aw%6!MJC70wt&s$#1fu5^(=3Iu9P!9A&N)b|Oa!Qa=oC7_P0zFsP=iG;s z8*-p0QlRJR=X2snS)BttkpeweAINzIDWA-No=Ab7s}JQIK*}9C&=V=pb9FMO8z~!e zpeItG=jvlQ<4CzL=LAoIo~w`NOrfR^=lc0I$gj{4DaHJ{ieI4>Qr7b;v_g0*zd|d7 zpWxS8euXATY2jCBg79H}g(e91^Xuz$#lS^9FmrjkD&Lr3w_~IP@lSL0EM$bjMo2M2 zQ6m%=p%_#3kSC;tyoyK98}ley8fJ-l5sGV*DPmD?K%|AdK@kdi3q?rrhD0b_vj{z1 zq~{;zF<6OQ&H)}P(PB$#d8|x}Eh^)&OqA_&Q;QYX^B62i?mCTA=)0<& z%l2uqn@f1CMT_0KjmHjHWCw-p=UjH!B1>wqRj+eduSM3c#cr+Pvf~!nxE5PA#bu`~ zva}Yvbv>6&$ui6f+}+A8=m}V4K`pk5+sspFk(FpM%`UX2k<;wriE6Q1#;H8dCM~Af z#S_zFtCC!{%_56yv0DqcY^O!0YOz(TxUAM9+o#2@W?a^y#ct{5u>%(5K`pkbkjoBR zWJxV{%e!3GYmxP9u~ktnJ8qGU3)yxqJ7tljwb-pKTs9@kykQ|bPBL$aE@KSq+3|%(IKR?`?TbFm{YcCYd;eM*Sk(zzZt{i z02erq1)7K2`E_+YW808Mn-_8(>@WVTjzU_TJ;+$g_sw|mLx`U>errU$2lm&=i1^t8_Io2N!T<0NP z$d|wqX006)3S8%-wNSzkk7xnpz}y!E57}Hbc~$_UAW3&_WhpuUcfUhf#8W0?q_S42 z&>8+VV7Lth&c7lM;AVkLuUE*9k?PKQkoN&#HVF>8p**;>JaW*IWP+2xihCY`8Q}3dWt~2_(730uXiD#e8Y zW5G!Fkue8k9x6+WW!XM9Oh$kH5Xw3z^GIcJ9#v}#3r5meF6*$&`eMhI{kL~+~nljZ>P^9 zayFf2Pt6Mi=BxAkuqtDvet})d*s+gwzsq_9F`OkR?4c#o;v}JxP7*4r*<#i`d46&- zeYWD4XU5L5#q+Gu`PS${YjlYvD#~Q6i}m2&Bz7KC)W1)E_Kq@Elu|Y-(>s#&j4ix3 z6}(G9O6V?158~=i#mfS?#^Q91#xb+Msh9;MnYx%2DX@EL(H$UE@k^`T)2u&F7|7bew-B~=TrTlLz1bT zi+u=3P&qL8amNvbMXwTGR+#IxTH-pI3YMiI(`!pLkH!^4C+J;%05uJB6xG_qZsOP| z^Y5=?9$2LqdhKIHdTm}Rp#5E0Zz@*S%L*VvIWL7+E;PI!rOHg(I8)3h)n~JWto{9h zzXbh%n~i5D=ZV{Rt~6>V^Xw#^REX=Q*It&_a5+Qm(F@Q!{3#a0s6#za8)18%9%V6R z)1#K_q1yCV?5Ia8m4jZwPJgSc5bdKxl6R)XgQwANuRsU%u+yKtlQdB7W?H{pa1O1b zA|-|^^xK-x3V6FOFj8>t#ck<_wanDZM5>-Mv^B))Q(?-Vif=_8Z~=o_1*rBxZkJ$~ z_nuzV0<8=?v}kQ@=*=?qz8rI$gWlg4dWXtu!4xj9Cq9Hx2R^Q1TDh@$N{L~&&Fiof zt(8QILu)MJ}E7Fh?BJ+D^!#q|g4Z zPe<}R4z-o$m&-$_uY&od7d28gCPh141s<9&LgkbmF7M~{?d4h^J%SN}Q8LAfMlX$_ zz6hh95%e_FJ_PJS<@T{#l4Qb??>(RAK?_j|@3s3E!M=~NtwtL9ph$brNJEcAT0U@5 zqdj@gjEAXbJ{#mCmfLRk0<<~VT(5)Px<>m)!q46uVb9)d=?B?r{|RWXGs+sQA`Ofl zqGXPTON*Vx!~CVZpHcsi$HN|dp1~~IZ;X%QyoH7ayk)~>LnqgljWc$#tPJA}?REmG zC(BMmLS^HTptRCZPm9J;JJOHVFEFMr(5uok4~X?ou3wZ}nC2XF6k=p(>tiJJ>?1nA z7{~hhSb&pORi#f)5bT1b+3%jjQ&;FaJ zrEIBM&J0_VjOxQ@&I_zOMsGD|Z)rX&Y~l0SgVy;h@H1^b!@QMrnpr3vqqYz;TMI%h zG_$>gLkz6^E5*Hd|AOghv^Zl$r?E3-^U(@v1GS9D{G-z?tc68den2&e?SB+GVuaeC zH$4e{#{5UHILxa}#c8BtzD$CVN~QAS@%*Jb_?-6{_C=cWB)Nt}*^V{vvpCAj#T*&e zN{M_i#s>T`wmU55qA-drh=gL8bx;zY(=Z12p@v_7Z&{wlkrgxUf2>^s@BW9`W%cRD z#ok4m^NfAVMf;fNI`#BtH`M+b>*1%=U-SKT9@hWc*)q&`w+C*24?T zOmbhBXAy1vk42`I?MTH+3zrp*E~b@KTSH4rmWef%B>U%it_6llW~Edzg;6rX=y5z( zYzx+4LZBbS_kSDxE>1}FyVIi|)mCWej676cBwp4V32(_of4C$P#Ja=#Ln?L;pBe8# zFU7duM=QR*V?w@nmuY*N52r%lz}|~ePzu8pPfNH4GxuJ**V>sdZ_Y;_?A6Ld?^~(w zP*TcW>e3xz1v1)Wc^K-TJ#MFUMyXJ>{YmaXD!2ioAr;yXz%{%fNF$?SUn;g9qiHmx z*`(st)JDQ(Q<2c; ziaB1aIXenz7TWWYEWjeF|gjmt1PDMh{JXkhmu=28Zgt4OFdGEK@dPLKjb*AFNKKoK^eTmi@ zk@${Wc|J>SQ5mC|F*gePpIl#&q^Ciwc^7GGSVcEtSYuMG;u!CJ#|_C4B;#E2y2cF_ zm;GVI3A8S>sQ4A_J1Wldp5jl1(C%n`P0MWd*yvy8`g<7RX#Aj9|ETXFuI;hUe-HB~ z^=Q!-;!_-pdT`qZu{U*-oN|*?V1>{|(~dG?+o9-eQoq>5B~eYHuZrtbK7x$#v$W7@ z|CV#J!~RXzlJ^X4hr0Vcs)MdeT#_{KouiZF0(rK%vOVT1X>yeua+B=2%vJKBtK?^{ z622SK?Hkc{9fo~_<4*SVKjmQG7(L}V^;@jb*g3zn0w)bcI8D)>jpKwCy9as>5_*H}`cNZ3Bf`iAH|8`N{oQzC!al2WF?7y>HI|rZ*mZf? zLd+Dg)E64pvVuF$sk94kHpO#opD7ofVRa2d$n_6A*F7`lx<=3C zp&eW&&$W7{T%Rkp12Hfe09l4(sAXP7l?-34)9i^Lia z^VMgwwo+iPava>T(s5i_=_yZ7sC+NZc1ECo4YJ0NL=`Cyv8=d|f`y3lBewaOsv%A~7Jq6f3_IgkwptY9& z`gZ$_>i$cwYapP$Z)lz8sl|1GSM@yJ>aP7oprzm`G&AlHK}iSro+ zCkK(JhxUFKMV3T9JCGM-joqi`MYdtz5|3=>x#Ik~)5sfKvXl9dPc`z@@qEWl&yVcm z`JU%FTKM$Q95H^~CgrPVG&iG$rEw$gw+8Z&_YCsZ^1RRRT=o3A4|!Q>3&(yVa&hFQ z-T2T4t#{KvZX7R9!9{KP@!jZC@E&+CPrEqsDS`adfY(4?9N8jLw^;H&;*kIA0{L}I z{%1w%vzGkdcgX*OK)ztf-yu>vEct)okbhVphb{TjA~lWPYu5kYGV_<_XvoqWIe%$L zq=w}DrPn#+zf~Y_wdCI@Qa29FGs`c1&>{cl1@iM!{%@A<%0Paz^bh5<$TvzGDIWPk zY2$!5h8OmHZKNG6t&OZHj5jNXSQ%DE#P?USa3q8=eo>^@v%{FF4xo2NceLIC=u%|v1Dm`H8ChzW=n6?`#?Z-?NMlCopLc3h){Ssm5 zJ%BvlSMcZQX4ciz-cX}7Hnk~DdlQYy-sYwk>S_`-%HG}8t&?YzU3CqK3f9-!R@Js) zvyy0TZfa(IsoDe=D0QtoXO+^Nc)Gozs+p%QXFX$MBV&&%J%om+ss^9)%7j3S98q>P zwKvu*XMMx%d!9-(D^0tU>e{O2s_M2xb1ToKY=?MPbwg8YLMyof=*}Sp9@CQHrV%>Q z-dNpM*VL#~H`OE_SGHH2dGk?aqT`6tT#Z=GqsmxEmp#(jNTTIzd#i#%ks0jWeMeJW zJ!2`Qx}mDIRjI9NRoa@M%&z7{Yi*(i3S?kpVc*lOyDJloq(tRYRjmnp@zY%W9V(>n zhjvS&SZ-X%V&pn|j`j^Jqhoz1J5oK$K+h?jYL${|eMkDbfUrn=hPz#JlFT8Wqt$=d zT-VlyUVu6a^{9zSe>RHqvKCgcH?fEHRp7-c>l>@AscNfgsC!DOu4-sdc2%LP)I6^2 z`T$MQXZA+wHp*Vn10RPOmG3Cq-&`(PQL{68Y~2eA6uJ!#x2vwYstujPpwjHl z4VnFAIXlr>^)zVY&(zIIx3?ym>uPkN(opqOq5*BF8|86?hkM=_>l;3*#FT1OvMqt` zr!*#hsOLc+>+Ts8h?+!0LPLn+kRMXsMPo`$U2AnyV`HMajX0!ADjRsgn-%&}93qif z!EiJgWjx36F+y!hT^D2Y&CwBz1n8OAzqhG5qYN82`b?EF+A}2PfW9F;cikSR+#7ya z*H()h)O;`ksi@TLLNw8uXl&a|UC`8<7d1N2H6i)~tT5JdWUObR7ux9quvM{+-sP;f zXK<9hxQkIKji^9dExL1UqG7KwN1>bVt!mzb;+m9(CQMURjWx;->(HNRN_;Azv?kin zBHL>!2v@ZStrhc&cu1 zZbls&4)8Ks+xL=vFy$IWqu9Eq8=IQ>gwuzqfOx_ zFU`DS(hYcD$xGrfFQBTdiurSW2)DCfLsL~vrM7TX(%i<_^z=UkD36Bs9Orm1;aNLd zQeB&<-d)+8Xlrk7tmLIlPyaKXZw>qbj?d-zzhetq(Ulq!mD+5rOixb~3SQO3dGpyK z^l|Fk0tno=z-{8V0N3~XY#~i|iORMnt}OUY90zV34+~*aPj8qN*0k^0TPY2fO0-lZ zIxN-i%^1`b^(XURlwpLc} zscEQdOmKKB?D4NH0w3ad-p)DW%)h6qu950Knf9@({PYtaq|5a5>oK}Fz+1lCd0Tw9 zQqMclXmdCZ3*S z8>et${k0f&XOUR>DiOb!;=5USbhoEGCZC&@Z#}ubd>ef^Lr>o2aaMG)tb8ZEOD(@= zU}5>a<@X?jXNmI9!9NVYeZX5@S-u^)N|*=NwRq}^p>)TSDD51!TuCuPfPWpdWY7ww zv7#67wKbmj`;q@Rp2=AZ2z=L5MDKJ%c>h4DDSUGh+=28{Jbj9VjC8!+(%zr#4wMI= zNkPEOvx>_KDNlKbozwGd)6$E%#gfDh>-i(0@@NF_boE`e`Nb2;-KU+tTjYhv8I1?U z=`DRTfU_*pmVXJu@U~CHN&BTyu#8J7{vcAy@qS;|Di$Wph88+2xEuYp6m5k#&Ofv` zSfS|#oaq_y0OEL8Y{c_5t8P4qGiu+)-jnM$9>ZJl^&9)CWj7v7v5jQcvW??-`VXVu z7&YH`*iy3quNfnG7B!D+@4W8R-g#j>VI1PhiupL4&*!h_SpegM@4;y7{U%BPZ9EabQkZ(S!%5CGo#c#8Z)IEA=#8IepGP02T>La>ksjU}K)Z?btwAY_(|Dw# z52sixNd1TMma?rOBbE0vN{zCuI0@4|OeTL}-JN1E!n6ROrAYzSKd9H14<^ zE!rSAWFf8%zGf-M=+3B-Rhwe2O-Rz_uld(FnjH&iTxk~jylF>5^VAgkJk1}X??<%0 zZ}bcL2HDF_|G^!w3BG?~G*929A{@dMt#mb&&C17Vw!S(Pi5J}zVMS<%@>56&7ZpXK zMWKjVbXlans4&t}R1i5>6pSQ`@+0F#fd~r)QbGS=c5x~g+yovaNVV?A{HmSbrO`F$ zjl7Ceb6zG`QCe9o%BM2@sqwOUgp)M3QwPghaBV3&fNOmjW{#9vb{N-aSrXSUzPfxp`qc62iKdH?LrMCAP3^S1@aQaJk2GKfR zb_>o*FUK2-6}VsW(jC07eERff=sO6cEEt#$vJk!)S;8Wr6>R?l)8~`*m>w3a3)iz$ z{hhF(_Fi`YXJjD=#Jp3_=N)a|6kwOqmZE)crSSkr8wPD_+^X<-hxR%2SdRUcQpNaw zkN@0Nk_GD;UufE$F!K`ry)y4Bz9jI)D#Lyfvl!e)mS5S_-bNdeuBOIn!cB*@`E76$ z0j8(_y@c*Gzv<2oW9VVVF2X1#M{7KHR96RA#CaIIrdJcLJb)vSSi3UOh+4H$+MVh2 zWqo5~6WxR7&Zf_ANx!uveOBr1?0n~)GwBFp*VdtsO=%X~H0=#-nr6jUq;X|=)B8We zNTr>dqER}1ncvkjc)W8WbtXM|KK<6@8J1F`usPbT7OgWcRj&qktQqG_OL7iw3PuB) z($W07APdyOqof*?RCrNv{=!Z5{=+X_%=(^HlfB5BpGqgG=f=|Dqc_DU?XpxT8ba)C z7En@&=LeQf=Y16;I#wHFo;r9sBT9u-tiP#XKXNYoLLM`;2s&vo z+L7w&RXWCcI+Per8F=Lss$E6;ok=p>`*&qpmc_q;Nzr~@{CtMpdHDCqNDbr((coZj zH-0vf+J32t_K5a0Q>-EHlr{bz8q@3GP^d@muR`Xx#T~L}NkQDm%Y%TTJdFaH^Tu%J zgG?kCw~2K6Eze>8BPmAOT;M;y1@`B#Tz!1cpSN`SPIVmLy)1q&lE&#aV}5C0%O=e_s#xwq4?Uye-Bd5O|BGKw>YqrE9QYej5qv_hFYe}3{& zKC~6sLtB^6rlhqh6?-@grgLO1{5)glU|$MIPlyI3oB|($ry(nn5R%+JDco6^>Uk4q zPrAcP=CvgDiC)`P*)`JLWBx!T{fs}!{XUg$EaT@bnRgwf`~4x6?p>AL9VzJtGLf{3 z()|Yi6Hgo;9ql+H6o3eGk;&g#iBlCEkeT}V`E;l2*I7xmHyzml*$sZOPgh@0%8LM{ z+guUiUeuQ6ulwNjX->d=1K=Zl7K#Mh&G$MIz~QaQw6yPCA*;`n`4^A55bgzSKW z><%G2d z+s|>%Szyira~7Dhz?=oFPDoeA?rZ6Y-n_T2zlOskO!zm09CB&(vH{ z-1S>b3ls}pCgRr#eh+^p!?RzphVx8mcRlW1Z;gAlTjSmWYh3@GB6@z$>o$4P7B95M zy^0n$t}!j-ray~oa-+PcE#7X8vu;~la1cY+6pPtwcOu8E$m6n+M27%zVD4LseCjM8;*5L$P23=Vd7bPaS2pW3YS z44)X9==){QhKV60BmQO&Do146&om%WIWjoXk=oGL)6?^)a%5z%`%y@TI*!n7Y;5RJ zrQ^sbXits|cHp!7p3PM5krTsRJtupHQ_9hiBS(;MbOZ%;_KYFedvuiFMo4?A;Mmyk z2nC1xQXMB!T5u3Q`$1`=9m-(G@X^7OgB$Rc8$X~!<`^Eq$2nwcWsqvqvte{(qVLVk zhz%bd?ilJ(21oI}d#K~hp`M`)XVT~2nSA>U@P>^eM=QpQG340mrB-i!b>6@C^4GN6091`t9cp6u%)MJI+vm5I?l z82HTF=cp|F4#=*7(Xo*fnnK~f5E55vYc8WeW#4f3iLO-N$gqOn7kRWNwP6qj{?W+9 zN&L#i%}S~lp9-P6O6tUL&xXnLX63~2*a!+B8&L@-Mxo+K1Wuxe5i;o;)ROpdu{Tk_ z;Q_P>H8c87-!Qe+1VB9~Xo4boCwNpjdZJ?tO*%3`Nyx($Mdd3dGwy@k_{X)wH)He%hDaNH0fj5otpGkB zal6Z?bI;ftZw_%De#zBn*ez-{_L0~#cr@86;(@;o-l(i5qN_J%hP6=77}0XC79@Y|i8nc2<#7voqHcF$aAJVs(n5>!YWuOhvnq z*Hc{Y&i#W94ls9cP)dA;bDh%9l; zASXK4%Rat15BQ|<^t!2X^oghgkD-jtW7sZpd_9Aj@jqgr^DHoOUm(Es z!Jn%NePjt5%b@qGTp!;l+$A2~kL#K7(iI`$M#o0S2Kk4o9zR$xPHRb$qq^7YAU^V= z{*1d>aAv)ZLCpK1UN6bcB=T+3veSJ=o;=l6AAbnh(Qb5~ktg8JlM_U>55VI-BhNf{ zp1d%=vF(M&eMTOd=UwbGZya57Cw_4#?lbZ%aOcSnVakSm=sqJ)zB|vtgN)J3c)HKX zv(TLfKQY4SB|qI~}FXqI>` zoh6>jhzFj=nXMnvKI3X;cNy)a@^NuF^3O)QUolHOSI!boXqI?Z5Dz@{Ynz?DFrfai z95bAYov%WE7anRa<0H12cs@)#1}KX_hCYn9d(kZMTs=!XADJbdYi5b3c$Rpsoh2T6 zZl8^I|L837tRx&PD3gqN1&V?tey7Q1u z!hv4HInw{sG*Gn}fOOK=_vQ`$_< zXm^}TNav8$55bes5B=}69~OW|e29GkO=hlFzRrWY{M-~0tO0R1Zueq93Vm>w zdGvf4Jeki;$f?acRJWDzu!-Hhula{~KIr^Ilhty&78!9jJ6q4OIS=@x`OsIdaTP`F zoTi;E=h(L)zXOk++u$kDQ%pPS&tJwlo6hsT`?GY;R-)-+KWF3PJPsYmTO5s3hjTXC z_v-pc_TgC%ihVEc>;m;VM&Ko?ws)ra)v5nX5lD9Cy2Bq*O(_M4=euFQ-dLqB;?Jn;(RINT2 zTYyfH?B)&515U|4{&9`&8gbWRbk+5-ozJgPp%ck*mv|_J+%@BLgiWp@hRzwb5gYApn}0r`n)Q--^z0ctX1iz1KUA;T zn1A$oeUSO*lTy889_l|q;c+va)PLmp=l4{ty{P?l+nSji_Pv?&YLdp(BI2Qp6sEi8 z^m&7CBlSdn*T<=C-XJ|zSb$Cu=XryW`hL}~3Lf0$dg<#Y*~sE_eJD|SUrF}i`rt0} z5R6;~5A`4EeI@i!$tG8mrwkW#GuNv~6+E~XU64x%dA+>MqlDFT_&z~=2SQS*Ki{gNZj^?*%tJ|VnLIA- z6;TBb&z8l-$ z#8W;?Ja^3!PsJ?pte+*G4YS0vah7=Qo+X~>Eb-i<^Wbiu4+}9L_A>EH+HmL2X+Bi7 z@6WCi5cgYl>jmclXOTORDY?M$xyh+2UGKw{ck4<{axJ(I`DJ^(*(0Upd5ImN(O=8jCBS_TeU|2_`vg`Ja~ zRh|V$h*-j~hQf0m3L{B4Pe>2h?}mL;%XfpcE<5npbDMFaUf_X)J}T)`LY@*X=-lgt z^8{Y6+f>1W`)!n_Iqetf>M{9l*30s~=|RuC3A_XO33_a91C=|c0Wu8*B32swF+BOd-efGWNRU^H~tO{zOj2y*fk=fZP?>dr&+ zBzcQ-;ki+D=TSgF-r`(%XkK-*PZR{?EzX5!t;%`c$9o6ZnZK{p+6&{Wmdc@V3Vkwo zLXgFU$IW!4kIv)g=d_&1uR8Kv;O7*adFZuvWo*;P0TbvWm+vldHCa2!PZw_C)V+j{iK=K-wQ_l5oHs>Ik?I(-!o@*gLC}SLW2yYqi!cY7F61}% zKQtc_#+Qj{)%$z_Fm$v^^_J_7ealsL%t~P7y32bTnI{CC;o{&CbCizpLl`mu2!sPy z`MfHhGneB=dmGxf$nEuUY2Tt_=*Yo_F~%}sXy0-bd>mePB~l;LF=RgrMw(l64DsyL zNpLTrekkS*9fNtEsWQf;EDOe=EaIt^d2D5gcE9GBgke&~Crktet+^KHn0tY#v13GA=$QL}dB%WsCz4+ST$5>tsX16u9t|s9Kvp z2>E3)Mq1-!Oi>mXOCNLLS(^oqk_G0WEHJSwFk7?0?92l5L>3q|3(TG@F#EE=Jf8)| zGA>-&>rfUvhqJ&O%K~E=UoQF#Wx;bQ3(T*wz*xqqvpyc06AkBr!E9?f7Yxl)hI7G$ z3;+Tym@LMrCyR0F$zq&(lq~dFmjz~17MLu?yC;?f&tq9&vKa54EXKR#{Ku`mvKa4{ z^B*^!7qh5W7USKM#dx<{T@deXS?&NSYMXP;b_3r~xTap*t9(=KCNcxIY6h{rN-xbPg7 z%W~1@=Q75Hr(4Fj@bt};8%TzJmPWx41x zC1adc+>F_p0zT@g-4MwE<9y2#)W6SjB(+)PsX_LY?3i9JTV#L!n0MzxbSS3F)loD86)wm zQnj;O>Zfua3x@*5`rNBy=&V5QV`1sMSH}=f2wrzLIq(D^l>5(3E<9nK1os;pc<8L4 zM8>%AC=%vI2Ob)Ka^JYog(oWU-0Z-U2f5ttH`{qsZEsgE@%UE+0{S_UZo>y4-zQ^S zcv@tP3(o-=*}|gLQ|Fb~>^UWrv-C=~U~HoA?3uIgr1ANvRIT4W*w^z$=bM8^6flHo0mfhT zd6ThUApZBoI8MiXycWmdxc@^7V}Ca;;S1@Bo&I1EZcU6GLtj1iKj4qRkHVw)?L?{}Ox>{(r+`&;K%Xc=`XpzsuMwIq)msai0Fl zXW_pJ|A+96@cZFW?khioe+B-Z;inmUH2{xtUoC_W!Q=bCSMlA)tKfLG6#g!Fyx)0s zGyEg)kHh~F{PXZH!v7S$6aHm*)a6y^^XfZz1(6582>vSg)$riyzX$#y_%FgkxBmYM z51aKj!2c=ykKhl%|1bDozz@TZ!=Hvf$JlF_++V{!;5_*UrHIhOq(YJg^iV-(L-U6utx= z?Jxkn2e!haEe5^`|1^9v{9nL#!NZ;dWAG>7-@-57fu4h~=^$)6xB`A9JoFsId*8tg z@DIRmfseyO$H86j&%(o|gZtrs0{^%0z3>C@&~p%a4noht^XO~nena3N!Z%JsMeyJs zTJ2$hp6)LEIj__Nf?Yj>$A|C-p*(ES?!)_3XsW8I+`GHF zb@EK*uDXVVhb^hDO;qo$Y)-VbH#b&RH`O3*VQbxgSgo&f+x9mnp z>9W*VO8c!wK@VHd+Sc4yUDcYX-h(1@pDJwqyP6XqZ?1cRbU+0v>l$}8 zp?pIoRTAZ2PU(q8GFxS0Kd+Yr@UV*{xx^|6YZ5%8FbFqS0NPZ-0978g*eLU<_FcOY z%}{k0x4Vbs?czq;h31nAcnVcIcNVQ&*Z4xy?nLDnCu*pB%EK-tQ?~CllgNNodrV7>ArB4?PN2c_ zXhd{UXrVqJPza3&OMJp67yV-iY^rB#O*FqySDm1&8EMF#ktQgXLY=;`v5D?MY7MR# z{UtmRL^n;F!AUcC#tiD&fPLFcJ!b~rF@sZP@VpV6G>e!tilvg!tS7K1@aOhmUs~_*M+t?cQ}pZJbGlO9gM9?+8a}QKM9!YVpYs!$5$w^1 z;4;C{)z^bA$M8yct9HXI_z27Ctn8WSeuU+AR;Dn;@jzeq*x*)k*6U@(6Q?H5q$kh3 zQ<0jSeEaS6xr(ulbUIy;8W}p-mp=1W#aQ~>q#eiC7qC^L+XhPkNP7HJn zO`JQcS2LY{O9W3M_!!IY>glPNz@>Az`^;l(L04xNqFwltg0CS4drnq#O-$g=FzOaJ z0wX+{yL6cnk{(L^c* zMbYSxqG*H!k~*J2QkT^Fo9`Q@)exk9LZ(7L=&bA;8pWT>1S55JbX4Bf==355A)YeS zF^c`6xnC^A#*B^Pk9FdPZ*JJbS0(vpS_rZnAAY=X3wkNsBqhLAYB$T3@{yBeUMIf;|p=d_!4 zU84Q^Us(pd7Bs=IbYHnMTv#(0L0g3l5LG(3)Py{4iT}Cr8dD%U|`i*`z-{;TuVV=Mg z!TZC16~OPv8C=3NEM%ujybH*_5^t3NJ|$-m`pU9g$jQsDTH?*O@zw~S6R#}8vjHP7 zyM)BM(8h~BJ$FvLvJB5(mT#>o)6){~A{#HBm$-A{m1XmQA}_l-iFdJ$_YVcoiC31* z2ade#{z&2t+IaEY#hnwcEL#8+dD;E3#Jj}C`&|Ka;+19jz>$|-BdgW>?~}jrVc1|Q z;|?Hwj@0Kao-fOJvO(v4a(a3i`Z7VQd_dmsS$StiUwM6^N{)67cH-t+^YZlv;Wr_S zXI;h+?uFln;7$?WL>Pp>MRA$Oi#T{Da0|kJ9^afNac66uyN&uetpFaMAHUpIUJ1U4 z^i_le3Qx>B3d@X)+J2*n-zsDZn_wP3n>cJKDx6UY7-mk z5v0?Xm4rG#cXV24q-eI|3Aj8816@fGpbqoIJXVy!g_9x8en9ndQ~(=ydx<#jFi^)i zY96~k1BFvEoAa=c6(#pOGU8}gAI@M{!J6mF>*2{7m#%s4PcOy&u{F(~_=|A_bhqZY z3ScS-69R_xaKNmO0@DxKC2OAhvum6&8^E)Hcs>Noe{;s%1D+`HT)yVHA6(*$xi`4x zxqIp%D+DIyjJdCW&2#rfA-j0ZbFDb*a?tt5ht{w8@n0Q-?89rG`%9Wnzk#}Uj3WR? zBaN;3@m~XTh%g@o=A*dF81z)a{1lkKAe)<`l`?2L~o;!^hN3NH* zgD`SGr)gl6KV7gt!B$uuvizv_#}7dqraYSSvo3mc=JRk6x0Ok4dImUT@$RWQXwO_ICAGh+$K_MHMI zL;net&!68D`EBx?B#wb-?xDG#T)?Vd&bW|&oXaxgnCrFtpM*S^nSWkLv_E#epMV@Y zU!0r{j|}$!3zr)c`fbtTcn-4I*Ra2tYKAC(i^%^3B2<2fOa9*z{I>p+r}sY<@-hf* z>qqXm)IW&gN-KY!G`?8~`3r3FkeT08g8UivljJC$eaM>MsQ+rnG-s)QUQ*P*8fDY? zJZR0I*CP7gt$KE=+~BAEK_SOj_ybJvCosNakVjqeui|;>V$H9J{7)l4=~rfz8|ANb z$*+q1b;ytYjo+7G;WzRxamlaS=Z`S-sr)ayXD~ruHa=A>^0FhfzM>kCXF|+~P#}pEeRL^7;DwfPLHTaoAuo zgJ0WUHE8*{+@PX>**__kDHrAQCp1D>^;@8J1^NE&3)+u6;yKi!pHV+CKiTE;V`6^! zEa%SHpUqcC1AP7pLmuSb!au)7$ZvuyRTS_OPggHNU=pp!(;-f5Ixa_kX*5 zArt&xM&9yF{)LKI-)Voc9zJIVew%!uUVrKvG)FJC=3l7SANJ=BY?tfxr}dF^u+@KI zQs}QjMjW{|{&69%hHNMNMOOJDCgfNj*mvP=?XxH(-d6ubNg=2C@4sit(Z99%@q3W{ z1U_ihKcj!xu4~<`YepSfHws;23khcgq^&dQg+U3UlMg51yzm0#1(xtT@&L~>G5BY;Y zNbR?T34UrHa#uhuxg{YXr}nubQ*M+`?L%vXE&npsrIr6E%0CPBuEeRPT)tlahmn^Y zKlRjtbX}s?pY$X9uc1>>(=AB~{b+6|h4^pC>l*yJH0S0Vch zyp4aUBIMLRXpLWL%O4YR>L0K{Mt)Vusee!%?EEc4PW|I+@Ln5#Qpjn3_&WSzn|xfz zX@01I|B_X1v>(k6zlOirDqp5_Y3=toPRYnV9;|j!`x*IZ{US$li|f+z<4n5mXIy^2 vV}2UH Date: Wed, 24 Jun 2020 11:27:15 +0200 Subject: [PATCH 34/37] remove backtick Signed-off-by: Vit Tomica --- files/jcl/ZWEKRING.jcl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/files/jcl/ZWEKRING.jcl b/files/jcl/ZWEKRING.jcl index b4f89ac636..cfb3330ea6 100644 --- a/files/jcl/ZWEKRING.jcl +++ b/files/jcl/ZWEKRING.jcl @@ -391,7 +391,7 @@ ACF SERVICE(READ) ALLOW) * Uncomment this command if SITE acid owns the Zowe certificate -* RECKEY IRR ADD(DIGTCERT.GENCERT ROLE(&`STCGRP`) + +* RECKEY IRR ADD(DIGTCERT.GENCERT ROLE(&STCGRP) + * SERVICE(CONTROL) ALLOW) F ACF2,REBUILD(FAC) From 955b65d02f4c06b3342c25096447da9573ba5fa5 Mon Sep 17 00:00:00 2001 From: Vit Tomica Date: Tue, 7 Jul 2020 10:39:04 +0200 Subject: [PATCH 35/37] update keyring utilities version to 1.0.2 Signed-off-by: Vit Tomica --- manifest.json.template | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/manifest.json.template b/manifest.json.template index cf69ee21fe..bf84cbaa9a 100644 --- a/manifest.json.template +++ b/manifest.json.template @@ -80,7 +80,7 @@ "excludePatterns": ["*PR*.zip"] }, "org.zowe.keyring-utilities": { - "version": "1.0.1", + "version": "1.0.2", "artifact": "keyring-util-*", "target": ".pax/keyring-util/keyring-util", "explode": "false", From 249ce27ce5e3e7807ddb966d3a90af8970726141 Mon Sep 17 00:00:00 2001 From: Vit Tomica Date: Wed, 8 Jul 2020 17:04:10 +0200 Subject: [PATCH 36/37] update keyring utilities version to 1.0.3 Signed-off-by: Vit Tomica --- manifest.json.template | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/manifest.json.template b/manifest.json.template index 564779b12d..70356f7aa3 100644 --- a/manifest.json.template +++ b/manifest.json.template @@ -80,7 +80,7 @@ "excludePatterns": ["*PR*.zip"] }, "org.zowe.keyring-utilities": { - "version": "1.0.2", + "version": "1.0.3", "artifact": "keyring-util-*", "target": ".pax/keyring-util/keyring-util", "explode": "false", From 4f559f6defb1a7f77b3f8f015c38c0109413e981 Mon Sep 17 00:00:00 2001 From: Vit Tomica Date: Mon, 20 Jul 2020 14:21:12 +0200 Subject: [PATCH 37/37] resolve PR review comments Signed-off-by: Vit Tomica --- .pax/prepare-workspace.sh | 6 +++--- files/jcl/ZWEKRING.jcl | 18 +++++++++--------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/.pax/prepare-workspace.sh b/.pax/prepare-workspace.sh index fd7ad2f282..9b2f4b0ef4 100755 --- a/.pax/prepare-workspace.sh +++ b/.pax/prepare-workspace.sh @@ -21,9 +21,9 @@ ####################################################################### set -x -# expected workspace layout: -# ./.pax/mediation/ +# expected input workspace layout ($ROOT_DIR): # ./.pax/keyring-util/ +# ./.pax/mediation/ # ./bin/ # ./files/ # ./install/ @@ -208,6 +208,6 @@ echo "[$SCRIPT_NAME] done" # ${PAX_WORKSPACE_DIR}/ascii/templates/ # ${PAX_WORKSPACE_DIR}/ascii/zowe-${ZOWE_VERSION}/ # ${PAX_WORKSPACE_DIR}/content/zowe-${ZOWE_VERSION}/ -# ${PAX_WORKSPACE_DIR}/mediation/ # already present # ${PAX_WORKSPACE_DIR}/keyring-util/ # already present +# ${PAX_WORKSPACE_DIR}/mediation/ # already present # ascii/* will move into content/, translated to ebcdic diff --git a/files/jcl/ZWEKRING.jcl b/files/jcl/ZWEKRING.jcl index cfb3330ea6..dc1b1c9edc 100644 --- a/files/jcl/ZWEKRING.jcl +++ b/files/jcl/ZWEKRING.jcl @@ -7,7 +7,7 @@ //* //* SPDX-License-Identifier: EPL-2.0 //* -//* Copyright Contributors to the Zowe Project. 2018, 2020 +//* Copyright Contributors to the Zowe Project. 2020, 2020 //* //********************************************************************* //* @@ -25,15 +25,15 @@ //* 2) Update the SET PRODUCT= statement to match your security //* product. //* -//* 3) Update the SET ZOWEUSER= statement to match the desired -//* user ID for the ZOWE started task. +//* 3) Update the SET ZOWEUSER= statement to match the existing +//* user ID for the Zowe started task. //* //* 4) Update the SET ZOWERING= statement to match the desired -//* name of the keyring owned by the ZOWEUSER. +//* name of the keyring owned by the &ZOWEUSER user ID. //* //* 5) Update the SET LABEL= statement with the name of the Zowe -//* certificate that will be added to the RACF database or that -//* is already stored in the RACF database. +//* certificate that will be added to the security database or +//* that is already stored in the security database. //* //* 6) Update the SET DSNAME= statement if you plan to import the Zowe //* certificate from a data set in PKCS12 format. @@ -53,7 +53,7 @@ //* TO ALTER SECURITY DEFINITIONS //* //* 2. Assumption: signing CA chain of the Zowe external certificate is -//* added to RACF database under the CERTAUTH userid. +//* added to the security database under the CERTAUTH userid. //* //* 3. If the Zowe certificate is imported from a data set then //* the certificate has to be in PKCS12 format and has to @@ -297,7 +297,7 @@ ACF * environment and follow the appropriate action */ * */ * Options: */ -* 1. Zowe's certificate is already loaded in RACF database */ +* 1. Zowe's certificate is already loaded in ACF2 database */ * ACTION: Modify the CERTDATA(&ZOWEUSER..ZOWECERT) keyword */ * below to match the desired certificate for Zowe */ * */ @@ -436,7 +436,7 @@ $$ /* environment and follow the appropriate action */ /* */ /* Options: */ -/* 1. Zowe's certificate is already loaded in RACF database */ +/* 1. Zowe's certificate is already loaded in TSS database */ /* ACTION: Modify the RINGDATA(&ZOWEUSER.,ZOWECERT) keyword */ /* below to match the desired certificate for Zowe */ /* */