#!/bin/bash
#------------------------------
# Script to manage vCenter SSL certificates.
#
# Author: Vincent Santa Maria [vinny.santa-maria@broadcom.com]
#------------------------------
#------------------------------
# for debugging purposes only, uncomment the following line:
# export PS4='+[${SECONDS}s][${BASH_SOURCE}:${LINENO}]: ${FUNCNAME[0]:+${FUNCNAME[0]}(): }'; set -x;
# to debug run: ./vCert 2>vCert-debug.txt
#------------------------------
VERSION="4.22.0"
set -o pipefail
#------------------------------
# Prints help information
#------------------------------
function printHelp() {
cat << EOF
vCert: vCenter Certificate Management Utility
Usage: $0 [options]
Options:
-h | --help Prints this help menu
-d | --debug Enables debug-level logging
-j | --just-do-it JUST DO IT! Script operations will continue if backup tasks fail
-u | --user Specify an SSO administrator account
-v | --version Prints script version
-w | --password Password for the specified SSO administrator account
EOF
}
#------------------------------
# Parses arguments passed to the script
#------------------------------
function parseArguments() {
logInfo 'Entering the parseArguments function'
logDetails "Arguments: $#"
if [ "$#" -ge 1 ]; then
logInfo 'There are arguments passed'
while [ "$#" -ge 1 ]; do
logInfo "Parsing argument '$1'"
case "$1" in
-h|--help)
logInfo 'Printing help menu'
stopLoading
printHelp
exit
;;
-d|--debug)
logInfo 'Enabling debug-level logging'
DEBUG=1
shift 1
;;
-j|--just-do-it)
logInfo 'Disabling exit on backup task failure'
EXIT_ON_BACKUP_FAILURE=0
shift 1
;;
-u|--user)
logInfo "Specified SSO Administrator account: $2"
VMDIR_USER_UPN="$2"
VMDIR_USER=$(echo $VMDIR_USER_UPN | awk -F'@' '{print $1}')
shift 2
;;
-v|--version)
logInfo 'Printing script version'
stopLoading
echo "vCert: version $VERSION"
exit
;;
-w|--password)
logInfo "Specified SSO Administrator password: $(echo $2 | tr '[:print:]' '*')"
echo -n "$2" > $STAGE_DIR/.vmdir-user-password
chmod 640 $STAGE_DIR/.vmdir-user-password
VMDIR_USER_PASSWORD="$2"
shift 2
;;
*)
logInfo "Invalid argument $1"
echo $'\n'"${YELLOW}Invalid argument '$1'"
stopLoading
printHelp
exit
;;
esac
done
fi
if [ -n "$VMDIR_USER_UPN" ] && [ -f $STAGE_DIR/.vmdir-user-password ]; then VERIFY_PASSED_CREDENTIALS=1; fi
}
#------------------------------
# Print loading message
#------------------------------
function loading() {
i=2
e[0]='.'
e[1]='..'
e[2]='...'
while [ $i -lt 3 ]; do
echo -ne "\r\033[KLoading${e[$i]}"
if [ $i -eq 2 ]; then
i=0
else
((++i))
fi
sleep 1
done
}
loading &
LOADING_PID=$!
#------------------------------
# Stop loading message
#------------------------------
function stopLoading() {
kill $LOADING_PID
wait $LOADING_PID > /dev/null 2>&1
unset LOADING_PID
echo -ne "\r\033[K"
}
#------------------------------
# Print Disclaimer
#------------------------------
function disclaimer() {
cat << EOF
${YELLOW}
------------------------!!! Attention !!!------------------------${NORMAL}
This script is intended to be used at the direction of Broadcom Global Support.
Changes made could render this system inoperable. Please ensure you have a valid
VAMI-based backup or offline snaphots of ${YELLOW}${UL}ALL${NORMAL} vCenter/PSC nodes in the SSO domain
before continuing. Please refer to the following Knowledge Base article:
${YELLOW}${UL}https://knowledge.broadcom.com/external/article?legacyId=85662${NORMAL}
EOF
read -p $'\nDo you acknowledge the risks and wish to continue? [y/n]: ' DISCLAIMER_ACKNOWLEDGE_INPUT
if [ -n "$DISCLAIMER_ACKNOWLEDGE_INPUT" ] && [[ "$DISCLAIMER_ACKNOWLEDGE_INPUT" =~ ^[Yy] ]]; then
logInfo 'User acknowledges the risk assessment disclaimer'
return
else
logInfo 'User does not acknowledge the risk assessment disclaimer'
exit
fi
}
#------------------------------
# Print section header
#------------------------------
function header() {
printf "\n%s\n" "${CYAN}$1"
printf "%65s${NORMAL}\n" | tr " " "-"
logInfo "Operation: $1"
}
#------------------------------
# Print task description
#------------------------------
function task() {
printf "%-52s" "$1"
logInfo "Task: $1"
}
#------------------------------
# Print formatted status message with colored text
#------------------------------
function statusMessage() {
printf "%13s\n" "${1}" | sed "s/${1}/${!2}&${NORMAL}/"
logInfo "Task Status: $1"
}
#------------------------------
# Print formatted 'errror' message
#------------------------------
function errorMessage() {
if [ -z $3 ]; then printf "%13s\n\n" "FAILED" | sed "s/FAILED/${RED}&${NORMAL}/"; else printf "\n\n"; fi
logError "Task Error: $1"
if [ -z $2 ]; then
printf "%s\n\n" "${YELLOW}${1}. Exiting...${NORMAL}"
exit
else
case $2 in
'backup')
if [ $EXIT_ON_BACKUP_FAILURE == 1 ]; then
printf "%s\n\n" "${YELLOW}${1}. Exiting...${NORMAL}"
exit
fi
;;
*)
printf "%s\n\n" "${YELLOW}${1}. Exiting...${NORMAL}"
exit
;;
esac
fi
}
#------------------------------
# Main logging function
#------------------------------
function logEntry() {
if [ -n "$1" ]; then
IN="$1"
LOG_LEVEL="$2"
else
read -r IN
LOG_LEVEL='INFO'
fi
LOG_TIMESTAMP=$(date "+%Y-%m-%dT%H:%M:%S %Z %:z")
echo "$LOG_TIMESTAMP $LOG_LEVEL $IN" >> $LOG 2>/dev/null
}
#------------------------------
# Logging function for log details
#------------------------------
function logDetails() {
if [ -n "$1" ]; then
IN="$1"
else
read -r IN
fi
echo "$IN" | sed -e 's/^[.]*/--> &/g' >> $LOG 2>/dev/null
}
#------------------------------
# Logging function for info-level logging
#------------------------------
function logInfo() {
if [ -n "$1" ]; then
IN="$1"
else
read -r IN
fi
logEntry "$IN" 'INFO'
}
#------------------------------
# Logging function for error-level logging
#------------------------------
function logError() {
if [ -n "$1" ]; then
IN="$1"
else
read -r IN
fi
logEntry "$IN" 'ERROR'
}
#------------------------------
# Logging function for debug-level logging
#------------------------------
function logDebug() {
if [ "$DEBUG" -gt 0 ]; then
if [ -n "$1" ]; then
IN="$1"
else
read -r IN
fi
logEntry "$IN" 'DEBUG'
fi
}
#------------------------------
# Logging function for debug-level logging
#------------------------------
function logDebugDetails() {
if [ "$DEBUG" -gt 0 ]; then
if [ -n "$1" ]; then
IN="$1"
else
read -r IN
fi
echo "$IN" | sed -e 's/^[.]*/--> &/g' >> $LOG 2>/dev/null
fi
}
#------------------------------
# Set color variables
#------------------------------
function enableColor() {
RED=$(tput setaf 1)
GREEN=$(tput setaf 2)
YELLOW=$(tput setaf 3)
CYAN=$(tput setaf 6)
UL=$(tput smul)
NORMAL=$(tput sgr0)
}
#------------------------------
# Clear color variables for reports
#------------------------------
function disableColor() {
RED=''
GREEN=''
YELLOW=''
CYAN=''
UL=''
NORMAL=''
}
#------------------------------
# Pre-start operations
#------------------------------
function preStartOperations() {
if [ ! -d $LOG_DIR ]; then mkdir $LOG_DIR; fi
if [ ! -d $STAGE_DIR ]; then mkdir -p $STAGE_DIR; fi
if [ ! -d $TRUSTED_CA_DIR ]; then mkdir -p $TRUSTED_CA_DIR; fi
if [ ! -d $REQUEST_DIR ]; then mkdir -p $REQUEST_DIR; fi
if [ ! -d $BACKUP_DIR ]; then mkdir -p $BACKUP_DIR; fi
if [ ! -f $LOG ]; then touch $LOG; fi
logInfo "Starting vCert version $VERSION"
echo -n "$VMDIR_MACHINE_PASSWORD" > $STAGE_DIR/.machine-account-password
chmod 640 $STAGE_DIR/.machine-account-password
updateVcSupport
setTimestamp
parseArguments "$@"
enableColor
checkServices
checkVmdirMachineCredentials
checkCAPermissions
setSolutionUsers
setVECSStores
clearCSRInfo
checkForVCF
stopLoading
}
#------------------------------
# make sure vCert.log is included in a support bundle
#------------------------------
function updateVcSupport() {
if [ ! -f /etc/vmware/vm-support/vcert.mfx ]; then
logInfo 'Creating vc-support manifest for vCert'
cat << EOF > /etc/vmware/vm-support/vcert.mfx
% Manifest name: vcert
% Manifest group: VirtualAppliance
% Manifest default: Enabled
# action Options file/command
copy IGNORE_MISSING $LOG_DIR/*
EOF
fi
}
#------------------------------
# set the TIMESTAMP variable
#------------------------------
function setTimestamp() {
TIMESTAMP=$(date +%Y%m%d%H%M%S)
}
#------------------------------
# Cleanup operations
#------------------------------
function cleanup() {
if [ -n "$LOADING_PID" ]; then stopLoading; fi
if [ $CLEANUP -eq 1 ]; then rm -Rf $STAGE_DIR; fi
}
#------------------------------
# Validate an IP address
#------------------------------
function validateIp() {
logInfo "Attempting to validate $1 as an IP address"
RETURN=1
if [[ $1 =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
OIFS=$IFS
IFS='.'
ip=($1)
IFS=$OIFS
[[ ${ip[0]} -le 255 && ${ip[1]} -le 255 && ${ip[2]} -le 255 && ${ip[3]} -le 255 ]]
RETURN=$?
fi
if [ $RETURN ]; then
logInfo '$1 is a valid IP address'
else
logInfo '$1 is not a valid IP address'
fi
return $RETURN
}
#------------------------------
# Authenticate if needed
#------------------------------
function authenticateIfNeeded() {
if [ -z "$VMDIR_USER_UPN" ] || [ ! -f $STAGE_DIR/.vmdir-user-password ]; then
getSSOCredentials
verifySSOCredentials
fi
if [ $VERIFY_PASSED_CREDENTIALS == 1 ]; then verifySSOCredentials; fi
}
#------------------------------
# Get SSO administrator credentials
#------------------------------
function getSSOCredentials() {
unset VMDIR_USER_UPN_INPUT
read -t $READ_TIMEOUTS -r -p $'\n'"Please enter a Single Sign-On administrator account [${VMDIR_USER_UPN_DEFAULT}]: " VMDIR_USER_UPN_INPUT
if [ $? -le 128 ]; then
if [ -z "$VMDIR_USER_UPN_INPUT" ]; then
VMDIR_USER_UPN=$VMDIR_USER_UPN_DEFAULT
else
VMDIR_USER_UPN=$VMDIR_USER_UPN_INPUT
fi
logInfo "User has chosen the following Single Sign-On account: $VMDIR_USER_UPN"
VMDIR_USER=$(echo $VMDIR_USER_UPN | awk -F'@' '{print $1}')
USER_PROVIDED_SSO_DOMAIN=$(echo $VMDIR_USER_UPN | awk -F'@' '{print $2}')
if [ "$USER_PROVIDED_SSO_DOMAIN" != "$SSO_DOMAIN" ]; then
echo ''
while [ "$USER_PROVIDED_SSO_DOMAIN" != "$SSO_DOMAIN" ]; do
read -r -p "${YELLOW}Invalid domain, please provide an account in the SSO domain ($SSO_DOMAIN):${NORMAL} " VMDIR_USER_UPN_INPUT
VMDIR_USER_UPN=$VMDIR_USER_UPN_INPUT
VMDIR_USER=$(echo $VMDIR_USER_UPN | awk -F'@' '{print $1}')
USER_PROVIDED_SSO_DOMAIN=$(echo $VMDIR_USER_UPN | awk -F'@' '{print $2}')
done
echo ''
fi
read -t $READ_TIMEOUTS -r -s -p "Please provide the password for $VMDIR_USER_UPN: " VMDIR_USER_PASSWORD
if [ $? -le 128 ]; then
echo -n "$VMDIR_USER_PASSWORD" > $STAGE_DIR/.vmdir-user-password
chmod 640 $STAGE_DIR/.vmdir-user-password
echo ''
else
errorMessage 'Timeout waiting for password' 'credentials' 'password'
fi
else
errorMessage 'Timeout waiting for SSO Admin account UPN' 'credentials' 'password'
fi
}
#------------------------------
# Verify SSO credentials
#------------------------------
function verifySSOCredentials() {
VERIFIED=0
ATTEMPT=1
logInfo "Validating credentials for ${VMDIR_USER_UPN}"
while [ $ATTEMPT -le 3 ]; do
if ! $LDAP_SEARCH -LLL -h $PSC_LOCATION -p $VMDIR_PORT -b "cn=Servers,cn=$SSO_SITE,cn=Sites,cn=Configuration,$VMDIR_DOMAIN_DN" -D "cn=$VMDIR_USER,cn=users,$VMDIR_DOMAIN_DN" -y $STAGE_DIR/.vmdir-user-password "(objectclass=vmwDirServer)" cn 2>/dev/null 1>/dev/null; then
logInfo "Invalid credentials for $VMDIR_USER_UPN (attempt $ATTEMPT)"
if [ $VERIFY_PASSED_CREDENTIALS == 1 ] && [ $ATTEMPT == 1 ]; then
echo "${YELLOW}Unable to validate the provided credentials for $VMDIR_USER_UPN${NORMAL}"
getSSOCredentials
else
read -r -s -p $'\n'"${YELLOW}Invalid credentials, please enter the password for $VMDIR_USER_UPN:${NORMAL} " VMDIR_USER_PASSWORD
echo -n "$VMDIR_USER_PASSWORD" > $STAGE_DIR/.vmdir-user-password
chmod 640 $STAGE_DIR/.vmdir-user-password
fi
((++ATTEMPT))
else
VERIFIED=1
logInfo "Credentials verified for $VMDIR_USER_UPN"
if [ $ATTEMPT -gt 1 ]; then echo ''; fi
break
fi
done
if [ $VERIFIED == 0 ]; then
errorMessage "Unable to verify credentials for $VMDIR_USER_UPN"
fi
}
#------------------------------
# Check if vmafdd, vmdird, and reverse proxy are running
#------------------------------
function checkServices() {
if [[ "$VC_VERSION" =~ ^[78] ]]; then
logInfo 'Checking state of the vmware-envoy service'
if ! checkService 'envoy'; then
logError 'The Envoy service is not running'
echo $'\n'"${YELLOW}The Envoy Service is not running!"
echo "The script cannot continue. Exiting...${NORMAL}"
stopLoading
exit
fi
logInfo 'The vmware-envoy service is running'
fi
logInfo 'Checking state of the vmware-rhttpproxy service'
if ! checkService 'rhttpproxy'; then
logError 'The reverse proxy service is not running'
echo $'\n'"${YELLOW}The Reverse Proxy Service is not running!"
echo "The script cannot continue. Exiting...${NORMAL}"
stopLoading
exit
fi
logInfo 'The vmware-rhttpproxy service is running'
logInfo 'Checking state of the vmafdd service'
if ! checkService 'vmafdd'; then
logError 'The vmafdd service is not running'
echo $'\n'"${YELLOW}The VMware Authentication Framework Service is not running!"
echo "The script cannot continue. Exiting...${NORMAL}"
stopLoading
exit
fi
logInfo 'The vmafdd service is running'
if [ $NODE_TYPE != 'management' ]; then
logInfo 'Checking state of the vmdird service'
if ! checkService 'vmdird'; then
logError 'The vmdird service is not running'
echo $'\n'"${YELLOW}The VMware Directory Service is not running!"
echo "The script cannot continue. Exiting...${NORMAL}"
stopLoading
exit
else
VMDIR_STATE=$(echo 6 | /usr/lib/vmware-vmdir/bin/vdcadmintool 2>/dev/null | awk -F ' - ' '{print $NF}' | tr -d '\n')
fi
logInfo "The vmdird service is running and in the following state: $VMDIR_STATE"
fi
}
#------------------------------
# Check if PSC is configured to be behind a load balancer
#------------------------------
function checkPSCHA() {
if [ $NODE_TYPE = 'infrastructure' ]; then
PSC_LB=$(grep proxyName /usr/lib/vmware-sso/vmware-sts/conf/server.xml | sed 's/ /\n/g' | grep proxyName | awk -F'=' '{print $NF}' | tr -d '"')
fi
}
#------------------------------
# Notice for additional steps with PSC HA
#------------------------------
function noticePSCHA() {
if [ $NODE_TYPE = 'infrastructure' ] && [ -n "$PSC_LB" ]; then
cat << EOF
${YELLOW}-------------------------!!! WARNING !!!-------------------------
This PSC has been detected to be in an HA configuration.
- The new certificate and private key should be installed on all other
PSCs configured behind the load balancer.
- If the load balancer is configured for SSL termination, it will need
the new Machine SSL certificate and private key.
- If the load balancer is configured for SSL passthrough, no additional
configuration should be necessary.${NORMAL}
EOF
fi
}
#------------------------------
# Check if service is running
#------------------------------
function checkService() {
VMON_SERVICE_LIST=$($VMON_CLI -l)
if echo "$VMON_SERVICE_LIST" | grep -q 'Connect error'; then
if service-control --status $1 | grep -q -i stopped; then
return 1
else
return 0
fi
else
if $VMON_CLI -l | grep -q $1; then
if $VMON_CLI -s $1 | grep 'RunState' | grep -q 'STARTED'; then
return 0
else
return 1
fi
else
if service-control --status $1 | grep -q -i stopped; then
return 1
else
return 0
fi
fi
fi
}
#------------------------------
# Check if machine account can connect to VMware Directory
#------------------------------
function checkVmdirMachineCredentials() {
logInfo "Checking credentials for machine account $VMDIR_MACHINE_ACCOUNT_DN"
if ! $LDAP_SEARCH -LLL -h $PSC_LOCATION -p $VMDIR_PORT -b "ou=Domain Controllers,$VMDIR_DOMAIN_DN" -D "$VMDIR_MACHINE_ACCOUNT_DN" -y $STAGE_DIR/.machine-account-password dn > /dev/null 2>&1; then
LDAP_ERROR="$?"
echo $'\n'"${YELLOW}The machine account $VMDIR_MACHINE_ACCOUNT_DN"
echo "was unable to authenticate to the VMware Directory instance at $PSC_LOCATION:$VMDIR_PORT"
echo "LDAP error: $LDAP_ERROR"
echo "The script cannot continue. Exiting...${NORMAL}"
logError "Credentials for machine account $VMDIR_MACHINE_ACCOUNT_DN could not be verified (LDAP error: $LDAP_ERROR)"
stopLoading
exit
fi
logInfo "Credentials for machine account $VMDIR_MACHINE_ACCOUNT_DN verified"
}
#------------------------------
# Check if machine account has proper CA permissions
#------------------------------
function checkCAPermissions() {
logInfo "Machine account DN: $VMDIR_MACHINE_ACCOUNT_DN"
logInfo "PSC location: $PSC_LOCATION"
if [ $NODE_TYPE != 'management' ]; then
DCADMINS=$($LDAP_SEARCH -o ldif-wrap=no -LLL -h $PSC_LOCATION -p $VMDIR_PORT -b "cn=DCAdmins,cn=BuiltIn,$VMDIR_DOMAIN_DN" -D "$VMDIR_MACHINE_ACCOUNT_DN" -y $STAGE_DIR/.machine-account-password member | sed -e 's/^ //g' | tr -d '\n' | sed -e 's/member:/\n&/g')
logInfo 'Checking DCAdmins membership:'
logDetails "$DCADMINS"
if echo "$DCADMINS" | grep -iq "$VMDIR_MACHINE_ACCOUNT_DN"; then
CAADMINS=$($LDAP_SEARCH -o ldif-wrap=no -LLL -h $PSC_LOCATION -p $VMDIR_PORT -b "cn=CAAdmins,cn=BuiltIn,$VMDIR_DOMAIN_DN" -D "$VMDIR_MACHINE_ACCOUNT_DN" -y $STAGE_DIR/.machine-account-password member | sed -e 's/^ //g' | tr -d '\n' | sed -e 's/member:/\n&/g')
if echo "$CAADMINS" | grep -iq "cn=DCAdmins,cn=BuiltIn,$VMDIR_DOMAIN_DN"; then
return 0
else
echo $'\n'"${YELLOW}The DCAdmins SSO group is not a member of the CAAdmins SSO group!"
echo "The script cannot continue. Exiting...${NORMAL}"
logError 'The DCAdmins SSO group is not a member of the CAAdmins SSO group'
stopLoading
exit
fi
else
echo $'\n'"${YELLOW}The machine account is not a member of the DCAdmins SSO group!"
echo "The script cannot continue. Exiting...${NORMAL}"
logError 'The machine account is not a member of the DCAdmins SSO group'
stopLoading
exit
fi
else
DCCLIENTS=$($LDAP_SEARCH -o ldif-wrap=no -LLL -h $PSC_LOCATION -p $VMDIR_PORT -b "cn=DCClients,cn=BuiltIn,$VMDIR_DOMAIN_DN" -D "$VMDIR_MACHINE_ACCOUNT_DN" -y $STAGE_DIR/.machine-account-password member | sed -e 's/^ //g' | tr -d '\n' | sed -e 's/member:/\n&/g')
logInfo 'Checking DCClients membership:'
logDetails "$DCCLIENTS"
if echo "$DCCLIENTS" | grep -iq "$VMDIR_MACHINE_ACCOUNT_DN"; then
CAADMINS=$($LDAP_SEARCH -o ldif-wrap=no -LLL -h $PSC_LOCATION -p $VMDIR_PORT -b "cn=CAAdmins,cn=BuiltIn,$VMDIR_DOMAIN_DN" -D "$VMDIR_MACHINE_ACCOUNT_DN" -y $STAGE_DIR/.machine-account-password member | sed -e 's/^ //g' | tr -d '\n' | sed -e 's/member:/\n&/g')
if echo "$CAADMINS" | grep -iq "cn=DCClients,cn=BuiltIn,$VMDIR_DOMAIN_DN"; then
return 0
else
echo $'\n'"${YELLOW}The DCAdmins SSO group is not a member of the CAAdmins SSO group!"
echo "The script cannot continue. Exiting...${NORMAL}"
logError 'The DCAdmins SSO group is not a member of the CAAdmins SSO group'
stopLoading
exit
fi
else
echo $'\n'"${YELLOW}The machine account is not a member of the DCClients SSO group!"
echo "The script cannot continue. Exiting...${NORMAL}"
logError 'The machine account is not a member of the DCAdmins SSO group'
stopLoading
exit
fi
fi
}
#------------------------------
# Set the Solution Users for this node
#------------------------------
function setSolutionUsers() {
SOLUTION_USERS=('machine' 'vsphere-webclient')
if [ $NODE_TYPE != 'infrastructure' ]; then
SOLUTION_USERS+=('vpxd' 'vpxd-extension')
if [[ "$VC_VERSION" =~ ^[78] ]]; then
SOLUTION_USERS+=('hvc' 'wcp')
fi
fi
logInfo "Setting Solution Users: ${SOLUTION_USERS[*]}"
}
#------------------------------
# Set the VECS Stores and default permissions for this node
#------------------------------
function setVECSStores() {
VECS_STORES='MACHINE_SSL_CERT TRUSTED_ROOTS TRUSTED_ROOT_CRLS machine vsphere-webclient'
declare -gA VECS_STORE_READ_PERMISSIONS=()
declare -gA VECS_STORE_WRITE_PERMISSIONS=()
if [ $NODE_TYPE == 'infrastructure' ]; then
VECS_STORE_READ_PERMISSIONS[MACHINE_SSL_CERT]=''
VECS_STORE_READ_PERMISSIONS[TRUSTED_ROOTS]='EVERYONE'
VECS_STORE_READ_PERMISSIONS[TRUSTED_ROOT_CRLS]='EVERYONE'
VECS_STORE_READ_PERMISSIONS[machine]='cm'
VECS_STORE_READ_PERMISSIONS[vsphere-webclient]='vapiEndpoint'
else
VECS_STORES+=' vpxd vpxd-extension SMS'
VECS_STORE_READ_PERMISSIONS[MACHINE_SSL_CERT]='updatemgr vsphere-ui vpxd vpostgres vsphere-client vsm'
VECS_STORE_READ_PERMISSIONS[TRUSTED_ROOTS]='EVERYONE vpxd'
VECS_STORE_READ_PERMISSIONS[TRUSTED_ROOT_CRLS]='EVERYONE vpxd'
VECS_STORE_READ_PERMISSIONS[machine]='vpxd cm'
VECS_STORE_READ_PERMISSIONS[vsphere-webclient]='vsphere-ui vpxd perfcharts vapiEndpoint'
VECS_STORE_READ_PERMISSIONS[vpxd]='vpxd'
VECS_STORE_READ_PERMISSIONS[vpxd-extension]='deploy updatemgr vsphere-ui vpxd vsm imagebuilder content-library eam mbcs'
VECS_STORE_READ_PERMISSIONS[SMS]='deploy vpxd'
fi
case $VC_VERSION in
'6.5')
if [ $NODE_TYPE != 'infrastructure' ]; then
VECS_STORE_READ_PERMISSIONS[SMS]='vpxd'
VECS_STORE_READ_PERMISSIONS[vpxd-extension]+=' vsphere-client'
fi
;;
'6.7')
VECS_STORES+=' APPLMGMT_PASSWORD'
if [ $NODE_TYPE == 'infrastructure' ]; then
VECS_STORE_READ_PERMISSIONS[APPLMGMT_PASSWORD]=''
else
VECS_STORE_READ_PERMISSIONS[APPLMGMT_PASSWORD]='vpxd'
VECS_STORE_READ_PERMISSIONS[data-encipherment]='vpxd'
VECS_STORE_READ_PERMISSIONS[vpxd-extension]+=' vsphere-client'
fi
;;
'7.0')
VECS_STORES+=' APPLMGMT_PASSWORD data-encipherment hvc wcp'
VECS_STORE_READ_PERMISSIONS[MACHINE_SSL_CERT]='updatemgr vsphere-ui vpxd vpostgres vsm'
VECS_STORE_READ_PERMISSIONS[machine]='vpxd vsan-health'
VECS_STORE_READ_PERMISSIONS[hvc]='vpxd'
if [ $VC_BUILD -ge 19480866 ]; then
VECS_STORE_READ_PERMISSIONS[vpxd-extension]='vlcm wcp deploy updatemgr vsphere-ui vpxd vsm vsan-health imagebuilder content-library eam vstatsuser'
VECS_STORE_READ_PERMISSIONS[wcp]='wcp vpxd content-library'
else
VECS_STORE_READ_PERMISSIONS[vpxd-extension]='vlcm deploy updatemgr vsphere-ui vpxd vsm imagebuilder content-library eam vstatsuser'
VECS_STORE_READ_PERMISSIONS[wcp]='vpxd content-library'
fi
if [ $VC_BUILD -ge 20051473 ]; then
VECS_STORE_WRITE_PERMISSIONS[TRUSTED_ROOTS]='sps'
VECS_STORE_READ_PERMISSIONS[machine]+=' observability'
VECS_STORE_WRITE_PERMISSIONS[machine]='infraprofile certauth certmgr'
VECS_STORE_READ_PERMISSIONS[vsphere-webclient]+=' analytics'
VECS_STORE_WRITE_PERMISSIONS[vsphere-webclient]='infraprofile'
VECS_STORE_WRITE_PERMISSIONS[vpxd-extension]='infraprofile sps'
VECS_STORE_READ_PERMISSIONS[vpxd-extension]+=' analytics'
VECS_STORE_WRITE_PERMISSIONS[SMS]='sps'
fi
VECS_STORE_READ_PERMISSIONS[APPLMGMT_PASSWORD]='vpxd'
VECS_STORE_READ_PERMISSIONS[data-encipherment]='vpxd'
;;
'8.0')
VECS_STORES+=' APPLMGMT_PASSWORD data-encipherment hvc wcp'
VECS_STORE_READ_PERMISSIONS[MACHINE_SSL_CERT]='lighttpd updatemgr vlcm vpostgres vpxd vsan-health vsm vsphere-ui'
VECS_STORE_WRITE_PERMISSIONS[MACHINE_SSL_CERT]='rhttpproxy'
VECS_STORE_READ_PERMISSIONS[machine]='observability sca statsmon vpxd vsan-health'
VECS_STORE_WRITE_PERMISSIONS[machine]='certauth certmgr infraprofile'
VECS_STORE_READ_PERMISSIONS[vpxd]='vpxd vsan-health'
VECS_STORE_WRITE_PERMISSIONS[vpxd]=''
VECS_STORE_READ_PERMISSIONS[vpxd-extension]='analytics content-library deploy eam imagebuilder updatemgr vlcm vpxd vsan-health vsm vsphere-ui vstatsuser wcp'
VECS_STORE_WRITE_PERMISSIONS[vpxd-extension]='infraprofile sps'
VECS_STORE_READ_PERMISSIONS[vsphere-webclient]='analytics perfcharts vapiEndpoint vpxd vsphere-ui'
VECS_STORE_WRITE_PERMISSIONS[vsphere-webclient]='infraprofile'
VECS_STORE_READ_PERMISSIONS[hvc]='vpxd'
VECS_STORE_WRITE_PERMISSIONS[hvc]=''
VECS_STORE_READ_PERMISSIONS[wcp]='content-library wcp'
VECS_STORE_WRITE_PERMISSIONS[wcp]=''
VECS_STORE_READ_PERMISSIONS[data-encipherment]='vpxd'
VECS_STORE_WRITE_PERMISSIONS[data-encipherment]=''
VECS_STORE_READ_PERMISSIONS[SMS]='deploy'
VECS_STORE_WRITE_PERMISSIONS[SMS]=''
case $VC_BUILD in
20519528)
VECS_STORE_WRITE_PERMISSIONS[machine]='certauth certmgr infraprofile sts'
;;&
21815093|22617221|23319993|23504390|24305161|24321653)
VECS_STORE_READ_PERMISSIONS[MACHINE_SSL_CERT]='updatemgr vlcm vpostgres vpxd vsan-health vsm vsphere-ui'
;;&
22385739|22617221|23319993|24321653)
VECS_STORE_READ_PERMISSIONS[vpxd-extension]='analytics content-library eam imagebuilder updatemgr vlcm vpxd vsan-health vsm vsphere-ui vstatsuser wcp'
;;&
22385739|22617221|23319993|23504390|23929136|24022515|24091160|24262322|24305161|24321653|24322831)
VECS_STORE_READ_PERMISSIONS[machine]='observability sca vpxd vsan-health'
;;&
23504390)
VECS_STORE_READ_PERMISSIONS[vpxd-extension]='analytics eam updatemgr vlcm vpxd vsan-health vsm vsphere-ui'
;;&
23929136)
VECS_STORE_READ_PERMISSIONS[vpxd-extension]='analytics content-library eam imagebuilder updatemgr vlcm vpxd vsan-health vsm vsphere-ui vstatsuser wcp'
VECS_STORE_READ_PERMISSIONS[wcp]='content-library vpxd wcp'
VECS_STORE_READ_PERMISSIONS[SMS]='deploy vpxd'
;;&
24022515|24091160|24262322|24305161|24322831)
VECS_STORE_READ_PERMISSIONS[vpxd-extension]='analytics content-library eam imagebuilder sps updatemgr vlcm vpxd vsan-health vsm vsphere-ui vstatsuser wcp'
VECS_STORE_WRITE_PERMISSIONS[vpxd-extension]='infraprofile'
;;
esac
;;
esac
}
#------------------------------
# Check if vCenter is managed by SDDC Manager
#------------------------------
function checkForVCF() {
SDDC_MANAGER=$($LDAP_SEARCH -LLL -h $PSC_LOCATION -b "cn=$SSO_DOMAIN,cn=Tenants,cn=IdentityManager,cn=Services,$VMDIR_DOMAIN_DN" -D "$VMDIR_MACHINE_ACCOUNT_DN" -y $STAGE_DIR/.machine-account-password '(objectclass=vmwSTSTenant)' vmwSTSLogonBanner | tr -d '\n' | awk -F'::' '{print $NF}' | tr -d ' ' | base64 -d 2>/dev/null | grep 'SDDC Manager' | awk -F '[()]' '{print $2}' | grep -v '^$')
}
#------------------------------
# Print warning about VCHA on the main operation menu
#------------------------------
function operationMenuSDDCWarning() {
cat << EOF
${YELLOW}-------------------------!!! WARNING !!!-------------------------
This vCenter is managed by the following SDDC Manager:
$SDDC_MANAGER
Updating certificates may require adding new
CA certificates to the SDDC Manager keystore.
See https://knowledge.broadcom.com/external/article/316056/how-to-adddelete-custom-ca-certificates.html for details.$NORMAL
EOF
}
#------------------------------
# Get access token for running API calls to SDDC Manager
#------------------------------
function getSDDCAccessToken() {
authenticateIfNeeded
task 'Get API access token'
SDDC_API_ACCESS_TOKEN_RESPONSE=$(curl -i -k -X POST https://$SDDC_MANAGER/v1/tokens -H 'Content-Type: application/json' -H 'Accept: application/json' -d "{'username' : '$VMDIR_USER_UPN', 'password' : '$(cat $STAGE_DIR/.vmdir-user-password)'}" 2>&1)
if echo "$SDDC_API_ACCESS_TOKEN_RESPONSE" | grep -q 'accessToken'; then
SDDC_API_ACCESS_TOKEN=$(echo "$SDDC_API_ACCESS_TOKEN_RESPONSE" | grep '^{' | jq . | grep accessToken | awk '{print $NF}' | tr -d '",')
statusMessage 'OK' 'GREEN'
else
errorMessage 'Unable to get access token from the SDDC Manager'
fi
}
#------------------------------
# Add new CA certificates to SDDC Manager via API
#------------------------------
function publishCACertsSDDCManager() {
CA_CERT_STRING=$(cat $1 | awk '{printf "%s\\n", $0}' | sed -e 's/[\\n]*$//g')
task 'Publish CA cert for outbound connections'
logDebug "CA JSON string: $CA_CERT_STRING"
if [ -n "$SDDC_API_ACCESS_TOKEN" ]; then
SDDC_API_PUBLISH_CA_OUTBOUND_RESPONSE=$(curl -i -k -X POST https://$SDDC_MANAGER/v1/sddc-manager/trusted-certificates -H "Authorization: Bearer $SDDC_API_ACCESS_TOKEN" -H 'Content-Type: application/json' -H 'Accept: application/json' -d "{'certificate':'$CA_CERT_STRING','certificateUsageType':'TRUSTED_FOR_OUTBOUND'}" 2>&1)
if echo "$SDDC_API_PUBLISH_CA_OUTBOUND_RESPONSE" | grep '^HTTP' | grep -q '200' || echo "$SDDC_API_PUBLISH_CA_OUTBOUND_RESPONSE" | grep -q 'CERTIFICATE_CHAIN_EXISTS_IN_TRUST_STORE'; then
statusMessage 'OK' 'GREEN'
else
logInfo 'Publish CA to SDDC Manager response (outbound trust):'
logDetails "$SDDC_API_PUBLISH_CA_OUTBOUND_RESPONSE"
errorMessage 'Unable to publish CA certificate to SDDC Manager'
fi
if ([[ "$VC_VERSION" =~ ^[7] ]] && [ $VC_BUILD -ge 17327517 ]) && ([[ "$VC_VERSION" =~ ^[7] ]] && [ $VC_BUILD -le 19234570 ]); then
task 'Publish CA cert for inbound connections'
SDDC_API_PUBLISH_CA_INBOUND_RESPONSE=$(curl -i -k -X POST https://$SDDC_MANAGER/v1/sddc-manager/trusted-certificates -H "Authorization: Bearer $SDDC_API_ACCESS_TOKEN" -H 'Content-Type: application/json' -H 'Accept: application/json' -d "{'certificate':'$CA_CERT_STRING','certificateUsageType':'TRUSTED_FOR_INBOUND'}" 2>&1)
if echo "$SDDC_API_PUBLISH_CA_INBOUND_RESPONSE" | grep '^HTTP' | grep -q '200' || echo "$SDDC_API_PUBLISH_CA_INBOUND_RESPONSE" | grep -q 'CERTIFICATE_CHAIN_EXISTS_IN_TRUST_STORE'; then
statusMessage 'OK' 'GREEN'
else
logInfo 'Publish CA to SDDC Manager response (inbound trust):'
logDetails "$SDDC_API_PUBLISH_CA_INBOUND_RESPONSE"
errorMessage 'Unable to publish CA certificate to SDDC Manager'
fi
fi
else
errorMessage 'No API access token found'
fi
}
#------------------------------
# Add new CA certificates to SDDC Manager via API
#------------------------------
function publishMachineSSLCACertsSDDCManager() {
rm $STAGE_DIR/sddc-ca-*.crt 2>/dev/null
header 'Publishing CA certificates to SDDC Manager'
getSDDCAccessToken
csplit -s -z -f $STAGE_DIR/sddc-ca- -b %02d.crt $TRUSTED_ROOT_CHAIN '/-----BEGIN CERTIFICATE-----/' '{*}' 2>&1 | logDetails
for cert in $STAGE_DIR/sddc-ca-*.crt; do
publishCACertsSDDCManager $cert
done
echo $'\n'"${YELLOW}Services may need to be restarted on the SDDC Manager"
echo "by running /opt/vmware/vcf/operationsmanager/scripts/cli/sddcmanager_restart_services.sh${NORMAL}"
}
#------------------------------
# Print the operation menu
#------------------------------
function operationMenu() {
UPDATED_MACHINE_SSL=0
UPDATED_TRUST_ANCHORS=0
header "vCenter $VC_VERSION Certificate Management Utility ($VERSION)"
logInfo 'Printing Main Menu'
cat << EOF
1. Check current certificates status
2. View certificate info
3. Manage certificates
4. Manage SSL trust anchors
5. Check configurations
6. Reset all certificates with VMCA-signed certificates
7. ESXi certificate operations
8. Restart services
9. Generate certificate report
EOF
if isVCHAConfigured; then echo ' I. vCenter High Availability information'; fi
echo ' E. Exit'
echo ''
if isVCHAConfigured; then
operationMenuVCHAWarning
fi
if [ -n "$SDDC_MANAGER" ]; then
operationMenuSDDCWarning
fi
if [ $NODE_TYPE != 'management' ] && [ "$VMDIR_STATE" != 'Normal' ] && [ "$VMDIR_STATE" != 'Standalone' ]; then
echo "${YELLOW}The VMware Directory service is not in NORMAL mode ($VMDIR_STATE)!"
echo 'Certificate operations should not be actioned until this service'
echo "is running correctly in a NORMAL state.${NORMAL}"
exit
else
if [ "$NODE_TYPE" != 'infrastructure' ] && ! checkService 'vmware-vpostgres'; then
echo "${YELLOW}The vPostgres service is stopped!"
echo "Many certificate operations require changes to the vCenter database."
echo "Please ensure this service is running before replacing any certificates."
echo "Hint: Check the number of CRL entries in VECS${NORMAL}"
echo ''
fi
read -p 'Select an option [1]: ' OPERATION
if [ -z $OPERATION ]; then OPERATION=1; fi
logInfo "User selected option '$OPERATION'"
fi
}
#------------------------------
# Check if VCHA is configured
#------------------------------
function isVCHAConfigured() {
if grep -q 'HACore' /storage/vmware-vmon/defaultStartProfile; then
VMON_SERVICE_PROFILE='--vmon-profile HAActive'
return 0
else
VMON_SERVICE_PROFILE='--all'
return 1
fi
}
#------------------------------
# Get current VCHA mode
#------------------------------
function getVCHAMode() {
authenticateIfNeeded
VCHA_MODE='UNKNOWN'
SESSION_HEADER=$(curl -k -i -u "$VMDIR_USER_UPN:$(cat $STAGE_DIR/.vmdir-user-password)" -X POST -c $STAGE_DIR/session-info.txt https://localhost/rest/com/vmware/cis/session 2>/dev/null)
if echo "$SESSION_HEADER" | grep '^HTTP' | grep -q '200'; then
if [[ "$VC_VERSION" =~ ^6 ]]; then
VCHA_MODE_INFO=$(curl -k -b $STAGE_DIR/session-info.txt https://localhost/rest/vcenter/vcha/cluster/mode 2>/dev/null | python -m json.tool --sort-keys)
else
VCHA_MODE_INFO=$(curl -k -b $STAGE_DIR/session-info.txt https://localhost/rest/vcenter/vcha/cluster/mode 2>/dev/null | jq .)
fi
logDebug "VCHA Mode API call: $VCHA_MODE_INFO"
VCHA_MODE=$(echo "$VCHA_MODE_INFO" | grep 'mode' | awk '{print $NF}' | tr -d '"')
fi
logInfo "VCHA Mode: $VCHA_MODE"
}
#------------------------------
# Print warning about VCHA on the main operation menu
#------------------------------
function operationMenuVCHAWarning() {
echo "${YELLOW}-------------------------!!! WARNING !!!-------------------------"
printf 'vCenter High Availability has been configured,'
if service-control --status vmware-vcha | grep -i stopped; then
printf " but the\nservice is currently stopped. "
else
printf " and the\nservice is currently running. "
fi
printf "\n\n%s\n%s\n\n" "Restarting services may trigger a failover." "For more information, select option 'I' from the menu.${NORMAL}"
}
#------------------------------
# Print VCHA information
#------------------------------
function VCHAInfo() {
if [ $NODE_TYPE != 'infrastructure' ]; then
getVCHAMode
cat << EOF
${YELLOW}The supported methods of replacing SSL certificates with
vCenter High Availability configured are:
1. Place VCHA into Maintenance Mode so restarting
services does not trigger an automatic failover, or
2. Destroy the VCHA cluster, replace the SSL certificate(s),
and re-create the VCHA cluster
EOF
case $VCHA_MODE in
'MAINTENANCE')
cat << EOF
The VCHA cluster is in Maintenance Mode, so you should be able
to proceed with the certificate replacement.${NORMAL}
EOF
if checkService 'vpxd'; then
read -p 'Place VCHA cluster into Enabled Mode? [n]: ' VCHA_SET_MM_INPUT
if [[ "$VCHA_SET_MM_INPUT" =~ ^[Yy] ]]; then
header 'vCenter High Availability Mode'
task 'Put VCHA cluster into Enabled Mode'
VCHA_MM_API=$(curl -k -i -b $STAGE_DIR/session-info.txt -H 'Content-Type: application/json' -X PUT https://localhost/rest/vcenter/vcha/cluster/mode?vmw-task=true -d '{"mode":"ENABLED"}' 2>/dev/null)
logDebug "$VCHA_MM_API"
if echo "$VCHA_MM_API" | grep '^HTTP' | grep -q '200'; then
statusMessage 'OK' 'GREEN'
else
errorMessage 'Unable to place VCHA cluster into Enabled Mode'
fi
fi
fi
;;
'ENABLED')
cat << EOF
The VCHA cluster is in Enabled Mode, so restarting
services will trigger a failover to the Passive Node.
It is recommended to place the VCHA cluster into
Maintenance Mode before performing operations on any
SSL certificates.${NORMAL}
EOF
if checkService 'vpxd'; then
read -p 'Place VCHA cluster into Maintenance Mode? [n]: ' VCHA_SET_MM_INPUT
if [[ "$VCHA_SET_MM_INPUT" =~ ^[Yy] ]]; then
header 'vCenter High Availability Mode'
task 'Put VCHA cluster into Maintenance Mode'
VCHA_MM_API=$(curl -k -i -b $STAGE_DIR/session-info.txt -H 'Content-Type: application/json' -X PUT https://localhost/rest/vcenter/vcha/cluster/mode?vmw-task=true -d '{"mode":"MAINTENANCE"}' 2>/dev/null)
logDebug "$VCHA_MM_API"
if echo "$VCHA_MM_API" | grep '^HTTP' | grep -q '200'; then
statusMessage 'OK' 'GREEN'
else
errorMessage 'Unable to place VCHA cluster into Maintenance Mode'
fi
fi
fi
;;
'UNKNOWN')
cat << EOF
The state of the VCHA cluster cannot be determined
via the REST API. It is recommended to destroy the
VCHA cluster before performing operations on any
SSL certificates.${NORMAL}
EOF
;;
esac
else
printf "\n%s\n\n" "${YELLOW}Invalid operation${NORMAL}"
fi
}
#------------------------------
# Process the operation selected by user
#------------------------------
function processOperationMenu() {
setTimestamp
if [[ $OPERATION =~ ^[Ee] ]]; then
cleanup
exit
fi
if [[ $OPERATION =~ ^[Ii] ]]; then
VCHAInfo
elif [[ "$OPERATION" =~ ^[0-9]+$ ]]; then
echo ''
case $OPERATION in
1)
checkCerts
;;
2)
viewCertificateMenu
;;
3)
manageCertificateMenu
;;
4)
manageSSLTrustAnchors
;;
5)
checkConfigurationMenu
;;
6)
resetAllCertificates
;;
7)
manageESXiCertificates
;;
8)
restartServicesMenu
;;
9)
generatevCenterCertificateReport
;;
*)
echo $'\n'"${YELLOW}Invalid operation${NORMAL}"
;;
esac
else
echo $'\n'"${YELLOW}Invalid operation${NORMAL}"
fi
operationMenu
processOperationMenu
}
#------------------------------
# Perform quick check of certificates
#------------------------------
function checkCerts() {
authenticateIfNeeded
resetCertStatusChecks
exportTrustedCACerts
header 'Checking Certificate Status'
task 'Checking Machine SSL certificate'
checkVECSCert 'MACHINE_SSL_CERT' '__MACHINE_CERT'
if checkMachineSSLCSR; then
task 'Checking Machine SSL CSR'
checkVECSCert 'MACHINE_SSL_CERT' '__MACHINE_CSR'
fi
echo 'Checking Solution User certificates:'
for soluser in "${SOLUTION_USERS[@]}"; do
task " $soluser"
checkVECSCert "$soluser" "$soluser"
done
if [ $NODE_TYPE != 'infrastructure' ]; then
task 'Checking SMS self-signed certificate'
checkVECSCert 'SMS' 'sms_self_signed'
if [[ "$VC_VERSION" =~ ^8 ]] && [ $VC_BUILD -ge 22385739 ]; then
task 'Checking SMS VMCA-signed certificate'
checkVECSCert 'SMS' 'sps-extension'
fi
if [ "$VC_VERSION" != '6.5' ]; then
task 'Checking data-encipherment certificate'
checkVECSCert 'data-encipherment' 'data-encipherment'
fi
task 'Checking Authentication Proxy certificate'
checkFilesystemCert '/var/lib/vmware/vmcam/ssl/vmcamcert.pem'
task 'Checking Auto Deploy CA certificate'
checkFilesystemCert '/etc/vmware-rbd/ssl/rbd-ca.crt'
fi
if checkVECSStore 'BACKUP_STORE'; then
echo 'Checking BACKUP_STORE entries:'
for alias in $($VECS_CLI entry list --store BACKUP_STORE | grep Alias | awk '{print $NF}'); do
task " $alias"
checkVECSCert 'BACKUP_STORE' $alias
done
fi
if checkVECSStore 'BACKUP_STORE_H5C'; then
echo 'Checking BACKUP_STORE_H5C entries:'
for alias in $($VECS_CLI entry list --store BACKUP_STORE_H5C | grep Alias | awk '{print $NF}'); do
task " $alias"
checkVECSCert 'BACKUP_STORE_H5C' $alias
done
fi
if checkVECSStore 'STS_INTERNAL_SSL_CERT'; then
task 'Checking legacy Lookup Service certificate'
checkVECSCert 'STS_INTERNAL_SSL_CERT' '__MACHINE_CERT'
fi
if [ $NODE_TYPE != 'management' ]; then
if [ -f '/usr/lib/vmware-vmdir/share/config/vmdircert.pem' ]; then
task 'Checking VMDir certificate'
checkFilesystemCert '/usr/lib/vmware-vmdir/share/config/vmdircert.pem'
fi
task 'Checking VMCA certificate'
checkFilesystemCert "$VMCA_CERT"
header 'Checking STS Signing Certs & Signing Chains'
manageSTSTenantCerts 'Check'
fi
checkCACertificates
if [ "$VC_VERSION" != '6.5' ]; then checkVMCACertsSSO; fi
checkSMSVASACerts
quickCheckVECSStores
quickCheckServicePrincipals
checkCRLs
manageCACCerts 'Check'
manageLDAPSCerts 'Check'
manageTanzuSupervisorClusterCerts 'Check'
quickCheckSSLTrustAnchors
if [ $NODE_TYPE != 'infrastructure' ]; then
manageVCExtensionThumbprints 'Checking'
checkAutoDeployDB
checkVMCADatabaseConfig
fi
if [ $NODE_TYPE != 'management' ]; then
quickCheckSTSConfig
fi
buildCertificateStatusMessage
if [ -n "$CERT_STATUS_MESSAGE" ]; then
echo $'\n'"${YELLOW}------------------------!!! Attention !!!------------------------ "
echo "$CERT_STATUS_MESSAGE${NORMAL}"
fi
}
#------------------------------
# Resets the certificate status flags
#------------------------------
function resetCertStatusChecks() {
CERT_STATUS_MESSAGE=''
CERT_STATUS_EXPIRES_SOON=0
CERT_STATUS_MISSING_PNID=0
CERT_STATUS_MISSING_SAN=0
CERT_STATUS_KEY_USAGE=0
CERT_STATUS_EXPIRED=0
CERT_STATUS_NON_CA=0
CERT_STATUS_BAD_ALIAS=0
CERT_STATUS_SHA1_SIGNING=0
CERT_STATUS_MISSING=0
CERT_STATUS_MISSING_VMDIR=0
CERT_STATUS_MISMATCH_SERVICE_PRINCIPAL=0
CERT_STATUS_TOO_MANY_CRLS=0
CERT_STATUS_MISSING_CA=0
CERT_STATUS_EXPIRED_EMBEDDED_CA=0
CERT_STATUS_STORE_MISSING=0
CERT_STATUS_STORE_PERMISSIONS=0
CERT_STATUS_SERVICE_PRINCIPAL_MISSING=0
CERT_STATUS_VMCA_EMPTY_CONFIG=0
CERT_STATUS_VMCA_MODE=0
CERT_STATUS_VMCA_UNRETRIEVABLE=0
CERT_STATUS_VMCA_MISSING=0
CERT_STATUS_CLIENT_CA_LIST_FILE_LOCATION=0
CERT_STATUS_CLIENT_CA_LIST_FILE_MISSING=0
CERT_STATUS_STS_VECS_CONFIG=0
CERT_STATUS_STS_CONNECTION_STRINGS=0
CERT_STATUS_UNSUPPORTED_SIGNATURE_ALGORITHM=0
CERT_STATUS_CA_MISSING_SKID=0
CERT_ROGUE_CA=0
}
#------------------------------
# Export CA certs from VMDir
#------------------------------
function exportTrustedCACerts() {
rm $TRUSTED_CA_DIR/* 2>/dev/null
for skid in $($DIR_CLI trustedcert list --login $VMDIR_USER_UPN --password "$(cat $STAGE_DIR/.vmdir-user-password)" | grep '^CN' | awk '{print $NF}'); do
$DIR_CLI trustedcert get --id $skid --outcert $TRUSTED_CA_DIR/$skid.crt --login $VMDIR_USER_UPN --password "$(cat $STAGE_DIR/.vmdir-user-password)" 2>&1 | logInfo
done
}
#------------------------------
# Checks on certificates in VECS
#------------------------------
function checkVECSCert() {
KU_LIST='Digital Signature Key Encipherment Key Agreement Data Encipherment Non Repudiation'
case $1 in
'MACHINE_SSL_CERT')
CHECK_PNID=1
CHECK_KU=1
CHECK_SAN=1
CHECK_SERVICE_PRINCIPAL=0
CHECK_CA_CHAIN=1
CHECK_ROGUE_CA=1
CHECK_EMBEDDED_CHAIN=1
;;
SMS)
CHECK_PNID=0
CHECK_KU=0
CHECK_SAN=0
CHECK_SERVICE_PRINCIPAL=0
CHECK_CA_CHAIN=0
CHECK_ROGUE_CA=0
CHECK_EMBEDDED_CHAIN=0
;;
*)
CHECK_PNID=0
CHECK_KU=1
CHECK_SAN=1
CHECK_CA_CHAIN=1
CHECK_ROGUE_CA=1
CHECK_EMBEDDED_CHAIN=1
CHECK_SERVICE_PRINCIPAL=0
if [[ " ${SOLUTION_USERS[*]} " =~ " $1 " ]]; then CHECK_SERVICE_PRINCIPAL=1; fi
if [ "$1" == 'wcp' ]; then CHECK_SAN=0; fi
;;
esac
logInfo "Checking VECS for store '$2'"
if ! $VECS_CLI entry list --store $1 | grep Alias | grep $2 > /dev/null 2>&1; then
CERT_STATUS_MISSING=1
statusMessage 'NOT FOUND' 'RED'
logError "Store '$2' not found"
return 1
else
logInfo "Found Store '$2'"
fi
TEMP_CERT=$($VECS_CLI entry getcert --store $1 --alias $2 2>/dev/null)
if [ -z "$TEMP_CERT" ]; then
statusMessage 'PROBLEM' 'RED'
logError "No certificate found for alias '$2' in store '$1'"
return 1
fi
if ! isExpired "$TEMP_CERT" 'hash'; then
DAYS_LEFT=$(checkCertExpireSoon "$TEMP_CERT")
if [[ $DAYS_LEFT -ge 0 ]]; then
CERT_STATUS_EXPIRES_SOON=1
statusMessage "$DAYS_LEFT DAYS" 'YELLOW'
logInfo "Certificate for alias '$2' in store '$1' expires in $DAYS_LEFT days"
return 0
else
if [ $CHECK_PNID = 1 ]; then
if ! echo "$TEMP_CERT" | openssl x509 -noout -text 2>&1 | grep -A1 'Subject Alternative Name' | grep -iq "$PNID"; then
CERT_STATUS_MISSING_PNID=1
statusMessage 'NO PNID' 'YELLOW'
logInfo "Certificate for alias '$2' in store '$1' does not have the PNID ($PNID) in the Subject Alternative Name field"
return 0
fi
fi
if [ $CHECK_KU = 1 ]; then
if ! checkCertKeyUsage "$TEMP_CERT" "$1:$2" "$KU_LIST"; then
CERT_STATUS_KEY_USAGE=1
statusMessage 'KEY USAGE' 'YELLOW'
logInfo "Certificate for alias '$2' in store '$1' does not have the expected Key Usage Values"
return 0
fi
fi
if [ $CHECK_SAN = 1 ]; then
if ! echo "$TEMP_CERT" | openssl x509 -noout -text 2>&1 | grep -q 'Subject Alternative Name'; then
CERT_STATUS_MISSING_SAN=1
statusMessage 'NO SAN' 'YELLOW'
logInfo "Certificate for alias '$2' in store '$1' has no values in the Subject Alternative Name field"
return 0
fi
fi
if [ $CHECK_SERVICE_PRINCIPAL = 1 ]; then
if ! checkServicePrincipalCert "$1"; then
CERT_STATUS_MISMATCH_SERVICE_PRINCIPAL=1
statusMessage 'MISMATCH' 'YELLOW'
logError "The certificate in the VECS store '$1' does not match the certificate for the corresponding Service Principal in VMware Directory"
return 0
fi
fi
if [ $CHECK_CA_CHAIN = 1 ]; then
if ! checkCACertsPresent "$TEMP_CERT"; then
CERT_STATUS_MISSING_CA=1
statusMessage 'MISSING CA' 'YELLOW'
logError "One of the CA certificates in the signing chain for the certificate for alias '$2' in store '$1' is missing"
return 0
fi
fi
if [ $CHECK_ROGUE_CA = 1 ]; then
if checkRogueCA "$TEMP_CERT"; then
CERT_ROGUE_CA=1
statusMessage 'ROGUE' 'YELLOW'
logError "Cert in alias '$2' in store '$1' is invalid due to a CA extending past a parent CA pathlen restrictions"
return 0
fi
fi
if [ $CHECK_EMBEDDED_CHAIN = 1 ]; then
if ! checkEmbeddedChain "$TEMP_CERT"; then
CERT_STATUS_EXPIRED_EMBEDDED_CA=1
statusMessage 'EMBEDDED CA' 'YELLOW'
return 0
fi
fi
if ! checkCertSignatureAlgorithm "$TEMP_CERT"; then
CERT_STATUS_UNSUPPORTED_SIGNATURE_ALGORITHM=1
statusMessage 'ALGORITHM' 'YELLOW'
logInfo "Certificate for alias '$2' in store '$1' is signed with an unsupported Signature Algorithm"
return 0
fi
statusMessage 'VALID' 'GREEN'
return 0
fi
else
CERT_STATUS_EXPIRED=1
statusMessage 'EXPIRED' 'YELLOW'
logError "Certificate for alias '$2' in store '$1' is expired"
return 1
fi
}
#------------------------------
# Check for the existence of the __MACHINE_CSR alias in VECS
#------------------------------
function checkMachineSSLCSR() {
if $VECS_CLI entry list --store 'MACHINE_SSL_CERT' | grep Alias | grep '__MACHINE_CSR' > /dev/null 2>&1; then
return 0
else
return 1
fi
}
#------------------------------
# Check Solution User cert in VECS matches Service Principal
#------------------------------
function checkServicePrincipalCert() {
VECS_THUMBPRINT=$($VECS_CLI entry getcert --store $1 --alias $1 2>&1 | openssl x509 -noout -fingerprint -sha1 2>&1)
SERVICE_PRINCIPAL_HASH=$($LDAP_SEARCH -o ldif-wrap=no -LLL -h $PSC_LOCATION -p $VMDIR_PORT -b "cn=$1-$MACHINE_ID,cn=ServicePrincipals,$VMDIR_DOMAIN_DN" -D "cn=$VMDIR_USER,cn=users,$VMDIR_DOMAIN_DN" -y $STAGE_DIR/.vmdir-user-password userCertificate 2>&1 | grep '^userCertificate' | awk '{print $NF}')
SERVICE_PRINCIPAL_CERT=$(buildCertFromHash "$SERVICE_PRINCIPAL_HASH")
SERVICE_PRINCIPAL_THUMBPRINT=$(echo "$SERVICE_PRINCIPAL_CERT" | openssl x509 -noout -fingerprint -sha1 2>&1)
logInfo "Checking Service Principal: VECS Thumbprint: $VECS_THUMBPRINT"
logInfo "Checking Service Principal: Service Principal Thumbprint: $SERVICE_PRINCIPAL_THUMBPRINT"
if [ "$VECS_THUMBPRINT" = "$SERVICE_PRINCIPAL_THUMBPRINT" ]; then
return 0
else
return 1
fi
}
#------------------------------
# Check if certificate on the file system has expired
#------------------------------
function checkFilesystemCert() {
if [ ! -f $1 ]; then
CERT_STATUS_MISSING=1
statusMessage 'NOT FOUND' 'RED'
logError "Certificate at $1 could not be found"
return 1
fi
logInfo "Checking certificate at $1"
FS_CERT=$(cat $1)
checkCert "$FS_CERT"
}
#------------------------------
# Check if certificate has expired
#------------------------------
function checkCert() {
logInfo 'Checking the following certificate'
logDetails "$1"
logDebugDetails "'$(echo "$1" | openssl x509 -noout -text 2>/dev/null)'"
if ! isExpired "$1" 'hash'; then
DAYS_LEFT=$(checkCertExpireSoon "$1")
if [[ $DAYS_LEFT -gt 0 ]]; then
CERT_STATUS_EXPIRES_SOON=1
statusMessage "$DAYS_LEFT DAYS" 'YELLOW'
logInfo "Certificate expires in $DAYS_LEFT days"
return 0
else
if ! checkCertSignatureAlgorithm "$1"; then
CERT_STATUS_UNSUPPORTED_SIGNATURE_ALGORITHM=1
statusMessage 'ALGORITHM' 'YELLOW'
return 1
fi
if isCertCA "$1" && ! echo "$1" | openssl x509 -noout -text 2>/dev/null | grep -q 'Subject Key Identifier:'; then
if [[ "$VC_VERSION" =~ ^[67] ]] && ! echo "$1" | openssl x509 -noout -subject | grep -q 'Auto Deploy'; then
CERT_STATUS_CA_MISSING_SKID=1
statusMessage 'NO SKID' 'YELLOW'
return 1
fi
fi
statusMessage 'VALID' 'GREEN'
logInfo 'Certificate is valid'
return 0
fi
else
CERT_STATUS_EXPIRED=1
statusMessage 'EXPIRED' 'YELLOW'
logError 'Certificate is expired'
return 1
fi
}
#------------------------------
# Check if a certificate is expired
#------------------------------
function isExpired() {
if [ "$2" == 'file' ]; then
HASH=$(cat "$1")
else
HASH="$1"
fi
logInfo 'Checking expiration of the following certificate'
logDetails "$HASH"
if echo "$HASH" | openssl x509 -noout -checkend 0 > /dev/null 2>&1; then
return 1
else
return 0
fi
}
#------------------------------
# Backup certificate and key from filesystem
#------------------------------
function backupFilesystemCertKey() {
task 'Backing up certificate and private key'
if [ -f $1 ]; then
cp $1 $BACKUP_DIR/$3-$TIMESTAMP.crt 2>&1 | logDebug || errorMessage "Unable to backup $3 certificate"
else
statusMessage 'NOT FOUND' 'YELLOW'
logError "Certificate not found at $1"
fi
if [ -f $2 ]; then
cp $2 $BACKUP_DIR/$3-$TIMESTAMP.key 2>&1 | logDebug || errorMessage "Unable to backup $3 key"
else
statusMessage 'NOT FOUND' 'YELLOW'
logError "Private key not found at $2"
fi
statusMessage 'OK' 'GREEN'
logInfo "Certificate and key backed up to $BACKUP_DIR/$3-$TIMESTAMP.crt and $BACKUP_DIR/$3-$TIMESTAMP.key"
}
#------------------------------
# Check if cert has unsupported signature algorithms
#------------------------------
function checkCertSignatureAlgorithm() {
CERT_HASH=$1
CERT_SIGNATURE_ALGORITHM=$(echo "$CERT_HASH" | openssl x509 -noout -text | grep 'Signature Algorithm' | head -n1 | awk '{print $NF}')
logInfo "Checking certificate signature algorithm '$CERT_SIGNATURE_ALGORITHM' against unsupported signature algorithms ($UNSUPPORTED_SIGNATURE_ALGORITHMS)"
if echo "$CERT_SIGNATURE_ALGORITHM" | grep -iqE "$UNSUPPORTED_SIGNATURE_ALGORITHMS"; then
return 1
else
return 0
fi
}
#------------------------------
# Check if cert has recommended Key Usage
#------------------------------
function checkCertKeyUsage() {
CERT_HASH=$1
CERT_DESCRIPTION=$2
KU_LIST=$3
UNSUPPORTED_KEY_USAGE=0
if ! echo "$CERT_HASH" | openssl x509 -text -noout 2>/dev/null | grep -q 'X509v3 Key Usage'; then
return 0
fi
logInfo "Checking Key Usage for cert $CERT_DESCRIPTION among supported values of: $KU_LIST"
KEY_USAGE_SEARCH=$(echo "$CERT_HASH" | openssl x509 -text -noout 2>/dev/null | grep -A1 'X509v3 Key Usage' | tail -n1 | sed -e 's/^[[:space:]]*//' -e 's/, /\n/g')
logInfo "Key Usages found in cert:"
logDetails "$KEY_USAGE_SEARCH"
if [ -z "$KEY_USAGE_SEARCH" ]; then return 1; fi
IFS=$'\n'
for key_usage in $KEY_USAGE_SEARCH; do
KEY_USAGE_SEARCH_RESULT=$(echo "$KU_LIST" | grep "$key_usage")
if [ -z "$KEY_USAGE_SEARCH_RESULT" ]; then
logInfo "Found unsupported Key Usage value: $key_usage"
UNSUPPORTED_KEY_USAGE=1
else
logInfo "Found supported Key Usage value: $key_usage"
fi
done
IFS=$' \t\n'
if [ "$UNSUPPORTED_KEY_USAGE" == 1 ]; then
return 1
else
return 0
fi
}
#------------------------------
# Check if cert is expiring within 30 days
#------------------------------
function checkCertExpireSoon() {
if ! echo "$1" | openssl x509 -noout -checkend 2592000 > /dev/null 2>&1; then
CERT_END_DATE=$(echo "$1" | openssl x509 -noout -enddate 2>/dev/null | sed "s/.*=\(.*\)/\1/")
CERT_END_EPOCH=$(date -d "$CERT_END_DATE" +%s)
NOW_EPOCH=$(date -d now +%s)
DAYS_LEFT=$(( (CERT_END_EPOCH - NOW_EPOCH) / 86400))
echo "$DAYS_LEFT"
else
echo '-1'
fi
}
#------------------------------
# Check VASA Provider certs in SMS store
#------------------------------
function checkSMSVASACerts() {
if [ $NODE_TYPE != 'infrastructure' ]; then
SMS_VASA_ENTRIES=$($VECS_CLI entry list --store SMS | grep Alias | sed -e 's/Alias ://g' -e 's/^[[:space:]]*//g' | grep -vE '^sms_self_signed$|^sps-extension$')
if [ -n "$SMS_VASA_ENTRIES" ]; then
header 'Checking Additional Entries in SMS Store'
for alias in $SMS_VASA_ENTRIES; do
task "$alias"
checkVECSCert 'SMS' "$alias"
done
fi
fi
}
#------------------------------
# Quick check of VECS store status and permissions
#------------------------------
function quickCheckVECSStores() {
header 'Checking VECS Stores'
echo 'Checking status and permissions for VECS stores:'
logInfo 'Checking status and permissions for VECS stores'
MISSING_STORES=''
declare -gA MISSING_STORE_READ_PERMISSIONS=()
declare -gA MISSING_STORE_WRITE_PERMISSIONS=()
for store in $VECS_STORES; do
task " $store"
if ! checkVECSStore $store; then
CERT_STATUS_STORE_MISSING=1
if [ -z "$MISSING_STORES" ]; then MISSING_STORES+="$store"; else MISSING_STORES+=" $store"; fi
statusMessage 'MISSING' 'YELLOW'
logError "Could not find store '$store' in VECS"
else
PERMISSIONS_OK=1
STORE_PERMISSIONS=$($VECS_CLI store get-permissions --name $store)
STORE_PERMISSIONS_FORMATTED=$'\n'$(echo "$STORE_PERMISSIONS" | head -n2)
STORE_PERMISSIONS_FORMATTED+=$'\n'$(echo "$STORE_PERMISSIONS" | tail -n+3 | column -t)
logInfo "Permissions for VECS store $store:"
logDetails "$STORE_PERMISSIONS_FORMATTED"
logInfo "Users with expected read permissions: ${VECS_STORE_READ_PERMISSIONS[$store]}"
logInfo "Users with expected write permissions: ${VECS_STORE_WRITE_PERMISSIONS[$store]}"
for user in ${VECS_STORE_READ_PERMISSIONS[$store]}; do
if ! echo "$STORE_PERMISSIONS" | grep $user | grep -q 'read'; then
logInfo "Could not find read permission for user $user in VECS store $store"
if [ -z ${MISSING_STORE_READ_PERMISSIONS[$store]} ]; then MISSING_STORE_READ_PERMISSIONS[$store]="$user"; else MISSING_STORE_READ_PERMISSIONS[$store]=" $user"; fi
PERMISSIONS_OK=0
else
logInfo "Found read permission for user $user in VECS store $store"
fi
done
if [[ "$VC_VERSION" =~ ^[78] ]] && [ $VC_BUILD -ge 20051473 ]; then
for user in ${VECS_STORE_WRITE_PERMISSIONS[$store]}; do
if ! echo "$STORE_PERMISSIONS" | grep $user | grep -qE 'OWNER|write'; then
logInfo "Could not find write permission for user $user in VECS store $store"
if [ -z ${MISSING_STORE_WRITE_PERMISSIONS[$store]} ]; then MISSING_STORE_WRITE_PERMISSIONS[$store]="$user"; else MISSING_STORE_WRITE_PERMISSIONS[$store]=" $user"; fi
PERMISSIONS_OK=0
else
logInfo "Found write permission for user $user in VECS store $store"
fi
done
fi
if [ $PERMISSIONS_OK == 1 ]; then
statusMessage 'OK' 'GREEN'
else
CERT_STATUS_STORE_PERMISSIONS=1
statusMessage 'PERMISSIONS' 'YELLOW'
fi
fi
done
}
#------------------------------
# Check and remediation of VECS store status and permissions
#------------------------------
function checkVECSStores() {
quickCheckVECSStores
unset RECREATE_VECS_STORES_INPUT
unset FIX_VECS_STORES_PERMISSIONS
if [ -n "$MISSING_STORES" ]; then
read -p $'\n'"Some VECS stores are missing, recreate them? [n]: " RECREATE_VECS_STORES_INPUT
if [[ $RECREATE_VECS_STORES_INPUT =~ ^[Yy] ]]; then recreateMissingVECSStores; fi
fi
if [[ ${MISSING_STORE_READ_PERMISSIONS[*]} ]] || [[ ${MISSING_STORE_WRITE_PERMISSIONS[*]} ]]; then
read -p $'\n'"Some VECS stores are missing expected permissions, reassign them? [n]: " FIX_VECS_STORES_PERMISSIONS
if [[ $FIX_VECS_STORES_PERMISSIONS =~ ^[Yy] ]]; then fixVECSStorePermissions; fi
fi
}
#------------------------------
# Recreate missing VECS store
#------------------------------
function recreateMissingVECSStores() {
header 'Recreate missing VECS stores'
for store in $MISSING_STORES; do
task "Recreate store $store"
if [ "$store" == "SMS" ]; then
vmon-cli -r sps > /dev/null 2>&1 || errorMessage "Unable to create the VECS store SMS by restarting the sps service"
else
$VECS_CLI store create --name $store > /dev/null 2>&1 || errorMessage "Unable to create VECS store $store"
fi
statusMessage 'OK' 'GREEN'
echo 'Assigning permissions:'
for user in ${VECS_STORE_READ_PERMISSIONS[$store]}; do
task " Read permmisson for user $user"
$VECS_CLI store permission --name $store --user $user --grant read > /dev/null 2>&1 || errorMessage "Unable to assign read permission to user $user on store $store"
statusMessage 'OK' 'GREEN'
done
if [[ "$VC_VERSION" =~ ^[78] ]] && [ $VC_BUILD -ge 20051473 ]; then
for user in ${VECS_STORE_WRITE_PERMISSIONS[$store]}; do
task " Write permmisson for user $user"
$VECS_CLI store permission --name $store --user $user --grant write > /dev/null 2>&1 || errorMessage "Unable to assign write permission to user $user on store $store"
statusMessage 'OK' 'GREEN'
done
fi
done
}
#------------------------------
# Recreate missing VECS store permissions
#------------------------------
function fixVECSStorePermissions() {
header 'Fix VECS store permissions'
logInfo "Stores missing read permissions: ${!MISSING_STORE_READ_PERMISSIONS[*]}"
for store in "${!MISSING_STORE_READ_PERMISSIONS[@]}"; do
echo "Assign read permissions on store $store:"
for user in ${MISSING_STORE_READ_PERMISSIONS[$store]}; do
task " Read permission for user $user"
$VECS_CLI store permission --name $store --user $user --grant read > /dev/null 2>&1 || errorMessage "Unable to assign read permission to user $user on store $store"
statusMessage 'OK' 'GREEN'
done
done
if [[ "$VC_VERSION" =~ ^[78] ]] && [ $VC_BUILD -ge 20051473 ]; then
logInfo "Stores missing write permissions: ${!MISSING_STORE_WRITE_PERMISSIONS[*]}"
for store in "${!MISSING_STORE_WRITE_PERMISSIONS[@]}"; do
echo "Assign write permissions on store $store:"
for user in ${MISSING_STORE_WRITE_PERMISSIONS[$store]}; do
task " Write permission for user $user"
$VECS_CLI store permission --name $store --user $user --grant write > /dev/null 2>&1 || errorMessage "Unable to assign write permission to user $user on store $store"
statusMessage 'OK' 'GREEN'
done
done
fi
}
#------------------------------
# Check if a particular VECS store is present
#------------------------------
function checkVECSStore() {
if $VECS_CLI store list | grep -q "^$1\$"; then
return 0
else
return 1
fi
}
#------------------------------
# Check if a particular entry exists in a VECS store
#------------------------------
function checkVECSEntry() {
if $VECS_CLI entry list --store "$1" | grep -q "$2\$"; then
return 0
else
return 1
fi
}
#------------------------------
# Manage STS Signing certificates
#------------------------------
function manageSTSTenantCerts() {
case $1 in
'Check')
checkSTSTenantCerts
checkSTSTrustedCertChains
;;
'View')
viewSTSTenantCerts
;;
'Replace')
authenticateIfNeeded
viewSTSTenantCerts
if promptReplaceSTS; then
if replaceSSOSTSCert; then promptRestartVMwareServices; fi
fi
;;
esac
}
#------------------------------
# Manage Smart Card (CAC) certificates
#------------------------------
function manageCACCerts() {
case $1 in
'Check')
if configuredForCAC; then
checkRhttpproxyCACCerts
checkVMDirCACCerts
fi
;;
'View')
if configuredForCAC; then
viewRhttpproxyCACCerts
viewVMDirCACCerts
else
echo $'\n'"${YELLOW}This vCenter Server is not configured for Smart Card authentication${NORMAL}"
fi
;;
'Manage')
if configuredForCAC; then
viewRhttpproxyCACCerts
viewVMDirCACCerts
header 'Manage Smart Card Issuing CA Certificates'
cat << EOF
1. Add Smart Card issuing CA certificate(s)
to Reverse Proxy filter file
2. Remove Smart Card issuing CA certificate(s)
from Reverse Proxy filter file
3. Add Smart Card issuing CA certificate(s)
to VMware Directory
4. Remove Smart Card issuing CA certificate(s)
from VMware Directory
EOF
read -p $'\n'"Enter selection [Return to Main Menu]: " MANAGE_CAC_INPUT
case $MANAGE_CAC_INPUT in
1)
addCACCertsFilterFile
;;
2)
removeCACCertsFilterFile
;;
3)
updateSSOCACConfig 'add'
;;
4)
updateSSOCACConfig 'remove'
;;
esac
else
echo $'\n'"This vCenter Server is not configured for Smart Card authentication"
read -t $READ_TIMEOUTS -p $'\nConfigure vCenter Server for Smart Card authentication? [n]: ' CONFIGURE_CAC_INPUT
if [ $? -lt 128 ]; then
if [[ "$CONFIGURE_CAC_INPUT" =~ ^[Yy] ]]; then configureCACAuthentication; fi
else
echo ''
fi
fi
;;
esac
}
#------------------------------
# Get the configured path for the Smart Card Filter file
#------------------------------
function getCACFilterFile() {
logInfo 'Obtaining Smart Card filter file path'
case $VC_VERSION in
'7.0')
if [ "$VC_BUILD" -ge 20845200 ]; then
FILTER_FILE='/usr/lib/vmware-sso/vmware-sts/conf/clienttrustCA.pem'
else
RHTTPPROXY_CONFIG=$(xmllint --xpath "string(//clientCAListFile/text())" /etc/vmware-rhttpproxy/config.xml)
if [ -z "$RHTTPPROXY_CONFIG" ]; then
FILTER_FILE=''
else
if [[ "$RHTTPPROXY_CONFIG" =~ ^/ ]]; then
FILTER_FILE="$RHTTPPROXY_CONFIG"
else
FILTER_FILE="/etc/vmware-rhttpproxy/$RHTTPPROXY_CONFIG"
fi
fi
fi
;;
'8.0')
FILTER_FILE='/usr/lib/vmware-sso/vmware-sts/conf/clienttrustCA.pem'
;;
*)
RHTTPPROXY_CONFIG=$(xmllint --xpath "string(//clientCAListFile/text())" /etc/vmware-rhttpproxy/config.xml)
if [ -z "$RHTTPPROXY_CONFIG" ]; then
FILTER_FILE=''
else
if [[ "$RHTTPPROXY_CONFIG" =~ ^/ ]]; then
FILTER_FILE="$RHTTPPROXY_CONFIG"
else
FILTER_FILE="/etc/vmware-rhttpproxy/$RHTTPPROXY_CONFIG"
fi
fi
;;
esac
logInfo "Smart Card filter file: $FILTER_FILE"
echo "$FILTER_FILE"
}
#------------------------------
# Check Reverse Proxy Smart Card signing CA certificates
#------------------------------
function checkRhttpproxyCACCerts() {
CAC_FILTER_FILE=$(getCACFilterFile)
if [ -n "$CAC_FILTER_FILE" ]; then
header 'Check Smart Card Issuing CA Filter File'
task 'Check CA Filter File'
if [[ "$VC_VERSION" =~ ^7 ]] && [[ $VC_BUILD -ge 20845200 ]]; then
if [ "$CAC_FILTER_FILE" == '/usr/lib/vmware-sso/vmware-sts/conf/clienttrustCA.pem' ]; then
if [ -s $CAC_FILTER_FILE ]; then
statusMessage 'OK' 'GREEN'
else
statusMessage 'MISSING' 'YELLOW'
CERT_STATUS_CLIENT_CA_LIST_FILE_MISSING=1
fi
else
statusMessage 'PROBLEM' 'YELLOW'
CERT_STATUS_CLIENT_CA_LIST_FILE_LOCATION=1
fi
else
if [ -s $CAC_FILTER_FILE ]; then
statusMessage 'OK' 'GREEN'
else
statusMessage 'MISSING' 'YELLOW'
CERT_STATUS_CLIENT_CA_LIST_FILE_MISSING=1
fi
fi
if [ -s $CAC_FILTER_FILE ]; then
rm $STAGE_DIR/rhttpproxy-ca-* 2>&1 | logDebug
csplit -s -z -f $STAGE_DIR/rhttpproxy-ca- -b %02d.crt $CAC_FILTER_FILE '/-----BEGIN CERTIFICATE-----/' '{*}'
i=1
for cert in $STAGE_DIR/rhttpproxy-ca-*; do
[[ -e "$cert" ]] || break
task "Certificate $i"
checkFilesystemCert "$cert"
((++i))
done
rm $STAGE_DIR/rhttpproxy-ca-* 2>&1 | logDebug
fi
fi
}
#------------------------------
# View Reverse Proxy Smart Card signing CA certificates
#------------------------------
function viewRhttpproxyCACCerts() {
REVERSE_PROXY_CAC_CERT_THUMBPRINTS=()
CAC_FILTER_FILE=$(getCACFilterFile)
header 'Smart Card Issuing CA Filter File'
logInfo "Smart Card filter file: $CAC_FILTER_FILE"
if [ -n "$CAC_FILTER_FILE" ] && [ -s "$CAC_FILTER_FILE" ]; then
rm $STAGE_DIR/rhttpproxy-ca-* 2>&1 | logDebug
csplit -s -z -f $STAGE_DIR/rhttpproxy-ca- -b %02d.crt $CAC_FILTER_FILE '/-----BEGIN CERTIFICATE-----/' '{*}'
i=1
for cert in $STAGE_DIR/rhttpproxy-ca-*; do
[[ -e "$cert" ]] || break
TEMP_CERT=$(cat "$cert")
CERT_OUTPUT=$(viewBriefCertificateInfo "$TEMP_CERT")
REVERSE_PROXY_CAC_CERT_THUMBPRINTS+=($(openssl x509 -noout -fingerprint -sha1 -in $cert 2>>/dev/null | awk -F'=' '{print $NF}'))
printf "%2s. %s\n\n" $i "$CERT_OUTPUT"
((++i))
done
rm $STAGE_DIR/rhttpproxy-ca-* 2>&1 | logDebug
else
echo "${YELLOW}No Smart Card CA filter file found or it is empty.$NORMAL"
fi
}
#------------------------------
# Check VMware Directory Smart Card signing CA certificates
#------------------------------
function checkVMDirCACCerts() {
CAC_CERTS=$($LDAP_SEARCH -o ldif-wrap=no -LLL -h $PSC_LOCATION -p $VMDIR_PORT -b "cn=ClientCertAuthnTrustedCAs,cn=Default,cn=ClientCertificatePolicies,cn=$SSO_DOMAIN,cn=Tenants,cn=IdentityManager,cn=Services,${VMDIR_DOMAIN_DN}" -D "cn=${VMDIR_USER},cn=users,${VMDIR_DOMAIN_DN}" -y $STAGE_DIR/.vmdir-user-password '(objectclass=*)' userCertificate 2>/dev/null | grep -v '^dn:' | sed -e 's/userCertificate:: //g')
if [ -n "$CAC_CERTS" ]; then
header 'Check VMDir Smart Card signing CA certificates'
i=1
for hash in $CAC_CERTS; do
TEMP_CERT=$(buildCertFromHash "$hash")
task "Certificate $i"
checkCert "$TEMP_CERT"
((++i))
done
fi
}
#------------------------------
# View VMware Directory Smart Card signing CA certificates
#------------------------------
function viewVMDirCACCerts() {
CAC_CERT_LIST=()
header 'Smart Card Issuing CA Certificates'
CAC_CERTS=$($LDAP_SEARCH -o ldif-wrap=no -LLL -h $PSC_LOCATION -p $VMDIR_PORT -b "cn=ClientCertAuthnTrustedCAs,cn=Default,cn=ClientCertificatePolicies,cn=$SSO_DOMAIN,cn=Tenants,cn=IdentityManager,cn=Services,${VMDIR_DOMAIN_DN}" -D "cn=${VMDIR_USER},cn=users,${VMDIR_DOMAIN_DN}" -y $STAGE_DIR/.vmdir-user-password '(objectclass=*)' userCertificate 2>/dev/null | grep -v '^dn:' | sed -e 's/userCertificate:: //g')
i=1
if [ -n "$CAC_CERTS" ]; then
for hash in $CAC_CERTS; do
TEMP_CERT=$(buildCertFromHash "$hash")
CAC_CERT_LIST+=("$TEMP_CERT")
CERT_OUTPUT=$(viewBriefCertificateInfo "$TEMP_CERT")
printf "%2s. %s\n\n" $i "$CERT_OUTPUT"
((++i))
done
else
echo "${YELLOW}No Smart Card issuing CA certificates found in VMware Directory.$NORMAL"
fi
}
#------------------------------
# Add Smart Card (CAC) issuing certificates to reverse proxy filter file
#------------------------------
function addCACCertsFilterFile() {
read -e -p $'\nEnter path to new Smart Card issuing certificate(s): ' NEW_CAC_CERTS_INPUT
while [ ! -f $NEW_CAC_CERTS_INPUT ]; do read -s -p $'\n'"${YELLOW}File not found, enter path to new Smart Card issuing certificate(s):${NORMAL} " NEW_CAC_CERTS_INPUT; done
rm $STAGE_DIR/new-cac-cert-* 2>&1 | logDebug
csplit -s -z -f $STAGE_DIR/new-cac-cert- -b %02d.crt $NEW_CAC_CERTS_INPUT '/-----BEGIN CERTIFICATE-----/' '{*}'
header 'Adding New Smart Card Issuing Certificates'
CAC_FILTER_FILE=$(getCACFilterFile)
for cert in $STAGE_DIR/new-cac-cert-*; do
[[ -e "$cert" ]] || break
if ! isExpired "$cert" 'file'; then
task "Adding cert $(openssl x509 -noout -hash -in $cert 2>&1) to reverse proxy file"
cat $cert >> $CAC_FILTER_FILE
statusMessage 'OK' 'GREEN'
fi
done
sed -i '/^$/d' $CAC_FILTER_FILE
}
#------------------------------
# Remove Smart Card (CAC) issuing certificates from reverse proxy filter file
#------------------------------
function removeCACCertsFilterFile() {
read -p $'\nEnter number of Smart Card issuing certificate(s) to remove (comma-separated list): ' CAC_CERT_REMOVE_INPUT
if [ -n "$CAC_CERT_REMOVE_INPUT" ]; then
header 'Removing Smart Card Issuing Certificates'
HASHES_TO_REMOVE=()
for index in $(echo $CAC_CERT_REMOVE_INPUT | tr -d ' ' | sed 's/,/ /g'); do
HASHES_TO_REMOVE+=(" ${REVERSE_PROXY_CAC_CERT_THUMBPRINTS[$((index - 1))]}")
done
CAC_FILTER_FILE=$(getCACFilterFile)
logInfo "Hashes to remove from $CAC_FILTER_FILE: ${HASHES_TO_REMOVE[*]}"
if [ -f $CAC_FILTER_FILE ]; then
if [ -f $STAGE_DIR/new-cac-certs.pem ]; then rm $STAGE_DIR/new-cac-certs.pem; fi
csplit -s -z -f $STAGE_DIR/rhttpproxy-ca- -b %02d.crt $CAC_FILTER_FILE '/-----BEGIN CERTIFICATE-----/' '{*}'
for cert in $STAGE_DIR/rhttpproxy-ca-*; do
[[ -e "$cert" ]] || break
CERT_THUMBPRINT=$(openssl x509 -noout -fingerprint -sha1 -in $cert 2>/dev/null | awk -F'=' '{print $NF}')
if [[ ! " ${HASHES_TO_REMOVE[*]} " =~ " $CERT_THUMBPRINT" ]]; then
cat $cert >> $STAGE_DIR/new-cac-certs.pem
fi
done
task 'Updating reverse proxy filter file'
cp $STAGE_DIR/new-cac-certs.pem $CAC_FILTER_FILE > /dev/null 2>&1 || errorMessage 'Unable to update reverse proxy filter file'
statusMessage 'OK' 'GREEN'
else
errorMessage 'Unable to determine reverse proxy filter file'
fi
fi
rm $STAGE_DIR/rhttpproxy-ca-* 2>&1 | logDebug
}
#------------------------------
# Configure Smart Card (CAC) authentication
#------------------------------
function configureCACAuthentication() {
read -e -p $'\nEnter path to Smart Card issuing CA certificate(s): ' CAC_CA_FILE_INPUT
while [ ! -f "$CAC_CA_FILE_INPUT" ]; do read -e -p 'File not found, please provide path to the Smart Card issuing CA certificate(s) certificate: ' CAC_CA_FILE_INPUT; done
header 'Configure Smart Card authentication'
task 'Verify CA certificates'
csplit -s -z -f $STAGE_DIR/cac-ca- -b %02d.crt "$CAC_CA_FILE_INPUT" '/-----BEGIN CERTIFICATE-----/' '{*}'
for cert in $STAGE_DIR/cac-ca-*; do
[[ -e "$cert" ]] || break
if isCertCA "$(cat $cert)"; then
if ! isExpired "$cert" 'file'; then
cat "$cert" >> $STAGE_DIR/cac-certs.pem
fi
fi
done
statusMessage 'OK' 'GREEN'
if [ ! -s $STAGE_DIR/cac-certs.pem ]; then
errorMessage "No valid CA certificates found in $CAC_CA_FILE_INPUT"
else
task 'Backup reverse proxy config'
cp /etc/vmware-rhttpproxy/config.xml /etc/vmware-rhttpproxy/config.xml.backup 2>/dev/null || errorMessage 'Unable to backup /etc/vmware-rhttpproxy/config.xml'
statusMessage 'OK' 'GREEN'
cp $STAGE_DIR/cac-certs.pem /usr/lib/vmware-sso/vmware-sts/conf/clienttrustCA.pem
task 'Configure reverse proxy'
CAC_FILTER_FILE=$(grep '' /etc/vmware-rhttpproxy/config.xml | awk -F'>' '{print $2}' | awk -F'<' '{print $1}')
sed -i -e "s|$CAC_FILTER_FILE|/usr/lib/vmware-sso/vmware-sts/conf/clienttrustCA.pem|" -e 's|||' -e 's|||' -e '//i true' /etc/vmware-rhttpproxy/config.xml > /dev/null 2>&1 || errorMessage 'Unable to update reverse proxy configuration'
statusMessage 'OK' 'GREEN'
updateSSOCACConfig 'add' '/usr/lib/vmware-sso/vmware-sts/conf/clienttrustCA.pem'
fi
}
#------------------------------
# Export SSO Smart Card CA certificates
#------------------------------
function exportSSOCACCerts() {
SSO_CAC_CA_CERTS=$(ldapsearch -LLL -h localhost -b "cn=DefaultClientCertCAStore,cn=ClientCertAuthnTrustedCAs,cn=Default,cn=ClientCertificatePolicies,cn=$SSO_DOMAIN,cn=Tenants,cn=IdentityManager,cn=Services,$VMDIR_DOMAIN_DN" -D "cn=$VMDIR_USER,cn=users,$VMDIR_DOMAIN_DN" -y $STAGE_DIR/.vmdir-user-password userCertificate 2>/dev/null | sed -e 's/^ //g' | tr -d '\n' | sed -e 's/dn:/\n&/g' -e 's/userCertificate:/\n&/g' | grep '^userCertificate' | awk '{print $NF}')
logInfo 'Exporting Smart Card CA certificates from VMware Directory'
SSO_CAC_CA_CERT_FILES=()
if [ -n "$SSO_CAC_CA_CERTS" ]; then
i=$1
for hash in $SSO_CAC_CA_CERTS; do
CERT_PRESENT=0
TEMP_CERT=$(buildCertFromHash "$hash")
TEMP_CERT_THUMBPRINT=$(echo "$TEMP_CERT" | openssl x509 -noout -fingerprint -sha1 2>/dev/null | awk -F'=' '{print $NF}')
logInfo "Checking SSO Smart Card CA certificate with thumbprint $TEMP_CERT_THUMBPRINT"
for cert in $STAGE_DIR/sso-cac-ca-cert-*.crt; do
[[ -e "$cert" ]] || break
CURRENT_CERT_THUMBPRINT=$(openssl x509 -noout -fingerprint -sha1 -in $cert 2>/dev/null | awk -F'=' '{print $NF}')
logDebug "Checking SSO Smart Card CA certificate thumbprint ($TEMP_CERT_THUMBPRINT) against new certificate thumbprint ($CURRENT_CERT_THUMBPRINT)"
if [ "$CURRENT_CERT_THUMBPRINT" = "$TEMP_CERT_THUMBPRINT" ]; then CERT_PRESENT=1; fi
done
if [ $CERT_PRESENT -eq 0 ]; then
echo "$TEMP_CERT" > $STAGE_DIR/sso-cac-ca-cert-$i.crt
SSO_CAC_CA_CERT_FILES+=("$STAGE_DIR/sso-cac-ca-cert-$i.crt")
logInfo "Saving SSO Smart Card CA certificate to $STAGE_DIR/sso-cac-ca-cert-$i.crt"
fi
((++i))
done
fi
}
#------------------------------
# Export SSO LDAPS CA certificates
#------------------------------
function exportSSOLDAPSCerts() {
logInfo "Exporting LDAPS certificates with Identity Source type: $1"
case $1 in
'Microsoft ADFS')
LDAPS_CERTS=$($LDAP_SEARCH -o ldif-wrap=no -LLL -h $PSC_LOCATION -p $VMDIR_PORT -b "cn=VCIdentityProviders,cn=$SSO_DOMAIN,cn=Tenants,cn=IdentityManager,cn=Services,$VMDIR_DOMAIN_DN" -D "cn=$VMDIR_USER,cn=users,$VMDIR_DOMAIN_DN" -y $STAGE_DIR/.vmdir-user-password '(vmwSTSProviderType=IDENTITY_STORE_TYPE_LDAP_WITH_AD_MAPPING)' userCertificate 2>/dev/null | sed -e 's/^ //g' | grep '^userCertificate:' | awk '{print $NF}')
;;
*)
LDAPS_CERTS=$($LDAP_SEARCH -o ldif-wrap=no -LLL -h $PSC_LOCATION -p $VMDIR_PORT -b "cn=$2,cn=IdentityProviders,cn=$SSO_DOMAIN,cn=Tenants,cn=IdentityManager,cn=Services,$VMDIR_DOMAIN_DN" -D "cn=$VMDIR_USER,cn=users,$VMDIR_DOMAIN_DN" -y $STAGE_DIR/.vmdir-user-password '(|(vmwSTSProviderType=IDENTITY_STORE_TYPE_LDAP_WITH_AD_MAPPING)(vmwSTSProviderType=IDENTITY_STORE_TYPE_LDAP))' userCertificate 2>/dev/null | sed -e 's/^ //g' | grep '^userCertificate:' | awk '{print $NF}')
;;
esac
for hash in $LDAPS_CERTS; do
TEMP_CERT=$(buildCertFromHash "$hash")
TEMP_CERT_SUBJECT_HASH=$(echo "$TEMP_CERT" | openssl x509 -noout -hash)
echo "$TEMP_CERT" > $STAGE_DIR/${3}$TEMP_CERT_SUBJECT_HASH.crt
done
}
#------------------------------
# Update SSO with Smart Card configuration
#------------------------------
function updateSSOCACConfig() {
rm $STAGE_DIR/sso-cac-ca-cert-* > /dev/null 2>&1
CAC_CA_CERTS=()
case $1 in
'add')
if [ -n "$2" ]; then
CA_FILE=$2
else
read -e -p $'\nEnter path to smart card CA certificate file: ' CA_FILE
while [ ! -f $CA_FILE ]; do read -e -p "${YELLOW}File not found, enter path to smart card CA certificate file:${NORMAL} " CA_FILE; done
fi
header 'Adding Smart Card CA certificates to VMware Directory'
csplit -z -s -f $STAGE_DIR/sso-cac-ca-cert- -b %01d.crt $CA_FILE '/-----BEGIN CERTIFICATE-----/' '{*}'
CAC_CA_CERT_COUNT=$(ls $STAGE_DIR/sso-cac-ca-cert-* | wc -l)
exportSSOCACCerts "$CAC_CA_CERT_COUNT"
for cert in $STAGE_DIR/sso-cac-ca-cert-*; do
[[ -e "$cert" ]] || break
CERT_HASH=$(openssl x509 -noout -hash -in $cert 2>&1 | logDebug)
task "Adding certificate $CERT_HASH"
CAC_CA_CERTS+=("$cert")
statusMessage 'OK' 'GREEN'
done
;;
'remove')
exportSSOCACCerts '0'
read -p $'\nEnter the number(s) of the certificate(s) to delete (multiple entries separated by a comma): ' CAC_CAS_TO_REMOVE
if [ -n "$CAC_CAS_TO_REMOVE" ]; then
logInfo "User has selected the following certificate(s) to delete: $CAC_CAS_TO_REMOVE"
header 'Removing Smart Card CA certificates from VMware Directory'
for index in $(echo $CAC_CAS_TO_REMOVE | tr -d ' ' | sed 's/,/ /g'); do
if [[ $index =~ ^[0-9]+$ ]]; then
CERT_TO_REMOVE=${CAC_CERT_LIST[$((index - 1))]}
THUMBPRINT_TO_REMOVE=$(echo "$CERT_TO_REMOVE" | openssl x509 -noout -fingerprint -sha1 2>/dev/null | awk -F'=' '{print $NF}')
SUBJECT_HASH_TO_REMOVE=$(echo "$CERT_TO_REMOVE" | openssl x509 -noout -hash)
for cert in $STAGE_DIR/sso-cac-ca-cert-*; do
[[ -e "$cert" ]] || break
CURRENT_CERT_THUMBPRINT=$(openssl x509 -noout -fingerprint -sha1 -in $cert 2>/dev/null | awk -F'=' '{print $NF}')
if [ "$THUMBPRINT_TO_REMOVE" = "$CURRENT_CERT_THUMBPRINT" ]; then
task "Removing certificate $SUBJECT_HASH_TO_REMOVE"
rm $cert > /dev/null 2>&1 || errorMessage "Unable to remove certificate $SUBJECT_HASH_TO_REMOVE"
statusMessage 'OK' 'GREEN'
fi
done
fi
done
fi
for cert in $STAGE_DIR/sso-cac-ca-cert-*; do
[[ -e "$cert" ]] || break
CAC_CA_CERTS+=("$cert")
done
;;
esac
SSO_CAC_CERTS=$(printf -v joined '%s,' "${CAC_CA_CERTS[@]}"; echo "${joined%,}")
logInfo "Updating SSO configuration with '$SSO_CAC_CERTS'"
task 'Update SSO configuration'
sso-config.sh -set_authn_policy -certAuthn true -cacerts "$SSO_CAC_CERTS" -t "$SSO_DOMAIN" > /dev/null 2>&1 || errorMessage "Unable to configure SSO for Smart Card authentication"
statusMessage 'OK' 'GREEN'
}
#------------------------------
# Manage AD over LDAP certificates
#------------------------------
function manageLDAPSCerts() {
if configuredForADoverLDAPS; then
case $1 in
'Check')
checkLDAPSCerts
;;
'View')
viewLDAPSCerts
read -p $'\nSelect certificate [Return to Main Menu]: ' VIEW_LDAPS_CERT_INPUT
if [ -n "$VIEW_LDAPS_CERT_INPUT" ] && [[ $VIEW_LDAPS_CERT_INPUT -le $LDAPS_CERT_COUNTER ]]; then
LDAP_CERT_HASH=${LDAPS_CERT_HASHES[$((VIEW_LDAPS_CERT_INPUT - 1))]}
TEMP_CERT=$(buildCertFromHash "$LDAP_CERT_HASH")
viewCertificateInfo "$TEMP_CERT" 'view-path'
fi
;;
'Manage')
selectLDAPSDomain
viewIdentitySourceLDAPSCerts
;;
esac
fi
}
#------------------------------
# List LDAPS domains
#------------------------------
function selectLDAPSDomain() {
LDAPS_DOMAINS=()
SELECTED_LDAPS_DOMAIN=''
AD_OVER_LDAPS_DOMAINS=$($LDAP_SEARCH -o ldif-wrap=no -LLL -h $PSC_LOCATION -p $VMDIR_PORT -b "cn=IdentityProviders,cn=$SSO_DOMAIN,cn=Tenants,cn=IdentityManager,cn=Services,$VMDIR_DOMAIN_DN" -D "cn=$VMDIR_USER,cn=users,$VMDIR_DOMAIN_DN" -y $STAGE_DIR/.vmdir-user-password '(vmwSTSProviderType=IDENTITY_STORE_TYPE_LDAP_WITH_AD_MAPPING)' -s one cn 2>/dev/null | sed -e 's/^ //g' | grep '^cn:' | awk '{print $NF}')
OPENLDAP_DOMAINS=$($LDAP_SEARCH -o ldif-wrap=no -LLL -h $PSC_LOCATION -p $VMDIR_PORT -b "cn=IdentityProviders,cn=$SSO_DOMAIN,cn=Tenants,cn=IdentityManager,cn=Services,$VMDIR_DOMAIN_DN" -D "cn=$VMDIR_USER,cn=users,$VMDIR_DOMAIN_DN" -y $STAGE_DIR/.vmdir-user-password '(vmwSTSProviderType=IDENTITY_STORE_TYPE_LDAP)' -s one cn 2>/dev/null | sed -e 's/^ //g' | grep '^cn:' | awk '{print $NF}')
ADFS_ISSUER=$($LDAP_SEARCH -o ldif-wrap=no -LLL -h $PSC_LOCATION -p $VMDIR_PORT -b "cn=VCIdentityProviders,cn=$SSO_DOMAIN,cn=Tenants,cn=IdentityManager,cn=Services,$VMDIR_DOMAIN_DN" -D "cn=$VMDIR_USER,cn=users,$VMDIR_DOMAIN_DN" -y $STAGE_DIR/.vmdir-user-password '(objectclass=vmwSTSExternalIdp)' -s one vmwSTSIssuerName 2>/dev/null | grep '^vmwSTSIssuerName:' | awk '{print $NF}')
for domain in $OPENLDAP_DOMAINS; do
LDAPS_DOMAINS+=("$domain|OpenLDAP")
done
for domain in $AD_OVER_LDAPS_DOMAINS; do
LDAPS_DOMAINS+=("$domain|AD over LDAPS")
done
if [[ "$VC_VERSION" =~ ^[78] ]]; then
if [ -n "$ADFS_ISSUER" ]; then
LDAPS_DOMAINS+=("$ADFS_ISSUER|Microsoft ADFS")
fi
fi
if [ ${#LDAPS_DOMAINS[@]} -eq 0 ]; then
echo "${YELLOW}There are no Identity Sources configured that can utilize an LDAPS connection.${NORMAL}"
else
header 'Select Domain to Manage LDAPS Certificates'
i=1
for entry in "${LDAPS_DOMAINS[@]}"; do
domain=$(echo "$entry" | awk -F '|' '{print $1}')
source_type=$(echo "$entry" | awk -F '|' '{print $2}')
printf "%2s. %s (%s)\n" $i $domain "$source_type"
((++i))
done
read -p $'\nSelect domain [1]: ' SELECTED_LDAPS_DOMAIN_INPUT
if [ -z $SELECTED_LDAPS_DOMAIN_INPUT ]; then SELECTED_LDAPS_DOMAIN_INPUT=1; fi
SELECTED_LDAPS_DOMAIN=${LDAPS_DOMAINS[(($SELECTED_LDAPS_DOMAIN_INPUT - 1))]}
fi
}
#------------------------------
# Check LDAPS certificates
#------------------------------
function checkLDAPSCerts() {
AD_OVER_LDAPS_DOMAINS=$($LDAP_SEARCH -o ldif-wrap=no -LLL -h $PSC_LOCATION -p $VMDIR_PORT -b "cn=IdentityProviders,cn=$SSO_DOMAIN,cn=Tenants,cn=IdentityManager,cn=Services,$VMDIR_DOMAIN_DN" -D "cn=$VMDIR_USER,cn=users,$VMDIR_DOMAIN_DN" -y $STAGE_DIR/.vmdir-user-password '(vmwSTSProviderType=IDENTITY_STORE_TYPE_LDAP_WITH_AD_MAPPING)' -s one cn 2>/dev/null | sed -e 's/^ //g' | grep '^cn:' | awk '{print $NF}')
OPENLDAP_DOMAINS=$($LDAP_SEARCH -o ldif-wrap=no -LLL -h $PSC_LOCATION -p $VMDIR_PORT -b "cn=IdentityProviders,cn=$SSO_DOMAIN,cn=Tenants,cn=IdentityManager,cn=Services,$VMDIR_DOMAIN_DN" -D "cn=$VMDIR_USER,cn=users,$VMDIR_DOMAIN_DN" -y $STAGE_DIR/.vmdir-user-password '(vmwSTSProviderType=IDENTITY_STORE_TYPE_LDAP)' -s one cn 2>/dev/null | sed -e 's/^ //g' | grep '^cn:' | awk '{print $NF}')
if [ -n "$OPENLDAP_DOMAINS" ]; then
header 'Check OpenLDAP LDAPS certificates'
for domain in $OPENLDAP_DOMAINS; do
echo "Domain: $domain"
LDAP_CERTS=$($LDAP_SEARCH -o ldif-wrap=no -LLL -h $PSC_LOCATION -p $VMDIR_PORT -b "cn=$domain,cn=IdentityProviders,cn=$SSO_DOMAIN,cn=Tenants,cn=IdentityManager,cn=Services,$VMDIR_DOMAIN_DN" -D "cn=$VMDIR_USER,cn=users,$VMDIR_DOMAIN_DN" -y $STAGE_DIR/.vmdir-user-password '(vmwSTSProviderType=IDENTITY_STORE_TYPE_LDAP)' userCertificate 2>/dev/null | sed -e 's/^ //g' | grep '^userCertificate:' | awk '{print $NF}')
i=1
for hash in $LDAP_CERTS; do
TEMP_CERT=$(buildCertFromHash "$hash")
task " Certificate $i"
checkCert "$TEMP_CERT"
((++i))
done
done
fi
if [ -n "$AD_OVER_LDAPS_DOMAINS" ]; then
header 'Check AD over LDAPS certificates'
for domain in $AD_OVER_LDAPS_DOMAINS; do
echo "Domain: $domain"
LDAP_CERTS=$($LDAP_SEARCH -o ldif-wrap=no -LLL -h $PSC_LOCATION -p $VMDIR_PORT -b "cn=$domain,cn=IdentityProviders,cn=$SSO_DOMAIN,cn=Tenants,cn=IdentityManager,cn=Services,$VMDIR_DOMAIN_DN" -D "cn=$VMDIR_USER,cn=users,$VMDIR_DOMAIN_DN" -y $STAGE_DIR/.vmdir-user-password '(vmwSTSProviderType=IDENTITY_STORE_TYPE_LDAP_WITH_AD_MAPPING)' userCertificate 2>/dev/null | sed -e 's/^ //g' | grep '^userCertificate:' | awk '{print $NF}')
i=1
for hash in $LDAP_CERTS; do
TEMP_CERT=$(buildCertFromHash "$hash")
task " Certificate $i"
checkCert "$TEMP_CERT"
((++i))
done
done
fi
if [[ "$VC_VERSION" =~ ^[78] ]]; then
ADFS_LDAPS_CERTS=$($LDAP_SEARCH -o ldif-wrap=no -LLL -h $PSC_LOCATION -p $VMDIR_PORT -b "cn=VCIdentityProviders,cn=$SSO_DOMAIN,cn=Tenants,cn=IdentityManager,cn=Services,$VMDIR_DOMAIN_DN" -D "cn=$VMDIR_USER,cn=users,$VMDIR_DOMAIN_DN" -y $STAGE_DIR/.vmdir-user-password '(vmwSTSProviderType=IDENTITY_STORE_TYPE_LDAP_WITH_AD_MAPPING)' userCertificate 2>/dev/null | grep '^userCertificate' | awk '{print $NF}')
if [ -n "$ADFS_LDAPS_CERTS" ]; then
header 'Check ADFS LDAPS certificates'
i=1
for hash in $ADFS_LDAPS_CERTS; do
TEMP_CERT=$(buildCertFromHash "$hash")
task "Certificate $i"
checkCert "$TEMP_CERT"
((++i))
done
fi
fi
}
#------------------------------
# View Identity Source LDAPS certificates
#------------------------------
function viewIdentitySourceLDAPSCerts() {
if [ -n "$SELECTED_LDAPS_DOMAIN" ]; then
LDAPS_CERT_THUMBPRINT_LIST=()
LDAPS_CERT_HASHES=()
LDAPS_CERT_COUNTER=1
domain=$(echo "$SELECTED_LDAPS_DOMAIN" | awk -F '|' '{print $1}')
source_type=$(echo "$SELECTED_LDAPS_DOMAIN" | awk -F '|' '{print $2}')
case $source_type in
'Microsoft ADFS')
LDAP_CERTS=$($LDAP_SEARCH -o ldif-wrap=no -LLL -h $PSC_LOCATION -p $VMDIR_PORT -b "cn=VCIdentityProviders,cn=$SSO_DOMAIN,cn=Tenants,cn=IdentityManager,cn=Services,$VMDIR_DOMAIN_DN" -D "cn=$VMDIR_USER,cn=users,$VMDIR_DOMAIN_DN" -y $STAGE_DIR/.vmdir-user-password '(vmwSTSProviderType=IDENTITY_STORE_TYPE_LDAP_WITH_AD_MAPPING)' userCertificate 2>/dev/null | grep '^userCertificate' | awk -F':' '{print $NF}')
header='Manage Certificates for External Provider: Microsoft ADFS'
;;
*)
LDAP_CERTS=$($LDAP_SEARCH -o ldif-wrap=no -LLL -h $PSC_LOCATION -p $VMDIR_PORT -b "cn=$domain,cn=IdentityProviders,cn=$SSO_DOMAIN,cn=Tenants,cn=IdentityManager,cn=Services,$VMDIR_DOMAIN_DN" -D "cn=$VMDIR_USER,cn=users,$VMDIR_DOMAIN_DN" -y $STAGE_DIR/.vmdir-user-password '(vmwSTSProviderType=IDENTITY_STORE_TYPE_LDAP_WITH_AD_MAPPING)' userCertificate 2>/dev/null | sed -e 's/^ //g' | grep '^userCertificate:' | awk '{print $NF}')
header="Manage Certificates for Identity Provider: Domain $domain"
;;
esac
header 'Currently Configured Certificatse for LDAPS Connection'
viewLDAPSCertInfo "$LDAP_CERTS" "$domain" "$source_type"
header "$header"
cat << EOF
1. Add LDAP server certificate(s)
2. Remove LDAP server certificate(s)
EOF
read -p $'\nEnter selection [Return to Main Menu]: ' MANAGE_LDAPS_INPUT
case $MANAGE_LDAPS_INPUT in
1)
addLDAPSCerts
;;
2)
removeLDAPSCerts
;;
esac
fi
}
#------------------------------
# View LDAPS certificates
#------------------------------
function viewLDAPSCerts() {
LDAPS_CERT_THUMBPRINT_LIST=()
LDAPS_DOMAINS=()
LDAPS_CERT_HASHES=()
LDAPS_CERT_COUNTER=1
LDAPS_CERT_DNS=()
AD_OVER_LDAPS_DOMAINS=$($LDAP_SEARCH -o ldif-wrap=no -LLL -h $PSC_LOCATION -p $VMDIR_PORT -b "cn=IdentityProviders,cn=$SSO_DOMAIN,cn=Tenants,cn=IdentityManager,cn=Services,$VMDIR_DOMAIN_DN" -D "cn=$VMDIR_USER,cn=users,$VMDIR_DOMAIN_DN" -y $STAGE_DIR/.vmdir-user-password '(vmwSTSProviderType=IDENTITY_STORE_TYPE_LDAP_WITH_AD_MAPPING)' -s one cn 2>/dev/null | sed -e 's/^ //g' | grep '^cn:' | awk '{print $NF}')
OPENLDAP_DOMAINS=$($LDAP_SEARCH -o ldif-wrap=no -LLL -h $PSC_LOCATION -p $VMDIR_PORT -b "cn=IdentityProviders,cn=$SSO_DOMAIN,cn=Tenants,cn=IdentityManager,cn=Services,$VMDIR_DOMAIN_DN" -D "cn=$VMDIR_USER,cn=users,$VMDIR_DOMAIN_DN" -y $STAGE_DIR/.vmdir-user-password '(vmwSTSProviderType=IDENTITY_STORE_TYPE_LDAP)' -s one cn 2>/dev/null | sed -e 's/^ //g' | grep '^cn:' | awk '{print $NF}')
ADFS_ISSUER=$($LDAP_SEARCH -o ldif-wrap=no -LLL -h $PSC_LOCATION -p $VMDIR_PORT -b "cn=VCIdentityProviders,cn=$SSO_DOMAIN,cn=Tenants,cn=IdentityManager,cn=Services,$VMDIR_DOMAIN_DN" -D "cn=$VMDIR_USER,cn=users,$VMDIR_DOMAIN_DN" -y $STAGE_DIR/.vmdir-user-password '(objectclass=vmwSTSExternalIdp)' -s one vmwSTSIssuerName 2>/dev/null | grep '^vmwSTSIssuerName:' | awk '{print $NF}')
header 'LDAPS Certificates'
if [ -n "$OPENLDAP_DOMAINS" ]; then
for domain in $OPENLDAP_DOMAINS; do
LDAPS_DOMAINS+=("$domain|OpenLDAP")
LDAP_CERTS=$($LDAP_SEARCH -o ldif-wrap=no -LLL -h $PSC_LOCATION -p $VMDIR_PORT -b "cn=$domain,cn=IdentityProviders,cn=$SSO_DOMAIN,cn=Tenants,cn=IdentityManager,cn=Services,$VMDIR_DOMAIN_DN" -D "cn=$VMDIR_USER,cn=users,$VMDIR_DOMAIN_DN" -y $STAGE_DIR/.vmdir-user-password '(vmwSTSProviderType=IDENTITY_STORE_TYPE_LDAP)' userCertificate 2>/dev/null | sed -e 's/^ //g' | grep '^userCertificate:' | awk '{print $NF}')
viewLDAPSCertInfo "$LDAP_CERTS" "$domain" 'OpenLDAP'
done
fi
if [ -n "$AD_OVER_LDAPS_DOMAINS" ]; then
for domain in $AD_OVER_LDAPS_DOMAINS; do
LDAPS_DOMAINS+=("$domain|AD over LDAPS")
LDAP_CERTS=$($LDAP_SEARCH -o ldif-wrap=no -LLL -h $PSC_LOCATION -p $VMDIR_PORT -b "cn=$domain,cn=IdentityProviders,cn=$SSO_DOMAIN,cn=Tenants,cn=IdentityManager,cn=Services,$VMDIR_DOMAIN_DN" -D "cn=$VMDIR_USER,cn=users,$VMDIR_DOMAIN_DN" -y $STAGE_DIR/.vmdir-user-password '(vmwSTSProviderType=IDENTITY_STORE_TYPE_LDAP_WITH_AD_MAPPING)' userCertificate 2>/dev/null | sed -e 's/^ //g' | grep '^userCertificate:' | awk '{print $NF}')
viewLDAPSCertInfo "$LDAP_CERTS" "$domain" 'AD over LDAPS'
done
fi
if [[ "$VC_VERSION" =~ ^[78] ]]; then
ADFS_LDAPS_CERTS=$($LDAP_SEARCH -o ldif-wrap=no -LLL -h $PSC_LOCATION -p $VMDIR_PORT -b "cn=VCIdentityProviders,cn=$SSO_DOMAIN,cn=Tenants,cn=IdentityManager,cn=Services,$VMDIR_DOMAIN_DN" -D "cn=$VMDIR_USER,cn=users,$VMDIR_DOMAIN_DN" -y $STAGE_DIR/.vmdir-user-password '(vmwSTSProviderType=IDENTITY_STORE_TYPE_LDAP_WITH_AD_MAPPING)' userCertificate 2>/dev/null | grep '^userCertificate' | awk -F':' '{print $NF}')
if [ -n "$ADFS_LDAPS_CERTS" ]; then
LDAP_CERTS=$ADFS_LDAPS_CERTS
LDAPS_DOMAINS+=("$ADFS_ISSUER|Microsoft ADFS")
viewLDAPSCertInfo "$LDAP_CERTS" "$ADFS_ISSUER" 'Microsoft ADFS'
fi
fi
}
#------------------------------
# View AD over LDAPS certificate info
#------------------------------
function viewLDAPSCertInfo() {
for hash in $1; do
TEMP_CERT=$(buildCertFromHash "$hash")
LDAPS_CERT_THUMBPRINT_LIST+=($(echo "$TEMP_CERT" | openssl x509 -noout -fingerprint -sha1 2>/dev/null | awk -F'=' '{print $NF}'))
LDAPS_CERT_HASHES+=($hash)
CERT_OUTPUT=$(viewBriefCertificateInfo "$TEMP_CERT")
if [[ "$2" =~ ^http ]]; then
CERT_OUTPUT+=$'\n'" External Issuer: $2"
else
CERT_OUTPUT+=$'\n'" Domain: $2"
fi
CERT_OUTPUT+=$'\n'" Identity Source Type: $3"
printf "%2s. %s\n\n" $LDAPS_CERT_COUNTER "$CERT_OUTPUT"
case $3 in
'AD over LDAPS')
LDAPS_CERT_DNS+=("cn=$2,cn=IdentityProviders,cn=$SSO_DOMAIN,cn=Tenants,cn=IdentityManager,cn=Services,$VMDIR_DOMAIN_DN")
;;
*)
ADFS_LDAP_PROVIDER_DN=$($LDAP_SEARCH -o ldif-wrap=no -LLL -h $PSC_LOCATION -p $VMDIR_PORT -b "cn=VCIdentityProviders,cn=$SSO_DOMAIN,cn=Tenants,cn=IdentityManager,cn=Services,$VMDIR_DOMAIN_DN" -D "cn=$VMDIR_USER,cn=users,$VMDIR_DOMAIN_DN" -y $STAGE_DIR/.vmdir-user-password '(objectclass=vmwSTSIdentityStore)' dn 2>>$LOG | awk '{print $NF}')
LDAPS_CERT_DNS+=("$ADFS_LDAP_PROVIDER_DN")
;;
esac
((++LDAPS_CERT_COUNTER))
done
}
#------------------------------
# Add LDAPS certificates
#------------------------------
function addLDAPSCerts() {
domain=$(echo "$SELECTED_LDAPS_DOMAIN" | awk -F '|' '{print $1}')
source_type=$(echo "$SELECTED_LDAPS_DOMAIN" | awk -F '|' '{print $2}')
case $source_type in
'Microsoft ADFS')
file_prefix='ldaps-adfs-cert-'
;;
*)
file_prefix="ldaps-$domain-cer-"
;;
esac
read -e -p $'\nEnter path to new LDAP server certificate(s): ' NEW_LDAPS_CERTS_INPUT
while [ ! -f "$NEW_LDAPS_CERTS_INPUT" ]; do read -e -p $'\n'"${YELLOW}File not found, enter path to new LDAP server certificate(s):${NORMAL} " NEW_LDAPS_CERTS_INPUT; done
if [ -f "$NEW_LDAPS_CERTS_INPUT" ]; then
csplit -s -z -f $STAGE_DIR/$file_prefix -b %02d.crt "$NEW_LDAPS_CERTS_INPUT" '/-----BEGIN CERTIFICATE-----/' '{*}'
exportSSOLDAPSCerts "$source_type" "$domain" "$file_prefix"
header 'Publish new LDAP server ceritifcates'
updateLDAPSCerts "$file_prefix"
fi
}
#------------------------------
# Remove LDAPS certificates
#------------------------------
function removeLDAPSCerts() {
domain=$(echo "$SELECTED_LDAPS_DOMAIN" | awk -F '|' '{print $1}')
source_type=$(echo "$SELECTED_LDAPS_DOMAIN" | awk -F '|' '{print $2}')
case $source_type in
'Microsoft ADFS')
file_prefix='ldaps-adfs-cert-'
;;
*)
file_prefix="ldaps-$domain-cer-"
;;
esac
read -p $'\nEnter the number(s) of the LDAP server certificate(s) to delete (multiple entries separated by a comma): ' REMOVE_LDAP_CERTS_INPUT
if [ -n "$REMOVE_LDAP_CERTS_INPUT" ]; then
logInfo "User has selected the following certificate(s) to delete: $REMOVE_LDAP_CERTS_INPUT"
exportSSOLDAPSCerts "$source_type" "$domain" "$file_prefix"
for index in $(echo "$REMOVE_LDAP_CERTS_INPUT" | tr -d ' ' | sed 's/,/ /g'); do
if [[ $index =~ ^[0-9]+$ ]]; then
to_delete_thumbprint=${LDAPS_CERT_THUMBPRINT_LIST[$((index - 1))]}
logInfo "Removing LDAPS certificate with thumbprint $to_delete_thumbprint"
for cert in $STAGE_DIR/$file_prefix*; do
[[ -e "$cert" ]] || break
current_thumbprint=$(openssl x509 -noout -fingerprint -sha1 -in $cert 2>/dev/null | awk -F'=' '{print $NF}')
if [ "$current_thumbprint" = "$to_delete_thumbprint" ]; then
logInfo "Removing $cert"
rm $cert 2>&1 | logDebug
fi
done
fi
done
header 'Publish new LDAP server ceritifcates'
updateLDAPSCerts "$file_prefix"
fi
}
#------------------------------
# Remove LDAP certificates
#------------------------------
function updateLDAPSCerts() {
domain=$(echo "$SELECTED_LDAPS_DOMAIN" | awk -F '|' '{print $1}')
source_type=$(echo "$SELECTED_LDAPS_DOMAIN" | awk -F '|' '{print $2}')
case $source_type in
'Microsoft ADFS')
LDAPS_UPDATE_DN=$($LDAP_SEARCH -LLL -o ldif-wrap=no -h $PSC_LOCATION -p $VMDIR_PORT -b "cn=VCIdentityProviders,cn=$SSO_DOMAIN,cn=Tenants,cn=IdentityManager,cn=Services,$VMDIR_DOMAIN_DN" -D "cn=$VMDIR_USER,cn=users,$VMDIR_DOMAIN_DN" -y $STAGE_DIR/.vmdir-user-password '(objectclass=vmwSTSIdentityStore)' dn | awk '{print $NF}')
;;
*)
LDAPS_UPDATE_DN="cn=$domain,cn=IdentityProviders,cn=$SSO_DOMAIN,cn=Tenants,cn=IdentityManager,cn=Services,$VMDIR_DOMAIN_DN"
;;
esac
echo "dn: $LDAPS_UPDATE_DN" > $STAGE_DIR/$1.ldif
echo 'changetype: modify' >> $STAGE_DIR/$1.ldif
echo 'replace: userCertificate' >> $STAGE_DIR/$1.ldif
for cert in $STAGE_DIR/$1*.crt; do
[[ -e "$cert" ]] || break
task "Staging certificate $(openssl x509 -noout -hash -in $cert 2>&1 | logDebug)"
CERT_BINARY_FILE=$(echo "$cert" | sed -e 's/.crt/.der/')
if openssl x509 -inform pem -outform der -in $cert -out $CERT_BINARY_FILE > /dev/null 2>&1; then
echo "userCertificate:< file://$CERT_BINARY_FILE" >> $STAGE_DIR/$1.ldif
statusMessage 'OK' 'GREEN'
else
statusMessage 'ERROR' 'YELLOW'
fi
done
task 'Update LDAPS certificates'
$LDAP_MODIFY -x -h $PSC_LOCATION -p $VMDIR_PORT -D "cn=$VMDIR_USER,cn=users,$VMDIR_DOMAIN_DN" -y $STAGE_DIR/.vmdir-user-password -f $STAGE_DIR/$1.ldif > /dev/null 2>&1 || errorMessage 'Unable to update LDAPS server certificates'
statusMessage 'OK' 'GREEN'
rm $STAGE_DIR/ldaps-$1-cert* 2>&1 | logDebug
}
#------------------------------
# Manage Tanzu Supervisor Cluster certificates
#------------------------------
function manageTanzuSupervisorClusterCerts() {
if tanzuSupervisorClustersPresent; then
case $1 in
'Check')
checkTanzuSupervisorCluseterCerts
;;
'View')
viewTanzuSupervisorCluseterCerts
;;
'Manage')
;;
esac
fi
}
#------------------------------
# Check certificates in the Tanzu Supervisor Clusters
#------------------------------
function checkTanzuSupervisorCluseterCerts() {
header 'Checking Tanzu Supervisor Cluster Certificates'
IFS=$'\n'
for line in $(/usr/lib/vmware-wcp/decryptK8Pwd.py | grep -E '^Cluster: |^IP: |^PWD: '); do
if [[ "$line" =~ ^Cluster ]]; then
TANZU_CLUSTER_ID=$(echo "$line" | awk '{print $NF}' | awk -F':' '{print $1}' | sed -e 's/domain-c//')
TANZU_CLUSTER=$(/opt/vmware/vpostgres/current/bin/psql -d VCDB -U postgres -c "SELECT e.name FROM vpx_entity AS e LEFT JOIN vpx_object_type AS ot ON e.type_id = ot.id WHERE ot.name='CLUSTER_COMPUTE_RESOURCE' AND e.id=$TANZU_CLUSTER_ID" -t | sed -e 's/^[[:space:]]*//g' | grep -v '^$')
fi
if [[ "$line" =~ ^IP ]]; then
TANZU_CLUSTER_IP=$(echo "$line" | awk '{print $NF}')
fi
if [[ "$line" =~ ^PWD ]]; then
TANZU_CLUSTER_PASSWD=$(echo "$line" | awk '{print $NF}')
echo "Cluster: $TANZU_CLUSTER"
logInfo "Checking cluster: $TANZU_CLUSTER"
ssh-keygen -R $TANZU_CLUSTER_IP 2>&1 | logDebug
sshpass -p "$TANZU_CLUSTER_PASSWD" ssh -q -o StrictHostKeyChecking=no -t -t root@$TANZU_CLUSTER_IP 'for cert in $(find / -type f \( -name "*.cert" -o -name "*.crt" \) -print 2>/dev/null | egrep -v "ca.crt$|ca-bundle.crt$|kubelet\/pods|var\/lib\/containerd|run\/containerd|bootstrapper"); do printf "%-52s" " $cert"; if openssl x509 -noout -in $cert -checkend 0 > /dev/null 2>&1; then printf "%13s\n" "VALID"; else printf "%13s\n" "EXPIRED"; fi; done' | sed -e "s/VALID/${GREEN}&${NORMAL}/g" -e "s/EXPIRED/${YELLOW}&${NORMAL}/g"
fi
done
IFS=$' \t\n'
}
#------------------------------
# View info on Tanzu Supervisor Cluster certificates
#------------------------------
function viewTanzuSupervisorCluseterCerts() {
header 'View Tanzu Supervisor Cluster Certificates'
TANZU_CLUSTERS=()
TANZU_CLUSTER_IDS=()
i=1
echo ''
for tanzu_cluster_id in $(/usr/lib/vmware-wcp/decryptK8Pwd.py | grep '^Cluster: ' | awk '{print $NF}' | awk -F':' '{print $1}' | sed -e 's/domain-c//'); do
TANZU_CLUSTER=$(/opt/vmware/vpostgres/current/bin/psql -d VCDB -U postgres -c "SELECT e.name FROM vpx_entity AS e LEFT JOIN vpx_object_type AS ot ON e.type_id = ot.id WHERE ot.name='CLUSTER_COMPUTE_RESOURCE' AND e.id=$tanzu_cluster_id" -t | sed -e 's/^[[:space:]]*//g' | grep -v '^$')
if [ -n "$TANZU_CLUSTER" ]; then
TANZU_CLUSTERS+=("$TANZU_CLUSTER")
TANZU_CLUSTER_IDS+=("$tanzu_cluster_id")
printf "%2s. %s\n" $i "$TANZU_CLUSTER"
fi
done
if [ -n "${TANZU_CLUSTERS[*]}" ]; then
read -p $'\nSelect Supervisor Cluster [Return to Main Menu]: ' TANZU_CLUSTER_INPUT
if [ -n "$TANZU_CLUSTER_INPUT" ]; then
TANZU_CLUSTER_NAME=${TANZU_CLUSTERS[$((TANZU_CLUSTER_INPUT - 1))]}
TANZU_CLUSTER_ID=${TANZU_CLUSTER_IDS[$((TANZU_CLUSTER_INPUT - 1))]}
TANZU_CLUSTER_INFO=$(/usr/lib/vmware-wcp/decryptK8Pwd.py | grep -A2 "domain-c$TANZU_CLUSTER_ID")
TANZU_CLUSTER_IP=$(echo "$TANZU_CLUSTER_INFO" | awk '/^IP: /{print $NF}')
TANZU_CLUSTER_PASSWD=$(echo "$TANZU_CLUSTER_INFO" | awk '/^PWD: /{print $NF}')
header "'$TANZU_CLUSTER_NAME' Certificates"
ssh-keygen -R $TANZU_CLUSTER_IP 2>&1 | logDebug
sshpass -p "$TANZU_CLUSTER_PASSWD" ssh -q -o StrictHostKeyChecking=no -t -t root@$TANZU_CLUSTER_IP 'for cert in $(find / -type f \( -name "*.cert" -o -name "*.crt" \) -print 2>/dev/null | egrep -v "ca.crt$|ca-bundle.crt$|kubelet\/pods|var\/lib\/containerd|run\/containerd|bootstrapper"); do echo "Cert: $cert"; openssl x509 -noout -in $cert -text; echo ''; done'
fi
fi
}
#------------------------------
# Check if STS Tenant Credential certificates have expired
#------------------------------
function checkSTSTenantCerts() {
CA_SKIDS=$($DIR_CLI trustedcert list --login $VMDIR_USER_UPN --password "$(cat $STAGE_DIR/.vmdir-user-password)" | grep '^CN' | awk '{print $NF}')
TENANT_CREDENTIAL_CERTS=$($LDAP_SEARCH -o ldif-wrap=no -LLL -h $PSC_LOCATION -p $VMDIR_PORT -b "cn=$SSO_DOMAIN,cn=Tenants,cn=IdentityManager,cn=Services,$VMDIR_DOMAIN_DN" -D "$VMDIR_MACHINE_ACCOUNT_DN" -y $STAGE_DIR/.machine-account-password '(objectclass=vmwSTSTenantCredential)' userCertificate)
IFS=$'\n'
for line in $TENANT_CREDENTIAL_CERTS; do
if [[ "$line" =~ ^dn: ]]; then
TENANT_CN=$(echo "$line" | awk '{print $NF}' | awk -F',' '{print $1}' | awk -F'=' '{print $NF}')
echo "Checking $TENANT_CN:"
else
hash=$(echo "$line" | awk '{print $NF}')
TEMP_CERT=$(buildCertFromHash "$hash")
if isCertCA "$TEMP_CERT"; then
checkSTSTenantCert "$TEMP_CERT" $TENANT_CN 'CA' "$CA_SKIDS"
else
checkSTSTenantCert "$TEMP_CERT" $TENANT_CN 'signing'
fi
fi
done
IFS=$' \t\n'
}
#------------------------------
# Check if STS Tenant Credential certificates have expired
#------------------------------
function checkSTSTrustedCertChains() {
CA_SKIDS=$($DIR_CLI trustedcert list --login $VMDIR_USER_UPN --password "$(cat $STAGE_DIR/.vmdir-user-password)" | grep '^CN' | awk '{print $NF}')
TENANT_TRUSTED_CERTS=$($LDAP_SEARCH -o ldif-wrap=no -LLL -h $PSC_LOCATION -p $VMDIR_PORT -b "cn=$SSO_DOMAIN,cn=Tenants,cn=IdentityManager,cn=Services,$VMDIR_DOMAIN_DN" -D "$VMDIR_MACHINE_ACCOUNT_DN" -y $STAGE_DIR/.machine-account-password '(&(objectclass=vmwSTSTenantTrustedCertificateChain)(cn=TrustedCertChain*))' userCertificate)
IFS=$'\n'
for line in $TENANT_TRUSTED_CERTS; do
if [[ "$line" =~ ^dn: ]]; then
CHAIN_CN=$(echo "$line" | awk '{print $NF}' | awk -F',' '{print $1}' | awk -F'=' '{print $NF}')
echo "Checking $CHAIN_CN:"
else
hash=$(echo "$line" | awk '{print $NF}')
TEMP_CERT=$(buildCertFromHash "$hash")
if isCertCA "$TEMP_CERT"; then
checkSTSTenantCert "$TEMP_CERT" $CHAIN_CN 'CA' "$CA_SKIDS"
else
checkSTSTenantCert "$TEMP_CERT" $CHAIN_CN 'signing'
fi
fi
done
IFS=$' \t\n'
}
#------------------------------
# Check if individual STS Signing certificate has expired
#------------------------------
function checkSTSTenantCert() {
task " $2 $3 certificate"
if ! isExpired "$1" 'hash'; then
CERT_SKID=$(echo "$1" | openssl x509 -noout -text | grep -A1 'Subject Key Id' | tail -n1 | tr -d ': ')
if ! echo "$4" | grep "$CERT_SKID" > /dev/null && [ "$3" == 'CA' ]; then
CERT_STATUS_MISSING_VMDIR=1
statusMessage 'MISSING' 'YELLOW'
return 0
else
DAYS_LEFT=$(checkCertExpireSoon "$1")
if [[ $DAYS_LEFT -gt 0 ]]; then
CERT_STATUS_EXPIRES_SOON=1
statusMessage "$DAYS_LEFT DAYS" 'YELLOW'
return 0
else
HAS_KEY_USAGE=$(checkCertKeyUsage "$1" "STS Tenant $2 $3")
if [[ $3 == 'signing' && $HAS_KEY_USAGE -gt 0 ]]; then
CERT_STATUS_KEY_USAGE=1
statusMessage 'KEY USAGE' 'YELLOW'
return 0
fi
statusMessage 'VALID' 'GREEN'
return 0
fi
fi
else
CERT_STATUS_EXPIRED=1
statusMessage 'EXPIRED' 'YELLOW'
return 1
fi
}
#------------------------------
# View STS Signing certificates
#------------------------------
function viewSTSTenantCerts() {
header 'View STS signing certificates'
TENANT_CREDENTIAL_ENTRIES=$($LDAP_SEARCH -o ldif-wrap=no -LLL -h $PSC_LOCATION -p $VMDIR_PORT -b "cn=$SSO_DOMAIN,cn=Tenants,cn=IdentityManager,cn=Services,$VMDIR_DOMAIN_DN" -D "$VMDIR_MACHINE_ACCOUNT_DN" -y $STAGE_DIR/.machine-account-password '(objectclass=vmwSTSTenantCredential)' userCertificate | grep -v '^$')
IFS=$'\n'
for line in $TENANT_CREDENTIAL_ENTRIES; do
if [[ "$line" =~ ^dn ]]; then
echo "$line" | awk '{print $2}' | awk -F ',' '{print $1}' | sed 's/cn=//'
else
hash=$(echo "$line" | awk '{print $NF}')
TEMP_CERT=$(buildCertFromHash "$hash")
CERT_INFO=$(viewBriefCertificateInfo "$TEMP_CERT")
if isCertCA "$TEMP_CERT"; then
CERT_OUTPUT=" Certificate Type: CA Certificate"$'\n '
else
CERT_OUTPUT=" Certificate Type: Signing Certificate"$'\n '
fi
CERT_OUTPUT+=$CERT_INFO
echo "$CERT_OUTPUT"$'\n'
fi
done
IFS=$' \t\n'
}
#------------------------------
# Check CA certificates in VMDir and VECS
#------------------------------
function checkCACertificates() {
VMDIR_CERTS=()
VECS_CERTS=()
CERT_STATUS_CA_DUPLICATES=0
exportTrustedCACerts
header 'Checking CA certificates in VMDir [by CN(id)]'
for cert in $(ls $TRUSTED_CA_DIR/*.crt); do
cert_file=$(echo "${cert##*/}")
skid=$(echo "${cert_file%%.*}")
SUBJECT_HASH=$(openssl x509 -noout -hash -in $cert 2>/dev/null)
task "${skid}"
CA_CERT=$(cat $cert)
if isExpired "$cert" 'file'; then
CERT_STATUS_EXPIRED=1
statusMessage 'EXPIRED' 'YELLOW'
elif ! isCertCA "$(cat $cert)"; then
CERT_STATUS_NON_CA=1
statusMessage 'NON-CA' 'YELLOW'
elif [ ! -z $SUBJECT_HASH ] && [[ "$(ls /etc/ssl/certs/$SUBJECT_HASH.[0-9] 2>/dev/null | wc -l)" -gt 1 ]]; then
CERT_STATUS_CA_DUPLICATES=1
statusMessage 'DUPLICATE' 'YELLOW'
elif ! checkCACertsPresent "$CA_CERT"; then
CERT_STATUS_MISSING_CA=1
statusMessage 'MISSING CA' 'YELLOW'
elif checkRogueCA "$CA_CERT"; then
CERT_ROGUE_CA=1
statusMessage 'ROGUE' 'YELLOW'
else
DAYS_LEFT=$(checkCertExpireSoon "$CA_CERT")
if ! openssl x509 -noout -text -in $cert 2>/dev/null | grep -q 'Subject Key Identifier:'; then
CERT_STATUS_CA_MISSING_SKID=1
statusMessage 'NO SKID' 'YELLOW'
elif [[ $DAYS_LEFT -gt 0 ]]; then
CERT_STATUS_EXPIRES_SOON=1
statusMessage "$DAYS_LEFT DAYS" 'YELLOW'
else
statusMessage 'VALID' 'GREEN'
fi
fi
done
header 'Checking CA certificates in VECS [by Alias]'
IFS=$'\n'
for alias in $($VECS_CLI entry list --store TRUSTED_ROOTS 2>>$LOG | grep '^Alias' | awk '{print $NF}'); do
logInfo "Checking certificate with alias '$alias'"
TEMP_VECS_CERT=$($VECS_CLI entry getcert --store TRUSTED_ROOTS --alias "$alias" 2>>$LOG)
SUBJECT_HASH=$(echo "$TEMP_VECS_CERT" | openssl x509 -noout -hash 2>/dev/null)
task $alias
if isExpired "$TEMP_VECS_CERT" 'hash'; then
CERT_STATUS_EXPIRED=1
statusMessage 'EXPIRED' 'YELLOW'
elif ! isCertCA "$TEMP_VECS_CERT"; then
CERT_STATUS_NON_CA=1
statusMessage 'NON-CA' 'YELLOW'
elif [ ! -z $SUBJECT_HASH ] && [[ "$(ls /etc/ssl/certs/$SUBJECT_HASH.[0-9] 2>/dev/null | wc -l)" -gt 1 ]]; then
CERT_STATUS_CA_DUPLICATES=1
statusMessage 'DUPLICATE' 'YELLOW'
elif [ $(echo "$TEMP_VECS_CERT" | openssl x509 -fingerprint -sha1 -noout 2>/dev/null | cut -d '=' -f 2 | tr -d ':' | awk '{print tolower($0)}') != "$alias" ]; then
CERT_STATUS_BAD_ALIAS=1
statusMessage 'BAD ALIAS' 'YELLOW'
elif ! checkCACertsPresent "$TEMP_VECS_CERT"; then
CERT_STATUS_MISSING_CA=1
statusMessage 'MISSING CA' 'YELLOW'
elif checkRogueCA "$TEMP_VECS_CERT"; then
CERT_ROGUE_CA=1
statusMessage 'ROGUE' 'YELLOW'
else
DAYS_LEFT=$(checkCertExpireSoon "$TEMP_VECS_CERT")
if ! echo "$TEMP_VECS_CERT" | openssl x509 -noout -text 2>/dev/null | grep -q 'Subject Key Identifier:'; then
CERT_STATUS_CA_MISSING_SKID=1
statusMessage 'NO SKID' 'YELLOW'
elif [[ $DAYS_LEFT -gt 0 ]]; then
CERT_STATUS_EXPIRES_SOON=1
statusMessage "$DAYS_LEFT DAYS" 'YELLOW'
else
statusMessage 'VALID' 'GREEN'
fi
fi
done
IFS=$' \t\n'
}
#------------------------------
# Ensure all VMCA certificates have been published to VMware Directory
#------------------------------
function checkVMCACertsSSO() {
CERT_STATUS_VMCA_MISSING=0
header "Check for VMCA certificates in SSO"
CA_SKIDS=$($DIR_CLI trustedcert list --login $VMDIR_USER_UPN --password "$(cat $STAGE_DIR/.vmdir-user-password)" | grep '^CN' | awk '{print $NF}')
CA_ALIASES=$($VECS_CLI entry list --store TRUSTED_ROOTS | grep 'Alias' | awk '{print $NF}')
for dc in $($LDAP_SEARCH -o ldif-wrap=no -LLL -h $PSC_LOCATION -b "ou=Domain Controllers,$VMDIR_DOMAIN_DN" -D "cn=$VMDIR_USER,cn=users,$VMDIR_DOMAIN_DN" -y $STAGE_DIR/.vmdir-user-password cn | grep '^cn' | awk '{print $NF}'); do
task "$dc"
dc_vmca_hash=$(curl -k https://$dc/afd/vecs/ca --output /dev/stdout 2>/dev/null | openssl x509 -inform der 2>/dev/null)
if [ -z "$dc_vmca_hash" ]; then
DC_VMCA_RESPONSE=$(curl -k https://$dc/afd/vecs/ca --output $STAGE_DIR/$dc-vmca.crt -s -w "%{http_code}")
statusMessage 'UNRETRIEVABLE' 'YELLOW'
logInfo "Response code from https://$dc/afd/vecs/ca: $DC_VMCA_RESPONSE"
CERT_STATUS_VMCA_UNRETRIEVABLE=1
else
dc_vmca_skid=$(echo "$dc_vmca_hash" | openssl x509 -noout -text | grep -A1 'Subject Key Id' | tail -1 | tr -d ' :')
dc_vmca_fingerprint=$(echo "$dc_vmca_hash" | openssl x509 -noout -fingerprint -sha1 | awk -F '=' '{print $NF}' | tr -d ' :' | tr [[:upper:]] [[:lower:]])
if [ -z "$dc_vmca_skid" ]; then
if echo "$CA_ALIASES" | grep -q $dc_vmca_fingerprint; then
statusMessage 'CHECK VMDIR' 'YELLOW'
else
statusMessage 'MISSING VECS' 'YELLOW'
CERT_STATUS_VMCA_MISSING=1
fi
else
if echo "$CA_SKIDS" | grep -q $dc_vmca_skid; then
if echo "$CA_ALIASES" | grep -q $dc_vmca_fingerprint; then
statusMessage 'PRESENT' 'GREEN'
else
statusMessage 'MISSING VECS' 'YELLOW'
CERT_STATUS_VMCA_MISSING=1
fi
else
statusMessage 'MISSING VMDIR' 'YELLOW'
CERT_STATUS_VMCA_MISSING=1
fi
fi
fi
done
}
#------------------------------
# Publish new signing chain to VMDir
#------------------------------
function publishCASigningCertificates() {
csplit -s -z -f $STAGE_DIR/signing-ca-new- -b %02d.crt $1 '/-----BEGIN CERTIFICATE-----/' '{*}'
VMDIR_CA_SKIDS=$($DIR_CLI trustedcert list --login $VMDIR_USER --password "$(cat $STAGE_DIR/.vmdir-user-password)" | grep '^CN' | tr -d '\t' | awk -F':' '{print $2}')
for cert in $STAGE_DIR/signing-ca-new-*.crt; do
[[ -e "$cert" ]] || break
CURRENT_SKID=$(openssl x509 -noout -text -in $cert 2>/dev/null | grep -A1 'Subject Key Id' | tail -n1 | tr -d ' ' | sed 's/keyid://' | tr -d ':')
if echo "$VMDIR_CA_SKIDS" | grep -q "$CURRENT_SKID"; then
$DIR_CLI trustedcert get --id $CURRENT_SKID --login $VMDIR_USER --password "$(cat $STAGE_DIR/.vmdir-user-password)" --outcert $STAGE_DIR/signing-ca-old-$CURRENT_SKID.crt 2>&1 | logInfo
$DIR_CLI trustedcert unpublish --login $VMDIR_USER --password "$(cat $STAGE_DIR/.vmdir-user-password)" --cert $STAGE_DIR/signing-ca-old-$CURRENT_SKID.crt 2>&1 | logInfo
fi
done
$DIR_CLI trustedcert publish --chain --cert $TRUSTED_ROOT_CHAIN --login $VMDIR_USER_UPN --password "$(cat $STAGE_DIR/.vmdir-user-password)" 2>&1 | logInfo || errorMessage 'Unable to publish trusted root chain to VMDir'
statusMessage 'OK' 'GREEN'
rm $STAGE_DIR/signing-ca-new-*.crt $STAGE_DIR/signing-ca-old-*.crt 2>&1 | logDebug
}
#------------------------------
# Check if certificate is a CA cert
#------------------------------
function isCertCA() {
if echo "$1" | openssl x509 -noout -text 2>/dev/null | grep -A1 'X509v3 Basic Constraints' | grep -q 'CA:TRUE' && echo "$1" | openssl x509 -noout -text 2>/dev/null | grep -A1 'X509v3 Key Usage' | grep -q 'Certificate Sign'; then
return 0
else
return 1
fi
}
#------------------------------
# Quick check if Service Principal entries exist in VMware Directory
#------------------------------
function quickCheckServicePrincipals() {
header 'Checking Service Principals'
EXISTING_SERVICE_PRINCIPALS=$($DIR_CLI service list --login $VMDIR_USER_UPN --password "$(cat $STAGE_DIR/.vmdir-user-password)" 2>/dev/null)
if [ -n "$EXISTING_SERVICE_PRINCIPALS" ]; then
echo "Node $MACHINE_ID:"
for soluser in "${SOLUTION_USERS[@]}"; do
task " $soluser"
if echo "$EXISTING_SERVICE_PRINCIPALS" | grep "$soluser-$MACHINE_ID" > /dev/null 2>&1; then
statusMessage 'PRESENT' 'GREEN'
else
CERT_STATUS_SERVICE_PRINCIPAL_MISSING=1
statusMessage 'MISSING' 'YELLOW'
fi
done
else
task 'Listing SSO Service Principals'
errorMessage 'Could not get list of Service Principal entries from VMware Directory'
fi
}
#------------------------------
# Check if Service Principal entries exist in VMware Directory
#------------------------------
function checkServicePrincipals() {
task 'Verifying Service Principal entries exist'
MISSING_SERVICE_PRINCIPALS=''
EXISTING_SERVICE_PRINCIPALS=$($DIR_CLI service list --login $VMDIR_USER_UPN --password "$(cat $STAGE_DIR/.vmdir-user-password)" 2>&1)
if [ -n "$EXISTING_SERVICE_PRINCIPALS" ]; then
for soluser in "${SOLUTION_USERS[@]}"; do
if ! echo "$EXISTING_SERVICE_PRINCIPALS" | grep "$soluser-$MACHINE_ID" > /dev/null 2>&1; then
if [ -z "$MISSING_SERVICE_PRINCIPALS" ]; then MISSING_SERVICE_PRINCIPALS+="$soluser-$MACHINE_ID"; else MISSING_SERVICE_PRINCIPALS+=" $soluser-$MACHINE_ID"; fi
fi
done
if [ -n "$MISSING_SERVICE_PRINCIPALS" ]; then
statusMessage 'ERROR' 'RED'
echo $'\n'"${YELLOW}------------------------!!! Attention !!!------------------------ "
echo 'The following Service Principal entries are missing:'
for sp in $MISSING_SERVICE_PRINCIPALS; do
echo " - $sp"
done
echo $'\nPlease refer to KB https://knowledge.broadcom.com/external/article?legacyId=80469'
echo 'on using the lsdoctor utility to recreate the missing'
echo "Solution User/Service Principal entries.${NORMAL}"
exit
else
statusMessage 'OK' 'GREEN'
fi
else
errorMessage 'Could not get list of Service Principal entries from VMware Directory'
fi
}
#------------------------------
# Builds the expanded message detailng issues with certificates
#------------------------------
function buildCertificateStatusMessage() {
if [ $CERT_STATUS_EXPIRES_SOON == 1 ]; then CERT_STATUS_MESSAGE+=$' - One or more certificates are expiring within 30 days\n'; fi
if [ $CERT_STATUS_MISSING_PNID == 1 ]; then CERT_STATUS_MESSAGE+=" - One or more certificates are missing the PNID ($PNID) from the SAN entry"$'\n'; fi
if [ $CERT_STATUS_KEY_USAGE == 1 ]; then
CERT_STATUS_MESSAGE+=$' - One or more certificates do not have the recommended\n'
CERT_STATUS_MESSAGE+=$' Key Usage values\n'; fi
if [ $CERT_STATUS_CA_DUPLICATES == 1 ]; then
CERT_STATUS_MESSAGE+=$' - Two or more CA certificates in VMWare Directory or VECS\n'
CERT_STATUS_MESSAGE+=$' have the same Subject string, which can cause issues with\n'
CERT_STATUS_MESSAGE+=$' certificate validation\n'
fi
if [ $CERT_STATUS_EXPIRED == 1 ]; then CERT_STATUS_MESSAGE+=$' - One or more certificates are expired\n'; fi
if [ $CERT_STATUS_NON_CA == 1 ]; then CERT_STATUS_MESSAGE+=$' - One or more certificates are not CA certificates\n'; fi
if [ $CERT_STATUS_BAD_ALIAS == 1 ]; then CERT_STATUS_MESSAGE+=$' - One or more entries in the TRUSTED_ROOTS store have an alias that is not the SHA1 thumbprint\n'; fi
if [ $CERT_STATUS_MISSING_SAN == 1 ]; then CERT_STATUS_MESSAGE+=$' - One or more certificates do not have any Subject Alternative Name values\n'; fi
if [ $CERT_STATUS_SHA1_SIGNING == 1 ]; then CERT_STATUS_MESSAGE+=$' - One or more certificates are signed using the SHA-1 algorithm\n'; fi
if [ $CERT_STATUS_MISSING == 1 ]; then CERT_STATUS_MESSAGE+=$' - One or more certificates are missing\n'; fi
if [ $CERT_ROGUE_CA == 1 ]; then
CERT_STATUS_MESSAGE+=$' - One or more certificates are invalid because it or a signing CA\n'
CERT_STATUS_MESSAGE+=$' extends beyond the pathlen restrictions of a parent CA\n'
fi
if [ $CERT_STATUS_MISSING_VMDIR == 1 ]; then
CERT_STATUS_MESSAGE+=$' - One or more CA certificates are missing from\n'
CERT_STATUS_MESSAGE+=$' VMware Directory\n'
fi
if [ $CERT_STATUS_VMCA_UNRETRIEVABLE == 1 ]; then
CERT_STATUS_MESSAGE+=$' - Could not retrieve one or more VMCA certificates\n'
CERT_STATUS_MESSAGE+=$' from a vCenter/PSC in this SSO domain\n'
fi
if [ $CERT_STATUS_VMCA_MISSING == 1 ]; then
CERT_STATUS_MESSAGE+=$' - One or more VMCA certificates are missing from\n'
CERT_STATUS_MESSAGE+=$' VMware Directory or VECS\n'
fi
if [ $CERT_STATUS_MISMATCH_SERVICE_PRINCIPAL == 1 ]; then
CERT_STATUS_MESSAGE+=$' - One or more Solution User certificates does not match\n'
CERT_STATUS_MESSAGE+=$' the Service Principal certificate in VMware Directory\n'
fi
if [ $CERT_STATUS_MISSING_CA == 1 ]; then
CERT_STATUS_MESSAGE+=$' - One or more certificates do not have all of the CA\n'
CERT_STATUS_MESSAGE+=$' certificates in its signing chain in VMware Directory\n'
fi
if [ $CERT_STATUS_EXPIRED_EMBEDDED_CA == 1 ]; then
CERT_STATUS_MESSAGE+=$' - One or more certificates has a CA certificate embedded\n'
CERT_STATUS_MESSAGE+=$' in its chain that is expired\n'
fi
if [ $CERT_STATUS_UNSUPPORTED_SIGNATURE_ALGORITHM == 1 ]; then
CERT_STATUS_MESSAGE+=$' - One or more certificates are using an unsupported\n'
CERT_STATUS_MESSAGE+=$' signature algorithm'
fi
if [ $CERT_STATUS_STORE_MISSING == 1 ]; then CERT_STATUS_MESSAGE+=$' - One or more VECS stores are missing\n'; fi
if [ $CERT_STATUS_STORE_PERMISSIONS == 1 ]; then CERT_STATUS_MESSAGE+=$' - One or more VECS stores are missing permissions\n'; fi
if [ $CERT_STATUS_SERVICE_PRINCIPAL_MISSING == 1 ]; then
CERT_STATUS_MESSAGE+=$' - One or more Service Principal entries are missing\n'
CERT_STATUS_MESSAGE+=$' from VMware Directory\n'; fi
if [ $TRUST_ANCHORS_MISMATCH == 1 ]; then
CERT_STATUS_MESSAGE+=$' - One or more vCenter/PSC nodes have mismatched SSL trust anchors\n'
fi
if [ $TRUST_ANCHORS_UNKNOWN == 1 ]; then
CERT_STATUS_MESSAGE+=$' - The Machine SSL certificate could not be obtained from\n'
CERT_STATUS_MESSAGE+=$' one or more nodes to check SSL trust anchors\n'
fi
if [ $TRUST_ANCHOR_CHECK_SAN == 1 ]; then
CERT_STATUS_MESSAGE+=$' - The SSL trust anchors for one or more nodes do not contain\n'
CERT_STATUS_MESSAGE+=$' the hostname/IP in the SAN that is used in the registration\n'
CERT_STATUS_MESSAGE+=$' endpoint URIs\n'
fi
if [ $TRUST_ANCHORS_CHECK_URI == 1 ]; then
if [ $TRUST_ANCHORS_STATUS_URI_MISMATCH == 1 ]; then
CERT_STATUS_MESSAGE+=$' - One or more vCenter/PSC nodes have mismatched SSL trust anchors and\n'
CERT_STATUS_MESSAGE+=$' have Lookup Service registrations using the IP address instead\n'
CERT_STATUS_MESSAGE+=$' of the PNID in the endpoint URIs. These can be fixed with the\n'
CERT_STATUS_MESSAGE+=$' lsdoctor utility: https://knowledge.broadcom.com/external/article?legacyId=80469\n'
else
CERT_STATUS_MESSAGE+=$' - One or more vCenter/PSC nodes have Lookup Service registrations\n'
CERT_STATUS_MESSAGE+=$' using the IP address instead of the PNID in the endpoint URIs.\n'
CERT_STATUS_MESSAGE+=$' These can be fixed with the lsdoctor utility:\n'
CERT_STATUS_MESSAGE+=$' https://knowledge.broadcom.com/external/article?legacyId=80469\n'
fi
fi
if [ $CERT_STATUS_TOO_MANY_CRLS == 1 ]; then CERT_STATUS_MESSAGE+=' - The number of CRLs in VECS may be preventing some services from starting'; fi
if [ $CERT_STATUS_VMCA_EMPTY_CONFIG == 1 ]; then
CERT_STATUS_MESSAGE+=$' - There are one or more vpxd.certmgmt.certs.cn.* settings with empty values\n'
CERT_STATUS_MESSAGE+=$' This can cause issues pushing VMCA-signed certificates to ESXi hosts\n'
fi
if [ $CERT_STATUS_VMCA_MODE == 1 ]; then
CERT_STATUS_MESSAGE+=" - The certificate management mode is set to 'thumbprint'"$'\n'
CERT_STATUS_MESSAGE+=" This is not recommended, and should be set to 'vmca' or 'custom'"$'\n'
fi
if [ $CERT_STATUS_CLIENT_CA_LIST_FILE_LOCATION == 1 ]; then
CERT_STATUS_MESSAGE+=" - The Smart Card issuing CA filter file does not reference this file:"$'\n'
CERT_STATUS_MESSAGE+=" /usr/lib/vmware-sso/vmware-sts/conf/clienttrustCA.pem"
fi
if [ $CERT_STATUS_CLIENT_CA_LIST_FILE_MISSING == 1 ]; then
CERT_STATUS_MESSAGE+=$' - The Smart Card issuing CA filter file at\n'
CERT_STATUS_MESSAGE+=" $CAC_FILTER_FILE"$'\n'
CERT_STATUS_MESSAGE+=$' does not exist\n'
fi
if [ $CERT_STATUS_STS_VECS_CONFIG == 1 ]; then
CERT_STATUS_MESSAGE+=$' - The STS server is configured to use a VECS store other than\n'
CERT_STATUS_MESSAGE+=$' the MACHINE_SSL_CERT store\n'
fi
if [ $CERT_STATUS_STS_CONNECTION_STRINGS == 1 ]; then
CERT_STATUS_MESSAGE+=$' - The STS ConnectionStrings value is not set properly for an SSO\n'
CERT_STATUS_MESSAGE+=$' domain with multiple Domain Controllers\n'
fi
if [ $CERT_STATUS_CA_MISSING_SKID == 1 ]; then
CERT_STATUS_MESSAGE+=$' - One or more CA certificates are missing the Subject Key ID extension'
fi
if [ $SERVICE_RESTART_PENDING == 1 ]; then
CERT_STATUS_MESSAGE+=$' - The current Machine SSL certificate is not being served on port\n'
CERT_STATUS_MESSAGE+=$' 443 due to a pending service restart\n'
fi
}
#------------------------------
# Check the number of CRLs in VECS
#------------------------------
function checkCRLs() {
CERT_STATUS_TOO_MANY_CRLS=0
NUM_CRLS=$($VECS_CLI entry list --store TRUSTED_ROOT_CRLS | head -n1 | awk '{print $NF}')
header 'Checking Certificate Revocation Lists'
task 'Number of CRLs in VECS'
if [ $NUM_CRLS -le 30 ]; then
statusMessage "$NUM_CRLS" 'GREEN'
elif [ $NUM_CRLS -le 100 ]; then
statusMessage "$NUM_CRLS" 'YELLOW'
else
statusMessage "$NUM_CRLS" 'RED'
CERT_STATUS_TOO_MANY_CRLS=1
fi
}
#------------------------------
# Clear CRLs in VECS
#------------------------------
function clearCRLs() {
header 'Clear Certificate Revocation Lists in VECS'
task 'Backup CRLs'
if [ ! -d $BACKUP_DIR/old-CRLs ]; then mkdir $BACKUP_DIR/old-CRLs 2>/dev/null || errorMessage 'Unable to create backup CRL directory'; fi
find /etc/ssl/certs -type f -iname '*.r[0-9]' -exec mv {} $BACKUP_DIR/old-CRLs \; || errorMessage "Unable to move CRL files to $BACKUP_DIR/old-CRLs"
statusMessage 'OK' 'GREEN'
task 'Delete CRLs from VECS (this may take some time)'
for alias in $($VECS_CLI entry list --store TRUSTED_ROOT_CRLS | grep Alias | awk '{print $NF}'); do
logInfo "Removing CRL $alias from VECS"
$VECS_CLI entry delete --store TRUSTED_ROOT_CRLS --alias $alias -y > /dev/null 2>&1
done
statusMessage 'OK' 'GREEN'
if [ $NODE_TYPE != 'management' ]; then
promptRestartVMwareServices 'vmafdd' 'vmdird' 'vmcad'
else
promptRestartVMwareServices 'vmafdd'
fi
}
#------------------------------
# Clear BACKUP_STORE in VECS
#------------------------------
function clearBackupStore() {
if checkVECSStore 'BACKUP_STORE'; then
header 'Clear BACKUP_STORE'
for alias in $($VECS_CLI entry list --store BACKUP_STORE | grep Alias | awk '{print $NF}'); do
task "Removing $alias"
$VECS_CLI entry delete --store BACKUP_STORE --alias $alias -y > /dev/null 2>&1 || errorMessage "Unable to remove $alias entry from BACKUP_STORE"
statusMessage 'OK' 'GREEN'
done
fi
if checkVECSStore 'BACKUP_STORE_H5C'; then
header 'Clear BACKUP_STORE_H5C'
for alias in $($VECS_CLI entry list --store BACKUP_STORE_H5C | grep Alias | awk '{print $NF}'); do
task "Removing $alias"
$VECS_CLI entry delete --store BACKUP_STORE_H5C --alias $alias -y > /dev/null 2>&1 || errorMessage "Unable to remove $alias entry from BACKUP_STORE_H5C"
statusMessage 'OK' 'GREEN'
done
fi
}
#------------------------------
# Clear __MACHINE_CSR in VECS
#------------------------------
function clearMachineSSLCSR() {
unset DELETE_MACHINE_CSR_INPUT
echo $'\n'"${YELLOW}-------------------------!!! WARNING !!!-------------------------"
echo "This entry was created using the 'Generate Certificate"
echo "Signing Request (CSR)' option from the vSphere Client."
echo 'It contains the corresponding private key associated'
echo 'with this CSR. DO NOT DELETE if you are still waiting'
echo "for this request to be signed by your Certificate Authority!${NORMAL}"
read -p $'\nDelete the __MACHINE_CSR entry from VECS? [n]: ' DELETE_MACHINE_CSR_INPUT
if [ -z $DELETE_MACHINE_CSR_INPUT ]; then DELETE_MACHINE_CSR_INPUT='n'; fi
if [[ $DELETE_MACHINE_CSR_INPUT =~ ^[Yy] ]]; then
header 'Delete Machine SSL CSR entry in VECS'
task 'Backup private key'
$VECS_CLI entry getkey --store MACHINE_SSL_CERT --alias __MACHINE_CSR > $BACKUP_DIR/__MACHINE_CSR.key 2>&1 || errorMessage 'Unable to backup private key in __MACHINE_CSR entry from VECS'
statusMessage 'OK' 'GREEN'
task 'Delete entry in MACHINE_SSL_CERT store'
$VECS_CLI entry delete --store MACHINE_SSL_CERT --alias __MACHINE_CSR -y > /dev/null 2>&1 || errorMessage "Unable to delete entry '__MACHINE_CSR' from VECS"
statusMessage 'OK' 'GREEN'
fi
}
#------------------------------
# Perform quick check of SSL trust anchors
#------------------------------
function quickCheckSSLTrustAnchors() {
header 'Checking SSL Trust Anchors'
getSSODomainNodes
TRUST_ANCHORS_UNKNOWN=0
TRUST_ANCHORS_MISMATCH=0
TRUST_ANCHOR_CHECK_SAN=0
TRUST_ANCHORS_CHECK_URI=0
SERVICE_RESTART_PENDING=0
for node in "${SSO_NODES[@]}"; do
TRUST_ANCHORS_STATUS_MISMATCH=0
TRUST_ANCHORS_STATUS_CHECK_URI=0
TRUST_ANCHORS_STATUS_URI_MISMATCH=0
TRUST_ANCHORS_STATUS_URI_SAN=0
TRUST_ANCHORS_SERVICE_RESTART_PENDING=0
task "$node"
NODE_IP=$(dig +short "$node")
NODE_LC=$(echo "$node" | awk '{print tolower($0)}')
logInfo 'Checking node name against IP'
logDetails "Node: $node"
logDetails "IP: $NODE_IP"
if [[ $node =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
NODE_SAN_CHECK='IP'
else
NODE_SAN_CHECK='FQDN'
fi
if [[ "$NODE_LC" == "$PNID_LC" ]] || [[ "$NODE_IP" == "$IP" ]]; then
MACHINE_SSL_VECS_THUMBPRINT=$($VECS_CLI entry getcert --store MACHINE_SSL_CERT --alias __MACHINE_CERT | openssl x509 -noout -fingerprint -sha1 | awk -F'=' '{print $NF}')
MACHINE_SSL_ENVOY_THUMBPRINT=$(echo | timeout 3 openssl s_client -connect $node:443 2>/dev/null | openssl x509 -noout -fingerprint -sha1 2>/dev/null | awk -F'=' '{print $NF}')
if [[ "$MACHINE_SSL_VECS_THUMBPRINT" != "$MACHINE_SSL_ENVOY_THUMBPRINT" ]]; then
TRUST_ANCHORS_SERVICE_RESTART_PENDING=1
SERVICE_RESTART_PENDING=1
fi
NODE_MACHINE_SSL_THUMBPRINT=$MACHINE_SSL_VECS_THUMBPRINT
else
NODE_MACHINE_SSL_THUMBPRINT=$(echo | timeout 3 openssl s_client -connect $node:443 2>/dev/null | openssl x509 -noout -fingerprint -sha1 2>/dev/null | awk -F'=' '{print $NF}')
fi
NODE_MACHINE_SSL_SAN=$(echo | timeout 3 openssl s_client -connect $node:443 2>/dev/null | openssl x509 -noout -text | grep -A1 'X509v3 Subject Alternative Name' | tail -n1)
if [ -n "$NODE_MACHINE_SSL_THUMBPRINT" ]; then
TRUST_ANCHOR_SEARCH_FILTER="(&(|(vmwLKUPURI=https://$node:*)(vmwLKUPURI=https://$node/*))(|(objectclass=vmwLKUPServiceEndpoint)(objectclass=vmwLKUPEndpointRegistration)))"
NODE_TRUST_ANCHORS=$($LDAP_SEARCH -o ldif-wrap=no -LLL -h $PSC_LOCATION -p $VMDIR_PORT -b "cn=Sites,cn=Configuration,$VMDIR_DOMAIN_DN" -D "$VMDIR_MACHINE_ACCOUNT_DN" -y $STAGE_DIR/.machine-account-password "$TRUST_ANCHOR_SEARCH_FILTER" vmwLKUPEndpointSslTrust vmwLKUPSslTrustAnchor 2>>$LOG | grep -v '^dn:' | awk '{print $NF}' | sort | uniq)
if [ -z "$NODE_TRUST_ANCHORS" ]; then
TRUST_ANCHOR_SEARCH_FILTER="(&(|(vmwLKUPURI=https://$NODE_IP:*)(vmwLKUPURI=https://$NODE_IP/*))(|(objectclass=vmwLKUPServiceEndpoint)(objectclass=vmwLKUPEndpointRegistration)))"
NODE_TRUST_ANCHORS=$($LDAP_SEARCH -o ldif-wrap=no -LLL -h $PSC_LOCATION -p $VMDIR_PORT -b "cn=Sites,cn=Configuration,$VMDIR_DOMAIN_DN" -D "$VMDIR_MACHINE_ACCOUNT_DN" -y $STAGE_DIR/.machine-account-password "$TRUST_ANCHOR_SEARCH_FILTER" vmwLKUPEndpointSslTrust vmwLKUPSslTrustAnchor 2>>$LOG | grep -v '^dn:' | awk '{print $NF}' | sort | uniq)
TRUST_ANCHORS_CHECK_URI=1
TRUST_ANCHORS_STATUS_CHECK_URI=1
NODE_SAN_CHECK="IP"
fi
if [ -z "$NODE_TRUST_ANCHORS" ]; then
statusMessage 'MISSING' 'YELLOW'
else
case $NODE_SAN_CHECK in
'FQDN')
if [ "$node" != 'localhost' ] && ! echo "$NODE_MACHINE_SSL_SAN" | grep -iq "DNS:$node"; then
logInfo "The node name '$node' is missing as a DNS entry in the SAN'"
TRUST_ANCHORS_STATUS_URI_SAN=1
TRUST_ANCHOR_CHECK_SAN=1
fi
;;
'IP')
if ! echo "$NODE_MACHINE_SSL_SAN" | grep -iq "IP Address:$NODE_IP"; then
logInfo "The node name '$node' is missing as an IP entry in the SAN'"
TRUST_ANCHORS_STATUS_URI_SAN=1
TRUST_ANCHOR_CHECK_SAN=1
fi
;;
esac
for hash_raw in $NODE_TRUST_ANCHORS; do
logInfo "Checking following raw certificate hash"
logDetails "$hash_raw"
if [[ "$hash_raw" =~ ^TUl ]]; then
hash=$(echo $hash_raw | base64 --decode | tr -d '\r\n')
else
hash="$hash_raw"
fi
TEMP_CERT=$(buildCertFromHash "$hash")
ANCHOR_THUMBPRINT=$(echo "$TEMP_CERT" | openssl x509 -noout -fingerprint -sha1 2>/dev/null | awk -F'=' '{print $NF}')
logInfo "Checking node thumbprint $NODE_MACHINE_SSL_THUMBPRINT against unique trust anchor thumbprint $ANCHOR_THUMBPRINT"
if [ "$NODE_MACHINE_SSL_THUMBPRINT" != "$ANCHOR_THUMBPRINT" ]; then
TRUST_ANCHORS_STATUS_MISMATCH=1
TRUST_ANCHORS_MISMATCH=1
if [ $TRUST_ANCHORS_CHECK_URI -eq 1 ]; then TRUST_ANCHORS_STATUS_URI_MISMATCH=1; fi
fi
done
logInfo 'Searching for ghost trust anchors'
CURRENT_DN=''
CURRENT_NODEID=''
VCENTERSERVER_REGS=$($LDAP_SEARCH -o ldif-wrap=no -LLL -h $PSC_LOCATION -b "cn=Sites,cn=Configuration,$VMDIR_DOMAIN_DN" -D "cn=$VMDIR_USER,cn=users,$VMDIR_DOMAIN_DN" -y $STAGE_DIR/.vmdir-user-password '(vmwLKUPType=vcenterserver)' vmwLKUPDeploymentNodeId | sed 's/, cn/,cn/g')
IFS=$'\n'
for line in $VCENTERSERVER_REGS; do
if [[ $line =~ ^dn: ]]; then
CURRENT_DN=${line//dn: /}
else
CURRENT_NODEID=${line//vmwLKUPDeploymentNodeId: /}
VCENTERSERVER_ENDPOINTS=$($LDAP_SEARCH -o ldif-wrap=no -LLL -h $PSC_LOCATION -b "$CURRENT_DN" -D "cn=$VMDIR_USER,cn=users,$VMDIR_DOMAIN_DN" -y $STAGE_DIR/.vmdir-user-password '(objectclass=vmwLKUPEndpointRegistration)' vmwLKUPURI)
logDebug "Searching for vcenterserver registrations tied to Node ID '$CURRENT_NODEID'"
if [ -n "$VCENTERSERVER_ENDPOINTS" ]; then
if echo "$VCENTERSERVER_ENDPOINTS" | grep -qE "https://$node/|https://$node:|https://$NODE_IP/|https://$NODE_IP:"; then
logDebug "Found vcenterserver registration for $NODE_FQDN: '$CURRENT_NODEID'"
GHOST_VMONAPI_DN=$($LDAP_SEARCH -o ldif-wrap=no -LLL -h $PSC_LOCATION -b "cn=Sites,cn=Configuration,$VMDIR_DOMAIN_DN" -D "cn=$VMDIR_USER,cn=users,$VMDIR_DOMAIN_DN" -y $STAGE_DIR/.vmdir-user-password "(&(vmwLKUPType=cis.vmonapi)(vmwLKUPDeploymentNodeId=$CURRENT_NODEID))" dn | sed -e 's/, cn/,cn/g' -e 's/^dn: //g')
if [ -n "$GHOST_VMONAPI_DN" ]; then
logDebug "cis.vmonapi registration DN: $GHOST_VMONAPI_DN"
GHOST_VMONAPI_ENDPOINT_TRUST_ANCHORS=$($LDAP_SEARCH -o ldif-wrap=no -LLL -h $PSC_LOCATION -b "$GHOST_VMONAPI_DN" -D "cn=$VMDIR_USER,cn=users,$VMDIR_DOMAIN_DN" -y $STAGE_DIR/.vmdir-user-password '(vmwLKUPURI=http://localhost*)' vmwLKUPEndpointSslTrust | grep '^vmwLKUPEndpointSslTrust' | awk '{print $NF}' | sort | uniq)
for hash_raw in $GHOST_VMONAPI_ENDPOINT_TRUST_ANCHORS; do
if [[ "$hash_raw" =~ ^TUl ]]; then
hash=$(echo $hash_raw | base64 --decode | tr -d '\r\n')
else
hash="$hash_raw"
fi
TEMP_CERT=$(buildCertFromHash "$hash")
ANCHOR_THUMBPRINT=$(echo "$TEMP_CERT" | openssl x509 -noout -fingerprint -sha1 2>/dev/null | awk -F'=' '{print $NF}')
logInfo "Checking node thumbprint $NODE_MACHINE_SSL_THUMBPRINT against unique trust anchor thumbprint $ANCHOR_THUMBPRINT"
if [ "$NODE_MACHINE_SSL_THUMBPRINT" != "$ANCHOR_THUMBPRINT" ]; then
TRUST_ANCHORS_STATUS_MISMATCH=1
TRUST_ANCHORS_MISMATCH=1
fi
done
fi
fi
fi
fi
done
if [ $TRUST_ANCHORS_STATUS_MISMATCH -eq 0 ]; then
if [ $TRUST_ANCHORS_STATUS_CHECK_URI -eq 1 ]; then
if [ $TRUST_ANCHORS_STATUS_URI_SAN -eq 1 ]; then
statusMessage 'CHECK SAN' 'YELLOW'
else
statusMessage 'CHECK URI' 'YELLOW'
fi
elif [ $TRUST_ANCHORS_SERVICE_RESTART_PENDING -eq 1 ]; then
statusMessage 'PENDING' 'YELLOW'
else
statusMessage 'VALID' 'GREEN'
fi
else
if [ $TRUST_ANCHORS_STATUS_URI_SAN -eq 1 ]; then
statusMessage 'CHECK SAN' 'YELLOW'
elif [ $TRUST_ANCHORS_CHECK_URI -eq 1 ]; then
statusMessage 'MISMATCH*' 'YELLOW'
else
statusMessage 'MISMATCH' 'YELLOW'
fi
fi
fi
else
TRUST_ANCHORS_UNKNOWN=1
statusMessage 'UNKNOWN' 'YELLOW'
fi
done
}
#------------------------------
# Get the PSC and vCenter nodes in an SSO Domain
#------------------------------
function getSSODomainNodes() {
SSO_NODES=()
PSC_NODES=$($LDAP_SEARCH -o ldif-wrap=no -LLL -h $PSC_LOCATION -p $VMDIR_PORT -b "ou=Domain Controllers,$VMDIR_DOMAIN_DN" -D "cn=$VMDIR_USER,cn=users,$VMDIR_DOMAIN_DN" -y $STAGE_DIR/.vmdir-user-password '(objectclass=computer)' cn | grep '^cn:' | awk '{print $NF}')
PSC_COUNT=$(echo "$PSC_NODES" | wc -l)
VCENTER_NODES=$($LDAP_SEARCH -o ldif-wrap=no -LLL -h $PSC_LOCATION -p $VMDIR_PORT -b "ou=Computers,$VMDIR_DOMAIN_DN" -D "cn=$VMDIR_USER,cn=users,$VMDIR_DOMAIN_DN" -y $STAGE_DIR/.vmdir-user-password '(objectclass=computer)' cn | grep '^cn:' | awk '{print $NF}')
VCENTER_COUNT=$(echo "$VCENTER_NODES" | wc -l)
for psc_node in $PSC_NODES; do
if [[ ! "${SSO_NODES[*]}" =~ "$psc_node" ]]; then SSO_NODES+=($psc_node); fi
done
for vc_node in $VCENTER_NODES; do
if [[ ! "${SSO_NODES[*]}" =~ "$vc_node" ]]; then SSO_NODES+=($vc_node); fi
done
}
#------------------------------
# Print menu to view or manage certificates
#------------------------------
function printCertificateMenu() {
authenticateIfNeeded
header "$1 vCenter Certificates"
logInfo "Printing the $1 vCenter Certificates Menu"
echo ' 1. Machine SSL certificate'
echo ' 2. Solution User certificates'
echo ' 3. CA certificates in VMware Directory'
echo ' 4. CA certificates in VECS'
if [ $NODE_TYPE = 'infrastructure' ]; then printf "%s" "$YELLOW"; fi
echo ' 5. Authentication Proxy certificate'
echo ' 6. Auto Deploy CA certificate'
echo ' 7. SMS certificates'
if [ "$VC_VERSION" == '6.5' ]; then printf "%s" "$YELLOW"; fi
echo ' 8. Data Encipherment certificate'
printf "%s" "$NORMAL"
if [ $NODE_TYPE = 'infrastructure' ]; then printf "%s" "$YELLOW"; fi
echo ' 9. vCenter Extension thumbprints'
printf "%s" "$NORMAL"
if [ $NODE_TYPE = 'management' ]; then
printf "%s" "$YELLOW"
else
printf "%s" "$NORMAL"
fi
echo '10. VMware Directory certificate'
echo '11. STS signing certificates'
echo '12. VMCA certificate'
if ! configuredForCAC; then printf "%s" "$YELLOW"; fi
echo '13. Smart Card CA certificates'
printf "%s" "$NORMAL"
if ! configuredForADoverLDAPS; then printf "%s" "$YELLOW"; fi
echo '14. LDAPS Identity Source certificates'
printf "%s" "$NORMAL"
if ! tanzuSupervisorClustersPresent || [ "$1" == 'Manage' ]; then printf "%s" "$YELLOW"; fi
echo '15. Tanzu Supervisor Cluster certificates'
printf "%s" "$NORMAL"
if [ "$1" == 'Manage' ]; then
if ! checkVECSStore 'BACKUP_STORE' && ! checkVECSStore 'BACKUP_STORE_H5C'; then printf "%s" "$YELLOW"; fi
echo '16. Clear BACKUP_STORE in VECS'
printf "%s" "$NORMAL"
echo '17. Clear TRUSTED_ROOT_CRLS store in VECS'
if ! checkMachineSSLCSR; then printf "%s" "$YELLOW"; fi
echo '18. Clear Machine SSL CSR in VECS'
printf "%s" "$NORMAL"
fi
echo ''
}
#------------------------------
# Check if Smart Card authentication is configured
#------------------------------
function configuredForCAC() {
if $LDAP_SEARCH -o ldif-wrap=no -LLL -h $PSC_LOCATION -p $VMDIR_PORT -b "cn=$SSO_DOMAIN,cn=Tenants,cn=IdentityManager,cn=Services,$VMDIR_DOMAIN_DN" -D "cn=$VMDIR_USER,cn=users,$VMDIR_DOMAIN_DN" -y $STAGE_DIR/.vmdir-user-password '(objectclass=vmwSTSTenant)' vmwSTSAuthnTypes | grep -q 'vmwSTSAuthnTypes: 4'; then
return 0
else
return 1
fi
}
#------------------------------
# Check the an AD over LDAPS Identity Source is configured
#------------------------------
function configuredForADoverLDAPS() {
if $LDAP_SEARCH -o ldif-wrap=no -LLL -h $PSC_LOCATION -p $VMDIR_PORT -b "cn=IdentityProviders,cn=$SSO_DOMAIN,cn=Tenants,cn=IdentityManager,cn=Services,$VMDIR_DOMAIN_DN" -D "cn=$VMDIR_USER,cn=users,$VMDIR_DOMAIN_DN" -y $STAGE_DIR/.vmdir-user-password '(vmwSTSProviderType=IDENTITY_STORE_TYPE_LDAP_WITH_AD_MAPPING)' cn 2>/dev/null | grep cn > /dev/null 2>&1; then
logInfo 'vCenter is using AD over LDAPS as an Identity Source'
return 0
elif $LDAP_SEARCH -o ldif-wrap=no -LLL -h $PSC_LOCATION -p $VMDIR_PORT -b "cn=VCIdentityProviders,cn=$SSO_DOMAIN,cn=Tenants,cn=IdentityManager,cn=Services,$VMDIR_DOMAIN_DN" -D "cn=$VMDIR_USER,cn=users,$VMDIR_DOMAIN_DN" -y $STAGE_DIR/.vmdir-user-password '(vmwSTSProviderType=IDENTITY_STORE_TYPE_LDAP_WITH_AD_MAPPING)' cn 2>/dev/null | grep cn > /dev/null 2>&1; then
logInfo 'vCenter is using ADFS as an Identity Source'
return 0
elif $LDAP_SEARCH -o ldif-wrap=no -LLL -h $PSC_LOCATION -p $VMDIR_PORT -b "cn=IdentityProviders,cn=$SSO_DOMAIN,cn=Tenants,cn=IdentityManager,cn=Services,$VMDIR_DOMAIN_DN" -D "cn=$VMDIR_USER,cn=users,$VMDIR_DOMAIN_DN" -y $STAGE_DIR/.vmdir-user-password '(vmwSTSProviderType=IDENTITY_STORE_TYPE_LDAP)' cn 2>/dev/null | grep cn > /dev/null 2>&1; then
logInfo 'vCenter is using OpenLDAP as an Identity Source'
return 0
else
logInfo 'vCenter is NOT using AD over LDAPS as an Identity Source'
return 1
fi
}
#------------------------------
# Check if there are any Tanzu Supervisor clusters deployed
#------------------------------
function tanzuSupervisorClustersPresent() {
if [ -f /usr/lib/vmware-wcp/decryptK8Pwd.py ]; then
if /usr/lib/vmware-wcp/decryptK8Pwd.py | grep -E '^Cluster: |^IP: |^PWD: ' > /dev/null 2>&1; then
logInfo 'Tanzu Supervisor Clusters detected'
return 0
else
logInfo 'No Tanzu Supervisor Clusters detected'
return 1
fi
else
return 1
fi
}
#------------------------------
# Display options to view certificate info
#------------------------------
function viewCertificateMenu() {
printCertificateMenu 'View'
read -p 'Select an option [Return to Main Menu]: ' VIEW_CERT_OPERATION
logInfo "User selected option $VIEW_CERT_OPERATION"
if [[ "$VIEW_CERT_OPERATION" -ge 0 && "$VIEW_CERT_OPERATION" -le 15 ]]; then processViewCertificate; fi
}
#------------------------------
# Display options to manage certificates
#------------------------------
function manageCertificateMenu() {
printCertificateMenu 'Manage'
read -t $READ_TIMEOUTS -p 'Select an option [Return to Main Menu]: ' MANAGE_CERT_OPERATION
if [ $? -le 128 ]; then
logInfo "User selected option '$MANAGE_CERT_OPERATION'"
if [[ "$MANAGE_CERT_OPERATION" -ge 1 && "$MANAGE_CERT_OPERATION" -le 18 ]]; then processManageCertificate; fi
else
echo ''
fi
}
#------------------------------
# Process view certificate selection
#------------------------------
function processViewCertificate() {
case $VIEW_CERT_OPERATION in
1)
viewVECSCertificateInfo 'MACHINE_SSL_CERT' '__MACHINE_CERT'
;;
2)
for soluser in "${SOLUTION_USERS[@]}"; do
echo $'\n'"Solution User: $soluser"
viewVECSCertificateInfo "$soluser" "$soluser"
done
;;
3)
manageVMDirCACertificates 'View'
;;
4)
manageVECSCACertificates 'View'
;;
5)
viewFilesystemCertificateInfo '/var/lib/vmware/vmcam/ssl/vmcamcert.pem'
;;
6)
viewFilesystemCertificateInfo '/etc/vmware-rbd/ssl/rbd-ca.crt'
;;
7)
manageSMSCertificates 'View'
;;
8)
viewVECSCertificateInfo 'data-encipherment' 'data-encipherment'
;;
9)
manageVCExtensionThumbprints 'View'
;;
10)
if [[ "$VC_VERSION" =~ ^[78] ]]; then
viewRemoteCertificateInfo 'localhost' '636'
else
viewFilesystemCertificateInfo '/usr/lib/vmware-vmdir/share/config/vmdircert.pem'
fi
;;
11)
manageSTSTenantCerts 'View'
;;
12)
viewFilesystemCertificateInfo "$VMCA_CERT"
;;
13)
manageCACCerts 'View'
;;
14)
manageLDAPSCerts 'View'
;;
15)
manageTanzuSupervisorClusterCerts 'View'
;;
esac
}
#------------------------------
# Process manage certificate selection
#------------------------------
function processManageCertificate() {
setTimestamp
case $MANAGE_CERT_OPERATION in
1)
if promptReplaceMachineSSL; then
if replaceMachineSSLCert && [[ $UPDATED_MACHINE_SSL -eq 1 ]]; then
if [ $NODE_TYPE != 'infrastructure' ]; then
SSLTrustAnchorSelf
updateSSLTrustAnchors
manageVCExtensionThumbprints 'Update'
updateAutoDeployDB
fi
if [ $NODE_TYPE = 'infrastructure' ]; then
if [ -n "$PSC_LB" ]; then
NODE_FQDN="$PSC_LB"
else
SSLTrustAnchorSelf
fi
updateSSLTrustAnchors
fi
if [ -n "$SDDC_MANAGER" ]; then
publishMachineSSLCACertsSDDCManager
fi
noticePSCHA
promptRestartVMwareServices
fi
clearCSRInfo
fi
;;
2)
if promptReplaceSolutionUsers; then
if replaceSolutionUserCerts && [ $NODE_TYPE != 'infrastructure' ]; then
manageVCExtensionThumbprints 'Update'
promptRestartVMwareServices
fi
clearCSRInfo
fi
;;
3)
manageVMDirCACertificates 'Manage'
;;
4)
manageVECSCACertificates 'Manage'
;;
5)
if [ $NODE_TYPE != 'infrastructure' ]; then
if promptReplaceAuthProxy; then
if replaceAuthProxyCert; then
manageVCExtensionThumbprints 'Update'
promptRestartVMwareServices 'vmcam'
fi
clearCSRInfo
fi
else
printf "\n%s\n\n" "${YELLOW}This operation must be done on the vCenter Server.${NORMAL}"
fi
;;
6)
if [ $NODE_TYPE != 'infrastructure' ]; then
if promptReplaceAutoDeployCA; then
if replaceAutoDeployCACert; then promptRestartVMwareServices 'vmware-rbd-watchdog'; fi
clearCSRInfo
fi
else
printf "\n%s\n\n" "${YELLOW}This operation must be done on the vCenter Server.${NORMAL}"
fi
;;
7)
manageSMSCertificates 'Manage'
;;
8)
replaceDataEnciphermentCertificate
;;
9)
if [ $NODE_TYPE != 'infrastructure' ]; then
manageVCExtensionThumbprints 'Check'
else
printf "\n%s\n\n" "${YELLOW}This operation must be done on the vCenter Server.${NORMAL}"
fi
;;
10)
if [[ "$VC_VERSION" =~ ^[78] ]]; then
if [ -f /usr/lib/vmware-vmdir/share/config/vmdircert.pem ]; then
removeVMDirCert
else
printf "\n%s\n\n" "${YELLOW}This operation is not available for vCenter 7.x or later${NORMAL}"
fi
elif [ $NODE_TYPE != 'management' ]; then
if promptReplaceVMDir; then replaceVMDirCert; fi
else
printf "\n%s\n\n" "${YELLOW}This operation must be done on the Platform Services Controller${NORMAL}"
fi
;;
11)
if [ $NODE_TYPE != 'management' ]; then
manageSTSTenantCerts 'Replace'
else
printf "\n%s\n\n" "${YELLOW}This operation must be done on the Platform Services Controller${NORMAL}"
fi
;;
12)
if [ $NODE_TYPE != 'management' ]; then
if promptReplaceVMCA; then
if replaceVMCACert && [ "$VMCA_REGENERATE_CERTIFICATES" == '1' ]; then resetAllCertificates; fi
fi
else
printf "\n%s\n\n" "${YELLOW}This operation must be done on the Platform Services Controller${NORMAL}"
fi
;;
13)
manageCACCerts 'Manage'
;;
14)
manageLDAPSCerts 'Manage'
;;
15)
#manageTanzuSupervisorClusterCerts 'Manage'
;;
16)
if checkVECSStore 'BACKUP_STORE' || checkVECSStore 'BACKUP_STORE_H5C'; then
clearBackupStore
else
echo $'\n'"${YELLOW}The BACKUP_STORE does not exist in VECS, nothing to do.$NORMAL"
fi
;;
17)
clearCRLs
;;
18)
clearMachineSSLCSR
;;
esac
}
#------------------------------
# Menu for options generating the certificate report
#------------------------------
function viewCertificateReportMenu() {
unset CERTIFICATE_REPORT_INPUT
header 'Certificate Report Options'
cat << EOF
1. Generate vCenter certificate report"
2. Generate ESXi certificate report"
3. Generate vCenter and ESXi certifiate report
EOF
read -p $'\nEnter report selection [Return to Main Menu]: ' CERTIFICATE_REPORT_INPUT
if [ -z $CERTIFICATE_REPORT_INPUT ]; then return 1; fi
if [ -f $VC_REPORT ]; then echo '' > $VC_REPORT; fi
printf "\n"
case $CERTIFICATE_REPORT_INPUT in
1)
generatevCenterCertificateReport
;;
2)
generateESXiCertificateReport
;;
3)
generatevCenterCertificateReport
generateESXiCertificateReport
;;
esac
}
#------------------------------
# Generate vCenter certificate report
#------------------------------
function generatevCenterCertificateReport() {
if [ "$NODE_TYPE" != 'infrastructure' ] && ! checkService 'vmware-vpostgres'; then
echo "${YELLOW}The vPostgres service is stopped!"
echo "Please ensure this service is running before generating a certificate report."
echo "Hint: Check the number of CRL entries in VECS${NORMAL}"
return 1
fi
authenticateIfNeeded
disableColor
printf '%0.1s' "="{1..130} | tee $VC_REPORT
printf '\n' | tee -a $VC_REPORT
echo 'SSL Certificate Report' | tee -a $VC_REPORT
echo "vCert $VERSION" | tee -a $VC_REPORT
echo "Host: $HOSTNAME" | tee -a $VC_REPORT
echo "Date: $(date -u)" | tee -a $VC_REPORT
echo "Node Type: $NODE_TYPE" | tee -a $VC_REPORT
echo "Build: $VC_BUILD" | tee -a $VC_REPORT
echo "Machine ID: $MACHINE_ID" | tee -a $VC_REPORT
echo "PNID: $PNID" | tee -a $VC_REPORT
if [ $NODE_TYPE != 'infrastructure' ]; then
CERT_MGMT_MODE=$($PSQL -d VCDB -U postgres -c "SELECT value FROM vpx_parameter WHERE name='vpxd.certmgmt.mode'" -t | grep -v '^$')
echo "Certificate Management Mode: $CERT_MGMT_MODE" | tee -a $VC_REPORT
fi
printf '%0.1s' "="{1..130} | tee -a $VC_REPORT
printf '\n' | tee -a $VC_REPORT
VMDIR_CA_SUBJECT_IDS=''
VECS_CA_SUBJECT_IDS=''
for CNID in $($DIR_CLI trustedcert list --login "$VMDIR_USER_UPN" --password "$VMDIR_USER_PASSWORD" | grep 'CN(id)' | awk '{print $NF}'); do
CERT=$($DIR_CLI trustedcert get --id $CNID --login "$VMDIR_USER_UPN" --password "$VMDIR_USER_PASSWORD" --outcert /dev/stdout | grep -v 'Certificate retrieved successfully')
VMDIR_CERT_INFO=$(viewCertificateInfo "$CERT")
VMDIR_CERT_SERIAL=$(echo "$VMDIR_CERT_INFO" | grep -A1 'Serial Number' | tail -n1 | tr -d ' ' | awk '{print toupper($0)}')
VMDIR_CERT_SUBJECT=$(echo "$VMDIR_CERT_INFO" | grep 'Subject: ' | sed 's/Subject: //')
VMDIR_CERT_SUBJECT_KEY=$(echo "$VMDIR_CERT_INFO" | grep -A1 'Subject Key Identifier' | tail -n1 | tr -d ' ')
VMDIR_CA_SUBJECT_IDS+="serial:$VMDIR_CERT_SERIAL|DirName:$VMDIR_CERT_SUBJECT|keyid:$VMDIR_CERT_SUBJECT_KEY"$'\n'
done
IFS=$'\n'
for alias in $($VECS_CLI entry list --store TRUSTED_ROOTS --text | grep 'Alias' | awk -F"[[:space:]]:[[:space:]]" '{print $NF}'); do
CERT=$($VECS_CLI entry getcert --store TRUSTED_ROOTS --alias "$alias")
VECS_CERT_INFO=$(viewCertificateInfo "$CERT")
VECS_CERT_SERIAL=$(echo "$VECS_CERT_INFO" | grep -A1 'Serial Number' | tail -n1 | tr -d ' ' | awk '{print toupper($0)}')
VECS_CERT_SUBJECT=$(echo "$VECS_CERT_INFO" | grep 'Subject: ' | sed 's/Subject: //')
VECS_CERT_SUBJECT_KEY=$(echo "$VECS_CERT_INFO" | grep -A1 'Subject Key Identifier' | tail -n1 | tr -d ' ')
VECS_CA_SUBJECT_IDS+="serial:$VECS_CERT_SERIAL|DirName:$VECS_CERT_SUBJECT|keyid:$VECS_CERT_SUBJECT_KEY"$'\n'
done
IFS=$' \t\n'
echo 'VECS Certificates' | tee -a $VC_REPORT
for store in $($VECS_CLI store list | grep -v 'APPLMGMT_PASSWORD'); do
echo " Store: $store" | tee -a $VC_REPORT
IFS=$'\n'
for alias in $($VECS_CLI entry list --store $store | grep 'Alias' | sed 's/^Alias[[:space:]]*:[[:space:]]*//g'); do
echo " Alias: $alias" | tee -a $VC_REPORT
VECS_HASH=$($VECS_CLI entry getcert --store $store --alias "$alias" 2>/dev/null)
if [[ $? -eq 0 ]]; then
if ! echo "$VECS_HASH" | head -n1 | grep -q 'BEGIN CERTIFICATE'; then
reportCRLDetails "$VECS_HASH"
else
case $store-$alias in
MACHINE_SSL_CERT-__MACHINE_CERT)
EXTRA_INFO='checkCurrentMachineSSLUsage|reportExtentionThumbprintsMachineSSL'
;;
vpxd-extension-vpxd-extension)
EXTRA_INFO='reportExtentionThumbprintsVpxdExtension'
;;
*)
EXTRA_INFO=''
;;
esac
reportCertDetails "$VECS_HASH" "$EXTRA_INFO"
fi
else
echo " |_No certificate found in store" | tee -a $VC_REPORT
fi
done
IFS=$' \t\n'
done
echo 'VMware Directory Certificates' | tee -a $VC_REPORT
echo ' CA Certificates' | tee -a $VC_REPORT
for CNID in $($DIR_CLI trustedcert list --login "$VMDIR_USER_UPN" --password "$VMDIR_USER_PASSWORD" | grep 'CN(id)' | awk '{print $NF}'); do
echo " CN(id): $CNID" | tee -a $VC_REPORT
VMDIR_CA_HASH=$($DIR_CLI trustedcert get --id $CNID --login "$VMDIR_USER_UPN" --password "$VMDIR_USER_PASSWORD" --outcert /dev/stdout | grep -v 'Certificate retrieved successfully')
reportCertDetails "$VMDIR_CA_HASH"
done
echo ' Service Principal (Solution User) Certificates' | tee -a $VC_REPORT
IFS=$'\n'
for line in $($LDAP_SEARCH -o ldif-wrap=no -LLL -h $PSC_LOCATION -p $VMDIR_PORT -b "cn=ServicePrincipals,$VMDIR_DOMAIN_DN" -D "cn=$VMDIR_USER,cn=users,$VMDIR_DOMAIN_DN" -y $STAGE_DIR/.vmdir-user-password '(objectclass=vmwServicePrincipal)' userCertificate); do
if [[ "$line" =~ ^dn: ]]; then
SERVICE_PRINCIPAL=$(echo "$line" | awk -F':' '{print $NF}' | awk -F',' '{print $1}' | awk -F'=' '{print $NF}')
echo " Service Principal: $SERVICE_PRINCIPAL" | tee -a $VC_REPORT
else
SERVICE_PRINCIPAL_CERT_HASH=$(echo "$line" | awk '{print $NF}')
TEMP_CERT=$(buildCertFromHash "$SERVICE_PRINCIPAL_CERT_HASH")
reportCertDetails "$TEMP_CERT"
fi
done
IFS=$' \t\n'
echo ' Single Sign-On Secure Token Service Certificates' | tee -a $VC_REPORT
TENANT_COUNT=0
for hash in $($LDAP_SEARCH -o ldif-wrap=no -LLL -h $PSC_LOCATION -p $VMDIR_PORT -b "cn=$SSO_DOMAIN,cn=Tenants,cn=IdentityManager,cn=Services,$VMDIR_DOMAIN_DN" -D "cn=$VMDIR_USER,cn=users,$VMDIR_DOMAIN_DN" -y $STAGE_DIR/.vmdir-user-password '(objectclass=vmwSTSTenantCredential)' userCertificate | grep '^userCertificate' | awk '{print $NF}'); do
TEMP_CERT=$(buildCertFromHash "$hash")
if isCertCA "$TEMP_CERT"; then
echo " TenantCredential-$TENANT_COUNT CA Certificate" | tee -a $VC_REPORT
else
((++TENANT_COUNT))
echo " TenantCredential-$TENANT_COUNT Signing Certificate" | tee -a $VC_REPORT
fi
reportCertDetails "$TEMP_CERT"
done
CHAIN_COUNT=0
for hash in $($LDAP_SEARCH -o ldif-wrap=no -LLL -h $PSC_LOCATION -p $VMDIR_PORT -b "cn=TrustedCertificateChains,cn=$SSO_DOMAIN,cn=Tenants,cn=IdentityManager,cn=Services,$VMDIR_DOMAIN_DN" -D "cn=$VMDIR_USER,cn=users,$VMDIR_DOMAIN_DN" -y $STAGE_DIR/.vmdir-user-password '(objectclass=vmwSTSTenantTrustedCertificateChain)' userCertificate | grep '^userCertificate' | awk '{print $NF}'); do
TEMP_CERT=$(buildCertFromHash "$hash")
if isCertCA "$TEMP_CERT"; then
echo " TrustedCertChain-$CHAIN_COUNT CA Certificate" | tee -a $VC_REPORT
else
((++CHAIN_COUNT))
echo " TrustedCertChain-$CHAIN_COUNT Signing Certificate" | tee -a $VC_REPORT
fi
reportCertDetails "$TEMP_CERT"
done
CAC_CAS=$($LDAP_SEARCH -o ldif-wrap=no -LLL -h $PSC_LOCATION -p $VMDIR_PORT -b "cn=DefaultClientCertCAStore,cn=ClientCertAuthnTrustedCAs,cn=Default,cn=ClientCertificatePolicies,cn=$SSO_DOMAIN,cn=Tenants,cn=IdentityManager,cn=Services,$VMDIR_DOMAIN_DN" -D "cn=$VMDIR_USER,cn=users,$VMDIR_DOMAIN_DN" -y $STAGE_DIR/.vmdir-user-password '(objectclass=vmwSTSTenantTrustedCertificateChain)' userCertificate 2>/dev/null | grep '^userCertificate' | awk '{print $NF}')
if [ -n "$CAC_CAS" ]; then
CAC_ISSUING_CA_COUNT=1
echo ' Smart Card Issuing CA Certificates' | tee -a $VC_REPORT
for hash in $CAC_CAS; do
TEMP_CERT=$(buildCertFromHash "$hash")
echo " Smart Card Issuing CA $CAC_ISSUING_CA_COUNT" | tee -a $VC_REPORT
reportCertDetails "$TEMP_CERT"
((++CAC_ISSUING_CA_COUNT))
done
fi
AD_LDAPS_CERTS=$($LDAP_SEARCH -o ldif-wrap=no -LLL -h $PSC_LOCATION -p $VMDIR_PORT -b "cn=IdentityProviders,cn=$SSO_DOMAIN,cn=Tenants,cn=IdentityManager,cn=Services,$VMDIR_DOMAIN_DN" -D "cn=$VMDIR_USER,cn=users,$VMDIR_DOMAIN_DN" -y $STAGE_DIR/.vmdir-user-password '(vmwSTSProviderType=IDENTITY_STORE_TYPE_LDAP_WITH_AD_MAPPING)' userCertificate 2>/dev/null | grep '^userCertificate::' | awk '{print $NF}')
if [ -n "$AD_LDAPS_CERTS" ]; then
echo ' AD Over LDAPS Domain Controller Certificates' | tee -a $VC_REPORT
LDAPS_DC_CERT_COUNT=1
for hash in $AD_LDAPS_CERTS; do
echo " Certificate $LDAPS_DC_CERT_COUNT" | tee -a $VC_REPORT
reportCertDetails "$(buildCertFromHash $hash)"
((++LDAPS_DC_CERT_COUNT))
done
fi
echo 'Filesystem Certificates' | tee -a $VC_REPORT
if [ "$NODE_TYPE" != 'management' ]; then
if [[ "$VC_VERSION" =~ ^6 ]]; then
echo ' VMware Directory Certificate' | tee -a $VC_REPORT
echo ' Certificate: /usr/lib/vmware-vmdir/share/config/vmdircert.pem' | tee -a $VC_REPORT
reportCertDetails "$(cat /usr/lib/vmware-vmdir/share/config/vmdircert.pem)"
fi
echo ' VMCA Certificate' | tee -a $VC_REPORT
echo " Certificate: $VMCA_CERT" | tee -a $VC_REPORT
reportCertDetails "$(cat $VMCA_CERT)"
fi
if [ "$NODE_TYPE" != 'infrastructure' ]; then
echo ' Authentication Proxy Certificate' | tee -a $VC_REPORT
echo ' Certificate: /var/lib/vmware/vmcam/ssl/vmcamcert.pem' | tee -a $VC_REPORT
reportCertDetails "$(cat /var/lib/vmware/vmcam/ssl/vmcamcert.pem)"
echo ' Auto Deploy CA Certificate' | tee -a $VC_REPORT
echo ' Certificate: /etc/vmware-rbd/ssl/rbd-ca.crt' | tee -a $VC_REPORT
reportCertDetails "$(cat /etc/vmware-rbd/ssl/rbd-ca.crt)"
fi
if grep '' /etc/vmware-rhttpproxy/config.xml | grep -qv '