Reputation: 23
Inside of AWS Lambda functions I have some libs that look for sensitive information in the os environment. I can encrypt the env vars using KMS, but I've found myself having to overwrite the encrypted env vars in the lambda handler module -- is this a vulnerability? Eg.
# lambda_handler.py
encrypted_env_var = os.environ["SECRET_KEY"]
decrypted_env_var = decrypt(encrypted_env_var)
os.environ["SECRET_KEY"] = decrypted_env_var
def lambda_function(event, context):
... libs get and use SECRET_KEY ...
I understand that encrypting them covers you eg. when using awscli, but could setting this in the container be a vulnerability? As I understand from here, the container may not be destroyed immediately.
Furthermore, in the suggested decryption code snippet that AWS gives you (in the lambda dashboard), the comments caught my attention:
# lambda_handler.py
ENCRYPTED = os.environ['SECRET_KEY']
# Decrypt code should run once and variables stored outside of the function
# handler so that these are decrypted once per container
DECRYPTED = boto3.client('kms').decrypt(CiphertextBlob=b64decode(ENCRYPTED))['Plaintext']
def lambda_handler(event, context):
# handle the event here
Would it be sufficient (albeit messy) to just unset the relevant variables at the end of the function?
Thanks
Upvotes: 2
Views: 977
Reputation: 179054
the container may not be destroyed immediately.
The container almost certainly will not be destroyed immediately... but that isn't bad.
Containers can persist for minutes to hours, and are reused -- this is why Lambda functions are usually able to execute so quickly, because under ideal conditions, the majority of your function invocations will find an idle container that they can reuse.
However... containers are reused only by one single version of one single function of yours. Nobody else, and no other functions or different versions of the same function, even from the same account, reuse your containers. Only the function version that caused the container to be created.
The infrastructure destroys containers that are no longer needed, and it does this based on the traffic your function is seeing (or not seeing). Anecdotal observations suggest that all idle containers will disappear completely after 10-15 minutes if you completely stop invoking your function, but this is not documented and may vary.
the comments caught my attention
The comments are saying that you should store the decrypted variables outside the handler function so they are in a global scope -- it would be very inefficient to call the KMS API to decrypt the variables with each invocation of the function. You could conceivably do that, but you should store the encrypted environment variables under a different name, and then set the decrypted values into the names your code expects.
Would it be sufficient (albeit messy) to just unset the relevant variables at the end of the function?
That won't work, unless you store the original encrypted values elsewhere (such as using different initial environment variable names), because your example code would overwrite the encrypted values, and the next time your function runs in that container, it would fail to decrypt those unset values.
The point of encrypted environment variables is that while they are stored at rest by the Lambda infrastructure, they are encrypted. Once they are in the memory space of your container, there is not a meaningful chance of them being compromised, since (as noted above) those containers are exclusive to your function.
Upvotes: 3