diff --git a/README.md b/README.md index 03a1b63..d2b4f53 100644 --- a/README.md +++ b/README.md @@ -359,7 +359,7 @@ https:///bbmri-localdatamanagement/fhir ``` The name of your server will generally be the full name of the VM that the Bridgehead runs on. You can alternatively supply an IP address. -The FHIR API uses basic auth. You can find the credentials in `/etc/bridgehead/.local.conf`. +The FHIR API uses basic auth. You can find the credentials in `/etc/bridgehead/.local.conf`. Exactly one set of credentials is supported, so `bridgehead setuser ` replaces the previous ones. Note that if you don't have a DNS certificate for the Bridgehead, you will need to allow an insecure connection. E.g. with curl, use the `-k` flag. diff --git a/bridgehead b/bridgehead index 09b46f5..499af66 100755 --- a/bridgehead +++ b/bridgehead @@ -169,13 +169,21 @@ case "$ACTION" in uninstall) exec ./lib/uninstall-bridgehead.sh $PROJECT ;; - adduser) + setuser) loadVars - log "INFO" "Adding encrypted credentials in /etc/bridgehead/$PROJECT.local.conf" - read -p "Please choose the component (LDM_AUTH|NNGM_AUTH|EXPORTER_USER) you want to add a user to : " COMPONENT - read -p "Please enter a username: " USER - read -s -p "Please enter a password (will not be echoed): "$'\n' PASSWORD - add_basic_auth_user $USER $PASSWORD $COMPONENT $PROJECT + log "INFO" "Setting encrypted credentials in /etc/bridgehead/$PROJECT.local.conf" + read -p "Please choose the component ($(echo $BASIC_AUTH_VARIABLES | tr ' ' '|')) you want to set the credentials for : " COMPONENT + case " $BASIC_AUTH_VARIABLES " in + *" $COMPONENT "*) + ;; + *) + log "ERROR" "\"$COMPONENT\" is not a basic auth component. Choose one of: $BASIC_AUTH_VARIABLES" + exit 1 + ;; + esac + read -p "Please enter a username: " USER + read -s -p "Please enter a password (will not be echoed): "$'\n' PASSWORD + set_basic_auth_user "$USER" "$PASSWORD" "$COMPONENT" "$PROJECT" ;; enroll) loadVars diff --git a/lib/functions.sh b/lib/functions.sh index 3a5cfe4..5729655 100644 --- a/lib/functions.sh +++ b/lib/functions.sh @@ -53,7 +53,7 @@ checkOwner(){ } printUsage() { - echo "Usage: bridgehead start|stop|logs|docker-logs|is-running|update|check|install|uninstall|adduser|enroll PROJECTNAME" + echo "Usage: bridgehead start|stop|logs|docker-logs|is-running|update|check|install|uninstall|setuser|enroll PROJECTNAME" echo "PROJECTNAME should be one of ccp|bbmri|cce|itcc|kr|dhki|nngm" } @@ -247,21 +247,55 @@ function do_enroll { do_enroll_inner $@ } -add_basic_auth_user() { - USER="${1}" - PASSWORD="${2}" - NAME="${3}" - PROJECT="${4}" - FILE="/etc/bridgehead/${PROJECT}.local.conf" - ENCRY_CREDENTIALS="$(docker run --rm docker.verbis.dkfz.de/cache/httpd:alpine htpasswd -nb $USER $PASSWORD | tr -d '\n' | tr -d '\r')" - if [ -f $FILE ] && grep -R -q "$NAME=" $FILE # if a specific basic auth user already exists: - then - sed -i "/$NAME/ s|='|='$ENCRY_CREDENTIALS,|" $FILE - else - echo -e "\n## Basic Authentication Credentials for:\n$NAME='$ENCRY_CREDENTIALS'" >> $FILE; - fi - log DEBUG "Saving clear text credentials in $FILE. If wanted, delete them manually." - sed -i "/^$NAME/ s|$|\n# User: $USER\n# Password: $PASSWORD|" $FILE +BASIC_AUTH_VARIABLES="LDM_AUTH NNGM_AUTH TRANSFAIR_AUTH EXPORTER_USER" + +# One entry of Traefik's basicauth.users list: "user:hash", with the username +# restricted to characters that cannot collide with either separator. +is_valid_basic_auth_entry() { + local entry="$1" + local user="${entry%%:*}" + local hash="${entry#*:}" + [ "$user" != "$entry" ] || return 1 + [ -n "$hash" ] || return 1 + [ "$hash" = "${hash#*:}" ] || return 1 + [[ "$user" =~ ^[A-Za-z0-9._-]+$ ]] +} + +# Stores one set of basic auth credentials in $NAME, replacing any existing ones. +set_basic_auth_user() { + local USER="${1}" + local PASSWORD="${2}" + local NAME="${3}" + local PROJECT="${4}" + local FILE="/etc/bridgehead/${PROJECT}.local.conf" + local ENCRY_CREDENTIALS + if [ -z "$USER" ] || [ -z "$PASSWORD" ]; then + log ERROR "Both a username and a password are required. $FILE is unchanged." + return 1 + fi + if ! ENCRY_CREDENTIALS="$(docker run --rm docker.verbis.dkfz.de/cache/httpd:alpine htpasswd -nb "$USER" "$PASSWORD")"; then + log ERROR "Unable to run htpasswd, so no credentials were generated. $FILE is unchanged." + return 1 + fi + ENCRY_CREDENTIALS="$(printf '%s' "$ENCRY_CREDENTIALS" | tr -d '\n' | tr -d '\r')" + if ! is_valid_basic_auth_entry "$ENCRY_CREDENTIALS"; then + log ERROR "htpasswd returned no usable credentials for \"$USER\". $FILE is unchanged." + return 1 + fi + if [ -f $FILE ] && grep -q "^$NAME=" $FILE # if this basic auth variable already exists: + then + sed -i "/^$NAME=/{:a;N;s/\n# User: [^\n]*//;s/\n# Password: [^\n]*//;ta}" $FILE + sed -i "0,/^$NAME=/!{/^$NAME=/d}" $FILE + sed -i "/^$NAME=/ s|=.*|='$ENCRY_CREDENTIALS'|" $FILE + else + echo -e "\n## Basic Authentication Credentials for:\n$NAME='$ENCRY_CREDENTIALS'" >> $FILE; + fi + log DEBUG "Saving clear text credentials in $FILE. If wanted, delete them manually." + sed -i "/^$NAME=/ s|$|\n# User: $USER\n# Password: $PASSWORD|" $FILE + if [ "$(grep -c "^$NAME=" $FILE)" -ne 1 ] || [ "$(sed -n "s|^$NAME='\(.*\)'$|\1|p" $FILE)" != "$ENCRY_CREDENTIALS" ]; then + log ERROR "$NAME in $FILE does not hold exactly one set of credentials. Please correct it manually." + return 1 + fi } OIDC_PUBLIC_REDIRECT_URLS=${OIDC_PUBLIC_REDIRECT_URLS:-""} diff --git a/lib/install-bridgehead.sh b/lib/install-bridgehead.sh index 2e2ec69..cbe6d5b 100755 --- a/lib/install-bridgehead.sh +++ b/lib/install-bridgehead.sh @@ -29,29 +29,29 @@ EOF # TODO: Determine whether this should be located in setup-bridgehead (triggered through bridgehead install) or in update bridgehead (triggered every hour) if [ -z "$LDM_AUTH" ]; then - log "INFO" "Now generating basic auth for the local data management (see adduser in bridgehead for more information). " + log "INFO" "Now generating basic auth for the local data management (see setuser in bridgehead for more information). " generated_passwd="$(cat /proc/sys/kernel/random/uuid | sed 's/[-]//g' | head -c 32)" - add_basic_auth_user $PROJECT $generated_passwd "LDM_AUTH" $PROJECT + set_basic_auth_user "$PROJECT" "$generated_passwd" "LDM_AUTH" "$PROJECT" fi if [ ! -z "$NNGM_CTS_APIKEY" ] && [ -z "$NNGM_AUTH" ]; then - log "INFO" "Now generating basic auth for nNGM upload API (see adduser in bridgehead for more information). " + log "INFO" "Now generating basic auth for nNGM upload API (see setuser in bridgehead for more information). " generated_passwd="$(cat /proc/sys/kernel/random/uuid | sed 's/[-]//g' | head -c 32)" - add_basic_auth_user "nngm" $generated_passwd "NNGM_AUTH" $PROJECT + set_basic_auth_user "nngm" "$generated_passwd" "NNGM_AUTH" "$PROJECT" fi if [ -z "$TRANSFAIR_AUTH" ]; then if [[ -n "$TTP_URL" || -n "$EXCHANGE_ID_SYSTEM" ]]; then - log "INFO" "Now generating basic auth user for transfair API (see adduser in bridgehead for more information). " + log "INFO" "Now generating basic auth user for transfair API (see setuser in bridgehead for more information). " generated_passwd="$(cat /proc/sys/kernel/random/uuid | sed 's/[-]//g' | head -c 32)" - add_basic_auth_user "transfair" $generated_passwd "TRANSFAIR_AUTH" $PROJECT + set_basic_auth_user "transfair" "$generated_passwd" "TRANSFAIR_AUTH" "$PROJECT" fi fi if [ "$ENABLE_EXPORTER" == "true" ] && [ -z "$EXPORTER_USER" ]; then - log "INFO" "Now generating basic auth for the exporter and reporter (see adduser in bridgehead for more information)." + log "INFO" "Now generating basic auth for the exporter and reporter (see setuser in bridgehead for more information)." generated_passwd="$(cat /proc/sys/kernel/random/uuid | sed 's/[-]//g' | head -c 32)" - add_basic_auth_user $PROJECT $generated_passwd "EXPORTER_USER" $PROJECT + set_basic_auth_user "$PROJECT" "$generated_passwd" "EXPORTER_USER" "$PROJECT" fi log "INFO" "Registering system units for bridgehead and bridgehead-update" diff --git a/lib/update-bridgehead.sh b/lib/update-bridgehead.sh index cf846db..5a493b3 100755 --- a/lib/update-bridgehead.sh +++ b/lib/update-bridgehead.sh @@ -140,9 +140,14 @@ fi if [ ! -z "$LDM_PASSWORD" ]; then FILE="/etc/bridgehead/$PROJECT.local.conf" log "INFO" "Migrating LDM_PASSWORD to encrypted credentials in $FILE" - add_basic_auth_user $PROJECT $LDM_PASSWORD "LDM_AUTH" $PROJECT - add_basic_auth_user $PROJECT $LDM_PASSWORD "NNGM_AUTH" $PROJECT - sed -i "/LDM_PASSWORD/{d;}" $FILE + if set_basic_auth_user "$PROJECT" "$LDM_PASSWORD" "LDM_AUTH" "$PROJECT"; then + if [ ! -z "$NNGM_CTS_APIKEY" ]; then + set_basic_auth_user "$PROJECT" "$LDM_PASSWORD" "NNGM_AUTH" "$PROJECT" + fi + sed -i "/LDM_PASSWORD/{d;}" $FILE + else + log "ERROR" "Migration failed, keeping LDM_PASSWORD in $FILE for the next attempt." + fi fi exit 0