Source code for stacker.lookups.handlers.kms

from __future__ import print_function
from __future__ import division
from __future__ import absolute_import
import codecs
import sys
from stacker.session_cache import get_session

from . import LookupHandler
from ...util import read_value_from_path

TYPE_NAME = "kms"


[docs]class KmsLookup(LookupHandler):
[docs] @classmethod def handle(cls, value, **kwargs): """Decrypt the specified value with a master key in KMS. kmssimple field types should be in the following format: [<region>@]<base64 encrypted value> Note: The region is optional, and defaults to the environment's `AWS_DEFAULT_REGION` if not specified. For example: # We use the aws cli to get the encrypted value for the string # "PASSWORD" using the master key called "myStackerKey" in # us-east-1 $ aws --region us-east-1 kms encrypt --key-id alias/myStackerKey \ --plaintext "PASSWORD" --output text --query CiphertextBlob CiD6bC8t2Y<...encrypted blob...> # In stacker we would reference the encrypted value like: conf_key: ${kms us-east-1@CiD6bC8t2Y<...encrypted blob...>} You can optionally store the encrypted value in a file, ie: kms_value.txt us-east-1@CiD6bC8t2Y<...encrypted blob...> and reference it within stacker (NOTE: the path should be relative to the stacker config file): conf_key: ${kms file://kms_value.txt} # Both of the above would resolve to conf_key: PASSWORD """ value = read_value_from_path(value) region = None if "@" in value: region, value = value.split("@", 1) kms = get_session(region).client('kms') # encode str value as an utf-8 bytestring for use with codecs.decode. value = value.encode('utf-8') # get raw but still encrypted value from base64 version. decoded = codecs.decode(value, 'base64') # check python version in your system python3_or_later = sys.version_info[0] >= 3 # decrypt and return the plain text raw value. if python3_or_later: return kms.decrypt(CiphertextBlob=decoded)["Plaintext"]\ .decode('utf-8') else: return kms.decrypt(CiphertextBlob=decoded)["Plaintext"]