UNPKG

@renovosolutions/cdk-aspects-library-encryption-enforcement

Version:
140 lines 17.5 kB
"use strict"; var _a, _b, _c; Object.defineProperty(exports, "__esModule", { value: true }); exports.EncryptionEnforcement = exports.RDSEncryptionEnforcementAspect = exports.EFSEncryptionEnforcementAspect = void 0; const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti"); const aws_cdk_lib_1 = require("aws-cdk-lib"); ; /** * Common base class for all aspects in this module. * * This exists to define the common properties and methods for all encryption enforcement aspects. * Right now, that's just exposing the `excludeResources` property. * * @abstract * @class EncryptionEnforcementAspect * @implements {IAspect} */ class EncryptionEnforcementAspect { /** * Constructs a new EncryptionEnforcementAspect. * * @param props - Optional properties to configure the aspect. */ constructor(props) { this.excludeResources = props?.excludeResources ?? []; } /** * Dummy visit method that must be overridden by subclasses. * @param _node - The construct to visit. */ visit(_node) { } } /** * An aspect that enforces encryption on all EFS FileSystems in the stack. */ class EFSEncryptionEnforcementAspect extends EncryptionEnforcementAspect { /** * Visits each construct in the stack and enforces encryption on EFS FileSystems. * * @param node - The construct to visit. */ visit(node) { // Check if this is an EFS FileSystem if (node instanceof aws_cdk_lib_1.CfnResource && node.cfnResourceType == 'AWS::EFS::FileSystem') { // Get the logical ID of the parent construct, so we can properly check for exclusions const parent = node.node.scope.node.id; /** * If it's an L1 resource, the first condition is relevant. * If it's an L2 resource, the second condition is the one. * We do this so both L1 and L2 constructs can be excluded by ID. */ if (this.excludeResources?.includes(node.node.id) || this.excludeResources?.includes(parent)) { return; // Skip this resource } // Check if the FileSystem is encrypted const encrypted = node.encrypted; if (!encrypted || encrypted.toString() !== 'true') { // If not encrypted, annotate an error aws_cdk_lib_1.Annotations.of(node).addError('EFS FileSystem must be encrypted. Please set the \'encrypted\' property to true.'); } } } } exports.EFSEncryptionEnforcementAspect = EFSEncryptionEnforcementAspect; _a = JSII_RTTI_SYMBOL_1; EFSEncryptionEnforcementAspect[_a] = { fqn: "@renovosolutions/cdk-aspects-library-encryption-enforcement.EFSEncryptionEnforcementAspect", version: "0.0.1" }; /** * An aspect that enforces encryption on all RDS databases in the stack. * Covers both single instances and clusters. */ class RDSEncryptionEnforcementAspect extends EncryptionEnforcementAspect { /** * Visits each construct in the stack and enforces encryption on RDS databases. * * @param node - The construct to visit. */ visit(node) { // Check if this is an RDS DBInstance or DBCluster if (node instanceof aws_cdk_lib_1.CfnResource && ['AWS::RDS::DBInstance', 'AWS::RDS::DBCluster'].includes(node.cfnResourceType)) { // Get the logical ID of the parent construct, so we can properly check for exclusions const parent = node.node.scope.node.id; /** * If it's an L1 resource, the first condition is relevant. * If it's an L2 resource, the second condition is the one. * We do this so both L1 and L2 constructs can be excluded by ID. */ if (this.excludeResources?.includes(node.node.id) || this.excludeResources?.includes(parent)) { return; // Skip this resource } if (node.dbClusterIdentifier !== undefined || node.sourceDbClusterIdentifier !== undefined) { /** * If this is a DBInstance that is part of a DBCluster, we skip it. * The L2 ClusterInstance class does not have `storageEncrypted` property, * it just inherits from the parent DBCluster. We have to skip it or we'd * tell the user to change a property that doesn't exist. * The L1 CfnDBInstance class does have `storageEncrypted`, but we still skip it * because Cfn will not allow it to be set to a conflicting value with the parent DBCluster. */ return; } /** * Check if the database is encrypted * This works even if it's actually a DBCluster. */ const encrypted = node.storageEncrypted; if (!encrypted || encrypted.toString() !== 'true') { // If not encrypted, annotate an error aws_cdk_lib_1.Annotations.of(node).addError('RDS database must have storage encryption enabled. Please set the \'storageEncrypted\' property to true.'); } } } } exports.RDSEncryptionEnforcementAspect = RDSEncryptionEnforcementAspect; _b = JSII_RTTI_SYMBOL_1; RDSEncryptionEnforcementAspect[_b] = { fqn: "@renovosolutions/cdk-aspects-library-encryption-enforcement.RDSEncryptionEnforcementAspect", version: "0.0.1" }; /** * An convenience class with a static function that adds all of the aspects in this module. * It's only a class because jsii skips standalone functions. */ class EncryptionEnforcement { /** * Adds all encryption enforcement aspects to the given scope. * * This is a convenience method to add all aspects in this module at once. * It can be used in the `main` function of your CDK app or in a stack constructor. * * @param scope - The scope to add the aspects to. * @param props - Optional properties to configure the aspects. * @returns void */ static addAllAspects(scope, props) { aws_cdk_lib_1.Aspects.of(scope).add(new EFSEncryptionEnforcementAspect(props)); aws_cdk_lib_1.Aspects.of(scope).add(new RDSEncryptionEnforcementAspect(props)); } } exports.EncryptionEnforcement = EncryptionEnforcement; _c = JSII_RTTI_SYMBOL_1; EncryptionEnforcement[_c] = { fqn: "@renovosolutions/cdk-aspects-library-encryption-enforcement.EncryptionEnforcement", version: "0.0.1" }; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFBQSw2Q0FPcUI7QUFnQnBCLENBQUM7QUFFRjs7Ozs7Ozs7O0dBU0c7QUFDSCxNQUFlLDJCQUEyQjtJQVd4Qzs7OztPQUlHO0lBQ0gsWUFBWSxLQUF3QztRQUNsRCxJQUFJLENBQUMsZ0JBQWdCLEdBQUcsS0FBSyxFQUFFLGdCQUFnQixJQUFJLEVBQUUsQ0FBQztJQUN4RCxDQUFDO0lBRUQ7OztPQUdHO0lBQ0gsS0FBSyxDQUFDLEtBQWlCLElBQVMsQ0FBQztDQUNsQztBQUVEOztHQUVHO0FBQ0gsTUFBYSw4QkFBK0IsU0FBUSwyQkFBMkI7SUFDN0U7Ozs7T0FJRztJQUNILEtBQUssQ0FBQyxJQUFnQjtRQUNwQixxQ0FBcUM7UUFDckMsSUFBSSxJQUFJLFlBQVkseUJBQVcsSUFBSSxJQUFJLENBQUMsZUFBZSxJQUFJLHNCQUFzQixFQUFFLENBQUM7WUFDbEYsc0ZBQXNGO1lBQ3RGLE1BQU0sTUFBTSxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsS0FBTSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUM7WUFFeEM7Ozs7ZUFJRztZQUNILElBQUksSUFBSSxDQUFDLGdCQUFnQixFQUFFLFFBQVEsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxJQUFJLElBQUksQ0FBQyxnQkFBZ0IsRUFBRSxRQUFRLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQztnQkFDN0YsT0FBTyxDQUFDLHFCQUFxQjtZQUMvQixDQUFDO1lBRUQsdUNBQXVDO1lBQ3ZDLE1BQU0sU0FBUyxHQUFJLElBQTBCLENBQUMsU0FBUyxDQUFDO1lBQ3hELElBQUksQ0FBQyxTQUFTLElBQUksU0FBUyxDQUFDLFFBQVEsRUFBRSxLQUFLLE1BQU0sRUFBRSxDQUFDO2dCQUNsRCxzQ0FBc0M7Z0JBQ3RDLHlCQUFXLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxDQUFDLFFBQVEsQ0FDM0Isa0ZBQWtGLENBQUMsQ0FBQztZQUN4RixDQUFDO1FBQ0gsQ0FBQztJQUNILENBQUM7O0FBN0JILHdFQThCQzs7O0FBRUQ7OztHQUdHO0FBQ0gsTUFBYSw4QkFBK0IsU0FBUSwyQkFBMkI7SUFDN0U7Ozs7T0FJRztJQUNILEtBQUssQ0FBQyxJQUFnQjtRQUNwQixrREFBa0Q7UUFDbEQsSUFBSSxJQUFJLFlBQVkseUJBQVcsSUFBSSxDQUFDLHNCQUFzQixFQUFFLHFCQUFxQixDQUFDLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxlQUFlLENBQUMsRUFBRSxDQUFDO1lBQ2xILHNGQUFzRjtZQUN0RixNQUFNLE1BQU0sR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLEtBQU0sQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDO1lBRXhDOzs7O2VBSUc7WUFDSCxJQUFJLElBQUksQ0FBQyxnQkFBZ0IsRUFBRSxRQUFRLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsSUFBSSxJQUFJLENBQUMsZ0JBQWdCLEVBQUUsUUFBUSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUM7Z0JBQzdGLE9BQU8sQ0FBQyxxQkFBcUI7WUFDL0IsQ0FBQztZQUVELElBQUssSUFBMEIsQ0FBQyxtQkFBbUIsS0FBSyxTQUFTO2dCQUM5RCxJQUEwQixDQUFDLHlCQUF5QixLQUFLLFNBQVMsRUFBRSxDQUFDO2dCQUN0RTs7Ozs7OzttQkFPRztnQkFDSCxPQUFPO1lBQ1QsQ0FBQztZQUVEOzs7ZUFHRztZQUNILE1BQU0sU0FBUyxHQUFJLElBQTBCLENBQUMsZ0JBQWdCLENBQUM7WUFDL0QsSUFBSSxDQUFDLFNBQVMsSUFBSSxTQUFTLENBQUMsUUFBUSxFQUFFLEtBQUssTUFBTSxFQUFFLENBQUM7Z0JBQ2xELHNDQUFzQztnQkFDdEMseUJBQVcsQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLENBQUMsUUFBUSxDQUMzQiwwR0FBMEcsQ0FBQyxDQUFDO1lBQ2hILENBQUM7UUFDSCxDQUFDO0lBQ0gsQ0FBQzs7QUE3Q0gsd0VBOENDOzs7QUFFRDs7O0dBR0c7QUFDSCxNQUFhLHFCQUFxQjtJQUNsQzs7Ozs7Ozs7O09BU0c7SUFDTSxNQUFNLENBQUMsYUFBYSxDQUFDLEtBQWlCLEVBQUUsS0FBd0M7UUFDckYscUJBQU8sQ0FBQyxFQUFFLENBQUMsS0FBSyxDQUFDLENBQUMsR0FBRyxDQUFDLElBQUksOEJBQThCLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQztRQUNqRSxxQkFBTyxDQUFDLEVBQUUsQ0FBQyxLQUFLLENBQUMsQ0FBQyxHQUFHLENBQUMsSUFBSSw4QkFBOEIsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDO0lBQ25FLENBQUM7O0FBZEgsc0RBZUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuICBBc3BlY3RzLFxuICBJQXNwZWN0LFxuICBDZm5SZXNvdXJjZSxcbiAgQW5ub3RhdGlvbnMsXG4gIGF3c19lZnMgYXMgZWZzLFxuICBhd3NfcmRzIGFzIHJkcyxcbn0gZnJvbSAnYXdzLWNkay1saWInO1xuaW1wb3J0IHsgSUNvbnN0cnVjdCB9IGZyb20gJ2NvbnN0cnVjdHMnO1xuXG4vKipcbiAqIENvbW1vbiBwcm9wZXJ0aWVzIGZvciBhbGwgYXNwZWN0cyBpbiB0aGlzIG1vZHVsZS5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBFbmNyeXB0aW9uRW5mb3JjZW1lbnRBc3BlY3RQcm9wcyB7XG4gIC8qKlxuICAgKiBUaGUgcmVzb3VyY2VzIHRvIGV4Y2x1ZGUgZnJvbSBlbmZvcmNlbWVudC5cbiAgICpcbiAgICogVXNlIGEgcmVzb3VyY2UncyBJRCB0byBleGNsdWRlIGEgc3BlY2lmaWMgcmVzb3VyY2UuXG4gICAqIFN1cHBvcnRzIGJvdGggQ2ZuUmVzb3VyY2UgYW5kIEwyIGNvbnN0cnVjdCBJRHMuXG4gICAqXG4gICAqIEBkZWZhdWx0IFtdXG4gICAqL1xuICByZWFkb25seSBleGNsdWRlUmVzb3VyY2VzPzogc3RyaW5nW107XG59O1xuXG4vKipcbiAqIENvbW1vbiBiYXNlIGNsYXNzIGZvciBhbGwgYXNwZWN0cyBpbiB0aGlzIG1vZHVsZS5cbiAqXG4gKiBUaGlzIGV4aXN0cyB0byBkZWZpbmUgdGhlIGNvbW1vbiBwcm9wZXJ0aWVzIGFuZCBtZXRob2RzIGZvciBhbGwgZW5jcnlwdGlvbiBlbmZvcmNlbWVudCBhc3BlY3RzLlxuICogUmlnaHQgbm93LCB0aGF0J3MganVzdCBleHBvc2luZyB0aGUgYGV4Y2x1ZGVSZXNvdXJjZXNgIHByb3BlcnR5LlxuICpcbiAqIEBhYnN0cmFjdFxuICogQGNsYXNzIEVuY3J5cHRpb25FbmZvcmNlbWVudEFzcGVjdFxuICogQGltcGxlbWVudHMge0lBc3BlY3R9XG4gKi9cbmFic3RyYWN0IGNsYXNzIEVuY3J5cHRpb25FbmZvcmNlbWVudEFzcGVjdCBpbXBsZW1lbnRzIElBc3BlY3Qge1xuICAvKipcbiAgICogVGhlIHJlc291cmNlcyB0byBleGNsdWRlIGZyb20gZW5mb3JjZW1lbnQuXG4gICAqXG4gICAqIFVzZSBhIHJlc291cmNlJ3MgSUQgdG8gZXhjbHVkZSBhIHNwZWNpZmljIHJlc291cmNlLlxuICAgKiBTdXBwb3J0cyBib3RoIENmblJlc291cmNlIGFuZCBMMiBjb25zdHJ1Y3QgSURzLlxuICAgKlxuICAgKiBAZGVmYXVsdCBbXVxuICAgKi9cbiAgcHVibGljIHJlYWRvbmx5IGV4Y2x1ZGVSZXNvdXJjZXM6IHN0cmluZ1tdO1xuXG4gIC8qKlxuICAgKiBDb25zdHJ1Y3RzIGEgbmV3IEVuY3J5cHRpb25FbmZvcmNlbWVudEFzcGVjdC5cbiAgICpcbiAgICogQHBhcmFtIHByb3BzIC0gT3B0aW9uYWwgcHJvcGVydGllcyB0byBjb25maWd1cmUgdGhlIGFzcGVjdC5cbiAgICovXG4gIGNvbnN0cnVjdG9yKHByb3BzPzogRW5jcnlwdGlvbkVuZm9yY2VtZW50QXNwZWN0UHJvcHMpIHtcbiAgICB0aGlzLmV4Y2x1ZGVSZXNvdXJjZXMgPSBwcm9wcz8uZXhjbHVkZVJlc291cmNlcyA/PyBbXTtcbiAgfVxuXG4gIC8qKlxuICAgKiBEdW1teSB2aXNpdCBtZXRob2QgdGhhdCBtdXN0IGJlIG92ZXJyaWRkZW4gYnkgc3ViY2xhc3Nlcy5cbiAgICogQHBhcmFtIF9ub2RlIC0gVGhlIGNvbnN0cnVjdCB0byB2aXNpdC5cbiAgICovXG4gIHZpc2l0KF9ub2RlOiBJQ29uc3RydWN0KTogdm9pZCB7fVxufVxuXG4vKipcbiAqIEFuIGFzcGVjdCB0aGF0IGVuZm9yY2VzIGVuY3J5cHRpb24gb24gYWxsIEVGUyBGaWxlU3lzdGVtcyBpbiB0aGUgc3RhY2suXG4gKi9cbmV4cG9ydCBjbGFzcyBFRlNFbmNyeXB0aW9uRW5mb3JjZW1lbnRBc3BlY3QgZXh0ZW5kcyBFbmNyeXB0aW9uRW5mb3JjZW1lbnRBc3BlY3Qge1xuICAvKipcbiAgICogVmlzaXRzIGVhY2ggY29uc3RydWN0IGluIHRoZSBzdGFjayBhbmQgZW5mb3JjZXMgZW5jcnlwdGlvbiBvbiBFRlMgRmlsZVN5c3RlbXMuXG4gICAqXG4gICAqIEBwYXJhbSBub2RlIC0gVGhlIGNvbnN0cnVjdCB0byB2aXNpdC5cbiAgICovXG4gIHZpc2l0KG5vZGU6IElDb25zdHJ1Y3QpIHtcbiAgICAvLyBDaGVjayBpZiB0aGlzIGlzIGFuIEVGUyBGaWxlU3lzdGVtXG4gICAgaWYgKG5vZGUgaW5zdGFuY2VvZiBDZm5SZXNvdXJjZSAmJiBub2RlLmNmblJlc291cmNlVHlwZSA9PSAnQVdTOjpFRlM6OkZpbGVTeXN0ZW0nKSB7XG4gICAgICAvLyBHZXQgdGhlIGxvZ2ljYWwgSUQgb2YgdGhlIHBhcmVudCBjb25zdHJ1Y3QsIHNvIHdlIGNhbiBwcm9wZXJseSBjaGVjayBmb3IgZXhjbHVzaW9uc1xuICAgICAgY29uc3QgcGFyZW50ID0gbm9kZS5ub2RlLnNjb3BlIS5ub2RlLmlkO1xuXG4gICAgICAvKipcbiAgICAgICAqIElmIGl0J3MgYW4gTDEgcmVzb3VyY2UsIHRoZSBmaXJzdCBjb25kaXRpb24gaXMgcmVsZXZhbnQuXG4gICAgICAgKiBJZiBpdCdzIGFuIEwyIHJlc291cmNlLCB0aGUgc2Vjb25kIGNvbmRpdGlvbiBpcyB0aGUgb25lLlxuICAgICAgICogV2UgZG8gdGhpcyBzbyBib3RoIEwxIGFuZCBMMiBjb25zdHJ1Y3RzIGNhbiBiZSBleGNsdWRlZCBieSBJRC5cbiAgICAgICAqL1xuICAgICAgaWYgKHRoaXMuZXhjbHVkZVJlc291cmNlcz8uaW5jbHVkZXMobm9kZS5ub2RlLmlkKSB8fCB0aGlzLmV4Y2x1ZGVSZXNvdXJjZXM/LmluY2x1ZGVzKHBhcmVudCkpIHtcbiAgICAgICAgcmV0dXJuOyAvLyBTa2lwIHRoaXMgcmVzb3VyY2VcbiAgICAgIH1cblxuICAgICAgLy8gQ2hlY2sgaWYgdGhlIEZpbGVTeXN0ZW0gaXMgZW5jcnlwdGVkXG4gICAgICBjb25zdCBlbmNyeXB0ZWQgPSAobm9kZSBhcyBlZnMuQ2ZuRmlsZVN5c3RlbSkuZW5jcnlwdGVkO1xuICAgICAgaWYgKCFlbmNyeXB0ZWQgfHwgZW5jcnlwdGVkLnRvU3RyaW5nKCkgIT09ICd0cnVlJykge1xuICAgICAgICAvLyBJZiBub3QgZW5jcnlwdGVkLCBhbm5vdGF0ZSBhbiBlcnJvclxuICAgICAgICBBbm5vdGF0aW9ucy5vZihub2RlKS5hZGRFcnJvcihcbiAgICAgICAgICAnRUZTIEZpbGVTeXN0ZW0gbXVzdCBiZSBlbmNyeXB0ZWQuIFBsZWFzZSBzZXQgdGhlIFxcJ2VuY3J5cHRlZFxcJyBwcm9wZXJ0eSB0byB0cnVlLicpO1xuICAgICAgfVxuICAgIH1cbiAgfVxufVxuXG4vKipcbiAqIEFuIGFzcGVjdCB0aGF0IGVuZm9yY2VzIGVuY3J5cHRpb24gb24gYWxsIFJEUyBkYXRhYmFzZXMgaW4gdGhlIHN0YWNrLlxuICogQ292ZXJzIGJvdGggc2luZ2xlIGluc3RhbmNlcyBhbmQgY2x1c3RlcnMuXG4gKi9cbmV4cG9ydCBjbGFzcyBSRFNFbmNyeXB0aW9uRW5mb3JjZW1lbnRBc3BlY3QgZXh0ZW5kcyBFbmNyeXB0aW9uRW5mb3JjZW1lbnRBc3BlY3Qge1xuICAvKipcbiAgICogVmlzaXRzIGVhY2ggY29uc3RydWN0IGluIHRoZSBzdGFjayBhbmQgZW5mb3JjZXMgZW5jcnlwdGlvbiBvbiBSRFMgZGF0YWJhc2VzLlxuICAgKlxuICAgKiBAcGFyYW0gbm9kZSAtIFRoZSBjb25zdHJ1Y3QgdG8gdmlzaXQuXG4gICAqL1xuICB2aXNpdChub2RlOiBJQ29uc3RydWN0KSB7XG4gICAgLy8gQ2hlY2sgaWYgdGhpcyBpcyBhbiBSRFMgREJJbnN0YW5jZSBvciBEQkNsdXN0ZXJcbiAgICBpZiAobm9kZSBpbnN0YW5jZW9mIENmblJlc291cmNlICYmIFsnQVdTOjpSRFM6OkRCSW5zdGFuY2UnLCAnQVdTOjpSRFM6OkRCQ2x1c3RlciddLmluY2x1ZGVzKG5vZGUuY2ZuUmVzb3VyY2VUeXBlKSkge1xuICAgICAgLy8gR2V0IHRoZSBsb2dpY2FsIElEIG9mIHRoZSBwYXJlbnQgY29uc3RydWN0LCBzbyB3ZSBjYW4gcHJvcGVybHkgY2hlY2sgZm9yIGV4Y2x1c2lvbnNcbiAgICAgIGNvbnN0IHBhcmVudCA9IG5vZGUubm9kZS5zY29wZSEubm9kZS5pZDtcblxuICAgICAgLyoqXG4gICAgICAgKiBJZiBpdCdzIGFuIEwxIHJlc291cmNlLCB0aGUgZmlyc3QgY29uZGl0aW9uIGlzIHJlbGV2YW50LlxuICAgICAgICogSWYgaXQncyBhbiBMMiByZXNvdXJjZSwgdGhlIHNlY29uZCBjb25kaXRpb24gaXMgdGhlIG9uZS5cbiAgICAgICAqIFdlIGRvIHRoaXMgc28gYm90aCBMMSBhbmQgTDIgY29uc3RydWN0cyBjYW4gYmUgZXhjbHVkZWQgYnkgSUQuXG4gICAgICAgKi9cbiAgICAgIGlmICh0aGlzLmV4Y2x1ZGVSZXNvdXJjZXM/LmluY2x1ZGVzKG5vZGUubm9kZS5pZCkgfHwgdGhpcy5leGNsdWRlUmVzb3VyY2VzPy5pbmNsdWRlcyhwYXJlbnQpKSB7XG4gICAgICAgIHJldHVybjsgLy8gU2tpcCB0aGlzIHJlc291cmNlXG4gICAgICB9XG5cbiAgICAgIGlmICgobm9kZSBhcyByZHMuQ2ZuREJJbnN0YW5jZSkuZGJDbHVzdGVySWRlbnRpZmllciAhPT0gdW5kZWZpbmVkIHx8XG4gICAgICAgIChub2RlIGFzIHJkcy5DZm5EQkluc3RhbmNlKS5zb3VyY2VEYkNsdXN0ZXJJZGVudGlmaWVyICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIElmIHRoaXMgaXMgYSBEQkluc3RhbmNlIHRoYXQgaXMgcGFydCBvZiBhIERCQ2x1c3Rlciwgd2Ugc2tpcCBpdC5cbiAgICAgICAgICogVGhlIEwyIENsdXN0ZXJJbnN0YW5jZSBjbGFzcyBkb2VzIG5vdCBoYXZlIGBzdG9yYWdlRW5jcnlwdGVkYCBwcm9wZXJ0eSxcbiAgICAgICAgICogaXQganVzdCBpbmhlcml0cyBmcm9tIHRoZSBwYXJlbnQgREJDbHVzdGVyLiBXZSBoYXZlIHRvIHNraXAgaXQgb3Igd2UnZFxuICAgICAgICAgKiB0ZWxsIHRoZSB1c2VyIHRvIGNoYW5nZSBhIHByb3BlcnR5IHRoYXQgZG9lc24ndCBleGlzdC5cbiAgICAgICAgICogVGhlIEwxIENmbkRCSW5zdGFuY2UgY2xhc3MgZG9lcyBoYXZlIGBzdG9yYWdlRW5jcnlwdGVkYCwgYnV0IHdlIHN0aWxsIHNraXAgaXRcbiAgICAgICAgICogYmVjYXVzZSBDZm4gd2lsbCBub3QgYWxsb3cgaXQgdG8gYmUgc2V0IHRvIGEgY29uZmxpY3RpbmcgdmFsdWUgd2l0aCB0aGUgcGFyZW50IERCQ2x1c3Rlci5cbiAgICAgICAgICovXG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgLyoqXG4gICAgICAgKiBDaGVjayBpZiB0aGUgZGF0YWJhc2UgaXMgZW5jcnlwdGVkXG4gICAgICAgKiBUaGlzIHdvcmtzIGV2ZW4gaWYgaXQncyBhY3R1YWxseSBhIERCQ2x1c3Rlci5cbiAgICAgICAqL1xuICAgICAgY29uc3QgZW5jcnlwdGVkID0gKG5vZGUgYXMgcmRzLkNmbkRCSW5zdGFuY2UpLnN0b3JhZ2VFbmNyeXB0ZWQ7XG4gICAgICBpZiAoIWVuY3J5cHRlZCB8fCBlbmNyeXB0ZWQudG9TdHJpbmcoKSAhPT0gJ3RydWUnKSB7XG4gICAgICAgIC8vIElmIG5vdCBlbmNyeXB0ZWQsIGFubm90YXRlIGFuIGVycm9yXG4gICAgICAgIEFubm90YXRpb25zLm9mKG5vZGUpLmFkZEVycm9yKFxuICAgICAgICAgICdSRFMgZGF0YWJhc2UgbXVzdCBoYXZlIHN0b3JhZ2UgZW5jcnlwdGlvbiBlbmFibGVkLiBQbGVhc2Ugc2V0IHRoZSBcXCdzdG9yYWdlRW5jcnlwdGVkXFwnIHByb3BlcnR5IHRvIHRydWUuJyk7XG4gICAgICB9XG4gICAgfVxuICB9XG59XG5cbi8qKlxuICogQW4gY29udmVuaWVuY2UgY2xhc3Mgd2l0aCBhIHN0YXRpYyBmdW5jdGlvbiB0aGF0IGFkZHMgYWxsIG9mIHRoZSBhc3BlY3RzIGluIHRoaXMgbW9kdWxlLlxuICogSXQncyBvbmx5IGEgY2xhc3MgYmVjYXVzZSBqc2lpIHNraXBzIHN0YW5kYWxvbmUgZnVuY3Rpb25zLlxuICovXG5leHBvcnQgY2xhc3MgRW5jcnlwdGlvbkVuZm9yY2VtZW50IHtcbi8qKlxuICogQWRkcyBhbGwgZW5jcnlwdGlvbiBlbmZvcmNlbWVudCBhc3BlY3RzIHRvIHRoZSBnaXZlbiBzY29wZS5cbiAqXG4gKiBUaGlzIGlzIGEgY29udmVuaWVuY2UgbWV0aG9kIHRvIGFkZCBhbGwgYXNwZWN0cyBpbiB0aGlzIG1vZHVsZSBhdCBvbmNlLlxuICogSXQgY2FuIGJlIHVzZWQgaW4gdGhlIGBtYWluYCBmdW5jdGlvbiBvZiB5b3VyIENESyBhcHAgb3IgaW4gYSBzdGFjayBjb25zdHJ1Y3Rvci5cbiAqXG4gKiBAcGFyYW0gc2NvcGUgLSBUaGUgc2NvcGUgdG8gYWRkIHRoZSBhc3BlY3RzIHRvLlxuICogQHBhcmFtIHByb3BzIC0gT3B0aW9uYWwgcHJvcGVydGllcyB0byBjb25maWd1cmUgdGhlIGFzcGVjdHMuXG4gKiBAcmV0dXJucyB2b2lkXG4gKi9cbiAgcHVibGljIHN0YXRpYyBhZGRBbGxBc3BlY3RzKHNjb3BlOiBJQ29uc3RydWN0LCBwcm9wcz86IEVuY3J5cHRpb25FbmZvcmNlbWVudEFzcGVjdFByb3BzKSB7XG4gICAgQXNwZWN0cy5vZihzY29wZSkuYWRkKG5ldyBFRlNFbmNyeXB0aW9uRW5mb3JjZW1lbnRBc3BlY3QocHJvcHMpKTtcbiAgICBBc3BlY3RzLm9mKHNjb3BlKS5hZGQobmV3IFJEU0VuY3J5cHRpb25FbmZvcmNlbWVudEFzcGVjdChwcm9wcykpO1xuICB9XG59XG4iXX0=