mirror of
https://github.com/apache/cloudstack.git
synced 2025-10-26 08:42:29 +01:00
This PR allows securing the console access through CloudStack to the virtual machines running on KVM. The secure access is achieved through the generated certificates for the CA Framework in CloudStack, that provides mutual TLS connections between agents. These certificates are used to also secure the connection between the console proxies and the VNC ports for VM console access. This feature is only supported on the KVM hypervisor Design Document: https://cwiki.apache.org/confluence/display/CLOUDSTACK/Secure+KVM+VNC+connection+using+the+CA+framework
144 lines
5.6 KiB
Bash
Executable File
144 lines
5.6 KiB
Bash
Executable File
#!/bin/bash
|
|
# Licensed to the Apache Software Foundation (ASF) under one
|
|
# or more contributor license agreements. See the NOTICE file
|
|
# distributed with this work for additional information
|
|
# regarding copyright ownership. The ASF licenses this file
|
|
# to you under the Apache License, Version 2.0 (the
|
|
# "License"); you may not use this file except in compliance
|
|
# with the License. You may obtain a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing,
|
|
# software distributed under the License is distributed on an
|
|
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
# KIND, either express or implied. See the License for the
|
|
# specific language governing permissions and limitations
|
|
# under the License.
|
|
|
|
PROPS_FILE="$1"
|
|
KS_PASS="$2"
|
|
KS_FILE="$3"
|
|
MODE="$4"
|
|
CERT_FILE="$5"
|
|
CERT=$(echo "$6" | tr '^' '\n' | tr '~' ' ')
|
|
CACERT_FILE="$7"
|
|
CACERT=$(echo "$8" | tr '^' '\n' | tr '~' ' ')
|
|
PRIVKEY_FILE="$9"
|
|
PRIVKEY=$(echo "${10}" | tr '^' '\n' | tr '~' ' ')
|
|
|
|
ALIAS="cloud"
|
|
SYSTEM_FILE="/var/cache/cloud/cmdline"
|
|
LIBVIRTD_FILE="/etc/libvirt/libvirtd.conf"
|
|
|
|
if [ ! -f "$LIBVIRTD_FILE" ]; then
|
|
# Re-use existing password or use the one provided
|
|
while [ ! -d /usr/local/cloud/systemvm/conf ]; do sleep 1; done
|
|
if [ -f "$PROPS_FILE" ]; then
|
|
OLD_PASS=$(sed -n '/keystore.passphrase/p' "$PROPS_FILE" 2>/dev/null | sed 's/keystore.passphrase=//g' 2>/dev/null)
|
|
if [ ! -z "${OLD_PASS// }" ]; then
|
|
KS_PASS="$OLD_PASS"
|
|
else
|
|
sed -i "/keystore.passphrase.*/d" $PROPS_FILE 2> /dev/null || true
|
|
echo "keystore.passphrase=$KS_PASS" >> $PROPS_FILE
|
|
fi
|
|
fi
|
|
fi
|
|
|
|
# Find keystore password
|
|
KS_PASS=$(sed -n '/keystore.passphrase/p' "$PROPS_FILE" 2>/dev/null | sed 's/keystore.passphrase=//g' 2>/dev/null)
|
|
|
|
if [ -z "${KS_PASS// }" ]; then
|
|
echo "Failed to find keystore passphrase from file: $PROPS_FILE, quiting!"
|
|
exit 1
|
|
fi
|
|
|
|
# Import certificate
|
|
if [ ! -z "${CERT// }" ]; then
|
|
echo "$CERT" > "$CERT_FILE"
|
|
elif [ ! -f "$CERT_FILE" ]; then
|
|
echo "Cannot find certificate file: $CERT_FILE, exiting"
|
|
exit
|
|
fi
|
|
|
|
# Import ca certs
|
|
if [ ! -z "${CACERT// }" ]; then
|
|
echo "$CACERT" > "$CACERT_FILE"
|
|
elif [ ! -f "$CACERT_FILE" ]; then
|
|
echo "Cannot find ca certificate file: $CACERT_FILE, exiting!"
|
|
exit
|
|
fi
|
|
|
|
# Import cacerts into the keystore
|
|
awk '/-----BEGIN CERTIFICATE-----?/{n++}{print > "cloudca." n }' "$CACERT_FILE"
|
|
for caChain in $(ls cloudca.*); do
|
|
keytool -delete -noprompt -alias "$caChain" -keystore "$KS_FILE" -storepass "$KS_PASS" > /dev/null 2>&1 || true
|
|
keytool -import -noprompt -storepass "$KS_PASS" -trustcacerts -alias "$caChain" -file "$caChain" -keystore "$KS_FILE" > /dev/null 2>&1
|
|
done
|
|
rm -f cloudca.*
|
|
|
|
# Stop cloud service in systemvm
|
|
if [ "$MODE" == "ssh" ] && [ -f $SYSTEM_FILE ]; then
|
|
systemctl stop cloud > /dev/null 2>&1
|
|
fi
|
|
|
|
# Import private key if available
|
|
if [ ! -z "${PRIVKEY// }" ]; then
|
|
echo "$PRIVKEY" > "$PRIVKEY_FILE"
|
|
else
|
|
> "$PRIVKEY_FILE"
|
|
fi
|
|
|
|
if [ -f "$PRIVKEY_FILE" ] && [ -s "$PRIVKEY_FILE" ]; then
|
|
# Re-initialize keystore when private key is provided
|
|
keytool -delete -noprompt -alias "$ALIAS" -keystore "$KS_FILE" -storepass "$KS_PASS" 2>/dev/null || true
|
|
openssl pkcs12 -export -name "$ALIAS" -in "$CERT_FILE" -inkey "$PRIVKEY_FILE" -out "$KS_FILE.p12" -password pass:"$KS_PASS" > /dev/null 2>&1
|
|
keytool -importkeystore -srckeystore "$KS_FILE.p12" -destkeystore "$KS_FILE" -srcstoretype PKCS12 -alias "$ALIAS" -deststorepass "$KS_PASS" -destkeypass "$KS_PASS" -srcstorepass "$KS_PASS" -srckeypass "$KS_PASS" > /dev/null 2>&1
|
|
else
|
|
# Import certificate into the keystore
|
|
keytool -import -storepass "$KS_PASS" -alias "$ALIAS" -file "$CERT_FILE" -keystore "$KS_FILE" > /dev/null 2>&1 || true
|
|
# Export private key from keystore
|
|
rm -f "$PRIVKEY_FILE"
|
|
keytool -importkeystore -srckeystore "$KS_FILE" -destkeystore "$KS_FILE.p12" -deststoretype PKCS12 -srcalias "$ALIAS" -deststorepass "$KS_PASS" -destkeypass "$KS_PASS" -srcstorepass "$KS_PASS" -srckeypass "$KS_PASS" > /dev/null 2>&1
|
|
openssl pkcs12 -in "$KS_FILE.p12" -nodes -nocerts -nomac -password pass:"$KS_PASS" 2>/dev/null | openssl rsa -out "$PRIVKEY_FILE" > /dev/null 2>&1
|
|
fi
|
|
|
|
rm -f "$KS_FILE.p12"
|
|
|
|
# Secure libvirtd on cert import
|
|
if [ -f "$LIBVIRTD_FILE" ]; then
|
|
mkdir -p /etc/pki/CA
|
|
mkdir -p /etc/pki/libvirt/private
|
|
ln -sf /etc/cloudstack/agent/cloud.ca.crt /etc/pki/CA/cacert.pem
|
|
ln -sf /etc/cloudstack/agent/cloud.crt /etc/pki/libvirt/clientcert.pem
|
|
ln -sf /etc/cloudstack/agent/cloud.crt /etc/pki/libvirt/servercert.pem
|
|
ln -sf /etc/cloudstack/agent/cloud.key /etc/pki/libvirt/private/clientkey.pem
|
|
ln -sf /etc/cloudstack/agent/cloud.key /etc/pki/libvirt/private/serverkey.pem
|
|
|
|
# VNC TLS directory and certificates
|
|
mkdir -p /etc/pki/libvirt-vnc
|
|
ln -sf /etc/pki/CA/cacert.pem /etc/pki/libvirt-vnc/ca-cert.pem
|
|
ln -sf /etc/pki/libvirt/servercert.pem /etc/pki/libvirt-vnc/server-cert.pem
|
|
ln -sf /etc/pki/libvirt/private/serverkey.pem /etc/pki/libvirt-vnc/server-key.pem
|
|
cloudstack-setup-agent -s > /dev/null
|
|
fi
|
|
|
|
# Update ca-certs if we're in systemvm
|
|
if [ -f "$SYSTEM_FILE" ]; then
|
|
mkdir -p /usr/local/share/ca-certificates/cloudstack
|
|
cp "$CACERT_FILE" /usr/local/share/ca-certificates/cloudstack/ca.crt
|
|
chmod 755 /usr/local/share/ca-certificates/cloudstack
|
|
chmod 644 /usr/local/share/ca-certificates/cloudstack/ca.crt
|
|
update-ca-certificates > /dev/null 2>&1 || true
|
|
|
|
# Ensure cloud service is running in systemvm
|
|
if [ "$MODE" == "ssh" ]; then
|
|
systemctl start cloud > /dev/null 2>&1
|
|
fi
|
|
fi
|
|
|
|
# Fix file permission
|
|
chmod 600 $CACERT_FILE
|
|
chmod 600 $CERT_FILE
|
|
chmod 600 $PRIVKEY_FILE
|