0

The problem
Starting a process will output sensitive information on the bash. I want to extract this value of an occuring pattern and assign it to bash variables. In concrete, starting the process vault (from hashicorp)

$ vault server -dev

will result in output like this

[...] You may need to set the following environment variable:

$ export VAULT_ADDR='http://127.0.0.1:8200'

The unseal key and root token are displayed below in case you want to seal/unseal the Vault or re-authenticate.

Unseal Key: n1yYaOhsKnE1mM+P1ezNTD1yHlhglmEM/F/+gzX0Zl0=
Root Token: s.k9C3agdaneOw809EnTqqErAM

Development mode should NOT be used in production installations!

==> Vault server started! Log data will stream in below:

[...]

So I'm interest in extracting the values from 'Unseal Key: ' and 'Root Token: '. Optionally all other output can be stored in a log file. However, the both values (unseal key and root token) should never be (directly) be visible on the commandline nor be stored in a file.

Approach(es)
I tried to solve this problem by using sed and redirect the output to the read command. It looks like this

$ read -r unseal_key root_token <<< $(vault server -dev | sed -n -e 's/Unseal Key: //p' -e 's/Root Token: //p' a.txt); echo "$unseal_key /\ $root_token"

a.txt should be a logfile where the rest of the output is stored. As said before, it is not necessary. The output for this command is empty. By splitting up the command and only executing

$ vault server -dev | sed -n -e 's/Unseal Key: //p' -e 's/Root Token: //p' 

I observed the (for me) odd behaviour, that the replaced string occured in different positions (but together) in the output.
Since I'm not really sure if sed fits the best for this case or if this even possible, the way I thought it, let me hear your thoughts about it.

So in summary

  • Starting a process results in commandline output
  • Two of these lines should not be displayed or temporarily stored in a file
  • These two values should be accessible after executing the command in variables
2
  • Should not be "stored in a file" or "stored on disk"? (There's a difference.)
    – user1686
    Apr 7, 2020 at 7:23
  • Thanks for your question, It should never be stored in disk.
    – Limon
    Apr 7, 2020 at 7:24

1 Answer 1

0

First capture everything in a single variable, then extract information as a separate step:

stuff=$(vault server -dev)

if [[ $stuff =~ Unseal\ Key:\ ([^[:space:]]+) ]]; then
    unseal_key=${BASH_REMATCH[1]}
else
    die "Could not find unseal key in vault's output"
fi

if [[ $stuff =~ Root\ Token:\ ([^[:space:]]+) ]]; then
    root_token=${BASH_REMATCH[1]}
else

You can use sed or grep if you want, of course, but Bash's built-in regex support will do.


Alternatively, you can redirect the program's output to a file that's stored in memory. For interactive desktop sessions (e.g. on your dev PC), many Linux distributions will give you $XDG_RUNTIME_DIR that's a tmpfs filesystem which does not correspond to any disk storage – it's meant for very small "runtime data", generally. (In fact the entire /run is also a tmpfs, but only accessible to root.)

Note that this is actually how <<< already works. Every time you use bash's <<EOF or <<< operators, it stores the provided text in a file under /tmp. (These days, /tmp is often a memory-only 'tmpfs' just like /run – but that's a relatively new feature; most older Linux systems almost always kept /tmp on disk.)

So if you really care about not storing this key on disk, perhaps do not use <<< or << with it...

3
  • Thanks for your comment and the hint on <<<. Unluckily, it produces nearly the same output as the command in the question with the variables being empty. Even starting it in the background by adding ampersand won't do the trick.
    – Limon
    Apr 7, 2020 at 12:08
  • Addition: Thanks, the solution worked quite well the other way. The problem was starting the server and trying to extract values from a running, non determinating process. In production enviroment, this is not the case. You start the server with your configuration in one shell (Process A) and initialized it in another shell (Process B). The initialization has a clearly defined end, so you can extract it there. With your solution provided, it supports the security aspect I mentioned.
    – Limon
    Apr 7, 2020 at 13:34
  • Ah, indeed, I overlooked the part where it says Log data will stream in below. Handling that kind of service would be rather more difficult, but I wonder if it's still doable with coproc.
    – user1686
    Apr 7, 2020 at 13:40

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.