From 410d13638202cf1fc667c0433139b51460b44572 Mon Sep 17 00:00:00 2001 From: Valentin Lab Date: Fri, 29 Nov 2019 14:20:06 +0100 Subject: [PATCH] chg: [nextcloud] change to admin password are supported Signed-off-by: Valentin Lab --- nextcloud/actions/occ | 30 +---- nextcloud/hooks/init | 39 +++++- .../hooks/postgres_database-relation-joined | 16 --- nextcloud/lib/common | 115 ++++++++++++++++++ 4 files changed, 152 insertions(+), 48 deletions(-) diff --git a/nextcloud/actions/occ b/nextcloud/actions/occ index e394fea5..e751d202 100755 --- a/nextcloud/actions/occ +++ b/nextcloud/actions/occ @@ -6,33 +6,7 @@ if [ -z "$SERVICE_DATASTORE" ]; then fi -export COMPOSE_IGNORE_ORPHANS=True +. "$CHARM_PATH/lib/common" -if ! [ -e "$SERVICE_DATASTORE/var/www/html/occ" ]; then - ## Here we use a nasty trick to launch only the initialisation - ## part of the ``entrypoint.sh``. By setting 'apache' as first - ## call argument, we satisfy the big first 'if' condition - ## triggering the installation if necessary, and will fail to - ## launch any apache - - ## Last, we do not want the relation web-proxy to run in this - ## bare-minimum nextcloud run AND we will use occ to set some info - ## in this very same relation. - compose --debug --without-relation="$SERVICE_NAME":web-proxy run \ - --rm --entrypoint /entrypoint.sh "$SERVICE_NAME" apache >&2 || true - if ! [ -e "$SERVICE_DATASTORE/var/www/html/occ" ]; then - err "Expected last command to create /var/www/html/occ" - exit 1 - fi -fi - - -## occ.batch will require /var/www/html to be populated ('occ' is -## supposed to exist). For that we need to make sure nextcloud have -## be ran and setup prior to running this next command. -compose -q --no-init --no-relations run \ - -v "$HOST_CHARM_STORE/${CHARM_REL_PATH#${CHARM_STORE}/}/src/occ.batch:/var/www/html/occ.batch" \ - -T --rm -u www-data "$SERVICE_NAME" /var/www/html/occ.batch "$@" | cat - -exit "${PIPESTATUS[0]}" \ No newline at end of file +occ "$@" diff --git a/nextcloud/hooks/init b/nextcloud/hooks/init index bb156586..dbbd3dc5 100755 --- a/nextcloud/hooks/init +++ b/nextcloud/hooks/init @@ -19,12 +19,43 @@ admin_user=$(options-get admin.user 2>&1) || { admin_user="admin" } -admin_password=$(options-get admin.password 2>&1) || { - err "Please specify an ${WHITE}admin.password${NORMAL} option" \ - "in ${DARKYELLOW}$SERVICE_NAME${NORMAL} service." - exit 1 +first_run=0 +read-0 current_user current_password < <(get_admin_user_password) || { + info "Probably no admin user and password set before." + first_run=1 } +admin_password=$(options-get admin.password 2>&1) || +admin_password=$(options-get admin-password 2>&1) || { + if [ "$current_password" ]; then + admin_password="$current_password" + else + info "Generating ${DARKYELLOW}$MASTER_BASE_SERVICE_NAME${NORMAL}'s"\ + "admin password" + admin_password=$(gen_password) + fi +} + +## We can't do anything with 'occ' before installation through +## postgres relation because the way 'entrypoint.sh' provided by +## nextcloud handles installation : it will not completely install +## nextcloud (it doesn't launch 'maintenance:install'), making +## nextcloud half installed and commands like 'user:*' unavailable. + +## Nicely enough, we don't need to do anything password wise if +## postgres was never launched before. +if [ "$first_run" == 0 ]; then + if [ "$current_password" != "$admin_password" ] || + [ "$current_user" != "$admin_user" ]; then + set_admin_user_password "$admin_user" "$admin_password" || { + err "Failed to set admin user and password." + exit 2 + } + fi +else + mkdir -p "$(dirname "$PASSWORD_FILE")" + p0 "$admin_user" "$admin_password" > "$PASSWORD_FILE" +fi ## XXXvlab: the directory here for datadir violates DRY as it is also ## in ``metadata.yml`` diff --git a/nextcloud/hooks/postgres_database-relation-joined b/nextcloud/hooks/postgres_database-relation-joined index f2852bb5..78340a2f 100755 --- a/nextcloud/hooks/postgres_database-relation-joined +++ b/nextcloud/hooks/postgres_database-relation-joined @@ -7,17 +7,6 @@ set -e PASSWORD="$(relation-get password)" USER="$(relation-get user)" DBNAME="$(relation-get dbname)" -ADMIN_PASSWORD=$(relation-base-compose-get admin-password 2>/dev/null) || { - if [ -e "$CONFIG" ]; then - ADMIN_PASSWORD=$(grep ^admin_passwd "$CONFIG" | sed -r 's/^admin_passwd\s+=\s+(.+)$/\1/g') - fi - if [ -z "$ADMIN_PASSWORD" ]; then - info "Generating odoo admin password" - ADMIN_PASSWORD=$(gen_password) - fi -} - -# control=$(echo -en "$USER\0$DBNAME\0$PASSWORD\0$ADMIN_PASSWORD" | md5_compat) config-add "\ services: @@ -29,9 +18,4 @@ services: POSTGRES_USER: $USER " -# [ "$control" == "$(relation-get control 2>/dev/null)" ] && exit 0 - - -# relation-set control "$control" - info "Configured $SERVICE_NAME code for $TARGET_SERVICE_NAME access." diff --git a/nextcloud/lib/common b/nextcloud/lib/common index 1558c9af..3c4a9de0 100644 --- a/nextcloud/lib/common +++ b/nextcloud/lib/common @@ -1,3 +1,118 @@ # -*- mode: shell-script -*- +## This place is not accessible from container on purpose: container +## don't need that. This should be stored in /var/lib/compose/ in a +## project, service directory a little like relation data. +PASSWORD_FILE="$SERVICE_CONFIGSTORE/etc/$SERVICE_NAME/pass" + + +has_user() { + local user="$1" + if ! out=$(occ user:info "$user"); then + if [ "$out" == "user not found" ]; then + return 1 + else + if [ -n "$out" ]; then + err "Command 'occ user:info $user' failed with this output:" + echo "$out" | prefix " | " >&2 + else + err "Command 'occ user:info $user' failed with no output." + fi + return 2 + fi + fi + return 0 +} + + +set_admin_user_password() { + local user="$1" password="$2" errlvl + + [ -z "$password" ] && { + err "Refusing to set admin user an empty password." + return 3 + } + + has_user "$user" + errlvl=$? + [[ "$errlvl" -gt 1 ]] && { + err "'has_user $user' failed. Bailing out." + return "$errlvl" + } + if [[ "$errlvl" == 1 ]]; then + info "User $user not found. Creating it in default 'admin' group." + ( + occ_docker_run_opts=("-e" "OC_PASS=$password") + occ user:add --group=admin --password-from-env --display-name="$user" "$user" + ) || return 1 + else + info "User $user found. Resetting password." + ( + occ_docker_run_opts=("-e" "OC_PASS=$password") + occ user:resetpassword "$user" "--password-from-env" + ) || { + err "'occ user:resetpassword' failed," \ + "common reason include password too simple." + return 1 + } + fi + ## XXXvlab: DRY violation: init does the same thing + mkdir -p "$(dirname "$PASSWORD_FILE")" + p0 "$user" "$password" > "$PASSWORD_FILE" +} + + +get_admin_user_password() { + if [ -e "$PASSWORD_FILE" ]; then + cat "$PASSWORD_FILE" + else + return 1 + fi +} + + +create_occ_if_not_exists() { + + if ! [ -e "$SERVICE_DATASTORE/var/www/html/occ" ]; then + ## Here we use a nasty trick to launch only the initialisation + ## part of the ``entrypoint.sh``. By setting 'apache' as first + ## call argument, we satisfy the big first 'if' condition + ## triggering the installation if necessary, and will fail to + ## launch any apache + + ## Last, we do not want the relation web-proxy to run in this + ## bare-minimum nextcloud run AND we will use occ to set some info + ## in this very same relation. + + ## Note also that ``init`` is required as it sets + ## NEXTCLOUD_ADMIN_{USER,PASSWORD} that is required to trigger + ## a full installation + + export COMPOSE_IGNORE_ORPHANS=true + compose --debug --without-relation="$SERVICE_NAME":web-proxy run \ + --rm --entrypoint /entrypoint.sh "$SERVICE_NAME" apache >&2 || true + if ! [ -e "$SERVICE_DATASTORE/var/www/html/occ" ]; then + err "Expected last command to create /var/www/html/occ" + return 1 + fi + fi +} + + +occ() { + + create_occ_if_not_exists || return 1 + + ## occ.batch will require /var/www/html to be populated ('occ' is + ## supposed to exist). For that we need to make sure nextcloud have + ## be ran and setup prior to running this next command. + export COMPOSE_IGNORE_ORPHANS=true + compose --debug -q --no-init --no-relations run \ + "${occ_docker_run_opts[@]}" \ + -v "$HOST_CHARM_STORE/${CHARM_REL_PATH#${CHARM_STORE}/}/src/occ.batch:/var/www/html/occ.batch" \ + -T --rm -u www-data "$SERVICE_NAME" /var/www/html/occ.batch "$@" | cat + + return "${PIPESTATUS[0]}" +} +