diff --git a/files/apache-keystone.template b/files/apache-keystone.template index 0a286b929c..88492d3408 100644 --- a/files/apache-keystone.template +++ b/files/apache-keystone.template @@ -11,6 +11,9 @@ Listen %ADMINPORT% ErrorLog /var/log/%APACHE_NAME%/keystone.log CustomLog /var/log/%APACHE_NAME%/keystone_access.log combined + %SSLENGINE% + %SSLCERTFILE% + %SSLKEYFILE% @@ -23,6 +26,9 @@ Listen %ADMINPORT% ErrorLog /var/log/%APACHE_NAME%/keystone.log CustomLog /var/log/%APACHE_NAME%/keystone_access.log combined + %SSLENGINE% + %SSLCERTFILE% + %SSLKEYFILE% # Workaround for missing path on RHEL6, see diff --git a/files/rpms/keystone b/files/rpms/keystone index e1873b7564..ce41ee598b 100644 --- a/files/rpms/keystone +++ b/files/rpms/keystone @@ -9,5 +9,6 @@ python-routes python-sqlalchemy python-webob sqlite +mod_ssl # Deps installed via pip for RHEL diff --git a/functions b/functions index 0194acf64e..376aff05e3 100644 --- a/functions +++ b/functions @@ -73,7 +73,7 @@ function upload_image { # OpenVZ-format images are provided as .tar.gz, but not decompressed prior to loading if [[ "$image_url" =~ 'openvz' ]]; then image_name="${image_fname%.tar.gz}" - openstack --os-token $token --os-url http://$GLANCE_HOSTPORT image create "$image_name" --public --container-format ami --disk-format ami < "${image}" + openstack --os-token $token --os-url $GLANCE_SERVICE_PROTOCOL://$GLANCE_HOSTPORT image create "$image_name" --public --container-format ami --disk-format ami < "${image}" return fi @@ -184,7 +184,7 @@ function upload_image { vmdk_adapter_type="${props[1]:-$vmdk_adapter_type}" vmdk_net_adapter="${props[2]:-$vmdk_net_adapter}" - openstack --os-token $token --os-url http://$GLANCE_HOSTPORT image create "$image_name" --public --container-format bare --disk-format vmdk --property vmware_disktype="$vmdk_disktype" --property vmware_adaptertype="$vmdk_adapter_type" --property hw_vif_model="$vmdk_net_adapter" < "${image}" + openstack --os-token $token --os-url $GLANCE_SERVICE_PROTOCOL://$GLANCE_HOSTPORT image create "$image_name" --public --container-format bare --disk-format vmdk --property vmware_disktype="$vmdk_disktype" --property vmware_adaptertype="$vmdk_adapter_type" --property hw_vif_model="$vmdk_net_adapter" < "${image}" return fi @@ -202,7 +202,7 @@ function upload_image { fi openstack \ --os-token $token \ - --os-url http://$GLANCE_HOSTPORT \ + --os-url $GLANCE_SERVICE_PROTOCOL://$GLANCE_HOSTPORT \ image create \ "$image_name" --public \ --container-format=ovf --disk-format=vhd \ @@ -217,7 +217,7 @@ function upload_image { image_name="${image_fname%.xen-raw.tgz}" openstack \ --os-token $token \ - --os-url http://$GLANCE_HOSTPORT \ + --os-url $GLANCE_SERVICE_PROTOCOL://$GLANCE_HOSTPORT \ image create \ "$image_name" --public \ --container-format=tgz --disk-format=raw \ @@ -295,9 +295,9 @@ function upload_image { if [ "$container_format" = "bare" ]; then if [ "$unpack" = "zcat" ]; then - openstack --os-token $token --os-url http://$GLANCE_HOSTPORT image create "$image_name" $img_property --public --container-format=$container_format --disk-format $disk_format < <(zcat --force "${image}") + openstack --os-token $token --os-url $GLANCE_SERVICE_PROTOCOL://$GLANCE_HOSTPORT image create "$image_name" $img_property --public --container-format=$container_format --disk-format $disk_format < <(zcat --force "${image}") else - openstack --os-token $token --os-url http://$GLANCE_HOSTPORT image create "$image_name" $img_property --public --container-format=$container_format --disk-format $disk_format < "${image}" + openstack --os-token $token --os-url $GLANCE_SERVICE_PROTOCOL://$GLANCE_HOSTPORT image create "$image_name" $img_property --public --container-format=$container_format --disk-format $disk_format < "${image}" fi else # Use glance client to add the kernel the root filesystem. @@ -305,12 +305,12 @@ function upload_image { # kernel for use when uploading the root filesystem. local kernel_id="" ramdisk_id=""; if [ -n "$kernel" ]; then - kernel_id=$(openstack --os-token $token --os-url http://$GLANCE_HOSTPORT image create "$image_name-kernel" $img_property --public --container-format aki --disk-format aki < "$kernel" | grep ' id ' | get_field 2) + kernel_id=$(openstack --os-token $token --os-url $GLANCE_SERVICE_PROTOCOL://$GLANCE_HOSTPORT image create "$image_name-kernel" $img_property --public --container-format aki --disk-format aki < "$kernel" | grep ' id ' | get_field 2) fi if [ -n "$ramdisk" ]; then - ramdisk_id=$(openstack --os-token $token --os-url http://$GLANCE_HOSTPORT image create "$image_name-ramdisk" $img_property --public --container-format ari --disk-format ari < "$ramdisk" | grep ' id ' | get_field 2) + ramdisk_id=$(openstack --os-token $token --os-url $GLANCE_SERVICE_PROTOCOL://$GLANCE_HOSTPORT image create "$image_name-ramdisk" $img_property --public --container-format ari --disk-format ari < "$ramdisk" | grep ' id ' | get_field 2) fi - openstack --os-token $token --os-url http://$GLANCE_HOSTPORT image create "${image_name%.img}" $img_property --public --container-format ami --disk-format ami ${kernel_id:+--property kernel_id=$kernel_id} ${ramdisk_id:+--property ramdisk_id=$ramdisk_id} < "${image}" + openstack --os-token $token --os-url $GLANCE_SERVICE_PROTOCOL://$GLANCE_HOSTPORT image create "${image_name%.img}" $img_property --public --container-format ami --disk-format ami ${kernel_id:+--property kernel_id=$kernel_id} ${ramdisk_id:+--property ramdisk_id=$ramdisk_id} < "${image}" fi } @@ -339,7 +339,7 @@ function use_database { function wait_for_service { local timeout=$1 local url=$2 - timeout $timeout sh -c "while ! curl --noproxy '*' -s $url >/dev/null; do sleep 1; done" + timeout $timeout sh -c "while ! curl -k --noproxy '*' -s $url >/dev/null; do sleep 1; done" } diff --git a/lib/cinder b/lib/cinder index cbca9c0c1d..b30a036d16 100644 --- a/lib/cinder +++ b/lib/cinder @@ -46,6 +46,9 @@ CINDER_CONF=$CINDER_CONF_DIR/cinder.conf CINDER_API_PASTE_INI=$CINDER_CONF_DIR/api-paste.ini # Public facing bits +if is_ssl_enabled_service "cinder" || is_service_enabled tls-proxy; then + CINDER_SERVICE_PROTOCOL="https" +fi CINDER_SERVICE_HOST=${CINDER_SERVICE_HOST:-$SERVICE_HOST} CINDER_SERVICE_PORT=${CINDER_SERVICE_PORT:-8776} CINDER_SERVICE_PORT_INT=${CINDER_SERVICE_PORT_INT:-18776} @@ -299,6 +302,20 @@ function configure_cinder { fi iniset $CINDER_CONF DEFAULT osapi_volume_workers "$API_WORKERS" + + iniset $CINDER_CONF DEFAULT glance_api_servers "${GLANCE_SERVICE_PROTOCOL}://${GLANCE_HOSTPORT}" + if is_ssl_enabled_service glance || is_service_enabled tls-proxy; then + iniset $CINDER_CONF DEFAULT glance_protocol https + fi + + # Register SSL certificates if provided + if is_ssl_enabled_service cinder; then + ensure_certificates CINDER + + iniset $CINDER_CONF DEFAULT ssl_cert_file "$CINDER_SSL_CERT" + iniset $CINDER_CONF DEFAULT ssl_key_file "$CINDER_SSL_KEY" + fi + } # create_cinder_accounts() - Set up common required cinder accounts @@ -399,6 +416,12 @@ function _configure_tgt_for_config_d { # start_cinder() - Start running processes, including screen function start_cinder { + local service_port=$CINDER_SERVICE_PORT + local service_protocol=$CINDER_SERVICE_PROTOCOL + if is_service_enabled tls-proxy; then + service_port=$CINDER_SERVICE_PORT_INT + service_protocol="http" + fi if is_service_enabled c-vol; then # Delete any old stack.conf sudo rm -f /etc/tgt/conf.d/stack.conf @@ -425,7 +448,7 @@ function start_cinder { run_process c-api "$CINDER_BIN_DIR/cinder-api --config-file $CINDER_CONF" echo "Waiting for Cinder API to start..." - if ! wait_for_service $SERVICE_TIMEOUT $CINDER_SERVICE_PROTOCOL://$CINDER_SERVICE_HOST:$CINDER_SERVICE_PORT; then + if ! wait_for_service $SERVICE_TIMEOUT $service_protocol://$CINDER_SERVICE_HOST:$service_port; then die $LINENO "c-api did not start" fi diff --git a/lib/glance b/lib/glance index 6ca2fb5ca6..4194842407 100644 --- a/lib/glance +++ b/lib/glance @@ -51,8 +51,18 @@ else GLANCE_BIN_DIR=$(get_python_exec_prefix) fi +if is_ssl_enabled_service "glance" || is_service_enabled tls-proxy; then + GLANCE_SERVICE_PROTOCOL="https" +fi + # Glance connection info. Note the port must be specified. -GLANCE_HOSTPORT=${GLANCE_HOSTPORT:-$SERVICE_HOST:9292} +GLANCE_SERVICE_HOST=${GLANCE_SERVICE_HOST:-$SERVICE_HOST} +GLANCE_SERVICE_PORT=${GLANCE_SERVICE_PORT:-9292} +GLANCE_SERVICE_PORT_INT=${GLANCE_SERVICE_PORT_INT:-19292} +GLANCE_HOSTPORT=${GLANCE_HOSTPORT:-$GLANCE_SERVICE_HOST:$GLANCE_SERVICE_PORT} +GLANCE_SERVICE_PROTOCOL=${GLANCE_SERVICE_PROTOCOL:-$SERVICE_PROTOCOL} +GLANCE_REGISTRY_PORT=${GLANCE_REGISTRY_PORT:-9191} +GLANCE_REGISTRY_PORT_INT=${GLANCE_REGISTRY_PORT_INT:-19191} # Tell Tempest this project is present TEMPEST_SERVICES+=,glance @@ -148,6 +158,26 @@ function configure_glance { iniset $GLANCE_API_CONF glance_store stores "file, http, swift" fi + if is_service_enabled tls-proxy; then + iniset $GLANCE_API_CONF DEFAULT bind_port $GLANCE_SERVICE_PORT_INT + iniset $GLANCE_REGISTRY_CONF DEFAULT bind_port $GLANCE_REGISTRY_PORT_INT + fi + + # Register SSL certificates if provided + if is_ssl_enabled_service glance; then + ensure_certificates GLANCE + + iniset $GLANCE_API_CONF DEFAULT cert_file "$GLANCE_SSL_CERT" + iniset $GLANCE_API_CONF DEFAULT key_file "$GLANCE_SSL_KEY" + + iniset $GLANCE_REGISTRY_CONF DEFAULT cert_file "$GLANCE_SSL_CERT" + iniset $GLANCE_REGISTRY_CONF DEFAULT key_file "$GLANCE_SSL_KEY" + fi + + if is_ssl_enabled_service glance || is_service_enabled tls-proxy; then + iniset $GLANCE_API_CONF DEFAULT registry_client_protocol https + fi + cp -p $GLANCE_DIR/etc/glance-registry-paste.ini $GLANCE_REGISTRY_PASTE_INI cp -p $GLANCE_DIR/etc/glance-api-paste.ini $GLANCE_API_PASTE_INI @@ -176,6 +206,14 @@ function configure_glance { cp -p $GLANCE_DIR/etc/schema-image.json $GLANCE_SCHEMA_JSON cp -p $GLANCE_DIR/etc/metadefs/*.json $GLANCE_METADEF_DIR + + if is_ssl_enabled_service "cinder" || is_service_enabled tls-proxy; then + CINDER_SERVICE_HOST=${CINDER_SERVICE_HOST:-$SERVICE_HOST} + CINDER_SERVICE_PORT=${CINDER_SERVICE_PORT:-8776} + + iniset $GLANCE_API_CONF DEFAULT cinder_endpoint_template "https://$CINDER_SERVICE_HOST:$CINDER_SERVICE_PORT/v1/%(project_id)s" + iniset $GLANCE_CACHE_CONF DEFAULT cinder_endpoint_template "https://$CINDER_SERVICE_HOST:$CINDER_SERVICE_PORT/v1/%(project_id)s" + fi } # create_glance_accounts() - Set up common required glance accounts @@ -206,9 +244,9 @@ function create_glance_accounts { "image" "Glance Image Service") get_or_create_endpoint $glance_service \ "$REGION_NAME" \ - "http://$GLANCE_HOSTPORT" \ - "http://$GLANCE_HOSTPORT" \ - "http://$GLANCE_HOSTPORT" + "$GLANCE_SERVICE_PROTOCOL://$GLANCE_HOSTPORT" \ + "$GLANCE_SERVICE_PROTOCOL://$GLANCE_HOSTPORT" \ + "$GLANCE_SERVICE_PROTOCOL://$GLANCE_HOSTPORT" fi fi } @@ -265,10 +303,17 @@ function install_glance { # start_glance() - Start running processes, including screen function start_glance { + local service_protocol=$GLANCE_SERVICE_PROTOCOL + if is_service_enabled tls-proxy; then + start_tls_proxy '*' $GLANCE_SERVICE_PORT $GLANCE_SERVICE_HOST $GLANCE_SERVICE_PORT_INT & + start_tls_proxy '*' $GLANCE_REGISTRY_PORT $GLANCE_SERVICE_HOST $GLANCE_REGISTRY_PORT_INT & + fi + run_process g-reg "$GLANCE_BIN_DIR/glance-registry --config-file=$GLANCE_CONF_DIR/glance-registry.conf" run_process g-api "$GLANCE_BIN_DIR/glance-api --config-file=$GLANCE_CONF_DIR/glance-api.conf" + echo "Waiting for g-api ($GLANCE_HOSTPORT) to start..." - if ! timeout $SERVICE_TIMEOUT sh -c "while ! wget --no-proxy -q -O- http://$GLANCE_HOSTPORT; do sleep 1; done"; then + if ! wait_for_service $SERVICE_TIMEOUT $GLANCE_SERVICE_PROTOCOL://$GLANCE_HOSTPORT; then die $LINENO "g-api did not start" fi } diff --git a/lib/heat b/lib/heat index f64cc9041c..ff3b307e5b 100644 --- a/lib/heat +++ b/lib/heat @@ -113,7 +113,7 @@ function configure_heat { configure_auth_token_middleware $HEAT_CONF heat $HEAT_AUTH_CACHE_DIR if is_ssl_enabled_service "key"; then - iniset $HEAT_CONF clients_keystone ca_file $KEYSTONE_SSL_CA + iniset $HEAT_CONF clients_keystone ca_file $SSL_BUNDLE_FILE fi # ec2authtoken @@ -131,6 +131,18 @@ function configure_heat { # Cloudwatch API iniset $HEAT_CONF heat_api_cloudwatch bind_port $HEAT_API_CW_PORT + if is_ssl_enabled_service "key" || is_service_enabled tls-proxy; then + iniset $HEAT_CONF clients_keystone ca_file $SSL_BUNDLE_FILE + fi + + if is_ssl_enabled_service "nova" || is_service_enabled tls-proxy; then + iniset $HEAT_CONF clients_nova ca_file $SSL_BUNDLE_FILE + fi + + if is_ssl_enabled_service "cinder" || is_service_enabled tls-proxy; then + iniset $HEAT_CONF clients_cinder ca_file $SSL_BUNDLE_FILE + fi + # heat environment sudo mkdir -p $HEAT_ENV_DIR sudo chown $STACK_USER $HEAT_ENV_DIR diff --git a/lib/keystone b/lib/keystone index 9eca80a3dd..a7742a9f2c 100644 --- a/lib/keystone +++ b/lib/keystone @@ -95,7 +95,7 @@ KEYSTONE_VALID_IDENTITY_BACKENDS=kvs,ldap,pam,sql KEYSTONE_VALID_ASSIGNMENT_BACKENDS=kvs,ldap,sql # if we are running with SSL use https protocols -if is_ssl_enabled_service "key"; then +if is_ssl_enabled_service "key" || is_service_enabled tls-proxy; then KEYSTONE_AUTH_PROTOCOL="https" KEYSTONE_SERVICE_PROTOCOL="https" fi @@ -123,7 +123,21 @@ function _config_keystone_apache_wsgi { sudo mkdir -p $KEYSTONE_WSGI_DIR local keystone_apache_conf=$(apache_site_config_for keystone) - local apache_version=$(get_apache_version) + local keystone_ssl="" + local keystone_certfile="" + local keystone_keyfile="" + local keystone_service_port=$KEYSTONE_SERVICE_PORT + local keystone_auth_port=$KEYSTONE_AUTH_PORT + + if is_ssl_enabled_service key; then + keystone_ssl="SSLEngine On" + keystone_certfile="SSLCertificateFile $KEYSTONE_SSL_CERT" + keystone_keyfile="SSLCertificateKeyFile $KEYSTONE_SSL_KEY" + fi + if is_service_enabled tls-proxy; then + keystone_service_port=$KEYSTONE_SERVICE_PORT_INT + keystone_auth_port=$KEYSTONE_AUTH_PORT_INT + fi # copy proxy vhost and wsgi file sudo cp $KEYSTONE_DIR/httpd/keystone.py $KEYSTONE_WSGI_DIR/main @@ -131,11 +145,14 @@ function _config_keystone_apache_wsgi { sudo cp $FILES/apache-keystone.template $keystone_apache_conf sudo sed -e " - s|%PUBLICPORT%|$KEYSTONE_SERVICE_PORT|g; - s|%ADMINPORT%|$KEYSTONE_AUTH_PORT|g; + s|%PUBLICPORT%|$keystone_service_port|g; + s|%ADMINPORT%|$keystone_auth_port|g; s|%APACHE_NAME%|$APACHE_NAME|g; s|%PUBLICWSGI%|$KEYSTONE_WSGI_DIR/main|g; s|%ADMINWSGI%|$KEYSTONE_WSGI_DIR/admin|g; + s|%SSLENGINE%|$keystone_ssl|g; + s|%SSLCERTFILE%|$keystone_certfile|g; + s|%SSLKEYFILE%|$keystone_keyfile|g; s|%USER%|$STACK_USER|g " -i $keystone_apache_conf } @@ -200,8 +217,13 @@ function configure_keystone { fi # Set the URL advertised in the ``versions`` structure returned by the '/' route - 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/" + if is_service_enabled tls-proxy; then + iniset $KEYSTONE_CONF DEFAULT public_endpoint "$KEYSTONE_SERVICE_PROTOCOL://$KEYSTONE_SERVICE_HOST:$KEYSTONE_SERVICE_PORT/" + iniset $KEYSTONE_CONF DEFAULT admin_endpoint "$KEYSTONE_SERVICE_PROTOCOL://$KEYSTONE_SERVICE_HOST:$KEYSTONE_AUTH_PORT/" + else + 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/" + fi iniset $KEYSTONE_CONF DEFAULT admin_bind_host "$KEYSTONE_ADMIN_BIND_HOST" # Register SSL certificates if provided @@ -412,7 +434,7 @@ function configure_auth_token_middleware { iniset $conf_file $section auth_port $KEYSTONE_AUTH_PORT iniset $conf_file $section auth_protocol $KEYSTONE_AUTH_PROTOCOL iniset $conf_file $section identity_uri $KEYSTONE_AUTH_URI - iniset $conf_file $section cafile $KEYSTONE_SSL_CA + iniset $conf_file $section cafile $SSL_BUNDLE_FILE configure_API_version $conf_file $IDENTITY_API_VERSION $section iniset $conf_file $section admin_tenant_name $SERVICE_TENANT_NAME iniset $conf_file $section admin_user $admin_user @@ -489,6 +511,9 @@ function install_keystone { setup_develop $KEYSTONE_DIR if [ "$KEYSTONE_USE_MOD_WSGI" == "True" ]; then install_apache_wsgi + if is_ssl_enabled_service "key"; then + enable_mod_ssl + fi fi } @@ -496,8 +521,10 @@ function install_keystone { function start_keystone { # Get right service port for testing local service_port=$KEYSTONE_SERVICE_PORT + local auth_protocol=$KEYSTONE_AUTH_PROTOCOL if is_service_enabled tls-proxy; then service_port=$KEYSTONE_SERVICE_PORT_INT + auth_protocol="http" fi if [ "$KEYSTONE_USE_MOD_WSGI" == "True" ]; then @@ -514,7 +541,7 @@ function start_keystone { # Check that the keystone service is running. Even if the tls tunnel # should be enabled, make sure the internal port is checked using # unencryted traffic at this point. - if ! timeout $SERVICE_TIMEOUT sh -c "while ! curl --noproxy '*' -k -s http://$KEYSTONE_SERVICE_HOST:$service_port/v$IDENTITY_API_VERSION/ >/dev/null; do sleep 1; done"; then + if ! timeout $SERVICE_TIMEOUT sh -c "while ! curl --noproxy '*' -k -s $auth_protocol://$KEYSTONE_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/neutron b/lib/neutron index 96cd47bdb6..81f2697abb 100644 --- a/lib/neutron +++ b/lib/neutron @@ -69,6 +69,11 @@ PUBLIC_NETWORK_GATEWAY=${PUBLIC_NETWORK_GATEWAY:-172.24.4.1} PRIVATE_SUBNET_NAME=${PRIVATE_SUBNET_NAME:-"private-subnet"} PUBLIC_SUBNET_NAME=${PUBLIC_SUBNET_NAME:-"public-subnet"} +if is_ssl_enabled_service "neutron" || is_service_enabled tls-proxy; then + Q_PROTOCOL="https" +fi + + # Set up default directories NEUTRON_DIR=$DEST/neutron NEUTRONCLIENT_DIR=$DEST/python-neutronclient @@ -105,8 +110,12 @@ Q_DB_NAME=${Q_DB_NAME:-neutron} Q_PLUGIN=${Q_PLUGIN:-ml2} # Default Neutron Port Q_PORT=${Q_PORT:-9696} +# Default Neutron Internal Port when using TLS proxy +Q_PORT_INT=${Q_PORT_INT:-19696} # Default Neutron Host Q_HOST=${Q_HOST:-$SERVICE_HOST} +# Default protocol +Q_PROTOCOL=${Q_PROTOCOL:-$SERVICE_PROTOCOL} # Default admin username Q_ADMIN_USERNAME=${Q_ADMIN_USERNAME:-neutron} # Default auth strategy @@ -409,7 +418,7 @@ function create_nova_conf_neutron { iniset $NOVA_CONF neutron auth_strategy "$Q_AUTH_STRATEGY" iniset $NOVA_CONF neutron admin_tenant_name "$SERVICE_TENANT_NAME" iniset $NOVA_CONF neutron region_name "$REGION_NAME" - iniset $NOVA_CONF neutron url "http://$Q_HOST:$Q_PORT" + iniset $NOVA_CONF neutron url "${Q_PROTOCOL}://$Q_HOST:$Q_PORT" if [[ "$Q_USE_SECGROUP" == "True" ]]; then LIBVIRT_FIREWALL_DRIVER=nova.virt.firewall.NoopFirewallDriver @@ -462,9 +471,9 @@ function create_neutron_accounts { "network" "Neutron Service") get_or_create_endpoint $neutron_service \ "$REGION_NAME" \ - "http://$SERVICE_HOST:$Q_PORT/" \ - "http://$SERVICE_HOST:$Q_PORT/" \ - "http://$SERVICE_HOST:$Q_PORT/" + "$Q_PROTOCOL://$SERVICE_HOST:$Q_PORT/" \ + "$Q_PROTOCOL://$SERVICE_HOST:$Q_PORT/" \ + "$Q_PROTOCOL://$SERVICE_HOST:$Q_PORT/" fi fi } @@ -590,12 +599,25 @@ function install_neutron_agent_packages { # Start running processes, including screen function start_neutron_service_and_check { local cfg_file_options="$(determine_config_files neutron-server)" + local service_port=$Q_PORT + local service_protocol=$Q_PROTOCOL + if is_service_enabled tls-proxy; then + service_port=$Q_PORT_INT + service_protocol="http" + fi # Start the Neutron service run_process q-svc "python $NEUTRON_BIN_DIR/neutron-server $cfg_file_options" echo "Waiting for Neutron to start..." - if ! timeout $SERVICE_TIMEOUT sh -c "while ! wget --no-proxy -q -O- http://$Q_HOST:$Q_PORT; do sleep 1; done"; then + if is_ssl_enabled_service "neutron"; then + ssl_ca="--ca-certificate=${SSL_BUNDLE_FILE}" + fi + if ! timeout $SERVICE_TIMEOUT sh -c "while ! wget ${ssl_ca} --no-proxy -q -O- $service_protocol://$Q_HOST:$service_port; do sleep 1; done"; then die $LINENO "Neutron did not start" fi + # Start proxy if enabled + if is_service_enabled tls-proxy; then + start_tls_proxy '*' $Q_PORT $Q_HOST $Q_PORT_INT & + fi } # Start running processes, including screen @@ -730,6 +752,23 @@ function _configure_neutron_common { setup_colorized_logging $NEUTRON_CONF DEFAULT project_id fi + if is_service_enabled tls-proxy; then + # Set the service port for a proxy to take the original + iniset $NEUTRON_CONF DEFAULT bind_port "$Q_PORT_INT" + fi + + if is_ssl_enabled_service "nova"; then + iniset $NEUTRON_CONF DEFAULT nova_ca_certificates_file "$SSL_BUNDLE_FILE" + fi + + if is_ssl_enabled_service "neutron"; then + ensure_certificates NEUTRON + + iniset $NEUTRON_CONF DEFAULT use_ssl True + iniset $NEUTRON_CONF DEFAULT ssl_cert_file "$NEUTRON_SSL_CERT" + iniset $NEUTRON_CONF DEFAULT ssl_key_file "$NEUTRON_SSL_KEY" + fi + _neutron_setup_rootwrap } diff --git a/lib/nova b/lib/nova index 2a3aae1835..cfa6f7a8ec 100644 --- a/lib/nova +++ b/lib/nova @@ -44,11 +44,20 @@ NOVA_CELLS_DB=${NOVA_CELLS_DB:-nova_cell} NOVA_API_PASTE_INI=${NOVA_API_PASTE_INI:-$NOVA_CONF_DIR/api-paste.ini} +if is_ssl_enabled_service "nova" || is_service_enabled tls-proxy; then + NOVA_SERVICE_PROTOCOL="https" + EC2_SERVICE_PROTOCOL="https" +else + EC2_SERVICE_PROTOCOL="http" +fi + # Public facing bits NOVA_SERVICE_HOST=${NOVA_SERVICE_HOST:-$SERVICE_HOST} NOVA_SERVICE_PORT=${NOVA_SERVICE_PORT:-8774} NOVA_SERVICE_PORT_INT=${NOVA_SERVICE_PORT_INT:-18774} NOVA_SERVICE_PROTOCOL=${NOVA_SERVICE_PROTOCOL:-$SERVICE_PROTOCOL} +EC2_SERVICE_PORT=${EC2_SERVICE_PORT:-8773} +EC2_SERVICE_PORT_INT=${EC2_SERVICE_PORT_INT:-18773} # Support entry points installation of console scripts if [[ -d $NOVA_DIR/bin ]]; then @@ -375,9 +384,9 @@ create_nova_accounts() { "ec2" "EC2 Compatibility Layer") get_or_create_endpoint $ec2_service \ "$REGION_NAME" \ - "http://$SERVICE_HOST:8773/services/Cloud" \ - "http://$SERVICE_HOST:8773/services/Admin" \ - "http://$SERVICE_HOST:8773/services/Cloud" + "$EC2_SERVICE_PROTOCOL://$SERVICE_HOST:8773/services/Cloud" \ + "$EC2_SERVICE_PROTOCOL://$SERVICE_HOST:8773/services/Admin" \ + "$EC2_SERVICE_PROTOCOL://$SERVICE_HOST:8773/services/Cloud" fi fi @@ -441,6 +450,16 @@ function create_nova_conf { configure_auth_token_middleware $NOVA_CONF nova $NOVA_AUTH_CACHE_DIR fi + if is_service_enabled cinder; then + iniset $NOVA_CONF DEFAULT volume_api_class "nova.volume.cinder.API" + if is_ssl_enabled_service "cinder" || is_service_enabled tls-proxy; then + CINDER_SERVICE_HOST=${CINDER_SERVICE_HOST:-$SERVICE_HOST} + CINDER_SERVICE_PORT=${CINDER_SERVICE_PORT:-8776} + iniset $NOVA_CONF DEFAULT cinder_endpoint_template "https://$CINDER_SERVICE_HOST:$CINDER_SERVICE_PORT/v1/%(project_id)s" + iniset $NOVA_CONF DEFAULT cinder_ca_certificates_file $SSL_BUNDLE_FILE + fi + fi + if [ -n "$NOVA_STATE_PATH" ]; then iniset $NOVA_CONF DEFAULT state_path "$NOVA_STATE_PATH" iniset $NOVA_CONF DEFAULT lock_path "$NOVA_STATE_PATH" @@ -508,12 +527,31 @@ function create_nova_conf { fi iniset $NOVA_CONF DEFAULT ec2_dmz_host "$EC2_DMZ_HOST" + iniset $NOVA_CONF DEFAULT keystone_ec2_url $KEYSTONE_SERVICE_PROTOCOL://$KEYSTONE_SERVICE_HOST:$KEYSTONE_SERVICE_PORT/v2.0/ec2tokens iniset_rpc_backend nova $NOVA_CONF DEFAULT - iniset $NOVA_CONF glance api_servers "$GLANCE_HOSTPORT" + iniset $NOVA_CONF glance api_servers "${GLANCE_SERVICE_PROTOCOL}://${GLANCE_HOSTPORT}" iniset $NOVA_CONF DEFAULT osci_compute_workers "$API_WORKERS" iniset $NOVA_CONF DEFAULT ec2_workers "$API_WORKERS" iniset $NOVA_CONF DEFAULT metadata_workers "$API_WORKERS" + + if is_ssl_enabled_service glance || is_service_enabled tls-proxy; then + iniset $NOVA_CONF DEFAULT glance_protocol https + fi + + # Register SSL certificates if provided + if is_ssl_enabled_service nova; then + ensure_certificates NOVA + + iniset $NOVA_CONF DEFAULT ssl_cert_file "$NOVA_SSL_CERT" + iniset $NOVA_CONF DEFAULT ssl_key_file "$NOVA_SSL_KEY" + + iniset $NOVA_CONF DEFAULT enabled_ssl_apis "$NOVA_ENABLED_APIS" + fi + + if is_service_enabled tls-proxy; then + iniset $NOVA_CONF DEFAULT ec2_listen_port $EC2_SERVICE_PORT_INT + fi } function init_nova_cells { @@ -642,19 +680,22 @@ function install_nova { function start_nova_api { # Get right service port for testing local service_port=$NOVA_SERVICE_PORT + local service_protocol=$NOVA_SERVICE_PROTOCOL if is_service_enabled tls-proxy; then service_port=$NOVA_SERVICE_PORT_INT + service_protocol="http" fi run_process n-api "$NOVA_BIN_DIR/nova-api" echo "Waiting for nova-api to start..." - if ! wait_for_service $SERVICE_TIMEOUT http://$SERVICE_HOST:$service_port; then + if ! wait_for_service $SERVICE_TIMEOUT $service_protocol://$SERVICE_HOST:$service_port; then die $LINENO "nova-api did not start" fi # Start proxies if enabled if is_service_enabled tls-proxy; then start_tls_proxy '*' $NOVA_SERVICE_PORT $NOVA_SERVICE_HOST $NOVA_SERVICE_PORT_INT & + start_tls_proxy '*' $EC2_SERVICE_PORT $NOVA_SERVICE_HOST $EC2_SERVICE_PORT_INT & fi } diff --git a/lib/swift b/lib/swift index 3c31dd293a..813955226e 100644 --- a/lib/swift +++ b/lib/swift @@ -29,6 +29,10 @@ set +o xtrace # Defaults # -------- +if is_ssl_enabled_service "s-proxy" || is_service_enabled tls-proxy; then + SWIFT_SERVICE_PROTOCOL="https" +fi + # Set up default directories SWIFT_DIR=$DEST/swift SWIFTCLIENT_DIR=$DEST/python-swiftclient @@ -36,6 +40,9 @@ SWIFT_AUTH_CACHE_DIR=${SWIFT_AUTH_CACHE_DIR:-/var/cache/swift} SWIFT_APACHE_WSGI_DIR=${SWIFT_APACHE_WSGI_DIR:-/var/www/swift} SWIFT3_DIR=$DEST/swift3 +SWIFT_SERVICE_PROTOCOL=${SWIFT_SERVICE_PROTOCOL:-$SERVICE_PROTOCOL} +SWIFT_DEFAULT_BIND_PORT_INT=${SWIFT_DEFAULT_BIND_PORT_INT:-8081} + # TODO: add logging to different location. # Set ``SWIFT_DATA_DIR`` to the location of swift drives and objects. @@ -334,7 +341,18 @@ function configure_swift { iniset ${SWIFT_CONFIG_PROXY_SERVER} DEFAULT log_level DEBUG iniuncomment ${SWIFT_CONFIG_PROXY_SERVER} DEFAULT bind_port - iniset ${SWIFT_CONFIG_PROXY_SERVER} DEFAULT bind_port ${SWIFT_DEFAULT_BIND_PORT:-8080} + if is_service_enabled tls-proxy; then + iniset ${SWIFT_CONFIG_PROXY_SERVER} DEFAULT bind_port ${SWIFT_DEFAULT_BIND_PORT_INT} + else + iniset ${SWIFT_CONFIG_PROXY_SERVER} DEFAULT bind_port ${SWIFT_DEFAULT_BIND_PORT:-8080} + fi + + if is_ssl_enabled_service s-proxy; then + ensure_certificates SWIFT + + iniset ${SWIFT_CONFIG_PROXY_SERVER} DEFAULT cert_file "$SWIFT_SSL_CERT" + iniset ${SWIFT_CONFIG_PROXY_SERVER} DEFAULT key_file "$SWIFT_SSL_KEY" + fi # Devstack is commonly run in a small slow environment, so bump the # timeouts up. @@ -401,7 +419,7 @@ paste.filter_factory = keystoneclient.middleware.s3_token:filter_factory auth_port = ${KEYSTONE_AUTH_PORT} auth_host = ${KEYSTONE_AUTH_HOST} auth_protocol = ${KEYSTONE_AUTH_PROTOCOL} -cafile = ${KEYSTONE_SSL_CA} +cafile = ${SSL_BUNDLE_FILE} auth_token = ${SERVICE_TOKEN} admin_token = ${SERVICE_TOKEN} @@ -560,9 +578,9 @@ function create_swift_accounts { "object-store" "Swift Service") get_or_create_endpoint $swift_service \ "$REGION_NAME" \ - "http://$SERVICE_HOST:8080/v1/AUTH_\$(tenant_id)s" \ - "http://$SERVICE_HOST:8080" \ - "http://$SERVICE_HOST:8080/v1/AUTH_\$(tenant_id)s" + "$SWIFT_SERVICE_PROTOCOL://$SERVICE_HOST:8080/v1/AUTH_\$(tenant_id)s" \ + "$SWIFT_SERVICE_PROTOCOL://$SERVICE_HOST:8080" \ + "$SWIFT_SERVICE_PROTOCOL://$SERVICE_HOST:8080/v1/AUTH_\$(tenant_id)s" fi local swift_tenant_test1=$(get_or_create_project swifttenanttest1) @@ -675,6 +693,10 @@ function start_swift { for type in proxy ${todo}; do swift-init --run-dir=${SWIFT_DATA_DIR}/run ${type} stop || true done + if is_service_enabled tls-proxy; then + local proxy_port=${SWIFT_DEFAULT_BIND_PORT:-8080} + start_tls_proxy '*' $proxy_port $SERVICE_HOST $SWIFT_DEFAULT_BIND_PORT_INT & + fi run_process s-proxy "$SWIFT_DIR/bin/swift-proxy-server ${SWIFT_CONF_DIR}/proxy-server.conf -v" if [[ ${SWIFT_REPLICAS} == 1 ]]; then for type in object container account; do diff --git a/lib/tempest b/lib/tempest index 906cb00f95..0e5f9c9496 100644 --- a/lib/tempest +++ b/lib/tempest @@ -317,7 +317,7 @@ function configure_tempest { iniset $TEMPEST_CONFIG network-feature-disabled api_extensions ${DISABLE_NETWORK_API_EXTENSIONS} # boto - iniset $TEMPEST_CONFIG boto ec2_url "http://$SERVICE_HOST:8773/services/Cloud" + iniset $TEMPEST_CONFIG boto ec2_url "$EC2_SERVICE_PROTOCOL://$SERVICE_HOST:8773/services/Cloud" iniset $TEMPEST_CONFIG boto s3_url "http://$SERVICE_HOST:${S3_SERVICE_PORT:-3333}" iniset $TEMPEST_CONFIG boto s3_materials_path "$BOTO_MATERIALS_PATH" iniset $TEMPEST_CONFIG boto ari_manifest cirros-${CIRROS_VERSION}-${CIRROS_ARCH}-initrd.manifest.xml diff --git a/lib/tls b/lib/tls index 061c1cabbf..15e8692556 100644 --- a/lib/tls +++ b/lib/tls @@ -14,6 +14,7 @@ # # - configure_CA # - init_CA +# - cleanup_CA # - configure_proxy # - start_tls_proxy @@ -27,6 +28,7 @@ # - start_tls_proxy HOST_IP 5000 localhost 5000 # - ensure_certificates # - is_ssl_enabled_service +# - enable_mod_ssl # Defaults # -------- @@ -34,14 +36,9 @@ if is_service_enabled tls-proxy; then # TODO(dtroyer): revisit this below after the search for HOST_IP has been done TLS_IP=${TLS_IP:-$SERVICE_IP} - - # Set the default ``SERVICE_PROTOCOL`` for TLS - SERVICE_PROTOCOL=https fi -# Make up a hostname for cert purposes -# will be added to /etc/hosts? -DEVSTACK_HOSTNAME=secure.devstack.org +DEVSTACK_HOSTNAME=$(hostname -f) DEVSTACK_CERT_NAME=devstack-cert DEVSTACK_CERT=$DATA_DIR/$DEVSTACK_CERT_NAME.pem @@ -209,6 +206,29 @@ function init_CA { # Create the CA bundle cat $ROOT_CA_DIR/cacert.pem $INT_CA_DIR/cacert.pem >>$INT_CA_DIR/ca-chain.pem + cat $INT_CA_DIR/ca-chain.pem >> $SSL_BUNDLE_FILE + + if is_fedora; then + sudo cp $INT_CA_DIR/ca-chain.pem /usr/share/pki/ca-trust-source/anchors/devstack-chain.pem + sudo update-ca-trust + elif is_ubuntu; then + sudo cp $INT_CA_DIR/ca-chain.pem /usr/local/share/ca-certificates/devstack-int.crt + sudo cp $ROOT_CA_DIR/cacert.pem /usr/local/share/ca-certificates/devstack-root.crt + sudo update-ca-certificates + fi +} + +# Clean up the CA files +# cleanup_CA +function cleanup_CA { + if is_fedora; then + sudo rm -f /usr/share/pki/ca-trust-source/anchors/devstack-chain.pem + sudo update-ca-trust + elif is_ubuntu; then + sudo rm -f /usr/local/share/ca-certificates/devstack-int.crt + sudo rm -f /usr/local/share/ca-certificates/devstack-root.crt + sudo update-ca-certificates + fi } # Create an initial server cert @@ -331,6 +351,9 @@ function make_root_CA { function is_ssl_enabled_service { local services=$@ local service="" + if [ "$USE_SSL" == "False" ]; then + return 1 + fi for service in ${services}; do [[ ,${SSL_ENABLED_SERVICES}, =~ ,${service}, ]] && return 0 done @@ -345,8 +368,12 @@ function is_ssl_enabled_service { # 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. +# KEYSTONE_SSL_CA. +# +# If it does not find these certificates then the devstack-issued server +# certificate, key and CA certificate will be associated with the service. +# +# If only some of the variables are provided then the function will quit. function ensure_certificates { local service=$1 @@ -358,7 +385,15 @@ function ensure_certificates { local key=${!key_var} local ca=${!ca_var} - if [[ -z "$cert" || -z "$key" || -z "$ca" ]]; then + if [[ -z "$cert" && -z "$key" && -z "$ca" ]]; then + local cert="$INT_CA_DIR/$DEVSTACK_CERT_NAME.crt" + local key="$INT_CA_DIR/private/$DEVSTACK_CERT_NAME.key" + local ca="$INT_CA_DIR/ca-chain.pem" + eval ${service}_SSL_CERT=\$cert + eval ${service}_SSL_KEY=\$key + eval ${service}_SSL_CA=\$ca + return # the CA certificate is already in the bundle + elif [[ -z "$cert" || -z "$key" || -z "$ca" ]]; then die $LINENO "Missing either the ${cert_var} ${key_var} or ${ca_var}" \ "variable to enable SSL for ${service}" fi @@ -366,6 +401,21 @@ function ensure_certificates { cat $ca >> $SSL_BUNDLE_FILE } +# Enable the mod_ssl plugin in Apache +function enable_mod_ssl { + echo "Enabling mod_ssl" + + if is_ubuntu; then + sudo a2enmod ssl + elif is_fedora; then + # Fedora enables mod_ssl by default + : + fi + if ! sudo `which httpd || which apache2ctl` -M | grep -w -q ssl_module; then + die $LINENO "mod_ssl is not enabled in apache2/httpd, please check for it manually and run stack.sh again" + fi +} + # Proxy Functions # =============== diff --git a/stack.sh b/stack.sh index c20e61031d..12f18e20ec 100755 --- a/stack.sh +++ b/stack.sh @@ -340,6 +340,15 @@ source $TOP_DIR/lib/rpc_backend # and the specified rpc backend is available on your platform. check_rpc_backend +# Use native SSL for servers in SSL_ENABLED_SERVICES +USE_SSL=$(trueorfalse False $USE_SSL) + +# Service to enable with SSL if USE_SSL is True +SSL_ENABLED_SERVICES="key,nova,cinder,glance,s-proxy,neutron" + +if is_service_enabled tls-proxy && [ "$USE_SSL" == "True" ]; then + die $LINENO "tls-proxy and SSL are mutually exclusive" +fi # Configure Projects # ================== @@ -822,7 +831,7 @@ if is_service_enabled heat; then configure_heat fi -if is_service_enabled tls-proxy; then +if is_service_enabled tls-proxy || [ "$USE_SSL" == "True" ]; then configure_CA init_CA init_cert