Middleware Client Certificate Issuance

Middleware Client certificates can be used for Client TLS authentication to the ED REST API and ED LDAP directory.

Certificate Request

Users creating a service for the first time should follow this procedure:

Request an ED service from IMCS by following VT 4Help KB0011183

After IMCS creates the ED service, they will provide the service owner with a password credential that is valid for 7 days.

Subsequently, the service owner should run the script below to request a Middleware Client certificate. Upon execution, the endpoint will deliver the keystore in P12 format along with the corresponding password. Neither the private key nor the keystore password will be retrievable later. Therefore, it’s imperative for the service owner to securely store them for future use.

client-cert-request.sh

#!/bin/bash

# Generates a Middleware client certificate that can be used to authenticate
# to ED services (REST API, LDAP). HTTP Basic authentication is used to
# authenticate to the ED REST endpoint for certificates, which requires the
# temporary password assigned to the service. A PKCS#12 file containing a
# certificate and private key is returned. The key is not stored (escrowed)
# in any way; you are responsible for storing it securely.

set -e  # Exit on any error

# Validate input parameters
if [ $# -lt 1 ] || [ $# -gt 3 ]; then
echo "USAGE: $(basename $0) <ed-service-name> [<output-directory>] [<tier>]"
exit 1
fi

ED_SERVICE=$1
OUTPUT_DIR=${2:-.}  # Default to current directory if not provided
TIER=${3:-prod}  # Default to prod if not provided

# Determine API URL based on tier
case "$TIER" in
dev)
API_URL="https://dev.api.middleware.vt.edu/v2/services/$ED_SERVICE/certificates"
;;
pprd)
API_URL="https://pprd.api.middleware.vt.edu/v2/services/$ED_SERVICE/certificates"
;;
prod)
API_URL="https://api.middleware.vt.edu/v2/services/$ED_SERVICE/certificates"
;;
*)
echo "Invalid tier specified. Use 'dev', 'pprd', or 'prod'."
exit 1
;;
esac

# Generate certificate and store response JSON
echo "Generating certificate for service: $ED_SERVICE in tier: $TIER"
read -s -p "Enter your ED service password: " ED_PASSWORD
echo
CREDS="$ED_SERVICE:$ED_PASSWORD"
curl -XPOST -u "$CREDS" -o "$OUTPUT_DIR/create-cert-response.json" "$API_URL"
echo "Response saved to: $OUTPUT_DIR/create-cert-response.json"

# Extract P12 file from JSON response
echo "Extracting P12 file"
P12_BASE64=$(jq -r '.p12' "$OUTPUT_DIR/create-cert-response.json")
echo "$P12_BASE64" | base64 -d > "$OUTPUT_DIR/$ED_SERVICE.p12"
PASSWORD=$(jq -r '.password' "$OUTPUT_DIR/create-cert-response.json")
echo "P12 file written to $OUTPUT_DIR/$ED_SERVICE.p12"
echo "P12 file password: $PASSWORD"

Certificate Renewal

Service owners seeking to renew their certificates should use their existing Middleware Client certificate and private key and use the script provided here to obtain new Middleware Client certificate:

client-cert-renewal.sh

#!/bin/bash

# Generates a new Middleware client certificate using a PKCS#12 file containing
# an existing Middleware client certificate and private key as an
# authentication credential. A new PKCS#12 file containing a certificate and
# private key is returned. The key is not stored (escrowed) in any way;
# you are responsible for storing it securely.

set -e  # Exit on any error

# Validate input parameters
if [ $# -lt 1 ] || [ $# -gt 3 ]; then
echo "USAGE: $(basename $0) <path-to-p12-file> [<output-directory>] [<tier>]"
exit 1
fi

P12_PATH="$1"
OUTPUT_DIR=${2:-.}  # Default to current directory if not provided
TIER=${3:-prod}  # Default to prod if not provided

# Determine API URL based on tier
case "$TIER" in
dev)
API_URL_BASE="https://dev.api.middleware.vt.edu/v2/services"
;;
pprd)
API_URL_BASE="https://pprd.api.middleware.vt.edu/v2/services"
;;
prod)
API_URL_BASE="https://api.middleware.vt.edu/v2/services"
;;
*)
echo "Invalid tier specified. Use 'dev', 'pprd', or 'prod'."
exit 1
;;
esac

AUTH_CERT="$OUTPUT_DIR/auth.crt"
AUTH_KEY="$OUTPUT_DIR/auth.key"

# Always clean up the extracted certificate and private key
trap "rm -f $AUTH_CERT $AUTH_KEY" EXIT

# Determine ED service name from certificate in P12 file
read -s -p "Enter the password to the P12 file: " P12_PWD
echo
openssl pkcs12 -in "$P12_PATH" -nokeys -passin "pass:$P12_PWD" -out "$AUTH_CERT"
openssl pkcs12 -in "$P12_PATH" -nocerts -noenc -passin "pass:$P12_PWD" -out "$AUTH_KEY"
SUBJECT=$(cat "$AUTH_CERT" | grep "subject=")
[[ $SUBJECT =~ CN=([^,]+) ]]
ED_SERVICE=${BASH_REMATCH[1]}

# # Generate certificate and store response JSON
echo "Generating certificate for service: $ED_SERVICE"
API_URL="$API_URL_BASE/$ED_SERVICE/certificates"
echo curl -XPOST --cert "$AUTH_CERT" --key "$AUTH_KEY" -o "$OUTPUT_DIR/renew-cert-response.json" "$API_URL"
curl -XPOST --cert "$AUTH_CERT" --key "$AUTH_KEY" -o "$OUTPUT_DIR/renew-cert-response.json" "$API_URL"
echo "Response saved to: $OUTPUT_DIR/renew-cert-response.json"

# Extract P12 file from JSON response
echo "Extracting P12 file"
P12_BASE64=$(jq -r '.p12' "$OUTPUT_DIR/renew-cert-response.json")
echo "$P12_BASE64" | base64 -d > "$OUTPUT_DIR/${ED_SERVICE}-renewed.p12"
PASSWORD=$(jq -r '.password' "$OUTPUT_DIR/renew-cert-response.json")
echo "P12 file written to $OUTPUT_DIR/${ED_SERVICE}-renewed.p12"
echo "P12 file password: $PASSWORD"