From 19ad316014d8825d7e35a980668d6b05fb684c6b Mon Sep 17 00:00:00 2001 From: Rico Huijbers Date: Sun, 27 Jan 2019 11:33:24 -0800 Subject: [PATCH 01/31] Introduce Role -> IIdentity -> IPrincipal --- packages/@aws-cdk/aws-iam/README.md | 8 + packages/@aws-cdk/aws-iam/lib/group.ts | 16 +- .../@aws-cdk/aws-iam/lib/identity-base.ts | 37 ++++ packages/@aws-cdk/aws-iam/lib/index.ts | 2 + .../@aws-cdk/aws-iam/lib/policy-document.ts | 192 +----------------- packages/@aws-cdk/aws-iam/lib/policy.ts | 37 +--- packages/@aws-cdk/aws-iam/lib/principals.ts | 189 +++++++++++++++++ packages/@aws-cdk/aws-iam/lib/role.ts | 28 +-- packages/@aws-cdk/aws-iam/lib/user.ts | 16 +- packages/@aws-cdk/aws-iam/lib/util.ts | 15 ++ .../aws-iam/test/test.policy-document.ts | 6 +- 11 files changed, 291 insertions(+), 255 deletions(-) create mode 100644 packages/@aws-cdk/aws-iam/lib/identity-base.ts create mode 100644 packages/@aws-cdk/aws-iam/lib/principals.ts diff --git a/packages/@aws-cdk/aws-iam/README.md b/packages/@aws-cdk/aws-iam/README.md index 59b875e56df8b..a1428f1eeacd4 100644 --- a/packages/@aws-cdk/aws-iam/README.md +++ b/packages/@aws-cdk/aws-iam/README.md @@ -22,6 +22,14 @@ an `ExternalId` works like this: [supplying an external ID](test/example.external-id.lit.ts) +### Principals vs Identities + +When we say *Principal*, we mean an entity you grant permissions to. This +entity can be an AWS Service, a Role, or something more abstract such as "all +users in this account" or even "all users in this organization". An +*Identity* is an IAM representing a single IAM entity that can have +a policy attached, one of `Role`, `User`, or `Group`. + ### IAM Principals When defining policy statements as part of an AssumeRole policy or as part of a diff --git a/packages/@aws-cdk/aws-iam/lib/group.ts b/packages/@aws-cdk/aws-iam/lib/group.ts index 7e68246eb7b1c..421eae23db319 100644 --- a/packages/@aws-cdk/aws-iam/lib/group.ts +++ b/packages/@aws-cdk/aws-iam/lib/group.ts @@ -1,7 +1,9 @@ import { Construct } from '@aws-cdk/cdk'; import { CfnGroup } from './iam.generated'; -import { IPrincipal, Policy } from './policy'; -import { ArnPrincipal, PolicyPrincipal, PolicyStatement } from './policy-document'; +import { IIdentity } from './identity-base'; +import { Policy } from './policy'; +import { PolicyStatement } from './policy-document'; +import { ArnPrincipal, PrincipalPolicyFragment } from './principals'; import { User } from './user'; import { AttachedPolicies, undefinedIfEmpty } from './util'; @@ -34,7 +36,8 @@ export interface GroupProps { path?: string; } -export class Group extends Construct implements IPrincipal { +export class Group extends Construct implements IIdentity { + public readonly assumeRoleAction: string = 'sts:AssumeRole'; /** * The runtime name of this group. */ @@ -45,10 +48,7 @@ export class Group extends Construct implements IPrincipal { */ public readonly groupArn: string; - /** - * An "AWS" policy principal that represents this group. - */ - public readonly principal: PolicyPrincipal; + public readonly policyFragment: PrincipalPolicyFragment; private readonly managedPolicies: any[]; private readonly attachedPolicies = new AttachedPolicies(); @@ -67,7 +67,7 @@ export class Group extends Construct implements IPrincipal { this.groupName = group.groupName; this.groupArn = group.groupArn; - this.principal = new ArnPrincipal(this.groupArn); + this.policyFragment = new ArnPrincipal(this.groupArn).policyFragment; } /** diff --git a/packages/@aws-cdk/aws-iam/lib/identity-base.ts b/packages/@aws-cdk/aws-iam/lib/identity-base.ts new file mode 100644 index 0000000000000..83f899a0e83ae --- /dev/null +++ b/packages/@aws-cdk/aws-iam/lib/identity-base.ts @@ -0,0 +1,37 @@ +import cdk = require('@aws-cdk/cdk'); +import { Policy } from "./policy"; +import { PolicyStatement } from "./policy-document"; +import { IPrincipal, PrincipalPolicyFragment } from "./principals"; + +/** + * A construct that represents an IAM principal, such as a user, group or role. + */ +export interface IIdentity extends IPrincipal { + /** + * Adds an IAM statement to the default inline policy associated with this + * principal. If a policy doesn't exist, it is created. + */ + addToPolicy(statement: PolicyStatement): void; + + /** + * Attaches an inline policy to this principal. + * This is the same as calling `policy.addToXxx(principal)`. + * @param policy The policy resource to attach to this principal. + */ + attachInlinePolicy(policy: Policy): void; + + /** + * Attaches a managed policy to this principal. + * @param arn The ARN of the managed policy + */ + attachManagedPolicy(arn: string): void; +} + +export abstract class IdentityBase extends cdk.Construct implements IIdentity { + public readonly assumeRoleAction: string = 'sts:AssumeRole'; + + public abstract policyFragment: PrincipalPolicyFragment; + public abstract addToPolicy(statement: PolicyStatement): void; + public abstract attachInlinePolicy(policy: Policy): void; + public abstract attachManagedPolicy(arn: string): void; +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-iam/lib/index.ts b/packages/@aws-cdk/aws-iam/lib/index.ts index 2301ccd5b6ae8..ce29004f943f3 100644 --- a/packages/@aws-cdk/aws-iam/lib/index.ts +++ b/packages/@aws-cdk/aws-iam/lib/index.ts @@ -5,6 +5,8 @@ export * from './policy'; export * from './user'; export * from './group'; export * from './lazy-role'; +export * from './principals'; +export * from './identity-base'; // AWS::IAM CloudFormation Resources: export * from './iam.generated'; diff --git a/packages/@aws-cdk/aws-iam/lib/policy-document.ts b/packages/@aws-cdk/aws-iam/lib/policy-document.ts index 3a30676b18a59..968d318f9ff6a 100644 --- a/packages/@aws-cdk/aws-iam/lib/policy-document.ts +++ b/packages/@aws-cdk/aws-iam/lib/policy-document.ts @@ -1,4 +1,7 @@ import cdk = require('@aws-cdk/cdk'); +import { AccountPrincipal, AccountRootPrincipal, Anyone, + ArnPrincipal, CanonicalUserPrincipal, FederatedPrincipal, IPrincipal, ServicePrincipal } from './principals'; +import { mergePrincipal } from './util'; export class PolicyDocument extends cdk.Token { private statements = new Array(); @@ -42,162 +45,6 @@ export class PolicyDocument extends cdk.Token { } } -/** - * Represents an IAM principal. - */ -export abstract class PolicyPrincipal { - /** - * When this Principal is used in an AssumeRole policy, the action to use. - */ - public assumeRoleAction: string = 'sts:AssumeRole'; - - /** - * Return the policy fragment that identifies this principal in a Policy. - */ - public abstract policyFragment(): PrincipalPolicyFragment; -} - -/** - * A collection of the fields in a PolicyStatement that can be used to identify a principal. - * - * This consists of the JSON used in the "Principal" field, and optionally a - * set of "Condition"s that need to be applied to the policy. - */ -export class PrincipalPolicyFragment { - constructor( - public readonly principalJson: { [key: string]: string[] }, - public readonly conditions: { [key: string]: any } = { }) { - } -} - -export class ArnPrincipal extends PolicyPrincipal { - constructor(public readonly arn: string) { - super(); - } - - public policyFragment(): PrincipalPolicyFragment { - return new PrincipalPolicyFragment({ AWS: [ this.arn ] }); - } -} - -export class AccountPrincipal extends ArnPrincipal { - constructor(public readonly accountId: any) { - super(new StackDependentToken(stack => `arn:${stack.partition}:iam::${accountId}:root`).toString()); - } -} - -/** - * An IAM principal that represents an AWS service (i.e. sqs.amazonaws.com). - */ -export class ServicePrincipal extends PolicyPrincipal { - constructor(public readonly service: string) { - super(); - } - - public policyFragment(): PrincipalPolicyFragment { - return new PrincipalPolicyFragment({ Service: [ this.service ] }); - } -} - -/** - * A policy prinicipal for canonicalUserIds - useful for S3 bucket policies that use - * Origin Access identities. - * - * See https://docs.aws.amazon.com/general/latest/gr/acct-identifiers.html - * - * and - * - * https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/private-content-restricting-access-to-s3.html - * - * for more details. - * - */ -export class CanonicalUserPrincipal extends PolicyPrincipal { - constructor(public readonly canonicalUserId: string) { - super(); - } - - public policyFragment(): PrincipalPolicyFragment { - return new PrincipalPolicyFragment({ CanonicalUser: [ this.canonicalUserId ] }); - } -} - -export class FederatedPrincipal extends PolicyPrincipal { - constructor( - public readonly federated: string, - public readonly conditions: {[key: string]: any}, - public assumeRoleAction: string = 'sts:AssumeRole') { - super(); - } - - public policyFragment(): PrincipalPolicyFragment { - return new PrincipalPolicyFragment({ Federated: [ this.federated ] }, this.conditions); - } -} - -export class AccountRootPrincipal extends AccountPrincipal { - constructor() { - super(new StackDependentToken(stack => stack.accountId).toString()); - } -} - -/** - * A principal representing all identities in all accounts - */ -export class AnyPrincipal extends ArnPrincipal { - constructor() { - super('*'); - } -} - -/** - * A principal representing all identities in all accounts - * @deprecated use `AnyPrincipal` - */ -export class Anyone extends AnyPrincipal { } - -export class CompositePrincipal extends PolicyPrincipal { - private readonly principals = new Array(); - - constructor(principal: PolicyPrincipal, ...additionalPrincipals: PolicyPrincipal[]) { - super(); - this.assumeRoleAction = principal.assumeRoleAction; - this.addPrincipals(principal); - this.addPrincipals(...additionalPrincipals); - } - - public addPrincipals(...principals: PolicyPrincipal[]): this { - for (const p of principals) { - if (p.assumeRoleAction !== this.assumeRoleAction) { - throw new Error( - `Cannot add multiple principals with different "assumeRoleAction". ` + - `Expecting "${this.assumeRoleAction}", got "${p.assumeRoleAction}"`); - } - - const fragment = p.policyFragment(); - if (fragment.conditions && Object.keys(fragment.conditions).length > 0) { - throw new Error( - `Components of a CompositePrincipal must not have conditions. ` + - `Tried to add the following fragment: ${JSON.stringify(fragment)}`); - } - - this.principals.push(p); - } - - return this; - } - - public policyFragment(): PrincipalPolicyFragment { - const principalJson: { [key: string]: string[] } = { }; - - for (const p of this.principals) { - mergePrincipal(principalJson, p.policyFragment().principalJson); - } - - return new PrincipalPolicyFragment(principalJson); - } -} - /** * Represents a statement in an IAM policy document. */ @@ -239,8 +86,8 @@ export class PolicyStatement extends cdk.Token { return Object.keys(this.principal).length > 0; } - public addPrincipal(principal: PolicyPrincipal): this { - const fragment = principal.policyFragment(); + public addPrincipal(principal: IPrincipal): this { + const fragment = principal.policyFragment; mergePrincipal(this.principal, fragment.principalJson); this.addConditions(fragment.conditions); return this; @@ -434,32 +281,3 @@ export enum PolicyStatementEffect { Allow = 'Allow', Deny = 'Deny', } - -function mergePrincipal(target: { [key: string]: string[] }, source: { [key: string]: string[] }) { - for (const key of Object.keys(source)) { - target[key] = target[key] || []; - - const value = source[key]; - if (!Array.isArray(value)) { - throw new Error(`Principal value must be an array (it will be normalized later): ${value}`); - } - - target[key].push(...value); - } - - return target; -} - -/** - * A lazy token that requires an instance of Stack to evaluate - */ -class StackDependentToken extends cdk.Token { - constructor(private readonly fn: (stack: cdk.Stack) => any) { - super(); - } - - public resolve(context: cdk.ResolveContext) { - const stack = cdk.Stack.find(context.scope); - return this.fn(stack); - } -} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-iam/lib/policy.ts b/packages/@aws-cdk/aws-iam/lib/policy.ts index 2121441970a85..a1efb7c834d61 100644 --- a/packages/@aws-cdk/aws-iam/lib/policy.ts +++ b/packages/@aws-cdk/aws-iam/lib/policy.ts @@ -1,46 +1,11 @@ import { Construct, IDependable, Token } from '@aws-cdk/cdk'; import { Group } from './group'; import { CfnPolicy } from './iam.generated'; -import { PolicyDocument, PolicyPrincipal, PolicyStatement } from './policy-document'; +import { PolicyDocument, PolicyStatement } from './policy-document'; import { IRole } from './role'; import { User } from './user'; import { generatePolicyName, undefinedIfEmpty } from './util'; -/** - * A construct that represents an IAM principal, such as a user, group or role. - */ -export interface IPrincipal { - /** - * The IAM principal of this identity (i.e. AWS principal, service principal, etc). - */ - readonly principal: PolicyPrincipal; - - /** - * Adds an IAM statement to the default inline policy associated with this - * principal. If a policy doesn't exist, it is created. - */ - addToPolicy(statement: PolicyStatement): void; - - /** - * Attaches an inline policy to this principal. - * This is the same as calling `policy.addToXxx(principal)`. - * @param policy The policy resource to attach to this principal. - */ - attachInlinePolicy(policy: Policy): void; - - /** - * Attaches a managed policy to this principal. - * @param arn The ARN of the managed policy - */ - attachManagedPolicy(arn: string): void; -} - -/** - * @deprecated Use IPrincipal - */ -// tslint:disable-next-line:no-empty-interface -export type IIdentityResource = IPrincipal; - export interface PolicyProps { /** * The name of the policy. If you specify multiple policies for an entity, diff --git a/packages/@aws-cdk/aws-iam/lib/principals.ts b/packages/@aws-cdk/aws-iam/lib/principals.ts new file mode 100644 index 0000000000000..762a3041038cb --- /dev/null +++ b/packages/@aws-cdk/aws-iam/lib/principals.ts @@ -0,0 +1,189 @@ +import cdk = require('@aws-cdk/cdk'); +import { mergePrincipal } from './util'; + +/** + * Represents an IAM principal. + * + * An IAM principal is any object that can have + */ +export interface IPrincipal { + /** + * When this Principal is used in an AssumeRole policy, the action to use. + */ + readonly assumeRoleAction: string; + + /** + * Return the policy fragment that identifies this principal in a Policy. + */ + readonly policyFragment: PrincipalPolicyFragment; +} + +/** + * Base class for policy principals + */ +export abstract class PrincipalBase implements IPrincipal { + /** + * When this Principal is used in an AssumeRole policy, the action to use. + */ + public assumeRoleAction: string = 'sts:AssumeRole'; + + /** + * Return the policy fragment that identifies this principal in a Policy. + */ + public abstract policyFragment: PrincipalPolicyFragment; +} + +/** + * A collection of the fields in a PolicyStatement that can be used to identify a principal. + * + * This consists of the JSON used in the "Principal" field, and optionally a + * set of "Condition"s that need to be applied to the policy. + */ +export class PrincipalPolicyFragment { + constructor( + public readonly principalJson: { [key: string]: string[] }, + public readonly conditions: { [key: string]: any } = { }) { + } +} + +export class ArnPrincipal extends PrincipalBase { + constructor(public readonly arn: string) { + super(); + } + + public get policyFragment(): PrincipalPolicyFragment { + return new PrincipalPolicyFragment({ AWS: [ this.arn ] }); + } +} + +export class AccountPrincipal extends ArnPrincipal { + constructor(public readonly accountId: any) { + super(new StackDependentToken(stack => `arn:${stack.partition}:iam::${accountId}:root`).toString()); + } +} + +/** + * An IAM principal that represents an AWS service (i.e. sqs.amazonaws.com). + */ +export class ServicePrincipal extends PrincipalBase { + constructor(public readonly service: string) { + super(); + } + + public get policyFragment(): PrincipalPolicyFragment { + return new PrincipalPolicyFragment({ Service: [ this.service ] }); + } +} + +/** + * A policy prinicipal for canonicalUserIds - useful for S3 bucket policies that use + * Origin Access identities. + * + * See https://docs.aws.amazon.com/general/latest/gr/acct-identifiers.html + * + * and + * + * https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/private-content-restricting-access-to-s3.html + * + * for more details. + * + */ +export class CanonicalUserPrincipal extends PrincipalBase { + constructor(public readonly canonicalUserId: string) { + super(); + } + + public get policyFragment(): PrincipalPolicyFragment { + return new PrincipalPolicyFragment({ CanonicalUser: [ this.canonicalUserId ] }); + } +} + +export class FederatedPrincipal extends PrincipalBase { + constructor( + public readonly federated: string, + public readonly conditions: {[key: string]: any}, + public assumeRoleAction: string = 'sts:AssumeRole') { + super(); + } + + public get policyFragment(): PrincipalPolicyFragment { + return new PrincipalPolicyFragment({ Federated: [ this.federated ] }, this.conditions); + } +} + +export class AccountRootPrincipal extends AccountPrincipal { + constructor() { + super(new StackDependentToken(stack => stack.accountId).toString()); + } +} + +/** + * A principal representing all identities in all accounts + */ +export class AnyPrincipal extends ArnPrincipal { + constructor() { + super('*'); + } +} + +/** + * A principal representing all identities in all accounts + * @deprecated use `AnyPrincipal` + */ +export class Anyone extends AnyPrincipal { } + +export class CompositePrincipal extends PrincipalBase { + private readonly principals = new Array(); + + constructor(principal: PrincipalBase, ...additionalPrincipals: PrincipalBase[]) { + super(); + this.assumeRoleAction = principal.assumeRoleAction; + this.addPrincipals(principal); + this.addPrincipals(...additionalPrincipals); + } + + public addPrincipals(...principals: PrincipalBase[]): this { + for (const p of principals) { + if (p.assumeRoleAction !== this.assumeRoleAction) { + throw new Error( + `Cannot add multiple principals with different "assumeRoleAction". ` + + `Expecting "${this.assumeRoleAction}", got "${p.assumeRoleAction}"`); + } + + const fragment = p.policyFragment; + if (fragment.conditions && Object.keys(fragment.conditions).length > 0) { + throw new Error( + `Components of a CompositePrincipal must not have conditions. ` + + `Tried to add the following fragment: ${JSON.stringify(fragment)}`); + } + + this.principals.push(p); + } + + return this; + } + + public get policyFragment(): PrincipalPolicyFragment { + const principalJson: { [key: string]: string[] } = { }; + + for (const p of this.principals) { + mergePrincipal(principalJson, p.policyFragment.principalJson); + } + + return new PrincipalPolicyFragment(principalJson); + } +} + +/** + * A lazy token that requires an instance of Stack to evaluate + */ +class StackDependentToken extends cdk.Token { + constructor(private readonly fn: (stack: cdk.Stack) => any) { + super(); + } + + public resolve(context: cdk.ResolveContext) { + const stack = cdk.Stack.find(context.scope); + return this.fn(stack); + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-iam/lib/role.ts b/packages/@aws-cdk/aws-iam/lib/role.ts index 3f83f67c401e4..c5c7e6e050ea5 100644 --- a/packages/@aws-cdk/aws-iam/lib/role.ts +++ b/packages/@aws-cdk/aws-iam/lib/role.ts @@ -1,7 +1,9 @@ import { Construct, IConstruct, IDependable, Output, Stack } from '@aws-cdk/cdk'; import { CfnRole } from './iam.generated'; -import { IPrincipal, Policy } from './policy'; -import { ArnPrincipal, PolicyDocument, PolicyPrincipal, PolicyStatement } from './policy-document'; +import { IIdentity } from './identity-base'; +import { Policy } from './policy'; +import { PolicyDocument, PolicyStatement } from './policy-document'; +import { ArnPrincipal, IPrincipal, PrincipalPolicyFragment } from './principals'; import { AttachedPolicies, undefinedIfEmpty } from './util'; export interface RoleProps { @@ -12,7 +14,7 @@ export interface RoleProps { * You can later modify the assume role policy document by accessing it via * the `assumeRolePolicy` property. */ - assumedBy: PolicyPrincipal; + assumedBy: IPrincipal; /** * ID that the role assumer needs to provide when assuming this role @@ -98,6 +100,8 @@ export class Role extends Construct implements IRole { return new ImportedRole(scope, id, props); } + public readonly assumeRoleAction: string = 'sts:AssumeRole'; + /** * The assume role policy document associated with this role. */ @@ -119,16 +123,13 @@ export class Role extends Construct implements IRole { */ public readonly roleName: string; - /** - * Returns the ARN of this role. - */ - public readonly principal: PolicyPrincipal; - /** * Returns the role. */ public readonly dependencyElements: IDependable[]; + public readonly policyFragment: PrincipalPolicyFragment; + private defaultPolicy?: Policy; private readonly managedPolicyArns: string[]; private readonly attachedPolicies = new AttachedPolicies(); @@ -152,9 +153,9 @@ export class Role extends Construct implements IRole { this.roleId = role.roleId; this.roleArn = role.roleArn; - this.principal = new ArnPrincipal(this.roleArn); this.roleName = role.roleName; this.dependencyElements = [ role ]; + this.policyFragment = new ArnPrincipal(this.roleArn).policyFragment; function _flatten(policies?: { [name: string]: PolicyDocument }) { if (policies == null || Object.keys(policies).length === 0) { @@ -211,7 +212,7 @@ export class Role extends Construct implements IRole { /** * A Role object */ -export interface IRole extends IConstruct, IPrincipal, IDependable { +export interface IRole extends IConstruct, IIdentity, IDependable { /** * Returns the ARN of this role. */ @@ -234,7 +235,7 @@ export interface IRole extends IConstruct, IPrincipal, IDependable { export(): RoleImportProps; } -function createAssumeRolePolicy(principal: PolicyPrincipal, externalId?: string) { +function createAssumeRolePolicy(principal: IPrincipal, externalId?: string) { const statement = new PolicyStatement(); statement .addPrincipal(principal) @@ -280,8 +281,9 @@ export interface RoleImportProps { * A role that already exists */ class ImportedRole extends Construct implements IRole { + public readonly assumeRoleAction: string = 'sts:AssumeRole'; + public readonly policyFragment: PrincipalPolicyFragment; public readonly roleArn: string; - public readonly principal: PolicyPrincipal; public readonly dependencyElements: IDependable[] = []; private readonly _roleId?: string; @@ -290,7 +292,7 @@ class ImportedRole extends Construct implements IRole { super(scope, id); this.roleArn = props.roleArn; this._roleId = props.roleId; - this.principal = new ArnPrincipal(this.roleArn); + this.policyFragment = new ArnPrincipal(this.roleArn).policyFragment; } public get roleId() { diff --git a/packages/@aws-cdk/aws-iam/lib/user.ts b/packages/@aws-cdk/aws-iam/lib/user.ts index 9ddca09349783..b0dc4374f2724 100644 --- a/packages/@aws-cdk/aws-iam/lib/user.ts +++ b/packages/@aws-cdk/aws-iam/lib/user.ts @@ -1,8 +1,10 @@ import { Construct } from '@aws-cdk/cdk'; import { Group } from './group'; import { CfnUser } from './iam.generated'; -import { IPrincipal, Policy } from './policy'; -import { ArnPrincipal, PolicyPrincipal, PolicyStatement } from './policy-document'; +import { IIdentity } from './identity-base'; +import { Policy } from './policy'; +import { PolicyStatement } from './policy-document'; +import { ArnPrincipal, PrincipalPolicyFragment } from './principals'; import { AttachedPolicies, undefinedIfEmpty } from './util'; export interface UserProps { @@ -62,7 +64,8 @@ export interface UserProps { passwordResetRequired?: boolean; } -export class User extends Construct implements IPrincipal { +export class User extends Construct implements IIdentity { + public readonly assumeRoleAction: string = 'sts:AssumeRole'; /** * An attribute that represents the user name. @@ -74,10 +77,7 @@ export class User extends Construct implements IPrincipal { */ public readonly userArn: string; - /** - * Returns the ARN of this user. - */ - public readonly principal: PolicyPrincipal; + public readonly policyFragment: PrincipalPolicyFragment; private readonly groups = new Array(); private readonly managedPolicyArns = new Array(); @@ -97,7 +97,7 @@ export class User extends Construct implements IPrincipal { this.userName = user.userName; this.userArn = user.userArn; - this.principal = new ArnPrincipal(this.userArn); + this.policyFragment = new ArnPrincipal(this.userArn).policyFragment; if (props.groups) { props.groups.forEach(g => this.addToGroup(g)); diff --git a/packages/@aws-cdk/aws-iam/lib/util.ts b/packages/@aws-cdk/aws-iam/lib/util.ts index aeb0f2c39652f..f8ae203a37552 100644 --- a/packages/@aws-cdk/aws-iam/lib/util.ts +++ b/packages/@aws-cdk/aws-iam/lib/util.ts @@ -44,3 +44,18 @@ export class AttachedPolicies { this.policies.push(policy); } } + +export function mergePrincipal(target: { [key: string]: string[] }, source: { [key: string]: string[] }) { + for (const key of Object.keys(source)) { + target[key] = target[key] || []; + + const value = source[key]; + if (!Array.isArray(value)) { + throw new Error(`Principal value must be an array (it will be normalized later): ${value}`); + } + + target[key].push(...value); + } + + return target; +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-iam/test/test.policy-document.ts b/packages/@aws-cdk/aws-iam/test/test.policy-document.ts index 97eeef42f95aa..5d3b15b162116 100644 --- a/packages/@aws-cdk/aws-iam/test/test.policy-document.ts +++ b/packages/@aws-cdk/aws-iam/test/test.policy-document.ts @@ -1,6 +1,6 @@ import { Stack, Token } from '@aws-cdk/cdk'; import { Test } from 'nodeunit'; -import { Anyone, AnyPrincipal, CanonicalUserPrincipal, PolicyDocument, PolicyPrincipal, PolicyStatement } from '../lib'; +import { Anyone, AnyPrincipal, CanonicalUserPrincipal, PolicyDocument, PolicyStatement, PrincipalBase } from '../lib'; import { ArnPrincipal, CompositePrincipal, FederatedPrincipal, PrincipalPolicyFragment, ServicePrincipal } from '../lib'; export = { @@ -278,9 +278,9 @@ export = { 'addPrincipal correctly merges array in'(test: Test) { const stack = new Stack(); - const arrayPrincipal: PolicyPrincipal = { + const arrayPrincipal: PrincipalBase = { assumeRoleAction: 'sts:AssumeRole', - policyFragment: () => new PrincipalPolicyFragment({ AWS: ['foo', 'bar'] }), + policyFragment: new PrincipalPolicyFragment({ AWS: ['foo', 'bar'] }), }; const s = new PolicyStatement().addAccountRootPrincipal() .addPrincipal(arrayPrincipal); From be0ec5d397442702548d0bbecca22462ce7e0a2e Mon Sep 17 00:00:00 2001 From: Rico Huijbers Date: Mon, 28 Jan 2019 13:03:06 +0100 Subject: [PATCH 02/31] feat(aws-iam): grants support non-identity principals Add support for non-identity Principals in grants (for example, principals that represent accounts or organization IDs). For resources that support them, the required IAM statements will be added to the resource policy. For resources that don't support them (because they don't have resource policies) an error will be thrown. Add a new `OrganizationPrincipal` principal which represents all identities in the given AWS Organization. Fixes #236. --- .../test/test.pipeline-actions.ts | 3 +- .../@aws-cdk/aws-cloudwatch/lib/metric.ts | 14 ++--- packages/@aws-cdk/aws-dynamodb/lib/table.ts | 37 ++++++------ .../@aws-cdk/aws-ecr/lib/repository-ref.ts | 31 +++++----- packages/@aws-cdk/aws-iam/lib/group.ts | 3 +- .../@aws-cdk/aws-iam/lib/identity-base.ts | 14 +---- packages/@aws-cdk/aws-iam/lib/index.ts | 1 + packages/@aws-cdk/aws-iam/lib/lazy-role.ts | 16 ++--- packages/@aws-cdk/aws-iam/lib/principals.ts | 29 +++++++++ packages/@aws-cdk/aws-iam/lib/role.ts | 8 ++- packages/@aws-cdk/aws-iam/lib/user.ts | 3 +- .../aws-iam/test/test.policy-document.ts | 1 + packages/@aws-cdk/aws-kinesis/lib/stream.ts | 6 +- packages/@aws-cdk/aws-kms/lib/key.ts | 60 +++++++++++++++++++ .../@aws-cdk/aws-lambda/lib/lambda-ref.ts | 25 +++++--- .../@aws-cdk/aws-lambda/lib/permission.ts | 4 +- packages/@aws-cdk/aws-logs/lib/log-group.ts | 12 ++-- packages/@aws-cdk/aws-s3/lib/bucket.ts | 27 +++------ packages/@aws-cdk/aws-s3/test/test.bucket.ts | 59 ++++++++++++++++++ packages/@aws-cdk/aws-sns/lib/topic-ref.ts | 15 +++-- packages/@aws-cdk/aws-sqs/lib/queue-ref.ts | 19 +++--- 21 files changed, 266 insertions(+), 121 deletions(-) diff --git a/packages/@aws-cdk/aws-cloudformation/test/test.pipeline-actions.ts b/packages/@aws-cdk/aws-cloudformation/test/test.pipeline-actions.ts index 65820d877ff1b..841260c6358c4 100644 --- a/packages/@aws-cdk/aws-cloudformation/test/test.pipeline-actions.ts +++ b/packages/@aws-cdk/aws-cloudformation/test/test.pipeline-actions.ts @@ -344,9 +344,10 @@ class RoleDouble extends iam.Role { super(scope, id, props); } - public addToPolicy(statement: iam.PolicyStatement) { + public addToPolicy(statement: iam.PolicyStatement): boolean { super.addToPolicy(statement); this.statements.push(statement); + return true; } } diff --git a/packages/@aws-cdk/aws-cloudwatch/lib/metric.ts b/packages/@aws-cdk/aws-cloudwatch/lib/metric.ts index d3a5bc9b5d4e7..c2dacf3ac2ac2 100644 --- a/packages/@aws-cdk/aws-cloudwatch/lib/metric.ts +++ b/packages/@aws-cdk/aws-cloudwatch/lib/metric.ts @@ -85,14 +85,14 @@ export class Metric { /** * Grant permissions to the given identity to write metrics. * - * @param identity The IAM identity to give permissions to. + * @param principal The IAM identity to give permissions to. */ - public static grantPutMetricData(identity?: iam.IPrincipal) { - if (!identity) { return; } - - identity.addToPolicy(new iam.PolicyStatement() - .addAllResources() - .addAction("cloudwatch:PutMetricData")); + public static grantPutMetricData(principal?: iam.IPrincipal) { + iam.grant({ + principal, + actions: ['cloudwatch:PutMetricData'], + resourceArns: ['*'], + }); } public readonly dimensions?: DimensionHash; diff --git a/packages/@aws-cdk/aws-dynamodb/lib/table.ts b/packages/@aws-cdk/aws-dynamodb/lib/table.ts index 9fb9d7f887c5b..b540b1df7ec8b 100644 --- a/packages/@aws-cdk/aws-dynamodb/lib/table.ts +++ b/packages/@aws-cdk/aws-dynamodb/lib/table.ts @@ -185,12 +185,12 @@ export class Table extends Construct { * @param principal The principal (no-op if undefined) */ public static grantListStreams(principal?: iam.IPrincipal): void { - if (principal) { - principal.addToPolicy(new iam.PolicyStatement() - .addAction('dynamodb:ListStreams') - .addResource("*")); - } - } + iam.grant({ + principal, + actions: ['dynamodb:ListStreams'], + resourceArns: ['*'], + }); + } public readonly tableArn: string; public readonly tableName: string; @@ -443,12 +443,14 @@ export class Table extends Construct { * @param actions The set of actions to allow (i.e. "dynamodb:PutItem", "dynamodb:GetItem", ...) */ public grant(principal?: iam.IPrincipal, ...actions: string[]) { - if (!principal) { - return; - } - principal.addToPolicy(new iam.PolicyStatement() - .addResources(this.tableArn, new cdk.Token(() => this.hasIndex ? `${this.tableArn}/index/*` : new cdk.Aws().noValue).toString()) - .addActions(...actions)); + iam.grant({ + principal, + actions, + resourceArns: [ + this.tableArn, + new cdk.Token(() => this.hasIndex ? `${this.tableArn}/index/*` : new cdk.Aws().noValue).toString() + ] + }); } /** @@ -458,12 +460,11 @@ export class Table extends Construct { * @param actions The set of actions to allow (i.e. "dynamodb:DescribeStream", "dynamodb:GetRecords", ...) */ public grantStream(principal?: iam.IPrincipal, ...actions: string[]) { - if (!principal) { - return; - } - principal.addToPolicy(new iam.PolicyStatement() - .addResource(this.tableStreamArn) - .addActions(...actions)); + iam.grant({ + principal, + actions, + resourceArns: [this.tableStreamArn] + }); } /** diff --git a/packages/@aws-cdk/aws-ecr/lib/repository-ref.ts b/packages/@aws-cdk/aws-ecr/lib/repository-ref.ts index ad7e8870f7ac1..d65e58aa724af 100644 --- a/packages/@aws-cdk/aws-ecr/lib/repository-ref.ts +++ b/packages/@aws-cdk/aws-ecr/lib/repository-ref.ts @@ -212,26 +212,27 @@ export abstract class RepositoryBase extends cdk.Construct implements IRepositor /** * Grant the given principal identity permissions to perform the actions on this repository */ - public grant(identity?: iam.IPrincipal, ...actions: string[]) { - if (!identity) { - return; - } - identity.addToPolicy(new iam.PolicyStatement() - .addResource(this.repositoryArn) - .addActions(...actions)); + public grant(principal?: iam.IPrincipal, ...actions: string[]) { + iam.grant({ + principal, + actions, + resourceArns: [this.repositoryArn], + addToResourcePolicy: this.addToResourcePolicy.bind(this), + }); } /** * Grant the given identity permissions to use the images in this repository */ - public grantPull(identity?: iam.IPrincipal) { - this.grant(identity, "ecr:BatchCheckLayerAvailability", "ecr:GetDownloadUrlForLayer", "ecr:BatchGetImage"); - - if (identity) { - identity.addToPolicy(new iam.PolicyStatement() - .addActions("ecr:GetAuthorizationToken", "logs:CreateLogStream", "logs:PutLogEvents") - .addAllResources()); - } + public grantPull(principal?: iam.IPrincipal) { + this.grant(principal, "ecr:BatchCheckLayerAvailability", "ecr:GetDownloadUrlForLayer", "ecr:BatchGetImage"); + + iam.grant({ + principal, + actions: ["ecr:GetAuthorizationToken", "logs:CreateLogStream", "logs:PutLogEvents"], + resourceArns: ['*'], + skipResourcePolicy: true, + }); } /** diff --git a/packages/@aws-cdk/aws-iam/lib/group.ts b/packages/@aws-cdk/aws-iam/lib/group.ts index 421eae23db319..82ce3de305f1e 100644 --- a/packages/@aws-cdk/aws-iam/lib/group.ts +++ b/packages/@aws-cdk/aws-iam/lib/group.ts @@ -97,12 +97,13 @@ export class Group extends Construct implements IIdentity { /** * Adds an IAM statement to the default policy. */ - public addToPolicy(statement: PolicyStatement) { + public addToPolicy(statement: PolicyStatement): boolean { if (!this.defaultPolicy) { this.defaultPolicy = new Policy(this, 'DefaultPolicy'); this.defaultPolicy.attachToGroup(this); } this.defaultPolicy.addStatement(statement); + return true; } } diff --git a/packages/@aws-cdk/aws-iam/lib/identity-base.ts b/packages/@aws-cdk/aws-iam/lib/identity-base.ts index 83f899a0e83ae..a3e9c9b7eaace 100644 --- a/packages/@aws-cdk/aws-iam/lib/identity-base.ts +++ b/packages/@aws-cdk/aws-iam/lib/identity-base.ts @@ -1,7 +1,6 @@ -import cdk = require('@aws-cdk/cdk'); import { Policy } from "./policy"; import { PolicyStatement } from "./policy-document"; -import { IPrincipal, PrincipalPolicyFragment } from "./principals"; +import { IPrincipal } from "./principals"; /** * A construct that represents an IAM principal, such as a user, group or role. @@ -11,7 +10,7 @@ export interface IIdentity extends IPrincipal { * Adds an IAM statement to the default inline policy associated with this * principal. If a policy doesn't exist, it is created. */ - addToPolicy(statement: PolicyStatement): void; + addToPolicy(statement: PolicyStatement): boolean; /** * Attaches an inline policy to this principal. @@ -25,13 +24,4 @@ export interface IIdentity extends IPrincipal { * @param arn The ARN of the managed policy */ attachManagedPolicy(arn: string): void; -} - -export abstract class IdentityBase extends cdk.Construct implements IIdentity { - public readonly assumeRoleAction: string = 'sts:AssumeRole'; - - public abstract policyFragment: PrincipalPolicyFragment; - public abstract addToPolicy(statement: PolicyStatement): void; - public abstract attachInlinePolicy(policy: Policy): void; - public abstract attachManagedPolicy(arn: string): void; } \ No newline at end of file diff --git a/packages/@aws-cdk/aws-iam/lib/index.ts b/packages/@aws-cdk/aws-iam/lib/index.ts index ce29004f943f3..11526872d93e7 100644 --- a/packages/@aws-cdk/aws-iam/lib/index.ts +++ b/packages/@aws-cdk/aws-iam/lib/index.ts @@ -7,6 +7,7 @@ export * from './group'; export * from './lazy-role'; export * from './principals'; export * from './identity-base'; +export * from './grant'; // AWS::IAM CloudFormation Resources: export * from './iam.generated'; diff --git a/packages/@aws-cdk/aws-iam/lib/lazy-role.ts b/packages/@aws-cdk/aws-iam/lib/lazy-role.ts index fcf8307fadb39..1e0ff661c7fd9 100644 --- a/packages/@aws-cdk/aws-iam/lib/lazy-role.ts +++ b/packages/@aws-cdk/aws-iam/lib/lazy-role.ts @@ -1,6 +1,7 @@ import cdk = require('@aws-cdk/cdk'); import { Policy } from './policy'; -import { PolicyPrincipal, PolicyStatement } from './policy-document'; +import { PolicyStatement } from './policy-document'; +import { PrincipalPolicyFragment } from './principals'; import { IRole, Role, RoleImportProps, RoleProps } from './role'; /** @@ -13,6 +14,7 @@ import { IRole, Role, RoleImportProps, RoleProps } from './role'; * not be synthesized or deployed. */ export class LazyRole extends cdk.Construct implements IRole { + public readonly assumeRoleAction: string = 'sts:AssumeRole'; private role?: Role; private readonly statements = new Array(); private readonly policies = new Array(); @@ -31,11 +33,12 @@ export class LazyRole extends cdk.Construct implements IRole { * If there is no default policy attached to this role, it will be created. * @param permission The permission statement to add to the policy document */ - public addToPolicy(statement: PolicyStatement): void { + public addToPolicy(statement: PolicyStatement): boolean { if (this.role) { - this.role.addToPolicy(statement); + return this.role.addToPolicy(statement); } else { this.statements.push(statement); + return true; } } @@ -85,11 +88,8 @@ export class LazyRole extends cdk.Construct implements IRole { return this.instantiate().roleName; } - /** - * Returns a Principal object representing the ARN of this role. - */ - public get principal(): PolicyPrincipal { - return this.instantiate().principal; + public get policyFragment(): PrincipalPolicyFragment { + return this.instantiate().policyFragment; } private instantiate(): Role { diff --git a/packages/@aws-cdk/aws-iam/lib/principals.ts b/packages/@aws-cdk/aws-iam/lib/principals.ts index 762a3041038cb..de943d9f0c8a0 100644 --- a/packages/@aws-cdk/aws-iam/lib/principals.ts +++ b/packages/@aws-cdk/aws-iam/lib/principals.ts @@ -1,4 +1,5 @@ import cdk = require('@aws-cdk/cdk'); +import { PolicyStatement } from './policy-document'; import { mergePrincipal } from './util'; /** @@ -16,6 +17,13 @@ export interface IPrincipal { * Return the policy fragment that identifies this principal in a Policy. */ readonly policyFragment: PrincipalPolicyFragment; + + /** + * Add to the policy of this principal. + * + * @returns true if the policy was added, false if the policy could not be added + */ + addToPolicy(statement: PolicyStatement): boolean; } /** @@ -31,6 +39,11 @@ export abstract class PrincipalBase implements IPrincipal { * Return the policy fragment that identifies this principal in a Policy. */ public abstract policyFragment: PrincipalPolicyFragment; + + public addToPolicy(_statement: PolicyStatement): boolean { + // None of these have a policy to add to + return false; + } } /** @@ -75,6 +88,22 @@ export class ServicePrincipal extends PrincipalBase { } } +/** + * A principal that represents an AWS Organization + */ +export class OrganizationPrincipal extends PrincipalBase { + constructor(public readonly organizationId: string) { + super(); + } + + public get policyFragment(): PrincipalPolicyFragment { + return new PrincipalPolicyFragment( + { AWS: ['*'] }, + { StringEquals: { 'aws:PrincipalOrgID': this.organizationId } } + ); + } +} + /** * A policy prinicipal for canonicalUserIds - useful for S3 bucket policies that use * Origin Access identities. diff --git a/packages/@aws-cdk/aws-iam/lib/role.ts b/packages/@aws-cdk/aws-iam/lib/role.ts index c5c7e6e050ea5..ab9a62bd24ffd 100644 --- a/packages/@aws-cdk/aws-iam/lib/role.ts +++ b/packages/@aws-cdk/aws-iam/lib/role.ts @@ -182,13 +182,14 @@ export class Role extends Construct implements IRole { * If there is no default policy attached to this role, it will be created. * @param permission The permission statement to add to the policy document */ - public addToPolicy(statement: PolicyStatement) { + public addToPolicy(statement: PolicyStatement): boolean { if (!this.defaultPolicy) { this.defaultPolicy = new Policy(this, 'DefaultPolicy'); this.attachInlinePolicy(this.defaultPolicy); this.dependencyElements.push(this.defaultPolicy); } this.defaultPolicy.addStatement(statement); + return true; } /** @@ -310,8 +311,9 @@ class ImportedRole extends Construct implements IRole { return this.props; } - public addToPolicy(_statement: PolicyStatement): void { - // FIXME: Add warning that we're ignoring this + public addToPolicy(_statement: PolicyStatement): boolean { + // Statement will be added to resource instead + return false; } public attachInlinePolicy(_policy: Policy): void { diff --git a/packages/@aws-cdk/aws-iam/lib/user.ts b/packages/@aws-cdk/aws-iam/lib/user.ts index b0dc4374f2724..17a4e956ea445 100644 --- a/packages/@aws-cdk/aws-iam/lib/user.ts +++ b/packages/@aws-cdk/aws-iam/lib/user.ts @@ -130,13 +130,14 @@ export class User extends Construct implements IIdentity { /** * Adds an IAM statement to the default policy. */ - public addToPolicy(statement: PolicyStatement) { + public addToPolicy(statement: PolicyStatement): boolean { if (!this.defaultPolicy) { this.defaultPolicy = new Policy(this, 'DefaultPolicy'); this.defaultPolicy.attachToUser(this); } this.defaultPolicy.addStatement(statement); + return true; } private parseLoginProfile(props: UserProps): CfnUser.LoginProfileProperty | undefined { diff --git a/packages/@aws-cdk/aws-iam/test/test.policy-document.ts b/packages/@aws-cdk/aws-iam/test/test.policy-document.ts index 5d3b15b162116..b2ccb35e24dba 100644 --- a/packages/@aws-cdk/aws-iam/test/test.policy-document.ts +++ b/packages/@aws-cdk/aws-iam/test/test.policy-document.ts @@ -281,6 +281,7 @@ export = { const arrayPrincipal: PrincipalBase = { assumeRoleAction: 'sts:AssumeRole', policyFragment: new PrincipalPolicyFragment({ AWS: ['foo', 'bar'] }), + addToPolicy() { return false; } }; const s = new PolicyStatement().addAccountRootPrincipal() .addPrincipal(arrayPrincipal); diff --git a/packages/@aws-cdk/aws-kinesis/lib/stream.ts b/packages/@aws-cdk/aws-kinesis/lib/stream.ts index 0b569ccf07227..8b57408893120 100644 --- a/packages/@aws-cdk/aws-kinesis/lib/stream.ts +++ b/packages/@aws-cdk/aws-kinesis/lib/stream.ts @@ -255,14 +255,14 @@ export abstract class StreamBase extends cdk.Construct implements IStream { return dest.logSubscriptionDestination(sourceLogGroup); } - private grant(identity: iam.IPrincipal, actions: { streamActions: string[], keyActions: string[] }) { - identity.addToPolicy(new iam.PolicyStatement() + private grant(principal: iam.IPrincipal, actions: { streamActions: string[], keyActions: string[] }) { + principal.addToPolicy(new iam.PolicyStatement() .addResource(this.streamArn) .addActions(...actions.streamActions)); // grant key permissions if there's an associated key. if (this.encryptionKey) { - identity.addToPolicy(new iam.PolicyStatement() + principal.addToPolicy(new iam.PolicyStatement() .addResource(this.encryptionKey.keyArn) .addActions(...actions.keyActions)); } diff --git a/packages/@aws-cdk/aws-kms/lib/key.ts b/packages/@aws-cdk/aws-kms/lib/key.ts index 7b259bfb8fc25..d162a165fe188 100644 --- a/packages/@aws-cdk/aws-kms/lib/key.ts +++ b/packages/@aws-cdk/aws-kms/lib/key.ts @@ -1,3 +1,4 @@ +import iam = require('@aws-cdk/aws-iam'); import { PolicyDocument, PolicyStatement } from '@aws-cdk/aws-iam'; import { Construct, DeletionPolicy, IConstruct, Output, TagManager, Tags } from '@aws-cdk/cdk'; import { EncryptionKeyAlias } from './alias'; @@ -28,6 +29,21 @@ export interface IEncryptionKey extends IConstruct { * @returns a key ref which can be used in a call to `EncryptionKey.import(ref)`. */ export(): EncryptionKeyImportProps; + + /** + * Grant the indicated permissions on this key to the given principal + */ + grant(principal: iam.IPrincipal | undefined, actions: string[]): void; + + /** + * Grant decryption permisisons using this key to the given principal + */ + grantDecrypt(principal: iam.IPrincipal | undefined): void; + + /** + * Grant encryption permisisons using this key to the given principal + */ + grantEncrypt(principal: iam.IPrincipal | undefined): void; } export interface EncryptionKeyImportProps { @@ -75,6 +91,50 @@ export abstract class EncryptionKeyBase extends Construct { } public abstract export(): EncryptionKeyImportProps; + + /** + * Grant the indicated permissions on this key to the given principal + * + * This modifies both the principal's policy as well as the resource policy, + * since the default CloudFormation setup for KMS keys is that the policy + * must not be empty and so default grants won't work. + */ + public grant(principal: iam.IPrincipal | undefined, actions: string[]): void { + iam.grant({ + principal, + actions, + resourceArns: [this.keyArn], + skipResourcePolicy: true, + }); + + if (principal) { + this.addToResourcePolicy(new iam.PolicyStatement() + .addPrincipal(principal) + .addActions(...actions) + .addAllResources()); + } + } + + /** + * Grant decryption permisisons using this key to the given principal + */ + public grantDecrypt(principal: iam.IPrincipal | undefined): void { + return this.grant(principal, [ + 'kms:Decrypt', + 'kms:DescribeKey', + ]); + } + + /** + * Grant encryption permisisons using this key to the given principal + */ + public grantEncrypt(principal: iam.IPrincipal | undefined): void { + return this.grant(principal, [ + 'kms:Encrypt', + 'kms:ReEncrypt*', + 'kms:GenerateDataKey*' + ]); + } } /** diff --git a/packages/@aws-cdk/aws-lambda/lib/lambda-ref.ts b/packages/@aws-cdk/aws-lambda/lib/lambda-ref.ts index 8c241d5428af6..e7c5fb11953ee 100644 --- a/packages/@aws-cdk/aws-lambda/lib/lambda-ref.ts +++ b/packages/@aws-cdk/aws-lambda/lib/lambda-ref.ts @@ -267,11 +267,23 @@ export abstract class FunctionBase extends cdk.Construct implements IFunction { /** * Grant the given identity permissions to invoke this Lambda */ - public grantInvoke(identity?: iam.IPrincipal) { - if (identity) { - identity.addToPolicy(new iam.PolicyStatement() - .addAction('lambda:InvokeFunction') - .addResource(this.functionArn)); + public grantInvoke(principal?: iam.IPrincipal) { + const added = iam.grant({ + principal, + actions: ['lambda:InvokeFunction'], + resourceArns: [this.functionArn], + // Can't use a resource policy because adding resource permissions + // looks different on a Lambda Function. + skipResourcePolicy: true + }); + + if (!added && principal) { + // Couldn't add permissions to the principal, so add them locally. + const identifier = 'Invoke' + JSON.stringify(principal!.policyFragment.principalJson); + this.addPermission(identifier, { + principal, + action: 'lambda:InvokeFunction', + }); } } @@ -401,11 +413,10 @@ export abstract class FunctionBase extends cdk.Construct implements IFunction { source.bind(this); } - private parsePermissionPrincipal(principal?: iam.PolicyPrincipal) { + private parsePermissionPrincipal(principal?: iam.IPrincipal) { if (!principal) { return undefined; } - // use duck-typing, not instance of if ('accountId' in principal) { diff --git a/packages/@aws-cdk/aws-lambda/lib/permission.ts b/packages/@aws-cdk/aws-lambda/lib/permission.ts index de4ab91c6794d..91fb834c9045d 100644 --- a/packages/@aws-cdk/aws-lambda/lib/permission.ts +++ b/packages/@aws-cdk/aws-lambda/lib/permission.ts @@ -1,4 +1,4 @@ -import { PolicyPrincipal } from '@aws-cdk/aws-iam'; +import iam = require('@aws-cdk/aws-iam'); /** * Represents a permission statement that can be added to a Lambda's resource policy @@ -34,7 +34,7 @@ export interface Permission { * * The principal can be either an AccountPrincipal or a ServicePrincipal. */ - principal: PolicyPrincipal; + principal: iam.IPrincipal; /** * The AWS account ID (without hyphens) of the source owner. For example, if diff --git a/packages/@aws-cdk/aws-logs/lib/log-group.ts b/packages/@aws-cdk/aws-logs/lib/log-group.ts index 4f548fd295bdc..42c5775264c29 100644 --- a/packages/@aws-cdk/aws-logs/lib/log-group.ts +++ b/packages/@aws-cdk/aws-logs/lib/log-group.ts @@ -179,13 +179,13 @@ export abstract class LogGroupBase extends cdk.Construct implements ILogGroup { * Give the indicated permissions on this log group and all streams */ public grant(principal?: iam.IPrincipal, ...actions: string[]) { - if (!principal) { return; } - - principal.addToPolicy(new iam.PolicyStatement() - .addActions(...actions) - // This ARN includes a ':*' at the end to include the log streams. + iam.grant({ + principal, + actions, + // A LogGroup ARN out of CloudFormation already includes a ':*' at the end to include the log streams under the group. // See https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-logs-loggroup.html#w2ab1c21c10c63c43c11 - .addResource(`${this.logGroupArn}`)); + resourceArns: [this.logGroupArn] + }); } } diff --git a/packages/@aws-cdk/aws-s3/lib/bucket.ts b/packages/@aws-cdk/aws-s3/lib/bucket.ts index b33445332bbab..3dd7d06e0f93f 100644 --- a/packages/@aws-cdk/aws-s3/lib/bucket.ts +++ b/packages/@aws-cdk/aws-s3/lib/bucket.ts @@ -503,32 +503,21 @@ export abstract class BucketBase extends cdk.Construct implements IBucket { return statement; } - private grant(identity: iam.IPrincipal | undefined, + private grant(principal: iam.IPrincipal | undefined, bucketActions: string[], keyActions: string[], resourceArn: string, ...otherResourceArns: string[]) { - - if (!identity) { - return; - } - const resources = [ resourceArn, ...otherResourceArns ]; - identity.addToPolicy(new iam.PolicyStatement() - .addResources(...resources) - .addActions(...bucketActions)); + iam.grant({ + principal, + actions: bucketActions, + resourceArns: resources, + addToResourcePolicy: this.addToResourcePolicy.bind(this), + }); - // grant key permissions if there's an associated key. if (this.encryptionKey) { - // KMS permissions need to be granted both directions - identity.addToPolicy(new iam.PolicyStatement() - .addResource(this.encryptionKey.keyArn) - .addActions(...keyActions)); - - this.encryptionKey.addToResourcePolicy(new iam.PolicyStatement() - .addAllResources() - .addPrincipal(identity.principal) - .addActions(...keyActions)); + this.encryptionKey.grant(principal, keyActions); } } } diff --git a/packages/@aws-cdk/aws-s3/test/test.bucket.ts b/packages/@aws-cdk/aws-s3/test/test.bucket.ts index 19c10b0840951..b1cca0910d834 100644 --- a/packages/@aws-cdk/aws-s3/test/test.bucket.ts +++ b/packages/@aws-cdk/aws-s3/test/test.bucket.ts @@ -673,6 +673,65 @@ export = { test.done(); }, + 'grant permissions to non-identity principal'(test: Test) { + // GIVEN + const stack = new cdk.Stack(); + const bucket = new s3.Bucket(stack, 'MyBucket', { encryption: s3.BucketEncryption.Kms }); + + // WHEN + bucket.grantRead(new iam.OrganizationPrincipal('o-1234')); + + // THEN + expect(stack).to(haveResource('AWS::S3::BucketPolicy', { + PolicyDocument: { + "Version": "2012-10-17", + "Statement": [ + { + "Action": [ "s3:GetObject*", "s3:GetBucket*", "s3:List*" ], + "Condition": { "StringEquals": { "aws:PrincipalOrgID": "o-1234" } }, + "Effect": "Allow", + "Principal": "*", + "Resource": [ + { "Fn::GetAtt": [ "MyBucketF68F3FF0", "Arn" ] }, + { "Fn::Join": [ "", [ { "Fn::GetAtt": [ "MyBucketF68F3FF0", "Arn" ] }, "/*" ] ] } + ] + } + ] + } + })); + + expect(stack).to(haveResource('AWS::KMS::Key', { + "KeyPolicy": { + "Statement": [ + { + "Action": [ "kms:Create*", "kms:Describe*", "kms:Enable*", "kms:List*", "kms:Put*", "kms:Update*", + "kms:Revoke*", "kms:Disable*", "kms:Get*", "kms:Delete*", "kms:ScheduleKeyDeletion", "kms:CancelKeyDeletion" ], + "Effect": "Allow", + "Principal": { + "AWS": { + "Fn::Join": [ "", [ + "arn:", { "Ref": "AWS::Partition" }, ":iam::", { "Ref": "AWS::AccountId" }, ":root" + ]] + } + }, + "Resource": "*" + }, + { + "Action": [ "kms:Decrypt", "kms:DescribeKey" ], + "Effect": "Allow", + "Resource": "*", + "Principal": "*", + "Condition": { "StringEquals": { "aws:PrincipalOrgID": "o-1234" } }, + } + ], + "Version": "2012-10-17" + }, + + })); + + test.done(); + }, + 'if an encryption key is included, encrypt/decrypt permissions are also added both ways'(test: Test) { const stack = new cdk.Stack(); const bucket = new s3.Bucket(stack, 'MyBucket', { encryption: s3.BucketEncryption.Kms }); diff --git a/packages/@aws-cdk/aws-sns/lib/topic-ref.ts b/packages/@aws-cdk/aws-sns/lib/topic-ref.ts index 4a562651af442..d6a749b1f88e7 100644 --- a/packages/@aws-cdk/aws-sns/lib/topic-ref.ts +++ b/packages/@aws-cdk/aws-sns/lib/topic-ref.ts @@ -285,14 +285,13 @@ export abstract class TopicBase extends cdk.Construct implements ITopic { /** * Grant topic publishing permissions to the given identity */ - public grantPublish(identity?: iam.IPrincipal) { - if (!identity) { - return; - } - - identity.addToPolicy(new iam.PolicyStatement() - .addResource(this.topicArn) - .addActions('sns:Publish')); + public grantPublish(principal?: iam.IPrincipal) { + iam.grant({ + principal, + actions: ['sns:Publish'], + resourceArns: [this.topicArn], + addToResourcePolicy: this.addToResourcePolicy.bind(this), + }); } /** diff --git a/packages/@aws-cdk/aws-sqs/lib/queue-ref.ts b/packages/@aws-cdk/aws-sqs/lib/queue-ref.ts index 69391f1257850..c452e6cb0f810 100644 --- a/packages/@aws-cdk/aws-sqs/lib/queue-ref.ts +++ b/packages/@aws-cdk/aws-sqs/lib/queue-ref.ts @@ -260,17 +260,16 @@ export abstract class QueueBase extends cdk.Construct implements IQueue { * Grant the actions defined in queueActions to the identity Principal given * on this SQS queue resource. * - * @param identity Principal to grant right to - * @param queueActions The actions to grant + * @param principal Principal to grant right to + * @param actions The actions to grant */ - public grant(identity?: iam.IPrincipal, ...queueActions: string[]) { - if (!identity) { - return; - } - - identity.addToPolicy(new iam.PolicyStatement() - .addResource(this.queueArn) - .addActions(...queueActions)); + public grant(principal?: iam.IPrincipal, ...actions: string[]) { + iam.grant({ + principal, + actions, + resourceArns: [this.queueArn], + addToResourcePolicy: this.addToResourcePolicy.bind(this), + }); } } From fcce2105d4e3fb157d3544b5f11efeb24d5c5dea Mon Sep 17 00:00:00 2001 From: Rico Huijbers Date: Mon, 28 Jan 2019 13:10:00 +0100 Subject: [PATCH 03/31] Forgot to add new file --- packages/@aws-cdk/aws-iam/lib/grant.ts | 78 ++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 packages/@aws-cdk/aws-iam/lib/grant.ts diff --git a/packages/@aws-cdk/aws-iam/lib/grant.ts b/packages/@aws-cdk/aws-iam/lib/grant.ts new file mode 100644 index 0000000000000..961a30413d88b --- /dev/null +++ b/packages/@aws-cdk/aws-iam/lib/grant.ts @@ -0,0 +1,78 @@ +import { PolicyStatement } from "./policy-document"; +import { IPrincipal } from "./principals"; + +/** + * Properties for a grant operation + */ +export interface GrantProps { + /** + * The principal to grant to + * + * @default No work is done + */ + principal?: IPrincipal; + + /** + * The actions to grant + */ + actions: string[]; + + /** + * The resource ARNs to grant to + */ + resourceArns: string[]; + + /** + * Adder to the resource policy + * + * @default Failure if no principal policy and `skipResourcePolicy` is not set. + */ + addToResourcePolicy?: (statement: PolicyStatement) => void; + + /** + * When referring to the resource in a resource policy, use this as ARN. + * + * (Depending on the resource type, this needs to be '*' in a resource policy). + * + * @default Same as regular resource ARNs + */ + resourceSelfArns?: string[]; + + /** + * If there is no resource policy, ignore the error + * + * @default false + */ + skipResourcePolicy?: boolean; +} + +/** + * Helper function to implement grants. + * + * The pattern is the same every time. We try to add to the principal + * first, then add to the resource afterwards. + * + * @returns false if `skipResourcePolicy` was used, true otherwise + */ +export function grant(props: GrantProps): boolean { + if (!props.principal) { return true; } + + const addedToPrincipal = props.principal.addToPolicy(new PolicyStatement() + .addActions(...props.actions) + .addResources(...props.resourceArns)); + + if (addedToPrincipal || props.skipResourcePolicy) { return false; } + + // This is a function so that it can be used by resources that lazily + // need to create a policy document (Queue, Bucket) which cannot have + // an empty policy. + if (!props.addToResourcePolicy) { + throw new Error('Could not add permissions to Principal without policy, and resource does not have policy either. Grant to a Role instead.'); + } + + props.addToResourcePolicy(new PolicyStatement() + .addActions(...props.actions) + .addResources(...(props.resourceSelfArns || props.resourceArns)) + .addPrincipal(props.principal)); + return true; +} \ No newline at end of file From d53d79405e77bd1c449771f2d6de84ee68205a19 Mon Sep 17 00:00:00 2001 From: Rico Huijbers Date: Mon, 11 Feb 2019 13:08:02 +0100 Subject: [PATCH 04/31] Undo move of principals to their own file --- packages/@aws-cdk/aws-iam/lib/group.ts | 3 +- packages/@aws-cdk/aws-iam/lib/lazy-role.ts | 2 +- .../@aws-cdk/aws-iam/lib/policy-document.ts | 194 ++++++++++++++++- packages/@aws-cdk/aws-iam/lib/principals.ts | 195 +----------------- packages/@aws-cdk/aws-iam/lib/role.ts | 4 +- packages/@aws-cdk/aws-iam/lib/user.ts | 2 +- 6 files changed, 199 insertions(+), 201 deletions(-) diff --git a/packages/@aws-cdk/aws-iam/lib/group.ts b/packages/@aws-cdk/aws-iam/lib/group.ts index 82ce3de305f1e..ae47133e88b97 100644 --- a/packages/@aws-cdk/aws-iam/lib/group.ts +++ b/packages/@aws-cdk/aws-iam/lib/group.ts @@ -2,8 +2,7 @@ import { Construct } from '@aws-cdk/cdk'; import { CfnGroup } from './iam.generated'; import { IIdentity } from './identity-base'; import { Policy } from './policy'; -import { PolicyStatement } from './policy-document'; -import { ArnPrincipal, PrincipalPolicyFragment } from './principals'; +import { PolicyStatement, PrincipalPolicyFragment, ArnPrincipal } from './policy-document'; import { User } from './user'; import { AttachedPolicies, undefinedIfEmpty } from './util'; diff --git a/packages/@aws-cdk/aws-iam/lib/lazy-role.ts b/packages/@aws-cdk/aws-iam/lib/lazy-role.ts index 973d3982adc30..7ae1987bca85b 100644 --- a/packages/@aws-cdk/aws-iam/lib/lazy-role.ts +++ b/packages/@aws-cdk/aws-iam/lib/lazy-role.ts @@ -1,7 +1,7 @@ import cdk = require('@aws-cdk/cdk'); import { Policy } from './policy'; import { PolicyStatement } from './policy-document'; -import { PrincipalPolicyFragment } from './principals'; +import { PrincipalPolicyFragment } from './policy-document'; import { IRole, Role, RoleImportProps, RoleProps } from './role'; /** diff --git a/packages/@aws-cdk/aws-iam/lib/policy-document.ts b/packages/@aws-cdk/aws-iam/lib/policy-document.ts index 968d318f9ff6a..df9d26f6b57be 100644 --- a/packages/@aws-cdk/aws-iam/lib/policy-document.ts +++ b/packages/@aws-cdk/aws-iam/lib/policy-document.ts @@ -1,6 +1,5 @@ import cdk = require('@aws-cdk/cdk'); -import { AccountPrincipal, AccountRootPrincipal, Anyone, - ArnPrincipal, CanonicalUserPrincipal, FederatedPrincipal, IPrincipal, ServicePrincipal } from './principals'; +import { IPrincipal } from './principals'; import { mergePrincipal } from './util'; export class PolicyDocument extends cdk.Token { @@ -45,6 +44,197 @@ export class PolicyDocument extends cdk.Token { } } +/** + * Base class for policy principals + */ +export abstract class PrincipalBase implements IPrincipal { + /** + * When this Principal is used in an AssumeRole policy, the action to use. + */ + public assumeRoleAction: string = 'sts:AssumeRole'; + + /** + * Return the policy fragment that identifies this principal in a Policy. + */ + public abstract policyFragment: PrincipalPolicyFragment; + + public addToPolicy(_statement: PolicyStatement): boolean { + // None of these have a policy to add to + return false; + } +} + +/** + * A collection of the fields in a PolicyStatement that can be used to identify a principal. + * + * This consists of the JSON used in the "Principal" field, and optionally a + * set of "Condition"s that need to be applied to the policy. + */ +export class PrincipalPolicyFragment { + constructor( + public readonly principalJson: { [key: string]: string[] }, + public readonly conditions: { [key: string]: any } = { }) { + } +} + +export class ArnPrincipal extends PrincipalBase { + constructor(public readonly arn: string) { + super(); + } + + public get policyFragment(): PrincipalPolicyFragment { + return new PrincipalPolicyFragment({ AWS: [ this.arn ] }); + } +} + +export class AccountPrincipal extends ArnPrincipal { + constructor(public readonly accountId: any) { + super(new StackDependentToken(stack => `arn:${stack.partition}:iam::${accountId}:root`).toString()); + } +} + +/** + * An IAM principal that represents an AWS service (i.e. sqs.amazonaws.com). + */ +export class ServicePrincipal extends PrincipalBase { + constructor(public readonly service: string) { + super(); + } + + public get policyFragment(): PrincipalPolicyFragment { + return new PrincipalPolicyFragment({ Service: [ this.service ] }); + } +} + +/** + * A principal that represents an AWS Organization + */ +export class OrganizationPrincipal extends PrincipalBase { + constructor(public readonly organizationId: string) { + super(); + } + + public get policyFragment(): PrincipalPolicyFragment { + return new PrincipalPolicyFragment( + { AWS: ['*'] }, + { StringEquals: { 'aws:PrincipalOrgID': this.organizationId } } + ); + } +} + +/** + * A policy prinicipal for canonicalUserIds - useful for S3 bucket policies that use + * Origin Access identities. + * + * See https://docs.aws.amazon.com/general/latest/gr/acct-identifiers.html + * + * and + * + * https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/private-content-restricting-access-to-s3.html + * + * for more details. + * + */ +export class CanonicalUserPrincipal extends PrincipalBase { + constructor(public readonly canonicalUserId: string) { + super(); + } + + public get policyFragment(): PrincipalPolicyFragment { + return new PrincipalPolicyFragment({ CanonicalUser: [ this.canonicalUserId ] }); + } +} + +export class FederatedPrincipal extends PrincipalBase { + constructor( + public readonly federated: string, + public readonly conditions: {[key: string]: any}, + public assumeRoleAction: string = 'sts:AssumeRole') { + super(); + } + + public get policyFragment(): PrincipalPolicyFragment { + return new PrincipalPolicyFragment({ Federated: [ this.federated ] }, this.conditions); + } +} + +export class AccountRootPrincipal extends AccountPrincipal { + constructor() { + super(new StackDependentToken(stack => stack.accountId).toString()); + } +} + +/** + * A principal representing all identities in all accounts + */ +export class AnyPrincipal extends ArnPrincipal { + constructor() { + super('*'); + } +} + +/** + * A principal representing all identities in all accounts + * @deprecated use `AnyPrincipal` + */ +export class Anyone extends AnyPrincipal { } + +export class CompositePrincipal extends PrincipalBase { + private readonly principals = new Array(); + + constructor(principal: PrincipalBase, ...additionalPrincipals: PrincipalBase[]) { + super(); + this.assumeRoleAction = principal.assumeRoleAction; + this.addPrincipals(principal); + this.addPrincipals(...additionalPrincipals); + } + + public addPrincipals(...principals: PrincipalBase[]): this { + for (const p of principals) { + if (p.assumeRoleAction !== this.assumeRoleAction) { + throw new Error( + `Cannot add multiple principals with different "assumeRoleAction". ` + + `Expecting "${this.assumeRoleAction}", got "${p.assumeRoleAction}"`); + } + + const fragment = p.policyFragment; + if (fragment.conditions && Object.keys(fragment.conditions).length > 0) { + throw new Error( + `Components of a CompositePrincipal must not have conditions. ` + + `Tried to add the following fragment: ${JSON.stringify(fragment)}`); + } + + this.principals.push(p); + } + + return this; + } + + public get policyFragment(): PrincipalPolicyFragment { + const principalJson: { [key: string]: string[] } = { }; + + for (const p of this.principals) { + mergePrincipal(principalJson, p.policyFragment.principalJson); + } + + return new PrincipalPolicyFragment(principalJson); + } +} + +/** + * A lazy token that requires an instance of Stack to evaluate + */ +class StackDependentToken extends cdk.Token { + constructor(private readonly fn: (stack: cdk.Stack) => any) { + super(); + } + + public resolve(context: cdk.ResolveContext) { + const stack = cdk.Stack.find(context.scope); + return this.fn(stack); + } +} + /** * Represents a statement in an IAM policy document. */ diff --git a/packages/@aws-cdk/aws-iam/lib/principals.ts b/packages/@aws-cdk/aws-iam/lib/principals.ts index de943d9f0c8a0..c971e10cfcf0b 100644 --- a/packages/@aws-cdk/aws-iam/lib/principals.ts +++ b/packages/@aws-cdk/aws-iam/lib/principals.ts @@ -1,6 +1,4 @@ -import cdk = require('@aws-cdk/cdk'); -import { PolicyStatement } from './policy-document'; -import { mergePrincipal } from './util'; +import { PolicyStatement, PrincipalPolicyFragment } from './policy-document'; /** * Represents an IAM principal. @@ -26,193 +24,4 @@ export interface IPrincipal { addToPolicy(statement: PolicyStatement): boolean; } -/** - * Base class for policy principals - */ -export abstract class PrincipalBase implements IPrincipal { - /** - * When this Principal is used in an AssumeRole policy, the action to use. - */ - public assumeRoleAction: string = 'sts:AssumeRole'; - - /** - * Return the policy fragment that identifies this principal in a Policy. - */ - public abstract policyFragment: PrincipalPolicyFragment; - - public addToPolicy(_statement: PolicyStatement): boolean { - // None of these have a policy to add to - return false; - } -} - -/** - * A collection of the fields in a PolicyStatement that can be used to identify a principal. - * - * This consists of the JSON used in the "Principal" field, and optionally a - * set of "Condition"s that need to be applied to the policy. - */ -export class PrincipalPolicyFragment { - constructor( - public readonly principalJson: { [key: string]: string[] }, - public readonly conditions: { [key: string]: any } = { }) { - } -} - -export class ArnPrincipal extends PrincipalBase { - constructor(public readonly arn: string) { - super(); - } - - public get policyFragment(): PrincipalPolicyFragment { - return new PrincipalPolicyFragment({ AWS: [ this.arn ] }); - } -} - -export class AccountPrincipal extends ArnPrincipal { - constructor(public readonly accountId: any) { - super(new StackDependentToken(stack => `arn:${stack.partition}:iam::${accountId}:root`).toString()); - } -} - -/** - * An IAM principal that represents an AWS service (i.e. sqs.amazonaws.com). - */ -export class ServicePrincipal extends PrincipalBase { - constructor(public readonly service: string) { - super(); - } - - public get policyFragment(): PrincipalPolicyFragment { - return new PrincipalPolicyFragment({ Service: [ this.service ] }); - } -} - -/** - * A principal that represents an AWS Organization - */ -export class OrganizationPrincipal extends PrincipalBase { - constructor(public readonly organizationId: string) { - super(); - } - - public get policyFragment(): PrincipalPolicyFragment { - return new PrincipalPolicyFragment( - { AWS: ['*'] }, - { StringEquals: { 'aws:PrincipalOrgID': this.organizationId } } - ); - } -} - -/** - * A policy prinicipal for canonicalUserIds - useful for S3 bucket policies that use - * Origin Access identities. - * - * See https://docs.aws.amazon.com/general/latest/gr/acct-identifiers.html - * - * and - * - * https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/private-content-restricting-access-to-s3.html - * - * for more details. - * - */ -export class CanonicalUserPrincipal extends PrincipalBase { - constructor(public readonly canonicalUserId: string) { - super(); - } - - public get policyFragment(): PrincipalPolicyFragment { - return new PrincipalPolicyFragment({ CanonicalUser: [ this.canonicalUserId ] }); - } -} - -export class FederatedPrincipal extends PrincipalBase { - constructor( - public readonly federated: string, - public readonly conditions: {[key: string]: any}, - public assumeRoleAction: string = 'sts:AssumeRole') { - super(); - } - - public get policyFragment(): PrincipalPolicyFragment { - return new PrincipalPolicyFragment({ Federated: [ this.federated ] }, this.conditions); - } -} - -export class AccountRootPrincipal extends AccountPrincipal { - constructor() { - super(new StackDependentToken(stack => stack.accountId).toString()); - } -} - -/** - * A principal representing all identities in all accounts - */ -export class AnyPrincipal extends ArnPrincipal { - constructor() { - super('*'); - } -} - -/** - * A principal representing all identities in all accounts - * @deprecated use `AnyPrincipal` - */ -export class Anyone extends AnyPrincipal { } - -export class CompositePrincipal extends PrincipalBase { - private readonly principals = new Array(); - - constructor(principal: PrincipalBase, ...additionalPrincipals: PrincipalBase[]) { - super(); - this.assumeRoleAction = principal.assumeRoleAction; - this.addPrincipals(principal); - this.addPrincipals(...additionalPrincipals); - } - - public addPrincipals(...principals: PrincipalBase[]): this { - for (const p of principals) { - if (p.assumeRoleAction !== this.assumeRoleAction) { - throw new Error( - `Cannot add multiple principals with different "assumeRoleAction". ` + - `Expecting "${this.assumeRoleAction}", got "${p.assumeRoleAction}"`); - } - - const fragment = p.policyFragment; - if (fragment.conditions && Object.keys(fragment.conditions).length > 0) { - throw new Error( - `Components of a CompositePrincipal must not have conditions. ` + - `Tried to add the following fragment: ${JSON.stringify(fragment)}`); - } - - this.principals.push(p); - } - - return this; - } - - public get policyFragment(): PrincipalPolicyFragment { - const principalJson: { [key: string]: string[] } = { }; - - for (const p of this.principals) { - mergePrincipal(principalJson, p.policyFragment.principalJson); - } - - return new PrincipalPolicyFragment(principalJson); - } -} - -/** - * A lazy token that requires an instance of Stack to evaluate - */ -class StackDependentToken extends cdk.Token { - constructor(private readonly fn: (stack: cdk.Stack) => any) { - super(); - } - - public resolve(context: cdk.ResolveContext) { - const stack = cdk.Stack.find(context.scope); - return this.fn(stack); - } -} \ No newline at end of file +// FIXME: Move all principals here after approval of changing PR. \ No newline at end of file diff --git a/packages/@aws-cdk/aws-iam/lib/role.ts b/packages/@aws-cdk/aws-iam/lib/role.ts index 48dd24232a8be..fc41dd8561a59 100644 --- a/packages/@aws-cdk/aws-iam/lib/role.ts +++ b/packages/@aws-cdk/aws-iam/lib/role.ts @@ -2,8 +2,8 @@ import { Construct, IConstruct, Output, Stack } from '@aws-cdk/cdk'; import { CfnRole } from './iam.generated'; import { IIdentity } from './identity-base'; import { Policy } from './policy'; -import { PolicyDocument, PolicyStatement } from './policy-document'; -import { ArnPrincipal, IPrincipal, PrincipalPolicyFragment } from './principals'; +import { PolicyDocument, PolicyStatement, PrincipalPolicyFragment, ArnPrincipal } from './policy-document'; +import { IPrincipal } from './principals'; import { AttachedPolicies, undefinedIfEmpty } from './util'; export interface RoleProps { diff --git a/packages/@aws-cdk/aws-iam/lib/user.ts b/packages/@aws-cdk/aws-iam/lib/user.ts index 17a4e956ea445..3341f2320b5b7 100644 --- a/packages/@aws-cdk/aws-iam/lib/user.ts +++ b/packages/@aws-cdk/aws-iam/lib/user.ts @@ -4,7 +4,7 @@ import { CfnUser } from './iam.generated'; import { IIdentity } from './identity-base'; import { Policy } from './policy'; import { PolicyStatement } from './policy-document'; -import { ArnPrincipal, PrincipalPolicyFragment } from './principals'; +import { ArnPrincipal, PrincipalPolicyFragment } from './policy-document'; import { AttachedPolicies, undefinedIfEmpty } from './util'; export interface UserProps { From a445780e32c108fd16bac2de30ef581a9884d692 Mon Sep 17 00:00:00 2001 From: Rico Huijbers Date: Tue, 12 Feb 2019 15:24:21 +0100 Subject: [PATCH 05/31] Change grants API --- .../@aws-cdk/aws-cloudwatch/lib/metric.ts | 10 +- packages/@aws-cdk/aws-dynamodb/lib/table.ts | 21 ++-- .../@aws-cdk/aws-ecr/lib/repository-ref.ts | 19 +-- packages/@aws-cdk/aws-iam/lib/grant.ts | 109 +++++++++++++----- packages/@aws-cdk/aws-iam/lib/group.ts | 2 +- .../@aws-cdk/aws-iam/lib/policy-document.ts | 21 ++-- packages/@aws-cdk/aws-iam/lib/principals.ts | 3 +- packages/@aws-cdk/aws-iam/lib/role.ts | 2 +- .../aws-iam/test/test.policy-document.ts | 4 +- packages/@aws-cdk/aws-kms/lib/key.ts | 3 +- .../@aws-cdk/aws-lambda/lib/function-base.ts | 7 +- packages/@aws-cdk/aws-logs/lib/log-group.ts | 5 +- packages/@aws-cdk/aws-s3/lib/bucket.ts | 4 +- .../@aws-cdk/aws-secretsmanager/lib/secret.ts | 2 +- packages/@aws-cdk/aws-sns/lib/topic-base.ts | 4 +- packages/@aws-cdk/aws-sqs/lib/queue-base.ts | 4 +- 16 files changed, 143 insertions(+), 77 deletions(-) diff --git a/packages/@aws-cdk/aws-cloudwatch/lib/metric.ts b/packages/@aws-cdk/aws-cloudwatch/lib/metric.ts index ffd275b85cfcb..f1e30677d6bc8 100644 --- a/packages/@aws-cdk/aws-cloudwatch/lib/metric.ts +++ b/packages/@aws-cdk/aws-cloudwatch/lib/metric.ts @@ -88,11 +88,11 @@ export class Metric { * @param principal The IAM identity to give permissions to. */ public static grantPutMetricData(principal?: iam.IPrincipal) { - iam.grant({ - principal, - actions: ['cloudwatch:PutMetricData'], - resourceArns: ['*'], - }); + if (principal) { + principal.addToPolicy(new iam.PolicyStatement() + .addAction('cloudwatch:PutMetricData') + .addAllResources()); + } } public readonly dimensions?: DimensionHash; diff --git a/packages/@aws-cdk/aws-dynamodb/lib/table.ts b/packages/@aws-cdk/aws-dynamodb/lib/table.ts index 5258d6fee9aab..2591b6c5f3770 100644 --- a/packages/@aws-cdk/aws-dynamodb/lib/table.ts +++ b/packages/@aws-cdk/aws-dynamodb/lib/table.ts @@ -1,5 +1,6 @@ import appscaling = require('@aws-cdk/aws-applicationautoscaling'); import iam = require('@aws-cdk/aws-iam'); +import { PolicyStatement } from '@aws-cdk/aws-iam'; import cdk = require('@aws-cdk/cdk'); import { Construct, Token } from '@aws-cdk/cdk'; import { CfnTable } from './dynamodb.generated'; @@ -179,11 +180,11 @@ export class Table extends Construct { * @param principal The principal (no-op if undefined) */ public static grantListStreams(principal?: iam.IPrincipal): void { - iam.grant({ - principal, - actions: ['dynamodb:ListStreams'], - resourceArns: ['*'], - }); + if (principal) { + principal.addToPolicy(new PolicyStatement() + .addAction('dynamodb:ListStreams') + .addAllResources()); + } } public readonly tableArn: string; @@ -436,13 +437,14 @@ export class Table extends Construct { * @param actions The set of actions to allow (i.e. "dynamodb:PutItem", "dynamodb:GetItem", ...) */ public grant(principal?: iam.IPrincipal, ...actions: string[]) { - iam.grant({ + iam.Permissions.grant({ principal, actions, resourceArns: [ this.tableArn, new cdk.Token(() => this.hasIndex ? `${this.tableArn}/index/*` : new cdk.Aws().noValue).toString() - ] + ], + scope: this, }); } @@ -453,10 +455,11 @@ export class Table extends Construct { * @param actions The set of actions to allow (i.e. "dynamodb:DescribeStream", "dynamodb:GetRecords", ...) */ public grantStream(principal?: iam.IPrincipal, ...actions: string[]) { - iam.grant({ + iam.Permissions.grant({ principal, actions, - resourceArns: [this.tableStreamArn] + resourceArns: [this.tableStreamArn], + scope: this, }); } diff --git a/packages/@aws-cdk/aws-ecr/lib/repository-ref.ts b/packages/@aws-cdk/aws-ecr/lib/repository-ref.ts index 88460ae8174e9..b7b44f97b3a23 100644 --- a/packages/@aws-cdk/aws-ecr/lib/repository-ref.ts +++ b/packages/@aws-cdk/aws-ecr/lib/repository-ref.ts @@ -207,11 +207,11 @@ export abstract class RepositoryBase extends cdk.Construct implements IRepositor * Grant the given principal identity permissions to perform the actions on this repository */ public grant(principal?: iam.IPrincipal, ...actions: string[]) { - iam.grant({ + iam.Permissions.grant({ principal, actions, resourceArns: [this.repositoryArn], - addToResourcePolicy: this.addToResourcePolicy.bind(this), + resource: this, }); } @@ -221,11 +221,12 @@ export abstract class RepositoryBase extends cdk.Construct implements IRepositor public grantPull(principal?: iam.IPrincipal) { this.grant(principal, "ecr:BatchCheckLayerAvailability", "ecr:GetDownloadUrlForLayer", "ecr:BatchGetImage"); - iam.grant({ + iam.Permissions.grant({ principal, actions: ["ecr:GetAuthorizationToken", "logs:CreateLogStream", "logs:PutLogEvents"], resourceArns: ['*'], skipResourcePolicy: true, + scope: this, }); } @@ -233,12 +234,12 @@ export abstract class RepositoryBase extends cdk.Construct implements IRepositor * Grant the given identity permissions to pull and push images to this repository. */ public grantPullPush(identity?: iam.IPrincipal) { - this.grantPull(identity); - this.grant(identity, - "ecr:PutImage", - "ecr:InitiateLayerUpload", - "ecr:UploadLayerPart", - "ecr:CompleteLayerUpload"); + this.grantPull(identity); + this.grant(identity, + "ecr:PutImage", + "ecr:InitiateLayerUpload", + "ecr:UploadLayerPart", + "ecr:CompleteLayerUpload"); } } diff --git a/packages/@aws-cdk/aws-iam/lib/grant.ts b/packages/@aws-cdk/aws-iam/lib/grant.ts index 961a30413d88b..49a43c451acbf 100644 --- a/packages/@aws-cdk/aws-iam/lib/grant.ts +++ b/packages/@aws-cdk/aws-iam/lib/grant.ts @@ -1,16 +1,17 @@ +import cdk = require('@aws-cdk/cdk'); import { PolicyStatement } from "./policy-document"; import { IPrincipal } from "./principals"; /** * Properties for a grant operation */ -export interface GrantProps { +export interface GrantOptions { /** * The principal to grant to * * @default No work is done */ - principal?: IPrincipal; + principal: IPrincipal | undefined; /** * The actions to grant @@ -25,9 +26,12 @@ export interface GrantProps { /** * Adder to the resource policy * - * @default Failure if no principal policy and `skipResourcePolicy` is not set. + * Either 'scope' or 'resource' must be supplied. + * + * An error will be thrown if the policy could not be added to the principal, + * no resource is supplied given and `skipResourcePolicy` is false. */ - addToResourcePolicy?: (statement: PolicyStatement) => void; + resource?: IResourceWithPolicy; /** * When referring to the resource in a resource policy, use this as ARN. @@ -39,40 +43,87 @@ export interface GrantProps { resourceSelfArns?: string[]; /** - * If there is no resource policy, ignore the error + * If we wanted to add to the resource policy but there is no resource, ignore the error. * * @default false */ skipResourcePolicy?: boolean; + + /** + * Construct to report warnings on in case grant could not be registered + * + * @default resource + */ + scope?: cdk.IConstruct; } -/** - * Helper function to implement grants. - * - * The pattern is the same every time. We try to add to the principal - * first, then add to the resource afterwards. - * - * @returns false if `skipResourcePolicy` was used, true otherwise - */ -export function grant(props: GrantProps): boolean { - if (!props.principal) { return true; } +export class Permissions { + /** + * Helper function to implement grants. + * + * The pattern is the same every time. We try to add to the principal + * first, then add to the resource afterwards. + */ + public static grant(options: GrantOptions): GrantResult { + let addedToPrincipal = false; + let addedToResource = false; + + const scope = options.scope || options.resource; + if (!scope) { + throw new Error(`Either 'scope' or 'resource' must be supplied.`); + } + + // One-iteration loop to be able to skip to end of function easily + do { + if (!options.principal) { + // tslint:disable-next-line:max-line-length + scope.node.addWarning(`Could not add grant for '${options.actions}' on '${options.resourceArns}' because the principal was not available. Add the permissions by hand.`); + break; + } + + addedToPrincipal = options.principal.addToPolicy(new PolicyStatement() + .addActions(...options.actions) + .addResources(...options.resourceArns)); + + if (addedToPrincipal || options.skipResourcePolicy) { break; } + + if (!options.resource) { + throw new Error('Could not add permissions to Principal without policy, and resource does not have policy either. Grant to a Role instead.'); + } - const addedToPrincipal = props.principal.addToPolicy(new PolicyStatement() - .addActions(...props.actions) - .addResources(...props.resourceArns)); + options.resource.addToResourcePolicy(new PolicyStatement() + .addActions(...options.actions) + .addResources(...(options.resourceSelfArns || options.resourceArns)) + .addPrincipal(options.principal)); + addedToResource = true; - if (addedToPrincipal || props.skipResourcePolicy) { return false; } + } while (false); - // This is a function so that it can be used by resources that lazily - // need to create a policy document (Queue, Bucket) which cannot have - // an empty policy. - if (!props.addToResourcePolicy) { - throw new Error('Could not add permissions to Principal without policy, and resource does not have policy either. Grant to a Role instead.'); + return { addedToPrincipal, addedToResource }; } +} + +/** + * The result of the grant() operation + */ +export interface GrantResult { + /** + * The grant was added to the principal's policy + */ + addedToPrincipal: boolean; + + /** + * The grant was added to the resource policy + */ + addedToResource: boolean; +} - props.addToResourcePolicy(new PolicyStatement() - .addActions(...props.actions) - .addResources(...(props.resourceSelfArns || props.resourceArns)) - .addPrincipal(props.principal)); - return true; +/** + * A resource with a resource policy that can be added to + */ +export interface IResourceWithPolicy extends cdk.IConstruct { + /** + * Add a statement to the resource's resource policy + */ + addToResourcePolicy(statement: PolicyStatement): void; } \ No newline at end of file diff --git a/packages/@aws-cdk/aws-iam/lib/group.ts b/packages/@aws-cdk/aws-iam/lib/group.ts index ae47133e88b97..ed66b035c1fc2 100644 --- a/packages/@aws-cdk/aws-iam/lib/group.ts +++ b/packages/@aws-cdk/aws-iam/lib/group.ts @@ -2,7 +2,7 @@ import { Construct } from '@aws-cdk/cdk'; import { CfnGroup } from './iam.generated'; import { IIdentity } from './identity-base'; import { Policy } from './policy'; -import { PolicyStatement, PrincipalPolicyFragment, ArnPrincipal } from './policy-document'; +import { ArnPrincipal, PolicyStatement, PrincipalPolicyFragment } from './policy-document'; import { User } from './user'; import { AttachedPolicies, undefinedIfEmpty } from './util'; diff --git a/packages/@aws-cdk/aws-iam/lib/policy-document.ts b/packages/@aws-cdk/aws-iam/lib/policy-document.ts index df9d26f6b57be..f50bbe15446fe 100644 --- a/packages/@aws-cdk/aws-iam/lib/policy-document.ts +++ b/packages/@aws-cdk/aws-iam/lib/policy-document.ts @@ -49,17 +49,22 @@ export class PolicyDocument extends cdk.Token { */ export abstract class PrincipalBase implements IPrincipal { /** - * When this Principal is used in an AssumeRole policy, the action to use. + * Return the policy fragment that identifies this principal in a Policy. */ - public assumeRoleAction: string = 'sts:AssumeRole'; + public abstract readonly policyFragment: PrincipalPolicyFragment; /** - * Return the policy fragment that identifies this principal in a Policy. + * When this Principal is used in an AssumeRole policy, the action to use. */ - public abstract policyFragment: PrincipalPolicyFragment; + protected _assumeRoleAction: string = 'sts:AssumeRole'; + + public get assumeRoleAction(): string { + return this._assumeRoleAction; + } public addToPolicy(_statement: PolicyStatement): boolean { - // None of these have a policy to add to + // This base class is used for non-identity principals. None of them + // have a PolicyDocument to add to. return false; } } @@ -149,8 +154,10 @@ export class FederatedPrincipal extends PrincipalBase { constructor( public readonly federated: string, public readonly conditions: {[key: string]: any}, - public assumeRoleAction: string = 'sts:AssumeRole') { + assumeRoleAction: string = 'sts:AssumeRole') { super(); + + this._assumeRoleAction = assumeRoleAction; } public get policyFragment(): PrincipalPolicyFragment { @@ -184,7 +191,7 @@ export class CompositePrincipal extends PrincipalBase { constructor(principal: PrincipalBase, ...additionalPrincipals: PrincipalBase[]) { super(); - this.assumeRoleAction = principal.assumeRoleAction; + this._assumeRoleAction = principal.assumeRoleAction; this.addPrincipals(principal); this.addPrincipals(...additionalPrincipals); } diff --git a/packages/@aws-cdk/aws-iam/lib/principals.ts b/packages/@aws-cdk/aws-iam/lib/principals.ts index c971e10cfcf0b..c1a5d69da20a9 100644 --- a/packages/@aws-cdk/aws-iam/lib/principals.ts +++ b/packages/@aws-cdk/aws-iam/lib/principals.ts @@ -19,7 +19,8 @@ export interface IPrincipal { /** * Add to the policy of this principal. * - * @returns true if the policy was added, false if the policy could not be added + * @returns true if the statement was added, false if the principal in + * question does not have a policy document to add the statement to. */ addToPolicy(statement: PolicyStatement): boolean; } diff --git a/packages/@aws-cdk/aws-iam/lib/role.ts b/packages/@aws-cdk/aws-iam/lib/role.ts index fc41dd8561a59..8e799ccf740d2 100644 --- a/packages/@aws-cdk/aws-iam/lib/role.ts +++ b/packages/@aws-cdk/aws-iam/lib/role.ts @@ -2,7 +2,7 @@ import { Construct, IConstruct, Output, Stack } from '@aws-cdk/cdk'; import { CfnRole } from './iam.generated'; import { IIdentity } from './identity-base'; import { Policy } from './policy'; -import { PolicyDocument, PolicyStatement, PrincipalPolicyFragment, ArnPrincipal } from './policy-document'; +import { ArnPrincipal, PolicyDocument, PolicyStatement, PrincipalPolicyFragment } from './policy-document'; import { IPrincipal } from './principals'; import { AttachedPolicies, undefinedIfEmpty } from './util'; diff --git a/packages/@aws-cdk/aws-iam/test/test.policy-document.ts b/packages/@aws-cdk/aws-iam/test/test.policy-document.ts index b2ccb35e24dba..62ce28c95a580 100644 --- a/packages/@aws-cdk/aws-iam/test/test.policy-document.ts +++ b/packages/@aws-cdk/aws-iam/test/test.policy-document.ts @@ -1,6 +1,6 @@ import { Stack, Token } from '@aws-cdk/cdk'; import { Test } from 'nodeunit'; -import { Anyone, AnyPrincipal, CanonicalUserPrincipal, PolicyDocument, PolicyStatement, PrincipalBase } from '../lib'; +import { Anyone, AnyPrincipal, CanonicalUserPrincipal, IPrincipal, PolicyDocument, PolicyStatement } from '../lib'; import { ArnPrincipal, CompositePrincipal, FederatedPrincipal, PrincipalPolicyFragment, ServicePrincipal } from '../lib'; export = { @@ -278,7 +278,7 @@ export = { 'addPrincipal correctly merges array in'(test: Test) { const stack = new Stack(); - const arrayPrincipal: PrincipalBase = { + const arrayPrincipal: IPrincipal = { assumeRoleAction: 'sts:AssumeRole', policyFragment: new PrincipalPolicyFragment({ AWS: ['foo', 'bar'] }), addToPolicy() { return false; } diff --git a/packages/@aws-cdk/aws-kms/lib/key.ts b/packages/@aws-cdk/aws-kms/lib/key.ts index 4da0f964a3230..85337c63085b6 100644 --- a/packages/@aws-cdk/aws-kms/lib/key.ts +++ b/packages/@aws-cdk/aws-kms/lib/key.ts @@ -100,11 +100,12 @@ export abstract class EncryptionKeyBase extends Construct { * must not be empty and so default grants won't work. */ public grant(principal: iam.IPrincipal | undefined, actions: string[]): void { - iam.grant({ + iam.Permissions.grant({ principal, actions, resourceArns: [this.keyArn], skipResourcePolicy: true, + scope: this }); if (principal) { diff --git a/packages/@aws-cdk/aws-lambda/lib/function-base.ts b/packages/@aws-cdk/aws-lambda/lib/function-base.ts index 2f0bd1e366f89..89ac16349f182 100644 --- a/packages/@aws-cdk/aws-lambda/lib/function-base.ts +++ b/packages/@aws-cdk/aws-lambda/lib/function-base.ts @@ -247,16 +247,17 @@ export abstract class FunctionBase extends cdk.Construct implements IFunction { * Grant the given identity permissions to invoke this Lambda */ public grantInvoke(principal?: iam.IPrincipal) { - const added = iam.grant({ + const added = iam.Permissions.grant({ principal, actions: ['lambda:InvokeFunction'], resourceArns: [this.functionArn], // Can't use a resource policy because adding resource permissions // looks different on a Lambda Function. - skipResourcePolicy: true + skipResourcePolicy: true, + scope: this, }); - if (!added && principal) { + if (principal && !added.addedToPrincipal) { // Couldn't add permissions to the principal, so add them locally. const identifier = 'Invoke' + JSON.stringify(principal!.policyFragment.principalJson); this.addPermission(identifier, { diff --git a/packages/@aws-cdk/aws-logs/lib/log-group.ts b/packages/@aws-cdk/aws-logs/lib/log-group.ts index 42c5775264c29..df17550e3b86a 100644 --- a/packages/@aws-cdk/aws-logs/lib/log-group.ts +++ b/packages/@aws-cdk/aws-logs/lib/log-group.ts @@ -179,12 +179,13 @@ export abstract class LogGroupBase extends cdk.Construct implements ILogGroup { * Give the indicated permissions on this log group and all streams */ public grant(principal?: iam.IPrincipal, ...actions: string[]) { - iam.grant({ + iam.Permissions.grant({ principal, actions, // A LogGroup ARN out of CloudFormation already includes a ':*' at the end to include the log streams under the group. // See https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-logs-loggroup.html#w2ab1c21c10c63c43c11 - resourceArns: [this.logGroupArn] + resourceArns: [this.logGroupArn], + scope: this, }); } } diff --git a/packages/@aws-cdk/aws-s3/lib/bucket.ts b/packages/@aws-cdk/aws-s3/lib/bucket.ts index e8ae8b58be71b..58394efb2fce4 100644 --- a/packages/@aws-cdk/aws-s3/lib/bucket.ts +++ b/packages/@aws-cdk/aws-s3/lib/bucket.ts @@ -522,11 +522,11 @@ export abstract class BucketBase extends cdk.Construct implements IBucket { resourceArn: string, ...otherResourceArns: string[]) { const resources = [ resourceArn, ...otherResourceArns ]; - iam.grant({ + iam.Permissions.grant({ principal, actions: bucketActions, resourceArns: resources, - addToResourcePolicy: this.addToResourcePolicy.bind(this), + resource: this, }); if (this.encryptionKey) { diff --git a/packages/@aws-cdk/aws-secretsmanager/lib/secret.ts b/packages/@aws-cdk/aws-secretsmanager/lib/secret.ts index 5d9ade85f9193..d1b6f0cbf6d4d 100644 --- a/packages/@aws-cdk/aws-secretsmanager/lib/secret.ts +++ b/packages/@aws-cdk/aws-secretsmanager/lib/secret.ts @@ -118,7 +118,7 @@ export abstract class SecretBase extends cdk.Construct implements ISecret { // @see https://docs.aws.amazon.com/fr_fr/kms/latest/developerguide/services-secrets-manager.html this.encryptionKey.addToResourcePolicy(new iam.PolicyStatement() .allow() - .addPrincipal(grantee.principal) + .addPrincipal(grantee) .addAction('kms:Decrypt') .addAllResources() .addCondition('StringEquals', { diff --git a/packages/@aws-cdk/aws-sns/lib/topic-base.ts b/packages/@aws-cdk/aws-sns/lib/topic-base.ts index 173f2ec70212d..58c78c4c622d6 100644 --- a/packages/@aws-cdk/aws-sns/lib/topic-base.ts +++ b/packages/@aws-cdk/aws-sns/lib/topic-base.ts @@ -264,11 +264,11 @@ export abstract class TopicBase extends cdk.Construct implements ITopic { * Grant topic publishing permissions to the given identity */ public grantPublish(principal?: iam.IPrincipal) { - iam.grant({ + iam.Permissions.grant({ principal, actions: ['sns:Publish'], resourceArns: [this.topicArn], - addToResourcePolicy: this.addToResourcePolicy.bind(this), + resource: this, }); } diff --git a/packages/@aws-cdk/aws-sqs/lib/queue-base.ts b/packages/@aws-cdk/aws-sqs/lib/queue-base.ts index 867f9590db18a..d9f178e18e1aa 100644 --- a/packages/@aws-cdk/aws-sqs/lib/queue-base.ts +++ b/packages/@aws-cdk/aws-sqs/lib/queue-base.ts @@ -274,11 +274,11 @@ export abstract class QueueBase extends cdk.Construct implements IQueue { * @param actions The actions to grant */ public grant(principal?: iam.IPrincipal, ...actions: string[]) { - iam.grant({ + iam.Permissions.grant({ principal, actions, resourceArns: [this.queueArn], - addToResourcePolicy: this.addToResourcePolicy.bind(this), + resource: this, }); } } From a43bf24b151231a421a5a4f466fafb4083e3b0d8 Mon Sep 17 00:00:00 2001 From: Rico Huijbers Date: Wed, 13 Feb 2019 14:10:04 +0100 Subject: [PATCH 06/31] Make key interface work with jsii --- packages/@aws-cdk/aws-kms/lib/key.ts | 14 +++--- packages/@aws-cdk/aws-kms/test/test.key.ts | 53 +++++++++++++++++++++- 2 files changed, 58 insertions(+), 9 deletions(-) diff --git a/packages/@aws-cdk/aws-kms/lib/key.ts b/packages/@aws-cdk/aws-kms/lib/key.ts index 85337c63085b6..d9bda43117702 100644 --- a/packages/@aws-cdk/aws-kms/lib/key.ts +++ b/packages/@aws-cdk/aws-kms/lib/key.ts @@ -33,7 +33,7 @@ export interface IEncryptionKey extends IConstruct { /** * Grant the indicated permissions on this key to the given principal */ - grant(principal: iam.IPrincipal | undefined, actions: string[]): void; + grant(principal: iam.IPrincipal | undefined, ...actions: string[]): void; /** * Grant decryption permisisons using this key to the given principal @@ -99,7 +99,7 @@ export abstract class EncryptionKeyBase extends Construct { * since the default CloudFormation setup for KMS keys is that the policy * must not be empty and so default grants won't work. */ - public grant(principal: iam.IPrincipal | undefined, actions: string[]): void { + public grant(principal: iam.IPrincipal | undefined, ...actions: string[]): void { iam.Permissions.grant({ principal, actions, @@ -120,21 +120,21 @@ export abstract class EncryptionKeyBase extends Construct { * Grant decryption permisisons using this key to the given principal */ public grantDecrypt(principal: iam.IPrincipal | undefined): void { - return this.grant(principal, [ + return this.grant(principal, 'kms:Decrypt', - 'kms:DescribeKey', - ]); + 'kms:DescribeKey' + ); } /** * Grant encryption permisisons using this key to the given principal */ public grantEncrypt(principal: iam.IPrincipal | undefined): void { - return this.grant(principal, [ + return this.grant(principal, 'kms:Encrypt', 'kms:ReEncrypt*', 'kms:GenerateDataKey*' - ]); + ); } } diff --git a/packages/@aws-cdk/aws-kms/test/test.key.ts b/packages/@aws-cdk/aws-kms/test/test.key.ts index dd51d1d7bffe7..9de886453ba39 100644 --- a/packages/@aws-cdk/aws-kms/test/test.key.ts +++ b/packages/@aws-cdk/aws-kms/test/test.key.ts @@ -1,5 +1,5 @@ -import { exactlyMatchTemplate, expect } from '@aws-cdk/assert'; -import { PolicyDocument, PolicyStatement } from '@aws-cdk/aws-iam'; +import { exactlyMatchTemplate, expect, haveResource } from '@aws-cdk/assert'; +import { PolicyDocument, PolicyStatement, User } from '@aws-cdk/aws-iam'; import { App, Stack, Tag } from '@aws-cdk/cdk'; import { Test } from 'nodeunit'; import { EncryptionKey } from '../lib'; @@ -311,6 +311,55 @@ export = { test.done(); }, + 'grant decrypt on a key'(test: Test) { + // GIVEN + const stack = new Stack(); + const key = new EncryptionKey(stack, 'Key'); + const user = new User(stack, 'User'); + + // WHEN + key.grantDecrypt(user); + + // THEN + expect(stack).to(haveResource('AWS::KMS::Key', { + KeyPolicy: { + Statement: [ + // This one is there by default + { + // tslint:disable-next-line:max-line-length + Action: [ "kms:Create*", "kms:Describe*", "kms:Enable*", "kms:List*", "kms:Put*", "kms:Update*", "kms:Revoke*", "kms:Disable*", "kms:Get*", "kms:Delete*", "kms:ScheduleKeyDeletion", "kms:CancelKeyDeletion" ], + Effect: "Allow", + Principal: { AWS: { "Fn::Join": [ "", [ "arn:", { Ref: "AWS::Partition" }, ":iam::", { Ref: "AWS::AccountId" }, ":root" ] ] } }, + Resource: "*" + }, + // This is the interesting one + { + Action: [ "kms:Decrypt", "kms:DescribeKey" ], + Effect: "Allow", + Principal: { AWS: { "Fn::GetAtt": [ "User00B015A1", "Arn" ] } }, + Resource: "*" + } + ], + Version: "2012-10-17" + } + })); + + expect(stack).to(haveResource('AWS::IAM::Policy', { + PolicyDocument: { + Statement: [ + { + Action: [ "kms:Decrypt", "kms:DescribeKey" ], + Effect: "Allow", + Resource: { "Fn::GetAtt": [ "Key961B73FD", "Arn" ] } + } + ], + Version: "2012-10-17" + }, + })); + + test.done(); + }, + 'import/export can be used to bring in an existing key'(test: Test) { const stack1 = new Stack(); const policy = new PolicyDocument(); From 2a756201c6073a9641c3887ce8ac4a189257023f Mon Sep 17 00:00:00 2001 From: Rico Huijbers Date: Wed, 13 Feb 2019 15:43:40 +0100 Subject: [PATCH 07/31] Splat in the consumer --- packages/@aws-cdk/aws-s3/lib/bucket.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/@aws-cdk/aws-s3/lib/bucket.ts b/packages/@aws-cdk/aws-s3/lib/bucket.ts index 58394efb2fce4..a3a5ce89de22f 100644 --- a/packages/@aws-cdk/aws-s3/lib/bucket.ts +++ b/packages/@aws-cdk/aws-s3/lib/bucket.ts @@ -530,7 +530,7 @@ export abstract class BucketBase extends cdk.Construct implements IBucket { }); if (this.encryptionKey) { - this.encryptionKey.grant(principal, keyActions); + this.encryptionKey.grant(principal, ...keyActions); } } } From 09cffbd35a77cc4f2cf9140210db294c9851e423 Mon Sep 17 00:00:00 2001 From: Rico Huijbers Date: Wed, 13 Feb 2019 18:32:59 +0100 Subject: [PATCH 08/31] Can't have the same function in 2 interfaces in C# --- packages/@aws-cdk/aws-iam/lib/identity-base.ts | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/packages/@aws-cdk/aws-iam/lib/identity-base.ts b/packages/@aws-cdk/aws-iam/lib/identity-base.ts index a3e9c9b7eaace..08050d0cc0236 100644 --- a/packages/@aws-cdk/aws-iam/lib/identity-base.ts +++ b/packages/@aws-cdk/aws-iam/lib/identity-base.ts @@ -1,17 +1,10 @@ import { Policy } from "./policy"; -import { PolicyStatement } from "./policy-document"; import { IPrincipal } from "./principals"; /** * A construct that represents an IAM principal, such as a user, group or role. */ export interface IIdentity extends IPrincipal { - /** - * Adds an IAM statement to the default inline policy associated with this - * principal. If a policy doesn't exist, it is created. - */ - addToPolicy(statement: PolicyStatement): boolean; - /** * Attaches an inline policy to this principal. * This is the same as calling `policy.addToXxx(principal)`. @@ -24,4 +17,4 @@ export interface IIdentity extends IPrincipal { * @param arn The ARN of the managed policy */ attachManagedPolicy(arn: string): void; -} \ No newline at end of file +} From 554816d8410bc58ab51998a5d7456a936f4de84d Mon Sep 17 00:00:00 2001 From: Rico Huijbers Date: Wed, 13 Feb 2019 20:09:48 +0100 Subject: [PATCH 09/31] Respect the refactoring --- packages/@aws-cdk/aws-iam/lib/policy-document.ts | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/packages/@aws-cdk/aws-iam/lib/policy-document.ts b/packages/@aws-cdk/aws-iam/lib/policy-document.ts index 3bc5988a6173c..41ad0081b83df 100644 --- a/packages/@aws-cdk/aws-iam/lib/policy-document.ts +++ b/packages/@aws-cdk/aws-iam/lib/policy-document.ts @@ -477,19 +477,3 @@ export enum PolicyStatementEffect { Allow = 'Allow', Deny = 'Deny', } - -function mergePrincipal(target: { [key: string]: string[] }, source: { [key: string]: string[] }) { - for (const key of Object.keys(source)) { - target[key] = target[key] || []; - - const value = source[key]; - if (!Array.isArray(value)) { - throw new Error(`Principal value must be an array (it will be normalized later): ${value}`); - } - - target[key].push(...value); - } - - return target; -} - From cf68f7d66231b397725d2046ad36faf85b2ef1a1 Mon Sep 17 00:00:00 2001 From: Rico Huijbers Date: Wed, 27 Feb 2019 15:41:35 +0100 Subject: [PATCH 10/31] Add awslint rule to force grant() methods to use helpers --- .../aws-codepipeline-api/lib/action.ts | 4 +- .../@aws-cdk/aws-codepipeline/lib/pipeline.ts | 8 +- packages/@aws-cdk/aws-dynamodb/lib/table.ts | 16 +- .../@aws-cdk/aws-ecr/lib/repository-ref.ts | 19 +- packages/@aws-cdk/aws-iam/lib/grant.ts | 228 +++++++++++++++--- packages/@aws-cdk/aws-iam/lib/role.ts | 18 +- packages/@aws-cdk/aws-kinesis/lib/stream.ts | 103 +++----- packages/@aws-cdk/aws-kms/lib/key.ts | 43 ++-- .../@aws-cdk/aws-lambda/lib/function-base.ts | 33 +-- packages/@aws-cdk/aws-lambda/package.json | 5 + packages/@aws-cdk/aws-logs/lib/log-group.ts | 8 +- packages/@aws-cdk/aws-s3/lib/bucket.ts | 42 ++-- packages/@aws-cdk/aws-s3/test/test.bucket.ts | 4 +- .../@aws-cdk/aws-secretsmanager/lib/secret.ts | 35 +-- packages/@aws-cdk/aws-sns/lib/topic-base.ts | 4 +- packages/@aws-cdk/aws-sqs/lib/queue-base.ts | 16 +- tools/awslint/lib/linter.ts | 57 +++-- tools/awslint/lib/rules/resource.ts | 27 ++- tools/awslint/lib/util.ts | 11 + 19 files changed, 444 insertions(+), 237 deletions(-) diff --git a/packages/@aws-cdk/aws-codepipeline-api/lib/action.ts b/packages/@aws-cdk/aws-codepipeline-api/lib/action.ts index 5553cf105a57a..f33df7aeefda6 100644 --- a/packages/@aws-cdk/aws-codepipeline-api/lib/action.ts +++ b/packages/@aws-cdk/aws-codepipeline-api/lib/action.ts @@ -62,14 +62,14 @@ export interface IPipeline extends cdk.IConstruct, events.IEventRuleTarget { * * @param identity the IAM Identity to grant the permissions to */ - grantBucketRead(identity?: iam.IPrincipal): void; + grantBucketRead(identity?: iam.IPrincipal): iam.GrantResult; /** * Grants read & write permissions to the Pipeline's S3 Bucket to the given Identity. * * @param identity the IAM Identity to grant the permissions to */ - grantBucketReadWrite(identity?: iam.IPrincipal): void; + grantBucketReadWrite(identity?: iam.IPrincipal): iam.GrantResult; } /** diff --git a/packages/@aws-cdk/aws-codepipeline/lib/pipeline.ts b/packages/@aws-cdk/aws-codepipeline/lib/pipeline.ts index add15cb903ab4..2f9dc5ade0451 100644 --- a/packages/@aws-cdk/aws-codepipeline/lib/pipeline.ts +++ b/packages/@aws-cdk/aws-codepipeline/lib/pipeline.ts @@ -292,12 +292,12 @@ export class Pipeline extends cdk.Construct implements cpapi.IPipeline { return this.stages.length; } - public grantBucketRead(identity?: iam.IPrincipal): void { - this.artifactBucket.grantRead(identity); + public grantBucketRead(identity?: iam.IPrincipal): iam.GrantResult { + return this.artifactBucket.grantRead(identity); } - public grantBucketReadWrite(identity?: iam.IPrincipal): void { - this.artifactBucket.grantReadWrite(identity); + public grantBucketReadWrite(identity?: iam.IPrincipal): iam.GrantResult { + return this.artifactBucket.grantReadWrite(identity); } /** diff --git a/packages/@aws-cdk/aws-dynamodb/lib/table.ts b/packages/@aws-cdk/aws-dynamodb/lib/table.ts index ae3e4e29cab91..e8b303a8a5d03 100644 --- a/packages/@aws-cdk/aws-dynamodb/lib/table.ts +++ b/packages/@aws-cdk/aws-dynamodb/lib/table.ts @@ -408,8 +408,8 @@ export class Table extends Construct { * @param principal The principal (no-op if undefined) * @param actions The set of actions to allow (i.e. "dynamodb:PutItem", "dynamodb:GetItem", ...) */ - public grant(principal?: iam.IPrincipal, ...actions: string[]) { - iam.Permissions.grant({ + public grant(principal?: iam.IPrincipal, ...actions: string[]): iam.GrantResult { + return iam.Permissions.grant({ principal, actions, resourceArns: [ @@ -427,7 +427,7 @@ export class Table extends Construct { * @param actions The set of actions to allow (i.e. "dynamodb:DescribeStream", "dynamodb:GetRecords", ...) */ public grantStream(principal?: iam.IPrincipal, ...actions: string[]) { - iam.Permissions.grant({ + return iam.Permissions.grant({ principal, actions, resourceArns: [this.tableStreamArn], @@ -441,7 +441,7 @@ export class Table extends Construct { * @param principal The principal to grant access to */ public grantReadData(principal?: iam.IPrincipal) { - this.grant(principal, ...READ_DATA_ACTIONS); + return this.grant(principal, ...READ_DATA_ACTIONS); } /** @@ -451,7 +451,7 @@ export class Table extends Construct { * @param principal The principal to grant access to */ public grantStreamRead(principal?: iam.IPrincipal) { - this.grantStream(principal, ...READ_STREAM_DATA_ACTIONS); + return this.grantStream(principal, ...READ_STREAM_DATA_ACTIONS); } /** @@ -460,7 +460,7 @@ export class Table extends Construct { * @param principal The principal to grant access to */ public grantWriteData(principal?: iam.IPrincipal) { - this.grant(principal, ...WRITE_DATA_ACTIONS); + return this.grant(principal, ...WRITE_DATA_ACTIONS); } /** @@ -470,7 +470,7 @@ export class Table extends Construct { * @param principal The principal to grant access to */ public grantReadWriteData(principal?: iam.IPrincipal) { - this.grant(principal, ...READ_DATA_ACTIONS, ...WRITE_DATA_ACTIONS); + return this.grant(principal, ...READ_DATA_ACTIONS, ...WRITE_DATA_ACTIONS); } /** @@ -478,7 +478,7 @@ export class Table extends Construct { * @param principal The principal to grant access to */ public grantFullAccess(principal?: iam.IPrincipal) { - this.grant(principal, 'dynamodb:*'); + return this.grant(principal, 'dynamodb:*'); } /** diff --git a/packages/@aws-cdk/aws-ecr/lib/repository-ref.ts b/packages/@aws-cdk/aws-ecr/lib/repository-ref.ts index ca36d34c503ce..725d8ea7342ea 100644 --- a/packages/@aws-cdk/aws-ecr/lib/repository-ref.ts +++ b/packages/@aws-cdk/aws-ecr/lib/repository-ref.ts @@ -51,17 +51,17 @@ export interface IRepository extends cdk.IConstruct { /** * Grant the given principal identity permissions to perform the actions on this repository */ - grant(identity?: iam.IPrincipal, ...actions: string[]): void; + grant(identity?: iam.IPrincipal, ...actions: string[]): iam.GrantResult; /** * Grant the given identity permissions to pull images in this repository. */ - grantPull(identity?: iam.IPrincipal): void; + grantPull(identity?: iam.IPrincipal): iam.GrantResult; /** * Grant the given identity permissions to pull and push images to this repository. */ - grantPullPush(identity?: iam.IPrincipal): void; + grantPullPush(identity?: iam.IPrincipal): iam.GrantResult; /** * Defines an AWS CloudWatch event rule that can trigger a target when an image is pushed to this @@ -207,7 +207,7 @@ export abstract class RepositoryBase extends cdk.Construct implements IRepositor * Grant the given principal identity permissions to perform the actions on this repository */ public grant(principal?: iam.IPrincipal, ...actions: string[]) { - iam.Permissions.grant({ + return iam.Permissions.grant({ principal, actions, resourceArns: [this.repositoryArn], @@ -219,15 +219,16 @@ export abstract class RepositoryBase extends cdk.Construct implements IRepositor * Grant the given identity permissions to use the images in this repository */ public grantPull(principal?: iam.IPrincipal) { - this.grant(principal, "ecr:BatchCheckLayerAvailability", "ecr:GetDownloadUrlForLayer", "ecr:BatchGetImage"); + const ret = this.grant(principal, "ecr:BatchCheckLayerAvailability", "ecr:GetDownloadUrlForLayer", "ecr:BatchGetImage"); - iam.Permissions.grant({ + iam.Permissions.tryGrantOnIdentity({ principal, - actions: ["ecr:GetAuthorizationToken", "logs:CreateLogStream", "logs:PutLogEvents"], + actions: ["ecr:GetAuthorizationToken"], resourceArns: ['*'], - skipResourcePolicy: true, scope: this, }); + + return ret; } /** @@ -235,7 +236,7 @@ export abstract class RepositoryBase extends cdk.Construct implements IRepositor */ public grantPullPush(identity?: iam.IPrincipal) { this.grantPull(identity); - this.grant(identity, + return this.grant(identity, "ecr:PutImage", "ecr:InitiateLayerUpload", "ecr:UploadLayerPart", diff --git a/packages/@aws-cdk/aws-iam/lib/grant.ts b/packages/@aws-cdk/aws-iam/lib/grant.ts index 49a43c451acbf..c85669e6b547e 100644 --- a/packages/@aws-cdk/aws-iam/lib/grant.ts +++ b/packages/@aws-cdk/aws-iam/lib/grant.ts @@ -3,7 +3,7 @@ import { PolicyStatement } from "./policy-document"; import { IPrincipal } from "./principals"; /** - * Properties for a grant operation + * Options for a grant operation */ export interface GrantOptions { /** @@ -43,79 +43,235 @@ export interface GrantOptions { resourceSelfArns?: string[]; /** - * If we wanted to add to the resource policy but there is no resource, ignore the error. + * Construct to report warnings on in case grant could not be registered * - * @default false + * @default resource + */ + scope?: cdk.IConstruct; +} + +/** + * Options for a tryGrant operation + */ +export interface TryGrantOnIdentityOptions { + /** + * The principal to grant to + * + * @default No work is done + */ + principal: IPrincipal | undefined; + + /** + * The actions to grant */ - skipResourcePolicy?: boolean; + actions: string[]; + + /** + * The resource ARNs to grant to + */ + resourceArns: string[]; /** * Construct to report warnings on in case grant could not be registered + */ + scope: cdk.IConstruct; +} + +/** + * Options for a grant operation to both identity and resource + */ +export interface GrantOnIdentityAndResourceOptions { + /** + * The principal to grant to * - * @default resource + * @default No work is done */ - scope?: cdk.IConstruct; + principal: IPrincipal | undefined; + + /** + * The actions to grant + */ + actions: string[]; + + /** + * The resource ARNs to grant to + */ + resourceArns: string[]; + + /** + * Adder to the resource policy + * + * Either 'scope' or 'resource' must be supplied. + * + * An error will be thrown if the policy could not be added to the principal, + * no resource is supplied given and `skipResourcePolicy` is false. + */ + resource: IResourceWithPolicy; + + /** + * When referring to the resource in a resource policy, use this as ARN. + * + * (Depending on the resource type, this needs to be '*' in a resource policy). + * + * @default Same as regular resource ARNs + */ + resourceSelfArns?: string[]; } export class Permissions { /** - * Helper function to implement grants. + * Grant the given permissions to the principal + * + * The permissions will be added to the principal policy primarily, falling + * back to the resource policy if necessary. The permissions must be granted + * somewhere. * - * The pattern is the same every time. We try to add to the principal - * first, then add to the resource afterwards. + * - Trying to grant permissions to a principal that does not admit adding to + * the principal policy while not providing a resource with a resource policy + * is an error. + * - Trying to grant permissions to an absent principal (possible in the + * case of imported resources) leads to a warning being added to the + * resource construct. */ public static grant(options: GrantOptions): GrantResult { - let addedToPrincipal = false; - let addedToResource = false; - const scope = options.scope || options.resource; if (!scope) { throw new Error(`Either 'scope' or 'resource' must be supplied.`); } - // One-iteration loop to be able to skip to end of function easily - do { - if (!options.principal) { - // tslint:disable-next-line:max-line-length - scope.node.addWarning(`Could not add grant for '${options.actions}' on '${options.resourceArns}' because the principal was not available. Add the permissions by hand.`); - break; - } + const result = Permissions.tryGrantOnIdentity({ + actions: options.actions, + principal: options.principal, + resourceArns: options.resourceArns, + scope + }); - addedToPrincipal = options.principal.addToPolicy(new PolicyStatement() - .addActions(...options.actions) - .addResources(...options.resourceArns)); + if (result.addedToPrincipal || result.principalMissing) { return result; } - if (addedToPrincipal || options.skipResourcePolicy) { break; } + if (!options.resource) { + // tslint:disable-next-line:max-line-length + throw new Error(`Neither principal (${options.principal}) nor resource (${scope}) allow adding to policy. Grant to a Role instead.`); + } + + const statement = new PolicyStatement() + .addActions(...options.actions) + .addResources(...(options.resourceSelfArns || options.resourceArns)) + .addPrincipal(options.principal!); - if (!options.resource) { - throw new Error('Could not add permissions to Principal without policy, and resource does not have policy either. Grant to a Role instead.'); - } + options.resource.addToResourcePolicy(statement); - options.resource.addToResourcePolicy(new PolicyStatement() - .addActions(...options.actions) - .addResources(...(options.resourceSelfArns || options.resourceArns)) - .addPrincipal(options.principal)); - addedToResource = true; + return grantResult({ addedToResource: true, statement }); + } - } while (false); + /** + * Try to grant the given permissions to the given principal + * + * Absence of a principal leads to a warning, but failing to add + * the permissions to a present principal is not an error. + */ + public static tryGrantOnIdentity(options: TryGrantOnIdentityOptions): GrantResult { + if (!options.principal) { + // tslint:disable-next-line:max-line-length + options.scope.node.addWarning(`Could not add grant for '${options.actions}' on '${options.resourceArns}' because the principal was not available. Add the permissions by hand.`); + return grantResult({ principalMissing: true }); + } - return { addedToPrincipal, addedToResource }; + const statement = new PolicyStatement() + .addActions(...options.actions) + .addResources(...options.resourceArns); + + const addedToPrincipal = options.principal.addToPolicy(statement); + + return grantResult({ addedToPrincipal, statement: addedToPrincipal ? statement : undefined }); + } + + /** + * Add a grant both on the identity and on the resource + * + * As long as any principal is given, granting on the pricipal may fail (in + * case of a non-identity principal), but granting on the resource will + * always be done. + * + * Statement will be the resource statement. + */ + public static grantOnIdentityAndResource(options: GrantOnIdentityAndResourceOptions): GrantResult { + const result = Permissions.tryGrantOnIdentity({ + actions: options.actions, + principal: options.principal, + resourceArns: options.resourceArns, + scope: options.resource + }); + + if (result.principalMissing) { return result; } + + const statement = new PolicyStatement() + .addActions(...options.actions) + .addResources(...(options.resourceSelfArns || options.resourceArns)) + .addPrincipal(options.principal!); + + options.resource.addToResourcePolicy(statement); + + return grantResult({ addedToPrincipal: result.addedToPrincipal, addedToResource: true, statement }); } } /** * The result of the grant() operation + * + * This class is not instantiable by consumers on purpose, so that they will be + * required to call the Permissions.grant() functions. */ -export interface GrantResult { +export class GrantResult { + /** + * There was no principal to add the permissions to + */ + public readonly principalMissing: boolean; + /** * The grant was added to the principal's policy */ - addedToPrincipal: boolean; + public readonly addedToPrincipal: boolean; /** * The grant was added to the resource policy */ - addedToResource: boolean; + public readonly addedToResource: boolean; + + /** + * The policy statement that was created for this permission + * + * Can be accessed to (e.g.) add additional conditions to the statement. + * + * Only set if either addedToPrincipal or addedToResource are true. + */ + public readonly statement?: PolicyStatement; + + /** + * Private member to make it impossible to construct object literals that structurally match this type + */ + private readonly _isGrantResult = true; + + private constructor(props: GrantResultProps) { + this.principalMissing = !!props.principalMissing; + this.addedToPrincipal = !!props.addedToPrincipal; + this.addedToResource = !!props.addedToResource; + this.statement = props.statement; + Array.isArray(this._isGrantResult); + } +} + +/** + * Instantiate a grantResult (which is normally not instantiable) + */ +function grantResult(props: GrantResultProps): GrantResult { + return Reflect.construct(GrantResult, [props]); +} + +interface GrantResultProps { + principalMissing?: boolean; + addedToPrincipal?: boolean; + addedToResource?: boolean; + statement?: PolicyStatement; } /** diff --git a/packages/@aws-cdk/aws-iam/lib/role.ts b/packages/@aws-cdk/aws-iam/lib/role.ts index be776567b2801..093343bbf3e9d 100644 --- a/packages/@aws-cdk/aws-iam/lib/role.ts +++ b/packages/@aws-cdk/aws-iam/lib/role.ts @@ -1,4 +1,5 @@ import { Construct, IConstruct, Output } from '@aws-cdk/cdk'; +import { Permissions } from './grant'; import { CfnRole } from './iam.generated'; import { IIdentity } from './identity-base'; import { Policy } from './policy'; @@ -208,21 +209,20 @@ export class Role extends Construct implements IRole { /** * Grant the actions defined in actions to the identity Principal on this resource. */ - public grant(identity?: IPrincipal, ...actions: string[]) { - if (!identity) { - return; - } - - identity.addToPolicy(new PolicyStatement() - .addResource(this.roleArn) - .addActions(...actions)); + public grant(principal?: IPrincipal, ...actions: string[]) { + return Permissions.grant({ + principal, + actions, + resourceArns: [this.roleArn], + scope: this, + }); } /** * Grant permissions to the given principal to pass this role. */ public grantPassRole(identity?: IPrincipal) { - this.grant(identity, 'iam:PassRole'); + return this.grant(identity, 'iam:PassRole'); } } diff --git a/packages/@aws-cdk/aws-kinesis/lib/stream.ts b/packages/@aws-cdk/aws-kinesis/lib/stream.ts index f95bd668ee79c..e057372c8ce53 100644 --- a/packages/@aws-cdk/aws-kinesis/lib/stream.ts +++ b/packages/@aws-cdk/aws-kinesis/lib/stream.ts @@ -32,7 +32,7 @@ export interface IStream extends cdk.IConstruct, logs.ILogSubscriptionDestinatio * If an encryption key is used, permission to ues the key to decrypt the * contents of the stream will also be granted. */ - grantRead(identity?: iam.IPrincipal): void; + grantRead(identity?: iam.IPrincipal): iam.GrantResult; /** * Grant write permissions for this stream and its contents to an IAM @@ -41,7 +41,7 @@ export interface IStream extends cdk.IConstruct, logs.ILogSubscriptionDestinatio * If an encryption key is used, permission to ues the key to encrypt the * contents of the stream will also be granted. */ - grantWrite(identity?: iam.IPrincipal): void; + grantWrite(identity?: iam.IPrincipal): iam.GrantResult; /** * Grants read/write permissions for this stream and its contents to an IAM @@ -50,7 +50,7 @@ export interface IStream extends cdk.IConstruct, logs.ILogSubscriptionDestinatio * If an encryption key is used, permission to use the key for * encrypt/decrypt will also be granted. */ - grantReadWrite(identity?: iam.IPrincipal): void; + grantReadWrite(identity?: iam.IPrincipal): iam.GrantResult; } /** @@ -117,23 +117,14 @@ export abstract class StreamBase extends cdk.Construct implements IStream { * If an encryption key is used, permission to ues the key to decrypt the * contents of the stream will also be granted. */ - public grantRead(identity?: iam.IPrincipal) { - if (!identity) { - return; + public grantRead(principal?: iam.IPrincipal) { + const ret = this.grant(principal, 'kinesis:DescribeStream', 'kinesis:GetRecords', 'kinesis:GetShardIterator'); + + if (this.encryptionKey) { + this.encryptionKey.grantDecrypt(principal); } - this.grant( - identity, - { - streamActions: [ - 'kinesis:DescribeStream', - 'kinesis:GetRecords', - 'kinesis:GetShardIterator' - ], - keyActions: [ - 'kms:Decrypt' - ] - } - ); + + return ret; } /** @@ -143,25 +134,14 @@ export abstract class StreamBase extends cdk.Construct implements IStream { * If an encryption key is used, permission to ues the key to decrypt the * contents of the stream will also be granted. */ - public grantWrite(identity?: iam.IPrincipal) { - if (!identity) { - return; + public grantWrite(principal?: iam.IPrincipal) { + const ret = this.grant(principal, 'kinesis:DescribeStream', 'kinesis:PutRecord', 'kinesis:PutRecords'); + + if (this.encryptionKey) { + this.encryptionKey.grantEncrypt(principal); } - this.grant( - identity, - { - streamActions: [ - 'kinesis:DescribeStream', - 'kinesis:PutRecord', - 'kinesis:PutRecords' - ], - keyActions: [ - 'kms:GenerateDataKey', - 'kms:Encrypt' - ] - } - ); + return ret; } /** @@ -171,27 +151,20 @@ export abstract class StreamBase extends cdk.Construct implements IStream { * If an encryption key is used, permission to use the key for * encrypt/decrypt will also be granted. */ - public grantReadWrite(identity?: iam.IPrincipal) { - if (!identity) { - return; + public grantReadWrite(principal?: iam.IPrincipal) { + const ret = this.grant( + principal, + 'kinesis:DescribeStream', + 'kinesis:GetRecords', + 'kinesis:GetShardIterator', + 'kinesis:PutRecord', + 'kinesis:PutRecords'); + + if (this.encryptionKey) { + this.encryptionKey.grantEncryptDecrypt(principal); } - this.grant( - identity, - { - streamActions: [ - 'kinesis:DescribeStream', - 'kinesis:GetRecords', - 'kinesis:GetShardIterator', - 'kinesis:PutRecord', - 'kinesis:PutRecords' - ], - keyActions: [ - 'kms:Decrypt', - 'kms:GenerateDataKey', - 'kms:Encrypt' - ] - } - ); + + return ret; } public logSubscriptionDestination(sourceLogGroup: logs.ILogGroup): logs.LogSubscriptionDestination { @@ -254,17 +227,13 @@ export abstract class StreamBase extends cdk.Construct implements IStream { return dest.logSubscriptionDestination(sourceLogGroup); } - private grant(principal: iam.IPrincipal, actions: { streamActions: string[], keyActions: string[] }) { - principal.addToPolicy(new iam.PolicyStatement() - .addResource(this.streamArn) - .addActions(...actions.streamActions)); - - // grant key permissions if there's an associated key. - if (this.encryptionKey) { - principal.addToPolicy(new iam.PolicyStatement() - .addResource(this.encryptionKey.keyArn) - .addActions(...actions.keyActions)); - } + private grant(principal?: iam.IPrincipal, ...actions: string[]) { + return iam.Permissions.grant({ + principal, + actions, + resourceArns: [this.streamArn], + scope: this, + }); } } diff --git a/packages/@aws-cdk/aws-kms/lib/key.ts b/packages/@aws-cdk/aws-kms/lib/key.ts index 1640cb338b917..60f89f051fa02 100644 --- a/packages/@aws-cdk/aws-kms/lib/key.ts +++ b/packages/@aws-cdk/aws-kms/lib/key.ts @@ -33,17 +33,22 @@ export interface IEncryptionKey extends IConstruct { /** * Grant the indicated permissions on this key to the given principal */ - grant(principal: iam.IPrincipal | undefined, ...actions: string[]): void; + grant(principal: iam.IPrincipal | undefined, ...actions: string[]): iam.GrantResult; /** * Grant decryption permisisons using this key to the given principal */ - grantDecrypt(principal: iam.IPrincipal | undefined): void; + grantDecrypt(principal: iam.IPrincipal | undefined): iam.GrantResult; /** * Grant encryption permisisons using this key to the given principal */ - grantEncrypt(principal: iam.IPrincipal | undefined): void; + grantEncrypt(principal: iam.IPrincipal | undefined): iam.GrantResult; + + /** + * Grant encryption and decryption permisisons using this key to the given principal + */ + grantEncryptDecrypt(principal: iam.IPrincipal | undefined): iam.GrantResult; } export interface EncryptionKeyImportProps { @@ -99,27 +104,20 @@ export abstract class EncryptionKeyBase extends Construct implements IEncryption * since the default CloudFormation setup for KMS keys is that the policy * must not be empty and so default grants won't work. */ - public grant(principal: iam.IPrincipal | undefined, ...actions: string[]): void { - iam.Permissions.grant({ + public grant(principal: iam.IPrincipal | undefined, ...actions: string[]): iam.GrantResult { + return iam.Permissions.grantOnIdentityAndResource({ principal, actions, resourceArns: [this.keyArn], - skipResourcePolicy: true, - scope: this + resource: this, + resourceSelfArns: ['*'] }); - - if (principal) { - this.addToResourcePolicy(new iam.PolicyStatement() - .addPrincipal(principal) - .addActions(...actions) - .addAllResources()); - } } /** * Grant decryption permisisons using this key to the given principal */ - public grantDecrypt(principal: iam.IPrincipal | undefined): void { + public grantDecrypt(principal: iam.IPrincipal | undefined): iam.GrantResult { return this.grant(principal, 'kms:Decrypt', 'kms:DescribeKey' @@ -129,13 +127,26 @@ export abstract class EncryptionKeyBase extends Construct implements IEncryption /** * Grant encryption permisisons using this key to the given principal */ - public grantEncrypt(principal: iam.IPrincipal | undefined): void { + public grantEncrypt(principal: iam.IPrincipal | undefined): iam.GrantResult { return this.grant(principal, 'kms:Encrypt', 'kms:ReEncrypt*', 'kms:GenerateDataKey*' ); } + + /** + * Grant encryption and decryption permisisons using this key to the given principal + */ + public grantEncryptDecrypt(principal: iam.IPrincipal | undefined): iam.GrantResult { + return this.grant(principal, + 'kms:Decrypt', + 'kms:DescribeKey', + 'kms:Encrypt', + 'kms:ReEncrypt*', + 'kms:GenerateDataKey*' + ); + } } /** diff --git a/packages/@aws-cdk/aws-lambda/lib/function-base.ts b/packages/@aws-cdk/aws-lambda/lib/function-base.ts index 52a452809a0ef..c2a349203aff2 100644 --- a/packages/@aws-cdk/aws-lambda/lib/function-base.ts +++ b/packages/@aws-cdk/aws-lambda/lib/function-base.ts @@ -60,7 +60,7 @@ export interface IFunction extends cdk.IConstruct, events.IEventRuleTarget, logs /** * Grant the given identity permissions to invoke this Lambda */ - grantInvoke(identity?: iam.IPrincipal): void; + grantInvoke(identity?: iam.IPrincipal): iam.GrantResult; /** * Return the given named metric for this Lambda @@ -246,25 +246,28 @@ export abstract class FunctionBase extends cdk.Construct implements IFunction { /** * Grant the given identity permissions to invoke this Lambda */ - public grantInvoke(principal?: iam.IPrincipal) { - const added = iam.Permissions.grant({ + public grantInvoke(principal?: iam.IPrincipal): iam.GrantResult { + return iam.Permissions.grant({ principal, actions: ['lambda:InvokeFunction'], resourceArns: [this.functionArn], - // Can't use a resource policy because adding resource permissions - // looks different on a Lambda Function. - skipResourcePolicy: true, scope: this, - }); - if (principal && !added.addedToPrincipal) { - // Couldn't add permissions to the principal, so add them locally. - const identifier = 'Invoke' + JSON.stringify(principal!.policyFragment.principalJson); - this.addPermission(identifier, { - principal, - action: 'lambda:InvokeFunction', - }); - } + // Fake resource-like object on which to call addToResourcePolicy(), which actually + // calls addPermission() + resource: { + addToResourcePolicy: (_statement) => { + // Couldn't add permissions to the principal, so add them locally. + const identifier = 'Invoke' + JSON.stringify(principal!.policyFragment.principalJson); + this.addPermission(identifier, { + principal: principal!, + action: 'lambda:InvokeFunction', + }); + }, + dependencyRoots: [], + node: this.node, + }, + }); } public logSubscriptionDestination(sourceLogGroup: logs.ILogGroup): logs.LogSubscriptionDestination { diff --git a/packages/@aws-cdk/aws-lambda/package.json b/packages/@aws-cdk/aws-lambda/package.json index df4ab8ab72c0b..8844cf7b801ca 100644 --- a/packages/@aws-cdk/aws-lambda/package.json +++ b/packages/@aws-cdk/aws-lambda/package.json @@ -96,5 +96,10 @@ }, "engines": { "node": ">= 8.10.0" + }, + "awslint": { + "exclude": [ + "grant-result:@aws-cdk/aws-lambda.LayerVersionBase.grantUsage" + ] } } diff --git a/packages/@aws-cdk/aws-logs/lib/log-group.ts b/packages/@aws-cdk/aws-logs/lib/log-group.ts index f1329da683cf1..74ac0f4292101 100644 --- a/packages/@aws-cdk/aws-logs/lib/log-group.ts +++ b/packages/@aws-cdk/aws-logs/lib/log-group.ts @@ -69,12 +69,12 @@ export interface ILogGroup extends cdk.IConstruct { /** * Give permissions to write to create and write to streams in this log group */ - grantWrite(principal?: iam.IPrincipal): void; + grantWrite(principal?: iam.IPrincipal): iam.GrantResult; /** * Give the indicated permissions on this log group and all streams */ - grant(principal?: iam.IPrincipal, ...actions: string[]): void; + grant(principal?: iam.IPrincipal, ...actions: string[]): iam.GrantResult; } /** @@ -172,14 +172,14 @@ export abstract class LogGroupBase extends cdk.Construct implements ILogGroup { * Give permissions to write to create and write to streams in this log group */ public grantWrite(principal?: iam.IPrincipal) { - this.grant(principal, 'logs:CreateLogStream', 'logs:PutLogEvents'); + return this.grant(principal, 'logs:CreateLogStream', 'logs:PutLogEvents'); } /** * Give the indicated permissions on this log group and all streams */ public grant(principal?: iam.IPrincipal, ...actions: string[]) { - iam.Permissions.grant({ + return iam.Permissions.grant({ principal, actions, // A LogGroup ARN out of CloudFormation already includes a ':*' at the end to include the log streams under the group. diff --git a/packages/@aws-cdk/aws-s3/lib/bucket.ts b/packages/@aws-cdk/aws-s3/lib/bucket.ts index 6d9076c4c2d10..3b89d3b6b8ae1 100644 --- a/packages/@aws-cdk/aws-s3/lib/bucket.ts +++ b/packages/@aws-cdk/aws-s3/lib/bucket.ts @@ -111,7 +111,7 @@ export interface IBucket extends cdk.IConstruct { * @param identity The principal * @param objectsKeyPattern Restrict the permission to a certain key pattern (default '*') */ - grantRead(identity?: iam.IPrincipal, objectsKeyPattern?: any): void; + grantRead(identity?: iam.IPrincipal, objectsKeyPattern?: any): iam.GrantResult; /** * Grant write permissions to this bucket to an IAM principal. @@ -122,7 +122,7 @@ export interface IBucket extends cdk.IConstruct { * @param identity The principal * @param objectsKeyPattern Restrict the permission to a certain key pattern (default '*') */ - grantWrite(identity?: iam.IPrincipal, objectsKeyPattern?: any): void; + grantWrite(identity?: iam.IPrincipal, objectsKeyPattern?: any): iam.GrantResult; /** * Grants s3:PutObject* and s3:Abort* permissions for this bucket to an IAM principal. @@ -132,7 +132,7 @@ export interface IBucket extends cdk.IConstruct { * @param identity The principal * @param objectsKeyPattern Restrict the permission to a certain key pattern (default '*') */ - grantPut(identity?: iam.IPrincipal, objectsKeyPattern?: any): void; + grantPut(identity?: iam.IPrincipal, objectsKeyPattern?: any): iam.GrantResult; /** * Grants s3:DeleteObject* permission to an IAM pricipal for objects @@ -141,7 +141,7 @@ export interface IBucket extends cdk.IConstruct { * @param identity The principal * @param objectsKeyPattern Restrict the permission to a certain key pattern (default '*') */ - grantDelete(identity?: iam.IPrincipal, objectsKeyPattern?: any): void; + grantDelete(identity?: iam.IPrincipal, objectsKeyPattern?: any): iam.GrantResult; /** * Grants read/write permissions for this bucket and it's contents to an IAM @@ -153,7 +153,7 @@ export interface IBucket extends cdk.IConstruct { * @param identity The principal * @param objectsKeyPattern Restrict the permission to a certain key pattern (default '*') */ - grantReadWrite(identity?: iam.IPrincipal, objectsKeyPattern?: any): void; + grantReadWrite(identity?: iam.IPrincipal, objectsKeyPattern?: any): iam.GrantResult; /** * Allows unrestricted access to objects from this bucket. @@ -178,7 +178,7 @@ export interface IBucket extends cdk.IConstruct { * @param allowedActions the set of S3 actions to allow. Default is "s3:GetObject". * @returns The `iam.PolicyStatement` object, which can be used to apply e.g. conditions. */ - grantPublicAccess(keyPrefix?: string, ...allowedActions: string[]): iam.PolicyStatement; + grantPublicAccess(keyPrefix?: string, ...allowedActions: string[]): iam.GrantResult; /** * Defines a CloudWatch Event Rule that triggers upon putting an object into the Bucket. @@ -410,7 +410,7 @@ export abstract class BucketBase extends cdk.Construct implements IBucket { * @param objectsKeyPattern Restrict the permission to a certain key pattern (default '*') */ public grantRead(identity?: iam.IPrincipal, objectsKeyPattern: any = '*') { - this.grant(identity, perms.BUCKET_READ_ACTIONS, perms.KEY_READ_ACTIONS, + return this.grant(identity, perms.BUCKET_READ_ACTIONS, perms.KEY_READ_ACTIONS, this.bucketArn, this.arnForObjects(objectsKeyPattern)); } @@ -425,7 +425,7 @@ export abstract class BucketBase extends cdk.Construct implements IBucket { * @param objectsKeyPattern Restrict the permission to a certain key pattern (default '*') */ public grantWrite(identity?: iam.IPrincipal, objectsKeyPattern: any = '*') { - this.grant(identity, perms.BUCKET_WRITE_ACTIONS, perms.KEY_WRITE_ACTIONS, + return this.grant(identity, perms.BUCKET_WRITE_ACTIONS, perms.KEY_WRITE_ACTIONS, this.bucketArn, this.arnForObjects(objectsKeyPattern)); } @@ -439,7 +439,7 @@ export abstract class BucketBase extends cdk.Construct implements IBucket { * @param objectsKeyPattern Restrict the permission to a certain key pattern (default '*') */ public grantPut(identity?: iam.IPrincipal, objectsKeyPattern: any = '*') { - this.grant(identity, perms.BUCKET_PUT_ACTIONS, perms.KEY_WRITE_ACTIONS, + return this.grant(identity, perms.BUCKET_PUT_ACTIONS, perms.KEY_WRITE_ACTIONS, this.arnForObjects(objectsKeyPattern)); } @@ -451,7 +451,7 @@ export abstract class BucketBase extends cdk.Construct implements IBucket { * @param objectsKeyPattern Restrict the permission to a certain key pattern (default '*') */ public grantDelete(identity?: iam.IPrincipal, objectsKeyPattern: any = '*') { - this.grant(identity, perms.BUCKET_DELETE_ACTIONS, [], + return this.grant(identity, perms.BUCKET_DELETE_ACTIONS, [], this.arnForObjects(objectsKeyPattern)); } @@ -469,7 +469,7 @@ export abstract class BucketBase extends cdk.Construct implements IBucket { const bucketActions = perms.BUCKET_READ_ACTIONS.concat(perms.BUCKET_WRITE_ACTIONS); const keyActions = perms.KEY_READ_ACTIONS.concat(perms.KEY_WRITE_ACTIONS); - this.grant(identity, + return this.grant(identity, bucketActions, keyActions, this.bucketArn, @@ -497,22 +497,20 @@ export abstract class BucketBase extends cdk.Construct implements IBucket { * * @param keyPrefix the prefix of S3 object keys (e.g. `home/*`). Default is "*". * @param allowedActions the set of S3 actions to allow. Default is "s3:GetObject". - * @returns The `iam.PolicyStatement` object, which can be used to apply e.g. conditions. */ - public grantPublicAccess(keyPrefix = '*', ...allowedActions: string[]): iam.PolicyStatement { + public grantPublicAccess(keyPrefix = '*', ...allowedActions: string[]) { if (this.disallowPublicAccess) { throw new Error("Cannot grant public access when 'blockPublicPolicy' is enabled"); } allowedActions = allowedActions.length > 0 ? allowedActions : [ 's3:GetObject' ]; - const statement = new iam.PolicyStatement() - .addActions(...allowedActions) - .addResource(this.arnForObjects(keyPrefix)) - .addPrincipal(new iam.Anyone()); - - this.addToResourcePolicy(statement); - return statement; + return iam.Permissions.grant({ + actions: allowedActions, + resourceArns: [this.arnForObjects(keyPrefix)], + principal: new iam.Anyone(), + resource: this, + }); } private grant(principal: iam.IPrincipal | undefined, @@ -521,7 +519,7 @@ export abstract class BucketBase extends cdk.Construct implements IBucket { resourceArn: string, ...otherResourceArns: string[]) { const resources = [ resourceArn, ...otherResourceArns ]; - iam.Permissions.grant({ + const ret = iam.Permissions.grant({ principal, actions: bucketActions, resourceArns: resources, @@ -531,6 +529,8 @@ export abstract class BucketBase extends cdk.Construct implements IBucket { if (this.encryptionKey) { this.encryptionKey.grant(principal, ...keyActions); } + + return ret; } } diff --git a/packages/@aws-cdk/aws-s3/test/test.bucket.ts b/packages/@aws-cdk/aws-s3/test/test.bucket.ts index e9d3b3596f97e..8f1e4ab131019 100644 --- a/packages/@aws-cdk/aws-s3/test/test.bucket.ts +++ b/packages/@aws-cdk/aws-s3/test/test.bucket.ts @@ -1273,8 +1273,8 @@ export = { const bucket = new s3.Bucket(stack, 'b'); // WHEN - const statement = bucket.grantPublicAccess(); - statement.addCondition('IpAddress', { "aws:SourceIp": "54.240.143.0/24" }); + const result = bucket.grantPublicAccess(); + result.statement!.addCondition('IpAddress', { "aws:SourceIp": "54.240.143.0/24" }); // THEN expect(stack).to(haveResource('AWS::S3::BucketPolicy', { diff --git a/packages/@aws-cdk/aws-secretsmanager/lib/secret.ts b/packages/@aws-cdk/aws-secretsmanager/lib/secret.ts index 659d91e4c59f2..fd1e63c16a93b 100644 --- a/packages/@aws-cdk/aws-secretsmanager/lib/secret.ts +++ b/packages/@aws-cdk/aws-secretsmanager/lib/secret.ts @@ -39,7 +39,7 @@ export interface ISecret extends cdk.IConstruct { * @param versionStages the version stages the grant is limited to. If not specified, no restriction on the version * stages is applied. */ - grantRead(grantee: iam.IPrincipal, versionStages?: string[]): void; + grantRead(principal?: iam.IPrincipal, versionStages?: string[]): iam.GrantResult; } /** @@ -101,30 +101,33 @@ export abstract class SecretBase extends cdk.Construct implements ISecret { public abstract export(): SecretImportProps; - public grantRead(grantee: iam.IPrincipal, versionStages?: string[]): void { + public grantRead(principal?: iam.IPrincipal, versionStages?: string[]): iam.GrantResult { // @see https://docs.aws.amazon.com/fr_fr/secretsmanager/latest/userguide/auth-and-access_identity-based-policies.html - const statement = new iam.PolicyStatement() - .allow() - .addAction('secretsmanager:GetSecretValue') - .addResource(this.secretArn); + + const result = iam.Permissions.grant({ + principal, + actions: ['secretsmanager:GetSecretValue'], + resourceArns: [this.secretArn], + scope: this + }); if (versionStages != null) { - statement.addCondition('ForAnyValue:StringEquals', { + result.statement!.addCondition('ForAnyValue:StringEquals', { 'secretsmanager:VersionStage': versionStages }); } - grantee.addToPolicy(statement); - if (this.encryptionKey) { + if (this.encryptionKey && principal) { // @see https://docs.aws.amazon.com/fr_fr/kms/latest/developerguide/services-secrets-manager.html this.encryptionKey.addToResourcePolicy(new iam.PolicyStatement() - .allow() - .addPrincipal(grantee) - .addAction('kms:Decrypt') - .addAllResources() - .addCondition('StringEquals', { - 'kms:ViaService': `secretsmanager.${this.node.stack.region}.amazonaws.com` - })); + .addPrincipal(principal) + .addAction('kms:Decrypt') + .addAllResources() + .addCondition('StringEquals', { + 'kms:ViaService': `secretsmanager.${this.node.stack.region}.amazonaws.com` + })); } + + return result; } public toSecretString() { diff --git a/packages/@aws-cdk/aws-sns/lib/topic-base.ts b/packages/@aws-cdk/aws-sns/lib/topic-base.ts index 58c78c4c622d6..537698ab343a1 100644 --- a/packages/@aws-cdk/aws-sns/lib/topic-base.ts +++ b/packages/@aws-cdk/aws-sns/lib/topic-base.ts @@ -81,7 +81,7 @@ export interface ITopic extends /** * Grant topic publishing permissions to the given identity */ - grantPublish(identity?: iam.IPrincipal): void; + grantPublish(identity?: iam.IPrincipal): iam.GrantResult; } /** @@ -264,7 +264,7 @@ export abstract class TopicBase extends cdk.Construct implements ITopic { * Grant topic publishing permissions to the given identity */ public grantPublish(principal?: iam.IPrincipal) { - iam.Permissions.grant({ + return iam.Permissions.grant({ principal, actions: ['sns:Publish'], resourceArns: [this.topicArn], diff --git a/packages/@aws-cdk/aws-sqs/lib/queue-base.ts b/packages/@aws-cdk/aws-sqs/lib/queue-base.ts index d9f178e18e1aa..9542aa63c5ecb 100644 --- a/packages/@aws-cdk/aws-sqs/lib/queue-base.ts +++ b/packages/@aws-cdk/aws-sqs/lib/queue-base.ts @@ -55,7 +55,7 @@ export interface IQueue extends cdk.IConstruct, s3n.IBucketNotificationDestinati * * @param identity Principal to grant consume rights to */ - grantConsumeMessages(identity?: iam.IPrincipal): void; + grantConsumeMessages(identity?: iam.IPrincipal): iam.GrantResult; /** * Grant access to send messages to a queue to the given identity. @@ -69,7 +69,7 @@ export interface IQueue extends cdk.IConstruct, s3n.IBucketNotificationDestinati * * @param identity Principal to grant send rights to */ - grantSendMessages(identity?: iam.IPrincipal): void; + grantSendMessages(identity?: iam.IPrincipal): iam.GrantResult; /** * Grant an IAM principal permissions to purge all messages from the queue. @@ -83,7 +83,7 @@ export interface IQueue extends cdk.IConstruct, s3n.IBucketNotificationDestinati * @param identity Principal to grant send rights to * @param queueActions additional queue actions to allow */ - grantPurge(identity?: iam.IPrincipal): void; + grantPurge(identity?: iam.IPrincipal): iam.GrantResult; /** * Grant the actions defined in queueActions to the identity Principal given @@ -92,7 +92,7 @@ export interface IQueue extends cdk.IConstruct, s3n.IBucketNotificationDestinati * @param identity Principal to grant right to * @param queueActions The actions to grant */ - grant(identity?: iam.IPrincipal, ...queueActions: string[]): void; + grant(identity?: iam.IPrincipal, ...queueActions: string[]): iam.GrantResult; } /** @@ -217,7 +217,7 @@ export abstract class QueueBase extends cdk.Construct implements IQueue { * @param identity Principal to grant consume rights to */ public grantConsumeMessages(identity?: iam.IPrincipal) { - this.grant(identity, + return this.grant(identity, 'sqs:ReceiveMessage', 'sqs:ChangeMessageVisibility', 'sqs:ChangeMessageVisibilityBatch', @@ -240,7 +240,7 @@ export abstract class QueueBase extends cdk.Construct implements IQueue { * @param identity Principal to grant send rights to */ public grantSendMessages(identity?: iam.IPrincipal) { - this.grant(identity, + return this.grant(identity, 'sqs:SendMessage', 'sqs:SendMessageBatch', 'sqs:GetQueueAttributes', @@ -260,7 +260,7 @@ export abstract class QueueBase extends cdk.Construct implements IQueue { * @param queueActions additional queue actions to allow */ public grantPurge(identity?: iam.IPrincipal) { - this.grant(identity, + return this.grant(identity, 'sqs:PurgeQueue', 'sqs:GetQueueAttributes', 'sqs:GetQueueUrl'); @@ -274,7 +274,7 @@ export abstract class QueueBase extends cdk.Construct implements IQueue { * @param actions The actions to grant */ public grant(principal?: iam.IPrincipal, ...actions: string[]) { - iam.Permissions.grant({ + return iam.Permissions.grant({ principal, actions, resourceArns: [this.queueArn], diff --git a/tools/awslint/lib/linter.ts b/tools/awslint/lib/linter.ts index 76fff07bd1d6d..049af76a92871 100644 --- a/tools/awslint/lib/linter.ts +++ b/tools/awslint/lib/linter.ts @@ -1,4 +1,5 @@ import reflect = require('jsii-reflect'); +import { PrimitiveType } from 'jsii-spec'; export interface LinterOptions { /** @@ -115,10 +116,16 @@ export class Evaluation { return this.assert(actual === expected, scope, ` (expected="${expected}",actual="${actual}")`); } + public assertTypesEqual(ts: reflect.TypeSystem, actual: TypeSpecifier, expected: TypeSpecifier, scope: string) { + const a = typeReferenceFrom(ts, actual); + const e = typeReferenceFrom(ts, expected); + return this.assert(a.toString() === e.toString(), scope, ` (expected="${e}",actual="${a}")`); + } + public assertSignature(method: reflect.Method, expectations: MethodSignatureExpectations) { const scope = method.parentType.fqn + '.' + method.name; if (expectations.returns) { - this.assertEquals(expectations.returns.toString(), expectations.returns, scope); + this.assertTypesEqual(method.system, method.returns, expectations.returns, scope); } if (expectations.parameters) { @@ -135,18 +142,7 @@ export class Evaluation { this.assertEquals(actualName, expectedName, pscope); } if (expect.type) { - const expectedType = expect.type; - const actualType = (() => { - if (actual.type.fqn) { - return actual.type.fqn.fqn; - } - if (actual.type.primitive) { - return actual.type.primitive; - } - return actual.type.toString(); - })(); - - this.assertEquals(actualType, expectedType, pscope); + this.assertTypesEqual(method.system, actual.type, expect.type, pscope); } } } @@ -205,9 +201,19 @@ export interface Rule { eval(linter: Evaluation): void; } +/** + * A type constraint + * + * Be super flexible about how types can be represented. Ultimately, we will + * compare what you give to a TypeReference, because that's what's in the JSII + * Reflect model. However, if you already have a real Type, or just a string to + * a user-defined type, that's fine too. We'll Do The Right Thing. + */ +export type TypeSpecifier = reflect.TypeReference | reflect.Type | string; + export interface MethodSignatureParameterExpectation { name?: string; - type?: string; + type?: TypeSpecifier; /** should this param be optional? */ optional?: boolean; @@ -215,7 +221,7 @@ export interface MethodSignatureParameterExpectation { export interface MethodSignatureExpectations { parameters?: MethodSignatureParameterExpectation[]; - returns?: string; + returns?: TypeSpecifier; } export enum DiagnosticLevel { @@ -232,3 +238,24 @@ export interface Diagnostic { scope: string; message: string; } + +/** + * Convert a type specifier to a TypeReference + */ +function typeReferenceFrom(ts: reflect.TypeSystem, x: TypeSpecifier): reflect.TypeReference { + if (isTypeReference(x)) { return x; } + + if (typeof x === 'string') { + if (x.indexOf('.') === -1) { + return new reflect.TypeReference(ts, { primitive: x as PrimitiveType }); + } else { + return new reflect.TypeReference(ts, { fqn: x }); + } + } + + return new reflect.TypeReference(ts, x); +} + +function isTypeReference(x: any): x is reflect.TypeReference { + return x instanceof reflect.TypeReference; +} \ No newline at end of file diff --git a/tools/awslint/lib/rules/resource.ts b/tools/awslint/lib/rules/resource.ts index 8c1f391fd2ffb..c09ef1b3f7226 100644 --- a/tools/awslint/lib/rules/resource.ts +++ b/tools/awslint/lib/rules/resource.ts @@ -1,7 +1,7 @@ import reflect = require('jsii-reflect'); import { CfnResourceSpec, findCfnResources } from '../cfn-resources'; import { Linter } from '../linter'; -import { CONSTRUCT_FQN, CONSTRUCT_INTERFACE_FQN, isConstruct } from '../util'; +import { classAndAncestors, CONSTRUCT_FQN, CONSTRUCT_INTERFACE_FQN, isConstruct } from '../util'; export const resourceLinter = new Linter(assembly => { return findCfnResources(assembly).map(cfn => ({ @@ -11,6 +11,8 @@ export const resourceLinter = new Linter(assembly => { })); }); +const GRANT_RESULT_FQN = '@aws-cdk/aws-iam.GrantResult'; + interface ResourceLinterContext { readonly ts: reflect.TypeSystem; readonly resource: CfnResourceSpec; @@ -149,7 +151,7 @@ resourceLinter.add({ } e.assertSignature(importMethod, { - returns: e.ctx.resourceInterface.fqn, + returns: e.ctx.resourceInterface, parameters: [ { name: 'scope', type: CONSTRUCT_FQN }, { name: 'id', type: 'string' }, @@ -173,8 +175,27 @@ resourceLinter.add({ if (!e.ctx.importPropsInterface) { return; } e.assertSignature(exportMethod, { - returns: e.ctx.importPropsInterface.fqn, + returns: e.ctx.importPropsInterface, parameters: [] }); } }); + +resourceLinter.add({ + code: 'grant-result', + message: `"grant" method must return ${GRANT_RESULT_FQN}`, + eval: e => { + if (!e.ctx.resourceClass) { return; } + + const grantResultType = e.ctx.ts.findFqn(GRANT_RESULT_FQN); + + for (const klass of classAndAncestors(e.ctx.resourceClass)) { + const grantMethods = klass.methods.filter(m => m.name.startsWith('grant') && !m.static); + for (const grantMethod of grantMethods) { + e.assertSignature(grantMethod, { + returns: grantResultType + }); + } + } + } +}); \ No newline at end of file diff --git a/tools/awslint/lib/util.ts b/tools/awslint/lib/util.ts index 59b13085074ae..535c189dc36c8 100644 --- a/tools/awslint/lib/util.ts +++ b/tools/awslint/lib/util.ts @@ -9,3 +9,14 @@ export function isConstruct(c: reflect.ClassType) { const root = bases[bases.length - 1]; return root === constructClass; } + +/** + * Iterate over a class and all of its ancestors + */ +export function* classAndAncestors(c: reflect.ClassType): Iterable { + yield c; + + for (const ancestor of c.getAncestors()) { + yield* classAndAncestors(ancestor); + } +} \ No newline at end of file From df4622127dd2555482c497e4b0591f8f6a4324bc Mon Sep 17 00:00:00 2001 From: Rico Huijbers Date: Wed, 27 Feb 2019 16:29:51 +0100 Subject: [PATCH 11/31] WIP --- .../aws-cloudformation/test/test.pipeline-actions.ts | 4 ++-- packages/@aws-cdk/aws-ecr/lib/repository-ref.ts | 2 +- packages/@aws-cdk/aws-iam/lib/grant.ts | 10 +++++----- packages/@aws-cdk/aws-kms/lib/key.ts | 2 +- tools/awslint/lib/rules/resource.ts | 2 +- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/packages/@aws-cdk/aws-cloudformation/test/test.pipeline-actions.ts b/packages/@aws-cdk/aws-cloudformation/test/test.pipeline-actions.ts index 43ff515896f67..b195105f486fd 100644 --- a/packages/@aws-cdk/aws-cloudformation/test/test.pipeline-actions.ts +++ b/packages/@aws-cdk/aws-cloudformation/test/test.pipeline-actions.ts @@ -316,11 +316,11 @@ class PipelineDouble extends cdk.Construct implements cpapi.IPipeline { throw new Error('asEventRuleTarget() is unsupported in PipelineDouble'); } - public grantBucketRead(_identity?: iam.IPrincipal): void { + public grantBucketRead(_identity?: iam.IPrincipal): iam.GrantResult { throw new Error('grantBucketRead() is unsupported in PipelineDouble'); } - public grantBucketReadWrite(_identity?: iam.IPrincipal): void { + public grantBucketReadWrite(_identity?: iam.IPrincipal): iam.GrantResult { throw new Error('grantBucketReadWrite() is unsupported in PipelineDouble'); } } diff --git a/packages/@aws-cdk/aws-ecr/lib/repository-ref.ts b/packages/@aws-cdk/aws-ecr/lib/repository-ref.ts index 725d8ea7342ea..5c9680e8116df 100644 --- a/packages/@aws-cdk/aws-ecr/lib/repository-ref.ts +++ b/packages/@aws-cdk/aws-ecr/lib/repository-ref.ts @@ -221,7 +221,7 @@ export abstract class RepositoryBase extends cdk.Construct implements IRepositor public grantPull(principal?: iam.IPrincipal) { const ret = this.grant(principal, "ecr:BatchCheckLayerAvailability", "ecr:GetDownloadUrlForLayer", "ecr:BatchGetImage"); - iam.Permissions.tryGrantOnIdentity({ + iam.Permissions.tryGrantOnPrincipal({ principal, actions: ["ecr:GetAuthorizationToken"], resourceArns: ['*'], diff --git a/packages/@aws-cdk/aws-iam/lib/grant.ts b/packages/@aws-cdk/aws-iam/lib/grant.ts index c85669e6b547e..a42823d925d2e 100644 --- a/packages/@aws-cdk/aws-iam/lib/grant.ts +++ b/packages/@aws-cdk/aws-iam/lib/grant.ts @@ -139,7 +139,7 @@ export class Permissions { throw new Error(`Either 'scope' or 'resource' must be supplied.`); } - const result = Permissions.tryGrantOnIdentity({ + const result = Permissions.tryGrantOnPrincipal({ actions: options.actions, principal: options.principal, resourceArns: options.resourceArns, @@ -169,7 +169,7 @@ export class Permissions { * Absence of a principal leads to a warning, but failing to add * the permissions to a present principal is not an error. */ - public static tryGrantOnIdentity(options: TryGrantOnIdentityOptions): GrantResult { + public static tryGrantOnPrincipal(options: TryGrantOnIdentityOptions): GrantResult { if (!options.principal) { // tslint:disable-next-line:max-line-length options.scope.node.addWarning(`Could not add grant for '${options.actions}' on '${options.resourceArns}' because the principal was not available. Add the permissions by hand.`); @@ -186,7 +186,7 @@ export class Permissions { } /** - * Add a grant both on the identity and on the resource + * Add a grant both on the principal and on the resource * * As long as any principal is given, granting on the pricipal may fail (in * case of a non-identity principal), but granting on the resource will @@ -194,8 +194,8 @@ export class Permissions { * * Statement will be the resource statement. */ - public static grantOnIdentityAndResource(options: GrantOnIdentityAndResourceOptions): GrantResult { - const result = Permissions.tryGrantOnIdentity({ + public static grantOnPrincipalAndResource(options: GrantOnIdentityAndResourceOptions): GrantResult { + const result = Permissions.tryGrantOnPrincipal({ actions: options.actions, principal: options.principal, resourceArns: options.resourceArns, diff --git a/packages/@aws-cdk/aws-kms/lib/key.ts b/packages/@aws-cdk/aws-kms/lib/key.ts index 60f89f051fa02..7fd0805dd9ec6 100644 --- a/packages/@aws-cdk/aws-kms/lib/key.ts +++ b/packages/@aws-cdk/aws-kms/lib/key.ts @@ -105,7 +105,7 @@ export abstract class EncryptionKeyBase extends Construct implements IEncryption * must not be empty and so default grants won't work. */ public grant(principal: iam.IPrincipal | undefined, ...actions: string[]): iam.GrantResult { - return iam.Permissions.grantOnIdentityAndResource({ + return iam.Permissions.grantOnPrincipalAndResource({ principal, actions, resourceArns: [this.keyArn], diff --git a/tools/awslint/lib/rules/resource.ts b/tools/awslint/lib/rules/resource.ts index c09ef1b3f7226..450a10d2d15b2 100644 --- a/tools/awslint/lib/rules/resource.ts +++ b/tools/awslint/lib/rules/resource.ts @@ -190,7 +190,7 @@ resourceLinter.add({ const grantResultType = e.ctx.ts.findFqn(GRANT_RESULT_FQN); for (const klass of classAndAncestors(e.ctx.resourceClass)) { - const grantMethods = klass.methods.filter(m => m.name.startsWith('grant') && !m.static); + const grantMethods = klass.methods.filter(m => m.name.startsWith('grant')); for (const grantMethod of grantMethods) { e.assertSignature(grantMethod, { returns: grantResultType From 84289377fc546ba7c7e57251212555a08250ed66 Mon Sep 17 00:00:00 2001 From: Rico Huijbers Date: Thu, 28 Feb 2019 14:10:35 +0100 Subject: [PATCH 12/31] Update API --- .../assets-docker/test/test.image-asset.ts | 13 +- .../test/test.pipeline-actions.ts | 4 +- .../aws-codepipeline-api/lib/action.ts | 4 +- .../@aws-cdk/aws-codepipeline/lib/pipeline.ts | 4 +- packages/@aws-cdk/aws-dynamodb/lib/table.ts | 6 +- .../@aws-cdk/aws-ecr/lib/repository-ref.ts | 10 +- packages/@aws-cdk/aws-iam/lib/grant.ts | 166 ++++++++---------- .../@aws-cdk/aws-iam/lib/policy-document.ts | 6 + packages/@aws-cdk/aws-iam/lib/role.ts | 4 +- packages/@aws-cdk/aws-kinesis/lib/stream.ts | 8 +- .../@aws-cdk/aws-kinesis/test/test.stream.ts | 67 ++++++- packages/@aws-cdk/aws-kms/lib/key.ts | 16 +- .../@aws-cdk/aws-lambda/lib/function-base.ts | 7 +- packages/@aws-cdk/aws-logs/lib/log-group.ts | 6 +- packages/@aws-cdk/aws-s3/lib/bucket.ts | 16 +- .../@aws-cdk/aws-secretsmanager/lib/secret.ts | 6 +- packages/@aws-cdk/aws-sns/lib/topic-base.ts | 4 +- packages/@aws-cdk/aws-sqs/lib/queue-base.ts | 10 +- tools/awslint/lib/rules/resource.ts | 2 +- 19 files changed, 191 insertions(+), 168 deletions(-) diff --git a/packages/@aws-cdk/assets-docker/test/test.image-asset.ts b/packages/@aws-cdk/assets-docker/test/test.image-asset.ts index 90f925bf333b1..6bced85d52a09 100644 --- a/packages/@aws-cdk/assets-docker/test/test.image-asset.ts +++ b/packages/@aws-cdk/assets-docker/test/test.image-asset.ts @@ -61,22 +61,13 @@ export = { ":", { "Ref": "AWS::AccountId" }, ":repository/", - { - "Fn::GetAtt": [ - "ImageAdoptRepositoryE1E84E35", - "RepositoryName" - ] - } + { "Fn::GetAtt": [ "ImageAdoptRepositoryE1E84E35", "RepositoryName" ] } ] ] } }, { - "Action": [ - "ecr:GetAuthorizationToken", - "logs:CreateLogStream", - "logs:PutLogEvents" - ], + "Action": "ecr:GetAuthorizationToken", "Effect": "Allow", "Resource": "*" } diff --git a/packages/@aws-cdk/aws-cloudformation/test/test.pipeline-actions.ts b/packages/@aws-cdk/aws-cloudformation/test/test.pipeline-actions.ts index b195105f486fd..220d4fd063c1e 100644 --- a/packages/@aws-cdk/aws-cloudformation/test/test.pipeline-actions.ts +++ b/packages/@aws-cdk/aws-cloudformation/test/test.pipeline-actions.ts @@ -316,11 +316,11 @@ class PipelineDouble extends cdk.Construct implements cpapi.IPipeline { throw new Error('asEventRuleTarget() is unsupported in PipelineDouble'); } - public grantBucketRead(_identity?: iam.IPrincipal): iam.GrantResult { + public grantBucketRead(_identity?: iam.IPrincipal): iam.Grant { throw new Error('grantBucketRead() is unsupported in PipelineDouble'); } - public grantBucketReadWrite(_identity?: iam.IPrincipal): iam.GrantResult { + public grantBucketReadWrite(_identity?: iam.IPrincipal): iam.Grant { throw new Error('grantBucketReadWrite() is unsupported in PipelineDouble'); } } diff --git a/packages/@aws-cdk/aws-codepipeline-api/lib/action.ts b/packages/@aws-cdk/aws-codepipeline-api/lib/action.ts index f33df7aeefda6..8d0510c6ec8f2 100644 --- a/packages/@aws-cdk/aws-codepipeline-api/lib/action.ts +++ b/packages/@aws-cdk/aws-codepipeline-api/lib/action.ts @@ -62,14 +62,14 @@ export interface IPipeline extends cdk.IConstruct, events.IEventRuleTarget { * * @param identity the IAM Identity to grant the permissions to */ - grantBucketRead(identity?: iam.IPrincipal): iam.GrantResult; + grantBucketRead(identity?: iam.IPrincipal): iam.Grant; /** * Grants read & write permissions to the Pipeline's S3 Bucket to the given Identity. * * @param identity the IAM Identity to grant the permissions to */ - grantBucketReadWrite(identity?: iam.IPrincipal): iam.GrantResult; + grantBucketReadWrite(identity?: iam.IPrincipal): iam.Grant; } /** diff --git a/packages/@aws-cdk/aws-codepipeline/lib/pipeline.ts b/packages/@aws-cdk/aws-codepipeline/lib/pipeline.ts index 2f9dc5ade0451..54478cbdaf712 100644 --- a/packages/@aws-cdk/aws-codepipeline/lib/pipeline.ts +++ b/packages/@aws-cdk/aws-codepipeline/lib/pipeline.ts @@ -292,11 +292,11 @@ export class Pipeline extends cdk.Construct implements cpapi.IPipeline { return this.stages.length; } - public grantBucketRead(identity?: iam.IPrincipal): iam.GrantResult { + public grantBucketRead(identity?: iam.IPrincipal): iam.Grant { return this.artifactBucket.grantRead(identity); } - public grantBucketReadWrite(identity?: iam.IPrincipal): iam.GrantResult { + public grantBucketReadWrite(identity?: iam.IPrincipal): iam.Grant { return this.artifactBucket.grantReadWrite(identity); } diff --git a/packages/@aws-cdk/aws-dynamodb/lib/table.ts b/packages/@aws-cdk/aws-dynamodb/lib/table.ts index e8b303a8a5d03..d8d79512b3715 100644 --- a/packages/@aws-cdk/aws-dynamodb/lib/table.ts +++ b/packages/@aws-cdk/aws-dynamodb/lib/table.ts @@ -408,8 +408,8 @@ export class Table extends Construct { * @param principal The principal (no-op if undefined) * @param actions The set of actions to allow (i.e. "dynamodb:PutItem", "dynamodb:GetItem", ...) */ - public grant(principal?: iam.IPrincipal, ...actions: string[]): iam.GrantResult { - return iam.Permissions.grant({ + public grant(principal?: iam.IPrincipal, ...actions: string[]): iam.Grant { + return iam.Permissions.grantOnPrincipal({ principal, actions, resourceArns: [ @@ -427,7 +427,7 @@ export class Table extends Construct { * @param actions The set of actions to allow (i.e. "dynamodb:DescribeStream", "dynamodb:GetRecords", ...) */ public grantStream(principal?: iam.IPrincipal, ...actions: string[]) { - return iam.Permissions.grant({ + return iam.Permissions.grantOnPrincipal({ principal, actions, resourceArns: [this.tableStreamArn], diff --git a/packages/@aws-cdk/aws-ecr/lib/repository-ref.ts b/packages/@aws-cdk/aws-ecr/lib/repository-ref.ts index 5c9680e8116df..c06a134190e74 100644 --- a/packages/@aws-cdk/aws-ecr/lib/repository-ref.ts +++ b/packages/@aws-cdk/aws-ecr/lib/repository-ref.ts @@ -51,17 +51,17 @@ export interface IRepository extends cdk.IConstruct { /** * Grant the given principal identity permissions to perform the actions on this repository */ - grant(identity?: iam.IPrincipal, ...actions: string[]): iam.GrantResult; + grant(identity?: iam.IPrincipal, ...actions: string[]): iam.Grant; /** * Grant the given identity permissions to pull images in this repository. */ - grantPull(identity?: iam.IPrincipal): iam.GrantResult; + grantPull(identity?: iam.IPrincipal): iam.Grant; /** * Grant the given identity permissions to pull and push images to this repository. */ - grantPullPush(identity?: iam.IPrincipal): iam.GrantResult; + grantPullPush(identity?: iam.IPrincipal): iam.Grant; /** * Defines an AWS CloudWatch event rule that can trigger a target when an image is pushed to this @@ -207,7 +207,7 @@ export abstract class RepositoryBase extends cdk.Construct implements IRepositor * Grant the given principal identity permissions to perform the actions on this repository */ public grant(principal?: iam.IPrincipal, ...actions: string[]) { - return iam.Permissions.grant({ + return iam.Permissions.grantWithResource({ principal, actions, resourceArns: [this.repositoryArn], @@ -221,7 +221,7 @@ export abstract class RepositoryBase extends cdk.Construct implements IRepositor public grantPull(principal?: iam.IPrincipal) { const ret = this.grant(principal, "ecr:BatchCheckLayerAvailability", "ecr:GetDownloadUrlForLayer", "ecr:BatchGetImage"); - iam.Permissions.tryGrantOnPrincipal({ + iam.Permissions.grantOnPrincipal({ principal, actions: ["ecr:GetAuthorizationToken"], resourceArns: ['*'], diff --git a/packages/@aws-cdk/aws-iam/lib/grant.ts b/packages/@aws-cdk/aws-iam/lib/grant.ts index a42823d925d2e..228f809fcdb3b 100644 --- a/packages/@aws-cdk/aws-iam/lib/grant.ts +++ b/packages/@aws-cdk/aws-iam/lib/grant.ts @@ -3,15 +3,15 @@ import { PolicyStatement } from "./policy-document"; import { IPrincipal } from "./principals"; /** - * Options for a grant operation + * Basic options for a grant operation */ -export interface GrantOptions { +export interface CommonGrantOptions { /** * The principal to grant to * * @default No work is done */ - principal: IPrincipal | undefined; + principal?: IPrincipal; /** * The actions to grant @@ -22,16 +22,19 @@ export interface GrantOptions { * The resource ARNs to grant to */ resourceArns: string[]; +} +/** + * Options for a grant operation + */ +export interface GrantWithResourceOptions extends CommonGrantOptions { /** - * Adder to the resource policy + * The resource with a resource policy * - * Either 'scope' or 'resource' must be supplied. - * - * An error will be thrown if the policy could not be added to the principal, - * no resource is supplied given and `skipResourcePolicy` is false. + * The statement will be added to the resource policy if it couldn't be + * added to the principal policy. */ - resource?: IResourceWithPolicy; + resource: IResourceWithPolicy; /** * When referring to the resource in a resource policy, use this as ARN. @@ -41,70 +44,26 @@ export interface GrantOptions { * @default Same as regular resource ARNs */ resourceSelfArns?: string[]; - - /** - * Construct to report warnings on in case grant could not be registered - * - * @default resource - */ - scope?: cdk.IConstruct; } /** - * Options for a tryGrant operation + * Options for a grant operation that only applies to principals */ -export interface TryGrantOnIdentityOptions { - /** - * The principal to grant to - * - * @default No work is done - */ - principal: IPrincipal | undefined; - - /** - * The actions to grant - */ - actions: string[]; - - /** - * The resource ARNs to grant to - */ - resourceArns: string[]; - +export interface GrantOnPrincipalOptions extends CommonGrantOptions { /** * Construct to report warnings on in case grant could not be registered */ - scope: cdk.IConstruct; + scope?: cdk.IConstruct; } /** * Options for a grant operation to both identity and resource */ -export interface GrantOnIdentityAndResourceOptions { - /** - * The principal to grant to - * - * @default No work is done - */ - principal: IPrincipal | undefined; - +export interface GrantOnPrincipalAndResourceOptions extends CommonGrantOptions { /** - * The actions to grant - */ - actions: string[]; - - /** - * The resource ARNs to grant to - */ - resourceArns: string[]; - - /** - * Adder to the resource policy - * - * Either 'scope' or 'resource' must be supplied. + * The resource with a resource policy * - * An error will be thrown if the policy could not be added to the principal, - * no resource is supplied given and `skipResourcePolicy` is false. + * The statement will always be added to the resource policy. */ resource: IResourceWithPolicy; @@ -133,25 +92,13 @@ export class Permissions { * case of imported resources) leads to a warning being added to the * resource construct. */ - public static grant(options: GrantOptions): GrantResult { - const scope = options.scope || options.resource; - if (!scope) { - throw new Error(`Either 'scope' or 'resource' must be supplied.`); - } - - const result = Permissions.tryGrantOnPrincipal({ - actions: options.actions, - principal: options.principal, - resourceArns: options.resourceArns, - scope + public static grantWithResource(options: GrantWithResourceOptions): Grant { + const result = Permissions.grantOnPrincipal({ + ...options, + scope: options.resource }); - if (result.addedToPrincipal || result.principalMissing) { return result; } - - if (!options.resource) { - // tslint:disable-next-line:max-line-length - throw new Error(`Neither principal (${options.principal}) nor resource (${scope}) allow adding to policy. Grant to a Role instead.`); - } + if (result.success) { return result; } const statement = new PolicyStatement() .addActions(...options.actions) @@ -160,7 +107,7 @@ export class Permissions { options.resource.addToResourcePolicy(statement); - return grantResult({ addedToResource: true, statement }); + return grantResult({ addedToResource: true, statement, options }); } /** @@ -169,11 +116,13 @@ export class Permissions { * Absence of a principal leads to a warning, but failing to add * the permissions to a present principal is not an error. */ - public static tryGrantOnPrincipal(options: TryGrantOnIdentityOptions): GrantResult { + public static grantOnPrincipal(options: GrantOnPrincipalOptions): Grant { if (!options.principal) { - // tslint:disable-next-line:max-line-length - options.scope.node.addWarning(`Could not add grant for '${options.actions}' on '${options.resourceArns}' because the principal was not available. Add the permissions by hand.`); - return grantResult({ principalMissing: true }); + if (options.scope) { + // tslint:disable-next-line:max-line-length + options.scope.node.addWarning(`Could not add grant for '${options.actions}' on '${options.resourceArns}' because the principal was not available. Add the permissions by hand.`); + } + return grantResult({ principalMissing: true, options }); } const statement = new PolicyStatement() @@ -182,7 +131,7 @@ export class Permissions { const addedToPrincipal = options.principal.addToPolicy(statement); - return grantResult({ addedToPrincipal, statement: addedToPrincipal ? statement : undefined }); + return grantResult({ addedToPrincipal, statement: addedToPrincipal ? statement : undefined, options }); } /** @@ -194,12 +143,10 @@ export class Permissions { * * Statement will be the resource statement. */ - public static grantOnPrincipalAndResource(options: GrantOnIdentityAndResourceOptions): GrantResult { - const result = Permissions.tryGrantOnPrincipal({ - actions: options.actions, - principal: options.principal, - resourceArns: options.resourceArns, - scope: options.resource + public static grantOnPrincipalAndResource(options: GrantOnPrincipalAndResourceOptions): Grant { + const result = Permissions.grantOnPrincipal({ + ...options, + scope: options.resource, }); if (result.principalMissing) { return result; } @@ -211,7 +158,7 @@ export class Permissions { options.resource.addToResourcePolicy(statement); - return grantResult({ addedToPrincipal: result.addedToPrincipal, addedToResource: true, statement }); + return grantResult({ addedToPrincipal: result.addedToPrincipal, addedToResource: true, statement, options }); } } @@ -221,7 +168,7 @@ export class Permissions { * This class is not instantiable by consumers on purpose, so that they will be * required to call the Permissions.grant() functions. */ -export class GrantResult { +export class Grant { /** * There was no principal to add the permissions to */ @@ -247,27 +194,52 @@ export class GrantResult { public readonly statement?: PolicyStatement; /** - * Private member to make it impossible to construct object literals that structurally match this type + * The options originally used to set this result + * + * Private member doubles as a way to make it impossible for an object literal to + * be structurally the same as this class. */ - private readonly _isGrantResult = true; + private readonly options: CommonGrantOptions; - private constructor(props: GrantResultProps) { + private constructor(props: GrantProps) { + this.options = props.options; this.principalMissing = !!props.principalMissing; this.addedToPrincipal = !!props.addedToPrincipal; this.addedToResource = !!props.addedToResource; this.statement = props.statement; - Array.isArray(this._isGrantResult); } + + /** + * Whether the grant operation was successful + */ + public get success(): boolean { + return this.principalMissing || this.addedToPrincipal || this.addedToResource; + } + + /** + * Throw an error if this grant wasn't successful + */ + public assertSuccess(): void { + if (!this.success) { + // tslint:disable-next-line:max-line-length + throw new Error(`${describeGrant(this.options)} could not be added on either identity or resource policy.`); + } + } +} + +function describeGrant(options: CommonGrantOptions) { + return `Permissions for '${options.principal}' to call '${options.actions}' on '${options.resourceArns}'`; } /** * Instantiate a grantResult (which is normally not instantiable) */ -function grantResult(props: GrantResultProps): GrantResult { - return Reflect.construct(GrantResult, [props]); +function grantResult(props: GrantProps): Grant { + return Reflect.construct(Grant, [props]); } -interface GrantResultProps { +interface GrantProps { + options: CommonGrantOptions; principalMissing?: boolean; addedToPrincipal?: boolean; addedToResource?: boolean; diff --git a/packages/@aws-cdk/aws-iam/lib/policy-document.ts b/packages/@aws-cdk/aws-iam/lib/policy-document.ts index 41ad0081b83df..762571bfd271b 100644 --- a/packages/@aws-cdk/aws-iam/lib/policy-document.ts +++ b/packages/@aws-cdk/aws-iam/lib/policy-document.ts @@ -67,6 +67,12 @@ export abstract class PrincipalBase implements IPrincipal { // have a PolicyDocument to add to. return false; } + + public toString() { + // This is a first pass to make the object readable. Descendant principals + // should return something nicer. + return JSON.stringify(this.policyFragment.principalJson); + } } /** diff --git a/packages/@aws-cdk/aws-iam/lib/role.ts b/packages/@aws-cdk/aws-iam/lib/role.ts index 093343bbf3e9d..815cbf20e0832 100644 --- a/packages/@aws-cdk/aws-iam/lib/role.ts +++ b/packages/@aws-cdk/aws-iam/lib/role.ts @@ -210,11 +210,11 @@ export class Role extends Construct implements IRole { * Grant the actions defined in actions to the identity Principal on this resource. */ public grant(principal?: IPrincipal, ...actions: string[]) { - return Permissions.grant({ + return Permissions.grantOnPrincipal({ principal, actions, resourceArns: [this.roleArn], - scope: this, + scope: this }); } diff --git a/packages/@aws-cdk/aws-kinesis/lib/stream.ts b/packages/@aws-cdk/aws-kinesis/lib/stream.ts index e057372c8ce53..c5c5b68a7fa49 100644 --- a/packages/@aws-cdk/aws-kinesis/lib/stream.ts +++ b/packages/@aws-cdk/aws-kinesis/lib/stream.ts @@ -32,7 +32,7 @@ export interface IStream extends cdk.IConstruct, logs.ILogSubscriptionDestinatio * If an encryption key is used, permission to ues the key to decrypt the * contents of the stream will also be granted. */ - grantRead(identity?: iam.IPrincipal): iam.GrantResult; + grantRead(identity?: iam.IPrincipal): iam.Grant; /** * Grant write permissions for this stream and its contents to an IAM @@ -41,7 +41,7 @@ export interface IStream extends cdk.IConstruct, logs.ILogSubscriptionDestinatio * If an encryption key is used, permission to ues the key to encrypt the * contents of the stream will also be granted. */ - grantWrite(identity?: iam.IPrincipal): iam.GrantResult; + grantWrite(identity?: iam.IPrincipal): iam.Grant; /** * Grants read/write permissions for this stream and its contents to an IAM @@ -50,7 +50,7 @@ export interface IStream extends cdk.IConstruct, logs.ILogSubscriptionDestinatio * If an encryption key is used, permission to use the key for * encrypt/decrypt will also be granted. */ - grantReadWrite(identity?: iam.IPrincipal): iam.GrantResult; + grantReadWrite(identity?: iam.IPrincipal): iam.Grant; } /** @@ -228,7 +228,7 @@ export abstract class StreamBase extends cdk.Construct implements IStream { } private grant(principal?: iam.IPrincipal, ...actions: string[]) { - return iam.Permissions.grant({ + return iam.Permissions.grantOnPrincipal({ principal, actions, resourceArns: [this.streamArn], diff --git a/packages/@aws-cdk/aws-kinesis/test/test.stream.ts b/packages/@aws-cdk/aws-kinesis/test/test.stream.ts index 5aaa910254d5f..7ed763a2cf155 100644 --- a/packages/@aws-cdk/aws-kinesis/test/test.stream.ts +++ b/packages/@aws-cdk/aws-kinesis/test/test.stream.ts @@ -305,6 +305,22 @@ export = { } }, "Resource": "*" + }, + { + "Action": [ + "kms:Decrypt", + "kms:DescribeKey" + ], + "Effect": "Allow", + "Principal": { + "AWS": { + "Fn::GetAtt": [ + "MyUserDC45028B", + "Arn" + ] + } + }, + "Resource": "*" } ], "Version": "2012-10-17" @@ -351,7 +367,7 @@ export = { } }, { - "Action": "kms:Decrypt", + "Action": ["kms:Decrypt", "kms:DescribeKey"], "Effect": "Allow", "Resource": { "Fn::GetAtt": [ @@ -428,6 +444,23 @@ export = { } }, "Resource": "*" + }, + { + "Action": [ + "kms:Encrypt", + "kms:ReEncrypt*", + "kms:GenerateDataKey*" + ], + "Effect": "Allow", + "Principal": { + "AWS": { + "Fn::GetAtt": [ + "MyUserDC45028B", + "Arn" + ] + } + }, + "Resource": "*" } ], "Version": "2012-10-17" @@ -475,8 +508,9 @@ export = { }, { "Action": [ - "kms:GenerateDataKey", - "kms:Encrypt" + "kms:Encrypt", + "kms:ReEncrypt*", + "kms:GenerateDataKey*", ], "Effect": "Allow", "Resource": { @@ -554,6 +588,25 @@ export = { } }, "Resource": "*" + }, + { + "Action": [ + "kms:Decrypt", + "kms:DescribeKey", + "kms:Encrypt", + "kms:ReEncrypt*", + "kms:GenerateDataKey*" + ], + "Effect": "Allow", + "Principal": { + "AWS": { + "Fn::GetAtt": [ + "MyUserDC45028B", + "Arn" + ] + } + }, + "Resource": "*" } ], "Version": "2012-10-17" @@ -604,8 +657,10 @@ export = { { "Action": [ "kms:Decrypt", - "kms:GenerateDataKey", - "kms:Encrypt" + "kms:DescribeKey", + "kms:Encrypt", + "kms:ReEncrypt*", + "kms:GenerateDataKey*" ], "Effect": "Allow", "Resource": { @@ -999,7 +1054,7 @@ export = { } }, { - "Action": "kms:Decrypt", + "Action": ["kms:Decrypt", "kms:DescribeKey"], "Effect": "Allow", "Resource": { "Fn::ImportValue": "MyStreamKeyKeyArn967BCB03" diff --git a/packages/@aws-cdk/aws-kms/lib/key.ts b/packages/@aws-cdk/aws-kms/lib/key.ts index 7fd0805dd9ec6..a02955482f6df 100644 --- a/packages/@aws-cdk/aws-kms/lib/key.ts +++ b/packages/@aws-cdk/aws-kms/lib/key.ts @@ -33,22 +33,22 @@ export interface IEncryptionKey extends IConstruct { /** * Grant the indicated permissions on this key to the given principal */ - grant(principal: iam.IPrincipal | undefined, ...actions: string[]): iam.GrantResult; + grant(principal: iam.IPrincipal | undefined, ...actions: string[]): iam.Grant; /** * Grant decryption permisisons using this key to the given principal */ - grantDecrypt(principal: iam.IPrincipal | undefined): iam.GrantResult; + grantDecrypt(principal: iam.IPrincipal | undefined): iam.Grant; /** * Grant encryption permisisons using this key to the given principal */ - grantEncrypt(principal: iam.IPrincipal | undefined): iam.GrantResult; + grantEncrypt(principal: iam.IPrincipal | undefined): iam.Grant; /** * Grant encryption and decryption permisisons using this key to the given principal */ - grantEncryptDecrypt(principal: iam.IPrincipal | undefined): iam.GrantResult; + grantEncryptDecrypt(principal: iam.IPrincipal | undefined): iam.Grant; } export interface EncryptionKeyImportProps { @@ -104,7 +104,7 @@ export abstract class EncryptionKeyBase extends Construct implements IEncryption * since the default CloudFormation setup for KMS keys is that the policy * must not be empty and so default grants won't work. */ - public grant(principal: iam.IPrincipal | undefined, ...actions: string[]): iam.GrantResult { + public grant(principal: iam.IPrincipal | undefined, ...actions: string[]): iam.Grant { return iam.Permissions.grantOnPrincipalAndResource({ principal, actions, @@ -117,7 +117,7 @@ export abstract class EncryptionKeyBase extends Construct implements IEncryption /** * Grant decryption permisisons using this key to the given principal */ - public grantDecrypt(principal: iam.IPrincipal | undefined): iam.GrantResult { + public grantDecrypt(principal: iam.IPrincipal | undefined): iam.Grant { return this.grant(principal, 'kms:Decrypt', 'kms:DescribeKey' @@ -127,7 +127,7 @@ export abstract class EncryptionKeyBase extends Construct implements IEncryption /** * Grant encryption permisisons using this key to the given principal */ - public grantEncrypt(principal: iam.IPrincipal | undefined): iam.GrantResult { + public grantEncrypt(principal: iam.IPrincipal | undefined): iam.Grant { return this.grant(principal, 'kms:Encrypt', 'kms:ReEncrypt*', @@ -138,7 +138,7 @@ export abstract class EncryptionKeyBase extends Construct implements IEncryption /** * Grant encryption and decryption permisisons using this key to the given principal */ - public grantEncryptDecrypt(principal: iam.IPrincipal | undefined): iam.GrantResult { + public grantEncryptDecrypt(principal: iam.IPrincipal | undefined): iam.Grant { return this.grant(principal, 'kms:Decrypt', 'kms:DescribeKey', diff --git a/packages/@aws-cdk/aws-lambda/lib/function-base.ts b/packages/@aws-cdk/aws-lambda/lib/function-base.ts index c2a349203aff2..40c554727a0ea 100644 --- a/packages/@aws-cdk/aws-lambda/lib/function-base.ts +++ b/packages/@aws-cdk/aws-lambda/lib/function-base.ts @@ -60,7 +60,7 @@ export interface IFunction extends cdk.IConstruct, events.IEventRuleTarget, logs /** * Grant the given identity permissions to invoke this Lambda */ - grantInvoke(identity?: iam.IPrincipal): iam.GrantResult; + grantInvoke(identity?: iam.IPrincipal): iam.Grant; /** * Return the given named metric for this Lambda @@ -246,12 +246,11 @@ export abstract class FunctionBase extends cdk.Construct implements IFunction { /** * Grant the given identity permissions to invoke this Lambda */ - public grantInvoke(principal?: iam.IPrincipal): iam.GrantResult { - return iam.Permissions.grant({ + public grantInvoke(principal?: iam.IPrincipal): iam.Grant { + return iam.Permissions.grantWithResource({ principal, actions: ['lambda:InvokeFunction'], resourceArns: [this.functionArn], - scope: this, // Fake resource-like object on which to call addToResourcePolicy(), which actually // calls addPermission() diff --git a/packages/@aws-cdk/aws-logs/lib/log-group.ts b/packages/@aws-cdk/aws-logs/lib/log-group.ts index 74ac0f4292101..7fda13bce3c0c 100644 --- a/packages/@aws-cdk/aws-logs/lib/log-group.ts +++ b/packages/@aws-cdk/aws-logs/lib/log-group.ts @@ -69,12 +69,12 @@ export interface ILogGroup extends cdk.IConstruct { /** * Give permissions to write to create and write to streams in this log group */ - grantWrite(principal?: iam.IPrincipal): iam.GrantResult; + grantWrite(principal?: iam.IPrincipal): iam.Grant; /** * Give the indicated permissions on this log group and all streams */ - grant(principal?: iam.IPrincipal, ...actions: string[]): iam.GrantResult; + grant(principal?: iam.IPrincipal, ...actions: string[]): iam.Grant; } /** @@ -179,7 +179,7 @@ export abstract class LogGroupBase extends cdk.Construct implements ILogGroup { * Give the indicated permissions on this log group and all streams */ public grant(principal?: iam.IPrincipal, ...actions: string[]) { - return iam.Permissions.grant({ + return iam.Permissions.grantOnPrincipal({ principal, actions, // A LogGroup ARN out of CloudFormation already includes a ':*' at the end to include the log streams under the group. diff --git a/packages/@aws-cdk/aws-s3/lib/bucket.ts b/packages/@aws-cdk/aws-s3/lib/bucket.ts index 3b89d3b6b8ae1..63322324f0a34 100644 --- a/packages/@aws-cdk/aws-s3/lib/bucket.ts +++ b/packages/@aws-cdk/aws-s3/lib/bucket.ts @@ -111,7 +111,7 @@ export interface IBucket extends cdk.IConstruct { * @param identity The principal * @param objectsKeyPattern Restrict the permission to a certain key pattern (default '*') */ - grantRead(identity?: iam.IPrincipal, objectsKeyPattern?: any): iam.GrantResult; + grantRead(identity?: iam.IPrincipal, objectsKeyPattern?: any): iam.Grant; /** * Grant write permissions to this bucket to an IAM principal. @@ -122,7 +122,7 @@ export interface IBucket extends cdk.IConstruct { * @param identity The principal * @param objectsKeyPattern Restrict the permission to a certain key pattern (default '*') */ - grantWrite(identity?: iam.IPrincipal, objectsKeyPattern?: any): iam.GrantResult; + grantWrite(identity?: iam.IPrincipal, objectsKeyPattern?: any): iam.Grant; /** * Grants s3:PutObject* and s3:Abort* permissions for this bucket to an IAM principal. @@ -132,7 +132,7 @@ export interface IBucket extends cdk.IConstruct { * @param identity The principal * @param objectsKeyPattern Restrict the permission to a certain key pattern (default '*') */ - grantPut(identity?: iam.IPrincipal, objectsKeyPattern?: any): iam.GrantResult; + grantPut(identity?: iam.IPrincipal, objectsKeyPattern?: any): iam.Grant; /** * Grants s3:DeleteObject* permission to an IAM pricipal for objects @@ -141,7 +141,7 @@ export interface IBucket extends cdk.IConstruct { * @param identity The principal * @param objectsKeyPattern Restrict the permission to a certain key pattern (default '*') */ - grantDelete(identity?: iam.IPrincipal, objectsKeyPattern?: any): iam.GrantResult; + grantDelete(identity?: iam.IPrincipal, objectsKeyPattern?: any): iam.Grant; /** * Grants read/write permissions for this bucket and it's contents to an IAM @@ -153,7 +153,7 @@ export interface IBucket extends cdk.IConstruct { * @param identity The principal * @param objectsKeyPattern Restrict the permission to a certain key pattern (default '*') */ - grantReadWrite(identity?: iam.IPrincipal, objectsKeyPattern?: any): iam.GrantResult; + grantReadWrite(identity?: iam.IPrincipal, objectsKeyPattern?: any): iam.Grant; /** * Allows unrestricted access to objects from this bucket. @@ -178,7 +178,7 @@ export interface IBucket extends cdk.IConstruct { * @param allowedActions the set of S3 actions to allow. Default is "s3:GetObject". * @returns The `iam.PolicyStatement` object, which can be used to apply e.g. conditions. */ - grantPublicAccess(keyPrefix?: string, ...allowedActions: string[]): iam.GrantResult; + grantPublicAccess(keyPrefix?: string, ...allowedActions: string[]): iam.Grant; /** * Defines a CloudWatch Event Rule that triggers upon putting an object into the Bucket. @@ -505,7 +505,7 @@ export abstract class BucketBase extends cdk.Construct implements IBucket { allowedActions = allowedActions.length > 0 ? allowedActions : [ 's3:GetObject' ]; - return iam.Permissions.grant({ + return iam.Permissions.grantWithResource({ actions: allowedActions, resourceArns: [this.arnForObjects(keyPrefix)], principal: new iam.Anyone(), @@ -519,7 +519,7 @@ export abstract class BucketBase extends cdk.Construct implements IBucket { resourceArn: string, ...otherResourceArns: string[]) { const resources = [ resourceArn, ...otherResourceArns ]; - const ret = iam.Permissions.grant({ + const ret = iam.Permissions.grantWithResource({ principal, actions: bucketActions, resourceArns: resources, diff --git a/packages/@aws-cdk/aws-secretsmanager/lib/secret.ts b/packages/@aws-cdk/aws-secretsmanager/lib/secret.ts index fd1e63c16a93b..61627d4e7a67b 100644 --- a/packages/@aws-cdk/aws-secretsmanager/lib/secret.ts +++ b/packages/@aws-cdk/aws-secretsmanager/lib/secret.ts @@ -39,7 +39,7 @@ export interface ISecret extends cdk.IConstruct { * @param versionStages the version stages the grant is limited to. If not specified, no restriction on the version * stages is applied. */ - grantRead(principal?: iam.IPrincipal, versionStages?: string[]): iam.GrantResult; + grantRead(principal?: iam.IPrincipal, versionStages?: string[]): iam.Grant; } /** @@ -101,10 +101,10 @@ export abstract class SecretBase extends cdk.Construct implements ISecret { public abstract export(): SecretImportProps; - public grantRead(principal?: iam.IPrincipal, versionStages?: string[]): iam.GrantResult { + public grantRead(principal?: iam.IPrincipal, versionStages?: string[]): iam.Grant { // @see https://docs.aws.amazon.com/fr_fr/secretsmanager/latest/userguide/auth-and-access_identity-based-policies.html - const result = iam.Permissions.grant({ + const result = iam.Permissions.grantOnPrincipal({ principal, actions: ['secretsmanager:GetSecretValue'], resourceArns: [this.secretArn], diff --git a/packages/@aws-cdk/aws-sns/lib/topic-base.ts b/packages/@aws-cdk/aws-sns/lib/topic-base.ts index 537698ab343a1..cf7388cc91ced 100644 --- a/packages/@aws-cdk/aws-sns/lib/topic-base.ts +++ b/packages/@aws-cdk/aws-sns/lib/topic-base.ts @@ -81,7 +81,7 @@ export interface ITopic extends /** * Grant topic publishing permissions to the given identity */ - grantPublish(identity?: iam.IPrincipal): iam.GrantResult; + grantPublish(identity?: iam.IPrincipal): iam.Grant; } /** @@ -264,7 +264,7 @@ export abstract class TopicBase extends cdk.Construct implements ITopic { * Grant topic publishing permissions to the given identity */ public grantPublish(principal?: iam.IPrincipal) { - return iam.Permissions.grant({ + return iam.Permissions.grantWithResource({ principal, actions: ['sns:Publish'], resourceArns: [this.topicArn], diff --git a/packages/@aws-cdk/aws-sqs/lib/queue-base.ts b/packages/@aws-cdk/aws-sqs/lib/queue-base.ts index 9542aa63c5ecb..3f4d6c42f0fd8 100644 --- a/packages/@aws-cdk/aws-sqs/lib/queue-base.ts +++ b/packages/@aws-cdk/aws-sqs/lib/queue-base.ts @@ -55,7 +55,7 @@ export interface IQueue extends cdk.IConstruct, s3n.IBucketNotificationDestinati * * @param identity Principal to grant consume rights to */ - grantConsumeMessages(identity?: iam.IPrincipal): iam.GrantResult; + grantConsumeMessages(identity?: iam.IPrincipal): iam.Grant; /** * Grant access to send messages to a queue to the given identity. @@ -69,7 +69,7 @@ export interface IQueue extends cdk.IConstruct, s3n.IBucketNotificationDestinati * * @param identity Principal to grant send rights to */ - grantSendMessages(identity?: iam.IPrincipal): iam.GrantResult; + grantSendMessages(identity?: iam.IPrincipal): iam.Grant; /** * Grant an IAM principal permissions to purge all messages from the queue. @@ -83,7 +83,7 @@ export interface IQueue extends cdk.IConstruct, s3n.IBucketNotificationDestinati * @param identity Principal to grant send rights to * @param queueActions additional queue actions to allow */ - grantPurge(identity?: iam.IPrincipal): iam.GrantResult; + grantPurge(identity?: iam.IPrincipal): iam.Grant; /** * Grant the actions defined in queueActions to the identity Principal given @@ -92,7 +92,7 @@ export interface IQueue extends cdk.IConstruct, s3n.IBucketNotificationDestinati * @param identity Principal to grant right to * @param queueActions The actions to grant */ - grant(identity?: iam.IPrincipal, ...queueActions: string[]): iam.GrantResult; + grant(identity?: iam.IPrincipal, ...queueActions: string[]): iam.Grant; } /** @@ -274,7 +274,7 @@ export abstract class QueueBase extends cdk.Construct implements IQueue { * @param actions The actions to grant */ public grant(principal?: iam.IPrincipal, ...actions: string[]) { - return iam.Permissions.grant({ + return iam.Permissions.grantWithResource({ principal, actions, resourceArns: [this.queueArn], diff --git a/tools/awslint/lib/rules/resource.ts b/tools/awslint/lib/rules/resource.ts index 450a10d2d15b2..31218232b9777 100644 --- a/tools/awslint/lib/rules/resource.ts +++ b/tools/awslint/lib/rules/resource.ts @@ -11,7 +11,7 @@ export const resourceLinter = new Linter(assembly => { })); }); -const GRANT_RESULT_FQN = '@aws-cdk/aws-iam.GrantResult'; +const GRANT_RESULT_FQN = '@aws-cdk/aws-iam.Grant'; interface ResourceLinterContext { readonly ts: reflect.TypeSystem; From 81de979cad4b4f809ce36724c3ddbeb0def3774d Mon Sep 17 00:00:00 2001 From: Rico Huijbers Date: Thu, 28 Feb 2019 16:19:00 +0100 Subject: [PATCH 13/31] Update ECS expectations --- .../ec2/integ.event-task.lit.expected.json | 38 ++-- .../test/ec2/integ.lb-awsvpc-nw.expected.json | 32 +-- .../test/ec2/integ.lb-bridge-nw.expected.json | 32 +-- .../fargate/integ.asset-image.expected.json | 208 +++++++++--------- .../test/fargate/integ.l3.expected.json | 202 ++++++++--------- .../fargate/integ.lb-awsvpc-nw.expected.json | 2 +- 6 files changed, 253 insertions(+), 261 deletions(-) diff --git a/packages/@aws-cdk/aws-ecs/test/ec2/integ.event-task.lit.expected.json b/packages/@aws-cdk/aws-ecs/test/ec2/integ.event-task.lit.expected.json index c0fc2a4bc026d..79fab044117e2 100644 --- a/packages/@aws-cdk/aws-ecs/test/ec2/integ.event-task.lit.expected.json +++ b/packages/@aws-cdk/aws-ecs/test/ec2/integ.event-task.lit.expected.json @@ -345,21 +345,6 @@ "EcsClusterDefaultAutoScalingGroupDrainECSHookTopicC705BD25": { "Type": "AWS::SNS::Topic" }, - "EcsClusterDefaultAutoScalingGroupDrainECSHookFunctionTopicSubscriptionDA5F8A10": { - "Type": "AWS::SNS::Subscription", - "Properties": { - "Endpoint": { - "Fn::GetAtt": [ - "EcsClusterDefaultAutoScalingGroupDrainECSHookFunctionE17A5F5E", - "Arn" - ] - }, - "Protocol": "lambda", - "TopicArn": { - "Ref": "EcsClusterDefaultAutoScalingGroupDrainECSHookTopicC705BD25" - } - } - }, "EcsClusterDefaultAutoScalingGroupDrainECSHookFunctionServiceRole94543EDA": { "Type": "AWS::IAM::Role", "Properties": { @@ -465,6 +450,21 @@ "EcsClusterDefaultAutoScalingGroupDrainECSHookFunctionServiceRole94543EDA" ] }, + "EcsClusterDefaultAutoScalingGroupDrainECSHookFunctionTopicSubscriptionDA5F8A10": { + "Type": "AWS::SNS::Subscription", + "Properties": { + "Endpoint": { + "Fn::GetAtt": [ + "EcsClusterDefaultAutoScalingGroupDrainECSHookFunctionE17A5F5E", + "Arn" + ] + }, + "Protocol": "lambda", + "TopicArn": { + "Ref": "EcsClusterDefaultAutoScalingGroupDrainECSHookTopicC705BD25" + } + } + }, "EcsClusterDefaultAutoScalingGroupDrainECSHookFunctionTopicE6B1EBA6": { "Type": "AWS::Lambda::Permission", "Properties": { @@ -773,11 +773,7 @@ } }, { - "Action": [ - "ecr:GetAuthorizationToken", - "logs:CreateLogStream", - "logs:PutLogEvents" - ], + "Action": "ecr:GetAuthorizationToken", "Effect": "Allow", "Resource": "*" }, @@ -1090,4 +1086,4 @@ "Description": "S3 key for asset version \"aws-ecs-integ-ecs/AdoptEcrRepositorydbc60defc59544bcaa5c28c95d68f62c/Code\"" } } -} +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-ecs/test/ec2/integ.lb-awsvpc-nw.expected.json b/packages/@aws-cdk/aws-ecs/test/ec2/integ.lb-awsvpc-nw.expected.json index b915396a9c18f..7d862514e6a90 100644 --- a/packages/@aws-cdk/aws-ecs/test/ec2/integ.lb-awsvpc-nw.expected.json +++ b/packages/@aws-cdk/aws-ecs/test/ec2/integ.lb-awsvpc-nw.expected.json @@ -501,21 +501,6 @@ "EcsClusterDefaultAutoScalingGroupDrainECSHookTopicC705BD25": { "Type": "AWS::SNS::Topic" }, - "EcsClusterDefaultAutoScalingGroupDrainECSHookFunctionTopicSubscriptionDA5F8A10": { - "Type": "AWS::SNS::Subscription", - "Properties": { - "Endpoint": { - "Fn::GetAtt": [ - "EcsClusterDefaultAutoScalingGroupDrainECSHookFunctionE17A5F5E", - "Arn" - ] - }, - "Protocol": "lambda", - "TopicArn": { - "Ref": "EcsClusterDefaultAutoScalingGroupDrainECSHookTopicC705BD25" - } - } - }, "EcsClusterDefaultAutoScalingGroupDrainECSHookFunctionServiceRole94543EDA": { "Type": "AWS::IAM::Role", "Properties": { @@ -621,6 +606,21 @@ "EcsClusterDefaultAutoScalingGroupDrainECSHookFunctionServiceRole94543EDA" ] }, + "EcsClusterDefaultAutoScalingGroupDrainECSHookFunctionTopicSubscriptionDA5F8A10": { + "Type": "AWS::SNS::Subscription", + "Properties": { + "Endpoint": { + "Fn::GetAtt": [ + "EcsClusterDefaultAutoScalingGroupDrainECSHookFunctionE17A5F5E", + "Arn" + ] + }, + "Protocol": "lambda", + "TopicArn": { + "Ref": "EcsClusterDefaultAutoScalingGroupDrainECSHookTopicC705BD25" + } + } + }, "EcsClusterDefaultAutoScalingGroupDrainECSHookFunctionTopicE6B1EBA6": { "Type": "AWS::Lambda::Permission", "Properties": { @@ -962,4 +962,4 @@ } } } -} +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-ecs/test/ec2/integ.lb-bridge-nw.expected.json b/packages/@aws-cdk/aws-ecs/test/ec2/integ.lb-bridge-nw.expected.json index 4bb3eea3c4626..a072b628ef712 100644 --- a/packages/@aws-cdk/aws-ecs/test/ec2/integ.lb-bridge-nw.expected.json +++ b/packages/@aws-cdk/aws-ecs/test/ec2/integ.lb-bridge-nw.expected.json @@ -522,21 +522,6 @@ "EcsClusterDefaultAutoScalingGroupDrainECSHookTopicC705BD25": { "Type": "AWS::SNS::Topic" }, - "EcsClusterDefaultAutoScalingGroupDrainECSHookFunctionTopicSubscriptionDA5F8A10": { - "Type": "AWS::SNS::Subscription", - "Properties": { - "Endpoint": { - "Fn::GetAtt": [ - "EcsClusterDefaultAutoScalingGroupDrainECSHookFunctionE17A5F5E", - "Arn" - ] - }, - "Protocol": "lambda", - "TopicArn": { - "Ref": "EcsClusterDefaultAutoScalingGroupDrainECSHookTopicC705BD25" - } - } - }, "EcsClusterDefaultAutoScalingGroupDrainECSHookFunctionServiceRole94543EDA": { "Type": "AWS::IAM::Role", "Properties": { @@ -642,6 +627,21 @@ "EcsClusterDefaultAutoScalingGroupDrainECSHookFunctionServiceRole94543EDA" ] }, + "EcsClusterDefaultAutoScalingGroupDrainECSHookFunctionTopicSubscriptionDA5F8A10": { + "Type": "AWS::SNS::Subscription", + "Properties": { + "Endpoint": { + "Fn::GetAtt": [ + "EcsClusterDefaultAutoScalingGroupDrainECSHookFunctionE17A5F5E", + "Arn" + ] + }, + "Protocol": "lambda", + "TopicArn": { + "Ref": "EcsClusterDefaultAutoScalingGroupDrainECSHookTopicC705BD25" + } + } + }, "EcsClusterDefaultAutoScalingGroupDrainECSHookFunctionTopicE6B1EBA6": { "Type": "AWS::Lambda::Permission", "Properties": { @@ -925,4 +925,4 @@ } } } -} +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-ecs/test/fargate/integ.asset-image.expected.json b/packages/@aws-cdk/aws-ecs/test/fargate/integ.asset-image.expected.json index d1d4f4a7ca4b9..c15585ea1a3e2 100644 --- a/packages/@aws-cdk/aws-ecs/test/fargate/integ.asset-image.expected.json +++ b/packages/@aws-cdk/aws-ecs/test/fargate/integ.asset-image.expected.json @@ -516,6 +516,106 @@ "AdoptEcrRepositorydbc60defc59544bcaa5c28c95d68f62cServiceRoleD788AA17" ] }, + "FargateServiceLBB353E155": { + "Type": "AWS::ElasticLoadBalancingV2::LoadBalancer", + "Properties": { + "LoadBalancerAttributes": [], + "Scheme": "internet-facing", + "SecurityGroups": [ + { + "Fn::GetAtt": [ + "FargateServiceLBSecurityGroup5F444C78", + "GroupId" + ] + } + ], + "Subnets": [ + { + "Ref": "VpcPublicSubnet1Subnet5C2D37C4" + }, + { + "Ref": "VpcPublicSubnet2Subnet691E08A3" + } + ], + "Type": "application" + }, + "DependsOn": [ + "VpcPublicSubnet1DefaultRoute3DA9E72A", + "VpcPublicSubnet2DefaultRoute97F91067" + ] + }, + "FargateServiceLBSecurityGroup5F444C78": { + "Type": "AWS::EC2::SecurityGroup", + "Properties": { + "GroupDescription": "Automatically created Security Group for ELB awsecsintegFargateServiceLB5FE4725D", + "SecurityGroupEgress": [], + "SecurityGroupIngress": [ + { + "CidrIp": "0.0.0.0/0", + "Description": "Allow from anyone on port 80", + "FromPort": 80, + "IpProtocol": "tcp", + "ToPort": 80 + } + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } + } + }, + "FargateServiceLBSecurityGrouptoawsecsintegFargateServiceSecurityGroup8930AEB880001FF8BADE": { + "Type": "AWS::EC2::SecurityGroupEgress", + "Properties": { + "GroupId": { + "Fn::GetAtt": [ + "FargateServiceLBSecurityGroup5F444C78", + "GroupId" + ] + }, + "IpProtocol": "tcp", + "Description": "Load balancer to target", + "DestinationSecurityGroupId": { + "Fn::GetAtt": [ + "FargateServiceSecurityGroup262B61DD", + "GroupId" + ] + }, + "FromPort": 8000, + "ToPort": 8000 + } + }, + "FargateServiceLBPublicListener4B4929CA": { + "Type": "AWS::ElasticLoadBalancingV2::Listener", + "Properties": { + "DefaultActions": [ + { + "TargetGroupArn": { + "Ref": "FargateServiceLBPublicListenerECSGroupBE57E081" + }, + "Type": "forward" + } + ], + "LoadBalancerArn": { + "Ref": "FargateServiceLBB353E155" + }, + "Port": 80, + "Protocol": "HTTP", + "Certificates": [] + } + }, + "FargateServiceLBPublicListenerECSGroupBE57E081": { + "Type": "AWS::ElasticLoadBalancingV2::TargetGroup", + "Properties": { + "Port": 80, + "Protocol": "HTTP", + "VpcId": { + "Ref": "Vpc8378EB38" + }, + "TargetGroupAttributes": [], + "Targets": [], + "TargetType": "ip" + } + }, "FargateServiceTaskDefTaskRole8CDCF85E": { "Type": "AWS::IAM::Role", "Properties": { @@ -752,11 +852,7 @@ } }, { - "Action": [ - "ecr:GetAuthorizationToken", - "logs:CreateLogStream", - "logs:PutLogEvents" - ], + "Action": "ecr:GetAuthorizationToken", "Effect": "Allow", "Resource": "*" }, @@ -879,106 +975,6 @@ }, "ToPort": 8000 } - }, - "FargateServiceLBB353E155": { - "Type": "AWS::ElasticLoadBalancingV2::LoadBalancer", - "Properties": { - "LoadBalancerAttributes": [], - "Scheme": "internet-facing", - "SecurityGroups": [ - { - "Fn::GetAtt": [ - "FargateServiceLBSecurityGroup5F444C78", - "GroupId" - ] - } - ], - "Subnets": [ - { - "Ref": "VpcPublicSubnet1Subnet5C2D37C4" - }, - { - "Ref": "VpcPublicSubnet2Subnet691E08A3" - } - ], - "Type": "application" - }, - "DependsOn": [ - "VpcPublicSubnet1DefaultRoute3DA9E72A", - "VpcPublicSubnet2DefaultRoute97F91067" - ] - }, - "FargateServiceLBSecurityGroup5F444C78": { - "Type": "AWS::EC2::SecurityGroup", - "Properties": { - "GroupDescription": "Automatically created Security Group for ELB awsecsintegFargateServiceLB5FE4725D", - "SecurityGroupEgress": [], - "SecurityGroupIngress": [ - { - "CidrIp": "0.0.0.0/0", - "Description": "Allow from anyone on port 80", - "FromPort": 80, - "IpProtocol": "tcp", - "ToPort": 80 - } - ], - "VpcId": { - "Ref": "Vpc8378EB38" - } - } - }, - "FargateServiceLBSecurityGrouptoawsecsintegFargateServiceSecurityGroup8930AEB880001FF8BADE": { - "Type": "AWS::EC2::SecurityGroupEgress", - "Properties": { - "GroupId": { - "Fn::GetAtt": [ - "FargateServiceLBSecurityGroup5F444C78", - "GroupId" - ] - }, - "IpProtocol": "tcp", - "Description": "Load balancer to target", - "DestinationSecurityGroupId": { - "Fn::GetAtt": [ - "FargateServiceSecurityGroup262B61DD", - "GroupId" - ] - }, - "FromPort": 8000, - "ToPort": 8000 - } - }, - "FargateServiceLBPublicListener4B4929CA": { - "Type": "AWS::ElasticLoadBalancingV2::Listener", - "Properties": { - "DefaultActions": [ - { - "TargetGroupArn": { - "Ref": "FargateServiceLBPublicListenerECSGroupBE57E081" - }, - "Type": "forward" - } - ], - "LoadBalancerArn": { - "Ref": "FargateServiceLBB353E155" - }, - "Port": 80, - "Protocol": "HTTP", - "Certificates": [] - } - }, - "FargateServiceLBPublicListenerECSGroupBE57E081": { - "Type": "AWS::ElasticLoadBalancingV2::TargetGroup", - "Properties": { - "Port": 80, - "Protocol": "HTTP", - "VpcId": { - "Ref": "Vpc8378EB38" - }, - "TargetGroupAttributes": [], - "Targets": [], - "TargetType": "ip" - } } }, "Parameters": { @@ -1013,4 +1009,4 @@ } } } -} +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-ecs/test/fargate/integ.l3.expected.json b/packages/@aws-cdk/aws-ecs/test/fargate/integ.l3.expected.json index e5416641368ce..79434fac1203c 100644 --- a/packages/@aws-cdk/aws-ecs/test/fargate/integ.l3.expected.json +++ b/packages/@aws-cdk/aws-ecs/test/fargate/integ.l3.expected.json @@ -346,6 +346,106 @@ "FargateCluster7CCD5F93": { "Type": "AWS::ECS::Cluster" }, + "L3LB212FC0E0": { + "Type": "AWS::ElasticLoadBalancingV2::LoadBalancer", + "Properties": { + "LoadBalancerAttributes": [], + "Scheme": "internet-facing", + "SecurityGroups": [ + { + "Fn::GetAtt": [ + "L3LBSecurityGroupEDE61198", + "GroupId" + ] + } + ], + "Subnets": [ + { + "Ref": "VpcPublicSubnet1Subnet5C2D37C4" + }, + { + "Ref": "VpcPublicSubnet2Subnet691E08A3" + } + ], + "Type": "application" + }, + "DependsOn": [ + "VpcPublicSubnet1DefaultRoute3DA9E72A", + "VpcPublicSubnet2DefaultRoute97F91067" + ] + }, + "L3LBSecurityGroupEDE61198": { + "Type": "AWS::EC2::SecurityGroup", + "Properties": { + "GroupDescription": "Automatically created Security Group for ELB awsecsintegL3LB6453BA0A", + "SecurityGroupEgress": [], + "SecurityGroupIngress": [ + { + "CidrIp": "0.0.0.0/0", + "Description": "Allow from anyone on port 80", + "FromPort": 80, + "IpProtocol": "tcp", + "ToPort": 80 + } + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } + } + }, + "L3LBSecurityGrouptoawsecsintegL3ServiceSecurityGroup7B96C87F8094933E0A": { + "Type": "AWS::EC2::SecurityGroupEgress", + "Properties": { + "GroupId": { + "Fn::GetAtt": [ + "L3LBSecurityGroupEDE61198", + "GroupId" + ] + }, + "IpProtocol": "tcp", + "Description": "Load balancer to target", + "DestinationSecurityGroupId": { + "Fn::GetAtt": [ + "L3ServiceSecurityGroup677B0897", + "GroupId" + ] + }, + "FromPort": 80, + "ToPort": 80 + } + }, + "L3LBPublicListener156FFC0F": { + "Type": "AWS::ElasticLoadBalancingV2::Listener", + "Properties": { + "DefaultActions": [ + { + "TargetGroupArn": { + "Ref": "L3LBPublicListenerECSGroup648EEA11" + }, + "Type": "forward" + } + ], + "LoadBalancerArn": { + "Ref": "L3LB212FC0E0" + }, + "Port": 80, + "Protocol": "HTTP", + "Certificates": [] + } + }, + "L3LBPublicListenerECSGroup648EEA11": { + "Type": "AWS::ElasticLoadBalancingV2::TargetGroup", + "Properties": { + "Port": 80, + "Protocol": "HTTP", + "VpcId": { + "Ref": "Vpc8378EB38" + }, + "TargetGroupAttributes": [], + "Targets": [], + "TargetType": "ip" + } + }, "L3TaskDefTaskRole21C75D10": { "Type": "AWS::IAM::Role", "Properties": { @@ -566,106 +666,6 @@ }, "ToPort": 80 } - }, - "L3LB212FC0E0": { - "Type": "AWS::ElasticLoadBalancingV2::LoadBalancer", - "Properties": { - "LoadBalancerAttributes": [], - "Scheme": "internet-facing", - "SecurityGroups": [ - { - "Fn::GetAtt": [ - "L3LBSecurityGroupEDE61198", - "GroupId" - ] - } - ], - "Subnets": [ - { - "Ref": "VpcPublicSubnet1Subnet5C2D37C4" - }, - { - "Ref": "VpcPublicSubnet2Subnet691E08A3" - } - ], - "Type": "application" - }, - "DependsOn": [ - "VpcPublicSubnet1DefaultRoute3DA9E72A", - "VpcPublicSubnet2DefaultRoute97F91067" - ] - }, - "L3LBSecurityGroupEDE61198": { - "Type": "AWS::EC2::SecurityGroup", - "Properties": { - "GroupDescription": "Automatically created Security Group for ELB awsecsintegL3LB6453BA0A", - "SecurityGroupEgress": [], - "SecurityGroupIngress": [ - { - "CidrIp": "0.0.0.0/0", - "Description": "Allow from anyone on port 80", - "FromPort": 80, - "IpProtocol": "tcp", - "ToPort": 80 - } - ], - "VpcId": { - "Ref": "Vpc8378EB38" - } - } - }, - "L3LBSecurityGrouptoawsecsintegL3ServiceSecurityGroup7B96C87F8094933E0A": { - "Type": "AWS::EC2::SecurityGroupEgress", - "Properties": { - "GroupId": { - "Fn::GetAtt": [ - "L3LBSecurityGroupEDE61198", - "GroupId" - ] - }, - "IpProtocol": "tcp", - "Description": "Load balancer to target", - "DestinationSecurityGroupId": { - "Fn::GetAtt": [ - "L3ServiceSecurityGroup677B0897", - "GroupId" - ] - }, - "FromPort": 80, - "ToPort": 80 - } - }, - "L3LBPublicListener156FFC0F": { - "Type": "AWS::ElasticLoadBalancingV2::Listener", - "Properties": { - "DefaultActions": [ - { - "TargetGroupArn": { - "Ref": "L3LBPublicListenerECSGroup648EEA11" - }, - "Type": "forward" - } - ], - "LoadBalancerArn": { - "Ref": "L3LB212FC0E0" - }, - "Port": 80, - "Protocol": "HTTP", - "Certificates": [] - } - }, - "L3LBPublicListenerECSGroup648EEA11": { - "Type": "AWS::ElasticLoadBalancingV2::TargetGroup", - "Properties": { - "Port": 80, - "Protocol": "HTTP", - "VpcId": { - "Ref": "Vpc8378EB38" - }, - "TargetGroupAttributes": [], - "Targets": [], - "TargetType": "ip" - } } }, "Outputs": { @@ -678,4 +678,4 @@ } } } -} +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-ecs/test/fargate/integ.lb-awsvpc-nw.expected.json b/packages/@aws-cdk/aws-ecs/test/fargate/integ.lb-awsvpc-nw.expected.json index 39c3355a8e0ae..96166f8f4ea75 100644 --- a/packages/@aws-cdk/aws-ecs/test/fargate/integ.lb-awsvpc-nw.expected.json +++ b/packages/@aws-cdk/aws-ecs/test/fargate/integ.lb-awsvpc-nw.expected.json @@ -671,4 +671,4 @@ } } } -} +} \ No newline at end of file From 28945ee4563cb8e703976f80bb8f1dd7805263bc Mon Sep 17 00:00:00 2001 From: Rico Huijbers Date: Thu, 28 Feb 2019 17:07:05 +0100 Subject: [PATCH 14/31] Make statics also return a Grant --- packages/@aws-cdk/aws-cloudwatch/lib/metric.ts | 12 ++++++------ packages/@aws-cdk/aws-dynamodb/lib/table.ts | 13 ++++++------- 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/packages/@aws-cdk/aws-cloudwatch/lib/metric.ts b/packages/@aws-cdk/aws-cloudwatch/lib/metric.ts index 43f5a0d65873a..8f07b26b5588b 100644 --- a/packages/@aws-cdk/aws-cloudwatch/lib/metric.ts +++ b/packages/@aws-cdk/aws-cloudwatch/lib/metric.ts @@ -87,12 +87,12 @@ export class Metric { * * @param principal The IAM identity to give permissions to. */ - public static grantPutMetricData(principal?: iam.IPrincipal) { - if (principal) { - principal.addToPolicy(new iam.PolicyStatement() - .addAction('cloudwatch:PutMetricData') - .addAllResources()); - } + public static grantPutMetricData(principal?: iam.IPrincipal): iam.Grant { + return iam.Permissions.grantOnPrincipal({ + principal, + actions: ['cloudwatch:PutMetricData'], + resourceArns: ['*'] + }); } public readonly dimensions?: DimensionHash; diff --git a/packages/@aws-cdk/aws-dynamodb/lib/table.ts b/packages/@aws-cdk/aws-dynamodb/lib/table.ts index fc769150799c5..1d400c3587c52 100644 --- a/packages/@aws-cdk/aws-dynamodb/lib/table.ts +++ b/packages/@aws-cdk/aws-dynamodb/lib/table.ts @@ -1,6 +1,5 @@ import appscaling = require('@aws-cdk/aws-applicationautoscaling'); import iam = require('@aws-cdk/aws-iam'); -import { PolicyStatement } from '@aws-cdk/aws-iam'; import cdk = require('@aws-cdk/cdk'); import { Construct, Token } from '@aws-cdk/cdk'; import { CfnTable } from './dynamodb.generated'; @@ -179,12 +178,12 @@ export class Table extends Construct { * Permits an IAM Principal to list all DynamoDB Streams. * @param principal The principal (no-op if undefined) */ - public static grantListStreams(principal?: iam.IPrincipal): void { - if (principal) { - principal.addToPolicy(new PolicyStatement() - .addAction('dynamodb:ListStreams') - .addAllResources()); - } + public static grantListStreams(principal?: iam.IPrincipal): iam.Grant { + return iam.Permissions.grantOnPrincipal({ + principal, + actions: ['dynamodb:ListStreams'], + resourceArns: ['*'], + }); } public readonly tableArn: string; From c7391f43424282392207d2857a81fdbae67b27b3 Mon Sep 17 00:00:00 2001 From: Rico Huijbers Date: Fri, 1 Mar 2019 15:21:05 +0100 Subject: [PATCH 15/31] Review comments --- packages/@aws-cdk/aws-dynamodb/lib/table.ts | 17 +++-- .../@aws-cdk/aws-ecr/lib/repository-ref.ts | 4 +- packages/@aws-cdk/aws-iam/lib/grant.ts | 69 +++++++++---------- .../@aws-cdk/aws-iam/lib/policy-document.ts | 36 ++++++++++ packages/@aws-cdk/aws-iam/lib/role.ts | 4 +- packages/@aws-cdk/aws-kinesis/lib/stream.ts | 2 +- packages/@aws-cdk/aws-kms/lib/key.ts | 2 +- .../@aws-cdk/aws-lambda/lib/function-base.ts | 2 +- packages/@aws-cdk/aws-logs/lib/log-group.ts | 2 +- packages/@aws-cdk/aws-s3/lib/bucket.ts | 4 +- .../@aws-cdk/aws-secretsmanager/lib/secret.ts | 2 +- packages/@aws-cdk/aws-sns/lib/topic-base.ts | 2 +- packages/@aws-cdk/aws-sqs/lib/queue-base.ts | 2 +- tools/awslint/lib/rules/resource.ts | 14 ++-- tools/awslint/lib/util.ts | 11 --- tools/awslint/package-lock.json | 2 +- tools/cdk-build-tools/package-lock.json | 2 +- 17 files changed, 96 insertions(+), 81 deletions(-) diff --git a/packages/@aws-cdk/aws-dynamodb/lib/table.ts b/packages/@aws-cdk/aws-dynamodb/lib/table.ts index d8d79512b3715..291e9fe4d25c5 100644 --- a/packages/@aws-cdk/aws-dynamodb/lib/table.ts +++ b/packages/@aws-cdk/aws-dynamodb/lib/table.ts @@ -1,6 +1,5 @@ import appscaling = require('@aws-cdk/aws-applicationautoscaling'); import iam = require('@aws-cdk/aws-iam'); -import { PolicyStatement } from '@aws-cdk/aws-iam'; import cdk = require('@aws-cdk/cdk'); import { Construct, Token } from '@aws-cdk/cdk'; import { CfnTable } from './dynamodb.generated'; @@ -179,12 +178,12 @@ export class Table extends Construct { * Permits an IAM Principal to list all DynamoDB Streams. * @param principal The principal (no-op if undefined) */ - public static grantListStreams(principal?: iam.IPrincipal): void { - if (principal) { - principal.addToPolicy(new PolicyStatement() - .addAction('dynamodb:ListStreams') - .addAllResources()); - } + public static grantListStreams(principal?: iam.IPrincipal): iam.Grant { + return iam.Grant.onPrincipal({ + principal, + actions: ['dynamodb:ListStreams'], + resourceArns: ['*'], + }); } public readonly tableArn: string; @@ -409,7 +408,7 @@ export class Table extends Construct { * @param actions The set of actions to allow (i.e. "dynamodb:PutItem", "dynamodb:GetItem", ...) */ public grant(principal?: iam.IPrincipal, ...actions: string[]): iam.Grant { - return iam.Permissions.grantOnPrincipal({ + return iam.Grant.onPrincipal({ principal, actions, resourceArns: [ @@ -427,7 +426,7 @@ export class Table extends Construct { * @param actions The set of actions to allow (i.e. "dynamodb:DescribeStream", "dynamodb:GetRecords", ...) */ public grantStream(principal?: iam.IPrincipal, ...actions: string[]) { - return iam.Permissions.grantOnPrincipal({ + return iam.Grant.onPrincipal({ principal, actions, resourceArns: [this.tableStreamArn], diff --git a/packages/@aws-cdk/aws-ecr/lib/repository-ref.ts b/packages/@aws-cdk/aws-ecr/lib/repository-ref.ts index c06a134190e74..e704f58031386 100644 --- a/packages/@aws-cdk/aws-ecr/lib/repository-ref.ts +++ b/packages/@aws-cdk/aws-ecr/lib/repository-ref.ts @@ -207,7 +207,7 @@ export abstract class RepositoryBase extends cdk.Construct implements IRepositor * Grant the given principal identity permissions to perform the actions on this repository */ public grant(principal?: iam.IPrincipal, ...actions: string[]) { - return iam.Permissions.grantWithResource({ + return iam.Grant.withResource({ principal, actions, resourceArns: [this.repositoryArn], @@ -221,7 +221,7 @@ export abstract class RepositoryBase extends cdk.Construct implements IRepositor public grantPull(principal?: iam.IPrincipal) { const ret = this.grant(principal, "ecr:BatchCheckLayerAvailability", "ecr:GetDownloadUrlForLayer", "ecr:BatchGetImage"); - iam.Permissions.grantOnPrincipal({ + iam.Grant.onPrincipal({ principal, actions: ["ecr:GetAuthorizationToken"], resourceArns: ['*'], diff --git a/packages/@aws-cdk/aws-iam/lib/grant.ts b/packages/@aws-cdk/aws-iam/lib/grant.ts index 228f809fcdb3b..5a19d38f79f23 100644 --- a/packages/@aws-cdk/aws-iam/lib/grant.ts +++ b/packages/@aws-cdk/aws-iam/lib/grant.ts @@ -77,7 +77,13 @@ export interface GrantOnPrincipalAndResourceOptions extends CommonGrantOptions { resourceSelfArns?: string[]; } -export class Permissions { +/** + * Result of a grant() operation + * + * This class is not instantiable by consumers on purpose, so that they will be + * required to call the Grant factory functions. + */ +export class Grant { /** * Grant the given permissions to the principal * @@ -92,8 +98,8 @@ export class Permissions { * case of imported resources) leads to a warning being added to the * resource construct. */ - public static grantWithResource(options: GrantWithResourceOptions): Grant { - const result = Permissions.grantOnPrincipal({ + public static withResource(options: GrantWithResourceOptions): Grant { + const result = Grant.onPrincipal({ ...options, scope: options.resource }); @@ -107,7 +113,7 @@ export class Permissions { options.resource.addToResourcePolicy(statement); - return grantResult({ addedToResource: true, statement, options }); + return new Grant({ resourceStatement: statement, options }); } /** @@ -116,13 +122,13 @@ export class Permissions { * Absence of a principal leads to a warning, but failing to add * the permissions to a present principal is not an error. */ - public static grantOnPrincipal(options: GrantOnPrincipalOptions): Grant { + public static onPrincipal(options: GrantOnPrincipalOptions): Grant { if (!options.principal) { if (options.scope) { // tslint:disable-next-line:max-line-length - options.scope.node.addWarning(`Could not add grant for '${options.actions}' on '${options.resourceArns}' because the principal was not available. Add the permissions by hand.`); + options.scope.node.addWarning(`Could not add grant '${options.actions}' on '${options.resourceArns}' because the principal was not available. Add the permissions by hand.`); } - return grantResult({ principalMissing: true, options }); + return new Grant({ principalMissing: true, options }); } const statement = new PolicyStatement() @@ -131,7 +137,7 @@ export class Permissions { const addedToPrincipal = options.principal.addToPolicy(statement); - return grantResult({ addedToPrincipal, statement: addedToPrincipal ? statement : undefined, options }); + return new Grant({ principalStatement: addedToPrincipal ? statement : undefined, options }); } /** @@ -143,8 +149,8 @@ export class Permissions { * * Statement will be the resource statement. */ - public static grantOnPrincipalAndResource(options: GrantOnPrincipalAndResourceOptions): Grant { - const result = Permissions.grantOnPrincipal({ + public static onPrincipalAndResource(options: GrantOnPrincipalAndResourceOptions): Grant { + const result = Grant.onPrincipal({ ...options, scope: options.resource, }); @@ -158,31 +164,27 @@ export class Permissions { options.resource.addToResourcePolicy(statement); - return grantResult({ addedToPrincipal: result.addedToPrincipal, addedToResource: true, statement, options }); + return new Grant({ principalStatement: statement, resourceStatement: result.resourceStatement, options }); } -} -/** - * The result of the grant() operation - * - * This class is not instantiable by consumers on purpose, so that they will be - * required to call the Permissions.grant() functions. - */ -export class Grant { /** * There was no principal to add the permissions to */ public readonly principalMissing: boolean; /** - * The grant was added to the principal's policy + * The statement that was added to the principal's policy + * + * Can be accessed to (e.g.) add additional conditions to the statement. */ - public readonly addedToPrincipal: boolean; + public readonly principalStatement?: PolicyStatement; /** - * The grant was added to the resource policy + * The statement that was added to the resource policy + * + * Can be accessed to (e.g.) add additional conditions to the statement. */ - public readonly addedToResource: boolean; + public readonly resourceStatement?: PolicyStatement; /** * The policy statement that was created for this permission @@ -204,16 +206,15 @@ export class Grant { private constructor(props: GrantProps) { this.options = props.options; this.principalMissing = !!props.principalMissing; - this.addedToPrincipal = !!props.addedToPrincipal; - this.addedToResource = !!props.addedToResource; - this.statement = props.statement; + this.principalStatement = props.principalStatement; + this.resourceStatement = props.resourceStatement; } /** * Whether the grant operation was successful */ public get success(): boolean { - return this.principalMissing || this.addedToPrincipal || this.addedToResource; + return this.principalMissing || this.principalMissing !== undefined || this.resourceStatement !== undefined; } /** @@ -231,19 +232,11 @@ function describeGrant(options: CommonGrantOptions) { return `Permissions for '${options.principal}' to call '${options.actions}' on '${options.resourceArns}'`; } -/** - * Instantiate a grantResult (which is normally not instantiable) - */ -function grantResult(props: GrantProps): Grant { - return Reflect.construct(Grant, [props]); -} - interface GrantProps { options: CommonGrantOptions; principalMissing?: boolean; - addedToPrincipal?: boolean; - addedToResource?: boolean; - statement?: PolicyStatement; + principalStatement?: PolicyStatement; + resourceStatement?: PolicyStatement; } /** @@ -254,4 +247,4 @@ export interface IResourceWithPolicy extends cdk.IConstruct { * Add a statement to the resource's resource policy */ addToResourcePolicy(statement: PolicyStatement): void; -} \ No newline at end of file +} diff --git a/packages/@aws-cdk/aws-iam/lib/policy-document.ts b/packages/@aws-cdk/aws-iam/lib/policy-document.ts index 762571bfd271b..e587e92ecbd3b 100644 --- a/packages/@aws-cdk/aws-iam/lib/policy-document.ts +++ b/packages/@aws-cdk/aws-iam/lib/policy-document.ts @@ -96,12 +96,20 @@ export class ArnPrincipal extends PrincipalBase { public get policyFragment(): PrincipalPolicyFragment { return new PrincipalPolicyFragment({ AWS: [ this.arn ] }); } + + public toString() { + return `ArnPrincipal(${this.arn})`; + } } export class AccountPrincipal extends ArnPrincipal { constructor(public readonly accountId: any) { super(new StackDependentToken(stack => `arn:${stack.partition}:iam::${accountId}:root`).toString()); } + + public toString() { + return `AccountPrincipal(${this.accountId})`; + } } /** @@ -115,6 +123,10 @@ export class ServicePrincipal extends PrincipalBase { public get policyFragment(): PrincipalPolicyFragment { return new PrincipalPolicyFragment({ Service: [ this.service ] }); } + + public toString() { + return `ServicePrincipal(${this.service})`; + } } /** @@ -131,6 +143,10 @@ export class OrganizationPrincipal extends PrincipalBase { { StringEquals: { 'aws:PrincipalOrgID': this.organizationId } } ); } + + public toString() { + return `OrganizationPrincipal(${this.organizationId})`; + } } /** @@ -154,6 +170,10 @@ export class CanonicalUserPrincipal extends PrincipalBase { public get policyFragment(): PrincipalPolicyFragment { return new PrincipalPolicyFragment({ CanonicalUser: [ this.canonicalUserId ] }); } + + public toString() { + return `CanonicalUserPrincipal(${this.canonicalUserId})`; + } } export class FederatedPrincipal extends PrincipalBase { @@ -169,12 +189,20 @@ export class FederatedPrincipal extends PrincipalBase { public get policyFragment(): PrincipalPolicyFragment { return new PrincipalPolicyFragment({ Federated: [ this.federated ] }, this.conditions); } + + public toString() { + return `FederatedPrincipal(${this.federated})`; + } } export class AccountRootPrincipal extends AccountPrincipal { constructor() { super(new StackDependentToken(stack => stack.accountId).toString()); } + + public toString() { + return `AccountRootPrincipal()`; + } } /** @@ -184,6 +212,10 @@ export class AnyPrincipal extends ArnPrincipal { constructor() { super('*'); } + + public toString() { + return `AnyPrincipal()`; + } } /** @@ -232,6 +264,10 @@ export class CompositePrincipal extends PrincipalBase { return new PrincipalPolicyFragment(principalJson); } + + public toString() { + return `CompositePrincipal(${this.principals})`; + } } /** diff --git a/packages/@aws-cdk/aws-iam/lib/role.ts b/packages/@aws-cdk/aws-iam/lib/role.ts index 815cbf20e0832..fa5cab1ae0f16 100644 --- a/packages/@aws-cdk/aws-iam/lib/role.ts +++ b/packages/@aws-cdk/aws-iam/lib/role.ts @@ -1,5 +1,5 @@ import { Construct, IConstruct, Output } from '@aws-cdk/cdk'; -import { Permissions } from './grant'; +import { Grant } from './grant'; import { CfnRole } from './iam.generated'; import { IIdentity } from './identity-base'; import { Policy } from './policy'; @@ -210,7 +210,7 @@ export class Role extends Construct implements IRole { * Grant the actions defined in actions to the identity Principal on this resource. */ public grant(principal?: IPrincipal, ...actions: string[]) { - return Permissions.grantOnPrincipal({ + return Grant.onPrincipal({ principal, actions, resourceArns: [this.roleArn], diff --git a/packages/@aws-cdk/aws-kinesis/lib/stream.ts b/packages/@aws-cdk/aws-kinesis/lib/stream.ts index c5c5b68a7fa49..6bfd387788f05 100644 --- a/packages/@aws-cdk/aws-kinesis/lib/stream.ts +++ b/packages/@aws-cdk/aws-kinesis/lib/stream.ts @@ -228,7 +228,7 @@ export abstract class StreamBase extends cdk.Construct implements IStream { } private grant(principal?: iam.IPrincipal, ...actions: string[]) { - return iam.Permissions.grantOnPrincipal({ + return iam.Grant.onPrincipal({ principal, actions, resourceArns: [this.streamArn], diff --git a/packages/@aws-cdk/aws-kms/lib/key.ts b/packages/@aws-cdk/aws-kms/lib/key.ts index a02955482f6df..31773dc8c6287 100644 --- a/packages/@aws-cdk/aws-kms/lib/key.ts +++ b/packages/@aws-cdk/aws-kms/lib/key.ts @@ -105,7 +105,7 @@ export abstract class EncryptionKeyBase extends Construct implements IEncryption * must not be empty and so default grants won't work. */ public grant(principal: iam.IPrincipal | undefined, ...actions: string[]): iam.Grant { - return iam.Permissions.grantOnPrincipalAndResource({ + return iam.Grant.onPrincipalAndResource({ principal, actions, resourceArns: [this.keyArn], diff --git a/packages/@aws-cdk/aws-lambda/lib/function-base.ts b/packages/@aws-cdk/aws-lambda/lib/function-base.ts index 40c554727a0ea..1b451e33deaa5 100644 --- a/packages/@aws-cdk/aws-lambda/lib/function-base.ts +++ b/packages/@aws-cdk/aws-lambda/lib/function-base.ts @@ -247,7 +247,7 @@ export abstract class FunctionBase extends cdk.Construct implements IFunction { * Grant the given identity permissions to invoke this Lambda */ public grantInvoke(principal?: iam.IPrincipal): iam.Grant { - return iam.Permissions.grantWithResource({ + return iam.Grant.withResource({ principal, actions: ['lambda:InvokeFunction'], resourceArns: [this.functionArn], diff --git a/packages/@aws-cdk/aws-logs/lib/log-group.ts b/packages/@aws-cdk/aws-logs/lib/log-group.ts index 7fda13bce3c0c..974bbaaff64f2 100644 --- a/packages/@aws-cdk/aws-logs/lib/log-group.ts +++ b/packages/@aws-cdk/aws-logs/lib/log-group.ts @@ -179,7 +179,7 @@ export abstract class LogGroupBase extends cdk.Construct implements ILogGroup { * Give the indicated permissions on this log group and all streams */ public grant(principal?: iam.IPrincipal, ...actions: string[]) { - return iam.Permissions.grantOnPrincipal({ + return iam.Grant.onPrincipal({ principal, actions, // A LogGroup ARN out of CloudFormation already includes a ':*' at the end to include the log streams under the group. diff --git a/packages/@aws-cdk/aws-s3/lib/bucket.ts b/packages/@aws-cdk/aws-s3/lib/bucket.ts index 63322324f0a34..0292cbb00fed1 100644 --- a/packages/@aws-cdk/aws-s3/lib/bucket.ts +++ b/packages/@aws-cdk/aws-s3/lib/bucket.ts @@ -505,7 +505,7 @@ export abstract class BucketBase extends cdk.Construct implements IBucket { allowedActions = allowedActions.length > 0 ? allowedActions : [ 's3:GetObject' ]; - return iam.Permissions.grantWithResource({ + return iam.Grant.withResource({ actions: allowedActions, resourceArns: [this.arnForObjects(keyPrefix)], principal: new iam.Anyone(), @@ -519,7 +519,7 @@ export abstract class BucketBase extends cdk.Construct implements IBucket { resourceArn: string, ...otherResourceArns: string[]) { const resources = [ resourceArn, ...otherResourceArns ]; - const ret = iam.Permissions.grantWithResource({ + const ret = iam.Grant.withResource({ principal, actions: bucketActions, resourceArns: resources, diff --git a/packages/@aws-cdk/aws-secretsmanager/lib/secret.ts b/packages/@aws-cdk/aws-secretsmanager/lib/secret.ts index 61627d4e7a67b..a5bef98d43d0f 100644 --- a/packages/@aws-cdk/aws-secretsmanager/lib/secret.ts +++ b/packages/@aws-cdk/aws-secretsmanager/lib/secret.ts @@ -104,7 +104,7 @@ export abstract class SecretBase extends cdk.Construct implements ISecret { public grantRead(principal?: iam.IPrincipal, versionStages?: string[]): iam.Grant { // @see https://docs.aws.amazon.com/fr_fr/secretsmanager/latest/userguide/auth-and-access_identity-based-policies.html - const result = iam.Permissions.grantOnPrincipal({ + const result = iam.Grant.onPrincipal({ principal, actions: ['secretsmanager:GetSecretValue'], resourceArns: [this.secretArn], diff --git a/packages/@aws-cdk/aws-sns/lib/topic-base.ts b/packages/@aws-cdk/aws-sns/lib/topic-base.ts index cf7388cc91ced..94477b6aef1d4 100644 --- a/packages/@aws-cdk/aws-sns/lib/topic-base.ts +++ b/packages/@aws-cdk/aws-sns/lib/topic-base.ts @@ -264,7 +264,7 @@ export abstract class TopicBase extends cdk.Construct implements ITopic { * Grant topic publishing permissions to the given identity */ public grantPublish(principal?: iam.IPrincipal) { - return iam.Permissions.grantWithResource({ + return iam.Grant.withResource({ principal, actions: ['sns:Publish'], resourceArns: [this.topicArn], diff --git a/packages/@aws-cdk/aws-sqs/lib/queue-base.ts b/packages/@aws-cdk/aws-sqs/lib/queue-base.ts index 3f4d6c42f0fd8..5c52c9e706f32 100644 --- a/packages/@aws-cdk/aws-sqs/lib/queue-base.ts +++ b/packages/@aws-cdk/aws-sqs/lib/queue-base.ts @@ -274,7 +274,7 @@ export abstract class QueueBase extends cdk.Construct implements IQueue { * @param actions The actions to grant */ public grant(principal?: iam.IPrincipal, ...actions: string[]) { - return iam.Permissions.grantWithResource({ + return iam.Grant.withResource({ principal, actions, resourceArns: [this.queueArn], diff --git a/tools/awslint/lib/rules/resource.ts b/tools/awslint/lib/rules/resource.ts index 31218232b9777..c56a649526270 100644 --- a/tools/awslint/lib/rules/resource.ts +++ b/tools/awslint/lib/rules/resource.ts @@ -1,7 +1,7 @@ import reflect = require('jsii-reflect'); import { CfnResourceSpec, findCfnResources } from '../cfn-resources'; import { Linter } from '../linter'; -import { classAndAncestors, CONSTRUCT_FQN, CONSTRUCT_INTERFACE_FQN, isConstruct } from '../util'; +import { CONSTRUCT_FQN, CONSTRUCT_INTERFACE_FQN, isConstruct } from '../util'; export const resourceLinter = new Linter(assembly => { return findCfnResources(assembly).map(cfn => ({ @@ -188,14 +188,12 @@ resourceLinter.add({ if (!e.ctx.resourceClass) { return; } const grantResultType = e.ctx.ts.findFqn(GRANT_RESULT_FQN); + const grantMethods = e.ctx.resourceClass.getMethods(true).filter(m => m.name.startsWith('grant')); - for (const klass of classAndAncestors(e.ctx.resourceClass)) { - const grantMethods = klass.methods.filter(m => m.name.startsWith('grant')); - for (const grantMethod of grantMethods) { - e.assertSignature(grantMethod, { - returns: grantResultType - }); - } + for (const grantMethod of grantMethods) { + e.assertSignature(grantMethod, { + returns: grantResultType + }); } } }); \ No newline at end of file diff --git a/tools/awslint/lib/util.ts b/tools/awslint/lib/util.ts index 535c189dc36c8..2f6385c12cc21 100644 --- a/tools/awslint/lib/util.ts +++ b/tools/awslint/lib/util.ts @@ -8,15 +8,4 @@ export function isConstruct(c: reflect.ClassType) { const bases = c.getAncestors(); const root = bases[bases.length - 1]; return root === constructClass; -} - -/** - * Iterate over a class and all of its ancestors - */ -export function* classAndAncestors(c: reflect.ClassType): Iterable { - yield c; - - for (const ancestor of c.getAncestors()) { - yield* classAndAncestors(ancestor); - } } \ No newline at end of file diff --git a/tools/awslint/package-lock.json b/tools/awslint/package-lock.json index 1e773adbf2802..154b72fe85a8e 100644 --- a/tools/awslint/package-lock.json +++ b/tools/awslint/package-lock.json @@ -1,6 +1,6 @@ { "name": "awslint", - "version": "0.23.0", + "version": "0.24.1", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/tools/cdk-build-tools/package-lock.json b/tools/cdk-build-tools/package-lock.json index 03b0f801bba99..54b9aaaa1e330 100644 --- a/tools/cdk-build-tools/package-lock.json +++ b/tools/cdk-build-tools/package-lock.json @@ -1,6 +1,6 @@ { "name": "cdk-build-tools", - "version": "0.23.0", + "version": "0.24.1", "lockfileVersion": 1, "requires": true, "dependencies": { From 2006891292cd7c4361044cf6b94847aaebb61f8e Mon Sep 17 00:00:00 2001 From: Rico Huijbers Date: Fri, 1 Mar 2019 17:00:46 +0100 Subject: [PATCH 16/31] Review comments --- .../@aws-cdk/aws-cloudwatch/lib/metric.ts | 2 +- packages/@aws-cdk/aws-iam/lib/grant.ts | 15 +---- .../@aws-cdk/aws-iam/lib/identity-base.ts | 3 +- packages/@aws-cdk/aws-iam/lib/principals.ts | 16 +++++- packages/@aws-cdk/aws-iam/lib/user.ts | 2 + packages/@aws-cdk/aws-iam/lib/util.ts | 3 + packages/@aws-cdk/aws-kms/lib/index.ts | 1 + .../aws-kms/lib/via-service-principal.ts | 27 +++++++++ .../test/test.via-service-principal.ts | 55 +++++++++++++++++++ packages/@aws-cdk/aws-s3/test/test.bucket.ts | 2 +- .../@aws-cdk/aws-secretsmanager/lib/secret.ts | 14 ++--- .../aws-secretsmanager/test/test.secret.ts | 4 +- tools/awslint/package-lock.json | 2 +- tools/cdk-build-tools/package-lock.json | 2 +- tools/decdk/package-lock.json | 43 ++++----------- tools/decdk/package.json | 2 +- 16 files changed, 131 insertions(+), 62 deletions(-) create mode 100644 packages/@aws-cdk/aws-kms/lib/via-service-principal.ts create mode 100644 packages/@aws-cdk/aws-kms/test/test.via-service-principal.ts diff --git a/packages/@aws-cdk/aws-cloudwatch/lib/metric.ts b/packages/@aws-cdk/aws-cloudwatch/lib/metric.ts index 8f07b26b5588b..5bde0dcf6d0e1 100644 --- a/packages/@aws-cdk/aws-cloudwatch/lib/metric.ts +++ b/packages/@aws-cdk/aws-cloudwatch/lib/metric.ts @@ -88,7 +88,7 @@ export class Metric { * @param principal The IAM identity to give permissions to. */ public static grantPutMetricData(principal?: iam.IPrincipal): iam.Grant { - return iam.Permissions.grantOnPrincipal({ + return iam.Grant.onPrincipal({ principal, actions: ['cloudwatch:PutMetricData'], resourceArns: ['*'] diff --git a/packages/@aws-cdk/aws-iam/lib/grant.ts b/packages/@aws-cdk/aws-iam/lib/grant.ts index 5a19d38f79f23..8936874be8c92 100644 --- a/packages/@aws-cdk/aws-iam/lib/grant.ts +++ b/packages/@aws-cdk/aws-iam/lib/grant.ts @@ -9,7 +9,7 @@ export interface CommonGrantOptions { /** * The principal to grant to * - * @default No work is done + * @default if principal is undefined, no work is done. */ principal?: IPrincipal; @@ -145,7 +145,7 @@ export class Grant { * * As long as any principal is given, granting on the pricipal may fail (in * case of a non-identity principal), but granting on the resource will - * always be done. + * never fail. * * Statement will be the resource statement. */ @@ -186,15 +186,6 @@ export class Grant { */ public readonly resourceStatement?: PolicyStatement; - /** - * The policy statement that was created for this permission - * - * Can be accessed to (e.g.) add additional conditions to the statement. - * - * Only set if either addedToPrincipal or addedToResource are true. - */ - public readonly statement?: PolicyStatement; - /** * The options originally used to set this result * @@ -214,7 +205,7 @@ export class Grant { * Whether the grant operation was successful */ public get success(): boolean { - return this.principalMissing || this.principalMissing !== undefined || this.resourceStatement !== undefined; + return this.principalMissing || this.principalStatement !== undefined || this.resourceStatement !== undefined; } /** diff --git a/packages/@aws-cdk/aws-iam/lib/identity-base.ts b/packages/@aws-cdk/aws-iam/lib/identity-base.ts index 08050d0cc0236..9b0e2d93bd7f6 100644 --- a/packages/@aws-cdk/aws-iam/lib/identity-base.ts +++ b/packages/@aws-cdk/aws-iam/lib/identity-base.ts @@ -1,10 +1,11 @@ +import cdk = require('@aws-cdk/cdk'); import { Policy } from "./policy"; import { IPrincipal } from "./principals"; /** * A construct that represents an IAM principal, such as a user, group or role. */ -export interface IIdentity extends IPrincipal { +export interface IIdentity extends IPrincipal, cdk.IConstruct { /** * Attaches an inline policy to this principal. * This is the same as calling `policy.addToXxx(principal)`. diff --git a/packages/@aws-cdk/aws-iam/lib/principals.ts b/packages/@aws-cdk/aws-iam/lib/principals.ts index c1a5d69da20a9..11d59cfea7773 100644 --- a/packages/@aws-cdk/aws-iam/lib/principals.ts +++ b/packages/@aws-cdk/aws-iam/lib/principals.ts @@ -1,9 +1,21 @@ import { PolicyStatement, PrincipalPolicyFragment } from './policy-document'; /** - * Represents an IAM principal. + * Represents a logical IAM principal. * - * An IAM principal is any object that can have + * An IPrincipal describes a logical entity that can perform AWS API calls + * against sets of resources, optionally under certain conditions. + * + * Examples of simple principals are IAM objects that you create, such + * as Users or Roles. + * + * An example of a more complex principals is a `ServicePrincipal` (such as + * `new ServicePrincipal("sns.amazonaws.com")`, which represents the Simple + * Notifications Service). + * + * A single logical Principal may also map to a set of physical principals. + * For example, `new OrganizationPrincipal('o-1234')` represents all + * identities that are part of the given AWS Organization. */ export interface IPrincipal { /** diff --git a/packages/@aws-cdk/aws-iam/lib/user.ts b/packages/@aws-cdk/aws-iam/lib/user.ts index 3341f2320b5b7..788515547f605 100644 --- a/packages/@aws-cdk/aws-iam/lib/user.ts +++ b/packages/@aws-cdk/aws-iam/lib/user.ts @@ -129,6 +129,8 @@ export class User extends Construct implements IIdentity { /** * Adds an IAM statement to the default policy. + * + * @returns true */ public addToPolicy(statement: PolicyStatement): boolean { if (!this.defaultPolicy) { diff --git a/packages/@aws-cdk/aws-iam/lib/util.ts b/packages/@aws-cdk/aws-iam/lib/util.ts index f8ae203a37552..896e36ce3e80b 100644 --- a/packages/@aws-cdk/aws-iam/lib/util.ts +++ b/packages/@aws-cdk/aws-iam/lib/util.ts @@ -45,6 +45,9 @@ export class AttachedPolicies { } } +/** + * Merge two dictionaries that represent IAM principals + */ export function mergePrincipal(target: { [key: string]: string[] }, source: { [key: string]: string[] }) { for (const key of Object.keys(source)) { target[key] = target[key] || []; diff --git a/packages/@aws-cdk/aws-kms/lib/index.ts b/packages/@aws-cdk/aws-kms/lib/index.ts index 52d9014cc7b9c..5affbeb43c54c 100644 --- a/packages/@aws-cdk/aws-kms/lib/index.ts +++ b/packages/@aws-cdk/aws-kms/lib/index.ts @@ -1,5 +1,6 @@ export * from './key'; export * from './alias'; +export * from './via-service-principal'; // AWS::KMS CloudFormation Resources: export * from './kms.generated'; diff --git a/packages/@aws-cdk/aws-kms/lib/via-service-principal.ts b/packages/@aws-cdk/aws-kms/lib/via-service-principal.ts new file mode 100644 index 0000000000000..08029a64d400f --- /dev/null +++ b/packages/@aws-cdk/aws-kms/lib/via-service-principal.ts @@ -0,0 +1,27 @@ +import iam = require('@aws-cdk/aws-iam'); + +/** + * A principal to allow access to a key if it's being used through another AWS service + */ +export class ViaServicePrincipal extends iam.PrincipalBase { + private readonly basePrincipal: iam.IPrincipal; + + constructor(private readonly serviceName: string, basePrincipal?: iam.IPrincipal) { + super(); + this.basePrincipal = basePrincipal ? basePrincipal : new iam.AnyPrincipal(); + } + + public get policyFragment(): iam.PrincipalPolicyFragment { + // Make a copy of the base policyFragment to add a condition to it + const base = this.basePrincipal.policyFragment; + const conditions = Object.assign({}, base.conditions); + + if (conditions.StringEquals) { + conditions.StringEquals = Object.assign({ 'kms:ViaService': this.serviceName }, conditions.StringEquals); + } else { + conditions.StringEquals = { 'kms:ViaService': this.serviceName }; + } + + return { principalJson: base.principalJson, conditions }; + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-kms/test/test.via-service-principal.ts b/packages/@aws-cdk/aws-kms/test/test.via-service-principal.ts new file mode 100644 index 0000000000000..308bdd996b829 --- /dev/null +++ b/packages/@aws-cdk/aws-kms/test/test.via-service-principal.ts @@ -0,0 +1,55 @@ +import iam = require('@aws-cdk/aws-iam'); +import cdk = require('@aws-cdk/cdk'); +import { Test } from 'nodeunit'; +import kms = require('../lib'); + +export = { + 'Via service, any principal'(test: Test) { + // GIVEN + const stack = new cdk.Stack(); + + // WHEN + const statement = new iam.PolicyStatement() + .addAction('abc:call') + .addPrincipal(new kms.ViaServicePrincipal('bla.amazonaws.com')) + .addResource('*'); + + // THEN + test.deepEqual(stack.node.resolve(statement), { + Action: 'abc:call', + Condition: { StringEquals: { 'kms:ViaService': 'bla.amazonaws.com' } }, + Effect: 'Allow', + Principal: '*', + Resource: '*' + }); + + test.done(); + }, + + 'Via service, principal with conditions'(test: Test) { + // GIVEN + const stack = new cdk.Stack(); + + // WHEN + const statement = new iam.PolicyStatement() + .addAction('abc:call') + .addPrincipal(new kms.ViaServicePrincipal('bla.amazonaws.com', new iam.OrganizationPrincipal('o-1234'))) + .addResource('*'); + + // THEN + test.deepEqual(stack.node.resolve(statement), { + Action: 'abc:call', + Condition: { + StringEquals: { + 'kms:ViaService': 'bla.amazonaws.com', + 'aws:PrincipalOrgID': 'o-1234' + } + }, + Effect: 'Allow', + Principal: '*', + Resource: '*' + }); + + test.done(); + }, +}; \ No newline at end of file diff --git a/packages/@aws-cdk/aws-s3/test/test.bucket.ts b/packages/@aws-cdk/aws-s3/test/test.bucket.ts index 8f1e4ab131019..2d5802c261d35 100644 --- a/packages/@aws-cdk/aws-s3/test/test.bucket.ts +++ b/packages/@aws-cdk/aws-s3/test/test.bucket.ts @@ -1274,7 +1274,7 @@ export = { // WHEN const result = bucket.grantPublicAccess(); - result.statement!.addCondition('IpAddress', { "aws:SourceIp": "54.240.143.0/24" }); + result.resourceStatement!.addCondition('IpAddress', { "aws:SourceIp": "54.240.143.0/24" }); // THEN expect(stack).to(haveResource('AWS::S3::BucketPolicy', { diff --git a/packages/@aws-cdk/aws-secretsmanager/lib/secret.ts b/packages/@aws-cdk/aws-secretsmanager/lib/secret.ts index f454f7d84d23b..e25cfefd47528 100644 --- a/packages/@aws-cdk/aws-secretsmanager/lib/secret.ts +++ b/packages/@aws-cdk/aws-secretsmanager/lib/secret.ts @@ -121,21 +121,17 @@ export abstract class SecretBase extends cdk.Construct implements ISecret { resourceArns: [this.secretArn], scope: this }); - if (versionStages != null) { - result.statement!.addCondition('ForAnyValue:StringEquals', { + if (versionStages != null && result.principalStatement) { + result.principalStatement.addCondition('ForAnyValue:StringEquals', { 'secretsmanager:VersionStage': versionStages }); } if (this.encryptionKey && principal) { // @see https://docs.aws.amazon.com/fr_fr/kms/latest/developerguide/services-secrets-manager.html - this.encryptionKey.addToResourcePolicy(new iam.PolicyStatement() - .addPrincipal(principal) - .addAction('kms:Decrypt') - .addAllResources() - .addCondition('StringEquals', { - 'kms:ViaService': `secretsmanager.${this.node.stack.region}.amazonaws.com` - })); + this.encryptionKey.grantDecrypt( + new kms.ViaServicePrincipal(`secretsmanager.${this.node.stack.region}.amazonaws.com`, principal) + ); } return result; diff --git a/packages/@aws-cdk/aws-secretsmanager/test/test.secret.ts b/packages/@aws-cdk/aws-secretsmanager/test/test.secret.ts index 47b724900612d..bb0a489fd54b7 100644 --- a/packages/@aws-cdk/aws-secretsmanager/test/test.secret.ts +++ b/packages/@aws-cdk/aws-secretsmanager/test/test.secret.ts @@ -80,7 +80,7 @@ export = { }, Resource: "*" }, { - Action: "kms:Decrypt", + Action: ["kms:Decrypt", "kms:DescribeKey"], Condition: { StringEquals: { "kms:ViaService": { @@ -179,7 +179,7 @@ export = { }, Resource: "*" }, { - Action: "kms:Decrypt", + Action: ["kms:Decrypt", "kms:DescribeKey"], Condition: { StringEquals: { "kms:ViaService": { diff --git a/tools/awslint/package-lock.json b/tools/awslint/package-lock.json index 543a255bc2255..074030faad5d4 100644 --- a/tools/awslint/package-lock.json +++ b/tools/awslint/package-lock.json @@ -1,6 +1,6 @@ { "name": "awslint", - "version": "0.24.1", + "version": "0.25.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/tools/cdk-build-tools/package-lock.json b/tools/cdk-build-tools/package-lock.json index 1b1bf4db9e942..f85495873304d 100644 --- a/tools/cdk-build-tools/package-lock.json +++ b/tools/cdk-build-tools/package-lock.json @@ -1,6 +1,6 @@ { "name": "cdk-build-tools", - "version": "0.24.1", + "version": "0.25.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/tools/decdk/package-lock.json b/tools/decdk/package-lock.json index ed11d30cf2c10..ef38d397ff8ad 100644 --- a/tools/decdk/package-lock.json +++ b/tools/decdk/package-lock.json @@ -1,6 +1,6 @@ { "name": "decdk", - "version": "0.24.1", + "version": "0.25.0", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -1426,8 +1426,7 @@ "ansi-regex": { "version": "2.1.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "aproba": { "version": "1.2.0", @@ -1448,14 +1447,12 @@ "balanced-match": { "version": "1.0.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, "dev": true, - "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -1470,20 +1467,17 @@ "code-point-at": { "version": "1.1.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "concat-map": { "version": "0.0.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "console-control-strings": { "version": "1.1.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "core-util-is": { "version": "1.0.2", @@ -1600,8 +1594,7 @@ "inherits": { "version": "2.0.3", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "ini": { "version": "1.3.5", @@ -1613,7 +1606,6 @@ "version": "1.0.0", "bundled": true, "dev": true, - "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -1628,7 +1620,6 @@ "version": "3.0.4", "bundled": true, "dev": true, - "optional": true, "requires": { "brace-expansion": "^1.1.7" } @@ -1636,14 +1627,12 @@ "minimist": { "version": "0.0.8", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "minipass": { "version": "2.3.5", "bundled": true, "dev": true, - "optional": true, "requires": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" @@ -1662,7 +1651,6 @@ "version": "0.5.1", "bundled": true, "dev": true, - "optional": true, "requires": { "minimist": "0.0.8" } @@ -1743,8 +1731,7 @@ "number-is-nan": { "version": "1.0.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "object-assign": { "version": "4.1.1", @@ -1756,7 +1743,6 @@ "version": "1.4.0", "bundled": true, "dev": true, - "optional": true, "requires": { "wrappy": "1" } @@ -1842,8 +1828,7 @@ "safe-buffer": { "version": "5.1.2", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "safer-buffer": { "version": "2.1.2", @@ -1879,7 +1864,6 @@ "version": "1.0.2", "bundled": true, "dev": true, - "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -1899,7 +1883,6 @@ "version": "3.0.1", "bundled": true, "dev": true, - "optional": true, "requires": { "ansi-regex": "^2.0.0" } @@ -1943,14 +1926,12 @@ "wrappy": { "version": "1.0.2", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "yallist": { "version": "3.0.3", "bundled": true, - "dev": true, - "optional": true + "dev": true } } }, diff --git a/tools/decdk/package.json b/tools/decdk/package.json index fcd24f061ebcf..76ee88fd653cd 100644 --- a/tools/decdk/package.json +++ b/tools/decdk/package.json @@ -143,4 +143,4 @@ "engines": { "node": ">= 8.10.0" } -} +} \ No newline at end of file From b195ac3739acf8cbfb88ba2c7df83625ec049697 Mon Sep 17 00:00:00 2001 From: Rico Huijbers Date: Fri, 1 Mar 2019 17:37:35 +0100 Subject: [PATCH 17/31] IRole implementing both IConstruct and IIdentity leads to a C# build errror --- packages/@aws-cdk/aws-iam/lib/role.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/@aws-cdk/aws-iam/lib/role.ts b/packages/@aws-cdk/aws-iam/lib/role.ts index fa5cab1ae0f16..58357363466f0 100644 --- a/packages/@aws-cdk/aws-iam/lib/role.ts +++ b/packages/@aws-cdk/aws-iam/lib/role.ts @@ -229,7 +229,7 @@ export class Role extends Construct implements IRole { /** * A Role object */ -export interface IRole extends IConstruct, IIdentity { +export interface IRole extends IIdentity { /** * Returns the ARN of this role. */ From 49f996e282470efec0b8eeba66a3991238414334 Mon Sep 17 00:00:00 2001 From: Rico Huijbers Date: Fri, 1 Mar 2019 17:38:13 +0100 Subject: [PATCH 18/31] Fix unused import --- packages/@aws-cdk/aws-iam/lib/role.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/@aws-cdk/aws-iam/lib/role.ts b/packages/@aws-cdk/aws-iam/lib/role.ts index 58357363466f0..0dc204a2d1660 100644 --- a/packages/@aws-cdk/aws-iam/lib/role.ts +++ b/packages/@aws-cdk/aws-iam/lib/role.ts @@ -1,4 +1,4 @@ -import { Construct, IConstruct, Output } from '@aws-cdk/cdk'; +import { Construct, Output } from '@aws-cdk/cdk'; import { Grant } from './grant'; import { CfnRole } from './iam.generated'; import { IIdentity } from './identity-base'; From a65d8058986572c05a191b985099c1893e0ec349 Mon Sep 17 00:00:00 2001 From: Rico Huijbers Date: Mon, 4 Mar 2019 10:10:51 +0100 Subject: [PATCH 19/31] awslint should also find indirect interface extensions --- tools/awslint/lib/rules/resource.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/awslint/lib/rules/resource.ts b/tools/awslint/lib/rules/resource.ts index c56a649526270..bc59f7efaad3c 100644 --- a/tools/awslint/lib/rules/resource.ts +++ b/tools/awslint/lib/rules/resource.ts @@ -99,10 +99,10 @@ resourceLinter.add({ resourceLinter.add({ code: 'resource-interface-extends-construct', - message: 'resource interface must extends cdk.IConstruct', + message: 'resource interface must extend cdk.IConstruct', eval: e => { if (!e.ctx.resourceInterface) { return; } - e.assert(e.ctx.resourceInterface.interfaces.some(i => i.fqn === CONSTRUCT_INTERFACE_FQN), e.ctx.resourceInterface.fqn); + e.assert(e.ctx.resourceInterface.getInterfaces(true).some(i => i.fqn === CONSTRUCT_INTERFACE_FQN), e.ctx.resourceInterface.fqn); } }); From 77865f56d90a047362c4008750646a1db94f65e5 Mon Sep 17 00:00:00 2001 From: Rico Huijbers Date: Wed, 20 Mar 2019 17:02:34 +0100 Subject: [PATCH 20/31] Fixes --- packages/@aws-cdk/aws-iam/lib/lazy-role.ts | 8 +++++--- .../@aws-cdk/aws-iam/lib/policy-document.ts | 15 +-------------- packages/@aws-cdk/aws-iam/lib/role.ts | 17 +++++++++++------ packages/@aws-cdk/aws-kms/lib/key.ts | 2 -- 4 files changed, 17 insertions(+), 25 deletions(-) diff --git a/packages/@aws-cdk/aws-iam/lib/lazy-role.ts b/packages/@aws-cdk/aws-iam/lib/lazy-role.ts index 1701f3652d5bf..850a44542cffb 100644 --- a/packages/@aws-cdk/aws-iam/lib/lazy-role.ts +++ b/packages/@aws-cdk/aws-iam/lib/lazy-role.ts @@ -1,6 +1,8 @@ import cdk = require('@aws-cdk/cdk'); -import { IPrincipal, Policy } from './policy'; +import { Grant } from './grant'; +import { Policy } from './policy'; import { PolicyStatement, PrincipalPolicyFragment } from './policy-document'; +import { IPrincipal } from './principals'; import { IRole, Role, RoleImportProps, RoleProps } from './role'; /** @@ -87,14 +89,14 @@ export class LazyRole extends cdk.Construct implements IRole { /** * Grant the actions defined in actions to the identity Principal on this resource. */ - public grant(identity?: IPrincipal, ...actions: string[]): void { + public grant(identity?: IPrincipal, ...actions: string[]): Grant { return this.instantiate().grant(identity, ...actions); } /** * Grant permissions to the given principal to pass this role. */ - public grantPassRole(identity?: IPrincipal): void { + public grantPassRole(identity?: IPrincipal): Grant { return this.instantiate().grantPassRole(identity); } diff --git a/packages/@aws-cdk/aws-iam/lib/policy-document.ts b/packages/@aws-cdk/aws-iam/lib/policy-document.ts index 0afe55f67e55a..0741079c6c0b8 100644 --- a/packages/@aws-cdk/aws-iam/lib/policy-document.ts +++ b/packages/@aws-cdk/aws-iam/lib/policy-document.ts @@ -1,7 +1,7 @@ import cdk = require('@aws-cdk/cdk'); +import { Default, RegionInfo } from '@aws-cdk/region-info'; import { IPrincipal } from './principals'; import { mergePrincipal } from './util'; -import { Default, RegionInfo } from '@aws-cdk/region-info'; export class PolicyDocument extends cdk.Token { private statements = new Array(); @@ -275,19 +275,6 @@ export class CompositePrincipal extends PrincipalBase { } } -/** - * A lazy token that requires an instance of Stack to evaluate - */ -class StackDependentToken extends cdk.Token { - constructor(private readonly fn: (stack: cdk.Stack) => any) { - super(); - } - - public resolve(context: cdk.ResolveContext) { - return this.fn(context.scope.node.stack); - } -} - /** * Represents a statement in an IAM policy document. */ diff --git a/packages/@aws-cdk/aws-iam/lib/role.ts b/packages/@aws-cdk/aws-iam/lib/role.ts index f29f6e72db8ae..d5490b7bba671 100644 --- a/packages/@aws-cdk/aws-iam/lib/role.ts +++ b/packages/@aws-cdk/aws-iam/lib/role.ts @@ -254,12 +254,12 @@ export interface IRole extends IIdentity { /** * Grant the actions defined in actions to the identity Principal on this resource. */ - grant(identity?: IPrincipal, ...actions: string[]): void; + grant(identity?: IPrincipal, ...actions: string[]): Grant; /** * Grant permissions to the given principal to pass this role. */ - grantPassRole(identity?: IPrincipal): void; + grantPassRole(identity?: IPrincipal): Grant; } function createAssumeRolePolicy(principal: IPrincipal, externalId?: string) { @@ -352,14 +352,19 @@ class ImportedRole extends Construct implements IRole { /** * Grant the actions defined in actions to the identity Principal on this resource. */ - public grant(_identity?: IPrincipal, ..._actions: string[]): void { - // FIXME: Add warning that we're ignoring this + public grant(principal?: IPrincipal, ...actions: string[]): Grant { + return Grant.onPrincipal({ + principal, + actions, + resourceArns: [this.roleArn], + scope: this + }); } /** * Grant permissions to the given principal to pass this role. */ - public grantPassRole(_identity?: IPrincipal): void { - // FIXME: Add warning that we're ignoring this + public grantPassRole(identity?: IPrincipal): Grant { + return this.grant(identity, 'iam:PassRole'); } } diff --git a/packages/@aws-cdk/aws-kms/lib/key.ts b/packages/@aws-cdk/aws-kms/lib/key.ts index 1663cff7150c6..4a5eefe118928 100644 --- a/packages/@aws-cdk/aws-kms/lib/key.ts +++ b/packages/@aws-cdk/aws-kms/lib/key.ts @@ -120,7 +120,6 @@ export abstract class EncryptionKeyBase extends Construct implements IEncryption public grantDecrypt(principal: iam.IPrincipal | undefined): iam.Grant { return this.grant(principal, 'kms:Decrypt', - 'kms:DescribeKey' ); } @@ -141,7 +140,6 @@ export abstract class EncryptionKeyBase extends Construct implements IEncryption public grantEncryptDecrypt(principal: iam.IPrincipal | undefined): iam.Grant { return this.grant(principal, 'kms:Decrypt', - 'kms:DescribeKey', 'kms:Encrypt', 'kms:ReEncrypt*', 'kms:GenerateDataKey*' From c9349f632e8cd0e7e8721c9d1d0c7d05ceb10d43 Mon Sep 17 00:00:00 2001 From: Rico Huijbers Date: Mon, 1 Apr 2019 11:56:20 +0200 Subject: [PATCH 21/31] Make it build --- packages/@aws-cdk/aws-iam/lib/grant.ts | 24 +++++++++---------- .../@aws-cdk/aws-iam/lib/policy-document.ts | 13 +++++----- packages/@aws-cdk/aws-iam/lib/role.ts | 2 +- 3 files changed, 19 insertions(+), 20 deletions(-) diff --git a/packages/@aws-cdk/aws-iam/lib/grant.ts b/packages/@aws-cdk/aws-iam/lib/grant.ts index 8936874be8c92..a7a83f0fd402b 100644 --- a/packages/@aws-cdk/aws-iam/lib/grant.ts +++ b/packages/@aws-cdk/aws-iam/lib/grant.ts @@ -11,17 +11,17 @@ export interface CommonGrantOptions { * * @default if principal is undefined, no work is done. */ - principal?: IPrincipal; + readonly principal?: IPrincipal; /** * The actions to grant */ - actions: string[]; + readonly actions: string[]; /** * The resource ARNs to grant to */ - resourceArns: string[]; + readonly resourceArns: string[]; } /** @@ -34,7 +34,7 @@ export interface GrantWithResourceOptions extends CommonGrantOptions { * The statement will be added to the resource policy if it couldn't be * added to the principal policy. */ - resource: IResourceWithPolicy; + readonly resource: IResourceWithPolicy; /** * When referring to the resource in a resource policy, use this as ARN. @@ -43,7 +43,7 @@ export interface GrantWithResourceOptions extends CommonGrantOptions { * * @default Same as regular resource ARNs */ - resourceSelfArns?: string[]; + readonly resourceSelfArns?: string[]; } /** @@ -53,7 +53,7 @@ export interface GrantOnPrincipalOptions extends CommonGrantOptions { /** * Construct to report warnings on in case grant could not be registered */ - scope?: cdk.IConstruct; + readonly scope?: cdk.IConstruct; } /** @@ -65,7 +65,7 @@ export interface GrantOnPrincipalAndResourceOptions extends CommonGrantOptions { * * The statement will always be added to the resource policy. */ - resource: IResourceWithPolicy; + readonly resource: IResourceWithPolicy; /** * When referring to the resource in a resource policy, use this as ARN. @@ -74,7 +74,7 @@ export interface GrantOnPrincipalAndResourceOptions extends CommonGrantOptions { * * @default Same as regular resource ARNs */ - resourceSelfArns?: string[]; + readonly resourceSelfArns?: string[]; } /** @@ -224,10 +224,10 @@ function describeGrant(options: CommonGrantOptions) { } interface GrantProps { - options: CommonGrantOptions; - principalMissing?: boolean; - principalStatement?: PolicyStatement; - resourceStatement?: PolicyStatement; + readonly options: CommonGrantOptions; + readonly principalMissing?: boolean; + readonly principalStatement?: PolicyStatement; + readonly resourceStatement?: PolicyStatement; } /** diff --git a/packages/@aws-cdk/aws-iam/lib/policy-document.ts b/packages/@aws-cdk/aws-iam/lib/policy-document.ts index 53b114108ec33..c5b2487e31e48 100644 --- a/packages/@aws-cdk/aws-iam/lib/policy-document.ts +++ b/packages/@aws-cdk/aws-iam/lib/policy-document.ts @@ -57,11 +57,7 @@ export abstract class PrincipalBase implements IPrincipal { /** * When this Principal is used in an AssumeRole policy, the action to use. */ - protected _assumeRoleAction: string = 'sts:AssumeRole'; - - public get assumeRoleAction(): string { - return this._assumeRoleAction; - } + public readonly assumeRoleAction: string = 'sts:AssumeRole'; public addToPolicy(_statement: PolicyStatement): boolean { // This base class is used for non-identity principals. None of them @@ -182,13 +178,15 @@ export class CanonicalUserPrincipal extends PrincipalBase { } export class FederatedPrincipal extends PrincipalBase { + public readonly assumeRoleAction: string; + constructor( public readonly federated: string, public readonly conditions: {[key: string]: any}, assumeRoleAction: string = 'sts:AssumeRole') { super(); - this._assumeRoleAction = assumeRoleAction; + this.assumeRoleAction = assumeRoleAction; } public get policyFragment(): PrincipalPolicyFragment { @@ -230,11 +228,12 @@ export class AnyPrincipal extends ArnPrincipal { export class Anyone extends AnyPrincipal { } export class CompositePrincipal extends PrincipalBase { + public readonly assumeRoleAction: string; private readonly principals = new Array(); constructor(principal: PrincipalBase, ...additionalPrincipals: PrincipalBase[]) { super(); - this._assumeRoleAction = principal.assumeRoleAction; + this.assumeRoleAction = principal.assumeRoleAction; this.addPrincipals(principal); this.addPrincipals(...additionalPrincipals); } diff --git a/packages/@aws-cdk/aws-iam/lib/role.ts b/packages/@aws-cdk/aws-iam/lib/role.ts index 5882a3eb39021..74f9481210ee3 100644 --- a/packages/@aws-cdk/aws-iam/lib/role.ts +++ b/packages/@aws-cdk/aws-iam/lib/role.ts @@ -15,7 +15,7 @@ export interface RoleProps { * You can later modify the assume role policy document by accessing it via * the `assumeRolePolicy` property. */ - readonly assumbedBy: IPrincipal; + readonly assumedBy: IPrincipal; /** * ID that the role assumer needs to provide when assuming this role From 929c6fbf8ca08aa6c06c0d9b7eea5a1d9bc7835b Mon Sep 17 00:00:00 2001 From: Rico Huijbers Date: Tue, 2 Apr 2019 12:43:03 +0200 Subject: [PATCH 22/31] Fix failing tests --- packages/@aws-cdk/aws-glue/lib/table.ts | 59 ++++++++----------- .../@aws-cdk/aws-kinesis/test/test.stream.ts | 11 +--- packages/@aws-cdk/aws-kms/test/test.key.ts | 4 +- .../aws-secretsmanager/test/test.secret.ts | 4 +- packages/decdk/package.json | 2 +- 5 files changed, 32 insertions(+), 48 deletions(-) diff --git a/packages/@aws-cdk/aws-glue/lib/table.ts b/packages/@aws-cdk/aws-glue/lib/table.ts index b12e811b95b4a..6bbdb37a8809f 100644 --- a/packages/@aws-cdk/aws-glue/lib/table.ts +++ b/packages/@aws-cdk/aws-glue/lib/table.ts @@ -264,56 +264,45 @@ export class Table extends cdk.Construct implements ITable { /** * Grant read permissions to the table and the underlying data stored in S3 to an IAM principal. * - * @param identity the principal + * @param principal the principal */ - public grantRead(identity: iam.IPrincipal): void { - this.grant(identity, { - permissions: readPermissions, - kmsActions: ['kms:Decrypt'] - }); - this.bucket.grantRead(identity, this.s3Prefix); + public grantRead(principal: iam.IPrincipal): iam.Grant { + const ret = this.grant(principal, readPermissions); + if (this.encryptionKey && this.encryption === TableEncryption.ClientSideKms) { this.encryptionKey.grantDecrypt(principal); } + this.bucket.grantRead(principal, this.s3Prefix); + return ret; } /** * Grant write permissions to the table and the underlying data stored in S3 to an IAM principal. * - * @param identity the principal + * @param principal the principal */ - public grantWrite(identity: iam.IPrincipal): void { - this.grant(identity, { - permissions: writePermissions, - kmsActions: ['kms:Encrypt', 'kms:GenerateDataKey'] - }); - this.bucket.grantWrite(identity, this.s3Prefix); + public grantWrite(principal: iam.IPrincipal): iam.Grant { + const ret = this.grant(principal, writePermissions); + if (this.encryptionKey && this.encryption === TableEncryption.ClientSideKms) { this.encryptionKey.grantEncrypt(principal); } + this.bucket.grantWrite(principal, this.s3Prefix); + return ret; } /** * Grant read and write permissions to the table and the underlying data stored in S3 to an IAM principal. * - * @param identity the principal + * @param principal the principal */ - public grantReadWrite(identity: iam.IPrincipal): void { - this.grant(identity, { - permissions: readPermissions.concat(writePermissions), - kmsActions: ['kms:Decrypt', 'kms:Encrypt', 'kms:GenerateDataKey'] - }); - this.bucket.grantReadWrite(identity, this.s3Prefix); + public grantReadWrite(principal: iam.IPrincipal): iam.Grant { + const ret = this.grant(principal, [...readPermissions, ...writePermissions]); + if (this.encryptionKey && this.encryption === TableEncryption.ClientSideKms) { this.encryptionKey.grantEncryptDecrypt(principal); } + this.bucket.grantReadWrite(principal, this.s3Prefix); + return ret; } - private grant(identity: iam.IPrincipal, props: { - permissions: string[]; - // CSE-KMS needs to grant its own KMS policies because the bucket is unaware of the key. - // TODO: we wouldn't need this if kms.EncryptionKey exposed grant methods. - kmsActions?: string[]; - }) { - identity.addToPolicy(new iam.PolicyStatement() - .addResource(this.tableArn) - .addActions(...props.permissions)); - if (this.encryption === TableEncryption.ClientSideKms) { - identity.addToPolicy(new iam.PolicyStatement() - .addResource(this.encryptionKey!.keyArn) - .addActions(...props.kmsActions!)); - } + private grant(principal: iam.IPrincipal, actions: string[]) { + return iam.Grant.onPrincipal({ + principal, + resourceArns: [this.tableArn], + actions, + }); } } diff --git a/packages/@aws-cdk/aws-kinesis/test/test.stream.ts b/packages/@aws-cdk/aws-kinesis/test/test.stream.ts index 27d801e1c94eb..4612cf0f3c14f 100644 --- a/packages/@aws-cdk/aws-kinesis/test/test.stream.ts +++ b/packages/@aws-cdk/aws-kinesis/test/test.stream.ts @@ -307,10 +307,7 @@ export = { "Resource": "*" }, { - "Action": [ - "kms:Decrypt", - "kms:DescribeKey" - ], + "Action": "kms:Decrypt", "Effect": "Allow", "Principal": { "AWS": { @@ -367,7 +364,7 @@ export = { } }, { - "Action": ["kms:Decrypt", "kms:DescribeKey"], + "Action": "kms:Decrypt", "Effect": "Allow", "Resource": { "Fn::GetAtt": [ @@ -592,7 +589,6 @@ export = { { "Action": [ "kms:Decrypt", - "kms:DescribeKey", "kms:Encrypt", "kms:ReEncrypt*", "kms:GenerateDataKey*" @@ -657,7 +653,6 @@ export = { { "Action": [ "kms:Decrypt", - "kms:DescribeKey", "kms:Encrypt", "kms:ReEncrypt*", "kms:GenerateDataKey*" @@ -1054,7 +1049,7 @@ export = { } }, { - "Action": ["kms:Decrypt", "kms:DescribeKey"], + "Action": "kms:Decrypt", "Effect": "Allow", "Resource": { "Fn::ImportValue": "Stack:MyStreamKeyKeyArn967BCB03" diff --git a/packages/@aws-cdk/aws-kms/test/test.key.ts b/packages/@aws-cdk/aws-kms/test/test.key.ts index dfe895ab9e890..b0afeab8c0978 100644 --- a/packages/@aws-cdk/aws-kms/test/test.key.ts +++ b/packages/@aws-cdk/aws-kms/test/test.key.ts @@ -344,7 +344,7 @@ export = { }, // This is the interesting one { - Action: [ "kms:Decrypt", "kms:DescribeKey" ], + Action: "kms:Decrypt", Effect: "Allow", Principal: { AWS: { "Fn::GetAtt": [ "User00B015A1", "Arn" ] } }, Resource: "*" @@ -358,7 +358,7 @@ export = { PolicyDocument: { Statement: [ { - Action: [ "kms:Decrypt", "kms:DescribeKey" ], + Action: "kms:Decrypt", Effect: "Allow", Resource: { "Fn::GetAtt": [ "Key961B73FD", "Arn" ] } } diff --git a/packages/@aws-cdk/aws-secretsmanager/test/test.secret.ts b/packages/@aws-cdk/aws-secretsmanager/test/test.secret.ts index 7960c4fef9638..d8d6435ef7d59 100644 --- a/packages/@aws-cdk/aws-secretsmanager/test/test.secret.ts +++ b/packages/@aws-cdk/aws-secretsmanager/test/test.secret.ts @@ -127,7 +127,7 @@ export = { }, Resource: "*" }, { - Action: ["kms:Decrypt", "kms:DescribeKey"], + Action: "kms:Decrypt", Condition: { StringEquals: { "kms:ViaService": { @@ -226,7 +226,7 @@ export = { }, Resource: "*" }, { - Action: ["kms:Decrypt", "kms:DescribeKey"], + Action: "kms:Decrypt", Condition: { StringEquals: { "kms:ViaService": { diff --git a/packages/decdk/package.json b/packages/decdk/package.json index c3fbf21c7cfbb..210a664ad1190 100644 --- a/packages/decdk/package.json +++ b/packages/decdk/package.json @@ -146,4 +146,4 @@ "engines": { "node": ">= 8.10.0" } -} +} \ No newline at end of file From 753eb8446ab52f38be6f5094f1f5857c2451fd06 Mon Sep 17 00:00:00 2001 From: Rico Huijbers Date: Tue, 2 Apr 2019 14:39:09 +0200 Subject: [PATCH 23/31] Make principal in grant methods nonoptional --- packages/@aws-cdk/assets/lib/asset.ts | 2 +- .../@aws-cdk/aws-cloudwatch/lib/metric.ts | 2 +- .../@aws-cdk/aws-codebuild/lib/project.ts | 10 ++++----- .../lib/server/deployment-group.ts | 6 ++--- .../@aws-cdk/aws-codepipeline/lib/action.ts | 4 ++-- .../@aws-cdk/aws-codepipeline/lib/pipeline.ts | 4 ++-- packages/@aws-cdk/aws-dynamodb/lib/table.ts | 16 +++++++------- .../@aws-cdk/aws-ecr/lib/repository-ref.ts | 12 +++++----- packages/@aws-cdk/aws-iam/lib/grant.ts | 21 ++---------------- packages/@aws-cdk/aws-iam/lib/lazy-role.ts | 4 ++-- packages/@aws-cdk/aws-iam/lib/role.ts | 12 +++++----- packages/@aws-cdk/aws-kinesis/lib/stream.ts | 14 ++++++------ packages/@aws-cdk/aws-kms/lib/key.ts | 16 +++++++------- .../@aws-cdk/aws-lambda/lib/function-base.ts | 8 +++---- packages/@aws-cdk/aws-lambda/lib/function.ts | 4 ++-- .../aws-lambda/lib/singleton-lambda.ts | 2 +- packages/@aws-cdk/aws-logs/lib/log-group.ts | 8 +++---- packages/@aws-cdk/aws-s3/lib/bucket.ts | 22 +++++++++---------- .../@aws-cdk/aws-secretsmanager/lib/secret.ts | 4 ++-- packages/@aws-cdk/aws-sns/lib/topic-base.ts | 4 ++-- packages/@aws-cdk/aws-sqs/lib/queue-base.ts | 16 +++++++------- packages/@aws-cdk/runtime-values/lib/rtv.ts | 2 +- scripts/foreach.sh | 11 ++++++++-- 23 files changed, 97 insertions(+), 107 deletions(-) diff --git a/packages/@aws-cdk/assets/lib/asset.ts b/packages/@aws-cdk/assets/lib/asset.ts index 378c73a2da87d..04787b93f93af 100644 --- a/packages/@aws-cdk/assets/lib/asset.ts +++ b/packages/@aws-cdk/assets/lib/asset.ts @@ -171,7 +171,7 @@ export class Asset extends cdk.Construct { /** * Grants read permissions to the principal on the asset's S3 object. */ - public grantRead(principal?: iam.IPrincipal) { + public grantRead(principal: iam.IPrincipal) { // We give permissions on all files with the same prefix. Presumably // different versions of the same file will have the same prefix // and we don't want to accidentally revoke permission on old versions diff --git a/packages/@aws-cdk/aws-cloudwatch/lib/metric.ts b/packages/@aws-cdk/aws-cloudwatch/lib/metric.ts index de7a615823524..11626f7af389b 100644 --- a/packages/@aws-cdk/aws-cloudwatch/lib/metric.ts +++ b/packages/@aws-cdk/aws-cloudwatch/lib/metric.ts @@ -87,7 +87,7 @@ export class Metric { * * @param principal The IAM identity to give permissions to. */ - public static grantPutMetricData(principal?: iam.IPrincipal): iam.Grant { + public static grantPutMetricData(principal: iam.IPrincipal): iam.Grant { return iam.Grant.onPrincipal({ principal, actions: ['cloudwatch:PutMetricData'], diff --git a/packages/@aws-cdk/aws-codebuild/lib/project.ts b/packages/@aws-cdk/aws-codebuild/lib/project.ts index a891b5400780f..89d6e07d84fa1 100644 --- a/packages/@aws-cdk/aws-codebuild/lib/project.ts +++ b/packages/@aws-cdk/aws-codebuild/lib/project.ts @@ -24,7 +24,7 @@ export interface IProject extends cdk.IConstruct, events.IEventRuleTarget { readonly projectName: string; /** The IAM service Role of this Project. Undefined for imported Projects. */ - readonly role?: iam.IRole; + readonly role: iam.IRole; /** * Defines a CloudWatch event rule triggered when the build project state @@ -162,8 +162,8 @@ export abstract class ProjectBase extends cdk.Construct implements IProject { /** The human-visible name of this Project. */ public abstract readonly projectName: string; - /** The IAM service Role of this Project. Undefined for imported Projects. */ - public abstract readonly role?: iam.IRole; + /** The IAM service Role of this Project. */ + public abstract readonly role: iam.IRole; /** A role used by CloudWatch events to trigger a build */ private eventsRole?: iam.Role; @@ -371,7 +371,7 @@ export abstract class ProjectBase extends cdk.Construct implements IProject { class ImportedProject extends ProjectBase { public readonly projectArn: string; public readonly projectName: string; - public readonly role?: iam.Role = undefined; + public readonly role: iam.Role = undefined; constructor(scope: cdk.Construct, id: string, private readonly props: ProjectImportProps) { super(scope, id); @@ -575,7 +575,7 @@ export class Project extends ProjectBase { /** * The IAM role for this project. */ - public readonly role?: iam.IRole; + public readonly role: iam.IRole; /** * The ARN of the project. diff --git a/packages/@aws-cdk/aws-codedeploy/lib/server/deployment-group.ts b/packages/@aws-cdk/aws-codedeploy/lib/server/deployment-group.ts index 0b0200220aba2..abd12e1428471 100644 --- a/packages/@aws-cdk/aws-codedeploy/lib/server/deployment-group.ts +++ b/packages/@aws-cdk/aws-codedeploy/lib/server/deployment-group.ts @@ -13,7 +13,7 @@ import { IServerDeploymentConfig, ServerDeploymentConfig } from './deployment-co export interface IServerDeploymentGroup extends cdk.IConstruct { readonly application: IServerApplication; - readonly role?: iam.Role; + readonly role: iam.Role; readonly deploymentGroupName: string; readonly deploymentGroupArn: string; readonly deploymentConfig: IServerDeploymentConfig; @@ -60,7 +60,7 @@ export interface ServerDeploymentGroupImportProps { */ export abstract class ServerDeploymentGroupBase extends cdk.Construct implements IServerDeploymentGroup { public abstract readonly application: IServerApplication; - public abstract readonly role?: iam.Role; + public abstract readonly role: iam.Role; public abstract readonly deploymentGroupName: string; public abstract readonly deploymentGroupArn: string; public readonly deploymentConfig: IServerDeploymentConfig; @@ -76,7 +76,7 @@ export abstract class ServerDeploymentGroupBase extends cdk.Construct implements class ImportedServerDeploymentGroup extends ServerDeploymentGroupBase { public readonly application: IServerApplication; - public readonly role?: iam.Role = undefined; + public readonly role: iam.Role = undefined; public readonly deploymentGroupName: string; public readonly deploymentGroupArn: string; public readonly autoScalingGroups?: autoscaling.AutoScalingGroup[] = undefined; diff --git a/packages/@aws-cdk/aws-codepipeline/lib/action.ts b/packages/@aws-cdk/aws-codepipeline/lib/action.ts index 9dbbdfd8ecb69..86b5a55a3ec92 100644 --- a/packages/@aws-cdk/aws-codepipeline/lib/action.ts +++ b/packages/@aws-cdk/aws-codepipeline/lib/action.ts @@ -83,14 +83,14 @@ export interface IPipeline extends cdk.IConstruct, events.IEventRuleTarget { * * @param identity the IAM Identity to grant the permissions to */ - grantBucketRead(identity?: iam.IPrincipal): iam.Grant; + grantBucketRead(identity: iam.IPrincipal): iam.Grant; /** * Grants read & write permissions to the Pipeline's S3 Bucket to the given Identity. * * @param identity the IAM Identity to grant the permissions to */ - grantBucketReadWrite(identity?: iam.IPrincipal): iam.Grant; + grantBucketReadWrite(identity: iam.IPrincipal): iam.Grant; } /** diff --git a/packages/@aws-cdk/aws-codepipeline/lib/pipeline.ts b/packages/@aws-cdk/aws-codepipeline/lib/pipeline.ts index ecb5a0eed3c5d..b0cc8ebf4a377 100644 --- a/packages/@aws-cdk/aws-codepipeline/lib/pipeline.ts +++ b/packages/@aws-cdk/aws-codepipeline/lib/pipeline.ts @@ -293,11 +293,11 @@ export class Pipeline extends cdk.Construct implements IPipeline { return this.stages.length; } - public grantBucketRead(identity?: iam.IPrincipal): iam.Grant { + public grantBucketRead(identity: iam.IPrincipal): iam.Grant { return this.artifactBucket.grantRead(identity); } - public grantBucketReadWrite(identity?: iam.IPrincipal): iam.Grant { + public grantBucketReadWrite(identity: iam.IPrincipal): iam.Grant { return this.artifactBucket.grantReadWrite(identity); } diff --git a/packages/@aws-cdk/aws-dynamodb/lib/table.ts b/packages/@aws-cdk/aws-dynamodb/lib/table.ts index 8ec2c4e86bbbf..7272d83d0b66a 100644 --- a/packages/@aws-cdk/aws-dynamodb/lib/table.ts +++ b/packages/@aws-cdk/aws-dynamodb/lib/table.ts @@ -178,7 +178,7 @@ export class Table extends Construct { * Permits an IAM Principal to list all DynamoDB Streams. * @param principal The principal (no-op if undefined) */ - public static grantListStreams(principal?: iam.IPrincipal): iam.Grant { + public static grantListStreams(principal: iam.IPrincipal): iam.Grant { return iam.Grant.onPrincipal({ principal, actions: ['dynamodb:ListStreams'], @@ -407,7 +407,7 @@ export class Table extends Construct { * @param principal The principal (no-op if undefined) * @param actions The set of actions to allow (i.e. "dynamodb:PutItem", "dynamodb:GetItem", ...) */ - public grant(principal?: iam.IPrincipal, ...actions: string[]): iam.Grant { + public grant(principal: iam.IPrincipal, ...actions: string[]): iam.Grant { return iam.Grant.onPrincipal({ principal, actions, @@ -425,7 +425,7 @@ export class Table extends Construct { * @param principal The principal (no-op if undefined) * @param actions The set of actions to allow (i.e. "dynamodb:DescribeStream", "dynamodb:GetRecords", ...) */ - public grantStream(principal?: iam.IPrincipal, ...actions: string[]) { + public grantStream(principal: iam.IPrincipal, ...actions: string[]) { return iam.Grant.onPrincipal({ principal, actions, @@ -439,7 +439,7 @@ export class Table extends Construct { * BatchGetItem, GetRecords, GetShardIterator, Query, GetItem, Scan. * @param principal The principal to grant access to */ - public grantReadData(principal?: iam.IPrincipal) { + public grantReadData(principal: iam.IPrincipal) { return this.grant(principal, ...READ_DATA_ACTIONS); } @@ -449,7 +449,7 @@ export class Table extends Construct { * DescribeStream, GetRecords, GetShardIterator, ListStreams. * @param principal The principal to grant access to */ - public grantStreamRead(principal?: iam.IPrincipal) { + public grantStreamRead(principal: iam.IPrincipal) { return this.grantStream(principal, ...READ_STREAM_DATA_ACTIONS); } @@ -458,7 +458,7 @@ export class Table extends Construct { * BatchWriteItem, PutItem, UpdateItem, DeleteItem. * @param principal The principal to grant access to */ - public grantWriteData(principal?: iam.IPrincipal) { + public grantWriteData(principal: iam.IPrincipal) { return this.grant(principal, ...WRITE_DATA_ACTIONS); } @@ -468,7 +468,7 @@ export class Table extends Construct { * BatchWriteItem, PutItem, UpdateItem, DeleteItem * @param principal The principal to grant access to */ - public grantReadWriteData(principal?: iam.IPrincipal) { + public grantReadWriteData(principal: iam.IPrincipal) { return this.grant(principal, ...READ_DATA_ACTIONS, ...WRITE_DATA_ACTIONS); } @@ -476,7 +476,7 @@ export class Table extends Construct { * Permits all DynamoDB operations ("dynamodb:*") to an IAM principal. * @param principal The principal to grant access to */ - public grantFullAccess(principal?: iam.IPrincipal) { + public grantFullAccess(principal: iam.IPrincipal) { return this.grant(principal, 'dynamodb:*'); } diff --git a/packages/@aws-cdk/aws-ecr/lib/repository-ref.ts b/packages/@aws-cdk/aws-ecr/lib/repository-ref.ts index 8d7373e20b872..e5c5d550e5357 100644 --- a/packages/@aws-cdk/aws-ecr/lib/repository-ref.ts +++ b/packages/@aws-cdk/aws-ecr/lib/repository-ref.ts @@ -41,17 +41,17 @@ export interface IRepository extends cdk.IConstruct { /** * Grant the given principal identity permissions to perform the actions on this repository */ - grant(identity?: iam.IPrincipal, ...actions: string[]): iam.Grant; + grant(identity: iam.IPrincipal, ...actions: string[]): iam.Grant; /** * Grant the given identity permissions to pull images in this repository. */ - grantPull(identity?: iam.IPrincipal): iam.Grant; + grantPull(identity: iam.IPrincipal): iam.Grant; /** * Grant the given identity permissions to pull and push images to this repository. */ - grantPullPush(identity?: iam.IPrincipal): iam.Grant; + grantPullPush(identity: iam.IPrincipal): iam.Grant; /** * Defines an AWS CloudWatch event rule that can trigger a target when an image is pushed to this @@ -189,7 +189,7 @@ export abstract class RepositoryBase extends cdk.Construct implements IRepositor /** * Grant the given principal identity permissions to perform the actions on this repository */ - public grant(principal?: iam.IPrincipal, ...actions: string[]) { + public grant(principal: iam.IPrincipal, ...actions: string[]) { return iam.Grant.withResource({ principal, actions, @@ -201,7 +201,7 @@ export abstract class RepositoryBase extends cdk.Construct implements IRepositor /** * Grant the given identity permissions to use the images in this repository */ - public grantPull(principal?: iam.IPrincipal) { + public grantPull(principal: iam.IPrincipal) { const ret = this.grant(principal, "ecr:BatchCheckLayerAvailability", "ecr:GetDownloadUrlForLayer", "ecr:BatchGetImage"); iam.Grant.onPrincipal({ @@ -217,7 +217,7 @@ export abstract class RepositoryBase extends cdk.Construct implements IRepositor /** * Grant the given identity permissions to pull and push images to this repository. */ - public grantPullPush(identity?: iam.IPrincipal) { + public grantPullPush(identity: iam.IPrincipal) { this.grantPull(identity); return this.grant(identity, "ecr:PutImage", diff --git a/packages/@aws-cdk/aws-iam/lib/grant.ts b/packages/@aws-cdk/aws-iam/lib/grant.ts index a7a83f0fd402b..3ca916d2f9182 100644 --- a/packages/@aws-cdk/aws-iam/lib/grant.ts +++ b/packages/@aws-cdk/aws-iam/lib/grant.ts @@ -11,7 +11,7 @@ export interface CommonGrantOptions { * * @default if principal is undefined, no work is done. */ - readonly principal?: IPrincipal; + readonly principal: IPrincipal; /** * The actions to grant @@ -123,14 +123,6 @@ export class Grant { * the permissions to a present principal is not an error. */ public static onPrincipal(options: GrantOnPrincipalOptions): Grant { - if (!options.principal) { - if (options.scope) { - // tslint:disable-next-line:max-line-length - options.scope.node.addWarning(`Could not add grant '${options.actions}' on '${options.resourceArns}' because the principal was not available. Add the permissions by hand.`); - } - return new Grant({ principalMissing: true, options }); - } - const statement = new PolicyStatement() .addActions(...options.actions) .addResources(...options.resourceArns); @@ -155,8 +147,6 @@ export class Grant { scope: options.resource, }); - if (result.principalMissing) { return result; } - const statement = new PolicyStatement() .addActions(...options.actions) .addResources(...(options.resourceSelfArns || options.resourceArns)) @@ -167,11 +157,6 @@ export class Grant { return new Grant({ principalStatement: statement, resourceStatement: result.resourceStatement, options }); } - /** - * There was no principal to add the permissions to - */ - public readonly principalMissing: boolean; - /** * The statement that was added to the principal's policy * @@ -196,7 +181,6 @@ export class Grant { private constructor(props: GrantProps) { this.options = props.options; - this.principalMissing = !!props.principalMissing; this.principalStatement = props.principalStatement; this.resourceStatement = props.resourceStatement; } @@ -205,7 +189,7 @@ export class Grant { * Whether the grant operation was successful */ public get success(): boolean { - return this.principalMissing || this.principalStatement !== undefined || this.resourceStatement !== undefined; + return this.principalStatement !== undefined || this.resourceStatement !== undefined; } /** @@ -225,7 +209,6 @@ function describeGrant(options: CommonGrantOptions) { interface GrantProps { readonly options: CommonGrantOptions; - readonly principalMissing?: boolean; readonly principalStatement?: PolicyStatement; readonly resourceStatement?: PolicyStatement; } diff --git a/packages/@aws-cdk/aws-iam/lib/lazy-role.ts b/packages/@aws-cdk/aws-iam/lib/lazy-role.ts index 850a44542cffb..81d9f0e271018 100644 --- a/packages/@aws-cdk/aws-iam/lib/lazy-role.ts +++ b/packages/@aws-cdk/aws-iam/lib/lazy-role.ts @@ -89,14 +89,14 @@ export class LazyRole extends cdk.Construct implements IRole { /** * Grant the actions defined in actions to the identity Principal on this resource. */ - public grant(identity?: IPrincipal, ...actions: string[]): Grant { + public grant(identity: IPrincipal, ...actions: string[]): Grant { return this.instantiate().grant(identity, ...actions); } /** * Grant permissions to the given principal to pass this role. */ - public grantPassRole(identity?: IPrincipal): Grant { + public grantPassRole(identity: IPrincipal): Grant { return this.instantiate().grantPassRole(identity); } diff --git a/packages/@aws-cdk/aws-iam/lib/role.ts b/packages/@aws-cdk/aws-iam/lib/role.ts index 74f9481210ee3..85a3eb697fe6a 100644 --- a/packages/@aws-cdk/aws-iam/lib/role.ts +++ b/packages/@aws-cdk/aws-iam/lib/role.ts @@ -209,7 +209,7 @@ export class Role extends Construct implements IRole { /** * Grant the actions defined in actions to the identity Principal on this resource. */ - public grant(principal?: IPrincipal, ...actions: string[]) { + public grant(principal: IPrincipal, ...actions: string[]) { return Grant.onPrincipal({ principal, actions, @@ -221,7 +221,7 @@ export class Role extends Construct implements IRole { /** * Grant permissions to the given principal to pass this role. */ - public grantPassRole(identity?: IPrincipal) { + public grantPassRole(identity: IPrincipal) { return this.grant(identity, 'iam:PassRole'); } } @@ -254,12 +254,12 @@ export interface IRole extends IIdentity { /** * Grant the actions defined in actions to the identity Principal on this resource. */ - grant(identity?: IPrincipal, ...actions: string[]): Grant; + grant(identity: IPrincipal, ...actions: string[]): Grant; /** * Grant permissions to the given principal to pass this role. */ - grantPassRole(identity?: IPrincipal): Grant; + grantPassRole(identity: IPrincipal): Grant; } function createAssumeRolePolicy(principal: IPrincipal, externalId?: string) { @@ -352,7 +352,7 @@ class ImportedRole extends Construct implements IRole { /** * Grant the actions defined in actions to the identity Principal on this resource. */ - public grant(principal?: IPrincipal, ...actions: string[]): Grant { + public grant(principal: IPrincipal, ...actions: string[]): Grant { return Grant.onPrincipal({ principal, actions, @@ -364,7 +364,7 @@ class ImportedRole extends Construct implements IRole { /** * Grant permissions to the given principal to pass this role. */ - public grantPassRole(identity?: IPrincipal): Grant { + public grantPassRole(identity: IPrincipal): Grant { return this.grant(identity, 'iam:PassRole'); } } diff --git a/packages/@aws-cdk/aws-kinesis/lib/stream.ts b/packages/@aws-cdk/aws-kinesis/lib/stream.ts index ca7a1815ec54d..d21e457d362e8 100644 --- a/packages/@aws-cdk/aws-kinesis/lib/stream.ts +++ b/packages/@aws-cdk/aws-kinesis/lib/stream.ts @@ -32,7 +32,7 @@ export interface IStream extends cdk.IConstruct, logs.ILogSubscriptionDestinatio * If an encryption key is used, permission to ues the key to decrypt the * contents of the stream will also be granted. */ - grantRead(identity?: iam.IPrincipal): iam.Grant; + grantRead(identity: iam.IPrincipal): iam.Grant; /** * Grant write permissions for this stream and its contents to an IAM @@ -41,7 +41,7 @@ export interface IStream extends cdk.IConstruct, logs.ILogSubscriptionDestinatio * If an encryption key is used, permission to ues the key to encrypt the * contents of the stream will also be granted. */ - grantWrite(identity?: iam.IPrincipal): iam.Grant; + grantWrite(identity: iam.IPrincipal): iam.Grant; /** * Grants read/write permissions for this stream and its contents to an IAM @@ -50,7 +50,7 @@ export interface IStream extends cdk.IConstruct, logs.ILogSubscriptionDestinatio * If an encryption key is used, permission to use the key for * encrypt/decrypt will also be granted. */ - grantReadWrite(identity?: iam.IPrincipal): iam.Grant; + grantReadWrite(identity: iam.IPrincipal): iam.Grant; } /** @@ -117,7 +117,7 @@ export abstract class StreamBase extends cdk.Construct implements IStream { * If an encryption key is used, permission to ues the key to decrypt the * contents of the stream will also be granted. */ - public grantRead(principal?: iam.IPrincipal) { + public grantRead(principal: iam.IPrincipal) { const ret = this.grant(principal, 'kinesis:DescribeStream', 'kinesis:GetRecords', 'kinesis:GetShardIterator'); if (this.encryptionKey) { @@ -134,7 +134,7 @@ export abstract class StreamBase extends cdk.Construct implements IStream { * If an encryption key is used, permission to ues the key to decrypt the * contents of the stream will also be granted. */ - public grantWrite(principal?: iam.IPrincipal) { + public grantWrite(principal: iam.IPrincipal) { const ret = this.grant(principal, 'kinesis:DescribeStream', 'kinesis:PutRecord', 'kinesis:PutRecords'); if (this.encryptionKey) { @@ -151,7 +151,7 @@ export abstract class StreamBase extends cdk.Construct implements IStream { * If an encryption key is used, permission to use the key for * encrypt/decrypt will also be granted. */ - public grantReadWrite(principal?: iam.IPrincipal) { + public grantReadWrite(principal: iam.IPrincipal) { const ret = this.grant( principal, 'kinesis:DescribeStream', @@ -227,7 +227,7 @@ export abstract class StreamBase extends cdk.Construct implements IStream { return dest.logSubscriptionDestination(sourceLogGroup); } - private grant(principal?: iam.IPrincipal, ...actions: string[]) { + private grant(principal: iam.IPrincipal, ...actions: string[]) { return iam.Grant.onPrincipal({ principal, actions, diff --git a/packages/@aws-cdk/aws-kms/lib/key.ts b/packages/@aws-cdk/aws-kms/lib/key.ts index 5af5be2d3ada2..3053128bab6cc 100644 --- a/packages/@aws-cdk/aws-kms/lib/key.ts +++ b/packages/@aws-cdk/aws-kms/lib/key.ts @@ -33,22 +33,22 @@ export interface IEncryptionKey extends IConstruct { /** * Grant the indicated permissions on this key to the given principal */ - grant(principal: iam.IPrincipal | undefined, ...actions: string[]): iam.Grant; + grant(principal: iam.IPrincipal, ...actions: string[]): iam.Grant; /** * Grant decryption permisisons using this key to the given principal */ - grantDecrypt(principal: iam.IPrincipal | undefined): iam.Grant; + grantDecrypt(principal: iam.IPrincipal): iam.Grant; /** * Grant encryption permisisons using this key to the given principal */ - grantEncrypt(principal: iam.IPrincipal | undefined): iam.Grant; + grantEncrypt(principal: iam.IPrincipal): iam.Grant; /** * Grant encryption and decryption permisisons using this key to the given principal */ - grantEncryptDecrypt(principal: iam.IPrincipal | undefined): iam.Grant; + grantEncryptDecrypt(principal: iam.IPrincipal): iam.Grant; } export interface EncryptionKeyImportProps { @@ -104,7 +104,7 @@ export abstract class EncryptionKeyBase extends Construct implements IEncryption * since the default CloudFormation setup for KMS keys is that the policy * must not be empty and so default grants won't work. */ - public grant(principal: iam.IPrincipal | undefined, ...actions: string[]): iam.Grant { + public grant(principal: iam.IPrincipal, ...actions: string[]): iam.Grant { return iam.Grant.onPrincipalAndResource({ principal, actions, @@ -117,7 +117,7 @@ export abstract class EncryptionKeyBase extends Construct implements IEncryption /** * Grant decryption permisisons using this key to the given principal */ - public grantDecrypt(principal: iam.IPrincipal | undefined): iam.Grant { + public grantDecrypt(principal: iam.IPrincipal): iam.Grant { return this.grant(principal, 'kms:Decrypt', ); @@ -126,7 +126,7 @@ export abstract class EncryptionKeyBase extends Construct implements IEncryption /** * Grant encryption permisisons using this key to the given principal */ - public grantEncrypt(principal: iam.IPrincipal | undefined): iam.Grant { + public grantEncrypt(principal: iam.IPrincipal): iam.Grant { return this.grant(principal, 'kms:Encrypt', 'kms:ReEncrypt*', @@ -137,7 +137,7 @@ export abstract class EncryptionKeyBase extends Construct implements IEncryption /** * Grant encryption and decryption permisisons using this key to the given principal */ - public grantEncryptDecrypt(principal: iam.IPrincipal | undefined): iam.Grant { + public grantEncryptDecrypt(principal: iam.IPrincipal): iam.Grant { return this.grant(principal, 'kms:Decrypt', 'kms:Encrypt', diff --git a/packages/@aws-cdk/aws-lambda/lib/function-base.ts b/packages/@aws-cdk/aws-lambda/lib/function-base.ts index 32d6e2fe1855e..59de8d6c3bee4 100644 --- a/packages/@aws-cdk/aws-lambda/lib/function-base.ts +++ b/packages/@aws-cdk/aws-lambda/lib/function-base.ts @@ -31,7 +31,7 @@ export interface IFunction extends cdk.IConstruct, events.IEventRuleTarget, logs /** * The IAM role associated with this function. */ - readonly role?: iam.IRole; + readonly role: iam.IRole; /** * Whether or not this Lambda function was bound to a VPC @@ -51,7 +51,7 @@ export interface IFunction extends cdk.IConstruct, events.IEventRuleTarget, logs /** * Grant the given identity permissions to invoke this Lambda */ - grantInvoke(identity?: iam.IPrincipal): iam.Grant; + grantInvoke(identity: iam.IPrincipal): iam.Grant; /** * Return the given named metric for this Lambda @@ -129,7 +129,7 @@ export abstract class FunctionBase extends cdk.Construct implements IFunction { /** * The IAM role associated with this function. */ - public abstract readonly role?: iam.IRole; + public abstract readonly role: iam.IRole; /** * Whether the addPermission() call adds any permissions @@ -231,7 +231,7 @@ export abstract class FunctionBase extends cdk.Construct implements IFunction { /** * Grant the given identity permissions to invoke this Lambda */ - public grantInvoke(principal?: iam.IPrincipal): iam.Grant { + public grantInvoke(principal: iam.IPrincipal): iam.Grant { return iam.Grant.withResource({ principal, actions: ['lambda:InvokeFunction'], diff --git a/packages/@aws-cdk/aws-lambda/lib/function.ts b/packages/@aws-cdk/aws-lambda/lib/function.ts index 87ad0335cf238..06561634e0cdc 100644 --- a/packages/@aws-cdk/aws-lambda/lib/function.ts +++ b/packages/@aws-cdk/aws-lambda/lib/function.ts @@ -321,7 +321,7 @@ export class Function extends FunctionBase { /** * Execution role associated with this function */ - public readonly role?: iam.IRole; + public readonly role: iam.IRole; /** * The runtime configured for this lambda. @@ -602,7 +602,7 @@ export class Function extends FunctionBase { export class ImportedFunction extends FunctionBase { public readonly functionName: string; public readonly functionArn: string; - public readonly role?: iam.IRole; + public readonly role: iam.IRole; protected readonly canCreatePermissions = false; diff --git a/packages/@aws-cdk/aws-lambda/lib/singleton-lambda.ts b/packages/@aws-cdk/aws-lambda/lib/singleton-lambda.ts index 2860c3e2456d5..50a9f7762522c 100644 --- a/packages/@aws-cdk/aws-lambda/lib/singleton-lambda.ts +++ b/packages/@aws-cdk/aws-lambda/lib/singleton-lambda.ts @@ -37,7 +37,7 @@ export interface SingletonFunctionProps extends FunctionProps { export class SingletonFunction extends FunctionBase { public readonly functionName: string; public readonly functionArn: string; - public readonly role?: iam.IRole | undefined; + public readonly role: iam.IRole; protected readonly canCreatePermissions: boolean; private lambdaFunction: IFunction; diff --git a/packages/@aws-cdk/aws-logs/lib/log-group.ts b/packages/@aws-cdk/aws-logs/lib/log-group.ts index 47ac5af532241..2c4cd5ebd69e5 100644 --- a/packages/@aws-cdk/aws-logs/lib/log-group.ts +++ b/packages/@aws-cdk/aws-logs/lib/log-group.ts @@ -69,12 +69,12 @@ export interface ILogGroup extends cdk.IConstruct { /** * Give permissions to write to create and write to streams in this log group */ - grantWrite(principal?: iam.IPrincipal): iam.Grant; + grantWrite(principal: iam.IPrincipal): iam.Grant; /** * Give the indicated permissions on this log group and all streams */ - grant(principal?: iam.IPrincipal, ...actions: string[]): iam.Grant; + grant(principal: iam.IPrincipal, ...actions: string[]): iam.Grant; } /** @@ -171,14 +171,14 @@ export abstract class LogGroupBase extends cdk.Construct implements ILogGroup { /** * Give permissions to write to create and write to streams in this log group */ - public grantWrite(principal?: iam.IPrincipal) { + public grantWrite(principal: iam.IPrincipal) { return this.grant(principal, 'logs:CreateLogStream', 'logs:PutLogEvents'); } /** * Give the indicated permissions on this log group and all streams */ - public grant(principal?: iam.IPrincipal, ...actions: string[]) { + public grant(principal: iam.IPrincipal, ...actions: string[]) { return iam.Grant.onPrincipal({ principal, actions, diff --git a/packages/@aws-cdk/aws-s3/lib/bucket.ts b/packages/@aws-cdk/aws-s3/lib/bucket.ts index 926f5e9d2a9a4..bd5782e2eade0 100644 --- a/packages/@aws-cdk/aws-s3/lib/bucket.ts +++ b/packages/@aws-cdk/aws-s3/lib/bucket.ts @@ -91,7 +91,7 @@ export interface IBucket extends cdk.IConstruct { * @param identity The principal * @param objectsKeyPattern Restrict the permission to a certain key pattern (default '*') */ - grantRead(identity?: iam.IPrincipal, objectsKeyPattern?: any): iam.Grant; + grantRead(identity: iam.IPrincipal, objectsKeyPattern?: any): iam.Grant; /** * Grant write permissions to this bucket to an IAM principal. @@ -102,7 +102,7 @@ export interface IBucket extends cdk.IConstruct { * @param identity The principal * @param objectsKeyPattern Restrict the permission to a certain key pattern (default '*') */ - grantWrite(identity?: iam.IPrincipal, objectsKeyPattern?: any): iam.Grant; + grantWrite(identity: iam.IPrincipal, objectsKeyPattern?: any): iam.Grant; /** * Grants s3:PutObject* and s3:Abort* permissions for this bucket to an IAM principal. @@ -112,7 +112,7 @@ export interface IBucket extends cdk.IConstruct { * @param identity The principal * @param objectsKeyPattern Restrict the permission to a certain key pattern (default '*') */ - grantPut(identity?: iam.IPrincipal, objectsKeyPattern?: any): iam.Grant; + grantPut(identity: iam.IPrincipal, objectsKeyPattern?: any): iam.Grant; /** * Grants s3:DeleteObject* permission to an IAM pricipal for objects @@ -121,7 +121,7 @@ export interface IBucket extends cdk.IConstruct { * @param identity The principal * @param objectsKeyPattern Restrict the permission to a certain key pattern (default '*') */ - grantDelete(identity?: iam.IPrincipal, objectsKeyPattern?: any): iam.Grant; + grantDelete(identity: iam.IPrincipal, objectsKeyPattern?: any): iam.Grant; /** * Grants read/write permissions for this bucket and it's contents to an IAM @@ -133,7 +133,7 @@ export interface IBucket extends cdk.IConstruct { * @param identity The principal * @param objectsKeyPattern Restrict the permission to a certain key pattern (default '*') */ - grantReadWrite(identity?: iam.IPrincipal, objectsKeyPattern?: any): iam.Grant; + grantReadWrite(identity: iam.IPrincipal, objectsKeyPattern?: any): iam.Grant; /** * Allows unrestricted access to objects from this bucket. @@ -375,7 +375,7 @@ export abstract class BucketBase extends cdk.Construct implements IBucket { * @param identity The principal * @param objectsKeyPattern Restrict the permission to a certain key pattern (default '*') */ - public grantRead(identity?: iam.IPrincipal, objectsKeyPattern: any = '*') { + public grantRead(identity: iam.IPrincipal, objectsKeyPattern: any = '*') { return this.grant(identity, perms.BUCKET_READ_ACTIONS, perms.KEY_READ_ACTIONS, this.bucketArn, this.arnForObjects(objectsKeyPattern)); @@ -390,7 +390,7 @@ export abstract class BucketBase extends cdk.Construct implements IBucket { * @param identity The principal * @param objectsKeyPattern Restrict the permission to a certain key pattern (default '*') */ - public grantWrite(identity?: iam.IPrincipal, objectsKeyPattern: any = '*') { + public grantWrite(identity: iam.IPrincipal, objectsKeyPattern: any = '*') { return this.grant(identity, perms.BUCKET_WRITE_ACTIONS, perms.KEY_WRITE_ACTIONS, this.bucketArn, this.arnForObjects(objectsKeyPattern)); @@ -404,7 +404,7 @@ export abstract class BucketBase extends cdk.Construct implements IBucket { * @param identity The principal * @param objectsKeyPattern Restrict the permission to a certain key pattern (default '*') */ - public grantPut(identity?: iam.IPrincipal, objectsKeyPattern: any = '*') { + public grantPut(identity: iam.IPrincipal, objectsKeyPattern: any = '*') { return this.grant(identity, perms.BUCKET_PUT_ACTIONS, perms.KEY_WRITE_ACTIONS, this.arnForObjects(objectsKeyPattern)); } @@ -416,7 +416,7 @@ export abstract class BucketBase extends cdk.Construct implements IBucket { * @param identity The principal * @param objectsKeyPattern Restrict the permission to a certain key pattern (default '*') */ - public grantDelete(identity?: iam.IPrincipal, objectsKeyPattern: any = '*') { + public grantDelete(identity: iam.IPrincipal, objectsKeyPattern: any = '*') { return this.grant(identity, perms.BUCKET_DELETE_ACTIONS, [], this.arnForObjects(objectsKeyPattern)); } @@ -431,7 +431,7 @@ export abstract class BucketBase extends cdk.Construct implements IBucket { * @param identity The principal * @param objectsKeyPattern Restrict the permission to a certain key pattern (default '*') */ - public grantReadWrite(identity?: iam.IPrincipal, objectsKeyPattern: any = '*') { + public grantReadWrite(identity: iam.IPrincipal, objectsKeyPattern: any = '*') { const bucketActions = perms.BUCKET_READ_ACTIONS.concat(perms.BUCKET_WRITE_ACTIONS); const keyActions = perms.KEY_READ_ACTIONS.concat(perms.KEY_WRITE_ACTIONS); @@ -479,7 +479,7 @@ export abstract class BucketBase extends cdk.Construct implements IBucket { }); } - private grant(principal: iam.IPrincipal | undefined, + private grant(principal: iam.IPrincipal, bucketActions: string[], keyActions: string[], resourceArn: string, ...otherResourceArns: string[]) { diff --git a/packages/@aws-cdk/aws-secretsmanager/lib/secret.ts b/packages/@aws-cdk/aws-secretsmanager/lib/secret.ts index 3e34186b03c11..6fbd01f5c0d25 100644 --- a/packages/@aws-cdk/aws-secretsmanager/lib/secret.ts +++ b/packages/@aws-cdk/aws-secretsmanager/lib/secret.ts @@ -51,7 +51,7 @@ export interface ISecret extends cdk.IConstruct { * @param versionStages the version stages the grant is limited to. If not specified, no restriction on the version * stages is applied. */ - grantRead(principal?: iam.IPrincipal, versionStages?: string[]): iam.Grant; + grantRead(principal: iam.IPrincipal, versionStages?: string[]): iam.Grant; /** * Adds a rotation schedule to the secret. @@ -118,7 +118,7 @@ export abstract class SecretBase extends cdk.Construct implements ISecret { public abstract export(): SecretImportProps; - public grantRead(principal?: iam.IPrincipal, versionStages?: string[]): iam.Grant { + public grantRead(principal: iam.IPrincipal, versionStages?: string[]): iam.Grant { // @see https://docs.aws.amazon.com/fr_fr/secretsmanager/latest/userguide/auth-and-access_identity-based-policies.html const result = iam.Grant.onPrincipal({ diff --git a/packages/@aws-cdk/aws-sns/lib/topic-base.ts b/packages/@aws-cdk/aws-sns/lib/topic-base.ts index 9e27c65ab85ce..cd40c1607b15c 100644 --- a/packages/@aws-cdk/aws-sns/lib/topic-base.ts +++ b/packages/@aws-cdk/aws-sns/lib/topic-base.ts @@ -83,7 +83,7 @@ export interface ITopic extends /** * Grant topic publishing permissions to the given identity */ - grantPublish(identity?: iam.IPrincipal): iam.Grant; + grantPublish(identity: iam.IPrincipal): iam.Grant; } /** @@ -270,7 +270,7 @@ export abstract class TopicBase extends cdk.Construct implements ITopic { /** * Grant topic publishing permissions to the given identity */ - public grantPublish(principal?: iam.IPrincipal) { + public grantPublish(principal: iam.IPrincipal) { return iam.Grant.withResource({ principal, actions: ['sns:Publish'], diff --git a/packages/@aws-cdk/aws-sqs/lib/queue-base.ts b/packages/@aws-cdk/aws-sqs/lib/queue-base.ts index f446f6dbfa400..efb504c830fa7 100644 --- a/packages/@aws-cdk/aws-sqs/lib/queue-base.ts +++ b/packages/@aws-cdk/aws-sqs/lib/queue-base.ts @@ -55,7 +55,7 @@ export interface IQueue extends cdk.IConstruct, s3n.IBucketNotificationDestinati * * @param identity Principal to grant consume rights to */ - grantConsumeMessages(identity?: iam.IPrincipal): iam.Grant; + grantConsumeMessages(identity: iam.IPrincipal): iam.Grant; /** * Grant access to send messages to a queue to the given identity. @@ -69,7 +69,7 @@ export interface IQueue extends cdk.IConstruct, s3n.IBucketNotificationDestinati * * @param identity Principal to grant send rights to */ - grantSendMessages(identity?: iam.IPrincipal): iam.Grant; + grantSendMessages(identity: iam.IPrincipal): iam.Grant; /** * Grant an IAM principal permissions to purge all messages from the queue. @@ -83,7 +83,7 @@ export interface IQueue extends cdk.IConstruct, s3n.IBucketNotificationDestinati * @param identity Principal to grant send rights to * @param queueActions additional queue actions to allow */ - grantPurge(identity?: iam.IPrincipal): iam.Grant; + grantPurge(identity: iam.IPrincipal): iam.Grant; /** * Grant the actions defined in queueActions to the identity Principal given @@ -92,7 +92,7 @@ export interface IQueue extends cdk.IConstruct, s3n.IBucketNotificationDestinati * @param identity Principal to grant right to * @param queueActions The actions to grant */ - grant(identity?: iam.IPrincipal, ...queueActions: string[]): iam.Grant; + grant(identity: iam.IPrincipal, ...queueActions: string[]): iam.Grant; } /** @@ -216,7 +216,7 @@ export abstract class QueueBase extends cdk.Construct implements IQueue { * * @param identity Principal to grant consume rights to */ - public grantConsumeMessages(identity?: iam.IPrincipal) { + public grantConsumeMessages(identity: iam.IPrincipal) { return this.grant(identity, 'sqs:ReceiveMessage', 'sqs:ChangeMessageVisibility', @@ -239,7 +239,7 @@ export abstract class QueueBase extends cdk.Construct implements IQueue { * * @param identity Principal to grant send rights to */ - public grantSendMessages(identity?: iam.IPrincipal) { + public grantSendMessages(identity: iam.IPrincipal) { return this.grant(identity, 'sqs:SendMessage', 'sqs:SendMessageBatch', @@ -259,7 +259,7 @@ export abstract class QueueBase extends cdk.Construct implements IQueue { * @param identity Principal to grant send rights to * @param queueActions additional queue actions to allow */ - public grantPurge(identity?: iam.IPrincipal) { + public grantPurge(identity: iam.IPrincipal) { return this.grant(identity, 'sqs:PurgeQueue', 'sqs:GetQueueAttributes', @@ -273,7 +273,7 @@ export abstract class QueueBase extends cdk.Construct implements IQueue { * @param principal Principal to grant right to * @param actions The actions to grant */ - public grant(principal?: iam.IPrincipal, ...actions: string[]) { + public grant(principal: iam.IPrincipal, ...actions: string[]) { return iam.Grant.withResource({ principal, actions, diff --git a/packages/@aws-cdk/runtime-values/lib/rtv.ts b/packages/@aws-cdk/runtime-values/lib/rtv.ts index 12811be13a3f3..8feb9f71457a8 100644 --- a/packages/@aws-cdk/runtime-values/lib/rtv.ts +++ b/packages/@aws-cdk/runtime-values/lib/rtv.ts @@ -74,7 +74,7 @@ export class RuntimeValue extends cdk.Construct { * Grants a principal read permissions on this runtime value. * @param principal The principal (e.g. Role, User, Group) */ - public grantRead(principal?: iam.IPrincipal) { + public grantRead(principal: iam.IPrincipal) { // sometimes "role" is optional, so we want `rtv.grantRead(role)` to be a no-op if (!principal) { diff --git a/scripts/foreach.sh b/scripts/foreach.sh index 514064f4c633f..47072ad0b3edf 100755 --- a/scripts/foreach.sh +++ b/scripts/foreach.sh @@ -37,11 +37,18 @@ function success { printf "\e[32;5;81m$@\e[0m\n" } +if [[ "${1:-}" == "--reset" ]]; then + rm -f ~/.foreach.* + success "state cleared. you are free to start a new command." + exit 0 +fi + + if [ -f "${statefile}" ] && [ -f "${commandfile}" ]; then command="$(cat ${commandfile})" if [ ! -z "${command_arg}" ] && [ "${command}" != "${command_arg}" ]; then error "error: there is still an active session for: \"${command}\". to reset:" - error " rm -f ~/.foreach.*" + error " $0 --reset" exit 1 fi fi @@ -61,7 +68,7 @@ fi next="$(head -n1 ${statefile})" if [ -z "${next}" ]; then success "done (queue is empty). to reset:" - success " rm -f ~/.foreach.*" + success " $0 --reset" exit 0 fi From c2ca705786414e3339c50266e44f0a26e273c308 Mon Sep 17 00:00:00 2001 From: Rico Huijbers Date: Tue, 2 Apr 2019 15:50:31 +0200 Subject: [PATCH 24/31] Adding IGrantable (WIP) --- packages/@aws-cdk/aws-iam/lib/grant.ts | 12 ++--- .../aws-iam/lib/imported-resource-role.ts | 45 +++++++++++++++++++ packages/@aws-cdk/aws-iam/lib/index.ts | 1 + .../@aws-cdk/aws-iam/lib/policy-document.ts | 2 + packages/@aws-cdk/aws-iam/lib/principals.ts | 12 ++++- packages/@aws-cdk/aws-iam/lib/role.ts | 7 ++- .../@aws-cdk/aws-lambda/lib/function-base.ts | 2 +- packages/cdk/package.json | 1 + 8 files changed, 72 insertions(+), 10 deletions(-) create mode 100644 packages/@aws-cdk/aws-iam/lib/imported-resource-role.ts diff --git a/packages/@aws-cdk/aws-iam/lib/grant.ts b/packages/@aws-cdk/aws-iam/lib/grant.ts index 3ca916d2f9182..a71b1a40f8030 100644 --- a/packages/@aws-cdk/aws-iam/lib/grant.ts +++ b/packages/@aws-cdk/aws-iam/lib/grant.ts @@ -1,6 +1,6 @@ import cdk = require('@aws-cdk/cdk'); import { PolicyStatement } from "./policy-document"; -import { IPrincipal } from "./principals"; +import { IGrantable } from "./principals"; /** * Basic options for a grant operation @@ -11,7 +11,7 @@ export interface CommonGrantOptions { * * @default if principal is undefined, no work is done. */ - readonly principal: IPrincipal; + readonly grantee: IGrantable; /** * The actions to grant @@ -109,7 +109,7 @@ export class Grant { const statement = new PolicyStatement() .addActions(...options.actions) .addResources(...(options.resourceSelfArns || options.resourceArns)) - .addPrincipal(options.principal!); + .addPrincipal(options.grantee!.grantPrincipal); options.resource.addToResourcePolicy(statement); @@ -127,7 +127,7 @@ export class Grant { .addActions(...options.actions) .addResources(...options.resourceArns); - const addedToPrincipal = options.principal.addToPolicy(statement); + const addedToPrincipal = options.grantee.grantPrincipal.addToPolicy(statement); return new Grant({ principalStatement: addedToPrincipal ? statement : undefined, options }); } @@ -150,7 +150,7 @@ export class Grant { const statement = new PolicyStatement() .addActions(...options.actions) .addResources(...(options.resourceSelfArns || options.resourceArns)) - .addPrincipal(options.principal!); + .addPrincipal(options.grantee!.grantPrincipal); options.resource.addToResourcePolicy(statement); @@ -204,7 +204,7 @@ export class Grant { } function describeGrant(options: CommonGrantOptions) { - return `Permissions for '${options.principal}' to call '${options.actions}' on '${options.resourceArns}'`; + return `Permissions for '${options.grantee}' to call '${options.actions}' on '${options.resourceArns}'`; } interface GrantProps { diff --git a/packages/@aws-cdk/aws-iam/lib/imported-resource-role.ts b/packages/@aws-cdk/aws-iam/lib/imported-resource-role.ts new file mode 100644 index 0000000000000..48311c8786dbc --- /dev/null +++ b/packages/@aws-cdk/aws-iam/lib/imported-resource-role.ts @@ -0,0 +1,45 @@ +import cdk = require('@aws-cdk/cdk'); +import { PolicyStatement, PrincipalPolicyFragment } from './policy-document'; +import { IPrincipal } from './principals'; + +/** + * Properties for an ImportedResourcePrincipal + */ +export interface ImportedResourcePrincipalProps { + /** + * The resource the role proxy is for + */ + resource: cdk.IConstruct; +} + +/** + * A principal associated with an imported resource + * + * Some resources have roles associated with them which they assume, such as + * Lambda Functions, CodeBuild projects, StepFunctions machines, etc. + * + * When those resources are imported, their actual roles are not always + * imported with them. When that happens, we use an instance of this class + * instead, which will add user warnings when statements are attempted to be + * added to it. + */ +export class ImportedResourcePrincipal implements IPrincipal { + public readonly assumeRoleAction: string = 'sts:AssumeRole'; + public readonly grantPrincipal: IPrincipal; + private readonly resource: cdk.IConstruct; + + constructor(props: ImportedResourcePrincipalProps) { + this.resource = props.resource; + this.grantPrincipal = this; + } + + public get policyFragment(): PrincipalPolicyFragment { + throw new Error(`Cannot get policy fragment of ${this.resource.node.path}, resource imported without a role`); + } + + public addToPolicy(statement: PolicyStatement): boolean { + const repr = JSON.stringify(this.resource.node.resolve(statement)); + this.resource.node.addWarning(`Add statement to this resource's role: ${repr}`); + return true; // Pretend we did the work. The human will do it for us, eventually. + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-iam/lib/index.ts b/packages/@aws-cdk/aws-iam/lib/index.ts index 11526872d93e7..ff0597a7a61fb 100644 --- a/packages/@aws-cdk/aws-iam/lib/index.ts +++ b/packages/@aws-cdk/aws-iam/lib/index.ts @@ -8,6 +8,7 @@ export * from './lazy-role'; export * from './principals'; export * from './identity-base'; export * from './grant'; +export * from './imported-resource-role'; // AWS::IAM CloudFormation Resources: export * from './iam.generated'; diff --git a/packages/@aws-cdk/aws-iam/lib/policy-document.ts b/packages/@aws-cdk/aws-iam/lib/policy-document.ts index c5b2487e31e48..c8d229d03ad34 100644 --- a/packages/@aws-cdk/aws-iam/lib/policy-document.ts +++ b/packages/@aws-cdk/aws-iam/lib/policy-document.ts @@ -49,6 +49,8 @@ export class PolicyDocument extends cdk.Token { * Base class for policy principals */ export abstract class PrincipalBase implements IPrincipal { + public readonly grantPrincipal: IPrincipal = this; + /** * Return the policy fragment that identifies this principal in a Policy. */ diff --git a/packages/@aws-cdk/aws-iam/lib/principals.ts b/packages/@aws-cdk/aws-iam/lib/principals.ts index 11d59cfea7773..70bd154fc2e3c 100644 --- a/packages/@aws-cdk/aws-iam/lib/principals.ts +++ b/packages/@aws-cdk/aws-iam/lib/principals.ts @@ -1,5 +1,15 @@ import { PolicyStatement, PrincipalPolicyFragment } from './policy-document'; +/** + * Any object that has an associated principal that a permission can be granted to + */ +export interface IGrantable { + /** + * The principal to grant permissions to + */ + readonly grantPrincipal: IPrincipal; +} + /** * Represents a logical IAM principal. * @@ -17,7 +27,7 @@ import { PolicyStatement, PrincipalPolicyFragment } from './policy-document'; * For example, `new OrganizationPrincipal('o-1234')` represents all * identities that are part of the given AWS Organization. */ -export interface IPrincipal { +export interface IPrincipal extends IGrantable { /** * When this Principal is used in an AssumeRole policy, the action to use. */ diff --git a/packages/@aws-cdk/aws-iam/lib/role.ts b/packages/@aws-cdk/aws-iam/lib/role.ts index 85a3eb697fe6a..ccb36501515aa 100644 --- a/packages/@aws-cdk/aws-iam/lib/role.ts +++ b/packages/@aws-cdk/aws-iam/lib/role.ts @@ -101,6 +101,8 @@ export class Role extends Construct implements IRole { return new ImportedRole(scope, id, props); } + public readonly grantPrincipal: IPrincipal = this; + public readonly assumeRoleAction: string = 'sts:AssumeRole'; /** @@ -211,7 +213,7 @@ export class Role extends Construct implements IRole { */ public grant(principal: IPrincipal, ...actions: string[]) { return Grant.onPrincipal({ - principal, + grantee: principal, actions, resourceArns: [this.roleArn], scope: this @@ -308,6 +310,7 @@ export interface RoleImportProps { * A role that already exists */ class ImportedRole extends Construct implements IRole { + public readonly grantPrincipal: IPrincipal = this; public readonly assumeRoleAction: string = 'sts:AssumeRole'; public readonly policyFragment: PrincipalPolicyFragment; public readonly roleArn: string; @@ -354,7 +357,7 @@ class ImportedRole extends Construct implements IRole { */ public grant(principal: IPrincipal, ...actions: string[]): Grant { return Grant.onPrincipal({ - principal, + grantee: principal, actions, resourceArns: [this.roleArn], scope: this diff --git a/packages/@aws-cdk/aws-lambda/lib/function-base.ts b/packages/@aws-cdk/aws-lambda/lib/function-base.ts index 59de8d6c3bee4..11ed36e8c5169 100644 --- a/packages/@aws-cdk/aws-lambda/lib/function-base.ts +++ b/packages/@aws-cdk/aws-lambda/lib/function-base.ts @@ -11,7 +11,7 @@ import { CfnPermission } from './lambda.generated'; import { Permission } from './permission'; export interface IFunction extends cdk.IConstruct, events.IEventRuleTarget, logs.ILogSubscriptionDestination, - s3n.IBucketNotificationDestination, ec2.IConnectable, stepfunctions.IStepFunctionsTaskResource { + s3n.IBucketNotificationDestination, ec2.IConnectable, stepfunctions.IStepFunctionsTaskResource, iam.IGrantable { /** * Logical ID of this Function. diff --git a/packages/cdk/package.json b/packages/cdk/package.json index cf2567a8498e8..9877c45e71427 100644 --- a/packages/cdk/package.json +++ b/packages/cdk/package.json @@ -29,6 +29,7 @@ }, "homepage": "https://github.com/awslabs/aws-cdk", "scripts": { + "build": "echo Nothing to build", "package": "mkdir -p dist/js && cd dist/js && npm pack ../../" }, "engines": { From e53474b74cbf6fb1bbcc13542ad2ecde95fe6fcf Mon Sep 17 00:00:00 2001 From: Rico Huijbers Date: Tue, 2 Apr 2019 15:50:31 +0200 Subject: [PATCH 25/31] Adding IGrantable (WIP) --- design/aws-guidelines.md | 8 +- packages/@aws-cdk/assets/lib/asset.ts | 10 +- .../@aws-cdk/aws-cloudwatch/lib/metric.ts | 6 +- .../lib/lambda/deployment-group.ts | 16 +- .../lib/server/deployment-group.ts | 6 +- .../cloudformation/test.pipeline-actions.ts | 4 +- .../@aws-cdk/aws-codepipeline/lib/action.ts | 4 +- .../@aws-cdk/aws-codepipeline/lib/pipeline.ts | 4 +- packages/@aws-cdk/aws-dynamodb-global/.nycrc | 1 + .../lib/aws-dynamodb-global.d.ts | 98 + .../lib/aws-dynamodb-global.js | 32 + .../lib/dynamodb.generated.d.ts | 279 +++ .../lib/dynamodb.generated.js | 455 ++++ .../lib/dynamodb.generated.ts | 702 ++++++ .../aws-dynamodb-global/lib/index.d.ts | 3 + .../@aws-cdk/aws-dynamodb-global/lib/index.js | 9 + .../lib/lambda-global-dynamodb.d.ts | 23 + .../lib/lambda-global-dynamodb.js | 46 + .../lib/multi-dynamodb-stack.d.ts | 13 + .../lib/multi-dynamodb-stack.js | 15 + .../test/integ.dynamodb.global.d.ts | 1 + .../test/integ.dynamodb.global.js | 21 + .../test/test.dynamodb.global.d.ts | 7 + .../test/test.dynamodb.global.js | 36 + .../aws-dynamodb-global/tsconfig.json | 46 + packages/@aws-cdk/aws-dynamodb/lib/table.ts | 44 +- .../@aws-cdk/aws-ecr/lib/repository-ref.ts | 22 +- packages/@aws-cdk/aws-glue/lib/table.ts | 30 +- packages/@aws-cdk/aws-iam/lib/grant.ts | 12 +- packages/@aws-cdk/aws-iam/lib/group.ts | 2 + .../lib/imported-resource-principal.ts | 45 + packages/@aws-cdk/aws-iam/lib/index.ts | 1 + packages/@aws-cdk/aws-iam/lib/lazy-role.ts | 1 + .../@aws-cdk/aws-iam/lib/policy-document.ts | 2 + packages/@aws-cdk/aws-iam/lib/principals.ts | 12 +- packages/@aws-cdk/aws-iam/lib/role.ts | 15 +- packages/@aws-cdk/aws-iam/lib/user.ts | 2 + .../aws-iam/test/test.policy-document.ts | 1 + packages/@aws-cdk/aws-kinesis/lib/stream.ts | 28 +- packages/@aws-cdk/aws-kms/lib/key.ts | 24 +- .../@aws-cdk/aws-lambda/lib/function-base.ts | 24 +- packages/@aws-cdk/aws-lambda/lib/function.ts | 12 +- .../aws-lambda/lib/singleton-lambda.ts | 4 +- .../@aws-cdk/aws-lambda/package-lock.json | 2 +- packages/@aws-cdk/aws-logs/lib/log-group.ts | 12 +- packages/@aws-cdk/aws-s3/lib/bucket.ts | 28 +- .../@aws-cdk/aws-secretsmanager/lib/secret.ts | 10 +- .../lib/serverless.generated.ts | 2035 +++++++++++++++++ .../@aws-cdk/aws-serverless/package-lock.json | 2 +- packages/@aws-cdk/aws-sns/lib/topic-base.ts | 4 +- packages/@aws-cdk/aws-sqs/lib/queue-base.ts | 40 +- packages/@aws-cdk/aws-ssm/lib/parameter.ts | 8 +- packages/@aws-cdk/runtime-values/lib/rtv.ts | 2 +- .../main/java/com/myorg/HelloConstruct.java | 8 +- packages/cdk/package.json | 1 + tools/cdk-build-tools/package-lock.json | 2 +- 56 files changed, 4093 insertions(+), 187 deletions(-) create mode 120000 packages/@aws-cdk/aws-dynamodb-global/.nycrc create mode 100644 packages/@aws-cdk/aws-dynamodb-global/lib/aws-dynamodb-global.d.ts create mode 100644 packages/@aws-cdk/aws-dynamodb-global/lib/aws-dynamodb-global.js create mode 100644 packages/@aws-cdk/aws-dynamodb-global/lib/dynamodb.generated.d.ts create mode 100644 packages/@aws-cdk/aws-dynamodb-global/lib/dynamodb.generated.js create mode 100644 packages/@aws-cdk/aws-dynamodb-global/lib/dynamodb.generated.ts create mode 100644 packages/@aws-cdk/aws-dynamodb-global/lib/index.d.ts create mode 100644 packages/@aws-cdk/aws-dynamodb-global/lib/index.js create mode 100644 packages/@aws-cdk/aws-dynamodb-global/lib/lambda-global-dynamodb.d.ts create mode 100644 packages/@aws-cdk/aws-dynamodb-global/lib/lambda-global-dynamodb.js create mode 100644 packages/@aws-cdk/aws-dynamodb-global/lib/multi-dynamodb-stack.d.ts create mode 100644 packages/@aws-cdk/aws-dynamodb-global/lib/multi-dynamodb-stack.js create mode 100644 packages/@aws-cdk/aws-dynamodb-global/test/integ.dynamodb.global.d.ts create mode 100644 packages/@aws-cdk/aws-dynamodb-global/test/integ.dynamodb.global.js create mode 100644 packages/@aws-cdk/aws-dynamodb-global/test/test.dynamodb.global.d.ts create mode 100644 packages/@aws-cdk/aws-dynamodb-global/test/test.dynamodb.global.js create mode 100644 packages/@aws-cdk/aws-dynamodb-global/tsconfig.json create mode 100644 packages/@aws-cdk/aws-iam/lib/imported-resource-principal.ts create mode 100644 packages/@aws-cdk/aws-serverless/lib/serverless.generated.ts diff --git a/design/aws-guidelines.md b/design/aws-guidelines.md index dfb1a27ee8458..c634976f4ad0e 100644 --- a/design/aws-guidelines.md +++ b/design/aws-guidelines.md @@ -326,9 +326,9 @@ export interface IFoo extends cdk.IConstruct, ISomething { readonly connections: ec2.Connections; // permission grants (adds statements to the principal's policy) - grant(principal?: iam.IPrincipal, ...actions: string[]): void; - grantFoo(principal?: iam.IPrincipal): void; - grantBar(principal?: iam.IPrincipal): void; + grant(grantee?: iam.IGrantable, ...actions: string[]): void; + grantFoo(grantee?: iam.IGrantable): void; + grantBar(grantee?: iam.IGrantable): void; // resource policy (if applicable) addToResourcePolicy(statement: iam.PolicyStatement): void; @@ -364,7 +364,7 @@ export abstract class FooBase extends cdk.Construct implements IFoo { public abstract export(): FooAttributes; // grants can usually be shared - public grantYyy(principal?: iam.IPrincipal) { + public grantYyy(grantee?: iam.IGrantable) { // ... } diff --git a/packages/@aws-cdk/assets/lib/asset.ts b/packages/@aws-cdk/assets/lib/asset.ts index 04787b93f93af..d985af72954b7 100644 --- a/packages/@aws-cdk/assets/lib/asset.ts +++ b/packages/@aws-cdk/assets/lib/asset.ts @@ -36,7 +36,7 @@ export interface GenericAssetProps { * A list of principals that should be able to read this asset from S3. * You can use `asset.grantRead(principal)` to grant read permissions later. */ - readonly readers?: iam.IPrincipal[]; + readonly readers?: iam.IGrantable[]; } /** @@ -171,12 +171,12 @@ export class Asset extends cdk.Construct { /** * Grants read permissions to the principal on the asset's S3 object. */ - public grantRead(principal: iam.IPrincipal) { + public grantRead(grantee: iam.IGrantable) { // We give permissions on all files with the same prefix. Presumably // different versions of the same file will have the same prefix // and we don't want to accidentally revoke permission on old versions // when deploying a new version. - this.bucket.grantRead(principal, `${this.s3Prefix}*`); + this.bucket.grantRead(grantee, `${this.s3Prefix}*`); } } @@ -190,7 +190,7 @@ export interface FileAssetProps { * A list of principals that should be able to read this file asset from S3. * You can use `asset.grantRead(principal)` to grant read permissions later. */ - readonly readers?: iam.IPrincipal[]; + readonly readers?: iam.IGrantable[]; } /** @@ -212,7 +212,7 @@ export interface ZipDirectoryAssetProps { * A list of principals that should be able to read this ZIP file from S3. * You can use `asset.grantRead(principal)` to grant read permissions later. */ - readonly readers?: iam.IPrincipal[]; + readonly readers?: iam.IGrantable[]; } /** diff --git a/packages/@aws-cdk/aws-cloudwatch/lib/metric.ts b/packages/@aws-cdk/aws-cloudwatch/lib/metric.ts index 11626f7af389b..75c2160e1fa5a 100644 --- a/packages/@aws-cdk/aws-cloudwatch/lib/metric.ts +++ b/packages/@aws-cdk/aws-cloudwatch/lib/metric.ts @@ -85,11 +85,11 @@ export class Metric { /** * Grant permissions to the given identity to write metrics. * - * @param principal The IAM identity to give permissions to. + * @param grantee The IAM identity to give permissions to. */ - public static grantPutMetricData(principal: iam.IPrincipal): iam.Grant { + public static grantPutMetricData(grantee: iam.IGrantable): iam.Grant { return iam.Grant.onPrincipal({ - principal, + grantee, actions: ['cloudwatch:PutMetricData'], resourceArns: ['*'] }); diff --git a/packages/@aws-cdk/aws-codedeploy/lib/lambda/deployment-group.ts b/packages/@aws-cdk/aws-codedeploy/lib/lambda/deployment-group.ts index 2eeaa41c3ce15..5f5f2e7295042 100644 --- a/packages/@aws-cdk/aws-codedeploy/lib/lambda/deployment-group.ts +++ b/packages/@aws-cdk/aws-codedeploy/lib/lambda/deployment-group.ts @@ -194,7 +194,7 @@ export class LambdaDeploymentGroup extends cdk.Construct implements ILambdaDeplo throw new Error('A pre-hook function is already defined for this deployment group'); } this.preHook = preHook; - this.grantPutLifecycleEventHookExecutionStatus(this.preHook.role); + this.grantPutLifecycleEventHookExecutionStatus(this.preHook); this.preHook.grantInvoke(this.role); } @@ -208,7 +208,7 @@ export class LambdaDeploymentGroup extends cdk.Construct implements ILambdaDeplo throw new Error('A post-hook function is already defined for this deployment group'); } this.postHook = postHook; - this.grantPutLifecycleEventHookExecutionStatus(this.postHook.role); + this.grantPutLifecycleEventHookExecutionStatus(this.postHook); this.postHook.grantInvoke(this.role); } @@ -217,12 +217,12 @@ export class LambdaDeploymentGroup extends cdk.Construct implements ILambdaDeplo * on this deployment group resource. * @param principal to grant permission to */ - public grantPutLifecycleEventHookExecutionStatus(principal?: iam.IPrincipal): void { - if (principal) { - principal.addToPolicy(new iam.PolicyStatement() - .addResource(this.deploymentGroupArn) - .addAction('codedeploy:PutLifecycleEventHookExecutionStatus')); - } + public grantPutLifecycleEventHookExecutionStatus(grantee: iam.IGrantable): iam.Grant { + return iam.Grant.onPrincipal({ + grantee, + resourceArns: [this.deploymentGroupArn], + actions: ['codedeploy:PutLifecycleEventHookExecutionStatus'], + }); } public export(): LambdaDeploymentGroupImportProps { diff --git a/packages/@aws-cdk/aws-codedeploy/lib/server/deployment-group.ts b/packages/@aws-cdk/aws-codedeploy/lib/server/deployment-group.ts index abd12e1428471..0b0200220aba2 100644 --- a/packages/@aws-cdk/aws-codedeploy/lib/server/deployment-group.ts +++ b/packages/@aws-cdk/aws-codedeploy/lib/server/deployment-group.ts @@ -13,7 +13,7 @@ import { IServerDeploymentConfig, ServerDeploymentConfig } from './deployment-co export interface IServerDeploymentGroup extends cdk.IConstruct { readonly application: IServerApplication; - readonly role: iam.Role; + readonly role?: iam.Role; readonly deploymentGroupName: string; readonly deploymentGroupArn: string; readonly deploymentConfig: IServerDeploymentConfig; @@ -60,7 +60,7 @@ export interface ServerDeploymentGroupImportProps { */ export abstract class ServerDeploymentGroupBase extends cdk.Construct implements IServerDeploymentGroup { public abstract readonly application: IServerApplication; - public abstract readonly role: iam.Role; + public abstract readonly role?: iam.Role; public abstract readonly deploymentGroupName: string; public abstract readonly deploymentGroupArn: string; public readonly deploymentConfig: IServerDeploymentConfig; @@ -76,7 +76,7 @@ export abstract class ServerDeploymentGroupBase extends cdk.Construct implements class ImportedServerDeploymentGroup extends ServerDeploymentGroupBase { public readonly application: IServerApplication; - public readonly role: iam.Role = undefined; + public readonly role?: iam.Role = undefined; public readonly deploymentGroupName: string; public readonly deploymentGroupArn: string; public readonly autoScalingGroups?: autoscaling.AutoScalingGroup[] = undefined; diff --git a/packages/@aws-cdk/aws-codepipeline-actions/test/cloudformation/test.pipeline-actions.ts b/packages/@aws-cdk/aws-codepipeline-actions/test/cloudformation/test.pipeline-actions.ts index d7449e70d7c2e..1ce4c7d4f8fa0 100644 --- a/packages/@aws-cdk/aws-codepipeline-actions/test/cloudformation/test.pipeline-actions.ts +++ b/packages/@aws-cdk/aws-codepipeline-actions/test/cloudformation/test.pipeline-actions.ts @@ -317,11 +317,11 @@ class PipelineDouble extends cdk.Construct implements codepipeline.IPipeline { throw new Error('asEventRuleTarget() is unsupported in PipelineDouble'); } - public grantBucketRead(_identity?: iam.IPrincipal): iam.Grant { + public grantBucketRead(_identity?: iam.IGrantable): iam.Grant { throw new Error('grantBucketRead() is unsupported in PipelineDouble'); } - public grantBucketReadWrite(_identity?: iam.IPrincipal): iam.Grant { + public grantBucketReadWrite(_identity?: iam.IGrantable): iam.Grant { throw new Error('grantBucketReadWrite() is unsupported in PipelineDouble'); } } diff --git a/packages/@aws-cdk/aws-codepipeline/lib/action.ts b/packages/@aws-cdk/aws-codepipeline/lib/action.ts index 86b5a55a3ec92..476049a5fe810 100644 --- a/packages/@aws-cdk/aws-codepipeline/lib/action.ts +++ b/packages/@aws-cdk/aws-codepipeline/lib/action.ts @@ -83,14 +83,14 @@ export interface IPipeline extends cdk.IConstruct, events.IEventRuleTarget { * * @param identity the IAM Identity to grant the permissions to */ - grantBucketRead(identity: iam.IPrincipal): iam.Grant; + grantBucketRead(identity: iam.IGrantable): iam.Grant; /** * Grants read & write permissions to the Pipeline's S3 Bucket to the given Identity. * * @param identity the IAM Identity to grant the permissions to */ - grantBucketReadWrite(identity: iam.IPrincipal): iam.Grant; + grantBucketReadWrite(identity: iam.IGrantable): iam.Grant; } /** diff --git a/packages/@aws-cdk/aws-codepipeline/lib/pipeline.ts b/packages/@aws-cdk/aws-codepipeline/lib/pipeline.ts index b0cc8ebf4a377..f17e421fc34e3 100644 --- a/packages/@aws-cdk/aws-codepipeline/lib/pipeline.ts +++ b/packages/@aws-cdk/aws-codepipeline/lib/pipeline.ts @@ -293,11 +293,11 @@ export class Pipeline extends cdk.Construct implements IPipeline { return this.stages.length; } - public grantBucketRead(identity: iam.IPrincipal): iam.Grant { + public grantBucketRead(identity: iam.IGrantable): iam.Grant { return this.artifactBucket.grantRead(identity); } - public grantBucketReadWrite(identity: iam.IPrincipal): iam.Grant { + public grantBucketReadWrite(identity: iam.IGrantable): iam.Grant { return this.artifactBucket.grantReadWrite(identity); } diff --git a/packages/@aws-cdk/aws-dynamodb-global/.nycrc b/packages/@aws-cdk/aws-dynamodb-global/.nycrc new file mode 120000 index 0000000000000..7a2684a2c4ebc --- /dev/null +++ b/packages/@aws-cdk/aws-dynamodb-global/.nycrc @@ -0,0 +1 @@ +/Users/huijbers/Workspaces/PublicCDK/aws-cdk/tools/cdk-build-tools/config/nycrc \ No newline at end of file diff --git a/packages/@aws-cdk/aws-dynamodb-global/lib/aws-dynamodb-global.d.ts b/packages/@aws-cdk/aws-dynamodb-global/lib/aws-dynamodb-global.d.ts new file mode 100644 index 0000000000000..43981bd156e3d --- /dev/null +++ b/packages/@aws-cdk/aws-dynamodb-global/lib/aws-dynamodb-global.d.ts @@ -0,0 +1,98 @@ +import dynamodb = require("@aws-cdk/aws-dynamodb"); +import cdk = require("@aws-cdk/cdk"); +import { LambdaGlobalDynamoDBMaker } from "./lambda-global-dynamodb"; +import { MultiDynamoDBStack } from "./multi-dynamodb-stack"; +/** + * NOTE: These props should match dynamodb.TableProps exactly + * EXCEPT for tableName is now required (for global tables to work, the + * table name must match across regions) + */ +export interface GlobalDynamoDBProps { + /** + * Partition key attribute definition. + */ + partitionKey: dynamodb.Attribute; + /** + * Table sort key attribute definition. + * + * @default no sort key + */ + sortKey?: dynamodb.Attribute; + /** + * The read capacity for the table. Careful if you add Global Secondary Indexes, as + * those will share the table's provisioned throughput. + * + * Can only be provided if billingMode is Provisioned. + * + * @default 5 + */ + readCapacity?: number; + /** + * The write capacity for the table. Careful if you add Global Secondary Indexes, as + * those will share the table's provisioned throughput. + * + * Can only be provided if billingMode is Provisioned. + * + * @default 5 + */ + writeCapacity?: number; + /** + * Specify how you are charged for read and write throughput and how you manage capacity. + * @default Provisioned + */ + billingMode?: dynamodb.BillingMode; + /** + * Enforces a particular physical table name. + * @default + */ + tableName: string; + /** + * Whether point-in-time recovery is enabled. + * @default undefined, point-in-time recovery is disabled + */ + pitrEnabled?: boolean; + /** + * Whether server-side encryption with an AWS managed customer master key is enabled. + * @default undefined, server-side encryption is enabled with an AWS owned customer master key + */ + sseEnabled?: boolean; + /** + * When an item in the table is modified, StreamViewType determines what information + * is written to the stream for this table. Valid values for StreamViewType are: + * @default dynamodb.StreamViewType.NewAndOldImages, streams must be enabled + */ + streamSpecification?: dynamodb.StreamViewType; + /** + * The name of TTL attribute. + * @default undefined, TTL is disabled + */ + ttlAttributeName?: string; +} +/** + * Properties for the mutliple DynamoDB tables to mash together into a + * global table + */ +export interface DynamoDBGlobalStackProps extends cdk.StackProps { + /** + * Properties for DynamoDB Tables + * All the properties must be exactly the same + * to make the tables mesh together as a global table + */ + dynamoProps: GlobalDynamoDBProps; + /** + * Array of environments to create DynamoDB tables in + * Accounts should be omitted, or at least all identical + */ + regions: string[]; +} +export declare class GlobalTable extends cdk.Construct { + /** + * Creates dynamoDB tables across regions that will be able to be globbed together into a global table + */ + tables: MultiDynamoDBStack[]; + /** + * Creates the cloudformation custom resource that launches a lambda to tie it all together + */ + lambdaGlobalDynamodbMaker: LambdaGlobalDynamoDBMaker; + constructor(scope: cdk.Construct, id: string, props: DynamoDBGlobalStackProps); +} diff --git a/packages/@aws-cdk/aws-dynamodb-global/lib/aws-dynamodb-global.js b/packages/@aws-cdk/aws-dynamodb-global/lib/aws-dynamodb-global.js new file mode 100644 index 0000000000000..599ffc59a72c5 --- /dev/null +++ b/packages/@aws-cdk/aws-dynamodb-global/lib/aws-dynamodb-global.js @@ -0,0 +1,32 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const dynamodb = require("@aws-cdk/aws-dynamodb"); +const cdk = require("@aws-cdk/cdk"); +const lambda_global_dynamodb_1 = require("./lambda-global-dynamodb"); +const multi_dynamodb_stack_1 = require("./multi-dynamodb-stack"); +class GlobalTable extends cdk.Construct { + constructor(scope, id, props) { + super(scope, id); + this.tables = []; + // Need to set this streamSpecification here, otherwise global tables don't work + // And no way to set a default value in an interface + props.dynamoProps.streamSpecification = dynamodb.StreamViewType.NewAndOldImages; + for (const reg of props.regions) { + this.tables.push(new multi_dynamodb_stack_1.MultiDynamoDBStack(scope, id + "-GlobalDynamodbTable-" + reg, { + dynamoProps: props.dynamoProps, + // Purposefully omitting account since not possible to deploy global dynamodDB tables across accounts + env: { + region: reg + }, + // The DynamoDB Stack doesn't need to know the other environments involved + regions: [] + })); + } + this.lambdaGlobalDynamodbMaker = new lambda_global_dynamodb_1.LambdaGlobalDynamoDBMaker(scope, id + "-GlobalDynamodbCustomResource", props); + for (const table of this.tables) { + this.lambdaGlobalDynamodbMaker.customResource.node.addDependency(table); + } + } +} +exports.GlobalTable = GlobalTable; +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXdzLWR5bmFtb2RiLWdsb2JhbC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImF3cy1keW5hbW9kYi1nbG9iYWwudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFBQSxrREFBbUQ7QUFDbkQsb0NBQXFDO0FBQ3JDLHFFQUFxRTtBQUNyRSxpRUFBNEQ7QUF3RjVELE1BQWEsV0FBWSxTQUFRLEdBQUcsQ0FBQyxTQUFTO0lBWTFDLFlBQVksS0FBb0IsRUFBRSxFQUFVLEVBQUUsS0FBK0I7UUFDekUsS0FBSyxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsQ0FBQztRQUNqQixJQUFJLENBQUMsTUFBTSxHQUFHLEVBQUUsQ0FBQztRQUNqQixnRkFBZ0Y7UUFDaEYsb0RBQW9EO1FBQ3BELEtBQUssQ0FBQyxXQUFXLENBQUMsbUJBQW1CLEdBQUcsUUFBUSxDQUFDLGNBQWMsQ0FBQyxlQUFlLENBQUM7UUFDaEYsS0FBSyxNQUFNLEdBQUcsSUFBSSxLQUFLLENBQUMsT0FBTyxFQUFFO1lBQzdCLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLElBQUkseUNBQWtCLENBQUMsS0FBSyxFQUFFLEVBQUUsR0FBRyx1QkFBdUIsR0FBRyxHQUFHLEVBQUU7Z0JBQy9FLFdBQVcsRUFBRSxLQUFLLENBQUMsV0FBVztnQkFDOUIscUdBQXFHO2dCQUNyRyxHQUFHLEVBQUU7b0JBQ0QsTUFBTSxFQUFFLEdBQUc7aUJBQ2Q7Z0JBQ0QsMEVBQTBFO2dCQUMxRSxPQUFPLEVBQUUsRUFBRTthQUNkLENBQUMsQ0FBQyxDQUFDO1NBQ1A7UUFFRCxJQUFJLENBQUMseUJBQXlCLEdBQUcsSUFBSSxrREFBeUIsQ0FBQyxLQUFLLEVBQUUsRUFBRSxHQUFHLCtCQUErQixFQUFFLEtBQUssQ0FBQyxDQUFDO1FBQ25ILEtBQUssTUFBTSxLQUFLLElBQUksSUFBSSxDQUFDLE1BQU0sRUFBRTtZQUM3QixJQUFJLENBQUMseUJBQXlCLENBQUMsY0FBYyxDQUFDLElBQUksQ0FBQyxhQUFhLENBQUMsS0FBSyxDQUFDLENBQUM7U0FDM0U7SUFDTCxDQUFDO0NBQ0o7QUFuQ0Qsa0NBbUNDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IGR5bmFtb2RiID0gcmVxdWlyZShcIkBhd3MtY2RrL2F3cy1keW5hbW9kYlwiKTtcbmltcG9ydCBjZGsgPSByZXF1aXJlKFwiQGF3cy1jZGsvY2RrXCIpO1xuaW1wb3J0IHsgTGFtYmRhR2xvYmFsRHluYW1vREJNYWtlciB9IGZyb20gXCIuL2xhbWJkYS1nbG9iYWwtZHluYW1vZGJcIjtcbmltcG9ydCB7IE11bHRpRHluYW1vREJTdGFjayB9IGZyb20gXCIuL211bHRpLWR5bmFtb2RiLXN0YWNrXCI7XG5cbi8qKlxuICogTk9URTogVGhlc2UgcHJvcHMgc2hvdWxkIG1hdGNoIGR5bmFtb2RiLlRhYmxlUHJvcHMgZXhhY3RseVxuICogRVhDRVBUIGZvciB0YWJsZU5hbWUgaXMgbm93IHJlcXVpcmVkIChmb3IgZ2xvYmFsIHRhYmxlcyB0byB3b3JrLCB0aGVcbiAqIHRhYmxlIG5hbWUgbXVzdCBtYXRjaCBhY3Jvc3MgcmVnaW9ucylcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBHbG9iYWxEeW5hbW9EQlByb3BzIHtcbiAgICAvKipcbiAgICAgKiBQYXJ0aXRpb24ga2V5IGF0dHJpYnV0ZSBkZWZpbml0aW9uLlxuICAgICAqL1xuICAgIHBhcnRpdGlvbktleTogZHluYW1vZGIuQXR0cmlidXRlO1xuICAgIC8qKlxuICAgICAqIFRhYmxlIHNvcnQga2V5IGF0dHJpYnV0ZSBkZWZpbml0aW9uLlxuICAgICAqXG4gICAgICogQGRlZmF1bHQgbm8gc29ydCBrZXlcbiAgICAgKi9cbiAgICBzb3J0S2V5PzogZHluYW1vZGIuQXR0cmlidXRlO1xuICAgIC8qKlxuICAgICAqIFRoZSByZWFkIGNhcGFjaXR5IGZvciB0aGUgdGFibGUuIENhcmVmdWwgaWYgeW91IGFkZCBHbG9iYWwgU2Vjb25kYXJ5IEluZGV4ZXMsIGFzXG4gICAgICogdGhvc2Ugd2lsbCBzaGFyZSB0aGUgdGFibGUncyBwcm92aXNpb25lZCB0aHJvdWdocHV0LlxuICAgICAqXG4gICAgICogQ2FuIG9ubHkgYmUgcHJvdmlkZWQgaWYgYmlsbGluZ01vZGUgaXMgUHJvdmlzaW9uZWQuXG4gICAgICpcbiAgICAgKiBAZGVmYXVsdCA1XG4gICAgICovXG4gICAgcmVhZENhcGFjaXR5PzogbnVtYmVyO1xuICAgIC8qKlxuICAgICAqIFRoZSB3cml0ZSBjYXBhY2l0eSBmb3IgdGhlIHRhYmxlLiBDYXJlZnVsIGlmIHlvdSBhZGQgR2xvYmFsIFNlY29uZGFyeSBJbmRleGVzLCBhc1xuICAgICAqIHRob3NlIHdpbGwgc2hhcmUgdGhlIHRhYmxlJ3MgcHJvdmlzaW9uZWQgdGhyb3VnaHB1dC5cbiAgICAgKlxuICAgICAqIENhbiBvbmx5IGJlIHByb3ZpZGVkIGlmIGJpbGxpbmdNb2RlIGlzIFByb3Zpc2lvbmVkLlxuICAgICAqXG4gICAgICogQGRlZmF1bHQgNVxuICAgICAqL1xuICAgIHdyaXRlQ2FwYWNpdHk/OiBudW1iZXI7XG4gICAgLyoqXG4gICAgICogU3BlY2lmeSBob3cgeW91IGFyZSBjaGFyZ2VkIGZvciByZWFkIGFuZCB3cml0ZSB0aHJvdWdocHV0IGFuZCBob3cgeW91IG1hbmFnZSBjYXBhY2l0eS5cbiAgICAgKiBAZGVmYXVsdCBQcm92aXNpb25lZFxuICAgICAqL1xuICAgIGJpbGxpbmdNb2RlPzogZHluYW1vZGIuQmlsbGluZ01vZGU7XG4gICAgLyoqXG4gICAgICogRW5mb3JjZXMgYSBwYXJ0aWN1bGFyIHBoeXNpY2FsIHRhYmxlIG5hbWUuXG4gICAgICogQGRlZmF1bHQgPGdlbmVyYXRlZD5cbiAgICAgKi9cbiAgICB0YWJsZU5hbWU6IHN0cmluZztcbiAgICAvKipcbiAgICAgKiBXaGV0aGVyIHBvaW50LWluLXRpbWUgcmVjb3ZlcnkgaXMgZW5hYmxlZC5cbiAgICAgKiBAZGVmYXVsdCB1bmRlZmluZWQsIHBvaW50LWluLXRpbWUgcmVjb3ZlcnkgaXMgZGlzYWJsZWRcbiAgICAgKi9cbiAgICBwaXRyRW5hYmxlZD86IGJvb2xlYW47XG4gICAgLyoqXG4gICAgICogV2hldGhlciBzZXJ2ZXItc2lkZSBlbmNyeXB0aW9uIHdpdGggYW4gQVdTIG1hbmFnZWQgY3VzdG9tZXIgbWFzdGVyIGtleSBpcyBlbmFibGVkLlxuICAgICAqIEBkZWZhdWx0IHVuZGVmaW5lZCwgc2VydmVyLXNpZGUgZW5jcnlwdGlvbiBpcyBlbmFibGVkIHdpdGggYW4gQVdTIG93bmVkIGN1c3RvbWVyIG1hc3RlciBrZXlcbiAgICAgKi9cbiAgICBzc2VFbmFibGVkPzogYm9vbGVhbjtcbiAgICAvKipcbiAgICAgKiBXaGVuIGFuIGl0ZW0gaW4gdGhlIHRhYmxlIGlzIG1vZGlmaWVkLCBTdHJlYW1WaWV3VHlwZSBkZXRlcm1pbmVzIHdoYXQgaW5mb3JtYXRpb25cbiAgICAgKiBpcyB3cml0dGVuIHRvIHRoZSBzdHJlYW0gZm9yIHRoaXMgdGFibGUuIFZhbGlkIHZhbHVlcyBmb3IgU3RyZWFtVmlld1R5cGUgYXJlOlxuICAgICAqIEBkZWZhdWx0IGR5bmFtb2RiLlN0cmVhbVZpZXdUeXBlLk5ld0FuZE9sZEltYWdlcywgc3RyZWFtcyBtdXN0IGJlIGVuYWJsZWRcbiAgICAgKi9cbiAgICBzdHJlYW1TcGVjaWZpY2F0aW9uPzogZHluYW1vZGIuU3RyZWFtVmlld1R5cGU7XG4gICAgLyoqXG4gICAgICogVGhlIG5hbWUgb2YgVFRMIGF0dHJpYnV0ZS5cbiAgICAgKiBAZGVmYXVsdCB1bmRlZmluZWQsIFRUTCBpcyBkaXNhYmxlZFxuICAgICAqL1xuICAgIHR0bEF0dHJpYnV0ZU5hbWU/OiBzdHJpbmc7XG59XG5cbi8qKlxuICogUHJvcGVydGllcyBmb3IgdGhlIG11dGxpcGxlIER5bmFtb0RCIHRhYmxlcyB0byBtYXNoIHRvZ2V0aGVyIGludG8gYVxuICogZ2xvYmFsIHRhYmxlXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgRHluYW1vREJHbG9iYWxTdGFja1Byb3BzIGV4dGVuZHMgY2RrLlN0YWNrUHJvcHMge1xuICAgIC8qKlxuICAgICAqIFByb3BlcnRpZXMgZm9yIER5bmFtb0RCIFRhYmxlc1xuICAgICAqIEFsbCB0aGUgcHJvcGVydGllcyBtdXN0IGJlIGV4YWN0bHkgdGhlIHNhbWVcbiAgICAgKiB0byBtYWtlIHRoZSB0YWJsZXMgbWVzaCB0b2dldGhlciBhcyBhIGdsb2JhbCB0YWJsZVxuICAgICAqL1xuICAgIGR5bmFtb1Byb3BzOiBHbG9iYWxEeW5hbW9EQlByb3BzO1xuXG4gICAgLyoqXG4gICAgICogQXJyYXkgb2YgZW52aXJvbm1lbnRzIHRvIGNyZWF0ZSBEeW5hbW9EQiB0YWJsZXMgaW5cbiAgICAgKiBBY2NvdW50cyBzaG91bGQgYmUgb21pdHRlZCwgb3IgYXQgbGVhc3QgYWxsIGlkZW50aWNhbFxuICAgICAqL1xuICAgIHJlZ2lvbnM6IHN0cmluZ1tdO1xufVxuXG5leHBvcnQgY2xhc3MgR2xvYmFsVGFibGUgZXh0ZW5kcyBjZGsuQ29uc3RydWN0IHtcblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgZHluYW1vREIgdGFibGVzIGFjcm9zcyByZWdpb25zIHRoYXQgd2lsbCBiZSBhYmxlIHRvIGJlIGdsb2JiZWQgdG9nZXRoZXIgaW50byBhIGdsb2JhbCB0YWJsZVxuICAgICAqL1xuICAgIHB1YmxpYyB0YWJsZXM6IE11bHRpRHluYW1vREJTdGFja1tdO1xuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyB0aGUgY2xvdWRmb3JtYXRpb24gY3VzdG9tIHJlc291cmNlIHRoYXQgbGF1bmNoZXMgYSBsYW1iZGEgdG8gdGllIGl0IGFsbCB0b2dldGhlclxuICAgICAqL1xuICAgIHB1YmxpYyBsYW1iZGFHbG9iYWxEeW5hbW9kYk1ha2VyOiBMYW1iZGFHbG9iYWxEeW5hbW9EQk1ha2VyO1xuXG4gICAgY29uc3RydWN0b3Ioc2NvcGU6IGNkay5Db25zdHJ1Y3QsIGlkOiBzdHJpbmcsIHByb3BzOiBEeW5hbW9EQkdsb2JhbFN0YWNrUHJvcHMpIHtcbiAgICAgICAgc3VwZXIoc2NvcGUsIGlkKTtcbiAgICAgICAgdGhpcy50YWJsZXMgPSBbXTtcbiAgICAgICAgLy8gTmVlZCB0byBzZXQgdGhpcyBzdHJlYW1TcGVjaWZpY2F0aW9uIGhlcmUsIG90aGVyd2lzZSBnbG9iYWwgdGFibGVzIGRvbid0IHdvcmtcbiAgICAgICAgLy8gQW5kIG5vIHdheSB0byBzZXQgYSBkZWZhdWx0IHZhbHVlIGluIGFuIGludGVyZmFjZVxuICAgICAgICBwcm9wcy5keW5hbW9Qcm9wcy5zdHJlYW1TcGVjaWZpY2F0aW9uID0gZHluYW1vZGIuU3RyZWFtVmlld1R5cGUuTmV3QW5kT2xkSW1hZ2VzO1xuICAgICAgICBmb3IgKGNvbnN0IHJlZyBvZiBwcm9wcy5yZWdpb25zKSB7XG4gICAgICAgICAgICB0aGlzLnRhYmxlcy5wdXNoKG5ldyBNdWx0aUR5bmFtb0RCU3RhY2soc2NvcGUsIGlkICsgXCItR2xvYmFsRHluYW1vZGJUYWJsZS1cIiArIHJlZywge1xuICAgICAgICAgICAgICAgIGR5bmFtb1Byb3BzOiBwcm9wcy5keW5hbW9Qcm9wcyxcbiAgICAgICAgICAgICAgICAvLyBQdXJwb3NlZnVsbHkgb21pdHRpbmcgYWNjb3VudCBzaW5jZSBub3QgcG9zc2libGUgdG8gZGVwbG95IGdsb2JhbCBkeW5hbW9kREIgdGFibGVzIGFjcm9zcyBhY2NvdW50c1xuICAgICAgICAgICAgICAgIGVudjoge1xuICAgICAgICAgICAgICAgICAgICByZWdpb246IHJlZ1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgLy8gVGhlIER5bmFtb0RCIFN0YWNrIGRvZXNuJ3QgbmVlZCB0byBrbm93IHRoZSBvdGhlciBlbnZpcm9ubWVudHMgaW52b2x2ZWRcbiAgICAgICAgICAgICAgICByZWdpb25zOiBbXVxuICAgICAgICAgICAgfSkpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5sYW1iZGFHbG9iYWxEeW5hbW9kYk1ha2VyID0gbmV3IExhbWJkYUdsb2JhbER5bmFtb0RCTWFrZXIoc2NvcGUsIGlkICsgXCItR2xvYmFsRHluYW1vZGJDdXN0b21SZXNvdXJjZVwiLCBwcm9wcyk7XG4gICAgICAgIGZvciAoY29uc3QgdGFibGUgb2YgdGhpcy50YWJsZXMpIHtcbiAgICAgICAgICAgIHRoaXMubGFtYmRhR2xvYmFsRHluYW1vZGJNYWtlci5jdXN0b21SZXNvdXJjZS5ub2RlLmFkZERlcGVuZGVuY3kodGFibGUpO1xuICAgICAgICB9XG4gICAgfVxufVxuIl19 \ No newline at end of file diff --git a/packages/@aws-cdk/aws-dynamodb-global/lib/dynamodb.generated.d.ts b/packages/@aws-cdk/aws-dynamodb-global/lib/dynamodb.generated.d.ts new file mode 100644 index 0000000000000..e9609e9ffb869 --- /dev/null +++ b/packages/@aws-cdk/aws-dynamodb-global/lib/dynamodb.generated.d.ts @@ -0,0 +1,279 @@ +import cdk = require('@aws-cdk/cdk'); +/** + * Properties for defining a `AWS::DynamoDB::Table` + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-dynamodb-table.html + */ +export interface CfnTableProps { + /** + * `AWS::DynamoDB::Table.KeySchema` + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-dynamodb-table.html#cfn-dynamodb-table-keyschema + */ + keySchema: Array | cdk.Token; + /** + * `AWS::DynamoDB::Table.AttributeDefinitions` + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-dynamodb-table.html#cfn-dynamodb-table-attributedef + */ + attributeDefinitions?: Array | cdk.Token; + /** + * `AWS::DynamoDB::Table.BillingMode` + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-dynamodb-table.html#cfn-dynamodb-table-billingmode + */ + billingMode?: string; + /** + * `AWS::DynamoDB::Table.GlobalSecondaryIndexes` + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-dynamodb-table.html#cfn-dynamodb-table-gsi + */ + globalSecondaryIndexes?: Array | cdk.Token; + /** + * `AWS::DynamoDB::Table.LocalSecondaryIndexes` + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-dynamodb-table.html#cfn-dynamodb-table-lsi + */ + localSecondaryIndexes?: Array | cdk.Token; + /** + * `AWS::DynamoDB::Table.PointInTimeRecoverySpecification` + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-dynamodb-table.html#cfn-dynamodb-table-pointintimerecoveryspecification + */ + pointInTimeRecoverySpecification?: CfnTable.PointInTimeRecoverySpecificationProperty | cdk.Token; + /** + * `AWS::DynamoDB::Table.ProvisionedThroughput` + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-dynamodb-table.html#cfn-dynamodb-table-provisionedthroughput + */ + provisionedThroughput?: CfnTable.ProvisionedThroughputProperty | cdk.Token; + /** + * `AWS::DynamoDB::Table.SSESpecification` + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-dynamodb-table.html#cfn-dynamodb-table-ssespecification + */ + sseSpecification?: CfnTable.SSESpecificationProperty | cdk.Token; + /** + * `AWS::DynamoDB::Table.StreamSpecification` + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-dynamodb-table.html#cfn-dynamodb-table-streamspecification + */ + streamSpecification?: CfnTable.StreamSpecificationProperty | cdk.Token; + /** + * `AWS::DynamoDB::Table.TableName` + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-dynamodb-table.html#cfn-dynamodb-table-tablename + */ + tableName?: string; + /** + * `AWS::DynamoDB::Table.Tags` + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-dynamodb-table.html#cfn-dynamodb-table-tags + */ + tags?: cdk.CfnTag[]; + /** + * `AWS::DynamoDB::Table.TimeToLiveSpecification` + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-dynamodb-table.html#cfn-dynamodb-table-timetolivespecification + */ + timeToLiveSpecification?: CfnTable.TimeToLiveSpecificationProperty | cdk.Token; +} +/** + * A CloudFormation `AWS::DynamoDB::Table` + * + * @cloudformationResource AWS::DynamoDB::Table + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-dynamodb-table.html + */ +export declare class CfnTable extends cdk.CfnResource { + /** + * The CloudFormation resource type name for this resource class. + */ + static readonly resourceTypeName = "AWS::DynamoDB::Table"; + /** + * @cloudformationAttribute Arn + */ + readonly tableArn: string; + /** + * @cloudformationAttribute StreamArn + */ + readonly tableStreamArn: string; + readonly tableName: string; + /** + * The `TagManager` handles setting, removing and formatting tags + * + * Tags should be managed either passing them as properties during + * initiation or by calling methods on this object. If both techniques are + * used only the tags from the TagManager will be used. `Tag` (aspect) + * will use the manager. + */ + readonly tags: cdk.TagManager; + /** + * Create a new `AWS::DynamoDB::Table`. + * + * @param scope - scope in which this resource is defined + * @param id - scoped id of the resource + * @param props - resource properties + */ + constructor(scope: cdk.Construct, id: string, props: CfnTableProps); + readonly propertyOverrides: CfnTableProps; + protected renderProperties(properties: any): { + [key: string]: any; + }; +} +export declare namespace CfnTable { + /** + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-attributedef.html + */ + interface AttributeDefinitionProperty { + /** + * `CfnTable.AttributeDefinitionProperty.AttributeName` + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-attributedef.html#cfn-dynamodb-attributedef-attributename + */ + attributeName: string; + /** + * `CfnTable.AttributeDefinitionProperty.AttributeType` + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-attributedef.html#cfn-dynamodb-attributedef-attributename-attributetype + */ + attributeType: string; + } +} +export declare namespace CfnTable { + /** + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-gsi.html + */ + interface GlobalSecondaryIndexProperty { + /** + * `CfnTable.GlobalSecondaryIndexProperty.IndexName` + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-gsi.html#cfn-dynamodb-gsi-indexname + */ + indexName: string; + /** + * `CfnTable.GlobalSecondaryIndexProperty.KeySchema` + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-gsi.html#cfn-dynamodb-gsi-keyschema + */ + keySchema: Array | cdk.Token; + /** + * `CfnTable.GlobalSecondaryIndexProperty.Projection` + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-gsi.html#cfn-dynamodb-gsi-projection + */ + projection: CfnTable.ProjectionProperty | cdk.Token; + /** + * `CfnTable.GlobalSecondaryIndexProperty.ProvisionedThroughput` + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-gsi.html#cfn-dynamodb-gsi-provisionedthroughput + */ + provisionedThroughput?: CfnTable.ProvisionedThroughputProperty | cdk.Token; + } +} +export declare namespace CfnTable { + /** + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-keyschema.html + */ + interface KeySchemaProperty { + /** + * `CfnTable.KeySchemaProperty.AttributeName` + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-keyschema.html#aws-properties-dynamodb-keyschema-attributename + */ + attributeName: string; + /** + * `CfnTable.KeySchemaProperty.KeyType` + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-keyschema.html#aws-properties-dynamodb-keyschema-keytype + */ + keyType: string; + } +} +export declare namespace CfnTable { + /** + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-lsi.html + */ + interface LocalSecondaryIndexProperty { + /** + * `CfnTable.LocalSecondaryIndexProperty.IndexName` + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-lsi.html#cfn-dynamodb-lsi-indexname + */ + indexName: string; + /** + * `CfnTable.LocalSecondaryIndexProperty.KeySchema` + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-lsi.html#cfn-dynamodb-lsi-keyschema + */ + keySchema: Array | cdk.Token; + /** + * `CfnTable.LocalSecondaryIndexProperty.Projection` + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-lsi.html#cfn-dynamodb-lsi-projection + */ + projection: CfnTable.ProjectionProperty | cdk.Token; + } +} +export declare namespace CfnTable { + /** + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-table-pointintimerecoveryspecification.html + */ + interface PointInTimeRecoverySpecificationProperty { + /** + * `CfnTable.PointInTimeRecoverySpecificationProperty.PointInTimeRecoveryEnabled` + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-table-pointintimerecoveryspecification.html#cfn-dynamodb-table-pointintimerecoveryspecification-pointintimerecoveryenabled + */ + pointInTimeRecoveryEnabled?: boolean | cdk.Token; + } +} +export declare namespace CfnTable { + /** + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-projectionobject.html + */ + interface ProjectionProperty { + /** + * `CfnTable.ProjectionProperty.NonKeyAttributes` + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-projectionobject.html#cfn-dynamodb-projectionobj-nonkeyatt + */ + nonKeyAttributes?: string[]; + /** + * `CfnTable.ProjectionProperty.ProjectionType` + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-projectionobject.html#cfn-dynamodb-projectionobj-projtype + */ + projectionType?: string; + } +} +export declare namespace CfnTable { + /** + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-provisionedthroughput.html + */ + interface ProvisionedThroughputProperty { + /** + * `CfnTable.ProvisionedThroughputProperty.ReadCapacityUnits` + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-provisionedthroughput.html#cfn-dynamodb-provisionedthroughput-readcapacityunits + */ + readCapacityUnits: number | cdk.Token; + /** + * `CfnTable.ProvisionedThroughputProperty.WriteCapacityUnits` + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-provisionedthroughput.html#cfn-dynamodb-provisionedthroughput-writecapacityunits + */ + writeCapacityUnits: number | cdk.Token; + } +} +export declare namespace CfnTable { + /** + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-table-ssespecification.html + */ + interface SSESpecificationProperty { + /** + * `CfnTable.SSESpecificationProperty.SSEEnabled` + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-table-ssespecification.html#cfn-dynamodb-table-ssespecification-sseenabled + */ + sseEnabled: boolean | cdk.Token; + } +} +export declare namespace CfnTable { + /** + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-streamspecification.html + */ + interface StreamSpecificationProperty { + /** + * `CfnTable.StreamSpecificationProperty.StreamViewType` + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-streamspecification.html#cfn-dynamodb-streamspecification-streamviewtype + */ + streamViewType: string; + } +} +export declare namespace CfnTable { + /** + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-timetolivespecification.html + */ + interface TimeToLiveSpecificationProperty { + /** + * `CfnTable.TimeToLiveSpecificationProperty.AttributeName` + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-timetolivespecification.html#cfn-dynamodb-timetolivespecification-attributename + */ + attributeName: string; + /** + * `CfnTable.TimeToLiveSpecificationProperty.Enabled` + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-timetolivespecification.html#cfn-dynamodb-timetolivespecification-enabled + */ + enabled: boolean | cdk.Token; + } +} diff --git a/packages/@aws-cdk/aws-dynamodb-global/lib/dynamodb.generated.js b/packages/@aws-cdk/aws-dynamodb-global/lib/dynamodb.generated.js new file mode 100644 index 0000000000000..d4a6f7690506c --- /dev/null +++ b/packages/@aws-cdk/aws-dynamodb-global/lib/dynamodb.generated.js @@ -0,0 +1,455 @@ +"use strict"; +// Copyright 2012-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. +// Generated from the AWS CloudFormation Resource Specification +// See: docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/cfn-resource-specification.html +// @cfn2ts:meta@ {"generated":"2019-03-21T16:19:16.881Z","fingerprint":"CPTpE9eD4ImqOKDnu7P0Kaol8j+SXNQUILMR4l/fi2g="} +Object.defineProperty(exports, "__esModule", { value: true }); +// tslint:disable:max-line-length | This is generated code - line lengths are difficult to control +const cdk = require("@aws-cdk/cdk"); +/** + * Determine whether the given properties match those of a `CfnTableProps` + * + * @param properties - the TypeScript properties of a `CfnTableProps` + * + * @returns the result of the validation. + */ +function CfnTablePropsValidator(properties) { + if (!cdk.canInspect(properties)) { + return cdk.VALIDATION_SUCCESS; + } + const errors = new cdk.ValidationResults(); + errors.collect(cdk.propertyValidator('attributeDefinitions', cdk.listValidator(CfnTable_AttributeDefinitionPropertyValidator))(properties.attributeDefinitions)); + errors.collect(cdk.propertyValidator('billingMode', cdk.validateString)(properties.billingMode)); + errors.collect(cdk.propertyValidator('globalSecondaryIndexes', cdk.listValidator(CfnTable_GlobalSecondaryIndexPropertyValidator))(properties.globalSecondaryIndexes)); + errors.collect(cdk.propertyValidator('keySchema', cdk.requiredValidator)(properties.keySchema)); + errors.collect(cdk.propertyValidator('keySchema', cdk.listValidator(CfnTable_KeySchemaPropertyValidator))(properties.keySchema)); + errors.collect(cdk.propertyValidator('localSecondaryIndexes', cdk.listValidator(CfnTable_LocalSecondaryIndexPropertyValidator))(properties.localSecondaryIndexes)); + errors.collect(cdk.propertyValidator('pointInTimeRecoverySpecification', CfnTable_PointInTimeRecoverySpecificationPropertyValidator)(properties.pointInTimeRecoverySpecification)); + errors.collect(cdk.propertyValidator('provisionedThroughput', CfnTable_ProvisionedThroughputPropertyValidator)(properties.provisionedThroughput)); + errors.collect(cdk.propertyValidator('sseSpecification', CfnTable_SSESpecificationPropertyValidator)(properties.sseSpecification)); + errors.collect(cdk.propertyValidator('streamSpecification', CfnTable_StreamSpecificationPropertyValidator)(properties.streamSpecification)); + errors.collect(cdk.propertyValidator('tableName', cdk.validateString)(properties.tableName)); + errors.collect(cdk.propertyValidator('tags', cdk.listValidator(cdk.validateCfnTag))(properties.tags)); + errors.collect(cdk.propertyValidator('timeToLiveSpecification', CfnTable_TimeToLiveSpecificationPropertyValidator)(properties.timeToLiveSpecification)); + return errors.wrap('supplied properties not correct for "CfnTableProps"'); +} +/** + * Renders the AWS CloudFormation properties of an `AWS::DynamoDB::Table` resource + * + * @param properties - the TypeScript properties of a `CfnTableProps` + * + * @returns the AWS CloudFormation properties of an `AWS::DynamoDB::Table` resource. + */ +// @ts-ignore TS6133 +function cfnTablePropsToCloudFormation(properties) { + if (!cdk.canInspect(properties)) { + return properties; + } + CfnTablePropsValidator(properties).assertSuccess(); + return { + KeySchema: cdk.listMapper(cfnTableKeySchemaPropertyToCloudFormation)(properties.keySchema), + AttributeDefinitions: cdk.listMapper(cfnTableAttributeDefinitionPropertyToCloudFormation)(properties.attributeDefinitions), + BillingMode: cdk.stringToCloudFormation(properties.billingMode), + GlobalSecondaryIndexes: cdk.listMapper(cfnTableGlobalSecondaryIndexPropertyToCloudFormation)(properties.globalSecondaryIndexes), + LocalSecondaryIndexes: cdk.listMapper(cfnTableLocalSecondaryIndexPropertyToCloudFormation)(properties.localSecondaryIndexes), + PointInTimeRecoverySpecification: cfnTablePointInTimeRecoverySpecificationPropertyToCloudFormation(properties.pointInTimeRecoverySpecification), + ProvisionedThroughput: cfnTableProvisionedThroughputPropertyToCloudFormation(properties.provisionedThroughput), + SSESpecification: cfnTableSSESpecificationPropertyToCloudFormation(properties.sseSpecification), + StreamSpecification: cfnTableStreamSpecificationPropertyToCloudFormation(properties.streamSpecification), + TableName: cdk.stringToCloudFormation(properties.tableName), + Tags: cdk.listMapper(cdk.cfnTagToCloudFormation)(properties.tags), + TimeToLiveSpecification: cfnTableTimeToLiveSpecificationPropertyToCloudFormation(properties.timeToLiveSpecification), + }; +} +/** + * A CloudFormation `AWS::DynamoDB::Table` + * + * @cloudformationResource AWS::DynamoDB::Table + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-dynamodb-table.html + */ +class CfnTable extends cdk.CfnResource { + /** + * Create a new `AWS::DynamoDB::Table`. + * + * @param scope - scope in which this resource is defined + * @param id - scoped id of the resource + * @param props - resource properties + */ + constructor(scope, id, props) { + super(scope, id, { type: CfnTable.resourceTypeName, properties: props }); + cdk.requireProperty(props, 'keySchema', this); + this.tableArn = this.getAtt('Arn').toString(); + this.tableStreamArn = this.getAtt('StreamArn').toString(); + this.tableName = this.ref.toString(); + const tags = props === undefined ? undefined : props.tags; + this.tags = new cdk.TagManager(cdk.TagType.Standard, "AWS::DynamoDB::Table", tags); + } + get propertyOverrides() { + return this.untypedPropertyOverrides; + } + renderProperties(properties) { + return cfnTablePropsToCloudFormation(this.node.resolve(properties)); + } +} +/** + * The CloudFormation resource type name for this resource class. + */ +CfnTable.resourceTypeName = "AWS::DynamoDB::Table"; +exports.CfnTable = CfnTable; +/** + * Determine whether the given properties match those of a `AttributeDefinitionProperty` + * + * @param properties - the TypeScript properties of a `AttributeDefinitionProperty` + * + * @returns the result of the validation. + */ +function CfnTable_AttributeDefinitionPropertyValidator(properties) { + if (!cdk.canInspect(properties)) { + return cdk.VALIDATION_SUCCESS; + } + const errors = new cdk.ValidationResults(); + errors.collect(cdk.propertyValidator('attributeName', cdk.requiredValidator)(properties.attributeName)); + errors.collect(cdk.propertyValidator('attributeName', cdk.validateString)(properties.attributeName)); + errors.collect(cdk.propertyValidator('attributeType', cdk.requiredValidator)(properties.attributeType)); + errors.collect(cdk.propertyValidator('attributeType', cdk.validateString)(properties.attributeType)); + return errors.wrap('supplied properties not correct for "AttributeDefinitionProperty"'); +} +/** + * Renders the AWS CloudFormation properties of an `AWS::DynamoDB::Table.AttributeDefinition` resource + * + * @param properties - the TypeScript properties of a `AttributeDefinitionProperty` + * + * @returns the AWS CloudFormation properties of an `AWS::DynamoDB::Table.AttributeDefinition` resource. + */ +// @ts-ignore TS6133 +function cfnTableAttributeDefinitionPropertyToCloudFormation(properties) { + if (!cdk.canInspect(properties)) { + return properties; + } + CfnTable_AttributeDefinitionPropertyValidator(properties).assertSuccess(); + return { + AttributeName: cdk.stringToCloudFormation(properties.attributeName), + AttributeType: cdk.stringToCloudFormation(properties.attributeType), + }; +} +/** + * Determine whether the given properties match those of a `GlobalSecondaryIndexProperty` + * + * @param properties - the TypeScript properties of a `GlobalSecondaryIndexProperty` + * + * @returns the result of the validation. + */ +function CfnTable_GlobalSecondaryIndexPropertyValidator(properties) { + if (!cdk.canInspect(properties)) { + return cdk.VALIDATION_SUCCESS; + } + const errors = new cdk.ValidationResults(); + errors.collect(cdk.propertyValidator('indexName', cdk.requiredValidator)(properties.indexName)); + errors.collect(cdk.propertyValidator('indexName', cdk.validateString)(properties.indexName)); + errors.collect(cdk.propertyValidator('keySchema', cdk.requiredValidator)(properties.keySchema)); + errors.collect(cdk.propertyValidator('keySchema', cdk.listValidator(CfnTable_KeySchemaPropertyValidator))(properties.keySchema)); + errors.collect(cdk.propertyValidator('projection', cdk.requiredValidator)(properties.projection)); + errors.collect(cdk.propertyValidator('projection', CfnTable_ProjectionPropertyValidator)(properties.projection)); + errors.collect(cdk.propertyValidator('provisionedThroughput', CfnTable_ProvisionedThroughputPropertyValidator)(properties.provisionedThroughput)); + return errors.wrap('supplied properties not correct for "GlobalSecondaryIndexProperty"'); +} +/** + * Renders the AWS CloudFormation properties of an `AWS::DynamoDB::Table.GlobalSecondaryIndex` resource + * + * @param properties - the TypeScript properties of a `GlobalSecondaryIndexProperty` + * + * @returns the AWS CloudFormation properties of an `AWS::DynamoDB::Table.GlobalSecondaryIndex` resource. + */ +// @ts-ignore TS6133 +function cfnTableGlobalSecondaryIndexPropertyToCloudFormation(properties) { + if (!cdk.canInspect(properties)) { + return properties; + } + CfnTable_GlobalSecondaryIndexPropertyValidator(properties).assertSuccess(); + return { + IndexName: cdk.stringToCloudFormation(properties.indexName), + KeySchema: cdk.listMapper(cfnTableKeySchemaPropertyToCloudFormation)(properties.keySchema), + Projection: cfnTableProjectionPropertyToCloudFormation(properties.projection), + ProvisionedThroughput: cfnTableProvisionedThroughputPropertyToCloudFormation(properties.provisionedThroughput), + }; +} +/** + * Determine whether the given properties match those of a `KeySchemaProperty` + * + * @param properties - the TypeScript properties of a `KeySchemaProperty` + * + * @returns the result of the validation. + */ +function CfnTable_KeySchemaPropertyValidator(properties) { + if (!cdk.canInspect(properties)) { + return cdk.VALIDATION_SUCCESS; + } + const errors = new cdk.ValidationResults(); + errors.collect(cdk.propertyValidator('attributeName', cdk.requiredValidator)(properties.attributeName)); + errors.collect(cdk.propertyValidator('attributeName', cdk.validateString)(properties.attributeName)); + errors.collect(cdk.propertyValidator('keyType', cdk.requiredValidator)(properties.keyType)); + errors.collect(cdk.propertyValidator('keyType', cdk.validateString)(properties.keyType)); + return errors.wrap('supplied properties not correct for "KeySchemaProperty"'); +} +/** + * Renders the AWS CloudFormation properties of an `AWS::DynamoDB::Table.KeySchema` resource + * + * @param properties - the TypeScript properties of a `KeySchemaProperty` + * + * @returns the AWS CloudFormation properties of an `AWS::DynamoDB::Table.KeySchema` resource. + */ +// @ts-ignore TS6133 +function cfnTableKeySchemaPropertyToCloudFormation(properties) { + if (!cdk.canInspect(properties)) { + return properties; + } + CfnTable_KeySchemaPropertyValidator(properties).assertSuccess(); + return { + AttributeName: cdk.stringToCloudFormation(properties.attributeName), + KeyType: cdk.stringToCloudFormation(properties.keyType), + }; +} +/** + * Determine whether the given properties match those of a `LocalSecondaryIndexProperty` + * + * @param properties - the TypeScript properties of a `LocalSecondaryIndexProperty` + * + * @returns the result of the validation. + */ +function CfnTable_LocalSecondaryIndexPropertyValidator(properties) { + if (!cdk.canInspect(properties)) { + return cdk.VALIDATION_SUCCESS; + } + const errors = new cdk.ValidationResults(); + errors.collect(cdk.propertyValidator('indexName', cdk.requiredValidator)(properties.indexName)); + errors.collect(cdk.propertyValidator('indexName', cdk.validateString)(properties.indexName)); + errors.collect(cdk.propertyValidator('keySchema', cdk.requiredValidator)(properties.keySchema)); + errors.collect(cdk.propertyValidator('keySchema', cdk.listValidator(CfnTable_KeySchemaPropertyValidator))(properties.keySchema)); + errors.collect(cdk.propertyValidator('projection', cdk.requiredValidator)(properties.projection)); + errors.collect(cdk.propertyValidator('projection', CfnTable_ProjectionPropertyValidator)(properties.projection)); + return errors.wrap('supplied properties not correct for "LocalSecondaryIndexProperty"'); +} +/** + * Renders the AWS CloudFormation properties of an `AWS::DynamoDB::Table.LocalSecondaryIndex` resource + * + * @param properties - the TypeScript properties of a `LocalSecondaryIndexProperty` + * + * @returns the AWS CloudFormation properties of an `AWS::DynamoDB::Table.LocalSecondaryIndex` resource. + */ +// @ts-ignore TS6133 +function cfnTableLocalSecondaryIndexPropertyToCloudFormation(properties) { + if (!cdk.canInspect(properties)) { + return properties; + } + CfnTable_LocalSecondaryIndexPropertyValidator(properties).assertSuccess(); + return { + IndexName: cdk.stringToCloudFormation(properties.indexName), + KeySchema: cdk.listMapper(cfnTableKeySchemaPropertyToCloudFormation)(properties.keySchema), + Projection: cfnTableProjectionPropertyToCloudFormation(properties.projection), + }; +} +/** + * Determine whether the given properties match those of a `PointInTimeRecoverySpecificationProperty` + * + * @param properties - the TypeScript properties of a `PointInTimeRecoverySpecificationProperty` + * + * @returns the result of the validation. + */ +function CfnTable_PointInTimeRecoverySpecificationPropertyValidator(properties) { + if (!cdk.canInspect(properties)) { + return cdk.VALIDATION_SUCCESS; + } + const errors = new cdk.ValidationResults(); + errors.collect(cdk.propertyValidator('pointInTimeRecoveryEnabled', cdk.validateBoolean)(properties.pointInTimeRecoveryEnabled)); + return errors.wrap('supplied properties not correct for "PointInTimeRecoverySpecificationProperty"'); +} +/** + * Renders the AWS CloudFormation properties of an `AWS::DynamoDB::Table.PointInTimeRecoverySpecification` resource + * + * @param properties - the TypeScript properties of a `PointInTimeRecoverySpecificationProperty` + * + * @returns the AWS CloudFormation properties of an `AWS::DynamoDB::Table.PointInTimeRecoverySpecification` resource. + */ +// @ts-ignore TS6133 +function cfnTablePointInTimeRecoverySpecificationPropertyToCloudFormation(properties) { + if (!cdk.canInspect(properties)) { + return properties; + } + CfnTable_PointInTimeRecoverySpecificationPropertyValidator(properties).assertSuccess(); + return { + PointInTimeRecoveryEnabled: cdk.booleanToCloudFormation(properties.pointInTimeRecoveryEnabled), + }; +} +/** + * Determine whether the given properties match those of a `ProjectionProperty` + * + * @param properties - the TypeScript properties of a `ProjectionProperty` + * + * @returns the result of the validation. + */ +function CfnTable_ProjectionPropertyValidator(properties) { + if (!cdk.canInspect(properties)) { + return cdk.VALIDATION_SUCCESS; + } + const errors = new cdk.ValidationResults(); + errors.collect(cdk.propertyValidator('nonKeyAttributes', cdk.listValidator(cdk.validateString))(properties.nonKeyAttributes)); + errors.collect(cdk.propertyValidator('projectionType', cdk.validateString)(properties.projectionType)); + return errors.wrap('supplied properties not correct for "ProjectionProperty"'); +} +/** + * Renders the AWS CloudFormation properties of an `AWS::DynamoDB::Table.Projection` resource + * + * @param properties - the TypeScript properties of a `ProjectionProperty` + * + * @returns the AWS CloudFormation properties of an `AWS::DynamoDB::Table.Projection` resource. + */ +// @ts-ignore TS6133 +function cfnTableProjectionPropertyToCloudFormation(properties) { + if (!cdk.canInspect(properties)) { + return properties; + } + CfnTable_ProjectionPropertyValidator(properties).assertSuccess(); + return { + NonKeyAttributes: cdk.listMapper(cdk.stringToCloudFormation)(properties.nonKeyAttributes), + ProjectionType: cdk.stringToCloudFormation(properties.projectionType), + }; +} +/** + * Determine whether the given properties match those of a `ProvisionedThroughputProperty` + * + * @param properties - the TypeScript properties of a `ProvisionedThroughputProperty` + * + * @returns the result of the validation. + */ +function CfnTable_ProvisionedThroughputPropertyValidator(properties) { + if (!cdk.canInspect(properties)) { + return cdk.VALIDATION_SUCCESS; + } + const errors = new cdk.ValidationResults(); + errors.collect(cdk.propertyValidator('readCapacityUnits', cdk.requiredValidator)(properties.readCapacityUnits)); + errors.collect(cdk.propertyValidator('readCapacityUnits', cdk.validateNumber)(properties.readCapacityUnits)); + errors.collect(cdk.propertyValidator('writeCapacityUnits', cdk.requiredValidator)(properties.writeCapacityUnits)); + errors.collect(cdk.propertyValidator('writeCapacityUnits', cdk.validateNumber)(properties.writeCapacityUnits)); + return errors.wrap('supplied properties not correct for "ProvisionedThroughputProperty"'); +} +/** + * Renders the AWS CloudFormation properties of an `AWS::DynamoDB::Table.ProvisionedThroughput` resource + * + * @param properties - the TypeScript properties of a `ProvisionedThroughputProperty` + * + * @returns the AWS CloudFormation properties of an `AWS::DynamoDB::Table.ProvisionedThroughput` resource. + */ +// @ts-ignore TS6133 +function cfnTableProvisionedThroughputPropertyToCloudFormation(properties) { + if (!cdk.canInspect(properties)) { + return properties; + } + CfnTable_ProvisionedThroughputPropertyValidator(properties).assertSuccess(); + return { + ReadCapacityUnits: cdk.numberToCloudFormation(properties.readCapacityUnits), + WriteCapacityUnits: cdk.numberToCloudFormation(properties.writeCapacityUnits), + }; +} +/** + * Determine whether the given properties match those of a `SSESpecificationProperty` + * + * @param properties - the TypeScript properties of a `SSESpecificationProperty` + * + * @returns the result of the validation. + */ +function CfnTable_SSESpecificationPropertyValidator(properties) { + if (!cdk.canInspect(properties)) { + return cdk.VALIDATION_SUCCESS; + } + const errors = new cdk.ValidationResults(); + errors.collect(cdk.propertyValidator('sseEnabled', cdk.requiredValidator)(properties.sseEnabled)); + errors.collect(cdk.propertyValidator('sseEnabled', cdk.validateBoolean)(properties.sseEnabled)); + return errors.wrap('supplied properties not correct for "SSESpecificationProperty"'); +} +/** + * Renders the AWS CloudFormation properties of an `AWS::DynamoDB::Table.SSESpecification` resource + * + * @param properties - the TypeScript properties of a `SSESpecificationProperty` + * + * @returns the AWS CloudFormation properties of an `AWS::DynamoDB::Table.SSESpecification` resource. + */ +// @ts-ignore TS6133 +function cfnTableSSESpecificationPropertyToCloudFormation(properties) { + if (!cdk.canInspect(properties)) { + return properties; + } + CfnTable_SSESpecificationPropertyValidator(properties).assertSuccess(); + return { + SSEEnabled: cdk.booleanToCloudFormation(properties.sseEnabled), + }; +} +/** + * Determine whether the given properties match those of a `StreamSpecificationProperty` + * + * @param properties - the TypeScript properties of a `StreamSpecificationProperty` + * + * @returns the result of the validation. + */ +function CfnTable_StreamSpecificationPropertyValidator(properties) { + if (!cdk.canInspect(properties)) { + return cdk.VALIDATION_SUCCESS; + } + const errors = new cdk.ValidationResults(); + errors.collect(cdk.propertyValidator('streamViewType', cdk.requiredValidator)(properties.streamViewType)); + errors.collect(cdk.propertyValidator('streamViewType', cdk.validateString)(properties.streamViewType)); + return errors.wrap('supplied properties not correct for "StreamSpecificationProperty"'); +} +/** + * Renders the AWS CloudFormation properties of an `AWS::DynamoDB::Table.StreamSpecification` resource + * + * @param properties - the TypeScript properties of a `StreamSpecificationProperty` + * + * @returns the AWS CloudFormation properties of an `AWS::DynamoDB::Table.StreamSpecification` resource. + */ +// @ts-ignore TS6133 +function cfnTableStreamSpecificationPropertyToCloudFormation(properties) { + if (!cdk.canInspect(properties)) { + return properties; + } + CfnTable_StreamSpecificationPropertyValidator(properties).assertSuccess(); + return { + StreamViewType: cdk.stringToCloudFormation(properties.streamViewType), + }; +} +/** + * Determine whether the given properties match those of a `TimeToLiveSpecificationProperty` + * + * @param properties - the TypeScript properties of a `TimeToLiveSpecificationProperty` + * + * @returns the result of the validation. + */ +function CfnTable_TimeToLiveSpecificationPropertyValidator(properties) { + if (!cdk.canInspect(properties)) { + return cdk.VALIDATION_SUCCESS; + } + const errors = new cdk.ValidationResults(); + errors.collect(cdk.propertyValidator('attributeName', cdk.requiredValidator)(properties.attributeName)); + errors.collect(cdk.propertyValidator('attributeName', cdk.validateString)(properties.attributeName)); + errors.collect(cdk.propertyValidator('enabled', cdk.requiredValidator)(properties.enabled)); + errors.collect(cdk.propertyValidator('enabled', cdk.validateBoolean)(properties.enabled)); + return errors.wrap('supplied properties not correct for "TimeToLiveSpecificationProperty"'); +} +/** + * Renders the AWS CloudFormation properties of an `AWS::DynamoDB::Table.TimeToLiveSpecification` resource + * + * @param properties - the TypeScript properties of a `TimeToLiveSpecificationProperty` + * + * @returns the AWS CloudFormation properties of an `AWS::DynamoDB::Table.TimeToLiveSpecification` resource. + */ +// @ts-ignore TS6133 +function cfnTableTimeToLiveSpecificationPropertyToCloudFormation(properties) { + if (!cdk.canInspect(properties)) { + return properties; + } + CfnTable_TimeToLiveSpecificationPropertyValidator(properties).assertSuccess(); + return { + AttributeName: cdk.stringToCloudFormation(properties.attributeName), + Enabled: cdk.booleanToCloudFormation(properties.enabled), + }; +} +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZHluYW1vZGIuZ2VuZXJhdGVkLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiZHluYW1vZGIuZ2VuZXJhdGVkLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQSwrRUFBK0U7QUFDL0UsK0RBQStEO0FBQy9ELDhGQUE4RjtBQUM5RixzSEFBc0g7O0FBRXRILGtHQUFrRztBQUVsRyxvQ0FBcUM7QUFxRXJDOzs7Ozs7R0FNRztBQUNILFNBQVMsc0JBQXNCLENBQUMsVUFBZTtJQUMzQyxJQUFJLENBQUMsR0FBRyxDQUFDLFVBQVUsQ0FBQyxVQUFVLENBQUMsRUFBRTtRQUFFLE9BQU8sR0FBRyxDQUFDLGtCQUFrQixDQUFDO0tBQUU7SUFDbkUsTUFBTSxNQUFNLEdBQUcsSUFBSSxHQUFHLENBQUMsaUJBQWlCLEVBQUUsQ0FBQztJQUMzQyxNQUFNLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxpQkFBaUIsQ0FBQyxzQkFBc0IsRUFBRSxHQUFHLENBQUMsYUFBYSxDQUFDLDZDQUE2QyxDQUFDLENBQUMsQ0FBQyxVQUFVLENBQUMsb0JBQW9CLENBQUMsQ0FBQyxDQUFDO0lBQ2pLLE1BQU0sQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLGlCQUFpQixDQUFDLGFBQWEsRUFBRSxHQUFHLENBQUMsY0FBYyxDQUFDLENBQUMsVUFBVSxDQUFDLFdBQVcsQ0FBQyxDQUFDLENBQUM7SUFDakcsTUFBTSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsaUJBQWlCLENBQUMsd0JBQXdCLEVBQUUsR0FBRyxDQUFDLGFBQWEsQ0FBQyw4Q0FBOEMsQ0FBQyxDQUFDLENBQUMsVUFBVSxDQUFDLHNCQUFzQixDQUFDLENBQUMsQ0FBQztJQUN0SyxNQUFNLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxpQkFBaUIsQ0FBQyxXQUFXLEVBQUUsR0FBRyxDQUFDLGlCQUFpQixDQUFDLENBQUMsVUFBVSxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUM7SUFDaEcsTUFBTSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsaUJBQWlCLENBQUMsV0FBVyxFQUFFLEdBQUcsQ0FBQyxhQUFhLENBQUMsbUNBQW1DLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDO0lBQ2pJLE1BQU0sQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLGlCQUFpQixDQUFDLHVCQUF1QixFQUFFLEdBQUcsQ0FBQyxhQUFhLENBQUMsNkNBQTZDLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxxQkFBcUIsQ0FBQyxDQUFDLENBQUM7SUFDbkssTUFBTSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsaUJBQWlCLENBQUMsa0NBQWtDLEVBQUUsMERBQTBELENBQUMsQ0FBQyxVQUFVLENBQUMsZ0NBQWdDLENBQUMsQ0FBQyxDQUFDO0lBQ25MLE1BQU0sQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLGlCQUFpQixDQUFDLHVCQUF1QixFQUFFLCtDQUErQyxDQUFDLENBQUMsVUFBVSxDQUFDLHFCQUFxQixDQUFDLENBQUMsQ0FBQztJQUNsSixNQUFNLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxpQkFBaUIsQ0FBQyxrQkFBa0IsRUFBRSwwQ0FBMEMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDLENBQUM7SUFDbkksTUFBTSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsaUJBQWlCLENBQUMscUJBQXFCLEVBQUUsNkNBQTZDLENBQUMsQ0FBQyxVQUFVLENBQUMsbUJBQW1CLENBQUMsQ0FBQyxDQUFDO0lBQzVJLE1BQU0sQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLGlCQUFpQixDQUFDLFdBQVcsRUFBRSxHQUFHLENBQUMsY0FBYyxDQUFDLENBQUMsVUFBVSxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUM7SUFDN0YsTUFBTSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsaUJBQWlCLENBQUMsTUFBTSxFQUFFLEdBQUcsQ0FBQyxhQUFhLENBQUMsR0FBRyxDQUFDLGNBQWMsQ0FBQyxDQUFDLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7SUFDdEcsTUFBTSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsaUJBQWlCLENBQUMseUJBQXlCLEVBQUUsaURBQWlELENBQUMsQ0FBQyxVQUFVLENBQUMsdUJBQXVCLENBQUMsQ0FBQyxDQUFDO0lBQ3hKLE9BQU8sTUFBTSxDQUFDLElBQUksQ0FBQyxxREFBcUQsQ0FBQyxDQUFDO0FBQzlFLENBQUM7QUFFRDs7Ozs7O0dBTUc7QUFDSCxvQkFBb0I7QUFDcEIsU0FBUyw2QkFBNkIsQ0FBQyxVQUFlO0lBQ2xELElBQUksQ0FBQyxHQUFHLENBQUMsVUFBVSxDQUFDLFVBQVUsQ0FBQyxFQUFFO1FBQUUsT0FBTyxVQUFVLENBQUM7S0FBRTtJQUN2RCxzQkFBc0IsQ0FBQyxVQUFVLENBQUMsQ0FBQyxhQUFhLEVBQUUsQ0FBQztJQUNuRCxPQUFPO1FBQ0wsU0FBUyxFQUFFLEdBQUcsQ0FBQyxVQUFVLENBQUMseUNBQXlDLENBQUMsQ0FBQyxVQUFVLENBQUMsU0FBUyxDQUFDO1FBQzFGLG9CQUFvQixFQUFFLEdBQUcsQ0FBQyxVQUFVLENBQUMsbURBQW1ELENBQUMsQ0FBQyxVQUFVLENBQUMsb0JBQW9CLENBQUM7UUFDMUgsV0FBVyxFQUFFLEdBQUcsQ0FBQyxzQkFBc0IsQ0FBQyxVQUFVLENBQUMsV0FBVyxDQUFDO1FBQy9ELHNCQUFzQixFQUFFLEdBQUcsQ0FBQyxVQUFVLENBQUMsb0RBQW9ELENBQUMsQ0FBQyxVQUFVLENBQUMsc0JBQXNCLENBQUM7UUFDL0gscUJBQXFCLEVBQUUsR0FBRyxDQUFDLFVBQVUsQ0FBQyxtREFBbUQsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxxQkFBcUIsQ0FBQztRQUM1SCxnQ0FBZ0MsRUFBRSxnRUFBZ0UsQ0FBQyxVQUFVLENBQUMsZ0NBQWdDLENBQUM7UUFDL0kscUJBQXFCLEVBQUUscURBQXFELENBQUMsVUFBVSxDQUFDLHFCQUFxQixDQUFDO1FBQzlHLGdCQUFnQixFQUFFLGdEQUFnRCxDQUFDLFVBQVUsQ0FBQyxnQkFBZ0IsQ0FBQztRQUMvRixtQkFBbUIsRUFBRSxtREFBbUQsQ0FBQyxVQUFVLENBQUMsbUJBQW1CLENBQUM7UUFDeEcsU0FBUyxFQUFFLEdBQUcsQ0FBQyxzQkFBc0IsQ0FBQyxVQUFVLENBQUMsU0FBUyxDQUFDO1FBQzNELElBQUksRUFBRSxHQUFHLENBQUMsVUFBVSxDQUFDLEdBQUcsQ0FBQyxzQkFBc0IsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUM7UUFDakUsdUJBQXVCLEVBQUUsdURBQXVELENBQUMsVUFBVSxDQUFDLHVCQUF1QixDQUFDO0tBQ3JILENBQUM7QUFDTixDQUFDO0FBRUQ7Ozs7O0dBS0c7QUFDSCxNQUFhLFFBQVMsU0FBUSxHQUFHLENBQUMsV0FBVztJQTJCekM7Ozs7OztPQU1HO0lBQ0gsWUFBWSxLQUFvQixFQUFFLEVBQVUsRUFBRSxLQUFvQjtRQUM5RCxLQUFLLENBQUMsS0FBSyxFQUFFLEVBQUUsRUFBRSxFQUFFLElBQUksRUFBRSxRQUFRLENBQUMsZ0JBQWdCLEVBQUUsVUFBVSxFQUFFLEtBQUssRUFBRSxDQUFDLENBQUM7UUFDekUsR0FBRyxDQUFDLGVBQWUsQ0FBQyxLQUFLLEVBQUUsV0FBVyxFQUFFLElBQUksQ0FBQyxDQUFDO1FBQzlDLElBQUksQ0FBQyxRQUFRLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxRQUFRLEVBQUUsQ0FBQztRQUM5QyxJQUFJLENBQUMsY0FBYyxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMsV0FBVyxDQUFDLENBQUMsUUFBUSxFQUFFLENBQUM7UUFDMUQsSUFBSSxDQUFDLFNBQVMsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLFFBQVEsRUFBRSxDQUFDO1FBQ3JDLE1BQU0sSUFBSSxHQUFHLEtBQUssS0FBSyxTQUFTLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQztRQUMxRCxJQUFJLENBQUMsSUFBSSxHQUFHLElBQUksR0FBRyxDQUFDLFVBQVUsQ0FBQyxHQUFHLENBQUMsT0FBTyxDQUFDLFFBQVEsRUFBRSxzQkFBc0IsRUFBRSxJQUFJLENBQUMsQ0FBQztJQUN2RixDQUFDO0lBRUQsSUFBVyxpQkFBaUI7UUFDeEIsT0FBTyxJQUFJLENBQUMsd0JBQXdCLENBQUM7SUFDekMsQ0FBQztJQUNTLGdCQUFnQixDQUFDLFVBQWU7UUFDdEMsT0FBTyw2QkFBNkIsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDO0lBQ3hFLENBQUM7O0FBaEREOztHQUVHO0FBQ29CLHlCQUFnQixHQUFHLHNCQUFzQixDQUFDO0FBSnJFLDRCQWtEQztBQW9CRDs7Ozs7O0dBTUc7QUFDSCxTQUFTLDZDQUE2QyxDQUFDLFVBQWU7SUFDbEUsSUFBSSxDQUFDLEdBQUcsQ0FBQyxVQUFVLENBQUMsVUFBVSxDQUFDLEVBQUU7UUFBRSxPQUFPLEdBQUcsQ0FBQyxrQkFBa0IsQ0FBQztLQUFFO0lBQ25FLE1BQU0sTUFBTSxHQUFHLElBQUksR0FBRyxDQUFDLGlCQUFpQixFQUFFLENBQUM7SUFDM0MsTUFBTSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsaUJBQWlCLENBQUMsZUFBZSxFQUFFLEdBQUcsQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxhQUFhLENBQUMsQ0FBQyxDQUFDO0lBQ3hHLE1BQU0sQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLGlCQUFpQixDQUFDLGVBQWUsRUFBRSxHQUFHLENBQUMsY0FBYyxDQUFDLENBQUMsVUFBVSxDQUFDLGFBQWEsQ0FBQyxDQUFDLENBQUM7SUFDckcsTUFBTSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsaUJBQWlCLENBQUMsZUFBZSxFQUFFLEdBQUcsQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxhQUFhLENBQUMsQ0FBQyxDQUFDO0lBQ3hHLE1BQU0sQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLGlCQUFpQixDQUFDLGVBQWUsRUFBRSxHQUFHLENBQUMsY0FBYyxDQUFDLENBQUMsVUFBVSxDQUFDLGFBQWEsQ0FBQyxDQUFDLENBQUM7SUFDckcsT0FBTyxNQUFNLENBQUMsSUFBSSxDQUFDLG1FQUFtRSxDQUFDLENBQUM7QUFDNUYsQ0FBQztBQUVEOzs7Ozs7R0FNRztBQUNILG9CQUFvQjtBQUNwQixTQUFTLG1EQUFtRCxDQUFDLFVBQWU7SUFDeEUsSUFBSSxDQUFDLEdBQUcsQ0FBQyxVQUFVLENBQUMsVUFBVSxDQUFDLEVBQUU7UUFBRSxPQUFPLFVBQVUsQ0FBQztLQUFFO0lBQ3ZELDZDQUE2QyxDQUFDLFVBQVUsQ0FBQyxDQUFDLGFBQWEsRUFBRSxDQUFDO0lBQzFFLE9BQU87UUFDTCxhQUFhLEVBQUUsR0FBRyxDQUFDLHNCQUFzQixDQUFDLFVBQVUsQ0FBQyxhQUFhLENBQUM7UUFDbkUsYUFBYSxFQUFFLEdBQUcsQ0FBQyxzQkFBc0IsQ0FBQyxVQUFVLENBQUMsYUFBYSxDQUFDO0tBQ3BFLENBQUM7QUFDTixDQUFDO0FBOEJEOzs7Ozs7R0FNRztBQUNILFNBQVMsOENBQThDLENBQUMsVUFBZTtJQUNuRSxJQUFJLENBQUMsR0FBRyxDQUFDLFVBQVUsQ0FBQyxVQUFVLENBQUMsRUFBRTtRQUFFLE9BQU8sR0FBRyxDQUFDLGtCQUFrQixDQUFDO0tBQUU7SUFDbkUsTUFBTSxNQUFNLEdBQUcsSUFBSSxHQUFHLENBQUMsaUJBQWlCLEVBQUUsQ0FBQztJQUMzQyxNQUFNLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxpQkFBaUIsQ0FBQyxXQUFXLEVBQUUsR0FBRyxDQUFDLGlCQUFpQixDQUFDLENBQUMsVUFBVSxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUM7SUFDaEcsTUFBTSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsaUJBQWlCLENBQUMsV0FBVyxFQUFFLEdBQUcsQ0FBQyxjQUFjLENBQUMsQ0FBQyxVQUFVLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQztJQUM3RixNQUFNLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxpQkFBaUIsQ0FBQyxXQUFXLEVBQUUsR0FBRyxDQUFDLGlCQUFpQixDQUFDLENBQUMsVUFBVSxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUM7SUFDaEcsTUFBTSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsaUJBQWlCLENBQUMsV0FBVyxFQUFFLEdBQUcsQ0FBQyxhQUFhLENBQUMsbUNBQW1DLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDO0lBQ2pJLE1BQU0sQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLGlCQUFpQixDQUFDLFlBQVksRUFBRSxHQUFHLENBQUMsaUJBQWlCLENBQUMsQ0FBQyxVQUFVLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQztJQUNsRyxNQUFNLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxpQkFBaUIsQ0FBQyxZQUFZLEVBQUUsb0NBQW9DLENBQUMsQ0FBQyxVQUFVLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQztJQUNqSCxNQUFNLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxpQkFBaUIsQ0FBQyx1QkFBdUIsRUFBRSwrQ0FBK0MsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxxQkFBcUIsQ0FBQyxDQUFDLENBQUM7SUFDbEosT0FBTyxNQUFNLENBQUMsSUFBSSxDQUFDLG9FQUFvRSxDQUFDLENBQUM7QUFDN0YsQ0FBQztBQUVEOzs7Ozs7R0FNRztBQUNILG9CQUFvQjtBQUNwQixTQUFTLG9EQUFvRCxDQUFDLFVBQWU7SUFDekUsSUFBSSxDQUFDLEdBQUcsQ0FBQyxVQUFVLENBQUMsVUFBVSxDQUFDLEVBQUU7UUFBRSxPQUFPLFVBQVUsQ0FBQztLQUFFO0lBQ3ZELDhDQUE4QyxDQUFDLFVBQVUsQ0FBQyxDQUFDLGFBQWEsRUFBRSxDQUFDO0lBQzNFLE9BQU87UUFDTCxTQUFTLEVBQUUsR0FBRyxDQUFDLHNCQUFzQixDQUFDLFVBQVUsQ0FBQyxTQUFTLENBQUM7UUFDM0QsU0FBUyxFQUFFLEdBQUcsQ0FBQyxVQUFVLENBQUMseUNBQXlDLENBQUMsQ0FBQyxVQUFVLENBQUMsU0FBUyxDQUFDO1FBQzFGLFVBQVUsRUFBRSwwQ0FBMEMsQ0FBQyxVQUFVLENBQUMsVUFBVSxDQUFDO1FBQzdFLHFCQUFxQixFQUFFLHFEQUFxRCxDQUFDLFVBQVUsQ0FBQyxxQkFBcUIsQ0FBQztLQUMvRyxDQUFDO0FBQ04sQ0FBQztBQW9CRDs7Ozs7O0dBTUc7QUFDSCxTQUFTLG1DQUFtQyxDQUFDLFVBQWU7SUFDeEQsSUFBSSxDQUFDLEdBQUcsQ0FBQyxVQUFVLENBQUMsVUFBVSxDQUFDLEVBQUU7UUFBRSxPQUFPLEdBQUcsQ0FBQyxrQkFBa0IsQ0FBQztLQUFFO0lBQ25FLE1BQU0sTUFBTSxHQUFHLElBQUksR0FBRyxDQUFDLGlCQUFpQixFQUFFLENBQUM7SUFDM0MsTUFBTSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsaUJBQWlCLENBQUMsZUFBZSxFQUFFLEdBQUcsQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxhQUFhLENBQUMsQ0FBQyxDQUFDO0lBQ3hHLE1BQU0sQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLGlCQUFpQixDQUFDLGVBQWUsRUFBRSxHQUFHLENBQUMsY0FBYyxDQUFDLENBQUMsVUFBVSxDQUFDLGFBQWEsQ0FBQyxDQUFDLENBQUM7SUFDckcsTUFBTSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsaUJBQWlCLENBQUMsU0FBUyxFQUFFLEdBQUcsQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDO0lBQzVGLE1BQU0sQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLGlCQUFpQixDQUFDLFNBQVMsRUFBRSxHQUFHLENBQUMsY0FBYyxDQUFDLENBQUMsVUFBVSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUM7SUFDekYsT0FBTyxNQUFNLENBQUMsSUFBSSxDQUFDLHlEQUF5RCxDQUFDLENBQUM7QUFDbEYsQ0FBQztBQUVEOzs7Ozs7R0FNRztBQUNILG9CQUFvQjtBQUNwQixTQUFTLHlDQUF5QyxDQUFDLFVBQWU7SUFDOUQsSUFBSSxDQUFDLEdBQUcsQ0FBQyxVQUFVLENBQUMsVUFBVSxDQUFDLEVBQUU7UUFBRSxPQUFPLFVBQVUsQ0FBQztLQUFFO0lBQ3ZELG1DQUFtQyxDQUFDLFVBQVUsQ0FBQyxDQUFDLGFBQWEsRUFBRSxDQUFDO0lBQ2hFLE9BQU87UUFDTCxhQUFhLEVBQUUsR0FBRyxDQUFDLHNCQUFzQixDQUFDLFVBQVUsQ0FBQyxhQUFhLENBQUM7UUFDbkUsT0FBTyxFQUFFLEdBQUcsQ0FBQyxzQkFBc0IsQ0FBQyxVQUFVLENBQUMsT0FBTyxDQUFDO0tBQ3hELENBQUM7QUFDTixDQUFDO0FBeUJEOzs7Ozs7R0FNRztBQUNILFNBQVMsNkNBQTZDLENBQUMsVUFBZTtJQUNsRSxJQUFJLENBQUMsR0FBRyxDQUFDLFVBQVUsQ0FBQyxVQUFVLENBQUMsRUFBRTtRQUFFLE9BQU8sR0FBRyxDQUFDLGtCQUFrQixDQUFDO0tBQUU7SUFDbkUsTUFBTSxNQUFNLEdBQUcsSUFBSSxHQUFHLENBQUMsaUJBQWlCLEVBQUUsQ0FBQztJQUMzQyxNQUFNLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxpQkFBaUIsQ0FBQyxXQUFXLEVBQUUsR0FBRyxDQUFDLGlCQUFpQixDQUFDLENBQUMsVUFBVSxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUM7SUFDaEcsTUFBTSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsaUJBQWlCLENBQUMsV0FBVyxFQUFFLEdBQUcsQ0FBQyxjQUFjLENBQUMsQ0FBQyxVQUFVLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQztJQUM3RixNQUFNLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxpQkFBaUIsQ0FBQyxXQUFXLEVBQUUsR0FBRyxDQUFDLGlCQUFpQixDQUFDLENBQUMsVUFBVSxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUM7SUFDaEcsTUFBTSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsaUJBQWlCLENBQUMsV0FBVyxFQUFFLEdBQUcsQ0FBQyxhQUFhLENBQUMsbUNBQW1DLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDO0lBQ2pJLE1BQU0sQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLGlCQUFpQixDQUFDLFlBQVksRUFBRSxHQUFHLENBQUMsaUJBQWlCLENBQUMsQ0FBQyxVQUFVLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQztJQUNsRyxNQUFNLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxpQkFBaUIsQ0FBQyxZQUFZLEVBQUUsb0NBQW9DLENBQUMsQ0FBQyxVQUFVLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQztJQUNqSCxPQUFPLE1BQU0sQ0FBQyxJQUFJLENBQUMsbUVBQW1FLENBQUMsQ0FBQztBQUM1RixDQUFDO0FBRUQ7Ozs7OztHQU1HO0FBQ0gsb0JBQW9CO0FBQ3BCLFNBQVMsbURBQW1ELENBQUMsVUFBZTtJQUN4RSxJQUFJLENBQUMsR0FBRyxDQUFDLFVBQVUsQ0FBQyxVQUFVLENBQUMsRUFBRTtRQUFFLE9BQU8sVUFBVSxDQUFDO0tBQUU7SUFDdkQsNkNBQTZDLENBQUMsVUFBVSxDQUFDLENBQUMsYUFBYSxFQUFFLENBQUM7SUFDMUUsT0FBTztRQUNMLFNBQVMsRUFBRSxHQUFHLENBQUMsc0JBQXNCLENBQUMsVUFBVSxDQUFDLFNBQVMsQ0FBQztRQUMzRCxTQUFTLEVBQUUsR0FBRyxDQUFDLFVBQVUsQ0FBQyx5Q0FBeUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxTQUFTLENBQUM7UUFDMUYsVUFBVSxFQUFFLDBDQUEwQyxDQUFDLFVBQVUsQ0FBQyxVQUFVLENBQUM7S0FDOUUsQ0FBQztBQUNOLENBQUM7QUFlRDs7Ozs7O0dBTUc7QUFDSCxTQUFTLDBEQUEwRCxDQUFDLFVBQWU7SUFDL0UsSUFBSSxDQUFDLEdBQUcsQ0FBQyxVQUFVLENBQUMsVUFBVSxDQUFDLEVBQUU7UUFBRSxPQUFPLEdBQUcsQ0FBQyxrQkFBa0IsQ0FBQztLQUFFO0lBQ25FLE1BQU0sTUFBTSxHQUFHLElBQUksR0FBRyxDQUFDLGlCQUFpQixFQUFFLENBQUM7SUFDM0MsTUFBTSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsaUJBQWlCLENBQUMsNEJBQTRCLEVBQUUsR0FBRyxDQUFDLGVBQWUsQ0FBQyxDQUFDLFVBQVUsQ0FBQywwQkFBMEIsQ0FBQyxDQUFDLENBQUM7SUFDaEksT0FBTyxNQUFNLENBQUMsSUFBSSxDQUFDLGdGQUFnRixDQUFDLENBQUM7QUFDekcsQ0FBQztBQUVEOzs7Ozs7R0FNRztBQUNILG9CQUFvQjtBQUNwQixTQUFTLGdFQUFnRSxDQUFDLFVBQWU7SUFDckYsSUFBSSxDQUFDLEdBQUcsQ0FBQyxVQUFVLENBQUMsVUFBVSxDQUFDLEVBQUU7UUFBRSxPQUFPLFVBQVUsQ0FBQztLQUFFO0lBQ3ZELDBEQUEwRCxDQUFDLFVBQVUsQ0FBQyxDQUFDLGFBQWEsRUFBRSxDQUFDO0lBQ3ZGLE9BQU87UUFDTCwwQkFBMEIsRUFBRSxHQUFHLENBQUMsdUJBQXVCLENBQUMsVUFBVSxDQUFDLDBCQUEwQixDQUFDO0tBQy9GLENBQUM7QUFDTixDQUFDO0FBb0JEOzs7Ozs7R0FNRztBQUNILFNBQVMsb0NBQW9DLENBQUMsVUFBZTtJQUN6RCxJQUFJLENBQUMsR0FBRyxDQUFDLFVBQVUsQ0FBQyxVQUFVLENBQUMsRUFBRTtRQUFFLE9BQU8sR0FBRyxDQUFDLGtCQUFrQixDQUFDO0tBQUU7SUFDbkUsTUFBTSxNQUFNLEdBQUcsSUFBSSxHQUFHLENBQUMsaUJBQWlCLEVBQUUsQ0FBQztJQUMzQyxNQUFNLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxpQkFBaUIsQ0FBQyxrQkFBa0IsRUFBRSxHQUFHLENBQUMsYUFBYSxDQUFDLEdBQUcsQ0FBQyxjQUFjLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDLENBQUM7SUFDOUgsTUFBTSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsaUJBQWlCLENBQUMsZ0JBQWdCLEVBQUUsR0FBRyxDQUFDLGNBQWMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxjQUFjLENBQUMsQ0FBQyxDQUFDO0lBQ3ZHLE9BQU8sTUFBTSxDQUFDLElBQUksQ0FBQywwREFBMEQsQ0FBQyxDQUFDO0FBQ25GLENBQUM7QUFFRDs7Ozs7O0dBTUc7QUFDSCxvQkFBb0I7QUFDcEIsU0FBUywwQ0FBMEMsQ0FBQyxVQUFlO0lBQy9ELElBQUksQ0FBQyxHQUFHLENBQUMsVUFBVSxDQUFDLFVBQVUsQ0FBQyxFQUFFO1FBQUUsT0FBTyxVQUFVLENBQUM7S0FBRTtJQUN2RCxvQ0FBb0MsQ0FBQyxVQUFVLENBQUMsQ0FBQyxhQUFhLEVBQUUsQ0FBQztJQUNqRSxPQUFPO1FBQ0wsZ0JBQWdCLEVBQUUsR0FBRyxDQUFDLFVBQVUsQ0FBQyxHQUFHLENBQUMsc0JBQXNCLENBQUMsQ0FBQyxVQUFVLENBQUMsZ0JBQWdCLENBQUM7UUFDekYsY0FBYyxFQUFFLEdBQUcsQ0FBQyxzQkFBc0IsQ0FBQyxVQUFVLENBQUMsY0FBYyxDQUFDO0tBQ3RFLENBQUM7QUFDTixDQUFDO0FBb0JEOzs7Ozs7R0FNRztBQUNILFNBQVMsK0NBQStDLENBQUMsVUFBZTtJQUNwRSxJQUFJLENBQUMsR0FBRyxDQUFDLFVBQVUsQ0FBQyxVQUFVLENBQUMsRUFBRTtRQUFFLE9BQU8sR0FBRyxDQUFDLGtCQUFrQixDQUFDO0tBQUU7SUFDbkUsTUFBTSxNQUFNLEdBQUcsSUFBSSxHQUFHLENBQUMsaUJBQWlCLEVBQUUsQ0FBQztJQUMzQyxNQUFNLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxpQkFBaUIsQ0FBQyxtQkFBbUIsRUFBRSxHQUFHLENBQUMsaUJBQWlCLENBQUMsQ0FBQyxVQUFVLENBQUMsaUJBQWlCLENBQUMsQ0FBQyxDQUFDO0lBQ2hILE1BQU0sQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLGlCQUFpQixDQUFDLG1CQUFtQixFQUFFLEdBQUcsQ0FBQyxjQUFjLENBQUMsQ0FBQyxVQUFVLENBQUMsaUJBQWlCLENBQUMsQ0FBQyxDQUFDO0lBQzdHLE1BQU0sQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLGlCQUFpQixDQUFDLG9CQUFvQixFQUFFLEdBQUcsQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDLENBQUM7SUFDbEgsTUFBTSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsaUJBQWlCLENBQUMsb0JBQW9CLEVBQUUsR0FBRyxDQUFDLGNBQWMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDLENBQUM7SUFDL0csT0FBTyxNQUFNLENBQUMsSUFBSSxDQUFDLHFFQUFxRSxDQUFDLENBQUM7QUFDOUYsQ0FBQztBQUVEOzs7Ozs7R0FNRztBQUNILG9CQUFvQjtBQUNwQixTQUFTLHFEQUFxRCxDQUFDLFVBQWU7SUFDMUUsSUFBSSxDQUFDLEdBQUcsQ0FBQyxVQUFVLENBQUMsVUFBVSxDQUFDLEVBQUU7UUFBRSxPQUFPLFVBQVUsQ0FBQztLQUFFO0lBQ3ZELCtDQUErQyxDQUFDLFVBQVUsQ0FBQyxDQUFDLGFBQWEsRUFBRSxDQUFDO0lBQzVFLE9BQU87UUFDTCxpQkFBaUIsRUFBRSxHQUFHLENBQUMsc0JBQXNCLENBQUMsVUFBVSxDQUFDLGlCQUFpQixDQUFDO1FBQzNFLGtCQUFrQixFQUFFLEdBQUcsQ0FBQyxzQkFBc0IsQ0FBQyxVQUFVLENBQUMsa0JBQWtCLENBQUM7S0FDOUUsQ0FBQztBQUNOLENBQUM7QUFlRDs7Ozs7O0dBTUc7QUFDSCxTQUFTLDBDQUEwQyxDQUFDLFVBQWU7SUFDL0QsSUFBSSxDQUFDLEdBQUcsQ0FBQyxVQUFVLENBQUMsVUFBVSxDQUFDLEVBQUU7UUFBRSxPQUFPLEdBQUcsQ0FBQyxrQkFBa0IsQ0FBQztLQUFFO0lBQ25FLE1BQU0sTUFBTSxHQUFHLElBQUksR0FBRyxDQUFDLGlCQUFpQixFQUFFLENBQUM7SUFDM0MsTUFBTSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsaUJBQWlCLENBQUMsWUFBWSxFQUFFLEdBQUcsQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDO0lBQ2xHLE1BQU0sQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLGlCQUFpQixDQUFDLFlBQVksRUFBRSxHQUFHLENBQUMsZUFBZSxDQUFDLENBQUMsVUFBVSxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUM7SUFDaEcsT0FBTyxNQUFNLENBQUMsSUFBSSxDQUFDLGdFQUFnRSxDQUFDLENBQUM7QUFDekYsQ0FBQztBQUVEOzs7Ozs7R0FNRztBQUNILG9CQUFvQjtBQUNwQixTQUFTLGdEQUFnRCxDQUFDLFVBQWU7SUFDckUsSUFBSSxDQUFDLEdBQUcsQ0FBQyxVQUFVLENBQUMsVUFBVSxDQUFDLEVBQUU7UUFBRSxPQUFPLFVBQVUsQ0FBQztLQUFFO0lBQ3ZELDBDQUEwQyxDQUFDLFVBQVUsQ0FBQyxDQUFDLGFBQWEsRUFBRSxDQUFDO0lBQ3ZFLE9BQU87UUFDTCxVQUFVLEVBQUUsR0FBRyxDQUFDLHVCQUF1QixDQUFDLFVBQVUsQ0FBQyxVQUFVLENBQUM7S0FDL0QsQ0FBQztBQUNOLENBQUM7QUFlRDs7Ozs7O0dBTUc7QUFDSCxTQUFTLDZDQUE2QyxDQUFDLFVBQWU7SUFDbEUsSUFBSSxDQUFDLEdBQUcsQ0FBQyxVQUFVLENBQUMsVUFBVSxDQUFDLEVBQUU7UUFBRSxPQUFPLEdBQUcsQ0FBQyxrQkFBa0IsQ0FBQztLQUFFO0lBQ25FLE1BQU0sTUFBTSxHQUFHLElBQUksR0FBRyxDQUFDLGlCQUFpQixFQUFFLENBQUM7SUFDM0MsTUFBTSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsaUJBQWlCLENBQUMsZ0JBQWdCLEVBQUUsR0FBRyxDQUFDLGlCQUFpQixDQUFDLENBQUMsVUFBVSxDQUFDLGNBQWMsQ0FBQyxDQUFDLENBQUM7SUFDMUcsTUFBTSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsaUJBQWlCLENBQUMsZ0JBQWdCLEVBQUUsR0FBRyxDQUFDLGNBQWMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxjQUFjLENBQUMsQ0FBQyxDQUFDO0lBQ3ZHLE9BQU8sTUFBTSxDQUFDLElBQUksQ0FBQyxtRUFBbUUsQ0FBQyxDQUFDO0FBQzVGLENBQUM7QUFFRDs7Ozs7O0dBTUc7QUFDSCxvQkFBb0I7QUFDcEIsU0FBUyxtREFBbUQsQ0FBQyxVQUFlO0lBQ3hFLElBQUksQ0FBQyxHQUFHLENBQUMsVUFBVSxDQUFDLFVBQVUsQ0FBQyxFQUFFO1FBQUUsT0FBTyxVQUFVLENBQUM7S0FBRTtJQUN2RCw2Q0FBNkMsQ0FBQyxVQUFVLENBQUMsQ0FBQyxhQUFhLEVBQUUsQ0FBQztJQUMxRSxPQUFPO1FBQ0wsY0FBYyxFQUFFLEdBQUcsQ0FBQyxzQkFBc0IsQ0FBQyxVQUFVLENBQUMsY0FBYyxDQUFDO0tBQ3RFLENBQUM7QUFDTixDQUFDO0FBb0JEOzs7Ozs7R0FNRztBQUNILFNBQVMsaURBQWlELENBQUMsVUFBZTtJQUN0RSxJQUFJLENBQUMsR0FBRyxDQUFDLFVBQVUsQ0FBQyxVQUFVLENBQUMsRUFBRTtRQUFFLE9BQU8sR0FBRyxDQUFDLGtCQUFrQixDQUFDO0tBQUU7SUFDbkUsTUFBTSxNQUFNLEdBQUcsSUFBSSxHQUFHLENBQUMsaUJBQWlCLEVBQUUsQ0FBQztJQUMzQyxNQUFNLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxpQkFBaUIsQ0FBQyxlQUFlLEVBQUUsR0FBRyxDQUFDLGlCQUFpQixDQUFDLENBQUMsVUFBVSxDQUFDLGFBQWEsQ0FBQyxDQUFDLENBQUM7SUFDeEcsTUFBTSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsaUJBQWlCLENBQUMsZUFBZSxFQUFFLEdBQUcsQ0FBQyxjQUFjLENBQUMsQ0FBQyxVQUFVLENBQUMsYUFBYSxDQUFDLENBQUMsQ0FBQztJQUNyRyxNQUFNLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxpQkFBaUIsQ0FBQyxTQUFTLEVBQUUsR0FBRyxDQUFDLGlCQUFpQixDQUFDLENBQUMsVUFBVSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUM7SUFDNUYsTUFBTSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsaUJBQWlCLENBQUMsU0FBUyxFQUFFLEdBQUcsQ0FBQyxlQUFlLENBQUMsQ0FBQyxVQUFVLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQztJQUMxRixPQUFPLE1BQU0sQ0FBQyxJQUFJLENBQUMsdUVBQXVFLENBQUMsQ0FBQztBQUNoRyxDQUFDO0FBRUQ7Ozs7OztHQU1HO0FBQ0gsb0JBQW9CO0FBQ3BCLFNBQVMsdURBQXVELENBQUMsVUFBZTtJQUM1RSxJQUFJLENBQUMsR0FBRyxDQUFDLFVBQVUsQ0FBQyxVQUFVLENBQUMsRUFBRTtRQUFFLE9BQU8sVUFBVSxDQUFDO0tBQUU7SUFDdkQsaURBQWlELENBQUMsVUFBVSxDQUFDLENBQUMsYUFBYSxFQUFFLENBQUM7SUFDOUUsT0FBTztRQUNMLGFBQWEsRUFBRSxHQUFHLENBQUMsc0JBQXNCLENBQUMsVUFBVSxDQUFDLGFBQWEsQ0FBQztRQUNuRSxPQUFPLEVBQUUsR0FBRyxDQUFDLHVCQUF1QixDQUFDLFVBQVUsQ0FBQyxPQUFPLENBQUM7S0FDekQsQ0FBQztBQUNOLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBDb3B5cmlnaHQgMjAxMi0yMDE5IEFtYXpvbi5jb20sIEluYy4gb3IgaXRzIGFmZmlsaWF0ZXMuIEFsbCBSaWdodHMgUmVzZXJ2ZWQuXG4vLyBHZW5lcmF0ZWQgZnJvbSB0aGUgQVdTIENsb3VkRm9ybWF0aW9uIFJlc291cmNlIFNwZWNpZmljYXRpb25cbi8vIFNlZTogZG9jcy5hd3MuYW1hem9uLmNvbS9BV1NDbG91ZEZvcm1hdGlvbi9sYXRlc3QvVXNlckd1aWRlL2Nmbi1yZXNvdXJjZS1zcGVjaWZpY2F0aW9uLmh0bWxcbi8vIEBjZm4ydHM6bWV0YUAge1wiZ2VuZXJhdGVkXCI6XCIyMDE5LTAzLTIxVDE2OjE5OjE2Ljg4MVpcIixcImZpbmdlcnByaW50XCI6XCJDUFRwRTllRDRJbXFPS0RudTdQMEthb2w4aitTWE5RVUlMTVI0bC9maTJnPVwifVxuXG4vLyB0c2xpbnQ6ZGlzYWJsZTptYXgtbGluZS1sZW5ndGggfCBUaGlzIGlzIGdlbmVyYXRlZCBjb2RlIC0gbGluZSBsZW5ndGhzIGFyZSBkaWZmaWN1bHQgdG8gY29udHJvbFxuXG5pbXBvcnQgY2RrID0gcmVxdWlyZSgnQGF3cy1jZGsvY2RrJyk7XG5cbi8qKlxuICogUHJvcGVydGllcyBmb3IgZGVmaW5pbmcgYSBgQVdTOjpEeW5hbW9EQjo6VGFibGVgXG4gKiBAc2VlIGh0dHA6Ly9kb2NzLmF3cy5hbWF6b24uY29tL0FXU0Nsb3VkRm9ybWF0aW9uL2xhdGVzdC9Vc2VyR3VpZGUvYXdzLXJlc291cmNlLWR5bmFtb2RiLXRhYmxlLmh0bWxcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBDZm5UYWJsZVByb3BzIHtcbiAgICAvKipcbiAgICAgKiBgQVdTOjpEeW5hbW9EQjo6VGFibGUuS2V5U2NoZW1hYFxuICAgICAqIEBzZWUgaHR0cDovL2RvY3MuYXdzLmFtYXpvbi5jb20vQVdTQ2xvdWRGb3JtYXRpb24vbGF0ZXN0L1VzZXJHdWlkZS9hd3MtcmVzb3VyY2UtZHluYW1vZGItdGFibGUuaHRtbCNjZm4tZHluYW1vZGItdGFibGUta2V5c2NoZW1hXG4gICAgICovXG4gICAga2V5U2NoZW1hOiBBcnJheTxDZm5UYWJsZS5LZXlTY2hlbWFQcm9wZXJ0eSB8IGNkay5Ub2tlbj4gfCBjZGsuVG9rZW47XG4gICAgLyoqXG4gICAgICogYEFXUzo6RHluYW1vREI6OlRhYmxlLkF0dHJpYnV0ZURlZmluaXRpb25zYFxuICAgICAqIEBzZWUgaHR0cDovL2RvY3MuYXdzLmFtYXpvbi5jb20vQVdTQ2xvdWRGb3JtYXRpb24vbGF0ZXN0L1VzZXJHdWlkZS9hd3MtcmVzb3VyY2UtZHluYW1vZGItdGFibGUuaHRtbCNjZm4tZHluYW1vZGItdGFibGUtYXR0cmlidXRlZGVmXG4gICAgICovXG4gICAgYXR0cmlidXRlRGVmaW5pdGlvbnM/OiBBcnJheTxDZm5UYWJsZS5BdHRyaWJ1dGVEZWZpbml0aW9uUHJvcGVydHkgfCBjZGsuVG9rZW4+IHwgY2RrLlRva2VuO1xuICAgIC8qKlxuICAgICAqIGBBV1M6OkR5bmFtb0RCOjpUYWJsZS5CaWxsaW5nTW9kZWBcbiAgICAgKiBAc2VlIGh0dHA6Ly9kb2NzLmF3cy5hbWF6b24uY29tL0FXU0Nsb3VkRm9ybWF0aW9uL2xhdGVzdC9Vc2VyR3VpZGUvYXdzLXJlc291cmNlLWR5bmFtb2RiLXRhYmxlLmh0bWwjY2ZuLWR5bmFtb2RiLXRhYmxlLWJpbGxpbmdtb2RlXG4gICAgICovXG4gICAgYmlsbGluZ01vZGU/OiBzdHJpbmc7XG4gICAgLyoqXG4gICAgICogYEFXUzo6RHluYW1vREI6OlRhYmxlLkdsb2JhbFNlY29uZGFyeUluZGV4ZXNgXG4gICAgICogQHNlZSBodHRwOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9BV1NDbG91ZEZvcm1hdGlvbi9sYXRlc3QvVXNlckd1aWRlL2F3cy1yZXNvdXJjZS1keW5hbW9kYi10YWJsZS5odG1sI2Nmbi1keW5hbW9kYi10YWJsZS1nc2lcbiAgICAgKi9cbiAgICBnbG9iYWxTZWNvbmRhcnlJbmRleGVzPzogQXJyYXk8Q2ZuVGFibGUuR2xvYmFsU2Vjb25kYXJ5SW5kZXhQcm9wZXJ0eSB8IGNkay5Ub2tlbj4gfCBjZGsuVG9rZW47XG4gICAgLyoqXG4gICAgICogYEFXUzo6RHluYW1vREI6OlRhYmxlLkxvY2FsU2Vjb25kYXJ5SW5kZXhlc2BcbiAgICAgKiBAc2VlIGh0dHA6Ly9kb2NzLmF3cy5hbWF6b24uY29tL0FXU0Nsb3VkRm9ybWF0aW9uL2xhdGVzdC9Vc2VyR3VpZGUvYXdzLXJlc291cmNlLWR5bmFtb2RiLXRhYmxlLmh0bWwjY2ZuLWR5bmFtb2RiLXRhYmxlLWxzaVxuICAgICAqL1xuICAgIGxvY2FsU2Vjb25kYXJ5SW5kZXhlcz86IEFycmF5PENmblRhYmxlLkxvY2FsU2Vjb25kYXJ5SW5kZXhQcm9wZXJ0eSB8IGNkay5Ub2tlbj4gfCBjZGsuVG9rZW47XG4gICAgLyoqXG4gICAgICogYEFXUzo6RHluYW1vREI6OlRhYmxlLlBvaW50SW5UaW1lUmVjb3ZlcnlTcGVjaWZpY2F0aW9uYFxuICAgICAqIEBzZWUgaHR0cDovL2RvY3MuYXdzLmFtYXpvbi5jb20vQVdTQ2xvdWRGb3JtYXRpb24vbGF0ZXN0L1VzZXJHdWlkZS9hd3MtcmVzb3VyY2UtZHluYW1vZGItdGFibGUuaHRtbCNjZm4tZHluYW1vZGItdGFibGUtcG9pbnRpbnRpbWVyZWNvdmVyeXNwZWNpZmljYXRpb25cbiAgICAgKi9cbiAgICBwb2ludEluVGltZVJlY292ZXJ5U3BlY2lmaWNhdGlvbj86IENmblRhYmxlLlBvaW50SW5UaW1lUmVjb3ZlcnlTcGVjaWZpY2F0aW9uUHJvcGVydHkgfCBjZGsuVG9rZW47XG4gICAgLyoqXG4gICAgICogYEFXUzo6RHluYW1vREI6OlRhYmxlLlByb3Zpc2lvbmVkVGhyb3VnaHB1dGBcbiAgICAgKiBAc2VlIGh0dHA6Ly9kb2NzLmF3cy5hbWF6b24uY29tL0FXU0Nsb3VkRm9ybWF0aW9uL2xhdGVzdC9Vc2VyR3VpZGUvYXdzLXJlc291cmNlLWR5bmFtb2RiLXRhYmxlLmh0bWwjY2ZuLWR5bmFtb2RiLXRhYmxlLXByb3Zpc2lvbmVkdGhyb3VnaHB1dFxuICAgICAqL1xuICAgIHByb3Zpc2lvbmVkVGhyb3VnaHB1dD86IENmblRhYmxlLlByb3Zpc2lvbmVkVGhyb3VnaHB1dFByb3BlcnR5IHwgY2RrLlRva2VuO1xuICAgIC8qKlxuICAgICAqIGBBV1M6OkR5bmFtb0RCOjpUYWJsZS5TU0VTcGVjaWZpY2F0aW9uYFxuICAgICAqIEBzZWUgaHR0cDovL2RvY3MuYXdzLmFtYXpvbi5jb20vQVdTQ2xvdWRGb3JtYXRpb24vbGF0ZXN0L1VzZXJHdWlkZS9hd3MtcmVzb3VyY2UtZHluYW1vZGItdGFibGUuaHRtbCNjZm4tZHluYW1vZGItdGFibGUtc3Nlc3BlY2lmaWNhdGlvblxuICAgICAqL1xuICAgIHNzZVNwZWNpZmljYXRpb24/OiBDZm5UYWJsZS5TU0VTcGVjaWZpY2F0aW9uUHJvcGVydHkgfCBjZGsuVG9rZW47XG4gICAgLyoqXG4gICAgICogYEFXUzo6RHluYW1vREI6OlRhYmxlLlN0cmVhbVNwZWNpZmljYXRpb25gXG4gICAgICogQHNlZSBodHRwOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9BV1NDbG91ZEZvcm1hdGlvbi9sYXRlc3QvVXNlckd1aWRlL2F3cy1yZXNvdXJjZS1keW5hbW9kYi10YWJsZS5odG1sI2Nmbi1keW5hbW9kYi10YWJsZS1zdHJlYW1zcGVjaWZpY2F0aW9uXG4gICAgICovXG4gICAgc3RyZWFtU3BlY2lmaWNhdGlvbj86IENmblRhYmxlLlN0cmVhbVNwZWNpZmljYXRpb25Qcm9wZXJ0eSB8IGNkay5Ub2tlbjtcbiAgICAvKipcbiAgICAgKiBgQVdTOjpEeW5hbW9EQjo6VGFibGUuVGFibGVOYW1lYFxuICAgICAqIEBzZWUgaHR0cDovL2RvY3MuYXdzLmFtYXpvbi5jb20vQVdTQ2xvdWRGb3JtYXRpb24vbGF0ZXN0L1VzZXJHdWlkZS9hd3MtcmVzb3VyY2UtZHluYW1vZGItdGFibGUuaHRtbCNjZm4tZHluYW1vZGItdGFibGUtdGFibGVuYW1lXG4gICAgICovXG4gICAgdGFibGVOYW1lPzogc3RyaW5nO1xuICAgIC8qKlxuICAgICAqIGBBV1M6OkR5bmFtb0RCOjpUYWJsZS5UYWdzYFxuICAgICAqIEBzZWUgaHR0cDovL2RvY3MuYXdzLmFtYXpvbi5jb20vQVdTQ2xvdWRGb3JtYXRpb24vbGF0ZXN0L1VzZXJHdWlkZS9hd3MtcmVzb3VyY2UtZHluYW1vZGItdGFibGUuaHRtbCNjZm4tZHluYW1vZGItdGFibGUtdGFnc1xuICAgICAqL1xuICAgIHRhZ3M/OiBjZGsuQ2ZuVGFnW107XG4gICAgLyoqXG4gICAgICogYEFXUzo6RHluYW1vREI6OlRhYmxlLlRpbWVUb0xpdmVTcGVjaWZpY2F0aW9uYFxuICAgICAqIEBzZWUgaHR0cDovL2RvY3MuYXdzLmFtYXpvbi5jb20vQVdTQ2xvdWRGb3JtYXRpb24vbGF0ZXN0L1VzZXJHdWlkZS9hd3MtcmVzb3VyY2UtZHluYW1vZGItdGFibGUuaHRtbCNjZm4tZHluYW1vZGItdGFibGUtdGltZXRvbGl2ZXNwZWNpZmljYXRpb25cbiAgICAgKi9cbiAgICB0aW1lVG9MaXZlU3BlY2lmaWNhdGlvbj86IENmblRhYmxlLlRpbWVUb0xpdmVTcGVjaWZpY2F0aW9uUHJvcGVydHkgfCBjZGsuVG9rZW47XG59XG5cbi8qKlxuICogRGV0ZXJtaW5lIHdoZXRoZXIgdGhlIGdpdmVuIHByb3BlcnRpZXMgbWF0Y2ggdGhvc2Ugb2YgYSBgQ2ZuVGFibGVQcm9wc2BcbiAqXG4gKiBAcGFyYW0gcHJvcGVydGllcyAtIHRoZSBUeXBlU2NyaXB0IHByb3BlcnRpZXMgb2YgYSBgQ2ZuVGFibGVQcm9wc2BcbiAqXG4gKiBAcmV0dXJucyB0aGUgcmVzdWx0IG9mIHRoZSB2YWxpZGF0aW9uLlxuICovXG5mdW5jdGlvbiBDZm5UYWJsZVByb3BzVmFsaWRhdG9yKHByb3BlcnRpZXM6IGFueSk6IGNkay5WYWxpZGF0aW9uUmVzdWx0IHtcbiAgICBpZiAoIWNkay5jYW5JbnNwZWN0KHByb3BlcnRpZXMpKSB7IHJldHVybiBjZGsuVkFMSURBVElPTl9TVUNDRVNTOyB9XG4gICAgY29uc3QgZXJyb3JzID0gbmV3IGNkay5WYWxpZGF0aW9uUmVzdWx0cygpO1xuICAgIGVycm9ycy5jb2xsZWN0KGNkay5wcm9wZXJ0eVZhbGlkYXRvcignYXR0cmlidXRlRGVmaW5pdGlvbnMnLCBjZGsubGlzdFZhbGlkYXRvcihDZm5UYWJsZV9BdHRyaWJ1dGVEZWZpbml0aW9uUHJvcGVydHlWYWxpZGF0b3IpKShwcm9wZXJ0aWVzLmF0dHJpYnV0ZURlZmluaXRpb25zKSk7XG4gICAgZXJyb3JzLmNvbGxlY3QoY2RrLnByb3BlcnR5VmFsaWRhdG9yKCdiaWxsaW5nTW9kZScsIGNkay52YWxpZGF0ZVN0cmluZykocHJvcGVydGllcy5iaWxsaW5nTW9kZSkpO1xuICAgIGVycm9ycy5jb2xsZWN0KGNkay5wcm9wZXJ0eVZhbGlkYXRvcignZ2xvYmFsU2Vjb25kYXJ5SW5kZXhlcycsIGNkay5saXN0VmFsaWRhdG9yKENmblRhYmxlX0dsb2JhbFNlY29uZGFyeUluZGV4UHJvcGVydHlWYWxpZGF0b3IpKShwcm9wZXJ0aWVzLmdsb2JhbFNlY29uZGFyeUluZGV4ZXMpKTtcbiAgICBlcnJvcnMuY29sbGVjdChjZGsucHJvcGVydHlWYWxpZGF0b3IoJ2tleVNjaGVtYScsIGNkay5yZXF1aXJlZFZhbGlkYXRvcikocHJvcGVydGllcy5rZXlTY2hlbWEpKTtcbiAgICBlcnJvcnMuY29sbGVjdChjZGsucHJvcGVydHlWYWxpZGF0b3IoJ2tleVNjaGVtYScsIGNkay5saXN0VmFsaWRhdG9yKENmblRhYmxlX0tleVNjaGVtYVByb3BlcnR5VmFsaWRhdG9yKSkocHJvcGVydGllcy5rZXlTY2hlbWEpKTtcbiAgICBlcnJvcnMuY29sbGVjdChjZGsucHJvcGVydHlWYWxpZGF0b3IoJ2xvY2FsU2Vjb25kYXJ5SW5kZXhlcycsIGNkay5saXN0VmFsaWRhdG9yKENmblRhYmxlX0xvY2FsU2Vjb25kYXJ5SW5kZXhQcm9wZXJ0eVZhbGlkYXRvcikpKHByb3BlcnRpZXMubG9jYWxTZWNvbmRhcnlJbmRleGVzKSk7XG4gICAgZXJyb3JzLmNvbGxlY3QoY2RrLnByb3BlcnR5VmFsaWRhdG9yKCdwb2ludEluVGltZVJlY292ZXJ5U3BlY2lmaWNhdGlvbicsIENmblRhYmxlX1BvaW50SW5UaW1lUmVjb3ZlcnlTcGVjaWZpY2F0aW9uUHJvcGVydHlWYWxpZGF0b3IpKHByb3BlcnRpZXMucG9pbnRJblRpbWVSZWNvdmVyeVNwZWNpZmljYXRpb24pKTtcbiAgICBlcnJvcnMuY29sbGVjdChjZGsucHJvcGVydHlWYWxpZGF0b3IoJ3Byb3Zpc2lvbmVkVGhyb3VnaHB1dCcsIENmblRhYmxlX1Byb3Zpc2lvbmVkVGhyb3VnaHB1dFByb3BlcnR5VmFsaWRhdG9yKShwcm9wZXJ0aWVzLnByb3Zpc2lvbmVkVGhyb3VnaHB1dCkpO1xuICAgIGVycm9ycy5jb2xsZWN0KGNkay5wcm9wZXJ0eVZhbGlkYXRvcignc3NlU3BlY2lmaWNhdGlvbicsIENmblRhYmxlX1NTRVNwZWNpZmljYXRpb25Qcm9wZXJ0eVZhbGlkYXRvcikocHJvcGVydGllcy5zc2VTcGVjaWZpY2F0aW9uKSk7XG4gICAgZXJyb3JzLmNvbGxlY3QoY2RrLnByb3BlcnR5VmFsaWRhdG9yKCdzdHJlYW1TcGVjaWZpY2F0aW9uJywgQ2ZuVGFibGVfU3RyZWFtU3BlY2lmaWNhdGlvblByb3BlcnR5VmFsaWRhdG9yKShwcm9wZXJ0aWVzLnN0cmVhbVNwZWNpZmljYXRpb24pKTtcbiAgICBlcnJvcnMuY29sbGVjdChjZGsucHJvcGVydHlWYWxpZGF0b3IoJ3RhYmxlTmFtZScsIGNkay52YWxpZGF0ZVN0cmluZykocHJvcGVydGllcy50YWJsZU5hbWUpKTtcbiAgICBlcnJvcnMuY29sbGVjdChjZGsucHJvcGVydHlWYWxpZGF0b3IoJ3RhZ3MnLCBjZGsubGlzdFZhbGlkYXRvcihjZGsudmFsaWRhdGVDZm5UYWcpKShwcm9wZXJ0aWVzLnRhZ3MpKTtcbiAgICBlcnJvcnMuY29sbGVjdChjZGsucHJvcGVydHlWYWxpZGF0b3IoJ3RpbWVUb0xpdmVTcGVjaWZpY2F0aW9uJywgQ2ZuVGFibGVfVGltZVRvTGl2ZVNwZWNpZmljYXRpb25Qcm9wZXJ0eVZhbGlkYXRvcikocHJvcGVydGllcy50aW1lVG9MaXZlU3BlY2lmaWNhdGlvbikpO1xuICAgIHJldHVybiBlcnJvcnMud3JhcCgnc3VwcGxpZWQgcHJvcGVydGllcyBub3QgY29ycmVjdCBmb3IgXCJDZm5UYWJsZVByb3BzXCInKTtcbn1cblxuLyoqXG4gKiBSZW5kZXJzIHRoZSBBV1MgQ2xvdWRGb3JtYXRpb24gcHJvcGVydGllcyBvZiBhbiBgQVdTOjpEeW5hbW9EQjo6VGFibGVgIHJlc291cmNlXG4gKlxuICogQHBhcmFtIHByb3BlcnRpZXMgLSB0aGUgVHlwZVNjcmlwdCBwcm9wZXJ0aWVzIG9mIGEgYENmblRhYmxlUHJvcHNgXG4gKlxuICogQHJldHVybnMgdGhlIEFXUyBDbG91ZEZvcm1hdGlvbiBwcm9wZXJ0aWVzIG9mIGFuIGBBV1M6OkR5bmFtb0RCOjpUYWJsZWAgcmVzb3VyY2UuXG4gKi9cbi8vIEB0cy1pZ25vcmUgVFM2MTMzXG5mdW5jdGlvbiBjZm5UYWJsZVByb3BzVG9DbG91ZEZvcm1hdGlvbihwcm9wZXJ0aWVzOiBhbnkpOiBhbnkge1xuICAgIGlmICghY2RrLmNhbkluc3BlY3QocHJvcGVydGllcykpIHsgcmV0dXJuIHByb3BlcnRpZXM7IH1cbiAgICBDZm5UYWJsZVByb3BzVmFsaWRhdG9yKHByb3BlcnRpZXMpLmFzc2VydFN1Y2Nlc3MoKTtcbiAgICByZXR1cm4ge1xuICAgICAgS2V5U2NoZW1hOiBjZGsubGlzdE1hcHBlcihjZm5UYWJsZUtleVNjaGVtYVByb3BlcnR5VG9DbG91ZEZvcm1hdGlvbikocHJvcGVydGllcy5rZXlTY2hlbWEpLFxuICAgICAgQXR0cmlidXRlRGVmaW5pdGlvbnM6IGNkay5saXN0TWFwcGVyKGNmblRhYmxlQXR0cmlidXRlRGVmaW5pdGlvblByb3BlcnR5VG9DbG91ZEZvcm1hdGlvbikocHJvcGVydGllcy5hdHRyaWJ1dGVEZWZpbml0aW9ucyksXG4gICAgICBCaWxsaW5nTW9kZTogY2RrLnN0cmluZ1RvQ2xvdWRGb3JtYXRpb24ocHJvcGVydGllcy5iaWxsaW5nTW9kZSksXG4gICAgICBHbG9iYWxTZWNvbmRhcnlJbmRleGVzOiBjZGsubGlzdE1hcHBlcihjZm5UYWJsZUdsb2JhbFNlY29uZGFyeUluZGV4UHJvcGVydHlUb0Nsb3VkRm9ybWF0aW9uKShwcm9wZXJ0aWVzLmdsb2JhbFNlY29uZGFyeUluZGV4ZXMpLFxuICAgICAgTG9jYWxTZWNvbmRhcnlJbmRleGVzOiBjZGsubGlzdE1hcHBlcihjZm5UYWJsZUxvY2FsU2Vjb25kYXJ5SW5kZXhQcm9wZXJ0eVRvQ2xvdWRGb3JtYXRpb24pKHByb3BlcnRpZXMubG9jYWxTZWNvbmRhcnlJbmRleGVzKSxcbiAgICAgIFBvaW50SW5UaW1lUmVjb3ZlcnlTcGVjaWZpY2F0aW9uOiBjZm5UYWJsZVBvaW50SW5UaW1lUmVjb3ZlcnlTcGVjaWZpY2F0aW9uUHJvcGVydHlUb0Nsb3VkRm9ybWF0aW9uKHByb3BlcnRpZXMucG9pbnRJblRpbWVSZWNvdmVyeVNwZWNpZmljYXRpb24pLFxuICAgICAgUHJvdmlzaW9uZWRUaHJvdWdocHV0OiBjZm5UYWJsZVByb3Zpc2lvbmVkVGhyb3VnaHB1dFByb3BlcnR5VG9DbG91ZEZvcm1hdGlvbihwcm9wZXJ0aWVzLnByb3Zpc2lvbmVkVGhyb3VnaHB1dCksXG4gICAgICBTU0VTcGVjaWZpY2F0aW9uOiBjZm5UYWJsZVNTRVNwZWNpZmljYXRpb25Qcm9wZXJ0eVRvQ2xvdWRGb3JtYXRpb24ocHJvcGVydGllcy5zc2VTcGVjaWZpY2F0aW9uKSxcbiAgICAgIFN0cmVhbVNwZWNpZmljYXRpb246IGNmblRhYmxlU3RyZWFtU3BlY2lmaWNhdGlvblByb3BlcnR5VG9DbG91ZEZvcm1hdGlvbihwcm9wZXJ0aWVzLnN0cmVhbVNwZWNpZmljYXRpb24pLFxuICAgICAgVGFibGVOYW1lOiBjZGsuc3RyaW5nVG9DbG91ZEZvcm1hdGlvbihwcm9wZXJ0aWVzLnRhYmxlTmFtZSksXG4gICAgICBUYWdzOiBjZGsubGlzdE1hcHBlcihjZGsuY2ZuVGFnVG9DbG91ZEZvcm1hdGlvbikocHJvcGVydGllcy50YWdzKSxcbiAgICAgIFRpbWVUb0xpdmVTcGVjaWZpY2F0aW9uOiBjZm5UYWJsZVRpbWVUb0xpdmVTcGVjaWZpY2F0aW9uUHJvcGVydHlUb0Nsb3VkRm9ybWF0aW9uKHByb3BlcnRpZXMudGltZVRvTGl2ZVNwZWNpZmljYXRpb24pLFxuICAgIH07XG59XG5cbi8qKlxuICogQSBDbG91ZEZvcm1hdGlvbiBgQVdTOjpEeW5hbW9EQjo6VGFibGVgXG4gKlxuICogQGNsb3VkZm9ybWF0aW9uUmVzb3VyY2UgQVdTOjpEeW5hbW9EQjo6VGFibGVcbiAqIEBzZWUgaHR0cDovL2RvY3MuYXdzLmFtYXpvbi5jb20vQVdTQ2xvdWRGb3JtYXRpb24vbGF0ZXN0L1VzZXJHdWlkZS9hd3MtcmVzb3VyY2UtZHluYW1vZGItdGFibGUuaHRtbFxuICovXG5leHBvcnQgY2xhc3MgQ2ZuVGFibGUgZXh0ZW5kcyBjZGsuQ2ZuUmVzb3VyY2Uge1xuICAgIC8qKlxuICAgICAqIFRoZSBDbG91ZEZvcm1hdGlvbiByZXNvdXJjZSB0eXBlIG5hbWUgZm9yIHRoaXMgcmVzb3VyY2UgY2xhc3MuXG4gICAgICovXG4gICAgcHVibGljIHN0YXRpYyByZWFkb25seSByZXNvdXJjZVR5cGVOYW1lID0gXCJBV1M6OkR5bmFtb0RCOjpUYWJsZVwiO1xuXG4gICAgLyoqXG4gICAgICogQGNsb3VkZm9ybWF0aW9uQXR0cmlidXRlIEFyblxuICAgICAqL1xuICAgIHB1YmxpYyByZWFkb25seSB0YWJsZUFybjogc3RyaW5nO1xuXG4gICAgLyoqXG4gICAgICogQGNsb3VkZm9ybWF0aW9uQXR0cmlidXRlIFN0cmVhbUFyblxuICAgICAqL1xuICAgIHB1YmxpYyByZWFkb25seSB0YWJsZVN0cmVhbUFybjogc3RyaW5nO1xuICAgIHB1YmxpYyByZWFkb25seSB0YWJsZU5hbWU6IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIFRoZSBgVGFnTWFuYWdlcmAgaGFuZGxlcyBzZXR0aW5nLCByZW1vdmluZyBhbmQgZm9ybWF0dGluZyB0YWdzXG4gICAgICpcbiAgICAgKiBUYWdzIHNob3VsZCBiZSBtYW5hZ2VkIGVpdGhlciBwYXNzaW5nIHRoZW0gYXMgcHJvcGVydGllcyBkdXJpbmdcbiAgICAgKiBpbml0aWF0aW9uIG9yIGJ5IGNhbGxpbmcgbWV0aG9kcyBvbiB0aGlzIG9iamVjdC4gSWYgYm90aCB0ZWNobmlxdWVzIGFyZVxuICAgICAqIHVzZWQgb25seSB0aGUgdGFncyBmcm9tIHRoZSBUYWdNYW5hZ2VyIHdpbGwgYmUgdXNlZC4gYFRhZ2AgKGFzcGVjdClcbiAgICAgKiB3aWxsIHVzZSB0aGUgbWFuYWdlci5cbiAgICAgKi9cbiAgICBwdWJsaWMgcmVhZG9ubHkgdGFnczogY2RrLlRhZ01hbmFnZXI7XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGUgYSBuZXcgYEFXUzo6RHluYW1vREI6OlRhYmxlYC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSBzY29wZSAtIHNjb3BlIGluIHdoaWNoIHRoaXMgcmVzb3VyY2UgaXMgZGVmaW5lZFxuICAgICAqIEBwYXJhbSBpZCAgICAtIHNjb3BlZCBpZCBvZiB0aGUgcmVzb3VyY2VcbiAgICAgKiBAcGFyYW0gcHJvcHMgLSByZXNvdXJjZSBwcm9wZXJ0aWVzXG4gICAgICovXG4gICAgY29uc3RydWN0b3Ioc2NvcGU6IGNkay5Db25zdHJ1Y3QsIGlkOiBzdHJpbmcsIHByb3BzOiBDZm5UYWJsZVByb3BzKSB7XG4gICAgICAgIHN1cGVyKHNjb3BlLCBpZCwgeyB0eXBlOiBDZm5UYWJsZS5yZXNvdXJjZVR5cGVOYW1lLCBwcm9wZXJ0aWVzOiBwcm9wcyB9KTtcbiAgICAgICAgY2RrLnJlcXVpcmVQcm9wZXJ0eShwcm9wcywgJ2tleVNjaGVtYScsIHRoaXMpO1xuICAgICAgICB0aGlzLnRhYmxlQXJuID0gdGhpcy5nZXRBdHQoJ0FybicpLnRvU3RyaW5nKCk7XG4gICAgICAgIHRoaXMudGFibGVTdHJlYW1Bcm4gPSB0aGlzLmdldEF0dCgnU3RyZWFtQXJuJykudG9TdHJpbmcoKTtcbiAgICAgICAgdGhpcy50YWJsZU5hbWUgPSB0aGlzLnJlZi50b1N0cmluZygpO1xuICAgICAgICBjb25zdCB0YWdzID0gcHJvcHMgPT09IHVuZGVmaW5lZCA/IHVuZGVmaW5lZCA6IHByb3BzLnRhZ3M7XG4gICAgICAgIHRoaXMudGFncyA9IG5ldyBjZGsuVGFnTWFuYWdlcihjZGsuVGFnVHlwZS5TdGFuZGFyZCwgXCJBV1M6OkR5bmFtb0RCOjpUYWJsZVwiLCB0YWdzKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgZ2V0IHByb3BlcnR5T3ZlcnJpZGVzKCk6IENmblRhYmxlUHJvcHMge1xuICAgICAgICByZXR1cm4gdGhpcy51bnR5cGVkUHJvcGVydHlPdmVycmlkZXM7XG4gICAgfVxuICAgIHByb3RlY3RlZCByZW5kZXJQcm9wZXJ0aWVzKHByb3BlcnRpZXM6IGFueSk6IHsgW2tleTogc3RyaW5nXTogYW55IH0gIHtcbiAgICAgICAgcmV0dXJuIGNmblRhYmxlUHJvcHNUb0Nsb3VkRm9ybWF0aW9uKHRoaXMubm9kZS5yZXNvbHZlKHByb3BlcnRpZXMpKTtcbiAgICB9XG59XG5cbmV4cG9ydCBuYW1lc3BhY2UgQ2ZuVGFibGUge1xuICAgIC8qKlxuICAgICAqIEBzZWUgaHR0cDovL2RvY3MuYXdzLmFtYXpvbi5jb20vQVdTQ2xvdWRGb3JtYXRpb24vbGF0ZXN0L1VzZXJHdWlkZS9hd3MtcHJvcGVydGllcy1keW5hbW9kYi1hdHRyaWJ1dGVkZWYuaHRtbFxuICAgICAqL1xuICAgIGV4cG9ydCBpbnRlcmZhY2UgQXR0cmlidXRlRGVmaW5pdGlvblByb3BlcnR5IHtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIGBDZm5UYWJsZS5BdHRyaWJ1dGVEZWZpbml0aW9uUHJvcGVydHkuQXR0cmlidXRlTmFtZWBcbiAgICAgICAgICogQHNlZSBodHRwOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9BV1NDbG91ZEZvcm1hdGlvbi9sYXRlc3QvVXNlckd1aWRlL2F3cy1wcm9wZXJ0aWVzLWR5bmFtb2RiLWF0dHJpYnV0ZWRlZi5odG1sI2Nmbi1keW5hbW9kYi1hdHRyaWJ1dGVkZWYtYXR0cmlidXRlbmFtZVxuICAgICAgICAgKi9cbiAgICAgICAgYXR0cmlidXRlTmFtZTogc3RyaW5nO1xuICAgICAgICAvKipcbiAgICAgICAgICogYENmblRhYmxlLkF0dHJpYnV0ZURlZmluaXRpb25Qcm9wZXJ0eS5BdHRyaWJ1dGVUeXBlYFxuICAgICAgICAgKiBAc2VlIGh0dHA6Ly9kb2NzLmF3cy5hbWF6b24uY29tL0FXU0Nsb3VkRm9ybWF0aW9uL2xhdGVzdC9Vc2VyR3VpZGUvYXdzLXByb3BlcnRpZXMtZHluYW1vZGItYXR0cmlidXRlZGVmLmh0bWwjY2ZuLWR5bmFtb2RiLWF0dHJpYnV0ZWRlZi1hdHRyaWJ1dGVuYW1lLWF0dHJpYnV0ZXR5cGVcbiAgICAgICAgICovXG4gICAgICAgIGF0dHJpYnV0ZVR5cGU6IHN0cmluZztcbiAgICB9XG59XG5cbi8qKlxuICogRGV0ZXJtaW5lIHdoZXRoZXIgdGhlIGdpdmVuIHByb3BlcnRpZXMgbWF0Y2ggdGhvc2Ugb2YgYSBgQXR0cmlidXRlRGVmaW5pdGlvblByb3BlcnR5YFxuICpcbiAqIEBwYXJhbSBwcm9wZXJ0aWVzIC0gdGhlIFR5cGVTY3JpcHQgcHJvcGVydGllcyBvZiBhIGBBdHRyaWJ1dGVEZWZpbml0aW9uUHJvcGVydHlgXG4gKlxuICogQHJldHVybnMgdGhlIHJlc3VsdCBvZiB0aGUgdmFsaWRhdGlvbi5cbiAqL1xuZnVuY3Rpb24gQ2ZuVGFibGVfQXR0cmlidXRlRGVmaW5pdGlvblByb3BlcnR5VmFsaWRhdG9yKHByb3BlcnRpZXM6IGFueSk6IGNkay5WYWxpZGF0aW9uUmVzdWx0IHtcbiAgICBpZiAoIWNkay5jYW5JbnNwZWN0KHByb3BlcnRpZXMpKSB7IHJldHVybiBjZGsuVkFMSURBVElPTl9TVUNDRVNTOyB9XG4gICAgY29uc3QgZXJyb3JzID0gbmV3IGNkay5WYWxpZGF0aW9uUmVzdWx0cygpO1xuICAgIGVycm9ycy5jb2xsZWN0KGNkay5wcm9wZXJ0eVZhbGlkYXRvcignYXR0cmlidXRlTmFtZScsIGNkay5yZXF1aXJlZFZhbGlkYXRvcikocHJvcGVydGllcy5hdHRyaWJ1dGVOYW1lKSk7XG4gICAgZXJyb3JzLmNvbGxlY3QoY2RrLnByb3BlcnR5VmFsaWRhdG9yKCdhdHRyaWJ1dGVOYW1lJywgY2RrLnZhbGlkYXRlU3RyaW5nKShwcm9wZXJ0aWVzLmF0dHJpYnV0ZU5hbWUpKTtcbiAgICBlcnJvcnMuY29sbGVjdChjZGsucHJvcGVydHlWYWxpZGF0b3IoJ2F0dHJpYnV0ZVR5cGUnLCBjZGsucmVxdWlyZWRWYWxpZGF0b3IpKHByb3BlcnRpZXMuYXR0cmlidXRlVHlwZSkpO1xuICAgIGVycm9ycy5jb2xsZWN0KGNkay5wcm9wZXJ0eVZhbGlkYXRvcignYXR0cmlidXRlVHlwZScsIGNkay52YWxpZGF0ZVN0cmluZykocHJvcGVydGllcy5hdHRyaWJ1dGVUeXBlKSk7XG4gICAgcmV0dXJuIGVycm9ycy53cmFwKCdzdXBwbGllZCBwcm9wZXJ0aWVzIG5vdCBjb3JyZWN0IGZvciBcIkF0dHJpYnV0ZURlZmluaXRpb25Qcm9wZXJ0eVwiJyk7XG59XG5cbi8qKlxuICogUmVuZGVycyB0aGUgQVdTIENsb3VkRm9ybWF0aW9uIHByb3BlcnRpZXMgb2YgYW4gYEFXUzo6RHluYW1vREI6OlRhYmxlLkF0dHJpYnV0ZURlZmluaXRpb25gIHJlc291cmNlXG4gKlxuICogQHBhcmFtIHByb3BlcnRpZXMgLSB0aGUgVHlwZVNjcmlwdCBwcm9wZXJ0aWVzIG9mIGEgYEF0dHJpYnV0ZURlZmluaXRpb25Qcm9wZXJ0eWBcbiAqXG4gKiBAcmV0dXJucyB0aGUgQVdTIENsb3VkRm9ybWF0aW9uIHByb3BlcnRpZXMgb2YgYW4gYEFXUzo6RHluYW1vREI6OlRhYmxlLkF0dHJpYnV0ZURlZmluaXRpb25gIHJlc291cmNlLlxuICovXG4vLyBAdHMtaWdub3JlIFRTNjEzM1xuZnVuY3Rpb24gY2ZuVGFibGVBdHRyaWJ1dGVEZWZpbml0aW9uUHJvcGVydHlUb0Nsb3VkRm9ybWF0aW9uKHByb3BlcnRpZXM6IGFueSk6IGFueSB7XG4gICAgaWYgKCFjZGsuY2FuSW5zcGVjdChwcm9wZXJ0aWVzKSkgeyByZXR1cm4gcHJvcGVydGllczsgfVxuICAgIENmblRhYmxlX0F0dHJpYnV0ZURlZmluaXRpb25Qcm9wZXJ0eVZhbGlkYXRvcihwcm9wZXJ0aWVzKS5hc3NlcnRTdWNjZXNzKCk7XG4gICAgcmV0dXJuIHtcbiAgICAgIEF0dHJpYnV0ZU5hbWU6IGNkay5zdHJpbmdUb0Nsb3VkRm9ybWF0aW9uKHByb3BlcnRpZXMuYXR0cmlidXRlTmFtZSksXG4gICAgICBBdHRyaWJ1dGVUeXBlOiBjZGsuc3RyaW5nVG9DbG91ZEZvcm1hdGlvbihwcm9wZXJ0aWVzLmF0dHJpYnV0ZVR5cGUpLFxuICAgIH07XG59XG5cbmV4cG9ydCBuYW1lc3BhY2UgQ2ZuVGFibGUge1xuICAgIC8qKlxuICAgICAqIEBzZWUgaHR0cDovL2RvY3MuYXdzLmFtYXpvbi5jb20vQVdTQ2xvdWRGb3JtYXRpb24vbGF0ZXN0L1VzZXJHdWlkZS9hd3MtcHJvcGVydGllcy1keW5hbW9kYi1nc2kuaHRtbFxuICAgICAqL1xuICAgIGV4cG9ydCBpbnRlcmZhY2UgR2xvYmFsU2Vjb25kYXJ5SW5kZXhQcm9wZXJ0eSB7XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBgQ2ZuVGFibGUuR2xvYmFsU2Vjb25kYXJ5SW5kZXhQcm9wZXJ0eS5JbmRleE5hbWVgXG4gICAgICAgICAqIEBzZWUgaHR0cDovL2RvY3MuYXdzLmFtYXpvbi5jb20vQVdTQ2xvdWRGb3JtYXRpb24vbGF0ZXN0L1VzZXJHdWlkZS9hd3MtcHJvcGVydGllcy1keW5hbW9kYi1nc2kuaHRtbCNjZm4tZHluYW1vZGItZ3NpLWluZGV4bmFtZVxuICAgICAgICAgKi9cbiAgICAgICAgaW5kZXhOYW1lOiBzdHJpbmc7XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBgQ2ZuVGFibGUuR2xvYmFsU2Vjb25kYXJ5SW5kZXhQcm9wZXJ0eS5LZXlTY2hlbWFgXG4gICAgICAgICAqIEBzZWUgaHR0cDovL2RvY3MuYXdzLmFtYXpvbi5jb20vQVdTQ2xvdWRGb3JtYXRpb24vbGF0ZXN0L1VzZXJHdWlkZS9hd3MtcHJvcGVydGllcy1keW5hbW9kYi1nc2kuaHRtbCNjZm4tZHluYW1vZGItZ3NpLWtleXNjaGVtYVxuICAgICAgICAgKi9cbiAgICAgICAga2V5U2NoZW1hOiBBcnJheTxDZm5UYWJsZS5LZXlTY2hlbWFQcm9wZXJ0eSB8IGNkay5Ub2tlbj4gfCBjZGsuVG9rZW47XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBgQ2ZuVGFibGUuR2xvYmFsU2Vjb25kYXJ5SW5kZXhQcm9wZXJ0eS5Qcm9qZWN0aW9uYFxuICAgICAgICAgKiBAc2VlIGh0dHA6Ly9kb2NzLmF3cy5hbWF6b24uY29tL0FXU0Nsb3VkRm9ybWF0aW9uL2xhdGVzdC9Vc2VyR3VpZGUvYXdzLXByb3BlcnRpZXMtZHluYW1vZGItZ3NpLmh0bWwjY2ZuLWR5bmFtb2RiLWdzaS1wcm9qZWN0aW9uXG4gICAgICAgICAqL1xuICAgICAgICBwcm9qZWN0aW9uOiBDZm5UYWJsZS5Qcm9qZWN0aW9uUHJvcGVydHkgfCBjZGsuVG9rZW47XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBgQ2ZuVGFibGUuR2xvYmFsU2Vjb25kYXJ5SW5kZXhQcm9wZXJ0eS5Qcm92aXNpb25lZFRocm91Z2hwdXRgXG4gICAgICAgICAqIEBzZWUgaHR0cDovL2RvY3MuYXdzLmFtYXpvbi5jb20vQVdTQ2xvdWRGb3JtYXRpb24vbGF0ZXN0L1VzZXJHdWlkZS9hd3MtcHJvcGVydGllcy1keW5hbW9kYi1nc2kuaHRtbCNjZm4tZHluYW1vZGItZ3NpLXByb3Zpc2lvbmVkdGhyb3VnaHB1dFxuICAgICAgICAgKi9cbiAgICAgICAgcHJvdmlzaW9uZWRUaHJvdWdocHV0PzogQ2ZuVGFibGUuUHJvdmlzaW9uZWRUaHJvdWdocHV0UHJvcGVydHkgfCBjZGsuVG9rZW47XG4gICAgfVxufVxuXG4vKipcbiAqIERldGVybWluZSB3aGV0aGVyIHRoZSBnaXZlbiBwcm9wZXJ0aWVzIG1hdGNoIHRob3NlIG9mIGEgYEdsb2JhbFNlY29uZGFyeUluZGV4UHJvcGVydHlgXG4gKlxuICogQHBhcmFtIHByb3BlcnRpZXMgLSB0aGUgVHlwZVNjcmlwdCBwcm9wZXJ0aWVzIG9mIGEgYEdsb2JhbFNlY29uZGFyeUluZGV4UHJvcGVydHlgXG4gKlxuICogQHJldHVybnMgdGhlIHJlc3VsdCBvZiB0aGUgdmFsaWRhdGlvbi5cbiAqL1xuZnVuY3Rpb24gQ2ZuVGFibGVfR2xvYmFsU2Vjb25kYXJ5SW5kZXhQcm9wZXJ0eVZhbGlkYXRvcihwcm9wZXJ0aWVzOiBhbnkpOiBjZGsuVmFsaWRhdGlvblJlc3VsdCB7XG4gICAgaWYgKCFjZGsuY2FuSW5zcGVjdChwcm9wZXJ0aWVzKSkgeyByZXR1cm4gY2RrLlZBTElEQVRJT05fU1VDQ0VTUzsgfVxuICAgIGNvbnN0IGVycm9ycyA9IG5ldyBjZGsuVmFsaWRhdGlvblJlc3VsdHMoKTtcbiAgICBlcnJvcnMuY29sbGVjdChjZGsucHJvcGVydHlWYWxpZGF0b3IoJ2luZGV4TmFtZScsIGNkay5yZXF1aXJlZFZhbGlkYXRvcikocHJvcGVydGllcy5pbmRleE5hbWUpKTtcbiAgICBlcnJvcnMuY29sbGVjdChjZGsucHJvcGVydHlWYWxpZGF0b3IoJ2luZGV4TmFtZScsIGNkay52YWxpZGF0ZVN0cmluZykocHJvcGVydGllcy5pbmRleE5hbWUpKTtcbiAgICBlcnJvcnMuY29sbGVjdChjZGsucHJvcGVydHlWYWxpZGF0b3IoJ2tleVNjaGVtYScsIGNkay5yZXF1aXJlZFZhbGlkYXRvcikocHJvcGVydGllcy5rZXlTY2hlbWEpKTtcbiAgICBlcnJvcnMuY29sbGVjdChjZGsucHJvcGVydHlWYWxpZGF0b3IoJ2tleVNjaGVtYScsIGNkay5saXN0VmFsaWRhdG9yKENmblRhYmxlX0tleVNjaGVtYVByb3BlcnR5VmFsaWRhdG9yKSkocHJvcGVydGllcy5rZXlTY2hlbWEpKTtcbiAgICBlcnJvcnMuY29sbGVjdChjZGsucHJvcGVydHlWYWxpZGF0b3IoJ3Byb2plY3Rpb24nLCBjZGsucmVxdWlyZWRWYWxpZGF0b3IpKHByb3BlcnRpZXMucHJvamVjdGlvbikpO1xuICAgIGVycm9ycy5jb2xsZWN0KGNkay5wcm9wZXJ0eVZhbGlkYXRvcigncHJvamVjdGlvbicsIENmblRhYmxlX1Byb2plY3Rpb25Qcm9wZXJ0eVZhbGlkYXRvcikocHJvcGVydGllcy5wcm9qZWN0aW9uKSk7XG4gICAgZXJyb3JzLmNvbGxlY3QoY2RrLnByb3BlcnR5VmFsaWRhdG9yKCdwcm92aXNpb25lZFRocm91Z2hwdXQnLCBDZm5UYWJsZV9Qcm92aXNpb25lZFRocm91Z2hwdXRQcm9wZXJ0eVZhbGlkYXRvcikocHJvcGVydGllcy5wcm92aXNpb25lZFRocm91Z2hwdXQpKTtcbiAgICByZXR1cm4gZXJyb3JzLndyYXAoJ3N1cHBsaWVkIHByb3BlcnRpZXMgbm90IGNvcnJlY3QgZm9yIFwiR2xvYmFsU2Vjb25kYXJ5SW5kZXhQcm9wZXJ0eVwiJyk7XG59XG5cbi8qKlxuICogUmVuZGVycyB0aGUgQVdTIENsb3VkRm9ybWF0aW9uIHByb3BlcnRpZXMgb2YgYW4gYEFXUzo6RHluYW1vREI6OlRhYmxlLkdsb2JhbFNlY29uZGFyeUluZGV4YCByZXNvdXJjZVxuICpcbiAqIEBwYXJhbSBwcm9wZXJ0aWVzIC0gdGhlIFR5cGVTY3JpcHQgcHJvcGVydGllcyBvZiBhIGBHbG9iYWxTZWNvbmRhcnlJbmRleFByb3BlcnR5YFxuICpcbiAqIEByZXR1cm5zIHRoZSBBV1MgQ2xvdWRGb3JtYXRpb24gcHJvcGVydGllcyBvZiBhbiBgQVdTOjpEeW5hbW9EQjo6VGFibGUuR2xvYmFsU2Vjb25kYXJ5SW5kZXhgIHJlc291cmNlLlxuICovXG4vLyBAdHMtaWdub3JlIFRTNjEzM1xuZnVuY3Rpb24gY2ZuVGFibGVHbG9iYWxTZWNvbmRhcnlJbmRleFByb3BlcnR5VG9DbG91ZEZvcm1hdGlvbihwcm9wZXJ0aWVzOiBhbnkpOiBhbnkge1xuICAgIGlmICghY2RrLmNhbkluc3BlY3QocHJvcGVydGllcykpIHsgcmV0dXJuIHByb3BlcnRpZXM7IH1cbiAgICBDZm5UYWJsZV9HbG9iYWxTZWNvbmRhcnlJbmRleFByb3BlcnR5VmFsaWRhdG9yKHByb3BlcnRpZXMpLmFzc2VydFN1Y2Nlc3MoKTtcbiAgICByZXR1cm4ge1xuICAgICAgSW5kZXhOYW1lOiBjZGsuc3RyaW5nVG9DbG91ZEZvcm1hdGlvbihwcm9wZXJ0aWVzLmluZGV4TmFtZSksXG4gICAgICBLZXlTY2hlbWE6IGNkay5saXN0TWFwcGVyKGNmblRhYmxlS2V5U2NoZW1hUHJvcGVydHlUb0Nsb3VkRm9ybWF0aW9uKShwcm9wZXJ0aWVzLmtleVNjaGVtYSksXG4gICAgICBQcm9qZWN0aW9uOiBjZm5UYWJsZVByb2plY3Rpb25Qcm9wZXJ0eVRvQ2xvdWRGb3JtYXRpb24ocHJvcGVydGllcy5wcm9qZWN0aW9uKSxcbiAgICAgIFByb3Zpc2lvbmVkVGhyb3VnaHB1dDogY2ZuVGFibGVQcm92aXNpb25lZFRocm91Z2hwdXRQcm9wZXJ0eVRvQ2xvdWRGb3JtYXRpb24ocHJvcGVydGllcy5wcm92aXNpb25lZFRocm91Z2hwdXQpLFxuICAgIH07XG59XG5cbmV4cG9ydCBuYW1lc3BhY2UgQ2ZuVGFibGUge1xuICAgIC8qKlxuICAgICAqIEBzZWUgaHR0cDovL2RvY3MuYXdzLmFtYXpvbi5jb20vQVdTQ2xvdWRGb3JtYXRpb24vbGF0ZXN0L1VzZXJHdWlkZS9hd3MtcHJvcGVydGllcy1keW5hbW9kYi1rZXlzY2hlbWEuaHRtbFxuICAgICAqL1xuICAgIGV4cG9ydCBpbnRlcmZhY2UgS2V5U2NoZW1hUHJvcGVydHkge1xuICAgICAgICAvKipcbiAgICAgICAgICogYENmblRhYmxlLktleVNjaGVtYVByb3BlcnR5LkF0dHJpYnV0ZU5hbWVgXG4gICAgICAgICAqIEBzZWUgaHR0cDovL2RvY3MuYXdzLmFtYXpvbi5jb20vQVdTQ2xvdWRGb3JtYXRpb24vbGF0ZXN0L1VzZXJHdWlkZS9hd3MtcHJvcGVydGllcy1keW5hbW9kYi1rZXlzY2hlbWEuaHRtbCNhd3MtcHJvcGVydGllcy1keW5hbW9kYi1rZXlzY2hlbWEtYXR0cmlidXRlbmFtZVxuICAgICAgICAgKi9cbiAgICAgICAgYXR0cmlidXRlTmFtZTogc3RyaW5nO1xuICAgICAgICAvKipcbiAgICAgICAgICogYENmblRhYmxlLktleVNjaGVtYVByb3BlcnR5LktleVR5cGVgXG4gICAgICAgICAqIEBzZWUgaHR0cDovL2RvY3MuYXdzLmFtYXpvbi5jb20vQVdTQ2xvdWRGb3JtYXRpb24vbGF0ZXN0L1VzZXJHdWlkZS9hd3MtcHJvcGVydGllcy1keW5hbW9kYi1rZXlzY2hlbWEuaHRtbCNhd3MtcHJvcGVydGllcy1keW5hbW9kYi1rZXlzY2hlbWEta2V5dHlwZVxuICAgICAgICAgKi9cbiAgICAgICAga2V5VHlwZTogc3RyaW5nO1xuICAgIH1cbn1cblxuLyoqXG4gKiBEZXRlcm1pbmUgd2hldGhlciB0aGUgZ2l2ZW4gcHJvcGVydGllcyBtYXRjaCB0aG9zZSBvZiBhIGBLZXlTY2hlbWFQcm9wZXJ0eWBcbiAqXG4gKiBAcGFyYW0gcHJvcGVydGllcyAtIHRoZSBUeXBlU2NyaXB0IHByb3BlcnRpZXMgb2YgYSBgS2V5U2NoZW1hUHJvcGVydHlgXG4gKlxuICogQHJldHVybnMgdGhlIHJlc3VsdCBvZiB0aGUgdmFsaWRhdGlvbi5cbiAqL1xuZnVuY3Rpb24gQ2ZuVGFibGVfS2V5U2NoZW1hUHJvcGVydHlWYWxpZGF0b3IocHJvcGVydGllczogYW55KTogY2RrLlZhbGlkYXRpb25SZXN1bHQge1xuICAgIGlmICghY2RrLmNhbkluc3BlY3QocHJvcGVydGllcykpIHsgcmV0dXJuIGNkay5WQUxJREFUSU9OX1NVQ0NFU1M7IH1cbiAgICBjb25zdCBlcnJvcnMgPSBuZXcgY2RrLlZhbGlkYXRpb25SZXN1bHRzKCk7XG4gICAgZXJyb3JzLmNvbGxlY3QoY2RrLnByb3BlcnR5VmFsaWRhdG9yKCdhdHRyaWJ1dGVOYW1lJywgY2RrLnJlcXVpcmVkVmFsaWRhdG9yKShwcm9wZXJ0aWVzLmF0dHJpYnV0ZU5hbWUpKTtcbiAgICBlcnJvcnMuY29sbGVjdChjZGsucHJvcGVydHlWYWxpZGF0b3IoJ2F0dHJpYnV0ZU5hbWUnLCBjZGsudmFsaWRhdGVTdHJpbmcpKHByb3BlcnRpZXMuYXR0cmlidXRlTmFtZSkpO1xuICAgIGVycm9ycy5jb2xsZWN0KGNkay5wcm9wZXJ0eVZhbGlkYXRvcigna2V5VHlwZScsIGNkay5yZXF1aXJlZFZhbGlkYXRvcikocHJvcGVydGllcy5rZXlUeXBlKSk7XG4gICAgZXJyb3JzLmNvbGxlY3QoY2RrLnByb3BlcnR5VmFsaWRhdG9yKCdrZXlUeXBlJywgY2RrLnZhbGlkYXRlU3RyaW5nKShwcm9wZXJ0aWVzLmtleVR5cGUpKTtcbiAgICByZXR1cm4gZXJyb3JzLndyYXAoJ3N1cHBsaWVkIHByb3BlcnRpZXMgbm90IGNvcnJlY3QgZm9yIFwiS2V5U2NoZW1hUHJvcGVydHlcIicpO1xufVxuXG4vKipcbiAqIFJlbmRlcnMgdGhlIEFXUyBDbG91ZEZvcm1hdGlvbiBwcm9wZXJ0aWVzIG9mIGFuIGBBV1M6OkR5bmFtb0RCOjpUYWJsZS5LZXlTY2hlbWFgIHJlc291cmNlXG4gKlxuICogQHBhcmFtIHByb3BlcnRpZXMgLSB0aGUgVHlwZVNjcmlwdCBwcm9wZXJ0aWVzIG9mIGEgYEtleVNjaGVtYVByb3BlcnR5YFxuICpcbiAqIEByZXR1cm5zIHRoZSBBV1MgQ2xvdWRGb3JtYXRpb24gcHJvcGVydGllcyBvZiBhbiBgQVdTOjpEeW5hbW9EQjo6VGFibGUuS2V5U2NoZW1hYCByZXNvdXJjZS5cbiAqL1xuLy8gQHRzLWlnbm9yZSBUUzYxMzNcbmZ1bmN0aW9uIGNmblRhYmxlS2V5U2NoZW1hUHJvcGVydHlUb0Nsb3VkRm9ybWF0aW9uKHByb3BlcnRpZXM6IGFueSk6IGFueSB7XG4gICAgaWYgKCFjZGsuY2FuSW5zcGVjdChwcm9wZXJ0aWVzKSkgeyByZXR1cm4gcHJvcGVydGllczsgfVxuICAgIENmblRhYmxlX0tleVNjaGVtYVByb3BlcnR5VmFsaWRhdG9yKHByb3BlcnRpZXMpLmFzc2VydFN1Y2Nlc3MoKTtcbiAgICByZXR1cm4ge1xuICAgICAgQXR0cmlidXRlTmFtZTogY2RrLnN0cmluZ1RvQ2xvdWRGb3JtYXRpb24ocHJvcGVydGllcy5hdHRyaWJ1dGVOYW1lKSxcbiAgICAgIEtleVR5cGU6IGNkay5zdHJpbmdUb0Nsb3VkRm9ybWF0aW9uKHByb3BlcnRpZXMua2V5VHlwZSksXG4gICAgfTtcbn1cblxuZXhwb3J0IG5hbWVzcGFjZSBDZm5UYWJsZSB7XG4gICAgLyoqXG4gICAgICogQHNlZSBodHRwOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9BV1NDbG91ZEZvcm1hdGlvbi9sYXRlc3QvVXNlckd1aWRlL2F3cy1wcm9wZXJ0aWVzLWR5bmFtb2RiLWxzaS5odG1sXG4gICAgICovXG4gICAgZXhwb3J0IGludGVyZmFjZSBMb2NhbFNlY29uZGFyeUluZGV4UHJvcGVydHkge1xuICAgICAgICAvKipcbiAgICAgICAgICogYENmblRhYmxlLkxvY2FsU2Vjb25kYXJ5SW5kZXhQcm9wZXJ0eS5JbmRleE5hbWVgXG4gICAgICAgICAqIEBzZWUgaHR0cDovL2RvY3MuYXdzLmFtYXpvbi5jb20vQVdTQ2xvdWRGb3JtYXRpb24vbGF0ZXN0L1VzZXJHdWlkZS9hd3MtcHJvcGVydGllcy1keW5hbW9kYi1sc2kuaHRtbCNjZm4tZHluYW1vZGItbHNpLWluZGV4bmFtZVxuICAgICAgICAgKi9cbiAgICAgICAgaW5kZXhOYW1lOiBzdHJpbmc7XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBgQ2ZuVGFibGUuTG9jYWxTZWNvbmRhcnlJbmRleFByb3BlcnR5LktleVNjaGVtYWBcbiAgICAgICAgICogQHNlZSBodHRwOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9BV1NDbG91ZEZvcm1hdGlvbi9sYXRlc3QvVXNlckd1aWRlL2F3cy1wcm9wZXJ0aWVzLWR5bmFtb2RiLWxzaS5odG1sI2Nmbi1keW5hbW9kYi1sc2kta2V5c2NoZW1hXG4gICAgICAgICAqL1xuICAgICAgICBrZXlTY2hlbWE6IEFycmF5PENmblRhYmxlLktleVNjaGVtYVByb3BlcnR5IHwgY2RrLlRva2VuPiB8IGNkay5Ub2tlbjtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIGBDZm5UYWJsZS5Mb2NhbFNlY29uZGFyeUluZGV4UHJvcGVydHkuUHJvamVjdGlvbmBcbiAgICAgICAgICogQHNlZSBodHRwOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9BV1NDbG91ZEZvcm1hdGlvbi9sYXRlc3QvVXNlckd1aWRlL2F3cy1wcm9wZXJ0aWVzLWR5bmFtb2RiLWxzaS5odG1sI2Nmbi1keW5hbW9kYi1sc2ktcHJvamVjdGlvblxuICAgICAgICAgKi9cbiAgICAgICAgcHJvamVjdGlvbjogQ2ZuVGFibGUuUHJvamVjdGlvblByb3BlcnR5IHwgY2RrLlRva2VuO1xuICAgIH1cbn1cblxuLyoqXG4gKiBEZXRlcm1pbmUgd2hldGhlciB0aGUgZ2l2ZW4gcHJvcGVydGllcyBtYXRjaCB0aG9zZSBvZiBhIGBMb2NhbFNlY29uZGFyeUluZGV4UHJvcGVydHlgXG4gKlxuICogQHBhcmFtIHByb3BlcnRpZXMgLSB0aGUgVHlwZVNjcmlwdCBwcm9wZXJ0aWVzIG9mIGEgYExvY2FsU2Vjb25kYXJ5SW5kZXhQcm9wZXJ0eWBcbiAqXG4gKiBAcmV0dXJucyB0aGUgcmVzdWx0IG9mIHRoZSB2YWxpZGF0aW9uLlxuICovXG5mdW5jdGlvbiBDZm5UYWJsZV9Mb2NhbFNlY29uZGFyeUluZGV4UHJvcGVydHlWYWxpZGF0b3IocHJvcGVydGllczogYW55KTogY2RrLlZhbGlkYXRpb25SZXN1bHQge1xuICAgIGlmICghY2RrLmNhbkluc3BlY3QocHJvcGVydGllcykpIHsgcmV0dXJuIGNkay5WQUxJREFUSU9OX1NVQ0NFU1M7IH1cbiAgICBjb25zdCBlcnJvcnMgPSBuZXcgY2RrLlZhbGlkYXRpb25SZXN1bHRzKCk7XG4gICAgZXJyb3JzLmNvbGxlY3QoY2RrLnByb3BlcnR5VmFsaWRhdG9yKCdpbmRleE5hbWUnLCBjZGsucmVxdWlyZWRWYWxpZGF0b3IpKHByb3BlcnRpZXMuaW5kZXhOYW1lKSk7XG4gICAgZXJyb3JzLmNvbGxlY3QoY2RrLnByb3BlcnR5VmFsaWRhdG9yKCdpbmRleE5hbWUnLCBjZGsudmFsaWRhdGVTdHJpbmcpKHByb3BlcnRpZXMuaW5kZXhOYW1lKSk7XG4gICAgZXJyb3JzLmNvbGxlY3QoY2RrLnByb3BlcnR5VmFsaWRhdG9yKCdrZXlTY2hlbWEnLCBjZGsucmVxdWlyZWRWYWxpZGF0b3IpKHByb3BlcnRpZXMua2V5U2NoZW1hKSk7XG4gICAgZXJyb3JzLmNvbGxlY3QoY2RrLnByb3BlcnR5VmFsaWRhdG9yKCdrZXlTY2hlbWEnLCBjZGsubGlzdFZhbGlkYXRvcihDZm5UYWJsZV9LZXlTY2hlbWFQcm9wZXJ0eVZhbGlkYXRvcikpKHByb3BlcnRpZXMua2V5U2NoZW1hKSk7XG4gICAgZXJyb3JzLmNvbGxlY3QoY2RrLnByb3BlcnR5VmFsaWRhdG9yKCdwcm9qZWN0aW9uJywgY2RrLnJlcXVpcmVkVmFsaWRhdG9yKShwcm9wZXJ0aWVzLnByb2plY3Rpb24pKTtcbiAgICBlcnJvcnMuY29sbGVjdChjZGsucHJvcGVydHlWYWxpZGF0b3IoJ3Byb2plY3Rpb24nLCBDZm5UYWJsZV9Qcm9qZWN0aW9uUHJvcGVydHlWYWxpZGF0b3IpKHByb3BlcnRpZXMucHJvamVjdGlvbikpO1xuICAgIHJldHVybiBlcnJvcnMud3JhcCgnc3VwcGxpZWQgcHJvcGVydGllcyBub3QgY29ycmVjdCBmb3IgXCJMb2NhbFNlY29uZGFyeUluZGV4UHJvcGVydHlcIicpO1xufVxuXG4vKipcbiAqIFJlbmRlcnMgdGhlIEFXUyBDbG91ZEZvcm1hdGlvbiBwcm9wZXJ0aWVzIG9mIGFuIGBBV1M6OkR5bmFtb0RCOjpUYWJsZS5Mb2NhbFNlY29uZGFyeUluZGV4YCByZXNvdXJjZVxuICpcbiAqIEBwYXJhbSBwcm9wZXJ0aWVzIC0gdGhlIFR5cGVTY3JpcHQgcHJvcGVydGllcyBvZiBhIGBMb2NhbFNlY29uZGFyeUluZGV4UHJvcGVydHlgXG4gKlxuICogQHJldHVybnMgdGhlIEFXUyBDbG91ZEZvcm1hdGlvbiBwcm9wZXJ0aWVzIG9mIGFuIGBBV1M6OkR5bmFtb0RCOjpUYWJsZS5Mb2NhbFNlY29uZGFyeUluZGV4YCByZXNvdXJjZS5cbiAqL1xuLy8gQHRzLWlnbm9yZSBUUzYxMzNcbmZ1bmN0aW9uIGNmblRhYmxlTG9jYWxTZWNvbmRhcnlJbmRleFByb3BlcnR5VG9DbG91ZEZvcm1hdGlvbihwcm9wZXJ0aWVzOiBhbnkpOiBhbnkge1xuICAgIGlmICghY2RrLmNhbkluc3BlY3QocHJvcGVydGllcykpIHsgcmV0dXJuIHByb3BlcnRpZXM7IH1cbiAgICBDZm5UYWJsZV9Mb2NhbFNlY29uZGFyeUluZGV4UHJvcGVydHlWYWxpZGF0b3IocHJvcGVydGllcykuYXNzZXJ0U3VjY2VzcygpO1xuICAgIHJldHVybiB7XG4gICAgICBJbmRleE5hbWU6IGNkay5zdHJpbmdUb0Nsb3VkRm9ybWF0aW9uKHByb3BlcnRpZXMuaW5kZXhOYW1lKSxcbiAgICAgIEtleVNjaGVtYTogY2RrLmxpc3RNYXBwZXIoY2ZuVGFibGVLZXlTY2hlbWFQcm9wZXJ0eVRvQ2xvdWRGb3JtYXRpb24pKHByb3BlcnRpZXMua2V5U2NoZW1hKSxcbiAgICAgIFByb2plY3Rpb246IGNmblRhYmxlUHJvamVjdGlvblByb3BlcnR5VG9DbG91ZEZvcm1hdGlvbihwcm9wZXJ0aWVzLnByb2plY3Rpb24pLFxuICAgIH07XG59XG5cbmV4cG9ydCBuYW1lc3BhY2UgQ2ZuVGFibGUge1xuICAgIC8qKlxuICAgICAqIEBzZWUgaHR0cDovL2RvY3MuYXdzLmFtYXpvbi5jb20vQVdTQ2xvdWRGb3JtYXRpb24vbGF0ZXN0L1VzZXJHdWlkZS9hd3MtcHJvcGVydGllcy1keW5hbW9kYi10YWJsZS1wb2ludGludGltZXJlY292ZXJ5c3BlY2lmaWNhdGlvbi5odG1sXG4gICAgICovXG4gICAgZXhwb3J0IGludGVyZmFjZSBQb2ludEluVGltZVJlY292ZXJ5U3BlY2lmaWNhdGlvblByb3BlcnR5IHtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIGBDZm5UYWJsZS5Qb2ludEluVGltZVJlY292ZXJ5U3BlY2lmaWNhdGlvblByb3BlcnR5LlBvaW50SW5UaW1lUmVjb3ZlcnlFbmFibGVkYFxuICAgICAgICAgKiBAc2VlIGh0dHA6Ly9kb2NzLmF3cy5hbWF6b24uY29tL0FXU0Nsb3VkRm9ybWF0aW9uL2xhdGVzdC9Vc2VyR3VpZGUvYXdzLXByb3BlcnRpZXMtZHluYW1vZGItdGFibGUtcG9pbnRpbnRpbWVyZWNvdmVyeXNwZWNpZmljYXRpb24uaHRtbCNjZm4tZHluYW1vZGItdGFibGUtcG9pbnRpbnRpbWVyZWNvdmVyeXNwZWNpZmljYXRpb24tcG9pbnRpbnRpbWVyZWNvdmVyeWVuYWJsZWRcbiAgICAgICAgICovXG4gICAgICAgIHBvaW50SW5UaW1lUmVjb3ZlcnlFbmFibGVkPzogYm9vbGVhbiB8IGNkay5Ub2tlbjtcbiAgICB9XG59XG5cbi8qKlxuICogRGV0ZXJtaW5lIHdoZXRoZXIgdGhlIGdpdmVuIHByb3BlcnRpZXMgbWF0Y2ggdGhvc2Ugb2YgYSBgUG9pbnRJblRpbWVSZWNvdmVyeVNwZWNpZmljYXRpb25Qcm9wZXJ0eWBcbiAqXG4gKiBAcGFyYW0gcHJvcGVydGllcyAtIHRoZSBUeXBlU2NyaXB0IHByb3BlcnRpZXMgb2YgYSBgUG9pbnRJblRpbWVSZWNvdmVyeVNwZWNpZmljYXRpb25Qcm9wZXJ0eWBcbiAqXG4gKiBAcmV0dXJucyB0aGUgcmVzdWx0IG9mIHRoZSB2YWxpZGF0aW9uLlxuICovXG5mdW5jdGlvbiBDZm5UYWJsZV9Qb2ludEluVGltZVJlY292ZXJ5U3BlY2lmaWNhdGlvblByb3BlcnR5VmFsaWRhdG9yKHByb3BlcnRpZXM6IGFueSk6IGNkay5WYWxpZGF0aW9uUmVzdWx0IHtcbiAgICBpZiAoIWNkay5jYW5JbnNwZWN0KHByb3BlcnRpZXMpKSB7IHJldHVybiBjZGsuVkFMSURBVElPTl9TVUNDRVNTOyB9XG4gICAgY29uc3QgZXJyb3JzID0gbmV3IGNkay5WYWxpZGF0aW9uUmVzdWx0cygpO1xuICAgIGVycm9ycy5jb2xsZWN0KGNkay5wcm9wZXJ0eVZhbGlkYXRvcigncG9pbnRJblRpbWVSZWNvdmVyeUVuYWJsZWQnLCBjZGsudmFsaWRhdGVCb29sZWFuKShwcm9wZXJ0aWVzLnBvaW50SW5UaW1lUmVjb3ZlcnlFbmFibGVkKSk7XG4gICAgcmV0dXJuIGVycm9ycy53cmFwKCdzdXBwbGllZCBwcm9wZXJ0aWVzIG5vdCBjb3JyZWN0IGZvciBcIlBvaW50SW5UaW1lUmVjb3ZlcnlTcGVjaWZpY2F0aW9uUHJvcGVydHlcIicpO1xufVxuXG4vKipcbiAqIFJlbmRlcnMgdGhlIEFXUyBDbG91ZEZvcm1hdGlvbiBwcm9wZXJ0aWVzIG9mIGFuIGBBV1M6OkR5bmFtb0RCOjpUYWJsZS5Qb2ludEluVGltZVJlY292ZXJ5U3BlY2lmaWNhdGlvbmAgcmVzb3VyY2VcbiAqXG4gKiBAcGFyYW0gcHJvcGVydGllcyAtIHRoZSBUeXBlU2NyaXB0IHByb3BlcnRpZXMgb2YgYSBgUG9pbnRJblRpbWVSZWNvdmVyeVNwZWNpZmljYXRpb25Qcm9wZXJ0eWBcbiAqXG4gKiBAcmV0dXJucyB0aGUgQVdTIENsb3VkRm9ybWF0aW9uIHByb3BlcnRpZXMgb2YgYW4gYEFXUzo6RHluYW1vREI6OlRhYmxlLlBvaW50SW5UaW1lUmVjb3ZlcnlTcGVjaWZpY2F0aW9uYCByZXNvdXJjZS5cbiAqL1xuLy8gQHRzLWlnbm9yZSBUUzYxMzNcbmZ1bmN0aW9uIGNmblRhYmxlUG9pbnRJblRpbWVSZWNvdmVyeVNwZWNpZmljYXRpb25Qcm9wZXJ0eVRvQ2xvdWRGb3JtYXRpb24ocHJvcGVydGllczogYW55KTogYW55IHtcbiAgICBpZiAoIWNkay5jYW5JbnNwZWN0KHByb3BlcnRpZXMpKSB7IHJldHVybiBwcm9wZXJ0aWVzOyB9XG4gICAgQ2ZuVGFibGVfUG9pbnRJblRpbWVSZWNvdmVyeVNwZWNpZmljYXRpb25Qcm9wZXJ0eVZhbGlkYXRvcihwcm9wZXJ0aWVzKS5hc3NlcnRTdWNjZXNzKCk7XG4gICAgcmV0dXJuIHtcbiAgICAgIFBvaW50SW5UaW1lUmVjb3ZlcnlFbmFibGVkOiBjZGsuYm9vbGVhblRvQ2xvdWRGb3JtYXRpb24ocHJvcGVydGllcy5wb2ludEluVGltZVJlY292ZXJ5RW5hYmxlZCksXG4gICAgfTtcbn1cblxuZXhwb3J0IG5hbWVzcGFjZSBDZm5UYWJsZSB7XG4gICAgLyoqXG4gICAgICogQHNlZSBodHRwOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9BV1NDbG91ZEZvcm1hdGlvbi9sYXRlc3QvVXNlckd1aWRlL2F3cy1wcm9wZXJ0aWVzLWR5bmFtb2RiLXByb2plY3Rpb25vYmplY3QuaHRtbFxuICAgICAqL1xuICAgIGV4cG9ydCBpbnRlcmZhY2UgUHJvamVjdGlvblByb3BlcnR5IHtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIGBDZm5UYWJsZS5Qcm9qZWN0aW9uUHJvcGVydHkuTm9uS2V5QXR0cmlidXRlc2BcbiAgICAgICAgICogQHNlZSBodHRwOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9BV1NDbG91ZEZvcm1hdGlvbi9sYXRlc3QvVXNlckd1aWRlL2F3cy1wcm9wZXJ0aWVzLWR5bmFtb2RiLXByb2plY3Rpb25vYmplY3QuaHRtbCNjZm4tZHluYW1vZGItcHJvamVjdGlvbm9iai1ub25rZXlhdHRcbiAgICAgICAgICovXG4gICAgICAgIG5vbktleUF0dHJpYnV0ZXM/OiBzdHJpbmdbXTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIGBDZm5UYWJsZS5Qcm9qZWN0aW9uUHJvcGVydHkuUHJvamVjdGlvblR5cGVgXG4gICAgICAgICAqIEBzZWUgaHR0cDovL2RvY3MuYXdzLmFtYXpvbi5jb20vQVdTQ2xvdWRGb3JtYXRpb24vbGF0ZXN0L1VzZXJHdWlkZS9hd3MtcHJvcGVydGllcy1keW5hbW9kYi1wcm9qZWN0aW9ub2JqZWN0Lmh0bWwjY2ZuLWR5bmFtb2RiLXByb2plY3Rpb25vYmotcHJvanR5cGVcbiAgICAgICAgICovXG4gICAgICAgIHByb2plY3Rpb25UeXBlPzogc3RyaW5nO1xuICAgIH1cbn1cblxuLyoqXG4gKiBEZXRlcm1pbmUgd2hldGhlciB0aGUgZ2l2ZW4gcHJvcGVydGllcyBtYXRjaCB0aG9zZSBvZiBhIGBQcm9qZWN0aW9uUHJvcGVydHlgXG4gKlxuICogQHBhcmFtIHByb3BlcnRpZXMgLSB0aGUgVHlwZVNjcmlwdCBwcm9wZXJ0aWVzIG9mIGEgYFByb2plY3Rpb25Qcm9wZXJ0eWBcbiAqXG4gKiBAcmV0dXJucyB0aGUgcmVzdWx0IG9mIHRoZSB2YWxpZGF0aW9uLlxuICovXG5mdW5jdGlvbiBDZm5UYWJsZV9Qcm9qZWN0aW9uUHJvcGVydHlWYWxpZGF0b3IocHJvcGVydGllczogYW55KTogY2RrLlZhbGlkYXRpb25SZXN1bHQge1xuICAgIGlmICghY2RrLmNhbkluc3BlY3QocHJvcGVydGllcykpIHsgcmV0dXJuIGNkay5WQUxJREFUSU9OX1NVQ0NFU1M7IH1cbiAgICBjb25zdCBlcnJvcnMgPSBuZXcgY2RrLlZhbGlkYXRpb25SZXN1bHRzKCk7XG4gICAgZXJyb3JzLmNvbGxlY3QoY2RrLnByb3BlcnR5VmFsaWRhdG9yKCdub25LZXlBdHRyaWJ1dGVzJywgY2RrLmxpc3RWYWxpZGF0b3IoY2RrLnZhbGlkYXRlU3RyaW5nKSkocHJvcGVydGllcy5ub25LZXlBdHRyaWJ1dGVzKSk7XG4gICAgZXJyb3JzLmNvbGxlY3QoY2RrLnByb3BlcnR5VmFsaWRhdG9yKCdwcm9qZWN0aW9uVHlwZScsIGNkay52YWxpZGF0ZVN0cmluZykocHJvcGVydGllcy5wcm9qZWN0aW9uVHlwZSkpO1xuICAgIHJldHVybiBlcnJvcnMud3JhcCgnc3VwcGxpZWQgcHJvcGVydGllcyBub3QgY29ycmVjdCBmb3IgXCJQcm9qZWN0aW9uUHJvcGVydHlcIicpO1xufVxuXG4vKipcbiAqIFJlbmRlcnMgdGhlIEFXUyBDbG91ZEZvcm1hdGlvbiBwcm9wZXJ0aWVzIG9mIGFuIGBBV1M6OkR5bmFtb0RCOjpUYWJsZS5Qcm9qZWN0aW9uYCByZXNvdXJjZVxuICpcbiAqIEBwYXJhbSBwcm9wZXJ0aWVzIC0gdGhlIFR5cGVTY3JpcHQgcHJvcGVydGllcyBvZiBhIGBQcm9qZWN0aW9uUHJvcGVydHlgXG4gKlxuICogQHJldHVybnMgdGhlIEFXUyBDbG91ZEZvcm1hdGlvbiBwcm9wZXJ0aWVzIG9mIGFuIGBBV1M6OkR5bmFtb0RCOjpUYWJsZS5Qcm9qZWN0aW9uYCByZXNvdXJjZS5cbiAqL1xuLy8gQHRzLWlnbm9yZSBUUzYxMzNcbmZ1bmN0aW9uIGNmblRhYmxlUHJvamVjdGlvblByb3BlcnR5VG9DbG91ZEZvcm1hdGlvbihwcm9wZXJ0aWVzOiBhbnkpOiBhbnkge1xuICAgIGlmICghY2RrLmNhbkluc3BlY3QocHJvcGVydGllcykpIHsgcmV0dXJuIHByb3BlcnRpZXM7IH1cbiAgICBDZm5UYWJsZV9Qcm9qZWN0aW9uUHJvcGVydHlWYWxpZGF0b3IocHJvcGVydGllcykuYXNzZXJ0U3VjY2VzcygpO1xuICAgIHJldHVybiB7XG4gICAgICBOb25LZXlBdHRyaWJ1dGVzOiBjZGsubGlzdE1hcHBlcihjZGsuc3RyaW5nVG9DbG91ZEZvcm1hdGlvbikocHJvcGVydGllcy5ub25LZXlBdHRyaWJ1dGVzKSxcbiAgICAgIFByb2plY3Rpb25UeXBlOiBjZGsuc3RyaW5nVG9DbG91ZEZvcm1hdGlvbihwcm9wZXJ0aWVzLnByb2plY3Rpb25UeXBlKSxcbiAgICB9O1xufVxuXG5leHBvcnQgbmFtZXNwYWNlIENmblRhYmxlIHtcbiAgICAvKipcbiAgICAgKiBAc2VlIGh0dHA6Ly9kb2NzLmF3cy5hbWF6b24uY29tL0FXU0Nsb3VkRm9ybWF0aW9uL2xhdGVzdC9Vc2VyR3VpZGUvYXdzLXByb3BlcnRpZXMtZHluYW1vZGItcHJvdmlzaW9uZWR0aHJvdWdocHV0Lmh0bWxcbiAgICAgKi9cbiAgICBleHBvcnQgaW50ZXJmYWNlIFByb3Zpc2lvbmVkVGhyb3VnaHB1dFByb3BlcnR5IHtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIGBDZm5UYWJsZS5Qcm92aXNpb25lZFRocm91Z2hwdXRQcm9wZXJ0eS5SZWFkQ2FwYWNpdHlVbml0c2BcbiAgICAgICAgICogQHNlZSBodHRwOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9BV1NDbG91ZEZvcm1hdGlvbi9sYXRlc3QvVXNlckd1aWRlL2F3cy1wcm9wZXJ0aWVzLWR5bmFtb2RiLXByb3Zpc2lvbmVkdGhyb3VnaHB1dC5odG1sI2Nmbi1keW5hbW9kYi1wcm92aXNpb25lZHRocm91Z2hwdXQtcmVhZGNhcGFjaXR5dW5pdHNcbiAgICAgICAgICovXG4gICAgICAgIHJlYWRDYXBhY2l0eVVuaXRzOiBudW1iZXIgfCBjZGsuVG9rZW47XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBgQ2ZuVGFibGUuUHJvdmlzaW9uZWRUaHJvdWdocHV0UHJvcGVydHkuV3JpdGVDYXBhY2l0eVVuaXRzYFxuICAgICAgICAgKiBAc2VlIGh0dHA6Ly9kb2NzLmF3cy5hbWF6b24uY29tL0FXU0Nsb3VkRm9ybWF0aW9uL2xhdGVzdC9Vc2VyR3VpZGUvYXdzLXByb3BlcnRpZXMtZHluYW1vZGItcHJvdmlzaW9uZWR0aHJvdWdocHV0Lmh0bWwjY2ZuLWR5bmFtb2RiLXByb3Zpc2lvbmVkdGhyb3VnaHB1dC13cml0ZWNhcGFjaXR5dW5pdHNcbiAgICAgICAgICovXG4gICAgICAgIHdyaXRlQ2FwYWNpdHlVbml0czogbnVtYmVyIHwgY2RrLlRva2VuO1xuICAgIH1cbn1cblxuLyoqXG4gKiBEZXRlcm1pbmUgd2hldGhlciB0aGUgZ2l2ZW4gcHJvcGVydGllcyBtYXRjaCB0aG9zZSBvZiBhIGBQcm92aXNpb25lZFRocm91Z2hwdXRQcm9wZXJ0eWBcbiAqXG4gKiBAcGFyYW0gcHJvcGVydGllcyAtIHRoZSBUeXBlU2NyaXB0IHByb3BlcnRpZXMgb2YgYSBgUHJvdmlzaW9uZWRUaHJvdWdocHV0UHJvcGVydHlgXG4gKlxuICogQHJldHVybnMgdGhlIHJlc3VsdCBvZiB0aGUgdmFsaWRhdGlvbi5cbiAqL1xuZnVuY3Rpb24gQ2ZuVGFibGVfUHJvdmlzaW9uZWRUaHJvdWdocHV0UHJvcGVydHlWYWxpZGF0b3IocHJvcGVydGllczogYW55KTogY2RrLlZhbGlkYXRpb25SZXN1bHQge1xuICAgIGlmICghY2RrLmNhbkluc3BlY3QocHJvcGVydGllcykpIHsgcmV0dXJuIGNkay5WQUxJREFUSU9OX1NVQ0NFU1M7IH1cbiAgICBjb25zdCBlcnJvcnMgPSBuZXcgY2RrLlZhbGlkYXRpb25SZXN1bHRzKCk7XG4gICAgZXJyb3JzLmNvbGxlY3QoY2RrLnByb3BlcnR5VmFsaWRhdG9yKCdyZWFkQ2FwYWNpdHlVbml0cycsIGNkay5yZXF1aXJlZFZhbGlkYXRvcikocHJvcGVydGllcy5yZWFkQ2FwYWNpdHlVbml0cykpO1xuICAgIGVycm9ycy5jb2xsZWN0KGNkay5wcm9wZXJ0eVZhbGlkYXRvcigncmVhZENhcGFjaXR5VW5pdHMnLCBjZGsudmFsaWRhdGVOdW1iZXIpKHByb3BlcnRpZXMucmVhZENhcGFjaXR5VW5pdHMpKTtcbiAgICBlcnJvcnMuY29sbGVjdChjZGsucHJvcGVydHlWYWxpZGF0b3IoJ3dyaXRlQ2FwYWNpdHlVbml0cycsIGNkay5yZXF1aXJlZFZhbGlkYXRvcikocHJvcGVydGllcy53cml0ZUNhcGFjaXR5VW5pdHMpKTtcbiAgICBlcnJvcnMuY29sbGVjdChjZGsucHJvcGVydHlWYWxpZGF0b3IoJ3dyaXRlQ2FwYWNpdHlVbml0cycsIGNkay52YWxpZGF0ZU51bWJlcikocHJvcGVydGllcy53cml0ZUNhcGFjaXR5VW5pdHMpKTtcbiAgICByZXR1cm4gZXJyb3JzLndyYXAoJ3N1cHBsaWVkIHByb3BlcnRpZXMgbm90IGNvcnJlY3QgZm9yIFwiUHJvdmlzaW9uZWRUaHJvdWdocHV0UHJvcGVydHlcIicpO1xufVxuXG4vKipcbiAqIFJlbmRlcnMgdGhlIEFXUyBDbG91ZEZvcm1hdGlvbiBwcm9wZXJ0aWVzIG9mIGFuIGBBV1M6OkR5bmFtb0RCOjpUYWJsZS5Qcm92aXNpb25lZFRocm91Z2hwdXRgIHJlc291cmNlXG4gKlxuICogQHBhcmFtIHByb3BlcnRpZXMgLSB0aGUgVHlwZVNjcmlwdCBwcm9wZXJ0aWVzIG9mIGEgYFByb3Zpc2lvbmVkVGhyb3VnaHB1dFByb3BlcnR5YFxuICpcbiAqIEByZXR1cm5zIHRoZSBBV1MgQ2xvdWRGb3JtYXRpb24gcHJvcGVydGllcyBvZiBhbiBgQVdTOjpEeW5hbW9EQjo6VGFibGUuUHJvdmlzaW9uZWRUaHJvdWdocHV0YCByZXNvdXJjZS5cbiAqL1xuLy8gQHRzLWlnbm9yZSBUUzYxMzNcbmZ1bmN0aW9uIGNmblRhYmxlUHJvdmlzaW9uZWRUaHJvdWdocHV0UHJvcGVydHlUb0Nsb3VkRm9ybWF0aW9uKHByb3BlcnRpZXM6IGFueSk6IGFueSB7XG4gICAgaWYgKCFjZGsuY2FuSW5zcGVjdChwcm9wZXJ0aWVzKSkgeyByZXR1cm4gcHJvcGVydGllczsgfVxuICAgIENmblRhYmxlX1Byb3Zpc2lvbmVkVGhyb3VnaHB1dFByb3BlcnR5VmFsaWRhdG9yKHByb3BlcnRpZXMpLmFzc2VydFN1Y2Nlc3MoKTtcbiAgICByZXR1cm4ge1xuICAgICAgUmVhZENhcGFjaXR5VW5pdHM6IGNkay5udW1iZXJUb0Nsb3VkRm9ybWF0aW9uKHByb3BlcnRpZXMucmVhZENhcGFjaXR5VW5pdHMpLFxuICAgICAgV3JpdGVDYXBhY2l0eVVuaXRzOiBjZGsubnVtYmVyVG9DbG91ZEZvcm1hdGlvbihwcm9wZXJ0aWVzLndyaXRlQ2FwYWNpdHlVbml0cyksXG4gICAgfTtcbn1cblxuZXhwb3J0IG5hbWVzcGFjZSBDZm5UYWJsZSB7XG4gICAgLyoqXG4gICAgICogQHNlZSBodHRwOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9BV1NDbG91ZEZvcm1hdGlvbi9sYXRlc3QvVXNlckd1aWRlL2F3cy1wcm9wZXJ0aWVzLWR5bmFtb2RiLXRhYmxlLXNzZXNwZWNpZmljYXRpb24uaHRtbFxuICAgICAqL1xuICAgIGV4cG9ydCBpbnRlcmZhY2UgU1NFU3BlY2lmaWNhdGlvblByb3BlcnR5IHtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIGBDZm5UYWJsZS5TU0VTcGVjaWZpY2F0aW9uUHJvcGVydHkuU1NFRW5hYmxlZGBcbiAgICAgICAgICogQHNlZSBodHRwOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9BV1NDbG91ZEZvcm1hdGlvbi9sYXRlc3QvVXNlckd1aWRlL2F3cy1wcm9wZXJ0aWVzLWR5bmFtb2RiLXRhYmxlLXNzZXNwZWNpZmljYXRpb24uaHRtbCNjZm4tZHluYW1vZGItdGFibGUtc3Nlc3BlY2lmaWNhdGlvbi1zc2VlbmFibGVkXG4gICAgICAgICAqL1xuICAgICAgICBzc2VFbmFibGVkOiBib29sZWFuIHwgY2RrLlRva2VuO1xuICAgIH1cbn1cblxuLyoqXG4gKiBEZXRlcm1pbmUgd2hldGhlciB0aGUgZ2l2ZW4gcHJvcGVydGllcyBtYXRjaCB0aG9zZSBvZiBhIGBTU0VTcGVjaWZpY2F0aW9uUHJvcGVydHlgXG4gKlxuICogQHBhcmFtIHByb3BlcnRpZXMgLSB0aGUgVHlwZVNjcmlwdCBwcm9wZXJ0aWVzIG9mIGEgYFNTRVNwZWNpZmljYXRpb25Qcm9wZXJ0eWBcbiAqXG4gKiBAcmV0dXJucyB0aGUgcmVzdWx0IG9mIHRoZSB2YWxpZGF0aW9uLlxuICovXG5mdW5jdGlvbiBDZm5UYWJsZV9TU0VTcGVjaWZpY2F0aW9uUHJvcGVydHlWYWxpZGF0b3IocHJvcGVydGllczogYW55KTogY2RrLlZhbGlkYXRpb25SZXN1bHQge1xuICAgIGlmICghY2RrLmNhbkluc3BlY3QocHJvcGVydGllcykpIHsgcmV0dXJuIGNkay5WQUxJREFUSU9OX1NVQ0NFU1M7IH1cbiAgICBjb25zdCBlcnJvcnMgPSBuZXcgY2RrLlZhbGlkYXRpb25SZXN1bHRzKCk7XG4gICAgZXJyb3JzLmNvbGxlY3QoY2RrLnByb3BlcnR5VmFsaWRhdG9yKCdzc2VFbmFibGVkJywgY2RrLnJlcXVpcmVkVmFsaWRhdG9yKShwcm9wZXJ0aWVzLnNzZUVuYWJsZWQpKTtcbiAgICBlcnJvcnMuY29sbGVjdChjZGsucHJvcGVydHlWYWxpZGF0b3IoJ3NzZUVuYWJsZWQnLCBjZGsudmFsaWRhdGVCb29sZWFuKShwcm9wZXJ0aWVzLnNzZUVuYWJsZWQpKTtcbiAgICByZXR1cm4gZXJyb3JzLndyYXAoJ3N1cHBsaWVkIHByb3BlcnRpZXMgbm90IGNvcnJlY3QgZm9yIFwiU1NFU3BlY2lmaWNhdGlvblByb3BlcnR5XCInKTtcbn1cblxuLyoqXG4gKiBSZW5kZXJzIHRoZSBBV1MgQ2xvdWRGb3JtYXRpb24gcHJvcGVydGllcyBvZiBhbiBgQVdTOjpEeW5hbW9EQjo6VGFibGUuU1NFU3BlY2lmaWNhdGlvbmAgcmVzb3VyY2VcbiAqXG4gKiBAcGFyYW0gcHJvcGVydGllcyAtIHRoZSBUeXBlU2NyaXB0IHByb3BlcnRpZXMgb2YgYSBgU1NFU3BlY2lmaWNhdGlvblByb3BlcnR5YFxuICpcbiAqIEByZXR1cm5zIHRoZSBBV1MgQ2xvdWRGb3JtYXRpb24gcHJvcGVydGllcyBvZiBhbiBgQVdTOjpEeW5hbW9EQjo6VGFibGUuU1NFU3BlY2lmaWNhdGlvbmAgcmVzb3VyY2UuXG4gKi9cbi8vIEB0cy1pZ25vcmUgVFM2MTMzXG5mdW5jdGlvbiBjZm5UYWJsZVNTRVNwZWNpZmljYXRpb25Qcm9wZXJ0eVRvQ2xvdWRGb3JtYXRpb24ocHJvcGVydGllczogYW55KTogYW55IHtcbiAgICBpZiAoIWNkay5jYW5JbnNwZWN0KHByb3BlcnRpZXMpKSB7IHJldHVybiBwcm9wZXJ0aWVzOyB9XG4gICAgQ2ZuVGFibGVfU1NFU3BlY2lmaWNhdGlvblByb3BlcnR5VmFsaWRhdG9yKHByb3BlcnRpZXMpLmFzc2VydFN1Y2Nlc3MoKTtcbiAgICByZXR1cm4ge1xuICAgICAgU1NFRW5hYmxlZDogY2RrLmJvb2xlYW5Ub0Nsb3VkRm9ybWF0aW9uKHByb3BlcnRpZXMuc3NlRW5hYmxlZCksXG4gICAgfTtcbn1cblxuZXhwb3J0IG5hbWVzcGFjZSBDZm5UYWJsZSB7XG4gICAgLyoqXG4gICAgICogQHNlZSBodHRwOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9BV1NDbG91ZEZvcm1hdGlvbi9sYXRlc3QvVXNlckd1aWRlL2F3cy1wcm9wZXJ0aWVzLWR5bmFtb2RiLXN0cmVhbXNwZWNpZmljYXRpb24uaHRtbFxuICAgICAqL1xuICAgIGV4cG9ydCBpbnRlcmZhY2UgU3RyZWFtU3BlY2lmaWNhdGlvblByb3BlcnR5IHtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIGBDZm5UYWJsZS5TdHJlYW1TcGVjaWZpY2F0aW9uUHJvcGVydHkuU3RyZWFtVmlld1R5cGVgXG4gICAgICAgICAqIEBzZWUgaHR0cDovL2RvY3MuYXdzLmFtYXpvbi5jb20vQVdTQ2xvdWRGb3JtYXRpb24vbGF0ZXN0L1VzZXJHdWlkZS9hd3MtcHJvcGVydGllcy1keW5hbW9kYi1zdHJlYW1zcGVjaWZpY2F0aW9uLmh0bWwjY2ZuLWR5bmFtb2RiLXN0cmVhbXNwZWNpZmljYXRpb24tc3RyZWFtdmlld3R5cGVcbiAgICAgICAgICovXG4gICAgICAgIHN0cmVhbVZpZXdUeXBlOiBzdHJpbmc7XG4gICAgfVxufVxuXG4vKipcbiAqIERldGVybWluZSB3aGV0aGVyIHRoZSBnaXZlbiBwcm9wZXJ0aWVzIG1hdGNoIHRob3NlIG9mIGEgYFN0cmVhbVNwZWNpZmljYXRpb25Qcm9wZXJ0eWBcbiAqXG4gKiBAcGFyYW0gcHJvcGVydGllcyAtIHRoZSBUeXBlU2NyaXB0IHByb3BlcnRpZXMgb2YgYSBgU3RyZWFtU3BlY2lmaWNhdGlvblByb3BlcnR5YFxuICpcbiAqIEByZXR1cm5zIHRoZSByZXN1bHQgb2YgdGhlIHZhbGlkYXRpb24uXG4gKi9cbmZ1bmN0aW9uIENmblRhYmxlX1N0cmVhbVNwZWNpZmljYXRpb25Qcm9wZXJ0eVZhbGlkYXRvcihwcm9wZXJ0aWVzOiBhbnkpOiBjZGsuVmFsaWRhdGlvblJlc3VsdCB7XG4gICAgaWYgKCFjZGsuY2FuSW5zcGVjdChwcm9wZXJ0aWVzKSkgeyByZXR1cm4gY2RrLlZBTElEQVRJT05fU1VDQ0VTUzsgfVxuICAgIGNvbnN0IGVycm9ycyA9IG5ldyBjZGsuVmFsaWRhdGlvblJlc3VsdHMoKTtcbiAgICBlcnJvcnMuY29sbGVjdChjZGsucHJvcGVydHlWYWxpZGF0b3IoJ3N0cmVhbVZpZXdUeXBlJywgY2RrLnJlcXVpcmVkVmFsaWRhdG9yKShwcm9wZXJ0aWVzLnN0cmVhbVZpZXdUeXBlKSk7XG4gICAgZXJyb3JzLmNvbGxlY3QoY2RrLnByb3BlcnR5VmFsaWRhdG9yKCdzdHJlYW1WaWV3VHlwZScsIGNkay52YWxpZGF0ZVN0cmluZykocHJvcGVydGllcy5zdHJlYW1WaWV3VHlwZSkpO1xuICAgIHJldHVybiBlcnJvcnMud3JhcCgnc3VwcGxpZWQgcHJvcGVydGllcyBub3QgY29ycmVjdCBmb3IgXCJTdHJlYW1TcGVjaWZpY2F0aW9uUHJvcGVydHlcIicpO1xufVxuXG4vKipcbiAqIFJlbmRlcnMgdGhlIEFXUyBDbG91ZEZvcm1hdGlvbiBwcm9wZXJ0aWVzIG9mIGFuIGBBV1M6OkR5bmFtb0RCOjpUYWJsZS5TdHJlYW1TcGVjaWZpY2F0aW9uYCByZXNvdXJjZVxuICpcbiAqIEBwYXJhbSBwcm9wZXJ0aWVzIC0gdGhlIFR5cGVTY3JpcHQgcHJvcGVydGllcyBvZiBhIGBTdHJlYW1TcGVjaWZpY2F0aW9uUHJvcGVydHlgXG4gKlxuICogQHJldHVybnMgdGhlIEFXUyBDbG91ZEZvcm1hdGlvbiBwcm9wZXJ0aWVzIG9mIGFuIGBBV1M6OkR5bmFtb0RCOjpUYWJsZS5TdHJlYW1TcGVjaWZpY2F0aW9uYCByZXNvdXJjZS5cbiAqL1xuLy8gQHRzLWlnbm9yZSBUUzYxMzNcbmZ1bmN0aW9uIGNmblRhYmxlU3RyZWFtU3BlY2lmaWNhdGlvblByb3BlcnR5VG9DbG91ZEZvcm1hdGlvbihwcm9wZXJ0aWVzOiBhbnkpOiBhbnkge1xuICAgIGlmICghY2RrLmNhbkluc3BlY3QocHJvcGVydGllcykpIHsgcmV0dXJuIHByb3BlcnRpZXM7IH1cbiAgICBDZm5UYWJsZV9TdHJlYW1TcGVjaWZpY2F0aW9uUHJvcGVydHlWYWxpZGF0b3IocHJvcGVydGllcykuYXNzZXJ0U3VjY2VzcygpO1xuICAgIHJldHVybiB7XG4gICAgICBTdHJlYW1WaWV3VHlwZTogY2RrLnN0cmluZ1RvQ2xvdWRGb3JtYXRpb24ocHJvcGVydGllcy5zdHJlYW1WaWV3VHlwZSksXG4gICAgfTtcbn1cblxuZXhwb3J0IG5hbWVzcGFjZSBDZm5UYWJsZSB7XG4gICAgLyoqXG4gICAgICogQHNlZSBodHRwOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9BV1NDbG91ZEZvcm1hdGlvbi9sYXRlc3QvVXNlckd1aWRlL2F3cy1wcm9wZXJ0aWVzLWR5bmFtb2RiLXRpbWV0b2xpdmVzcGVjaWZpY2F0aW9uLmh0bWxcbiAgICAgKi9cbiAgICBleHBvcnQgaW50ZXJmYWNlIFRpbWVUb0xpdmVTcGVjaWZpY2F0aW9uUHJvcGVydHkge1xuICAgICAgICAvKipcbiAgICAgICAgICogYENmblRhYmxlLlRpbWVUb0xpdmVTcGVjaWZpY2F0aW9uUHJvcGVydHkuQXR0cmlidXRlTmFtZWBcbiAgICAgICAgICogQHNlZSBodHRwOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9BV1NDbG91ZEZvcm1hdGlvbi9sYXRlc3QvVXNlckd1aWRlL2F3cy1wcm9wZXJ0aWVzLWR5bmFtb2RiLXRpbWV0b2xpdmVzcGVjaWZpY2F0aW9uLmh0bWwjY2ZuLWR5bmFtb2RiLXRpbWV0b2xpdmVzcGVjaWZpY2F0aW9uLWF0dHJpYnV0ZW5hbWVcbiAgICAgICAgICovXG4gICAgICAgIGF0dHJpYnV0ZU5hbWU6IHN0cmluZztcbiAgICAgICAgLyoqXG4gICAgICAgICAqIGBDZm5UYWJsZS5UaW1lVG9MaXZlU3BlY2lmaWNhdGlvblByb3BlcnR5LkVuYWJsZWRgXG4gICAgICAgICAqIEBzZWUgaHR0cDovL2RvY3MuYXdzLmFtYXpvbi5jb20vQVdTQ2xvdWRGb3JtYXRpb24vbGF0ZXN0L1VzZXJHdWlkZS9hd3MtcHJvcGVydGllcy1keW5hbW9kYi10aW1ldG9saXZlc3BlY2lmaWNhdGlvbi5odG1sI2Nmbi1keW5hbW9kYi10aW1ldG9saXZlc3BlY2lmaWNhdGlvbi1lbmFibGVkXG4gICAgICAgICAqL1xuICAgICAgICBlbmFibGVkOiBib29sZWFuIHwgY2RrLlRva2VuO1xuICAgIH1cbn1cblxuLyoqXG4gKiBEZXRlcm1pbmUgd2hldGhlciB0aGUgZ2l2ZW4gcHJvcGVydGllcyBtYXRjaCB0aG9zZSBvZiBhIGBUaW1lVG9MaXZlU3BlY2lmaWNhdGlvblByb3BlcnR5YFxuICpcbiAqIEBwYXJhbSBwcm9wZXJ0aWVzIC0gdGhlIFR5cGVTY3JpcHQgcHJvcGVydGllcyBvZiBhIGBUaW1lVG9MaXZlU3BlY2lmaWNhdGlvblByb3BlcnR5YFxuICpcbiAqIEByZXR1cm5zIHRoZSByZXN1bHQgb2YgdGhlIHZhbGlkYXRpb24uXG4gKi9cbmZ1bmN0aW9uIENmblRhYmxlX1RpbWVUb0xpdmVTcGVjaWZpY2F0aW9uUHJvcGVydHlWYWxpZGF0b3IocHJvcGVydGllczogYW55KTogY2RrLlZhbGlkYXRpb25SZXN1bHQge1xuICAgIGlmICghY2RrLmNhbkluc3BlY3QocHJvcGVydGllcykpIHsgcmV0dXJuIGNkay5WQUxJREFUSU9OX1NVQ0NFU1M7IH1cbiAgICBjb25zdCBlcnJvcnMgPSBuZXcgY2RrLlZhbGlkYXRpb25SZXN1bHRzKCk7XG4gICAgZXJyb3JzLmNvbGxlY3QoY2RrLnByb3BlcnR5VmFsaWRhdG9yKCdhdHRyaWJ1dGVOYW1lJywgY2RrLnJlcXVpcmVkVmFsaWRhdG9yKShwcm9wZXJ0aWVzLmF0dHJpYnV0ZU5hbWUpKTtcbiAgICBlcnJvcnMuY29sbGVjdChjZGsucHJvcGVydHlWYWxpZGF0b3IoJ2F0dHJpYnV0ZU5hbWUnLCBjZGsudmFsaWRhdGVTdHJpbmcpKHByb3BlcnRpZXMuYXR0cmlidXRlTmFtZSkpO1xuICAgIGVycm9ycy5jb2xsZWN0KGNkay5wcm9wZXJ0eVZhbGlkYXRvcignZW5hYmxlZCcsIGNkay5yZXF1aXJlZFZhbGlkYXRvcikocHJvcGVydGllcy5lbmFibGVkKSk7XG4gICAgZXJyb3JzLmNvbGxlY3QoY2RrLnByb3BlcnR5VmFsaWRhdG9yKCdlbmFibGVkJywgY2RrLnZhbGlkYXRlQm9vbGVhbikocHJvcGVydGllcy5lbmFibGVkKSk7XG4gICAgcmV0dXJuIGVycm9ycy53cmFwKCdzdXBwbGllZCBwcm9wZXJ0aWVzIG5vdCBjb3JyZWN0IGZvciBcIlRpbWVUb0xpdmVTcGVjaWZpY2F0aW9uUHJvcGVydHlcIicpO1xufVxuXG4vKipcbiAqIFJlbmRlcnMgdGhlIEFXUyBDbG91ZEZvcm1hdGlvbiBwcm9wZXJ0aWVzIG9mIGFuIGBBV1M6OkR5bmFtb0RCOjpUYWJsZS5UaW1lVG9MaXZlU3BlY2lmaWNhdGlvbmAgcmVzb3VyY2VcbiAqXG4gKiBAcGFyYW0gcHJvcGVydGllcyAtIHRoZSBUeXBlU2NyaXB0IHByb3BlcnRpZXMgb2YgYSBgVGltZVRvTGl2ZVNwZWNpZmljYXRpb25Qcm9wZXJ0eWBcbiAqXG4gKiBAcmV0dXJucyB0aGUgQVdTIENsb3VkRm9ybWF0aW9uIHByb3BlcnRpZXMgb2YgYW4gYEFXUzo6RHluYW1vREI6OlRhYmxlLlRpbWVUb0xpdmVTcGVjaWZpY2F0aW9uYCByZXNvdXJjZS5cbiAqL1xuLy8gQHRzLWlnbm9yZSBUUzYxMzNcbmZ1bmN0aW9uIGNmblRhYmxlVGltZVRvTGl2ZVNwZWNpZmljYXRpb25Qcm9wZXJ0eVRvQ2xvdWRGb3JtYXRpb24ocHJvcGVydGllczogYW55KTogYW55IHtcbiAgICBpZiAoIWNkay5jYW5JbnNwZWN0KHByb3BlcnRpZXMpKSB7IHJldHVybiBwcm9wZXJ0aWVzOyB9XG4gICAgQ2ZuVGFibGVfVGltZVRvTGl2ZVNwZWNpZmljYXRpb25Qcm9wZXJ0eVZhbGlkYXRvcihwcm9wZXJ0aWVzKS5hc3NlcnRTdWNjZXNzKCk7XG4gICAgcmV0dXJuIHtcbiAgICAgIEF0dHJpYnV0ZU5hbWU6IGNkay5zdHJpbmdUb0Nsb3VkRm9ybWF0aW9uKHByb3BlcnRpZXMuYXR0cmlidXRlTmFtZSksXG4gICAgICBFbmFibGVkOiBjZGsuYm9vbGVhblRvQ2xvdWRGb3JtYXRpb24ocHJvcGVydGllcy5lbmFibGVkKSxcbiAgICB9O1xufVxuIl19 \ No newline at end of file diff --git a/packages/@aws-cdk/aws-dynamodb-global/lib/dynamodb.generated.ts b/packages/@aws-cdk/aws-dynamodb-global/lib/dynamodb.generated.ts new file mode 100644 index 0000000000000..5d7ca7bc37382 --- /dev/null +++ b/packages/@aws-cdk/aws-dynamodb-global/lib/dynamodb.generated.ts @@ -0,0 +1,702 @@ +// Copyright 2012-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. +// Generated from the AWS CloudFormation Resource Specification +// See: docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/cfn-resource-specification.html +// @cfn2ts:meta@ {"generated":"2019-03-21T16:19:16.881Z","fingerprint":"CPTpE9eD4ImqOKDnu7P0Kaol8j+SXNQUILMR4l/fi2g="} + +// tslint:disable:max-line-length | This is generated code - line lengths are difficult to control + +import cdk = require('@aws-cdk/cdk'); + +/** + * Properties for defining a `AWS::DynamoDB::Table` + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-dynamodb-table.html + */ +export interface CfnTableProps { + /** + * `AWS::DynamoDB::Table.KeySchema` + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-dynamodb-table.html#cfn-dynamodb-table-keyschema + */ + keySchema: Array | cdk.Token; + /** + * `AWS::DynamoDB::Table.AttributeDefinitions` + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-dynamodb-table.html#cfn-dynamodb-table-attributedef + */ + attributeDefinitions?: Array | cdk.Token; + /** + * `AWS::DynamoDB::Table.BillingMode` + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-dynamodb-table.html#cfn-dynamodb-table-billingmode + */ + billingMode?: string; + /** + * `AWS::DynamoDB::Table.GlobalSecondaryIndexes` + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-dynamodb-table.html#cfn-dynamodb-table-gsi + */ + globalSecondaryIndexes?: Array | cdk.Token; + /** + * `AWS::DynamoDB::Table.LocalSecondaryIndexes` + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-dynamodb-table.html#cfn-dynamodb-table-lsi + */ + localSecondaryIndexes?: Array | cdk.Token; + /** + * `AWS::DynamoDB::Table.PointInTimeRecoverySpecification` + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-dynamodb-table.html#cfn-dynamodb-table-pointintimerecoveryspecification + */ + pointInTimeRecoverySpecification?: CfnTable.PointInTimeRecoverySpecificationProperty | cdk.Token; + /** + * `AWS::DynamoDB::Table.ProvisionedThroughput` + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-dynamodb-table.html#cfn-dynamodb-table-provisionedthroughput + */ + provisionedThroughput?: CfnTable.ProvisionedThroughputProperty | cdk.Token; + /** + * `AWS::DynamoDB::Table.SSESpecification` + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-dynamodb-table.html#cfn-dynamodb-table-ssespecification + */ + sseSpecification?: CfnTable.SSESpecificationProperty | cdk.Token; + /** + * `AWS::DynamoDB::Table.StreamSpecification` + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-dynamodb-table.html#cfn-dynamodb-table-streamspecification + */ + streamSpecification?: CfnTable.StreamSpecificationProperty | cdk.Token; + /** + * `AWS::DynamoDB::Table.TableName` + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-dynamodb-table.html#cfn-dynamodb-table-tablename + */ + tableName?: string; + /** + * `AWS::DynamoDB::Table.Tags` + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-dynamodb-table.html#cfn-dynamodb-table-tags + */ + tags?: cdk.CfnTag[]; + /** + * `AWS::DynamoDB::Table.TimeToLiveSpecification` + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-dynamodb-table.html#cfn-dynamodb-table-timetolivespecification + */ + timeToLiveSpecification?: CfnTable.TimeToLiveSpecificationProperty | cdk.Token; +} + +/** + * Determine whether the given properties match those of a `CfnTableProps` + * + * @param properties - the TypeScript properties of a `CfnTableProps` + * + * @returns the result of the validation. + */ +function CfnTablePropsValidator(properties: any): cdk.ValidationResult { + if (!cdk.canInspect(properties)) { return cdk.VALIDATION_SUCCESS; } + const errors = new cdk.ValidationResults(); + errors.collect(cdk.propertyValidator('attributeDefinitions', cdk.listValidator(CfnTable_AttributeDefinitionPropertyValidator))(properties.attributeDefinitions)); + errors.collect(cdk.propertyValidator('billingMode', cdk.validateString)(properties.billingMode)); + errors.collect(cdk.propertyValidator('globalSecondaryIndexes', cdk.listValidator(CfnTable_GlobalSecondaryIndexPropertyValidator))(properties.globalSecondaryIndexes)); + errors.collect(cdk.propertyValidator('keySchema', cdk.requiredValidator)(properties.keySchema)); + errors.collect(cdk.propertyValidator('keySchema', cdk.listValidator(CfnTable_KeySchemaPropertyValidator))(properties.keySchema)); + errors.collect(cdk.propertyValidator('localSecondaryIndexes', cdk.listValidator(CfnTable_LocalSecondaryIndexPropertyValidator))(properties.localSecondaryIndexes)); + errors.collect(cdk.propertyValidator('pointInTimeRecoverySpecification', CfnTable_PointInTimeRecoverySpecificationPropertyValidator)(properties.pointInTimeRecoverySpecification)); + errors.collect(cdk.propertyValidator('provisionedThroughput', CfnTable_ProvisionedThroughputPropertyValidator)(properties.provisionedThroughput)); + errors.collect(cdk.propertyValidator('sseSpecification', CfnTable_SSESpecificationPropertyValidator)(properties.sseSpecification)); + errors.collect(cdk.propertyValidator('streamSpecification', CfnTable_StreamSpecificationPropertyValidator)(properties.streamSpecification)); + errors.collect(cdk.propertyValidator('tableName', cdk.validateString)(properties.tableName)); + errors.collect(cdk.propertyValidator('tags', cdk.listValidator(cdk.validateCfnTag))(properties.tags)); + errors.collect(cdk.propertyValidator('timeToLiveSpecification', CfnTable_TimeToLiveSpecificationPropertyValidator)(properties.timeToLiveSpecification)); + return errors.wrap('supplied properties not correct for "CfnTableProps"'); +} + +/** + * Renders the AWS CloudFormation properties of an `AWS::DynamoDB::Table` resource + * + * @param properties - the TypeScript properties of a `CfnTableProps` + * + * @returns the AWS CloudFormation properties of an `AWS::DynamoDB::Table` resource. + */ +// @ts-ignore TS6133 +function cfnTablePropsToCloudFormation(properties: any): any { + if (!cdk.canInspect(properties)) { return properties; } + CfnTablePropsValidator(properties).assertSuccess(); + return { + KeySchema: cdk.listMapper(cfnTableKeySchemaPropertyToCloudFormation)(properties.keySchema), + AttributeDefinitions: cdk.listMapper(cfnTableAttributeDefinitionPropertyToCloudFormation)(properties.attributeDefinitions), + BillingMode: cdk.stringToCloudFormation(properties.billingMode), + GlobalSecondaryIndexes: cdk.listMapper(cfnTableGlobalSecondaryIndexPropertyToCloudFormation)(properties.globalSecondaryIndexes), + LocalSecondaryIndexes: cdk.listMapper(cfnTableLocalSecondaryIndexPropertyToCloudFormation)(properties.localSecondaryIndexes), + PointInTimeRecoverySpecification: cfnTablePointInTimeRecoverySpecificationPropertyToCloudFormation(properties.pointInTimeRecoverySpecification), + ProvisionedThroughput: cfnTableProvisionedThroughputPropertyToCloudFormation(properties.provisionedThroughput), + SSESpecification: cfnTableSSESpecificationPropertyToCloudFormation(properties.sseSpecification), + StreamSpecification: cfnTableStreamSpecificationPropertyToCloudFormation(properties.streamSpecification), + TableName: cdk.stringToCloudFormation(properties.tableName), + Tags: cdk.listMapper(cdk.cfnTagToCloudFormation)(properties.tags), + TimeToLiveSpecification: cfnTableTimeToLiveSpecificationPropertyToCloudFormation(properties.timeToLiveSpecification), + }; +} + +/** + * A CloudFormation `AWS::DynamoDB::Table` + * + * @cloudformationResource AWS::DynamoDB::Table + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-dynamodb-table.html + */ +export class CfnTable extends cdk.CfnResource { + /** + * The CloudFormation resource type name for this resource class. + */ + public static readonly resourceTypeName = "AWS::DynamoDB::Table"; + + /** + * @cloudformationAttribute Arn + */ + public readonly tableArn: string; + + /** + * @cloudformationAttribute StreamArn + */ + public readonly tableStreamArn: string; + public readonly tableName: string; + + /** + * The `TagManager` handles setting, removing and formatting tags + * + * Tags should be managed either passing them as properties during + * initiation or by calling methods on this object. If both techniques are + * used only the tags from the TagManager will be used. `Tag` (aspect) + * will use the manager. + */ + public readonly tags: cdk.TagManager; + + /** + * Create a new `AWS::DynamoDB::Table`. + * + * @param scope - scope in which this resource is defined + * @param id - scoped id of the resource + * @param props - resource properties + */ + constructor(scope: cdk.Construct, id: string, props: CfnTableProps) { + super(scope, id, { type: CfnTable.resourceTypeName, properties: props }); + cdk.requireProperty(props, 'keySchema', this); + this.tableArn = this.getAtt('Arn').toString(); + this.tableStreamArn = this.getAtt('StreamArn').toString(); + this.tableName = this.ref.toString(); + const tags = props === undefined ? undefined : props.tags; + this.tags = new cdk.TagManager(cdk.TagType.Standard, "AWS::DynamoDB::Table", tags); + } + + public get propertyOverrides(): CfnTableProps { + return this.untypedPropertyOverrides; + } + protected renderProperties(properties: any): { [key: string]: any } { + return cfnTablePropsToCloudFormation(this.node.resolve(properties)); + } +} + +export namespace CfnTable { + /** + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-attributedef.html + */ + export interface AttributeDefinitionProperty { + /** + * `CfnTable.AttributeDefinitionProperty.AttributeName` + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-attributedef.html#cfn-dynamodb-attributedef-attributename + */ + attributeName: string; + /** + * `CfnTable.AttributeDefinitionProperty.AttributeType` + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-attributedef.html#cfn-dynamodb-attributedef-attributename-attributetype + */ + attributeType: string; + } +} + +/** + * Determine whether the given properties match those of a `AttributeDefinitionProperty` + * + * @param properties - the TypeScript properties of a `AttributeDefinitionProperty` + * + * @returns the result of the validation. + */ +function CfnTable_AttributeDefinitionPropertyValidator(properties: any): cdk.ValidationResult { + if (!cdk.canInspect(properties)) { return cdk.VALIDATION_SUCCESS; } + const errors = new cdk.ValidationResults(); + errors.collect(cdk.propertyValidator('attributeName', cdk.requiredValidator)(properties.attributeName)); + errors.collect(cdk.propertyValidator('attributeName', cdk.validateString)(properties.attributeName)); + errors.collect(cdk.propertyValidator('attributeType', cdk.requiredValidator)(properties.attributeType)); + errors.collect(cdk.propertyValidator('attributeType', cdk.validateString)(properties.attributeType)); + return errors.wrap('supplied properties not correct for "AttributeDefinitionProperty"'); +} + +/** + * Renders the AWS CloudFormation properties of an `AWS::DynamoDB::Table.AttributeDefinition` resource + * + * @param properties - the TypeScript properties of a `AttributeDefinitionProperty` + * + * @returns the AWS CloudFormation properties of an `AWS::DynamoDB::Table.AttributeDefinition` resource. + */ +// @ts-ignore TS6133 +function cfnTableAttributeDefinitionPropertyToCloudFormation(properties: any): any { + if (!cdk.canInspect(properties)) { return properties; } + CfnTable_AttributeDefinitionPropertyValidator(properties).assertSuccess(); + return { + AttributeName: cdk.stringToCloudFormation(properties.attributeName), + AttributeType: cdk.stringToCloudFormation(properties.attributeType), + }; +} + +export namespace CfnTable { + /** + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-gsi.html + */ + export interface GlobalSecondaryIndexProperty { + /** + * `CfnTable.GlobalSecondaryIndexProperty.IndexName` + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-gsi.html#cfn-dynamodb-gsi-indexname + */ + indexName: string; + /** + * `CfnTable.GlobalSecondaryIndexProperty.KeySchema` + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-gsi.html#cfn-dynamodb-gsi-keyschema + */ + keySchema: Array | cdk.Token; + /** + * `CfnTable.GlobalSecondaryIndexProperty.Projection` + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-gsi.html#cfn-dynamodb-gsi-projection + */ + projection: CfnTable.ProjectionProperty | cdk.Token; + /** + * `CfnTable.GlobalSecondaryIndexProperty.ProvisionedThroughput` + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-gsi.html#cfn-dynamodb-gsi-provisionedthroughput + */ + provisionedThroughput?: CfnTable.ProvisionedThroughputProperty | cdk.Token; + } +} + +/** + * Determine whether the given properties match those of a `GlobalSecondaryIndexProperty` + * + * @param properties - the TypeScript properties of a `GlobalSecondaryIndexProperty` + * + * @returns the result of the validation. + */ +function CfnTable_GlobalSecondaryIndexPropertyValidator(properties: any): cdk.ValidationResult { + if (!cdk.canInspect(properties)) { return cdk.VALIDATION_SUCCESS; } + const errors = new cdk.ValidationResults(); + errors.collect(cdk.propertyValidator('indexName', cdk.requiredValidator)(properties.indexName)); + errors.collect(cdk.propertyValidator('indexName', cdk.validateString)(properties.indexName)); + errors.collect(cdk.propertyValidator('keySchema', cdk.requiredValidator)(properties.keySchema)); + errors.collect(cdk.propertyValidator('keySchema', cdk.listValidator(CfnTable_KeySchemaPropertyValidator))(properties.keySchema)); + errors.collect(cdk.propertyValidator('projection', cdk.requiredValidator)(properties.projection)); + errors.collect(cdk.propertyValidator('projection', CfnTable_ProjectionPropertyValidator)(properties.projection)); + errors.collect(cdk.propertyValidator('provisionedThroughput', CfnTable_ProvisionedThroughputPropertyValidator)(properties.provisionedThroughput)); + return errors.wrap('supplied properties not correct for "GlobalSecondaryIndexProperty"'); +} + +/** + * Renders the AWS CloudFormation properties of an `AWS::DynamoDB::Table.GlobalSecondaryIndex` resource + * + * @param properties - the TypeScript properties of a `GlobalSecondaryIndexProperty` + * + * @returns the AWS CloudFormation properties of an `AWS::DynamoDB::Table.GlobalSecondaryIndex` resource. + */ +// @ts-ignore TS6133 +function cfnTableGlobalSecondaryIndexPropertyToCloudFormation(properties: any): any { + if (!cdk.canInspect(properties)) { return properties; } + CfnTable_GlobalSecondaryIndexPropertyValidator(properties).assertSuccess(); + return { + IndexName: cdk.stringToCloudFormation(properties.indexName), + KeySchema: cdk.listMapper(cfnTableKeySchemaPropertyToCloudFormation)(properties.keySchema), + Projection: cfnTableProjectionPropertyToCloudFormation(properties.projection), + ProvisionedThroughput: cfnTableProvisionedThroughputPropertyToCloudFormation(properties.provisionedThroughput), + }; +} + +export namespace CfnTable { + /** + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-keyschema.html + */ + export interface KeySchemaProperty { + /** + * `CfnTable.KeySchemaProperty.AttributeName` + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-keyschema.html#aws-properties-dynamodb-keyschema-attributename + */ + attributeName: string; + /** + * `CfnTable.KeySchemaProperty.KeyType` + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-keyschema.html#aws-properties-dynamodb-keyschema-keytype + */ + keyType: string; + } +} + +/** + * Determine whether the given properties match those of a `KeySchemaProperty` + * + * @param properties - the TypeScript properties of a `KeySchemaProperty` + * + * @returns the result of the validation. + */ +function CfnTable_KeySchemaPropertyValidator(properties: any): cdk.ValidationResult { + if (!cdk.canInspect(properties)) { return cdk.VALIDATION_SUCCESS; } + const errors = new cdk.ValidationResults(); + errors.collect(cdk.propertyValidator('attributeName', cdk.requiredValidator)(properties.attributeName)); + errors.collect(cdk.propertyValidator('attributeName', cdk.validateString)(properties.attributeName)); + errors.collect(cdk.propertyValidator('keyType', cdk.requiredValidator)(properties.keyType)); + errors.collect(cdk.propertyValidator('keyType', cdk.validateString)(properties.keyType)); + return errors.wrap('supplied properties not correct for "KeySchemaProperty"'); +} + +/** + * Renders the AWS CloudFormation properties of an `AWS::DynamoDB::Table.KeySchema` resource + * + * @param properties - the TypeScript properties of a `KeySchemaProperty` + * + * @returns the AWS CloudFormation properties of an `AWS::DynamoDB::Table.KeySchema` resource. + */ +// @ts-ignore TS6133 +function cfnTableKeySchemaPropertyToCloudFormation(properties: any): any { + if (!cdk.canInspect(properties)) { return properties; } + CfnTable_KeySchemaPropertyValidator(properties).assertSuccess(); + return { + AttributeName: cdk.stringToCloudFormation(properties.attributeName), + KeyType: cdk.stringToCloudFormation(properties.keyType), + }; +} + +export namespace CfnTable { + /** + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-lsi.html + */ + export interface LocalSecondaryIndexProperty { + /** + * `CfnTable.LocalSecondaryIndexProperty.IndexName` + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-lsi.html#cfn-dynamodb-lsi-indexname + */ + indexName: string; + /** + * `CfnTable.LocalSecondaryIndexProperty.KeySchema` + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-lsi.html#cfn-dynamodb-lsi-keyschema + */ + keySchema: Array | cdk.Token; + /** + * `CfnTable.LocalSecondaryIndexProperty.Projection` + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-lsi.html#cfn-dynamodb-lsi-projection + */ + projection: CfnTable.ProjectionProperty | cdk.Token; + } +} + +/** + * Determine whether the given properties match those of a `LocalSecondaryIndexProperty` + * + * @param properties - the TypeScript properties of a `LocalSecondaryIndexProperty` + * + * @returns the result of the validation. + */ +function CfnTable_LocalSecondaryIndexPropertyValidator(properties: any): cdk.ValidationResult { + if (!cdk.canInspect(properties)) { return cdk.VALIDATION_SUCCESS; } + const errors = new cdk.ValidationResults(); + errors.collect(cdk.propertyValidator('indexName', cdk.requiredValidator)(properties.indexName)); + errors.collect(cdk.propertyValidator('indexName', cdk.validateString)(properties.indexName)); + errors.collect(cdk.propertyValidator('keySchema', cdk.requiredValidator)(properties.keySchema)); + errors.collect(cdk.propertyValidator('keySchema', cdk.listValidator(CfnTable_KeySchemaPropertyValidator))(properties.keySchema)); + errors.collect(cdk.propertyValidator('projection', cdk.requiredValidator)(properties.projection)); + errors.collect(cdk.propertyValidator('projection', CfnTable_ProjectionPropertyValidator)(properties.projection)); + return errors.wrap('supplied properties not correct for "LocalSecondaryIndexProperty"'); +} + +/** + * Renders the AWS CloudFormation properties of an `AWS::DynamoDB::Table.LocalSecondaryIndex` resource + * + * @param properties - the TypeScript properties of a `LocalSecondaryIndexProperty` + * + * @returns the AWS CloudFormation properties of an `AWS::DynamoDB::Table.LocalSecondaryIndex` resource. + */ +// @ts-ignore TS6133 +function cfnTableLocalSecondaryIndexPropertyToCloudFormation(properties: any): any { + if (!cdk.canInspect(properties)) { return properties; } + CfnTable_LocalSecondaryIndexPropertyValidator(properties).assertSuccess(); + return { + IndexName: cdk.stringToCloudFormation(properties.indexName), + KeySchema: cdk.listMapper(cfnTableKeySchemaPropertyToCloudFormation)(properties.keySchema), + Projection: cfnTableProjectionPropertyToCloudFormation(properties.projection), + }; +} + +export namespace CfnTable { + /** + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-table-pointintimerecoveryspecification.html + */ + export interface PointInTimeRecoverySpecificationProperty { + /** + * `CfnTable.PointInTimeRecoverySpecificationProperty.PointInTimeRecoveryEnabled` + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-table-pointintimerecoveryspecification.html#cfn-dynamodb-table-pointintimerecoveryspecification-pointintimerecoveryenabled + */ + pointInTimeRecoveryEnabled?: boolean | cdk.Token; + } +} + +/** + * Determine whether the given properties match those of a `PointInTimeRecoverySpecificationProperty` + * + * @param properties - the TypeScript properties of a `PointInTimeRecoverySpecificationProperty` + * + * @returns the result of the validation. + */ +function CfnTable_PointInTimeRecoverySpecificationPropertyValidator(properties: any): cdk.ValidationResult { + if (!cdk.canInspect(properties)) { return cdk.VALIDATION_SUCCESS; } + const errors = new cdk.ValidationResults(); + errors.collect(cdk.propertyValidator('pointInTimeRecoveryEnabled', cdk.validateBoolean)(properties.pointInTimeRecoveryEnabled)); + return errors.wrap('supplied properties not correct for "PointInTimeRecoverySpecificationProperty"'); +} + +/** + * Renders the AWS CloudFormation properties of an `AWS::DynamoDB::Table.PointInTimeRecoverySpecification` resource + * + * @param properties - the TypeScript properties of a `PointInTimeRecoverySpecificationProperty` + * + * @returns the AWS CloudFormation properties of an `AWS::DynamoDB::Table.PointInTimeRecoverySpecification` resource. + */ +// @ts-ignore TS6133 +function cfnTablePointInTimeRecoverySpecificationPropertyToCloudFormation(properties: any): any { + if (!cdk.canInspect(properties)) { return properties; } + CfnTable_PointInTimeRecoverySpecificationPropertyValidator(properties).assertSuccess(); + return { + PointInTimeRecoveryEnabled: cdk.booleanToCloudFormation(properties.pointInTimeRecoveryEnabled), + }; +} + +export namespace CfnTable { + /** + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-projectionobject.html + */ + export interface ProjectionProperty { + /** + * `CfnTable.ProjectionProperty.NonKeyAttributes` + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-projectionobject.html#cfn-dynamodb-projectionobj-nonkeyatt + */ + nonKeyAttributes?: string[]; + /** + * `CfnTable.ProjectionProperty.ProjectionType` + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-projectionobject.html#cfn-dynamodb-projectionobj-projtype + */ + projectionType?: string; + } +} + +/** + * Determine whether the given properties match those of a `ProjectionProperty` + * + * @param properties - the TypeScript properties of a `ProjectionProperty` + * + * @returns the result of the validation. + */ +function CfnTable_ProjectionPropertyValidator(properties: any): cdk.ValidationResult { + if (!cdk.canInspect(properties)) { return cdk.VALIDATION_SUCCESS; } + const errors = new cdk.ValidationResults(); + errors.collect(cdk.propertyValidator('nonKeyAttributes', cdk.listValidator(cdk.validateString))(properties.nonKeyAttributes)); + errors.collect(cdk.propertyValidator('projectionType', cdk.validateString)(properties.projectionType)); + return errors.wrap('supplied properties not correct for "ProjectionProperty"'); +} + +/** + * Renders the AWS CloudFormation properties of an `AWS::DynamoDB::Table.Projection` resource + * + * @param properties - the TypeScript properties of a `ProjectionProperty` + * + * @returns the AWS CloudFormation properties of an `AWS::DynamoDB::Table.Projection` resource. + */ +// @ts-ignore TS6133 +function cfnTableProjectionPropertyToCloudFormation(properties: any): any { + if (!cdk.canInspect(properties)) { return properties; } + CfnTable_ProjectionPropertyValidator(properties).assertSuccess(); + return { + NonKeyAttributes: cdk.listMapper(cdk.stringToCloudFormation)(properties.nonKeyAttributes), + ProjectionType: cdk.stringToCloudFormation(properties.projectionType), + }; +} + +export namespace CfnTable { + /** + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-provisionedthroughput.html + */ + export interface ProvisionedThroughputProperty { + /** + * `CfnTable.ProvisionedThroughputProperty.ReadCapacityUnits` + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-provisionedthroughput.html#cfn-dynamodb-provisionedthroughput-readcapacityunits + */ + readCapacityUnits: number | cdk.Token; + /** + * `CfnTable.ProvisionedThroughputProperty.WriteCapacityUnits` + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-provisionedthroughput.html#cfn-dynamodb-provisionedthroughput-writecapacityunits + */ + writeCapacityUnits: number | cdk.Token; + } +} + +/** + * Determine whether the given properties match those of a `ProvisionedThroughputProperty` + * + * @param properties - the TypeScript properties of a `ProvisionedThroughputProperty` + * + * @returns the result of the validation. + */ +function CfnTable_ProvisionedThroughputPropertyValidator(properties: any): cdk.ValidationResult { + if (!cdk.canInspect(properties)) { return cdk.VALIDATION_SUCCESS; } + const errors = new cdk.ValidationResults(); + errors.collect(cdk.propertyValidator('readCapacityUnits', cdk.requiredValidator)(properties.readCapacityUnits)); + errors.collect(cdk.propertyValidator('readCapacityUnits', cdk.validateNumber)(properties.readCapacityUnits)); + errors.collect(cdk.propertyValidator('writeCapacityUnits', cdk.requiredValidator)(properties.writeCapacityUnits)); + errors.collect(cdk.propertyValidator('writeCapacityUnits', cdk.validateNumber)(properties.writeCapacityUnits)); + return errors.wrap('supplied properties not correct for "ProvisionedThroughputProperty"'); +} + +/** + * Renders the AWS CloudFormation properties of an `AWS::DynamoDB::Table.ProvisionedThroughput` resource + * + * @param properties - the TypeScript properties of a `ProvisionedThroughputProperty` + * + * @returns the AWS CloudFormation properties of an `AWS::DynamoDB::Table.ProvisionedThroughput` resource. + */ +// @ts-ignore TS6133 +function cfnTableProvisionedThroughputPropertyToCloudFormation(properties: any): any { + if (!cdk.canInspect(properties)) { return properties; } + CfnTable_ProvisionedThroughputPropertyValidator(properties).assertSuccess(); + return { + ReadCapacityUnits: cdk.numberToCloudFormation(properties.readCapacityUnits), + WriteCapacityUnits: cdk.numberToCloudFormation(properties.writeCapacityUnits), + }; +} + +export namespace CfnTable { + /** + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-table-ssespecification.html + */ + export interface SSESpecificationProperty { + /** + * `CfnTable.SSESpecificationProperty.SSEEnabled` + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-table-ssespecification.html#cfn-dynamodb-table-ssespecification-sseenabled + */ + sseEnabled: boolean | cdk.Token; + } +} + +/** + * Determine whether the given properties match those of a `SSESpecificationProperty` + * + * @param properties - the TypeScript properties of a `SSESpecificationProperty` + * + * @returns the result of the validation. + */ +function CfnTable_SSESpecificationPropertyValidator(properties: any): cdk.ValidationResult { + if (!cdk.canInspect(properties)) { return cdk.VALIDATION_SUCCESS; } + const errors = new cdk.ValidationResults(); + errors.collect(cdk.propertyValidator('sseEnabled', cdk.requiredValidator)(properties.sseEnabled)); + errors.collect(cdk.propertyValidator('sseEnabled', cdk.validateBoolean)(properties.sseEnabled)); + return errors.wrap('supplied properties not correct for "SSESpecificationProperty"'); +} + +/** + * Renders the AWS CloudFormation properties of an `AWS::DynamoDB::Table.SSESpecification` resource + * + * @param properties - the TypeScript properties of a `SSESpecificationProperty` + * + * @returns the AWS CloudFormation properties of an `AWS::DynamoDB::Table.SSESpecification` resource. + */ +// @ts-ignore TS6133 +function cfnTableSSESpecificationPropertyToCloudFormation(properties: any): any { + if (!cdk.canInspect(properties)) { return properties; } + CfnTable_SSESpecificationPropertyValidator(properties).assertSuccess(); + return { + SSEEnabled: cdk.booleanToCloudFormation(properties.sseEnabled), + }; +} + +export namespace CfnTable { + /** + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-streamspecification.html + */ + export interface StreamSpecificationProperty { + /** + * `CfnTable.StreamSpecificationProperty.StreamViewType` + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-streamspecification.html#cfn-dynamodb-streamspecification-streamviewtype + */ + streamViewType: string; + } +} + +/** + * Determine whether the given properties match those of a `StreamSpecificationProperty` + * + * @param properties - the TypeScript properties of a `StreamSpecificationProperty` + * + * @returns the result of the validation. + */ +function CfnTable_StreamSpecificationPropertyValidator(properties: any): cdk.ValidationResult { + if (!cdk.canInspect(properties)) { return cdk.VALIDATION_SUCCESS; } + const errors = new cdk.ValidationResults(); + errors.collect(cdk.propertyValidator('streamViewType', cdk.requiredValidator)(properties.streamViewType)); + errors.collect(cdk.propertyValidator('streamViewType', cdk.validateString)(properties.streamViewType)); + return errors.wrap('supplied properties not correct for "StreamSpecificationProperty"'); +} + +/** + * Renders the AWS CloudFormation properties of an `AWS::DynamoDB::Table.StreamSpecification` resource + * + * @param properties - the TypeScript properties of a `StreamSpecificationProperty` + * + * @returns the AWS CloudFormation properties of an `AWS::DynamoDB::Table.StreamSpecification` resource. + */ +// @ts-ignore TS6133 +function cfnTableStreamSpecificationPropertyToCloudFormation(properties: any): any { + if (!cdk.canInspect(properties)) { return properties; } + CfnTable_StreamSpecificationPropertyValidator(properties).assertSuccess(); + return { + StreamViewType: cdk.stringToCloudFormation(properties.streamViewType), + }; +} + +export namespace CfnTable { + /** + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-timetolivespecification.html + */ + export interface TimeToLiveSpecificationProperty { + /** + * `CfnTable.TimeToLiveSpecificationProperty.AttributeName` + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-timetolivespecification.html#cfn-dynamodb-timetolivespecification-attributename + */ + attributeName: string; + /** + * `CfnTable.TimeToLiveSpecificationProperty.Enabled` + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-timetolivespecification.html#cfn-dynamodb-timetolivespecification-enabled + */ + enabled: boolean | cdk.Token; + } +} + +/** + * Determine whether the given properties match those of a `TimeToLiveSpecificationProperty` + * + * @param properties - the TypeScript properties of a `TimeToLiveSpecificationProperty` + * + * @returns the result of the validation. + */ +function CfnTable_TimeToLiveSpecificationPropertyValidator(properties: any): cdk.ValidationResult { + if (!cdk.canInspect(properties)) { return cdk.VALIDATION_SUCCESS; } + const errors = new cdk.ValidationResults(); + errors.collect(cdk.propertyValidator('attributeName', cdk.requiredValidator)(properties.attributeName)); + errors.collect(cdk.propertyValidator('attributeName', cdk.validateString)(properties.attributeName)); + errors.collect(cdk.propertyValidator('enabled', cdk.requiredValidator)(properties.enabled)); + errors.collect(cdk.propertyValidator('enabled', cdk.validateBoolean)(properties.enabled)); + return errors.wrap('supplied properties not correct for "TimeToLiveSpecificationProperty"'); +} + +/** + * Renders the AWS CloudFormation properties of an `AWS::DynamoDB::Table.TimeToLiveSpecification` resource + * + * @param properties - the TypeScript properties of a `TimeToLiveSpecificationProperty` + * + * @returns the AWS CloudFormation properties of an `AWS::DynamoDB::Table.TimeToLiveSpecification` resource. + */ +// @ts-ignore TS6133 +function cfnTableTimeToLiveSpecificationPropertyToCloudFormation(properties: any): any { + if (!cdk.canInspect(properties)) { return properties; } + CfnTable_TimeToLiveSpecificationPropertyValidator(properties).assertSuccess(); + return { + AttributeName: cdk.stringToCloudFormation(properties.attributeName), + Enabled: cdk.booleanToCloudFormation(properties.enabled), + }; +} diff --git a/packages/@aws-cdk/aws-dynamodb-global/lib/index.d.ts b/packages/@aws-cdk/aws-dynamodb-global/lib/index.d.ts new file mode 100644 index 0000000000000..710580c8bdf9b --- /dev/null +++ b/packages/@aws-cdk/aws-dynamodb-global/lib/index.d.ts @@ -0,0 +1,3 @@ +export * from "./aws-dynamodb-global"; +export * from "./lambda-global-dynamodb"; +export * from "./multi-dynamodb-stack"; diff --git a/packages/@aws-cdk/aws-dynamodb-global/lib/index.js b/packages/@aws-cdk/aws-dynamodb-global/lib/index.js new file mode 100644 index 0000000000000..b8df4cf851a64 --- /dev/null +++ b/packages/@aws-cdk/aws-dynamodb-global/lib/index.js @@ -0,0 +1,9 @@ +"use strict"; +function __export(m) { + for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; +} +Object.defineProperty(exports, "__esModule", { value: true }); +__export(require("./aws-dynamodb-global")); +__export(require("./lambda-global-dynamodb")); +__export(require("./multi-dynamodb-stack")); +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJpbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQUFBLDJDQUFzQztBQUN0Qyw4Q0FBeUM7QUFDekMsNENBQXVDIiwic291cmNlc0NvbnRlbnQiOlsiZXhwb3J0ICogZnJvbSBcIi4vYXdzLWR5bmFtb2RiLWdsb2JhbFwiO1xuZXhwb3J0ICogZnJvbSBcIi4vbGFtYmRhLWdsb2JhbC1keW5hbW9kYlwiO1xuZXhwb3J0ICogZnJvbSBcIi4vbXVsdGktZHluYW1vZGItc3RhY2tcIjtcbiJdfQ== \ No newline at end of file diff --git a/packages/@aws-cdk/aws-dynamodb-global/lib/lambda-global-dynamodb.d.ts b/packages/@aws-cdk/aws-dynamodb-global/lib/lambda-global-dynamodb.d.ts new file mode 100644 index 0000000000000..1a874aead8ec8 --- /dev/null +++ b/packages/@aws-cdk/aws-dynamodb-global/lib/lambda-global-dynamodb.d.ts @@ -0,0 +1,23 @@ +import cfn = require("@aws-cdk/aws-cloudformation"); +import lambda = require("@aws-cdk/aws-lambda"); +import cdk = require("@aws-cdk/cdk"); +import { DynamoDBGlobalStackProps } from "./aws-dynamodb-global"; +/** + * A stack that will make a Lambda that will launch a lambda to glue + * together all the DynamoDB tables into a global table + */ +export declare class LambdaGlobalDynamoDBMaker extends cdk.Stack { + /** + * The singleton Lambda function that will connect all the DynamoDB tables together into a global table + */ + lambdaFunction: lambda.IFunction; + /** + * The content of the lambdaFunction (python3.7 using boto3) + */ + lambdaFunctionContent: string; + /** + * The CloudFormation CustomResource that will manage the lambda + */ + customResource: cfn.CustomResource; + constructor(scope: cdk.Construct, id: string, props: DynamoDBGlobalStackProps); +} diff --git a/packages/@aws-cdk/aws-dynamodb-global/lib/lambda-global-dynamodb.js b/packages/@aws-cdk/aws-dynamodb-global/lib/lambda-global-dynamodb.js new file mode 100644 index 0000000000000..a38bedeb8d3d2 --- /dev/null +++ b/packages/@aws-cdk/aws-dynamodb-global/lib/lambda-global-dynamodb.js @@ -0,0 +1,46 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const cfn = require("@aws-cdk/aws-cloudformation"); +const iam = require("@aws-cdk/aws-iam"); +const lambda = require("@aws-cdk/aws-lambda"); +const cdk = require("@aws-cdk/cdk"); +const fs = require("fs"); +const path = require("path"); +/** + * A stack that will make a Lambda that will launch a lambda to glue + * together all the DynamoDB tables into a global table + */ +class LambdaGlobalDynamoDBMaker extends cdk.Stack { + constructor(scope, id, props) { + super(scope, id, props); + const codeLocation = path.resolve(__dirname, "lambda", "handler.js"); + this.lambdaFunctionContent = fs.readFileSync(codeLocation, "utf8"); + console.log('boop the woop'); + this.lambdaFunction = new lambda.Function(this, id + "-SingletonLambda", { + code: new lambda.InlineCode(this.lambdaFunctionContent), + description: "Lambda to make DynamoDB a global table", + handler: "index.handler", + runtime: lambda.Runtime.NodeJS810, + timeout: 300, + }); + this.lambdaFunction.addToRolePolicy(new iam.PolicyStatement() + .allow() + .addAllResources() + .addAction("iam:CreateServiceLinkedRole") + .addAction("application-autoscaling:DeleteScalingPolicy") + .addAction("application-autoscaling:DeregisterScalableTarget") + .addAction("dynamodb:CreateGlobalTable") + .addAction("dynamodb:DescribeLimits") + .addAction("dynamodb:UpdateGlobalTable")); + this.customResource = new cfn.CustomResource(this, id + "-CfnCustomResource", { + lambdaProvider: this.lambdaFunction, + properties: { + regions: props.regions, + resourceType: "Custom::MakeGlobalDynamoDB", + tableName: props.dynamoProps.tableName, + }, + }); + } +} +exports.LambdaGlobalDynamoDBMaker = LambdaGlobalDynamoDBMaker; +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibGFtYmRhLWdsb2JhbC1keW5hbW9kYi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImxhbWJkYS1nbG9iYWwtZHluYW1vZGIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFBQSxtREFBb0Q7QUFDcEQsd0NBQXlDO0FBQ3pDLDhDQUErQztBQUMvQyxvQ0FBcUM7QUFDckMseUJBQTBCO0FBQzFCLDZCQUE4QjtBQUc5Qjs7O0dBR0c7QUFDSCxNQUFhLHlCQUEwQixTQUFRLEdBQUcsQ0FBQyxLQUFLO0lBZ0JwRCxZQUFZLEtBQW9CLEVBQUUsRUFBVSxFQUFFLEtBQStCO1FBQ3pFLEtBQUssQ0FBQyxLQUFLLEVBQUUsRUFBRSxFQUFFLEtBQUssQ0FBQyxDQUFDO1FBQ3hCLE1BQU0sWUFBWSxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsU0FBUyxFQUFFLFFBQVEsRUFBRSxZQUFZLENBQUMsQ0FBQztRQUNyRSxJQUFJLENBQUMscUJBQXFCLEdBQUcsRUFBRSxDQUFDLFlBQVksQ0FBQyxZQUFZLEVBQUUsTUFBTSxDQUFDLENBQUM7UUFFbkUsT0FBTyxDQUFDLEdBQUcsQ0FBQyxlQUFlLENBQUMsQ0FBQztRQUU3QixJQUFJLENBQUMsY0FBYyxHQUFHLElBQUksTUFBTSxDQUFDLFFBQVEsQ0FBQyxJQUFJLEVBQUUsRUFBRSxHQUFHLGtCQUFrQixFQUFFO1lBQ3JFLElBQUksRUFBRSxJQUFJLE1BQU0sQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLHFCQUFxQixDQUFDO1lBQ3ZELFdBQVcsRUFBRSx3Q0FBd0M7WUFDckQsT0FBTyxFQUFFLGVBQWU7WUFDeEIsT0FBTyxFQUFFLE1BQU0sQ0FBQyxPQUFPLENBQUMsU0FBUztZQUNqQyxPQUFPLEVBQUUsR0FBRztTQUVmLENBQUMsQ0FBQztRQUNILElBQUksQ0FBQyxjQUFjLENBQUMsZUFBZSxDQUFDLElBQUksR0FBRyxDQUFDLGVBQWUsRUFBRTthQUN4RCxLQUFLLEVBQUU7YUFDUCxlQUFlLEVBQUU7YUFDakIsU0FBUyxDQUFDLDZCQUE2QixDQUFDO2FBQ3hDLFNBQVMsQ0FBQyw2Q0FBNkMsQ0FBQzthQUN4RCxTQUFTLENBQUMsa0RBQWtELENBQUM7YUFDN0QsU0FBUyxDQUFDLDRCQUE0QixDQUFDO2FBQ3ZDLFNBQVMsQ0FBQyx5QkFBeUIsQ0FBQzthQUNwQyxTQUFTLENBQUMsNEJBQTRCLENBQUMsQ0FBQyxDQUFDO1FBQzlDLElBQUksQ0FBQyxjQUFjLEdBQUcsSUFBSSxHQUFHLENBQUMsY0FBYyxDQUFDLElBQUksRUFBRSxFQUFFLEdBQUcsb0JBQW9CLEVBQUU7WUFDMUUsY0FBYyxFQUFFLElBQUksQ0FBQyxjQUFjO1lBQ25DLFVBQVUsRUFBRTtnQkFDUixPQUFPLEVBQUUsS0FBSyxDQUFDLE9BQU87Z0JBQ3RCLFlBQVksRUFBRSw0QkFBNEI7Z0JBQzFDLFNBQVMsRUFBRSxLQUFLLENBQUMsV0FBVyxDQUFDLFNBQVM7YUFDekM7U0FDSixDQUFDLENBQUM7SUFDTCxDQUFDO0NBQ047QUFqREQsOERBaURDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IGNmbiA9IHJlcXVpcmUoXCJAYXdzLWNkay9hd3MtY2xvdWRmb3JtYXRpb25cIik7XG5pbXBvcnQgaWFtID0gcmVxdWlyZShcIkBhd3MtY2RrL2F3cy1pYW1cIik7XG5pbXBvcnQgbGFtYmRhID0gcmVxdWlyZShcIkBhd3MtY2RrL2F3cy1sYW1iZGFcIik7XG5pbXBvcnQgY2RrID0gcmVxdWlyZShcIkBhd3MtY2RrL2Nka1wiKTtcbmltcG9ydCBmcyA9IHJlcXVpcmUoXCJmc1wiKTtcbmltcG9ydCBwYXRoID0gcmVxdWlyZShcInBhdGhcIik7XG5pbXBvcnQgeyBEeW5hbW9EQkdsb2JhbFN0YWNrUHJvcHMgfSBmcm9tIFwiLi9hd3MtZHluYW1vZGItZ2xvYmFsXCI7XG5cbi8qKlxuICogQSBzdGFjayB0aGF0IHdpbGwgbWFrZSBhIExhbWJkYSB0aGF0IHdpbGwgbGF1bmNoIGEgbGFtYmRhIHRvIGdsdWVcbiAqIHRvZ2V0aGVyIGFsbCB0aGUgRHluYW1vREIgdGFibGVzIGludG8gYSBnbG9iYWwgdGFibGVcbiAqL1xuZXhwb3J0IGNsYXNzIExhbWJkYUdsb2JhbER5bmFtb0RCTWFrZXIgZXh0ZW5kcyBjZGsuU3RhY2sge1xuICAgIC8qKlxuICAgICAqIFRoZSBzaW5nbGV0b24gTGFtYmRhIGZ1bmN0aW9uIHRoYXQgd2lsbCBjb25uZWN0IGFsbCB0aGUgRHluYW1vREIgdGFibGVzIHRvZ2V0aGVyIGludG8gYSBnbG9iYWwgdGFibGVcbiAgICAgKi9cbiAgICBwdWJsaWMgbGFtYmRhRnVuY3Rpb246IGxhbWJkYS5JRnVuY3Rpb247XG5cbiAgICAvKipcbiAgICAgKiBUaGUgY29udGVudCBvZiB0aGUgbGFtYmRhRnVuY3Rpb24gKHB5dGhvbjMuNyB1c2luZyBib3RvMylcbiAgICAgKi9cbiAgICBwdWJsaWMgbGFtYmRhRnVuY3Rpb25Db250ZW50OiBzdHJpbmc7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgQ2xvdWRGb3JtYXRpb24gQ3VzdG9tUmVzb3VyY2UgdGhhdCB3aWxsIG1hbmFnZSB0aGUgbGFtYmRhXG4gICAgICovXG4gICAgcHVibGljIGN1c3RvbVJlc291cmNlOiBjZm4uQ3VzdG9tUmVzb3VyY2U7XG5cbiAgICBjb25zdHJ1Y3RvcihzY29wZTogY2RrLkNvbnN0cnVjdCwgaWQ6IHN0cmluZywgcHJvcHM6IER5bmFtb0RCR2xvYmFsU3RhY2tQcm9wcykge1xuICAgICAgICBzdXBlcihzY29wZSwgaWQsIHByb3BzKTtcbiAgICAgICAgY29uc3QgY29kZUxvY2F0aW9uID0gcGF0aC5yZXNvbHZlKF9fZGlybmFtZSwgXCJsYW1iZGFcIiwgXCJoYW5kbGVyLmpzXCIpO1xuICAgICAgICB0aGlzLmxhbWJkYUZ1bmN0aW9uQ29udGVudCA9IGZzLnJlYWRGaWxlU3luYyhjb2RlTG9jYXRpb24sIFwidXRmOFwiKTtcblxuICAgICAgICBjb25zb2xlLmxvZygnYm9vcCB0aGUgd29vcCcpO1xuXG4gICAgICAgIHRoaXMubGFtYmRhRnVuY3Rpb24gPSBuZXcgbGFtYmRhLkZ1bmN0aW9uKHRoaXMsIGlkICsgXCItU2luZ2xldG9uTGFtYmRhXCIsIHtcbiAgICAgICAgICAgIGNvZGU6IG5ldyBsYW1iZGEuSW5saW5lQ29kZSh0aGlzLmxhbWJkYUZ1bmN0aW9uQ29udGVudCksXG4gICAgICAgICAgICBkZXNjcmlwdGlvbjogXCJMYW1iZGEgdG8gbWFrZSBEeW5hbW9EQiBhIGdsb2JhbCB0YWJsZVwiLFxuICAgICAgICAgICAgaGFuZGxlcjogXCJpbmRleC5oYW5kbGVyXCIsXG4gICAgICAgICAgICBydW50aW1lOiBsYW1iZGEuUnVudGltZS5Ob2RlSlM4MTAsXG4gICAgICAgICAgICB0aW1lb3V0OiAzMDAsXG4gICAgICAgICAgICAvLyB1dWlkOiBcIkQzOEI2NUE2LTZCNTQtNEZCNi05QkFELTlDRDQwQTZEQUMxMlwiLFxuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy5sYW1iZGFGdW5jdGlvbi5hZGRUb1JvbGVQb2xpY3kobmV3IGlhbS5Qb2xpY3lTdGF0ZW1lbnQoKVxuICAgICAgICAgICAgLmFsbG93KClcbiAgICAgICAgICAgIC5hZGRBbGxSZXNvdXJjZXMoKVxuICAgICAgICAgICAgLmFkZEFjdGlvbihcImlhbTpDcmVhdGVTZXJ2aWNlTGlua2VkUm9sZVwiKVxuICAgICAgICAgICAgLmFkZEFjdGlvbihcImFwcGxpY2F0aW9uLWF1dG9zY2FsaW5nOkRlbGV0ZVNjYWxpbmdQb2xpY3lcIilcbiAgICAgICAgICAgIC5hZGRBY3Rpb24oXCJhcHBsaWNhdGlvbi1hdXRvc2NhbGluZzpEZXJlZ2lzdGVyU2NhbGFibGVUYXJnZXRcIilcbiAgICAgICAgICAgIC5hZGRBY3Rpb24oXCJkeW5hbW9kYjpDcmVhdGVHbG9iYWxUYWJsZVwiKVxuICAgICAgICAgICAgLmFkZEFjdGlvbihcImR5bmFtb2RiOkRlc2NyaWJlTGltaXRzXCIpXG4gICAgICAgICAgICAuYWRkQWN0aW9uKFwiZHluYW1vZGI6VXBkYXRlR2xvYmFsVGFibGVcIikpO1xuICAgICAgICB0aGlzLmN1c3RvbVJlc291cmNlID0gbmV3IGNmbi5DdXN0b21SZXNvdXJjZSh0aGlzLCBpZCArIFwiLUNmbkN1c3RvbVJlc291cmNlXCIsIHtcbiAgICAgICAgICAgIGxhbWJkYVByb3ZpZGVyOiB0aGlzLmxhbWJkYUZ1bmN0aW9uLFxuICAgICAgICAgICAgcHJvcGVydGllczoge1xuICAgICAgICAgICAgICAgIHJlZ2lvbnM6IHByb3BzLnJlZ2lvbnMsXG4gICAgICAgICAgICAgICAgcmVzb3VyY2VUeXBlOiBcIkN1c3RvbTo6TWFrZUdsb2JhbER5bmFtb0RCXCIsXG4gICAgICAgICAgICAgICAgdGFibGVOYW1lOiBwcm9wcy5keW5hbW9Qcm9wcy50YWJsZU5hbWUsXG4gICAgICAgICAgICB9LFxuICAgICAgICB9KTtcbiAgICAgIH1cbn1cbiJdfQ== \ No newline at end of file diff --git a/packages/@aws-cdk/aws-dynamodb-global/lib/multi-dynamodb-stack.d.ts b/packages/@aws-cdk/aws-dynamodb-global/lib/multi-dynamodb-stack.d.ts new file mode 100644 index 0000000000000..907b72b571d9c --- /dev/null +++ b/packages/@aws-cdk/aws-dynamodb-global/lib/multi-dynamodb-stack.d.ts @@ -0,0 +1,13 @@ +import dynamodb = require("@aws-cdk/aws-dynamodb"); +import cdk = require("@aws-cdk/cdk"); +import { DynamoDBGlobalStackProps } from "./aws-dynamodb-global"; +/** + * Stack to create a single DynamoDB Table + */ +export declare class MultiDynamoDBStack extends cdk.Stack { + /** + * The DynamoDB Table created + */ + table: dynamodb.Table; + constructor(scope: cdk.Construct, id: string, props: DynamoDBGlobalStackProps); +} diff --git a/packages/@aws-cdk/aws-dynamodb-global/lib/multi-dynamodb-stack.js b/packages/@aws-cdk/aws-dynamodb-global/lib/multi-dynamodb-stack.js new file mode 100644 index 0000000000000..3ecbf5920ed8e --- /dev/null +++ b/packages/@aws-cdk/aws-dynamodb-global/lib/multi-dynamodb-stack.js @@ -0,0 +1,15 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const dynamodb = require("@aws-cdk/aws-dynamodb"); +const cdk = require("@aws-cdk/cdk"); +/** + * Stack to create a single DynamoDB Table + */ +class MultiDynamoDBStack extends cdk.Stack { + constructor(scope, id, props) { + super(scope, id, props); + this.table = new dynamodb.Table(this, id + "-table", props.dynamoProps); + } +} +exports.MultiDynamoDBStack = MultiDynamoDBStack; +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibXVsdGktZHluYW1vZGItc3RhY2suanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJtdWx0aS1keW5hbW9kYi1zdGFjay50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQUFBLGtEQUFtRDtBQUNuRCxvQ0FBcUM7QUFHckM7O0dBRUc7QUFDSCxNQUFhLGtCQUFtQixTQUFRLEdBQUcsQ0FBQyxLQUFLO0lBTTdDLFlBQVksS0FBb0IsRUFBRSxFQUFVLEVBQUUsS0FBK0I7UUFDekUsS0FBSyxDQUFDLEtBQUssRUFBRSxFQUFFLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFDeEIsSUFBSSxDQUFDLEtBQUssR0FBRyxJQUFJLFFBQVEsQ0FBQyxLQUFLLENBQUMsSUFBSSxFQUFFLEVBQUUsR0FBRyxRQUFRLEVBQUUsS0FBSyxDQUFDLFdBQVcsQ0FBQyxDQUFDO0lBQzVFLENBQUM7Q0FDSjtBQVZELGdEQVVDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IGR5bmFtb2RiID0gcmVxdWlyZShcIkBhd3MtY2RrL2F3cy1keW5hbW9kYlwiKTtcbmltcG9ydCBjZGsgPSByZXF1aXJlKFwiQGF3cy1jZGsvY2RrXCIpO1xuaW1wb3J0IHsgRHluYW1vREJHbG9iYWxTdGFja1Byb3BzIH0gZnJvbSBcIi4vYXdzLWR5bmFtb2RiLWdsb2JhbFwiO1xuXG4vKipcbiAqIFN0YWNrIHRvIGNyZWF0ZSBhIHNpbmdsZSBEeW5hbW9EQiBUYWJsZVxuICovXG5leHBvcnQgY2xhc3MgTXVsdGlEeW5hbW9EQlN0YWNrIGV4dGVuZHMgY2RrLlN0YWNrIHtcbiAgICAvKipcbiAgICAgKiBUaGUgRHluYW1vREIgVGFibGUgY3JlYXRlZFxuICAgICAqL1xuICAgIHB1YmxpYyB0YWJsZTogZHluYW1vZGIuVGFibGU7XG5cbiAgICBjb25zdHJ1Y3RvcihzY29wZTogY2RrLkNvbnN0cnVjdCwgaWQ6IHN0cmluZywgcHJvcHM6IER5bmFtb0RCR2xvYmFsU3RhY2tQcm9wcykge1xuICAgICAgICBzdXBlcihzY29wZSwgaWQsIHByb3BzKTtcbiAgICAgICAgdGhpcy50YWJsZSA9IG5ldyBkeW5hbW9kYi5UYWJsZSh0aGlzLCBpZCArIFwiLXRhYmxlXCIsIHByb3BzLmR5bmFtb1Byb3BzKTtcbiAgICB9XG59Il19 \ No newline at end of file diff --git a/packages/@aws-cdk/aws-dynamodb-global/test/integ.dynamodb.global.d.ts b/packages/@aws-cdk/aws-dynamodb-global/test/integ.dynamodb.global.d.ts new file mode 100644 index 0000000000000..cb0ff5c3b541f --- /dev/null +++ b/packages/@aws-cdk/aws-dynamodb-global/test/integ.dynamodb.global.d.ts @@ -0,0 +1 @@ +export {}; diff --git a/packages/@aws-cdk/aws-dynamodb-global/test/integ.dynamodb.global.js b/packages/@aws-cdk/aws-dynamodb-global/test/integ.dynamodb.global.js new file mode 100644 index 0000000000000..11ea9b1108a57 --- /dev/null +++ b/packages/@aws-cdk/aws-dynamodb-global/test/integ.dynamodb.global.js @@ -0,0 +1,21 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const aws_dynamodb_1 = require("@aws-cdk/aws-dynamodb"); +const cdk_1 = require("@aws-cdk/cdk"); +const lib_1 = require("../lib"); +// CDK parameters +const STACK_NAME = 'aws-cdk-dynamodb-global'; +// DynamoDB table parameters +const TABLE = 'GlobalTable'; +const TABLE_PARTITION_KEY = { name: 'hashKey', type: aws_dynamodb_1.AttributeType.String }; +const STACK_PROPS = { + dynamoProps: { + partitionKey: TABLE_PARTITION_KEY, + tableName: TABLE + }, + regions: ["us-east-1", "us-east-2", "us-west-2"] +}; +const app = new cdk_1.App(); +new lib_1.GlobalTable(app, STACK_NAME, STACK_PROPS); +app.run(); +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW50ZWcuZHluYW1vZGIuZ2xvYmFsLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiaW50ZWcuZHluYW1vZGIuZ2xvYmFsLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBQUEsd0RBQWlFO0FBQ2pFLHNDQUFtQztBQUNuQyxnQ0FBK0Q7QUFFL0QsaUJBQWlCO0FBQ2pCLE1BQU0sVUFBVSxHQUFHLHlCQUF5QixDQUFDO0FBRTdDLDRCQUE0QjtBQUM1QixNQUFNLEtBQUssR0FBRyxhQUFhLENBQUM7QUFDNUIsTUFBTSxtQkFBbUIsR0FBYyxFQUFFLElBQUksRUFBRSxTQUFTLEVBQUUsSUFBSSxFQUFFLDRCQUFhLENBQUMsTUFBTSxFQUFFLENBQUM7QUFFdkYsTUFBTSxXQUFXLEdBQTZCO0lBQzFDLFdBQVcsRUFBRTtRQUNULFlBQVksRUFBRSxtQkFBbUI7UUFDakMsU0FBUyxFQUFFLEtBQUs7S0FDbkI7SUFDRCxPQUFPLEVBQUUsQ0FBRSxXQUFXLEVBQUUsV0FBVyxFQUFFLFdBQVcsQ0FBRTtDQUNyRCxDQUFDO0FBRUYsTUFBTSxHQUFHLEdBQUcsSUFBSSxTQUFHLEVBQUUsQ0FBQztBQUN0QixJQUFJLGlCQUFXLENBQUMsR0FBRyxFQUFFLFVBQVUsRUFBRSxXQUFXLENBQUMsQ0FBQztBQUM5QyxHQUFHLENBQUMsR0FBRyxFQUFFLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBBdHRyaWJ1dGUsIEF0dHJpYnV0ZVR5cGUgfSBmcm9tICdAYXdzLWNkay9hd3MtZHluYW1vZGInO1xuaW1wb3J0IHsgQXBwIH0gZnJvbSAnQGF3cy1jZGsvY2RrJztcbmltcG9ydCB7IER5bmFtb0RCR2xvYmFsU3RhY2tQcm9wcywgR2xvYmFsVGFibGUgfSBmcm9tICcuLi9saWInO1xuXG4vLyBDREsgcGFyYW1ldGVyc1xuY29uc3QgU1RBQ0tfTkFNRSA9ICdhd3MtY2RrLWR5bmFtb2RiLWdsb2JhbCc7XG5cbi8vIER5bmFtb0RCIHRhYmxlIHBhcmFtZXRlcnNcbmNvbnN0IFRBQkxFID0gJ0dsb2JhbFRhYmxlJztcbmNvbnN0IFRBQkxFX1BBUlRJVElPTl9LRVk6IEF0dHJpYnV0ZSA9IHsgbmFtZTogJ2hhc2hLZXknLCB0eXBlOiBBdHRyaWJ1dGVUeXBlLlN0cmluZyB9O1xuXG5jb25zdCBTVEFDS19QUk9QUzogRHluYW1vREJHbG9iYWxTdGFja1Byb3BzID0ge1xuICAgIGR5bmFtb1Byb3BzOiB7XG4gICAgICAgIHBhcnRpdGlvbktleTogVEFCTEVfUEFSVElUSU9OX0tFWSxcbiAgICAgICAgdGFibGVOYW1lOiBUQUJMRVxuICAgIH0sXG4gICAgcmVnaW9uczogWyBcInVzLWVhc3QtMVwiLCBcInVzLWVhc3QtMlwiLCBcInVzLXdlc3QtMlwiIF1cbn07XG5cbmNvbnN0IGFwcCA9IG5ldyBBcHAoKTtcbm5ldyBHbG9iYWxUYWJsZShhcHAsIFNUQUNLX05BTUUsIFNUQUNLX1BST1BTKTtcbmFwcC5ydW4oKTtcbiJdfQ== \ No newline at end of file diff --git a/packages/@aws-cdk/aws-dynamodb-global/test/test.dynamodb.global.d.ts b/packages/@aws-cdk/aws-dynamodb-global/test/test.dynamodb.global.d.ts new file mode 100644 index 0000000000000..b01a554b50f83 --- /dev/null +++ b/packages/@aws-cdk/aws-dynamodb-global/test/test.dynamodb.global.d.ts @@ -0,0 +1,7 @@ +import { Test } from 'nodeunit'; +declare const _default: { + 'default stack': { + 'default'(test: Test): void; + }; +}; +export = _default; diff --git a/packages/@aws-cdk/aws-dynamodb-global/test/test.dynamodb.global.js b/packages/@aws-cdk/aws-dynamodb-global/test/test.dynamodb.global.js new file mode 100644 index 0000000000000..64cacdc793a27 --- /dev/null +++ b/packages/@aws-cdk/aws-dynamodb-global/test/test.dynamodb.global.js @@ -0,0 +1,36 @@ +"use strict"; +const assert_1 = require("@aws-cdk/assert"); +const aws_dynamodb_1 = require("@aws-cdk/aws-dynamodb"); +const cdk_1 = require("@aws-cdk/cdk"); +const ddb = require("@aws-cdk/aws-dynamodb"); +// tslint:disable:object-literal-key-quotes +// CDK parameters +// const CONSTRUCT_NAME = 'aws-cdk-dynamodb-global'; +// DynamoDB table parameters +const TABLE_NAME = 'GlobalTable'; +const TABLE_PARTITION_KEY = { name: 'hashKey', type: aws_dynamodb_1.AttributeType.String }; +const STACK_PROPS = { + dynamoProps: { + partitionKey: TABLE_PARTITION_KEY, + tableName: TABLE_NAME + }, + regions: ["us-east-1", "us-east-2", "us-west-2"] +}; +module.exports = { + 'default stack': { + 'default'(test) { + const app = new cdk_1.App(); + const stack = new cdk_1.Stack(app, 'Stack'); + // new GlobalTable(stack, CONSTRUCT_NAME, STACK_PROPS); + new ddb.Table(stack, 'xxx', { + partitionKey: { name: 'asdf', type: ddb.AttributeType.String }, + }); + console.log(stack._toCloudFormation()); + assert_1.expect(stack).to(assert_1.haveResource('AWS::Lambda::Function', { + "Regions": STACK_PROPS.regions + })); + test.done(); + } + } +}; +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGVzdC5keW5hbW9kYi5nbG9iYWwuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJ0ZXN0LmR5bmFtb2RiLmdsb2JhbC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUEsNENBQXVEO0FBQ3ZELHdEQUFpRTtBQUNqRSxzQ0FBMEM7QUFPMUMsNkNBQThDO0FBRTlDLDJDQUEyQztBQUUzQyxpQkFBaUI7QUFDakIsb0RBQW9EO0FBRXBELDRCQUE0QjtBQUM1QixNQUFNLFVBQVUsR0FBRyxhQUFhLENBQUM7QUFDakMsTUFBTSxtQkFBbUIsR0FBYyxFQUFFLElBQUksRUFBRSxTQUFTLEVBQUUsSUFBSSxFQUFFLDRCQUFhLENBQUMsTUFBTSxFQUFFLENBQUM7QUFFdkYsTUFBTSxXQUFXLEdBQTZCO0lBQzFDLFdBQVcsRUFBRTtRQUNULFlBQVksRUFBRSxtQkFBbUI7UUFDakMsU0FBUyxFQUFFLFVBQVU7S0FDeEI7SUFDRCxPQUFPLEVBQUUsQ0FBRSxXQUFXLEVBQUUsV0FBVyxFQUFFLFdBQVcsQ0FBRTtDQUNyRCxDQUFDO0FBRUYsaUJBQVM7SUFDTCxlQUFlLEVBQUU7UUFDYixTQUFTLENBQUMsSUFBVTtZQUNoQixNQUFNLEdBQUcsR0FBRyxJQUFJLFNBQUcsRUFBRSxDQUFDO1lBQ3RCLE1BQU0sS0FBSyxHQUFHLElBQUksV0FBSyxDQUFDLEdBQUcsRUFBRSxPQUFPLENBQUMsQ0FBQztZQUN0Qyx1REFBdUQ7WUFDdkQsSUFBSSxHQUFHLENBQUMsS0FBSyxDQUFDLEtBQUssRUFBRSxLQUFLLEVBQUU7Z0JBQ3hCLFlBQVksRUFBRSxFQUFFLElBQUksRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFLEdBQUcsQ0FBQyxhQUFhLENBQUMsTUFBTSxFQUFFO2FBQ2pFLENBQUMsQ0FBQztZQUVILE9BQU8sQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLGlCQUFpQixFQUFFLENBQUMsQ0FBQztZQUV2QyxlQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsRUFBRSxDQUFDLHFCQUFZLENBQUMsdUJBQXVCLEVBQUU7Z0JBQ25ELFNBQVMsRUFBRSxXQUFXLENBQUMsT0FBTzthQUNqQyxDQUFDLENBQUMsQ0FBQztZQUVKLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQztRQUNoQixDQUFDO0tBQ0o7Q0FDSixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgZXhwZWN0LCBoYXZlUmVzb3VyY2UgfSBmcm9tICdAYXdzLWNkay9hc3NlcnQnO1xuaW1wb3J0IHsgQXR0cmlidXRlLCBBdHRyaWJ1dGVUeXBlIH0gZnJvbSAnQGF3cy1jZGsvYXdzLWR5bmFtb2RiJztcbmltcG9ydCB7IEFwcCwgU3RhY2sgfSBmcm9tICdAYXdzLWNkay9jZGsnO1xuaW1wb3J0IHsgVGVzdCB9IGZyb20gJ25vZGV1bml0JztcbmltcG9ydCB7XG4gICAgRHluYW1vREJHbG9iYWxTdGFja1Byb3BzLFxuLy8gICAgR2xvYmFsVGFibGUsXG59IGZyb20gJy4uL2xpYic7XG5cbmltcG9ydCBkZGIgPSByZXF1aXJlKCdAYXdzLWNkay9hd3MtZHluYW1vZGInKTtcblxuLy8gdHNsaW50OmRpc2FibGU6b2JqZWN0LWxpdGVyYWwta2V5LXF1b3Rlc1xuXG4vLyBDREsgcGFyYW1ldGVyc1xuLy8gY29uc3QgQ09OU1RSVUNUX05BTUUgPSAnYXdzLWNkay1keW5hbW9kYi1nbG9iYWwnO1xuXG4vLyBEeW5hbW9EQiB0YWJsZSBwYXJhbWV0ZXJzXG5jb25zdCBUQUJMRV9OQU1FID0gJ0dsb2JhbFRhYmxlJztcbmNvbnN0IFRBQkxFX1BBUlRJVElPTl9LRVk6IEF0dHJpYnV0ZSA9IHsgbmFtZTogJ2hhc2hLZXknLCB0eXBlOiBBdHRyaWJ1dGVUeXBlLlN0cmluZyB9O1xuXG5jb25zdCBTVEFDS19QUk9QUzogRHluYW1vREJHbG9iYWxTdGFja1Byb3BzID0ge1xuICAgIGR5bmFtb1Byb3BzOiB7XG4gICAgICAgIHBhcnRpdGlvbktleTogVEFCTEVfUEFSVElUSU9OX0tFWSxcbiAgICAgICAgdGFibGVOYW1lOiBUQUJMRV9OQU1FXG4gICAgfSxcbiAgICByZWdpb25zOiBbIFwidXMtZWFzdC0xXCIsIFwidXMtZWFzdC0yXCIsIFwidXMtd2VzdC0yXCIgXVxufTtcblxuZXhwb3J0ID0ge1xuICAgICdkZWZhdWx0IHN0YWNrJzoge1xuICAgICAgICAnZGVmYXVsdCcodGVzdDogVGVzdCkge1xuICAgICAgICAgICAgY29uc3QgYXBwID0gbmV3IEFwcCgpO1xuICAgICAgICAgICAgY29uc3Qgc3RhY2sgPSBuZXcgU3RhY2soYXBwLCAnU3RhY2snKTtcbiAgICAgICAgICAgIC8vIG5ldyBHbG9iYWxUYWJsZShzdGFjaywgQ09OU1RSVUNUX05BTUUsIFNUQUNLX1BST1BTKTtcbiAgICAgICAgICAgIG5ldyBkZGIuVGFibGUoc3RhY2ssICd4eHgnLCB7XG4gICAgICAgICAgICAgICAgcGFydGl0aW9uS2V5OiB7IG5hbWU6ICdhc2RmJywgdHlwZTogZGRiLkF0dHJpYnV0ZVR5cGUuU3RyaW5nIH0sXG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgY29uc29sZS5sb2coc3RhY2suX3RvQ2xvdWRGb3JtYXRpb24oKSk7XG5cbiAgICAgICAgICAgIGV4cGVjdChzdGFjaykudG8oaGF2ZVJlc291cmNlKCdBV1M6OkxhbWJkYTo6RnVuY3Rpb24nLCB7XG4gICAgICAgICAgICAgICAgXCJSZWdpb25zXCI6IFNUQUNLX1BST1BTLnJlZ2lvbnNcbiAgICAgICAgICAgIH0pKTtcblxuICAgICAgICAgICAgdGVzdC5kb25lKCk7XG4gICAgICAgIH1cbiAgICB9XG59O1xuIl19 \ No newline at end of file diff --git a/packages/@aws-cdk/aws-dynamodb-global/tsconfig.json b/packages/@aws-cdk/aws-dynamodb-global/tsconfig.json new file mode 100644 index 0000000000000..b22e4f3c11020 --- /dev/null +++ b/packages/@aws-cdk/aws-dynamodb-global/tsconfig.json @@ -0,0 +1,46 @@ +{ + "compilerOptions": { + "alwaysStrict": true, + "charset": "utf8", + "declaration": true, + "experimentalDecorators": true, + "inlineSourceMap": true, + "inlineSources": true, + "lib": [ + "es2016", + "es2017.object", + "es2017.string" + ], + "module": "CommonJS", + "noEmitOnError": true, + "noFallthroughCasesInSwitch": true, + "noImplicitAny": true, + "noImplicitReturns": true, + "noImplicitThis": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "resolveJsonModule": true, + "strict": true, + "strictNullChecks": true, + "target": "ES2018", + "composite": true + }, + "include": [ + "**/*.ts" + ], + "exclude": [ + "node_modules" + ], + "references": [ + { + "path": "../aws-dynamodb" + }, + { + "path": "../aws-lambda" + }, + { + "path": "../aws-cloudformation" + } + ], + "_generated_by_jsii_": "Generated by jsii - safe to delete, and ideally should be in .gitignore" +} diff --git a/packages/@aws-cdk/aws-dynamodb/lib/table.ts b/packages/@aws-cdk/aws-dynamodb/lib/table.ts index 7272d83d0b66a..9731d92928977 100644 --- a/packages/@aws-cdk/aws-dynamodb/lib/table.ts +++ b/packages/@aws-cdk/aws-dynamodb/lib/table.ts @@ -176,11 +176,11 @@ export interface LocalSecondaryIndexProps extends SecondaryIndexProps { export class Table extends Construct { /** * Permits an IAM Principal to list all DynamoDB Streams. - * @param principal The principal (no-op if undefined) + * @param grantee The principal (no-op if undefined) */ - public static grantListStreams(principal: iam.IPrincipal): iam.Grant { + public static grantListStreams(grantee: iam.IGrantable): iam.Grant { return iam.Grant.onPrincipal({ - principal, + grantee, actions: ['dynamodb:ListStreams'], resourceArns: ['*'], }); @@ -404,12 +404,12 @@ export class Table extends Construct { /** * Adds an IAM policy statement associated with this table to an IAM * principal's policy. - * @param principal The principal (no-op if undefined) + * @param grantee The principal (no-op if undefined) * @param actions The set of actions to allow (i.e. "dynamodb:PutItem", "dynamodb:GetItem", ...) */ - public grant(principal: iam.IPrincipal, ...actions: string[]): iam.Grant { + public grant(grantee: iam.IGrantable, ...actions: string[]): iam.Grant { return iam.Grant.onPrincipal({ - principal, + grantee, actions, resourceArns: [ this.tableArn, @@ -422,12 +422,12 @@ export class Table extends Construct { /** * Adds an IAM policy statement associated with this table's stream to an * IAM principal's policy. - * @param principal The principal (no-op if undefined) + * @param grantee The principal (no-op if undefined) * @param actions The set of actions to allow (i.e. "dynamodb:DescribeStream", "dynamodb:GetRecords", ...) */ - public grantStream(principal: iam.IPrincipal, ...actions: string[]) { + public grantStream(grantee: iam.IGrantable, ...actions: string[]) { return iam.Grant.onPrincipal({ - principal, + grantee, actions, resourceArns: [this.tableStreamArn], scope: this, @@ -439,18 +439,18 @@ export class Table extends Construct { * BatchGetItem, GetRecords, GetShardIterator, Query, GetItem, Scan. * @param principal The principal to grant access to */ - public grantReadData(principal: iam.IPrincipal) { - return this.grant(principal, ...READ_DATA_ACTIONS); + public grantReadData(grantee: iam.IGrantable) { + return this.grant(grantee, ...READ_DATA_ACTIONS); } /** * Permis an IAM principal all stream data read operations for this * table's stream: * DescribeStream, GetRecords, GetShardIterator, ListStreams. - * @param principal The principal to grant access to + * @param grantee The principal to grant access to */ - public grantStreamRead(principal: iam.IPrincipal) { - return this.grantStream(principal, ...READ_STREAM_DATA_ACTIONS); + public grantStreamRead(grantee: iam.IGrantable) { + return this.grantStream(grantee, ...READ_STREAM_DATA_ACTIONS); } /** @@ -458,26 +458,26 @@ export class Table extends Construct { * BatchWriteItem, PutItem, UpdateItem, DeleteItem. * @param principal The principal to grant access to */ - public grantWriteData(principal: iam.IPrincipal) { - return this.grant(principal, ...WRITE_DATA_ACTIONS); + public grantWriteData(grantee: iam.IGrantable) { + return this.grant(grantee, ...WRITE_DATA_ACTIONS); } /** * Permits an IAM principal to all data read/write operations to this table. * BatchGetItem, GetRecords, GetShardIterator, Query, GetItem, Scan, * BatchWriteItem, PutItem, UpdateItem, DeleteItem - * @param principal The principal to grant access to + * @param grantee The principal to grant access to */ - public grantReadWriteData(principal: iam.IPrincipal) { - return this.grant(principal, ...READ_DATA_ACTIONS, ...WRITE_DATA_ACTIONS); + public grantReadWriteData(grantee: iam.IGrantable) { + return this.grant(grantee, ...READ_DATA_ACTIONS, ...WRITE_DATA_ACTIONS); } /** * Permits all DynamoDB operations ("dynamodb:*") to an IAM principal. - * @param principal The principal to grant access to + * @param grantee The principal to grant access to */ - public grantFullAccess(principal: iam.IPrincipal) { - return this.grant(principal, 'dynamodb:*'); + public grantFullAccess(grantee: iam.IGrantable) { + return this.grant(grantee, 'dynamodb:*'); } /** diff --git a/packages/@aws-cdk/aws-ecr/lib/repository-ref.ts b/packages/@aws-cdk/aws-ecr/lib/repository-ref.ts index e5c5d550e5357..fe8179c101d15 100644 --- a/packages/@aws-cdk/aws-ecr/lib/repository-ref.ts +++ b/packages/@aws-cdk/aws-ecr/lib/repository-ref.ts @@ -41,17 +41,17 @@ export interface IRepository extends cdk.IConstruct { /** * Grant the given principal identity permissions to perform the actions on this repository */ - grant(identity: iam.IPrincipal, ...actions: string[]): iam.Grant; + grant(grantee: iam.IGrantable, ...actions: string[]): iam.Grant; /** * Grant the given identity permissions to pull images in this repository. */ - grantPull(identity: iam.IPrincipal): iam.Grant; + grantPull(grantee: iam.IGrantable): iam.Grant; /** * Grant the given identity permissions to pull and push images to this repository. */ - grantPullPush(identity: iam.IPrincipal): iam.Grant; + grantPullPush(grantee: iam.IGrantable): iam.Grant; /** * Defines an AWS CloudWatch event rule that can trigger a target when an image is pushed to this @@ -189,9 +189,9 @@ export abstract class RepositoryBase extends cdk.Construct implements IRepositor /** * Grant the given principal identity permissions to perform the actions on this repository */ - public grant(principal: iam.IPrincipal, ...actions: string[]) { + public grant(grantee: iam.IGrantable, ...actions: string[]) { return iam.Grant.withResource({ - principal, + grantee, actions, resourceArns: [this.repositoryArn], resource: this, @@ -201,11 +201,11 @@ export abstract class RepositoryBase extends cdk.Construct implements IRepositor /** * Grant the given identity permissions to use the images in this repository */ - public grantPull(principal: iam.IPrincipal) { - const ret = this.grant(principal, "ecr:BatchCheckLayerAvailability", "ecr:GetDownloadUrlForLayer", "ecr:BatchGetImage"); + public grantPull(grantee: iam.IGrantable) { + const ret = this.grant(grantee, "ecr:BatchCheckLayerAvailability", "ecr:GetDownloadUrlForLayer", "ecr:BatchGetImage"); iam.Grant.onPrincipal({ - principal, + grantee, actions: ["ecr:GetAuthorizationToken"], resourceArns: ['*'], scope: this, @@ -217,9 +217,9 @@ export abstract class RepositoryBase extends cdk.Construct implements IRepositor /** * Grant the given identity permissions to pull and push images to this repository. */ - public grantPullPush(identity: iam.IPrincipal) { - this.grantPull(identity); - return this.grant(identity, + public grantPullPush(grantee: iam.IGrantable) { + this.grantPull(grantee); + return this.grant(grantee, "ecr:PutImage", "ecr:InitiateLayerUpload", "ecr:UploadLayerPart", diff --git a/packages/@aws-cdk/aws-glue/lib/table.ts b/packages/@aws-cdk/aws-glue/lib/table.ts index 6bbdb37a8809f..e0b024ac22a58 100644 --- a/packages/@aws-cdk/aws-glue/lib/table.ts +++ b/packages/@aws-cdk/aws-glue/lib/table.ts @@ -264,11 +264,11 @@ export class Table extends cdk.Construct implements ITable { /** * Grant read permissions to the table and the underlying data stored in S3 to an IAM principal. * - * @param principal the principal + * @param grantee the principal */ - public grantRead(principal: iam.IPrincipal): iam.Grant { - const ret = this.grant(principal, readPermissions); - if (this.encryptionKey && this.encryption === TableEncryption.ClientSideKms) { this.encryptionKey.grantDecrypt(principal); } + public grantRead(grantee: iam.IGrantable): iam.Grant { + const ret = this.grant(grantee, readPermissions); + if (this.encryptionKey && this.encryption === TableEncryption.ClientSideKms) { this.encryptionKey.grantDecrypt(grantee); } this.bucket.grantRead(principal, this.s3Prefix); return ret; } @@ -276,30 +276,30 @@ export class Table extends cdk.Construct implements ITable { /** * Grant write permissions to the table and the underlying data stored in S3 to an IAM principal. * - * @param principal the principal + * @param grantee the principal */ - public grantWrite(principal: iam.IPrincipal): iam.Grant { - const ret = this.grant(principal, writePermissions); - if (this.encryptionKey && this.encryption === TableEncryption.ClientSideKms) { this.encryptionKey.grantEncrypt(principal); } - this.bucket.grantWrite(principal, this.s3Prefix); + public grantWrite(grantee: iam.IGrantable): iam.Grant { + const ret = this.grant(grantee, writePermissions); + if (this.encryptionKey && this.encryption === TableEncryption.ClientSideKms) { this.encryptionKey.grantEncrypt(grantee); } + this.bucket.grantWrite(grantee, this.s3Prefix); return ret; } /** * Grant read and write permissions to the table and the underlying data stored in S3 to an IAM principal. * - * @param principal the principal + * @param grantee the principal */ - public grantReadWrite(principal: iam.IPrincipal): iam.Grant { - const ret = this.grant(principal, [...readPermissions, ...writePermissions]); - if (this.encryptionKey && this.encryption === TableEncryption.ClientSideKms) { this.encryptionKey.grantEncryptDecrypt(principal); } + public grantReadWrite(grantee: iam.IGrantable): iam.Grant { + const ret = this.grant(grantee, [...readPermissions, ...writePermissions]); + if (this.encryptionKey && this.encryption === TableEncryption.ClientSideKms) { this.encryptionKey.grantEncryptDecrypt(grantee); } this.bucket.grantReadWrite(principal, this.s3Prefix); return ret; } - private grant(principal: iam.IPrincipal, actions: string[]) { + private grant(grantee: iam.IGrantable, actions: string[]) { return iam.Grant.onPrincipal({ - principal, + grantee, resourceArns: [this.tableArn], actions, }); diff --git a/packages/@aws-cdk/aws-iam/lib/grant.ts b/packages/@aws-cdk/aws-iam/lib/grant.ts index 3ca916d2f9182..a71b1a40f8030 100644 --- a/packages/@aws-cdk/aws-iam/lib/grant.ts +++ b/packages/@aws-cdk/aws-iam/lib/grant.ts @@ -1,6 +1,6 @@ import cdk = require('@aws-cdk/cdk'); import { PolicyStatement } from "./policy-document"; -import { IPrincipal } from "./principals"; +import { IGrantable } from "./principals"; /** * Basic options for a grant operation @@ -11,7 +11,7 @@ export interface CommonGrantOptions { * * @default if principal is undefined, no work is done. */ - readonly principal: IPrincipal; + readonly grantee: IGrantable; /** * The actions to grant @@ -109,7 +109,7 @@ export class Grant { const statement = new PolicyStatement() .addActions(...options.actions) .addResources(...(options.resourceSelfArns || options.resourceArns)) - .addPrincipal(options.principal!); + .addPrincipal(options.grantee!.grantPrincipal); options.resource.addToResourcePolicy(statement); @@ -127,7 +127,7 @@ export class Grant { .addActions(...options.actions) .addResources(...options.resourceArns); - const addedToPrincipal = options.principal.addToPolicy(statement); + const addedToPrincipal = options.grantee.grantPrincipal.addToPolicy(statement); return new Grant({ principalStatement: addedToPrincipal ? statement : undefined, options }); } @@ -150,7 +150,7 @@ export class Grant { const statement = new PolicyStatement() .addActions(...options.actions) .addResources(...(options.resourceSelfArns || options.resourceArns)) - .addPrincipal(options.principal!); + .addPrincipal(options.grantee!.grantPrincipal); options.resource.addToResourcePolicy(statement); @@ -204,7 +204,7 @@ export class Grant { } function describeGrant(options: CommonGrantOptions) { - return `Permissions for '${options.principal}' to call '${options.actions}' on '${options.resourceArns}'`; + return `Permissions for '${options.grantee}' to call '${options.actions}' on '${options.resourceArns}'`; } interface GrantProps { diff --git a/packages/@aws-cdk/aws-iam/lib/group.ts b/packages/@aws-cdk/aws-iam/lib/group.ts index 4f4f462822ac4..f9e6360230e04 100644 --- a/packages/@aws-cdk/aws-iam/lib/group.ts +++ b/packages/@aws-cdk/aws-iam/lib/group.ts @@ -3,6 +3,7 @@ import { CfnGroup } from './iam.generated'; import { IIdentity } from './identity-base'; import { Policy } from './policy'; import { ArnPrincipal, PolicyStatement, PrincipalPolicyFragment } from './policy-document'; +import { IPrincipal } from './principals'; import { User } from './user'; import { AttachedPolicies, undefinedIfEmpty } from './util'; @@ -36,6 +37,7 @@ export interface GroupProps { } export class Group extends Construct implements IIdentity { + public readonly grantPrincipal: IPrincipal = this; public readonly assumeRoleAction: string = 'sts:AssumeRole'; /** * The runtime name of this group. diff --git a/packages/@aws-cdk/aws-iam/lib/imported-resource-principal.ts b/packages/@aws-cdk/aws-iam/lib/imported-resource-principal.ts new file mode 100644 index 0000000000000..e4079c8c75694 --- /dev/null +++ b/packages/@aws-cdk/aws-iam/lib/imported-resource-principal.ts @@ -0,0 +1,45 @@ +import cdk = require('@aws-cdk/cdk'); +import { PolicyStatement, PrincipalPolicyFragment } from './policy-document'; +import { IPrincipal } from './principals'; + +/** + * Properties for an ImportedResourcePrincipal + */ +export interface ImportedResourcePrincipalProps { + /** + * The resource the role proxy is for + */ + readonly resource: cdk.IConstruct; +} + +/** + * A principal associated with an imported resource + * + * Some resources have roles associated with them which they assume, such as + * Lambda Functions, CodeBuild projects, StepFunctions machines, etc. + * + * When those resources are imported, their actual roles are not always + * imported with them. When that happens, we use an instance of this class + * instead, which will add user warnings when statements are attempted to be + * added to it. + */ +export class ImportedResourcePrincipal implements IPrincipal { + public readonly assumeRoleAction: string = 'sts:AssumeRole'; + public readonly grantPrincipal: IPrincipal; + private readonly resource: cdk.IConstruct; + + constructor(props: ImportedResourcePrincipalProps) { + this.resource = props.resource; + this.grantPrincipal = this; + } + + public get policyFragment(): PrincipalPolicyFragment { + throw new Error(`Cannot get policy fragment of ${this.resource.node.path}, resource imported without a role`); + } + + public addToPolicy(statement: PolicyStatement): boolean { + const repr = JSON.stringify(this.resource.node.resolve(statement)); + this.resource.node.addWarning(`Add statement to this resource's role: ${repr}`); + return true; // Pretend we did the work. The human will do it for us, eventually. + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-iam/lib/index.ts b/packages/@aws-cdk/aws-iam/lib/index.ts index 11526872d93e7..d8566a304f30f 100644 --- a/packages/@aws-cdk/aws-iam/lib/index.ts +++ b/packages/@aws-cdk/aws-iam/lib/index.ts @@ -8,6 +8,7 @@ export * from './lazy-role'; export * from './principals'; export * from './identity-base'; export * from './grant'; +export * from './imported-resource-principal'; // AWS::IAM CloudFormation Resources: export * from './iam.generated'; diff --git a/packages/@aws-cdk/aws-iam/lib/lazy-role.ts b/packages/@aws-cdk/aws-iam/lib/lazy-role.ts index 81d9f0e271018..9b4a290b9fa1f 100644 --- a/packages/@aws-cdk/aws-iam/lib/lazy-role.ts +++ b/packages/@aws-cdk/aws-iam/lib/lazy-role.ts @@ -15,6 +15,7 @@ import { IRole, Role, RoleImportProps, RoleProps } from './role'; * not be synthesized or deployed. */ export class LazyRole extends cdk.Construct implements IRole { + public readonly grantPrincipal: IPrincipal = this; public readonly assumeRoleAction: string = 'sts:AssumeRole'; private role?: Role; private readonly statements = new Array(); diff --git a/packages/@aws-cdk/aws-iam/lib/policy-document.ts b/packages/@aws-cdk/aws-iam/lib/policy-document.ts index c5b2487e31e48..c8d229d03ad34 100644 --- a/packages/@aws-cdk/aws-iam/lib/policy-document.ts +++ b/packages/@aws-cdk/aws-iam/lib/policy-document.ts @@ -49,6 +49,8 @@ export class PolicyDocument extends cdk.Token { * Base class for policy principals */ export abstract class PrincipalBase implements IPrincipal { + public readonly grantPrincipal: IPrincipal = this; + /** * Return the policy fragment that identifies this principal in a Policy. */ diff --git a/packages/@aws-cdk/aws-iam/lib/principals.ts b/packages/@aws-cdk/aws-iam/lib/principals.ts index 11d59cfea7773..70bd154fc2e3c 100644 --- a/packages/@aws-cdk/aws-iam/lib/principals.ts +++ b/packages/@aws-cdk/aws-iam/lib/principals.ts @@ -1,5 +1,15 @@ import { PolicyStatement, PrincipalPolicyFragment } from './policy-document'; +/** + * Any object that has an associated principal that a permission can be granted to + */ +export interface IGrantable { + /** + * The principal to grant permissions to + */ + readonly grantPrincipal: IPrincipal; +} + /** * Represents a logical IAM principal. * @@ -17,7 +27,7 @@ import { PolicyStatement, PrincipalPolicyFragment } from './policy-document'; * For example, `new OrganizationPrincipal('o-1234')` represents all * identities that are part of the given AWS Organization. */ -export interface IPrincipal { +export interface IPrincipal extends IGrantable { /** * When this Principal is used in an AssumeRole policy, the action to use. */ diff --git a/packages/@aws-cdk/aws-iam/lib/role.ts b/packages/@aws-cdk/aws-iam/lib/role.ts index 85a3eb697fe6a..1e9e160fe77cf 100644 --- a/packages/@aws-cdk/aws-iam/lib/role.ts +++ b/packages/@aws-cdk/aws-iam/lib/role.ts @@ -101,6 +101,8 @@ export class Role extends Construct implements IRole { return new ImportedRole(scope, id, props); } + public readonly grantPrincipal: IPrincipal = this; + public readonly assumeRoleAction: string = 'sts:AssumeRole'; /** @@ -209,9 +211,9 @@ export class Role extends Construct implements IRole { /** * Grant the actions defined in actions to the identity Principal on this resource. */ - public grant(principal: IPrincipal, ...actions: string[]) { + public grant(grantee: IPrincipal, ...actions: string[]) { return Grant.onPrincipal({ - principal, + grantee, actions, resourceArns: [this.roleArn], scope: this @@ -254,12 +256,12 @@ export interface IRole extends IIdentity { /** * Grant the actions defined in actions to the identity Principal on this resource. */ - grant(identity: IPrincipal, ...actions: string[]): Grant; + grant(grantee: IPrincipal, ...actions: string[]): Grant; /** * Grant permissions to the given principal to pass this role. */ - grantPassRole(identity: IPrincipal): Grant; + grantPassRole(grantee: IPrincipal): Grant; } function createAssumeRolePolicy(principal: IPrincipal, externalId?: string) { @@ -308,6 +310,7 @@ export interface RoleImportProps { * A role that already exists */ class ImportedRole extends Construct implements IRole { + public readonly grantPrincipal: IPrincipal = this; public readonly assumeRoleAction: string = 'sts:AssumeRole'; public readonly policyFragment: PrincipalPolicyFragment; public readonly roleArn: string; @@ -352,9 +355,9 @@ class ImportedRole extends Construct implements IRole { /** * Grant the actions defined in actions to the identity Principal on this resource. */ - public grant(principal: IPrincipal, ...actions: string[]): Grant { + public grant(grantee: IPrincipal, ...actions: string[]): Grant { return Grant.onPrincipal({ - principal, + grantee, actions, resourceArns: [this.roleArn], scope: this diff --git a/packages/@aws-cdk/aws-iam/lib/user.ts b/packages/@aws-cdk/aws-iam/lib/user.ts index 7b236be56c56f..3c9a04e49a7af 100644 --- a/packages/@aws-cdk/aws-iam/lib/user.ts +++ b/packages/@aws-cdk/aws-iam/lib/user.ts @@ -5,6 +5,7 @@ import { IIdentity } from './identity-base'; import { Policy } from './policy'; import { PolicyStatement } from './policy-document'; import { ArnPrincipal, PrincipalPolicyFragment } from './policy-document'; +import { IPrincipal } from './principals'; import { AttachedPolicies, undefinedIfEmpty } from './util'; export interface UserProps { @@ -65,6 +66,7 @@ export interface UserProps { } export class User extends Construct implements IIdentity { + public readonly grantPrincipal: IPrincipal = this; public readonly assumeRoleAction: string = 'sts:AssumeRole'; /** diff --git a/packages/@aws-cdk/aws-iam/test/test.policy-document.ts b/packages/@aws-cdk/aws-iam/test/test.policy-document.ts index 96b5efa1a2b3a..6b730c272ac3d 100644 --- a/packages/@aws-cdk/aws-iam/test/test.policy-document.ts +++ b/packages/@aws-cdk/aws-iam/test/test.policy-document.ts @@ -279,6 +279,7 @@ export = { 'addPrincipal correctly merges array in'(test: Test) { const stack = new Stack(); const arrayPrincipal: IPrincipal = { + get grantPrincipal() { return this; }, assumeRoleAction: 'sts:AssumeRole', policyFragment: new PrincipalPolicyFragment({ AWS: ['foo', 'bar'] }), addToPolicy() { return false; } diff --git a/packages/@aws-cdk/aws-kinesis/lib/stream.ts b/packages/@aws-cdk/aws-kinesis/lib/stream.ts index d21e457d362e8..064226f689adc 100644 --- a/packages/@aws-cdk/aws-kinesis/lib/stream.ts +++ b/packages/@aws-cdk/aws-kinesis/lib/stream.ts @@ -32,7 +32,7 @@ export interface IStream extends cdk.IConstruct, logs.ILogSubscriptionDestinatio * If an encryption key is used, permission to ues the key to decrypt the * contents of the stream will also be granted. */ - grantRead(identity: iam.IPrincipal): iam.Grant; + grantRead(grantee: iam.IGrantable): iam.Grant; /** * Grant write permissions for this stream and its contents to an IAM @@ -41,7 +41,7 @@ export interface IStream extends cdk.IConstruct, logs.ILogSubscriptionDestinatio * If an encryption key is used, permission to ues the key to encrypt the * contents of the stream will also be granted. */ - grantWrite(identity: iam.IPrincipal): iam.Grant; + grantWrite(grantee: iam.IGrantable): iam.Grant; /** * Grants read/write permissions for this stream and its contents to an IAM @@ -50,7 +50,7 @@ export interface IStream extends cdk.IConstruct, logs.ILogSubscriptionDestinatio * If an encryption key is used, permission to use the key for * encrypt/decrypt will also be granted. */ - grantReadWrite(identity: iam.IPrincipal): iam.Grant; + grantReadWrite(grantee: iam.IGrantable): iam.Grant; } /** @@ -117,11 +117,11 @@ export abstract class StreamBase extends cdk.Construct implements IStream { * If an encryption key is used, permission to ues the key to decrypt the * contents of the stream will also be granted. */ - public grantRead(principal: iam.IPrincipal) { - const ret = this.grant(principal, 'kinesis:DescribeStream', 'kinesis:GetRecords', 'kinesis:GetShardIterator'); + public grantRead(grantee: iam.IGrantable) { + const ret = this.grant(grantee, 'kinesis:DescribeStream', 'kinesis:GetRecords', 'kinesis:GetShardIterator'); if (this.encryptionKey) { - this.encryptionKey.grantDecrypt(principal); + this.encryptionKey.grantDecrypt(grantee); } return ret; @@ -134,11 +134,11 @@ export abstract class StreamBase extends cdk.Construct implements IStream { * If an encryption key is used, permission to ues the key to decrypt the * contents of the stream will also be granted. */ - public grantWrite(principal: iam.IPrincipal) { - const ret = this.grant(principal, 'kinesis:DescribeStream', 'kinesis:PutRecord', 'kinesis:PutRecords'); + public grantWrite(grantee: iam.IGrantable) { + const ret = this.grant(grantee, 'kinesis:DescribeStream', 'kinesis:PutRecord', 'kinesis:PutRecords'); if (this.encryptionKey) { - this.encryptionKey.grantEncrypt(principal); + this.encryptionKey.grantEncrypt(grantee); } return ret; @@ -151,9 +151,9 @@ export abstract class StreamBase extends cdk.Construct implements IStream { * If an encryption key is used, permission to use the key for * encrypt/decrypt will also be granted. */ - public grantReadWrite(principal: iam.IPrincipal) { + public grantReadWrite(grantee: iam.IGrantable) { const ret = this.grant( - principal, + grantee, 'kinesis:DescribeStream', 'kinesis:GetRecords', 'kinesis:GetShardIterator', @@ -161,7 +161,7 @@ export abstract class StreamBase extends cdk.Construct implements IStream { 'kinesis:PutRecords'); if (this.encryptionKey) { - this.encryptionKey.grantEncryptDecrypt(principal); + this.encryptionKey.grantEncryptDecrypt(grantee); } return ret; @@ -227,9 +227,9 @@ export abstract class StreamBase extends cdk.Construct implements IStream { return dest.logSubscriptionDestination(sourceLogGroup); } - private grant(principal: iam.IPrincipal, ...actions: string[]) { + private grant(grantee: iam.IGrantable, ...actions: string[]) { return iam.Grant.onPrincipal({ - principal, + grantee, actions, resourceArns: [this.streamArn], scope: this, diff --git a/packages/@aws-cdk/aws-kms/lib/key.ts b/packages/@aws-cdk/aws-kms/lib/key.ts index 3053128bab6cc..65db50e30bb8b 100644 --- a/packages/@aws-cdk/aws-kms/lib/key.ts +++ b/packages/@aws-cdk/aws-kms/lib/key.ts @@ -33,22 +33,22 @@ export interface IEncryptionKey extends IConstruct { /** * Grant the indicated permissions on this key to the given principal */ - grant(principal: iam.IPrincipal, ...actions: string[]): iam.Grant; + grant(grantee: iam.IGrantable, ...actions: string[]): iam.Grant; /** * Grant decryption permisisons using this key to the given principal */ - grantDecrypt(principal: iam.IPrincipal): iam.Grant; + grantDecrypt(grantee: iam.IGrantable): iam.Grant; /** * Grant encryption permisisons using this key to the given principal */ - grantEncrypt(principal: iam.IPrincipal): iam.Grant; + grantEncrypt(grantee: iam.IGrantable): iam.Grant; /** * Grant encryption and decryption permisisons using this key to the given principal */ - grantEncryptDecrypt(principal: iam.IPrincipal): iam.Grant; + grantEncryptDecrypt(grantee: iam.IGrantable): iam.Grant; } export interface EncryptionKeyImportProps { @@ -104,9 +104,9 @@ export abstract class EncryptionKeyBase extends Construct implements IEncryption * since the default CloudFormation setup for KMS keys is that the policy * must not be empty and so default grants won't work. */ - public grant(principal: iam.IPrincipal, ...actions: string[]): iam.Grant { + public grant(grantee: iam.IGrantable, ...actions: string[]): iam.Grant { return iam.Grant.onPrincipalAndResource({ - principal, + grantee, actions, resourceArns: [this.keyArn], resource: this, @@ -117,8 +117,8 @@ export abstract class EncryptionKeyBase extends Construct implements IEncryption /** * Grant decryption permisisons using this key to the given principal */ - public grantDecrypt(principal: iam.IPrincipal): iam.Grant { - return this.grant(principal, + public grantDecrypt(grantee: iam.IGrantable): iam.Grant { + return this.grant(grantee, 'kms:Decrypt', ); } @@ -126,8 +126,8 @@ export abstract class EncryptionKeyBase extends Construct implements IEncryption /** * Grant encryption permisisons using this key to the given principal */ - public grantEncrypt(principal: iam.IPrincipal): iam.Grant { - return this.grant(principal, + public grantEncrypt(grantee: iam.IGrantable): iam.Grant { + return this.grant(grantee, 'kms:Encrypt', 'kms:ReEncrypt*', 'kms:GenerateDataKey*' @@ -137,8 +137,8 @@ export abstract class EncryptionKeyBase extends Construct implements IEncryption /** * Grant encryption and decryption permisisons using this key to the given principal */ - public grantEncryptDecrypt(principal: iam.IPrincipal): iam.Grant { - return this.grant(principal, + public grantEncryptDecrypt(grantee: iam.IGrantable): iam.Grant { + return this.grant(grantee, 'kms:Decrypt', 'kms:Encrypt', 'kms:ReEncrypt*', diff --git a/packages/@aws-cdk/aws-lambda/lib/function-base.ts b/packages/@aws-cdk/aws-lambda/lib/function-base.ts index 59de8d6c3bee4..6d30cd6afb67b 100644 --- a/packages/@aws-cdk/aws-lambda/lib/function-base.ts +++ b/packages/@aws-cdk/aws-lambda/lib/function-base.ts @@ -11,7 +11,7 @@ import { CfnPermission } from './lambda.generated'; import { Permission } from './permission'; export interface IFunction extends cdk.IConstruct, events.IEventRuleTarget, logs.ILogSubscriptionDestination, - s3n.IBucketNotificationDestination, ec2.IConnectable, stepfunctions.IStepFunctionsTaskResource { + s3n.IBucketNotificationDestination, ec2.IConnectable, stepfunctions.IStepFunctionsTaskResource, iam.IGrantable { /** * Logical ID of this Function. @@ -31,7 +31,7 @@ export interface IFunction extends cdk.IConstruct, events.IEventRuleTarget, logs /** * The IAM role associated with this function. */ - readonly role: iam.IRole; + readonly role?: iam.IRole; /** * Whether or not this Lambda function was bound to a VPC @@ -51,7 +51,7 @@ export interface IFunction extends cdk.IConstruct, events.IEventRuleTarget, logs /** * Grant the given identity permissions to invoke this Lambda */ - grantInvoke(identity: iam.IPrincipal): iam.Grant; + grantInvoke(identity: iam.IGrantable): iam.Grant; /** * Return the given named metric for this Lambda @@ -115,6 +115,10 @@ export interface FunctionImportProps { } export abstract class FunctionBase extends cdk.Construct implements IFunction { + /** + * The principal this Lambda Function is running as + */ + public abstract readonly grantPrincipal: iam.IPrincipal; /** * The name of the function. @@ -128,8 +132,10 @@ export abstract class FunctionBase extends cdk.Construct implements IFunction { /** * The IAM role associated with this function. + * + * Undefined if the function was imported without a role. */ - public abstract readonly role: iam.IRole; + public abstract readonly role?: iam.IRole; /** * Whether the addPermission() call adds any permissions @@ -231,9 +237,9 @@ export abstract class FunctionBase extends cdk.Construct implements IFunction { /** * Grant the given identity permissions to invoke this Lambda */ - public grantInvoke(principal: iam.IPrincipal): iam.Grant { + public grantInvoke(grantee: iam.IGrantable): iam.Grant { return iam.Grant.withResource({ - principal, + grantee, actions: ['lambda:InvokeFunction'], resourceArns: [this.functionArn], @@ -242,9 +248,9 @@ export abstract class FunctionBase extends cdk.Construct implements IFunction { resource: { addToResourcePolicy: (_statement) => { // Couldn't add permissions to the principal, so add them locally. - const identifier = 'Invoke' + JSON.stringify(principal!.policyFragment.principalJson); + const identifier = 'Invoke' + JSON.stringify(grantee!.grantPrincipal.policyFragment.principalJson); this.addPermission(identifier, { - principal: principal!, + principal: grantee.grantPrincipal!, action: 'lambda:InvokeFunction', }); }, @@ -330,7 +336,7 @@ export abstract class FunctionBase extends cdk.Construct implements IFunction { source.bind(this); } - private parsePermissionPrincipal(principal?: iam.IPrincipal) { + private parsePermissionPrincipal(principal?: iam.IGrantable) { if (!principal) { return undefined; } diff --git a/packages/@aws-cdk/aws-lambda/lib/function.ts b/packages/@aws-cdk/aws-lambda/lib/function.ts index 06561634e0cdc..c0a750f248731 100644 --- a/packages/@aws-cdk/aws-lambda/lib/function.ts +++ b/packages/@aws-cdk/aws-lambda/lib/function.ts @@ -321,7 +321,7 @@ export class Function extends FunctionBase { /** * Execution role associated with this function */ - public readonly role: iam.IRole; + public readonly role?: iam.IRole; /** * The runtime configured for this lambda. @@ -333,6 +333,11 @@ export class Function extends FunctionBase { */ public readonly handler: string; + /** + * The principal this Lambda Function is running as + */ + public readonly grantPrincipal: iam.IPrincipal; + protected readonly canCreatePermissions = true; private readonly layers: ILayerVersion[] = []; @@ -361,6 +366,7 @@ export class Function extends FunctionBase { assumedBy: new iam.ServicePrincipal('lambda.amazonaws.com'), managedPolicyArns, }); + this.grantPrincipal = this.role; for (const statement of (props.initialPolicy || [])) { this.role.addToPolicy(statement); @@ -600,9 +606,10 @@ export class Function extends FunctionBase { } export class ImportedFunction extends FunctionBase { + public readonly grantPrincipal: iam.IPrincipal; public readonly functionName: string; public readonly functionArn: string; - public readonly role: iam.IRole; + public readonly role?: iam.IRole; protected readonly canCreatePermissions = false; @@ -612,6 +619,7 @@ export class ImportedFunction extends FunctionBase { this.functionArn = props.functionArn; this.functionName = extractNameFromArn(props.functionArn); this.role = props.role; + this.grantPrincipal = this.role || new iam.ImportedResourcePrincipal({ resource: this } ); if (props.securityGroupId) { this._connections = new ec2.Connections({ diff --git a/packages/@aws-cdk/aws-lambda/lib/singleton-lambda.ts b/packages/@aws-cdk/aws-lambda/lib/singleton-lambda.ts index 50a9f7762522c..fbecb0b0e997e 100644 --- a/packages/@aws-cdk/aws-lambda/lib/singleton-lambda.ts +++ b/packages/@aws-cdk/aws-lambda/lib/singleton-lambda.ts @@ -35,9 +35,10 @@ export interface SingletonFunctionProps extends FunctionProps { * for every SingletonLambda you create. */ export class SingletonFunction extends FunctionBase { + public readonly grantPrincipal: iam.IPrincipal; public readonly functionName: string; public readonly functionArn: string; - public readonly role: iam.IRole; + public readonly role?: iam.IRole; protected readonly canCreatePermissions: boolean; private lambdaFunction: IFunction; @@ -49,6 +50,7 @@ export class SingletonFunction extends FunctionBase { this.functionArn = this.lambdaFunction.functionArn; this.functionName = this.lambdaFunction.functionName; this.role = this.lambdaFunction.role; + this.grantPrincipal = this.lambdaFunction.grantPrincipal; this.canCreatePermissions = true; // Doesn't matter, addPermission is overriden anyway } diff --git a/packages/@aws-cdk/aws-lambda/package-lock.json b/packages/@aws-cdk/aws-lambda/package-lock.json index a2bc8923e4b90..7da9748305bf3 100644 --- a/packages/@aws-cdk/aws-lambda/package-lock.json +++ b/packages/@aws-cdk/aws-lambda/package-lock.json @@ -1,6 +1,6 @@ { "name": "@aws-cdk/aws-lambda", - "version": "0.26.0", + "version": "0.27.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/packages/@aws-cdk/aws-logs/lib/log-group.ts b/packages/@aws-cdk/aws-logs/lib/log-group.ts index 2c4cd5ebd69e5..dcf4eddc93f53 100644 --- a/packages/@aws-cdk/aws-logs/lib/log-group.ts +++ b/packages/@aws-cdk/aws-logs/lib/log-group.ts @@ -69,12 +69,12 @@ export interface ILogGroup extends cdk.IConstruct { /** * Give permissions to write to create and write to streams in this log group */ - grantWrite(principal: iam.IPrincipal): iam.Grant; + grantWrite(grantee: iam.IGrantable): iam.Grant; /** * Give the indicated permissions on this log group and all streams */ - grant(principal: iam.IPrincipal, ...actions: string[]): iam.Grant; + grant(grantee: iam.IGrantable, ...actions: string[]): iam.Grant; } /** @@ -171,16 +171,16 @@ export abstract class LogGroupBase extends cdk.Construct implements ILogGroup { /** * Give permissions to write to create and write to streams in this log group */ - public grantWrite(principal: iam.IPrincipal) { - return this.grant(principal, 'logs:CreateLogStream', 'logs:PutLogEvents'); + public grantWrite(grantee: iam.IGrantable) { + return this.grant(grantee, 'logs:CreateLogStream', 'logs:PutLogEvents'); } /** * Give the indicated permissions on this log group and all streams */ - public grant(principal: iam.IPrincipal, ...actions: string[]) { + public grant(grantee: iam.IGrantable, ...actions: string[]) { return iam.Grant.onPrincipal({ - principal, + grantee, actions, // A LogGroup ARN out of CloudFormation already includes a ':*' at the end to include the log streams under the group. // See https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-logs-loggroup.html#w2ab1c21c10c63c43c11 diff --git a/packages/@aws-cdk/aws-s3/lib/bucket.ts b/packages/@aws-cdk/aws-s3/lib/bucket.ts index bd5782e2eade0..0511c54c48893 100644 --- a/packages/@aws-cdk/aws-s3/lib/bucket.ts +++ b/packages/@aws-cdk/aws-s3/lib/bucket.ts @@ -91,7 +91,7 @@ export interface IBucket extends cdk.IConstruct { * @param identity The principal * @param objectsKeyPattern Restrict the permission to a certain key pattern (default '*') */ - grantRead(identity: iam.IPrincipal, objectsKeyPattern?: any): iam.Grant; + grantRead(identity: iam.IGrantable, objectsKeyPattern?: any): iam.Grant; /** * Grant write permissions to this bucket to an IAM principal. @@ -102,7 +102,7 @@ export interface IBucket extends cdk.IConstruct { * @param identity The principal * @param objectsKeyPattern Restrict the permission to a certain key pattern (default '*') */ - grantWrite(identity: iam.IPrincipal, objectsKeyPattern?: any): iam.Grant; + grantWrite(identity: iam.IGrantable, objectsKeyPattern?: any): iam.Grant; /** * Grants s3:PutObject* and s3:Abort* permissions for this bucket to an IAM principal. @@ -112,7 +112,7 @@ export interface IBucket extends cdk.IConstruct { * @param identity The principal * @param objectsKeyPattern Restrict the permission to a certain key pattern (default '*') */ - grantPut(identity: iam.IPrincipal, objectsKeyPattern?: any): iam.Grant; + grantPut(identity: iam.IGrantable, objectsKeyPattern?: any): iam.Grant; /** * Grants s3:DeleteObject* permission to an IAM pricipal for objects @@ -121,7 +121,7 @@ export interface IBucket extends cdk.IConstruct { * @param identity The principal * @param objectsKeyPattern Restrict the permission to a certain key pattern (default '*') */ - grantDelete(identity: iam.IPrincipal, objectsKeyPattern?: any): iam.Grant; + grantDelete(identity: iam.IGrantable, objectsKeyPattern?: any): iam.Grant; /** * Grants read/write permissions for this bucket and it's contents to an IAM @@ -133,7 +133,7 @@ export interface IBucket extends cdk.IConstruct { * @param identity The principal * @param objectsKeyPattern Restrict the permission to a certain key pattern (default '*') */ - grantReadWrite(identity: iam.IPrincipal, objectsKeyPattern?: any): iam.Grant; + grantReadWrite(identity: iam.IGrantable, objectsKeyPattern?: any): iam.Grant; /** * Allows unrestricted access to objects from this bucket. @@ -375,7 +375,7 @@ export abstract class BucketBase extends cdk.Construct implements IBucket { * @param identity The principal * @param objectsKeyPattern Restrict the permission to a certain key pattern (default '*') */ - public grantRead(identity: iam.IPrincipal, objectsKeyPattern: any = '*') { + public grantRead(identity: iam.IGrantable, objectsKeyPattern: any = '*') { return this.grant(identity, perms.BUCKET_READ_ACTIONS, perms.KEY_READ_ACTIONS, this.bucketArn, this.arnForObjects(objectsKeyPattern)); @@ -390,7 +390,7 @@ export abstract class BucketBase extends cdk.Construct implements IBucket { * @param identity The principal * @param objectsKeyPattern Restrict the permission to a certain key pattern (default '*') */ - public grantWrite(identity: iam.IPrincipal, objectsKeyPattern: any = '*') { + public grantWrite(identity: iam.IGrantable, objectsKeyPattern: any = '*') { return this.grant(identity, perms.BUCKET_WRITE_ACTIONS, perms.KEY_WRITE_ACTIONS, this.bucketArn, this.arnForObjects(objectsKeyPattern)); @@ -404,7 +404,7 @@ export abstract class BucketBase extends cdk.Construct implements IBucket { * @param identity The principal * @param objectsKeyPattern Restrict the permission to a certain key pattern (default '*') */ - public grantPut(identity: iam.IPrincipal, objectsKeyPattern: any = '*') { + public grantPut(identity: iam.IGrantable, objectsKeyPattern: any = '*') { return this.grant(identity, perms.BUCKET_PUT_ACTIONS, perms.KEY_WRITE_ACTIONS, this.arnForObjects(objectsKeyPattern)); } @@ -416,7 +416,7 @@ export abstract class BucketBase extends cdk.Construct implements IBucket { * @param identity The principal * @param objectsKeyPattern Restrict the permission to a certain key pattern (default '*') */ - public grantDelete(identity: iam.IPrincipal, objectsKeyPattern: any = '*') { + public grantDelete(identity: iam.IGrantable, objectsKeyPattern: any = '*') { return this.grant(identity, perms.BUCKET_DELETE_ACTIONS, [], this.arnForObjects(objectsKeyPattern)); } @@ -431,7 +431,7 @@ export abstract class BucketBase extends cdk.Construct implements IBucket { * @param identity The principal * @param objectsKeyPattern Restrict the permission to a certain key pattern (default '*') */ - public grantReadWrite(identity: iam.IPrincipal, objectsKeyPattern: any = '*') { + public grantReadWrite(identity: iam.IGrantable, objectsKeyPattern: any = '*') { const bucketActions = perms.BUCKET_READ_ACTIONS.concat(perms.BUCKET_WRITE_ACTIONS); const keyActions = perms.KEY_READ_ACTIONS.concat(perms.KEY_WRITE_ACTIONS); @@ -474,26 +474,26 @@ export abstract class BucketBase extends cdk.Construct implements IBucket { return iam.Grant.withResource({ actions: allowedActions, resourceArns: [this.arnForObjects(keyPrefix)], - principal: new iam.Anyone(), + grantee: new iam.Anyone(), resource: this, }); } - private grant(principal: iam.IPrincipal, + private grant(grantee: iam.IGrantable, bucketActions: string[], keyActions: string[], resourceArn: string, ...otherResourceArns: string[]) { const resources = [ resourceArn, ...otherResourceArns ]; const ret = iam.Grant.withResource({ - principal, + grantee, actions: bucketActions, resourceArns: resources, resource: this, }); if (this.encryptionKey) { - this.encryptionKey.grant(principal, ...keyActions); + this.encryptionKey.grant(grantee, ...keyActions); } return ret; diff --git a/packages/@aws-cdk/aws-secretsmanager/lib/secret.ts b/packages/@aws-cdk/aws-secretsmanager/lib/secret.ts index 6fbd01f5c0d25..b2727082167f1 100644 --- a/packages/@aws-cdk/aws-secretsmanager/lib/secret.ts +++ b/packages/@aws-cdk/aws-secretsmanager/lib/secret.ts @@ -51,7 +51,7 @@ export interface ISecret extends cdk.IConstruct { * @param versionStages the version stages the grant is limited to. If not specified, no restriction on the version * stages is applied. */ - grantRead(principal: iam.IPrincipal, versionStages?: string[]): iam.Grant; + grantRead(grantee: iam.IGrantable, versionStages?: string[]): iam.Grant; /** * Adds a rotation schedule to the secret. @@ -118,11 +118,11 @@ export abstract class SecretBase extends cdk.Construct implements ISecret { public abstract export(): SecretImportProps; - public grantRead(principal: iam.IPrincipal, versionStages?: string[]): iam.Grant { + public grantRead(grantee: iam.IGrantable, versionStages?: string[]): iam.Grant { // @see https://docs.aws.amazon.com/fr_fr/secretsmanager/latest/userguide/auth-and-access_identity-based-policies.html const result = iam.Grant.onPrincipal({ - principal, + grantee, actions: ['secretsmanager:GetSecretValue'], resourceArns: [this.secretArn], scope: this @@ -133,10 +133,10 @@ export abstract class SecretBase extends cdk.Construct implements ISecret { }); } - if (this.encryptionKey && principal) { + if (this.encryptionKey) { // @see https://docs.aws.amazon.com/fr_fr/kms/latest/developerguide/services-secrets-manager.html this.encryptionKey.grantDecrypt( - new kms.ViaServicePrincipal(`secretsmanager.${this.node.stack.region}.amazonaws.com`, principal) + new kms.ViaServicePrincipal(`secretsmanager.${this.node.stack.region}.amazonaws.com`, grantee.grantPrincipal) ); } diff --git a/packages/@aws-cdk/aws-serverless/lib/serverless.generated.ts b/packages/@aws-cdk/aws-serverless/lib/serverless.generated.ts new file mode 100644 index 0000000000000..d45bee28444ee --- /dev/null +++ b/packages/@aws-cdk/aws-serverless/lib/serverless.generated.ts @@ -0,0 +1,2035 @@ +// Copyright 2012-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. +// Generated from the AWS CloudFormation Resource Specification +// See: docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/cfn-resource-specification.html +// @cfn2ts:meta@ {"generated":"2019-03-21T09:12:23.615Z","fingerprint":"UJ42fezBazlHPOkm0pNitOMM9peubfGEd2/XcTwSlsI="} + +// tslint:disable:max-line-length | This is generated code - line lengths are difficult to control + +import cdk = require('@aws-cdk/cdk'); + +/** + * Properties for defining a `AWS::Serverless::Api` + * @see https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessapi + */ +export interface CfnApiProps { + /** + * `AWS::Serverless::Api.StageName` + * @see https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessapi + */ + stageName: string; + /** + * `AWS::Serverless::Api.Auth` + * @see https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessapi + */ + auth?: CfnApi.AuthProperty | cdk.Token; + /** + * `AWS::Serverless::Api.BinaryMediaTypes` + * @see https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessapi + */ + binaryMediaTypes?: string[]; + /** + * `AWS::Serverless::Api.CacheClusterEnabled` + * @see https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessapi + */ + cacheClusterEnabled?: boolean | cdk.Token; + /** + * `AWS::Serverless::Api.CacheClusterSize` + * @see https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessapi + */ + cacheClusterSize?: string; + /** + * `AWS::Serverless::Api.Cors` + * @see https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessapi + */ + cors?: string; + /** + * `AWS::Serverless::Api.DefinitionBody` + * @see https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessapi + */ + definitionBody?: object | cdk.Token; + /** + * `AWS::Serverless::Api.DefinitionUri` + * @see https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessapi + */ + definitionUri?: CfnApi.S3LocationProperty | string | cdk.Token; + /** + * `AWS::Serverless::Api.EndpointConfiguration` + * @see https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessapi + */ + endpointConfiguration?: string; + /** + * `AWS::Serverless::Api.MethodSettings` + * @see https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessapi + */ + methodSettings?: object | cdk.Token; + /** + * `AWS::Serverless::Api.Name` + * @see https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessapi + */ + name?: string; + /** + * `AWS::Serverless::Api.Variables` + * @see https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessapi + */ + variables?: { [key: string]: (string) } | cdk.Token; +} + +/** + * Determine whether the given properties match those of a `CfnApiProps` + * + * @param properties - the TypeScript properties of a `CfnApiProps` + * + * @returns the result of the validation. + */ +function CfnApiPropsValidator(properties: any): cdk.ValidationResult { + if (!cdk.canInspect(properties)) { return cdk.VALIDATION_SUCCESS; } + const errors = new cdk.ValidationResults(); + errors.collect(cdk.propertyValidator('auth', CfnApi_AuthPropertyValidator)(properties.auth)); + errors.collect(cdk.propertyValidator('binaryMediaTypes', cdk.listValidator(cdk.validateString))(properties.binaryMediaTypes)); + errors.collect(cdk.propertyValidator('cacheClusterEnabled', cdk.validateBoolean)(properties.cacheClusterEnabled)); + errors.collect(cdk.propertyValidator('cacheClusterSize', cdk.validateString)(properties.cacheClusterSize)); + errors.collect(cdk.propertyValidator('cors', cdk.validateString)(properties.cors)); + errors.collect(cdk.propertyValidator('definitionBody', cdk.validateObject)(properties.definitionBody)); + errors.collect(cdk.propertyValidator('definitionUri', cdk.unionValidator(CfnApi_S3LocationPropertyValidator, cdk.validateString))(properties.definitionUri)); + errors.collect(cdk.propertyValidator('endpointConfiguration', cdk.validateString)(properties.endpointConfiguration)); + errors.collect(cdk.propertyValidator('methodSettings', cdk.validateObject)(properties.methodSettings)); + errors.collect(cdk.propertyValidator('name', cdk.validateString)(properties.name)); + errors.collect(cdk.propertyValidator('stageName', cdk.requiredValidator)(properties.stageName)); + errors.collect(cdk.propertyValidator('stageName', cdk.validateString)(properties.stageName)); + errors.collect(cdk.propertyValidator('variables', cdk.hashValidator(cdk.validateString))(properties.variables)); + return errors.wrap('supplied properties not correct for "CfnApiProps"'); +} + +/** + * Renders the AWS CloudFormation properties of an `AWS::Serverless::Api` resource + * + * @param properties - the TypeScript properties of a `CfnApiProps` + * + * @returns the AWS CloudFormation properties of an `AWS::Serverless::Api` resource. + */ +// @ts-ignore TS6133 +function cfnApiPropsToCloudFormation(properties: any): any { + if (!cdk.canInspect(properties)) { return properties; } + CfnApiPropsValidator(properties).assertSuccess(); + return { + StageName: cdk.stringToCloudFormation(properties.stageName), + Auth: cfnApiAuthPropertyToCloudFormation(properties.auth), + BinaryMediaTypes: cdk.listMapper(cdk.stringToCloudFormation)(properties.binaryMediaTypes), + CacheClusterEnabled: cdk.booleanToCloudFormation(properties.cacheClusterEnabled), + CacheClusterSize: cdk.stringToCloudFormation(properties.cacheClusterSize), + Cors: cdk.stringToCloudFormation(properties.cors), + DefinitionBody: cdk.objectToCloudFormation(properties.definitionBody), + DefinitionUri: cdk.unionMapper([CfnApi_S3LocationPropertyValidator, cdk.validateString], [cfnApiS3LocationPropertyToCloudFormation, cdk.stringToCloudFormation])(properties.definitionUri), + EndpointConfiguration: cdk.stringToCloudFormation(properties.endpointConfiguration), + MethodSettings: cdk.objectToCloudFormation(properties.methodSettings), + Name: cdk.stringToCloudFormation(properties.name), + Variables: cdk.hashMapper(cdk.stringToCloudFormation)(properties.variables), + }; +} + +/** + * A CloudFormation `AWS::Serverless::Api` + * + * @cloudformationResource AWS::Serverless::Api + * @see https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessapi + */ +export class CfnApi extends cdk.CfnResource { + /** + * The CloudFormation resource type name for this resource class. + */ + public static readonly resourceTypeName = "AWS::Serverless::Api"; + /** + * The `Transform` a template must use in order to use this resource + */ + public static readonly requiredTransform = "AWS::Serverless-2016-10-31"; + public readonly apiName: string; + + /** + * Create a new `AWS::Serverless::Api`. + * + * @param scope - scope in which this resource is defined + * @param id - scoped id of the resource + * @param props - resource properties + */ + constructor(scope: cdk.Construct, id: string, props: CfnApiProps) { + super(scope, id, { type: CfnApi.resourceTypeName, properties: props }); + cdk.requireProperty(props, 'stageName', this); + // If a different transform than the required one is in use, this resource cannot be used + if (this.node.stack.templateOptions.transform && this.node.stack.templateOptions.transform !== CfnApi.requiredTransform) { + throw new Error(`The ${JSON.stringify(CfnApi.requiredTransform)} transform is required when using CfnApi, but the ${JSON.stringify(this.node.stack.templateOptions.transform)} is used.`); + } + // Automatically configure the required transform + this.node.stack.templateOptions.transform = CfnApi.requiredTransform; + this.apiName = this.ref.toString(); + } + + public get propertyOverrides(): CfnApiProps { + return this.untypedPropertyOverrides; + } + protected renderProperties(properties: any): { [key: string]: any } { + return cfnApiPropsToCloudFormation(this.node.resolve(properties)); + } +} + +export namespace CfnApi { + /** + * @see https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#api-auth-object + */ + export interface AuthProperty { + /** + * `CfnApi.AuthProperty.Authorizers` + * @see https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#api-auth-object + */ + authorizers?: object | cdk.Token; + /** + * `CfnApi.AuthProperty.DefaultAuthorizer` + * @see https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#api-auth-object + */ + defaultAuthorizer?: string; + } +} + +/** + * Determine whether the given properties match those of a `AuthProperty` + * + * @param properties - the TypeScript properties of a `AuthProperty` + * + * @returns the result of the validation. + */ +function CfnApi_AuthPropertyValidator(properties: any): cdk.ValidationResult { + if (!cdk.canInspect(properties)) { return cdk.VALIDATION_SUCCESS; } + const errors = new cdk.ValidationResults(); + errors.collect(cdk.propertyValidator('authorizers', cdk.validateObject)(properties.authorizers)); + errors.collect(cdk.propertyValidator('defaultAuthorizer', cdk.validateString)(properties.defaultAuthorizer)); + return errors.wrap('supplied properties not correct for "AuthProperty"'); +} + +/** + * Renders the AWS CloudFormation properties of an `AWS::Serverless::Api.Auth` resource + * + * @param properties - the TypeScript properties of a `AuthProperty` + * + * @returns the AWS CloudFormation properties of an `AWS::Serverless::Api.Auth` resource. + */ +// @ts-ignore TS6133 +function cfnApiAuthPropertyToCloudFormation(properties: any): any { + if (!cdk.canInspect(properties)) { return properties; } + CfnApi_AuthPropertyValidator(properties).assertSuccess(); + return { + Authorizers: cdk.objectToCloudFormation(properties.authorizers), + DefaultAuthorizer: cdk.stringToCloudFormation(properties.defaultAuthorizer), + }; +} + +export namespace CfnApi { + /** + * @see https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#s3-location-object + */ + export interface S3LocationProperty { + /** + * `CfnApi.S3LocationProperty.Bucket` + * @see https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction + */ + bucket: string; + /** + * `CfnApi.S3LocationProperty.Key` + * @see https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction + */ + key: string; + /** + * `CfnApi.S3LocationProperty.Version` + * @see https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction + */ + version: number | cdk.Token; + } +} + +/** + * Determine whether the given properties match those of a `S3LocationProperty` + * + * @param properties - the TypeScript properties of a `S3LocationProperty` + * + * @returns the result of the validation. + */ +function CfnApi_S3LocationPropertyValidator(properties: any): cdk.ValidationResult { + if (!cdk.canInspect(properties)) { return cdk.VALIDATION_SUCCESS; } + const errors = new cdk.ValidationResults(); + errors.collect(cdk.propertyValidator('bucket', cdk.requiredValidator)(properties.bucket)); + errors.collect(cdk.propertyValidator('bucket', cdk.validateString)(properties.bucket)); + errors.collect(cdk.propertyValidator('key', cdk.requiredValidator)(properties.key)); + errors.collect(cdk.propertyValidator('key', cdk.validateString)(properties.key)); + errors.collect(cdk.propertyValidator('version', cdk.requiredValidator)(properties.version)); + errors.collect(cdk.propertyValidator('version', cdk.validateNumber)(properties.version)); + return errors.wrap('supplied properties not correct for "S3LocationProperty"'); +} + +/** + * Renders the AWS CloudFormation properties of an `AWS::Serverless::Api.S3Location` resource + * + * @param properties - the TypeScript properties of a `S3LocationProperty` + * + * @returns the AWS CloudFormation properties of an `AWS::Serverless::Api.S3Location` resource. + */ +// @ts-ignore TS6133 +function cfnApiS3LocationPropertyToCloudFormation(properties: any): any { + if (!cdk.canInspect(properties)) { return properties; } + CfnApi_S3LocationPropertyValidator(properties).assertSuccess(); + return { + Bucket: cdk.stringToCloudFormation(properties.bucket), + Key: cdk.stringToCloudFormation(properties.key), + Version: cdk.numberToCloudFormation(properties.version), + }; +} + +/** + * Properties for defining a `AWS::Serverless::Application` + * @see https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessapplication + */ +export interface CfnApplicationProps { + /** + * `AWS::Serverless::Application.Location` + * @see https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessapplication + */ + location: CfnApplication.ApplicationLocationProperty | string | cdk.Token; + /** + * `AWS::Serverless::Application.NotificationArns` + * @see https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessapplication + */ + notificationArns?: string[]; + /** + * `AWS::Serverless::Application.Parameters` + * @see https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessapplication + */ + parameters?: { [key: string]: (string) } | cdk.Token; + /** + * `AWS::Serverless::Application.Tags` + * @see https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessapplication + */ + tags?: { [key: string]: (string) }; + /** + * `AWS::Serverless::Application.TimeoutInMinutes` + * @see https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessapplication + */ + timeoutInMinutes?: number | cdk.Token; +} + +/** + * Determine whether the given properties match those of a `CfnApplicationProps` + * + * @param properties - the TypeScript properties of a `CfnApplicationProps` + * + * @returns the result of the validation. + */ +function CfnApplicationPropsValidator(properties: any): cdk.ValidationResult { + if (!cdk.canInspect(properties)) { return cdk.VALIDATION_SUCCESS; } + const errors = new cdk.ValidationResults(); + errors.collect(cdk.propertyValidator('location', cdk.requiredValidator)(properties.location)); + errors.collect(cdk.propertyValidator('location', cdk.unionValidator(CfnApplication_ApplicationLocationPropertyValidator, cdk.validateString))(properties.location)); + errors.collect(cdk.propertyValidator('notificationArns', cdk.listValidator(cdk.validateString))(properties.notificationArns)); + errors.collect(cdk.propertyValidator('parameters', cdk.hashValidator(cdk.validateString))(properties.parameters)); + errors.collect(cdk.propertyValidator('tags', cdk.hashValidator(cdk.validateString))(properties.tags)); + errors.collect(cdk.propertyValidator('timeoutInMinutes', cdk.validateNumber)(properties.timeoutInMinutes)); + return errors.wrap('supplied properties not correct for "CfnApplicationProps"'); +} + +/** + * Renders the AWS CloudFormation properties of an `AWS::Serverless::Application` resource + * + * @param properties - the TypeScript properties of a `CfnApplicationProps` + * + * @returns the AWS CloudFormation properties of an `AWS::Serverless::Application` resource. + */ +// @ts-ignore TS6133 +function cfnApplicationPropsToCloudFormation(properties: any): any { + if (!cdk.canInspect(properties)) { return properties; } + CfnApplicationPropsValidator(properties).assertSuccess(); + return { + Location: cdk.unionMapper([CfnApplication_ApplicationLocationPropertyValidator, cdk.validateString], [cfnApplicationApplicationLocationPropertyToCloudFormation, cdk.stringToCloudFormation])(properties.location), + NotificationArns: cdk.listMapper(cdk.stringToCloudFormation)(properties.notificationArns), + Parameters: cdk.hashMapper(cdk.stringToCloudFormation)(properties.parameters), + Tags: cdk.hashMapper(cdk.stringToCloudFormation)(properties.tags), + TimeoutInMinutes: cdk.numberToCloudFormation(properties.timeoutInMinutes), + }; +} + +/** + * A CloudFormation `AWS::Serverless::Application` + * + * @cloudformationResource AWS::Serverless::Application + * @see https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessapplication + */ +export class CfnApplication extends cdk.CfnResource { + /** + * The CloudFormation resource type name for this resource class. + */ + public static readonly resourceTypeName = "AWS::Serverless::Application"; + /** + * The `Transform` a template must use in order to use this resource + */ + public static readonly requiredTransform = "AWS::Serverless-2016-10-31"; + public readonly applicationName: string; + + /** + * The `TagManager` handles setting, removing and formatting tags + * + * Tags should be managed either passing them as properties during + * initiation or by calling methods on this object. If both techniques are + * used only the tags from the TagManager will be used. `Tag` (aspect) + * will use the manager. + */ + public readonly tags: cdk.TagManager; + + /** + * Create a new `AWS::Serverless::Application`. + * + * @param scope - scope in which this resource is defined + * @param id - scoped id of the resource + * @param props - resource properties + */ + constructor(scope: cdk.Construct, id: string, props: CfnApplicationProps) { + super(scope, id, { type: CfnApplication.resourceTypeName, properties: props }); + cdk.requireProperty(props, 'location', this); + // If a different transform than the required one is in use, this resource cannot be used + if (this.node.stack.templateOptions.transform && this.node.stack.templateOptions.transform !== CfnApplication.requiredTransform) { + throw new Error(`The ${JSON.stringify(CfnApplication.requiredTransform)} transform is required when using CfnApplication, but the ${JSON.stringify(this.node.stack.templateOptions.transform)} is used.`); + } + // Automatically configure the required transform + this.node.stack.templateOptions.transform = CfnApplication.requiredTransform; + this.applicationName = this.ref.toString(); + const tags = props === undefined ? undefined : props.tags; + this.tags = new cdk.TagManager(cdk.TagType.Map, "AWS::Serverless::Application", tags); + } + + public get propertyOverrides(): CfnApplicationProps { + return this.untypedPropertyOverrides; + } + protected renderProperties(properties: any): { [key: string]: any } { + return cfnApplicationPropsToCloudFormation(this.node.resolve(properties)); + } +} + +export namespace CfnApplication { + /** + * @see https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessapplication + */ + export interface ApplicationLocationProperty { + /** + * `CfnApplication.ApplicationLocationProperty.ApplicationId` + * @see https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessapplication + */ + applicationId: string; + /** + * `CfnApplication.ApplicationLocationProperty.SemanticVersion` + * @see https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessapplication + */ + semanticVersion: string; + } +} + +/** + * Determine whether the given properties match those of a `ApplicationLocationProperty` + * + * @param properties - the TypeScript properties of a `ApplicationLocationProperty` + * + * @returns the result of the validation. + */ +function CfnApplication_ApplicationLocationPropertyValidator(properties: any): cdk.ValidationResult { + if (!cdk.canInspect(properties)) { return cdk.VALIDATION_SUCCESS; } + const errors = new cdk.ValidationResults(); + errors.collect(cdk.propertyValidator('applicationId', cdk.requiredValidator)(properties.applicationId)); + errors.collect(cdk.propertyValidator('applicationId', cdk.validateString)(properties.applicationId)); + errors.collect(cdk.propertyValidator('semanticVersion', cdk.requiredValidator)(properties.semanticVersion)); + errors.collect(cdk.propertyValidator('semanticVersion', cdk.validateString)(properties.semanticVersion)); + return errors.wrap('supplied properties not correct for "ApplicationLocationProperty"'); +} + +/** + * Renders the AWS CloudFormation properties of an `AWS::Serverless::Application.ApplicationLocation` resource + * + * @param properties - the TypeScript properties of a `ApplicationLocationProperty` + * + * @returns the AWS CloudFormation properties of an `AWS::Serverless::Application.ApplicationLocation` resource. + */ +// @ts-ignore TS6133 +function cfnApplicationApplicationLocationPropertyToCloudFormation(properties: any): any { + if (!cdk.canInspect(properties)) { return properties; } + CfnApplication_ApplicationLocationPropertyValidator(properties).assertSuccess(); + return { + ApplicationId: cdk.stringToCloudFormation(properties.applicationId), + SemanticVersion: cdk.stringToCloudFormation(properties.semanticVersion), + }; +} + +/** + * Properties for defining a `AWS::Serverless::Function` + * @see https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction + */ +export interface CfnFunctionProps { + /** + * `AWS::Serverless::Function.CodeUri` + * @see https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction + */ + codeUri: CfnFunction.S3LocationProperty | string | cdk.Token; + /** + * `AWS::Serverless::Function.Handler` + * @see https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction + */ + handler: string; + /** + * `AWS::Serverless::Function.Runtime` + * @see https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction + */ + runtime: string; + /** + * `AWS::Serverless::Function.AutoPublishAlias` + * @see https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction + */ + autoPublishAlias?: string; + /** + * `AWS::Serverless::Function.DeadLetterQueue` + * @see https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction + */ + deadLetterQueue?: CfnFunction.DeadLetterQueueProperty | cdk.Token; + /** + * `AWS::Serverless::Function.DeploymentPreference` + * @see https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#deploymentpreference-object + */ + deploymentPreference?: CfnFunction.DeploymentPreferenceProperty | cdk.Token; + /** + * `AWS::Serverless::Function.Description` + * @see https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction + */ + description?: string; + /** + * `AWS::Serverless::Function.Environment` + * @see https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction + */ + environment?: CfnFunction.FunctionEnvironmentProperty | cdk.Token; + /** + * `AWS::Serverless::Function.Events` + * @see https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction + */ + events?: { [key: string]: (CfnFunction.EventSourceProperty | cdk.Token) } | cdk.Token; + /** + * `AWS::Serverless::Function.FunctionName` + * @see https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction + */ + functionName?: string; + /** + * `AWS::Serverless::Function.KmsKeyArn` + * @see https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction + */ + kmsKeyArn?: string; + /** + * `AWS::Serverless::Function.Layers` + * @see https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction + */ + layers?: string[]; + /** + * `AWS::Serverless::Function.MemorySize` + * @see https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction + */ + memorySize?: number | cdk.Token; + /** + * `AWS::Serverless::Function.Policies` + * @see https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction + */ + policies?: Array | CfnFunction.IAMPolicyDocumentProperty | string | cdk.Token; + /** + * `AWS::Serverless::Function.ReservedConcurrentExecutions` + * @see https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction + */ + reservedConcurrentExecutions?: number | cdk.Token; + /** + * `AWS::Serverless::Function.Role` + * @see https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction + */ + role?: string; + /** + * `AWS::Serverless::Function.Tags` + * @see https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction + */ + tags?: { [key: string]: (string) }; + /** + * `AWS::Serverless::Function.Timeout` + * @see https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction + */ + timeout?: number | cdk.Token; + /** + * `AWS::Serverless::Function.Tracing` + * @see https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction + */ + tracing?: string; + /** + * `AWS::Serverless::Function.VpcConfig` + * @see https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction + */ + vpcConfig?: CfnFunction.VpcConfigProperty | cdk.Token; +} + +/** + * Determine whether the given properties match those of a `CfnFunctionProps` + * + * @param properties - the TypeScript properties of a `CfnFunctionProps` + * + * @returns the result of the validation. + */ +function CfnFunctionPropsValidator(properties: any): cdk.ValidationResult { + if (!cdk.canInspect(properties)) { return cdk.VALIDATION_SUCCESS; } + const errors = new cdk.ValidationResults(); + errors.collect(cdk.propertyValidator('autoPublishAlias', cdk.validateString)(properties.autoPublishAlias)); + errors.collect(cdk.propertyValidator('codeUri', cdk.requiredValidator)(properties.codeUri)); + errors.collect(cdk.propertyValidator('codeUri', cdk.unionValidator(CfnFunction_S3LocationPropertyValidator, cdk.validateString))(properties.codeUri)); + errors.collect(cdk.propertyValidator('deadLetterQueue', CfnFunction_DeadLetterQueuePropertyValidator)(properties.deadLetterQueue)); + errors.collect(cdk.propertyValidator('deploymentPreference', CfnFunction_DeploymentPreferencePropertyValidator)(properties.deploymentPreference)); + errors.collect(cdk.propertyValidator('description', cdk.validateString)(properties.description)); + errors.collect(cdk.propertyValidator('environment', CfnFunction_FunctionEnvironmentPropertyValidator)(properties.environment)); + errors.collect(cdk.propertyValidator('events', cdk.hashValidator(CfnFunction_EventSourcePropertyValidator))(properties.events)); + errors.collect(cdk.propertyValidator('functionName', cdk.validateString)(properties.functionName)); + errors.collect(cdk.propertyValidator('handler', cdk.requiredValidator)(properties.handler)); + errors.collect(cdk.propertyValidator('handler', cdk.validateString)(properties.handler)); + errors.collect(cdk.propertyValidator('kmsKeyArn', cdk.validateString)(properties.kmsKeyArn)); + errors.collect(cdk.propertyValidator('layers', cdk.listValidator(cdk.validateString))(properties.layers)); + errors.collect(cdk.propertyValidator('memorySize', cdk.validateNumber)(properties.memorySize)); + errors.collect(cdk.propertyValidator('policies', cdk.unionValidator(cdk.unionValidator(CfnFunction_IAMPolicyDocumentPropertyValidator, cdk.validateString), cdk.listValidator(cdk.unionValidator(CfnFunction_IAMPolicyDocumentPropertyValidator, cdk.validateString))))(properties.policies)); + errors.collect(cdk.propertyValidator('reservedConcurrentExecutions', cdk.validateNumber)(properties.reservedConcurrentExecutions)); + errors.collect(cdk.propertyValidator('role', cdk.validateString)(properties.role)); + errors.collect(cdk.propertyValidator('runtime', cdk.requiredValidator)(properties.runtime)); + errors.collect(cdk.propertyValidator('runtime', cdk.validateString)(properties.runtime)); + errors.collect(cdk.propertyValidator('tags', cdk.hashValidator(cdk.validateString))(properties.tags)); + errors.collect(cdk.propertyValidator('timeout', cdk.validateNumber)(properties.timeout)); + errors.collect(cdk.propertyValidator('tracing', cdk.validateString)(properties.tracing)); + errors.collect(cdk.propertyValidator('vpcConfig', CfnFunction_VpcConfigPropertyValidator)(properties.vpcConfig)); + return errors.wrap('supplied properties not correct for "CfnFunctionProps"'); +} + +/** + * Renders the AWS CloudFormation properties of an `AWS::Serverless::Function` resource + * + * @param properties - the TypeScript properties of a `CfnFunctionProps` + * + * @returns the AWS CloudFormation properties of an `AWS::Serverless::Function` resource. + */ +// @ts-ignore TS6133 +function cfnFunctionPropsToCloudFormation(properties: any): any { + if (!cdk.canInspect(properties)) { return properties; } + CfnFunctionPropsValidator(properties).assertSuccess(); + return { + CodeUri: cdk.unionMapper([CfnFunction_S3LocationPropertyValidator, cdk.validateString], [cfnFunctionS3LocationPropertyToCloudFormation, cdk.stringToCloudFormation])(properties.codeUri), + Handler: cdk.stringToCloudFormation(properties.handler), + Runtime: cdk.stringToCloudFormation(properties.runtime), + AutoPublishAlias: cdk.stringToCloudFormation(properties.autoPublishAlias), + DeadLetterQueue: cfnFunctionDeadLetterQueuePropertyToCloudFormation(properties.deadLetterQueue), + DeploymentPreference: cfnFunctionDeploymentPreferencePropertyToCloudFormation(properties.deploymentPreference), + Description: cdk.stringToCloudFormation(properties.description), + Environment: cfnFunctionFunctionEnvironmentPropertyToCloudFormation(properties.environment), + Events: cdk.hashMapper(cfnFunctionEventSourcePropertyToCloudFormation)(properties.events), + FunctionName: cdk.stringToCloudFormation(properties.functionName), + KmsKeyArn: cdk.stringToCloudFormation(properties.kmsKeyArn), + Layers: cdk.listMapper(cdk.stringToCloudFormation)(properties.layers), + MemorySize: cdk.numberToCloudFormation(properties.memorySize), + Policies: cdk.unionMapper([cdk.unionValidator(CfnFunction_IAMPolicyDocumentPropertyValidator, cdk.validateString), cdk.listValidator(cdk.unionValidator(CfnFunction_IAMPolicyDocumentPropertyValidator, cdk.validateString))], [cdk.unionMapper([CfnFunction_IAMPolicyDocumentPropertyValidator, cdk.validateString], [cfnFunctionIAMPolicyDocumentPropertyToCloudFormation, cdk.stringToCloudFormation]), cdk.listMapper(cdk.unionMapper([CfnFunction_IAMPolicyDocumentPropertyValidator, cdk.validateString], [cfnFunctionIAMPolicyDocumentPropertyToCloudFormation, cdk.stringToCloudFormation]))])(properties.policies), + ReservedConcurrentExecutions: cdk.numberToCloudFormation(properties.reservedConcurrentExecutions), + Role: cdk.stringToCloudFormation(properties.role), + Tags: cdk.hashMapper(cdk.stringToCloudFormation)(properties.tags), + Timeout: cdk.numberToCloudFormation(properties.timeout), + Tracing: cdk.stringToCloudFormation(properties.tracing), + VpcConfig: cfnFunctionVpcConfigPropertyToCloudFormation(properties.vpcConfig), + }; +} + +/** + * A CloudFormation `AWS::Serverless::Function` + * + * @cloudformationResource AWS::Serverless::Function + * @see https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction + */ +export class CfnFunction extends cdk.CfnResource { + /** + * The CloudFormation resource type name for this resource class. + */ + public static readonly resourceTypeName = "AWS::Serverless::Function"; + /** + * The `Transform` a template must use in order to use this resource + */ + public static readonly requiredTransform = "AWS::Serverless-2016-10-31"; + public readonly functionName: string; + + /** + * The `TagManager` handles setting, removing and formatting tags + * + * Tags should be managed either passing them as properties during + * initiation or by calling methods on this object. If both techniques are + * used only the tags from the TagManager will be used. `Tag` (aspect) + * will use the manager. + */ + public readonly tags: cdk.TagManager; + + /** + * Create a new `AWS::Serverless::Function`. + * + * @param scope - scope in which this resource is defined + * @param id - scoped id of the resource + * @param props - resource properties + */ + constructor(scope: cdk.Construct, id: string, props: CfnFunctionProps) { + super(scope, id, { type: CfnFunction.resourceTypeName, properties: props }); + cdk.requireProperty(props, 'codeUri', this); + cdk.requireProperty(props, 'handler', this); + cdk.requireProperty(props, 'runtime', this); + // If a different transform than the required one is in use, this resource cannot be used + if (this.node.stack.templateOptions.transform && this.node.stack.templateOptions.transform !== CfnFunction.requiredTransform) { + throw new Error(`The ${JSON.stringify(CfnFunction.requiredTransform)} transform is required when using CfnFunction, but the ${JSON.stringify(this.node.stack.templateOptions.transform)} is used.`); + } + // Automatically configure the required transform + this.node.stack.templateOptions.transform = CfnFunction.requiredTransform; + this.functionName = this.ref.toString(); + const tags = props === undefined ? undefined : props.tags; + this.tags = new cdk.TagManager(cdk.TagType.Map, "AWS::Serverless::Function", tags); + } + + public get propertyOverrides(): CfnFunctionProps { + return this.untypedPropertyOverrides; + } + protected renderProperties(properties: any): { [key: string]: any } { + return cfnFunctionPropsToCloudFormation(this.node.resolve(properties)); + } +} + +export namespace CfnFunction { + /** + * @see https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#alexaskill + */ + export interface AlexaSkillEventProperty { + /** + * `CfnFunction.AlexaSkillEventProperty.Variables` + * @see https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#alexaskill + */ + variables?: { [key: string]: (string) } | cdk.Token; + } +} + +/** + * Determine whether the given properties match those of a `AlexaSkillEventProperty` + * + * @param properties - the TypeScript properties of a `AlexaSkillEventProperty` + * + * @returns the result of the validation. + */ +function CfnFunction_AlexaSkillEventPropertyValidator(properties: any): cdk.ValidationResult { + if (!cdk.canInspect(properties)) { return cdk.VALIDATION_SUCCESS; } + const errors = new cdk.ValidationResults(); + errors.collect(cdk.propertyValidator('variables', cdk.hashValidator(cdk.validateString))(properties.variables)); + return errors.wrap('supplied properties not correct for "AlexaSkillEventProperty"'); +} + +/** + * Renders the AWS CloudFormation properties of an `AWS::Serverless::Function.AlexaSkillEvent` resource + * + * @param properties - the TypeScript properties of a `AlexaSkillEventProperty` + * + * @returns the AWS CloudFormation properties of an `AWS::Serverless::Function.AlexaSkillEvent` resource. + */ +// @ts-ignore TS6133 +function cfnFunctionAlexaSkillEventPropertyToCloudFormation(properties: any): any { + if (!cdk.canInspect(properties)) { return properties; } + CfnFunction_AlexaSkillEventPropertyValidator(properties).assertSuccess(); + return { + Variables: cdk.hashMapper(cdk.stringToCloudFormation)(properties.variables), + }; +} + +export namespace CfnFunction { + /** + * @see https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#api + */ + export interface ApiEventProperty { + /** + * `CfnFunction.ApiEventProperty.Method` + * @see https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#api + */ + method: string; + /** + * `CfnFunction.ApiEventProperty.Path` + * @see https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#api + */ + path: string; + /** + * `CfnFunction.ApiEventProperty.RestApiId` + * @see https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#api + */ + restApiId?: string; + } +} + +/** + * Determine whether the given properties match those of a `ApiEventProperty` + * + * @param properties - the TypeScript properties of a `ApiEventProperty` + * + * @returns the result of the validation. + */ +function CfnFunction_ApiEventPropertyValidator(properties: any): cdk.ValidationResult { + if (!cdk.canInspect(properties)) { return cdk.VALIDATION_SUCCESS; } + const errors = new cdk.ValidationResults(); + errors.collect(cdk.propertyValidator('method', cdk.requiredValidator)(properties.method)); + errors.collect(cdk.propertyValidator('method', cdk.validateString)(properties.method)); + errors.collect(cdk.propertyValidator('path', cdk.requiredValidator)(properties.path)); + errors.collect(cdk.propertyValidator('path', cdk.validateString)(properties.path)); + errors.collect(cdk.propertyValidator('restApiId', cdk.validateString)(properties.restApiId)); + return errors.wrap('supplied properties not correct for "ApiEventProperty"'); +} + +/** + * Renders the AWS CloudFormation properties of an `AWS::Serverless::Function.ApiEvent` resource + * + * @param properties - the TypeScript properties of a `ApiEventProperty` + * + * @returns the AWS CloudFormation properties of an `AWS::Serverless::Function.ApiEvent` resource. + */ +// @ts-ignore TS6133 +function cfnFunctionApiEventPropertyToCloudFormation(properties: any): any { + if (!cdk.canInspect(properties)) { return properties; } + CfnFunction_ApiEventPropertyValidator(properties).assertSuccess(); + return { + Method: cdk.stringToCloudFormation(properties.method), + Path: cdk.stringToCloudFormation(properties.path), + RestApiId: cdk.stringToCloudFormation(properties.restApiId), + }; +} + +export namespace CfnFunction { + /** + * @see https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#cloudwatchevent + */ + export interface CloudWatchEventEventProperty { + /** + * `CfnFunction.CloudWatchEventEventProperty.Input` + * @see https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#cloudwatchevent + */ + input?: string; + /** + * `CfnFunction.CloudWatchEventEventProperty.InputPath` + * @see https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#cloudwatchevent + */ + inputPath?: string; + /** + * `CfnFunction.CloudWatchEventEventProperty.Pattern` + * @see http://docs.aws.amazon.com/AmazonCloudWatch/latest/events/CloudWatchEventsandEventPatterns.html + */ + pattern: object | cdk.Token; + } +} + +/** + * Determine whether the given properties match those of a `CloudWatchEventEventProperty` + * + * @param properties - the TypeScript properties of a `CloudWatchEventEventProperty` + * + * @returns the result of the validation. + */ +function CfnFunction_CloudWatchEventEventPropertyValidator(properties: any): cdk.ValidationResult { + if (!cdk.canInspect(properties)) { return cdk.VALIDATION_SUCCESS; } + const errors = new cdk.ValidationResults(); + errors.collect(cdk.propertyValidator('input', cdk.validateString)(properties.input)); + errors.collect(cdk.propertyValidator('inputPath', cdk.validateString)(properties.inputPath)); + errors.collect(cdk.propertyValidator('pattern', cdk.requiredValidator)(properties.pattern)); + errors.collect(cdk.propertyValidator('pattern', cdk.validateObject)(properties.pattern)); + return errors.wrap('supplied properties not correct for "CloudWatchEventEventProperty"'); +} + +/** + * Renders the AWS CloudFormation properties of an `AWS::Serverless::Function.CloudWatchEventEvent` resource + * + * @param properties - the TypeScript properties of a `CloudWatchEventEventProperty` + * + * @returns the AWS CloudFormation properties of an `AWS::Serverless::Function.CloudWatchEventEvent` resource. + */ +// @ts-ignore TS6133 +function cfnFunctionCloudWatchEventEventPropertyToCloudFormation(properties: any): any { + if (!cdk.canInspect(properties)) { return properties; } + CfnFunction_CloudWatchEventEventPropertyValidator(properties).assertSuccess(); + return { + Input: cdk.stringToCloudFormation(properties.input), + InputPath: cdk.stringToCloudFormation(properties.inputPath), + Pattern: cdk.objectToCloudFormation(properties.pattern), + }; +} + +export namespace CfnFunction { + /** + * @see https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#deadletterqueue-object + */ + export interface DeadLetterQueueProperty { + /** + * `CfnFunction.DeadLetterQueueProperty.TargetArn` + * @see https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction + */ + targetArn: string; + /** + * `CfnFunction.DeadLetterQueueProperty.Type` + * @see https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction + */ + type: string; + } +} + +/** + * Determine whether the given properties match those of a `DeadLetterQueueProperty` + * + * @param properties - the TypeScript properties of a `DeadLetterQueueProperty` + * + * @returns the result of the validation. + */ +function CfnFunction_DeadLetterQueuePropertyValidator(properties: any): cdk.ValidationResult { + if (!cdk.canInspect(properties)) { return cdk.VALIDATION_SUCCESS; } + const errors = new cdk.ValidationResults(); + errors.collect(cdk.propertyValidator('targetArn', cdk.requiredValidator)(properties.targetArn)); + errors.collect(cdk.propertyValidator('targetArn', cdk.validateString)(properties.targetArn)); + errors.collect(cdk.propertyValidator('type', cdk.requiredValidator)(properties.type)); + errors.collect(cdk.propertyValidator('type', cdk.validateString)(properties.type)); + return errors.wrap('supplied properties not correct for "DeadLetterQueueProperty"'); +} + +/** + * Renders the AWS CloudFormation properties of an `AWS::Serverless::Function.DeadLetterQueue` resource + * + * @param properties - the TypeScript properties of a `DeadLetterQueueProperty` + * + * @returns the AWS CloudFormation properties of an `AWS::Serverless::Function.DeadLetterQueue` resource. + */ +// @ts-ignore TS6133 +function cfnFunctionDeadLetterQueuePropertyToCloudFormation(properties: any): any { + if (!cdk.canInspect(properties)) { return properties; } + CfnFunction_DeadLetterQueuePropertyValidator(properties).assertSuccess(); + return { + TargetArn: cdk.stringToCloudFormation(properties.targetArn), + Type: cdk.stringToCloudFormation(properties.type), + }; +} + +export namespace CfnFunction { + /** + * @see https://github.com/awslabs/serverless-application-model/blob/master/docs/safe_lambda_deployments.rst + */ + export interface DeploymentPreferenceProperty { + /** + * `CfnFunction.DeploymentPreferenceProperty.Enabled` + * @see https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#deploymentpreference-object + */ + enabled: boolean | cdk.Token; + /** + * `CfnFunction.DeploymentPreferenceProperty.Type` + * @see https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#deploymentpreference-object + */ + type: string; + /** + * `CfnFunction.DeploymentPreferenceProperty.Alarms` + * @see https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#deploymentpreference-object + */ + alarms?: string[]; + /** + * `CfnFunction.DeploymentPreferenceProperty.Hooks` + * @see https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#deploymentpreference-object + */ + hooks?: string[]; + } +} + +/** + * Determine whether the given properties match those of a `DeploymentPreferenceProperty` + * + * @param properties - the TypeScript properties of a `DeploymentPreferenceProperty` + * + * @returns the result of the validation. + */ +function CfnFunction_DeploymentPreferencePropertyValidator(properties: any): cdk.ValidationResult { + if (!cdk.canInspect(properties)) { return cdk.VALIDATION_SUCCESS; } + const errors = new cdk.ValidationResults(); + errors.collect(cdk.propertyValidator('enabled', cdk.requiredValidator)(properties.enabled)); + errors.collect(cdk.propertyValidator('enabled', cdk.validateBoolean)(properties.enabled)); + errors.collect(cdk.propertyValidator('type', cdk.requiredValidator)(properties.type)); + errors.collect(cdk.propertyValidator('type', cdk.validateString)(properties.type)); + errors.collect(cdk.propertyValidator('alarms', cdk.listValidator(cdk.validateString))(properties.alarms)); + errors.collect(cdk.propertyValidator('hooks', cdk.listValidator(cdk.validateString))(properties.hooks)); + return errors.wrap('supplied properties not correct for "DeploymentPreferenceProperty"'); +} + +/** + * Renders the AWS CloudFormation properties of an `AWS::Serverless::Function.DeploymentPreference` resource + * + * @param properties - the TypeScript properties of a `DeploymentPreferenceProperty` + * + * @returns the AWS CloudFormation properties of an `AWS::Serverless::Function.DeploymentPreference` resource. + */ +// @ts-ignore TS6133 +function cfnFunctionDeploymentPreferencePropertyToCloudFormation(properties: any): any { + if (!cdk.canInspect(properties)) { return properties; } + CfnFunction_DeploymentPreferencePropertyValidator(properties).assertSuccess(); + return { + Enabled: cdk.booleanToCloudFormation(properties.enabled), + Type: cdk.stringToCloudFormation(properties.type), + Alarms: cdk.listMapper(cdk.stringToCloudFormation)(properties.alarms), + Hooks: cdk.listMapper(cdk.stringToCloudFormation)(properties.hooks), + }; +} + +export namespace CfnFunction { + /** + * @see https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#dynamodb + */ + export interface DynamoDBEventProperty { + /** + * `CfnFunction.DynamoDBEventProperty.BatchSize` + * @see https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#dynamodb + */ + batchSize: number | cdk.Token; + /** + * `CfnFunction.DynamoDBEventProperty.StartingPosition` + * @see https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#dynamodb + */ + startingPosition: string; + /** + * `CfnFunction.DynamoDBEventProperty.Stream` + * @see https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#dynamodb + */ + stream: string; + } +} + +/** + * Determine whether the given properties match those of a `DynamoDBEventProperty` + * + * @param properties - the TypeScript properties of a `DynamoDBEventProperty` + * + * @returns the result of the validation. + */ +function CfnFunction_DynamoDBEventPropertyValidator(properties: any): cdk.ValidationResult { + if (!cdk.canInspect(properties)) { return cdk.VALIDATION_SUCCESS; } + const errors = new cdk.ValidationResults(); + errors.collect(cdk.propertyValidator('batchSize', cdk.requiredValidator)(properties.batchSize)); + errors.collect(cdk.propertyValidator('batchSize', cdk.validateNumber)(properties.batchSize)); + errors.collect(cdk.propertyValidator('startingPosition', cdk.requiredValidator)(properties.startingPosition)); + errors.collect(cdk.propertyValidator('startingPosition', cdk.validateString)(properties.startingPosition)); + errors.collect(cdk.propertyValidator('stream', cdk.requiredValidator)(properties.stream)); + errors.collect(cdk.propertyValidator('stream', cdk.validateString)(properties.stream)); + return errors.wrap('supplied properties not correct for "DynamoDBEventProperty"'); +} + +/** + * Renders the AWS CloudFormation properties of an `AWS::Serverless::Function.DynamoDBEvent` resource + * + * @param properties - the TypeScript properties of a `DynamoDBEventProperty` + * + * @returns the AWS CloudFormation properties of an `AWS::Serverless::Function.DynamoDBEvent` resource. + */ +// @ts-ignore TS6133 +function cfnFunctionDynamoDBEventPropertyToCloudFormation(properties: any): any { + if (!cdk.canInspect(properties)) { return properties; } + CfnFunction_DynamoDBEventPropertyValidator(properties).assertSuccess(); + return { + BatchSize: cdk.numberToCloudFormation(properties.batchSize), + StartingPosition: cdk.stringToCloudFormation(properties.startingPosition), + Stream: cdk.stringToCloudFormation(properties.stream), + }; +} + +export namespace CfnFunction { + /** + * @see https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#event-source-object + */ + export interface EventSourceProperty { + /** + * `CfnFunction.EventSourceProperty.Properties` + * @see https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#event-source-types + */ + properties: CfnFunction.S3EventProperty | CfnFunction.SNSEventProperty | CfnFunction.SQSEventProperty | CfnFunction.KinesisEventProperty | CfnFunction.DynamoDBEventProperty | CfnFunction.ApiEventProperty | CfnFunction.ScheduleEventProperty | CfnFunction.CloudWatchEventEventProperty | CfnFunction.IoTRuleEventProperty | CfnFunction.AlexaSkillEventProperty | cdk.Token; + /** + * `CfnFunction.EventSourceProperty.Type` + * @see https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#event-source-object + */ + type: string; + } +} + +/** + * Determine whether the given properties match those of a `EventSourceProperty` + * + * @param properties - the TypeScript properties of a `EventSourceProperty` + * + * @returns the result of the validation. + */ +function CfnFunction_EventSourcePropertyValidator(properties: any): cdk.ValidationResult { + if (!cdk.canInspect(properties)) { return cdk.VALIDATION_SUCCESS; } + const errors = new cdk.ValidationResults(); + errors.collect(cdk.propertyValidator('properties', cdk.requiredValidator)(properties.properties)); + errors.collect(cdk.propertyValidator('properties', cdk.unionValidator(CfnFunction_S3EventPropertyValidator, CfnFunction_SNSEventPropertyValidator, CfnFunction_SQSEventPropertyValidator, CfnFunction_KinesisEventPropertyValidator, CfnFunction_DynamoDBEventPropertyValidator, CfnFunction_ApiEventPropertyValidator, CfnFunction_ScheduleEventPropertyValidator, CfnFunction_CloudWatchEventEventPropertyValidator, CfnFunction_IoTRuleEventPropertyValidator, CfnFunction_AlexaSkillEventPropertyValidator))(properties.properties)); + errors.collect(cdk.propertyValidator('type', cdk.requiredValidator)(properties.type)); + errors.collect(cdk.propertyValidator('type', cdk.validateString)(properties.type)); + return errors.wrap('supplied properties not correct for "EventSourceProperty"'); +} + +/** + * Renders the AWS CloudFormation properties of an `AWS::Serverless::Function.EventSource` resource + * + * @param properties - the TypeScript properties of a `EventSourceProperty` + * + * @returns the AWS CloudFormation properties of an `AWS::Serverless::Function.EventSource` resource. + */ +// @ts-ignore TS6133 +function cfnFunctionEventSourcePropertyToCloudFormation(properties: any): any { + if (!cdk.canInspect(properties)) { return properties; } + CfnFunction_EventSourcePropertyValidator(properties).assertSuccess(); + return { + Properties: cdk.unionMapper([CfnFunction_S3EventPropertyValidator, CfnFunction_SNSEventPropertyValidator, CfnFunction_SQSEventPropertyValidator, CfnFunction_KinesisEventPropertyValidator, CfnFunction_DynamoDBEventPropertyValidator, CfnFunction_ApiEventPropertyValidator, CfnFunction_ScheduleEventPropertyValidator, CfnFunction_CloudWatchEventEventPropertyValidator, CfnFunction_IoTRuleEventPropertyValidator, CfnFunction_AlexaSkillEventPropertyValidator], [cfnFunctionS3EventPropertyToCloudFormation, cfnFunctionSNSEventPropertyToCloudFormation, cfnFunctionSQSEventPropertyToCloudFormation, cfnFunctionKinesisEventPropertyToCloudFormation, cfnFunctionDynamoDBEventPropertyToCloudFormation, cfnFunctionApiEventPropertyToCloudFormation, cfnFunctionScheduleEventPropertyToCloudFormation, cfnFunctionCloudWatchEventEventPropertyToCloudFormation, cfnFunctionIoTRuleEventPropertyToCloudFormation, cfnFunctionAlexaSkillEventPropertyToCloudFormation])(properties.properties), + Type: cdk.stringToCloudFormation(properties.type), + }; +} + +export namespace CfnFunction { + /** + * @see https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#environment-object + */ + export interface FunctionEnvironmentProperty { + /** + * `CfnFunction.FunctionEnvironmentProperty.Variables` + * @see https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#environment-object + */ + variables: { [key: string]: (string) } | cdk.Token; + } +} + +/** + * Determine whether the given properties match those of a `FunctionEnvironmentProperty` + * + * @param properties - the TypeScript properties of a `FunctionEnvironmentProperty` + * + * @returns the result of the validation. + */ +function CfnFunction_FunctionEnvironmentPropertyValidator(properties: any): cdk.ValidationResult { + if (!cdk.canInspect(properties)) { return cdk.VALIDATION_SUCCESS; } + const errors = new cdk.ValidationResults(); + errors.collect(cdk.propertyValidator('variables', cdk.requiredValidator)(properties.variables)); + errors.collect(cdk.propertyValidator('variables', cdk.hashValidator(cdk.validateString))(properties.variables)); + return errors.wrap('supplied properties not correct for "FunctionEnvironmentProperty"'); +} + +/** + * Renders the AWS CloudFormation properties of an `AWS::Serverless::Function.FunctionEnvironment` resource + * + * @param properties - the TypeScript properties of a `FunctionEnvironmentProperty` + * + * @returns the AWS CloudFormation properties of an `AWS::Serverless::Function.FunctionEnvironment` resource. + */ +// @ts-ignore TS6133 +function cfnFunctionFunctionEnvironmentPropertyToCloudFormation(properties: any): any { + if (!cdk.canInspect(properties)) { return properties; } + CfnFunction_FunctionEnvironmentPropertyValidator(properties).assertSuccess(); + return { + Variables: cdk.hashMapper(cdk.stringToCloudFormation)(properties.variables), + }; +} + +export namespace CfnFunction { + /** + * @see http://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies.html + */ + export interface IAMPolicyDocumentProperty { + /** + * `CfnFunction.IAMPolicyDocumentProperty.Statement` + * @see http://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies.html + */ + statement: object | cdk.Token; + } +} + +/** + * Determine whether the given properties match those of a `IAMPolicyDocumentProperty` + * + * @param properties - the TypeScript properties of a `IAMPolicyDocumentProperty` + * + * @returns the result of the validation. + */ +function CfnFunction_IAMPolicyDocumentPropertyValidator(properties: any): cdk.ValidationResult { + if (!cdk.canInspect(properties)) { return cdk.VALIDATION_SUCCESS; } + const errors = new cdk.ValidationResults(); + errors.collect(cdk.propertyValidator('statement', cdk.requiredValidator)(properties.statement)); + errors.collect(cdk.propertyValidator('statement', cdk.validateObject)(properties.statement)); + return errors.wrap('supplied properties not correct for "IAMPolicyDocumentProperty"'); +} + +/** + * Renders the AWS CloudFormation properties of an `AWS::Serverless::Function.IAMPolicyDocument` resource + * + * @param properties - the TypeScript properties of a `IAMPolicyDocumentProperty` + * + * @returns the AWS CloudFormation properties of an `AWS::Serverless::Function.IAMPolicyDocument` resource. + */ +// @ts-ignore TS6133 +function cfnFunctionIAMPolicyDocumentPropertyToCloudFormation(properties: any): any { + if (!cdk.canInspect(properties)) { return properties; } + CfnFunction_IAMPolicyDocumentPropertyValidator(properties).assertSuccess(); + return { + Statement: cdk.objectToCloudFormation(properties.statement), + }; +} + +export namespace CfnFunction { + /** + * @see https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#iotrule + */ + export interface IoTRuleEventProperty { + /** + * `CfnFunction.IoTRuleEventProperty.AwsIotSqlVersion` + * @see https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#iotrule + */ + awsIotSqlVersion?: string; + /** + * `CfnFunction.IoTRuleEventProperty.Sql` + * @see https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#iotrule + */ + sql: string; + } +} + +/** + * Determine whether the given properties match those of a `IoTRuleEventProperty` + * + * @param properties - the TypeScript properties of a `IoTRuleEventProperty` + * + * @returns the result of the validation. + */ +function CfnFunction_IoTRuleEventPropertyValidator(properties: any): cdk.ValidationResult { + if (!cdk.canInspect(properties)) { return cdk.VALIDATION_SUCCESS; } + const errors = new cdk.ValidationResults(); + errors.collect(cdk.propertyValidator('awsIotSqlVersion', cdk.validateString)(properties.awsIotSqlVersion)); + errors.collect(cdk.propertyValidator('sql', cdk.requiredValidator)(properties.sql)); + errors.collect(cdk.propertyValidator('sql', cdk.validateString)(properties.sql)); + return errors.wrap('supplied properties not correct for "IoTRuleEventProperty"'); +} + +/** + * Renders the AWS CloudFormation properties of an `AWS::Serverless::Function.IoTRuleEvent` resource + * + * @param properties - the TypeScript properties of a `IoTRuleEventProperty` + * + * @returns the AWS CloudFormation properties of an `AWS::Serverless::Function.IoTRuleEvent` resource. + */ +// @ts-ignore TS6133 +function cfnFunctionIoTRuleEventPropertyToCloudFormation(properties: any): any { + if (!cdk.canInspect(properties)) { return properties; } + CfnFunction_IoTRuleEventPropertyValidator(properties).assertSuccess(); + return { + AwsIotSqlVersion: cdk.stringToCloudFormation(properties.awsIotSqlVersion), + Sql: cdk.stringToCloudFormation(properties.sql), + }; +} + +export namespace CfnFunction { + /** + * @see https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#kinesis + */ + export interface KinesisEventProperty { + /** + * `CfnFunction.KinesisEventProperty.BatchSize` + * @see https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#kinesis + */ + batchSize?: number | cdk.Token; + /** + * `CfnFunction.KinesisEventProperty.StartingPosition` + * @see https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#kinesis + */ + startingPosition: string; + /** + * `CfnFunction.KinesisEventProperty.Stream` + * @see https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#kinesis + */ + stream: string; + } +} + +/** + * Determine whether the given properties match those of a `KinesisEventProperty` + * + * @param properties - the TypeScript properties of a `KinesisEventProperty` + * + * @returns the result of the validation. + */ +function CfnFunction_KinesisEventPropertyValidator(properties: any): cdk.ValidationResult { + if (!cdk.canInspect(properties)) { return cdk.VALIDATION_SUCCESS; } + const errors = new cdk.ValidationResults(); + errors.collect(cdk.propertyValidator('batchSize', cdk.validateNumber)(properties.batchSize)); + errors.collect(cdk.propertyValidator('startingPosition', cdk.requiredValidator)(properties.startingPosition)); + errors.collect(cdk.propertyValidator('startingPosition', cdk.validateString)(properties.startingPosition)); + errors.collect(cdk.propertyValidator('stream', cdk.requiredValidator)(properties.stream)); + errors.collect(cdk.propertyValidator('stream', cdk.validateString)(properties.stream)); + return errors.wrap('supplied properties not correct for "KinesisEventProperty"'); +} + +/** + * Renders the AWS CloudFormation properties of an `AWS::Serverless::Function.KinesisEvent` resource + * + * @param properties - the TypeScript properties of a `KinesisEventProperty` + * + * @returns the AWS CloudFormation properties of an `AWS::Serverless::Function.KinesisEvent` resource. + */ +// @ts-ignore TS6133 +function cfnFunctionKinesisEventPropertyToCloudFormation(properties: any): any { + if (!cdk.canInspect(properties)) { return properties; } + CfnFunction_KinesisEventPropertyValidator(properties).assertSuccess(); + return { + BatchSize: cdk.numberToCloudFormation(properties.batchSize), + StartingPosition: cdk.stringToCloudFormation(properties.startingPosition), + Stream: cdk.stringToCloudFormation(properties.stream), + }; +} + +export namespace CfnFunction { + /** + * @see https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#s3 + */ + export interface S3EventProperty { + /** + * `CfnFunction.S3EventProperty.Bucket` + * @see https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#s3 + */ + bucket: string; + /** + * `CfnFunction.S3EventProperty.Events` + * @see https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#s3 + */ + events: string[] | string | cdk.Token; + /** + * `CfnFunction.S3EventProperty.Filter` + * @see https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#s3 + */ + filter?: CfnFunction.S3NotificationFilterProperty | cdk.Token; + } +} + +/** + * Determine whether the given properties match those of a `S3EventProperty` + * + * @param properties - the TypeScript properties of a `S3EventProperty` + * + * @returns the result of the validation. + */ +function CfnFunction_S3EventPropertyValidator(properties: any): cdk.ValidationResult { + if (!cdk.canInspect(properties)) { return cdk.VALIDATION_SUCCESS; } + const errors = new cdk.ValidationResults(); + errors.collect(cdk.propertyValidator('bucket', cdk.requiredValidator)(properties.bucket)); + errors.collect(cdk.propertyValidator('bucket', cdk.validateString)(properties.bucket)); + errors.collect(cdk.propertyValidator('events', cdk.requiredValidator)(properties.events)); + errors.collect(cdk.propertyValidator('events', cdk.unionValidator(cdk.unionValidator(cdk.validateString), cdk.listValidator(cdk.unionValidator(cdk.validateString))))(properties.events)); + errors.collect(cdk.propertyValidator('filter', CfnFunction_S3NotificationFilterPropertyValidator)(properties.filter)); + return errors.wrap('supplied properties not correct for "S3EventProperty"'); +} + +/** + * Renders the AWS CloudFormation properties of an `AWS::Serverless::Function.S3Event` resource + * + * @param properties - the TypeScript properties of a `S3EventProperty` + * + * @returns the AWS CloudFormation properties of an `AWS::Serverless::Function.S3Event` resource. + */ +// @ts-ignore TS6133 +function cfnFunctionS3EventPropertyToCloudFormation(properties: any): any { + if (!cdk.canInspect(properties)) { return properties; } + CfnFunction_S3EventPropertyValidator(properties).assertSuccess(); + return { + Bucket: cdk.stringToCloudFormation(properties.bucket), + Events: cdk.unionMapper([cdk.unionValidator(cdk.validateString), cdk.listValidator(cdk.unionValidator(cdk.validateString))], [cdk.unionMapper([cdk.validateString], [cdk.stringToCloudFormation]), cdk.listMapper(cdk.unionMapper([cdk.validateString], [cdk.stringToCloudFormation]))])(properties.events), + Filter: cfnFunctionS3NotificationFilterPropertyToCloudFormation(properties.filter), + }; +} + +export namespace CfnFunction { + /** + * @see https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#s3-location-object + */ + export interface S3LocationProperty { + /** + * `CfnFunction.S3LocationProperty.Bucket` + * @see https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction + */ + bucket: string; + /** + * `CfnFunction.S3LocationProperty.Key` + * @see https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction + */ + key: string; + /** + * `CfnFunction.S3LocationProperty.Version` + * @see https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction + */ + version?: number | cdk.Token; + } +} + +/** + * Determine whether the given properties match those of a `S3LocationProperty` + * + * @param properties - the TypeScript properties of a `S3LocationProperty` + * + * @returns the result of the validation. + */ +function CfnFunction_S3LocationPropertyValidator(properties: any): cdk.ValidationResult { + if (!cdk.canInspect(properties)) { return cdk.VALIDATION_SUCCESS; } + const errors = new cdk.ValidationResults(); + errors.collect(cdk.propertyValidator('bucket', cdk.requiredValidator)(properties.bucket)); + errors.collect(cdk.propertyValidator('bucket', cdk.validateString)(properties.bucket)); + errors.collect(cdk.propertyValidator('key', cdk.requiredValidator)(properties.key)); + errors.collect(cdk.propertyValidator('key', cdk.validateString)(properties.key)); + errors.collect(cdk.propertyValidator('version', cdk.validateNumber)(properties.version)); + return errors.wrap('supplied properties not correct for "S3LocationProperty"'); +} + +/** + * Renders the AWS CloudFormation properties of an `AWS::Serverless::Function.S3Location` resource + * + * @param properties - the TypeScript properties of a `S3LocationProperty` + * + * @returns the AWS CloudFormation properties of an `AWS::Serverless::Function.S3Location` resource. + */ +// @ts-ignore TS6133 +function cfnFunctionS3LocationPropertyToCloudFormation(properties: any): any { + if (!cdk.canInspect(properties)) { return properties; } + CfnFunction_S3LocationPropertyValidator(properties).assertSuccess(); + return { + Bucket: cdk.stringToCloudFormation(properties.bucket), + Key: cdk.stringToCloudFormation(properties.key), + Version: cdk.numberToCloudFormation(properties.version), + }; +} + +export namespace CfnFunction { + /** + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-s3-bucket-notificationconfiguration-config-filter.html + */ + export interface S3NotificationFilterProperty { + /** + * `CfnFunction.S3NotificationFilterProperty.S3Key` + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-s3-bucket-notificationconfiguration-config-filter.html + */ + s3Key: string; + } +} + +/** + * Determine whether the given properties match those of a `S3NotificationFilterProperty` + * + * @param properties - the TypeScript properties of a `S3NotificationFilterProperty` + * + * @returns the result of the validation. + */ +function CfnFunction_S3NotificationFilterPropertyValidator(properties: any): cdk.ValidationResult { + if (!cdk.canInspect(properties)) { return cdk.VALIDATION_SUCCESS; } + const errors = new cdk.ValidationResults(); + errors.collect(cdk.propertyValidator('s3Key', cdk.requiredValidator)(properties.s3Key)); + errors.collect(cdk.propertyValidator('s3Key', cdk.validateString)(properties.s3Key)); + return errors.wrap('supplied properties not correct for "S3NotificationFilterProperty"'); +} + +/** + * Renders the AWS CloudFormation properties of an `AWS::Serverless::Function.S3NotificationFilter` resource + * + * @param properties - the TypeScript properties of a `S3NotificationFilterProperty` + * + * @returns the AWS CloudFormation properties of an `AWS::Serverless::Function.S3NotificationFilter` resource. + */ +// @ts-ignore TS6133 +function cfnFunctionS3NotificationFilterPropertyToCloudFormation(properties: any): any { + if (!cdk.canInspect(properties)) { return properties; } + CfnFunction_S3NotificationFilterPropertyValidator(properties).assertSuccess(); + return { + S3Key: cdk.stringToCloudFormation(properties.s3Key), + }; +} + +export namespace CfnFunction { + /** + * @see https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#sns + */ + export interface SNSEventProperty { + /** + * `CfnFunction.SNSEventProperty.Topic` + * @see https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#sns + */ + topic: string; + } +} + +/** + * Determine whether the given properties match those of a `SNSEventProperty` + * + * @param properties - the TypeScript properties of a `SNSEventProperty` + * + * @returns the result of the validation. + */ +function CfnFunction_SNSEventPropertyValidator(properties: any): cdk.ValidationResult { + if (!cdk.canInspect(properties)) { return cdk.VALIDATION_SUCCESS; } + const errors = new cdk.ValidationResults(); + errors.collect(cdk.propertyValidator('topic', cdk.requiredValidator)(properties.topic)); + errors.collect(cdk.propertyValidator('topic', cdk.validateString)(properties.topic)); + return errors.wrap('supplied properties not correct for "SNSEventProperty"'); +} + +/** + * Renders the AWS CloudFormation properties of an `AWS::Serverless::Function.SNSEvent` resource + * + * @param properties - the TypeScript properties of a `SNSEventProperty` + * + * @returns the AWS CloudFormation properties of an `AWS::Serverless::Function.SNSEvent` resource. + */ +// @ts-ignore TS6133 +function cfnFunctionSNSEventPropertyToCloudFormation(properties: any): any { + if (!cdk.canInspect(properties)) { return properties; } + CfnFunction_SNSEventPropertyValidator(properties).assertSuccess(); + return { + Topic: cdk.stringToCloudFormation(properties.topic), + }; +} + +export namespace CfnFunction { + /** + * @see https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#sqs + */ + export interface SQSEventProperty { + /** + * `CfnFunction.SQSEventProperty.BatchSize` + * @see https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#sqs + */ + batchSize?: number | cdk.Token; + /** + * `CfnFunction.SQSEventProperty.Queue` + * @see https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#sqs + */ + queue: string; + } +} + +/** + * Determine whether the given properties match those of a `SQSEventProperty` + * + * @param properties - the TypeScript properties of a `SQSEventProperty` + * + * @returns the result of the validation. + */ +function CfnFunction_SQSEventPropertyValidator(properties: any): cdk.ValidationResult { + if (!cdk.canInspect(properties)) { return cdk.VALIDATION_SUCCESS; } + const errors = new cdk.ValidationResults(); + errors.collect(cdk.propertyValidator('batchSize', cdk.validateNumber)(properties.batchSize)); + errors.collect(cdk.propertyValidator('queue', cdk.requiredValidator)(properties.queue)); + errors.collect(cdk.propertyValidator('queue', cdk.validateString)(properties.queue)); + return errors.wrap('supplied properties not correct for "SQSEventProperty"'); +} + +/** + * Renders the AWS CloudFormation properties of an `AWS::Serverless::Function.SQSEvent` resource + * + * @param properties - the TypeScript properties of a `SQSEventProperty` + * + * @returns the AWS CloudFormation properties of an `AWS::Serverless::Function.SQSEvent` resource. + */ +// @ts-ignore TS6133 +function cfnFunctionSQSEventPropertyToCloudFormation(properties: any): any { + if (!cdk.canInspect(properties)) { return properties; } + CfnFunction_SQSEventPropertyValidator(properties).assertSuccess(); + return { + BatchSize: cdk.numberToCloudFormation(properties.batchSize), + Queue: cdk.stringToCloudFormation(properties.queue), + }; +} + +export namespace CfnFunction { + /** + * @see https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#schedule + */ + export interface ScheduleEventProperty { + /** + * `CfnFunction.ScheduleEventProperty.Input` + * @see https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#schedule + */ + input?: string; + /** + * `CfnFunction.ScheduleEventProperty.Schedule` + * @see https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#schedule + */ + schedule: string; + } +} + +/** + * Determine whether the given properties match those of a `ScheduleEventProperty` + * + * @param properties - the TypeScript properties of a `ScheduleEventProperty` + * + * @returns the result of the validation. + */ +function CfnFunction_ScheduleEventPropertyValidator(properties: any): cdk.ValidationResult { + if (!cdk.canInspect(properties)) { return cdk.VALIDATION_SUCCESS; } + const errors = new cdk.ValidationResults(); + errors.collect(cdk.propertyValidator('input', cdk.validateString)(properties.input)); + errors.collect(cdk.propertyValidator('schedule', cdk.requiredValidator)(properties.schedule)); + errors.collect(cdk.propertyValidator('schedule', cdk.validateString)(properties.schedule)); + return errors.wrap('supplied properties not correct for "ScheduleEventProperty"'); +} + +/** + * Renders the AWS CloudFormation properties of an `AWS::Serverless::Function.ScheduleEvent` resource + * + * @param properties - the TypeScript properties of a `ScheduleEventProperty` + * + * @returns the AWS CloudFormation properties of an `AWS::Serverless::Function.ScheduleEvent` resource. + */ +// @ts-ignore TS6133 +function cfnFunctionScheduleEventPropertyToCloudFormation(properties: any): any { + if (!cdk.canInspect(properties)) { return properties; } + CfnFunction_ScheduleEventPropertyValidator(properties).assertSuccess(); + return { + Input: cdk.stringToCloudFormation(properties.input), + Schedule: cdk.stringToCloudFormation(properties.schedule), + }; +} + +export namespace CfnFunction { + /** + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-lambda-function-vpcconfig.html + */ + export interface VpcConfigProperty { + /** + * `CfnFunction.VpcConfigProperty.SecurityGroupIds` + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-lambda-function-vpcconfig.html + */ + securityGroupIds: string[]; + /** + * `CfnFunction.VpcConfigProperty.SubnetIds` + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-lambda-function-vpcconfig.html + */ + subnetIds: string[]; + } +} + +/** + * Determine whether the given properties match those of a `VpcConfigProperty` + * + * @param properties - the TypeScript properties of a `VpcConfigProperty` + * + * @returns the result of the validation. + */ +function CfnFunction_VpcConfigPropertyValidator(properties: any): cdk.ValidationResult { + if (!cdk.canInspect(properties)) { return cdk.VALIDATION_SUCCESS; } + const errors = new cdk.ValidationResults(); + errors.collect(cdk.propertyValidator('securityGroupIds', cdk.requiredValidator)(properties.securityGroupIds)); + errors.collect(cdk.propertyValidator('securityGroupIds', cdk.listValidator(cdk.validateString))(properties.securityGroupIds)); + errors.collect(cdk.propertyValidator('subnetIds', cdk.requiredValidator)(properties.subnetIds)); + errors.collect(cdk.propertyValidator('subnetIds', cdk.listValidator(cdk.validateString))(properties.subnetIds)); + return errors.wrap('supplied properties not correct for "VpcConfigProperty"'); +} + +/** + * Renders the AWS CloudFormation properties of an `AWS::Serverless::Function.VpcConfig` resource + * + * @param properties - the TypeScript properties of a `VpcConfigProperty` + * + * @returns the AWS CloudFormation properties of an `AWS::Serverless::Function.VpcConfig` resource. + */ +// @ts-ignore TS6133 +function cfnFunctionVpcConfigPropertyToCloudFormation(properties: any): any { + if (!cdk.canInspect(properties)) { return properties; } + CfnFunction_VpcConfigPropertyValidator(properties).assertSuccess(); + return { + SecurityGroupIds: cdk.listMapper(cdk.stringToCloudFormation)(properties.securityGroupIds), + SubnetIds: cdk.listMapper(cdk.stringToCloudFormation)(properties.subnetIds), + }; +} + +/** + * Properties for defining a `AWS::Serverless::LayerVersion` + * @see https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlesslayerversion + */ +export interface CfnLayerVersionProps { + /** + * `AWS::Serverless::LayerVersion.CompatibleRuntimes` + * @see https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlesslayerversion + */ + compatibleRuntimes?: string[]; + /** + * `AWS::Serverless::LayerVersion.ContentUri` + * @see https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlesslayerversion + */ + contentUri?: string; + /** + * `AWS::Serverless::LayerVersion.Description` + * @see https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlesslayerversion + */ + description?: string; + /** + * `AWS::Serverless::LayerVersion.LayerName` + * @see https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlesslayerversion + */ + layerName?: string; + /** + * `AWS::Serverless::LayerVersion.LicenseInfo` + * @see https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlesslayerversion + */ + licenseInfo?: string; + /** + * `AWS::Serverless::LayerVersion.RetentionPolicy` + * @see https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlesslayerversion + */ + retentionPolicy?: string; +} + +/** + * Determine whether the given properties match those of a `CfnLayerVersionProps` + * + * @param properties - the TypeScript properties of a `CfnLayerVersionProps` + * + * @returns the result of the validation. + */ +function CfnLayerVersionPropsValidator(properties: any): cdk.ValidationResult { + if (!cdk.canInspect(properties)) { return cdk.VALIDATION_SUCCESS; } + const errors = new cdk.ValidationResults(); + errors.collect(cdk.propertyValidator('compatibleRuntimes', cdk.listValidator(cdk.validateString))(properties.compatibleRuntimes)); + errors.collect(cdk.propertyValidator('contentUri', cdk.validateString)(properties.contentUri)); + errors.collect(cdk.propertyValidator('description', cdk.validateString)(properties.description)); + errors.collect(cdk.propertyValidator('layerName', cdk.validateString)(properties.layerName)); + errors.collect(cdk.propertyValidator('licenseInfo', cdk.validateString)(properties.licenseInfo)); + errors.collect(cdk.propertyValidator('retentionPolicy', cdk.validateString)(properties.retentionPolicy)); + return errors.wrap('supplied properties not correct for "CfnLayerVersionProps"'); +} + +/** + * Renders the AWS CloudFormation properties of an `AWS::Serverless::LayerVersion` resource + * + * @param properties - the TypeScript properties of a `CfnLayerVersionProps` + * + * @returns the AWS CloudFormation properties of an `AWS::Serverless::LayerVersion` resource. + */ +// @ts-ignore TS6133 +function cfnLayerVersionPropsToCloudFormation(properties: any): any { + if (!cdk.canInspect(properties)) { return properties; } + CfnLayerVersionPropsValidator(properties).assertSuccess(); + return { + CompatibleRuntimes: cdk.listMapper(cdk.stringToCloudFormation)(properties.compatibleRuntimes), + ContentUri: cdk.stringToCloudFormation(properties.contentUri), + Description: cdk.stringToCloudFormation(properties.description), + LayerName: cdk.stringToCloudFormation(properties.layerName), + LicenseInfo: cdk.stringToCloudFormation(properties.licenseInfo), + RetentionPolicy: cdk.stringToCloudFormation(properties.retentionPolicy), + }; +} + +/** + * A CloudFormation `AWS::Serverless::LayerVersion` + * + * @cloudformationResource AWS::Serverless::LayerVersion + * @see https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlesslayerversion + */ +export class CfnLayerVersion extends cdk.CfnResource { + /** + * The CloudFormation resource type name for this resource class. + */ + public static readonly resourceTypeName = "AWS::Serverless::LayerVersion"; + /** + * The `Transform` a template must use in order to use this resource + */ + public static readonly requiredTransform = "AWS::Serverless-2016-10-31"; + public readonly layerVersionArn: string; + + /** + * Create a new `AWS::Serverless::LayerVersion`. + * + * @param scope - scope in which this resource is defined + * @param id - scoped id of the resource + * @param props - resource properties + */ + constructor(scope: cdk.Construct, id: string, props?: CfnLayerVersionProps) { + super(scope, id, { type: CfnLayerVersion.resourceTypeName, properties: props }); + // If a different transform than the required one is in use, this resource cannot be used + if (this.node.stack.templateOptions.transform && this.node.stack.templateOptions.transform !== CfnLayerVersion.requiredTransform) { + throw new Error(`The ${JSON.stringify(CfnLayerVersion.requiredTransform)} transform is required when using CfnLayerVersion, but the ${JSON.stringify(this.node.stack.templateOptions.transform)} is used.`); + } + // Automatically configure the required transform + this.node.stack.templateOptions.transform = CfnLayerVersion.requiredTransform; + this.layerVersionArn = this.ref.toString(); + } + + public get propertyOverrides(): CfnLayerVersionProps { + return this.untypedPropertyOverrides; + } + protected renderProperties(properties: any): { [key: string]: any } { + return cfnLayerVersionPropsToCloudFormation(this.node.resolve(properties)); + } +} + +/** + * Properties for defining a `AWS::Serverless::SimpleTable` + * @see https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlesssimpletable + */ +export interface CfnSimpleTableProps { + /** + * `AWS::Serverless::SimpleTable.PrimaryKey` + * @see https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#primary-key-object + */ + primaryKey?: CfnSimpleTable.PrimaryKeyProperty | cdk.Token; + /** + * `AWS::Serverless::SimpleTable.ProvisionedThroughput` + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-provisionedthroughput.html + */ + provisionedThroughput?: CfnSimpleTable.ProvisionedThroughputProperty | cdk.Token; + /** + * `AWS::Serverless::SimpleTable.SSESpecification` + * @see https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlesssimpletable + */ + sseSpecification?: CfnSimpleTable.SSESpecificationProperty | cdk.Token; + /** + * `AWS::Serverless::SimpleTable.TableName` + * @see https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlesssimpletable + */ + tableName?: string; + /** + * `AWS::Serverless::SimpleTable.Tags` + * @see https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlesssimpletable + */ + tags?: { [key: string]: (string) }; +} + +/** + * Determine whether the given properties match those of a `CfnSimpleTableProps` + * + * @param properties - the TypeScript properties of a `CfnSimpleTableProps` + * + * @returns the result of the validation. + */ +function CfnSimpleTablePropsValidator(properties: any): cdk.ValidationResult { + if (!cdk.canInspect(properties)) { return cdk.VALIDATION_SUCCESS; } + const errors = new cdk.ValidationResults(); + errors.collect(cdk.propertyValidator('primaryKey', CfnSimpleTable_PrimaryKeyPropertyValidator)(properties.primaryKey)); + errors.collect(cdk.propertyValidator('provisionedThroughput', CfnSimpleTable_ProvisionedThroughputPropertyValidator)(properties.provisionedThroughput)); + errors.collect(cdk.propertyValidator('sseSpecification', CfnSimpleTable_SSESpecificationPropertyValidator)(properties.sseSpecification)); + errors.collect(cdk.propertyValidator('tableName', cdk.validateString)(properties.tableName)); + errors.collect(cdk.propertyValidator('tags', cdk.hashValidator(cdk.validateString))(properties.tags)); + return errors.wrap('supplied properties not correct for "CfnSimpleTableProps"'); +} + +/** + * Renders the AWS CloudFormation properties of an `AWS::Serverless::SimpleTable` resource + * + * @param properties - the TypeScript properties of a `CfnSimpleTableProps` + * + * @returns the AWS CloudFormation properties of an `AWS::Serverless::SimpleTable` resource. + */ +// @ts-ignore TS6133 +function cfnSimpleTablePropsToCloudFormation(properties: any): any { + if (!cdk.canInspect(properties)) { return properties; } + CfnSimpleTablePropsValidator(properties).assertSuccess(); + return { + PrimaryKey: cfnSimpleTablePrimaryKeyPropertyToCloudFormation(properties.primaryKey), + ProvisionedThroughput: cfnSimpleTableProvisionedThroughputPropertyToCloudFormation(properties.provisionedThroughput), + SSESpecification: cfnSimpleTableSSESpecificationPropertyToCloudFormation(properties.sseSpecification), + TableName: cdk.stringToCloudFormation(properties.tableName), + Tags: cdk.hashMapper(cdk.stringToCloudFormation)(properties.tags), + }; +} + +/** + * A CloudFormation `AWS::Serverless::SimpleTable` + * + * @cloudformationResource AWS::Serverless::SimpleTable + * @see https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlesssimpletable + */ +export class CfnSimpleTable extends cdk.CfnResource { + /** + * The CloudFormation resource type name for this resource class. + */ + public static readonly resourceTypeName = "AWS::Serverless::SimpleTable"; + /** + * The `Transform` a template must use in order to use this resource + */ + public static readonly requiredTransform = "AWS::Serverless-2016-10-31"; + public readonly simpleTableName: string; + + /** + * The `TagManager` handles setting, removing and formatting tags + * + * Tags should be managed either passing them as properties during + * initiation or by calling methods on this object. If both techniques are + * used only the tags from the TagManager will be used. `Tag` (aspect) + * will use the manager. + */ + public readonly tags: cdk.TagManager; + + /** + * Create a new `AWS::Serverless::SimpleTable`. + * + * @param scope - scope in which this resource is defined + * @param id - scoped id of the resource + * @param props - resource properties + */ + constructor(scope: cdk.Construct, id: string, props?: CfnSimpleTableProps) { + super(scope, id, { type: CfnSimpleTable.resourceTypeName, properties: props }); + // If a different transform than the required one is in use, this resource cannot be used + if (this.node.stack.templateOptions.transform && this.node.stack.templateOptions.transform !== CfnSimpleTable.requiredTransform) { + throw new Error(`The ${JSON.stringify(CfnSimpleTable.requiredTransform)} transform is required when using CfnSimpleTable, but the ${JSON.stringify(this.node.stack.templateOptions.transform)} is used.`); + } + // Automatically configure the required transform + this.node.stack.templateOptions.transform = CfnSimpleTable.requiredTransform; + this.simpleTableName = this.ref.toString(); + const tags = props === undefined ? undefined : props.tags; + this.tags = new cdk.TagManager(cdk.TagType.Map, "AWS::Serverless::SimpleTable", tags); + } + + public get propertyOverrides(): CfnSimpleTableProps { + return this.untypedPropertyOverrides; + } + protected renderProperties(properties: any): { [key: string]: any } { + return cfnSimpleTablePropsToCloudFormation(this.node.resolve(properties)); + } +} + +export namespace CfnSimpleTable { + /** + * @see https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#primary-key-object + */ + export interface PrimaryKeyProperty { + /** + * `CfnSimpleTable.PrimaryKeyProperty.Name` + * @see https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#primary-key-object + */ + name?: string; + /** + * `CfnSimpleTable.PrimaryKeyProperty.Type` + * @see https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#primary-key-object + */ + type: string; + } +} + +/** + * Determine whether the given properties match those of a `PrimaryKeyProperty` + * + * @param properties - the TypeScript properties of a `PrimaryKeyProperty` + * + * @returns the result of the validation. + */ +function CfnSimpleTable_PrimaryKeyPropertyValidator(properties: any): cdk.ValidationResult { + if (!cdk.canInspect(properties)) { return cdk.VALIDATION_SUCCESS; } + const errors = new cdk.ValidationResults(); + errors.collect(cdk.propertyValidator('name', cdk.validateString)(properties.name)); + errors.collect(cdk.propertyValidator('type', cdk.requiredValidator)(properties.type)); + errors.collect(cdk.propertyValidator('type', cdk.validateString)(properties.type)); + return errors.wrap('supplied properties not correct for "PrimaryKeyProperty"'); +} + +/** + * Renders the AWS CloudFormation properties of an `AWS::Serverless::SimpleTable.PrimaryKey` resource + * + * @param properties - the TypeScript properties of a `PrimaryKeyProperty` + * + * @returns the AWS CloudFormation properties of an `AWS::Serverless::SimpleTable.PrimaryKey` resource. + */ +// @ts-ignore TS6133 +function cfnSimpleTablePrimaryKeyPropertyToCloudFormation(properties: any): any { + if (!cdk.canInspect(properties)) { return properties; } + CfnSimpleTable_PrimaryKeyPropertyValidator(properties).assertSuccess(); + return { + Name: cdk.stringToCloudFormation(properties.name), + Type: cdk.stringToCloudFormation(properties.type), + }; +} + +export namespace CfnSimpleTable { + /** + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-provisionedthroughput.html + */ + export interface ProvisionedThroughputProperty { + /** + * `CfnSimpleTable.ProvisionedThroughputProperty.ReadCapacityUnits` + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-provisionedthroughput.html + */ + readCapacityUnits?: number | cdk.Token; + /** + * `CfnSimpleTable.ProvisionedThroughputProperty.WriteCapacityUnits` + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-provisionedthroughput.html + */ + writeCapacityUnits: number | cdk.Token; + } +} + +/** + * Determine whether the given properties match those of a `ProvisionedThroughputProperty` + * + * @param properties - the TypeScript properties of a `ProvisionedThroughputProperty` + * + * @returns the result of the validation. + */ +function CfnSimpleTable_ProvisionedThroughputPropertyValidator(properties: any): cdk.ValidationResult { + if (!cdk.canInspect(properties)) { return cdk.VALIDATION_SUCCESS; } + const errors = new cdk.ValidationResults(); + errors.collect(cdk.propertyValidator('readCapacityUnits', cdk.validateNumber)(properties.readCapacityUnits)); + errors.collect(cdk.propertyValidator('writeCapacityUnits', cdk.requiredValidator)(properties.writeCapacityUnits)); + errors.collect(cdk.propertyValidator('writeCapacityUnits', cdk.validateNumber)(properties.writeCapacityUnits)); + return errors.wrap('supplied properties not correct for "ProvisionedThroughputProperty"'); +} + +/** + * Renders the AWS CloudFormation properties of an `AWS::Serverless::SimpleTable.ProvisionedThroughput` resource + * + * @param properties - the TypeScript properties of a `ProvisionedThroughputProperty` + * + * @returns the AWS CloudFormation properties of an `AWS::Serverless::SimpleTable.ProvisionedThroughput` resource. + */ +// @ts-ignore TS6133 +function cfnSimpleTableProvisionedThroughputPropertyToCloudFormation(properties: any): any { + if (!cdk.canInspect(properties)) { return properties; } + CfnSimpleTable_ProvisionedThroughputPropertyValidator(properties).assertSuccess(); + return { + ReadCapacityUnits: cdk.numberToCloudFormation(properties.readCapacityUnits), + WriteCapacityUnits: cdk.numberToCloudFormation(properties.writeCapacityUnits), + }; +} + +export namespace CfnSimpleTable { + /** + * @see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-table-ssespecification.html + */ + export interface SSESpecificationProperty { + /** + * `CfnSimpleTable.SSESpecificationProperty.SSEEnabled` + * @see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-table-ssespecification.html + */ + sseEnabled?: boolean | cdk.Token; + } +} + +/** + * Determine whether the given properties match those of a `SSESpecificationProperty` + * + * @param properties - the TypeScript properties of a `SSESpecificationProperty` + * + * @returns the result of the validation. + */ +function CfnSimpleTable_SSESpecificationPropertyValidator(properties: any): cdk.ValidationResult { + if (!cdk.canInspect(properties)) { return cdk.VALIDATION_SUCCESS; } + const errors = new cdk.ValidationResults(); + errors.collect(cdk.propertyValidator('sseEnabled', cdk.validateBoolean)(properties.sseEnabled)); + return errors.wrap('supplied properties not correct for "SSESpecificationProperty"'); +} + +/** + * Renders the AWS CloudFormation properties of an `AWS::Serverless::SimpleTable.SSESpecification` resource + * + * @param properties - the TypeScript properties of a `SSESpecificationProperty` + * + * @returns the AWS CloudFormation properties of an `AWS::Serverless::SimpleTable.SSESpecification` resource. + */ +// @ts-ignore TS6133 +function cfnSimpleTableSSESpecificationPropertyToCloudFormation(properties: any): any { + if (!cdk.canInspect(properties)) { return properties; } + CfnSimpleTable_SSESpecificationPropertyValidator(properties).assertSuccess(); + return { + SSEEnabled: cdk.booleanToCloudFormation(properties.sseEnabled), + }; +} diff --git a/packages/@aws-cdk/aws-serverless/package-lock.json b/packages/@aws-cdk/aws-serverless/package-lock.json index f1cdf8eef8c79..cb6dd241cad10 100644 --- a/packages/@aws-cdk/aws-serverless/package-lock.json +++ b/packages/@aws-cdk/aws-serverless/package-lock.json @@ -1,6 +1,6 @@ { "name": "@aws-cdk/aws-serverless", - "version": "0.26.0", + "version": "0.27.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/packages/@aws-cdk/aws-sns/lib/topic-base.ts b/packages/@aws-cdk/aws-sns/lib/topic-base.ts index cd40c1607b15c..06e73bf8227e3 100644 --- a/packages/@aws-cdk/aws-sns/lib/topic-base.ts +++ b/packages/@aws-cdk/aws-sns/lib/topic-base.ts @@ -83,7 +83,7 @@ export interface ITopic extends /** * Grant topic publishing permissions to the given identity */ - grantPublish(identity: iam.IPrincipal): iam.Grant; + grantPublish(identity: iam.IGrantable): iam.Grant; } /** @@ -270,7 +270,7 @@ export abstract class TopicBase extends cdk.Construct implements ITopic { /** * Grant topic publishing permissions to the given identity */ - public grantPublish(principal: iam.IPrincipal) { + public grantPublish(principal: iam.IGrantable) { return iam.Grant.withResource({ principal, actions: ['sns:Publish'], diff --git a/packages/@aws-cdk/aws-sqs/lib/queue-base.ts b/packages/@aws-cdk/aws-sqs/lib/queue-base.ts index efb504c830fa7..42dfef6bbff05 100644 --- a/packages/@aws-cdk/aws-sqs/lib/queue-base.ts +++ b/packages/@aws-cdk/aws-sqs/lib/queue-base.ts @@ -53,9 +53,9 @@ export interface IQueue extends cdk.IConstruct, s3n.IBucketNotificationDestinati * - sqs:GetQueueAttributes * - sqs:GetQueueUrl * - * @param identity Principal to grant consume rights to + * @param grantee Principal to grant consume rights to */ - grantConsumeMessages(identity: iam.IPrincipal): iam.Grant; + grantConsumeMessages(grantee: iam.IGrantable): iam.Grant; /** * Grant access to send messages to a queue to the given identity. @@ -67,9 +67,9 @@ export interface IQueue extends cdk.IConstruct, s3n.IBucketNotificationDestinati * - sqs:GetQueueAttributes * - sqs:GetQueueUrl * - * @param identity Principal to grant send rights to + * @param grantee Principal to grant send rights to */ - grantSendMessages(identity: iam.IPrincipal): iam.Grant; + grantSendMessages(grantee: iam.IGrantable): iam.Grant; /** * Grant an IAM principal permissions to purge all messages from the queue. @@ -80,19 +80,19 @@ export interface IQueue extends cdk.IConstruct, s3n.IBucketNotificationDestinati * - sqs:GetQueueAttributes * - sqs:GetQueueUrl * - * @param identity Principal to grant send rights to + * @param grantee Principal to grant send rights to * @param queueActions additional queue actions to allow */ - grantPurge(identity: iam.IPrincipal): iam.Grant; + grantPurge(grantee: iam.IGrantable): iam.Grant; /** * Grant the actions defined in queueActions to the identity Principal given * on this SQS queue resource. * - * @param identity Principal to grant right to + * @param grantee Principal to grant right to * @param queueActions The actions to grant */ - grant(identity: iam.IPrincipal, ...queueActions: string[]): iam.Grant; + grant(grantee: iam.IGrantable, ...queueActions: string[]): iam.Grant; } /** @@ -214,10 +214,10 @@ export abstract class QueueBase extends cdk.Construct implements IQueue { * - sqs:GetQueueAttributes * - sqs:GetQueueUrl * - * @param identity Principal to grant consume rights to + * @param grantee Principal to grant consume rights to */ - public grantConsumeMessages(identity: iam.IPrincipal) { - return this.grant(identity, + public grantConsumeMessages(grantee: iam.IGrantable) { + return this.grant(grantee, 'sqs:ReceiveMessage', 'sqs:ChangeMessageVisibility', 'sqs:ChangeMessageVisibilityBatch', @@ -237,10 +237,10 @@ export abstract class QueueBase extends cdk.Construct implements IQueue { * - sqs:GetQueueAttributes * - sqs:GetQueueUrl * - * @param identity Principal to grant send rights to + * @param grantee Principal to grant send rights to */ - public grantSendMessages(identity: iam.IPrincipal) { - return this.grant(identity, + public grantSendMessages(grantee: iam.IGrantable) { + return this.grant(grantee, 'sqs:SendMessage', 'sqs:SendMessageBatch', 'sqs:GetQueueAttributes', @@ -256,11 +256,11 @@ export abstract class QueueBase extends cdk.Construct implements IQueue { * - sqs:GetQueueAttributes * - sqs:GetQueueUrl * - * @param identity Principal to grant send rights to + * @param grantee Principal to grant send rights to * @param queueActions additional queue actions to allow */ - public grantPurge(identity: iam.IPrincipal) { - return this.grant(identity, + public grantPurge(grantee: iam.IGrantable) { + return this.grant(grantee, 'sqs:PurgeQueue', 'sqs:GetQueueAttributes', 'sqs:GetQueueUrl'); @@ -270,12 +270,12 @@ export abstract class QueueBase extends cdk.Construct implements IQueue { * Grant the actions defined in queueActions to the identity Principal given * on this SQS queue resource. * - * @param principal Principal to grant right to + * @param grantee Principal to grant right to * @param actions The actions to grant */ - public grant(principal: iam.IPrincipal, ...actions: string[]) { + public grant(grantee: iam.IGrantable, ...actions: string[]) { return iam.Grant.withResource({ - principal, + grantee, actions, resourceArns: [this.queueArn], resource: this, diff --git a/packages/@aws-cdk/aws-ssm/lib/parameter.ts b/packages/@aws-cdk/aws-ssm/lib/parameter.ts index de096ba82fb40..4980611161262 100644 --- a/packages/@aws-cdk/aws-ssm/lib/parameter.ts +++ b/packages/@aws-cdk/aws-ssm/lib/parameter.ts @@ -26,14 +26,14 @@ export interface IParameter extends cdk.IConstruct { * * @param grantee the role to be granted read-only access to the parameter. */ - grantRead(grantee: iam.IPrincipal): void; + grantRead(grantee: iam.IGrantable): void; /** * Grants write (PutParameter) permissions on the SSM Parameter. * * @param grantee the role to be granted write access to the parameter. */ - grantWrite(grantee: iam.IPrincipal): void; + grantWrite(grantee: iam.IGrantable): void; } /** @@ -124,14 +124,14 @@ export abstract class ParameterBase extends cdk.Construct implements IParameter }); } - public grantRead(grantee: iam.IPrincipal): void { + public grantRead(grantee: iam.IGrantable): void { grantee.addToPolicy(new iam.PolicyStatement() .allow() .addActions('ssm:DescribeParameters', 'ssm:GetParameter', 'ssm:GetParameterHistory') .addResource(this.parameterArn)); } - public grantWrite(grantee: iam.IPrincipal): void { + public grantWrite(grantee: iam.IGrantable): void { grantee.addToPolicy(new iam.PolicyStatement() .allow() .addAction('ssm:PutParameter') diff --git a/packages/@aws-cdk/runtime-values/lib/rtv.ts b/packages/@aws-cdk/runtime-values/lib/rtv.ts index 8feb9f71457a8..0b2829511fe38 100644 --- a/packages/@aws-cdk/runtime-values/lib/rtv.ts +++ b/packages/@aws-cdk/runtime-values/lib/rtv.ts @@ -74,7 +74,7 @@ export class RuntimeValue extends cdk.Construct { * Grants a principal read permissions on this runtime value. * @param principal The principal (e.g. Role, User, Group) */ - public grantRead(principal: iam.IPrincipal) { + public grantRead(principal: iam.IGrantable) { // sometimes "role" is optional, so we want `rtv.grantRead(role)` to be a no-op if (!principal) { diff --git a/packages/aws-cdk/lib/init-templates/app/java/src/main/java/com/myorg/HelloConstruct.java b/packages/aws-cdk/lib/init-templates/app/java/src/main/java/com/myorg/HelloConstruct.java index 7a2b629a6135b..3b57fa5725f4a 100644 --- a/packages/aws-cdk/lib/init-templates/app/java/src/main/java/com/myorg/HelloConstruct.java +++ b/packages/aws-cdk/lib/init-templates/app/java/src/main/java/com/myorg/HelloConstruct.java @@ -1,7 +1,7 @@ package com.myorg; import software.amazon.awscdk.Construct; -import software.amazon.awscdk.services.iam.IPrincipal; +import software.amazon.awscdk.services.iam.IGrantable; import software.amazon.awscdk.services.s3.Bucket; import software.amazon.awscdk.services.s3.BucketProps; @@ -24,9 +24,9 @@ public HelloConstruct(final Construct parent, final String name, final HelloCons /** * Given an principal, grants it READ access on all buckets. - * @param principal The principal (User, Group, Role) + * @param grantee The principal (User, Group, Role) */ - public void grantRead(final IPrincipal principal) { - buckets.forEach(b -> b.grantRead(principal, "*")); + public void grantRead(final IGrantable grantee) { + buckets.forEach(b -> b.grantRead(grantee, "*")); } } diff --git a/packages/cdk/package.json b/packages/cdk/package.json index cf2567a8498e8..9877c45e71427 100644 --- a/packages/cdk/package.json +++ b/packages/cdk/package.json @@ -29,6 +29,7 @@ }, "homepage": "https://github.com/awslabs/aws-cdk", "scripts": { + "build": "echo Nothing to build", "package": "mkdir -p dist/js && cd dist/js && npm pack ../../" }, "engines": { diff --git a/tools/cdk-build-tools/package-lock.json b/tools/cdk-build-tools/package-lock.json index 7eb5fa77153ce..e716f752a5427 100644 --- a/tools/cdk-build-tools/package-lock.json +++ b/tools/cdk-build-tools/package-lock.json @@ -1,6 +1,6 @@ { "name": "cdk-build-tools", - "version": "0.26.0", + "version": "0.27.0", "lockfileVersion": 1, "requires": true, "dependencies": { From 74bbf35aab9325f7be41e60be3e67c5e45572259 Mon Sep 17 00:00:00 2001 From: Rico Huijbers Date: Wed, 3 Apr 2019 13:59:50 +0200 Subject: [PATCH 26/31] Finish introduction of IGrantable, rename Grant.withResource -> Grant.onPonPrincipalOrResource --- package.json | 3 +- .../@aws-cdk/aws-codebuild/lib/artifacts.ts | 2 +- .../@aws-cdk/aws-codebuild/lib/project.ts | 17 ++++--- packages/@aws-cdk/aws-codebuild/lib/source.ts | 2 +- .../lib/codebuild/pipeline-actions.ts | 4 +- .../@aws-cdk/aws-ecr/lib/repository-ref.ts | 2 +- packages/@aws-cdk/aws-glue/lib/table.ts | 4 +- packages/@aws-cdk/aws-iam/lib/grant.ts | 2 +- .../aws-iam/lib/imported-resource-role.ts | 45 ------------------- .../aws-lambda-event-sources/lib/dynamodb.ts | 4 +- .../aws-lambda-event-sources/lib/kinesis.ts | 2 +- .../aws-lambda-event-sources/lib/sqs.ts | 2 +- packages/@aws-cdk/aws-lambda/lib/alias.ts | 4 ++ .../@aws-cdk/aws-lambda/lib/function-base.ts | 2 +- .../lib/bucket-deployment.ts | 4 +- packages/@aws-cdk/aws-s3/lib/bucket.ts | 4 +- packages/@aws-cdk/aws-sns/lib/topic-base.ts | 6 +-- packages/@aws-cdk/aws-sqs/lib/queue-base.ts | 2 +- packages/@aws-cdk/aws-ssm/lib/parameter.ts | 22 ++++----- packages/@aws-cdk/runtime-values/lib/rtv.ts | 15 +++---- .../runtime-values/test/integ.rtv.lambda.ts | 2 +- 21 files changed, 58 insertions(+), 92 deletions(-) delete mode 100644 packages/@aws-cdk/aws-iam/lib/imported-resource-role.ts diff --git a/package.json b/package.json index 1d7a4c13b30aa..ad3efdffe367f 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,8 @@ "include": "dependencies/node-version" }, "scripts": { - "pkglint": "tools/pkglint/bin/pkglint -f ." + "pkglint": "tools/pkglint/bin/pkglint -f .", + "build-all": "tsc -b" }, "devDependencies": { "@types/node": "8.10.40", diff --git a/packages/@aws-cdk/aws-codebuild/lib/artifacts.ts b/packages/@aws-cdk/aws-codebuild/lib/artifacts.ts index c85c79c7b4cc6..53c9e835a2766 100644 --- a/packages/@aws-cdk/aws-codebuild/lib/artifacts.ts +++ b/packages/@aws-cdk/aws-codebuild/lib/artifacts.ts @@ -130,7 +130,7 @@ export class S3BucketBuildArtifacts extends BuildArtifacts { * @internal */ public _bind(project: Project) { - this.props.bucket.grantReadWrite(project.role); + this.props.bucket.grantReadWrite(project); } protected toArtifactsProperty(): any { diff --git a/packages/@aws-cdk/aws-codebuild/lib/project.ts b/packages/@aws-cdk/aws-codebuild/lib/project.ts index 89d6e07d84fa1..e6bc958412eb9 100644 --- a/packages/@aws-cdk/aws-codebuild/lib/project.ts +++ b/packages/@aws-cdk/aws-codebuild/lib/project.ts @@ -16,7 +16,7 @@ const CODEPIPELINE_TYPE = 'CODEPIPELINE'; const S3_BUCKET_ENV = 'SCRIPT_S3_BUCKET'; const S3_KEY_ENV = 'SCRIPT_S3_KEY'; -export interface IProject extends cdk.IConstruct, events.IEventRuleTarget { +export interface IProject extends cdk.IConstruct, events.IEventRuleTarget, iam.IGrantable { /** The ARN of this Project. */ readonly projectArn: string; @@ -24,7 +24,7 @@ export interface IProject extends cdk.IConstruct, events.IEventRuleTarget { readonly projectName: string; /** The IAM service Role of this Project. Undefined for imported Projects. */ - readonly role: iam.IRole; + readonly role?: iam.IRole; /** * Defines a CloudWatch event rule triggered when the build project state @@ -156,6 +156,8 @@ export interface ProjectImportProps { * use the {@link import} method. */ export abstract class ProjectBase extends cdk.Construct implements IProject { + public abstract readonly grantPrincipal: iam.IPrincipal; + /** The ARN of this Project. */ public abstract readonly projectArn: string; @@ -163,7 +165,7 @@ export abstract class ProjectBase extends cdk.Construct implements IProject { public abstract readonly projectName: string; /** The IAM service Role of this Project. */ - public abstract readonly role: iam.IRole; + public abstract readonly role?: iam.IRole; /** A role used by CloudWatch events to trigger a build */ private eventsRole?: iam.Role; @@ -369,9 +371,10 @@ export abstract class ProjectBase extends cdk.Construct implements IProject { } class ImportedProject extends ProjectBase { + public readonly grantPrincipal: iam.IPrincipal; public readonly projectArn: string; public readonly projectName: string; - public readonly role: iam.Role = undefined; + public readonly role?: iam.Role = undefined; constructor(scope: cdk.Construct, id: string, private readonly props: ProjectImportProps) { super(scope, id); @@ -381,6 +384,7 @@ class ImportedProject extends ProjectBase { resource: 'project', resourceName: props.projectName, }); + this.grantPrincipal = new iam.ImportedResourcePrincipal({ resource: this }); this.projectName = props.projectName; } @@ -572,10 +576,12 @@ export class Project extends ProjectBase { return new ImportedProject(scope, id, props); } + public readonly grantPrincipal: iam.IPrincipal; + /** * The IAM role for this project. */ - public readonly role: iam.IRole; + public readonly role?: iam.IRole; /** * The ARN of the project. @@ -603,6 +609,7 @@ export class Project extends ProjectBase { this.role = props.role || new iam.Role(this, 'Role', { assumedBy: new iam.ServicePrincipal('codebuild.amazonaws.com') }); + this.grantPrincipal = this.role; let cache: CfnProject.ProjectCacheProperty | undefined; if (props.cacheBucket) { diff --git a/packages/@aws-cdk/aws-codebuild/lib/source.ts b/packages/@aws-cdk/aws-codebuild/lib/source.ts index a268399bc2e9f..d646a6e9c8c07 100644 --- a/packages/@aws-cdk/aws-codebuild/lib/source.ts +++ b/packages/@aws-cdk/aws-codebuild/lib/source.ts @@ -167,7 +167,7 @@ export class S3BucketSource extends BuildSource { * @internal */ public _bind(project: Project) { - this.bucket.grantRead(project.role); + this.bucket.grantRead(project); } protected toSourceProperty(): any { diff --git a/packages/@aws-cdk/aws-codepipeline-actions/lib/codebuild/pipeline-actions.ts b/packages/@aws-cdk/aws-codepipeline-actions/lib/codebuild/pipeline-actions.ts index 21ab3255eec60..1ff4ae6f53c87 100644 --- a/packages/@aws-cdk/aws-codepipeline-actions/lib/codebuild/pipeline-actions.ts +++ b/packages/@aws-cdk/aws-codepipeline-actions/lib/codebuild/pipeline-actions.ts @@ -186,9 +186,9 @@ function setCodeBuildNeededPermissions(info: codepipeline.ActionBind, project: c // allow the Project access to the Pipline's artifact Bucket if (needsPipelineBucketWrite) { - info.pipeline.grantBucketReadWrite(project.role); + info.pipeline.grantBucketReadWrite(project); } else { - info.pipeline.grantBucketRead(project.role); + info.pipeline.grantBucketRead(project); } } diff --git a/packages/@aws-cdk/aws-ecr/lib/repository-ref.ts b/packages/@aws-cdk/aws-ecr/lib/repository-ref.ts index fe8179c101d15..30fe2ab2691cf 100644 --- a/packages/@aws-cdk/aws-ecr/lib/repository-ref.ts +++ b/packages/@aws-cdk/aws-ecr/lib/repository-ref.ts @@ -190,7 +190,7 @@ export abstract class RepositoryBase extends cdk.Construct implements IRepositor * Grant the given principal identity permissions to perform the actions on this repository */ public grant(grantee: iam.IGrantable, ...actions: string[]) { - return iam.Grant.withResource({ + return iam.Grant.onPrincipalOrResource({ grantee, actions, resourceArns: [this.repositoryArn], diff --git a/packages/@aws-cdk/aws-glue/lib/table.ts b/packages/@aws-cdk/aws-glue/lib/table.ts index e0b024ac22a58..6fd1d60a2c88e 100644 --- a/packages/@aws-cdk/aws-glue/lib/table.ts +++ b/packages/@aws-cdk/aws-glue/lib/table.ts @@ -269,7 +269,7 @@ export class Table extends cdk.Construct implements ITable { public grantRead(grantee: iam.IGrantable): iam.Grant { const ret = this.grant(grantee, readPermissions); if (this.encryptionKey && this.encryption === TableEncryption.ClientSideKms) { this.encryptionKey.grantDecrypt(grantee); } - this.bucket.grantRead(principal, this.s3Prefix); + this.bucket.grantRead(grantee, this.s3Prefix); return ret; } @@ -293,7 +293,7 @@ export class Table extends cdk.Construct implements ITable { public grantReadWrite(grantee: iam.IGrantable): iam.Grant { const ret = this.grant(grantee, [...readPermissions, ...writePermissions]); if (this.encryptionKey && this.encryption === TableEncryption.ClientSideKms) { this.encryptionKey.grantEncryptDecrypt(grantee); } - this.bucket.grantReadWrite(principal, this.s3Prefix); + this.bucket.grantReadWrite(grantee, this.s3Prefix); return ret; } diff --git a/packages/@aws-cdk/aws-iam/lib/grant.ts b/packages/@aws-cdk/aws-iam/lib/grant.ts index a71b1a40f8030..a050479654637 100644 --- a/packages/@aws-cdk/aws-iam/lib/grant.ts +++ b/packages/@aws-cdk/aws-iam/lib/grant.ts @@ -98,7 +98,7 @@ export class Grant { * case of imported resources) leads to a warning being added to the * resource construct. */ - public static withResource(options: GrantWithResourceOptions): Grant { + public static onPrincipalOrResource(options: GrantWithResourceOptions): Grant { const result = Grant.onPrincipal({ ...options, scope: options.resource diff --git a/packages/@aws-cdk/aws-iam/lib/imported-resource-role.ts b/packages/@aws-cdk/aws-iam/lib/imported-resource-role.ts deleted file mode 100644 index 48311c8786dbc..0000000000000 --- a/packages/@aws-cdk/aws-iam/lib/imported-resource-role.ts +++ /dev/null @@ -1,45 +0,0 @@ -import cdk = require('@aws-cdk/cdk'); -import { PolicyStatement, PrincipalPolicyFragment } from './policy-document'; -import { IPrincipal } from './principals'; - -/** - * Properties for an ImportedResourcePrincipal - */ -export interface ImportedResourcePrincipalProps { - /** - * The resource the role proxy is for - */ - resource: cdk.IConstruct; -} - -/** - * A principal associated with an imported resource - * - * Some resources have roles associated with them which they assume, such as - * Lambda Functions, CodeBuild projects, StepFunctions machines, etc. - * - * When those resources are imported, their actual roles are not always - * imported with them. When that happens, we use an instance of this class - * instead, which will add user warnings when statements are attempted to be - * added to it. - */ -export class ImportedResourcePrincipal implements IPrincipal { - public readonly assumeRoleAction: string = 'sts:AssumeRole'; - public readonly grantPrincipal: IPrincipal; - private readonly resource: cdk.IConstruct; - - constructor(props: ImportedResourcePrincipalProps) { - this.resource = props.resource; - this.grantPrincipal = this; - } - - public get policyFragment(): PrincipalPolicyFragment { - throw new Error(`Cannot get policy fragment of ${this.resource.node.path}, resource imported without a role`); - } - - public addToPolicy(statement: PolicyStatement): boolean { - const repr = JSON.stringify(this.resource.node.resolve(statement)); - this.resource.node.addWarning(`Add statement to this resource's role: ${repr}`); - return true; // Pretend we did the work. The human will do it for us, eventually. - } -} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda-event-sources/lib/dynamodb.ts b/packages/@aws-cdk/aws-lambda-event-sources/lib/dynamodb.ts index 46678640f36ce..156ceea800db7 100644 --- a/packages/@aws-cdk/aws-lambda-event-sources/lib/dynamodb.ts +++ b/packages/@aws-cdk/aws-lambda-event-sources/lib/dynamodb.ts @@ -37,7 +37,7 @@ export class DynamoEventSource implements lambda.IEventSource { startingPosition: this.props.startingPosition }); - this.table.grantStreamRead(target.role); - dynamodb.Table.grantListStreams(target.role); + this.table.grantStreamRead(target); + dynamodb.Table.grantListStreams(target); } } diff --git a/packages/@aws-cdk/aws-lambda-event-sources/lib/kinesis.ts b/packages/@aws-cdk/aws-lambda-event-sources/lib/kinesis.ts index db015ffcc7cad..5893935ab375b 100644 --- a/packages/@aws-cdk/aws-lambda-event-sources/lib/kinesis.ts +++ b/packages/@aws-cdk/aws-lambda-event-sources/lib/kinesis.ts @@ -37,6 +37,6 @@ export class KinesisEventSource implements lambda.IEventSource { eventSourceArn: this.stream.streamArn, }); - this.stream.grantRead(target.role); + this.stream.grantRead(target); } } \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda-event-sources/lib/sqs.ts b/packages/@aws-cdk/aws-lambda-event-sources/lib/sqs.ts index 5206fce5cae05..d372116fe49f2 100644 --- a/packages/@aws-cdk/aws-lambda-event-sources/lib/sqs.ts +++ b/packages/@aws-cdk/aws-lambda-event-sources/lib/sqs.ts @@ -31,6 +31,6 @@ export class SqsEventSource implements lambda.IEventSource { eventSourceArn: this.queue.queueArn, }); - this.queue.grantConsumeMessages(target.role); + this.queue.grantConsumeMessages(target); } } \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda/lib/alias.ts b/packages/@aws-cdk/aws-lambda/lib/alias.ts index 98fa53ed58c02..9a046e2422e10 100644 --- a/packages/@aws-cdk/aws-lambda/lib/alias.ts +++ b/packages/@aws-cdk/aws-lambda/lib/alias.ts @@ -101,6 +101,10 @@ export class Alias extends FunctionBase { return this.underlyingLambda.role; } + public get grantPrincipal() { + return this.underlyingLambda.grantPrincipal; + } + public metric(metricName: string, props: cloudwatch.MetricCustomization = {}): cloudwatch.Metric { // Metrics on Aliases need the "bare" function name, and the alias' ARN, this differes from the base behavior. return super.metric(metricName, { diff --git a/packages/@aws-cdk/aws-lambda/lib/function-base.ts b/packages/@aws-cdk/aws-lambda/lib/function-base.ts index 6d30cd6afb67b..0f59fc12cd13d 100644 --- a/packages/@aws-cdk/aws-lambda/lib/function-base.ts +++ b/packages/@aws-cdk/aws-lambda/lib/function-base.ts @@ -238,7 +238,7 @@ export abstract class FunctionBase extends cdk.Construct implements IFunction { * Grant the given identity permissions to invoke this Lambda */ public grantInvoke(grantee: iam.IGrantable): iam.Grant { - return iam.Grant.withResource({ + return iam.Grant.onPrincipalOrResource({ grantee, actions: ['lambda:InvokeFunction'], resourceArns: [this.functionArn], diff --git a/packages/@aws-cdk/aws-s3-deployment/lib/bucket-deployment.ts b/packages/@aws-cdk/aws-s3-deployment/lib/bucket-deployment.ts index e3b7b7b9ef7ef..950143b8100ca 100644 --- a/packages/@aws-cdk/aws-s3-deployment/lib/bucket-deployment.ts +++ b/packages/@aws-cdk/aws-s3-deployment/lib/bucket-deployment.ts @@ -54,8 +54,8 @@ export class BucketDeployment extends cdk.Construct { const source = props.source.bind(this); - source.bucket.grantRead(handler.role); - props.destinationBucket.grantReadWrite(handler.role); + source.bucket.grantRead(handler); + props.destinationBucket.grantReadWrite(handler); new cloudformation.CustomResource(this, 'CustomResource', { lambdaProvider: handler, diff --git a/packages/@aws-cdk/aws-s3/lib/bucket.ts b/packages/@aws-cdk/aws-s3/lib/bucket.ts index 0511c54c48893..11d9e14346ade 100644 --- a/packages/@aws-cdk/aws-s3/lib/bucket.ts +++ b/packages/@aws-cdk/aws-s3/lib/bucket.ts @@ -471,7 +471,7 @@ export abstract class BucketBase extends cdk.Construct implements IBucket { allowedActions = allowedActions.length > 0 ? allowedActions : [ 's3:GetObject' ]; - return iam.Grant.withResource({ + return iam.Grant.onPrincipalOrResource({ actions: allowedActions, resourceArns: [this.arnForObjects(keyPrefix)], grantee: new iam.Anyone(), @@ -485,7 +485,7 @@ export abstract class BucketBase extends cdk.Construct implements IBucket { resourceArn: string, ...otherResourceArns: string[]) { const resources = [ resourceArn, ...otherResourceArns ]; - const ret = iam.Grant.withResource({ + const ret = iam.Grant.onPrincipalOrResource({ grantee, actions: bucketActions, resourceArns: resources, diff --git a/packages/@aws-cdk/aws-sns/lib/topic-base.ts b/packages/@aws-cdk/aws-sns/lib/topic-base.ts index 06e73bf8227e3..b044491c7d69b 100644 --- a/packages/@aws-cdk/aws-sns/lib/topic-base.ts +++ b/packages/@aws-cdk/aws-sns/lib/topic-base.ts @@ -270,9 +270,9 @@ export abstract class TopicBase extends cdk.Construct implements ITopic { /** * Grant topic publishing permissions to the given identity */ - public grantPublish(principal: iam.IGrantable) { - return iam.Grant.withResource({ - principal, + public grantPublish(grantee: iam.IGrantable) { + return iam.Grant.onPrincipalOrResource({ + grantee, actions: ['sns:Publish'], resourceArns: [this.topicArn], resource: this, diff --git a/packages/@aws-cdk/aws-sqs/lib/queue-base.ts b/packages/@aws-cdk/aws-sqs/lib/queue-base.ts index 42dfef6bbff05..00547b385aa84 100644 --- a/packages/@aws-cdk/aws-sqs/lib/queue-base.ts +++ b/packages/@aws-cdk/aws-sqs/lib/queue-base.ts @@ -274,7 +274,7 @@ export abstract class QueueBase extends cdk.Construct implements IQueue { * @param actions The actions to grant */ public grant(grantee: iam.IGrantable, ...actions: string[]) { - return iam.Grant.withResource({ + return iam.Grant.onPrincipalOrResource({ grantee, actions, resourceArns: [this.queueArn], diff --git a/packages/@aws-cdk/aws-ssm/lib/parameter.ts b/packages/@aws-cdk/aws-ssm/lib/parameter.ts index 4980611161262..992bc66e8f3ca 100644 --- a/packages/@aws-cdk/aws-ssm/lib/parameter.ts +++ b/packages/@aws-cdk/aws-ssm/lib/parameter.ts @@ -124,18 +124,20 @@ export abstract class ParameterBase extends cdk.Construct implements IParameter }); } - public grantRead(grantee: iam.IGrantable): void { - grantee.addToPolicy(new iam.PolicyStatement() - .allow() - .addActions('ssm:DescribeParameters', 'ssm:GetParameter', 'ssm:GetParameterHistory') - .addResource(this.parameterArn)); + public grantRead(grantee: iam.IGrantable): iam.Grant { + return iam.Grant.onPrincipal({ + grantee, + actions: ['ssm:DescribeParameters', 'ssm:GetParameter', 'ssm:GetParameterHistory'], + resourceArns: [this.parameterArn], + }); } - public grantWrite(grantee: iam.IGrantable): void { - grantee.addToPolicy(new iam.PolicyStatement() - .allow() - .addAction('ssm:PutParameter') - .addResource(this.parameterArn)); + public grantWrite(grantee: iam.IGrantable): iam.Grant { + return iam.Grant.onPrincipal({ + grantee, + actions: ['ssm:PutParameter'], + resourceArns: [this.parameterArn], + }); } } diff --git a/packages/@aws-cdk/runtime-values/lib/rtv.ts b/packages/@aws-cdk/runtime-values/lib/rtv.ts index 0b2829511fe38..0f349e4ec2f73 100644 --- a/packages/@aws-cdk/runtime-values/lib/rtv.ts +++ b/packages/@aws-cdk/runtime-values/lib/rtv.ts @@ -74,15 +74,12 @@ export class RuntimeValue extends cdk.Construct { * Grants a principal read permissions on this runtime value. * @param principal The principal (e.g. Role, User, Group) */ - public grantRead(principal: iam.IGrantable) { + public grantRead(grantee: iam.IGrantable) { + return iam.Grant.onPrincipal({ + grantee, + resourceArns: [this.parameterArn], + actions: RuntimeValue.SSM_READ_ACTIONS - // sometimes "role" is optional, so we want `rtv.grantRead(role)` to be a no-op - if (!principal) { - return; - } - - principal.addToPolicy(new iam.PolicyStatement() - .addResource(this.parameterArn) - .addActions(...RuntimeValue.SSM_READ_ACTIONS)); + }); } } diff --git a/packages/@aws-cdk/runtime-values/test/integ.rtv.lambda.ts b/packages/@aws-cdk/runtime-values/test/integ.rtv.lambda.ts index 81e8b7d4d48f6..0c45cf9b4eb33 100644 --- a/packages/@aws-cdk/runtime-values/test/integ.rtv.lambda.ts +++ b/packages/@aws-cdk/runtime-values/test/integ.rtv.lambda.ts @@ -27,7 +27,7 @@ class TestStack extends cdk.Stack { // this line adds read permissions for this SSM parameter to the policies associated with // the IAM roles of the Lambda function and the EC2 fleet - queueUrlRtv.grantRead(fn.role); + queueUrlRtv.grantRead(fn); // adds the `RTV_STACK_NAME` to the environment of the lambda function // and the fleet (via user-data) From 71964e79719a592061d0a568ad3cd89ca9a49f9b Mon Sep 17 00:00:00 2001 From: Rico Huijbers Date: Wed, 3 Apr 2019 14:07:42 +0200 Subject: [PATCH 27/31] Rename grant methods to be more explicit --- packages/@aws-cdk/aws-cloudwatch/lib/metric.ts | 2 +- .../aws-codedeploy/lib/lambda/deployment-group.ts | 2 +- packages/@aws-cdk/aws-dynamodb/lib/table.ts | 6 +++--- packages/@aws-cdk/aws-ecr/lib/repository-ref.ts | 4 ++-- packages/@aws-cdk/aws-glue/lib/table.ts | 2 +- packages/@aws-cdk/aws-iam/lib/grant.ts | 10 +++++----- packages/@aws-cdk/aws-iam/lib/role.ts | 4 ++-- packages/@aws-cdk/aws-kinesis/lib/stream.ts | 2 +- packages/@aws-cdk/aws-kms/lib/key.ts | 2 +- packages/@aws-cdk/aws-lambda/lib/function-base.ts | 2 +- packages/@aws-cdk/aws-s3/lib/bucket.ts | 4 ++-- packages/@aws-cdk/aws-secretsmanager/lib/secret.ts | 2 +- packages/@aws-cdk/aws-sns/lib/topic-base.ts | 2 +- packages/@aws-cdk/aws-sqs/lib/queue-base.ts | 2 +- packages/@aws-cdk/aws-ssm/lib/parameter.ts | 4 ++-- packages/@aws-cdk/runtime-values/lib/rtv.ts | 2 +- 16 files changed, 26 insertions(+), 26 deletions(-) diff --git a/packages/@aws-cdk/aws-cloudwatch/lib/metric.ts b/packages/@aws-cdk/aws-cloudwatch/lib/metric.ts index 75c2160e1fa5a..08e401470e925 100644 --- a/packages/@aws-cdk/aws-cloudwatch/lib/metric.ts +++ b/packages/@aws-cdk/aws-cloudwatch/lib/metric.ts @@ -88,7 +88,7 @@ export class Metric { * @param grantee The IAM identity to give permissions to. */ public static grantPutMetricData(grantee: iam.IGrantable): iam.Grant { - return iam.Grant.onPrincipal({ + return iam.Grant.addToPrincipal({ grantee, actions: ['cloudwatch:PutMetricData'], resourceArns: ['*'] diff --git a/packages/@aws-cdk/aws-codedeploy/lib/lambda/deployment-group.ts b/packages/@aws-cdk/aws-codedeploy/lib/lambda/deployment-group.ts index 5f5f2e7295042..e661ad5bd5b2c 100644 --- a/packages/@aws-cdk/aws-codedeploy/lib/lambda/deployment-group.ts +++ b/packages/@aws-cdk/aws-codedeploy/lib/lambda/deployment-group.ts @@ -218,7 +218,7 @@ export class LambdaDeploymentGroup extends cdk.Construct implements ILambdaDeplo * @param principal to grant permission to */ public grantPutLifecycleEventHookExecutionStatus(grantee: iam.IGrantable): iam.Grant { - return iam.Grant.onPrincipal({ + return iam.Grant.addToPrincipal({ grantee, resourceArns: [this.deploymentGroupArn], actions: ['codedeploy:PutLifecycleEventHookExecutionStatus'], diff --git a/packages/@aws-cdk/aws-dynamodb/lib/table.ts b/packages/@aws-cdk/aws-dynamodb/lib/table.ts index 9731d92928977..48e6518954020 100644 --- a/packages/@aws-cdk/aws-dynamodb/lib/table.ts +++ b/packages/@aws-cdk/aws-dynamodb/lib/table.ts @@ -179,7 +179,7 @@ export class Table extends Construct { * @param grantee The principal (no-op if undefined) */ public static grantListStreams(grantee: iam.IGrantable): iam.Grant { - return iam.Grant.onPrincipal({ + return iam.Grant.addToPrincipal({ grantee, actions: ['dynamodb:ListStreams'], resourceArns: ['*'], @@ -408,7 +408,7 @@ export class Table extends Construct { * @param actions The set of actions to allow (i.e. "dynamodb:PutItem", "dynamodb:GetItem", ...) */ public grant(grantee: iam.IGrantable, ...actions: string[]): iam.Grant { - return iam.Grant.onPrincipal({ + return iam.Grant.addToPrincipal({ grantee, actions, resourceArns: [ @@ -426,7 +426,7 @@ export class Table extends Construct { * @param actions The set of actions to allow (i.e. "dynamodb:DescribeStream", "dynamodb:GetRecords", ...) */ public grantStream(grantee: iam.IGrantable, ...actions: string[]) { - return iam.Grant.onPrincipal({ + return iam.Grant.addToPrincipal({ grantee, actions, resourceArns: [this.tableStreamArn], diff --git a/packages/@aws-cdk/aws-ecr/lib/repository-ref.ts b/packages/@aws-cdk/aws-ecr/lib/repository-ref.ts index 30fe2ab2691cf..ed3c7685826b6 100644 --- a/packages/@aws-cdk/aws-ecr/lib/repository-ref.ts +++ b/packages/@aws-cdk/aws-ecr/lib/repository-ref.ts @@ -190,7 +190,7 @@ export abstract class RepositoryBase extends cdk.Construct implements IRepositor * Grant the given principal identity permissions to perform the actions on this repository */ public grant(grantee: iam.IGrantable, ...actions: string[]) { - return iam.Grant.onPrincipalOrResource({ + return iam.Grant.addToPrincipalOrResource({ grantee, actions, resourceArns: [this.repositoryArn], @@ -204,7 +204,7 @@ export abstract class RepositoryBase extends cdk.Construct implements IRepositor public grantPull(grantee: iam.IGrantable) { const ret = this.grant(grantee, "ecr:BatchCheckLayerAvailability", "ecr:GetDownloadUrlForLayer", "ecr:BatchGetImage"); - iam.Grant.onPrincipal({ + iam.Grant.addToPrincipal({ grantee, actions: ["ecr:GetAuthorizationToken"], resourceArns: ['*'], diff --git a/packages/@aws-cdk/aws-glue/lib/table.ts b/packages/@aws-cdk/aws-glue/lib/table.ts index 6fd1d60a2c88e..266e4d185d929 100644 --- a/packages/@aws-cdk/aws-glue/lib/table.ts +++ b/packages/@aws-cdk/aws-glue/lib/table.ts @@ -298,7 +298,7 @@ export class Table extends cdk.Construct implements ITable { } private grant(grantee: iam.IGrantable, actions: string[]) { - return iam.Grant.onPrincipal({ + return iam.Grant.addToPrincipal({ grantee, resourceArns: [this.tableArn], actions, diff --git a/packages/@aws-cdk/aws-iam/lib/grant.ts b/packages/@aws-cdk/aws-iam/lib/grant.ts index a050479654637..f9eaad56795b7 100644 --- a/packages/@aws-cdk/aws-iam/lib/grant.ts +++ b/packages/@aws-cdk/aws-iam/lib/grant.ts @@ -98,8 +98,8 @@ export class Grant { * case of imported resources) leads to a warning being added to the * resource construct. */ - public static onPrincipalOrResource(options: GrantWithResourceOptions): Grant { - const result = Grant.onPrincipal({ + public static addToPrincipalOrResource(options: GrantWithResourceOptions): Grant { + const result = Grant.addToPrincipal({ ...options, scope: options.resource }); @@ -122,7 +122,7 @@ export class Grant { * Absence of a principal leads to a warning, but failing to add * the permissions to a present principal is not an error. */ - public static onPrincipal(options: GrantOnPrincipalOptions): Grant { + public static addToPrincipal(options: GrantOnPrincipalOptions): Grant { const statement = new PolicyStatement() .addActions(...options.actions) .addResources(...options.resourceArns); @@ -141,8 +141,8 @@ export class Grant { * * Statement will be the resource statement. */ - public static onPrincipalAndResource(options: GrantOnPrincipalAndResourceOptions): Grant { - const result = Grant.onPrincipal({ + public static addToPrincipalAndResource(options: GrantOnPrincipalAndResourceOptions): Grant { + const result = Grant.addToPrincipal({ ...options, scope: options.resource, }); diff --git a/packages/@aws-cdk/aws-iam/lib/role.ts b/packages/@aws-cdk/aws-iam/lib/role.ts index 1e9e160fe77cf..dc20cdbf382d8 100644 --- a/packages/@aws-cdk/aws-iam/lib/role.ts +++ b/packages/@aws-cdk/aws-iam/lib/role.ts @@ -212,7 +212,7 @@ export class Role extends Construct implements IRole { * Grant the actions defined in actions to the identity Principal on this resource. */ public grant(grantee: IPrincipal, ...actions: string[]) { - return Grant.onPrincipal({ + return Grant.addToPrincipal({ grantee, actions, resourceArns: [this.roleArn], @@ -356,7 +356,7 @@ class ImportedRole extends Construct implements IRole { * Grant the actions defined in actions to the identity Principal on this resource. */ public grant(grantee: IPrincipal, ...actions: string[]): Grant { - return Grant.onPrincipal({ + return Grant.addToPrincipal({ grantee, actions, resourceArns: [this.roleArn], diff --git a/packages/@aws-cdk/aws-kinesis/lib/stream.ts b/packages/@aws-cdk/aws-kinesis/lib/stream.ts index 064226f689adc..1e86c62ad84bd 100644 --- a/packages/@aws-cdk/aws-kinesis/lib/stream.ts +++ b/packages/@aws-cdk/aws-kinesis/lib/stream.ts @@ -228,7 +228,7 @@ export abstract class StreamBase extends cdk.Construct implements IStream { } private grant(grantee: iam.IGrantable, ...actions: string[]) { - return iam.Grant.onPrincipal({ + return iam.Grant.addToPrincipal({ grantee, actions, resourceArns: [this.streamArn], diff --git a/packages/@aws-cdk/aws-kms/lib/key.ts b/packages/@aws-cdk/aws-kms/lib/key.ts index 65db50e30bb8b..cf4c7584c061c 100644 --- a/packages/@aws-cdk/aws-kms/lib/key.ts +++ b/packages/@aws-cdk/aws-kms/lib/key.ts @@ -105,7 +105,7 @@ export abstract class EncryptionKeyBase extends Construct implements IEncryption * must not be empty and so default grants won't work. */ public grant(grantee: iam.IGrantable, ...actions: string[]): iam.Grant { - return iam.Grant.onPrincipalAndResource({ + return iam.Grant.addToPrincipalAndResource({ grantee, actions, resourceArns: [this.keyArn], diff --git a/packages/@aws-cdk/aws-lambda/lib/function-base.ts b/packages/@aws-cdk/aws-lambda/lib/function-base.ts index 0f59fc12cd13d..23a0ea7cf82d4 100644 --- a/packages/@aws-cdk/aws-lambda/lib/function-base.ts +++ b/packages/@aws-cdk/aws-lambda/lib/function-base.ts @@ -238,7 +238,7 @@ export abstract class FunctionBase extends cdk.Construct implements IFunction { * Grant the given identity permissions to invoke this Lambda */ public grantInvoke(grantee: iam.IGrantable): iam.Grant { - return iam.Grant.onPrincipalOrResource({ + return iam.Grant.addToPrincipalOrResource({ grantee, actions: ['lambda:InvokeFunction'], resourceArns: [this.functionArn], diff --git a/packages/@aws-cdk/aws-s3/lib/bucket.ts b/packages/@aws-cdk/aws-s3/lib/bucket.ts index 11d9e14346ade..5357dbe754dc4 100644 --- a/packages/@aws-cdk/aws-s3/lib/bucket.ts +++ b/packages/@aws-cdk/aws-s3/lib/bucket.ts @@ -471,7 +471,7 @@ export abstract class BucketBase extends cdk.Construct implements IBucket { allowedActions = allowedActions.length > 0 ? allowedActions : [ 's3:GetObject' ]; - return iam.Grant.onPrincipalOrResource({ + return iam.Grant.addToPrincipalOrResource({ actions: allowedActions, resourceArns: [this.arnForObjects(keyPrefix)], grantee: new iam.Anyone(), @@ -485,7 +485,7 @@ export abstract class BucketBase extends cdk.Construct implements IBucket { resourceArn: string, ...otherResourceArns: string[]) { const resources = [ resourceArn, ...otherResourceArns ]; - const ret = iam.Grant.onPrincipalOrResource({ + const ret = iam.Grant.addToPrincipalOrResource({ grantee, actions: bucketActions, resourceArns: resources, diff --git a/packages/@aws-cdk/aws-secretsmanager/lib/secret.ts b/packages/@aws-cdk/aws-secretsmanager/lib/secret.ts index b2727082167f1..74661d1ccc1d2 100644 --- a/packages/@aws-cdk/aws-secretsmanager/lib/secret.ts +++ b/packages/@aws-cdk/aws-secretsmanager/lib/secret.ts @@ -121,7 +121,7 @@ export abstract class SecretBase extends cdk.Construct implements ISecret { public grantRead(grantee: iam.IGrantable, versionStages?: string[]): iam.Grant { // @see https://docs.aws.amazon.com/fr_fr/secretsmanager/latest/userguide/auth-and-access_identity-based-policies.html - const result = iam.Grant.onPrincipal({ + const result = iam.Grant.addToPrincipal({ grantee, actions: ['secretsmanager:GetSecretValue'], resourceArns: [this.secretArn], diff --git a/packages/@aws-cdk/aws-sns/lib/topic-base.ts b/packages/@aws-cdk/aws-sns/lib/topic-base.ts index b044491c7d69b..f455cb8648dcb 100644 --- a/packages/@aws-cdk/aws-sns/lib/topic-base.ts +++ b/packages/@aws-cdk/aws-sns/lib/topic-base.ts @@ -271,7 +271,7 @@ export abstract class TopicBase extends cdk.Construct implements ITopic { * Grant topic publishing permissions to the given identity */ public grantPublish(grantee: iam.IGrantable) { - return iam.Grant.onPrincipalOrResource({ + return iam.Grant.addToPrincipalOrResource({ grantee, actions: ['sns:Publish'], resourceArns: [this.topicArn], diff --git a/packages/@aws-cdk/aws-sqs/lib/queue-base.ts b/packages/@aws-cdk/aws-sqs/lib/queue-base.ts index 00547b385aa84..1a281b5691fdd 100644 --- a/packages/@aws-cdk/aws-sqs/lib/queue-base.ts +++ b/packages/@aws-cdk/aws-sqs/lib/queue-base.ts @@ -274,7 +274,7 @@ export abstract class QueueBase extends cdk.Construct implements IQueue { * @param actions The actions to grant */ public grant(grantee: iam.IGrantable, ...actions: string[]) { - return iam.Grant.onPrincipalOrResource({ + return iam.Grant.addToPrincipalOrResource({ grantee, actions, resourceArns: [this.queueArn], diff --git a/packages/@aws-cdk/aws-ssm/lib/parameter.ts b/packages/@aws-cdk/aws-ssm/lib/parameter.ts index 992bc66e8f3ca..88411d307a1cf 100644 --- a/packages/@aws-cdk/aws-ssm/lib/parameter.ts +++ b/packages/@aws-cdk/aws-ssm/lib/parameter.ts @@ -125,7 +125,7 @@ export abstract class ParameterBase extends cdk.Construct implements IParameter } public grantRead(grantee: iam.IGrantable): iam.Grant { - return iam.Grant.onPrincipal({ + return iam.Grant.addToPrincipal({ grantee, actions: ['ssm:DescribeParameters', 'ssm:GetParameter', 'ssm:GetParameterHistory'], resourceArns: [this.parameterArn], @@ -133,7 +133,7 @@ export abstract class ParameterBase extends cdk.Construct implements IParameter } public grantWrite(grantee: iam.IGrantable): iam.Grant { - return iam.Grant.onPrincipal({ + return iam.Grant.addToPrincipal({ grantee, actions: ['ssm:PutParameter'], resourceArns: [this.parameterArn], diff --git a/packages/@aws-cdk/runtime-values/lib/rtv.ts b/packages/@aws-cdk/runtime-values/lib/rtv.ts index 0f349e4ec2f73..ac60a15dc3a81 100644 --- a/packages/@aws-cdk/runtime-values/lib/rtv.ts +++ b/packages/@aws-cdk/runtime-values/lib/rtv.ts @@ -75,7 +75,7 @@ export class RuntimeValue extends cdk.Construct { * @param principal The principal (e.g. Role, User, Group) */ public grantRead(grantee: iam.IGrantable) { - return iam.Grant.onPrincipal({ + return iam.Grant.addToPrincipal({ grantee, resourceArns: [this.parameterArn], actions: RuntimeValue.SSM_READ_ACTIONS From 361a92eb2d278c9620f1fe6774d5adb75fa88a7b Mon Sep 17 00:00:00 2001 From: Rico Huijbers Date: Wed, 3 Apr 2019 14:10:29 +0200 Subject: [PATCH 28/31] Remove dynamodb global --- packages/@aws-cdk/aws-dynamodb-global/.nycrc | 1 - .../lib/aws-dynamodb-global.d.ts | 98 --- .../lib/aws-dynamodb-global.js | 32 - .../lib/dynamodb.generated.d.ts | 279 ------- .../lib/dynamodb.generated.js | 455 ------------ .../lib/dynamodb.generated.ts | 702 ------------------ .../aws-dynamodb-global/lib/index.d.ts | 3 - .../@aws-cdk/aws-dynamodb-global/lib/index.js | 9 - .../lib/lambda-global-dynamodb.d.ts | 23 - .../lib/lambda-global-dynamodb.js | 46 -- .../lib/multi-dynamodb-stack.d.ts | 13 - .../lib/multi-dynamodb-stack.js | 15 - .../test/integ.dynamodb.global.d.ts | 1 - .../test/integ.dynamodb.global.js | 21 - .../test/test.dynamodb.global.d.ts | 7 - .../test/test.dynamodb.global.js | 36 - .../aws-dynamodb-global/tsconfig.json | 46 -- 17 files changed, 1787 deletions(-) delete mode 120000 packages/@aws-cdk/aws-dynamodb-global/.nycrc delete mode 100644 packages/@aws-cdk/aws-dynamodb-global/lib/aws-dynamodb-global.d.ts delete mode 100644 packages/@aws-cdk/aws-dynamodb-global/lib/aws-dynamodb-global.js delete mode 100644 packages/@aws-cdk/aws-dynamodb-global/lib/dynamodb.generated.d.ts delete mode 100644 packages/@aws-cdk/aws-dynamodb-global/lib/dynamodb.generated.js delete mode 100644 packages/@aws-cdk/aws-dynamodb-global/lib/dynamodb.generated.ts delete mode 100644 packages/@aws-cdk/aws-dynamodb-global/lib/index.d.ts delete mode 100644 packages/@aws-cdk/aws-dynamodb-global/lib/index.js delete mode 100644 packages/@aws-cdk/aws-dynamodb-global/lib/lambda-global-dynamodb.d.ts delete mode 100644 packages/@aws-cdk/aws-dynamodb-global/lib/lambda-global-dynamodb.js delete mode 100644 packages/@aws-cdk/aws-dynamodb-global/lib/multi-dynamodb-stack.d.ts delete mode 100644 packages/@aws-cdk/aws-dynamodb-global/lib/multi-dynamodb-stack.js delete mode 100644 packages/@aws-cdk/aws-dynamodb-global/test/integ.dynamodb.global.d.ts delete mode 100644 packages/@aws-cdk/aws-dynamodb-global/test/integ.dynamodb.global.js delete mode 100644 packages/@aws-cdk/aws-dynamodb-global/test/test.dynamodb.global.d.ts delete mode 100644 packages/@aws-cdk/aws-dynamodb-global/test/test.dynamodb.global.js delete mode 100644 packages/@aws-cdk/aws-dynamodb-global/tsconfig.json diff --git a/packages/@aws-cdk/aws-dynamodb-global/.nycrc b/packages/@aws-cdk/aws-dynamodb-global/.nycrc deleted file mode 120000 index 7a2684a2c4ebc..0000000000000 --- a/packages/@aws-cdk/aws-dynamodb-global/.nycrc +++ /dev/null @@ -1 +0,0 @@ -/Users/huijbers/Workspaces/PublicCDK/aws-cdk/tools/cdk-build-tools/config/nycrc \ No newline at end of file diff --git a/packages/@aws-cdk/aws-dynamodb-global/lib/aws-dynamodb-global.d.ts b/packages/@aws-cdk/aws-dynamodb-global/lib/aws-dynamodb-global.d.ts deleted file mode 100644 index 43981bd156e3d..0000000000000 --- a/packages/@aws-cdk/aws-dynamodb-global/lib/aws-dynamodb-global.d.ts +++ /dev/null @@ -1,98 +0,0 @@ -import dynamodb = require("@aws-cdk/aws-dynamodb"); -import cdk = require("@aws-cdk/cdk"); -import { LambdaGlobalDynamoDBMaker } from "./lambda-global-dynamodb"; -import { MultiDynamoDBStack } from "./multi-dynamodb-stack"; -/** - * NOTE: These props should match dynamodb.TableProps exactly - * EXCEPT for tableName is now required (for global tables to work, the - * table name must match across regions) - */ -export interface GlobalDynamoDBProps { - /** - * Partition key attribute definition. - */ - partitionKey: dynamodb.Attribute; - /** - * Table sort key attribute definition. - * - * @default no sort key - */ - sortKey?: dynamodb.Attribute; - /** - * The read capacity for the table. Careful if you add Global Secondary Indexes, as - * those will share the table's provisioned throughput. - * - * Can only be provided if billingMode is Provisioned. - * - * @default 5 - */ - readCapacity?: number; - /** - * The write capacity for the table. Careful if you add Global Secondary Indexes, as - * those will share the table's provisioned throughput. - * - * Can only be provided if billingMode is Provisioned. - * - * @default 5 - */ - writeCapacity?: number; - /** - * Specify how you are charged for read and write throughput and how you manage capacity. - * @default Provisioned - */ - billingMode?: dynamodb.BillingMode; - /** - * Enforces a particular physical table name. - * @default - */ - tableName: string; - /** - * Whether point-in-time recovery is enabled. - * @default undefined, point-in-time recovery is disabled - */ - pitrEnabled?: boolean; - /** - * Whether server-side encryption with an AWS managed customer master key is enabled. - * @default undefined, server-side encryption is enabled with an AWS owned customer master key - */ - sseEnabled?: boolean; - /** - * When an item in the table is modified, StreamViewType determines what information - * is written to the stream for this table. Valid values for StreamViewType are: - * @default dynamodb.StreamViewType.NewAndOldImages, streams must be enabled - */ - streamSpecification?: dynamodb.StreamViewType; - /** - * The name of TTL attribute. - * @default undefined, TTL is disabled - */ - ttlAttributeName?: string; -} -/** - * Properties for the mutliple DynamoDB tables to mash together into a - * global table - */ -export interface DynamoDBGlobalStackProps extends cdk.StackProps { - /** - * Properties for DynamoDB Tables - * All the properties must be exactly the same - * to make the tables mesh together as a global table - */ - dynamoProps: GlobalDynamoDBProps; - /** - * Array of environments to create DynamoDB tables in - * Accounts should be omitted, or at least all identical - */ - regions: string[]; -} -export declare class GlobalTable extends cdk.Construct { - /** - * Creates dynamoDB tables across regions that will be able to be globbed together into a global table - */ - tables: MultiDynamoDBStack[]; - /** - * Creates the cloudformation custom resource that launches a lambda to tie it all together - */ - lambdaGlobalDynamodbMaker: LambdaGlobalDynamoDBMaker; - constructor(scope: cdk.Construct, id: string, props: DynamoDBGlobalStackProps); -} diff --git a/packages/@aws-cdk/aws-dynamodb-global/lib/aws-dynamodb-global.js b/packages/@aws-cdk/aws-dynamodb-global/lib/aws-dynamodb-global.js deleted file mode 100644 index 599ffc59a72c5..0000000000000 --- a/packages/@aws-cdk/aws-dynamodb-global/lib/aws-dynamodb-global.js +++ /dev/null @@ -1,32 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -const dynamodb = require("@aws-cdk/aws-dynamodb"); -const cdk = require("@aws-cdk/cdk"); -const lambda_global_dynamodb_1 = require("./lambda-global-dynamodb"); -const multi_dynamodb_stack_1 = require("./multi-dynamodb-stack"); -class GlobalTable extends cdk.Construct { - constructor(scope, id, props) { - super(scope, id); - this.tables = []; - // Need to set this streamSpecification here, otherwise global tables don't work - // And no way to set a default value in an interface - props.dynamoProps.streamSpecification = dynamodb.StreamViewType.NewAndOldImages; - for (const reg of props.regions) { - this.tables.push(new multi_dynamodb_stack_1.MultiDynamoDBStack(scope, id + "-GlobalDynamodbTable-" + reg, { - dynamoProps: props.dynamoProps, - // Purposefully omitting account since not possible to deploy global dynamodDB tables across accounts - env: { - region: reg - }, - // The DynamoDB Stack doesn't need to know the other environments involved - regions: [] - })); - } - this.lambdaGlobalDynamodbMaker = new lambda_global_dynamodb_1.LambdaGlobalDynamoDBMaker(scope, id + "-GlobalDynamodbCustomResource", props); - for (const table of this.tables) { - this.lambdaGlobalDynamodbMaker.customResource.node.addDependency(table); - } - } -} -exports.GlobalTable = GlobalTable; -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXdzLWR5bmFtb2RiLWdsb2JhbC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImF3cy1keW5hbW9kYi1nbG9iYWwudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFBQSxrREFBbUQ7QUFDbkQsb0NBQXFDO0FBQ3JDLHFFQUFxRTtBQUNyRSxpRUFBNEQ7QUF3RjVELE1BQWEsV0FBWSxTQUFRLEdBQUcsQ0FBQyxTQUFTO0lBWTFDLFlBQVksS0FBb0IsRUFBRSxFQUFVLEVBQUUsS0FBK0I7UUFDekUsS0FBSyxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsQ0FBQztRQUNqQixJQUFJLENBQUMsTUFBTSxHQUFHLEVBQUUsQ0FBQztRQUNqQixnRkFBZ0Y7UUFDaEYsb0RBQW9EO1FBQ3BELEtBQUssQ0FBQyxXQUFXLENBQUMsbUJBQW1CLEdBQUcsUUFBUSxDQUFDLGNBQWMsQ0FBQyxlQUFlLENBQUM7UUFDaEYsS0FBSyxNQUFNLEdBQUcsSUFBSSxLQUFLLENBQUMsT0FBTyxFQUFFO1lBQzdCLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLElBQUkseUNBQWtCLENBQUMsS0FBSyxFQUFFLEVBQUUsR0FBRyx1QkFBdUIsR0FBRyxHQUFHLEVBQUU7Z0JBQy9FLFdBQVcsRUFBRSxLQUFLLENBQUMsV0FBVztnQkFDOUIscUdBQXFHO2dCQUNyRyxHQUFHLEVBQUU7b0JBQ0QsTUFBTSxFQUFFLEdBQUc7aUJBQ2Q7Z0JBQ0QsMEVBQTBFO2dCQUMxRSxPQUFPLEVBQUUsRUFBRTthQUNkLENBQUMsQ0FBQyxDQUFDO1NBQ1A7UUFFRCxJQUFJLENBQUMseUJBQXlCLEdBQUcsSUFBSSxrREFBeUIsQ0FBQyxLQUFLLEVBQUUsRUFBRSxHQUFHLCtCQUErQixFQUFFLEtBQUssQ0FBQyxDQUFDO1FBQ25ILEtBQUssTUFBTSxLQUFLLElBQUksSUFBSSxDQUFDLE1BQU0sRUFBRTtZQUM3QixJQUFJLENBQUMseUJBQXlCLENBQUMsY0FBYyxDQUFDLElBQUksQ0FBQyxhQUFhLENBQUMsS0FBSyxDQUFDLENBQUM7U0FDM0U7SUFDTCxDQUFDO0NBQ0o7QUFuQ0Qsa0NBbUNDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IGR5bmFtb2RiID0gcmVxdWlyZShcIkBhd3MtY2RrL2F3cy1keW5hbW9kYlwiKTtcbmltcG9ydCBjZGsgPSByZXF1aXJlKFwiQGF3cy1jZGsvY2RrXCIpO1xuaW1wb3J0IHsgTGFtYmRhR2xvYmFsRHluYW1vREJNYWtlciB9IGZyb20gXCIuL2xhbWJkYS1nbG9iYWwtZHluYW1vZGJcIjtcbmltcG9ydCB7IE11bHRpRHluYW1vREJTdGFjayB9IGZyb20gXCIuL211bHRpLWR5bmFtb2RiLXN0YWNrXCI7XG5cbi8qKlxuICogTk9URTogVGhlc2UgcHJvcHMgc2hvdWxkIG1hdGNoIGR5bmFtb2RiLlRhYmxlUHJvcHMgZXhhY3RseVxuICogRVhDRVBUIGZvciB0YWJsZU5hbWUgaXMgbm93IHJlcXVpcmVkIChmb3IgZ2xvYmFsIHRhYmxlcyB0byB3b3JrLCB0aGVcbiAqIHRhYmxlIG5hbWUgbXVzdCBtYXRjaCBhY3Jvc3MgcmVnaW9ucylcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBHbG9iYWxEeW5hbW9EQlByb3BzIHtcbiAgICAvKipcbiAgICAgKiBQYXJ0aXRpb24ga2V5IGF0dHJpYnV0ZSBkZWZpbml0aW9uLlxuICAgICAqL1xuICAgIHBhcnRpdGlvbktleTogZHluYW1vZGIuQXR0cmlidXRlO1xuICAgIC8qKlxuICAgICAqIFRhYmxlIHNvcnQga2V5IGF0dHJpYnV0ZSBkZWZpbml0aW9uLlxuICAgICAqXG4gICAgICogQGRlZmF1bHQgbm8gc29ydCBrZXlcbiAgICAgKi9cbiAgICBzb3J0S2V5PzogZHluYW1vZGIuQXR0cmlidXRlO1xuICAgIC8qKlxuICAgICAqIFRoZSByZWFkIGNhcGFjaXR5IGZvciB0aGUgdGFibGUuIENhcmVmdWwgaWYgeW91IGFkZCBHbG9iYWwgU2Vjb25kYXJ5IEluZGV4ZXMsIGFzXG4gICAgICogdGhvc2Ugd2lsbCBzaGFyZSB0aGUgdGFibGUncyBwcm92aXNpb25lZCB0aHJvdWdocHV0LlxuICAgICAqXG4gICAgICogQ2FuIG9ubHkgYmUgcHJvdmlkZWQgaWYgYmlsbGluZ01vZGUgaXMgUHJvdmlzaW9uZWQuXG4gICAgICpcbiAgICAgKiBAZGVmYXVsdCA1XG4gICAgICovXG4gICAgcmVhZENhcGFjaXR5PzogbnVtYmVyO1xuICAgIC8qKlxuICAgICAqIFRoZSB3cml0ZSBjYXBhY2l0eSBmb3IgdGhlIHRhYmxlLiBDYXJlZnVsIGlmIHlvdSBhZGQgR2xvYmFsIFNlY29uZGFyeSBJbmRleGVzLCBhc1xuICAgICAqIHRob3NlIHdpbGwgc2hhcmUgdGhlIHRhYmxlJ3MgcHJvdmlzaW9uZWQgdGhyb3VnaHB1dC5cbiAgICAgKlxuICAgICAqIENhbiBvbmx5IGJlIHByb3ZpZGVkIGlmIGJpbGxpbmdNb2RlIGlzIFByb3Zpc2lvbmVkLlxuICAgICAqXG4gICAgICogQGRlZmF1bHQgNVxuICAgICAqL1xuICAgIHdyaXRlQ2FwYWNpdHk/OiBudW1iZXI7XG4gICAgLyoqXG4gICAgICogU3BlY2lmeSBob3cgeW91IGFyZSBjaGFyZ2VkIGZvciByZWFkIGFuZCB3cml0ZSB0aHJvdWdocHV0IGFuZCBob3cgeW91IG1hbmFnZSBjYXBhY2l0eS5cbiAgICAgKiBAZGVmYXVsdCBQcm92aXNpb25lZFxuICAgICAqL1xuICAgIGJpbGxpbmdNb2RlPzogZHluYW1vZGIuQmlsbGluZ01vZGU7XG4gICAgLyoqXG4gICAgICogRW5mb3JjZXMgYSBwYXJ0aWN1bGFyIHBoeXNpY2FsIHRhYmxlIG5hbWUuXG4gICAgICogQGRlZmF1bHQgPGdlbmVyYXRlZD5cbiAgICAgKi9cbiAgICB0YWJsZU5hbWU6IHN0cmluZztcbiAgICAvKipcbiAgICAgKiBXaGV0aGVyIHBvaW50LWluLXRpbWUgcmVjb3ZlcnkgaXMgZW5hYmxlZC5cbiAgICAgKiBAZGVmYXVsdCB1bmRlZmluZWQsIHBvaW50LWluLXRpbWUgcmVjb3ZlcnkgaXMgZGlzYWJsZWRcbiAgICAgKi9cbiAgICBwaXRyRW5hYmxlZD86IGJvb2xlYW47XG4gICAgLyoqXG4gICAgICogV2hldGhlciBzZXJ2ZXItc2lkZSBlbmNyeXB0aW9uIHdpdGggYW4gQVdTIG1hbmFnZWQgY3VzdG9tZXIgbWFzdGVyIGtleSBpcyBlbmFibGVkLlxuICAgICAqIEBkZWZhdWx0IHVuZGVmaW5lZCwgc2VydmVyLXNpZGUgZW5jcnlwdGlvbiBpcyBlbmFibGVkIHdpdGggYW4gQVdTIG93bmVkIGN1c3RvbWVyIG1hc3RlciBrZXlcbiAgICAgKi9cbiAgICBzc2VFbmFibGVkPzogYm9vbGVhbjtcbiAgICAvKipcbiAgICAgKiBXaGVuIGFuIGl0ZW0gaW4gdGhlIHRhYmxlIGlzIG1vZGlmaWVkLCBTdHJlYW1WaWV3VHlwZSBkZXRlcm1pbmVzIHdoYXQgaW5mb3JtYXRpb25cbiAgICAgKiBpcyB3cml0dGVuIHRvIHRoZSBzdHJlYW0gZm9yIHRoaXMgdGFibGUuIFZhbGlkIHZhbHVlcyBmb3IgU3RyZWFtVmlld1R5cGUgYXJlOlxuICAgICAqIEBkZWZhdWx0IGR5bmFtb2RiLlN0cmVhbVZpZXdUeXBlLk5ld0FuZE9sZEltYWdlcywgc3RyZWFtcyBtdXN0IGJlIGVuYWJsZWRcbiAgICAgKi9cbiAgICBzdHJlYW1TcGVjaWZpY2F0aW9uPzogZHluYW1vZGIuU3RyZWFtVmlld1R5cGU7XG4gICAgLyoqXG4gICAgICogVGhlIG5hbWUgb2YgVFRMIGF0dHJpYnV0ZS5cbiAgICAgKiBAZGVmYXVsdCB1bmRlZmluZWQsIFRUTCBpcyBkaXNhYmxlZFxuICAgICAqL1xuICAgIHR0bEF0dHJpYnV0ZU5hbWU/OiBzdHJpbmc7XG59XG5cbi8qKlxuICogUHJvcGVydGllcyBmb3IgdGhlIG11dGxpcGxlIER5bmFtb0RCIHRhYmxlcyB0byBtYXNoIHRvZ2V0aGVyIGludG8gYVxuICogZ2xvYmFsIHRhYmxlXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgRHluYW1vREJHbG9iYWxTdGFja1Byb3BzIGV4dGVuZHMgY2RrLlN0YWNrUHJvcHMge1xuICAgIC8qKlxuICAgICAqIFByb3BlcnRpZXMgZm9yIER5bmFtb0RCIFRhYmxlc1xuICAgICAqIEFsbCB0aGUgcHJvcGVydGllcyBtdXN0IGJlIGV4YWN0bHkgdGhlIHNhbWVcbiAgICAgKiB0byBtYWtlIHRoZSB0YWJsZXMgbWVzaCB0b2dldGhlciBhcyBhIGdsb2JhbCB0YWJsZVxuICAgICAqL1xuICAgIGR5bmFtb1Byb3BzOiBHbG9iYWxEeW5hbW9EQlByb3BzO1xuXG4gICAgLyoqXG4gICAgICogQXJyYXkgb2YgZW52aXJvbm1lbnRzIHRvIGNyZWF0ZSBEeW5hbW9EQiB0YWJsZXMgaW5cbiAgICAgKiBBY2NvdW50cyBzaG91bGQgYmUgb21pdHRlZCwgb3IgYXQgbGVhc3QgYWxsIGlkZW50aWNhbFxuICAgICAqL1xuICAgIHJlZ2lvbnM6IHN0cmluZ1tdO1xufVxuXG5leHBvcnQgY2xhc3MgR2xvYmFsVGFibGUgZXh0ZW5kcyBjZGsuQ29uc3RydWN0IHtcblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgZHluYW1vREIgdGFibGVzIGFjcm9zcyByZWdpb25zIHRoYXQgd2lsbCBiZSBhYmxlIHRvIGJlIGdsb2JiZWQgdG9nZXRoZXIgaW50byBhIGdsb2JhbCB0YWJsZVxuICAgICAqL1xuICAgIHB1YmxpYyB0YWJsZXM6IE11bHRpRHluYW1vREJTdGFja1tdO1xuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyB0aGUgY2xvdWRmb3JtYXRpb24gY3VzdG9tIHJlc291cmNlIHRoYXQgbGF1bmNoZXMgYSBsYW1iZGEgdG8gdGllIGl0IGFsbCB0b2dldGhlclxuICAgICAqL1xuICAgIHB1YmxpYyBsYW1iZGFHbG9iYWxEeW5hbW9kYk1ha2VyOiBMYW1iZGFHbG9iYWxEeW5hbW9EQk1ha2VyO1xuXG4gICAgY29uc3RydWN0b3Ioc2NvcGU6IGNkay5Db25zdHJ1Y3QsIGlkOiBzdHJpbmcsIHByb3BzOiBEeW5hbW9EQkdsb2JhbFN0YWNrUHJvcHMpIHtcbiAgICAgICAgc3VwZXIoc2NvcGUsIGlkKTtcbiAgICAgICAgdGhpcy50YWJsZXMgPSBbXTtcbiAgICAgICAgLy8gTmVlZCB0byBzZXQgdGhpcyBzdHJlYW1TcGVjaWZpY2F0aW9uIGhlcmUsIG90aGVyd2lzZSBnbG9iYWwgdGFibGVzIGRvbid0IHdvcmtcbiAgICAgICAgLy8gQW5kIG5vIHdheSB0byBzZXQgYSBkZWZhdWx0IHZhbHVlIGluIGFuIGludGVyZmFjZVxuICAgICAgICBwcm9wcy5keW5hbW9Qcm9wcy5zdHJlYW1TcGVjaWZpY2F0aW9uID0gZHluYW1vZGIuU3RyZWFtVmlld1R5cGUuTmV3QW5kT2xkSW1hZ2VzO1xuICAgICAgICBmb3IgKGNvbnN0IHJlZyBvZiBwcm9wcy5yZWdpb25zKSB7XG4gICAgICAgICAgICB0aGlzLnRhYmxlcy5wdXNoKG5ldyBNdWx0aUR5bmFtb0RCU3RhY2soc2NvcGUsIGlkICsgXCItR2xvYmFsRHluYW1vZGJUYWJsZS1cIiArIHJlZywge1xuICAgICAgICAgICAgICAgIGR5bmFtb1Byb3BzOiBwcm9wcy5keW5hbW9Qcm9wcyxcbiAgICAgICAgICAgICAgICAvLyBQdXJwb3NlZnVsbHkgb21pdHRpbmcgYWNjb3VudCBzaW5jZSBub3QgcG9zc2libGUgdG8gZGVwbG95IGdsb2JhbCBkeW5hbW9kREIgdGFibGVzIGFjcm9zcyBhY2NvdW50c1xuICAgICAgICAgICAgICAgIGVudjoge1xuICAgICAgICAgICAgICAgICAgICByZWdpb246IHJlZ1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgLy8gVGhlIER5bmFtb0RCIFN0YWNrIGRvZXNuJ3QgbmVlZCB0byBrbm93IHRoZSBvdGhlciBlbnZpcm9ubWVudHMgaW52b2x2ZWRcbiAgICAgICAgICAgICAgICByZWdpb25zOiBbXVxuICAgICAgICAgICAgfSkpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5sYW1iZGFHbG9iYWxEeW5hbW9kYk1ha2VyID0gbmV3IExhbWJkYUdsb2JhbER5bmFtb0RCTWFrZXIoc2NvcGUsIGlkICsgXCItR2xvYmFsRHluYW1vZGJDdXN0b21SZXNvdXJjZVwiLCBwcm9wcyk7XG4gICAgICAgIGZvciAoY29uc3QgdGFibGUgb2YgdGhpcy50YWJsZXMpIHtcbiAgICAgICAgICAgIHRoaXMubGFtYmRhR2xvYmFsRHluYW1vZGJNYWtlci5jdXN0b21SZXNvdXJjZS5ub2RlLmFkZERlcGVuZGVuY3kodGFibGUpO1xuICAgICAgICB9XG4gICAgfVxufVxuIl19 \ No newline at end of file diff --git a/packages/@aws-cdk/aws-dynamodb-global/lib/dynamodb.generated.d.ts b/packages/@aws-cdk/aws-dynamodb-global/lib/dynamodb.generated.d.ts deleted file mode 100644 index e9609e9ffb869..0000000000000 --- a/packages/@aws-cdk/aws-dynamodb-global/lib/dynamodb.generated.d.ts +++ /dev/null @@ -1,279 +0,0 @@ -import cdk = require('@aws-cdk/cdk'); -/** - * Properties for defining a `AWS::DynamoDB::Table` - * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-dynamodb-table.html - */ -export interface CfnTableProps { - /** - * `AWS::DynamoDB::Table.KeySchema` - * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-dynamodb-table.html#cfn-dynamodb-table-keyschema - */ - keySchema: Array | cdk.Token; - /** - * `AWS::DynamoDB::Table.AttributeDefinitions` - * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-dynamodb-table.html#cfn-dynamodb-table-attributedef - */ - attributeDefinitions?: Array | cdk.Token; - /** - * `AWS::DynamoDB::Table.BillingMode` - * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-dynamodb-table.html#cfn-dynamodb-table-billingmode - */ - billingMode?: string; - /** - * `AWS::DynamoDB::Table.GlobalSecondaryIndexes` - * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-dynamodb-table.html#cfn-dynamodb-table-gsi - */ - globalSecondaryIndexes?: Array | cdk.Token; - /** - * `AWS::DynamoDB::Table.LocalSecondaryIndexes` - * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-dynamodb-table.html#cfn-dynamodb-table-lsi - */ - localSecondaryIndexes?: Array | cdk.Token; - /** - * `AWS::DynamoDB::Table.PointInTimeRecoverySpecification` - * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-dynamodb-table.html#cfn-dynamodb-table-pointintimerecoveryspecification - */ - pointInTimeRecoverySpecification?: CfnTable.PointInTimeRecoverySpecificationProperty | cdk.Token; - /** - * `AWS::DynamoDB::Table.ProvisionedThroughput` - * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-dynamodb-table.html#cfn-dynamodb-table-provisionedthroughput - */ - provisionedThroughput?: CfnTable.ProvisionedThroughputProperty | cdk.Token; - /** - * `AWS::DynamoDB::Table.SSESpecification` - * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-dynamodb-table.html#cfn-dynamodb-table-ssespecification - */ - sseSpecification?: CfnTable.SSESpecificationProperty | cdk.Token; - /** - * `AWS::DynamoDB::Table.StreamSpecification` - * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-dynamodb-table.html#cfn-dynamodb-table-streamspecification - */ - streamSpecification?: CfnTable.StreamSpecificationProperty | cdk.Token; - /** - * `AWS::DynamoDB::Table.TableName` - * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-dynamodb-table.html#cfn-dynamodb-table-tablename - */ - tableName?: string; - /** - * `AWS::DynamoDB::Table.Tags` - * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-dynamodb-table.html#cfn-dynamodb-table-tags - */ - tags?: cdk.CfnTag[]; - /** - * `AWS::DynamoDB::Table.TimeToLiveSpecification` - * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-dynamodb-table.html#cfn-dynamodb-table-timetolivespecification - */ - timeToLiveSpecification?: CfnTable.TimeToLiveSpecificationProperty | cdk.Token; -} -/** - * A CloudFormation `AWS::DynamoDB::Table` - * - * @cloudformationResource AWS::DynamoDB::Table - * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-dynamodb-table.html - */ -export declare class CfnTable extends cdk.CfnResource { - /** - * The CloudFormation resource type name for this resource class. - */ - static readonly resourceTypeName = "AWS::DynamoDB::Table"; - /** - * @cloudformationAttribute Arn - */ - readonly tableArn: string; - /** - * @cloudformationAttribute StreamArn - */ - readonly tableStreamArn: string; - readonly tableName: string; - /** - * The `TagManager` handles setting, removing and formatting tags - * - * Tags should be managed either passing them as properties during - * initiation or by calling methods on this object. If both techniques are - * used only the tags from the TagManager will be used. `Tag` (aspect) - * will use the manager. - */ - readonly tags: cdk.TagManager; - /** - * Create a new `AWS::DynamoDB::Table`. - * - * @param scope - scope in which this resource is defined - * @param id - scoped id of the resource - * @param props - resource properties - */ - constructor(scope: cdk.Construct, id: string, props: CfnTableProps); - readonly propertyOverrides: CfnTableProps; - protected renderProperties(properties: any): { - [key: string]: any; - }; -} -export declare namespace CfnTable { - /** - * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-attributedef.html - */ - interface AttributeDefinitionProperty { - /** - * `CfnTable.AttributeDefinitionProperty.AttributeName` - * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-attributedef.html#cfn-dynamodb-attributedef-attributename - */ - attributeName: string; - /** - * `CfnTable.AttributeDefinitionProperty.AttributeType` - * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-attributedef.html#cfn-dynamodb-attributedef-attributename-attributetype - */ - attributeType: string; - } -} -export declare namespace CfnTable { - /** - * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-gsi.html - */ - interface GlobalSecondaryIndexProperty { - /** - * `CfnTable.GlobalSecondaryIndexProperty.IndexName` - * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-gsi.html#cfn-dynamodb-gsi-indexname - */ - indexName: string; - /** - * `CfnTable.GlobalSecondaryIndexProperty.KeySchema` - * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-gsi.html#cfn-dynamodb-gsi-keyschema - */ - keySchema: Array | cdk.Token; - /** - * `CfnTable.GlobalSecondaryIndexProperty.Projection` - * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-gsi.html#cfn-dynamodb-gsi-projection - */ - projection: CfnTable.ProjectionProperty | cdk.Token; - /** - * `CfnTable.GlobalSecondaryIndexProperty.ProvisionedThroughput` - * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-gsi.html#cfn-dynamodb-gsi-provisionedthroughput - */ - provisionedThroughput?: CfnTable.ProvisionedThroughputProperty | cdk.Token; - } -} -export declare namespace CfnTable { - /** - * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-keyschema.html - */ - interface KeySchemaProperty { - /** - * `CfnTable.KeySchemaProperty.AttributeName` - * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-keyschema.html#aws-properties-dynamodb-keyschema-attributename - */ - attributeName: string; - /** - * `CfnTable.KeySchemaProperty.KeyType` - * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-keyschema.html#aws-properties-dynamodb-keyschema-keytype - */ - keyType: string; - } -} -export declare namespace CfnTable { - /** - * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-lsi.html - */ - interface LocalSecondaryIndexProperty { - /** - * `CfnTable.LocalSecondaryIndexProperty.IndexName` - * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-lsi.html#cfn-dynamodb-lsi-indexname - */ - indexName: string; - /** - * `CfnTable.LocalSecondaryIndexProperty.KeySchema` - * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-lsi.html#cfn-dynamodb-lsi-keyschema - */ - keySchema: Array | cdk.Token; - /** - * `CfnTable.LocalSecondaryIndexProperty.Projection` - * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-lsi.html#cfn-dynamodb-lsi-projection - */ - projection: CfnTable.ProjectionProperty | cdk.Token; - } -} -export declare namespace CfnTable { - /** - * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-table-pointintimerecoveryspecification.html - */ - interface PointInTimeRecoverySpecificationProperty { - /** - * `CfnTable.PointInTimeRecoverySpecificationProperty.PointInTimeRecoveryEnabled` - * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-table-pointintimerecoveryspecification.html#cfn-dynamodb-table-pointintimerecoveryspecification-pointintimerecoveryenabled - */ - pointInTimeRecoveryEnabled?: boolean | cdk.Token; - } -} -export declare namespace CfnTable { - /** - * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-projectionobject.html - */ - interface ProjectionProperty { - /** - * `CfnTable.ProjectionProperty.NonKeyAttributes` - * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-projectionobject.html#cfn-dynamodb-projectionobj-nonkeyatt - */ - nonKeyAttributes?: string[]; - /** - * `CfnTable.ProjectionProperty.ProjectionType` - * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-projectionobject.html#cfn-dynamodb-projectionobj-projtype - */ - projectionType?: string; - } -} -export declare namespace CfnTable { - /** - * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-provisionedthroughput.html - */ - interface ProvisionedThroughputProperty { - /** - * `CfnTable.ProvisionedThroughputProperty.ReadCapacityUnits` - * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-provisionedthroughput.html#cfn-dynamodb-provisionedthroughput-readcapacityunits - */ - readCapacityUnits: number | cdk.Token; - /** - * `CfnTable.ProvisionedThroughputProperty.WriteCapacityUnits` - * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-provisionedthroughput.html#cfn-dynamodb-provisionedthroughput-writecapacityunits - */ - writeCapacityUnits: number | cdk.Token; - } -} -export declare namespace CfnTable { - /** - * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-table-ssespecification.html - */ - interface SSESpecificationProperty { - /** - * `CfnTable.SSESpecificationProperty.SSEEnabled` - * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-table-ssespecification.html#cfn-dynamodb-table-ssespecification-sseenabled - */ - sseEnabled: boolean | cdk.Token; - } -} -export declare namespace CfnTable { - /** - * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-streamspecification.html - */ - interface StreamSpecificationProperty { - /** - * `CfnTable.StreamSpecificationProperty.StreamViewType` - * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-streamspecification.html#cfn-dynamodb-streamspecification-streamviewtype - */ - streamViewType: string; - } -} -export declare namespace CfnTable { - /** - * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-timetolivespecification.html - */ - interface TimeToLiveSpecificationProperty { - /** - * `CfnTable.TimeToLiveSpecificationProperty.AttributeName` - * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-timetolivespecification.html#cfn-dynamodb-timetolivespecification-attributename - */ - attributeName: string; - /** - * `CfnTable.TimeToLiveSpecificationProperty.Enabled` - * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-timetolivespecification.html#cfn-dynamodb-timetolivespecification-enabled - */ - enabled: boolean | cdk.Token; - } -} diff --git a/packages/@aws-cdk/aws-dynamodb-global/lib/dynamodb.generated.js b/packages/@aws-cdk/aws-dynamodb-global/lib/dynamodb.generated.js deleted file mode 100644 index d4a6f7690506c..0000000000000 --- a/packages/@aws-cdk/aws-dynamodb-global/lib/dynamodb.generated.js +++ /dev/null @@ -1,455 +0,0 @@ -"use strict"; -// Copyright 2012-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. -// Generated from the AWS CloudFormation Resource Specification -// See: docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/cfn-resource-specification.html -// @cfn2ts:meta@ {"generated":"2019-03-21T16:19:16.881Z","fingerprint":"CPTpE9eD4ImqOKDnu7P0Kaol8j+SXNQUILMR4l/fi2g="} -Object.defineProperty(exports, "__esModule", { value: true }); -// tslint:disable:max-line-length | This is generated code - line lengths are difficult to control -const cdk = require("@aws-cdk/cdk"); -/** - * Determine whether the given properties match those of a `CfnTableProps` - * - * @param properties - the TypeScript properties of a `CfnTableProps` - * - * @returns the result of the validation. - */ -function CfnTablePropsValidator(properties) { - if (!cdk.canInspect(properties)) { - return cdk.VALIDATION_SUCCESS; - } - const errors = new cdk.ValidationResults(); - errors.collect(cdk.propertyValidator('attributeDefinitions', cdk.listValidator(CfnTable_AttributeDefinitionPropertyValidator))(properties.attributeDefinitions)); - errors.collect(cdk.propertyValidator('billingMode', cdk.validateString)(properties.billingMode)); - errors.collect(cdk.propertyValidator('globalSecondaryIndexes', cdk.listValidator(CfnTable_GlobalSecondaryIndexPropertyValidator))(properties.globalSecondaryIndexes)); - errors.collect(cdk.propertyValidator('keySchema', cdk.requiredValidator)(properties.keySchema)); - errors.collect(cdk.propertyValidator('keySchema', cdk.listValidator(CfnTable_KeySchemaPropertyValidator))(properties.keySchema)); - errors.collect(cdk.propertyValidator('localSecondaryIndexes', cdk.listValidator(CfnTable_LocalSecondaryIndexPropertyValidator))(properties.localSecondaryIndexes)); - errors.collect(cdk.propertyValidator('pointInTimeRecoverySpecification', CfnTable_PointInTimeRecoverySpecificationPropertyValidator)(properties.pointInTimeRecoverySpecification)); - errors.collect(cdk.propertyValidator('provisionedThroughput', CfnTable_ProvisionedThroughputPropertyValidator)(properties.provisionedThroughput)); - errors.collect(cdk.propertyValidator('sseSpecification', CfnTable_SSESpecificationPropertyValidator)(properties.sseSpecification)); - errors.collect(cdk.propertyValidator('streamSpecification', CfnTable_StreamSpecificationPropertyValidator)(properties.streamSpecification)); - errors.collect(cdk.propertyValidator('tableName', cdk.validateString)(properties.tableName)); - errors.collect(cdk.propertyValidator('tags', cdk.listValidator(cdk.validateCfnTag))(properties.tags)); - errors.collect(cdk.propertyValidator('timeToLiveSpecification', CfnTable_TimeToLiveSpecificationPropertyValidator)(properties.timeToLiveSpecification)); - return errors.wrap('supplied properties not correct for "CfnTableProps"'); -} -/** - * Renders the AWS CloudFormation properties of an `AWS::DynamoDB::Table` resource - * - * @param properties - the TypeScript properties of a `CfnTableProps` - * - * @returns the AWS CloudFormation properties of an `AWS::DynamoDB::Table` resource. - */ -// @ts-ignore TS6133 -function cfnTablePropsToCloudFormation(properties) { - if (!cdk.canInspect(properties)) { - return properties; - } - CfnTablePropsValidator(properties).assertSuccess(); - return { - KeySchema: cdk.listMapper(cfnTableKeySchemaPropertyToCloudFormation)(properties.keySchema), - AttributeDefinitions: cdk.listMapper(cfnTableAttributeDefinitionPropertyToCloudFormation)(properties.attributeDefinitions), - BillingMode: cdk.stringToCloudFormation(properties.billingMode), - GlobalSecondaryIndexes: cdk.listMapper(cfnTableGlobalSecondaryIndexPropertyToCloudFormation)(properties.globalSecondaryIndexes), - LocalSecondaryIndexes: cdk.listMapper(cfnTableLocalSecondaryIndexPropertyToCloudFormation)(properties.localSecondaryIndexes), - PointInTimeRecoverySpecification: cfnTablePointInTimeRecoverySpecificationPropertyToCloudFormation(properties.pointInTimeRecoverySpecification), - ProvisionedThroughput: cfnTableProvisionedThroughputPropertyToCloudFormation(properties.provisionedThroughput), - SSESpecification: cfnTableSSESpecificationPropertyToCloudFormation(properties.sseSpecification), - StreamSpecification: cfnTableStreamSpecificationPropertyToCloudFormation(properties.streamSpecification), - TableName: cdk.stringToCloudFormation(properties.tableName), - Tags: cdk.listMapper(cdk.cfnTagToCloudFormation)(properties.tags), - TimeToLiveSpecification: cfnTableTimeToLiveSpecificationPropertyToCloudFormation(properties.timeToLiveSpecification), - }; -} -/** - * A CloudFormation `AWS::DynamoDB::Table` - * - * @cloudformationResource AWS::DynamoDB::Table - * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-dynamodb-table.html - */ -class CfnTable extends cdk.CfnResource { - /** - * Create a new `AWS::DynamoDB::Table`. - * - * @param scope - scope in which this resource is defined - * @param id - scoped id of the resource - * @param props - resource properties - */ - constructor(scope, id, props) { - super(scope, id, { type: CfnTable.resourceTypeName, properties: props }); - cdk.requireProperty(props, 'keySchema', this); - this.tableArn = this.getAtt('Arn').toString(); - this.tableStreamArn = this.getAtt('StreamArn').toString(); - this.tableName = this.ref.toString(); - const tags = props === undefined ? undefined : props.tags; - this.tags = new cdk.TagManager(cdk.TagType.Standard, "AWS::DynamoDB::Table", tags); - } - get propertyOverrides() { - return this.untypedPropertyOverrides; - } - renderProperties(properties) { - return cfnTablePropsToCloudFormation(this.node.resolve(properties)); - } -} -/** - * The CloudFormation resource type name for this resource class. - */ -CfnTable.resourceTypeName = "AWS::DynamoDB::Table"; -exports.CfnTable = CfnTable; -/** - * Determine whether the given properties match those of a `AttributeDefinitionProperty` - * - * @param properties - the TypeScript properties of a `AttributeDefinitionProperty` - * - * @returns the result of the validation. - */ -function CfnTable_AttributeDefinitionPropertyValidator(properties) { - if (!cdk.canInspect(properties)) { - return cdk.VALIDATION_SUCCESS; - } - const errors = new cdk.ValidationResults(); - errors.collect(cdk.propertyValidator('attributeName', cdk.requiredValidator)(properties.attributeName)); - errors.collect(cdk.propertyValidator('attributeName', cdk.validateString)(properties.attributeName)); - errors.collect(cdk.propertyValidator('attributeType', cdk.requiredValidator)(properties.attributeType)); - errors.collect(cdk.propertyValidator('attributeType', cdk.validateString)(properties.attributeType)); - return errors.wrap('supplied properties not correct for "AttributeDefinitionProperty"'); -} -/** - * Renders the AWS CloudFormation properties of an `AWS::DynamoDB::Table.AttributeDefinition` resource - * - * @param properties - the TypeScript properties of a `AttributeDefinitionProperty` - * - * @returns the AWS CloudFormation properties of an `AWS::DynamoDB::Table.AttributeDefinition` resource. - */ -// @ts-ignore TS6133 -function cfnTableAttributeDefinitionPropertyToCloudFormation(properties) { - if (!cdk.canInspect(properties)) { - return properties; - } - CfnTable_AttributeDefinitionPropertyValidator(properties).assertSuccess(); - return { - AttributeName: cdk.stringToCloudFormation(properties.attributeName), - AttributeType: cdk.stringToCloudFormation(properties.attributeType), - }; -} -/** - * Determine whether the given properties match those of a `GlobalSecondaryIndexProperty` - * - * @param properties - the TypeScript properties of a `GlobalSecondaryIndexProperty` - * - * @returns the result of the validation. - */ -function CfnTable_GlobalSecondaryIndexPropertyValidator(properties) { - if (!cdk.canInspect(properties)) { - return cdk.VALIDATION_SUCCESS; - } - const errors = new cdk.ValidationResults(); - errors.collect(cdk.propertyValidator('indexName', cdk.requiredValidator)(properties.indexName)); - errors.collect(cdk.propertyValidator('indexName', cdk.validateString)(properties.indexName)); - errors.collect(cdk.propertyValidator('keySchema', cdk.requiredValidator)(properties.keySchema)); - errors.collect(cdk.propertyValidator('keySchema', cdk.listValidator(CfnTable_KeySchemaPropertyValidator))(properties.keySchema)); - errors.collect(cdk.propertyValidator('projection', cdk.requiredValidator)(properties.projection)); - errors.collect(cdk.propertyValidator('projection', CfnTable_ProjectionPropertyValidator)(properties.projection)); - errors.collect(cdk.propertyValidator('provisionedThroughput', CfnTable_ProvisionedThroughputPropertyValidator)(properties.provisionedThroughput)); - return errors.wrap('supplied properties not correct for "GlobalSecondaryIndexProperty"'); -} -/** - * Renders the AWS CloudFormation properties of an `AWS::DynamoDB::Table.GlobalSecondaryIndex` resource - * - * @param properties - the TypeScript properties of a `GlobalSecondaryIndexProperty` - * - * @returns the AWS CloudFormation properties of an `AWS::DynamoDB::Table.GlobalSecondaryIndex` resource. - */ -// @ts-ignore TS6133 -function cfnTableGlobalSecondaryIndexPropertyToCloudFormation(properties) { - if (!cdk.canInspect(properties)) { - return properties; - } - CfnTable_GlobalSecondaryIndexPropertyValidator(properties).assertSuccess(); - return { - IndexName: cdk.stringToCloudFormation(properties.indexName), - KeySchema: cdk.listMapper(cfnTableKeySchemaPropertyToCloudFormation)(properties.keySchema), - Projection: cfnTableProjectionPropertyToCloudFormation(properties.projection), - ProvisionedThroughput: cfnTableProvisionedThroughputPropertyToCloudFormation(properties.provisionedThroughput), - }; -} -/** - * Determine whether the given properties match those of a `KeySchemaProperty` - * - * @param properties - the TypeScript properties of a `KeySchemaProperty` - * - * @returns the result of the validation. - */ -function CfnTable_KeySchemaPropertyValidator(properties) { - if (!cdk.canInspect(properties)) { - return cdk.VALIDATION_SUCCESS; - } - const errors = new cdk.ValidationResults(); - errors.collect(cdk.propertyValidator('attributeName', cdk.requiredValidator)(properties.attributeName)); - errors.collect(cdk.propertyValidator('attributeName', cdk.validateString)(properties.attributeName)); - errors.collect(cdk.propertyValidator('keyType', cdk.requiredValidator)(properties.keyType)); - errors.collect(cdk.propertyValidator('keyType', cdk.validateString)(properties.keyType)); - return errors.wrap('supplied properties not correct for "KeySchemaProperty"'); -} -/** - * Renders the AWS CloudFormation properties of an `AWS::DynamoDB::Table.KeySchema` resource - * - * @param properties - the TypeScript properties of a `KeySchemaProperty` - * - * @returns the AWS CloudFormation properties of an `AWS::DynamoDB::Table.KeySchema` resource. - */ -// @ts-ignore TS6133 -function cfnTableKeySchemaPropertyToCloudFormation(properties) { - if (!cdk.canInspect(properties)) { - return properties; - } - CfnTable_KeySchemaPropertyValidator(properties).assertSuccess(); - return { - AttributeName: cdk.stringToCloudFormation(properties.attributeName), - KeyType: cdk.stringToCloudFormation(properties.keyType), - }; -} -/** - * Determine whether the given properties match those of a `LocalSecondaryIndexProperty` - * - * @param properties - the TypeScript properties of a `LocalSecondaryIndexProperty` - * - * @returns the result of the validation. - */ -function CfnTable_LocalSecondaryIndexPropertyValidator(properties) { - if (!cdk.canInspect(properties)) { - return cdk.VALIDATION_SUCCESS; - } - const errors = new cdk.ValidationResults(); - errors.collect(cdk.propertyValidator('indexName', cdk.requiredValidator)(properties.indexName)); - errors.collect(cdk.propertyValidator('indexName', cdk.validateString)(properties.indexName)); - errors.collect(cdk.propertyValidator('keySchema', cdk.requiredValidator)(properties.keySchema)); - errors.collect(cdk.propertyValidator('keySchema', cdk.listValidator(CfnTable_KeySchemaPropertyValidator))(properties.keySchema)); - errors.collect(cdk.propertyValidator('projection', cdk.requiredValidator)(properties.projection)); - errors.collect(cdk.propertyValidator('projection', CfnTable_ProjectionPropertyValidator)(properties.projection)); - return errors.wrap('supplied properties not correct for "LocalSecondaryIndexProperty"'); -} -/** - * Renders the AWS CloudFormation properties of an `AWS::DynamoDB::Table.LocalSecondaryIndex` resource - * - * @param properties - the TypeScript properties of a `LocalSecondaryIndexProperty` - * - * @returns the AWS CloudFormation properties of an `AWS::DynamoDB::Table.LocalSecondaryIndex` resource. - */ -// @ts-ignore TS6133 -function cfnTableLocalSecondaryIndexPropertyToCloudFormation(properties) { - if (!cdk.canInspect(properties)) { - return properties; - } - CfnTable_LocalSecondaryIndexPropertyValidator(properties).assertSuccess(); - return { - IndexName: cdk.stringToCloudFormation(properties.indexName), - KeySchema: cdk.listMapper(cfnTableKeySchemaPropertyToCloudFormation)(properties.keySchema), - Projection: cfnTableProjectionPropertyToCloudFormation(properties.projection), - }; -} -/** - * Determine whether the given properties match those of a `PointInTimeRecoverySpecificationProperty` - * - * @param properties - the TypeScript properties of a `PointInTimeRecoverySpecificationProperty` - * - * @returns the result of the validation. - */ -function CfnTable_PointInTimeRecoverySpecificationPropertyValidator(properties) { - if (!cdk.canInspect(properties)) { - return cdk.VALIDATION_SUCCESS; - } - const errors = new cdk.ValidationResults(); - errors.collect(cdk.propertyValidator('pointInTimeRecoveryEnabled', cdk.validateBoolean)(properties.pointInTimeRecoveryEnabled)); - return errors.wrap('supplied properties not correct for "PointInTimeRecoverySpecificationProperty"'); -} -/** - * Renders the AWS CloudFormation properties of an `AWS::DynamoDB::Table.PointInTimeRecoverySpecification` resource - * - * @param properties - the TypeScript properties of a `PointInTimeRecoverySpecificationProperty` - * - * @returns the AWS CloudFormation properties of an `AWS::DynamoDB::Table.PointInTimeRecoverySpecification` resource. - */ -// @ts-ignore TS6133 -function cfnTablePointInTimeRecoverySpecificationPropertyToCloudFormation(properties) { - if (!cdk.canInspect(properties)) { - return properties; - } - CfnTable_PointInTimeRecoverySpecificationPropertyValidator(properties).assertSuccess(); - return { - PointInTimeRecoveryEnabled: cdk.booleanToCloudFormation(properties.pointInTimeRecoveryEnabled), - }; -} -/** - * Determine whether the given properties match those of a `ProjectionProperty` - * - * @param properties - the TypeScript properties of a `ProjectionProperty` - * - * @returns the result of the validation. - */ -function CfnTable_ProjectionPropertyValidator(properties) { - if (!cdk.canInspect(properties)) { - return cdk.VALIDATION_SUCCESS; - } - const errors = new cdk.ValidationResults(); - errors.collect(cdk.propertyValidator('nonKeyAttributes', cdk.listValidator(cdk.validateString))(properties.nonKeyAttributes)); - errors.collect(cdk.propertyValidator('projectionType', cdk.validateString)(properties.projectionType)); - return errors.wrap('supplied properties not correct for "ProjectionProperty"'); -} -/** - * Renders the AWS CloudFormation properties of an `AWS::DynamoDB::Table.Projection` resource - * - * @param properties - the TypeScript properties of a `ProjectionProperty` - * - * @returns the AWS CloudFormation properties of an `AWS::DynamoDB::Table.Projection` resource. - */ -// @ts-ignore TS6133 -function cfnTableProjectionPropertyToCloudFormation(properties) { - if (!cdk.canInspect(properties)) { - return properties; - } - CfnTable_ProjectionPropertyValidator(properties).assertSuccess(); - return { - NonKeyAttributes: cdk.listMapper(cdk.stringToCloudFormation)(properties.nonKeyAttributes), - ProjectionType: cdk.stringToCloudFormation(properties.projectionType), - }; -} -/** - * Determine whether the given properties match those of a `ProvisionedThroughputProperty` - * - * @param properties - the TypeScript properties of a `ProvisionedThroughputProperty` - * - * @returns the result of the validation. - */ -function CfnTable_ProvisionedThroughputPropertyValidator(properties) { - if (!cdk.canInspect(properties)) { - return cdk.VALIDATION_SUCCESS; - } - const errors = new cdk.ValidationResults(); - errors.collect(cdk.propertyValidator('readCapacityUnits', cdk.requiredValidator)(properties.readCapacityUnits)); - errors.collect(cdk.propertyValidator('readCapacityUnits', cdk.validateNumber)(properties.readCapacityUnits)); - errors.collect(cdk.propertyValidator('writeCapacityUnits', cdk.requiredValidator)(properties.writeCapacityUnits)); - errors.collect(cdk.propertyValidator('writeCapacityUnits', cdk.validateNumber)(properties.writeCapacityUnits)); - return errors.wrap('supplied properties not correct for "ProvisionedThroughputProperty"'); -} -/** - * Renders the AWS CloudFormation properties of an `AWS::DynamoDB::Table.ProvisionedThroughput` resource - * - * @param properties - the TypeScript properties of a `ProvisionedThroughputProperty` - * - * @returns the AWS CloudFormation properties of an `AWS::DynamoDB::Table.ProvisionedThroughput` resource. - */ -// @ts-ignore TS6133 -function cfnTableProvisionedThroughputPropertyToCloudFormation(properties) { - if (!cdk.canInspect(properties)) { - return properties; - } - CfnTable_ProvisionedThroughputPropertyValidator(properties).assertSuccess(); - return { - ReadCapacityUnits: cdk.numberToCloudFormation(properties.readCapacityUnits), - WriteCapacityUnits: cdk.numberToCloudFormation(properties.writeCapacityUnits), - }; -} -/** - * Determine whether the given properties match those of a `SSESpecificationProperty` - * - * @param properties - the TypeScript properties of a `SSESpecificationProperty` - * - * @returns the result of the validation. - */ -function CfnTable_SSESpecificationPropertyValidator(properties) { - if (!cdk.canInspect(properties)) { - return cdk.VALIDATION_SUCCESS; - } - const errors = new cdk.ValidationResults(); - errors.collect(cdk.propertyValidator('sseEnabled', cdk.requiredValidator)(properties.sseEnabled)); - errors.collect(cdk.propertyValidator('sseEnabled', cdk.validateBoolean)(properties.sseEnabled)); - return errors.wrap('supplied properties not correct for "SSESpecificationProperty"'); -} -/** - * Renders the AWS CloudFormation properties of an `AWS::DynamoDB::Table.SSESpecification` resource - * - * @param properties - the TypeScript properties of a `SSESpecificationProperty` - * - * @returns the AWS CloudFormation properties of an `AWS::DynamoDB::Table.SSESpecification` resource. - */ -// @ts-ignore TS6133 -function cfnTableSSESpecificationPropertyToCloudFormation(properties) { - if (!cdk.canInspect(properties)) { - return properties; - } - CfnTable_SSESpecificationPropertyValidator(properties).assertSuccess(); - return { - SSEEnabled: cdk.booleanToCloudFormation(properties.sseEnabled), - }; -} -/** - * Determine whether the given properties match those of a `StreamSpecificationProperty` - * - * @param properties - the TypeScript properties of a `StreamSpecificationProperty` - * - * @returns the result of the validation. - */ -function CfnTable_StreamSpecificationPropertyValidator(properties) { - if (!cdk.canInspect(properties)) { - return cdk.VALIDATION_SUCCESS; - } - const errors = new cdk.ValidationResults(); - errors.collect(cdk.propertyValidator('streamViewType', cdk.requiredValidator)(properties.streamViewType)); - errors.collect(cdk.propertyValidator('streamViewType', cdk.validateString)(properties.streamViewType)); - return errors.wrap('supplied properties not correct for "StreamSpecificationProperty"'); -} -/** - * Renders the AWS CloudFormation properties of an `AWS::DynamoDB::Table.StreamSpecification` resource - * - * @param properties - the TypeScript properties of a `StreamSpecificationProperty` - * - * @returns the AWS CloudFormation properties of an `AWS::DynamoDB::Table.StreamSpecification` resource. - */ -// @ts-ignore TS6133 -function cfnTableStreamSpecificationPropertyToCloudFormation(properties) { - if (!cdk.canInspect(properties)) { - return properties; - } - CfnTable_StreamSpecificationPropertyValidator(properties).assertSuccess(); - return { - StreamViewType: cdk.stringToCloudFormation(properties.streamViewType), - }; -} -/** - * Determine whether the given properties match those of a `TimeToLiveSpecificationProperty` - * - * @param properties - the TypeScript properties of a `TimeToLiveSpecificationProperty` - * - * @returns the result of the validation. - */ -function CfnTable_TimeToLiveSpecificationPropertyValidator(properties) { - if (!cdk.canInspect(properties)) { - return cdk.VALIDATION_SUCCESS; - } - const errors = new cdk.ValidationResults(); - errors.collect(cdk.propertyValidator('attributeName', cdk.requiredValidator)(properties.attributeName)); - errors.collect(cdk.propertyValidator('attributeName', cdk.validateString)(properties.attributeName)); - errors.collect(cdk.propertyValidator('enabled', cdk.requiredValidator)(properties.enabled)); - errors.collect(cdk.propertyValidator('enabled', cdk.validateBoolean)(properties.enabled)); - return errors.wrap('supplied properties not correct for "TimeToLiveSpecificationProperty"'); -} -/** - * Renders the AWS CloudFormation properties of an `AWS::DynamoDB::Table.TimeToLiveSpecification` resource - * - * @param properties - the TypeScript properties of a `TimeToLiveSpecificationProperty` - * - * @returns the AWS CloudFormation properties of an `AWS::DynamoDB::Table.TimeToLiveSpecification` resource. - */ -// @ts-ignore TS6133 -function cfnTableTimeToLiveSpecificationPropertyToCloudFormation(properties) { - if (!cdk.canInspect(properties)) { - return properties; - } - CfnTable_TimeToLiveSpecificationPropertyValidator(properties).assertSuccess(); - return { - AttributeName: cdk.stringToCloudFormation(properties.attributeName), - Enabled: cdk.booleanToCloudFormation(properties.enabled), - }; -} -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZHluYW1vZGIuZ2VuZXJhdGVkLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiZHluYW1vZGIuZ2VuZXJhdGVkLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQSwrRUFBK0U7QUFDL0UsK0RBQStEO0FBQy9ELDhGQUE4RjtBQUM5RixzSEFBc0g7O0FBRXRILGtHQUFrRztBQUVsRyxvQ0FBcUM7QUFxRXJDOzs7Ozs7R0FNRztBQUNILFNBQVMsc0JBQXNCLENBQUMsVUFBZTtJQUMzQyxJQUFJLENBQUMsR0FBRyxDQUFDLFVBQVUsQ0FBQyxVQUFVLENBQUMsRUFBRTtRQUFFLE9BQU8sR0FBRyxDQUFDLGtCQUFrQixDQUFDO0tBQUU7SUFDbkUsTUFBTSxNQUFNLEdBQUcsSUFBSSxHQUFHLENBQUMsaUJBQWlCLEVBQUUsQ0FBQztJQUMzQyxNQUFNLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxpQkFBaUIsQ0FBQyxzQkFBc0IsRUFBRSxHQUFHLENBQUMsYUFBYSxDQUFDLDZDQUE2QyxDQUFDLENBQUMsQ0FBQyxVQUFVLENBQUMsb0JBQW9CLENBQUMsQ0FBQyxDQUFDO0lBQ2pLLE1BQU0sQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLGlCQUFpQixDQUFDLGFBQWEsRUFBRSxHQUFHLENBQUMsY0FBYyxDQUFDLENBQUMsVUFBVSxDQUFDLFdBQVcsQ0FBQyxDQUFDLENBQUM7SUFDakcsTUFBTSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsaUJBQWlCLENBQUMsd0JBQXdCLEVBQUUsR0FBRyxDQUFDLGFBQWEsQ0FBQyw4Q0FBOEMsQ0FBQyxDQUFDLENBQUMsVUFBVSxDQUFDLHNCQUFzQixDQUFDLENBQUMsQ0FBQztJQUN0SyxNQUFNLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxpQkFBaUIsQ0FBQyxXQUFXLEVBQUUsR0FBRyxDQUFDLGlCQUFpQixDQUFDLENBQUMsVUFBVSxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUM7SUFDaEcsTUFBTSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsaUJBQWlCLENBQUMsV0FBVyxFQUFFLEdBQUcsQ0FBQyxhQUFhLENBQUMsbUNBQW1DLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDO0lBQ2pJLE1BQU0sQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLGlCQUFpQixDQUFDLHVCQUF1QixFQUFFLEdBQUcsQ0FBQyxhQUFhLENBQUMsNkNBQTZDLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxxQkFBcUIsQ0FBQyxDQUFDLENBQUM7SUFDbkssTUFBTSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsaUJBQWlCLENBQUMsa0NBQWtDLEVBQUUsMERBQTBELENBQUMsQ0FBQyxVQUFVLENBQUMsZ0NBQWdDLENBQUMsQ0FBQyxDQUFDO0lBQ25MLE1BQU0sQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLGlCQUFpQixDQUFDLHVCQUF1QixFQUFFLCtDQUErQyxDQUFDLENBQUMsVUFBVSxDQUFDLHFCQUFxQixDQUFDLENBQUMsQ0FBQztJQUNsSixNQUFNLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxpQkFBaUIsQ0FBQyxrQkFBa0IsRUFBRSwwQ0FBMEMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDLENBQUM7SUFDbkksTUFBTSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsaUJBQWlCLENBQUMscUJBQXFCLEVBQUUsNkNBQTZDLENBQUMsQ0FBQyxVQUFVLENBQUMsbUJBQW1CLENBQUMsQ0FBQyxDQUFDO0lBQzVJLE1BQU0sQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLGlCQUFpQixDQUFDLFdBQVcsRUFBRSxHQUFHLENBQUMsY0FBYyxDQUFDLENBQUMsVUFBVSxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUM7SUFDN0YsTUFBTSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsaUJBQWlCLENBQUMsTUFBTSxFQUFFLEdBQUcsQ0FBQyxhQUFhLENBQUMsR0FBRyxDQUFDLGNBQWMsQ0FBQyxDQUFDLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7SUFDdEcsTUFBTSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsaUJBQWlCLENBQUMseUJBQXlCLEVBQUUsaURBQWlELENBQUMsQ0FBQyxVQUFVLENBQUMsdUJBQXVCLENBQUMsQ0FBQyxDQUFDO0lBQ3hKLE9BQU8sTUFBTSxDQUFDLElBQUksQ0FBQyxxREFBcUQsQ0FBQyxDQUFDO0FBQzlFLENBQUM7QUFFRDs7Ozs7O0dBTUc7QUFDSCxvQkFBb0I7QUFDcEIsU0FBUyw2QkFBNkIsQ0FBQyxVQUFlO0lBQ2xELElBQUksQ0FBQyxHQUFHLENBQUMsVUFBVSxDQUFDLFVBQVUsQ0FBQyxFQUFFO1FBQUUsT0FBTyxVQUFVLENBQUM7S0FBRTtJQUN2RCxzQkFBc0IsQ0FBQyxVQUFVLENBQUMsQ0FBQyxhQUFhLEVBQUUsQ0FBQztJQUNuRCxPQUFPO1FBQ0wsU0FBUyxFQUFFLEdBQUcsQ0FBQyxVQUFVLENBQUMseUNBQXlDLENBQUMsQ0FBQyxVQUFVLENBQUMsU0FBUyxDQUFDO1FBQzFGLG9CQUFvQixFQUFFLEdBQUcsQ0FBQyxVQUFVLENBQUMsbURBQW1ELENBQUMsQ0FBQyxVQUFVLENBQUMsb0JBQW9CLENBQUM7UUFDMUgsV0FBVyxFQUFFLEdBQUcsQ0FBQyxzQkFBc0IsQ0FBQyxVQUFVLENBQUMsV0FBVyxDQUFDO1FBQy9ELHNCQUFzQixFQUFFLEdBQUcsQ0FBQyxVQUFVLENBQUMsb0RBQW9ELENBQUMsQ0FBQyxVQUFVLENBQUMsc0JBQXNCLENBQUM7UUFDL0gscUJBQXFCLEVBQUUsR0FBRyxDQUFDLFVBQVUsQ0FBQyxtREFBbUQsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxxQkFBcUIsQ0FBQztRQUM1SCxnQ0FBZ0MsRUFBRSxnRUFBZ0UsQ0FBQyxVQUFVLENBQUMsZ0NBQWdDLENBQUM7UUFDL0kscUJBQXFCLEVBQUUscURBQXFELENBQUMsVUFBVSxDQUFDLHFCQUFxQixDQUFDO1FBQzlHLGdCQUFnQixFQUFFLGdEQUFnRCxDQUFDLFVBQVUsQ0FBQyxnQkFBZ0IsQ0FBQztRQUMvRixtQkFBbUIsRUFBRSxtREFBbUQsQ0FBQyxVQUFVLENBQUMsbUJBQW1CLENBQUM7UUFDeEcsU0FBUyxFQUFFLEdBQUcsQ0FBQyxzQkFBc0IsQ0FBQyxVQUFVLENBQUMsU0FBUyxDQUFDO1FBQzNELElBQUksRUFBRSxHQUFHLENBQUMsVUFBVSxDQUFDLEdBQUcsQ0FBQyxzQkFBc0IsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUM7UUFDakUsdUJBQXVCLEVBQUUsdURBQXVELENBQUMsVUFBVSxDQUFDLHVCQUF1QixDQUFDO0tBQ3JILENBQUM7QUFDTixDQUFDO0FBRUQ7Ozs7O0dBS0c7QUFDSCxNQUFhLFFBQVMsU0FBUSxHQUFHLENBQUMsV0FBVztJQTJCekM7Ozs7OztPQU1HO0lBQ0gsWUFBWSxLQUFvQixFQUFFLEVBQVUsRUFBRSxLQUFvQjtRQUM5RCxLQUFLLENBQUMsS0FBSyxFQUFFLEVBQUUsRUFBRSxFQUFFLElBQUksRUFBRSxRQUFRLENBQUMsZ0JBQWdCLEVBQUUsVUFBVSxFQUFFLEtBQUssRUFBRSxDQUFDLENBQUM7UUFDekUsR0FBRyxDQUFDLGVBQWUsQ0FBQyxLQUFLLEVBQUUsV0FBVyxFQUFFLElBQUksQ0FBQyxDQUFDO1FBQzlDLElBQUksQ0FBQyxRQUFRLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxRQUFRLEVBQUUsQ0FBQztRQUM5QyxJQUFJLENBQUMsY0FBYyxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMsV0FBVyxDQUFDLENBQUMsUUFBUSxFQUFFLENBQUM7UUFDMUQsSUFBSSxDQUFDLFNBQVMsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLFFBQVEsRUFBRSxDQUFDO1FBQ3JDLE1BQU0sSUFBSSxHQUFHLEtBQUssS0FBSyxTQUFTLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQztRQUMxRCxJQUFJLENBQUMsSUFBSSxHQUFHLElBQUksR0FBRyxDQUFDLFVBQVUsQ0FBQyxHQUFHLENBQUMsT0FBTyxDQUFDLFFBQVEsRUFBRSxzQkFBc0IsRUFBRSxJQUFJLENBQUMsQ0FBQztJQUN2RixDQUFDO0lBRUQsSUFBVyxpQkFBaUI7UUFDeEIsT0FBTyxJQUFJLENBQUMsd0JBQXdCLENBQUM7SUFDekMsQ0FBQztJQUNTLGdCQUFnQixDQUFDLFVBQWU7UUFDdEMsT0FBTyw2QkFBNkIsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDO0lBQ3hFLENBQUM7O0FBaEREOztHQUVHO0FBQ29CLHlCQUFnQixHQUFHLHNCQUFzQixDQUFDO0FBSnJFLDRCQWtEQztBQW9CRDs7Ozs7O0dBTUc7QUFDSCxTQUFTLDZDQUE2QyxDQUFDLFVBQWU7SUFDbEUsSUFBSSxDQUFDLEdBQUcsQ0FBQyxVQUFVLENBQUMsVUFBVSxDQUFDLEVBQUU7UUFBRSxPQUFPLEdBQUcsQ0FBQyxrQkFBa0IsQ0FBQztLQUFFO0lBQ25FLE1BQU0sTUFBTSxHQUFHLElBQUksR0FBRyxDQUFDLGlCQUFpQixFQUFFLENBQUM7SUFDM0MsTUFBTSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsaUJBQWlCLENBQUMsZUFBZSxFQUFFLEdBQUcsQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxhQUFhLENBQUMsQ0FBQyxDQUFDO0lBQ3hHLE1BQU0sQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLGlCQUFpQixDQUFDLGVBQWUsRUFBRSxHQUFHLENBQUMsY0FBYyxDQUFDLENBQUMsVUFBVSxDQUFDLGFBQWEsQ0FBQyxDQUFDLENBQUM7SUFDckcsTUFBTSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsaUJBQWlCLENBQUMsZUFBZSxFQUFFLEdBQUcsQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxhQUFhLENBQUMsQ0FBQyxDQUFDO0lBQ3hHLE1BQU0sQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLGlCQUFpQixDQUFDLGVBQWUsRUFBRSxHQUFHLENBQUMsY0FBYyxDQUFDLENBQUMsVUFBVSxDQUFDLGFBQWEsQ0FBQyxDQUFDLENBQUM7SUFDckcsT0FBTyxNQUFNLENBQUMsSUFBSSxDQUFDLG1FQUFtRSxDQUFDLENBQUM7QUFDNUYsQ0FBQztBQUVEOzs7Ozs7R0FNRztBQUNILG9CQUFvQjtBQUNwQixTQUFTLG1EQUFtRCxDQUFDLFVBQWU7SUFDeEUsSUFBSSxDQUFDLEdBQUcsQ0FBQyxVQUFVLENBQUMsVUFBVSxDQUFDLEVBQUU7UUFBRSxPQUFPLFVBQVUsQ0FBQztLQUFFO0lBQ3ZELDZDQUE2QyxDQUFDLFVBQVUsQ0FBQyxDQUFDLGFBQWEsRUFBRSxDQUFDO0lBQzFFLE9BQU87UUFDTCxhQUFhLEVBQUUsR0FBRyxDQUFDLHNCQUFzQixDQUFDLFVBQVUsQ0FBQyxhQUFhLENBQUM7UUFDbkUsYUFBYSxFQUFFLEdBQUcsQ0FBQyxzQkFBc0IsQ0FBQyxVQUFVLENBQUMsYUFBYSxDQUFDO0tBQ3BFLENBQUM7QUFDTixDQUFDO0FBOEJEOzs7Ozs7R0FNRztBQUNILFNBQVMsOENBQThDLENBQUMsVUFBZTtJQUNuRSxJQUFJLENBQUMsR0FBRyxDQUFDLFVBQVUsQ0FBQyxVQUFVLENBQUMsRUFBRTtRQUFFLE9BQU8sR0FBRyxDQUFDLGtCQUFrQixDQUFDO0tBQUU7SUFDbkUsTUFBTSxNQUFNLEdBQUcsSUFBSSxHQUFHLENBQUMsaUJBQWlCLEVBQUUsQ0FBQztJQUMzQyxNQUFNLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxpQkFBaUIsQ0FBQyxXQUFXLEVBQUUsR0FBRyxDQUFDLGlCQUFpQixDQUFDLENBQUMsVUFBVSxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUM7SUFDaEcsTUFBTSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsaUJBQWlCLENBQUMsV0FBVyxFQUFFLEdBQUcsQ0FBQyxjQUFjLENBQUMsQ0FBQyxVQUFVLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQztJQUM3RixNQUFNLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxpQkFBaUIsQ0FBQyxXQUFXLEVBQUUsR0FBRyxDQUFDLGlCQUFpQixDQUFDLENBQUMsVUFBVSxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUM7SUFDaEcsTUFBTSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsaUJBQWlCLENBQUMsV0FBVyxFQUFFLEdBQUcsQ0FBQyxhQUFhLENBQUMsbUNBQW1DLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDO0lBQ2pJLE1BQU0sQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLGlCQUFpQixDQUFDLFlBQVksRUFBRSxHQUFHLENBQUMsaUJBQWlCLENBQUMsQ0FBQyxVQUFVLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQztJQUNsRyxNQUFNLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxpQkFBaUIsQ0FBQyxZQUFZLEVBQUUsb0NBQW9DLENBQUMsQ0FBQyxVQUFVLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQztJQUNqSCxNQUFNLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxpQkFBaUIsQ0FBQyx1QkFBdUIsRUFBRSwrQ0FBK0MsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxxQkFBcUIsQ0FBQyxDQUFDLENBQUM7SUFDbEosT0FBTyxNQUFNLENBQUMsSUFBSSxDQUFDLG9FQUFvRSxDQUFDLENBQUM7QUFDN0YsQ0FBQztBQUVEOzs7Ozs7R0FNRztBQUNILG9CQUFvQjtBQUNwQixTQUFTLG9EQUFvRCxDQUFDLFVBQWU7SUFDekUsSUFBSSxDQUFDLEdBQUcsQ0FBQyxVQUFVLENBQUMsVUFBVSxDQUFDLEVBQUU7UUFBRSxPQUFPLFVBQVUsQ0FBQztLQUFFO0lBQ3ZELDhDQUE4QyxDQUFDLFVBQVUsQ0FBQyxDQUFDLGFBQWEsRUFBRSxDQUFDO0lBQzNFLE9BQU87UUFDTCxTQUFTLEVBQUUsR0FBRyxDQUFDLHNCQUFzQixDQUFDLFVBQVUsQ0FBQyxTQUFTLENBQUM7UUFDM0QsU0FBUyxFQUFFLEdBQUcsQ0FBQyxVQUFVLENBQUMseUNBQXlDLENBQUMsQ0FBQyxVQUFVLENBQUMsU0FBUyxDQUFDO1FBQzFGLFVBQVUsRUFBRSwwQ0FBMEMsQ0FBQyxVQUFVLENBQUMsVUFBVSxDQUFDO1FBQzdFLHFCQUFxQixFQUFFLHFEQUFxRCxDQUFDLFVBQVUsQ0FBQyxxQkFBcUIsQ0FBQztLQUMvRyxDQUFDO0FBQ04sQ0FBQztBQW9CRDs7Ozs7O0dBTUc7QUFDSCxTQUFTLG1DQUFtQyxDQUFDLFVBQWU7SUFDeEQsSUFBSSxDQUFDLEdBQUcsQ0FBQyxVQUFVLENBQUMsVUFBVSxDQUFDLEVBQUU7UUFBRSxPQUFPLEdBQUcsQ0FBQyxrQkFBa0IsQ0FBQztLQUFFO0lBQ25FLE1BQU0sTUFBTSxHQUFHLElBQUksR0FBRyxDQUFDLGlCQUFpQixFQUFFLENBQUM7SUFDM0MsTUFBTSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsaUJBQWlCLENBQUMsZUFBZSxFQUFFLEdBQUcsQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxhQUFhLENBQUMsQ0FBQyxDQUFDO0lBQ3hHLE1BQU0sQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLGlCQUFpQixDQUFDLGVBQWUsRUFBRSxHQUFHLENBQUMsY0FBYyxDQUFDLENBQUMsVUFBVSxDQUFDLGFBQWEsQ0FBQyxDQUFDLENBQUM7SUFDckcsTUFBTSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsaUJBQWlCLENBQUMsU0FBUyxFQUFFLEdBQUcsQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDO0lBQzVGLE1BQU0sQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLGlCQUFpQixDQUFDLFNBQVMsRUFBRSxHQUFHLENBQUMsY0FBYyxDQUFDLENBQUMsVUFBVSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUM7SUFDekYsT0FBTyxNQUFNLENBQUMsSUFBSSxDQUFDLHlEQUF5RCxDQUFDLENBQUM7QUFDbEYsQ0FBQztBQUVEOzs7Ozs7R0FNRztBQUNILG9CQUFvQjtBQUNwQixTQUFTLHlDQUF5QyxDQUFDLFVBQWU7SUFDOUQsSUFBSSxDQUFDLEdBQUcsQ0FBQyxVQUFVLENBQUMsVUFBVSxDQUFDLEVBQUU7UUFBRSxPQUFPLFVBQVUsQ0FBQztLQUFFO0lBQ3ZELG1DQUFtQyxDQUFDLFVBQVUsQ0FBQyxDQUFDLGFBQWEsRUFBRSxDQUFDO0lBQ2hFLE9BQU87UUFDTCxhQUFhLEVBQUUsR0FBRyxDQUFDLHNCQUFzQixDQUFDLFVBQVUsQ0FBQyxhQUFhLENBQUM7UUFDbkUsT0FBTyxFQUFFLEdBQUcsQ0FBQyxzQkFBc0IsQ0FBQyxVQUFVLENBQUMsT0FBTyxDQUFDO0tBQ3hELENBQUM7QUFDTixDQUFDO0FBeUJEOzs7Ozs7R0FNRztBQUNILFNBQVMsNkNBQTZDLENBQUMsVUFBZTtJQUNsRSxJQUFJLENBQUMsR0FBRyxDQUFDLFVBQVUsQ0FBQyxVQUFVLENBQUMsRUFBRTtRQUFFLE9BQU8sR0FBRyxDQUFDLGtCQUFrQixDQUFDO0tBQUU7SUFDbkUsTUFBTSxNQUFNLEdBQUcsSUFBSSxHQUFHLENBQUMsaUJBQWlCLEVBQUUsQ0FBQztJQUMzQyxNQUFNLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxpQkFBaUIsQ0FBQyxXQUFXLEVBQUUsR0FBRyxDQUFDLGlCQUFpQixDQUFDLENBQUMsVUFBVSxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUM7SUFDaEcsTUFBTSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsaUJBQWlCLENBQUMsV0FBVyxFQUFFLEdBQUcsQ0FBQyxjQUFjLENBQUMsQ0FBQyxVQUFVLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQztJQUM3RixNQUFNLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxpQkFBaUIsQ0FBQyxXQUFXLEVBQUUsR0FBRyxDQUFDLGlCQUFpQixDQUFDLENBQUMsVUFBVSxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUM7SUFDaEcsTUFBTSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsaUJBQWlCLENBQUMsV0FBVyxFQUFFLEdBQUcsQ0FBQyxhQUFhLENBQUMsbUNBQW1DLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDO0lBQ2pJLE1BQU0sQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLGlCQUFpQixDQUFDLFlBQVksRUFBRSxHQUFHLENBQUMsaUJBQWlCLENBQUMsQ0FBQyxVQUFVLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQztJQUNsRyxNQUFNLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxpQkFBaUIsQ0FBQyxZQUFZLEVBQUUsb0NBQW9DLENBQUMsQ0FBQyxVQUFVLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQztJQUNqSCxPQUFPLE1BQU0sQ0FBQyxJQUFJLENBQUMsbUVBQW1FLENBQUMsQ0FBQztBQUM1RixDQUFDO0FBRUQ7Ozs7OztHQU1HO0FBQ0gsb0JBQW9CO0FBQ3BCLFNBQVMsbURBQW1ELENBQUMsVUFBZTtJQUN4RSxJQUFJLENBQUMsR0FBRyxDQUFDLFVBQVUsQ0FBQyxVQUFVLENBQUMsRUFBRTtRQUFFLE9BQU8sVUFBVSxDQUFDO0tBQUU7SUFDdkQsNkNBQTZDLENBQUMsVUFBVSxDQUFDLENBQUMsYUFBYSxFQUFFLENBQUM7SUFDMUUsT0FBTztRQUNMLFNBQVMsRUFBRSxHQUFHLENBQUMsc0JBQXNCLENBQUMsVUFBVSxDQUFDLFNBQVMsQ0FBQztRQUMzRCxTQUFTLEVBQUUsR0FBRyxDQUFDLFVBQVUsQ0FBQyx5Q0FBeUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxTQUFTLENBQUM7UUFDMUYsVUFBVSxFQUFFLDBDQUEwQyxDQUFDLFVBQVUsQ0FBQyxVQUFVLENBQUM7S0FDOUUsQ0FBQztBQUNOLENBQUM7QUFlRDs7Ozs7O0dBTUc7QUFDSCxTQUFTLDBEQUEwRCxDQUFDLFVBQWU7SUFDL0UsSUFBSSxDQUFDLEdBQUcsQ0FBQyxVQUFVLENBQUMsVUFBVSxDQUFDLEVBQUU7UUFBRSxPQUFPLEdBQUcsQ0FBQyxrQkFBa0IsQ0FBQztLQUFFO0lBQ25FLE1BQU0sTUFBTSxHQUFHLElBQUksR0FBRyxDQUFDLGlCQUFpQixFQUFFLENBQUM7SUFDM0MsTUFBTSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsaUJBQWlCLENBQUMsNEJBQTRCLEVBQUUsR0FBRyxDQUFDLGVBQWUsQ0FBQyxDQUFDLFVBQVUsQ0FBQywwQkFBMEIsQ0FBQyxDQUFDLENBQUM7SUFDaEksT0FBTyxNQUFNLENBQUMsSUFBSSxDQUFDLGdGQUFnRixDQUFDLENBQUM7QUFDekcsQ0FBQztBQUVEOzs7Ozs7R0FNRztBQUNILG9CQUFvQjtBQUNwQixTQUFTLGdFQUFnRSxDQUFDLFVBQWU7SUFDckYsSUFBSSxDQUFDLEdBQUcsQ0FBQyxVQUFVLENBQUMsVUFBVSxDQUFDLEVBQUU7UUFBRSxPQUFPLFVBQVUsQ0FBQztLQUFFO0lBQ3ZELDBEQUEwRCxDQUFDLFVBQVUsQ0FBQyxDQUFDLGFBQWEsRUFBRSxDQUFDO0lBQ3ZGLE9BQU87UUFDTCwwQkFBMEIsRUFBRSxHQUFHLENBQUMsdUJBQXVCLENBQUMsVUFBVSxDQUFDLDBCQUEwQixDQUFDO0tBQy9GLENBQUM7QUFDTixDQUFDO0FBb0JEOzs7Ozs7R0FNRztBQUNILFNBQVMsb0NBQW9DLENBQUMsVUFBZTtJQUN6RCxJQUFJLENBQUMsR0FBRyxDQUFDLFVBQVUsQ0FBQyxVQUFVLENBQUMsRUFBRTtRQUFFLE9BQU8sR0FBRyxDQUFDLGtCQUFrQixDQUFDO0tBQUU7SUFDbkUsTUFBTSxNQUFNLEdBQUcsSUFBSSxHQUFHLENBQUMsaUJBQWlCLEVBQUUsQ0FBQztJQUMzQyxNQUFNLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxpQkFBaUIsQ0FBQyxrQkFBa0IsRUFBRSxHQUFHLENBQUMsYUFBYSxDQUFDLEdBQUcsQ0FBQyxjQUFjLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDLENBQUM7SUFDOUgsTUFBTSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsaUJBQWlCLENBQUMsZ0JBQWdCLEVBQUUsR0FBRyxDQUFDLGNBQWMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxjQUFjLENBQUMsQ0FBQyxDQUFDO0lBQ3ZHLE9BQU8sTUFBTSxDQUFDLElBQUksQ0FBQywwREFBMEQsQ0FBQyxDQUFDO0FBQ25GLENBQUM7QUFFRDs7Ozs7O0dBTUc7QUFDSCxvQkFBb0I7QUFDcEIsU0FBUywwQ0FBMEMsQ0FBQyxVQUFlO0lBQy9ELElBQUksQ0FBQyxHQUFHLENBQUMsVUFBVSxDQUFDLFVBQVUsQ0FBQyxFQUFFO1FBQUUsT0FBTyxVQUFVLENBQUM7S0FBRTtJQUN2RCxvQ0FBb0MsQ0FBQyxVQUFVLENBQUMsQ0FBQyxhQUFhLEVBQUUsQ0FBQztJQUNqRSxPQUFPO1FBQ0wsZ0JBQWdCLEVBQUUsR0FBRyxDQUFDLFVBQVUsQ0FBQyxHQUFHLENBQUMsc0JBQXNCLENBQUMsQ0FBQyxVQUFVLENBQUMsZ0JBQWdCLENBQUM7UUFDekYsY0FBYyxFQUFFLEdBQUcsQ0FBQyxzQkFBc0IsQ0FBQyxVQUFVLENBQUMsY0FBYyxDQUFDO0tBQ3RFLENBQUM7QUFDTixDQUFDO0FBb0JEOzs7Ozs7R0FNRztBQUNILFNBQVMsK0NBQStDLENBQUMsVUFBZTtJQUNwRSxJQUFJLENBQUMsR0FBRyxDQUFDLFVBQVUsQ0FBQyxVQUFVLENBQUMsRUFBRTtRQUFFLE9BQU8sR0FBRyxDQUFDLGtCQUFrQixDQUFDO0tBQUU7SUFDbkUsTUFBTSxNQUFNLEdBQUcsSUFBSSxHQUFHLENBQUMsaUJBQWlCLEVBQUUsQ0FBQztJQUMzQyxNQUFNLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxpQkFBaUIsQ0FBQyxtQkFBbUIsRUFBRSxHQUFHLENBQUMsaUJBQWlCLENBQUMsQ0FBQyxVQUFVLENBQUMsaUJBQWlCLENBQUMsQ0FBQyxDQUFDO0lBQ2hILE1BQU0sQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLGlCQUFpQixDQUFDLG1CQUFtQixFQUFFLEdBQUcsQ0FBQyxjQUFjLENBQUMsQ0FBQyxVQUFVLENBQUMsaUJBQWlCLENBQUMsQ0FBQyxDQUFDO0lBQzdHLE1BQU0sQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLGlCQUFpQixDQUFDLG9CQUFvQixFQUFFLEdBQUcsQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDLENBQUM7SUFDbEgsTUFBTSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsaUJBQWlCLENBQUMsb0JBQW9CLEVBQUUsR0FBRyxDQUFDLGNBQWMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDLENBQUM7SUFDL0csT0FBTyxNQUFNLENBQUMsSUFBSSxDQUFDLHFFQUFxRSxDQUFDLENBQUM7QUFDOUYsQ0FBQztBQUVEOzs7Ozs7R0FNRztBQUNILG9CQUFvQjtBQUNwQixTQUFTLHFEQUFxRCxDQUFDLFVBQWU7SUFDMUUsSUFBSSxDQUFDLEdBQUcsQ0FBQyxVQUFVLENBQUMsVUFBVSxDQUFDLEVBQUU7UUFBRSxPQUFPLFVBQVUsQ0FBQztLQUFFO0lBQ3ZELCtDQUErQyxDQUFDLFVBQVUsQ0FBQyxDQUFDLGFBQWEsRUFBRSxDQUFDO0lBQzVFLE9BQU87UUFDTCxpQkFBaUIsRUFBRSxHQUFHLENBQUMsc0JBQXNCLENBQUMsVUFBVSxDQUFDLGlCQUFpQixDQUFDO1FBQzNFLGtCQUFrQixFQUFFLEdBQUcsQ0FBQyxzQkFBc0IsQ0FBQyxVQUFVLENBQUMsa0JBQWtCLENBQUM7S0FDOUUsQ0FBQztBQUNOLENBQUM7QUFlRDs7Ozs7O0dBTUc7QUFDSCxTQUFTLDBDQUEwQyxDQUFDLFVBQWU7SUFDL0QsSUFBSSxDQUFDLEdBQUcsQ0FBQyxVQUFVLENBQUMsVUFBVSxDQUFDLEVBQUU7UUFBRSxPQUFPLEdBQUcsQ0FBQyxrQkFBa0IsQ0FBQztLQUFFO0lBQ25FLE1BQU0sTUFBTSxHQUFHLElBQUksR0FBRyxDQUFDLGlCQUFpQixFQUFFLENBQUM7SUFDM0MsTUFBTSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsaUJBQWlCLENBQUMsWUFBWSxFQUFFLEdBQUcsQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDO0lBQ2xHLE1BQU0sQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLGlCQUFpQixDQUFDLFlBQVksRUFBRSxHQUFHLENBQUMsZUFBZSxDQUFDLENBQUMsVUFBVSxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUM7SUFDaEcsT0FBTyxNQUFNLENBQUMsSUFBSSxDQUFDLGdFQUFnRSxDQUFDLENBQUM7QUFDekYsQ0FBQztBQUVEOzs7Ozs7R0FNRztBQUNILG9CQUFvQjtBQUNwQixTQUFTLGdEQUFnRCxDQUFDLFVBQWU7SUFDckUsSUFBSSxDQUFDLEdBQUcsQ0FBQyxVQUFVLENBQUMsVUFBVSxDQUFDLEVBQUU7UUFBRSxPQUFPLFVBQVUsQ0FBQztLQUFFO0lBQ3ZELDBDQUEwQyxDQUFDLFVBQVUsQ0FBQyxDQUFDLGFBQWEsRUFBRSxDQUFDO0lBQ3ZFLE9BQU87UUFDTCxVQUFVLEVBQUUsR0FBRyxDQUFDLHVCQUF1QixDQUFDLFVBQVUsQ0FBQyxVQUFVLENBQUM7S0FDL0QsQ0FBQztBQUNOLENBQUM7QUFlRDs7Ozs7O0dBTUc7QUFDSCxTQUFTLDZDQUE2QyxDQUFDLFVBQWU7SUFDbEUsSUFBSSxDQUFDLEdBQUcsQ0FBQyxVQUFVLENBQUMsVUFBVSxDQUFDLEVBQUU7UUFBRSxPQUFPLEdBQUcsQ0FBQyxrQkFBa0IsQ0FBQztLQUFFO0lBQ25FLE1BQU0sTUFBTSxHQUFHLElBQUksR0FBRyxDQUFDLGlCQUFpQixFQUFFLENBQUM7SUFDM0MsTUFBTSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsaUJBQWlCLENBQUMsZ0JBQWdCLEVBQUUsR0FBRyxDQUFDLGlCQUFpQixDQUFDLENBQUMsVUFBVSxDQUFDLGNBQWMsQ0FBQyxDQUFDLENBQUM7SUFDMUcsTUFBTSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsaUJBQWlCLENBQUMsZ0JBQWdCLEVBQUUsR0FBRyxDQUFDLGNBQWMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxjQUFjLENBQUMsQ0FBQyxDQUFDO0lBQ3ZHLE9BQU8sTUFBTSxDQUFDLElBQUksQ0FBQyxtRUFBbUUsQ0FBQyxDQUFDO0FBQzVGLENBQUM7QUFFRDs7Ozs7O0dBTUc7QUFDSCxvQkFBb0I7QUFDcEIsU0FBUyxtREFBbUQsQ0FBQyxVQUFlO0lBQ3hFLElBQUksQ0FBQyxHQUFHLENBQUMsVUFBVSxDQUFDLFVBQVUsQ0FBQyxFQUFFO1FBQUUsT0FBTyxVQUFVLENBQUM7S0FBRTtJQUN2RCw2Q0FBNkMsQ0FBQyxVQUFVLENBQUMsQ0FBQyxhQUFhLEVBQUUsQ0FBQztJQUMxRSxPQUFPO1FBQ0wsY0FBYyxFQUFFLEdBQUcsQ0FBQyxzQkFBc0IsQ0FBQyxVQUFVLENBQUMsY0FBYyxDQUFDO0tBQ3RFLENBQUM7QUFDTixDQUFDO0FBb0JEOzs7Ozs7R0FNRztBQUNILFNBQVMsaURBQWlELENBQUMsVUFBZTtJQUN0RSxJQUFJLENBQUMsR0FBRyxDQUFDLFVBQVUsQ0FBQyxVQUFVLENBQUMsRUFBRTtRQUFFLE9BQU8sR0FBRyxDQUFDLGtCQUFrQixDQUFDO0tBQUU7SUFDbkUsTUFBTSxNQUFNLEdBQUcsSUFBSSxHQUFHLENBQUMsaUJBQWlCLEVBQUUsQ0FBQztJQUMzQyxNQUFNLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxpQkFBaUIsQ0FBQyxlQUFlLEVBQUUsR0FBRyxDQUFDLGlCQUFpQixDQUFDLENBQUMsVUFBVSxDQUFDLGFBQWEsQ0FBQyxDQUFDLENBQUM7SUFDeEcsTUFBTSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsaUJBQWlCLENBQUMsZUFBZSxFQUFFLEdBQUcsQ0FBQyxjQUFjLENBQUMsQ0FBQyxVQUFVLENBQUMsYUFBYSxDQUFDLENBQUMsQ0FBQztJQUNyRyxNQUFNLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxpQkFBaUIsQ0FBQyxTQUFTLEVBQUUsR0FBRyxDQUFDLGlCQUFpQixDQUFDLENBQUMsVUFBVSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUM7SUFDNUYsTUFBTSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsaUJBQWlCLENBQUMsU0FBUyxFQUFFLEdBQUcsQ0FBQyxlQUFlLENBQUMsQ0FBQyxVQUFVLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQztJQUMxRixPQUFPLE1BQU0sQ0FBQyxJQUFJLENBQUMsdUVBQXVFLENBQUMsQ0FBQztBQUNoRyxDQUFDO0FBRUQ7Ozs7OztHQU1HO0FBQ0gsb0JBQW9CO0FBQ3BCLFNBQVMsdURBQXVELENBQUMsVUFBZTtJQUM1RSxJQUFJLENBQUMsR0FBRyxDQUFDLFVBQVUsQ0FBQyxVQUFVLENBQUMsRUFBRTtRQUFFLE9BQU8sVUFBVSxDQUFDO0tBQUU7SUFDdkQsaURBQWlELENBQUMsVUFBVSxDQUFDLENBQUMsYUFBYSxFQUFFLENBQUM7SUFDOUUsT0FBTztRQUNMLGFBQWEsRUFBRSxHQUFHLENBQUMsc0JBQXNCLENBQUMsVUFBVSxDQUFDLGFBQWEsQ0FBQztRQUNuRSxPQUFPLEVBQUUsR0FBRyxDQUFDLHVCQUF1QixDQUFDLFVBQVUsQ0FBQyxPQUFPLENBQUM7S0FDekQsQ0FBQztBQUNOLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBDb3B5cmlnaHQgMjAxMi0yMDE5IEFtYXpvbi5jb20sIEluYy4gb3IgaXRzIGFmZmlsaWF0ZXMuIEFsbCBSaWdodHMgUmVzZXJ2ZWQuXG4vLyBHZW5lcmF0ZWQgZnJvbSB0aGUgQVdTIENsb3VkRm9ybWF0aW9uIFJlc291cmNlIFNwZWNpZmljYXRpb25cbi8vIFNlZTogZG9jcy5hd3MuYW1hem9uLmNvbS9BV1NDbG91ZEZvcm1hdGlvbi9sYXRlc3QvVXNlckd1aWRlL2Nmbi1yZXNvdXJjZS1zcGVjaWZpY2F0aW9uLmh0bWxcbi8vIEBjZm4ydHM6bWV0YUAge1wiZ2VuZXJhdGVkXCI6XCIyMDE5LTAzLTIxVDE2OjE5OjE2Ljg4MVpcIixcImZpbmdlcnByaW50XCI6XCJDUFRwRTllRDRJbXFPS0RudTdQMEthb2w4aitTWE5RVUlMTVI0bC9maTJnPVwifVxuXG4vLyB0c2xpbnQ6ZGlzYWJsZTptYXgtbGluZS1sZW5ndGggfCBUaGlzIGlzIGdlbmVyYXRlZCBjb2RlIC0gbGluZSBsZW5ndGhzIGFyZSBkaWZmaWN1bHQgdG8gY29udHJvbFxuXG5pbXBvcnQgY2RrID0gcmVxdWlyZSgnQGF3cy1jZGsvY2RrJyk7XG5cbi8qKlxuICogUHJvcGVydGllcyBmb3IgZGVmaW5pbmcgYSBgQVdTOjpEeW5hbW9EQjo6VGFibGVgXG4gKiBAc2VlIGh0dHA6Ly9kb2NzLmF3cy5hbWF6b24uY29tL0FXU0Nsb3VkRm9ybWF0aW9uL2xhdGVzdC9Vc2VyR3VpZGUvYXdzLXJlc291cmNlLWR5bmFtb2RiLXRhYmxlLmh0bWxcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBDZm5UYWJsZVByb3BzIHtcbiAgICAvKipcbiAgICAgKiBgQVdTOjpEeW5hbW9EQjo6VGFibGUuS2V5U2NoZW1hYFxuICAgICAqIEBzZWUgaHR0cDovL2RvY3MuYXdzLmFtYXpvbi5jb20vQVdTQ2xvdWRGb3JtYXRpb24vbGF0ZXN0L1VzZXJHdWlkZS9hd3MtcmVzb3VyY2UtZHluYW1vZGItdGFibGUuaHRtbCNjZm4tZHluYW1vZGItdGFibGUta2V5c2NoZW1hXG4gICAgICovXG4gICAga2V5U2NoZW1hOiBBcnJheTxDZm5UYWJsZS5LZXlTY2hlbWFQcm9wZXJ0eSB8IGNkay5Ub2tlbj4gfCBjZGsuVG9rZW47XG4gICAgLyoqXG4gICAgICogYEFXUzo6RHluYW1vREI6OlRhYmxlLkF0dHJpYnV0ZURlZmluaXRpb25zYFxuICAgICAqIEBzZWUgaHR0cDovL2RvY3MuYXdzLmFtYXpvbi5jb20vQVdTQ2xvdWRGb3JtYXRpb24vbGF0ZXN0L1VzZXJHdWlkZS9hd3MtcmVzb3VyY2UtZHluYW1vZGItdGFibGUuaHRtbCNjZm4tZHluYW1vZGItdGFibGUtYXR0cmlidXRlZGVmXG4gICAgICovXG4gICAgYXR0cmlidXRlRGVmaW5pdGlvbnM/OiBBcnJheTxDZm5UYWJsZS5BdHRyaWJ1dGVEZWZpbml0aW9uUHJvcGVydHkgfCBjZGsuVG9rZW4+IHwgY2RrLlRva2VuO1xuICAgIC8qKlxuICAgICAqIGBBV1M6OkR5bmFtb0RCOjpUYWJsZS5CaWxsaW5nTW9kZWBcbiAgICAgKiBAc2VlIGh0dHA6Ly9kb2NzLmF3cy5hbWF6b24uY29tL0FXU0Nsb3VkRm9ybWF0aW9uL2xhdGVzdC9Vc2VyR3VpZGUvYXdzLXJlc291cmNlLWR5bmFtb2RiLXRhYmxlLmh0bWwjY2ZuLWR5bmFtb2RiLXRhYmxlLWJpbGxpbmdtb2RlXG4gICAgICovXG4gICAgYmlsbGluZ01vZGU/OiBzdHJpbmc7XG4gICAgLyoqXG4gICAgICogYEFXUzo6RHluYW1vREI6OlRhYmxlLkdsb2JhbFNlY29uZGFyeUluZGV4ZXNgXG4gICAgICogQHNlZSBodHRwOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9BV1NDbG91ZEZvcm1hdGlvbi9sYXRlc3QvVXNlckd1aWRlL2F3cy1yZXNvdXJjZS1keW5hbW9kYi10YWJsZS5odG1sI2Nmbi1keW5hbW9kYi10YWJsZS1nc2lcbiAgICAgKi9cbiAgICBnbG9iYWxTZWNvbmRhcnlJbmRleGVzPzogQXJyYXk8Q2ZuVGFibGUuR2xvYmFsU2Vjb25kYXJ5SW5kZXhQcm9wZXJ0eSB8IGNkay5Ub2tlbj4gfCBjZGsuVG9rZW47XG4gICAgLyoqXG4gICAgICogYEFXUzo6RHluYW1vREI6OlRhYmxlLkxvY2FsU2Vjb25kYXJ5SW5kZXhlc2BcbiAgICAgKiBAc2VlIGh0dHA6Ly9kb2NzLmF3cy5hbWF6b24uY29tL0FXU0Nsb3VkRm9ybWF0aW9uL2xhdGVzdC9Vc2VyR3VpZGUvYXdzLXJlc291cmNlLWR5bmFtb2RiLXRhYmxlLmh0bWwjY2ZuLWR5bmFtb2RiLXRhYmxlLWxzaVxuICAgICAqL1xuICAgIGxvY2FsU2Vjb25kYXJ5SW5kZXhlcz86IEFycmF5PENmblRhYmxlLkxvY2FsU2Vjb25kYXJ5SW5kZXhQcm9wZXJ0eSB8IGNkay5Ub2tlbj4gfCBjZGsuVG9rZW47XG4gICAgLyoqXG4gICAgICogYEFXUzo6RHluYW1vREI6OlRhYmxlLlBvaW50SW5UaW1lUmVjb3ZlcnlTcGVjaWZpY2F0aW9uYFxuICAgICAqIEBzZWUgaHR0cDovL2RvY3MuYXdzLmFtYXpvbi5jb20vQVdTQ2xvdWRGb3JtYXRpb24vbGF0ZXN0L1VzZXJHdWlkZS9hd3MtcmVzb3VyY2UtZHluYW1vZGItdGFibGUuaHRtbCNjZm4tZHluYW1vZGItdGFibGUtcG9pbnRpbnRpbWVyZWNvdmVyeXNwZWNpZmljYXRpb25cbiAgICAgKi9cbiAgICBwb2ludEluVGltZVJlY292ZXJ5U3BlY2lmaWNhdGlvbj86IENmblRhYmxlLlBvaW50SW5UaW1lUmVjb3ZlcnlTcGVjaWZpY2F0aW9uUHJvcGVydHkgfCBjZGsuVG9rZW47XG4gICAgLyoqXG4gICAgICogYEFXUzo6RHluYW1vREI6OlRhYmxlLlByb3Zpc2lvbmVkVGhyb3VnaHB1dGBcbiAgICAgKiBAc2VlIGh0dHA6Ly9kb2NzLmF3cy5hbWF6b24uY29tL0FXU0Nsb3VkRm9ybWF0aW9uL2xhdGVzdC9Vc2VyR3VpZGUvYXdzLXJlc291cmNlLWR5bmFtb2RiLXRhYmxlLmh0bWwjY2ZuLWR5bmFtb2RiLXRhYmxlLXByb3Zpc2lvbmVkdGhyb3VnaHB1dFxuICAgICAqL1xuICAgIHByb3Zpc2lvbmVkVGhyb3VnaHB1dD86IENmblRhYmxlLlByb3Zpc2lvbmVkVGhyb3VnaHB1dFByb3BlcnR5IHwgY2RrLlRva2VuO1xuICAgIC8qKlxuICAgICAqIGBBV1M6OkR5bmFtb0RCOjpUYWJsZS5TU0VTcGVjaWZpY2F0aW9uYFxuICAgICAqIEBzZWUgaHR0cDovL2RvY3MuYXdzLmFtYXpvbi5jb20vQVdTQ2xvdWRGb3JtYXRpb24vbGF0ZXN0L1VzZXJHdWlkZS9hd3MtcmVzb3VyY2UtZHluYW1vZGItdGFibGUuaHRtbCNjZm4tZHluYW1vZGItdGFibGUtc3Nlc3BlY2lmaWNhdGlvblxuICAgICAqL1xuICAgIHNzZVNwZWNpZmljYXRpb24/OiBDZm5UYWJsZS5TU0VTcGVjaWZpY2F0aW9uUHJvcGVydHkgfCBjZGsuVG9rZW47XG4gICAgLyoqXG4gICAgICogYEFXUzo6RHluYW1vREI6OlRhYmxlLlN0cmVhbVNwZWNpZmljYXRpb25gXG4gICAgICogQHNlZSBodHRwOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9BV1NDbG91ZEZvcm1hdGlvbi9sYXRlc3QvVXNlckd1aWRlL2F3cy1yZXNvdXJjZS1keW5hbW9kYi10YWJsZS5odG1sI2Nmbi1keW5hbW9kYi10YWJsZS1zdHJlYW1zcGVjaWZpY2F0aW9uXG4gICAgICovXG4gICAgc3RyZWFtU3BlY2lmaWNhdGlvbj86IENmblRhYmxlLlN0cmVhbVNwZWNpZmljYXRpb25Qcm9wZXJ0eSB8IGNkay5Ub2tlbjtcbiAgICAvKipcbiAgICAgKiBgQVdTOjpEeW5hbW9EQjo6VGFibGUuVGFibGVOYW1lYFxuICAgICAqIEBzZWUgaHR0cDovL2RvY3MuYXdzLmFtYXpvbi5jb20vQVdTQ2xvdWRGb3JtYXRpb24vbGF0ZXN0L1VzZXJHdWlkZS9hd3MtcmVzb3VyY2UtZHluYW1vZGItdGFibGUuaHRtbCNjZm4tZHluYW1vZGItdGFibGUtdGFibGVuYW1lXG4gICAgICovXG4gICAgdGFibGVOYW1lPzogc3RyaW5nO1xuICAgIC8qKlxuICAgICAqIGBBV1M6OkR5bmFtb0RCOjpUYWJsZS5UYWdzYFxuICAgICAqIEBzZWUgaHR0cDovL2RvY3MuYXdzLmFtYXpvbi5jb20vQVdTQ2xvdWRGb3JtYXRpb24vbGF0ZXN0L1VzZXJHdWlkZS9hd3MtcmVzb3VyY2UtZHluYW1vZGItdGFibGUuaHRtbCNjZm4tZHluYW1vZGItdGFibGUtdGFnc1xuICAgICAqL1xuICAgIHRhZ3M/OiBjZGsuQ2ZuVGFnW107XG4gICAgLyoqXG4gICAgICogYEFXUzo6RHluYW1vREI6OlRhYmxlLlRpbWVUb0xpdmVTcGVjaWZpY2F0aW9uYFxuICAgICAqIEBzZWUgaHR0cDovL2RvY3MuYXdzLmFtYXpvbi5jb20vQVdTQ2xvdWRGb3JtYXRpb24vbGF0ZXN0L1VzZXJHdWlkZS9hd3MtcmVzb3VyY2UtZHluYW1vZGItdGFibGUuaHRtbCNjZm4tZHluYW1vZGItdGFibGUtdGltZXRvbGl2ZXNwZWNpZmljYXRpb25cbiAgICAgKi9cbiAgICB0aW1lVG9MaXZlU3BlY2lmaWNhdGlvbj86IENmblRhYmxlLlRpbWVUb0xpdmVTcGVjaWZpY2F0aW9uUHJvcGVydHkgfCBjZGsuVG9rZW47XG59XG5cbi8qKlxuICogRGV0ZXJtaW5lIHdoZXRoZXIgdGhlIGdpdmVuIHByb3BlcnRpZXMgbWF0Y2ggdGhvc2Ugb2YgYSBgQ2ZuVGFibGVQcm9wc2BcbiAqXG4gKiBAcGFyYW0gcHJvcGVydGllcyAtIHRoZSBUeXBlU2NyaXB0IHByb3BlcnRpZXMgb2YgYSBgQ2ZuVGFibGVQcm9wc2BcbiAqXG4gKiBAcmV0dXJucyB0aGUgcmVzdWx0IG9mIHRoZSB2YWxpZGF0aW9uLlxuICovXG5mdW5jdGlvbiBDZm5UYWJsZVByb3BzVmFsaWRhdG9yKHByb3BlcnRpZXM6IGFueSk6IGNkay5WYWxpZGF0aW9uUmVzdWx0IHtcbiAgICBpZiAoIWNkay5jYW5JbnNwZWN0KHByb3BlcnRpZXMpKSB7IHJldHVybiBjZGsuVkFMSURBVElPTl9TVUNDRVNTOyB9XG4gICAgY29uc3QgZXJyb3JzID0gbmV3IGNkay5WYWxpZGF0aW9uUmVzdWx0cygpO1xuICAgIGVycm9ycy5jb2xsZWN0KGNkay5wcm9wZXJ0eVZhbGlkYXRvcignYXR0cmlidXRlRGVmaW5pdGlvbnMnLCBjZGsubGlzdFZhbGlkYXRvcihDZm5UYWJsZV9BdHRyaWJ1dGVEZWZpbml0aW9uUHJvcGVydHlWYWxpZGF0b3IpKShwcm9wZXJ0aWVzLmF0dHJpYnV0ZURlZmluaXRpb25zKSk7XG4gICAgZXJyb3JzLmNvbGxlY3QoY2RrLnByb3BlcnR5VmFsaWRhdG9yKCdiaWxsaW5nTW9kZScsIGNkay52YWxpZGF0ZVN0cmluZykocHJvcGVydGllcy5iaWxsaW5nTW9kZSkpO1xuICAgIGVycm9ycy5jb2xsZWN0KGNkay5wcm9wZXJ0eVZhbGlkYXRvcignZ2xvYmFsU2Vjb25kYXJ5SW5kZXhlcycsIGNkay5saXN0VmFsaWRhdG9yKENmblRhYmxlX0dsb2JhbFNlY29uZGFyeUluZGV4UHJvcGVydHlWYWxpZGF0b3IpKShwcm9wZXJ0aWVzLmdsb2JhbFNlY29uZGFyeUluZGV4ZXMpKTtcbiAgICBlcnJvcnMuY29sbGVjdChjZGsucHJvcGVydHlWYWxpZGF0b3IoJ2tleVNjaGVtYScsIGNkay5yZXF1aXJlZFZhbGlkYXRvcikocHJvcGVydGllcy5rZXlTY2hlbWEpKTtcbiAgICBlcnJvcnMuY29sbGVjdChjZGsucHJvcGVydHlWYWxpZGF0b3IoJ2tleVNjaGVtYScsIGNkay5saXN0VmFsaWRhdG9yKENmblRhYmxlX0tleVNjaGVtYVByb3BlcnR5VmFsaWRhdG9yKSkocHJvcGVydGllcy5rZXlTY2hlbWEpKTtcbiAgICBlcnJvcnMuY29sbGVjdChjZGsucHJvcGVydHlWYWxpZGF0b3IoJ2xvY2FsU2Vjb25kYXJ5SW5kZXhlcycsIGNkay5saXN0VmFsaWRhdG9yKENmblRhYmxlX0xvY2FsU2Vjb25kYXJ5SW5kZXhQcm9wZXJ0eVZhbGlkYXRvcikpKHByb3BlcnRpZXMubG9jYWxTZWNvbmRhcnlJbmRleGVzKSk7XG4gICAgZXJyb3JzLmNvbGxlY3QoY2RrLnByb3BlcnR5VmFsaWRhdG9yKCdwb2ludEluVGltZVJlY292ZXJ5U3BlY2lmaWNhdGlvbicsIENmblRhYmxlX1BvaW50SW5UaW1lUmVjb3ZlcnlTcGVjaWZpY2F0aW9uUHJvcGVydHlWYWxpZGF0b3IpKHByb3BlcnRpZXMucG9pbnRJblRpbWVSZWNvdmVyeVNwZWNpZmljYXRpb24pKTtcbiAgICBlcnJvcnMuY29sbGVjdChjZGsucHJvcGVydHlWYWxpZGF0b3IoJ3Byb3Zpc2lvbmVkVGhyb3VnaHB1dCcsIENmblRhYmxlX1Byb3Zpc2lvbmVkVGhyb3VnaHB1dFByb3BlcnR5VmFsaWRhdG9yKShwcm9wZXJ0aWVzLnByb3Zpc2lvbmVkVGhyb3VnaHB1dCkpO1xuICAgIGVycm9ycy5jb2xsZWN0KGNkay5wcm9wZXJ0eVZhbGlkYXRvcignc3NlU3BlY2lmaWNhdGlvbicsIENmblRhYmxlX1NTRVNwZWNpZmljYXRpb25Qcm9wZXJ0eVZhbGlkYXRvcikocHJvcGVydGllcy5zc2VTcGVjaWZpY2F0aW9uKSk7XG4gICAgZXJyb3JzLmNvbGxlY3QoY2RrLnByb3BlcnR5VmFsaWRhdG9yKCdzdHJlYW1TcGVjaWZpY2F0aW9uJywgQ2ZuVGFibGVfU3RyZWFtU3BlY2lmaWNhdGlvblByb3BlcnR5VmFsaWRhdG9yKShwcm9wZXJ0aWVzLnN0cmVhbVNwZWNpZmljYXRpb24pKTtcbiAgICBlcnJvcnMuY29sbGVjdChjZGsucHJvcGVydHlWYWxpZGF0b3IoJ3RhYmxlTmFtZScsIGNkay52YWxpZGF0ZVN0cmluZykocHJvcGVydGllcy50YWJsZU5hbWUpKTtcbiAgICBlcnJvcnMuY29sbGVjdChjZGsucHJvcGVydHlWYWxpZGF0b3IoJ3RhZ3MnLCBjZGsubGlzdFZhbGlkYXRvcihjZGsudmFsaWRhdGVDZm5UYWcpKShwcm9wZXJ0aWVzLnRhZ3MpKTtcbiAgICBlcnJvcnMuY29sbGVjdChjZGsucHJvcGVydHlWYWxpZGF0b3IoJ3RpbWVUb0xpdmVTcGVjaWZpY2F0aW9uJywgQ2ZuVGFibGVfVGltZVRvTGl2ZVNwZWNpZmljYXRpb25Qcm9wZXJ0eVZhbGlkYXRvcikocHJvcGVydGllcy50aW1lVG9MaXZlU3BlY2lmaWNhdGlvbikpO1xuICAgIHJldHVybiBlcnJvcnMud3JhcCgnc3VwcGxpZWQgcHJvcGVydGllcyBub3QgY29ycmVjdCBmb3IgXCJDZm5UYWJsZVByb3BzXCInKTtcbn1cblxuLyoqXG4gKiBSZW5kZXJzIHRoZSBBV1MgQ2xvdWRGb3JtYXRpb24gcHJvcGVydGllcyBvZiBhbiBgQVdTOjpEeW5hbW9EQjo6VGFibGVgIHJlc291cmNlXG4gKlxuICogQHBhcmFtIHByb3BlcnRpZXMgLSB0aGUgVHlwZVNjcmlwdCBwcm9wZXJ0aWVzIG9mIGEgYENmblRhYmxlUHJvcHNgXG4gKlxuICogQHJldHVybnMgdGhlIEFXUyBDbG91ZEZvcm1hdGlvbiBwcm9wZXJ0aWVzIG9mIGFuIGBBV1M6OkR5bmFtb0RCOjpUYWJsZWAgcmVzb3VyY2UuXG4gKi9cbi8vIEB0cy1pZ25vcmUgVFM2MTMzXG5mdW5jdGlvbiBjZm5UYWJsZVByb3BzVG9DbG91ZEZvcm1hdGlvbihwcm9wZXJ0aWVzOiBhbnkpOiBhbnkge1xuICAgIGlmICghY2RrLmNhbkluc3BlY3QocHJvcGVydGllcykpIHsgcmV0dXJuIHByb3BlcnRpZXM7IH1cbiAgICBDZm5UYWJsZVByb3BzVmFsaWRhdG9yKHByb3BlcnRpZXMpLmFzc2VydFN1Y2Nlc3MoKTtcbiAgICByZXR1cm4ge1xuICAgICAgS2V5U2NoZW1hOiBjZGsubGlzdE1hcHBlcihjZm5UYWJsZUtleVNjaGVtYVByb3BlcnR5VG9DbG91ZEZvcm1hdGlvbikocHJvcGVydGllcy5rZXlTY2hlbWEpLFxuICAgICAgQXR0cmlidXRlRGVmaW5pdGlvbnM6IGNkay5saXN0TWFwcGVyKGNmblRhYmxlQXR0cmlidXRlRGVmaW5pdGlvblByb3BlcnR5VG9DbG91ZEZvcm1hdGlvbikocHJvcGVydGllcy5hdHRyaWJ1dGVEZWZpbml0aW9ucyksXG4gICAgICBCaWxsaW5nTW9kZTogY2RrLnN0cmluZ1RvQ2xvdWRGb3JtYXRpb24ocHJvcGVydGllcy5iaWxsaW5nTW9kZSksXG4gICAgICBHbG9iYWxTZWNvbmRhcnlJbmRleGVzOiBjZGsubGlzdE1hcHBlcihjZm5UYWJsZUdsb2JhbFNlY29uZGFyeUluZGV4UHJvcGVydHlUb0Nsb3VkRm9ybWF0aW9uKShwcm9wZXJ0aWVzLmdsb2JhbFNlY29uZGFyeUluZGV4ZXMpLFxuICAgICAgTG9jYWxTZWNvbmRhcnlJbmRleGVzOiBjZGsubGlzdE1hcHBlcihjZm5UYWJsZUxvY2FsU2Vjb25kYXJ5SW5kZXhQcm9wZXJ0eVRvQ2xvdWRGb3JtYXRpb24pKHByb3BlcnRpZXMubG9jYWxTZWNvbmRhcnlJbmRleGVzKSxcbiAgICAgIFBvaW50SW5UaW1lUmVjb3ZlcnlTcGVjaWZpY2F0aW9uOiBjZm5UYWJsZVBvaW50SW5UaW1lUmVjb3ZlcnlTcGVjaWZpY2F0aW9uUHJvcGVydHlUb0Nsb3VkRm9ybWF0aW9uKHByb3BlcnRpZXMucG9pbnRJblRpbWVSZWNvdmVyeVNwZWNpZmljYXRpb24pLFxuICAgICAgUHJvdmlzaW9uZWRUaHJvdWdocHV0OiBjZm5UYWJsZVByb3Zpc2lvbmVkVGhyb3VnaHB1dFByb3BlcnR5VG9DbG91ZEZvcm1hdGlvbihwcm9wZXJ0aWVzLnByb3Zpc2lvbmVkVGhyb3VnaHB1dCksXG4gICAgICBTU0VTcGVjaWZpY2F0aW9uOiBjZm5UYWJsZVNTRVNwZWNpZmljYXRpb25Qcm9wZXJ0eVRvQ2xvdWRGb3JtYXRpb24ocHJvcGVydGllcy5zc2VTcGVjaWZpY2F0aW9uKSxcbiAgICAgIFN0cmVhbVNwZWNpZmljYXRpb246IGNmblRhYmxlU3RyZWFtU3BlY2lmaWNhdGlvblByb3BlcnR5VG9DbG91ZEZvcm1hdGlvbihwcm9wZXJ0aWVzLnN0cmVhbVNwZWNpZmljYXRpb24pLFxuICAgICAgVGFibGVOYW1lOiBjZGsuc3RyaW5nVG9DbG91ZEZvcm1hdGlvbihwcm9wZXJ0aWVzLnRhYmxlTmFtZSksXG4gICAgICBUYWdzOiBjZGsubGlzdE1hcHBlcihjZGsuY2ZuVGFnVG9DbG91ZEZvcm1hdGlvbikocHJvcGVydGllcy50YWdzKSxcbiAgICAgIFRpbWVUb0xpdmVTcGVjaWZpY2F0aW9uOiBjZm5UYWJsZVRpbWVUb0xpdmVTcGVjaWZpY2F0aW9uUHJvcGVydHlUb0Nsb3VkRm9ybWF0aW9uKHByb3BlcnRpZXMudGltZVRvTGl2ZVNwZWNpZmljYXRpb24pLFxuICAgIH07XG59XG5cbi8qKlxuICogQSBDbG91ZEZvcm1hdGlvbiBgQVdTOjpEeW5hbW9EQjo6VGFibGVgXG4gKlxuICogQGNsb3VkZm9ybWF0aW9uUmVzb3VyY2UgQVdTOjpEeW5hbW9EQjo6VGFibGVcbiAqIEBzZWUgaHR0cDovL2RvY3MuYXdzLmFtYXpvbi5jb20vQVdTQ2xvdWRGb3JtYXRpb24vbGF0ZXN0L1VzZXJHdWlkZS9hd3MtcmVzb3VyY2UtZHluYW1vZGItdGFibGUuaHRtbFxuICovXG5leHBvcnQgY2xhc3MgQ2ZuVGFibGUgZXh0ZW5kcyBjZGsuQ2ZuUmVzb3VyY2Uge1xuICAgIC8qKlxuICAgICAqIFRoZSBDbG91ZEZvcm1hdGlvbiByZXNvdXJjZSB0eXBlIG5hbWUgZm9yIHRoaXMgcmVzb3VyY2UgY2xhc3MuXG4gICAgICovXG4gICAgcHVibGljIHN0YXRpYyByZWFkb25seSByZXNvdXJjZVR5cGVOYW1lID0gXCJBV1M6OkR5bmFtb0RCOjpUYWJsZVwiO1xuXG4gICAgLyoqXG4gICAgICogQGNsb3VkZm9ybWF0aW9uQXR0cmlidXRlIEFyblxuICAgICAqL1xuICAgIHB1YmxpYyByZWFkb25seSB0YWJsZUFybjogc3RyaW5nO1xuXG4gICAgLyoqXG4gICAgICogQGNsb3VkZm9ybWF0aW9uQXR0cmlidXRlIFN0cmVhbUFyblxuICAgICAqL1xuICAgIHB1YmxpYyByZWFkb25seSB0YWJsZVN0cmVhbUFybjogc3RyaW5nO1xuICAgIHB1YmxpYyByZWFkb25seSB0YWJsZU5hbWU6IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIFRoZSBgVGFnTWFuYWdlcmAgaGFuZGxlcyBzZXR0aW5nLCByZW1vdmluZyBhbmQgZm9ybWF0dGluZyB0YWdzXG4gICAgICpcbiAgICAgKiBUYWdzIHNob3VsZCBiZSBtYW5hZ2VkIGVpdGhlciBwYXNzaW5nIHRoZW0gYXMgcHJvcGVydGllcyBkdXJpbmdcbiAgICAgKiBpbml0aWF0aW9uIG9yIGJ5IGNhbGxpbmcgbWV0aG9kcyBvbiB0aGlzIG9iamVjdC4gSWYgYm90aCB0ZWNobmlxdWVzIGFyZVxuICAgICAqIHVzZWQgb25seSB0aGUgdGFncyBmcm9tIHRoZSBUYWdNYW5hZ2VyIHdpbGwgYmUgdXNlZC4gYFRhZ2AgKGFzcGVjdClcbiAgICAgKiB3aWxsIHVzZSB0aGUgbWFuYWdlci5cbiAgICAgKi9cbiAgICBwdWJsaWMgcmVhZG9ubHkgdGFnczogY2RrLlRhZ01hbmFnZXI7XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGUgYSBuZXcgYEFXUzo6RHluYW1vREI6OlRhYmxlYC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSBzY29wZSAtIHNjb3BlIGluIHdoaWNoIHRoaXMgcmVzb3VyY2UgaXMgZGVmaW5lZFxuICAgICAqIEBwYXJhbSBpZCAgICAtIHNjb3BlZCBpZCBvZiB0aGUgcmVzb3VyY2VcbiAgICAgKiBAcGFyYW0gcHJvcHMgLSByZXNvdXJjZSBwcm9wZXJ0aWVzXG4gICAgICovXG4gICAgY29uc3RydWN0b3Ioc2NvcGU6IGNkay5Db25zdHJ1Y3QsIGlkOiBzdHJpbmcsIHByb3BzOiBDZm5UYWJsZVByb3BzKSB7XG4gICAgICAgIHN1cGVyKHNjb3BlLCBpZCwgeyB0eXBlOiBDZm5UYWJsZS5yZXNvdXJjZVR5cGVOYW1lLCBwcm9wZXJ0aWVzOiBwcm9wcyB9KTtcbiAgICAgICAgY2RrLnJlcXVpcmVQcm9wZXJ0eShwcm9wcywgJ2tleVNjaGVtYScsIHRoaXMpO1xuICAgICAgICB0aGlzLnRhYmxlQXJuID0gdGhpcy5nZXRBdHQoJ0FybicpLnRvU3RyaW5nKCk7XG4gICAgICAgIHRoaXMudGFibGVTdHJlYW1Bcm4gPSB0aGlzLmdldEF0dCgnU3RyZWFtQXJuJykudG9TdHJpbmcoKTtcbiAgICAgICAgdGhpcy50YWJsZU5hbWUgPSB0aGlzLnJlZi50b1N0cmluZygpO1xuICAgICAgICBjb25zdCB0YWdzID0gcHJvcHMgPT09IHVuZGVmaW5lZCA/IHVuZGVmaW5lZCA6IHByb3BzLnRhZ3M7XG4gICAgICAgIHRoaXMudGFncyA9IG5ldyBjZGsuVGFnTWFuYWdlcihjZGsuVGFnVHlwZS5TdGFuZGFyZCwgXCJBV1M6OkR5bmFtb0RCOjpUYWJsZVwiLCB0YWdzKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgZ2V0IHByb3BlcnR5T3ZlcnJpZGVzKCk6IENmblRhYmxlUHJvcHMge1xuICAgICAgICByZXR1cm4gdGhpcy51bnR5cGVkUHJvcGVydHlPdmVycmlkZXM7XG4gICAgfVxuICAgIHByb3RlY3RlZCByZW5kZXJQcm9wZXJ0aWVzKHByb3BlcnRpZXM6IGFueSk6IHsgW2tleTogc3RyaW5nXTogYW55IH0gIHtcbiAgICAgICAgcmV0dXJuIGNmblRhYmxlUHJvcHNUb0Nsb3VkRm9ybWF0aW9uKHRoaXMubm9kZS5yZXNvbHZlKHByb3BlcnRpZXMpKTtcbiAgICB9XG59XG5cbmV4cG9ydCBuYW1lc3BhY2UgQ2ZuVGFibGUge1xuICAgIC8qKlxuICAgICAqIEBzZWUgaHR0cDovL2RvY3MuYXdzLmFtYXpvbi5jb20vQVdTQ2xvdWRGb3JtYXRpb24vbGF0ZXN0L1VzZXJHdWlkZS9hd3MtcHJvcGVydGllcy1keW5hbW9kYi1hdHRyaWJ1dGVkZWYuaHRtbFxuICAgICAqL1xuICAgIGV4cG9ydCBpbnRlcmZhY2UgQXR0cmlidXRlRGVmaW5pdGlvblByb3BlcnR5IHtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIGBDZm5UYWJsZS5BdHRyaWJ1dGVEZWZpbml0aW9uUHJvcGVydHkuQXR0cmlidXRlTmFtZWBcbiAgICAgICAgICogQHNlZSBodHRwOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9BV1NDbG91ZEZvcm1hdGlvbi9sYXRlc3QvVXNlckd1aWRlL2F3cy1wcm9wZXJ0aWVzLWR5bmFtb2RiLWF0dHJpYnV0ZWRlZi5odG1sI2Nmbi1keW5hbW9kYi1hdHRyaWJ1dGVkZWYtYXR0cmlidXRlbmFtZVxuICAgICAgICAgKi9cbiAgICAgICAgYXR0cmlidXRlTmFtZTogc3RyaW5nO1xuICAgICAgICAvKipcbiAgICAgICAgICogYENmblRhYmxlLkF0dHJpYnV0ZURlZmluaXRpb25Qcm9wZXJ0eS5BdHRyaWJ1dGVUeXBlYFxuICAgICAgICAgKiBAc2VlIGh0dHA6Ly9kb2NzLmF3cy5hbWF6b24uY29tL0FXU0Nsb3VkRm9ybWF0aW9uL2xhdGVzdC9Vc2VyR3VpZGUvYXdzLXByb3BlcnRpZXMtZHluYW1vZGItYXR0cmlidXRlZGVmLmh0bWwjY2ZuLWR5bmFtb2RiLWF0dHJpYnV0ZWRlZi1hdHRyaWJ1dGVuYW1lLWF0dHJpYnV0ZXR5cGVcbiAgICAgICAgICovXG4gICAgICAgIGF0dHJpYnV0ZVR5cGU6IHN0cmluZztcbiAgICB9XG59XG5cbi8qKlxuICogRGV0ZXJtaW5lIHdoZXRoZXIgdGhlIGdpdmVuIHByb3BlcnRpZXMgbWF0Y2ggdGhvc2Ugb2YgYSBgQXR0cmlidXRlRGVmaW5pdGlvblByb3BlcnR5YFxuICpcbiAqIEBwYXJhbSBwcm9wZXJ0aWVzIC0gdGhlIFR5cGVTY3JpcHQgcHJvcGVydGllcyBvZiBhIGBBdHRyaWJ1dGVEZWZpbml0aW9uUHJvcGVydHlgXG4gKlxuICogQHJldHVybnMgdGhlIHJlc3VsdCBvZiB0aGUgdmFsaWRhdGlvbi5cbiAqL1xuZnVuY3Rpb24gQ2ZuVGFibGVfQXR0cmlidXRlRGVmaW5pdGlvblByb3BlcnR5VmFsaWRhdG9yKHByb3BlcnRpZXM6IGFueSk6IGNkay5WYWxpZGF0aW9uUmVzdWx0IHtcbiAgICBpZiAoIWNkay5jYW5JbnNwZWN0KHByb3BlcnRpZXMpKSB7IHJldHVybiBjZGsuVkFMSURBVElPTl9TVUNDRVNTOyB9XG4gICAgY29uc3QgZXJyb3JzID0gbmV3IGNkay5WYWxpZGF0aW9uUmVzdWx0cygpO1xuICAgIGVycm9ycy5jb2xsZWN0KGNkay5wcm9wZXJ0eVZhbGlkYXRvcignYXR0cmlidXRlTmFtZScsIGNkay5yZXF1aXJlZFZhbGlkYXRvcikocHJvcGVydGllcy5hdHRyaWJ1dGVOYW1lKSk7XG4gICAgZXJyb3JzLmNvbGxlY3QoY2RrLnByb3BlcnR5VmFsaWRhdG9yKCdhdHRyaWJ1dGVOYW1lJywgY2RrLnZhbGlkYXRlU3RyaW5nKShwcm9wZXJ0aWVzLmF0dHJpYnV0ZU5hbWUpKTtcbiAgICBlcnJvcnMuY29sbGVjdChjZGsucHJvcGVydHlWYWxpZGF0b3IoJ2F0dHJpYnV0ZVR5cGUnLCBjZGsucmVxdWlyZWRWYWxpZGF0b3IpKHByb3BlcnRpZXMuYXR0cmlidXRlVHlwZSkpO1xuICAgIGVycm9ycy5jb2xsZWN0KGNkay5wcm9wZXJ0eVZhbGlkYXRvcignYXR0cmlidXRlVHlwZScsIGNkay52YWxpZGF0ZVN0cmluZykocHJvcGVydGllcy5hdHRyaWJ1dGVUeXBlKSk7XG4gICAgcmV0dXJuIGVycm9ycy53cmFwKCdzdXBwbGllZCBwcm9wZXJ0aWVzIG5vdCBjb3JyZWN0IGZvciBcIkF0dHJpYnV0ZURlZmluaXRpb25Qcm9wZXJ0eVwiJyk7XG59XG5cbi8qKlxuICogUmVuZGVycyB0aGUgQVdTIENsb3VkRm9ybWF0aW9uIHByb3BlcnRpZXMgb2YgYW4gYEFXUzo6RHluYW1vREI6OlRhYmxlLkF0dHJpYnV0ZURlZmluaXRpb25gIHJlc291cmNlXG4gKlxuICogQHBhcmFtIHByb3BlcnRpZXMgLSB0aGUgVHlwZVNjcmlwdCBwcm9wZXJ0aWVzIG9mIGEgYEF0dHJpYnV0ZURlZmluaXRpb25Qcm9wZXJ0eWBcbiAqXG4gKiBAcmV0dXJucyB0aGUgQVdTIENsb3VkRm9ybWF0aW9uIHByb3BlcnRpZXMgb2YgYW4gYEFXUzo6RHluYW1vREI6OlRhYmxlLkF0dHJpYnV0ZURlZmluaXRpb25gIHJlc291cmNlLlxuICovXG4vLyBAdHMtaWdub3JlIFRTNjEzM1xuZnVuY3Rpb24gY2ZuVGFibGVBdHRyaWJ1dGVEZWZpbml0aW9uUHJvcGVydHlUb0Nsb3VkRm9ybWF0aW9uKHByb3BlcnRpZXM6IGFueSk6IGFueSB7XG4gICAgaWYgKCFjZGsuY2FuSW5zcGVjdChwcm9wZXJ0aWVzKSkgeyByZXR1cm4gcHJvcGVydGllczsgfVxuICAgIENmblRhYmxlX0F0dHJpYnV0ZURlZmluaXRpb25Qcm9wZXJ0eVZhbGlkYXRvcihwcm9wZXJ0aWVzKS5hc3NlcnRTdWNjZXNzKCk7XG4gICAgcmV0dXJuIHtcbiAgICAgIEF0dHJpYnV0ZU5hbWU6IGNkay5zdHJpbmdUb0Nsb3VkRm9ybWF0aW9uKHByb3BlcnRpZXMuYXR0cmlidXRlTmFtZSksXG4gICAgICBBdHRyaWJ1dGVUeXBlOiBjZGsuc3RyaW5nVG9DbG91ZEZvcm1hdGlvbihwcm9wZXJ0aWVzLmF0dHJpYnV0ZVR5cGUpLFxuICAgIH07XG59XG5cbmV4cG9ydCBuYW1lc3BhY2UgQ2ZuVGFibGUge1xuICAgIC8qKlxuICAgICAqIEBzZWUgaHR0cDovL2RvY3MuYXdzLmFtYXpvbi5jb20vQVdTQ2xvdWRGb3JtYXRpb24vbGF0ZXN0L1VzZXJHdWlkZS9hd3MtcHJvcGVydGllcy1keW5hbW9kYi1nc2kuaHRtbFxuICAgICAqL1xuICAgIGV4cG9ydCBpbnRlcmZhY2UgR2xvYmFsU2Vjb25kYXJ5SW5kZXhQcm9wZXJ0eSB7XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBgQ2ZuVGFibGUuR2xvYmFsU2Vjb25kYXJ5SW5kZXhQcm9wZXJ0eS5JbmRleE5hbWVgXG4gICAgICAgICAqIEBzZWUgaHR0cDovL2RvY3MuYXdzLmFtYXpvbi5jb20vQVdTQ2xvdWRGb3JtYXRpb24vbGF0ZXN0L1VzZXJHdWlkZS9hd3MtcHJvcGVydGllcy1keW5hbW9kYi1nc2kuaHRtbCNjZm4tZHluYW1vZGItZ3NpLWluZGV4bmFtZVxuICAgICAgICAgKi9cbiAgICAgICAgaW5kZXhOYW1lOiBzdHJpbmc7XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBgQ2ZuVGFibGUuR2xvYmFsU2Vjb25kYXJ5SW5kZXhQcm9wZXJ0eS5LZXlTY2hlbWFgXG4gICAgICAgICAqIEBzZWUgaHR0cDovL2RvY3MuYXdzLmFtYXpvbi5jb20vQVdTQ2xvdWRGb3JtYXRpb24vbGF0ZXN0L1VzZXJHdWlkZS9hd3MtcHJvcGVydGllcy1keW5hbW9kYi1nc2kuaHRtbCNjZm4tZHluYW1vZGItZ3NpLWtleXNjaGVtYVxuICAgICAgICAgKi9cbiAgICAgICAga2V5U2NoZW1hOiBBcnJheTxDZm5UYWJsZS5LZXlTY2hlbWFQcm9wZXJ0eSB8IGNkay5Ub2tlbj4gfCBjZGsuVG9rZW47XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBgQ2ZuVGFibGUuR2xvYmFsU2Vjb25kYXJ5SW5kZXhQcm9wZXJ0eS5Qcm9qZWN0aW9uYFxuICAgICAgICAgKiBAc2VlIGh0dHA6Ly9kb2NzLmF3cy5hbWF6b24uY29tL0FXU0Nsb3VkRm9ybWF0aW9uL2xhdGVzdC9Vc2VyR3VpZGUvYXdzLXByb3BlcnRpZXMtZHluYW1vZGItZ3NpLmh0bWwjY2ZuLWR5bmFtb2RiLWdzaS1wcm9qZWN0aW9uXG4gICAgICAgICAqL1xuICAgICAgICBwcm9qZWN0aW9uOiBDZm5UYWJsZS5Qcm9qZWN0aW9uUHJvcGVydHkgfCBjZGsuVG9rZW47XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBgQ2ZuVGFibGUuR2xvYmFsU2Vjb25kYXJ5SW5kZXhQcm9wZXJ0eS5Qcm92aXNpb25lZFRocm91Z2hwdXRgXG4gICAgICAgICAqIEBzZWUgaHR0cDovL2RvY3MuYXdzLmFtYXpvbi5jb20vQVdTQ2xvdWRGb3JtYXRpb24vbGF0ZXN0L1VzZXJHdWlkZS9hd3MtcHJvcGVydGllcy1keW5hbW9kYi1nc2kuaHRtbCNjZm4tZHluYW1vZGItZ3NpLXByb3Zpc2lvbmVkdGhyb3VnaHB1dFxuICAgICAgICAgKi9cbiAgICAgICAgcHJvdmlzaW9uZWRUaHJvdWdocHV0PzogQ2ZuVGFibGUuUHJvdmlzaW9uZWRUaHJvdWdocHV0UHJvcGVydHkgfCBjZGsuVG9rZW47XG4gICAgfVxufVxuXG4vKipcbiAqIERldGVybWluZSB3aGV0aGVyIHRoZSBnaXZlbiBwcm9wZXJ0aWVzIG1hdGNoIHRob3NlIG9mIGEgYEdsb2JhbFNlY29uZGFyeUluZGV4UHJvcGVydHlgXG4gKlxuICogQHBhcmFtIHByb3BlcnRpZXMgLSB0aGUgVHlwZVNjcmlwdCBwcm9wZXJ0aWVzIG9mIGEgYEdsb2JhbFNlY29uZGFyeUluZGV4UHJvcGVydHlgXG4gKlxuICogQHJldHVybnMgdGhlIHJlc3VsdCBvZiB0aGUgdmFsaWRhdGlvbi5cbiAqL1xuZnVuY3Rpb24gQ2ZuVGFibGVfR2xvYmFsU2Vjb25kYXJ5SW5kZXhQcm9wZXJ0eVZhbGlkYXRvcihwcm9wZXJ0aWVzOiBhbnkpOiBjZGsuVmFsaWRhdGlvblJlc3VsdCB7XG4gICAgaWYgKCFjZGsuY2FuSW5zcGVjdChwcm9wZXJ0aWVzKSkgeyByZXR1cm4gY2RrLlZBTElEQVRJT05fU1VDQ0VTUzsgfVxuICAgIGNvbnN0IGVycm9ycyA9IG5ldyBjZGsuVmFsaWRhdGlvblJlc3VsdHMoKTtcbiAgICBlcnJvcnMuY29sbGVjdChjZGsucHJvcGVydHlWYWxpZGF0b3IoJ2luZGV4TmFtZScsIGNkay5yZXF1aXJlZFZhbGlkYXRvcikocHJvcGVydGllcy5pbmRleE5hbWUpKTtcbiAgICBlcnJvcnMuY29sbGVjdChjZGsucHJvcGVydHlWYWxpZGF0b3IoJ2luZGV4TmFtZScsIGNkay52YWxpZGF0ZVN0cmluZykocHJvcGVydGllcy5pbmRleE5hbWUpKTtcbiAgICBlcnJvcnMuY29sbGVjdChjZGsucHJvcGVydHlWYWxpZGF0b3IoJ2tleVNjaGVtYScsIGNkay5yZXF1aXJlZFZhbGlkYXRvcikocHJvcGVydGllcy5rZXlTY2hlbWEpKTtcbiAgICBlcnJvcnMuY29sbGVjdChjZGsucHJvcGVydHlWYWxpZGF0b3IoJ2tleVNjaGVtYScsIGNkay5saXN0VmFsaWRhdG9yKENmblRhYmxlX0tleVNjaGVtYVByb3BlcnR5VmFsaWRhdG9yKSkocHJvcGVydGllcy5rZXlTY2hlbWEpKTtcbiAgICBlcnJvcnMuY29sbGVjdChjZGsucHJvcGVydHlWYWxpZGF0b3IoJ3Byb2plY3Rpb24nLCBjZGsucmVxdWlyZWRWYWxpZGF0b3IpKHByb3BlcnRpZXMucHJvamVjdGlvbikpO1xuICAgIGVycm9ycy5jb2xsZWN0KGNkay5wcm9wZXJ0eVZhbGlkYXRvcigncHJvamVjdGlvbicsIENmblRhYmxlX1Byb2plY3Rpb25Qcm9wZXJ0eVZhbGlkYXRvcikocHJvcGVydGllcy5wcm9qZWN0aW9uKSk7XG4gICAgZXJyb3JzLmNvbGxlY3QoY2RrLnByb3BlcnR5VmFsaWRhdG9yKCdwcm92aXNpb25lZFRocm91Z2hwdXQnLCBDZm5UYWJsZV9Qcm92aXNpb25lZFRocm91Z2hwdXRQcm9wZXJ0eVZhbGlkYXRvcikocHJvcGVydGllcy5wcm92aXNpb25lZFRocm91Z2hwdXQpKTtcbiAgICByZXR1cm4gZXJyb3JzLndyYXAoJ3N1cHBsaWVkIHByb3BlcnRpZXMgbm90IGNvcnJlY3QgZm9yIFwiR2xvYmFsU2Vjb25kYXJ5SW5kZXhQcm9wZXJ0eVwiJyk7XG59XG5cbi8qKlxuICogUmVuZGVycyB0aGUgQVdTIENsb3VkRm9ybWF0aW9uIHByb3BlcnRpZXMgb2YgYW4gYEFXUzo6RHluYW1vREI6OlRhYmxlLkdsb2JhbFNlY29uZGFyeUluZGV4YCByZXNvdXJjZVxuICpcbiAqIEBwYXJhbSBwcm9wZXJ0aWVzIC0gdGhlIFR5cGVTY3JpcHQgcHJvcGVydGllcyBvZiBhIGBHbG9iYWxTZWNvbmRhcnlJbmRleFByb3BlcnR5YFxuICpcbiAqIEByZXR1cm5zIHRoZSBBV1MgQ2xvdWRGb3JtYXRpb24gcHJvcGVydGllcyBvZiBhbiBgQVdTOjpEeW5hbW9EQjo6VGFibGUuR2xvYmFsU2Vjb25kYXJ5SW5kZXhgIHJlc291cmNlLlxuICovXG4vLyBAdHMtaWdub3JlIFRTNjEzM1xuZnVuY3Rpb24gY2ZuVGFibGVHbG9iYWxTZWNvbmRhcnlJbmRleFByb3BlcnR5VG9DbG91ZEZvcm1hdGlvbihwcm9wZXJ0aWVzOiBhbnkpOiBhbnkge1xuICAgIGlmICghY2RrLmNhbkluc3BlY3QocHJvcGVydGllcykpIHsgcmV0dXJuIHByb3BlcnRpZXM7IH1cbiAgICBDZm5UYWJsZV9HbG9iYWxTZWNvbmRhcnlJbmRleFByb3BlcnR5VmFsaWRhdG9yKHByb3BlcnRpZXMpLmFzc2VydFN1Y2Nlc3MoKTtcbiAgICByZXR1cm4ge1xuICAgICAgSW5kZXhOYW1lOiBjZGsuc3RyaW5nVG9DbG91ZEZvcm1hdGlvbihwcm9wZXJ0aWVzLmluZGV4TmFtZSksXG4gICAgICBLZXlTY2hlbWE6IGNkay5saXN0TWFwcGVyKGNmblRhYmxlS2V5U2NoZW1hUHJvcGVydHlUb0Nsb3VkRm9ybWF0aW9uKShwcm9wZXJ0aWVzLmtleVNjaGVtYSksXG4gICAgICBQcm9qZWN0aW9uOiBjZm5UYWJsZVByb2plY3Rpb25Qcm9wZXJ0eVRvQ2xvdWRGb3JtYXRpb24ocHJvcGVydGllcy5wcm9qZWN0aW9uKSxcbiAgICAgIFByb3Zpc2lvbmVkVGhyb3VnaHB1dDogY2ZuVGFibGVQcm92aXNpb25lZFRocm91Z2hwdXRQcm9wZXJ0eVRvQ2xvdWRGb3JtYXRpb24ocHJvcGVydGllcy5wcm92aXNpb25lZFRocm91Z2hwdXQpLFxuICAgIH07XG59XG5cbmV4cG9ydCBuYW1lc3BhY2UgQ2ZuVGFibGUge1xuICAgIC8qKlxuICAgICAqIEBzZWUgaHR0cDovL2RvY3MuYXdzLmFtYXpvbi5jb20vQVdTQ2xvdWRGb3JtYXRpb24vbGF0ZXN0L1VzZXJHdWlkZS9hd3MtcHJvcGVydGllcy1keW5hbW9kYi1rZXlzY2hlbWEuaHRtbFxuICAgICAqL1xuICAgIGV4cG9ydCBpbnRlcmZhY2UgS2V5U2NoZW1hUHJvcGVydHkge1xuICAgICAgICAvKipcbiAgICAgICAgICogYENmblRhYmxlLktleVNjaGVtYVByb3BlcnR5LkF0dHJpYnV0ZU5hbWVgXG4gICAgICAgICAqIEBzZWUgaHR0cDovL2RvY3MuYXdzLmFtYXpvbi5jb20vQVdTQ2xvdWRGb3JtYXRpb24vbGF0ZXN0L1VzZXJHdWlkZS9hd3MtcHJvcGVydGllcy1keW5hbW9kYi1rZXlzY2hlbWEuaHRtbCNhd3MtcHJvcGVydGllcy1keW5hbW9kYi1rZXlzY2hlbWEtYXR0cmlidXRlbmFtZVxuICAgICAgICAgKi9cbiAgICAgICAgYXR0cmlidXRlTmFtZTogc3RyaW5nO1xuICAgICAgICAvKipcbiAgICAgICAgICogYENmblRhYmxlLktleVNjaGVtYVByb3BlcnR5LktleVR5cGVgXG4gICAgICAgICAqIEBzZWUgaHR0cDovL2RvY3MuYXdzLmFtYXpvbi5jb20vQVdTQ2xvdWRGb3JtYXRpb24vbGF0ZXN0L1VzZXJHdWlkZS9hd3MtcHJvcGVydGllcy1keW5hbW9kYi1rZXlzY2hlbWEuaHRtbCNhd3MtcHJvcGVydGllcy1keW5hbW9kYi1rZXlzY2hlbWEta2V5dHlwZVxuICAgICAgICAgKi9cbiAgICAgICAga2V5VHlwZTogc3RyaW5nO1xuICAgIH1cbn1cblxuLyoqXG4gKiBEZXRlcm1pbmUgd2hldGhlciB0aGUgZ2l2ZW4gcHJvcGVydGllcyBtYXRjaCB0aG9zZSBvZiBhIGBLZXlTY2hlbWFQcm9wZXJ0eWBcbiAqXG4gKiBAcGFyYW0gcHJvcGVydGllcyAtIHRoZSBUeXBlU2NyaXB0IHByb3BlcnRpZXMgb2YgYSBgS2V5U2NoZW1hUHJvcGVydHlgXG4gKlxuICogQHJldHVybnMgdGhlIHJlc3VsdCBvZiB0aGUgdmFsaWRhdGlvbi5cbiAqL1xuZnVuY3Rpb24gQ2ZuVGFibGVfS2V5U2NoZW1hUHJvcGVydHlWYWxpZGF0b3IocHJvcGVydGllczogYW55KTogY2RrLlZhbGlkYXRpb25SZXN1bHQge1xuICAgIGlmICghY2RrLmNhbkluc3BlY3QocHJvcGVydGllcykpIHsgcmV0dXJuIGNkay5WQUxJREFUSU9OX1NVQ0NFU1M7IH1cbiAgICBjb25zdCBlcnJvcnMgPSBuZXcgY2RrLlZhbGlkYXRpb25SZXN1bHRzKCk7XG4gICAgZXJyb3JzLmNvbGxlY3QoY2RrLnByb3BlcnR5VmFsaWRhdG9yKCdhdHRyaWJ1dGVOYW1lJywgY2RrLnJlcXVpcmVkVmFsaWRhdG9yKShwcm9wZXJ0aWVzLmF0dHJpYnV0ZU5hbWUpKTtcbiAgICBlcnJvcnMuY29sbGVjdChjZGsucHJvcGVydHlWYWxpZGF0b3IoJ2F0dHJpYnV0ZU5hbWUnLCBjZGsudmFsaWRhdGVTdHJpbmcpKHByb3BlcnRpZXMuYXR0cmlidXRlTmFtZSkpO1xuICAgIGVycm9ycy5jb2xsZWN0KGNkay5wcm9wZXJ0eVZhbGlkYXRvcigna2V5VHlwZScsIGNkay5yZXF1aXJlZFZhbGlkYXRvcikocHJvcGVydGllcy5rZXlUeXBlKSk7XG4gICAgZXJyb3JzLmNvbGxlY3QoY2RrLnByb3BlcnR5VmFsaWRhdG9yKCdrZXlUeXBlJywgY2RrLnZhbGlkYXRlU3RyaW5nKShwcm9wZXJ0aWVzLmtleVR5cGUpKTtcbiAgICByZXR1cm4gZXJyb3JzLndyYXAoJ3N1cHBsaWVkIHByb3BlcnRpZXMgbm90IGNvcnJlY3QgZm9yIFwiS2V5U2NoZW1hUHJvcGVydHlcIicpO1xufVxuXG4vKipcbiAqIFJlbmRlcnMgdGhlIEFXUyBDbG91ZEZvcm1hdGlvbiBwcm9wZXJ0aWVzIG9mIGFuIGBBV1M6OkR5bmFtb0RCOjpUYWJsZS5LZXlTY2hlbWFgIHJlc291cmNlXG4gKlxuICogQHBhcmFtIHByb3BlcnRpZXMgLSB0aGUgVHlwZVNjcmlwdCBwcm9wZXJ0aWVzIG9mIGEgYEtleVNjaGVtYVByb3BlcnR5YFxuICpcbiAqIEByZXR1cm5zIHRoZSBBV1MgQ2xvdWRGb3JtYXRpb24gcHJvcGVydGllcyBvZiBhbiBgQVdTOjpEeW5hbW9EQjo6VGFibGUuS2V5U2NoZW1hYCByZXNvdXJjZS5cbiAqL1xuLy8gQHRzLWlnbm9yZSBUUzYxMzNcbmZ1bmN0aW9uIGNmblRhYmxlS2V5U2NoZW1hUHJvcGVydHlUb0Nsb3VkRm9ybWF0aW9uKHByb3BlcnRpZXM6IGFueSk6IGFueSB7XG4gICAgaWYgKCFjZGsuY2FuSW5zcGVjdChwcm9wZXJ0aWVzKSkgeyByZXR1cm4gcHJvcGVydGllczsgfVxuICAgIENmblRhYmxlX0tleVNjaGVtYVByb3BlcnR5VmFsaWRhdG9yKHByb3BlcnRpZXMpLmFzc2VydFN1Y2Nlc3MoKTtcbiAgICByZXR1cm4ge1xuICAgICAgQXR0cmlidXRlTmFtZTogY2RrLnN0cmluZ1RvQ2xvdWRGb3JtYXRpb24ocHJvcGVydGllcy5hdHRyaWJ1dGVOYW1lKSxcbiAgICAgIEtleVR5cGU6IGNkay5zdHJpbmdUb0Nsb3VkRm9ybWF0aW9uKHByb3BlcnRpZXMua2V5VHlwZSksXG4gICAgfTtcbn1cblxuZXhwb3J0IG5hbWVzcGFjZSBDZm5UYWJsZSB7XG4gICAgLyoqXG4gICAgICogQHNlZSBodHRwOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9BV1NDbG91ZEZvcm1hdGlvbi9sYXRlc3QvVXNlckd1aWRlL2F3cy1wcm9wZXJ0aWVzLWR5bmFtb2RiLWxzaS5odG1sXG4gICAgICovXG4gICAgZXhwb3J0IGludGVyZmFjZSBMb2NhbFNlY29uZGFyeUluZGV4UHJvcGVydHkge1xuICAgICAgICAvKipcbiAgICAgICAgICogYENmblRhYmxlLkxvY2FsU2Vjb25kYXJ5SW5kZXhQcm9wZXJ0eS5JbmRleE5hbWVgXG4gICAgICAgICAqIEBzZWUgaHR0cDovL2RvY3MuYXdzLmFtYXpvbi5jb20vQVdTQ2xvdWRGb3JtYXRpb24vbGF0ZXN0L1VzZXJHdWlkZS9hd3MtcHJvcGVydGllcy1keW5hbW9kYi1sc2kuaHRtbCNjZm4tZHluYW1vZGItbHNpLWluZGV4bmFtZVxuICAgICAgICAgKi9cbiAgICAgICAgaW5kZXhOYW1lOiBzdHJpbmc7XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBgQ2ZuVGFibGUuTG9jYWxTZWNvbmRhcnlJbmRleFByb3BlcnR5LktleVNjaGVtYWBcbiAgICAgICAgICogQHNlZSBodHRwOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9BV1NDbG91ZEZvcm1hdGlvbi9sYXRlc3QvVXNlckd1aWRlL2F3cy1wcm9wZXJ0aWVzLWR5bmFtb2RiLWxzaS5odG1sI2Nmbi1keW5hbW9kYi1sc2kta2V5c2NoZW1hXG4gICAgICAgICAqL1xuICAgICAgICBrZXlTY2hlbWE6IEFycmF5PENmblRhYmxlLktleVNjaGVtYVByb3BlcnR5IHwgY2RrLlRva2VuPiB8IGNkay5Ub2tlbjtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIGBDZm5UYWJsZS5Mb2NhbFNlY29uZGFyeUluZGV4UHJvcGVydHkuUHJvamVjdGlvbmBcbiAgICAgICAgICogQHNlZSBodHRwOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9BV1NDbG91ZEZvcm1hdGlvbi9sYXRlc3QvVXNlckd1aWRlL2F3cy1wcm9wZXJ0aWVzLWR5bmFtb2RiLWxzaS5odG1sI2Nmbi1keW5hbW9kYi1sc2ktcHJvamVjdGlvblxuICAgICAgICAgKi9cbiAgICAgICAgcHJvamVjdGlvbjogQ2ZuVGFibGUuUHJvamVjdGlvblByb3BlcnR5IHwgY2RrLlRva2VuO1xuICAgIH1cbn1cblxuLyoqXG4gKiBEZXRlcm1pbmUgd2hldGhlciB0aGUgZ2l2ZW4gcHJvcGVydGllcyBtYXRjaCB0aG9zZSBvZiBhIGBMb2NhbFNlY29uZGFyeUluZGV4UHJvcGVydHlgXG4gKlxuICogQHBhcmFtIHByb3BlcnRpZXMgLSB0aGUgVHlwZVNjcmlwdCBwcm9wZXJ0aWVzIG9mIGEgYExvY2FsU2Vjb25kYXJ5SW5kZXhQcm9wZXJ0eWBcbiAqXG4gKiBAcmV0dXJucyB0aGUgcmVzdWx0IG9mIHRoZSB2YWxpZGF0aW9uLlxuICovXG5mdW5jdGlvbiBDZm5UYWJsZV9Mb2NhbFNlY29uZGFyeUluZGV4UHJvcGVydHlWYWxpZGF0b3IocHJvcGVydGllczogYW55KTogY2RrLlZhbGlkYXRpb25SZXN1bHQge1xuICAgIGlmICghY2RrLmNhbkluc3BlY3QocHJvcGVydGllcykpIHsgcmV0dXJuIGNkay5WQUxJREFUSU9OX1NVQ0NFU1M7IH1cbiAgICBjb25zdCBlcnJvcnMgPSBuZXcgY2RrLlZhbGlkYXRpb25SZXN1bHRzKCk7XG4gICAgZXJyb3JzLmNvbGxlY3QoY2RrLnByb3BlcnR5VmFsaWRhdG9yKCdpbmRleE5hbWUnLCBjZGsucmVxdWlyZWRWYWxpZGF0b3IpKHByb3BlcnRpZXMuaW5kZXhOYW1lKSk7XG4gICAgZXJyb3JzLmNvbGxlY3QoY2RrLnByb3BlcnR5VmFsaWRhdG9yKCdpbmRleE5hbWUnLCBjZGsudmFsaWRhdGVTdHJpbmcpKHByb3BlcnRpZXMuaW5kZXhOYW1lKSk7XG4gICAgZXJyb3JzLmNvbGxlY3QoY2RrLnByb3BlcnR5VmFsaWRhdG9yKCdrZXlTY2hlbWEnLCBjZGsucmVxdWlyZWRWYWxpZGF0b3IpKHByb3BlcnRpZXMua2V5U2NoZW1hKSk7XG4gICAgZXJyb3JzLmNvbGxlY3QoY2RrLnByb3BlcnR5VmFsaWRhdG9yKCdrZXlTY2hlbWEnLCBjZGsubGlzdFZhbGlkYXRvcihDZm5UYWJsZV9LZXlTY2hlbWFQcm9wZXJ0eVZhbGlkYXRvcikpKHByb3BlcnRpZXMua2V5U2NoZW1hKSk7XG4gICAgZXJyb3JzLmNvbGxlY3QoY2RrLnByb3BlcnR5VmFsaWRhdG9yKCdwcm9qZWN0aW9uJywgY2RrLnJlcXVpcmVkVmFsaWRhdG9yKShwcm9wZXJ0aWVzLnByb2plY3Rpb24pKTtcbiAgICBlcnJvcnMuY29sbGVjdChjZGsucHJvcGVydHlWYWxpZGF0b3IoJ3Byb2plY3Rpb24nLCBDZm5UYWJsZV9Qcm9qZWN0aW9uUHJvcGVydHlWYWxpZGF0b3IpKHByb3BlcnRpZXMucHJvamVjdGlvbikpO1xuICAgIHJldHVybiBlcnJvcnMud3JhcCgnc3VwcGxpZWQgcHJvcGVydGllcyBub3QgY29ycmVjdCBmb3IgXCJMb2NhbFNlY29uZGFyeUluZGV4UHJvcGVydHlcIicpO1xufVxuXG4vKipcbiAqIFJlbmRlcnMgdGhlIEFXUyBDbG91ZEZvcm1hdGlvbiBwcm9wZXJ0aWVzIG9mIGFuIGBBV1M6OkR5bmFtb0RCOjpUYWJsZS5Mb2NhbFNlY29uZGFyeUluZGV4YCByZXNvdXJjZVxuICpcbiAqIEBwYXJhbSBwcm9wZXJ0aWVzIC0gdGhlIFR5cGVTY3JpcHQgcHJvcGVydGllcyBvZiBhIGBMb2NhbFNlY29uZGFyeUluZGV4UHJvcGVydHlgXG4gKlxuICogQHJldHVybnMgdGhlIEFXUyBDbG91ZEZvcm1hdGlvbiBwcm9wZXJ0aWVzIG9mIGFuIGBBV1M6OkR5bmFtb0RCOjpUYWJsZS5Mb2NhbFNlY29uZGFyeUluZGV4YCByZXNvdXJjZS5cbiAqL1xuLy8gQHRzLWlnbm9yZSBUUzYxMzNcbmZ1bmN0aW9uIGNmblRhYmxlTG9jYWxTZWNvbmRhcnlJbmRleFByb3BlcnR5VG9DbG91ZEZvcm1hdGlvbihwcm9wZXJ0aWVzOiBhbnkpOiBhbnkge1xuICAgIGlmICghY2RrLmNhbkluc3BlY3QocHJvcGVydGllcykpIHsgcmV0dXJuIHByb3BlcnRpZXM7IH1cbiAgICBDZm5UYWJsZV9Mb2NhbFNlY29uZGFyeUluZGV4UHJvcGVydHlWYWxpZGF0b3IocHJvcGVydGllcykuYXNzZXJ0U3VjY2VzcygpO1xuICAgIHJldHVybiB7XG4gICAgICBJbmRleE5hbWU6IGNkay5zdHJpbmdUb0Nsb3VkRm9ybWF0aW9uKHByb3BlcnRpZXMuaW5kZXhOYW1lKSxcbiAgICAgIEtleVNjaGVtYTogY2RrLmxpc3RNYXBwZXIoY2ZuVGFibGVLZXlTY2hlbWFQcm9wZXJ0eVRvQ2xvdWRGb3JtYXRpb24pKHByb3BlcnRpZXMua2V5U2NoZW1hKSxcbiAgICAgIFByb2plY3Rpb246IGNmblRhYmxlUHJvamVjdGlvblByb3BlcnR5VG9DbG91ZEZvcm1hdGlvbihwcm9wZXJ0aWVzLnByb2plY3Rpb24pLFxuICAgIH07XG59XG5cbmV4cG9ydCBuYW1lc3BhY2UgQ2ZuVGFibGUge1xuICAgIC8qKlxuICAgICAqIEBzZWUgaHR0cDovL2RvY3MuYXdzLmFtYXpvbi5jb20vQVdTQ2xvdWRGb3JtYXRpb24vbGF0ZXN0L1VzZXJHdWlkZS9hd3MtcHJvcGVydGllcy1keW5hbW9kYi10YWJsZS1wb2ludGludGltZXJlY292ZXJ5c3BlY2lmaWNhdGlvbi5odG1sXG4gICAgICovXG4gICAgZXhwb3J0IGludGVyZmFjZSBQb2ludEluVGltZVJlY292ZXJ5U3BlY2lmaWNhdGlvblByb3BlcnR5IHtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIGBDZm5UYWJsZS5Qb2ludEluVGltZVJlY292ZXJ5U3BlY2lmaWNhdGlvblByb3BlcnR5LlBvaW50SW5UaW1lUmVjb3ZlcnlFbmFibGVkYFxuICAgICAgICAgKiBAc2VlIGh0dHA6Ly9kb2NzLmF3cy5hbWF6b24uY29tL0FXU0Nsb3VkRm9ybWF0aW9uL2xhdGVzdC9Vc2VyR3VpZGUvYXdzLXByb3BlcnRpZXMtZHluYW1vZGItdGFibGUtcG9pbnRpbnRpbWVyZWNvdmVyeXNwZWNpZmljYXRpb24uaHRtbCNjZm4tZHluYW1vZGItdGFibGUtcG9pbnRpbnRpbWVyZWNvdmVyeXNwZWNpZmljYXRpb24tcG9pbnRpbnRpbWVyZWNvdmVyeWVuYWJsZWRcbiAgICAgICAgICovXG4gICAgICAgIHBvaW50SW5UaW1lUmVjb3ZlcnlFbmFibGVkPzogYm9vbGVhbiB8IGNkay5Ub2tlbjtcbiAgICB9XG59XG5cbi8qKlxuICogRGV0ZXJtaW5lIHdoZXRoZXIgdGhlIGdpdmVuIHByb3BlcnRpZXMgbWF0Y2ggdGhvc2Ugb2YgYSBgUG9pbnRJblRpbWVSZWNvdmVyeVNwZWNpZmljYXRpb25Qcm9wZXJ0eWBcbiAqXG4gKiBAcGFyYW0gcHJvcGVydGllcyAtIHRoZSBUeXBlU2NyaXB0IHByb3BlcnRpZXMgb2YgYSBgUG9pbnRJblRpbWVSZWNvdmVyeVNwZWNpZmljYXRpb25Qcm9wZXJ0eWBcbiAqXG4gKiBAcmV0dXJucyB0aGUgcmVzdWx0IG9mIHRoZSB2YWxpZGF0aW9uLlxuICovXG5mdW5jdGlvbiBDZm5UYWJsZV9Qb2ludEluVGltZVJlY292ZXJ5U3BlY2lmaWNhdGlvblByb3BlcnR5VmFsaWRhdG9yKHByb3BlcnRpZXM6IGFueSk6IGNkay5WYWxpZGF0aW9uUmVzdWx0IHtcbiAgICBpZiAoIWNkay5jYW5JbnNwZWN0KHByb3BlcnRpZXMpKSB7IHJldHVybiBjZGsuVkFMSURBVElPTl9TVUNDRVNTOyB9XG4gICAgY29uc3QgZXJyb3JzID0gbmV3IGNkay5WYWxpZGF0aW9uUmVzdWx0cygpO1xuICAgIGVycm9ycy5jb2xsZWN0KGNkay5wcm9wZXJ0eVZhbGlkYXRvcigncG9pbnRJblRpbWVSZWNvdmVyeUVuYWJsZWQnLCBjZGsudmFsaWRhdGVCb29sZWFuKShwcm9wZXJ0aWVzLnBvaW50SW5UaW1lUmVjb3ZlcnlFbmFibGVkKSk7XG4gICAgcmV0dXJuIGVycm9ycy53cmFwKCdzdXBwbGllZCBwcm9wZXJ0aWVzIG5vdCBjb3JyZWN0IGZvciBcIlBvaW50SW5UaW1lUmVjb3ZlcnlTcGVjaWZpY2F0aW9uUHJvcGVydHlcIicpO1xufVxuXG4vKipcbiAqIFJlbmRlcnMgdGhlIEFXUyBDbG91ZEZvcm1hdGlvbiBwcm9wZXJ0aWVzIG9mIGFuIGBBV1M6OkR5bmFtb0RCOjpUYWJsZS5Qb2ludEluVGltZVJlY292ZXJ5U3BlY2lmaWNhdGlvbmAgcmVzb3VyY2VcbiAqXG4gKiBAcGFyYW0gcHJvcGVydGllcyAtIHRoZSBUeXBlU2NyaXB0IHByb3BlcnRpZXMgb2YgYSBgUG9pbnRJblRpbWVSZWNvdmVyeVNwZWNpZmljYXRpb25Qcm9wZXJ0eWBcbiAqXG4gKiBAcmV0dXJucyB0aGUgQVdTIENsb3VkRm9ybWF0aW9uIHByb3BlcnRpZXMgb2YgYW4gYEFXUzo6RHluYW1vREI6OlRhYmxlLlBvaW50SW5UaW1lUmVjb3ZlcnlTcGVjaWZpY2F0aW9uYCByZXNvdXJjZS5cbiAqL1xuLy8gQHRzLWlnbm9yZSBUUzYxMzNcbmZ1bmN0aW9uIGNmblRhYmxlUG9pbnRJblRpbWVSZWNvdmVyeVNwZWNpZmljYXRpb25Qcm9wZXJ0eVRvQ2xvdWRGb3JtYXRpb24ocHJvcGVydGllczogYW55KTogYW55IHtcbiAgICBpZiAoIWNkay5jYW5JbnNwZWN0KHByb3BlcnRpZXMpKSB7IHJldHVybiBwcm9wZXJ0aWVzOyB9XG4gICAgQ2ZuVGFibGVfUG9pbnRJblRpbWVSZWNvdmVyeVNwZWNpZmljYXRpb25Qcm9wZXJ0eVZhbGlkYXRvcihwcm9wZXJ0aWVzKS5hc3NlcnRTdWNjZXNzKCk7XG4gICAgcmV0dXJuIHtcbiAgICAgIFBvaW50SW5UaW1lUmVjb3ZlcnlFbmFibGVkOiBjZGsuYm9vbGVhblRvQ2xvdWRGb3JtYXRpb24ocHJvcGVydGllcy5wb2ludEluVGltZVJlY292ZXJ5RW5hYmxlZCksXG4gICAgfTtcbn1cblxuZXhwb3J0IG5hbWVzcGFjZSBDZm5UYWJsZSB7XG4gICAgLyoqXG4gICAgICogQHNlZSBodHRwOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9BV1NDbG91ZEZvcm1hdGlvbi9sYXRlc3QvVXNlckd1aWRlL2F3cy1wcm9wZXJ0aWVzLWR5bmFtb2RiLXByb2plY3Rpb25vYmplY3QuaHRtbFxuICAgICAqL1xuICAgIGV4cG9ydCBpbnRlcmZhY2UgUHJvamVjdGlvblByb3BlcnR5IHtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIGBDZm5UYWJsZS5Qcm9qZWN0aW9uUHJvcGVydHkuTm9uS2V5QXR0cmlidXRlc2BcbiAgICAgICAgICogQHNlZSBodHRwOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9BV1NDbG91ZEZvcm1hdGlvbi9sYXRlc3QvVXNlckd1aWRlL2F3cy1wcm9wZXJ0aWVzLWR5bmFtb2RiLXByb2plY3Rpb25vYmplY3QuaHRtbCNjZm4tZHluYW1vZGItcHJvamVjdGlvbm9iai1ub25rZXlhdHRcbiAgICAgICAgICovXG4gICAgICAgIG5vbktleUF0dHJpYnV0ZXM/OiBzdHJpbmdbXTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIGBDZm5UYWJsZS5Qcm9qZWN0aW9uUHJvcGVydHkuUHJvamVjdGlvblR5cGVgXG4gICAgICAgICAqIEBzZWUgaHR0cDovL2RvY3MuYXdzLmFtYXpvbi5jb20vQVdTQ2xvdWRGb3JtYXRpb24vbGF0ZXN0L1VzZXJHdWlkZS9hd3MtcHJvcGVydGllcy1keW5hbW9kYi1wcm9qZWN0aW9ub2JqZWN0Lmh0bWwjY2ZuLWR5bmFtb2RiLXByb2plY3Rpb25vYmotcHJvanR5cGVcbiAgICAgICAgICovXG4gICAgICAgIHByb2plY3Rpb25UeXBlPzogc3RyaW5nO1xuICAgIH1cbn1cblxuLyoqXG4gKiBEZXRlcm1pbmUgd2hldGhlciB0aGUgZ2l2ZW4gcHJvcGVydGllcyBtYXRjaCB0aG9zZSBvZiBhIGBQcm9qZWN0aW9uUHJvcGVydHlgXG4gKlxuICogQHBhcmFtIHByb3BlcnRpZXMgLSB0aGUgVHlwZVNjcmlwdCBwcm9wZXJ0aWVzIG9mIGEgYFByb2plY3Rpb25Qcm9wZXJ0eWBcbiAqXG4gKiBAcmV0dXJucyB0aGUgcmVzdWx0IG9mIHRoZSB2YWxpZGF0aW9uLlxuICovXG5mdW5jdGlvbiBDZm5UYWJsZV9Qcm9qZWN0aW9uUHJvcGVydHlWYWxpZGF0b3IocHJvcGVydGllczogYW55KTogY2RrLlZhbGlkYXRpb25SZXN1bHQge1xuICAgIGlmICghY2RrLmNhbkluc3BlY3QocHJvcGVydGllcykpIHsgcmV0dXJuIGNkay5WQUxJREFUSU9OX1NVQ0NFU1M7IH1cbiAgICBjb25zdCBlcnJvcnMgPSBuZXcgY2RrLlZhbGlkYXRpb25SZXN1bHRzKCk7XG4gICAgZXJyb3JzLmNvbGxlY3QoY2RrLnByb3BlcnR5VmFsaWRhdG9yKCdub25LZXlBdHRyaWJ1dGVzJywgY2RrLmxpc3RWYWxpZGF0b3IoY2RrLnZhbGlkYXRlU3RyaW5nKSkocHJvcGVydGllcy5ub25LZXlBdHRyaWJ1dGVzKSk7XG4gICAgZXJyb3JzLmNvbGxlY3QoY2RrLnByb3BlcnR5VmFsaWRhdG9yKCdwcm9qZWN0aW9uVHlwZScsIGNkay52YWxpZGF0ZVN0cmluZykocHJvcGVydGllcy5wcm9qZWN0aW9uVHlwZSkpO1xuICAgIHJldHVybiBlcnJvcnMud3JhcCgnc3VwcGxpZWQgcHJvcGVydGllcyBub3QgY29ycmVjdCBmb3IgXCJQcm9qZWN0aW9uUHJvcGVydHlcIicpO1xufVxuXG4vKipcbiAqIFJlbmRlcnMgdGhlIEFXUyBDbG91ZEZvcm1hdGlvbiBwcm9wZXJ0aWVzIG9mIGFuIGBBV1M6OkR5bmFtb0RCOjpUYWJsZS5Qcm9qZWN0aW9uYCByZXNvdXJjZVxuICpcbiAqIEBwYXJhbSBwcm9wZXJ0aWVzIC0gdGhlIFR5cGVTY3JpcHQgcHJvcGVydGllcyBvZiBhIGBQcm9qZWN0aW9uUHJvcGVydHlgXG4gKlxuICogQHJldHVybnMgdGhlIEFXUyBDbG91ZEZvcm1hdGlvbiBwcm9wZXJ0aWVzIG9mIGFuIGBBV1M6OkR5bmFtb0RCOjpUYWJsZS5Qcm9qZWN0aW9uYCByZXNvdXJjZS5cbiAqL1xuLy8gQHRzLWlnbm9yZSBUUzYxMzNcbmZ1bmN0aW9uIGNmblRhYmxlUHJvamVjdGlvblByb3BlcnR5VG9DbG91ZEZvcm1hdGlvbihwcm9wZXJ0aWVzOiBhbnkpOiBhbnkge1xuICAgIGlmICghY2RrLmNhbkluc3BlY3QocHJvcGVydGllcykpIHsgcmV0dXJuIHByb3BlcnRpZXM7IH1cbiAgICBDZm5UYWJsZV9Qcm9qZWN0aW9uUHJvcGVydHlWYWxpZGF0b3IocHJvcGVydGllcykuYXNzZXJ0U3VjY2VzcygpO1xuICAgIHJldHVybiB7XG4gICAgICBOb25LZXlBdHRyaWJ1dGVzOiBjZGsubGlzdE1hcHBlcihjZGsuc3RyaW5nVG9DbG91ZEZvcm1hdGlvbikocHJvcGVydGllcy5ub25LZXlBdHRyaWJ1dGVzKSxcbiAgICAgIFByb2plY3Rpb25UeXBlOiBjZGsuc3RyaW5nVG9DbG91ZEZvcm1hdGlvbihwcm9wZXJ0aWVzLnByb2plY3Rpb25UeXBlKSxcbiAgICB9O1xufVxuXG5leHBvcnQgbmFtZXNwYWNlIENmblRhYmxlIHtcbiAgICAvKipcbiAgICAgKiBAc2VlIGh0dHA6Ly9kb2NzLmF3cy5hbWF6b24uY29tL0FXU0Nsb3VkRm9ybWF0aW9uL2xhdGVzdC9Vc2VyR3VpZGUvYXdzLXByb3BlcnRpZXMtZHluYW1vZGItcHJvdmlzaW9uZWR0aHJvdWdocHV0Lmh0bWxcbiAgICAgKi9cbiAgICBleHBvcnQgaW50ZXJmYWNlIFByb3Zpc2lvbmVkVGhyb3VnaHB1dFByb3BlcnR5IHtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIGBDZm5UYWJsZS5Qcm92aXNpb25lZFRocm91Z2hwdXRQcm9wZXJ0eS5SZWFkQ2FwYWNpdHlVbml0c2BcbiAgICAgICAgICogQHNlZSBodHRwOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9BV1NDbG91ZEZvcm1hdGlvbi9sYXRlc3QvVXNlckd1aWRlL2F3cy1wcm9wZXJ0aWVzLWR5bmFtb2RiLXByb3Zpc2lvbmVkdGhyb3VnaHB1dC5odG1sI2Nmbi1keW5hbW9kYi1wcm92aXNpb25lZHRocm91Z2hwdXQtcmVhZGNhcGFjaXR5dW5pdHNcbiAgICAgICAgICovXG4gICAgICAgIHJlYWRDYXBhY2l0eVVuaXRzOiBudW1iZXIgfCBjZGsuVG9rZW47XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBgQ2ZuVGFibGUuUHJvdmlzaW9uZWRUaHJvdWdocHV0UHJvcGVydHkuV3JpdGVDYXBhY2l0eVVuaXRzYFxuICAgICAgICAgKiBAc2VlIGh0dHA6Ly9kb2NzLmF3cy5hbWF6b24uY29tL0FXU0Nsb3VkRm9ybWF0aW9uL2xhdGVzdC9Vc2VyR3VpZGUvYXdzLXByb3BlcnRpZXMtZHluYW1vZGItcHJvdmlzaW9uZWR0aHJvdWdocHV0Lmh0bWwjY2ZuLWR5bmFtb2RiLXByb3Zpc2lvbmVkdGhyb3VnaHB1dC13cml0ZWNhcGFjaXR5dW5pdHNcbiAgICAgICAgICovXG4gICAgICAgIHdyaXRlQ2FwYWNpdHlVbml0czogbnVtYmVyIHwgY2RrLlRva2VuO1xuICAgIH1cbn1cblxuLyoqXG4gKiBEZXRlcm1pbmUgd2hldGhlciB0aGUgZ2l2ZW4gcHJvcGVydGllcyBtYXRjaCB0aG9zZSBvZiBhIGBQcm92aXNpb25lZFRocm91Z2hwdXRQcm9wZXJ0eWBcbiAqXG4gKiBAcGFyYW0gcHJvcGVydGllcyAtIHRoZSBUeXBlU2NyaXB0IHByb3BlcnRpZXMgb2YgYSBgUHJvdmlzaW9uZWRUaHJvdWdocHV0UHJvcGVydHlgXG4gKlxuICogQHJldHVybnMgdGhlIHJlc3VsdCBvZiB0aGUgdmFsaWRhdGlvbi5cbiAqL1xuZnVuY3Rpb24gQ2ZuVGFibGVfUHJvdmlzaW9uZWRUaHJvdWdocHV0UHJvcGVydHlWYWxpZGF0b3IocHJvcGVydGllczogYW55KTogY2RrLlZhbGlkYXRpb25SZXN1bHQge1xuICAgIGlmICghY2RrLmNhbkluc3BlY3QocHJvcGVydGllcykpIHsgcmV0dXJuIGNkay5WQUxJREFUSU9OX1NVQ0NFU1M7IH1cbiAgICBjb25zdCBlcnJvcnMgPSBuZXcgY2RrLlZhbGlkYXRpb25SZXN1bHRzKCk7XG4gICAgZXJyb3JzLmNvbGxlY3QoY2RrLnByb3BlcnR5VmFsaWRhdG9yKCdyZWFkQ2FwYWNpdHlVbml0cycsIGNkay5yZXF1aXJlZFZhbGlkYXRvcikocHJvcGVydGllcy5yZWFkQ2FwYWNpdHlVbml0cykpO1xuICAgIGVycm9ycy5jb2xsZWN0KGNkay5wcm9wZXJ0eVZhbGlkYXRvcigncmVhZENhcGFjaXR5VW5pdHMnLCBjZGsudmFsaWRhdGVOdW1iZXIpKHByb3BlcnRpZXMucmVhZENhcGFjaXR5VW5pdHMpKTtcbiAgICBlcnJvcnMuY29sbGVjdChjZGsucHJvcGVydHlWYWxpZGF0b3IoJ3dyaXRlQ2FwYWNpdHlVbml0cycsIGNkay5yZXF1aXJlZFZhbGlkYXRvcikocHJvcGVydGllcy53cml0ZUNhcGFjaXR5VW5pdHMpKTtcbiAgICBlcnJvcnMuY29sbGVjdChjZGsucHJvcGVydHlWYWxpZGF0b3IoJ3dyaXRlQ2FwYWNpdHlVbml0cycsIGNkay52YWxpZGF0ZU51bWJlcikocHJvcGVydGllcy53cml0ZUNhcGFjaXR5VW5pdHMpKTtcbiAgICByZXR1cm4gZXJyb3JzLndyYXAoJ3N1cHBsaWVkIHByb3BlcnRpZXMgbm90IGNvcnJlY3QgZm9yIFwiUHJvdmlzaW9uZWRUaHJvdWdocHV0UHJvcGVydHlcIicpO1xufVxuXG4vKipcbiAqIFJlbmRlcnMgdGhlIEFXUyBDbG91ZEZvcm1hdGlvbiBwcm9wZXJ0aWVzIG9mIGFuIGBBV1M6OkR5bmFtb0RCOjpUYWJsZS5Qcm92aXNpb25lZFRocm91Z2hwdXRgIHJlc291cmNlXG4gKlxuICogQHBhcmFtIHByb3BlcnRpZXMgLSB0aGUgVHlwZVNjcmlwdCBwcm9wZXJ0aWVzIG9mIGEgYFByb3Zpc2lvbmVkVGhyb3VnaHB1dFByb3BlcnR5YFxuICpcbiAqIEByZXR1cm5zIHRoZSBBV1MgQ2xvdWRGb3JtYXRpb24gcHJvcGVydGllcyBvZiBhbiBgQVdTOjpEeW5hbW9EQjo6VGFibGUuUHJvdmlzaW9uZWRUaHJvdWdocHV0YCByZXNvdXJjZS5cbiAqL1xuLy8gQHRzLWlnbm9yZSBUUzYxMzNcbmZ1bmN0aW9uIGNmblRhYmxlUHJvdmlzaW9uZWRUaHJvdWdocHV0UHJvcGVydHlUb0Nsb3VkRm9ybWF0aW9uKHByb3BlcnRpZXM6IGFueSk6IGFueSB7XG4gICAgaWYgKCFjZGsuY2FuSW5zcGVjdChwcm9wZXJ0aWVzKSkgeyByZXR1cm4gcHJvcGVydGllczsgfVxuICAgIENmblRhYmxlX1Byb3Zpc2lvbmVkVGhyb3VnaHB1dFByb3BlcnR5VmFsaWRhdG9yKHByb3BlcnRpZXMpLmFzc2VydFN1Y2Nlc3MoKTtcbiAgICByZXR1cm4ge1xuICAgICAgUmVhZENhcGFjaXR5VW5pdHM6IGNkay5udW1iZXJUb0Nsb3VkRm9ybWF0aW9uKHByb3BlcnRpZXMucmVhZENhcGFjaXR5VW5pdHMpLFxuICAgICAgV3JpdGVDYXBhY2l0eVVuaXRzOiBjZGsubnVtYmVyVG9DbG91ZEZvcm1hdGlvbihwcm9wZXJ0aWVzLndyaXRlQ2FwYWNpdHlVbml0cyksXG4gICAgfTtcbn1cblxuZXhwb3J0IG5hbWVzcGFjZSBDZm5UYWJsZSB7XG4gICAgLyoqXG4gICAgICogQHNlZSBodHRwOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9BV1NDbG91ZEZvcm1hdGlvbi9sYXRlc3QvVXNlckd1aWRlL2F3cy1wcm9wZXJ0aWVzLWR5bmFtb2RiLXRhYmxlLXNzZXNwZWNpZmljYXRpb24uaHRtbFxuICAgICAqL1xuICAgIGV4cG9ydCBpbnRlcmZhY2UgU1NFU3BlY2lmaWNhdGlvblByb3BlcnR5IHtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIGBDZm5UYWJsZS5TU0VTcGVjaWZpY2F0aW9uUHJvcGVydHkuU1NFRW5hYmxlZGBcbiAgICAgICAgICogQHNlZSBodHRwOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9BV1NDbG91ZEZvcm1hdGlvbi9sYXRlc3QvVXNlckd1aWRlL2F3cy1wcm9wZXJ0aWVzLWR5bmFtb2RiLXRhYmxlLXNzZXNwZWNpZmljYXRpb24uaHRtbCNjZm4tZHluYW1vZGItdGFibGUtc3Nlc3BlY2lmaWNhdGlvbi1zc2VlbmFibGVkXG4gICAgICAgICAqL1xuICAgICAgICBzc2VFbmFibGVkOiBib29sZWFuIHwgY2RrLlRva2VuO1xuICAgIH1cbn1cblxuLyoqXG4gKiBEZXRlcm1pbmUgd2hldGhlciB0aGUgZ2l2ZW4gcHJvcGVydGllcyBtYXRjaCB0aG9zZSBvZiBhIGBTU0VTcGVjaWZpY2F0aW9uUHJvcGVydHlgXG4gKlxuICogQHBhcmFtIHByb3BlcnRpZXMgLSB0aGUgVHlwZVNjcmlwdCBwcm9wZXJ0aWVzIG9mIGEgYFNTRVNwZWNpZmljYXRpb25Qcm9wZXJ0eWBcbiAqXG4gKiBAcmV0dXJucyB0aGUgcmVzdWx0IG9mIHRoZSB2YWxpZGF0aW9uLlxuICovXG5mdW5jdGlvbiBDZm5UYWJsZV9TU0VTcGVjaWZpY2F0aW9uUHJvcGVydHlWYWxpZGF0b3IocHJvcGVydGllczogYW55KTogY2RrLlZhbGlkYXRpb25SZXN1bHQge1xuICAgIGlmICghY2RrLmNhbkluc3BlY3QocHJvcGVydGllcykpIHsgcmV0dXJuIGNkay5WQUxJREFUSU9OX1NVQ0NFU1M7IH1cbiAgICBjb25zdCBlcnJvcnMgPSBuZXcgY2RrLlZhbGlkYXRpb25SZXN1bHRzKCk7XG4gICAgZXJyb3JzLmNvbGxlY3QoY2RrLnByb3BlcnR5VmFsaWRhdG9yKCdzc2VFbmFibGVkJywgY2RrLnJlcXVpcmVkVmFsaWRhdG9yKShwcm9wZXJ0aWVzLnNzZUVuYWJsZWQpKTtcbiAgICBlcnJvcnMuY29sbGVjdChjZGsucHJvcGVydHlWYWxpZGF0b3IoJ3NzZUVuYWJsZWQnLCBjZGsudmFsaWRhdGVCb29sZWFuKShwcm9wZXJ0aWVzLnNzZUVuYWJsZWQpKTtcbiAgICByZXR1cm4gZXJyb3JzLndyYXAoJ3N1cHBsaWVkIHByb3BlcnRpZXMgbm90IGNvcnJlY3QgZm9yIFwiU1NFU3BlY2lmaWNhdGlvblByb3BlcnR5XCInKTtcbn1cblxuLyoqXG4gKiBSZW5kZXJzIHRoZSBBV1MgQ2xvdWRGb3JtYXRpb24gcHJvcGVydGllcyBvZiBhbiBgQVdTOjpEeW5hbW9EQjo6VGFibGUuU1NFU3BlY2lmaWNhdGlvbmAgcmVzb3VyY2VcbiAqXG4gKiBAcGFyYW0gcHJvcGVydGllcyAtIHRoZSBUeXBlU2NyaXB0IHByb3BlcnRpZXMgb2YgYSBgU1NFU3BlY2lmaWNhdGlvblByb3BlcnR5YFxuICpcbiAqIEByZXR1cm5zIHRoZSBBV1MgQ2xvdWRGb3JtYXRpb24gcHJvcGVydGllcyBvZiBhbiBgQVdTOjpEeW5hbW9EQjo6VGFibGUuU1NFU3BlY2lmaWNhdGlvbmAgcmVzb3VyY2UuXG4gKi9cbi8vIEB0cy1pZ25vcmUgVFM2MTMzXG5mdW5jdGlvbiBjZm5UYWJsZVNTRVNwZWNpZmljYXRpb25Qcm9wZXJ0eVRvQ2xvdWRGb3JtYXRpb24ocHJvcGVydGllczogYW55KTogYW55IHtcbiAgICBpZiAoIWNkay5jYW5JbnNwZWN0KHByb3BlcnRpZXMpKSB7IHJldHVybiBwcm9wZXJ0aWVzOyB9XG4gICAgQ2ZuVGFibGVfU1NFU3BlY2lmaWNhdGlvblByb3BlcnR5VmFsaWRhdG9yKHByb3BlcnRpZXMpLmFzc2VydFN1Y2Nlc3MoKTtcbiAgICByZXR1cm4ge1xuICAgICAgU1NFRW5hYmxlZDogY2RrLmJvb2xlYW5Ub0Nsb3VkRm9ybWF0aW9uKHByb3BlcnRpZXMuc3NlRW5hYmxlZCksXG4gICAgfTtcbn1cblxuZXhwb3J0IG5hbWVzcGFjZSBDZm5UYWJsZSB7XG4gICAgLyoqXG4gICAgICogQHNlZSBodHRwOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9BV1NDbG91ZEZvcm1hdGlvbi9sYXRlc3QvVXNlckd1aWRlL2F3cy1wcm9wZXJ0aWVzLWR5bmFtb2RiLXN0cmVhbXNwZWNpZmljYXRpb24uaHRtbFxuICAgICAqL1xuICAgIGV4cG9ydCBpbnRlcmZhY2UgU3RyZWFtU3BlY2lmaWNhdGlvblByb3BlcnR5IHtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIGBDZm5UYWJsZS5TdHJlYW1TcGVjaWZpY2F0aW9uUHJvcGVydHkuU3RyZWFtVmlld1R5cGVgXG4gICAgICAgICAqIEBzZWUgaHR0cDovL2RvY3MuYXdzLmFtYXpvbi5jb20vQVdTQ2xvdWRGb3JtYXRpb24vbGF0ZXN0L1VzZXJHdWlkZS9hd3MtcHJvcGVydGllcy1keW5hbW9kYi1zdHJlYW1zcGVjaWZpY2F0aW9uLmh0bWwjY2ZuLWR5bmFtb2RiLXN0cmVhbXNwZWNpZmljYXRpb24tc3RyZWFtdmlld3R5cGVcbiAgICAgICAgICovXG4gICAgICAgIHN0cmVhbVZpZXdUeXBlOiBzdHJpbmc7XG4gICAgfVxufVxuXG4vKipcbiAqIERldGVybWluZSB3aGV0aGVyIHRoZSBnaXZlbiBwcm9wZXJ0aWVzIG1hdGNoIHRob3NlIG9mIGEgYFN0cmVhbVNwZWNpZmljYXRpb25Qcm9wZXJ0eWBcbiAqXG4gKiBAcGFyYW0gcHJvcGVydGllcyAtIHRoZSBUeXBlU2NyaXB0IHByb3BlcnRpZXMgb2YgYSBgU3RyZWFtU3BlY2lmaWNhdGlvblByb3BlcnR5YFxuICpcbiAqIEByZXR1cm5zIHRoZSByZXN1bHQgb2YgdGhlIHZhbGlkYXRpb24uXG4gKi9cbmZ1bmN0aW9uIENmblRhYmxlX1N0cmVhbVNwZWNpZmljYXRpb25Qcm9wZXJ0eVZhbGlkYXRvcihwcm9wZXJ0aWVzOiBhbnkpOiBjZGsuVmFsaWRhdGlvblJlc3VsdCB7XG4gICAgaWYgKCFjZGsuY2FuSW5zcGVjdChwcm9wZXJ0aWVzKSkgeyByZXR1cm4gY2RrLlZBTElEQVRJT05fU1VDQ0VTUzsgfVxuICAgIGNvbnN0IGVycm9ycyA9IG5ldyBjZGsuVmFsaWRhdGlvblJlc3VsdHMoKTtcbiAgICBlcnJvcnMuY29sbGVjdChjZGsucHJvcGVydHlWYWxpZGF0b3IoJ3N0cmVhbVZpZXdUeXBlJywgY2RrLnJlcXVpcmVkVmFsaWRhdG9yKShwcm9wZXJ0aWVzLnN0cmVhbVZpZXdUeXBlKSk7XG4gICAgZXJyb3JzLmNvbGxlY3QoY2RrLnByb3BlcnR5VmFsaWRhdG9yKCdzdHJlYW1WaWV3VHlwZScsIGNkay52YWxpZGF0ZVN0cmluZykocHJvcGVydGllcy5zdHJlYW1WaWV3VHlwZSkpO1xuICAgIHJldHVybiBlcnJvcnMud3JhcCgnc3VwcGxpZWQgcHJvcGVydGllcyBub3QgY29ycmVjdCBmb3IgXCJTdHJlYW1TcGVjaWZpY2F0aW9uUHJvcGVydHlcIicpO1xufVxuXG4vKipcbiAqIFJlbmRlcnMgdGhlIEFXUyBDbG91ZEZvcm1hdGlvbiBwcm9wZXJ0aWVzIG9mIGFuIGBBV1M6OkR5bmFtb0RCOjpUYWJsZS5TdHJlYW1TcGVjaWZpY2F0aW9uYCByZXNvdXJjZVxuICpcbiAqIEBwYXJhbSBwcm9wZXJ0aWVzIC0gdGhlIFR5cGVTY3JpcHQgcHJvcGVydGllcyBvZiBhIGBTdHJlYW1TcGVjaWZpY2F0aW9uUHJvcGVydHlgXG4gKlxuICogQHJldHVybnMgdGhlIEFXUyBDbG91ZEZvcm1hdGlvbiBwcm9wZXJ0aWVzIG9mIGFuIGBBV1M6OkR5bmFtb0RCOjpUYWJsZS5TdHJlYW1TcGVjaWZpY2F0aW9uYCByZXNvdXJjZS5cbiAqL1xuLy8gQHRzLWlnbm9yZSBUUzYxMzNcbmZ1bmN0aW9uIGNmblRhYmxlU3RyZWFtU3BlY2lmaWNhdGlvblByb3BlcnR5VG9DbG91ZEZvcm1hdGlvbihwcm9wZXJ0aWVzOiBhbnkpOiBhbnkge1xuICAgIGlmICghY2RrLmNhbkluc3BlY3QocHJvcGVydGllcykpIHsgcmV0dXJuIHByb3BlcnRpZXM7IH1cbiAgICBDZm5UYWJsZV9TdHJlYW1TcGVjaWZpY2F0aW9uUHJvcGVydHlWYWxpZGF0b3IocHJvcGVydGllcykuYXNzZXJ0U3VjY2VzcygpO1xuICAgIHJldHVybiB7XG4gICAgICBTdHJlYW1WaWV3VHlwZTogY2RrLnN0cmluZ1RvQ2xvdWRGb3JtYXRpb24ocHJvcGVydGllcy5zdHJlYW1WaWV3VHlwZSksXG4gICAgfTtcbn1cblxuZXhwb3J0IG5hbWVzcGFjZSBDZm5UYWJsZSB7XG4gICAgLyoqXG4gICAgICogQHNlZSBodHRwOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9BV1NDbG91ZEZvcm1hdGlvbi9sYXRlc3QvVXNlckd1aWRlL2F3cy1wcm9wZXJ0aWVzLWR5bmFtb2RiLXRpbWV0b2xpdmVzcGVjaWZpY2F0aW9uLmh0bWxcbiAgICAgKi9cbiAgICBleHBvcnQgaW50ZXJmYWNlIFRpbWVUb0xpdmVTcGVjaWZpY2F0aW9uUHJvcGVydHkge1xuICAgICAgICAvKipcbiAgICAgICAgICogYENmblRhYmxlLlRpbWVUb0xpdmVTcGVjaWZpY2F0aW9uUHJvcGVydHkuQXR0cmlidXRlTmFtZWBcbiAgICAgICAgICogQHNlZSBodHRwOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9BV1NDbG91ZEZvcm1hdGlvbi9sYXRlc3QvVXNlckd1aWRlL2F3cy1wcm9wZXJ0aWVzLWR5bmFtb2RiLXRpbWV0b2xpdmVzcGVjaWZpY2F0aW9uLmh0bWwjY2ZuLWR5bmFtb2RiLXRpbWV0b2xpdmVzcGVjaWZpY2F0aW9uLWF0dHJpYnV0ZW5hbWVcbiAgICAgICAgICovXG4gICAgICAgIGF0dHJpYnV0ZU5hbWU6IHN0cmluZztcbiAgICAgICAgLyoqXG4gICAgICAgICAqIGBDZm5UYWJsZS5UaW1lVG9MaXZlU3BlY2lmaWNhdGlvblByb3BlcnR5LkVuYWJsZWRgXG4gICAgICAgICAqIEBzZWUgaHR0cDovL2RvY3MuYXdzLmFtYXpvbi5jb20vQVdTQ2xvdWRGb3JtYXRpb24vbGF0ZXN0L1VzZXJHdWlkZS9hd3MtcHJvcGVydGllcy1keW5hbW9kYi10aW1ldG9saXZlc3BlY2lmaWNhdGlvbi5odG1sI2Nmbi1keW5hbW9kYi10aW1ldG9saXZlc3BlY2lmaWNhdGlvbi1lbmFibGVkXG4gICAgICAgICAqL1xuICAgICAgICBlbmFibGVkOiBib29sZWFuIHwgY2RrLlRva2VuO1xuICAgIH1cbn1cblxuLyoqXG4gKiBEZXRlcm1pbmUgd2hldGhlciB0aGUgZ2l2ZW4gcHJvcGVydGllcyBtYXRjaCB0aG9zZSBvZiBhIGBUaW1lVG9MaXZlU3BlY2lmaWNhdGlvblByb3BlcnR5YFxuICpcbiAqIEBwYXJhbSBwcm9wZXJ0aWVzIC0gdGhlIFR5cGVTY3JpcHQgcHJvcGVydGllcyBvZiBhIGBUaW1lVG9MaXZlU3BlY2lmaWNhdGlvblByb3BlcnR5YFxuICpcbiAqIEByZXR1cm5zIHRoZSByZXN1bHQgb2YgdGhlIHZhbGlkYXRpb24uXG4gKi9cbmZ1bmN0aW9uIENmblRhYmxlX1RpbWVUb0xpdmVTcGVjaWZpY2F0aW9uUHJvcGVydHlWYWxpZGF0b3IocHJvcGVydGllczogYW55KTogY2RrLlZhbGlkYXRpb25SZXN1bHQge1xuICAgIGlmICghY2RrLmNhbkluc3BlY3QocHJvcGVydGllcykpIHsgcmV0dXJuIGNkay5WQUxJREFUSU9OX1NVQ0NFU1M7IH1cbiAgICBjb25zdCBlcnJvcnMgPSBuZXcgY2RrLlZhbGlkYXRpb25SZXN1bHRzKCk7XG4gICAgZXJyb3JzLmNvbGxlY3QoY2RrLnByb3BlcnR5VmFsaWRhdG9yKCdhdHRyaWJ1dGVOYW1lJywgY2RrLnJlcXVpcmVkVmFsaWRhdG9yKShwcm9wZXJ0aWVzLmF0dHJpYnV0ZU5hbWUpKTtcbiAgICBlcnJvcnMuY29sbGVjdChjZGsucHJvcGVydHlWYWxpZGF0b3IoJ2F0dHJpYnV0ZU5hbWUnLCBjZGsudmFsaWRhdGVTdHJpbmcpKHByb3BlcnRpZXMuYXR0cmlidXRlTmFtZSkpO1xuICAgIGVycm9ycy5jb2xsZWN0KGNkay5wcm9wZXJ0eVZhbGlkYXRvcignZW5hYmxlZCcsIGNkay5yZXF1aXJlZFZhbGlkYXRvcikocHJvcGVydGllcy5lbmFibGVkKSk7XG4gICAgZXJyb3JzLmNvbGxlY3QoY2RrLnByb3BlcnR5VmFsaWRhdG9yKCdlbmFibGVkJywgY2RrLnZhbGlkYXRlQm9vbGVhbikocHJvcGVydGllcy5lbmFibGVkKSk7XG4gICAgcmV0dXJuIGVycm9ycy53cmFwKCdzdXBwbGllZCBwcm9wZXJ0aWVzIG5vdCBjb3JyZWN0IGZvciBcIlRpbWVUb0xpdmVTcGVjaWZpY2F0aW9uUHJvcGVydHlcIicpO1xufVxuXG4vKipcbiAqIFJlbmRlcnMgdGhlIEFXUyBDbG91ZEZvcm1hdGlvbiBwcm9wZXJ0aWVzIG9mIGFuIGBBV1M6OkR5bmFtb0RCOjpUYWJsZS5UaW1lVG9MaXZlU3BlY2lmaWNhdGlvbmAgcmVzb3VyY2VcbiAqXG4gKiBAcGFyYW0gcHJvcGVydGllcyAtIHRoZSBUeXBlU2NyaXB0IHByb3BlcnRpZXMgb2YgYSBgVGltZVRvTGl2ZVNwZWNpZmljYXRpb25Qcm9wZXJ0eWBcbiAqXG4gKiBAcmV0dXJucyB0aGUgQVdTIENsb3VkRm9ybWF0aW9uIHByb3BlcnRpZXMgb2YgYW4gYEFXUzo6RHluYW1vREI6OlRhYmxlLlRpbWVUb0xpdmVTcGVjaWZpY2F0aW9uYCByZXNvdXJjZS5cbiAqL1xuLy8gQHRzLWlnbm9yZSBUUzYxMzNcbmZ1bmN0aW9uIGNmblRhYmxlVGltZVRvTGl2ZVNwZWNpZmljYXRpb25Qcm9wZXJ0eVRvQ2xvdWRGb3JtYXRpb24ocHJvcGVydGllczogYW55KTogYW55IHtcbiAgICBpZiAoIWNkay5jYW5JbnNwZWN0KHByb3BlcnRpZXMpKSB7IHJldHVybiBwcm9wZXJ0aWVzOyB9XG4gICAgQ2ZuVGFibGVfVGltZVRvTGl2ZVNwZWNpZmljYXRpb25Qcm9wZXJ0eVZhbGlkYXRvcihwcm9wZXJ0aWVzKS5hc3NlcnRTdWNjZXNzKCk7XG4gICAgcmV0dXJuIHtcbiAgICAgIEF0dHJpYnV0ZU5hbWU6IGNkay5zdHJpbmdUb0Nsb3VkRm9ybWF0aW9uKHByb3BlcnRpZXMuYXR0cmlidXRlTmFtZSksXG4gICAgICBFbmFibGVkOiBjZGsuYm9vbGVhblRvQ2xvdWRGb3JtYXRpb24ocHJvcGVydGllcy5lbmFibGVkKSxcbiAgICB9O1xufVxuIl19 \ No newline at end of file diff --git a/packages/@aws-cdk/aws-dynamodb-global/lib/dynamodb.generated.ts b/packages/@aws-cdk/aws-dynamodb-global/lib/dynamodb.generated.ts deleted file mode 100644 index 5d7ca7bc37382..0000000000000 --- a/packages/@aws-cdk/aws-dynamodb-global/lib/dynamodb.generated.ts +++ /dev/null @@ -1,702 +0,0 @@ -// Copyright 2012-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. -// Generated from the AWS CloudFormation Resource Specification -// See: docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/cfn-resource-specification.html -// @cfn2ts:meta@ {"generated":"2019-03-21T16:19:16.881Z","fingerprint":"CPTpE9eD4ImqOKDnu7P0Kaol8j+SXNQUILMR4l/fi2g="} - -// tslint:disable:max-line-length | This is generated code - line lengths are difficult to control - -import cdk = require('@aws-cdk/cdk'); - -/** - * Properties for defining a `AWS::DynamoDB::Table` - * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-dynamodb-table.html - */ -export interface CfnTableProps { - /** - * `AWS::DynamoDB::Table.KeySchema` - * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-dynamodb-table.html#cfn-dynamodb-table-keyschema - */ - keySchema: Array | cdk.Token; - /** - * `AWS::DynamoDB::Table.AttributeDefinitions` - * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-dynamodb-table.html#cfn-dynamodb-table-attributedef - */ - attributeDefinitions?: Array | cdk.Token; - /** - * `AWS::DynamoDB::Table.BillingMode` - * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-dynamodb-table.html#cfn-dynamodb-table-billingmode - */ - billingMode?: string; - /** - * `AWS::DynamoDB::Table.GlobalSecondaryIndexes` - * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-dynamodb-table.html#cfn-dynamodb-table-gsi - */ - globalSecondaryIndexes?: Array | cdk.Token; - /** - * `AWS::DynamoDB::Table.LocalSecondaryIndexes` - * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-dynamodb-table.html#cfn-dynamodb-table-lsi - */ - localSecondaryIndexes?: Array | cdk.Token; - /** - * `AWS::DynamoDB::Table.PointInTimeRecoverySpecification` - * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-dynamodb-table.html#cfn-dynamodb-table-pointintimerecoveryspecification - */ - pointInTimeRecoverySpecification?: CfnTable.PointInTimeRecoverySpecificationProperty | cdk.Token; - /** - * `AWS::DynamoDB::Table.ProvisionedThroughput` - * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-dynamodb-table.html#cfn-dynamodb-table-provisionedthroughput - */ - provisionedThroughput?: CfnTable.ProvisionedThroughputProperty | cdk.Token; - /** - * `AWS::DynamoDB::Table.SSESpecification` - * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-dynamodb-table.html#cfn-dynamodb-table-ssespecification - */ - sseSpecification?: CfnTable.SSESpecificationProperty | cdk.Token; - /** - * `AWS::DynamoDB::Table.StreamSpecification` - * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-dynamodb-table.html#cfn-dynamodb-table-streamspecification - */ - streamSpecification?: CfnTable.StreamSpecificationProperty | cdk.Token; - /** - * `AWS::DynamoDB::Table.TableName` - * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-dynamodb-table.html#cfn-dynamodb-table-tablename - */ - tableName?: string; - /** - * `AWS::DynamoDB::Table.Tags` - * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-dynamodb-table.html#cfn-dynamodb-table-tags - */ - tags?: cdk.CfnTag[]; - /** - * `AWS::DynamoDB::Table.TimeToLiveSpecification` - * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-dynamodb-table.html#cfn-dynamodb-table-timetolivespecification - */ - timeToLiveSpecification?: CfnTable.TimeToLiveSpecificationProperty | cdk.Token; -} - -/** - * Determine whether the given properties match those of a `CfnTableProps` - * - * @param properties - the TypeScript properties of a `CfnTableProps` - * - * @returns the result of the validation. - */ -function CfnTablePropsValidator(properties: any): cdk.ValidationResult { - if (!cdk.canInspect(properties)) { return cdk.VALIDATION_SUCCESS; } - const errors = new cdk.ValidationResults(); - errors.collect(cdk.propertyValidator('attributeDefinitions', cdk.listValidator(CfnTable_AttributeDefinitionPropertyValidator))(properties.attributeDefinitions)); - errors.collect(cdk.propertyValidator('billingMode', cdk.validateString)(properties.billingMode)); - errors.collect(cdk.propertyValidator('globalSecondaryIndexes', cdk.listValidator(CfnTable_GlobalSecondaryIndexPropertyValidator))(properties.globalSecondaryIndexes)); - errors.collect(cdk.propertyValidator('keySchema', cdk.requiredValidator)(properties.keySchema)); - errors.collect(cdk.propertyValidator('keySchema', cdk.listValidator(CfnTable_KeySchemaPropertyValidator))(properties.keySchema)); - errors.collect(cdk.propertyValidator('localSecondaryIndexes', cdk.listValidator(CfnTable_LocalSecondaryIndexPropertyValidator))(properties.localSecondaryIndexes)); - errors.collect(cdk.propertyValidator('pointInTimeRecoverySpecification', CfnTable_PointInTimeRecoverySpecificationPropertyValidator)(properties.pointInTimeRecoverySpecification)); - errors.collect(cdk.propertyValidator('provisionedThroughput', CfnTable_ProvisionedThroughputPropertyValidator)(properties.provisionedThroughput)); - errors.collect(cdk.propertyValidator('sseSpecification', CfnTable_SSESpecificationPropertyValidator)(properties.sseSpecification)); - errors.collect(cdk.propertyValidator('streamSpecification', CfnTable_StreamSpecificationPropertyValidator)(properties.streamSpecification)); - errors.collect(cdk.propertyValidator('tableName', cdk.validateString)(properties.tableName)); - errors.collect(cdk.propertyValidator('tags', cdk.listValidator(cdk.validateCfnTag))(properties.tags)); - errors.collect(cdk.propertyValidator('timeToLiveSpecification', CfnTable_TimeToLiveSpecificationPropertyValidator)(properties.timeToLiveSpecification)); - return errors.wrap('supplied properties not correct for "CfnTableProps"'); -} - -/** - * Renders the AWS CloudFormation properties of an `AWS::DynamoDB::Table` resource - * - * @param properties - the TypeScript properties of a `CfnTableProps` - * - * @returns the AWS CloudFormation properties of an `AWS::DynamoDB::Table` resource. - */ -// @ts-ignore TS6133 -function cfnTablePropsToCloudFormation(properties: any): any { - if (!cdk.canInspect(properties)) { return properties; } - CfnTablePropsValidator(properties).assertSuccess(); - return { - KeySchema: cdk.listMapper(cfnTableKeySchemaPropertyToCloudFormation)(properties.keySchema), - AttributeDefinitions: cdk.listMapper(cfnTableAttributeDefinitionPropertyToCloudFormation)(properties.attributeDefinitions), - BillingMode: cdk.stringToCloudFormation(properties.billingMode), - GlobalSecondaryIndexes: cdk.listMapper(cfnTableGlobalSecondaryIndexPropertyToCloudFormation)(properties.globalSecondaryIndexes), - LocalSecondaryIndexes: cdk.listMapper(cfnTableLocalSecondaryIndexPropertyToCloudFormation)(properties.localSecondaryIndexes), - PointInTimeRecoverySpecification: cfnTablePointInTimeRecoverySpecificationPropertyToCloudFormation(properties.pointInTimeRecoverySpecification), - ProvisionedThroughput: cfnTableProvisionedThroughputPropertyToCloudFormation(properties.provisionedThroughput), - SSESpecification: cfnTableSSESpecificationPropertyToCloudFormation(properties.sseSpecification), - StreamSpecification: cfnTableStreamSpecificationPropertyToCloudFormation(properties.streamSpecification), - TableName: cdk.stringToCloudFormation(properties.tableName), - Tags: cdk.listMapper(cdk.cfnTagToCloudFormation)(properties.tags), - TimeToLiveSpecification: cfnTableTimeToLiveSpecificationPropertyToCloudFormation(properties.timeToLiveSpecification), - }; -} - -/** - * A CloudFormation `AWS::DynamoDB::Table` - * - * @cloudformationResource AWS::DynamoDB::Table - * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-dynamodb-table.html - */ -export class CfnTable extends cdk.CfnResource { - /** - * The CloudFormation resource type name for this resource class. - */ - public static readonly resourceTypeName = "AWS::DynamoDB::Table"; - - /** - * @cloudformationAttribute Arn - */ - public readonly tableArn: string; - - /** - * @cloudformationAttribute StreamArn - */ - public readonly tableStreamArn: string; - public readonly tableName: string; - - /** - * The `TagManager` handles setting, removing and formatting tags - * - * Tags should be managed either passing them as properties during - * initiation or by calling methods on this object. If both techniques are - * used only the tags from the TagManager will be used. `Tag` (aspect) - * will use the manager. - */ - public readonly tags: cdk.TagManager; - - /** - * Create a new `AWS::DynamoDB::Table`. - * - * @param scope - scope in which this resource is defined - * @param id - scoped id of the resource - * @param props - resource properties - */ - constructor(scope: cdk.Construct, id: string, props: CfnTableProps) { - super(scope, id, { type: CfnTable.resourceTypeName, properties: props }); - cdk.requireProperty(props, 'keySchema', this); - this.tableArn = this.getAtt('Arn').toString(); - this.tableStreamArn = this.getAtt('StreamArn').toString(); - this.tableName = this.ref.toString(); - const tags = props === undefined ? undefined : props.tags; - this.tags = new cdk.TagManager(cdk.TagType.Standard, "AWS::DynamoDB::Table", tags); - } - - public get propertyOverrides(): CfnTableProps { - return this.untypedPropertyOverrides; - } - protected renderProperties(properties: any): { [key: string]: any } { - return cfnTablePropsToCloudFormation(this.node.resolve(properties)); - } -} - -export namespace CfnTable { - /** - * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-attributedef.html - */ - export interface AttributeDefinitionProperty { - /** - * `CfnTable.AttributeDefinitionProperty.AttributeName` - * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-attributedef.html#cfn-dynamodb-attributedef-attributename - */ - attributeName: string; - /** - * `CfnTable.AttributeDefinitionProperty.AttributeType` - * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-attributedef.html#cfn-dynamodb-attributedef-attributename-attributetype - */ - attributeType: string; - } -} - -/** - * Determine whether the given properties match those of a `AttributeDefinitionProperty` - * - * @param properties - the TypeScript properties of a `AttributeDefinitionProperty` - * - * @returns the result of the validation. - */ -function CfnTable_AttributeDefinitionPropertyValidator(properties: any): cdk.ValidationResult { - if (!cdk.canInspect(properties)) { return cdk.VALIDATION_SUCCESS; } - const errors = new cdk.ValidationResults(); - errors.collect(cdk.propertyValidator('attributeName', cdk.requiredValidator)(properties.attributeName)); - errors.collect(cdk.propertyValidator('attributeName', cdk.validateString)(properties.attributeName)); - errors.collect(cdk.propertyValidator('attributeType', cdk.requiredValidator)(properties.attributeType)); - errors.collect(cdk.propertyValidator('attributeType', cdk.validateString)(properties.attributeType)); - return errors.wrap('supplied properties not correct for "AttributeDefinitionProperty"'); -} - -/** - * Renders the AWS CloudFormation properties of an `AWS::DynamoDB::Table.AttributeDefinition` resource - * - * @param properties - the TypeScript properties of a `AttributeDefinitionProperty` - * - * @returns the AWS CloudFormation properties of an `AWS::DynamoDB::Table.AttributeDefinition` resource. - */ -// @ts-ignore TS6133 -function cfnTableAttributeDefinitionPropertyToCloudFormation(properties: any): any { - if (!cdk.canInspect(properties)) { return properties; } - CfnTable_AttributeDefinitionPropertyValidator(properties).assertSuccess(); - return { - AttributeName: cdk.stringToCloudFormation(properties.attributeName), - AttributeType: cdk.stringToCloudFormation(properties.attributeType), - }; -} - -export namespace CfnTable { - /** - * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-gsi.html - */ - export interface GlobalSecondaryIndexProperty { - /** - * `CfnTable.GlobalSecondaryIndexProperty.IndexName` - * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-gsi.html#cfn-dynamodb-gsi-indexname - */ - indexName: string; - /** - * `CfnTable.GlobalSecondaryIndexProperty.KeySchema` - * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-gsi.html#cfn-dynamodb-gsi-keyschema - */ - keySchema: Array | cdk.Token; - /** - * `CfnTable.GlobalSecondaryIndexProperty.Projection` - * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-gsi.html#cfn-dynamodb-gsi-projection - */ - projection: CfnTable.ProjectionProperty | cdk.Token; - /** - * `CfnTable.GlobalSecondaryIndexProperty.ProvisionedThroughput` - * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-gsi.html#cfn-dynamodb-gsi-provisionedthroughput - */ - provisionedThroughput?: CfnTable.ProvisionedThroughputProperty | cdk.Token; - } -} - -/** - * Determine whether the given properties match those of a `GlobalSecondaryIndexProperty` - * - * @param properties - the TypeScript properties of a `GlobalSecondaryIndexProperty` - * - * @returns the result of the validation. - */ -function CfnTable_GlobalSecondaryIndexPropertyValidator(properties: any): cdk.ValidationResult { - if (!cdk.canInspect(properties)) { return cdk.VALIDATION_SUCCESS; } - const errors = new cdk.ValidationResults(); - errors.collect(cdk.propertyValidator('indexName', cdk.requiredValidator)(properties.indexName)); - errors.collect(cdk.propertyValidator('indexName', cdk.validateString)(properties.indexName)); - errors.collect(cdk.propertyValidator('keySchema', cdk.requiredValidator)(properties.keySchema)); - errors.collect(cdk.propertyValidator('keySchema', cdk.listValidator(CfnTable_KeySchemaPropertyValidator))(properties.keySchema)); - errors.collect(cdk.propertyValidator('projection', cdk.requiredValidator)(properties.projection)); - errors.collect(cdk.propertyValidator('projection', CfnTable_ProjectionPropertyValidator)(properties.projection)); - errors.collect(cdk.propertyValidator('provisionedThroughput', CfnTable_ProvisionedThroughputPropertyValidator)(properties.provisionedThroughput)); - return errors.wrap('supplied properties not correct for "GlobalSecondaryIndexProperty"'); -} - -/** - * Renders the AWS CloudFormation properties of an `AWS::DynamoDB::Table.GlobalSecondaryIndex` resource - * - * @param properties - the TypeScript properties of a `GlobalSecondaryIndexProperty` - * - * @returns the AWS CloudFormation properties of an `AWS::DynamoDB::Table.GlobalSecondaryIndex` resource. - */ -// @ts-ignore TS6133 -function cfnTableGlobalSecondaryIndexPropertyToCloudFormation(properties: any): any { - if (!cdk.canInspect(properties)) { return properties; } - CfnTable_GlobalSecondaryIndexPropertyValidator(properties).assertSuccess(); - return { - IndexName: cdk.stringToCloudFormation(properties.indexName), - KeySchema: cdk.listMapper(cfnTableKeySchemaPropertyToCloudFormation)(properties.keySchema), - Projection: cfnTableProjectionPropertyToCloudFormation(properties.projection), - ProvisionedThroughput: cfnTableProvisionedThroughputPropertyToCloudFormation(properties.provisionedThroughput), - }; -} - -export namespace CfnTable { - /** - * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-keyschema.html - */ - export interface KeySchemaProperty { - /** - * `CfnTable.KeySchemaProperty.AttributeName` - * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-keyschema.html#aws-properties-dynamodb-keyschema-attributename - */ - attributeName: string; - /** - * `CfnTable.KeySchemaProperty.KeyType` - * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-keyschema.html#aws-properties-dynamodb-keyschema-keytype - */ - keyType: string; - } -} - -/** - * Determine whether the given properties match those of a `KeySchemaProperty` - * - * @param properties - the TypeScript properties of a `KeySchemaProperty` - * - * @returns the result of the validation. - */ -function CfnTable_KeySchemaPropertyValidator(properties: any): cdk.ValidationResult { - if (!cdk.canInspect(properties)) { return cdk.VALIDATION_SUCCESS; } - const errors = new cdk.ValidationResults(); - errors.collect(cdk.propertyValidator('attributeName', cdk.requiredValidator)(properties.attributeName)); - errors.collect(cdk.propertyValidator('attributeName', cdk.validateString)(properties.attributeName)); - errors.collect(cdk.propertyValidator('keyType', cdk.requiredValidator)(properties.keyType)); - errors.collect(cdk.propertyValidator('keyType', cdk.validateString)(properties.keyType)); - return errors.wrap('supplied properties not correct for "KeySchemaProperty"'); -} - -/** - * Renders the AWS CloudFormation properties of an `AWS::DynamoDB::Table.KeySchema` resource - * - * @param properties - the TypeScript properties of a `KeySchemaProperty` - * - * @returns the AWS CloudFormation properties of an `AWS::DynamoDB::Table.KeySchema` resource. - */ -// @ts-ignore TS6133 -function cfnTableKeySchemaPropertyToCloudFormation(properties: any): any { - if (!cdk.canInspect(properties)) { return properties; } - CfnTable_KeySchemaPropertyValidator(properties).assertSuccess(); - return { - AttributeName: cdk.stringToCloudFormation(properties.attributeName), - KeyType: cdk.stringToCloudFormation(properties.keyType), - }; -} - -export namespace CfnTable { - /** - * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-lsi.html - */ - export interface LocalSecondaryIndexProperty { - /** - * `CfnTable.LocalSecondaryIndexProperty.IndexName` - * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-lsi.html#cfn-dynamodb-lsi-indexname - */ - indexName: string; - /** - * `CfnTable.LocalSecondaryIndexProperty.KeySchema` - * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-lsi.html#cfn-dynamodb-lsi-keyschema - */ - keySchema: Array | cdk.Token; - /** - * `CfnTable.LocalSecondaryIndexProperty.Projection` - * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-lsi.html#cfn-dynamodb-lsi-projection - */ - projection: CfnTable.ProjectionProperty | cdk.Token; - } -} - -/** - * Determine whether the given properties match those of a `LocalSecondaryIndexProperty` - * - * @param properties - the TypeScript properties of a `LocalSecondaryIndexProperty` - * - * @returns the result of the validation. - */ -function CfnTable_LocalSecondaryIndexPropertyValidator(properties: any): cdk.ValidationResult { - if (!cdk.canInspect(properties)) { return cdk.VALIDATION_SUCCESS; } - const errors = new cdk.ValidationResults(); - errors.collect(cdk.propertyValidator('indexName', cdk.requiredValidator)(properties.indexName)); - errors.collect(cdk.propertyValidator('indexName', cdk.validateString)(properties.indexName)); - errors.collect(cdk.propertyValidator('keySchema', cdk.requiredValidator)(properties.keySchema)); - errors.collect(cdk.propertyValidator('keySchema', cdk.listValidator(CfnTable_KeySchemaPropertyValidator))(properties.keySchema)); - errors.collect(cdk.propertyValidator('projection', cdk.requiredValidator)(properties.projection)); - errors.collect(cdk.propertyValidator('projection', CfnTable_ProjectionPropertyValidator)(properties.projection)); - return errors.wrap('supplied properties not correct for "LocalSecondaryIndexProperty"'); -} - -/** - * Renders the AWS CloudFormation properties of an `AWS::DynamoDB::Table.LocalSecondaryIndex` resource - * - * @param properties - the TypeScript properties of a `LocalSecondaryIndexProperty` - * - * @returns the AWS CloudFormation properties of an `AWS::DynamoDB::Table.LocalSecondaryIndex` resource. - */ -// @ts-ignore TS6133 -function cfnTableLocalSecondaryIndexPropertyToCloudFormation(properties: any): any { - if (!cdk.canInspect(properties)) { return properties; } - CfnTable_LocalSecondaryIndexPropertyValidator(properties).assertSuccess(); - return { - IndexName: cdk.stringToCloudFormation(properties.indexName), - KeySchema: cdk.listMapper(cfnTableKeySchemaPropertyToCloudFormation)(properties.keySchema), - Projection: cfnTableProjectionPropertyToCloudFormation(properties.projection), - }; -} - -export namespace CfnTable { - /** - * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-table-pointintimerecoveryspecification.html - */ - export interface PointInTimeRecoverySpecificationProperty { - /** - * `CfnTable.PointInTimeRecoverySpecificationProperty.PointInTimeRecoveryEnabled` - * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-table-pointintimerecoveryspecification.html#cfn-dynamodb-table-pointintimerecoveryspecification-pointintimerecoveryenabled - */ - pointInTimeRecoveryEnabled?: boolean | cdk.Token; - } -} - -/** - * Determine whether the given properties match those of a `PointInTimeRecoverySpecificationProperty` - * - * @param properties - the TypeScript properties of a `PointInTimeRecoverySpecificationProperty` - * - * @returns the result of the validation. - */ -function CfnTable_PointInTimeRecoverySpecificationPropertyValidator(properties: any): cdk.ValidationResult { - if (!cdk.canInspect(properties)) { return cdk.VALIDATION_SUCCESS; } - const errors = new cdk.ValidationResults(); - errors.collect(cdk.propertyValidator('pointInTimeRecoveryEnabled', cdk.validateBoolean)(properties.pointInTimeRecoveryEnabled)); - return errors.wrap('supplied properties not correct for "PointInTimeRecoverySpecificationProperty"'); -} - -/** - * Renders the AWS CloudFormation properties of an `AWS::DynamoDB::Table.PointInTimeRecoverySpecification` resource - * - * @param properties - the TypeScript properties of a `PointInTimeRecoverySpecificationProperty` - * - * @returns the AWS CloudFormation properties of an `AWS::DynamoDB::Table.PointInTimeRecoverySpecification` resource. - */ -// @ts-ignore TS6133 -function cfnTablePointInTimeRecoverySpecificationPropertyToCloudFormation(properties: any): any { - if (!cdk.canInspect(properties)) { return properties; } - CfnTable_PointInTimeRecoverySpecificationPropertyValidator(properties).assertSuccess(); - return { - PointInTimeRecoveryEnabled: cdk.booleanToCloudFormation(properties.pointInTimeRecoveryEnabled), - }; -} - -export namespace CfnTable { - /** - * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-projectionobject.html - */ - export interface ProjectionProperty { - /** - * `CfnTable.ProjectionProperty.NonKeyAttributes` - * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-projectionobject.html#cfn-dynamodb-projectionobj-nonkeyatt - */ - nonKeyAttributes?: string[]; - /** - * `CfnTable.ProjectionProperty.ProjectionType` - * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-projectionobject.html#cfn-dynamodb-projectionobj-projtype - */ - projectionType?: string; - } -} - -/** - * Determine whether the given properties match those of a `ProjectionProperty` - * - * @param properties - the TypeScript properties of a `ProjectionProperty` - * - * @returns the result of the validation. - */ -function CfnTable_ProjectionPropertyValidator(properties: any): cdk.ValidationResult { - if (!cdk.canInspect(properties)) { return cdk.VALIDATION_SUCCESS; } - const errors = new cdk.ValidationResults(); - errors.collect(cdk.propertyValidator('nonKeyAttributes', cdk.listValidator(cdk.validateString))(properties.nonKeyAttributes)); - errors.collect(cdk.propertyValidator('projectionType', cdk.validateString)(properties.projectionType)); - return errors.wrap('supplied properties not correct for "ProjectionProperty"'); -} - -/** - * Renders the AWS CloudFormation properties of an `AWS::DynamoDB::Table.Projection` resource - * - * @param properties - the TypeScript properties of a `ProjectionProperty` - * - * @returns the AWS CloudFormation properties of an `AWS::DynamoDB::Table.Projection` resource. - */ -// @ts-ignore TS6133 -function cfnTableProjectionPropertyToCloudFormation(properties: any): any { - if (!cdk.canInspect(properties)) { return properties; } - CfnTable_ProjectionPropertyValidator(properties).assertSuccess(); - return { - NonKeyAttributes: cdk.listMapper(cdk.stringToCloudFormation)(properties.nonKeyAttributes), - ProjectionType: cdk.stringToCloudFormation(properties.projectionType), - }; -} - -export namespace CfnTable { - /** - * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-provisionedthroughput.html - */ - export interface ProvisionedThroughputProperty { - /** - * `CfnTable.ProvisionedThroughputProperty.ReadCapacityUnits` - * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-provisionedthroughput.html#cfn-dynamodb-provisionedthroughput-readcapacityunits - */ - readCapacityUnits: number | cdk.Token; - /** - * `CfnTable.ProvisionedThroughputProperty.WriteCapacityUnits` - * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-provisionedthroughput.html#cfn-dynamodb-provisionedthroughput-writecapacityunits - */ - writeCapacityUnits: number | cdk.Token; - } -} - -/** - * Determine whether the given properties match those of a `ProvisionedThroughputProperty` - * - * @param properties - the TypeScript properties of a `ProvisionedThroughputProperty` - * - * @returns the result of the validation. - */ -function CfnTable_ProvisionedThroughputPropertyValidator(properties: any): cdk.ValidationResult { - if (!cdk.canInspect(properties)) { return cdk.VALIDATION_SUCCESS; } - const errors = new cdk.ValidationResults(); - errors.collect(cdk.propertyValidator('readCapacityUnits', cdk.requiredValidator)(properties.readCapacityUnits)); - errors.collect(cdk.propertyValidator('readCapacityUnits', cdk.validateNumber)(properties.readCapacityUnits)); - errors.collect(cdk.propertyValidator('writeCapacityUnits', cdk.requiredValidator)(properties.writeCapacityUnits)); - errors.collect(cdk.propertyValidator('writeCapacityUnits', cdk.validateNumber)(properties.writeCapacityUnits)); - return errors.wrap('supplied properties not correct for "ProvisionedThroughputProperty"'); -} - -/** - * Renders the AWS CloudFormation properties of an `AWS::DynamoDB::Table.ProvisionedThroughput` resource - * - * @param properties - the TypeScript properties of a `ProvisionedThroughputProperty` - * - * @returns the AWS CloudFormation properties of an `AWS::DynamoDB::Table.ProvisionedThroughput` resource. - */ -// @ts-ignore TS6133 -function cfnTableProvisionedThroughputPropertyToCloudFormation(properties: any): any { - if (!cdk.canInspect(properties)) { return properties; } - CfnTable_ProvisionedThroughputPropertyValidator(properties).assertSuccess(); - return { - ReadCapacityUnits: cdk.numberToCloudFormation(properties.readCapacityUnits), - WriteCapacityUnits: cdk.numberToCloudFormation(properties.writeCapacityUnits), - }; -} - -export namespace CfnTable { - /** - * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-table-ssespecification.html - */ - export interface SSESpecificationProperty { - /** - * `CfnTable.SSESpecificationProperty.SSEEnabled` - * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-table-ssespecification.html#cfn-dynamodb-table-ssespecification-sseenabled - */ - sseEnabled: boolean | cdk.Token; - } -} - -/** - * Determine whether the given properties match those of a `SSESpecificationProperty` - * - * @param properties - the TypeScript properties of a `SSESpecificationProperty` - * - * @returns the result of the validation. - */ -function CfnTable_SSESpecificationPropertyValidator(properties: any): cdk.ValidationResult { - if (!cdk.canInspect(properties)) { return cdk.VALIDATION_SUCCESS; } - const errors = new cdk.ValidationResults(); - errors.collect(cdk.propertyValidator('sseEnabled', cdk.requiredValidator)(properties.sseEnabled)); - errors.collect(cdk.propertyValidator('sseEnabled', cdk.validateBoolean)(properties.sseEnabled)); - return errors.wrap('supplied properties not correct for "SSESpecificationProperty"'); -} - -/** - * Renders the AWS CloudFormation properties of an `AWS::DynamoDB::Table.SSESpecification` resource - * - * @param properties - the TypeScript properties of a `SSESpecificationProperty` - * - * @returns the AWS CloudFormation properties of an `AWS::DynamoDB::Table.SSESpecification` resource. - */ -// @ts-ignore TS6133 -function cfnTableSSESpecificationPropertyToCloudFormation(properties: any): any { - if (!cdk.canInspect(properties)) { return properties; } - CfnTable_SSESpecificationPropertyValidator(properties).assertSuccess(); - return { - SSEEnabled: cdk.booleanToCloudFormation(properties.sseEnabled), - }; -} - -export namespace CfnTable { - /** - * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-streamspecification.html - */ - export interface StreamSpecificationProperty { - /** - * `CfnTable.StreamSpecificationProperty.StreamViewType` - * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-streamspecification.html#cfn-dynamodb-streamspecification-streamviewtype - */ - streamViewType: string; - } -} - -/** - * Determine whether the given properties match those of a `StreamSpecificationProperty` - * - * @param properties - the TypeScript properties of a `StreamSpecificationProperty` - * - * @returns the result of the validation. - */ -function CfnTable_StreamSpecificationPropertyValidator(properties: any): cdk.ValidationResult { - if (!cdk.canInspect(properties)) { return cdk.VALIDATION_SUCCESS; } - const errors = new cdk.ValidationResults(); - errors.collect(cdk.propertyValidator('streamViewType', cdk.requiredValidator)(properties.streamViewType)); - errors.collect(cdk.propertyValidator('streamViewType', cdk.validateString)(properties.streamViewType)); - return errors.wrap('supplied properties not correct for "StreamSpecificationProperty"'); -} - -/** - * Renders the AWS CloudFormation properties of an `AWS::DynamoDB::Table.StreamSpecification` resource - * - * @param properties - the TypeScript properties of a `StreamSpecificationProperty` - * - * @returns the AWS CloudFormation properties of an `AWS::DynamoDB::Table.StreamSpecification` resource. - */ -// @ts-ignore TS6133 -function cfnTableStreamSpecificationPropertyToCloudFormation(properties: any): any { - if (!cdk.canInspect(properties)) { return properties; } - CfnTable_StreamSpecificationPropertyValidator(properties).assertSuccess(); - return { - StreamViewType: cdk.stringToCloudFormation(properties.streamViewType), - }; -} - -export namespace CfnTable { - /** - * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-timetolivespecification.html - */ - export interface TimeToLiveSpecificationProperty { - /** - * `CfnTable.TimeToLiveSpecificationProperty.AttributeName` - * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-timetolivespecification.html#cfn-dynamodb-timetolivespecification-attributename - */ - attributeName: string; - /** - * `CfnTable.TimeToLiveSpecificationProperty.Enabled` - * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-timetolivespecification.html#cfn-dynamodb-timetolivespecification-enabled - */ - enabled: boolean | cdk.Token; - } -} - -/** - * Determine whether the given properties match those of a `TimeToLiveSpecificationProperty` - * - * @param properties - the TypeScript properties of a `TimeToLiveSpecificationProperty` - * - * @returns the result of the validation. - */ -function CfnTable_TimeToLiveSpecificationPropertyValidator(properties: any): cdk.ValidationResult { - if (!cdk.canInspect(properties)) { return cdk.VALIDATION_SUCCESS; } - const errors = new cdk.ValidationResults(); - errors.collect(cdk.propertyValidator('attributeName', cdk.requiredValidator)(properties.attributeName)); - errors.collect(cdk.propertyValidator('attributeName', cdk.validateString)(properties.attributeName)); - errors.collect(cdk.propertyValidator('enabled', cdk.requiredValidator)(properties.enabled)); - errors.collect(cdk.propertyValidator('enabled', cdk.validateBoolean)(properties.enabled)); - return errors.wrap('supplied properties not correct for "TimeToLiveSpecificationProperty"'); -} - -/** - * Renders the AWS CloudFormation properties of an `AWS::DynamoDB::Table.TimeToLiveSpecification` resource - * - * @param properties - the TypeScript properties of a `TimeToLiveSpecificationProperty` - * - * @returns the AWS CloudFormation properties of an `AWS::DynamoDB::Table.TimeToLiveSpecification` resource. - */ -// @ts-ignore TS6133 -function cfnTableTimeToLiveSpecificationPropertyToCloudFormation(properties: any): any { - if (!cdk.canInspect(properties)) { return properties; } - CfnTable_TimeToLiveSpecificationPropertyValidator(properties).assertSuccess(); - return { - AttributeName: cdk.stringToCloudFormation(properties.attributeName), - Enabled: cdk.booleanToCloudFormation(properties.enabled), - }; -} diff --git a/packages/@aws-cdk/aws-dynamodb-global/lib/index.d.ts b/packages/@aws-cdk/aws-dynamodb-global/lib/index.d.ts deleted file mode 100644 index 710580c8bdf9b..0000000000000 --- a/packages/@aws-cdk/aws-dynamodb-global/lib/index.d.ts +++ /dev/null @@ -1,3 +0,0 @@ -export * from "./aws-dynamodb-global"; -export * from "./lambda-global-dynamodb"; -export * from "./multi-dynamodb-stack"; diff --git a/packages/@aws-cdk/aws-dynamodb-global/lib/index.js b/packages/@aws-cdk/aws-dynamodb-global/lib/index.js deleted file mode 100644 index b8df4cf851a64..0000000000000 --- a/packages/@aws-cdk/aws-dynamodb-global/lib/index.js +++ /dev/null @@ -1,9 +0,0 @@ -"use strict"; -function __export(m) { - for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; -} -Object.defineProperty(exports, "__esModule", { value: true }); -__export(require("./aws-dynamodb-global")); -__export(require("./lambda-global-dynamodb")); -__export(require("./multi-dynamodb-stack")); -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJpbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQUFBLDJDQUFzQztBQUN0Qyw4Q0FBeUM7QUFDekMsNENBQXVDIiwic291cmNlc0NvbnRlbnQiOlsiZXhwb3J0ICogZnJvbSBcIi4vYXdzLWR5bmFtb2RiLWdsb2JhbFwiO1xuZXhwb3J0ICogZnJvbSBcIi4vbGFtYmRhLWdsb2JhbC1keW5hbW9kYlwiO1xuZXhwb3J0ICogZnJvbSBcIi4vbXVsdGktZHluYW1vZGItc3RhY2tcIjtcbiJdfQ== \ No newline at end of file diff --git a/packages/@aws-cdk/aws-dynamodb-global/lib/lambda-global-dynamodb.d.ts b/packages/@aws-cdk/aws-dynamodb-global/lib/lambda-global-dynamodb.d.ts deleted file mode 100644 index 1a874aead8ec8..0000000000000 --- a/packages/@aws-cdk/aws-dynamodb-global/lib/lambda-global-dynamodb.d.ts +++ /dev/null @@ -1,23 +0,0 @@ -import cfn = require("@aws-cdk/aws-cloudformation"); -import lambda = require("@aws-cdk/aws-lambda"); -import cdk = require("@aws-cdk/cdk"); -import { DynamoDBGlobalStackProps } from "./aws-dynamodb-global"; -/** - * A stack that will make a Lambda that will launch a lambda to glue - * together all the DynamoDB tables into a global table - */ -export declare class LambdaGlobalDynamoDBMaker extends cdk.Stack { - /** - * The singleton Lambda function that will connect all the DynamoDB tables together into a global table - */ - lambdaFunction: lambda.IFunction; - /** - * The content of the lambdaFunction (python3.7 using boto3) - */ - lambdaFunctionContent: string; - /** - * The CloudFormation CustomResource that will manage the lambda - */ - customResource: cfn.CustomResource; - constructor(scope: cdk.Construct, id: string, props: DynamoDBGlobalStackProps); -} diff --git a/packages/@aws-cdk/aws-dynamodb-global/lib/lambda-global-dynamodb.js b/packages/@aws-cdk/aws-dynamodb-global/lib/lambda-global-dynamodb.js deleted file mode 100644 index a38bedeb8d3d2..0000000000000 --- a/packages/@aws-cdk/aws-dynamodb-global/lib/lambda-global-dynamodb.js +++ /dev/null @@ -1,46 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -const cfn = require("@aws-cdk/aws-cloudformation"); -const iam = require("@aws-cdk/aws-iam"); -const lambda = require("@aws-cdk/aws-lambda"); -const cdk = require("@aws-cdk/cdk"); -const fs = require("fs"); -const path = require("path"); -/** - * A stack that will make a Lambda that will launch a lambda to glue - * together all the DynamoDB tables into a global table - */ -class LambdaGlobalDynamoDBMaker extends cdk.Stack { - constructor(scope, id, props) { - super(scope, id, props); - const codeLocation = path.resolve(__dirname, "lambda", "handler.js"); - this.lambdaFunctionContent = fs.readFileSync(codeLocation, "utf8"); - console.log('boop the woop'); - this.lambdaFunction = new lambda.Function(this, id + "-SingletonLambda", { - code: new lambda.InlineCode(this.lambdaFunctionContent), - description: "Lambda to make DynamoDB a global table", - handler: "index.handler", - runtime: lambda.Runtime.NodeJS810, - timeout: 300, - }); - this.lambdaFunction.addToRolePolicy(new iam.PolicyStatement() - .allow() - .addAllResources() - .addAction("iam:CreateServiceLinkedRole") - .addAction("application-autoscaling:DeleteScalingPolicy") - .addAction("application-autoscaling:DeregisterScalableTarget") - .addAction("dynamodb:CreateGlobalTable") - .addAction("dynamodb:DescribeLimits") - .addAction("dynamodb:UpdateGlobalTable")); - this.customResource = new cfn.CustomResource(this, id + "-CfnCustomResource", { - lambdaProvider: this.lambdaFunction, - properties: { - regions: props.regions, - resourceType: "Custom::MakeGlobalDynamoDB", - tableName: props.dynamoProps.tableName, - }, - }); - } -} -exports.LambdaGlobalDynamoDBMaker = LambdaGlobalDynamoDBMaker; -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibGFtYmRhLWdsb2JhbC1keW5hbW9kYi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImxhbWJkYS1nbG9iYWwtZHluYW1vZGIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFBQSxtREFBb0Q7QUFDcEQsd0NBQXlDO0FBQ3pDLDhDQUErQztBQUMvQyxvQ0FBcUM7QUFDckMseUJBQTBCO0FBQzFCLDZCQUE4QjtBQUc5Qjs7O0dBR0c7QUFDSCxNQUFhLHlCQUEwQixTQUFRLEdBQUcsQ0FBQyxLQUFLO0lBZ0JwRCxZQUFZLEtBQW9CLEVBQUUsRUFBVSxFQUFFLEtBQStCO1FBQ3pFLEtBQUssQ0FBQyxLQUFLLEVBQUUsRUFBRSxFQUFFLEtBQUssQ0FBQyxDQUFDO1FBQ3hCLE1BQU0sWUFBWSxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsU0FBUyxFQUFFLFFBQVEsRUFBRSxZQUFZLENBQUMsQ0FBQztRQUNyRSxJQUFJLENBQUMscUJBQXFCLEdBQUcsRUFBRSxDQUFDLFlBQVksQ0FBQyxZQUFZLEVBQUUsTUFBTSxDQUFDLENBQUM7UUFFbkUsT0FBTyxDQUFDLEdBQUcsQ0FBQyxlQUFlLENBQUMsQ0FBQztRQUU3QixJQUFJLENBQUMsY0FBYyxHQUFHLElBQUksTUFBTSxDQUFDLFFBQVEsQ0FBQyxJQUFJLEVBQUUsRUFBRSxHQUFHLGtCQUFrQixFQUFFO1lBQ3JFLElBQUksRUFBRSxJQUFJLE1BQU0sQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLHFCQUFxQixDQUFDO1lBQ3ZELFdBQVcsRUFBRSx3Q0FBd0M7WUFDckQsT0FBTyxFQUFFLGVBQWU7WUFDeEIsT0FBTyxFQUFFLE1BQU0sQ0FBQyxPQUFPLENBQUMsU0FBUztZQUNqQyxPQUFPLEVBQUUsR0FBRztTQUVmLENBQUMsQ0FBQztRQUNILElBQUksQ0FBQyxjQUFjLENBQUMsZUFBZSxDQUFDLElBQUksR0FBRyxDQUFDLGVBQWUsRUFBRTthQUN4RCxLQUFLLEVBQUU7YUFDUCxlQUFlLEVBQUU7YUFDakIsU0FBUyxDQUFDLDZCQUE2QixDQUFDO2FBQ3hDLFNBQVMsQ0FBQyw2Q0FBNkMsQ0FBQzthQUN4RCxTQUFTLENBQUMsa0RBQWtELENBQUM7YUFDN0QsU0FBUyxDQUFDLDRCQUE0QixDQUFDO2FBQ3ZDLFNBQVMsQ0FBQyx5QkFBeUIsQ0FBQzthQUNwQyxTQUFTLENBQUMsNEJBQTRCLENBQUMsQ0FBQyxDQUFDO1FBQzlDLElBQUksQ0FBQyxjQUFjLEdBQUcsSUFBSSxHQUFHLENBQUMsY0FBYyxDQUFDLElBQUksRUFBRSxFQUFFLEdBQUcsb0JBQW9CLEVBQUU7WUFDMUUsY0FBYyxFQUFFLElBQUksQ0FBQyxjQUFjO1lBQ25DLFVBQVUsRUFBRTtnQkFDUixPQUFPLEVBQUUsS0FBSyxDQUFDLE9BQU87Z0JBQ3RCLFlBQVksRUFBRSw0QkFBNEI7Z0JBQzFDLFNBQVMsRUFBRSxLQUFLLENBQUMsV0FBVyxDQUFDLFNBQVM7YUFDekM7U0FDSixDQUFDLENBQUM7SUFDTCxDQUFDO0NBQ047QUFqREQsOERBaURDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IGNmbiA9IHJlcXVpcmUoXCJAYXdzLWNkay9hd3MtY2xvdWRmb3JtYXRpb25cIik7XG5pbXBvcnQgaWFtID0gcmVxdWlyZShcIkBhd3MtY2RrL2F3cy1pYW1cIik7XG5pbXBvcnQgbGFtYmRhID0gcmVxdWlyZShcIkBhd3MtY2RrL2F3cy1sYW1iZGFcIik7XG5pbXBvcnQgY2RrID0gcmVxdWlyZShcIkBhd3MtY2RrL2Nka1wiKTtcbmltcG9ydCBmcyA9IHJlcXVpcmUoXCJmc1wiKTtcbmltcG9ydCBwYXRoID0gcmVxdWlyZShcInBhdGhcIik7XG5pbXBvcnQgeyBEeW5hbW9EQkdsb2JhbFN0YWNrUHJvcHMgfSBmcm9tIFwiLi9hd3MtZHluYW1vZGItZ2xvYmFsXCI7XG5cbi8qKlxuICogQSBzdGFjayB0aGF0IHdpbGwgbWFrZSBhIExhbWJkYSB0aGF0IHdpbGwgbGF1bmNoIGEgbGFtYmRhIHRvIGdsdWVcbiAqIHRvZ2V0aGVyIGFsbCB0aGUgRHluYW1vREIgdGFibGVzIGludG8gYSBnbG9iYWwgdGFibGVcbiAqL1xuZXhwb3J0IGNsYXNzIExhbWJkYUdsb2JhbER5bmFtb0RCTWFrZXIgZXh0ZW5kcyBjZGsuU3RhY2sge1xuICAgIC8qKlxuICAgICAqIFRoZSBzaW5nbGV0b24gTGFtYmRhIGZ1bmN0aW9uIHRoYXQgd2lsbCBjb25uZWN0IGFsbCB0aGUgRHluYW1vREIgdGFibGVzIHRvZ2V0aGVyIGludG8gYSBnbG9iYWwgdGFibGVcbiAgICAgKi9cbiAgICBwdWJsaWMgbGFtYmRhRnVuY3Rpb246IGxhbWJkYS5JRnVuY3Rpb247XG5cbiAgICAvKipcbiAgICAgKiBUaGUgY29udGVudCBvZiB0aGUgbGFtYmRhRnVuY3Rpb24gKHB5dGhvbjMuNyB1c2luZyBib3RvMylcbiAgICAgKi9cbiAgICBwdWJsaWMgbGFtYmRhRnVuY3Rpb25Db250ZW50OiBzdHJpbmc7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgQ2xvdWRGb3JtYXRpb24gQ3VzdG9tUmVzb3VyY2UgdGhhdCB3aWxsIG1hbmFnZSB0aGUgbGFtYmRhXG4gICAgICovXG4gICAgcHVibGljIGN1c3RvbVJlc291cmNlOiBjZm4uQ3VzdG9tUmVzb3VyY2U7XG5cbiAgICBjb25zdHJ1Y3RvcihzY29wZTogY2RrLkNvbnN0cnVjdCwgaWQ6IHN0cmluZywgcHJvcHM6IER5bmFtb0RCR2xvYmFsU3RhY2tQcm9wcykge1xuICAgICAgICBzdXBlcihzY29wZSwgaWQsIHByb3BzKTtcbiAgICAgICAgY29uc3QgY29kZUxvY2F0aW9uID0gcGF0aC5yZXNvbHZlKF9fZGlybmFtZSwgXCJsYW1iZGFcIiwgXCJoYW5kbGVyLmpzXCIpO1xuICAgICAgICB0aGlzLmxhbWJkYUZ1bmN0aW9uQ29udGVudCA9IGZzLnJlYWRGaWxlU3luYyhjb2RlTG9jYXRpb24sIFwidXRmOFwiKTtcblxuICAgICAgICBjb25zb2xlLmxvZygnYm9vcCB0aGUgd29vcCcpO1xuXG4gICAgICAgIHRoaXMubGFtYmRhRnVuY3Rpb24gPSBuZXcgbGFtYmRhLkZ1bmN0aW9uKHRoaXMsIGlkICsgXCItU2luZ2xldG9uTGFtYmRhXCIsIHtcbiAgICAgICAgICAgIGNvZGU6IG5ldyBsYW1iZGEuSW5saW5lQ29kZSh0aGlzLmxhbWJkYUZ1bmN0aW9uQ29udGVudCksXG4gICAgICAgICAgICBkZXNjcmlwdGlvbjogXCJMYW1iZGEgdG8gbWFrZSBEeW5hbW9EQiBhIGdsb2JhbCB0YWJsZVwiLFxuICAgICAgICAgICAgaGFuZGxlcjogXCJpbmRleC5oYW5kbGVyXCIsXG4gICAgICAgICAgICBydW50aW1lOiBsYW1iZGEuUnVudGltZS5Ob2RlSlM4MTAsXG4gICAgICAgICAgICB0aW1lb3V0OiAzMDAsXG4gICAgICAgICAgICAvLyB1dWlkOiBcIkQzOEI2NUE2LTZCNTQtNEZCNi05QkFELTlDRDQwQTZEQUMxMlwiLFxuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy5sYW1iZGFGdW5jdGlvbi5hZGRUb1JvbGVQb2xpY3kobmV3IGlhbS5Qb2xpY3lTdGF0ZW1lbnQoKVxuICAgICAgICAgICAgLmFsbG93KClcbiAgICAgICAgICAgIC5hZGRBbGxSZXNvdXJjZXMoKVxuICAgICAgICAgICAgLmFkZEFjdGlvbihcImlhbTpDcmVhdGVTZXJ2aWNlTGlua2VkUm9sZVwiKVxuICAgICAgICAgICAgLmFkZEFjdGlvbihcImFwcGxpY2F0aW9uLWF1dG9zY2FsaW5nOkRlbGV0ZVNjYWxpbmdQb2xpY3lcIilcbiAgICAgICAgICAgIC5hZGRBY3Rpb24oXCJhcHBsaWNhdGlvbi1hdXRvc2NhbGluZzpEZXJlZ2lzdGVyU2NhbGFibGVUYXJnZXRcIilcbiAgICAgICAgICAgIC5hZGRBY3Rpb24oXCJkeW5hbW9kYjpDcmVhdGVHbG9iYWxUYWJsZVwiKVxuICAgICAgICAgICAgLmFkZEFjdGlvbihcImR5bmFtb2RiOkRlc2NyaWJlTGltaXRzXCIpXG4gICAgICAgICAgICAuYWRkQWN0aW9uKFwiZHluYW1vZGI6VXBkYXRlR2xvYmFsVGFibGVcIikpO1xuICAgICAgICB0aGlzLmN1c3RvbVJlc291cmNlID0gbmV3IGNmbi5DdXN0b21SZXNvdXJjZSh0aGlzLCBpZCArIFwiLUNmbkN1c3RvbVJlc291cmNlXCIsIHtcbiAgICAgICAgICAgIGxhbWJkYVByb3ZpZGVyOiB0aGlzLmxhbWJkYUZ1bmN0aW9uLFxuICAgICAgICAgICAgcHJvcGVydGllczoge1xuICAgICAgICAgICAgICAgIHJlZ2lvbnM6IHByb3BzLnJlZ2lvbnMsXG4gICAgICAgICAgICAgICAgcmVzb3VyY2VUeXBlOiBcIkN1c3RvbTo6TWFrZUdsb2JhbER5bmFtb0RCXCIsXG4gICAgICAgICAgICAgICAgdGFibGVOYW1lOiBwcm9wcy5keW5hbW9Qcm9wcy50YWJsZU5hbWUsXG4gICAgICAgICAgICB9LFxuICAgICAgICB9KTtcbiAgICAgIH1cbn1cbiJdfQ== \ No newline at end of file diff --git a/packages/@aws-cdk/aws-dynamodb-global/lib/multi-dynamodb-stack.d.ts b/packages/@aws-cdk/aws-dynamodb-global/lib/multi-dynamodb-stack.d.ts deleted file mode 100644 index 907b72b571d9c..0000000000000 --- a/packages/@aws-cdk/aws-dynamodb-global/lib/multi-dynamodb-stack.d.ts +++ /dev/null @@ -1,13 +0,0 @@ -import dynamodb = require("@aws-cdk/aws-dynamodb"); -import cdk = require("@aws-cdk/cdk"); -import { DynamoDBGlobalStackProps } from "./aws-dynamodb-global"; -/** - * Stack to create a single DynamoDB Table - */ -export declare class MultiDynamoDBStack extends cdk.Stack { - /** - * The DynamoDB Table created - */ - table: dynamodb.Table; - constructor(scope: cdk.Construct, id: string, props: DynamoDBGlobalStackProps); -} diff --git a/packages/@aws-cdk/aws-dynamodb-global/lib/multi-dynamodb-stack.js b/packages/@aws-cdk/aws-dynamodb-global/lib/multi-dynamodb-stack.js deleted file mode 100644 index 3ecbf5920ed8e..0000000000000 --- a/packages/@aws-cdk/aws-dynamodb-global/lib/multi-dynamodb-stack.js +++ /dev/null @@ -1,15 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -const dynamodb = require("@aws-cdk/aws-dynamodb"); -const cdk = require("@aws-cdk/cdk"); -/** - * Stack to create a single DynamoDB Table - */ -class MultiDynamoDBStack extends cdk.Stack { - constructor(scope, id, props) { - super(scope, id, props); - this.table = new dynamodb.Table(this, id + "-table", props.dynamoProps); - } -} -exports.MultiDynamoDBStack = MultiDynamoDBStack; -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibXVsdGktZHluYW1vZGItc3RhY2suanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJtdWx0aS1keW5hbW9kYi1zdGFjay50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQUFBLGtEQUFtRDtBQUNuRCxvQ0FBcUM7QUFHckM7O0dBRUc7QUFDSCxNQUFhLGtCQUFtQixTQUFRLEdBQUcsQ0FBQyxLQUFLO0lBTTdDLFlBQVksS0FBb0IsRUFBRSxFQUFVLEVBQUUsS0FBK0I7UUFDekUsS0FBSyxDQUFDLEtBQUssRUFBRSxFQUFFLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFDeEIsSUFBSSxDQUFDLEtBQUssR0FBRyxJQUFJLFFBQVEsQ0FBQyxLQUFLLENBQUMsSUFBSSxFQUFFLEVBQUUsR0FBRyxRQUFRLEVBQUUsS0FBSyxDQUFDLFdBQVcsQ0FBQyxDQUFDO0lBQzVFLENBQUM7Q0FDSjtBQVZELGdEQVVDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IGR5bmFtb2RiID0gcmVxdWlyZShcIkBhd3MtY2RrL2F3cy1keW5hbW9kYlwiKTtcbmltcG9ydCBjZGsgPSByZXF1aXJlKFwiQGF3cy1jZGsvY2RrXCIpO1xuaW1wb3J0IHsgRHluYW1vREJHbG9iYWxTdGFja1Byb3BzIH0gZnJvbSBcIi4vYXdzLWR5bmFtb2RiLWdsb2JhbFwiO1xuXG4vKipcbiAqIFN0YWNrIHRvIGNyZWF0ZSBhIHNpbmdsZSBEeW5hbW9EQiBUYWJsZVxuICovXG5leHBvcnQgY2xhc3MgTXVsdGlEeW5hbW9EQlN0YWNrIGV4dGVuZHMgY2RrLlN0YWNrIHtcbiAgICAvKipcbiAgICAgKiBUaGUgRHluYW1vREIgVGFibGUgY3JlYXRlZFxuICAgICAqL1xuICAgIHB1YmxpYyB0YWJsZTogZHluYW1vZGIuVGFibGU7XG5cbiAgICBjb25zdHJ1Y3RvcihzY29wZTogY2RrLkNvbnN0cnVjdCwgaWQ6IHN0cmluZywgcHJvcHM6IER5bmFtb0RCR2xvYmFsU3RhY2tQcm9wcykge1xuICAgICAgICBzdXBlcihzY29wZSwgaWQsIHByb3BzKTtcbiAgICAgICAgdGhpcy50YWJsZSA9IG5ldyBkeW5hbW9kYi5UYWJsZSh0aGlzLCBpZCArIFwiLXRhYmxlXCIsIHByb3BzLmR5bmFtb1Byb3BzKTtcbiAgICB9XG59Il19 \ No newline at end of file diff --git a/packages/@aws-cdk/aws-dynamodb-global/test/integ.dynamodb.global.d.ts b/packages/@aws-cdk/aws-dynamodb-global/test/integ.dynamodb.global.d.ts deleted file mode 100644 index cb0ff5c3b541f..0000000000000 --- a/packages/@aws-cdk/aws-dynamodb-global/test/integ.dynamodb.global.d.ts +++ /dev/null @@ -1 +0,0 @@ -export {}; diff --git a/packages/@aws-cdk/aws-dynamodb-global/test/integ.dynamodb.global.js b/packages/@aws-cdk/aws-dynamodb-global/test/integ.dynamodb.global.js deleted file mode 100644 index 11ea9b1108a57..0000000000000 --- a/packages/@aws-cdk/aws-dynamodb-global/test/integ.dynamodb.global.js +++ /dev/null @@ -1,21 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -const aws_dynamodb_1 = require("@aws-cdk/aws-dynamodb"); -const cdk_1 = require("@aws-cdk/cdk"); -const lib_1 = require("../lib"); -// CDK parameters -const STACK_NAME = 'aws-cdk-dynamodb-global'; -// DynamoDB table parameters -const TABLE = 'GlobalTable'; -const TABLE_PARTITION_KEY = { name: 'hashKey', type: aws_dynamodb_1.AttributeType.String }; -const STACK_PROPS = { - dynamoProps: { - partitionKey: TABLE_PARTITION_KEY, - tableName: TABLE - }, - regions: ["us-east-1", "us-east-2", "us-west-2"] -}; -const app = new cdk_1.App(); -new lib_1.GlobalTable(app, STACK_NAME, STACK_PROPS); -app.run(); -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW50ZWcuZHluYW1vZGIuZ2xvYmFsLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiaW50ZWcuZHluYW1vZGIuZ2xvYmFsLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBQUEsd0RBQWlFO0FBQ2pFLHNDQUFtQztBQUNuQyxnQ0FBK0Q7QUFFL0QsaUJBQWlCO0FBQ2pCLE1BQU0sVUFBVSxHQUFHLHlCQUF5QixDQUFDO0FBRTdDLDRCQUE0QjtBQUM1QixNQUFNLEtBQUssR0FBRyxhQUFhLENBQUM7QUFDNUIsTUFBTSxtQkFBbUIsR0FBYyxFQUFFLElBQUksRUFBRSxTQUFTLEVBQUUsSUFBSSxFQUFFLDRCQUFhLENBQUMsTUFBTSxFQUFFLENBQUM7QUFFdkYsTUFBTSxXQUFXLEdBQTZCO0lBQzFDLFdBQVcsRUFBRTtRQUNULFlBQVksRUFBRSxtQkFBbUI7UUFDakMsU0FBUyxFQUFFLEtBQUs7S0FDbkI7SUFDRCxPQUFPLEVBQUUsQ0FBRSxXQUFXLEVBQUUsV0FBVyxFQUFFLFdBQVcsQ0FBRTtDQUNyRCxDQUFDO0FBRUYsTUFBTSxHQUFHLEdBQUcsSUFBSSxTQUFHLEVBQUUsQ0FBQztBQUN0QixJQUFJLGlCQUFXLENBQUMsR0FBRyxFQUFFLFVBQVUsRUFBRSxXQUFXLENBQUMsQ0FBQztBQUM5QyxHQUFHLENBQUMsR0FBRyxFQUFFLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBBdHRyaWJ1dGUsIEF0dHJpYnV0ZVR5cGUgfSBmcm9tICdAYXdzLWNkay9hd3MtZHluYW1vZGInO1xuaW1wb3J0IHsgQXBwIH0gZnJvbSAnQGF3cy1jZGsvY2RrJztcbmltcG9ydCB7IER5bmFtb0RCR2xvYmFsU3RhY2tQcm9wcywgR2xvYmFsVGFibGUgfSBmcm9tICcuLi9saWInO1xuXG4vLyBDREsgcGFyYW1ldGVyc1xuY29uc3QgU1RBQ0tfTkFNRSA9ICdhd3MtY2RrLWR5bmFtb2RiLWdsb2JhbCc7XG5cbi8vIER5bmFtb0RCIHRhYmxlIHBhcmFtZXRlcnNcbmNvbnN0IFRBQkxFID0gJ0dsb2JhbFRhYmxlJztcbmNvbnN0IFRBQkxFX1BBUlRJVElPTl9LRVk6IEF0dHJpYnV0ZSA9IHsgbmFtZTogJ2hhc2hLZXknLCB0eXBlOiBBdHRyaWJ1dGVUeXBlLlN0cmluZyB9O1xuXG5jb25zdCBTVEFDS19QUk9QUzogRHluYW1vREJHbG9iYWxTdGFja1Byb3BzID0ge1xuICAgIGR5bmFtb1Byb3BzOiB7XG4gICAgICAgIHBhcnRpdGlvbktleTogVEFCTEVfUEFSVElUSU9OX0tFWSxcbiAgICAgICAgdGFibGVOYW1lOiBUQUJMRVxuICAgIH0sXG4gICAgcmVnaW9uczogWyBcInVzLWVhc3QtMVwiLCBcInVzLWVhc3QtMlwiLCBcInVzLXdlc3QtMlwiIF1cbn07XG5cbmNvbnN0IGFwcCA9IG5ldyBBcHAoKTtcbm5ldyBHbG9iYWxUYWJsZShhcHAsIFNUQUNLX05BTUUsIFNUQUNLX1BST1BTKTtcbmFwcC5ydW4oKTtcbiJdfQ== \ No newline at end of file diff --git a/packages/@aws-cdk/aws-dynamodb-global/test/test.dynamodb.global.d.ts b/packages/@aws-cdk/aws-dynamodb-global/test/test.dynamodb.global.d.ts deleted file mode 100644 index b01a554b50f83..0000000000000 --- a/packages/@aws-cdk/aws-dynamodb-global/test/test.dynamodb.global.d.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { Test } from 'nodeunit'; -declare const _default: { - 'default stack': { - 'default'(test: Test): void; - }; -}; -export = _default; diff --git a/packages/@aws-cdk/aws-dynamodb-global/test/test.dynamodb.global.js b/packages/@aws-cdk/aws-dynamodb-global/test/test.dynamodb.global.js deleted file mode 100644 index 64cacdc793a27..0000000000000 --- a/packages/@aws-cdk/aws-dynamodb-global/test/test.dynamodb.global.js +++ /dev/null @@ -1,36 +0,0 @@ -"use strict"; -const assert_1 = require("@aws-cdk/assert"); -const aws_dynamodb_1 = require("@aws-cdk/aws-dynamodb"); -const cdk_1 = require("@aws-cdk/cdk"); -const ddb = require("@aws-cdk/aws-dynamodb"); -// tslint:disable:object-literal-key-quotes -// CDK parameters -// const CONSTRUCT_NAME = 'aws-cdk-dynamodb-global'; -// DynamoDB table parameters -const TABLE_NAME = 'GlobalTable'; -const TABLE_PARTITION_KEY = { name: 'hashKey', type: aws_dynamodb_1.AttributeType.String }; -const STACK_PROPS = { - dynamoProps: { - partitionKey: TABLE_PARTITION_KEY, - tableName: TABLE_NAME - }, - regions: ["us-east-1", "us-east-2", "us-west-2"] -}; -module.exports = { - 'default stack': { - 'default'(test) { - const app = new cdk_1.App(); - const stack = new cdk_1.Stack(app, 'Stack'); - // new GlobalTable(stack, CONSTRUCT_NAME, STACK_PROPS); - new ddb.Table(stack, 'xxx', { - partitionKey: { name: 'asdf', type: ddb.AttributeType.String }, - }); - console.log(stack._toCloudFormation()); - assert_1.expect(stack).to(assert_1.haveResource('AWS::Lambda::Function', { - "Regions": STACK_PROPS.regions - })); - test.done(); - } - } -}; -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGVzdC5keW5hbW9kYi5nbG9iYWwuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJ0ZXN0LmR5bmFtb2RiLmdsb2JhbC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUEsNENBQXVEO0FBQ3ZELHdEQUFpRTtBQUNqRSxzQ0FBMEM7QUFPMUMsNkNBQThDO0FBRTlDLDJDQUEyQztBQUUzQyxpQkFBaUI7QUFDakIsb0RBQW9EO0FBRXBELDRCQUE0QjtBQUM1QixNQUFNLFVBQVUsR0FBRyxhQUFhLENBQUM7QUFDakMsTUFBTSxtQkFBbUIsR0FBYyxFQUFFLElBQUksRUFBRSxTQUFTLEVBQUUsSUFBSSxFQUFFLDRCQUFhLENBQUMsTUFBTSxFQUFFLENBQUM7QUFFdkYsTUFBTSxXQUFXLEdBQTZCO0lBQzFDLFdBQVcsRUFBRTtRQUNULFlBQVksRUFBRSxtQkFBbUI7UUFDakMsU0FBUyxFQUFFLFVBQVU7S0FDeEI7SUFDRCxPQUFPLEVBQUUsQ0FBRSxXQUFXLEVBQUUsV0FBVyxFQUFFLFdBQVcsQ0FBRTtDQUNyRCxDQUFDO0FBRUYsaUJBQVM7SUFDTCxlQUFlLEVBQUU7UUFDYixTQUFTLENBQUMsSUFBVTtZQUNoQixNQUFNLEdBQUcsR0FBRyxJQUFJLFNBQUcsRUFBRSxDQUFDO1lBQ3RCLE1BQU0sS0FBSyxHQUFHLElBQUksV0FBSyxDQUFDLEdBQUcsRUFBRSxPQUFPLENBQUMsQ0FBQztZQUN0Qyx1REFBdUQ7WUFDdkQsSUFBSSxHQUFHLENBQUMsS0FBSyxDQUFDLEtBQUssRUFBRSxLQUFLLEVBQUU7Z0JBQ3hCLFlBQVksRUFBRSxFQUFFLElBQUksRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFLEdBQUcsQ0FBQyxhQUFhLENBQUMsTUFBTSxFQUFFO2FBQ2pFLENBQUMsQ0FBQztZQUVILE9BQU8sQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLGlCQUFpQixFQUFFLENBQUMsQ0FBQztZQUV2QyxlQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsRUFBRSxDQUFDLHFCQUFZLENBQUMsdUJBQXVCLEVBQUU7Z0JBQ25ELFNBQVMsRUFBRSxXQUFXLENBQUMsT0FBTzthQUNqQyxDQUFDLENBQUMsQ0FBQztZQUVKLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQztRQUNoQixDQUFDO0tBQ0o7Q0FDSixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgZXhwZWN0LCBoYXZlUmVzb3VyY2UgfSBmcm9tICdAYXdzLWNkay9hc3NlcnQnO1xuaW1wb3J0IHsgQXR0cmlidXRlLCBBdHRyaWJ1dGVUeXBlIH0gZnJvbSAnQGF3cy1jZGsvYXdzLWR5bmFtb2RiJztcbmltcG9ydCB7IEFwcCwgU3RhY2sgfSBmcm9tICdAYXdzLWNkay9jZGsnO1xuaW1wb3J0IHsgVGVzdCB9IGZyb20gJ25vZGV1bml0JztcbmltcG9ydCB7XG4gICAgRHluYW1vREJHbG9iYWxTdGFja1Byb3BzLFxuLy8gICAgR2xvYmFsVGFibGUsXG59IGZyb20gJy4uL2xpYic7XG5cbmltcG9ydCBkZGIgPSByZXF1aXJlKCdAYXdzLWNkay9hd3MtZHluYW1vZGInKTtcblxuLy8gdHNsaW50OmRpc2FibGU6b2JqZWN0LWxpdGVyYWwta2V5LXF1b3Rlc1xuXG4vLyBDREsgcGFyYW1ldGVyc1xuLy8gY29uc3QgQ09OU1RSVUNUX05BTUUgPSAnYXdzLWNkay1keW5hbW9kYi1nbG9iYWwnO1xuXG4vLyBEeW5hbW9EQiB0YWJsZSBwYXJhbWV0ZXJzXG5jb25zdCBUQUJMRV9OQU1FID0gJ0dsb2JhbFRhYmxlJztcbmNvbnN0IFRBQkxFX1BBUlRJVElPTl9LRVk6IEF0dHJpYnV0ZSA9IHsgbmFtZTogJ2hhc2hLZXknLCB0eXBlOiBBdHRyaWJ1dGVUeXBlLlN0cmluZyB9O1xuXG5jb25zdCBTVEFDS19QUk9QUzogRHluYW1vREJHbG9iYWxTdGFja1Byb3BzID0ge1xuICAgIGR5bmFtb1Byb3BzOiB7XG4gICAgICAgIHBhcnRpdGlvbktleTogVEFCTEVfUEFSVElUSU9OX0tFWSxcbiAgICAgICAgdGFibGVOYW1lOiBUQUJMRV9OQU1FXG4gICAgfSxcbiAgICByZWdpb25zOiBbIFwidXMtZWFzdC0xXCIsIFwidXMtZWFzdC0yXCIsIFwidXMtd2VzdC0yXCIgXVxufTtcblxuZXhwb3J0ID0ge1xuICAgICdkZWZhdWx0IHN0YWNrJzoge1xuICAgICAgICAnZGVmYXVsdCcodGVzdDogVGVzdCkge1xuICAgICAgICAgICAgY29uc3QgYXBwID0gbmV3IEFwcCgpO1xuICAgICAgICAgICAgY29uc3Qgc3RhY2sgPSBuZXcgU3RhY2soYXBwLCAnU3RhY2snKTtcbiAgICAgICAgICAgIC8vIG5ldyBHbG9iYWxUYWJsZShzdGFjaywgQ09OU1RSVUNUX05BTUUsIFNUQUNLX1BST1BTKTtcbiAgICAgICAgICAgIG5ldyBkZGIuVGFibGUoc3RhY2ssICd4eHgnLCB7XG4gICAgICAgICAgICAgICAgcGFydGl0aW9uS2V5OiB7IG5hbWU6ICdhc2RmJywgdHlwZTogZGRiLkF0dHJpYnV0ZVR5cGUuU3RyaW5nIH0sXG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgY29uc29sZS5sb2coc3RhY2suX3RvQ2xvdWRGb3JtYXRpb24oKSk7XG5cbiAgICAgICAgICAgIGV4cGVjdChzdGFjaykudG8oaGF2ZVJlc291cmNlKCdBV1M6OkxhbWJkYTo6RnVuY3Rpb24nLCB7XG4gICAgICAgICAgICAgICAgXCJSZWdpb25zXCI6IFNUQUNLX1BST1BTLnJlZ2lvbnNcbiAgICAgICAgICAgIH0pKTtcblxuICAgICAgICAgICAgdGVzdC5kb25lKCk7XG4gICAgICAgIH1cbiAgICB9XG59O1xuIl19 \ No newline at end of file diff --git a/packages/@aws-cdk/aws-dynamodb-global/tsconfig.json b/packages/@aws-cdk/aws-dynamodb-global/tsconfig.json deleted file mode 100644 index b22e4f3c11020..0000000000000 --- a/packages/@aws-cdk/aws-dynamodb-global/tsconfig.json +++ /dev/null @@ -1,46 +0,0 @@ -{ - "compilerOptions": { - "alwaysStrict": true, - "charset": "utf8", - "declaration": true, - "experimentalDecorators": true, - "inlineSourceMap": true, - "inlineSources": true, - "lib": [ - "es2016", - "es2017.object", - "es2017.string" - ], - "module": "CommonJS", - "noEmitOnError": true, - "noFallthroughCasesInSwitch": true, - "noImplicitAny": true, - "noImplicitReturns": true, - "noImplicitThis": true, - "noUnusedLocals": true, - "noUnusedParameters": true, - "resolveJsonModule": true, - "strict": true, - "strictNullChecks": true, - "target": "ES2018", - "composite": true - }, - "include": [ - "**/*.ts" - ], - "exclude": [ - "node_modules" - ], - "references": [ - { - "path": "../aws-dynamodb" - }, - { - "path": "../aws-lambda" - }, - { - "path": "../aws-cloudformation" - } - ], - "_generated_by_jsii_": "Generated by jsii - safe to delete, and ideally should be in .gitignore" -} From 3772ba41c507f76a13b374710577044ab3139e18 Mon Sep 17 00:00:00 2001 From: Rico Huijbers Date: Wed, 3 Apr 2019 14:12:19 +0200 Subject: [PATCH 29/31] Update IParameter --- packages/@aws-cdk/aws-ssm/lib/parameter.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/@aws-cdk/aws-ssm/lib/parameter.ts b/packages/@aws-cdk/aws-ssm/lib/parameter.ts index 88411d307a1cf..47de0226b1fbf 100644 --- a/packages/@aws-cdk/aws-ssm/lib/parameter.ts +++ b/packages/@aws-cdk/aws-ssm/lib/parameter.ts @@ -26,14 +26,14 @@ export interface IParameter extends cdk.IConstruct { * * @param grantee the role to be granted read-only access to the parameter. */ - grantRead(grantee: iam.IGrantable): void; + grantRead(grantee: iam.IGrantable): iam.Grant; /** * Grants write (PutParameter) permissions on the SSM Parameter. * * @param grantee the role to be granted write access to the parameter. */ - grantWrite(grantee: iam.IGrantable): void; + grantWrite(grantee: iam.IGrantable): iam.Grant; } /** From 0d24421de52ce313b079e1db13f774a99475e7ec Mon Sep 17 00:00:00 2001 From: Rico Huijbers Date: Wed, 3 Apr 2019 14:21:45 +0200 Subject: [PATCH 30/31] Fix stray unrenamed call --- packages/@aws-cdk/aws-logs/lib/log-group.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/@aws-cdk/aws-logs/lib/log-group.ts b/packages/@aws-cdk/aws-logs/lib/log-group.ts index dcf4eddc93f53..9453cfa67c448 100644 --- a/packages/@aws-cdk/aws-logs/lib/log-group.ts +++ b/packages/@aws-cdk/aws-logs/lib/log-group.ts @@ -179,7 +179,7 @@ export abstract class LogGroupBase extends cdk.Construct implements ILogGroup { * Give the indicated permissions on this log group and all streams */ public grant(grantee: iam.IGrantable, ...actions: string[]) { - return iam.Grant.onPrincipal({ + return iam.Grant.addToPrincipal({ grantee, actions, // A LogGroup ARN out of CloudFormation already includes a ':*' at the end to include the log streams under the group. From b51c76d464462afc18f8b5859020570fa0553344 Mon Sep 17 00:00:00 2001 From: Rico Huijbers Date: Wed, 3 Apr 2019 14:42:54 +0200 Subject: [PATCH 31/31] Make sure JSON.stringify(principal) doesn't recurse indefinitely --- packages/@aws-cdk/aws-iam/lib/policy-document.ts | 5 +++++ packages/@aws-cdk/aws-lambda/lib/function-base.ts | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/packages/@aws-cdk/aws-iam/lib/policy-document.ts b/packages/@aws-cdk/aws-iam/lib/policy-document.ts index c8d229d03ad34..21022bb5ee64c 100644 --- a/packages/@aws-cdk/aws-iam/lib/policy-document.ts +++ b/packages/@aws-cdk/aws-iam/lib/policy-document.ts @@ -72,6 +72,11 @@ export abstract class PrincipalBase implements IPrincipal { // should return something nicer. return JSON.stringify(this.policyFragment.principalJson); } + + public toJSON() { + // Have to implement toJSON() because the default will lead to infinite recursion. + return this.policyFragment.principalJson; + } } /** diff --git a/packages/@aws-cdk/aws-lambda/lib/function-base.ts b/packages/@aws-cdk/aws-lambda/lib/function-base.ts index 23a0ea7cf82d4..0fb8dd77cd6bd 100644 --- a/packages/@aws-cdk/aws-lambda/lib/function-base.ts +++ b/packages/@aws-cdk/aws-lambda/lib/function-base.ts @@ -336,7 +336,7 @@ export abstract class FunctionBase extends cdk.Construct implements IFunction { source.bind(this); } - private parsePermissionPrincipal(principal?: iam.IGrantable) { + private parsePermissionPrincipal(principal?: iam.IPrincipal) { if (!principal) { return undefined; } @@ -350,7 +350,7 @@ export abstract class FunctionBase extends cdk.Construct implements IFunction { return (principal as iam.ServicePrincipal).service; } - throw new Error(`Invalid principal type for Lambda permission statement: ${JSON.stringify(this.node.resolve(principal))}. ` + + throw new Error(`Invalid principal type for Lambda permission statement: ${this.node.resolve(principal.toString())}. ` + 'Supported: AccountPrincipal, ServicePrincipal'); } }