cdk-rds-sql
Version:
A CDK construct that allows creating roles or users and databases on Aurora Serverless PostgreSQL or MySQL/MariaDB clusters, as well as AWS DSQL clusters.
156 lines • 28.4 kB
JavaScript
;
var _a;
Object.defineProperty(exports, "__esModule", { value: true });
exports.Role = void 0;
const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
const aws_cdk_lib_1 = require("aws-cdk-lib");
const iam = require("aws-cdk-lib/aws-iam");
const aws_secretsmanager_1 = require("aws-cdk-lib/aws-secretsmanager");
const ssm = require("aws-cdk-lib/aws-ssm");
const constructs_1 = require("constructs");
const enum_1 = require("./enum");
const provider_1 = require("./provider");
const role_custom_resource_1 = require("./role.custom-resource");
// Private Parameters construct (not exported)
class Parameters extends constructs_1.Construct {
constructor(scope, id, props) {
super(scope, id);
// Create parameters for each key-value pair
Object.entries(props.paramData).forEach(([key, value]) => {
if (value !== undefined) {
new ssm.StringParameter(this, `Parameter-${key}`, {
parameterName: `${props.parameterPrefix}${key}`,
stringValue: value.toString(),
});
}
});
// For password, use the existing provider to store it in SSM
// Skip password parameter for IAM auth roles (no passwordArn)
if (props.passwordArn) {
const passwordParameterName = `${props.parameterPrefix}password`;
const password_parameter = new aws_cdk_lib_1.CustomResource(this, "PasswordParameter", {
serviceToken: props.providerServiceToken,
properties: {
SecretArn: props.secretArn,
Resource: enum_1.RdsSqlResource.PARAMETER_PASSWORD,
PasswordArn: props.passwordArn,
ParameterName: passwordParameterName,
},
});
password_parameter.node.addDependency(props.provider);
const paramArn = `arn:${aws_cdk_lib_1.Stack.of(this).partition}:ssm:${aws_cdk_lib_1.Stack.of(this).region}:${aws_cdk_lib_1.Stack.of(this).account}:parameter${passwordParameterName.startsWith("/") ? "" : "/"}${passwordParameterName}`;
props.provider.handler.addToRolePolicy(new iam.PolicyStatement({
actions: ["ssm:PutParameter", "ssm:AddTagsToResource", "ssm:GetParameters"],
resources: [paramArn],
}));
}
}
}
class Role extends constructs_1.Construct {
constructor(scope, id, props) {
if (props.provider.engine !== provider_1.DatabaseEngine.DSQL) {
if (props.database && props.databaseName) {
throw "Specify either database or databaseName";
}
if (!props.database && !props.databaseName) {
// If neither is specified, we might need a default or throw an error depending on desired behavior.
// For now, let's assume it's allowed but the secret won't have a dbname.
// If it should be required, uncomment the line below:
throw "Specify either database or databaseName";
}
}
super(scope, id);
// Skip secret creation for DSQL (always uses IAM auth) or when enableIamAuth is true
const useIamAuth = props.enableIamAuth || props.provider.engine === provider_1.DatabaseEngine.DSQL;
// For non-DSQL providers, we need cluster info for secrets and/or parameters
if (props.provider.engine !== provider_1.DatabaseEngine.DSQL) {
// For imported providers without cluster details, provide helpful error message
if (!props.provider.cluster) {
throw new Error("Role creation requires cluster information. When importing a provider with " +
"Provider.fromProviderAttributes(), include the 'cluster' property if you plan " +
"to create new roles. Alternatively, use existing roles created with the original provider.");
}
// For RDS/Aurora clusters and instances, get endpoint details
const isCluster = !!props.provider.cluster.clusterEndpoint;
const host = isCluster
? props.provider.cluster.clusterEndpoint.hostname
: props.provider.cluster.instanceEndpoint.hostname;
const port = isCluster
? props.provider.cluster.clusterEndpoint.port
: props.provider.cluster.instanceEndpoint.port;
const identifier = isCluster
? props.provider.cluster.clusterIdentifier
: props.provider.cluster.instanceIdentifier;
const databaseName = props.database
? props.database.databaseName
: props.databaseName;
// Create secret only for password auth (not IAM auth)
if (!useIamAuth) {
const identifierKey = isCluster ? "dbClusterIdentifier" : "dbInstanceIdentifier";
const secretTemplate = {
[identifierKey]: identifier,
engine: props.provider.engine,
host: host,
port: port,
username: props.roleName,
dbname: databaseName,
};
this.secret = new aws_secretsmanager_1.Secret(this, "Secret", {
secretName: props.secretName,
encryptionKey: props.encryptionKey,
description: `Generated secret for ${props.provider.engine} role ${props.roleName}`,
generateSecretString: {
passwordLength: 30, // Oracle password cannot have more than 30 characters
secretStringTemplate: JSON.stringify(secretTemplate),
generateStringKey: "password",
excludeCharacters: " %+~`#$&*()|[]{}:;<>?!'/@\"\\",
},
removalPolicy: aws_cdk_lib_1.RemovalPolicy.DESTROY,
});
}
// Create Parameters if parameterPrefix is provided (for both password and IAM auth)
if (props.parameterPrefix) {
const identifierKey = isCluster ? "dbClusterIdentifier" : "dbInstanceIdentifier";
const paramData = {
[identifierKey]: identifier,
engine: props.provider.engine,
host: host,
port: port,
username: props.roleName,
};
if (databaseName) {
paramData.dbname = databaseName;
}
new Parameters(this, "Parameters", {
secretArn: props.provider.secret?.secretArn || "",
parameterPrefix: props.parameterPrefix,
passwordArn: this.secret?.secretArn, // undefined for IAM auth - skips password param
providerServiceToken: props.provider.serviceToken,
provider: props.provider,
paramData,
});
}
}
const role = new role_custom_resource_1.Role(this, "PostgresRole", {
provider: props.provider,
roleName: props.roleName,
passwordArn: useIamAuth ? "" : this.secret.secretArn,
database: props.database,
databaseName: props.databaseName,
enableIamAuth: useIamAuth,
});
if (this.secret) {
role.node.addDependency(this.secret);
this.secret.grantRead(props.provider.handler);
if (this.secret.encryptionKey) {
// It seems we need to grant explicit permission
this.secret.encryptionKey.grantDecrypt(props.provider.handler);
}
}
this.roleName = props.roleName;
}
}
exports.Role = Role;
_a = JSII_RTTI_SYMBOL_1;
Role[_a] = { fqn: "cdk-rds-sql.Role", version: "8.0.11" };
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm9sZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9yb2xlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBQUEsNkNBQWtFO0FBQ2xFLDJDQUEwQztBQUcxQyx1RUFBZ0U7QUFDaEUsMkNBQTBDO0FBQzFDLDJDQUFzQztBQUV0QyxpQ0FBdUM7QUFDdkMseUNBQXNEO0FBQ3RELGlFQUFtRTtBQStFbkUsOENBQThDO0FBQzlDLE1BQU0sVUFBVyxTQUFRLHNCQUFTO0lBQ2hDLFlBQ0UsS0FBZ0IsRUFDaEIsRUFBVSxFQUNWLEtBT0M7UUFFRCxLQUFLLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxDQUFBO1FBRWhCLDRDQUE0QztRQUM1QyxNQUFNLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxTQUFTLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLEdBQUcsRUFBRSxLQUFLLENBQUMsRUFBRSxFQUFFO1lBQ3ZELElBQUksS0FBSyxLQUFLLFNBQVMsRUFBRSxDQUFDO2dCQUN4QixJQUFJLEdBQUcsQ0FBQyxlQUFlLENBQUMsSUFBSSxFQUFFLGFBQWEsR0FBRyxFQUFFLEVBQUU7b0JBQ2hELGFBQWEsRUFBRSxHQUFHLEtBQUssQ0FBQyxlQUFlLEdBQUcsR0FBRyxFQUFFO29CQUMvQyxXQUFXLEVBQUUsS0FBSyxDQUFDLFFBQVEsRUFBRTtpQkFDOUIsQ0FBQyxDQUFBO1lBQ0osQ0FBQztRQUNILENBQUMsQ0FBQyxDQUFBO1FBRUYsNkRBQTZEO1FBQzdELDhEQUE4RDtRQUM5RCxJQUFJLEtBQUssQ0FBQyxXQUFXLEVBQUUsQ0FBQztZQUN0QixNQUFNLHFCQUFxQixHQUFHLEdBQUcsS0FBSyxDQUFDLGVBQWUsVUFBVSxDQUFBO1lBQ2hFLE1BQU0sa0JBQWtCLEdBQUcsSUFBSSw0QkFBYyxDQUFDLElBQUksRUFBRSxtQkFBbUIsRUFBRTtnQkFDdkUsWUFBWSxFQUFFLEtBQUssQ0FBQyxvQkFBb0I7Z0JBQ3hDLFVBQVUsRUFBRTtv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QUFRO1lBQ3hCLFFBQVEsRUFBRSxLQUFLLENBQUMsUUFBUTtZQUN4QixXQUFXLEVBQUUsVUFBVSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxNQUFPLENBQUMsU0FBUztZQUNyRCxRQUFRLEVBQUUsS0FBSyxDQUFDLFFBQVE7WUFDeEIsWUFBWSxFQUFFLEtBQUssQ0FBQyxZQUFZO1lBQ2hDLGFBQWEsRUFBRSxVQUFVO1NBQzFCLENBQUMsQ0FBQTtRQUVGLElBQUksSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDO1lBQ2hCLElBQUksQ0FBQyxJQUFJLENBQUMsYUFBYSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQTtZQUNwQyxJQUFJLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxDQUFBO1lBQzdDLElBQUksSUFBSSxDQUFDLE1BQU0sQ0FBQyxhQUFhLEVBQUUsQ0FBQztnQkFDOUIsZ0RBQWdEO2dCQUNoRCxJQUFJLENBQUMsTUFBTSxDQUFDLGFBQWEsQ0FBQyxZQUFZLENBQUMsS0FBSyxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsQ0FBQTtZQUNoRSxDQUFDO1FBQ0gsQ0FBQztRQUVELElBQUksQ0FBQyxRQUFRLEdBQUcsS0FBSyxDQUFDLFFBQVEsQ0FBQTtJQUNoQyxDQUFDOztBQXhJSCxvQkF5SUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDdXN0b21SZXNvdXJjZSwgUmVtb3ZhbFBvbGljeSwgU3RhY2sgfSBmcm9tIFwiYXdzLWNkay1saWJcIlxuaW1wb3J0ICogYXMgaWFtIGZyb20gXCJhd3MtY2RrLWxpYi9hd3MtaWFtXCJcbmltcG9ydCAqIGFzIGttcyBmcm9tIFwiYXdzLWNkay1saWIvYXdzLWttc1wiXG5pbXBvcnQgeyBJRGF0YWJhc2VDbHVzdGVyLCBJRGF0YWJhc2VJbnN0YW5jZSB9IGZyb20gXCJhd3MtY2RrLWxpYi9hd3MtcmRzXCJcbmltcG9ydCB7IElTZWNyZXQsIFNlY3JldCB9IGZyb20gXCJhd3MtY2RrLWxpYi9hd3Mtc2VjcmV0c21hbmFnZXJcIlxuaW1wb3J0ICogYXMgc3NtIGZyb20gXCJhd3MtY2RrLWxpYi9hd3Mtc3NtXCJcbmltcG9ydCB7IENvbnN0cnVjdCB9IGZyb20gXCJjb25zdHJ1Y3RzXCJcbmltcG9ydCB7IElEYXRhYmFzZSB9IGZyb20gXCIuL2RhdGFiYXNlXCJcbmltcG9ydCB7IFJkc1NxbFJlc291cmNlIH0gZnJvbSBcIi4vZW51bVwiXG5pbXBvcnQgeyBJUHJvdmlkZXIsIERhdGFiYXNlRW5naW5lIH0gZnJvbSBcIi4vcHJvdmlkZXJcIlxuaW1wb3J0IHsgUm9sZSBhcyBDdXN0b21SZXNvdXJjZVJvbGUgfSBmcm9tIFwiLi9yb2xlLmN1c3RvbS1yZXNvdXJjZVwiXG5cbmV4cG9ydCBpbnRlcmZhY2UgUm9sZVByb3BzIHtcbiAgLyoqXG4gICAqIFByb3ZpZGVyLlxuICAgKi9cbiAgcmVhZG9ubHkgcHJvdmlkZXI6IElQcm92aWRlclxuXG4gIC8qKlxuICAgKiBTUUwuXG4gICAqL1xuICByZWFkb25seSByb2xlTmFtZTogc3RyaW5nXG5cbiAgLyoqXG4gICAqIE9wdGlvbmFsIGRhdGFiYXNlIHRoaXMgdXNlciBpcyBleHBlY3RlZCB0byB1c2UuXG4gICAqXG4gICAqIElmIHRoZSBkYXRhYmFzZSBleGlzdHMsIGNvbm5lY3QgcHJpdmlsZWdlcyBhcmUgZ3JhbnRlZC5cbiAgICpcbiAgICogU3BlY2lmeSBvbmUgb2YgYGRhdGFiYXNlYCBvciBgZGF0YWJhc2VOYW1lYC4gVGhpcyBpcyB0aGUgbmFtZVxuICAgKiB0aGF0IHdpbGwgYmUgc3RvcmVkIGluIHRoZSByb2xlJ3Mgc2VjcmV0IGFzIHRoZSBkYXRhYmFzZSBuYW1lIHRvXG4gICAqIHVzZS5cbiAgICovXG4gIHJlYWRvbmx5IGRhdGFiYXNlPzogSURhdGFiYXNlXG5cbiAgLyoqXG4gICAqIE9wdGlvbmFsIGRhdGFiYXNlIG5hbWUgdGhpcyB1c2VyIGlzIGV4cGVjdGVkIHRvIHVzZS5cbiAgICpcbiAgICogSWYgdGhlIGRhdGFiYXNlIGV4aXN0cywgY29ubmVjdCBwcml2aWxlZ2VzIGFyZSBncmFudGVkLlxuICAgKlxuICAgKiBTcGVjaWZ5IG9uZSBvZiBgZGF0YWJhc2VgIG9yIGBkYXRhYmFzZU5hbWVgLiBUaGlzIGlzIHRoZSBuYW1lXG4gICAqIHRoYXQgd2lsbCBiZSBzdG9yZWQgaW4gdGhlIHJvbGUncyBzZWNyZXQgYXMgdGhlIGRhdGFiYXNlIG5hbWUgdG9cbiAgICogdXNlLlxuICAgKi9cbiAgcmVhZG9ubHkgZGF0YWJhc2VOYW1lPzogc3RyaW5nXG5cbiAgLyoqXG4gICAqIEEgbmV3IHNlY3JldCBpcyBjcmVhdGVkIGZvciB0aGlzIHVzZXIuXG4gICAqXG4gICAqIE9wdGlvbmFsbHkgZW5jcnlwdCBpdCB3aXRoIHRoZSBnaXZlbiBrZXkuXG4gICAqL1xuICByZWFkb25seSBlbmNyeXB0aW9uS2V5Pzoga21zLklLZXlcblxuICAvKipcbiAgICogQSBuZXcgc2VjcmV0IGlzIGNyZWF0ZWQgZm9yIHRoaXMgdXNlci5cbiAgICpcbiAgICogT3B0aW9uYWxseSBhZGQgc2VjcmV0IG5hbWUgdG8gdGhlIHNlY3JldC5cbiAgICovXG4gIHJlYWRvbmx5IHNlY3JldE5hbWU/OiBzdHJpbmdcblxuICAvKipcbiAgICogUHJlZml4IGZvciBTU00gcGFyYW1ldGVycyB0byBzdG9yZSBjcmVkZW50aWFscyBpbiBQYXJhbWV0ZXIgU3RvcmUuXG4gICAqIFdoZW4gZGVmaW5lZCwgY3JlZGVudGlhbHMgd2lsbCBhbHNvIGJlIHN0b3JlZCBhcyBwYXJhbWV0ZXJzLlxuICAgKlxuICAgKiBUaGUgcGFyYW1ldGVyIG5hbWVzIHN1Y2ggYXMgXCJwYXNzd29yZFwiIGlzIHNpbXBseSBhcHBlbmRlZCB0b1xuICAgKiBgcGFyYW1ldGVyUHJlZml4YCwgc28gbWFrZSBzdXJlIHRoZSBwcmVmaXggZW5kcyB3aXRoIGEgc2xhc2ggaWZcbiAgICogIHlvdSBoYXZlIHlvdXIgcGFyYW1ldGVyIG5hbWVzIHNsYXNoIHNlcGFyYXRlZC5cbiAgICpcbiAgICogTm90ZSB0aGF0IHRoZSBwYXNzd29yZCBmcm9tIHRoZSBzZWNyZXQgaXMgY29waWVkIGp1c3Qgb25jZSwgdGhleVxuICAgKiBhcmUgbm90IGtlcHQgaW4gc3luYy5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBjcmVkZW50aWFscyBhcmUgb25seSBzdG9yZWQgaW4gU2VjcmV0cyBNYW5hZ2VyXG4gICAqL1xuICByZWFkb25seSBwYXJhbWV0ZXJQcmVmaXg/OiBzdHJpbmdcblxuICAvKipcbiAgICogRW5hYmxlIElBTSBhdXRoZW50aWNhdGlvbiBmb3IgdGhpcyByb2xlLlxuICAgKlxuICAgKiBXaGVuIGVuYWJsZWQsIHRoZSByb2xlIHdpbGwgYmUgY3JlYXRlZCB3aXRob3V0IGEgcGFzc3dvcmQgYW5kXG4gICAqIGNvbmZpZ3VyZWQgZm9yIEFXUyBJQU0gZGF0YWJhc2UgYXV0aGVudGljYXRpb24uIE5vIHNlY3JldCB3aWxsXG4gICAqIGJlIGNyZWF0ZWQgZm9yIHRoaXMgcm9sZS5cbiAgICpcbiAgICogTm90ZTogRm9yIERTUUwgY2x1c3RlcnMsIHRoaXMgcHJvcGVydHkgaXMgaWdub3JlZCBhcyBEU1FMIGFsd2F5c1xuICAgKiB1c2VzIElBTSBhdXRoZW50aWNhdGlvbi5cbiAgICpcbiAgICogQGRlZmF1bHQgZmFsc2UgLSB1c2UgcGFzc3dvcmQgYXV0aGVudGljYXRpb25cbiAgICovXG4gIHJlYWRvbmx5IGVuYWJsZUlhbUF1dGg/OiBib29sZWFuXG59XG5cbi8vIFByaXZhdGUgUGFyYW1ldGVycyBjb25zdHJ1Y3QgKG5vdCBleHBvcnRlZClcbmNsYXNzIFBhcmFtZXRlcnMgZXh0ZW5kcyBDb25zdHJ1Y3Qge1xuICBjb25zdHJ1Y3RvcihcbiAgICBzY29wZTogQ29uc3RydWN0LFxuICAgIGlkOiBzdHJpbmcsXG4gICAgcHJvcHM6IHtcbiAgICAgIHByb3ZpZGVyOiBJUHJvdmlkZXJcbiAgICAgIHNlY3JldEFybjogc3RyaW5nXG4gICAgICBwYXJhbWV0ZXJQcmVmaXg6IHN0cmluZ1xuICAgICAgcGFzc3dvcmRBcm4/OiBzdHJpbmdcbiAgICAgIHByb3ZpZGVyU2VydmljZVRva2VuOiBzdHJpbmdcbiAgICAgIHBhcmFtRGF0YTogUmVjb3JkPHN0cmluZywgc3RyaW5nIHwgbnVtYmVyPlxuICAgIH1cbiAgKSB7XG4gICAgc3VwZXIoc2NvcGUsIGlkKVxuXG4gICAgLy8gQ3JlYXRlIHBhcmFtZXRlcnMgZm9yIGVhY2gga2V5LXZhbHVlIHBhaXJcbiAgICBPYmplY3QuZW50cmllcyhwcm9wcy5wYXJhbURhdGEpLmZvckVhY2goKFtrZXksIHZhbHVlXSkgPT4ge1xuICAgICAgaWYgKHZhbHVlICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgbmV3IHNzbS5TdHJpbmdQYXJhbWV0ZXIodGhpcywgYFBhcmFtZXRlci0ke2tleX1gLCB7XG4gICAgICAgICAgcGFyYW1ldGVyTmFtZTogYCR7cHJvcHMucGFyYW1ldGVyUHJlZml4fSR7a2V5fWAsXG4gICAgICAgICAgc3RyaW5nVmFsdWU6IHZhbHVlLnRvU3RyaW5nKCksXG4gICAgICAgIH0pXG4gICAgICB9XG4gICAgfSlcblxuICAgIC8vIEZvciBwYXNzd29yZCwgdXNlIHRoZSBleGlzdGluZyBwcm92aWRlciB0byBzdG9yZSBpdCBpbiBTU01cbiAgICAvLyBTa2lwIHBhc3N3b3JkIHBhcmFtZXRlciBmb3IgSUFNIGF1dGggcm9sZXMgKG5vIHBhc3N3b3JkQXJuKVxuICAgIGlmIChwcm9wcy5wYXNzd29yZEFybikge1xuICAgICAgY29uc3QgcGFzc3dvcmRQYXJhbWV0ZXJOYW1lID0gYCR7cHJvcHMucGFyYW1ldGVyUHJlZml4fXBhc3N3b3JkYFxuICAgICAgY29uc3QgcGFzc3dvcmRfcGFyYW1ldGVyID0gbmV3IEN1c3RvbVJlc291cmNlKHRoaXMsIFwiUGFzc3dvcmRQYXJhbWV0ZXJcIiwge1xuICAgICAgICBzZXJ2aWNlVG9rZW46IHByb3BzLnByb3ZpZGVyU2VydmljZVRva2VuLFxuICAgICAgICBwcm9wZXJ0aWVzOiB7XG4gICAgICAgICAgU2VjcmV0QXJuOiBwcm9wcy5zZWNyZXRBcm4sXG4gICAgICAgICAgUmVzb3VyY2U6IFJkc1NxbFJlc291cmNlLlBBUkFNRVRFUl9QQVNTV09SRCxcbiAgICAgICAgICBQYXNzd29yZEFybjogcHJvcHMucGFzc3dvcmRBcm4sXG4gICAgICAgICAgUGFyYW1ldGVyTmFtZTogcGFzc3dvcmRQYXJhbWV0ZXJOYW1lLFxuICAgICAgICB9LFxuICAgICAgfSlcbiAgICAgIHBhc3N3b3JkX3BhcmFtZXRlci5ub2RlLmFkZERlcGVuZGVuY3kocHJvcHMucHJvdmlkZXIpXG5cbiAgICAgIGNvbnN0IHBhcmFtQXJuID0gYGFybjoke1N0YWNrLm9mKHRoaXMpLnBhcnRpdGlvbn06c3NtOiR7U3RhY2sub2YodGhpcykucmVnaW9ufToke1xuICAgICAgICBTdGFjay5vZih0aGlzKS5hY2NvdW50XG4gICAgICB9OnBhcmFtZXRlciR7XG4gICAgICAgIHBhc3N3b3JkUGFyYW1ldGVyTmFtZS5zdGFydHNXaXRoKFwiL1wiKSA/IFwiXCIgOiBcIi9cIlxuICAgICAgfSR7cGFzc3dvcmRQYXJhbWV0ZXJOYW1lfWBcblxuICAgICAgcHJvcHMucHJvdmlkZXIuaGFuZGxlci5hZGRUb1JvbGVQb2xpY3koXG4gICAgICAgIG5ldyBpYW0uUG9saWN5U3RhdGVtZW50KHtcbiAgICAgICAgICBhY3Rpb25zOiBbXCJzc206UHV0UGFyYW1ldGVyXCIsIFwic3NtOkFkZFRhZ3NUb1Jlc291cmNlXCIsIFwic3NtOkdldFBhcmFtZXRlcnNcIl0sXG4gICAgICAgICAgcmVzb3VyY2VzOiBbcGFyYW1Bcm5dLFxuICAgICAgICB9KVxuICAgICAgKVxuICAgIH1cbiAgfVxufVxuXG5leHBvcnQgY2xhc3MgUm9sZSBleHRlbmRzIENvbnN0cnVjdCB7XG4gIC8qKlxuICAgKiBUaGUgcm9sZSBuYW1lLlxuICAgKi9cbiAgcHVibGljIHJlYWRvbmx5IHJvbGVOYW1lOiBzdHJpbmdcblxuICAvKipcbiAgICogVGhlIGdlbmVyYXRlZCBzZWNyZXQgY29udGFpbmluZyBjb25uZWN0aW9uIGluZm9ybWF0aW9uIGFuZCBwYXNzd29yZC5cbiAgICpcbiAgICogVGhpcyBpcyBvbmx5IGF2YWlsYWJsZSB3aGVuOlxuICAgKiAtIFRoZSBwcm92aWRlciBpcyBub3QgYSBEU1FMIGNsdXN0ZXIgKERTUUwgdXNlcyBJQU0gYXV0aGVudGljYXRpb24pXG4gICAqIC0gYGVuYWJsZUlhbUF1dGhgIGlzIG5vdCBzZXQgdG8gYHRydWVgXG4gICAqXG4gICAqIFdoZW4gdXNpbmcgSUFNIGF1dGhlbnRpY2F0aW9uLCBubyBzZWNyZXQgaXMgY3JlYXRlZCBhcyB0aGUgcGFzc3dvcmRcbiAgICogaXMgZ2VuZXJhdGVkIGR5bmFtaWNhbGx5IHVzaW5nIElBTSBjcmVkZW50aWFscy5cbiAgICovXG4gIHB1YmxpYyByZWFkb25seSBzZWNyZXQ/OiBJU2VjcmV0XG5cbiAgY29uc3RydWN0b3Ioc2NvcGU6IENvbnN0cnVjdCwgaWQ6IHN0cmluZywgcHJvcHM6IFJvbGVQcm9wcykge1xuICAgIGlmIChwcm9wcy5wcm92aWRlci5lbmdpbmUgIT09IERhdGFiYXNlRW5naW5lLkRTUUwpIHtcbiAgICAgIGlmIChwcm9wcy5kYXRhYmFzZSAmJiBwcm9wcy5kYXRhYmFzZU5hbWUpIHtcbiAgICAgICAgdGhyb3cgXCJTcGVjaWZ5IGVpdGhlciBkYXRhYmFzZSBvciBkYXRhYmFzZU5hbWVcIlxuICAgICAgfVxuICAgICAgaWYgKCFwcm9wcy5kYXRhYmFzZSAmJiAhcHJvcHMuZGF0YWJhc2VOYW1lKSB7XG4gICAgICAgIC8vIElmIG5laXRoZXIgaXMgc3BlY2lmaWVkLCB3ZSBtaWdodCBuZWVkIGEgZGVmYXVsdCBvciB0aHJvdyBhbiBlcnJvciBkZXBlbmRpbmcgb24gZGVzaXJlZCBiZWhhdmlvci5cbiAgICAgICAgLy8gRm9yIG5vdywgbGV0J3MgYXNzdW1lIGl0J3MgYWxsb3dlZCBidXQgdGhlIHNlY3JldCB3b24ndCBoYXZlIGEgZGJuYW1lLlxuICAgICAgICAvLyBJZiBpdCBzaG91bGQgYmUgcmVxdWlyZWQsIHVuY29tbWVudCB0aGUgbGluZSBiZWxvdzpcbiAgICAgICAgdGhyb3cgXCJTcGVjaWZ5IGVpdGhlciBkYXRhYmFzZSBvciBkYXRhYmFzZU5hbWVcIlxuICAgICAgfVxuICAgIH1cbiAgICBzdXBlcihzY29wZSwgaWQpXG5cbiAgICAvLyBTa2lwIHNlY3JldCBjcmVhdGlvbiBmb3IgRFNRTCAoYWx3YXlzIHVzZXMgSUFNIGF1dGgpIG9yIHdoZW4gZW5hYmxlSWFtQXV0aCBpcyB0cnVlXG4gICAgY29uc3QgdXNlSWFtQXV0aCA9XG4gICAgICBwcm9wcy5lbmFibGVJYW1BdXRoIHx8IHByb3BzLnByb3ZpZGVyLmVuZ2luZSA9PT0gRGF0YWJhc2VFbmdpbmUuRFNRTFxuXG4gICAgLy8gRm9yIG5vbi1EU1FMIHByb3ZpZGVycywgd2UgbmVlZCBjbHVzdGVyIGluZm8gZm9yIHNlY3JldHMgYW5kL29yIHBhcmFtZXRlcnNcbiAgICBpZiAocHJvcHMucHJvdmlkZXIuZW5naW5lICE9PSBEYXRhYmFzZUVuZ2luZS5EU1FMKSB7XG4gICAgICAvLyBGb3IgaW1wb3J0ZWQgcHJvdmlkZXJzIHdpdGhvdXQgY2x1c3RlciBkZXRhaWxzLCBwcm92aWRlIGhlbHBmdWwgZXJyb3IgbWVzc2FnZVxuICAgICAgaWYgKCFwcm9wcy5wcm92aWRlci5jbHVzdGVyKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICBcIlJvbGUgY3JlYXRpb24gcmVxdWlyZXMgY2x1c3RlciBpbmZvcm1hdGlvbi4gV2hlbiBpbXBvcnRpbmcgYSBwcm92aWRlciB3aXRoIFwiICtcbiAgICAgICAgICAgIFwiUHJvdmlkZXIuZnJvbVByb3ZpZGVyQXR0cmlidXRlcygpLCBpbmNsdWRlIHRoZSAnY2x1c3RlcicgcHJvcGVydHkgaWYgeW91IHBsYW4gXCIgK1xuICAgICAgICAgICAgXCJ0byBjcmVhdGUgbmV3IHJvbGVzLiBBbHRlcm5hdGl2ZWx5LCB1c2UgZXhpc3Rpbmcgcm9sZXMgY3JlYXRlZCB3aXRoIHRoZSBvcmlnaW5hbCBwcm92aWRlci5cIlxuICAgICAgICApXG4gICAgICB9XG5cbiAgICAgIC8vIEZvciBSRFMvQXVyb3JhIGNsdXN0ZXJzIGFuZCBpbnN0YW5jZXMsIGdldCBlbmRwb2ludCBkZXRhaWxzXG4gICAgICBjb25zdCBpc0NsdXN0ZXIgPSAhIShwcm9wcy5wcm92aWRlci5jbHVzdGVyIGFzIElEYXRhYmFzZUNsdXN0ZXIpLmNsdXN0ZXJFbmRwb2ludFxuXG4gICAgICBjb25zdCBob3N0ID0gaXNDbHVzdGVyXG4gICAgICAgID8gKHByb3BzLnByb3ZpZGVyLmNsdXN0ZXIgYXMgSURhdGFiYXNlQ2x1c3RlcikuY2x1c3RlckVuZHBvaW50Lmhvc3RuYW1lXG4gICAgICAgIDogKHByb3BzLnByb3ZpZGVyLmNsdXN0ZXIgYXMgSURhdGFiYXNlSW5zdGFuY2UpLmluc3RhbmNlRW5kcG9pbnQuaG9zdG5hbWVcblxuICAgICAgY29uc3QgcG9ydCA9IGlzQ2x1c3RlclxuICAgICAgICA/IChwcm9wcy5wcm92aWRlci5jbHVzdGVyIGFzIElEYXRhYmFzZUNsdXN0ZXIpLmNsdXN0ZXJFbmRwb2ludC5wb3J0XG4gICAgICAgIDogKHByb3BzLnByb3ZpZGVyLmNsdXN0ZXIgYXMgSURhdGFiYXNlSW5zdGFuY2UpLmluc3RhbmNlRW5kcG9pbnQucG9ydFxuXG4gICAgICBjb25zdCBpZGVudGlmaWVyID0gaXNDbHVzdGVyXG4gICAgICAgID8gKHByb3BzLnByb3ZpZGVyLmNsdXN0ZXIgYXMgSURhdGFiYXNlQ2x1c3RlcikuY2x1c3RlcklkZW50aWZpZXJcbiAgICAgICAgOiAocHJvcHMucHJvdmlkZXIuY2x1c3RlciBhcyBJRGF0YWJhc2VJbnN0YW5jZSkuaW5zdGFuY2VJZGVudGlmaWVyXG5cbiAgICAgIGNvbnN0IGRhdGFiYXNlTmFtZSA9IHByb3BzLmRhdGFiYXNlXG4gICAgICAgID8gcHJvcHMuZGF0YWJhc2UuZGF0YWJhc2VOYW1lXG4gICAgICAgIDogcHJvcHMuZGF0YWJhc2VOYW1lXG5cbiAgICAgIC8vIENyZWF0ZSBzZWNyZXQgb25seSBmb3IgcGFzc3dvcmQgYXV0aCAobm90IElBTSBhdXRoKVxuICAgICAgaWYgKCF1c2VJYW1BdXRoKSB7XG4gICAgICAgIGNvbnN0IGlkZW50aWZpZXJLZXkgPSBpc0NsdXN0ZXIgPyBcImRiQ2x1c3RlcklkZW50aWZpZXJcIiA6IFwiZGJJbnN0YW5jZUlkZW50aWZpZXJcIlxuICAgICAgICBjb25zdCBzZWNyZXRUZW1wbGF0ZSA9IHtcbiAgICAgICAgICBbaWRlbnRpZmllcktleV06IGlkZW50aWZpZXIsXG4gICAgICAgICAgZW5naW5lOiBwcm9wcy5wcm92aWRlci5lbmdpbmUsXG4gICAgICAgICAgaG9zdDogaG9zdCxcbiAgICAgICAgICBwb3J0OiBwb3J0LFxuICAgICAgICAgIHVzZXJuYW1lOiBwcm9wcy5yb2xlTmFtZSxcbiAgICAgICAgICBkYm5hbWU6IGRhdGFiYXNlTmFtZSxcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuc2VjcmV0ID0gbmV3IFNlY3JldCh0aGlzLCBcIlNlY3JldFwiLCB7XG4gICAgICAgICAgc2VjcmV0TmFtZTogcHJvcHMuc2VjcmV0TmFtZSxcbiAgICAgICAgICBlbmNyeXB0aW9uS2V5OiBwcm9wcy5lbmNyeXB0aW9uS2V5LFxuICAgICAgICAgIGRlc2NyaXB0aW9uOiBgR2VuZXJhdGVkIHNlY3JldCBmb3IgJHtwcm9wcy5wcm92aWRlci5lbmdpbmV9IHJvbGUgJHtwcm9wcy5yb2xlTmFtZX1gLFxuICAgICAgICAgIGdlbmVyYXRlU2VjcmV0U3RyaW5nOiB7XG4gICAgICAgICAgICBwYXNzd29yZExlbmd0aDogMzAsIC8vIE9yYWNsZSBwYXNzd29yZCBjYW5ub3QgaGF2ZSBtb3JlIHRoYW4gMzAgY2hhcmFjdGVyc1xuICAgICAgICAgICAgc2VjcmV0U3RyaW5nVGVtcGxhdGU6IEpTT04uc3RyaW5naWZ5KHNlY3JldFRlbXBsYXRlKSxcbiAgICAgICAgICAgIGdlbmVyYXRlU3RyaW5nS2V5OiBcInBhc3N3b3JkXCIsXG4gICAgICAgICAgICBleGNsdWRlQ2hhcmFjdGVyczogXCIgJSt+YCMkJiooKXxbXXt9Ojs8Pj8hJy9AXFxcIlxcXFxcIixcbiAgICAgICAgICB9LFxuICAgICAgICAgIHJlbW92YWxQb2xpY3k6IFJlbW92YWxQb2xpY3kuREVTVFJPWSxcbiAgICAgICAgfSlcbiAgICAgIH1cblxuICAgICAgLy8gQ3JlYXRlIFBhcmFtZXRlcnMgaWYgcGFyYW1ldGVyUHJlZml4IGlzIHByb3ZpZGVkIChmb3IgYm90aCBwYXNzd29yZCBhbmQgSUFNIGF1dGgpXG4gICAgICBpZiAocHJvcHMucGFyYW1ldGVyUHJlZml4KSB7XG4gICAgICAgIGNvbnN0IGlkZW50aWZpZXJLZXkgPSBpc0NsdXN0ZXIgPyBcImRiQ2x1c3RlcklkZW50aWZpZXJcIiA6IFwiZGJJbnN0YW5jZUlkZW50aWZpZXJcIlxuICAgICAgICBjb25zdCBwYXJhbURhdGE6IFJlY29yZDxzdHJpbmcsIHN0cmluZyB8IG51bWJlcj4gPSB7XG4gICAgICAgICAgW2lkZW50aWZpZXJLZXldOiBpZGVudGlmaWVyLFxuICAgICAgICAgIGVuZ2luZTogcHJvcHMucHJvdmlkZXIuZW5naW5lLFxuICAgICAgICAgIGhvc3Q6IGhvc3QsXG4gICAgICAgICAgcG9ydDogcG9ydCxcbiAgICAgICAgICB1c2VybmFtZTogcHJvcHMucm9sZU5hbWUsXG4gICAgICAgIH1cbiAgICAgICAgaWYgKGRhdGFiYXNlTmFtZSkge1xuICAgICAgICAgIHBhcmFtRGF0YS5kYm5hbWUgPSBkYXRhYmFzZU5hbWVcbiAgICAgICAgfVxuXG4gICAgICAgIG5ldyBQYXJhbWV0ZXJzKHRoaXMsIFwiUGFyYW1ldGVyc1wiLCB7XG4gICAgICAgICAgc2VjcmV0QXJuOiBwcm9wcy5wcm92aWRlci5zZWNyZXQ/LnNlY3JldEFybiB8fCBcIlwiLFxuICAgICAgICAgIHBhcmFtZXRlclByZWZpeDogcHJvcHMucGFyYW1ldGVyUHJlZml4LFxuICAgICAgICAgIHBhc3N3b3JkQXJuOiB0aGlzLnNlY3JldD8uc2VjcmV0QXJuLCAvLyB1bmRlZmluZWQgZm9yIElBTSBhdXRoIC0gc2tpcHMgcGFzc3dvcmQgcGFyYW1cbiAgICAgICAgICBwcm92aWRlclNlcnZpY2VUb2tlbjogcHJvcHMucHJvdmlkZXIuc2VydmljZVRva2VuLFxuICAgICAgICAgIHByb3ZpZGVyOiBwcm9wcy5wcm92aWRlcixcbiAgICAgICAgICBwYXJhbURhdGEsXG4gICAgICAgIH0pXG4gICAgICB9XG4gICAgfVxuXG4gICAgY29uc3Qgcm9sZSA9IG5ldyBDdXN0b21SZXNvdXJjZVJvbGUodGhpcywgXCJQb3N0Z3Jlc1JvbGVcIiwge1xuICAgICAgcHJvdmlkZXI6IHByb3BzLnByb3ZpZGVyLFxuICAgICAgcm9sZU5hbWU6IHByb3BzLnJvbGVOYW1lLFxuICAgICAgcGFzc3dvcmRBcm46IHVzZUlhbUF1dGggPyBcIlwiIDogdGhpcy5zZWNyZXQhLnNlY3JldEFybixcbiAgICAgIGRhdGFiYXNlOiBwcm9wcy5kYXRhYmFzZSxcbiAgICAgIGRhdGFiYXNlTmFtZTogcHJvcHMuZGF0YWJhc2VOYW1lLFxuICAgICAgZW5hYmxlSWFtQXV0aDogdXNlSWFtQXV0aCxcbiAgICB9KVxuXG4gICAgaWYgKHRoaXMuc2VjcmV0KSB7XG4gICAgICByb2xlLm5vZGUuYWRkRGVwZW5kZW5jeSh0aGlzLnNlY3JldClcbiAgICAgIHRoaXMuc2VjcmV0LmdyYW50UmVhZChwcm9wcy5wcm92aWRlci5oYW5kbGVyKVxuICAgICAgaWYgKHRoaXMuc2VjcmV0LmVuY3J5cHRpb25LZXkpIHtcbiAgICAgICAgLy8gSXQgc2VlbXMgd2UgbmVlZCB0byBncmFudCBleHBsaWNpdCBwZXJtaXNzaW9uXG4gICAgICAgIHRoaXMuc2VjcmV0LmVuY3J5cHRpb25LZXkuZ3JhbnREZWNyeXB0KHByb3BzLnByb3ZpZGVyLmhhbmRsZXIpXG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhpcy5yb2xlTmFtZSA9IHByb3BzLnJvbGVOYW1lXG4gIH1cbn1cbiJdfQ==