diff --git a/bin/compose-core b/bin/compose-core index 60fd2f9..e478032 100755 --- a/bin/compose-core +++ b/bin/compose-core @@ -476,6 +476,121 @@ EOF export -f yaml_key_val_str +## +## Intended for charm +## + + +password:get() { + local service="$SERVICE_NAME" label="$1" type="$2" size="${2:-32}" + + local password_file + password_file="$(password:get-location "$label" "$type" "$size")" || return 1 + cat "$password_file" +} +export -f password:get + + +password:get-location() { + local service="$SERVICE_NAME" label="$1" type="$2" size="${2:-32}" + + if [ -z "$service" ]; then + err "${FUNCNAME[0]}: should be called from a charm hook" + return 1 + fi + + charm=$(get_service_charm "$service") || return 1 + case "$type" in + "internal") + : + ;; + "user") + if ! fn.exists "$charm:password:check"; then + err "Charm '$charm' doesn't provide a '$charm:password:check' function." + echo " This function is required to check if a user password was changed." >&2 + return 1 + fi + ;; + *) + err "${FUNCNAME[0]}: unknown type '$type'" + echo " Should be 'internal' or 'user'." >&2 + return 1 + ;; + esac + + local password_file="$SERVICE_DATASTORE"/.compose/passwords/"$type"/"$label" + + if ! [ -f "$password_file" ]; then + info "Generating password" >&2 + mkdir -p "${password_file%/*}" && + umask 077 && + openssl rand -base64 32 | tr -d '\n' > "$password_file" + e "$password_file" + return 0 + fi + if [ "$type" != "user" ]; then + info "Using existing secret password" >&2 + e "$password_file" + return 0 + fi + if [ -s "$password_file" ]; then + ## password was already set by user through the service + e "$password_file" + return 0 + fi + if ! out=$("$charm:password:check" "$label" "$password_file"); then + err "Failed to check password for '$label' in '$charm'." + return 1 + fi + case "$out" in + "changed") + info "Password for '$label' has changed, forgetting it." >&2 + e "" > "$password_file" ## empty file + e "$password_file" + return 0 + ;; + "ok") + e "$password_file" + return 0 + ;; + *) + err "Unknown return value from '$charm:password:check': $out" + return 1 + ;; + esac +} +export -f password:get-location + + +passwords:advertise() { + local services file label + services=("$@") + local service + complete_msg="" + for service in "${services[@]}"; do + dir="$DATASTORE"/"$service"/.compose/passwords/user + [ -d "$dir" ] || continue + msg="" + for file in "$dir"/*; do + [ -s "$file" ] || continue + ls -al "$file" >&2 + label=${file##*/} + msg+=" - $label is $(cat "$file")"$'\n' + done + if [ -n "$msg" ]; then + msg=" ${DARKYELLOW}$service${NORMAL}:"$'\n'"$msg" + fi + complete_msg+="$msg" + done + if [ -n "$complete_msg" ]; then + echo + echo "${WHITE}Compose generated passwords${NORMAL}:" + echo " (Consider changing these password in their respective services)" + echo + echo "$complete_msg" + fi >&2 +} + ## ## Docker ##