#!/usr/bin/env bash # Install and start **Barbican** service # To enable a minimal set of Barbican features, add the following to localrc: # enable_service barbican-svc barbican-retry barbican-keystone-listener # # Dependencies: # - functions # - OS_AUTH_URL for auth in api # - DEST set to the destination directory # - SERVICE_PASSWORD, SERVICE_PROJECT_NAME for auth in api # - STACK_USER service user # stack.sh # --------- # install_barbican # configure_barbican # init_barbican # start_barbican # stop_barbican # cleanup_barbican # Save trace setting XTRACE=$(set +o | grep xtrace) set +o xtrace # PyKMIP configuration PYKMIP_SERVER_KEY=${PYKMIP_SERVER_KEY:-$INT_CA_DIR/private/pykmip-server.key} PYKMIP_SERVER_CERT=${PYKMIP_SERVER_CERT:-$INT_CA_DIR/pykmip-server.crt} PYKMIP_CLIENT_KEY=${PYKMIP_CLIENT_KEY:-$INT_CA_DIR/private/pykmip-client.key} PYKMIP_CLIENT_CERT=${PYKMIP_CLIENT_CERT:-$INT_CA_DIR/pykmip-client.crt} PYKMIP_CA_PATH=${PYKMIP_CA_PATH:-$INT_CA_DIR/ca-chain.pem} # Functions # --------- # TODO(john-wood-w) These 'magic' functions are called by devstack to enable # a given service (so the name between 'is_' and '_enabled'). Currently the # Zuul infra gate configuration (at https://github.com/openstack-infra/project-config/blob/master/jenkins/jobs/barbican.yaml) # only enables the 'barbican' service. So the two functions below, for the two # services we wish to run, have to key off of that lone 'barbican' selection. # Once the Zuul config is updated to add these two services properly, then # these functions should be replaced by the single method below. # !!!! Special thanks to rm_work for figuring this out !!!! function is_barbican-retry_enabled { [[ ,${ENABLED_SERVICES} =~ ,"barbican" ]] && return 0 } function is_barbican-svc_enabled { [[ ,${ENABLED_SERVICES} =~ ,"barbican" ]] && return 0 } function is_barbican-keystone-listener_enabled { [[ ,${ENABLED_SERVICES} =~ ,"barbican" ]] && return 0 } # TODO(john-wood-w) Replace the above two functions with the one below once # Zuul is update per above. ## Test if any Barbican services are enabled ## is_barbican_enabled #function is_barbican_enabled { # [[ ,${ENABLED_SERVICES} =~ ,"barbican-" ]] && return 0 # return 1 #} # cleanup_barbican - Remove residual data files, anything left over from previous # runs that a clean run would need to clean up function cleanup_barbican { if is_service_enabled barbican-vault; then # Kill the vault process, screen session and remove the generated files # during installation. local session_name="barbican_vault" local vault_token_file="${BARBICAN_DIR}/vault_root_token_id" existing_ses=$(screen -ls | grep ${session_name} | awk '{print $1}') if [[ -n "${existing_ses}" ]]; then screen -S ${existing_ses} -X quit fi sudo pkill -f -9 "vault server" sudo rm -f ${vault_token_file} vault.log fi } # configure_barbicanclient - Set config files, create data dirs, etc function configure_barbicanclient { setup_dev_lib "python-barbicanclient" } # configure_dogtag_plugin - Change config to use dogtag plugin function configure_dogtag_plugin { sudo openssl pkcs12 -in /root/.dogtag/pki-tomcat/ca_admin_cert.p12 -passin pass:PASSWORD -out $BARBICAN_CONF_DIR/kra_admin_cert.pem -nodes sudo chown $USER $BARBICAN_CONF_DIR/kra_admin_cert.pem iniset $BARBICAN_CONF dogtag_plugin dogtag_port 8373 iniset $BARBICAN_CONF dogtag_plugin pem_path "$BARBICAN_CONF_DIR/kra_admin_cert.pem" iniset $BARBICAN_CONF dogtag_plugin dogtag_host localhost iniset $BARBICAN_CONF dogtag_plugin nss_db_path '/etc/barbican/alias' iniset $BARBICAN_CONF dogtag_plugin nss_db_path_ca '/etc/barbican/alias-ca' iniset $BARBICAN_CONF dogtag_plugin nss_password 'password123' iniset $BARBICAN_CONF dogtag_plugin simple_cmc_profile 'caOtherCert' iniset $BARBICAN_CONF dogtag_plugin ca_expiration_time 1 iniset $BARBICAN_CONF dogtag_plugin plugin_working_dir '/etc/barbican/dogtag' iniset $BARBICAN_CONF secretstore enabled_secretstore_plugins dogtag_crypto iniset $BARBICAN_CONF certificate enabled_certificate_plugins dogtag } # configure_barbican - Set config files, create data dirs, etc function configure_barbican { setup_develop $BARBICAN_DIR [ ! -d $BARBICAN_CONF_DIR ] && sudo mkdir -m 755 -p $BARBICAN_CONF_DIR sudo chown $USER $BARBICAN_CONF_DIR [ ! -d $BARBICAN_API_LOG_DIR ] && sudo mkdir -m 755 -p $BARBICAN_API_LOG_DIR sudo chown $USER $BARBICAN_API_LOG_DIR [ ! -d $BARBICAN_CONF_DIR ] && sudo mkdir -m 755 -p $BARBICAN_CONF_DIR sudo chown $USER $BARBICAN_CONF_DIR # Copy the barbican config files to the config dir cp $BARBICAN_DIR/etc/barbican/barbican-api-paste.ini $BARBICAN_CONF_DIR cp -R $BARBICAN_DIR/etc/barbican/vassals $BARBICAN_CONF_DIR # Copy functional test config cp $BARBICAN_DIR/etc/barbican/barbican-functional.conf $BARBICAN_CONF_DIR # Enable DEBUG iniset $BARBICAN_CONF DEFAULT debug $ENABLE_DEBUG_LOG_LEVEL # Set the host_href iniset $BARBICAN_CONF DEFAULT host_href "$BARBICAN_HOST_HREF" # Enable logging to stderr to have log also in the screen window iniset $BARBICAN_CONF DEFAULT use_stderr True # Format logging if [ "$LOG_COLOR" == "True" ] && [ "$SYSLOG" == "False" ]; then setup_colorized_logging $BARBICAN_CONF DEFAULT project user fi # Set the database connection url BARBICAN_DATABASE_USER=$(get_data_from_secret barbican-mysql openstack USER) BARBICAN_DATABASE_PASSWORD=$(get_data_from_secret barbican-mysql openstack PASSWORD) BARBICAN_DATABASE_NAME=$(get_data_from_secret barbican-mysql openstack DATABASE) iniset $BARBICAN_CONF DEFAULT sql_connection "mysql+pymysql://$BARBICAN_DATABASE_USER:$BARBICAN_DATABASE_PASSWORD@barbican-mysql-master/$BARBICAN_DATABASE_NAME?charset=utf8" # Disable auto-migration when deploying Barbican iniset $BARBICAN_CONF DEFAULT db_auto_create False # Increase default request buffer size, keystone auth PKI tokens can be very long iniset $BARBICAN_CONF_DIR/vassals/barbican-api.ini uwsgi buffer-size 65535 # Rabbit settings if is_service_enabled rabbit; then iniset $BARBICAN_CONF DEFAULT transport_url rabbit://$RABBIT_USERID:$RABBIT_PASSWORD@$RABBIT_HOST:5672 else echo_summary "Barbican requires that the RabbitMQ service is enabled" fi write_uwsgi_config "$BARBICAN_UWSGI_CONF" "$BARBICAN_WSGI" "/key-manager" ## Set up keystone # Turn on the middleware iniset $BARBICAN_PASTE_CONF 'pipeline:barbican_api' pipeline 'barbican-api-keystone' # Set the keystone parameters configure_auth_token_middleware $BARBICAN_CONF barbican $BARBICAN_AUTH_CACHE_DIR # NOTE(Alex): Operator stuff for memcached iniset $BARBICAN_CONF keystone_authtoken memcached_servers "mcrouter-memcached-barbican:11211" # Enable the keystone listener iniset $BARBICAN_CONF keystone_notifications enable True iniset $BARBICAN_CONF keystone_notifications control_exchange 'keystone' } # init_barbican - Initialize etc. function init_barbican { kubectl create secret generic barbican-config -n openstack \ --from-file=/etc/barbican/barbican.conf \ --from-file=/etc/barbican/barbican-api-paste.ini \ --from-file=/etc/barbican/barbican-functional.conf # Create cache dir sudo mkdir -p $BARBICAN_AUTH_CACHE_DIR sudo chown $STACK_USER $BARBICAN_AUTH_CACHE_DIR rm -f $BARBICAN_AUTH_CACHE_DIR/* recreate_database barbican utf8 } # install_barbican - Collect source and prepare function install_barbican { echo noop } # install_barbicanclient - Collect source and prepare function install_barbicanclient { if use_library_from_git "python-barbicanclient"; then git_clone_by_name "python-barbicanclient" setup_dev_lib "python-barbicanclient" fi } # start_barbican - Start running processes, including screen function start_barbican { # Start the Barbican service up. kubernetes_rollout_restart daemonset/barbican kubernetes_rollout_status daemonset/barbican proxy_pass_to_kubernetes /key-manager barbican barbican-wsgi-api # Pause while the barbican-svc populates the database, otherwise the retry # service below might try to do this at the same time, leading to race # conditions. sleep 10 # Start the retry scheduler server up. run_process barbican-retry "$BARBICAN_BIN_DIR/barbican-retry --config-file=$BARBICAN_CONF_DIR/barbican.conf" # Start the barbican-keystone-listener run_process barbican-keystone-listener "$BARBICAN_BIN_DIR/barbican-keystone-listener --config-file=$BARBICAN_CONF_DIR/barbican.conf" } # stop_barbican - Stop running processes function stop_barbican { # This will eventually be refactored to work like # Solum and Manila (script to kick off a wsgiref server) # For now, this will stop uWSGI rather than have it hang killall -9 uwsgi # This cleans up the PID file, but uses pkill so Barbican # uWSGI emperor process doesn't actually stop stop_process barbican-svc stop_process barbican-retry stop_process barbican-keystone-listener } function get_id { echo `"$@" | awk '/ id / { print $4 }'` } function create_barbican_accounts { # # Setup Default Admin User # SERVICE_PROJECT=$(openstack project list | awk "/ $SERVICE_PROJECT_NAME / { print \$2 }") ADMIN_ROLE=$(openstack role list | awk "/ admin / { print \$2 }") BARBICAN_USER=$(openstack user create \ --password "$SERVICE_PASSWORD" \ --project $SERVICE_PROJECT \ --email "barbican@example.com" \ barbican \ | grep " id " | get_field 2) openstack role add --project $SERVICE_PROJECT \ --user $BARBICAN_USER \ $ADMIN_ROLE # # Setup Default service-admin User # SERVICE_ADMIN=$(get_id openstack user create \ --password "$SERVICE_PASSWORD" \ --email "service-admin@example.com" \ "service-admin") SERVICE_ADMIN_ROLE=$(get_id openstack role create \ "key-manager:service-admin") openstack role add \ --user "$SERVICE_ADMIN" \ --project "$SERVICE_PROJECT" \ "$SERVICE_ADMIN_ROLE" # # Setup RBAC User Projects and Roles # PASSWORD="barbican" PROJECT_A_ID=$(get_id openstack project create "project_a") PROJECT_B_ID=$(get_id openstack project create "project_b") ROLE_ADMIN_ID=$(get_id openstack role show admin) ROLE_CREATOR_ID=$(get_id openstack role create "creator") ROLE_OBSERVER_ID=$(get_id openstack role create "observer") ROLE_AUDIT_ID=$(get_id openstack role create "audit") # # Setup RBAC Admin of Project A # USER_ID=$(get_id openstack user create \ --password "$PASSWORD" \ --email "admin_a@example.net" \ "project_a_admin") openstack role add \ --user "$USER_ID" \ --project "$PROJECT_A_ID" \ "$ROLE_ADMIN_ID" # # Setup RBAC Creator of Project A # USER_ID=$(get_id openstack user create \ --password "$PASSWORD" \ --email "creator_a@example.net" \ "project_a_creator") openstack role add \ --user "$USER_ID" \ --project "$PROJECT_A_ID" \ "$ROLE_CREATOR_ID" # Adding second creator user in project_a USER_ID=$(openstack user create \ --password "$PASSWORD" \ --email "creator2_a@example.net" \ "project_a_creator_2" -f value -c id) openstack role add \ --user "$USER_ID" \ --project "$PROJECT_A_ID" \ "$ROLE_CREATOR_ID" # # Setup RBAC Observer of Project A # USER_ID=$(get_id openstack user create \ --password "$PASSWORD" \ --email "observer_a@example.net" \ "project_a_observer") openstack role add \ --user "$USER_ID" \ --project "$PROJECT_A_ID" \ "$ROLE_OBSERVER_ID" # # Setup RBAC Auditor of Project A # USER_ID=$(get_id openstack user create \ --password "$PASSWORD" \ --email "auditor_a@example.net" \ "project_a_auditor") openstack role add \ --user "$USER_ID" \ --project "$PROJECT_A_ID" \ "$ROLE_AUDIT_ID" # # Setup RBAC Admin of Project B # USER_ID=$(get_id openstack user create \ --password "$PASSWORD" \ --email "admin_b@example.net" \ "project_b_admin") openstack role add \ --user "$USER_ID" \ --project "$PROJECT_B_ID" \ "$ROLE_ADMIN_ID" # # Setup RBAC Creator of Project B # USER_ID=$(get_id openstack user create \ --password "$PASSWORD" \ --email "creator_b@example.net" \ "project_b_creator") openstack role add \ --user "$USER_ID" \ --project "$PROJECT_B_ID" \ "$ROLE_CREATOR_ID" # # Setup RBAC Observer of Project B # USER_ID=$(get_id openstack user create \ --password "$PASSWORD" \ --email "observer_b@example.net" \ "project_b_observer") openstack role add \ --user "$USER_ID" \ --project "$PROJECT_B_ID" \ "$ROLE_OBSERVER_ID" # # Setup RBAC auditor of Project B # USER_ID=$(get_id openstack user create \ --password "$PASSWORD" \ --email "auditor_b@example.net" \ "project_b_auditor") openstack role add \ --user "$USER_ID" \ --project "$PROJECT_B_ID" \ "$ROLE_AUDIT_ID" } # PyKMIP functions # ---------------- # install_pykmip - install the PyKMIP python module # create keys and certificate for server function install_pykmip { pip_install 'pykmip' if is_service_enabled pykmip-server; then [ ! -d ${PYKMIP_CONF_DIR} ] && sudo mkdir -p ${PYKMIP_CONF_DIR} sudo chown ${USER} ${PYKMIP_CONF_DIR} [ ! -d ${PYKMIP_LOG_DIR} ] && sudo mkdir -p ${PYKMIP_LOG_DIR} sudo chown ${USER} ${PYKMIP_LOG_DIR} init_CA if [ ! -e ${PYKMIP_SERVER_KEY} ]; then make_cert ${INT_CA_DIR} 'pykmip-server' 'pykmip-server' chmod 400 ${PYKMIP_SERVER_KEY} fi if [ ! -e ${PYKMIP_CLIENT_KEY} ]; then make_cert ${INT_CA_DIR} 'pykmip-client' 'pykmip-client' chmod 400 ${PYKMIP_CLIENT_KEY} fi if [ ! -e ${PYKMIP_CONF} ]; then cat > ${PYKMIP_CONF} < ds.inf rm ds.tmp sudo mv ds.inf /etc/389-ds/ds.inf sudo dscreate from-file /etc/389-ds/ds.inf } function install_dogtag_ca { sudo mkdir -p /etc/dogtag cat > .tmp.ca.cfg < .tmp.kra.cfg <&1 >vault.log\n' # get the root_token_id, use tempfile for counter touch $TOKEN_ID_FILE COUNTER=0 while [ ! -s $TOKEN_ID_FILE ] && [ "$COUNTER" -lt "20" ] do sleep 2 awk '/Root Token:/ {print $3}' vault.log > $TOKEN_ID_FILE COUNTER=$[COUNTER + 1] done if [ ! -s $TOKEN_ID_FILE ]; then echo "Wah! Need to throw an error code here!" fi export VAULT_ADDR="http://127.0.0.1:8200" # Enable kv version 1 vault secrets disable secret/ vault secrets enable -version=1 -path=secret -description "kv version 1" kv #debug code follows: vault status vault kv put secret/hello foo=world vault kv get secret/hello vault kv delete secret/hello } function configure_vault_plugin { root_token_id=`cat ${BARBICAN_DIR}/vault_root_token_id` iniset $BARBICAN_CONF secretstore enabled_secretstore_plugins vault_plugin iniset $BARBICAN_CONF vault_plugin root_token_id $root_token_id iniset $BARBICAN_CONF vault_plugin vault_url "http://127.0.0.1:8200" iniset $BARBICAN_CONF vault_plugin use_ssl "false" } # Restore xtrace $XTRACE