This is a part of my script
sudo bash -c "printf '%s\n' \
'user-test:' \
' hash: \"$HASHED_PASSWORD\"' \
' reserved: true' \
' backend_roles:' \
' - \"admin\"' \
' description: \"admin user\"' >> /etc/opensearch/opensearch security/internal_users.yml"
$HASHED_PASSWORD
is generated using usr/share/opensearch/plugins/opensearch-security/tools/hash.sh
It generates it in this format
$2y$12$M44wSxuwYbYRUqRKf1IUAuY5jvBlh4tu5XVx7/PO6SqvPjuXzJaCK
I want this exact value to be written in the /etc/opensearch/opensearch security/internal_users.yml
file but it is unable to do so, as $2, $12, $M is treated as a variable.
This is how it actually writes.
user-test:
hash: "y2/PO6SqvPjuXzJaCK"
reserved: true
backend_roles:
- "admin"
description: "admin user"
This is all about quoting.
I made a local file to test it.
$: cat tst
#! /usr/bin/env bash
set -x
bash -c "printf '%s\n' '
user-test:
hash: \"${1:-${HASHED_PASSWORD:?Password Not Set}}\" # arg 1st, env 2nd, else bail
reserved: true
backend_roles:
- \"admin\"
description: \"admin user\"
'"
If the password data isn't exported in the environment OR passed in, it fails.
$: ./tst
./tst: line 3: HASHED_PASSWORD: Password Not Set
Pass it in -
$: ./tst "$tmp"
+ bash -c 'printf '\''%s\n'\'' '\''
user-test:
hash: "$2y$12$M44wSxuwYbYRUqRKf1IUAuY5jvBlh4tu5XVx7/PO6SqvPjuXzJaCK" # arg 1st, env 2nd, else bail
reserved: true
backend_roles:
- "admin"
description: "admin user"
'\'''
user-test:
hash: "$2y$12$M44wSxuwYbYRUqRKf1IUAuY5jvBlh4tu5XVx7/PO6SqvPjuXzJaCK" # arg 1st, env 2nd, else bail
reserved: true
backend_roles:
- "admin"
description: "admin user"
(Yes, I added an explanatory comment that ends up in the yaml, but it's also a yaml comment.)
You can set the value inline -
$: HASHED_PASSWORD='$2y$12$M44wSxuwYbYRUqRKf1IUAuY5jvBlh4tu5XVx7/PO6SqvPjuXzJaCK' ./tst
+ bash -c 'printf '\''%s\n'\'' '\''
user-test:
hash: "$2y$12$M44wSxuwYbYRUqRKf1IUAuY5jvBlh4tu5XVx7/PO6SqvPjuXzJaCK" # arg 1st, env 2nd, else bail
reserved: true
backend_roles:
- "admin"
description: "admin user"
'\'''
user-test:
hash: "$2y$12$M44wSxuwYbYRUqRKf1IUAuY5jvBlh4tu5XVx7/PO6SqvPjuXzJaCK" # arg 1st, env 2nd, else bail
reserved: true
backend_roles:
- "admin"
description: "admin user"
Or export it -
$: export HASHED_PASSWORD='$2y$12$M44wSxuwYbYRUqRKf1IUAuY5jvBlh4tu5XVx7/PO6SqvPjuXzJaCK'
$: ./tst
+ bash -c 'printf '\''%s\n'\'' '\''
user-test:
hash: "$2y$12$M44wSxuwYbYRUqRKf1IUAuY5jvBlh4tu5XVx7/PO6SqvPjuXzJaCK" # arg 1st, env 2nd, else bail
reserved: true
backend_roles:
- "admin"
description: "admin user"
'\'''
user-test:
hash: "$2y$12$M44wSxuwYbYRUqRKf1IUAuY5jvBlh4tu5XVx7/PO6SqvPjuXzJaCK" # arg 1st, env 2nd, else bail
reserved: true
backend_roles:
- "admin"
description: "admin user"
I put the whole yaml string in one outer set of single-quotes with your newlines embedded to simplify a bit. The command using it is in double-quotes so that the single-quotes are just data in the string, and it's double-quote interpolated, so the var value goes in as data and doesn't get re-interpolated. All that gets passed to the bash -c
, so it works.
YMMV.