Search code examples
shposix

For every environment variable, create an environment variable with the base64 encoded value


For certain environment variables (*_PASSWORD), I want to create a second environment variable containing a base64 encoded copy of that variable (*PASSWORD_B64). I have a working solution for bash, but I would like to have a solution based on POSIX, so it runs in sh.

while read -r line; do
  CMD="${line}_B64=$(echo -n "${!line}" | base64)";
  export "$CMD";
done <<< $(env | grep -E "PASSWORD=" | sed 's/=.*//g')

I think there are two issues here:

  1. Indirect parameter expansion ${!line}: Which I could replace with eval.
  2. The while loop with <<<: this was the only while loop I could get it to work with, since the other ways, it would run it in a subshell and the environment variables wouldn't be visible in the "parent shell".

Is there a way to get it to run in sh?

Edit: Here's an example of what the command above is doing:

$ env
TEST1_PASSWORD=Hello
TEST2_PASSWORD=World
$ # run command from above
$ env
TEST1_PASSWORD=Hello
TEST2_PASSWORD=World
TEST1_PASSWORD_B64=SGVsbG8=
TEST2_PASSWORD_B64=V29ybGQ=

Solution

  • Overall, in POSIX, you jump straight into POSIX awk. Your code requires base64 to be installed.

    The following runs an awk shell that filters the env and calls shell with base64 to output base64 encoded variable. The awk script outputs a export var_B64=base64_of_var for each environment variable. The result is then evaluated.

    Also, at least GNU implementation of base64 from coreutils, splits long lines. Use base64 -w0.

    export BLA_PASSWORD='hello * world'
    eval "$(awk 'BEGIN{
      for (i in ENVIRON) {
        if (i ~ /^[a-zA-Z_][a-zA-Z0-9_]*PASSWORD$/) {
          printf "export " i "_B64=";
          system("echo \"$"i"\" | base64 -w0");
          print;
        }
      }
    }' /dev/null)"
    echo "$BLA_PASSWORD_B64"
    

    If you want it to be truly posix, write the base64 in awk.