Complex Stuff as Environment Variables

Do not limit yourself with strings

There might be a time where you want to pass something more complex than a string as an enviroment variable to your VM or Docker container or simply you want to set it on your local system. It could be a JSON object or it could be a string with non ASCII characters.

I recently needed to pass a pem certificate as an environment variable, along with many other variables. It was a bit trickier than I thought...

One could argue passing certificate as an env variable may be not the best approach but in my case I had simply no other option.

The solution I settled was to serialize it to base64 string. Function below serializes a python dict as ASCII string so that we can pass as env variable.

import json
import base64

def serialize_dict(d: dict) -> str:
    """
    Encode a dictionary into a base64 string

    :param d: dictionary
    :return: base56 ascii string
    >>> my_dict = {'a': 3, 'b': 4}
    >>> encode_dict_to_b64(my_dict)
    'eyJhIjogMywgImIiOiA0fQ=='
    """

    ascii_byte = json.dumps(d).encode('ascii')
    return base64.b64encode(ascii_byte).decode('ascii')

You can decode base64 encoded string back to python dict again.

def deserialize_dict(base64string) -> dict:
    """
    Deserialize a base64 string back to python dict 

    :param base64string: base64 ascii encoded string
    :return: Python dict
    >>> my_str = 'eyJhIjogMywgImIiOiA0fQ=='
    >>> decode_b64str_to_dict(my_str)
    {'a': 3, 'b': 4}
    """

    try:
        decoded_json = base64.b64decode(base64string.encode('ascii')).decode('ascii')
        return json.loads(decoded_json)
    except Exception as e:
        raise ValueError(f"Failed to decode {base64string} to a python dict: {e}")

Disclaimer: It's been a while since I solved this issue and initially I read about this idea somewhere but cannot remember where it was now. So credits/kudos to that person. Mine is just a quick implementation of that idea.