diff --git a/lib/cinder b/lib/cinder index 96d25058ce..9288685365 100644 --- a/lib/cinder +++ b/lib/cinder @@ -209,6 +209,7 @@ function configure_cinder() { inicomment $CINDER_API_PASTE_INI filter:authtoken auth_host inicomment $CINDER_API_PASTE_INI filter:authtoken auth_port inicomment $CINDER_API_PASTE_INI filter:authtoken auth_protocol + inicomment $CINDER_API_PASTE_INI filter:authtoken cafile inicomment $CINDER_API_PASTE_INI filter:authtoken admin_tenant_name inicomment $CINDER_API_PASTE_INI filter:authtoken admin_user inicomment $CINDER_API_PASTE_INI filter:authtoken admin_password @@ -219,6 +220,7 @@ function configure_cinder() { iniset $CINDER_CONF keystone_authtoken auth_host $KEYSTONE_AUTH_HOST iniset $CINDER_CONF keystone_authtoken auth_port $KEYSTONE_AUTH_PORT iniset $CINDER_CONF keystone_authtoken auth_protocol $KEYSTONE_AUTH_PROTOCOL + iniset $CINDER_CONF keystone_authtoken cafile $KEYSTONE_SSL_CA iniset $CINDER_CONF keystone_authtoken admin_tenant_name $SERVICE_TENANT_NAME iniset $CINDER_CONF keystone_authtoken admin_user cinder iniset $CINDER_CONF keystone_authtoken admin_password $SERVICE_PASSWORD diff --git a/lib/glance b/lib/glance index f40b1a7fc9..2e29a8f77c 100644 --- a/lib/glance +++ b/lib/glance @@ -82,6 +82,7 @@ function configure_glance() { iniset $GLANCE_REGISTRY_CONF keystone_authtoken auth_host $KEYSTONE_AUTH_HOST iniset $GLANCE_REGISTRY_CONF keystone_authtoken auth_port $KEYSTONE_AUTH_PORT iniset $GLANCE_REGISTRY_CONF keystone_authtoken auth_protocol $KEYSTONE_AUTH_PROTOCOL + iniset $GLANCE_REGISTRY_CONF keystone_authtoken cafile $KEYSTONE_SSL_CA iniset $GLANCE_REGISTRY_CONF keystone_authtoken auth_uri $KEYSTONE_SERVICE_PROTOCOL://$KEYSTONE_SERVICE_HOST:$KEYSTONE_SERVICE_PORT/ iniset $GLANCE_REGISTRY_CONF keystone_authtoken admin_tenant_name $SERVICE_TENANT_NAME iniset $GLANCE_REGISTRY_CONF keystone_authtoken admin_user glance @@ -99,6 +100,7 @@ function configure_glance() { iniset $GLANCE_API_CONF keystone_authtoken auth_host $KEYSTONE_AUTH_HOST iniset $GLANCE_API_CONF keystone_authtoken auth_port $KEYSTONE_AUTH_PORT iniset $GLANCE_API_CONF keystone_authtoken auth_protocol $KEYSTONE_AUTH_PROTOCOL + iniset $GLANCE_API_CONF keystone_authtoken cafile $KEYSTONE_SSL_CA iniset $GLANCE_API_CONF keystone_authtoken auth_uri $KEYSTONE_SERVICE_PROTOCOL://$KEYSTONE_SERVICE_HOST:$KEYSTONE_SERVICE_PORT/ iniset $GLANCE_API_CONF keystone_authtoken admin_tenant_name $SERVICE_TENANT_NAME iniset $GLANCE_API_CONF keystone_authtoken admin_user glance diff --git a/lib/heat b/lib/heat index 7a9ef0da26..e44a618162 100644 --- a/lib/heat +++ b/lib/heat @@ -96,6 +96,7 @@ function configure_heat() { iniset $HEAT_CONF keystone_authtoken auth_port $KEYSTONE_AUTH_PORT iniset $HEAT_CONF keystone_authtoken auth_protocol $KEYSTONE_AUTH_PROTOCOL iniset $HEAT_CONF keystone_authtoken auth_uri $KEYSTONE_SERVICE_PROTOCOL://$KEYSTONE_SERVICE_HOST:$KEYSTONE_SERVICE_PORT/v2.0 + iniset $HEAT_CONF keystone_authtoken cafile $KEYSTONE_SSL_CA iniset $HEAT_CONF keystone_authtoken admin_tenant_name $SERVICE_TENANT_NAME iniset $HEAT_CONF keystone_authtoken admin_user heat iniset $HEAT_CONF keystone_authtoken admin_password $SERVICE_PASSWORD diff --git a/lib/ironic b/lib/ironic index 9f86e841d8..099746ae22 100644 --- a/lib/ironic +++ b/lib/ironic @@ -98,6 +98,7 @@ function configure_ironic_api() { iniset $IRONIC_CONF_FILE keystone_authtoken auth_host $KEYSTONE_AUTH_HOST iniset $IRONIC_CONF_FILE keystone_authtoken auth_port $KEYSTONE_AUTH_PORT iniset $IRONIC_CONF_FILE keystone_authtoken auth_protocol $KEYSTONE_AUTH_PROTOCOL + iniset $IRONIC_CONF_FILE keystone_authtoken cafile $KEYSTONE_SSL_CA iniset $IRONIC_CONF_FILE keystone_authtoken auth_uri $KEYSTONE_SERVICE_PROTOCOL://$KEYSTONE_SERVICE_HOST:$KEYSTONE_SERVICE_PORT/ iniset $IRONIC_CONF_FILE keystone_authtoken admin_tenant_name $SERVICE_TENANT_NAME iniset $IRONIC_CONF_FILE keystone_authtoken admin_user ironic diff --git a/lib/keystone b/lib/keystone index c1fa0af8af..6d0c1cd99a 100644 --- a/lib/keystone +++ b/lib/keystone @@ -4,6 +4,7 @@ # Dependencies: # # - ``functions`` file +# - ``tls`` file # - ``DEST``, ``STACK_USER`` # - ``IDENTITY_API_VERSION`` # - ``BASE_SQL_CONN`` @@ -79,6 +80,13 @@ KEYSTONE_VALID_IDENTITY_BACKENDS=kvs,ldap,pam,sql # valid assignment backends as per dir keystone/identity/backends KEYSTONE_VALID_ASSIGNMENT_BACKENDS=kvs,ldap,sql +# if we are running with SSL use https protocols +if is_ssl_enabled_service "key"; then + KEYSTONE_AUTH_PROTOCOL="https" + KEYSTONE_SERVICE_PROTOCOL="https" +fi + + # Functions # --------- # cleanup_keystone() - Remove residual data files, anything left over from previous @@ -172,6 +180,15 @@ function configure_keystone() { iniset $KEYSTONE_CONF DEFAULT public_endpoint "$KEYSTONE_SERVICE_PROTOCOL://$KEYSTONE_SERVICE_HOST:%(public_port)s/" iniset $KEYSTONE_CONF DEFAULT admin_endpoint "$KEYSTONE_SERVICE_PROTOCOL://$KEYSTONE_SERVICE_HOST:%(admin_port)s/" + # Register SSL certificates if provided + if is_ssl_enabled_service key; then + ensure_certificates KEYSTONE + + iniset $KEYSTONE_CONF ssl enable True + iniset $KEYSTONE_CONF ssl certfile $KEYSTONE_SSL_CERT + iniset $KEYSTONE_CONF ssl keyfile $KEYSTONE_SSL_KEY + fi + if is_service_enabled tls-proxy; then # Set the service ports for a proxy to take the originals iniset $KEYSTONE_CONF DEFAULT public_port $KEYSTONE_SERVICE_PORT_INT @@ -386,7 +403,7 @@ function start_keystone() { fi echo "Waiting for keystone to start..." - if ! timeout $SERVICE_TIMEOUT sh -c "while ! curl --noproxy '*' -s http://$SERVICE_HOST:$service_port/v$IDENTITY_API_VERSION/ >/dev/null; do sleep 1; done"; then + if ! timeout $SERVICE_TIMEOUT sh -c "while ! curl --noproxy '*' -s $KEYSTONE_AUTH_PROTOCOL://$SERVICE_HOST:$service_port/v$IDENTITY_API_VERSION/ >/dev/null; do sleep 1; done"; then die $LINENO "keystone did not start" fi diff --git a/lib/nova b/lib/nova index 6ab2000111..5fd0bebf65 100644 --- a/lib/nova +++ b/lib/nova @@ -225,6 +225,7 @@ function configure_nova() { inicomment $NOVA_API_PASTE_INI filter:authtoken auth_host inicomment $NOVA_API_PASTE_INI filter:authtoken auth_protocol inicomment $NOVA_API_PASTE_INI filter:authtoken admin_tenant_name + inicomment $NOVA_API_PASTE_INI filter:authtoken cafile inicomment $NOVA_API_PASTE_INI filter:authtoken admin_user inicomment $NOVA_API_PASTE_INI filter:authtoken admin_password fi @@ -399,6 +400,7 @@ function create_nova_conf() { iniset $NOVA_CONF keystone_authtoken auth_host $KEYSTONE_AUTH_HOST iniset $NOVA_CONF keystone_authtoken auth_protocol $KEYSTONE_AUTH_PROTOCOL iniset $NOVA_CONF keystone_authtoken admin_tenant_name $SERVICE_TENANT_NAME + iniset $NOVA_CONF keystone_authtoken cafile $KEYSTONE_SSL_CA iniset $NOVA_CONF keystone_authtoken admin_user nova iniset $NOVA_CONF keystone_authtoken admin_password $SERVICE_PASSWORD fi diff --git a/lib/swift b/lib/swift index 40722ab030..8a1489bcb5 100644 --- a/lib/swift +++ b/lib/swift @@ -316,6 +316,7 @@ function configure_swift() { iniset ${SWIFT_CONFIG_PROXY_SERVER} filter:authtoken auth_host $KEYSTONE_AUTH_HOST iniset ${SWIFT_CONFIG_PROXY_SERVER} filter:authtoken auth_port $KEYSTONE_AUTH_PORT iniset ${SWIFT_CONFIG_PROXY_SERVER} filter:authtoken auth_protocol $KEYSTONE_AUTH_PROTOCOL + iniset ${SWIFT_CONFIG_PROXY_SERVER} filter:authtoken cafile $KEYSTONE_SSL_CA iniset ${SWIFT_CONFIG_PROXY_SERVER} filter:authtoken auth_uri $KEYSTONE_SERVICE_PROTOCOL://$KEYSTONE_SERVICE_HOST:$KEYSTONE_SERVICE_PORT/ iniset ${SWIFT_CONFIG_PROXY_SERVER} filter:authtoken admin_tenant_name $SERVICE_TENANT_NAME iniset ${SWIFT_CONFIG_PROXY_SERVER} filter:authtoken admin_user swift @@ -339,6 +340,7 @@ paste.filter_factory = keystone.middleware.s3_token:filter_factory auth_port = ${KEYSTONE_AUTH_PORT} auth_host = ${KEYSTONE_AUTH_HOST} auth_protocol = ${KEYSTONE_AUTH_PROTOCOL} +cafile = ${KEYSTONE_SSL_CA} auth_token = ${SERVICE_TOKEN} admin_token = ${SERVICE_TOKEN} diff --git a/lib/tls b/lib/tls index a1a7fddc18..6134fa1bad 100644 --- a/lib/tls +++ b/lib/tls @@ -22,7 +22,8 @@ # - make_int_ca # - new_cert $INT_CA_DIR int-server "abc" # - start_tls_proxy HOST_IP 5000 localhost 5000 - +# - ensure_certificates +# - is_ssl_enabled_service # Defaults # -------- @@ -309,6 +310,53 @@ function make_root_CA() { } +# Certificate Input Configuration +# =============================== + +# check to see if the service(s) specified are to be SSL enabled. +# +# Multiple services specified as arguments are ``OR``'ed together; the test +# is a short-circuit boolean, i.e it returns on the first match. +# +# Uses global ``SSL_ENABLED_SERVICES`` +function is_ssl_enabled_service() { + services=$@ + for service in ${services}; do + [[ ,${SSL_ENABLED_SERVICES}, =~ ,${service}, ]] && return 0 + done + return 1 +} + + +# Ensure that the certificates for a service are in place. This function does +# not check that a service is SSL enabled, this should already have been +# completed. +# +# The function expects to find a certificate, key and CA certificate in the +# variables {service}_SSL_CERT, {service}_SSL_KEY and {service}_SSL_CA. For +# example for keystone this would be KEYSTONE_SSL_CERT, KEYSTONE_SSL_KEY and +# KEYSTONE_SSL_CA. If it does not find these certificates the program will +# quit. +function ensure_certificates() { + local service=$1 + + local cert_var="${service}_SSL_CERT" + local key_var="${service}_SSL_KEY" + local ca_var="${service}_SSL_CA" + + local cert=${!cert_var} + local key=${!key_var} + local ca=${!ca_var} + + if [[ !($cert && $key && $ca) ]]; then + die $LINENO "Missing either the ${cert_var} ${key_var} or ${ca_var}" \ + "variable to enable SSL for ${service}" + fi + + cat $ca >> $SSL_BUNDLE_FILE +} + + # Proxy Functions # =============== diff --git a/lib/trove b/lib/trove index c40006bf5d..5ba4de5a4f 100644 --- a/lib/trove +++ b/lib/trove @@ -29,7 +29,6 @@ TROVE_DIR=$DEST/trove TROVECLIENT_DIR=$DEST/python-troveclient TROVE_CONF_DIR=/etc/trove TROVE_LOCAL_CONF_DIR=$TROVE_DIR/etc/trove -TROVE_AUTH_ENDPOINT=$KEYSTONE_AUTH_PROTOCOL://$KEYSTONE_AUTH_HOST:$KEYSTONE_AUTH_PORT//v$IDENTITY_API_VERSION TROVE_AUTH_CACHE_DIR=${TROVE_AUTH_CACHE_DIR:-/var/cache/trove} TROVE_BIN_DIR=/usr/local/bin @@ -102,6 +101,7 @@ function configure_trove() { iniset $TROVE_API_PASTE_INI filter:tokenauth auth_host $KEYSTONE_AUTH_HOST iniset $TROVE_API_PASTE_INI filter:tokenauth auth_port $KEYSTONE_AUTH_PORT iniset $TROVE_API_PASTE_INI filter:tokenauth auth_protocol $KEYSTONE_AUTH_PROTOCOL + iniset $TROVE_API_PASTE_INI filter:tokenauth cafile $KEYSTONE_SSL_CA iniset $TROVE_API_PASTE_INI filter:tokenauth admin_tenant_name $SERVICE_TENANT_NAME iniset $TROVE_API_PASTE_INI filter:tokenauth admin_user trove iniset $TROVE_API_PASTE_INI filter:tokenauth admin_password $SERVICE_PASSWORD @@ -123,6 +123,8 @@ function configure_trove() { # (Re)create trove taskmanager conf file if needed if is_service_enabled tr-tmgr; then + TROVE_AUTH_ENDPOINT=$KEYSTONE_AUTH_PROTOCOL://$KEYSTONE_AUTH_HOST:$KEYSTONE_AUTH_PORT//v$IDENTITY_API_VERSION + iniset $TROVE_CONF_DIR/trove-taskmanager.conf DEFAULT rabbit_password $RABBIT_PASSWORD iniset $TROVE_CONF_DIR/trove-taskmanager.conf DEFAULT sql_connection `database_connection_url trove` iniset $TROVE_CONF_DIR/trove-taskmanager.conf DEFAULT taskmanager_manager trove.taskmanager.manager.Manager diff --git a/openrc b/openrc index 804bb3f3d7..784b00e51b 100644 --- a/openrc +++ b/openrc @@ -58,6 +58,7 @@ export OS_NO_CACHE=${OS_NO_CACHE:-1} HOST_IP=${HOST_IP:-127.0.0.1} SERVICE_HOST=${SERVICE_HOST:-$HOST_IP} SERVICE_PROTOCOL=${SERVICE_PROTOCOL:-http} +KEYSTONE_AUTH_PROTOCOL=${KEYSTONE_AUTH_PROTOCOL:-$SERVICE_PROTOCOL} # Some exercises call glance directly. On a single-node installation, Glance # should be listening on HOST_IP. If its running elsewhere, it can be set here @@ -71,10 +72,10 @@ export OS_IDENTITY_API_VERSION=${IDENTITY_API_VERSION:-2.0} # the user/tenant has access to - including nova, glance, keystone, swift, ... # We currently recommend using the 2.0 *identity api*. # -export OS_AUTH_URL=$SERVICE_PROTOCOL://$SERVICE_HOST:5000/v${OS_IDENTITY_API_VERSION} +export OS_AUTH_URL=$KEYSTONE_AUTH_PROTOCOL://$SERVICE_HOST:5000/v${OS_IDENTITY_API_VERSION} # Set the pointer to our CA certificate chain. Harmless if TLS is not used. -export OS_CACERT=$INT_CA_DIR/ca-chain.pem +export OS_CACERT=${OS_CACERT:-$INT_CA_DIR/ca-chain.pem} # Currently novaclient needs you to specify the *compute api* version. This # needs to match the config of your catalog returned by Keystone. diff --git a/stack.sh b/stack.sh index 825373e8c5..a2ef679a4e 100755 --- a/stack.sh +++ b/stack.sh @@ -290,6 +290,10 @@ LOG_COLOR=`trueorfalse True $LOG_COLOR` # Service startup timeout SERVICE_TIMEOUT=${SERVICE_TIMEOUT:-60} +# Reset the bundle of CA certificates +SSL_BUNDLE_FILE="$DATA_DIR/ca-bundle.pem" +rm -f $SSL_BUNDLE_FILE + # Configure Projects # ================== @@ -799,6 +803,17 @@ fi restart_rpc_backend +# Export Certicate Authority Bundle +# --------------------------------- + +# If certificates were used and written to the SSL bundle file then these +# should be exported so clients can validate their connections. + +if [ -f $SSL_BUNDLE_FILE ]; then + export OS_CACERT=$SSL_BUNDLE_FILE +fi + + # Configure database # ------------------ @@ -1146,6 +1161,7 @@ if is_service_enabled trove; then start_trove fi + # Create account rc files # ======================= @@ -1154,7 +1170,13 @@ fi # which is helpful in image bundle steps. if is_service_enabled nova && is_service_enabled key; then - $TOP_DIR/tools/create_userrc.sh -PA --target-dir $TOP_DIR/accrc + USERRC_PARAMS="-PA --target-dir $TOP_DIR/accrc" + + if [ -f $SSL_BUNDLE_FILE ]; then + USERRC_PARAMS="$USERRC_PARAMS --os-cacert $SSL_BUNDLE_FILE" + fi + + $TOP_DIR/tools/create_userrc.sh $USERRC_PARAMS fi @@ -1230,7 +1252,7 @@ fi CURRENT_RUN_TIME=$(date "+$TIMESTAMP_FORMAT") echo "# $CURRENT_RUN_TIME" >$TOP_DIR/.stackenv for i in BASE_SQL_CONN ENABLED_SERVICES HOST_IP LOGFILE \ - SERVICE_HOST SERVICE_PROTOCOL STACK_USER TLS_IP; do + SERVICE_HOST SERVICE_PROTOCOL STACK_USER TLS_IP KEYSTONE_AUTH_PROTOCOL OS_CACERT; do echo $i=${!i} >>$TOP_DIR/.stackenv done diff --git a/tools/create_userrc.sh b/tools/create_userrc.sh index 8383fe7d77..5f4c48660b 100755 --- a/tools/create_userrc.sh +++ b/tools/create_userrc.sh @@ -43,6 +43,7 @@ Optional Arguments --os-tenant-name --os-tenant-id --os-auth-url +--os-cacert --target-dir --skip-tenant --debug @@ -53,7 +54,7 @@ $0 -P -C mytenant -u myuser -p mypass EOF } -if ! options=$(getopt -o hPAp:u:r:C: -l os-username:,os-password:,os-tenant-name:,os-tenant-id:,os-auth-url:,target-dir:,skip-tenant:,help,debug -- "$@") +if ! options=$(getopt -o hPAp:u:r:C: -l os-username:,os-password:,os-tenant-name:,os-tenant-id:,os-auth-url:,target-dir:,skip-tenant:,os-cacert:,help,debug -- "$@") then #parse error display_help @@ -80,6 +81,7 @@ do --os-tenant-id) export OS_TENANT_ID=$2; shift ;; --skip-tenant) SKIP_TENANT="$SKIP_TENANT$2,"; shift ;; --os-auth-url) export OS_AUTH_URL=$2; shift ;; + --os-cacert) export OS_CACERT=$2; shift ;; --target-dir) ACCOUNT_DIR=$2; shift ;; --debug) set -o xtrace ;; -u) MODE=${MODE:-one}; USER_NAME=$2; shift ;; @@ -201,6 +203,7 @@ export OS_USERNAME="$user_name" # Openstack Tenant ID = $tenant_id export OS_TENANT_NAME="$tenant_name" export OS_AUTH_URL="$OS_AUTH_URL" +export OS_CACERT="$OS_CACERT" export EC2_CERT="$ec2_cert" export EC2_PRIVATE_KEY="$ec2_private_key" export EC2_USER_ID=42 #not checked by nova (can be a 12-digit id)