"use strict";
// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
Object.defineProperty(exports, "__esModule", { value: true });
exports.DynamoDBKeyStorage = void 0;
const types_1 = require("./types");
const client_dynamodb_1 = require("@aws-sdk/client-dynamodb");
const branch_keystore_helpers_1 = require("./branch_keystore_helpers");
const constants_1 = require("./constants");
const material_management_1 = require("@aws-crypto/material-management");
//= aws-encryption-sdk-specification/framework/key-store/dynamodb-key-storage.md#operations
//= type=implication
//# The Dynamodb Key Storage Interface MUST implement the [key storage interface](./key-storage.md#interface).
class DynamoDBKeyStorage {
    constructor({ ddbTableName, logicalKeyStoreName, ddbClient, }) {
        /* Precondition: DDB table name must be a string */
        (0, material_management_1.needs)(typeof ddbTableName === 'string', 'DDB table name must be a string');
        //= aws-encryption-sdk-specification/framework/branch-key-store.md#table-name
        //# The table name of the DynamoDb table that backs this Keystore.
        (0, material_management_1.needs)(ddbTableName, 'DynamoDb table name required');
        (0, material_management_1.needs)(typeof logicalKeyStoreName === 'string', 'Logical Key Store name must be a string');
        (0, material_management_1.needs)(logicalKeyStoreName, 'Logical Key Store name required');
        /* Precondition: DDB client must be a DynamoDBClient */
        (0, material_management_1.needs)(ddbClient instanceof client_dynamodb_1.DynamoDBClient, 'DDB client must be a DynamoDBClient');
        (0, material_management_1.readOnlyProperty)(this, 'ddbTableName', ddbTableName);
        (0, material_management_1.readOnlyProperty)(this, 'ddbClient', ddbClient);
        (0, material_management_1.readOnlyProperty)(this, 'logicalKeyStoreName', logicalKeyStoreName);
        // make this instance immutable
        Object.freeze(this);
    }
    async getEncryptedActiveBranchKey(branchKeyId) {
        //= aws-encryption-sdk-specification/framework/key-store/dynamodb-key-storage.md#getencryptedactivebranchkey
        //# To get the active version for the branch key id from the keystore
        //# this operation MUST call AWS DDB `GetItem`
        //# using the `branch-key-id` as the Partition Key and `"branch:ACTIVE"` value as the Sort Key.
        // get the ddb response item using the partition & sort keys
        const ddbBranchKeyItem = await (0, branch_keystore_helpers_1.getBranchKeyItem)(this, branchKeyId, constants_1.BRANCH_KEY_ACTIVE_TYPE);
        // validate and form the branch key record
        //= aws-encryption-sdk-specification/framework/key-store/dynamodb-key-storage.md#getencryptedactivebranchkey
        //# If the record does not contain the defined fields, this operation MUST fail.
        //= aws-encryption-sdk-specification/framework/key-store/dynamodb-key-storage.md#getencryptedactivebranchkey
        //# The AWS DDB response MUST contain the fields defined in the [branch keystore record format](#record-format).
        const ddbBranchKeyRecord = (0, branch_keystore_helpers_1.validateBranchKeyRecord)(ddbBranchKeyItem);
        // construct an encryption context from the record
        const authenticatedEncryptionContext = (0, branch_keystore_helpers_1.constructAuthenticatedEncryptionContext)(this, ddbBranchKeyRecord);
        const encrypted = new types_1.EncryptedHierarchicalKey(authenticatedEncryptionContext, ddbBranchKeyRecord[constants_1.BRANCH_KEY_FIELD]);
        //= aws-encryption-sdk-specification/framework/key-store/dynamodb-key-storage.md#getencryptedactivebranchkey
        //# The returned EncryptedHierarchicalKey MUST have the same identifier as the input.
        (0, material_management_1.needs)(encrypted.branchKeyId == branchKeyId, 'Unexpected branch key id.');
        //= aws-encryption-sdk-specification/framework/key-store/dynamodb-key-storage.md#getencryptedactivebranchkey
        //# The returned EncryptedHierarchicalKey MUST have a type of ActiveHierarchicalSymmetricVersion.
        (0, material_management_1.needs)(encrypted.type instanceof types_1.ActiveHierarchicalSymmetricVersion, 'Unexpected type. Not an active record.');
        return encrypted;
    }
    async getEncryptedBranchKeyVersion(branchKeyId, branchKeyVersion) {
        //= aws-encryption-sdk-specification/framework/key-store/dynamodb-key-storage.md#getencryptedbranchkeyversion
        //# To get a branch key from the keystore this operation MUST call AWS DDB `GetItem`
        //# using the `branch-key-id` as the Partition Key and "branch:version:" + `branchKeyVersion` value as the Sort Key.
        // get the ddb response item using the partition & sort keys
        const ddbBranchKeyItem = await (0, branch_keystore_helpers_1.getBranchKeyItem)(this, branchKeyId, constants_1.BRANCH_KEY_TYPE_PREFIX + branchKeyVersion);
        //= aws-encryption-sdk-specification/framework/key-store/dynamodb-key-storage.md#getencryptedbranchkeyversion
        //# If the record does not contain the defined fields, this operation MUST fail.
        //= aws-encryption-sdk-specification/framework/key-store/dynamodb-key-storage.md#getencryptedbranchkeyversion
        //# The AWS DDB response MUST contain the fields defined in the [branch keystore record format](#record-format).
        // validate and form the branch key record
        const ddbBranchKeyRecord = (0, branch_keystore_helpers_1.validateBranchKeyRecord)(ddbBranchKeyItem);
        // construct an encryption context from the record
        const authenticatedEncryptionContext = (0, branch_keystore_helpers_1.constructAuthenticatedEncryptionContext)(this, ddbBranchKeyRecord);
        const encrypted = new types_1.EncryptedHierarchicalKey(authenticatedEncryptionContext, ddbBranchKeyRecord[constants_1.BRANCH_KEY_FIELD]);
        //= aws-encryption-sdk-specification/framework/key-store/dynamodb-key-storage.md#getencryptedbranchkeyversion
        //# The returned EncryptedHierarchicalKey MUST have the same identifier as the input.
        (0, material_management_1.needs)(encrypted.branchKeyId == branchKeyId, 'Unexpected branch key id. Expected ${branchKeyId}, found ${encrypted.branchKeyId}');
        //= aws-encryption-sdk-specification/framework/key-store/dynamodb-key-storage.md#getencryptedbranchkeyversion
        //# The returned EncryptedHierarchicalKey MUST have the same version as the input.
        (0, material_management_1.needs)(encrypted.type.version == branchKeyVersion, 'Unexpected branch key version.');
        //= aws-encryption-sdk-specification/framework/key-store/dynamodb-key-storage.md#getencryptedbranchkeyversion
        //# The returned EncryptedHierarchicalKey MUST have a type of HierarchicalSymmetricVersion.
        (0, material_management_1.needs)(encrypted.type instanceof types_1.HierarchicalSymmetricVersion, 'Unexpected type. Not an version record.');
        return encrypted;
    }
    getKeyStorageInfo() {
        return {
            name: this.ddbTableName,
            logicalName: this.logicalKeyStoreName,
        };
    }
}
exports.DynamoDBKeyStorage = DynamoDBKeyStorage;
(0, material_management_1.immutableClass)(DynamoDBKeyStorage);
// This is a limited release for JS only.
// The full Key Store operations are available
// in the AWS Cryptographic Material Providers library
// in various languages (Java, .Net, Python, Rust...)
//= aws-encryption-sdk-specification/framework/key-store/dynamodb-key-storage.md#writenewencryptedbranchkey
//= type=exception
//# To add the branch keys and a beacon key to the keystore the
//# operation MUST call [Amazon DynamoDB API TransactWriteItems](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_TransactWriteItems.html).
//# The call to Amazon DynamoDB TransactWriteItems MUST use the configured Amazon DynamoDB Client to make the call.
//# The operation MUST call Amazon DynamoDB TransactWriteItems with a request constructed as follows:
//= aws-encryption-sdk-specification/framework/key-store/dynamodb-key-storage.md#writenewencryptedbranchkey
//= type=exception
//# If DDB TransactWriteItems is successful, this operation MUST return a successful response containing no additional data.
//# Otherwise, this operation MUST yield an error.
//= aws-encryption-sdk-specification/framework/key-store/dynamodb-key-storage.md#writenewencryptedbranchkeyversion
//= type=exception
//# To add the new branch key to the keystore,
//# the operation MUST call [Amazon DynamoDB API TransactWriteItems](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_TransactWriteItems.html).
//# The call to Amazon DynamoDB TransactWriteItems MUST use the configured Amazon DynamoDB Client to make the call.
//# The operation MUST call Amazon DynamoDB TransactWriteItems with a request constructed as follows:
//= aws-encryption-sdk-specification/framework/key-store/dynamodb-key-storage.md#getencryptedbeaconkey
//= type=exception
//# To get a branch key from the keystore this operation MUST call AWS DDB `GetItem`
//# using the `branch-key-id` as the Partition Key and "beacon:ACTIVE" value as the Sort Key.
//# The AWS DDB response MUST contain the fields defined in the [branch keystore record format](#record-format).
//# The returned EncryptedHierarchicalKey MUST have the same identifier as the input.
//# The returned EncryptedHierarchicalKey MUST have a type of ActiveHierarchicalSymmetricBeacon.
//# If the record does not contain the defined fields, this operation MUST fail.
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZHluYW1vZGJfa2V5X3N0b3JhZ2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvZHluYW1vZGJfa2V5X3N0b3JhZ2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLG9FQUFvRTtBQUNwRSxzQ0FBc0M7OztBQUV0QyxtQ0FLZ0I7QUFDaEIsOERBQXlEO0FBQ3pELHVFQUlrQztBQUVsQywyQ0FJb0I7QUFDcEIseUVBSXdDO0FBY3hDLDJGQUEyRjtBQUMzRixvQkFBb0I7QUFDcEIsOEdBQThHO0FBQzlHLE1BQWEsa0JBQWtCO0lBSzdCLFlBQVksRUFDVixZQUFZLEVBQ1osbUJBQW1CLEVBQ25CLFNBQVMsR0FDZTtRQUN4QixtREFBbUQ7UUFDbkQsSUFBQSwyQkFBSyxFQUFDLE9BQU8sWUFBWSxLQUFLLFFBQVEsRUFBRSxpQ0FBaUMsQ0FBQyxDQUFBO1FBQzFFLDZFQUE2RTtRQUM3RSxrRUFBa0U7UUFDbEUsSUFBQSwyQkFBSyxFQUFDLFlBQVksRUFBRSw4QkFBOEIsQ0FBQyxDQUFBO1FBRW5ELElBQUEsMkJBQUssRUFDSCxPQUFPLG1CQUFtQixLQUFLLFFBQVEsRUFDdkMseUNBQXlDLENBQzFDLENBQUE7UUFDRCxJQUFBLDJCQUFLLEVBQUMsbUJBQW1CLEVBQUUsaUNBQWlDLENBQUMsQ0FBQTtRQUM3RCx1REFBdUQ7UUFDdkQsSUFBQSwyQkFBSyxFQUNILFNBQVMsWUFBWSxnQ0FBYyxFQUNuQyxxQ0FBcUMsQ0FDdEMsQ0FBQTtRQUVELElBQUEsc0NBQWdCLEVBQUMsSUFBSSxFQUFFLGNBQWMsRUFBRSxZQUFZLENBQUMsQ0FBQTtRQUNwRCxJQUFBLHNDQUFnQixFQUFDLElBQUksRUFBRSxXQUFXLEVBQUUsU0FBUyxDQUFDLENBQUE7UUFDOUMsSUFBQSxzQ0FBZ0IsRUFBQyxJQUFJLEVBQUUscUJBQXFCLEVBQUUsbUJBQW1CLENBQUMsQ0FBQTtRQUVsRSwrQkFBK0I7UUFDL0IsTUFBTSxDQUFDLE1BQU0sQ0FBQyxJQUFJ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