Example #1
0
def getSecret(name, version="", region="us-east-1", table="credential-store"):
    '''
    fetch and decrypt the secret called `name`
    '''
    secretStore = Table(table, connection=boto.dynamodb2.connect_to_region(region))
    if version == "":
        # do a consistent fetch of the credential with the highest version
        result_set = [x for x in secretStore.query_2(limit=1, reverse=True, consistent=True, name__eq=name)]
        if not result_set:
            raise ItemNotFound("Item {'name': '%s'} couldn't be found." % name)
        material = result_set[0]
    else:
        material = secretStore.get_item(name=name, version=version)

    kms = boto.kms.connect_to_region(region)
    # Check the HMAC before we decrypt to verify ciphertext integrity
    try:
        kms_response = kms.decrypt(b64decode(material['key']))
    except:
        raise KmsError("Could not decrypt hmac key with KMS")
    key = kms_response['Plaintext'][:32]
    hmac_key = kms_response['Plaintext'][32:]
    hmac = HMAC(hmac_key, msg=b64decode(material['contents']), digestmod=SHA256)
    if hmac.hexdigest() != material['hmac']:
        raise IntegrityError("Computed HMAC on %s does not match stored HMAC" % name)
    dec_ctr = Counter.new(128)
    decryptor = AES.new(key, AES.MODE_CTR, counter=dec_ctr)
    plaintext = decryptor.decrypt(b64decode(material['contents']))
    return plaintext
Example #2
0
def test_decrypt__wrong_encryption_context():
    kms = boto3.client('kms', region_name='us-west-2')

    key = kms.create_key()
    key_id = key['KeyMetadata']['KeyId']

    encryption_context = {'Key': 'Value'}

    response = kms.encrypt(KeyId=key_id,
                           Plaintext=b'my plaintext',
                           EncryptionContext=encryption_context)

    ciphertext = response['CiphertextBlob']
    key_id = response['KeyId']

    with assert_raises(JSONResponseError):
        kms.decrypt(CiphertextBlob=ciphertext)
Example #3
0
def getSecret(name,
              version="",
              region="us-east-1",
              table="credential-store",
              context=None):
    '''
    fetch and decrypt the secret called `name`
    '''
    if not context:
        context = {}
    secretStore = Table(table,
                        connection=boto.dynamodb2.connect_to_region(region))
    if version == "":
        # do a consistent fetch of the credential with the highest version
        result_set = [
            x for x in secretStore.query_2(
                limit=1, reverse=True, consistent=True, name__eq=name)
        ]
        if not result_set:
            raise ItemNotFound("Item {'name': '%s'} couldn't be found." % name)
        material = result_set[0]
    else:
        material = secretStore.get_item(name=name, version=version)

    kms = boto3.client('kms', region_name=region)
    # Check the HMAC before we decrypt to verify ciphertext integrity
    try:
        kms_response = kms.decrypt(CiphertextBlob=b64decode(material['key']),
                                   EncryptionContext=context)
    except boto.kms.exceptions.InvalidCiphertextException:
        if context is None:
            msg = ("Could not decrypt hmac key with KMS. The credential may "
                   "require that an encryption context be provided to decrypt "
                   "it.")
        else:
            msg = ("Could not decrypt hmac key with KMS. The encryption "
                   "context provided may not match the one used when the "
                   "credential was stored.")
        raise KmsError(msg)
    except Exception as e:
        raise KmsError("Decryption error %s" % e)
    key = kms_response['Plaintext'][:32]
    hmac_key = kms_response['Plaintext'][32:]
    hmac = HMAC(hmac_key,
                msg=b64decode(material['contents']),
                digestmod=SHA256)
    if hmac.hexdigest() != material['hmac']:
        raise IntegrityError("Computed HMAC on %s does not match stored HMAC" %
                             name)
    dec_ctr = Counter.new(128)
    decryptor = AES.new(key, AES.MODE_CTR, counter=dec_ctr)
    plaintext = decryptor.decrypt(b64decode(
        material['contents'])).decode("utf-8")
    return plaintext
def getSecret(name,
              version="",
              region="us-east-1",
              table="credential-store",
              context=None):
    '''
    fetch and decrypt the secret called `name`
    '''
    if not context:
        context = {}

    if version == "":
        # do a consistent fetch of the credential with the highest version
        # list all files matching pattern
        pass


#        if not result_set:
#            raise ItemNotFound("Item {'name': '%s'} couldn't be found." % name)
#        material = result_set[0]

    with open("{0}.{1}.json".format(name, version), 'r') as fp:
        material = json.load(fp)

    kms = boto3.client('kms', region_name=region)
    # Check the HMAC before we decrypt to verify ciphertext integrity
    try:
        kms_response = kms.decrypt(CiphertextBlob=b64decode(material['key']),
                                   EncryptionContext=context)
    except InvalidCiphertextException:
        if context is None:
            msg = ("Could not decrypt hmac key with KMS. The credential may "
                   "require that an encryption context be provided to decrypt "
                   "it.")
        else:
            msg = ("Could not decrypt hmac key with KMS. The encryption "
                   "context provided may not match the one used when the "
                   "credential was stored.")
        raise KmsError(msg)
    except Exception as e:
        raise KmsError("Decryption error %s" % e)
    key = kms_response['Plaintext'][:32]
    hmac_key = kms_response['Plaintext'][32:]
    hmac = HMAC(hmac_key,
                msg=b64decode(material['contents']),
                digestmod=SHA256)
    if hmac.hexdigest() != material['hmac']:
        raise IntegrityError("Computed HMAC on %s does not match stored HMAC" %
                             name)
    dec_ctr = Counter.new(128)
    decryptor = AES.new(key, AES.MODE_CTR, counter=dec_ctr)
    plaintext = decryptor.decrypt(b64decode(
        material['contents'])).decode("utf-8")
    return plaintext
Example #5
0
    def run(self,
            conn,
            tmp,
            module_name,
            module_args,
            inject,
            complex_args=None,
            **kwargs):
        args = parse_kv(module_args)
        environment = args.get('environment')
        account_id = args.get('account_id')
        assume_role = args.get('assume_role')

        for name, val in (("environment", environment),
                          ("account_id", account_id), ("assume_role",
                                                       assume_role)):
            if val is None:
                result = dict(failed=True, msg="No {0} specified".format(name))
                return ReturnData(conn=conn, comm_ok=True, result=result)

        source = template.template(self.runner.basedir, environment, inject)

        if '_original_file' in inject:
            source = utils.path_dwim_relative(inject['_original_file'], 'vars',
                                              source, self.runner.basedir)
        else:
            source = utils.path_dwim(self.runner.basedir, source)

        if os.path.exists(source):
            decrypted_data = {}
            data = json.load(open(source))

            with assume(account_id, assume_role):
                kms = boto.kms.connect_to_region('ap-southeast-2')

                for key, val in data.items():
                    data_key = kms.decrypt(base64.b64decode(
                        val['key']))["Plaintext"]
                    content = base64.b64decode(val['content'])
                    counter = Counter.new(128)
                    decryptor = AES.new(data_key[:32],
                                        AES.MODE_CTR,
                                        counter=counter)
                    decrypted_data[key] = decryptor.decrypt(content)

                result = dict(ansible_facts=decrypted_data)
                return ReturnData(conn=conn, comm_ok=True, result=result)
        else:
            result = dict(failed=True,
                          msg="Couldn't find secrets!",
                          file=source)
            return ReturnData(conn=conn, comm_ok=True, result=result)
Example #6
0
def getSecret(name, version="", region="us-east-1",
              table="credential-store", context=None):
    '''
    fetch and decrypt the secret called `name`
    '''
    if not context:
        context = {}
    secretStore = Table(table,
                        connection=boto.dynamodb2.connect_to_region(region))
    if version == "":
        # do a consistent fetch of the credential with the highest version
        result_set = [x for x in secretStore.query_2(limit=1, reverse=True,
                                                     consistent=True,
                                                     name__eq=name)]
        if not result_set:
            raise ItemNotFound("Item {'name': '%s'} couldn't be found." % name)
        material = result_set[0]
    else:
        material = secretStore.get_item(name=name, version=version)

    kms = boto3.client('kms', region_name=region)
    # Check the HMAC before we decrypt to verify ciphertext integrity
    try:
        kms_response = kms.decrypt(CiphertextBlob=b64decode(material['key']), EncryptionContext=context)
    except boto.kms.exceptions.InvalidCiphertextException:
        if context is None:
            msg = ("Could not decrypt hmac key with KMS. The credential may "
                   "require that an encryption context be provided to decrypt "
                   "it.")
        else:
            msg = ("Could not decrypt hmac key with KMS. The encryption "
                   "context provided may not match the one used when the "
                   "credential was stored.")
        raise KmsError(msg)
    except Exception as e:
        raise KmsError("Decryption error %s" % e)
    key = kms_response['Plaintext'][:32]
    hmac_key = kms_response['Plaintext'][32:]
    hmac = HMAC(hmac_key, msg=b64decode(material['contents']),
                digestmod=SHA256)
    if hmac.hexdigest() != material['hmac']:
        raise IntegrityError("Computed HMAC on %s does not match stored HMAC"
                             % name)
    dec_ctr = Counter.new(128)
    decryptor = AES.new(key, AES.MODE_CTR, counter=dec_ctr)
    plaintext = decryptor.decrypt(b64decode(material['contents'])).decode("utf-8")
    return plaintext
def getSecret(name, version="", region="us-east-1",
              table="credential-store", context=None):
    '''
    fetch and decrypt the secret called `name`
    '''
    if not context:
        context = {}

    if version == "":
        # do a consistent fetch of the credential with the highest version
        # list all files matching pattern
        pass
#        if not result_set:
#            raise ItemNotFound("Item {'name': '%s'} couldn't be found." % name)
#        material = result_set[0]

    with open("{0}.{1}.json".format(name, version), 'r') as fp:
        material = json.load(fp)

    kms = boto3.client('kms', region_name=region)
    # Check the HMAC before we decrypt to verify ciphertext integrity
    try:
        kms_response = kms.decrypt(CiphertextBlob=b64decode(material['key']), EncryptionContext=context)
    except InvalidCiphertextException:
        if context is None:
            msg = ("Could not decrypt hmac key with KMS. The credential may "
                   "require that an encryption context be provided to decrypt "
                   "it.")
        else:
            msg = ("Could not decrypt hmac key with KMS. The encryption "
                   "context provided may not match the one used when the "
                   "credential was stored.")
        raise KmsError(msg)
    except Exception as e:
        raise KmsError("Decryption error %s" % e)
    key = kms_response['Plaintext'][:32]
    hmac_key = kms_response['Plaintext'][32:]
    hmac = HMAC(hmac_key, msg=b64decode(material['contents']),
                digestmod=SHA256)
    if hmac.hexdigest() != material['hmac']:
        raise IntegrityError("Computed HMAC on %s does not match stored HMAC"
                             % name)
    dec_ctr = Counter.new(128)
    decryptor = AES.new(key, AES.MODE_CTR, counter=dec_ctr)
    plaintext = decryptor.decrypt(b64decode(material['contents'])).decode("utf-8")
    return plaintext
Example #8
0
def test_decrypt():
    kms = boto3.client('kms', region_name='us-west-2')

    key = kms.create_key()
    key_id = key['KeyMetadata']['KeyId']

    encryption_context = {'Key': 'Value'}

    response = kms.encrypt(KeyId=key_id,
                           Plaintext=b'my plaintext',
                           EncryptionContext=encryption_context)

    ciphertext = response['CiphertextBlob']
    key_id = response['KeyId']

    response = kms.decrypt(CiphertextBlob=ciphertext,
                           EncryptionContext=encryption_context)

    plaintext = response['Plaintext']
    response_key_id = response['KeyId']

    assert response_key_id == key_id
    assert plaintext == b'my plaintext'
Example #9
0
    def run(self, conn, tmp, module_name, module_args, inject, complex_args=None, **kwargs):
        args = parse_kv(module_args)
        environment = args.get('environment')
        account_id = args.get('account_id')
        assume_role = args.get('assume_role')

        for name, val in (("environment", environment), ("account_id", account_id), ("assume_role", assume_role)):
            if val is None:
                result = dict(failed=True, msg="No {0} specified".format(name))
                return ReturnData(conn=conn, comm_ok=True, result=result)

        source = template.template(self.runner.basedir, environment, inject)

        if '_original_file' in inject:
            source = utils.path_dwim_relative(inject['_original_file'], 'vars', source, self.runner.basedir)
        else:
            source = utils.path_dwim(self.runner.basedir, source)

        if os.path.exists(source):
            decrypted_data = {}
            data = json.load(open(source))

            with assume(account_id, assume_role):
                kms = boto.kms.connect_to_region('ap-southeast-2')

                for key, val in data.items():
                    data_key = kms.decrypt(base64.b64decode(val['key']))["Plaintext"]
                    content = base64.b64decode(val['content'])
                    counter = Counter.new(128)
                    decryptor = AES.new(data_key[:32], AES.MODE_CTR, counter=counter)
                    decrypted_data[key] = decryptor.decrypt(content)

                result = dict(ansible_facts=decrypted_data)
                return ReturnData(conn=conn, comm_ok=True, result=result)
        else:
            result = dict(failed=True, msg="Couldn't find secrets!", file=source)
            return ReturnData(conn=conn, comm_ok=True, result=result)