Chapter 6. The configure-federation file

Commands:
#!/bin/sh prog_name=`basename USD0` action= dry_run=0 verbose=0 base_dir=USD(pwd) stage_dir="USD{base_dir}/fed_deployment" mellon_root="/v3" mellon_endpoint="mellon" mellon_app_name="v3" overcloud_deploy_script="overcloud_deploy.sh" overcloudrc_file="./overcloudrc" function cmd_template { local status=0 local cmd="USD1" if [ USDverbose -ne 0 -o USDdry_run -ne 0 ]; then echo USDcmd fi if [ USDdry_run -ne 0 ]; then return USDstatus fi USDcmd status=USD? if [ USDstatus -ne 0 ]; then (>&2 echo -e "ERROR cmd \"USDcmd\" failed\nstatus = USDstatus") fi return USDstatus } function cmds_template { local return_status=0 declare -a cmds=( "date" "ls xxx" "head USD0" ) if [ USDdry_run -ne 0 ]; then for cmd in "USD{cmds[@]}"; do echo USDcmd done else for cmd in "USD{cmds[@]}"; do if [ USDverbose -ne 0 ]; then echo USDcmd fi USDcmd status=USD? if [ USDstatus -ne 0 ]; then (>&2 echo -e "ERROR cmd \"USDcmd\" failed\nstatus = USDstatus") return_status=USDstatus fi done fi return USDreturn_status } function show_variables { echo "base_dir: USDbase_dir" echo "stage_dir: USDstage_dir" echo "config_tar_filename: USDconfig_tar_filename" echo "config_tar_pathname: USDconfig_tar_pathname" echo "overcloud_deploy_script: USDovercloud_deploy_script" echo "overcloudrc_file: USDovercloudrc_file" echo "puppet_override_apache_pathname: USDpuppet_override_apache_pathname" echo "puppet_override_keystone_pathname: USDpuppet_override_keystone_pathname" echo echo "FED_RHSSO_URL: USDFED_RHSSO_URL" echo "FED_RHSSO_ADMIN_PASSWORD: USDFED_RHSSO_ADMIN_PASSWORD" echo "FED_RHSSO_REALM: USDFED_RHSSO_REALM" echo echo "FED_KEYSTONE_HOST: USDFED_KEYSTONE_HOST" echo "FED_KEYSTONE_HTTPS_PORT: USDFED_KEYSTONE_HTTPS_PORT" echo "mellon_http_url: USDmellon_http_url" echo "mellon_root: USDmellon_root" echo "mellon_endpoint: USDmellon_endpoint" echo "mellon_app_name: USDmellon_app_name" echo "mellon_endpoint_path: USDmellon_endpoint_path" echo "mellon_entity_id: USDmellon_entity_id" echo echo "FED_OPENSTACK_IDP_NAME: USDFED_OPENSTACK_IDP_NAME" echo "openstack_mapping_pathname: USDopenstack_mapping_pathname" echo "FED_OPENSTACK_MAPPING_NAME: USDFED_OPENSTACK_MAPPING_NAME" echo echo "idp_metadata_filename: USDidp_metadata_filename" echo "mellon_httpd_config_filename: USDmellon_httpd_config_filename" } function initialize { local return_status=0 declare -a cmds=( "mkdir -p USDstage_dir" ) if [ USDdry_run -ne 0 ]; then for cmd in "USD{cmds[@]}"; do echo USDcmd done else for cmd in "USD{cmds[@]}"; do if [ USDverbose -ne 0 ]; then echo USDcmd fi USDcmd status=USD? if [ USDstatus -ne 0 ]; then (>&2 echo -e "ERROR cmd \"USDcmd\" failed\nstatus = USDstatus") return_status=USDstatus fi done fi return USDreturn_status } function copy_helper_to_controller { local status=0 local controller=USD{1:-"controller-0"} local cmd="scp configure-federation fed_variables heat-admin@USD{controller}:/home/heat-admin" if [ USDverbose -ne 0 -o USDdry_run -ne 0 ]; then echo USDcmd fi if [ USDdry_run -ne 0 ]; then return USDstatus fi USDcmd status=USD? if [ USDstatus -ne 0 ]; then (>&2 echo -e "ERROR cmd \"USDcmd\" failed\nstatus = USDstatus") fi return USDstatus } function install_mod_auth_mellon { local status=0 local cmd="sudo dnf -y install mod_auth_mellon" if [ USDverbose -ne 0 -o USDdry_run -ne 0 ]; then echo USDcmd fi if [ USDdry_run -ne 0 ]; then return USDstatus fi USDcmd status=USD? if [ USDstatus -ne 0 ]; then (>&2 echo -e "ERROR cmd \"USDcmd\" failed\nstatus = USDstatus") fi return USDstatus } function create_ipa_service_account { # Note, after setting up the service account it can be tested # by performing a user search like this: # ldapsearch -H USDldap_url -x -D "USDservice_dn" -w "USDFED_IPA_RHSSO_SERVICE_PASSWD" -b "cn=users,cn=accounts,USDFED_IPA_BASE_DN" local status=0 local ldap_url="ldaps://USDFED_IPA_HOST" local dir_mgr_dn="cn=Directory Manager" local service_name="rhsso" local service_dn="uid=USDservice_name,cn=sysaccounts,cn=etc,USDFED_IPA_BASE_DN" local cmd="ldapmodify -H \"USDldap_url\" -x -D \"USDdir_mgr_dn\" -w \"USDFED_IPA_ADMIN_PASSWD\"" read -r -d '' contents <<EOF dn: USDservice_dn changetype: add objectclass: account objectclass: simplesecurityobject uid: USDservice_name userPassword: USDFED_IPA_RHSSO_SERVICE_PASSWD passwordExpirationTime: 20380119031407Z nsIdleTimeout: 0 EOF if [ USDverbose -ne 0 -o USDdry_run -ne 0 ]; then echo USDcmd echo -e "USDcontents" fi if [ USDdry_run -ne 0 ]; then return USDstatus fi sh <<< "USDcmd <<< \"USDcontents\"" status=USD? if [ USDstatus -ne 0 ]; then (>&2 echo -e "ERROR cmd \"USDcmd\" failed\nstatus = USDstatus") fi return USDstatus } function client_install { local status=0 local cmd_client_install="sudo dnf -y install keycloak-httpd-client-install" local cmd="sudo keycloak-httpd-client-install --client-originate-method registration --mellon-https-port USDFED_KEYSTONE_HTTPS_PORT --mellon-hostname USDFED_KEYSTONE_HOST --mellon-root USDmellon_root --keycloak-server-url USDFED_RHSSO_URL --keycloak-admin-password USDFED_RHSSO_ADMIN_PASSWORD --app-name USDmellon_app_name --keycloak-realm USDFED_RHSSO_REALM -l "/v3/auth/OS-FEDERATION/websso/mapped" -l "/v3/auth/OS-FEDERATION/identity_providers/rhsso/protocols/mapped/websso" -l "/v3/OS-FEDERATION/identity_providers/rhsso/protocols/mapped/auth" " if [ USDverbose -ne 0 -o USDdry_run -ne 0 ]; then echo USDcmd_client_install echo USDcmd fi if [ USDdry_run -ne 0 ]; then return USDstatus fi USDcmd_client_install status=USD? if [ USDstatus -ne 0 ]; then (>&2 echo -e "ERROR cmd \"USDcmd_client_install\" failed\nstatus = USDstatus") else USDcmd status=USD? if [ USDstatus -ne 0 ]; then (>&2 echo -e "ERROR cmd \"USDcmd\" failed\nstatus = USDstatus") fi fi return USDstatus } function create_sp_archive { # Note, we put the exclude patterns in a file because it is # insanely difficult to put --exclude patttern in the USDcmd shell # variable and get the final quoting correct. local status=0 local cmd="tar -cvzf USDconfig_tar_pathname --exclude-from USDstage_dir/tar_excludes /var/lib/config-data/puppet-generated/keystone/etc/httpd/federation /var/lib/config-data/puppet-generated/keystone/etc/httpd/conf.d/USDmellon_httpd_config_filename" if [ USDverbose -ne 0 -o USDdry_run -ne 0 ]; then echo USDcmd fi if [ USDdry_run -ne 0 ]; then return USDstatus fi cat <<'EOF' > USDstage_dir/tar_excludes *.orig *~ EOF USDcmd status=USD? if [ USDstatus -ne 0 ]; then (>&2 echo -e "ERROR cmd \"USDcmd\" failed\nstatus = USDstatus") fi return USDstatus } function fetch_sp_archive { local return_status=0 declare -a cmds=( "scp heat-admin@controller-0:/home/heat-admin/fed_deployment/USDconfig_tar_filename USDstage_dir" "tar -C USDstage_dir -xvf USDconfig_tar_pathname" ) if [ USDdry_run -ne 0 ]; then for cmd in "USD{cmds[@]}"; do echo USDcmd done else for cmd in "USD{cmds[@]}"; do if [ USDverbose -ne 0 ]; then echo USDcmd fi USDcmd status=USD? if [ USDstatus -ne 0 ]; then (>&2 echo -e "ERROR cmd \"USDcmd\" failed\nstatus = USDstatus") return_status=USDstatus fi done fi return USDreturn_status } function deploy_mellon_configuration { local status=0 local cmd="upload-swift-artifacts -f USDconfig_tar_pathname" if [ USDverbose -ne 0 -o USDdry_run -ne 0 ]; then echo USDcmd fi if [ USDdry_run -ne 0 ]; then return USDstatus fi USDcmd status=USD? if [ USDstatus -ne 0 ]; then (>&2 echo -e "ERROR cmd \"USDcmd\" failed\nstatus = USDstatus") fi return USDstatus } function idp_entity_id { local metadata_file=USD{1:-USDidp_metadata_filename} # Extract the entitID from the metadata file, should really be parsed # with an XML xpath but a simple string match is probably OK entity_id=`sed -rne 's/^.*entityID="([^"]*)".*USD/\1/p' USD{metadata_file}` status=USD? if [ USDstatus -ne 0 -o "USDentity_id"x = "x" ]; then (>&2 echo -e "ERROR search for entityID in USD{metadata_file} failed\nstatus = USDstatus") return 1 fi echo USDentity_id return 0 } function append_deploy_script { local status=0 local deploy_script=USD1 local extra_line=USD2 local count count=USD(grep -c -e "USDextra_line" USDdeploy_script) if [ USDcount -eq 1 ]; then echo -e "SKIP appending:\nUSDextra_line" echo "already present in USDdeploy_script" return USDstatus elif [ USDcount -gt 1 ]; then status=1 (>&2 echo -e "ERROR multiple copies of line in USD{deploy_script}\nstatus = USDstatus\nline=USDextra_line") return USDstatus fi if [ USDverbose -ne 0 -o USDdry_run -ne 0 ]; then echo "appending USDdeploy_script with:" echo -e USDextra_line fi if [ USDdry_run -ne 0 ]; then return USDstatus fi # insert line after last -e line already in script # # This is not easy with sed, we'll use tac and awk instead. Here # is how this works: The logic is easier if you insert before the # first line rather than trying to find the last line and insert # after it. We use tac to reverse the lines in the file. Then the # awk script looks for the candidate line. If found it outputs the # line we're adding, sets a flag (p) to indicate it's already been # printed. The "; 1" pattern always output the input line. Then we # run the output through tac again to set things back in the # original order. local tmp_file=USD(mktemp) tac USDdeploy_script | awk "!p && /^-e/{print \"USD{extra_line} \\\\\"; p=1}; 1" | tac > USDtmp_file count=USD(grep -c -e "USD{extra_line}" USDtmp_file) if [ USDcount -ne 1 ]; then status=1 fi if [ USDstatus -ne 0 ]; then rm USDtmp_file (>&2 echo -e "ERROR failed to append USD{deploy_script}\nstatus = USDstatus\nline=USDextra_line") else mv USDtmp_file USDdeploy_script fi return USDstatus } function puppet_override_apache { local status=0 local pathname=USD{1:-USDpuppet_override_apache_pathname} local deploy_cmd="-e USDpathname" read -r -d '' contents <<'EOF' parameter_defaults: ControllerExtraConfig: apache::purge_configs: false EOF if [ USDverbose -ne 0 -o USDdry_run -ne 0 ]; then echo "writing pathname = USDpathname with contents" echo -e "USDcontents" fi if [ USDdry_run -ne 0 ]; then return USDstatus fi echo -e "USDcontents" > USDpathname status=USD? if [ USDstatus -ne 0 ]; then (>&2 echo -e "ERROR failed to write USD{pathname}\nstatus = USDstatus") fi append_deploy_script USDovercloud_deploy_script "USDdeploy_cmd" status=USD? return USDstatus } function puppet_override_keystone { local status=0 local pathname=USD{1:-USDpuppet_override_keystone_pathname} local deploy_cmd="-e USDpathname" read -r -d '' contents <<EOF parameter_defaults: controllerExtraConfig: keystone::using_domain_config: true keystone::config::keystone_config: identity/domain_configurations_from_database: value: true auth/methods: value: external,password,token,oauth1,mapped federation/trusted_dashboard: value: https://USDFED_KEYSTONE_HOST/dashboard/auth/websso/ federation/sso_callback_template: value: /etc/keystone/sso_callback_template.html federation/remote_id_attribute: value: MELLON_IDP EOF if [ USDverbose -ne 0 -o USDdry_run -ne 0 ]; then echo "writing pathname = USDpathname with contents" echo -e "USDcontents" fi if [ USDdry_run -ne 0 ]; then return USDstatus fi echo -e "USDcontents" > USDpathname status=USD? if [ USDstatus -ne 0 ]; then (>&2 echo -e "ERROR failed to write USD{pathname}\nstatus = USDstatus") fi append_deploy_script USDovercloud_deploy_script "USDdeploy_cmd" status=USD? return USDstatus } function create_federated_resources { # follow example in Keystone federation documentation # http://docs.openstack.org/developer/keystone/federation/federated_identity.html#create-keystone-groups-and-assign-roles local return_status=0 declare -a cmds=( "openstack domain create federated_domain" "openstack project create --domain federated_domain federated_project" "openstack group create federated_users --domain federated_domain" "openstack role add --group federated_users --group-domain federated_domain --domain federated_domain _member_" "openstack role add --group federated_users --project federated_project Member" ) if [ USDdry_run -ne 0 ]; then for cmd in "USD{cmds[@]}"; do echo USDcmd done else for cmd in "USD{cmds[@]}"; do if [ USDverbose -ne 0 ]; then echo USDcmd fi USDcmd status=USD? if [ USDstatus -ne 0 ]; then (>&2 echo -e "ERROR cmd \"USDcmd\" failed\nstatus = USDstatus") return_status=USDstatus fi done fi return USDreturn_status } function create_mapping { # Matches documentation # http://docs.openstack.org/developer/keystone/federation/federated_identity.html#create-keystone-groups-and-assign-roles local status=0 local pathname=USD{1:-USDopenstack_mapping_pathname} read -r -d '' contents <<'EOF' [ { "local": [ { "user": { "name": "{0}" }, "group": { "domain": { "name": "federated_domain" }, "name": "federated_users" } } ], "remote": [ { "type": "MELLON_NAME_ID" }, { "type": "MELLON_groups", "any_one_of": ["openstack-users"] } ] } ] EOF if [ USDverbose -ne 0 -o USDdry_run -ne 0 ]; then echo "writing pathname = USDpathname with contents" echo -e "USDcontents" fi if [ USDdry_run -ne 0 ]; then return USDstatus fi echo -e "USDcontents" > USDpathname status=USD? if [ USDstatus -ne 0 ]; then (>&2 echo -e "ERROR failed to write USD{pathname}\nstatus = USDstatus") fi return USDstatus } function create_v3_rcfile { local status=0 local input_file=USD{1:-USDovercloudrc_file} local output_file="USD{input_file}.v3" source USDinput_file #clear the old environment NEW_OS_AUTH_URL=`echo USDOS_AUTH_URL | sed 's!v2.0!v3!'` read -r -d '' contents <<EOF for key in \USD( set | sed 's!=.*!!g' | grep -E '^OS_') ; do unset USDkey ; done export OS_AUTH_URL=USDNEW_OS_AUTH_URL export OS_USERNAME=USDOS_USERNAME export OS_PASSWORD=USDOS_PASSWORD export OS_USER_DOMAIN_NAME=Default export OS_PROJECT_DOMAIN_NAME=Default export OS_PROJECT_NAME=USDOS_TENANT_NAME export OS_IDENTITY_API_VERSION=3 EOF if [ USDverbose -ne 0 -o USDdry_run -ne 0 ]; then echo "writing output_file = USDoutput_file with contents:" echo -e "USDcontents" fi if [ USDdry_run -ne 0 ]; then return USDstatus fi echo -e "USDcontents" > USDoutput_file status=USD? if [ USDstatus -ne 0 ]; then (>&2 echo -e "ERROR failed to write USD{output_file}\nstatus = USDstatus") fi return USDstatus } function openstack_create_idp { local status=0 local metadata_file="USDstage_dir/var/lib/config-data/puppet-generated/keystone/etc/httpd/federation/USDidp_metadata_filename" local entity_id entity_id=USD(idp_entity_id USDmetadata_file) status=USD? if [ USDstatus -ne 0 ]; then return USDstatus fi local cmd="openstack identity provider create --remote-id USDentity_id USDFED_OPENSTACK_IDP_NAME" if [ USDverbose -ne 0 -o USDdry_run -ne 0 ]; then echo USDcmd fi if [ USDdry_run -ne 0 ]; then return USDstatus fi USDcmd status=USD? if [ USDstatus -ne 0 ]; then (>&2 echo -e "ERROR cmd \"USDcmd\" failed\nstatus = USDstatus") fi return USDstatus } function openstack_create_mapping { local status=0 local mapping_file=USD{1:-USDopenstack_mapping_pathname} local mapping_name=USD{2:-USDFED_OPENSTACK_MAPPING_NAME} cmd="openstack mapping create --rules USDmapping_file USDmapping_name" if [ USDverbose -ne 0 -o USDdry_run -ne 0 ]; then echo USDcmd fi if [ USDdry_run -ne 0 ]; then return USDstatus fi USDcmd status=USD? if [ USDstatus -ne 0 ]; then (>&2 echo -e "ERROR cmd \"USDcmd\" failed\nstatus = USDstatus") fi return USDstatus } function openstack_create_protocol { local status=0 local idp_name=USD{1:-USDFED_OPENSTACK_IDP_NAME} local mapping_name=USD{2:-USDFED_OPENSTACK_MAPPING_NAME} cmd="openstack federation protocol create --identity-provider USDidp_name --mapping USDmapping_name mapped" if [ USDverbose -ne 0 -o USDdry_run -ne 0 ]; then echo USDcmd fi if [ USDdry_run -ne 0 ]; then return USDstatus fi USDcmd status=USD? if [ USDstatus -ne 0 ]; then (>&2 echo -e "ERROR cmd \"USDcmd\" failed\nstatus = USDstatus") fi return USDstatus } function usage { cat <<EOF USDprog_name action -h --help print usage -n --dry-run dry run, just print computed command -v --verbose be chatty action may be one of: show-variables initialize copy-helper-to-controller install-mod-auth-mellon create-ipa-service-account client-install create-sp-archive fetch-sp-archive deploy-mellon-configuration puppet-override-apache puppet-override-keystone create-federated-resources create-mapping create-v3-rcfile openstack-create-idp openstack-create-mapping openstack-create-protocol EOF } #----------------------------------------------------------------------------- options may be followed by one colon to indicate they have a required argument if ! options=USD(getopt -o hnv -l help,dry-run,verbose -- "USD@") then # something went wrong, getopt will put out an error message for us exit 1 fi eval set -- "USDoptions" while [ USD# -gt 0 ] do case USD1 in -h|--help) usage; exit 1 ;; -n|--dry-run) dry_run=1 ;; -v|--verbose) verbose=1 ;; # for options with required arguments, an additional shift is required (--) shift; break;; (-*) echo "USD0: error - unrecognized option USD1" 1>&2; exit 1;; (*) break;; esac shift done #----------------------------------------------------------------------------- source ./fed_variables Strip leading and trailing space and slash from these variables mellon_root=`echo USD{mellon_root} | perl -pe 's!^[ /]*(.*?)[ /]*USD!\1!'` mellon_endpoint=`echo USD{mellon_endpoint} | perl -pe 's!^[ /]*(.*?)[ /]*USD!\1!'` mellon_root="/USD{mellon_root}" mellon_endpoint_path="USD{mellon_root}/USD{mellon_endpoint}" mellon_http_url="https://USD{FED_KEYSTONE_HOST}:USD{FED_KEYSTONE_HTTPS_PORT}" mellon_entity_id="USD{mellon_http_url}USD{mellon_endpoint_path}/metadata" openstack_mapping_pathname="USD{stage_dir}/mapping_USD{FED_OPENSTACK_IDP_NAME}_saml2.json" idp_metadata_filename="USD{mellon_app_name}_keycloak_USD{FED_RHSSO_REALM}_idp_metadata.xml" mellon_httpd_config_filename="USD{mellon_app_name}_mellon_keycloak_USD{FED_RHSSO_REALM}.conf" config_tar_filename="rhsso_config.tar.gz" config_tar_pathname="USD{stage_dir}/USD{config_tar_filename}" puppet_override_apache_pathname="USD{stage_dir}/puppet_override_apache.yaml" puppet_override_keystone_pathname="USD{stage_dir}/puppet_override_keystone.yaml" #----------------------------------------------------------------------------- if [ USD# -lt 1 ]; then echo "ERROR: no action specified" exit 1 fi action="USD1"; shift if [ USDdry_run -ne 0 ]; then echo "Dry Run Enabled!" fi case USDaction in show-var*) show_variables ;; initialize) initialize ;; copy-helper-to-controller) copy_helper_to_controller "USD1" ;; install-mod-auth-mellon) install_mod_auth_mellon ;; create-ipa-service-account) create_ipa_service_account ;; client-install) client_install ;; create-sp-archive) create_sp_archive ;; fetch-sp-archive) fetch_sp_archive ;; deploy-mellon-configuration) deploy_mellon_configuration ;; create-v3-rcfile) create_v3_rcfile "USD1" ;; puppet-override-apache) puppet_override_apache "USD1" ;; puppet-override-keystone) puppet_override_keystone "USD1" ;; create-federated-resources) create_federated_resources ;; create-mapping) create_mapping "USD1" ;; openstack-create-idp) openstack_create_idp "USD1" ;; openstack-create-mapping) openstack_create_mapping "USD1" "USD2" ;; openstack-create-protocol) openstack_create_protocol "USD1" "USD2" ;; *) echo "unknown action: USDaction" usage exit 1 ;; esac