From 932e2496ed87b830a468a263cf1b1f5e6a88e2ef Mon Sep 17 00:00:00 2001 From: Dennis Camera Date: Tue, 15 Dec 2020 18:40:39 +0100 Subject: [PATCH 1/8] [type/__postgres_role] Lint --- .../conf/type/__postgres_role/explorer/state | 32 ++++---- .../conf/type/__postgres_role/gencode-remote | 78 ++++++++++--------- 2 files changed, 58 insertions(+), 52 deletions(-) diff --git a/cdist/conf/type/__postgres_role/explorer/state b/cdist/conf/type/__postgres_role/explorer/state index c8e1fa9d..110d29d5 100755 --- a/cdist/conf/type/__postgres_role/explorer/state +++ b/cdist/conf/type/__postgres_role/explorer/state @@ -1,4 +1,4 @@ -#!/bin/sh +#!/bin/sh -e # # 2011 Steven Armstrong (steven-cdist at armstrong.cc) # @@ -11,32 +11,32 @@ # # cdist is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with cdist. If not, see . # -case "$("${__explorer}/os")" +case $("${__explorer:?}/os") in - netbsd) - postgres_user='pgsql' - ;; - openbsd) - postgres_user='_postgresql' - ;; - *) - postgres_user='postgres' - ;; + (netbsd) + postgres_user='pgsql' + ;; + (openbsd) + postgres_user='_postgresql' + ;; + (*) + postgres_user='postgres' + ;; esac -name="$__object_id" +rolename=${__object_id:?} -if test -n "$(su - "$postgres_user" -c "psql postgres -twAc \"SELECT 1 FROM pg_roles WHERE rolname='$name'\"")" +if test -n "$(su - "${postgres_user}" -c "psql postgres -twAc \"SELECT 1 FROM pg_roles WHERE rolname='${rolename}'\"")" then - echo 'present' + echo 'present' else - echo 'absent' + echo 'absent' fi diff --git a/cdist/conf/type/__postgres_role/gencode-remote b/cdist/conf/type/__postgres_role/gencode-remote index 282294c9..4fb761ed 100755 --- a/cdist/conf/type/__postgres_role/gencode-remote +++ b/cdist/conf/type/__postgres_role/gencode-remote @@ -11,55 +11,61 @@ # # cdist is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with cdist. If not, see . # -case "$(cat "${__global}/explorer/os")" +case $(cat "${__global:?}/explorer/os") in - netbsd) - postgres_user='pgsql' - ;; - openbsd) - postgres_user='_postgresql' - ;; - *) - postgres_user='postgres' - ;; + (netbsd) + postgres_user='pgsql' + ;; + (openbsd) + postgres_user='_postgresql' + ;; + (*) + postgres_user='postgres' + ;; esac -name="$__object_id" -state_is="$(cat "$__object/explorer/state")" -state_should="$(cat "$__object/parameter/state")" +rolename=${__object_id:?} +state_is=$(cat "${__object:?}/explorer/state") +state_should=$(cat "${__object:?}/parameter/state") -[ "$state_is" = "$state_should" ] && exit 0 +if test "${state_is}" = "${state_should}" +then + exit 0 +fi -case "$state_should" in - present) - if [ -f "$__object/parameter/password" ]; then - password="$(cat "$__object/parameter/password")" - fi - booleans="" - for boolean in login createdb createrole superuser; do - if [ ! -f "$__object/parameter/$boolean" ]; then - boolean="no${boolean}" - fi - upper=$(echo $boolean | tr '[:lower:]' '[:upper:]') - booleans="$booleans $upper" - done +case ${state_should} +in + (present) + if test -f "${__object:?}/parameter/password" + then + password=$(cat "${__object:?}/parameter/password") + fi + booleans= + for boolean in login createdb createrole superuser + do + if test ! -f "${__object:?}/parameter/${boolean}" + then + boolean="no${boolean}" + fi + booleans="${booleans} $(echo ${boolean} | tr '[:lower:]' '[:upper:]')" + done - [ -n "$password" ] && password="PASSWORD '$password'" - cat << EOF -su - '$postgres_user' -c "psql postgres -wc \"CREATE ROLE \\\\\"$name\\\\\" WITH $password $booleans;\"" + [ -n "${password}" ] && password="PASSWORD '${password}'" + cat << EOF +su - '${postgres_user}' -c "psql postgres -wc 'CREATE ROLE \\"${rolename}\\" WITH ${password} ${booleans};'" EOF - ;; - absent) - cat << EOF -su - '$postgres_user' -c "dropuser \"$name\"" + ;; + (absent) + cat << EOF +su - '${postgres_user}' -c "dropuser '${rolename}'" EOF - ;; + ;; esac From c36df82882fedb6ce3630e4718c46992a7c153a0 Mon Sep 17 00:00:00 2001 From: Dennis Camera Date: Tue, 15 Dec 2020 21:05:55 +0100 Subject: [PATCH 2/8] [type/__postgres_role] ALTER ROLE when parameters change --- .../conf/type/__postgres_role/explorer/state | 42 +++++++++++- .../conf/type/__postgres_role/gencode-remote | 65 +++++++++++++++---- 2 files changed, 91 insertions(+), 16 deletions(-) diff --git a/cdist/conf/type/__postgres_role/explorer/state b/cdist/conf/type/__postgres_role/explorer/state index 110d29d5..033afcb2 100755 --- a/cdist/conf/type/__postgres_role/explorer/state +++ b/cdist/conf/type/__postgres_role/explorer/state @@ -1,6 +1,7 @@ #!/bin/sh -e # # 2011 Steven Armstrong (steven-cdist at armstrong.cc) +# 2020 Dennis Camera (dennis.camera at ssrq-sds-fds.ch) # # This file is part of cdist. # @@ -31,11 +32,48 @@ in ;; esac - rolename=${__object_id:?} -if test -n "$(su - "${postgres_user}" -c "psql postgres -twAc \"SELECT 1 FROM pg_roles WHERE rolname='${rolename}'\"")" +role_properties=$( + cmd=$(printf "psql -F '\034' -R '\036' -wAc \"SELECT * FROM pg_roles WHERE rolname='%s'\"" "${rolename}") + su -l "${postgres_user}" -c "${cmd}" \ + | awk ' + BEGIN { RS = "\036"; FS = "\034" } + /^\([0-9]+ rows?\)/ { exit } + NR == 1 { for (i = 1; i <= NF; i++) cols[i] = $i; next } + NR == 2 { for (i = 1; i <= NF; i++) printf "%s=%s\n", cols[i], $i } + ' +) + +if test -n "${role_properties}" then + # Check if the user's properties match the parameters + for prop in login createdb createrole superuser + do + bool_should=$(test -f "${__object:?}/parameter/${prop}" && echo 't' || echo 'f') + bool_is=$( + printf '%s\n' "${role_properties}" | + awk -F '=' -v key="${prop}" ' + BEGIN { + if (key == "login") + key = "canlogin" + else if (key == "superuser") + key = "super" + key = "rol" key + } + $1 == key { + sub(/^[^=]*=/, "") + print + } + ' + ) + + test "${bool_is}" = "${bool_should}" || { + echo 'different' + exit 0 + } + done + echo 'present' else echo 'absent' diff --git a/cdist/conf/type/__postgres_role/gencode-remote b/cdist/conf/type/__postgres_role/gencode-remote index 4fb761ed..7837976c 100755 --- a/cdist/conf/type/__postgres_role/gencode-remote +++ b/cdist/conf/type/__postgres_role/gencode-remote @@ -1,6 +1,7 @@ #!/bin/sh -e # # 2011 Steven Armstrong (steven-cdist at armstrong.cc) +# 2020 Dennis Camera (dennis.camera at ssrq-sds-fds.ch) # # This file is part of cdist. # @@ -18,6 +19,15 @@ # along with cdist. If not, see . # +quote() { + if test $# -gt 0 + then + printf '%s' "$*" + else + cat - + fi | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/'/" +} + case $(cat "${__global:?}/explorer/os") in (netbsd) @@ -44,28 +54,55 @@ fi case ${state_should} in (present) - if test -f "${__object:?}/parameter/password" + if test -s "${__object:?}/parameter/password" then - password=$(cat "${__object:?}/parameter/password") + quoted_password=$( + delim='$$' + while grep -q -F "${delim}" "${__object:?}/parameter/password" + do + delim="\$$(LC_ALL=C tr -cd '[:alpha:]' /dev/null)$" + done + + raw_passwd=$(cat "${__object:?}/parameter/password"; printf .) + # shellcheck disable=SC2016 + printf '%s%s%s' "${delim}" "${raw_passwd%?.}" "${delim}" + ) fi + booleans= for boolean in login createdb createrole superuser do - if test ! -f "${__object:?}/parameter/${boolean}" - then - boolean="no${boolean}" - fi - booleans="${booleans} $(echo ${boolean} | tr '[:lower:]' '[:upper:]')" + booleans="${booleans}${booleans:+ }$( + if test -f "${__object:?}/parameter/${boolean}" + then + echo "${boolean}" + else + echo "no${boolean}" + fi \ + | tr '[:lower:]' '[:upper:]')" done - [ -n "${password}" ] && password="PASSWORD '${password}'" - cat << EOF -su - '${postgres_user}' -c "psql postgres -wc 'CREATE ROLE \\"${rolename}\\" WITH ${password} ${booleans};'" -EOF + case ${state_is} + in + (absent) + query=$(printf 'CREATE ROLE "%s" WITH %s PASSWORD %s;' \ + "${rolename}" "${booleans}" "${quoted_password:-NULL}") + ;; + (different) + query=$(printf 'ALTER ROLE "%s" WITH %s PASSWORD %s;' \ + "${rolename}" "${booleans}" "${quoted_password:-NULL}") + ;; + (*) + exit 1 # TODO: error msg + ;; + esac + + psql_cmd=$(printf 'psql postgres -wc %s' "$(quote "${query}")" | quote) + printf "su -l '%s' -c %s\\n" "${postgres_user}" "${psql_cmd}" ;; (absent) - cat << EOF -su - '${postgres_user}' -c "dropuser '${rolename}'" -EOF + printf "su -l '%s' -c 'dropuser '\\\\'%s\\\\'\\n" \ + "${postgres_user}" \ + "$(quote "${rolename}")" ;; esac From 7b7ca4d385ccd025cbefced58419468651652da8 Mon Sep 17 00:00:00 2001 From: Dennis Camera Date: Wed, 16 Dec 2020 19:06:50 +0100 Subject: [PATCH 3/8] [type/__postgres_role] Handle password changes --- .../conf/type/__postgres_role/explorer/state | 76 +++++++++++++++++-- .../conf/type/__postgres_role/gencode-remote | 23 ++++-- 2 files changed, 88 insertions(+), 11 deletions(-) diff --git a/cdist/conf/type/__postgres_role/explorer/state b/cdist/conf/type/__postgres_role/explorer/state index 033afcb2..4aadbdff 100755 --- a/cdist/conf/type/__postgres_role/explorer/state +++ b/cdist/conf/type/__postgres_role/explorer/state @@ -34,9 +34,23 @@ esac rolename=${__object_id:?} + +psql_query() { + su -l "${postgres_user}" -c "$( + printf "psql -F '\034' -R '\036' -wAc '%s'" \ + "$(printf %s "$*" | sed "s/'/'\\\\''/g")" + )" +} + +password_check_login() ( + PGPASSWORD=$(cat "${__object:?}/parameter/password"; printf .) + PGPASSWORD=${PGPASSWORD%?.} + export PGPASSWORD + psql -w -h localhost -U "${rolename}" template1 -c '\q' >/dev/null 2>&1 +) + role_properties=$( - cmd=$(printf "psql -F '\034' -R '\036' -wAc \"SELECT * FROM pg_roles WHERE rolname='%s'\"" "${rolename}") - su -l "${postgres_user}" -c "${cmd}" \ + psql_query "SELECT * FROM pg_roles WHERE rolname = '${rolename}'" \ | awk ' BEGIN { RS = "\036"; FS = "\034" } /^\([0-9]+ rows?\)/ { exit } @@ -69,12 +83,62 @@ then ) test "${bool_is}" = "${bool_should}" || { - echo 'different' - exit 0 + state='different properties' } done - echo 'present' + # Check password + passwd_stored=$( + psql_query "SELECT rolpassword FROM pg_authid WHERE rolname = '${rolename}'" \ + | awk 'BEGIN { RS = "\036" } NR == 2' + printf . + ) + passwd_stored=${passwd_stored%?.} + + passwd_should=$(cat "${__object}/parameter/password"; printf .) + passwd_should=${passwd_should%?.} + + if expr "${passwd_stored}" : 'SCRAM-SHA-256\$.*$' >/dev/null + then + # SCRAM-SHA-256 "encrypted" password + # NOTE: There is currently no easy way to check SCRAM passwords + password_check_login || state="${state:-different} password" + elif expr "${passwd_stored}" : 'md5[0-9a-f]\{32\}$' >/dev/null + then + # MD5 "encrypted" password + if command -v md5sum >/dev/null 2>&1 + then + should_md5=$( + printf '%s%s' "${passwd_should}" "${rolename}" \ + | md5sum - | sed -e 's/[^0-9a-f]*$//') + elif command -v gmd5sum >/dev/null 2>&1 + then + should_md5=$( + printf '%s%s' "${passwd_should}" "${rolename}" \ + | gmd5sum - | sed -e 's/[^0-9a-f]*$//') + elif command -v openssl >/dev/null 2>&1 + then + should_md5=$( + printf '%s%s' "${passwd_should}" "${rolename}" \ + | openssl dgst -md5 | sed 's/^.* //') + fi + + if test -n "${should_md5}" + then + test "${passwd_stored}" = "md5${should_md5}" \ + || state="${state:-different} password" + else + password_check_login || state="${state:-different} password" + fi + else + # unencrypted password (unsupported since PostgreSQL 10) + test "${passwd_stored}" = "${passwd_should}" \ + || state="${state:-different} password" + fi + + test -n "${state}" || state='present' else - echo 'absent' + state='absent' fi + +echo "${state}" diff --git a/cdist/conf/type/__postgres_role/gencode-remote b/cdist/conf/type/__postgres_role/gencode-remote index 7837976c..fd590a4b 100755 --- a/cdist/conf/type/__postgres_role/gencode-remote +++ b/cdist/conf/type/__postgres_role/gencode-remote @@ -58,7 +58,9 @@ in then quoted_password=$( delim='$$' - while grep -q -F "${delim}" "${__object:?}/parameter/password" + # NOTE: Strip away trailing $ because with it the check breaks + # if the password ends with $ + random value. + while grep -q -F "${delim%$}" "${__object:?}/parameter/password" do delim="\$$(LC_ALL=C tr -cd '[:alpha:]' /dev/null)$" done @@ -88,12 +90,23 @@ in query=$(printf 'CREATE ROLE "%s" WITH %s PASSWORD %s;' \ "${rolename}" "${booleans}" "${quoted_password:-NULL}") ;; - (different) - query=$(printf 'ALTER ROLE "%s" WITH %s PASSWORD %s;' \ - "${rolename}" "${booleans}" "${quoted_password:-NULL}") + (different*) + query="ALTER ROLE \"${rolename}\" WITH" + + if expr "${state_is}" : 'different.*properties' >/dev/null + then + query="${query} ${booleans}" + fi + if expr "${state_is}" : 'different.*password' >/dev/null + then + query="${query} PASSWORD ${quoted_password:-NULL}" + fi + + query="${query};" ;; (*) - exit 1 # TODO: error msg + printf 'Invalid state reported by state explorer: %s\n' "${state_is}" >&2 + exit 1 ;; esac From 4859c27900d125841c703e0270dd8c0eae05d504 Mon Sep 17 00:00:00 2001 From: Dennis Camera Date: Thu, 17 Dec 2020 16:57:03 +0100 Subject: [PATCH 4/8] [type/__postgres_role] Refactor gencode-remote --- .../conf/type/__postgres_role/gencode-remote | 65 ++++++++++--------- 1 file changed, 34 insertions(+), 31 deletions(-) diff --git a/cdist/conf/type/__postgres_role/gencode-remote b/cdist/conf/type/__postgres_role/gencode-remote index fd590a4b..540eb606 100755 --- a/cdist/conf/type/__postgres_role/gencode-remote +++ b/cdist/conf/type/__postgres_role/gencode-remote @@ -51,9 +51,6 @@ then exit 0 fi -case ${state_should} -in - (present) if test -s "${__object:?}/parameter/password" then quoted_password=$( @@ -64,6 +61,11 @@ in do delim="\$$(LC_ALL=C tr -cd '[:alpha:]' /dev/null)$" done +psql_query() { + printf 'su -l %s -c %s\n' \ + "$(quote "${postgres_user}")" \ + "$(quote "psql postgres -wc $(quote "$1")")" +} raw_passwd=$(cat "${__object:?}/parameter/password"; printf .) # shellcheck disable=SC2016 @@ -71,51 +73,52 @@ in ) fi - booleans= - for boolean in login createdb createrole superuser - do - booleans="${booleans}${booleans:+ }$( - if test -f "${__object:?}/parameter/${boolean}" - then - echo "${boolean}" - else - echo "no${boolean}" - fi \ - | tr '[:lower:]' '[:upper:]')" - done +role_properties_should() { + _props= + for _prop in login createdb createrole superuser + do + _props="${_props}${_props:+ }$( + if test -f "${__object:?}/parameter/${_prop}" + then + echo "${_prop}" + else + echo "no${_prop}" + fi \ + | tr '[:lower:]' '[:upper:]')" + done + printf '%s\n' "${_props}" + unset _prop _props +} +case ${state_should} +in + (present) case ${state_is} in (absent) - query=$(printf 'CREATE ROLE "%s" WITH %s PASSWORD %s;' \ - "${rolename}" "${booleans}" "${quoted_password:-NULL}") + psql_query "$(printf 'CREATE ROLE "%s" WITH %s PASSWORD %s;' \ + "${rolename}" "$(role_properties_should)" "${quoted_password:-NULL}")" ;; (different*) - query="ALTER ROLE \"${rolename}\" WITH" - if expr "${state_is}" : 'different.*properties' >/dev/null then - query="${query} ${booleans}" - fi - if expr "${state_is}" : 'different.*password' >/dev/null - then - query="${query} PASSWORD ${quoted_password:-NULL}" + psql_query "ALTER ROLE \"${rolename}\" WITH $(role_properties_should);" fi - query="${query};" + if expr "${state_is}" : 'different.*password' >/dev/null + then + psql_query "ALTER ROLE \"${rolename}\" WITH PASSWORD ${quoted_password:-NULL};" + fi ;; (*) printf 'Invalid state reported by state explorer: %s\n' "${state_is}" >&2 exit 1 ;; esac - - psql_cmd=$(printf 'psql postgres -wc %s' "$(quote "${query}")" | quote) - printf "su -l '%s' -c %s\\n" "${postgres_user}" "${psql_cmd}" ;; (absent) - printf "su -l '%s' -c 'dropuser '\\\\'%s\\\\'\\n" \ - "${postgres_user}" \ - "$(quote "${rolename}")" + printf 'su -l %s -c %s\n' \ + "$(quote "${postgres_user}")" \ + "$(quote "dropuser $(quote "${rolename}")")" ;; esac From 1180f13ed6c12e0277bebdf32bdd9840320d0fb9 Mon Sep 17 00:00:00 2001 From: Dennis Camera Date: Thu, 17 Dec 2020 16:58:32 +0100 Subject: [PATCH 5/8] [type/__postgres_role] Fix setting password We need to make sure that the password does not end up in ~/.psql_history. --- .../conf/type/__postgres_role/gencode-remote | 38 ++++++++++--------- 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/cdist/conf/type/__postgres_role/gencode-remote b/cdist/conf/type/__postgres_role/gencode-remote index 540eb606..15c3e692 100755 --- a/cdist/conf/type/__postgres_role/gencode-remote +++ b/cdist/conf/type/__postgres_role/gencode-remote @@ -51,27 +51,29 @@ then exit 0 fi - if test -s "${__object:?}/parameter/password" - then - quoted_password=$( - delim='$$' - # NOTE: Strip away trailing $ because with it the check breaks - # if the password ends with $ + random value. - while grep -q -F "${delim%$}" "${__object:?}/parameter/password" - do - delim="\$$(LC_ALL=C tr -cd '[:alpha:]' /dev/null)$" - done psql_query() { printf 'su -l %s -c %s\n' \ "$(quote "${postgres_user}")" \ "$(quote "psql postgres -wc $(quote "$1")")" } - raw_passwd=$(cat "${__object:?}/parameter/password"; printf .) - # shellcheck disable=SC2016 - printf '%s%s%s' "${delim}" "${raw_passwd%?.}" "${delim}" - ) - fi +psql_set_password() { + # NOTE: Always make sure that the password does not end up in psql_history! + if test -s "${__object:?}/parameter/password" + then + cat <<-EOF + exec 3< "\${__object:?}/parameter/password" + su -l '${postgres_user}' -c 'psql -q postgres -w' <<'SQL' + \set HISTFILE /dev/null + \set pw \`cat <&3\` + ALTER ROLE "${rolename}" WITH PASSWORD :'pw'; + SQL + exec 3<&- + EOF + else + psql_query "ALTER ROLE \"${rolename}\" WITH PASSWORD NULL;" + fi +} role_properties_should() { _props= @@ -96,8 +98,8 @@ in case ${state_is} in (absent) - psql_query "$(printf 'CREATE ROLE "%s" WITH %s PASSWORD %s;' \ - "${rolename}" "$(role_properties_should)" "${quoted_password:-NULL}")" + psql_query "CREATE ROLE \"${rolename}\" WITH $(role_properties_should);" + psql_set_password ;; (different*) if expr "${state_is}" : 'different.*properties' >/dev/null @@ -107,7 +109,7 @@ in if expr "${state_is}" : 'different.*password' >/dev/null then - psql_query "ALTER ROLE \"${rolename}\" WITH PASSWORD ${quoted_password:-NULL};" + psql_set_password fi ;; (*) From 99d82fd0d5ab6d6ccd95fe8a7d3b24f5d82a4cce Mon Sep 17 00:00:00 2001 From: Dennis Camera Date: Thu, 17 Dec 2020 17:05:58 +0100 Subject: [PATCH 6/8] [type/__postgres_role] Always set psql -q --- cdist/conf/type/__postgres_role/explorer/state | 4 ++-- cdist/conf/type/__postgres_role/gencode-remote | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/cdist/conf/type/__postgres_role/explorer/state b/cdist/conf/type/__postgres_role/explorer/state index 4aadbdff..77779662 100755 --- a/cdist/conf/type/__postgres_role/explorer/state +++ b/cdist/conf/type/__postgres_role/explorer/state @@ -37,7 +37,7 @@ rolename=${__object_id:?} psql_query() { su -l "${postgres_user}" -c "$( - printf "psql -F '\034' -R '\036' -wAc '%s'" \ + printf "psql -q -F '\034' -R '\036' -wAc '%s'" \ "$(printf %s "$*" | sed "s/'/'\\\\''/g")" )" } @@ -46,7 +46,7 @@ password_check_login() ( PGPASSWORD=$(cat "${__object:?}/parameter/password"; printf .) PGPASSWORD=${PGPASSWORD%?.} export PGPASSWORD - psql -w -h localhost -U "${rolename}" template1 -c '\q' >/dev/null 2>&1 + psql -q -w -h localhost -U "${rolename}" template1 -c '\q' >/dev/null 2>&1 ) role_properties=$( diff --git a/cdist/conf/type/__postgres_role/gencode-remote b/cdist/conf/type/__postgres_role/gencode-remote index 15c3e692..877c8135 100755 --- a/cdist/conf/type/__postgres_role/gencode-remote +++ b/cdist/conf/type/__postgres_role/gencode-remote @@ -54,7 +54,7 @@ fi psql_query() { printf 'su -l %s -c %s\n' \ "$(quote "${postgres_user}")" \ - "$(quote "psql postgres -wc $(quote "$1")")" + "$(quote "psql postgres -q -w -c $(quote "$1")")" } psql_set_password() { @@ -63,7 +63,7 @@ psql_set_password() { then cat <<-EOF exec 3< "\${__object:?}/parameter/password" - su -l '${postgres_user}' -c 'psql -q postgres -w' <<'SQL' + su -l '${postgres_user}' -c 'psql -q -w postgres' <<'SQL' \set HISTFILE /dev/null \set pw \`cat <&3\` ALTER ROLE "${rolename}" WITH PASSWORD :'pw'; From 2954347771e00610a084c7b033016765f7a3d6d7 Mon Sep 17 00:00:00 2001 From: Dennis Camera Date: Thu, 14 Jan 2021 13:46:40 +0100 Subject: [PATCH 7/8] [type/__postgres_role] Add note regarding empty passwords --- cdist/conf/type/__postgres_role/gencode-remote | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cdist/conf/type/__postgres_role/gencode-remote b/cdist/conf/type/__postgres_role/gencode-remote index 877c8135..d7631fbd 100755 --- a/cdist/conf/type/__postgres_role/gencode-remote +++ b/cdist/conf/type/__postgres_role/gencode-remote @@ -59,6 +59,8 @@ psql_query() { psql_set_password() { # NOTE: Always make sure that the password does not end up in psql_history! + # NOTE: Never set an empty string as the password, because they can be + # interpreted differently by different tooling. if test -s "${__object:?}/parameter/password" then cat <<-EOF From 35cde3e666c229ceb94a1c5074083f7ba905768a Mon Sep 17 00:00:00 2001 From: Dennis Camera Date: Mon, 18 Jan 2021 13:09:29 +0100 Subject: [PATCH 8/8] [type/__postgres_role] Fix state explorer when stored password is empty --- cdist/conf/type/__postgres_role/explorer/state | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/cdist/conf/type/__postgres_role/explorer/state b/cdist/conf/type/__postgres_role/explorer/state index 77779662..34069de9 100755 --- a/cdist/conf/type/__postgres_role/explorer/state +++ b/cdist/conf/type/__postgres_role/explorer/state @@ -95,13 +95,20 @@ then ) passwd_stored=${passwd_stored%?.} - passwd_should=$(cat "${__object}/parameter/password"; printf .) + if test -f "${__object:?}/parameter/password" + then + passwd_should=$(cat "${__object:?}/parameter/password"; printf .) + fi passwd_should=${passwd_should%?.} - if expr "${passwd_stored}" : 'SCRAM-SHA-256\$.*$' >/dev/null + if test -z "${passwd_stored}" + then + test -z "${passwd_should}" || state="${state:-different} password" + elif expr "${passwd_stored}" : 'SCRAM-SHA-256\$.*$' >/dev/null then # SCRAM-SHA-256 "encrypted" password - # NOTE: There is currently no easy way to check SCRAM passwords + # NOTE: There is currently no easy way to check SCRAM passwords without + # logging in password_check_login || state="${state:-different} password" elif expr "${passwd_stored}" : 'md5[0-9a-f]\{32\}$' >/dev/null then