@guardian/cdk 63.6.2 → 64.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (110) hide show
  1. package/lib/aspects/cfn-include-reporter.js.map +1 -1
  2. package/lib/aspects/cfn-parameter-reporter.js.map +1 -1
  3. package/lib/aspects/metadata.js.map +1 -1
  4. package/lib/bin/aws-credential-provider.d.ts.map +1 -1
  5. package/lib/bin/commands/account-readiness/index.d.ts.map +1 -1
  6. package/lib/bin/commands/account-readiness/index.js.map +1 -1
  7. package/lib/bin/commands/account-readiness/ssm.d.ts.map +1 -1
  8. package/lib/bin/commands/account-readiness/ssm.js.map +1 -1
  9. package/lib/bin/commands/aws-cdk-version.d.ts.map +1 -1
  10. package/lib/bin/commands/new-project/index.d.ts.map +1 -1
  11. package/lib/bin/commands/new-project/index.js.map +1 -1
  12. package/lib/bin/commands/new-project/utils/app.d.ts.map +1 -1
  13. package/lib/bin/commands/new-project/utils/app.js.map +1 -1
  14. package/lib/bin/commands/new-project/utils/imports.js.map +1 -1
  15. package/lib/bin/commands/new-project/utils/init.d.ts.map +1 -1
  16. package/lib/bin/commands/new-project/utils/init.js.map +1 -1
  17. package/lib/bin/commands/new-project/utils/snapshot.d.ts.map +1 -1
  18. package/lib/bin/commands/new-project/utils/snapshot.js.map +1 -1
  19. package/lib/bin/commands/new-project/utils/stack.d.ts.map +1 -1
  20. package/lib/bin/commands/new-project/utils/stack.js.map +1 -1
  21. package/lib/bin/commands/new-project/utils/utils.js +1 -2
  22. package/lib/bin/commands/new-project/utils/utils.js.map +1 -1
  23. package/lib/bin/index.js.map +1 -1
  24. package/lib/constants/library-info.js +3 -3
  25. package/lib/constants/library-info.js.map +1 -1
  26. package/lib/constructs/autoscaling/asg.js.map +1 -1
  27. package/lib/constructs/autoscaling/user-data.js.map +1 -1
  28. package/lib/constructs/cloudwatch/alarm.js.map +1 -1
  29. package/lib/constructs/core/identity.d.ts.map +1 -1
  30. package/lib/constructs/core/parameters/anghammarad.js.map +1 -1
  31. package/lib/constructs/core/parameters/fastly.js.map +1 -1
  32. package/lib/constructs/core/parameters/log-shipping.js.map +1 -1
  33. package/lib/constructs/core/parameters/s3.js.map +1 -1
  34. package/lib/constructs/core/parameters/vpc.js.map +1 -1
  35. package/lib/constructs/core/stack.js.map +1 -1
  36. package/lib/constructs/dns/dns-records.js.map +1 -1
  37. package/lib/constructs/ec2/security-groups/base.js.map +1 -1
  38. package/lib/constructs/ec2/vpc.d.ts.map +1 -1
  39. package/lib/constructs/ec2/vpc.js.map +1 -1
  40. package/lib/constructs/ecs/ecs-task.js +1 -1
  41. package/lib/constructs/ecs/ecs-task.js.map +1 -1
  42. package/lib/constructs/iam/policies/anghammarad.js.map +1 -1
  43. package/lib/constructs/iam/policies/describe-ec2.js.map +1 -1
  44. package/lib/constructs/iam/policies/kcl.js +1 -1
  45. package/lib/constructs/iam/policies/kcl.js.map +1 -1
  46. package/lib/constructs/iam/policies/log-shipping.js.map +1 -1
  47. package/lib/constructs/iam/policies/parameter-store-read.d.ts +8 -1
  48. package/lib/constructs/iam/policies/parameter-store-read.d.ts.map +1 -1
  49. package/lib/constructs/iam/policies/parameter-store-read.js +21 -0
  50. package/lib/constructs/iam/policies/parameter-store-read.js.map +1 -1
  51. package/lib/constructs/iam/policies/ssm-ssh.js.map +1 -1
  52. package/lib/constructs/iam/roles/instance-role.js +1 -1
  53. package/lib/constructs/iam/roles/instance-role.js.map +1 -1
  54. package/lib/constructs/lambda/lambda.js.map +1 -1
  55. package/lib/constructs/loadbalancing/alb/application-load-balancer.js.map +1 -1
  56. package/lib/constructs/loadbalancing/alb/application-target-group.js +1 -1
  57. package/lib/constructs/loadbalancing/alb/application-target-group.js.map +1 -1
  58. package/lib/constructs/ses/index.js.map +1 -1
  59. package/lib/constructs/vpc/vpc.js.map +1 -1
  60. package/lib/experimental/constructs/iam/policies/developer-policy.js.map +1 -1
  61. package/lib/experimental/constructs/riff-raff-deployment-id.js.map +1 -1
  62. package/lib/experimental/patterns/ec2-app.js.map +1 -1
  63. package/lib/experimental/patterns/gu-load-balanced-app.d.ts +5 -5
  64. package/lib/experimental/patterns/gu-load-balanced-app.d.ts.map +1 -1
  65. package/lib/experimental/patterns/gu-load-balanced-app.js +37 -28
  66. package/lib/experimental/patterns/gu-load-balanced-app.js.map +1 -1
  67. package/lib/patterns/api-lambda.js.map +1 -1
  68. package/lib/patterns/api-multiple-lambdas.js.map +1 -1
  69. package/lib/patterns/ec2-app/base.d.ts +3 -3
  70. package/lib/patterns/ec2-app/base.d.ts.map +1 -1
  71. package/lib/patterns/ec2-app/base.js +4 -11
  72. package/lib/patterns/ec2-app/base.js.map +1 -1
  73. package/lib/riff-raff-yaml-file/deployments/autoscaling.js +2 -3
  74. package/lib/riff-raff-yaml-file/deployments/autoscaling.js.map +1 -1
  75. package/lib/riff-raff-yaml-file/deployments/cloudformation.js +3 -4
  76. package/lib/riff-raff-yaml-file/deployments/cloudformation.js.map +1 -1
  77. package/lib/riff-raff-yaml-file/deployments/lambda.js +2 -3
  78. package/lib/riff-raff-yaml-file/deployments/lambda.js.map +1 -1
  79. package/lib/riff-raff-yaml-file/deployments/update-parameters.js +1 -2
  80. package/lib/riff-raff-yaml-file/deployments/update-parameters.js.map +1 -1
  81. package/lib/riff-raff-yaml-file/group-by.js +5 -6
  82. package/lib/riff-raff-yaml-file/group-by.js.map +1 -1
  83. package/lib/riff-raff-yaml-file/index.js +2 -2
  84. package/lib/riff-raff-yaml-file/index.js.map +1 -1
  85. package/lib/types/access.js.map +1 -1
  86. package/lib/utils/array.js +1 -2
  87. package/lib/utils/array.js.map +1 -1
  88. package/lib/utils/cli/vpc.d.ts.map +1 -1
  89. package/lib/utils/cli/vpc.js.map +1 -1
  90. package/lib/utils/cognito/cognito.d.ts.map +1 -1
  91. package/lib/utils/exec.js +2 -3
  92. package/lib/utils/exec.js.map +1 -1
  93. package/lib/utils/git.js +2 -3
  94. package/lib/utils/git.js.map +1 -1
  95. package/lib/utils/lambda/event-source.js +2 -2
  96. package/lib/utils/lambda/event-source.js.map +1 -1
  97. package/lib/utils/math.d.ts.map +1 -1
  98. package/lib/utils/mixin/app-aware-construct.js +1 -2
  99. package/lib/utils/mixin/app-aware-construct.js.map +1 -1
  100. package/lib/utils/security-groups/helpers.d.ts.map +1 -1
  101. package/lib/utils/singleton.d.ts +1 -1
  102. package/lib/utils/singleton.d.ts.map +1 -1
  103. package/lib/utils/string.d.ts.map +1 -1
  104. package/lib/utils/test/assertions.js.map +1 -1
  105. package/lib/utils/test/attach-policy-to-test-role.d.ts.map +1 -1
  106. package/lib/utils/test/simple-gu-stack.js +1 -2
  107. package/lib/utils/test/simple-gu-stack.js.map +1 -1
  108. package/lib/utils/test/template.js +1 -2
  109. package/lib/utils/test/template.js.map +1 -1
  110. package/package.json +4 -4
@@ -1 +1 @@
1
- {"version":3,"file":"anghammarad.js","sourceRoot":"","sources":["../../../../src/constructs/core/parameters/anghammarad.ts"],"names":[],"mappings":";;;AAAA,kDAA+D;AAC/D,wDAAqE;AAErE,iCAA2C;AAE3C;;;;;GAKG;AACH,MAAa,2BAA4B,SAAQ,wBAAiB;IAGhE,YAAoB,KAAc;QAChC,KAAK,CAAC,KAAK,EAAE,mBAAmB,EAAE;YAChC,OAAO,EAAE,IAAI;YACb,OAAO,EAAE,qCAAyB,CAAC,WAAW,CAAC,IAAI;YACnD,WAAW,EAAE,qCAAyB,CAAC,WAAW,CAAC,WAAW;SAC/D,CAAC,CAAC;IACL,CAAC;IAED;;;;;OAKG;IACI,MAAM,CAAC,WAAW,CAAC,KAAc;QACtC,IAAI,CAAC,IAAI,CAAC,QAAQ,IAAI,CAAC,IAAA,qCAAyB,EAAC,KAAK,EAAE,IAAI,CAAC,QAAQ,CAAC,EAAE;YACtE,IAAI,CAAC,QAAQ,GAAG,IAAI,2BAA2B,CAAC,KAAK,CAAC,CAAC;SACxD;QAED,OAAO,IAAI,CAAC,QAAQ,CAAC;IACvB,CAAC;CACF;AAxBD,kEAwBC","sourcesContent":["import { NAMED_SSM_PARAMETER_PATHS } from \"../../../constants\";\nimport { isSingletonPresentInStack } from \"../../../utils/singleton\";\nimport type { GuStack } from \"../stack\";\nimport { GuStringParameter } from \"./base\";\n\n/**\n * Creates a CloudFormation parameter to a SSM Parameter Store item that holds the ARN of the Anghammarad SNS topic.\n * This parameter is implemented as a singleton, meaning only one can ever be added to a stack and will be reused if necessary.\n *\n * @see https://github.com/guardian/anghammarad\n */\nexport class GuAnghammaradTopicParameter extends GuStringParameter {\n private static instance: GuAnghammaradTopicParameter | undefined;\n\n private constructor(scope: GuStack) {\n super(scope, \"AnghammaradSnsArn\", {\n fromSSM: true,\n default: NAMED_SSM_PARAMETER_PATHS.Anghammarad.path,\n description: NAMED_SSM_PARAMETER_PATHS.Anghammarad.description,\n });\n }\n\n /**\n * Returns a pre-existing parameter in the stack.\n * If no parameter exists, creates a new parameter.\n *\n * @param stack the stack to operate on\n */\n public static getInstance(stack: GuStack): GuAnghammaradTopicParameter {\n if (!this.instance || !isSingletonPresentInStack(stack, this.instance)) {\n this.instance = new GuAnghammaradTopicParameter(stack);\n }\n\n return this.instance;\n }\n}\n"]}
1
+ {"version":3,"file":"anghammarad.js","sourceRoot":"","sources":["../../../../src/constructs/core/parameters/anghammarad.ts"],"names":[],"mappings":";;;AAAA,kDAA+D;AAC/D,wDAAqE;AAErE,iCAA2C;AAE3C;;;;;GAKG;AACH,MAAa,2BAA4B,SAAQ,wBAAiB;IAGhE,YAAoB,KAAc;QAChC,KAAK,CAAC,KAAK,EAAE,mBAAmB,EAAE;YAChC,OAAO,EAAE,IAAI;YACb,OAAO,EAAE,qCAAyB,CAAC,WAAW,CAAC,IAAI;YACnD,WAAW,EAAE,qCAAyB,CAAC,WAAW,CAAC,WAAW;SAC/D,CAAC,CAAC;IACL,CAAC;IAED;;;;;OAKG;IACI,MAAM,CAAC,WAAW,CAAC,KAAc;QACtC,IAAI,CAAC,IAAI,CAAC,QAAQ,IAAI,CAAC,IAAA,qCAAyB,EAAC,KAAK,EAAE,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;YACvE,IAAI,CAAC,QAAQ,GAAG,IAAI,2BAA2B,CAAC,KAAK,CAAC,CAAC;QACzD,CAAC;QAED,OAAO,IAAI,CAAC,QAAQ,CAAC;IACvB,CAAC;CACF;AAxBD,kEAwBC","sourcesContent":["import { NAMED_SSM_PARAMETER_PATHS } from \"../../../constants\";\nimport { isSingletonPresentInStack } from \"../../../utils/singleton\";\nimport type { GuStack } from \"../stack\";\nimport { GuStringParameter } from \"./base\";\n\n/**\n * Creates a CloudFormation parameter to a SSM Parameter Store item that holds the ARN of the Anghammarad SNS topic.\n * This parameter is implemented as a singleton, meaning only one can ever be added to a stack and will be reused if necessary.\n *\n * @see https://github.com/guardian/anghammarad\n */\nexport class GuAnghammaradTopicParameter extends GuStringParameter {\n private static instance: GuAnghammaradTopicParameter | undefined;\n\n private constructor(scope: GuStack) {\n super(scope, \"AnghammaradSnsArn\", {\n fromSSM: true,\n default: NAMED_SSM_PARAMETER_PATHS.Anghammarad.path,\n description: NAMED_SSM_PARAMETER_PATHS.Anghammarad.description,\n });\n }\n\n /**\n * Returns a pre-existing parameter in the stack.\n * If no parameter exists, creates a new parameter.\n *\n * @param stack the stack to operate on\n */\n public static getInstance(stack: GuStack): GuAnghammaradTopicParameter {\n if (!this.instance || !isSingletonPresentInStack(stack, this.instance)) {\n this.instance = new GuAnghammaradTopicParameter(stack);\n }\n\n return this.instance;\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"fastly.js","sourceRoot":"","sources":["../../../../src/constructs/core/parameters/fastly.ts"],"names":[],"mappings":";;;AAAA,kDAA+D;AAC/D,wDAAqE;AAErE,iCAA2C;AAE3C;;;;GAIG;AACH,MAAa,2BAA4B,SAAQ,wBAAiB;IAGhE,YAAoB,KAAc;QAChC,KAAK,CAAC,KAAK,EAAE,kBAAkB,EAAE;YAC/B,WAAW,EAAE,qCAAyB,CAAC,gBAAgB,CAAC,WAAW;YACnE,OAAO,EAAE,qCAAyB,CAAC,gBAAgB,CAAC,IAAI;YACxD,OAAO,EAAE,IAAI;SACd,CAAC,CAAC;IACL,CAAC;IAEM,MAAM,CAAC,WAAW,CAAC,KAAc;QACtC,IAAI,CAAC,IAAI,CAAC,QAAQ,IAAI,CAAC,IAAA,qCAAyB,EAAC,KAAK,EAAE,IAAI,CAAC,QAAQ,CAAC,EAAE;YACtE,IAAI,CAAC,QAAQ,GAAG,IAAI,2BAA2B,CAAC,KAAK,CAAC,CAAC;SACxD;QAED,OAAO,IAAI,CAAC,QAAQ,CAAC;IACvB,CAAC;CACF;AAlBD,kEAkBC","sourcesContent":["import { NAMED_SSM_PARAMETER_PATHS } from \"../../../constants\";\nimport { isSingletonPresentInStack } from \"../../../utils/singleton\";\nimport type { GuStack } from \"../stack\";\nimport { GuStringParameter } from \"./base\";\n\n/**\n * Creates a CloudFormation parameter which contains the Fastly customer ID to use in\n * setting up a Fastly logging role. By default, the customer ID is stored in an SSM\n * Parameter called `/account/external/fastly/customer.id`.\n */\nexport class GuFastlyCustomerIdParameter extends GuStringParameter {\n private static instance: GuFastlyCustomerIdParameter | undefined;\n\n private constructor(scope: GuStack) {\n super(scope, \"FastlyCustomerId\", {\n description: NAMED_SSM_PARAMETER_PATHS.FastlyCustomerId.description,\n default: NAMED_SSM_PARAMETER_PATHS.FastlyCustomerId.path,\n fromSSM: true,\n });\n }\n\n public static getInstance(stack: GuStack): GuFastlyCustomerIdParameter {\n if (!this.instance || !isSingletonPresentInStack(stack, this.instance)) {\n this.instance = new GuFastlyCustomerIdParameter(stack);\n }\n\n return this.instance;\n }\n}\n"]}
1
+ {"version":3,"file":"fastly.js","sourceRoot":"","sources":["../../../../src/constructs/core/parameters/fastly.ts"],"names":[],"mappings":";;;AAAA,kDAA+D;AAC/D,wDAAqE;AAErE,iCAA2C;AAE3C;;;;GAIG;AACH,MAAa,2BAA4B,SAAQ,wBAAiB;IAGhE,YAAoB,KAAc;QAChC,KAAK,CAAC,KAAK,EAAE,kBAAkB,EAAE;YAC/B,WAAW,EAAE,qCAAyB,CAAC,gBAAgB,CAAC,WAAW;YACnE,OAAO,EAAE,qCAAyB,CAAC,gBAAgB,CAAC,IAAI;YACxD,OAAO,EAAE,IAAI;SACd,CAAC,CAAC;IACL,CAAC;IAEM,MAAM,CAAC,WAAW,CAAC,KAAc;QACtC,IAAI,CAAC,IAAI,CAAC,QAAQ,IAAI,CAAC,IAAA,qCAAyB,EAAC,KAAK,EAAE,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;YACvE,IAAI,CAAC,QAAQ,GAAG,IAAI,2BAA2B,CAAC,KAAK,CAAC,CAAC;QACzD,CAAC;QAED,OAAO,IAAI,CAAC,QAAQ,CAAC;IACvB,CAAC;CACF;AAlBD,kEAkBC","sourcesContent":["import { NAMED_SSM_PARAMETER_PATHS } from \"../../../constants\";\nimport { isSingletonPresentInStack } from \"../../../utils/singleton\";\nimport type { GuStack } from \"../stack\";\nimport { GuStringParameter } from \"./base\";\n\n/**\n * Creates a CloudFormation parameter which contains the Fastly customer ID to use in\n * setting up a Fastly logging role. By default, the customer ID is stored in an SSM\n * Parameter called `/account/external/fastly/customer.id`.\n */\nexport class GuFastlyCustomerIdParameter extends GuStringParameter {\n private static instance: GuFastlyCustomerIdParameter | undefined;\n\n private constructor(scope: GuStack) {\n super(scope, \"FastlyCustomerId\", {\n description: NAMED_SSM_PARAMETER_PATHS.FastlyCustomerId.description,\n default: NAMED_SSM_PARAMETER_PATHS.FastlyCustomerId.path,\n fromSSM: true,\n });\n }\n\n public static getInstance(stack: GuStack): GuFastlyCustomerIdParameter {\n if (!this.instance || !isSingletonPresentInStack(stack, this.instance)) {\n this.instance = new GuFastlyCustomerIdParameter(stack);\n }\n\n return this.instance;\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"log-shipping.js","sourceRoot":"","sources":["../../../../src/constructs/core/parameters/log-shipping.ts"],"names":[],"mappings":";;;AAAA,kDAA+D;AAC/D,wDAAqE;AAErE,iCAA2C;AAE3C,MAAa,4BAA6B,SAAQ,wBAAiB;IAGjE,YAAoB,KAAc;QAChC,KAAK,CAAC,KAAK,EAAE,mBAAmB,EAAE;YAChC,WAAW,EAAE,qCAAyB,CAAC,iBAAiB,CAAC,WAAW;YACpE,OAAO,EAAE,qCAAyB,CAAC,iBAAiB,CAAC,IAAI;YACzD,OAAO,EAAE,IAAI;SACd,CAAC,CAAC;IACL,CAAC;IAEM,MAAM,CAAC,WAAW,CAAC,KAAc;QACtC,IAAI,CAAC,IAAI,CAAC,QAAQ,IAAI,CAAC,IAAA,qCAAyB,EAAC,KAAK,EAAE,IAAI,CAAC,QAAQ,CAAC,EAAE;YACtE,IAAI,CAAC,QAAQ,GAAG,IAAI,4BAA4B,CAAC,KAAK,CAAC,CAAC;SACzD;QAED,OAAO,IAAI,CAAC,QAAQ,CAAC;IACvB,CAAC;CACF;AAlBD,oEAkBC","sourcesContent":["import { NAMED_SSM_PARAMETER_PATHS } from \"../../../constants\";\nimport { isSingletonPresentInStack } from \"../../../utils/singleton\";\nimport type { GuStack } from \"../stack\";\nimport { GuStringParameter } from \"./base\";\n\nexport class GuLoggingStreamNameParameter extends GuStringParameter {\n private static instance: GuStringParameter | undefined;\n\n private constructor(scope: GuStack) {\n super(scope, \"LoggingStreamName\", {\n description: NAMED_SSM_PARAMETER_PATHS.LoggingStreamName.description,\n default: NAMED_SSM_PARAMETER_PATHS.LoggingStreamName.path,\n fromSSM: true,\n });\n }\n\n public static getInstance(stack: GuStack): GuLoggingStreamNameParameter {\n if (!this.instance || !isSingletonPresentInStack(stack, this.instance)) {\n this.instance = new GuLoggingStreamNameParameter(stack);\n }\n\n return this.instance;\n }\n}\n"]}
1
+ {"version":3,"file":"log-shipping.js","sourceRoot":"","sources":["../../../../src/constructs/core/parameters/log-shipping.ts"],"names":[],"mappings":";;;AAAA,kDAA+D;AAC/D,wDAAqE;AAErE,iCAA2C;AAE3C,MAAa,4BAA6B,SAAQ,wBAAiB;IAGjE,YAAoB,KAAc;QAChC,KAAK,CAAC,KAAK,EAAE,mBAAmB,EAAE;YAChC,WAAW,EAAE,qCAAyB,CAAC,iBAAiB,CAAC,WAAW;YACpE,OAAO,EAAE,qCAAyB,CAAC,iBAAiB,CAAC,IAAI;YACzD,OAAO,EAAE,IAAI;SACd,CAAC,CAAC;IACL,CAAC;IAEM,MAAM,CAAC,WAAW,CAAC,KAAc;QACtC,IAAI,CAAC,IAAI,CAAC,QAAQ,IAAI,CAAC,IAAA,qCAAyB,EAAC,KAAK,EAAE,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;YACvE,IAAI,CAAC,QAAQ,GAAG,IAAI,4BAA4B,CAAC,KAAK,CAAC,CAAC;QAC1D,CAAC;QAED,OAAO,IAAI,CAAC,QAAQ,CAAC;IACvB,CAAC;CACF;AAlBD,oEAkBC","sourcesContent":["import { NAMED_SSM_PARAMETER_PATHS } from \"../../../constants\";\nimport { isSingletonPresentInStack } from \"../../../utils/singleton\";\nimport type { GuStack } from \"../stack\";\nimport { GuStringParameter } from \"./base\";\n\nexport class GuLoggingStreamNameParameter extends GuStringParameter {\n private static instance: GuStringParameter | undefined;\n\n private constructor(scope: GuStack) {\n super(scope, \"LoggingStreamName\", {\n description: NAMED_SSM_PARAMETER_PATHS.LoggingStreamName.description,\n default: NAMED_SSM_PARAMETER_PATHS.LoggingStreamName.path,\n fromSSM: true,\n });\n }\n\n public static getInstance(stack: GuStack): GuLoggingStreamNameParameter {\n if (!this.instance || !isSingletonPresentInStack(stack, this.instance)) {\n this.instance = new GuLoggingStreamNameParameter(stack);\n }\n\n return this.instance;\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"s3.js","sourceRoot":"","sources":["../../../../src/constructs/core/parameters/s3.ts"],"names":[],"mappings":";;;AAAA,kDAA+D;AAC/D,wDAAqE;AAErE,iCAA2C;AAE3C;;;GAGG;AACH,MAAa,6BAA8B,SAAQ,wBAAiB;IAGlE,YAAoB,KAAc;QAChC,KAAK,CAAC,KAAK,EAAE,wBAAwB,EAAE;YACrC,WAAW,EAAE,qCAAyB,CAAC,kBAAkB,CAAC,WAAW;YACrE,OAAO,EAAE,qCAAyB,CAAC,kBAAkB,CAAC,IAAI;YAC1D,OAAO,EAAE,IAAI;SACd,CAAC,CAAC;IACL,CAAC;IAEM,MAAM,CAAC,WAAW,CAAC,KAAc;QACtC,IAAI,CAAC,IAAI,CAAC,QAAQ,IAAI,CAAC,IAAA,qCAAyB,EAAC,KAAK,EAAE,IAAI,CAAC,QAAQ,CAAC,EAAE;YACtE,IAAI,CAAC,QAAQ,GAAG,IAAI,6BAA6B,CAAC,KAAK,CAAC,CAAC;SAC1D;QAED,OAAO,IAAI,CAAC,QAAQ,CAAC;IACvB,CAAC;CACF;AAlBD,sEAkBC;AAED,MAAa,8BAA+B,SAAQ,wBAAiB;IAGnE,YAAY,KAAc;QACxB,KAAK,CAAC,KAAK,EAAE,8BAA8B,CAAC,aAAa,EAAE;YACzD,WAAW,EAAE,qCAAyB,CAAC,mBAAmB,CAAC,WAAW;YACtE,OAAO,EAAE,qCAAyB,CAAC,mBAAmB,CAAC,IAAI;YAC3D,OAAO,EAAE,IAAI;SACd,CAAC,CAAC;IACL,CAAC;;AATH,wEAUC;AATe,4CAAa,GAAG,yBAAyB,CAAC;AAW1D;;;GAGG;AACH,MAAa,8BAA+B,SAAQ,wBAAiB;IAGnE,YAAoB,KAAc;QAChC,KAAK,CAAC,KAAK,EAAE,qBAAqB,EAAE;YAClC,WAAW,EAAE,qCAAyB,CAAC,mBAAmB,CAAC,WAAW;YACtE,OAAO,EAAE,qCAAyB,CAAC,mBAAmB,CAAC,IAAI;YAC3D,OAAO,EAAE,IAAI;SACd,CAAC,CAAC;IACL,CAAC;IAEM,MAAM,CAAC,WAAW,CAAC,KAAc;QACtC,IAAI,CAAC,IAAI,CAAC,QAAQ,IAAI,CAAC,IAAA,qCAAyB,EAAC,KAAK,EAAE,IAAI,CAAC,QAAQ,CAAC,EAAE;YACtE,IAAI,CAAC,QAAQ,GAAG,IAAI,8BAA8B,CAAC,KAAK,CAAC,CAAC;SAC3D;QAED,OAAO,IAAI,CAAC,QAAQ,CAAC;IACvB,CAAC;CACF;AAlBD,wEAkBC","sourcesContent":["import { NAMED_SSM_PARAMETER_PATHS } from \"../../../constants\";\nimport { isSingletonPresentInStack } from \"../../../utils/singleton\";\nimport type { GuStack } from \"../stack\";\nimport { GuStringParameter } from \"./base\";\n\n/**\n * Creates a CloudFormation parameter which references the bucket used to store code artifacts.\n * By default, the bucket name is stored in an SSM Parameter called `/account/services/artifact.bucket`.\n */\nexport class GuDistributionBucketParameter extends GuStringParameter {\n private static instance: GuDistributionBucketParameter | undefined;\n\n private constructor(scope: GuStack) {\n super(scope, \"DistributionBucketName\", {\n description: NAMED_SSM_PARAMETER_PATHS.DistributionBucket.description,\n default: NAMED_SSM_PARAMETER_PATHS.DistributionBucket.path,\n fromSSM: true,\n });\n }\n\n public static getInstance(stack: GuStack): GuDistributionBucketParameter {\n if (!this.instance || !isSingletonPresentInStack(stack, this.instance)) {\n this.instance = new GuDistributionBucketParameter(stack);\n }\n\n return this.instance;\n }\n}\n\nexport class GuPrivateConfigBucketParameter extends GuStringParameter {\n public static parameterName = \"PrivateConfigBucketName\";\n\n constructor(scope: GuStack) {\n super(scope, GuPrivateConfigBucketParameter.parameterName, {\n description: NAMED_SSM_PARAMETER_PATHS.ConfigurationBucket.description,\n default: NAMED_SSM_PARAMETER_PATHS.ConfigurationBucket.path,\n fromSSM: true,\n });\n }\n}\n\n/**\n * Creates a CloudFormation parameter which references the bucket used to store load balancer access logs.\n * By default, the bucket name is stored in an SSM Parameter called `/account/services/access-logging/bucket`.\n */\nexport class GuAccessLoggingBucketParameter extends GuStringParameter {\n private static instance: GuAccessLoggingBucketParameter | undefined;\n\n private constructor(scope: GuStack) {\n super(scope, \"AccessLoggingBucket\", {\n description: NAMED_SSM_PARAMETER_PATHS.AccessLoggingBucket.description,\n default: NAMED_SSM_PARAMETER_PATHS.AccessLoggingBucket.path,\n fromSSM: true,\n });\n }\n\n public static getInstance(stack: GuStack): GuAccessLoggingBucketParameter {\n if (!this.instance || !isSingletonPresentInStack(stack, this.instance)) {\n this.instance = new GuAccessLoggingBucketParameter(stack);\n }\n\n return this.instance;\n }\n}\n"]}
1
+ {"version":3,"file":"s3.js","sourceRoot":"","sources":["../../../../src/constructs/core/parameters/s3.ts"],"names":[],"mappings":";;;AAAA,kDAA+D;AAC/D,wDAAqE;AAErE,iCAA2C;AAE3C;;;GAGG;AACH,MAAa,6BAA8B,SAAQ,wBAAiB;IAGlE,YAAoB,KAAc;QAChC,KAAK,CAAC,KAAK,EAAE,wBAAwB,EAAE;YACrC,WAAW,EAAE,qCAAyB,CAAC,kBAAkB,CAAC,WAAW;YACrE,OAAO,EAAE,qCAAyB,CAAC,kBAAkB,CAAC,IAAI;YAC1D,OAAO,EAAE,IAAI;SACd,CAAC,CAAC;IACL,CAAC;IAEM,MAAM,CAAC,WAAW,CAAC,KAAc;QACtC,IAAI,CAAC,IAAI,CAAC,QAAQ,IAAI,CAAC,IAAA,qCAAyB,EAAC,KAAK,EAAE,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;YACvE,IAAI,CAAC,QAAQ,GAAG,IAAI,6BAA6B,CAAC,KAAK,CAAC,CAAC;QAC3D,CAAC;QAED,OAAO,IAAI,CAAC,QAAQ,CAAC;IACvB,CAAC;CACF;AAlBD,sEAkBC;AAED,MAAa,8BAA+B,SAAQ,wBAAiB;IAGnE,YAAY,KAAc;QACxB,KAAK,CAAC,KAAK,EAAE,8BAA8B,CAAC,aAAa,EAAE;YACzD,WAAW,EAAE,qCAAyB,CAAC,mBAAmB,CAAC,WAAW;YACtE,OAAO,EAAE,qCAAyB,CAAC,mBAAmB,CAAC,IAAI;YAC3D,OAAO,EAAE,IAAI;SACd,CAAC,CAAC;IACL,CAAC;;AATH,wEAUC;AATe,4CAAa,GAAG,yBAAyB,CAAC;AAW1D;;;GAGG;AACH,MAAa,8BAA+B,SAAQ,wBAAiB;IAGnE,YAAoB,KAAc;QAChC,KAAK,CAAC,KAAK,EAAE,qBAAqB,EAAE;YAClC,WAAW,EAAE,qCAAyB,CAAC,mBAAmB,CAAC,WAAW;YACtE,OAAO,EAAE,qCAAyB,CAAC,mBAAmB,CAAC,IAAI;YAC3D,OAAO,EAAE,IAAI;SACd,CAAC,CAAC;IACL,CAAC;IAEM,MAAM,CAAC,WAAW,CAAC,KAAc;QACtC,IAAI,CAAC,IAAI,CAAC,QAAQ,IAAI,CAAC,IAAA,qCAAyB,EAAC,KAAK,EAAE,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;YACvE,IAAI,CAAC,QAAQ,GAAG,IAAI,8BAA8B,CAAC,KAAK,CAAC,CAAC;QAC5D,CAAC;QAED,OAAO,IAAI,CAAC,QAAQ,CAAC;IACvB,CAAC;CACF;AAlBD,wEAkBC","sourcesContent":["import { NAMED_SSM_PARAMETER_PATHS } from \"../../../constants\";\nimport { isSingletonPresentInStack } from \"../../../utils/singleton\";\nimport type { GuStack } from \"../stack\";\nimport { GuStringParameter } from \"./base\";\n\n/**\n * Creates a CloudFormation parameter which references the bucket used to store code artifacts.\n * By default, the bucket name is stored in an SSM Parameter called `/account/services/artifact.bucket`.\n */\nexport class GuDistributionBucketParameter extends GuStringParameter {\n private static instance: GuDistributionBucketParameter | undefined;\n\n private constructor(scope: GuStack) {\n super(scope, \"DistributionBucketName\", {\n description: NAMED_SSM_PARAMETER_PATHS.DistributionBucket.description,\n default: NAMED_SSM_PARAMETER_PATHS.DistributionBucket.path,\n fromSSM: true,\n });\n }\n\n public static getInstance(stack: GuStack): GuDistributionBucketParameter {\n if (!this.instance || !isSingletonPresentInStack(stack, this.instance)) {\n this.instance = new GuDistributionBucketParameter(stack);\n }\n\n return this.instance;\n }\n}\n\nexport class GuPrivateConfigBucketParameter extends GuStringParameter {\n public static parameterName = \"PrivateConfigBucketName\";\n\n constructor(scope: GuStack) {\n super(scope, GuPrivateConfigBucketParameter.parameterName, {\n description: NAMED_SSM_PARAMETER_PATHS.ConfigurationBucket.description,\n default: NAMED_SSM_PARAMETER_PATHS.ConfigurationBucket.path,\n fromSSM: true,\n });\n }\n}\n\n/**\n * Creates a CloudFormation parameter which references the bucket used to store load balancer access logs.\n * By default, the bucket name is stored in an SSM Parameter called `/account/services/access-logging/bucket`.\n */\nexport class GuAccessLoggingBucketParameter extends GuStringParameter {\n private static instance: GuAccessLoggingBucketParameter | undefined;\n\n private constructor(scope: GuStack) {\n super(scope, \"AccessLoggingBucket\", {\n description: NAMED_SSM_PARAMETER_PATHS.AccessLoggingBucket.description,\n default: NAMED_SSM_PARAMETER_PATHS.AccessLoggingBucket.path,\n fromSSM: true,\n });\n }\n\n public static getInstance(stack: GuStack): GuAccessLoggingBucketParameter {\n if (!this.instance || !isSingletonPresentInStack(stack, this.instance)) {\n this.instance = new GuAccessLoggingBucketParameter(stack);\n }\n\n return this.instance;\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"vpc.js","sourceRoot":"","sources":["../../../../src/constructs/core/parameters/vpc.ts"],"names":[],"mappings":";;;AAAA,kDAA+D;AAC/D,wDAAqE;AAErE,iCAAqC;AAGrC,MAAa,qBAAsB,SAAQ,kBAAW;IACpD,YAAY,KAAc,EAAE,EAAU,EAAE,KAA6B;QACnE,KAAK,CAAC,KAAK,EAAE,EAAE,EAAE,EAAE,GAAG,KAAK,EAAE,IAAI,EAAE,4BAA4B,EAAE,CAAC,CAAC;IACrE,CAAC;CACF;AAJD,sDAIC;AAED;;;;GAIG;AACH,MAAa,cAAe,SAAQ,kBAAW;IAG7C,YAAoB,KAAc;QAChC,KAAK,CAAC,KAAK,EAAE,OAAO,EAAE;YACpB,WAAW,EAAE,qCAAyB,CAAC,YAAY,CAAC,WAAW;YAC/D,OAAO,EAAE,qCAAyB,CAAC,YAAY,CAAC,IAAI;YACpD,IAAI,EAAE,mBAAmB;YACzB,OAAO,EAAE,IAAI;SACd,CAAC,CAAC;IACL,CAAC;IAEM,MAAM,CAAC,WAAW,CAAC,KAAc;QACtC,IAAI,CAAC,IAAI,CAAC,QAAQ,IAAI,CAAC,IAAA,qCAAyB,EAAC,KAAK,EAAE,IAAI,CAAC,QAAQ,CAAC,EAAE;YACtE,IAAI,CAAC,QAAQ,GAAG,IAAI,cAAc,CAAC,KAAK,CAAC,CAAC;SAC3C;QAED,OAAO,IAAI,CAAC,QAAQ,CAAC;IACvB,CAAC;CACF;AAnBD,wCAmBC","sourcesContent":["import { NAMED_SSM_PARAMETER_PATHS } from \"../../../constants\";\nimport { isSingletonPresentInStack } from \"../../../utils/singleton\";\nimport type { GuStack } from \"../stack\";\nimport { GuParameter } from \"./base\";\nimport type { GuNoTypeParameterProps } from \"./base\";\n\nexport class GuSubnetListParameter extends GuParameter {\n constructor(scope: GuStack, id: string, props: GuNoTypeParameterProps) {\n super(scope, id, { ...props, type: \"List<AWS::EC2::Subnet::Id>\" });\n }\n}\n\n/**\n * Adds a \"VpcId\" parameter to a stack.\n * This parameter will read from Parameter Store.\n * By default it will read from `/account/vpc/primary/id`, this can be changed at runtime if needed.\n */\nexport class GuVpcParameter extends GuParameter {\n private static instance: GuVpcParameter | undefined;\n\n private constructor(scope: GuStack) {\n super(scope, \"VpcId\", {\n description: NAMED_SSM_PARAMETER_PATHS.PrimaryVpcId.description,\n default: NAMED_SSM_PARAMETER_PATHS.PrimaryVpcId.path,\n type: \"AWS::EC2::VPC::Id\",\n fromSSM: true,\n });\n }\n\n public static getInstance(stack: GuStack): GuVpcParameter {\n if (!this.instance || !isSingletonPresentInStack(stack, this.instance)) {\n this.instance = new GuVpcParameter(stack);\n }\n\n return this.instance;\n }\n}\n"]}
1
+ {"version":3,"file":"vpc.js","sourceRoot":"","sources":["../../../../src/constructs/core/parameters/vpc.ts"],"names":[],"mappings":";;;AAAA,kDAA+D;AAC/D,wDAAqE;AAErE,iCAAqC;AAGrC,MAAa,qBAAsB,SAAQ,kBAAW;IACpD,YAAY,KAAc,EAAE,EAAU,EAAE,KAA6B;QACnE,KAAK,CAAC,KAAK,EAAE,EAAE,EAAE,EAAE,GAAG,KAAK,EAAE,IAAI,EAAE,4BAA4B,EAAE,CAAC,CAAC;IACrE,CAAC;CACF;AAJD,sDAIC;AAED;;;;GAIG;AACH,MAAa,cAAe,SAAQ,kBAAW;IAG7C,YAAoB,KAAc;QAChC,KAAK,CAAC,KAAK,EAAE,OAAO,EAAE;YACpB,WAAW,EAAE,qCAAyB,CAAC,YAAY,CAAC,WAAW;YAC/D,OAAO,EAAE,qCAAyB,CAAC,YAAY,CAAC,IAAI;YACpD,IAAI,EAAE,mBAAmB;YACzB,OAAO,EAAE,IAAI;SACd,CAAC,CAAC;IACL,CAAC;IAEM,MAAM,CAAC,WAAW,CAAC,KAAc;QACtC,IAAI,CAAC,IAAI,CAAC,QAAQ,IAAI,CAAC,IAAA,qCAAyB,EAAC,KAAK,EAAE,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;YACvE,IAAI,CAAC,QAAQ,GAAG,IAAI,cAAc,CAAC,KAAK,CAAC,CAAC;QAC5C,CAAC;QAED,OAAO,IAAI,CAAC,QAAQ,CAAC;IACvB,CAAC;CACF;AAnBD,wCAmBC","sourcesContent":["import { NAMED_SSM_PARAMETER_PATHS } from \"../../../constants\";\nimport { isSingletonPresentInStack } from \"../../../utils/singleton\";\nimport type { GuStack } from \"../stack\";\nimport { GuParameter } from \"./base\";\nimport type { GuNoTypeParameterProps } from \"./base\";\n\nexport class GuSubnetListParameter extends GuParameter {\n constructor(scope: GuStack, id: string, props: GuNoTypeParameterProps) {\n super(scope, id, { ...props, type: \"List<AWS::EC2::Subnet::Id>\" });\n }\n}\n\n/**\n * Adds a \"VpcId\" parameter to a stack.\n * This parameter will read from Parameter Store.\n * By default it will read from `/account/vpc/primary/id`, this can be changed at runtime if needed.\n */\nexport class GuVpcParameter extends GuParameter {\n private static instance: GuVpcParameter | undefined;\n\n private constructor(scope: GuStack) {\n super(scope, \"VpcId\", {\n description: NAMED_SSM_PARAMETER_PATHS.PrimaryVpcId.description,\n default: NAMED_SSM_PARAMETER_PATHS.PrimaryVpcId.path,\n type: \"AWS::EC2::VPC::Id\",\n fromSSM: true,\n });\n }\n\n public static getInstance(stack: GuStack): GuVpcParameter {\n if (!this.instance || !isSingletonPresentInStack(stack, this.instance)) {\n this.instance = new GuVpcParameter(stack);\n }\n\n return this.instance;\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"stack.js","sourceRoot":"","sources":["../../../src/constructs/core/stack.ts"],"names":[],"mappings":"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","sourcesContent":["import type { App, CfnElement, StackProps } from \"aws-cdk-lib\";\nimport { Annotations, Aspects, CfnParameter, LegacyStackSynthesizer, Stack, Tags } from \"aws-cdk-lib\";\nimport type { IConstruct } from \"constructs\";\nimport gitUrlParse from \"git-url-parse\";\nimport { CfnIncludeReporter } from \"../../aspects/cfn-include-reporter\";\nimport { CfnParameterReporter } from \"../../aspects/cfn-parameter-reporter\";\nimport { Metadata } from \"../../aspects/metadata\";\nimport { ContextKeys, MetadataKeys, TrackingTag } from \"../../constants\";\nimport { gitRemoteOriginUrl } from \"../../utils/git\";\nimport type { StackStageIdentity } from \"./identity\";\nimport type { GuStaticLogicalId } from \"./migrating\";\n\nexport interface GuStackProps extends Omit<StackProps, \"stackName\"> {\n /**\n * The Guardian stack being used (as defined in your riff-raff.yaml).\n * This will be applied as a tag to all of your resources.\n */\n stack: string;\n\n /**\n * The stage being used (as defined in your riff-raff.yaml).\n * This will be applied as a tag to all of your resources.\n */\n stage: string;\n\n /**\n * Optional name of the app. If defined, all resources will have an App tag.\n */\n app?: string;\n\n /**\n * The name of the Riff-Raff project used to deploy these resources.\n * Used as the value of the `gu:riff-raff-project` tag on all resources.\n * If using {@link GuRoot} or {@link RiffRaffYamlFile}, this value is also used in the location of the generated `riff-raff.yaml`.\n *\n * @see https://github.com/guardian/riffraff-platform\n */\n riffRaffProjectName?: string;\n\n /**\n * The AWS CloudFormation stack name (as shown in the AWS CloudFormation UI).\n * @defaultValue the `GU_CFN_STACK_NAME` environment variable\n */\n cloudFormationStackName?: string;\n /**\n * Set this to true to stop the GuStack from tagging all of your AWS resources.\n * This should only be turned on as part of an initial migration from CloudFormation.\n */\n withoutTags?: boolean;\n\n /**\n * Set to disable CDK metadata. Only for internal use (for disabling for some\n * snapshot tests). We rely on tracking data to prioritise future work so\n * please do not override this.\n */\n withoutMetadata?: boolean;\n}\n\n/**\n * GuStack provides the `stack` and `stage` parameters to a template.\n * It also takes the `app` in the constructor.\n *\n * GuStack will add the Stack, Stage and App tags to all resources.\n *\n * GuStack also adds the tag `X-Gu-CDK-Version`.\n * This tag allows us to measure adoption of this library.\n * It's value is the version of guardian/cdk being used, as defined in `package.json`.\n * As a result, the change sets between version numbers will be fairly noisy,\n * as all resources receive a tag update.\n * It is recommended to upgrade the version of @guardian/cdk being used in two steps:\n * 1. Bump the library, apply the tag updates\n * 2. Make any other stack changes\n *\n * Typical usage is to extend GuStack:\n *\n * ```typescript\n * class MyStack extends GuStack {\n * constructor(scope: App, id: string, props: GuStackProps) {\n * super(scope, id, props)\n * }\n *\n * // add resources here\n * }\n * ```\n */\nexport class GuStack extends Stack implements StackStageIdentity {\n public readonly stack: string;\n public readonly stage: string;\n public readonly app: string | undefined;\n public readonly riffRaffProjectName: string | undefined;\n\n /**\n * The repository name, if it can be determined from the context or the git remote origin url.\n * If it cannot be determined from either of these sources, it will be `undefined`.\n */\n public readonly repositoryName: string | undefined;\n\n /**\n * A helper function to add a tag to all resources in a stack.\n *\n * Note: tags will be listed in alphabetical order during synthesis.\n *\n * @param key the tag name\n * @param value the value of the tag\n * @param applyToLaunchedInstances whether or not to apply the tag to instances launched in an ASG.\n * @protected\n */\n protected addTag(key: string, value: string, applyToLaunchedInstances: boolean = true): void {\n // TODO add validation for `key` and `value`\n // see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-resource-tags.html\n Tags.of(this).add(key, value, { applyToLaunchedInstances });\n }\n\n /**\n * Returns all the parameters on this stack.\n *\n * @see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/parameters-section-structure.html\n */\n get parameters(): Record<string, CfnParameter> {\n return this.node\n .findAll()\n .filter((construct) => construct instanceof CfnParameter)\n .reduce((acc, param) => ({ ...acc, [param.node.id]: param as CfnParameter }), {});\n }\n\n // eslint-disable-next-line custom-rules/valid-constructors -- GuStack is the exception as it must take an App\n constructor(scope: App, id: string, props: GuStackProps) {\n const {\n cloudFormationStackName = process.env.GU_CFN_STACK_NAME,\n stack,\n stage,\n app,\n riffRaffProjectName,\n withoutTags,\n } = props;\n\n super(scope, id, {\n ...props,\n stackName: cloudFormationStackName,\n\n // TODO Use `DefaultStackSynthesizer` or create own synthesizer?\n // see https://docs.aws.amazon.com/cdk/v2/guide/bootstrapping.html#bootstrapping-custom-synth\n synthesizer: new LegacyStackSynthesizer(),\n });\n\n this.stack = stack;\n this.stage = stage.toUpperCase();\n this.app = app;\n this.riffRaffProjectName = riffRaffProjectName;\n this.repositoryName = this.tryGetRepositoryTag();\n\n if (!withoutTags) {\n this.addTag(TrackingTag.Key, TrackingTag.Value);\n\n this.addTag(\"Stack\", this.stack);\n this.addTag(\"Stage\", this.stage);\n if (this.app) {\n this.addTag(\"App\", this.app);\n }\n\n if (this.riffRaffProjectName) {\n this.addTag(\"gu:riff-raff:project\", this.riffRaffProjectName);\n }\n\n if (this.repositoryName) {\n this.addTag(MetadataKeys.REPOSITORY_NAME, this.repositoryName);\n }\n }\n\n if (!props.withoutMetadata) {\n Aspects.of(this).add(new Metadata(this));\n }\n\n Aspects.of(this).add(new CfnIncludeReporter());\n Aspects.of(this).add(new CfnParameterReporter());\n }\n\n /**\n * Returns the repository name.\n * The value is retrieved in the following order:\n * 1. From the context\n * 2. From git config\n *\n * @private\n */\n private tryGetRepositoryTag(): string | undefined {\n try {\n const urlFromContext = this.node.tryGetContext(ContextKeys.REPOSITORY_URL) as string | undefined;\n const repositoryUrl: string = urlFromContext ?? gitRemoteOriginUrl();\n return gitUrlParse(repositoryUrl).full_name;\n } catch {\n console.info(\n `Unable to find git repository name. Set the ${ContextKeys.REPOSITORY_URL} context value or configure a git remote`,\n );\n return undefined;\n }\n }\n\n /**\n * Override the auto-generated logical ID for a resource, in the generated CloudFormation template, with a static one.\n *\n * Of particular use when migrating a JSON/YAML CloudFormation template into GuCDK.\n * It's generally advised to retain the logical ID for stateful resources, such as databases or buckets.\n *\n * Let's say we have a YAML template:\n *\n * ```yaml\n * AWSTemplateFormatVersion: '2010-09-09'\n * Resources:\n * UsesTable:\n * Type: AWS::DynamoDB::Table\n * Properties:\n * TableName: !Sub 'users-${stage}'\n * ```\n *\n * When moving to GuCDK we'll have this:\n *\n * class MyStack extends GuStack {\n * constructor(app: App, id: string, props: GuStackProps) {\n * super(app, id, props);\n *\n * const { stage } = this;\n *\n * new Table(this, \"UsersTable\", {\n * name: `users-${stage}`\n * });\n * }\n * }\n *\n * During synthesis, CDK auto-generates logical IDs, so we'll have a stack with a DynamoDB table named 'UsersTable<SOME GUID>', NOT `UsersTable`.\n * That is, the `UsersTable` table will be deleted.\n *\n * In order to retain the original ID from the YAML template, we will do:\n *\n * class MyStack extends GuStack {\n * constructor(app: App, id: string, props: GuStackProps) {\n * super(app, id, props);\n *\n * const { stage } = this;\n *\n * const table = new Table(this, \"UsersTable\", {\n * name: `users-${stage}`\n * });\n *\n * this.overrideLogicalId(table, { logicalId: \"UsersTable\", reason: \"Retaining a stateful resource from the YAML template\" });\n * }\n * }\n *\n * @param construct The (stateful) resource to retain the logical ID of.\n * @param logicalId The logical ID of the resource (as defined in the JSON/YAML template.\n * @param reason A small explanation to keep the logical ID. Mainly used to help future developers.\n */\n public overrideLogicalId(construct: IConstruct, { logicalId, reason }: GuStaticLogicalId): void {\n const {\n node: { id, defaultChild },\n } = construct;\n\n (defaultChild as CfnElement).overrideLogicalId(logicalId);\n Annotations.of(construct).addInfo(`Setting logical ID for ${id} to ${logicalId}. Reason: ${reason}`);\n }\n}\n"]}
1
+ {"version":3,"file":"stack.js","sourceRoot":"","sources":["../../../src/constructs/core/stack.ts"],"names":[],"mappings":"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","sourcesContent":["import type { App, CfnElement, StackProps } from \"aws-cdk-lib\";\nimport { Annotations, Aspects, CfnParameter, LegacyStackSynthesizer, Stack, Tags } from \"aws-cdk-lib\";\nimport type { IConstruct } from \"constructs\";\nimport gitUrlParse from \"git-url-parse\";\nimport { CfnIncludeReporter } from \"../../aspects/cfn-include-reporter\";\nimport { CfnParameterReporter } from \"../../aspects/cfn-parameter-reporter\";\nimport { Metadata } from \"../../aspects/metadata\";\nimport { ContextKeys, MetadataKeys, TrackingTag } from \"../../constants\";\nimport { gitRemoteOriginUrl } from \"../../utils/git\";\nimport type { StackStageIdentity } from \"./identity\";\nimport type { GuStaticLogicalId } from \"./migrating\";\n\nexport interface GuStackProps extends Omit<StackProps, \"stackName\"> {\n /**\n * The Guardian stack being used (as defined in your riff-raff.yaml).\n * This will be applied as a tag to all of your resources.\n */\n stack: string;\n\n /**\n * The stage being used (as defined in your riff-raff.yaml).\n * This will be applied as a tag to all of your resources.\n */\n stage: string;\n\n /**\n * Optional name of the app. If defined, all resources will have an App tag.\n */\n app?: string;\n\n /**\n * The name of the Riff-Raff project used to deploy these resources.\n * Used as the value of the `gu:riff-raff-project` tag on all resources.\n * If using {@link GuRoot} or {@link RiffRaffYamlFile}, this value is also used in the location of the generated `riff-raff.yaml`.\n *\n * @see https://github.com/guardian/riffraff-platform\n */\n riffRaffProjectName?: string;\n\n /**\n * The AWS CloudFormation stack name (as shown in the AWS CloudFormation UI).\n * @defaultValue the `GU_CFN_STACK_NAME` environment variable\n */\n cloudFormationStackName?: string;\n /**\n * Set this to true to stop the GuStack from tagging all of your AWS resources.\n * This should only be turned on as part of an initial migration from CloudFormation.\n */\n withoutTags?: boolean;\n\n /**\n * Set to disable CDK metadata. Only for internal use (for disabling for some\n * snapshot tests). We rely on tracking data to prioritise future work so\n * please do not override this.\n */\n withoutMetadata?: boolean;\n}\n\n/**\n * GuStack provides the `stack` and `stage` parameters to a template.\n * It also takes the `app` in the constructor.\n *\n * GuStack will add the Stack, Stage and App tags to all resources.\n *\n * GuStack also adds the tag `X-Gu-CDK-Version`.\n * This tag allows us to measure adoption of this library.\n * It's value is the version of guardian/cdk being used, as defined in `package.json`.\n * As a result, the change sets between version numbers will be fairly noisy,\n * as all resources receive a tag update.\n * It is recommended to upgrade the version of @guardian/cdk being used in two steps:\n * 1. Bump the library, apply the tag updates\n * 2. Make any other stack changes\n *\n * Typical usage is to extend GuStack:\n *\n * ```typescript\n * class MyStack extends GuStack {\n * constructor(scope: App, id: string, props: GuStackProps) {\n * super(scope, id, props)\n * }\n *\n * // add resources here\n * }\n * ```\n */\nexport class GuStack extends Stack implements StackStageIdentity {\n public readonly stack: string;\n public readonly stage: string;\n public readonly app: string | undefined;\n public readonly riffRaffProjectName: string | undefined;\n\n /**\n * The repository name, if it can be determined from the context or the git remote origin url.\n * If it cannot be determined from either of these sources, it will be `undefined`.\n */\n public readonly repositoryName: string | undefined;\n\n /**\n * A helper function to add a tag to all resources in a stack.\n *\n * Note: tags will be listed in alphabetical order during synthesis.\n *\n * @param key the tag name\n * @param value the value of the tag\n * @param applyToLaunchedInstances whether or not to apply the tag to instances launched in an ASG.\n * @protected\n */\n protected addTag(key: string, value: string, applyToLaunchedInstances: boolean = true): void {\n // TODO add validation for `key` and `value`\n // see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-resource-tags.html\n Tags.of(this).add(key, value, { applyToLaunchedInstances });\n }\n\n /**\n * Returns all the parameters on this stack.\n *\n * @see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/parameters-section-structure.html\n */\n get parameters(): Record<string, CfnParameter> {\n return this.node\n .findAll()\n .filter((construct) => construct instanceof CfnParameter)\n .reduce((acc, param) => ({ ...acc, [param.node.id]: param }), {});\n }\n\n // eslint-disable-next-line custom-rules/valid-constructors -- GuStack is the exception as it must take an App\n constructor(scope: App, id: string, props: GuStackProps) {\n const {\n cloudFormationStackName = process.env.GU_CFN_STACK_NAME,\n stack,\n stage,\n app,\n riffRaffProjectName,\n withoutTags,\n } = props;\n\n super(scope, id, {\n ...props,\n stackName: cloudFormationStackName,\n\n // TODO Use `DefaultStackSynthesizer` or create own synthesizer?\n // see https://docs.aws.amazon.com/cdk/v2/guide/bootstrapping.html#bootstrapping-custom-synth\n synthesizer: new LegacyStackSynthesizer(),\n });\n\n this.stack = stack;\n this.stage = stage.toUpperCase();\n this.app = app;\n this.riffRaffProjectName = riffRaffProjectName;\n this.repositoryName = this.tryGetRepositoryTag();\n\n if (!withoutTags) {\n this.addTag(TrackingTag.Key, TrackingTag.Value);\n\n this.addTag(\"Stack\", this.stack);\n this.addTag(\"Stage\", this.stage);\n if (this.app) {\n this.addTag(\"App\", this.app);\n }\n\n if (this.riffRaffProjectName) {\n this.addTag(\"gu:riff-raff:project\", this.riffRaffProjectName);\n }\n\n if (this.repositoryName) {\n this.addTag(MetadataKeys.REPOSITORY_NAME, this.repositoryName);\n }\n }\n\n if (!props.withoutMetadata) {\n Aspects.of(this).add(new Metadata(this));\n }\n\n Aspects.of(this).add(new CfnIncludeReporter());\n Aspects.of(this).add(new CfnParameterReporter());\n }\n\n /**\n * Returns the repository name.\n * The value is retrieved in the following order:\n * 1. From the context\n * 2. From git config\n *\n * @private\n */\n private tryGetRepositoryTag(): string | undefined {\n try {\n const urlFromContext = this.node.tryGetContext(ContextKeys.REPOSITORY_URL) as string | undefined;\n const repositoryUrl: string = urlFromContext ?? gitRemoteOriginUrl();\n return gitUrlParse(repositoryUrl).full_name;\n } catch {\n console.info(\n `Unable to find git repository name. Set the ${ContextKeys.REPOSITORY_URL} context value or configure a git remote`,\n );\n return undefined;\n }\n }\n\n /**\n * Override the auto-generated logical ID for a resource, in the generated CloudFormation template, with a static one.\n *\n * Of particular use when migrating a JSON/YAML CloudFormation template into GuCDK.\n * It's generally advised to retain the logical ID for stateful resources, such as databases or buckets.\n *\n * Let's say we have a YAML template:\n *\n * ```yaml\n * AWSTemplateFormatVersion: '2010-09-09'\n * Resources:\n * UsesTable:\n * Type: AWS::DynamoDB::Table\n * Properties:\n * TableName: !Sub 'users-${stage}'\n * ```\n *\n * When moving to GuCDK we'll have this:\n *\n * class MyStack extends GuStack {\n * constructor(app: App, id: string, props: GuStackProps) {\n * super(app, id, props);\n *\n * const { stage } = this;\n *\n * new Table(this, \"UsersTable\", {\n * name: `users-${stage}`\n * });\n * }\n * }\n *\n * During synthesis, CDK auto-generates logical IDs, so we'll have a stack with a DynamoDB table named 'UsersTable<SOME GUID>', NOT `UsersTable`.\n * That is, the `UsersTable` table will be deleted.\n *\n * In order to retain the original ID from the YAML template, we will do:\n *\n * class MyStack extends GuStack {\n * constructor(app: App, id: string, props: GuStackProps) {\n * super(app, id, props);\n *\n * const { stage } = this;\n *\n * const table = new Table(this, \"UsersTable\", {\n * name: `users-${stage}`\n * });\n *\n * this.overrideLogicalId(table, { logicalId: \"UsersTable\", reason: \"Retaining a stateful resource from the YAML template\" });\n * }\n * }\n *\n * @param construct The (stateful) resource to retain the logical ID of.\n * @param logicalId The logical ID of the resource (as defined in the JSON/YAML template.\n * @param reason A small explanation to keep the logical ID. Mainly used to help future developers.\n */\n public overrideLogicalId(construct: IConstruct, { logicalId, reason }: GuStaticLogicalId): void {\n const {\n node: { id, defaultChild },\n } = construct;\n\n (defaultChild as CfnElement).overrideLogicalId(logicalId);\n Annotations.of(construct).addInfo(`Setting logical ID for ${id} to ${logicalId}. Reason: ${reason}`);\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"dns-records.js","sourceRoot":"","sources":["../../../src/constructs/dns/dns-records.ts"],"names":[],"mappings":";;;AACA,6CAA0C;AAC1C,2CAAuC;AAIvC,IAAY,UAEX;AAFD,WAAY,UAAU;IACpB,6BAAe,CAAA;AACjB,CAAC,EAFW,UAAU,0BAAV,UAAU,QAErB;AASD;;;;;GAKG;AACH,MAAa,cAAe,SAAQ,sBAAS;IAC3C,YAAY,KAAc,EAAE,EAAU,EAAE,KAA0B;QAChE,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,eAAe,EAAE,GAAG,EAAE,GAAG,KAAK,CAAC;QACzD,MAAM,EAAE,KAAK,EAAE,GAAG,KAAK,CAAC;QAExB;;;;WAIG;QACH,MAAM,iBAAiB,GAAG,GAAG,IAAI,eAAe,CAAC;QACjD,MAAM,iBAAiB,GAAG,EAAE,CAAC;QAE7B,KAAK,CAAC,KAAK,EAAE,iBAAiB,CAAC,CAAC;QAEhC,iHAAiH;QACjH,IAAI,UAAU,KAAK,UAAU,CAAC,KAAK,EAAE;YACnC;;;;;;;;eAQG;YACH,IAAI,eAAe,CAAC,MAAM,KAAK,CAAC,EAAE;gBAChC,MAAM,IAAI,KAAK,CACb,qHAAqH,CACtH,CAAC;aACH;SACF;QAED,6DAA6D;QAC7D,gHAAgH;QAChH,IAAI,yBAAW,CAAC,KAAK,EAAE,iBAAiB,EAAE;YACxC,IAAI,EAAE,0BAA0B;YAChC,UAAU,EAAE;gBACV,IAAI,EAAE,IAAI;gBACV,eAAe,EAAE,eAAe;gBAChC,UAAU,EAAE,UAAU;gBACtB,GAAG,EAAE,GAAG,CAAC,SAAS,EAAE;gBACpB,KAAK,EAAE,KAAK;aACb;SACF,CAAC,CAAC;IACL,CAAC;CACF;AA9CD,wCA8CC;AASD;;;;GAIG;AACH,MAAa,OAAQ,SAAQ,cAAc;IACzC,YAAY,KAAc,EAAE,EAAU,EAAE,KAAmB;QACzD,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,cAAc,EAAE,GAAG,EAAE,GAAG,KAAK,CAAC;QAExD,KAAK,CAAC,KAAK,EAAE,EAAE,EAAE;YACf,IAAI;YACJ,UAAU,EAAE,UAAU,CAAC,KAAK;YAC5B,eAAe,EAAE,CAAC,cAAc,CAAC;YACjC,GAAG;SACJ,CAAC,CAAC;IACL,CAAC;CACF;AAXD,0BAWC","sourcesContent":["import type { Duration } from \"aws-cdk-lib\";\nimport { CfnResource } from \"aws-cdk-lib\";\nimport { Construct } from \"constructs\";\nimport type { GuDomainName } from \"../../types\";\nimport type { AppIdentity, GuStack } from \"../core\";\n\nexport enum RecordType {\n CNAME = \"CNAME\",\n}\n\nexport interface GuDnsRecordSetProps {\n name: string;\n recordType: RecordType;\n resourceRecords: string[];\n ttl: Duration;\n}\n\n/**\n * This construct can be used to create DNS records in NS1.\n *\n * Prefer to use [[`GuCname`]] when creating a CNAME for a load balancer,\n * as this requires less boilerplate.\n */\nexport class GuDnsRecordSet extends Construct {\n constructor(scope: GuStack, id: string, props: GuDnsRecordSetProps) {\n const { name, recordType, resourceRecords, ttl } = props;\n const { stage } = scope;\n\n /*\n Nodes in the CDK tree must have a unique ID. This class adds two nodes to the tree, so we have two IDs.\n `id`, by definition, must be unique. `name` represents a fully qualified domain name, which must also be unique.\n `id` being given to the level 1 construct means it also becomes the logicalId in the template.\n */\n const level2ConstructId = `${name}-DnsRecordSet`;\n const level1ConstructId = id;\n\n super(scope, level2ConstructId);\n\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- more `RecordType`s will be added soon!\n if (recordType === RecordType.CNAME) {\n /*\n If you try to create a CNAME with multiple records within NS1, you are greeted with:\n\n According to RFC, a CNAME record should not return multiple answers.\n Doing so may cause problems during resolution.\n If you want to use multiple answers, you should ensure you have the correct filters in place (such as SELECT_FIRST_N 1) to limit them to a single answer at resolution time.\n\n `Guardian::DNS::RecordSet` does not implement \"correct filters\", so fail fast by throwing.\n */\n if (resourceRecords.length !== 1) {\n throw new Error(\n \"According to RFC, a CNAME record should not return multiple answers. Doing so may cause problems during resolution.\",\n );\n }\n }\n\n // The spec for this private resource type can be found here:\n // https://github.com/guardian/cfn-private-resource-types/tree/main/dns/guardian-dns-record-set-type/docs#syntax\n new CfnResource(scope, level1ConstructId, {\n type: \"Guardian::DNS::RecordSet\",\n properties: {\n Name: name,\n ResourceRecords: resourceRecords,\n RecordType: recordType,\n TTL: ttl.toSeconds(),\n Stage: stage,\n },\n });\n }\n}\n\nexport interface GuCnameProps extends GuDomainName, AppIdentity {\n /** The record your CNAME should point to, for example your Load Balancer DNS name */\n resourceRecord: string;\n /** The time to live for the DNS record */\n ttl: Duration;\n}\n\n/**\n * Construct for creating CNAME records in NS1.\n *\n * See [[`GuCnameProps`]] for configuration options.\n */\nexport class GuCname extends GuDnsRecordSet {\n constructor(scope: GuStack, id: string, props: GuCnameProps) {\n const { domainName: name, resourceRecord, ttl } = props;\n\n super(scope, id, {\n name,\n recordType: RecordType.CNAME,\n resourceRecords: [resourceRecord],\n ttl,\n });\n }\n}\n"]}
1
+ {"version":3,"file":"dns-records.js","sourceRoot":"","sources":["../../../src/constructs/dns/dns-records.ts"],"names":[],"mappings":";;;AACA,6CAA0C;AAC1C,2CAAuC;AAIvC,IAAY,UAEX;AAFD,WAAY,UAAU;IACpB,6BAAe,CAAA;AACjB,CAAC,EAFW,UAAU,0BAAV,UAAU,QAErB;AASD;;;;;GAKG;AACH,MAAa,cAAe,SAAQ,sBAAS;IAC3C,YAAY,KAAc,EAAE,EAAU,EAAE,KAA0B;QAChE,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,eAAe,EAAE,GAAG,EAAE,GAAG,KAAK,CAAC;QACzD,MAAM,EAAE,KAAK,EAAE,GAAG,KAAK,CAAC;QAExB;;;;WAIG;QACH,MAAM,iBAAiB,GAAG,GAAG,IAAI,eAAe,CAAC;QACjD,MAAM,iBAAiB,GAAG,EAAE,CAAC;QAE7B,KAAK,CAAC,KAAK,EAAE,iBAAiB,CAAC,CAAC;QAEhC,iHAAiH;QACjH,IAAI,UAAU,KAAK,UAAU,CAAC,KAAK,EAAE,CAAC;YACpC;;;;;;;;eAQG;YACH,IAAI,eAAe,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACjC,MAAM,IAAI,KAAK,CACb,qHAAqH,CACtH,CAAC;YACJ,CAAC;QACH,CAAC;QAED,6DAA6D;QAC7D,gHAAgH;QAChH,IAAI,yBAAW,CAAC,KAAK,EAAE,iBAAiB,EAAE;YACxC,IAAI,EAAE,0BAA0B;YAChC,UAAU,EAAE;gBACV,IAAI,EAAE,IAAI;gBACV,eAAe,EAAE,eAAe;gBAChC,UAAU,EAAE,UAAU;gBACtB,GAAG,EAAE,GAAG,CAAC,SAAS,EAAE;gBACpB,KAAK,EAAE,KAAK;aACb;SACF,CAAC,CAAC;IACL,CAAC;CACF;AA9CD,wCA8CC;AASD;;;;GAIG;AACH,MAAa,OAAQ,SAAQ,cAAc;IACzC,YAAY,KAAc,EAAE,EAAU,EAAE,KAAmB;QACzD,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,cAAc,EAAE,GAAG,EAAE,GAAG,KAAK,CAAC;QAExD,KAAK,CAAC,KAAK,EAAE,EAAE,EAAE;YACf,IAAI;YACJ,UAAU,EAAE,UAAU,CAAC,KAAK;YAC5B,eAAe,EAAE,CAAC,cAAc,CAAC;YACjC,GAAG;SACJ,CAAC,CAAC;IACL,CAAC;CACF;AAXD,0BAWC","sourcesContent":["import type { Duration } from \"aws-cdk-lib\";\nimport { CfnResource } from \"aws-cdk-lib\";\nimport { Construct } from \"constructs\";\nimport type { GuDomainName } from \"../../types\";\nimport type { AppIdentity, GuStack } from \"../core\";\n\nexport enum RecordType {\n CNAME = \"CNAME\",\n}\n\nexport interface GuDnsRecordSetProps {\n name: string;\n recordType: RecordType;\n resourceRecords: string[];\n ttl: Duration;\n}\n\n/**\n * This construct can be used to create DNS records in NS1.\n *\n * Prefer to use [[`GuCname`]] when creating a CNAME for a load balancer,\n * as this requires less boilerplate.\n */\nexport class GuDnsRecordSet extends Construct {\n constructor(scope: GuStack, id: string, props: GuDnsRecordSetProps) {\n const { name, recordType, resourceRecords, ttl } = props;\n const { stage } = scope;\n\n /*\n Nodes in the CDK tree must have a unique ID. This class adds two nodes to the tree, so we have two IDs.\n `id`, by definition, must be unique. `name` represents a fully qualified domain name, which must also be unique.\n `id` being given to the level 1 construct means it also becomes the logicalId in the template.\n */\n const level2ConstructId = `${name}-DnsRecordSet`;\n const level1ConstructId = id;\n\n super(scope, level2ConstructId);\n\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- more `RecordType`s will be added soon!\n if (recordType === RecordType.CNAME) {\n /*\n If you try to create a CNAME with multiple records within NS1, you are greeted with:\n\n According to RFC, a CNAME record should not return multiple answers.\n Doing so may cause problems during resolution.\n If you want to use multiple answers, you should ensure you have the correct filters in place (such as SELECT_FIRST_N 1) to limit them to a single answer at resolution time.\n\n `Guardian::DNS::RecordSet` does not implement \"correct filters\", so fail fast by throwing.\n */\n if (resourceRecords.length !== 1) {\n throw new Error(\n \"According to RFC, a CNAME record should not return multiple answers. Doing so may cause problems during resolution.\",\n );\n }\n }\n\n // The spec for this private resource type can be found here:\n // https://github.com/guardian/cfn-private-resource-types/tree/main/dns/guardian-dns-record-set-type/docs#syntax\n new CfnResource(scope, level1ConstructId, {\n type: \"Guardian::DNS::RecordSet\",\n properties: {\n Name: name,\n ResourceRecords: resourceRecords,\n RecordType: recordType,\n TTL: ttl.toSeconds(),\n Stage: stage,\n },\n });\n }\n}\n\nexport interface GuCnameProps extends GuDomainName, AppIdentity {\n /** The record your CNAME should point to, for example your Load Balancer DNS name */\n resourceRecord: string;\n /** The time to live for the DNS record */\n ttl: Duration;\n}\n\n/**\n * Construct for creating CNAME records in NS1.\n *\n * See [[`GuCnameProps`]] for configuration options.\n */\nexport class GuCname extends GuDnsRecordSet {\n constructor(scope: GuStack, id: string, props: GuCnameProps) {\n const { domainName: name, resourceRecord, ttl } = props;\n\n super(scope, id, {\n name,\n recordType: RecordType.CNAME,\n resourceRecords: [resourceRecord],\n ttl,\n });\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"base.js","sourceRoot":"","sources":["../../../../src/constructs/ec2/security-groups/base.ts"],"names":[],"mappings":";;;AAAA,iDAAgE;AAEhE,kFAA+E;AAmC/E;;;;;;;;GAQG;AACH,MAAa,mBAAoB,SAAQ,uBAAa;IACpD,YAAY,KAAc,EAAE,EAAU,EAAE,KAA+B;QACrE,KAAK,CAAC,KAAK,EAAE,EAAE,EAAE,KAAK,CAAC,CAAC;QAExB,KAAK,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,WAAW,EAAE,EAAE,EAAE;YACxD,MAAM,UAAU,GAAS,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,cAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;YAE1E,IAAI,UAAU,CAAC,QAAQ,EAAE,KAAK,IAAI,EAAE;gBAClC,MAAM,IAAI,KAAK,CAAC,yEAAyE,CAAC,CAAC;aAC5F;YAED,IAAI,CAAC,cAAc,CAAC,KAAK,EAAE,UAAU,EAAE,WAAW,CAAC,CAAC;QACtD,CAAC,CAAC,CAAC;QAEH,KAAK,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,WAAW,EAAE,EAAE,EAAE;YACvD,MAAM,UAAU,GAAS,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,cAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;YAC1E,IAAI,CAAC,aAAa,CAAC,KAAK,EAAE,UAAU,EAAE,WAAW,CAAC,CAAC;QACrD,CAAC,CAAC,CAAC;IACL,CAAC;CACF;AAnBD,kDAmBC;AAED,MAAa,eAAgB,SAAQ,IAAA,yCAAmB,EAAC,mBAAmB,CAAC;IAC3E,YAAY,KAAc,EAAE,EAAU,EAAE,KAA2B;QACjE,KAAK,CAAC,KAAK,EAAE,EAAE,EAAE,KAAK,CAAC,CAAC;IAC1B,CAAC;CACF;AAJD,0CAIC;AAED;;GAEG;AACH,mCAAmC;AACnC,MAAa,0BAA2B,SAAQ,eAAe;IAC7D,YAAY,KAAc,EAAE,EAAU,EAAE,KAA2B;QACjE,KAAK,CAAC,KAAK,EAAE,EAAE,EAAE;YACf,GAAG,KAAK;YACR,gBAAgB,EAAE,KAAK;YACvB,WAAW,EAAE,kCAAkC;YAC/C,SAAS,EAAE,EAAE;YACb,QAAQ,EAAE,CAAC,EAAE,KAAK,EAAE,cAAI,CAAC,OAAO,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,WAAW,EAAE,kCAAkC,EAAE,CAAC;SAClG,CAAC,CAAC;IACL,CAAC;IAEM,MAAM,CAAC,MAAM,CAAC,KAAc,EAAE,KAA2B;QAC9D,OAAO,IAAI,0BAA0B,CAAC,KAAK,EAAE,4BAA4B,EAAE,KAAK,CAAC,CAAC;IACpF,CAAC;CACF;AAdD,gEAcC","sourcesContent":["import { Peer, Port, SecurityGroup } from \"aws-cdk-lib/aws-ec2\";\nimport type { IPeer, SecurityGroupProps } from \"aws-cdk-lib/aws-ec2\";\nimport { GuAppAwareConstruct } from \"../../../utils/mixin/app-aware-construct\";\nimport type { AppIdentity, GuStack } from \"../../core\";\n\n/**\n * A way to describe an ingress or egress rule for a security group.\n *\n * See [[transformToSecurityGroupAccessRule]] for a handy helper function.\n */\nexport interface SecurityGroupAccessRule {\n /**\n * The CIDR address for this rule.\n * Use `Peer.anyIpv4()` for global access.\n */\n range: IPeer;\n\n /**\n * The port to open in a security group.\n * The default protocol is TCP.\n * Use `Port.udp(port)` for the UDP protocol.\n */\n port: number | Port;\n\n /**\n * A short explanation for this rule.\n */\n description: string;\n}\n\nexport interface GuBaseSecurityGroupProps extends SecurityGroupProps {\n ingresses?: SecurityGroupAccessRule[];\n egresses?: SecurityGroupAccessRule[];\n}\n\nexport interface GuSecurityGroupProps extends GuBaseSecurityGroupProps, AppIdentity {}\n\n/**\n * Defining an AWS Security Group with ingress and egress rules.\n *\n * An ingress rule on port 22 is strictly forbidden as SSH via SSM is preferred.\n *\n * Prefer to use a concrete implementation where possible. See:\n * - [[GuPublicInternetAccessSecurityGroup]]\n * - [[GuHttpsEgressSecurityGroup]]\n */\nexport class GuBaseSecurityGroup extends SecurityGroup {\n constructor(scope: GuStack, id: string, props: GuBaseSecurityGroupProps) {\n super(scope, id, props);\n\n props.ingresses?.forEach(({ range, port, description }) => {\n const connection: Port = typeof port === \"number\" ? Port.tcp(port) : port;\n\n if (connection.toString() === \"22\") {\n throw new Error(\"An ingress rule on port 22 is not allowed. Prefer to setup SSH via SSM.\");\n }\n\n this.addIngressRule(range, connection, description);\n });\n\n props.egresses?.forEach(({ range, port, description }) => {\n const connection: Port = typeof port === \"number\" ? Port.tcp(port) : port;\n this.addEgressRule(range, connection, description);\n });\n }\n}\n\nexport class GuSecurityGroup extends GuAppAwareConstruct(GuBaseSecurityGroup) {\n constructor(scope: GuStack, id: string, props: GuSecurityGroupProps) {\n super(scope, id, props);\n }\n}\n\n/**\n * Creates a security group which allows all outbound HTTPS traffic.\n */\n// TODO should this be a singleton?\nexport class GuHttpsEgressSecurityGroup extends GuSecurityGroup {\n constructor(scope: GuStack, id: string, props: GuSecurityGroupProps) {\n super(scope, id, {\n ...props,\n allowAllOutbound: false,\n description: \"Allow all outbound HTTPS traffic\",\n ingresses: [],\n egresses: [{ range: Peer.anyIpv4(), port: 443, description: \"Allow all outbound HTTPS traffic\" }],\n });\n }\n\n public static forVpc(scope: GuStack, props: GuSecurityGroupProps): GuHttpsEgressSecurityGroup {\n return new GuHttpsEgressSecurityGroup(scope, \"GuHttpsEgressSecurityGroup\", props);\n }\n}\n"]}
1
+ {"version":3,"file":"base.js","sourceRoot":"","sources":["../../../../src/constructs/ec2/security-groups/base.ts"],"names":[],"mappings":";;;AAAA,iDAAgE;AAEhE,kFAA+E;AAmC/E;;;;;;;;GAQG;AACH,MAAa,mBAAoB,SAAQ,uBAAa;IACpD,YAAY,KAAc,EAAE,EAAU,EAAE,KAA+B;QACrE,KAAK,CAAC,KAAK,EAAE,EAAE,EAAE,KAAK,CAAC,CAAC;QAExB,KAAK,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,WAAW,EAAE,EAAE,EAAE;YACxD,MAAM,UAAU,GAAS,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,cAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;YAE1E,IAAI,UAAU,CAAC,QAAQ,EAAE,KAAK,IAAI,EAAE,CAAC;gBACnC,MAAM,IAAI,KAAK,CAAC,yEAAyE,CAAC,CAAC;YAC7F,CAAC;YAED,IAAI,CAAC,cAAc,CAAC,KAAK,EAAE,UAAU,EAAE,WAAW,CAAC,CAAC;QACtD,CAAC,CAAC,CAAC;QAEH,KAAK,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,WAAW,EAAE,EAAE,EAAE;YACvD,MAAM,UAAU,GAAS,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,cAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;YAC1E,IAAI,CAAC,aAAa,CAAC,KAAK,EAAE,UAAU,EAAE,WAAW,CAAC,CAAC;QACrD,CAAC,CAAC,CAAC;IACL,CAAC;CACF;AAnBD,kDAmBC;AAED,MAAa,eAAgB,SAAQ,IAAA,yCAAmB,EAAC,mBAAmB,CAAC;IAC3E,YAAY,KAAc,EAAE,EAAU,EAAE,KAA2B;QACjE,KAAK,CAAC,KAAK,EAAE,EAAE,EAAE,KAAK,CAAC,CAAC;IAC1B,CAAC;CACF;AAJD,0CAIC;AAED;;GAEG;AACH,mCAAmC;AACnC,MAAa,0BAA2B,SAAQ,eAAe;IAC7D,YAAY,KAAc,EAAE,EAAU,EAAE,KAA2B;QACjE,KAAK,CAAC,KAAK,EAAE,EAAE,EAAE;YACf,GAAG,KAAK;YACR,gBAAgB,EAAE,KAAK;YACvB,WAAW,EAAE,kCAAkC;YAC/C,SAAS,EAAE,EAAE;YACb,QAAQ,EAAE,CAAC,EAAE,KAAK,EAAE,cAAI,CAAC,OAAO,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,WAAW,EAAE,kCAAkC,EAAE,CAAC;SAClG,CAAC,CAAC;IACL,CAAC;IAEM,MAAM,CAAC,MAAM,CAAC,KAAc,EAAE,KAA2B;QAC9D,OAAO,IAAI,0BAA0B,CAAC,KAAK,EAAE,4BAA4B,EAAE,KAAK,CAAC,CAAC;IACpF,CAAC;CACF;AAdD,gEAcC","sourcesContent":["import { Peer, Port, SecurityGroup } from \"aws-cdk-lib/aws-ec2\";\nimport type { IPeer, SecurityGroupProps } from \"aws-cdk-lib/aws-ec2\";\nimport { GuAppAwareConstruct } from \"../../../utils/mixin/app-aware-construct\";\nimport type { AppIdentity, GuStack } from \"../../core\";\n\n/**\n * A way to describe an ingress or egress rule for a security group.\n *\n * See [[transformToSecurityGroupAccessRule]] for a handy helper function.\n */\nexport interface SecurityGroupAccessRule {\n /**\n * The CIDR address for this rule.\n * Use `Peer.anyIpv4()` for global access.\n */\n range: IPeer;\n\n /**\n * The port to open in a security group.\n * The default protocol is TCP.\n * Use `Port.udp(port)` for the UDP protocol.\n */\n port: number | Port;\n\n /**\n * A short explanation for this rule.\n */\n description: string;\n}\n\nexport interface GuBaseSecurityGroupProps extends SecurityGroupProps {\n ingresses?: SecurityGroupAccessRule[];\n egresses?: SecurityGroupAccessRule[];\n}\n\nexport interface GuSecurityGroupProps extends GuBaseSecurityGroupProps, AppIdentity {}\n\n/**\n * Defining an AWS Security Group with ingress and egress rules.\n *\n * An ingress rule on port 22 is strictly forbidden as SSH via SSM is preferred.\n *\n * Prefer to use a concrete implementation where possible. See:\n * - [[GuPublicInternetAccessSecurityGroup]]\n * - [[GuHttpsEgressSecurityGroup]]\n */\nexport class GuBaseSecurityGroup extends SecurityGroup {\n constructor(scope: GuStack, id: string, props: GuBaseSecurityGroupProps) {\n super(scope, id, props);\n\n props.ingresses?.forEach(({ range, port, description }) => {\n const connection: Port = typeof port === \"number\" ? Port.tcp(port) : port;\n\n if (connection.toString() === \"22\") {\n throw new Error(\"An ingress rule on port 22 is not allowed. Prefer to setup SSH via SSM.\");\n }\n\n this.addIngressRule(range, connection, description);\n });\n\n props.egresses?.forEach(({ range, port, description }) => {\n const connection: Port = typeof port === \"number\" ? Port.tcp(port) : port;\n this.addEgressRule(range, connection, description);\n });\n }\n}\n\nexport class GuSecurityGroup extends GuAppAwareConstruct(GuBaseSecurityGroup) {\n constructor(scope: GuStack, id: string, props: GuSecurityGroupProps) {\n super(scope, id, props);\n }\n}\n\n/**\n * Creates a security group which allows all outbound HTTPS traffic.\n */\n// TODO should this be a singleton?\nexport class GuHttpsEgressSecurityGroup extends GuSecurityGroup {\n constructor(scope: GuStack, id: string, props: GuSecurityGroupProps) {\n super(scope, id, {\n ...props,\n allowAllOutbound: false,\n description: \"Allow all outbound HTTPS traffic\",\n ingresses: [],\n egresses: [{ range: Peer.anyIpv4(), port: 443, description: \"Allow all outbound HTTPS traffic\" }],\n });\n }\n\n public static forVpc(scope: GuStack, props: GuSecurityGroupProps): GuHttpsEgressSecurityGroup {\n return new GuHttpsEgressSecurityGroup(scope, \"GuHttpsEgressSecurityGroup\", props);\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"vpc.d.ts","sourceRoot":"","sources":["../../../src/constructs/ec2/vpc.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAGxE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAEvC,UAAU,cAAe,SAAQ,IAAI,CAAC,aAAa,EAAE,mBAAmB,CAAC;IACvE,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;CAC9B;AAED,KAAK,uBAAuB,GAAG,IAAI,CAAC,cAAc,EAAE,OAAO,CAAC,CAAC;AAG7D,oBAAY,UAAU;IACpB,MAAM,WAAW;IACjB,OAAO,YAAY;CACpB;AAGD,MAAM,WAAW,aAAa;IAC5B,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAMD,eAAO,MAAM,QAAQ,WAAY;IAAE,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,KAAG,MAA0B,CAAC;AAE/E,qBAAa,KAAK;IAChB,MAAM,CAAC,OAAO,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,OAAO,EAAE;IAkB5D,MAAM,CAAC,oBAAoB,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,CAAC,EAAE,aAAa,GAAG,OAAO,EAAE;IAgB7E,MAAM,CAAC,+BAA+B,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,CAAC,EAAE,aAAa,EAAE,UAAU,GAAE,MAAU,GAAG,OAAO,EAAE;IAoBhH,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,cAAc,GAAG,IAAI;IAOtE,MAAM,CAAC,eAAe,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,uBAAuB,GAAG,IAAI;CAI1F"}
1
+ {"version":3,"file":"vpc.d.ts","sourceRoot":"","sources":["../../../src/constructs/ec2/vpc.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAGxE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAEvC,UAAU,cAAe,SAAQ,IAAI,CAAC,aAAa,EAAE,mBAAmB,CAAC;IACvE,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;CAC9B;AAED,KAAK,uBAAuB,GAAG,IAAI,CAAC,cAAc,EAAE,OAAO,CAAC,CAAC;AAG7D,oBAAY,UAAU;IACpB,MAAM,WAAW;IACjB,OAAO,YAAY;CACpB;AAGD,MAAM,WAAW,aAAa;IAC5B,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAMD,eAAO,MAAM,QAAQ,GAAI,QAAQ;IAAE,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,KAAG,MAA0B,CAAC;AAE/E,qBAAa,KAAK;IAChB,MAAM,CAAC,OAAO,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,OAAO,EAAE;IAkB5D,MAAM,CAAC,oBAAoB,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,CAAC,EAAE,aAAa,GAAG,OAAO,EAAE;IAgB7E,MAAM,CAAC,+BAA+B,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,CAAC,EAAE,aAAa,EAAE,UAAU,GAAE,MAAU,GAAG,OAAO,EAAE;IAoBhH,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,cAAc,GAAG,IAAI;IAOtE,MAAM,CAAC,eAAe,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,uBAAuB,GAAG,IAAI;CAI1F"}
@@ -1 +1 @@
1
- {"version":3,"file":"vpc.js","sourceRoot":"","sources":["../../../src/constructs/ec2/vpc.ts"],"names":[],"mappings":"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","sourcesContent":["import { Fn } from \"aws-cdk-lib\";\nimport { Subnet, Vpc } from \"aws-cdk-lib/aws-ec2\";\nimport type { ISubnet, IVpc, VpcAttributes } from \"aws-cdk-lib/aws-ec2\";\nimport { NAMED_SSM_PARAMETER_PATHS } from \"../../constants\";\nimport { GuSubnetListParameter, GuVpcParameter } from \"../core\";\nimport type { GuStack } from \"../core\";\n\ninterface VpcFromIdProps extends Omit<VpcAttributes, \"availabilityZones\"> {\n availabilityZones?: string[];\n}\n\ntype VpcFromIdParameterProps = Omit<VpcFromIdProps, \"vpcId\">;\n\n// TODO convert to boolean\nexport enum SubnetType {\n PUBLIC = \"Public\",\n PRIVATE = \"Private\",\n}\n\n// TODO: Migrate this to use `AppIdentity`\nexport interface GuSubnetProps {\n type?: SubnetType;\n app?: string;\n}\n\n/*\n * Some stacks maybe have multiple patterns (such as `GuEc2App`), therefore creating multiple VPC and subnet resources.\n * This function ensures that, where desired, we can have unique IDs for each VPC and subnet declaration\n */\nexport const maybeApp = (props?: { app?: string }): string => props?.app ?? \"\";\n\nexport class GuVpc {\n static subnets(scope: GuStack, subnets: string[]): ISubnet[] {\n /**\n * As of ~1.77.0 of the aws/cdk, this line\n * [ previously Subnet.fromSubnetId(scope, `subnet-${subnetId}`, subnetId)) ]\n * resulted in the following error\n * \"Found an encoded list token string in a scalar string context. Use 'Fn.select(0, list)' (not 'list[0]') to extract elements from token lists.\"\n * See https://github.com/aws/aws-cdk/issues/11945 for more information\n *\n * As a hacky workaround, we have moved to using the fromSubnetAttributes method and hardcoded an empty value\n * for the routeTableId prop. This prevents the error and, when tested on existing stacks, results in no change to the CFN output\n *\n * TODO: Understand VPCs and Subnets better and develop a better solution to this problem\n */\n return subnets.map((subnetId) =>\n Subnet.fromSubnetAttributes(scope, `subnet-${subnetId}`, { subnetId, routeTableId: \" \" }),\n );\n }\n\n static subnetsFromParameter(scope: GuStack, props?: GuSubnetProps): ISubnet[] {\n const type = props?.type ?? SubnetType.PRIVATE;\n const parameterDefault =\n type === SubnetType.PRIVATE\n ? NAMED_SSM_PARAMETER_PATHS.PrimaryVpcPrivateSubnets\n : NAMED_SSM_PARAMETER_PATHS.PrimaryVpcPublicSubnets;\n\n const subnets = new GuSubnetListParameter(scope, `${maybeApp(props)}${type}Subnets`, {\n description: `A list of ${type.toLowerCase()} subnets`,\n default: parameterDefault.path,\n fromSSM: true,\n });\n\n return GuVpc.subnets(scope, subnets.valueAsList);\n }\n\n static subnetsFromParameterFixedNumber(scope: GuStack, props?: GuSubnetProps, numSubnets: number = 3): ISubnet[] {\n const type = props?.type ?? SubnetType.PRIVATE;\n const parameterDefault =\n type === SubnetType.PRIVATE\n ? NAMED_SSM_PARAMETER_PATHS.PrimaryVpcPrivateSubnets\n : NAMED_SSM_PARAMETER_PATHS.PrimaryVpcPublicSubnets;\n\n const subnets = new GuSubnetListParameter(scope, `${maybeApp(props)}${type}Subnets`, {\n description: `A list of ${type.toLowerCase()} subnets`,\n default: parameterDefault.path,\n fromSSM: true,\n });\n\n const subnetIds: string[] = [];\n for (let i = 0; i < numSubnets; i++) {\n subnetIds.push(Fn.select(i, subnets.valueAsList));\n }\n return subnetIds.map((subnetId) => Subnet.fromSubnetId(scope, `subnet-${subnetId}`, subnetId));\n }\n\n static fromId(scope: GuStack, id: string, props: VpcFromIdProps): IVpc {\n return Vpc.fromVpcAttributes(scope, id, {\n availabilityZones: scope.availabilityZones,\n ...props,\n });\n }\n\n static fromIdParameter(scope: GuStack, id: string, props?: VpcFromIdParameterProps): IVpc {\n const vpc = GuVpcParameter.getInstance(scope);\n return GuVpc.fromId(scope, id, { ...props, vpcId: vpc.valueAsString });\n }\n}\n"]}
1
+ {"version":3,"file":"vpc.js","sourceRoot":"","sources":["../../../src/constructs/ec2/vpc.ts"],"names":[],"mappings":"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","sourcesContent":["import { Fn } from \"aws-cdk-lib\";\nimport { Subnet, Vpc } from \"aws-cdk-lib/aws-ec2\";\nimport type { ISubnet, IVpc, VpcAttributes } from \"aws-cdk-lib/aws-ec2\";\nimport { NAMED_SSM_PARAMETER_PATHS } from \"../../constants\";\nimport { GuSubnetListParameter, GuVpcParameter } from \"../core\";\nimport type { GuStack } from \"../core\";\n\ninterface VpcFromIdProps extends Omit<VpcAttributes, \"availabilityZones\"> {\n availabilityZones?: string[];\n}\n\ntype VpcFromIdParameterProps = Omit<VpcFromIdProps, \"vpcId\">;\n\n// TODO convert to boolean\nexport enum SubnetType {\n PUBLIC = \"Public\",\n PRIVATE = \"Private\",\n}\n\n// TODO: Migrate this to use `AppIdentity`\nexport interface GuSubnetProps {\n type?: SubnetType;\n app?: string;\n}\n\n/*\n * Some stacks maybe have multiple patterns (such as `GuEc2App`), therefore creating multiple VPC and subnet resources.\n * This function ensures that, where desired, we can have unique IDs for each VPC and subnet declaration\n */\nexport const maybeApp = (props?: { app?: string }): string => props?.app ?? \"\";\n\nexport class GuVpc {\n static subnets(scope: GuStack, subnets: string[]): ISubnet[] {\n /**\n * As of ~1.77.0 of the aws/cdk, this line\n * [ previously Subnet.fromSubnetId(scope, `subnet-${subnetId}`, subnetId)) ]\n * resulted in the following error\n * \"Found an encoded list token string in a scalar string context. Use 'Fn.select(0, list)' (not 'list[0]') to extract elements from token lists.\"\n * See https://github.com/aws/aws-cdk/issues/11945 for more information\n *\n * As a hacky workaround, we have moved to using the fromSubnetAttributes method and hardcoded an empty value\n * for the routeTableId prop. This prevents the error and, when tested on existing stacks, results in no change to the CFN output\n *\n * TODO: Understand VPCs and Subnets better and develop a better solution to this problem\n */\n return subnets.map((subnetId) =>\n Subnet.fromSubnetAttributes(scope, `subnet-${subnetId}`, { subnetId, routeTableId: \" \" }),\n );\n }\n\n static subnetsFromParameter(scope: GuStack, props?: GuSubnetProps): ISubnet[] {\n const type = props?.type ?? SubnetType.PRIVATE;\n const parameterDefault =\n type === SubnetType.PRIVATE\n ? NAMED_SSM_PARAMETER_PATHS.PrimaryVpcPrivateSubnets\n : NAMED_SSM_PARAMETER_PATHS.PrimaryVpcPublicSubnets;\n\n const subnets = new GuSubnetListParameter(scope, `${maybeApp(props)}${type}Subnets`, {\n description: `A list of ${type.toLowerCase()} subnets`,\n default: parameterDefault.path,\n fromSSM: true,\n });\n\n return GuVpc.subnets(scope, subnets.valueAsList);\n }\n\n static subnetsFromParameterFixedNumber(scope: GuStack, props?: GuSubnetProps, numSubnets: number = 3): ISubnet[] {\n const type = props?.type ?? SubnetType.PRIVATE;\n const parameterDefault =\n type === SubnetType.PRIVATE\n ? NAMED_SSM_PARAMETER_PATHS.PrimaryVpcPrivateSubnets\n : NAMED_SSM_PARAMETER_PATHS.PrimaryVpcPublicSubnets;\n\n const subnets = new GuSubnetListParameter(scope, `${maybeApp(props)}${type}Subnets`, {\n description: `A list of ${type.toLowerCase()} subnets`,\n default: parameterDefault.path,\n fromSSM: true,\n });\n\n const subnetIds: string[] = [];\n for (let i = 0; i < numSubnets; i++) {\n subnetIds.push(Fn.select(i, subnets.valueAsList));\n }\n return subnetIds.map((subnetId) => Subnet.fromSubnetId(scope, `subnet-${subnetId}`, subnetId));\n }\n\n static fromId(scope: GuStack, id: string, props: VpcFromIdProps): IVpc {\n return Vpc.fromVpcAttributes(scope, id, {\n availabilityZones: scope.availabilityZones,\n ...props,\n });\n }\n\n static fromIdParameter(scope: GuStack, id: string, props?: VpcFromIdParameterProps): IVpc {\n const vpc = GuVpcParameter.getInstance(scope);\n return GuVpc.fromId(scope, id, { ...props, vpcId: vpc.valueAsString });\n }\n}\n"]}
@@ -69,7 +69,7 @@ class GuEcsTask extends constructs_1.Construct {
69
69
  const containerDefinition = taskDefinition.addContainer(`${id}-TaskContainer`, {
70
70
  image: getContainer(containerConfiguration),
71
71
  entryPoint: taskCommand ? ["/bin/sh"] : undefined,
72
- command: taskCommand ? ["-c", taskCommand] : undefined,
72
+ command: taskCommand ? ["-c", taskCommand] : undefined, // if unset, falls back to CMD in docker file, or no command will be run
73
73
  cpu,
74
74
  memoryLimitMiB: memory,
75
75
  logging: aws_ecs_1.LogDrivers.awsLogs({
@@ -1 +1 @@
1
- {"version":3,"file":"ecs-task.js","sourceRoot":"","sources":["../../../src/constructs/ecs/ecs-task.ts"],"names":[],"mappings":";;;AAAA,6CAAkD;AAClD,+DAAqE;AACrE,+EAA+D;AAG/D,iDAS6B;AAE7B,iDAA8D;AAC9D,iDAA4C;AAC5C,qEAAoH;AAEpH,iFAAyF;AACzF,2CAAuC;AAGvC,kCAAsC;AACtC,gCAA2D;AAkH3D;;;GAGG;AACH,MAAM,YAAY,GAAG,CAAC,MAA8B,EAAE,EAAE;IACtD,IAAI,MAAM,CAAC,IAAI,IAAI,YAAY,EAAE;QAC/B,OAAO,wBAAc,CAAC,iBAAiB,CAAC,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;KAC5E;SAAM;QACL,OAAO,wBAAc,CAAC,YAAY,CAAC,MAAM,CAAC,EAAE,IAAI,cAAc,EAAE,MAAM,CAAC,UAAU,CAAC,CAAC;KACpF;AACH,CAAC,CAAC;AAEF;;;;;;;;;;GAUG;AACH,MAAa,SAAU,SAAQ,sBAAS;IAMtC,YAAY,KAAc,EAAE,EAAU,EAAE,KAAqB;QAC3D,KAAK,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QAEjB,MAAM,EACJ,GAAG;QAEH,iJAAiJ;QACjJ,GAAG,GAAG,IAAI,EAAE,iCAAiC;QAC7C,MAAM,GAAG,IAAI,EAAE,MAAM;QACrB,OAAO,EAAE,8CAA8C;QACvD,sBAAsB,EACtB,WAAW,EACX,oBAAoB,GAAG,EAAE,EACzB,kBAAkB,EAClB,GAAG,EACH,OAAO,EACP,uBAAuB,EACvB,cAAc,GAAG,EAAE,EACnB,oBAAoB,EACpB,yBAAyB,GAAG,IAAI,EAChC,iBAAiB,GAClB,GAAG,KAAK,CAAC;QAEV,IAAI,OAAO,IAAI,OAAO,GAAG,EAAE,EAAE;YAC3B,MAAM,IAAI,KAAK,CACb,yJAAyJ,CAC1J,CAAC;SACH;QAED,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,KAAK,CAAC;QAE/B,MAAM,OAAO,GAAG,IAAI,iBAAO,CAAC,KAAK,EAAE,GAAG,EAAE,UAAU,EAAE;YAClD,WAAW,EAAE,GAAG,GAAG,YAAY,KAAK,EAAE;YACtC,8BAA8B,EAAE,IAAI;YACpC,GAAG;YACH,mBAAmB,EAAE,iBAAiB;SACvC,CAAC,CAAC;QAEH,MAAM,cAAc,GAAG,IAAI,wBAAc,CAAC,KAAK,EAAE,GAAG,EAAE,iBAAiB,EAAE;YACvE,aAAa,EAAE,uBAAa,CAAC,OAAO;YACpC,GAAG,EAAE,GAAG,CAAC,QAAQ,EAAE;YACnB,SAAS,EAAE,MAAM,CAAC,QAAQ,EAAE;YAC5B,MAAM,EAAE,GAAG,KAAK,IAAI,KAAK,IAAI,GAAG,EAAE;YAClC,mBAAmB,EAAE,OAAO;YAC5B,eAAe,EAAE;gBACf,eAAe,EAAE,yBAAe,CAAC,KAAK;gBACtC,qBAAqB,EAAE,+BAAqB,CAAC,EAAE,CAAC,OAAO,CAAC;aACzD;SACF,CAAC,CAAC;QACH,IAAI,CAAC,cAAc,GAAG,cAAc,CAAC;QAErC,MAAM,mBAAmB,GAAG,cAAc,CAAC,YAAY,CAAC,GAAG,EAAE,gBAAgB,EAAE;YAC7E,KAAK,EAAE,YAAY,CAAC,sBAAsB,CAAC;YAC3C,UAAU,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS;YACjD,OAAO,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC,SAAS;YACtD,GAAG;YACH,cAAc,EAAE,MAAM;YACtB,OAAO,EAAE,oBAAU,CAAC,OAAO,CAAC;gBAC1B,YAAY,EAAE,GAAG;gBACjB,YAAY,EAAE,EAAE;aACjB,CAAC;YACF,sBAAsB,EAAE,IAAI;SAC7B,CAAC,CAAC;QACH,IAAI,CAAC,mBAAmB,GAAG,mBAAmB,CAAC;QAE/C,IAAI,yBAAyB,EAAE;YAC7B,MAAM,UAAU,GAAG,IAAI,uCAAiC,CAAC,KAAK,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC;YACzE,cAAc,CAAC,mBAAmB,CAAC,UAAU,CAAC,CAAC;SAChD;QAED,8DAA8D;QAC9D,sIAAsI;QACtI,MAAM,kBAAkB,GAAG,IAAI,yBAAe,CAAC;YAC7C,MAAM,EAAE,gBAAM,CAAC,KAAK;YACpB,OAAO,EAAE,CAAC,2BAA2B,CAAC;YACtC,SAAS,EAAE,CAAC,GAAG,CAAC;SACjB,CAAC,CAAC;QACH,MAAM,wBAAwB,GAAG,IAAI,yBAAe,CAAC;YACnD,MAAM,EAAE,gBAAM,CAAC,KAAK;YACpB,OAAO,EAAE,CAAC,iCAAiC,EAAE,4BAA4B,EAAE,mBAAmB,CAAC;YAC/F,uGAAuG;YACvG,sGAAsG;YACtG,SAAS,EAAE,CAAC,2EAA2E,CAAC;SACzF,CAAC,CAAC;QAEH,cAAc,CAAC,wBAAwB,CAAC,kBAAkB,CAAC,CAAC;QAC5D,cAAc,CAAC,wBAAwB,CAAC,wBAAwB,CAAC,CAAC;QAElE,CAAC,kBAAkB,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,cAAc,CAAC,mBAAmB,CAAC,CAAC,CAAC,CAAC,CAAC;QAEjF,MAAM,IAAI,GAAG,IAAI,oCAAU,CAAC,KAAK,EAAE,GAAG,EAAE,OAAO,EAAE;YAC/C,OAAO;YACP,YAAY,EAAE,IAAI,gDAAsB,CAAC;gBACvC,eAAe,EAAE,gCAAsB,CAAC,MAAM;aAC/C,CAAC;YACF,cAAc;YACd,OAAO,EAAE,EAAE,OAAO,EAAE;YACpB,cAAc,EAAE,KAAK;YACrB,kBAAkB,EAAE,sCAAkB,CAAC,OAAO;YAC9C,UAAU,EAAE,4BAAQ,CAAC,OAAO;YAC5B,WAAW,EAAE,2BAAO,CAAC,QAAQ,CAAC,sBAAQ,CAAC,OAAO,CAAC,oBAAoB,CAAC,CAAC;YACrE,cAAc;YACd,kBAAkB,EAAE;gBAClB;oBACE,mBAAmB,EAAE,mBAAmB;oBACxC,WAAW,EAAE,oBAAoB;iBAClC;aACF;SACF,CAAC,CAAC;QACH,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QAEjB,IAAI,CAAC,YAAY,GAAG,IAAI,gCAAY,CAAC,KAAK,EAAE,GAAG,EAAE,eAAe,EAAE;YAChE,cAAc,EAAE,kCAAc,CAAC,aAAa,CAAC,IAAI,CAAC;YAClD,gBAAgB,EAAE,GAAG,GAAG,IAAI,KAAK,EAAE;SACpC,CAAC,CAAC;QAEH,IAAI,CAAC,uBAAuB,CAAC,YAAY,EAAE;YACzC,MAAM,UAAU,GAAG,eAAK,CAAC,YAAY,CACnC,KAAK,EACL,kBAAW,CAAC,UAAU,CAAC,KAAK,EAAE,YAAY,CAAC,EAC3C,uBAAuB,CAAC,WAAW,CACpC,CAAC;YACF,MAAM,MAAM,GAAG;gBACb;oBACE,IAAI,EAAE,GAAG,GAAG,mBAAmB;oBAC/B,WAAW,EAAE,GAAG,GAAG,IAAI,KAAK,cAAc;oBAC1C,MAAM,EAAE,IAAI,CAAC,YAAY,CAAC,YAAY,CAAC;wBACrC,MAAM,EAAE,sBAAQ,CAAC,KAAK,CAAC,CAAC,CAAC;wBACzB,SAAS,EAAE,KAAK;qBACjB,CAAC;iBACH;gBACD;oBACE,IAAI,EAAE,GAAG,GAAG,UAAU;oBACtB,WAAW,EAAE,GAAG,GAAG,IAAI,KAAK,iBAAiB;oBAC7C,MAAM,EAAE,IAAI,CAAC,YAAY,CAAC,cAAc,CAAC;wBACvC,MAAM,EAAE,sBAAQ,CAAC,KAAK,CAAC,CAAC,CAAC;wBACzB,SAAS,EAAE,KAAK;qBACjB,CAAC;iBACH;aACF,CAAC;YAEF,MAAM,CAAC,OAAO,CAAC,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,EAAE,EAAE,EAAE;gBAC/C,MAAM,KAAK,GAAG,IAAI,sBAAK,CAAC,KAAK,EAAE,IAAI,EAAE;oBACnC,gBAAgB,EAAE,WAAW;oBAC7B,cAAc,EAAE,IAAI;oBACpB,MAAM,EAAE,MAAM;oBACd,kEAAkE;oBAClE,SAAS,EAAE,CAAC;oBACZ,iBAAiB,EAAE,CAAC;oBACpB,gBAAgB,EAAE,iCAAgB,CAAC,aAAa;iBACjD,CAAC,CAAC;gBACH,KAAK,CAAC,cAAc,CAAC,IAAI,kCAAS,CAAC,UAAU,CAAC,CAAC,CAAC;gBAChD,kBAAW,CAAC,eAAe,CAAC,EAAE,GAAG,EAAE,EAAE,KAAK,CAAC,CAAC;YAC9C,CAAC,CAAC,CAAC;SACJ;QAED,0CAA0C;QAC1C,CAAC,OAAO,EAAE,IAAI,EAAE,cAAc,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,kBAAW,CAAC,eAAe,CAAC,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC;QAE3G,IAAI,uBAAS,CAAC,KAAK,EAAE,GAAG,EAAE,wBAAwB,EAAE;YAClD,KAAK,EAAE,IAAI,CAAC,YAAY,CAAC,eAAe;SACzC,CAAC,CAAC;IACL,CAAC;CACF;AAzKD,8BAyKC","sourcesContent":["import { CfnOutput, Duration } from \"aws-cdk-lib\";\nimport { Alarm, TreatMissingData } from \"aws-cdk-lib/aws-cloudwatch\";\nimport { SnsAction } from \"aws-cdk-lib/aws-cloudwatch-actions\";\nimport type { ISecurityGroup, ISubnet, IVpc } from \"aws-cdk-lib/aws-ec2\";\nimport type { IRepository } from \"aws-cdk-lib/aws-ecr\";\nimport {\n Cluster,\n Compatibility,\n ContainerImage,\n CpuArchitecture,\n FargatePlatformVersion,\n LogDrivers,\n OperatingSystemFamily,\n TaskDefinition,\n} from \"aws-cdk-lib/aws-ecs\";\nimport type { ContainerDefinition, ContainerInsights, RepositoryImageProps } from \"aws-cdk-lib/aws-ecs\";\nimport { Effect, PolicyStatement } from \"aws-cdk-lib/aws-iam\";\nimport { Topic } from \"aws-cdk-lib/aws-sns\";\nimport { DefinitionBody, IntegrationPattern, JsonPath, StateMachine, Timeout } from \"aws-cdk-lib/aws-stepfunctions\";\nimport type { TaskEnvironmentVariable } from \"aws-cdk-lib/aws-stepfunctions-tasks\";\nimport { EcsFargateLaunchTarget, EcsRunTask } from \"aws-cdk-lib/aws-stepfunctions-tasks\";\nimport { Construct } from \"constructs\";\nimport type { NoMonitoring } from \"../cloudwatch\";\nimport type { GuStack } from \"../core\";\nimport { AppIdentity } from \"../core\";\nimport { GuGetDistributablePolicyStatement } from \"../iam\";\n\n/**\n * Configuration to determine what container to use for the task\n * For example, to run the task in the latest node container:\n *\n * ```typescript\n * const containerConfiguration = {\n * id: 'node:latest'\n * }\n * ```\n *\n * Alternatively you can specify a repository and version, for example for an ECR repository:\n * ```typescript\n * import { Repository } from \"aws-cdk-lib/aws-ecr\";\n * const repository = new Repository(scope, `${app}-repository`, {\n repositoryName: app,\n });\n * const containerConfiguration = {\n * repository: Repository.fromRepositoryArn(\"<repository arn>\"),\n * version: '1'\n * }\n * ```\n */\n\nexport type RepositoryContainer = {\n repository: IRepository;\n version: string;\n type: \"repository\";\n};\n\nexport type RegistryContainer = {\n id?: string;\n imageProps?: RepositoryImageProps;\n type: \"registry\";\n};\n\nexport type ContainerConfiguration = RepositoryContainer | RegistryContainer;\n\nexport type GuEcsTaskMonitoringProps = { snsTopicArn: string; noMonitoring: false };\n\n/**\n * Configuration options for the [[`GuEcsTask`]] pattern.\n *\n * Note it is recommended to use GuVpc.subnetsFromParameterFixedNumber for the subnets prop rather than\n * GuVpc.subnetsFromParameter, as using the latter can result a custom resource being required\n *\n * See [[`ContainerConfiguration`]] for details of how to configure the container used to run the task.\n *\n * `taskTimeoutInMinutes` does what is says on the tin. The default timeout is 15 minutes.\n *\n * The `taskCommand` prop allows you to specify a command to run when the task starts (this can also be done via a CMD statement in\n * your Dockerfile). For example:\n *\n * const props = {\n * //other props\n * taskCommand: `aws s3 cp s3://${distbucket}/${stack}/${stage}/${app}/task.sh . && ./task.sh\n }\n *\n * It is advisable to configure alarms for when the job fails/times out. To do this specify the alarmSnsTopicArn prop.\n *\n * `customTaskPolicies` allows your task to interact with other AWS services. By default a task\n * will have read access to the distribution bucket for your account.\n *\n * You can specify security groups to apply to task using the `securityGroups` prop.\n *\n * You can also set the memory and cpu units for your task. See https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task_definition_parameters.html#task_size\n * for further details.\n *\n * If you want to pass input from the step function into your EcsTask you can do so via the `environmentOverrides` prop, which allows you to wire up\n * step function input JSON to environment variables set on the container. For example,\n * const props = {\n * ...otherProps\n * environmentOverrides: [\n {\n name: \"VERSION\",\n value: JsonPath.stringAt(\"$.version\"),\n },\n }\n * With the above override, your task will attempt to find a `version` property in the JSON input passed to the step function, and apply it to the\n * VERSION environment variable. Alternatively, you could hard code a value for the variable in CDK.\n * See https://docs.aws.amazon.com/step-functions/latest/dg/connect-ecs.html for further detail and other override options - this construct currently\n * only supports environment variables.\n */\nexport interface GuEcsTaskProps extends AppIdentity {\n vpc: IVpc;\n subnets: ISubnet[];\n assignPublicIp?: boolean;\n containerConfiguration: ContainerConfiguration;\n taskTimeoutInMinutes?: number;\n cpu?: number;\n memory?: number;\n taskCommand?: string;\n monitoringConfiguration: NoMonitoring | GuEcsTaskMonitoringProps;\n securityGroups?: ISecurityGroup[];\n customTaskPolicies?: PolicyStatement[];\n environmentOverrides?: TaskEnvironmentVariable[];\n storage?: number;\n /**\n * Whether to give the task IAM role access to the account's dist bucket.\n * This is enabled by default to avoid breaking changes, but consumers of this pattern\n * that pull a container image that doesn't need extra dependencies from S3\n * shoud set this value to `false`.\n */\n enableDistributablePolicy?: boolean;\n\n /**\n * The CloudWatch Container Insights setting\n *\n * @see https://docs.aws.amazon.com/AmazonECS/latest/developerguide/cloudwatch-container-insights.html\n */\n containerInsights: ContainerInsights;\n}\n\n/**\n * Containers can be specified either via a repository and version or by container id (in which case it will\n * be fetched from docker hub).\n */\nconst getContainer = (config: ContainerConfiguration) => {\n if (config.type == \"repository\") {\n return ContainerImage.fromEcrRepository(config.repository, config.version);\n } else {\n return ContainerImage.fromRegistry(config.id ?? \"ubuntu:jammy\", config.imageProps);\n }\n};\n\n/**\n * Pattern which creates all of the resources needed for a fargate task\n *\n * The task will be wrapped in a step function to allow for easier triggering and alarming on failure.\n *\n * For all configuration options, see [[`GuEcsTaskProps`]].\n *\n * Note that if your task reliably completes in less than 15 minutes then you should probably use a [[`GuLambda`]] instead. This\n * pattern was mainly created to work around the 15 minute lambda timeout.\n *\n */\nexport class GuEcsTask extends Construct {\n public readonly stateMachine: StateMachine;\n public readonly taskDefinition: TaskDefinition;\n public readonly containerDefinition: ContainerDefinition;\n public readonly task: EcsRunTask;\n\n constructor(scope: GuStack, id: string, props: GuEcsTaskProps) {\n super(scope, id);\n\n const {\n app,\n\n // see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ecs-taskdefinition.html#cfn-ecs-taskdefinition-cpu for details\n cpu = 2048, // 2 cores and from 4-16GB memory\n memory = 4096, // 4GB\n storage, // default is 20 GB when not provided in props\n containerConfiguration,\n taskCommand,\n taskTimeoutInMinutes = 15,\n customTaskPolicies,\n vpc,\n subnets,\n monitoringConfiguration,\n securityGroups = [],\n environmentOverrides,\n enableDistributablePolicy = true,\n containerInsights,\n } = props;\n\n if (storage && storage < 21) {\n throw new Error(\n \"Storage must be at least 21. See https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ecs-taskdefinition-ephemeralstorage.html\",\n );\n }\n\n const { stack, stage } = scope;\n\n const cluster = new Cluster(scope, `${id}-Cluster`, {\n clusterName: `${app}-cluster-${stage}`,\n enableFargateCapacityProviders: true,\n vpc,\n containerInsightsV2: containerInsights,\n });\n\n const taskDefinition = new TaskDefinition(scope, `${id}-TaskDefinition`, {\n compatibility: Compatibility.FARGATE,\n cpu: cpu.toString(),\n memoryMiB: memory.toString(),\n family: `${stack}-${stage}-${app}`,\n ephemeralStorageGiB: storage,\n runtimePlatform: {\n cpuArchitecture: CpuArchitecture.ARM64,\n operatingSystemFamily: OperatingSystemFamily.of(\"LINUX\"),\n },\n });\n this.taskDefinition = taskDefinition;\n\n const containerDefinition = taskDefinition.addContainer(`${id}-TaskContainer`, {\n image: getContainer(containerConfiguration),\n entryPoint: taskCommand ? [\"/bin/sh\"] : undefined,\n command: taskCommand ? [\"-c\", taskCommand] : undefined, // if unset, falls back to CMD in docker file, or no command will be run\n cpu,\n memoryLimitMiB: memory,\n logging: LogDrivers.awsLogs({\n streamPrefix: app,\n logRetention: 14,\n }),\n readonlyRootFilesystem: true,\n });\n this.containerDefinition = containerDefinition;\n\n if (enableDistributablePolicy) {\n const distPolicy = new GuGetDistributablePolicyStatement(scope, { app });\n taskDefinition.addToTaskRolePolicy(distPolicy);\n }\n\n // these policies are needed for guard duty runtime monitoring\n // See https://docs.aws.amazon.com/guardduty/latest/ug/prereq-runtime-monitoring-ecs-support.html#before-enable-runtime-monitoring-ecs\n const getAuthTokenPolicy = new PolicyStatement({\n effect: Effect.ALLOW,\n actions: [\"ecr:GetAuthorizationToken\"],\n resources: [\"*\"],\n });\n const guardDutyContainerPolicy = new PolicyStatement({\n effect: Effect.ALLOW,\n actions: [\"ecr:BatchCheckLayerAvailability\", \"ecr:GetDownloadUrlForLayer\", \"ecr:BatchGetImage\"],\n // See https://docs.aws.amazon.com/guardduty/latest/ug/runtime-monitoring-ecr-repository-gdu-agent.html\n // note that if you are using a region other than eu-west-1 you'll need to add extra repositories here\n resources: [\"arn:aws:ecr:eu-west-1:694911143906:repository/aws-guardduty-agent-fargate\"],\n });\n\n taskDefinition.addToExecutionRolePolicy(getAuthTokenPolicy);\n taskDefinition.addToExecutionRolePolicy(guardDutyContainerPolicy);\n\n (customTaskPolicies ?? []).forEach((p) => taskDefinition.addToTaskRolePolicy(p));\n\n const task = new EcsRunTask(scope, `${id}-task`, {\n cluster,\n launchTarget: new EcsFargateLaunchTarget({\n platformVersion: FargatePlatformVersion.LATEST,\n }),\n taskDefinition,\n subnets: { subnets },\n assignPublicIp: false,\n integrationPattern: IntegrationPattern.RUN_JOB,\n resultPath: JsonPath.DISCARD,\n taskTimeout: Timeout.duration(Duration.minutes(taskTimeoutInMinutes)),\n securityGroups,\n containerOverrides: [\n {\n containerDefinition: containerDefinition,\n environment: environmentOverrides,\n },\n ],\n });\n this.task = task;\n\n this.stateMachine = new StateMachine(scope, `${id}-StateMachine`, {\n definitionBody: DefinitionBody.fromChainable(task),\n stateMachineName: `${app}-${stage}`,\n });\n\n if (!monitoringConfiguration.noMonitoring) {\n const alarmTopic = Topic.fromTopicArn(\n scope,\n AppIdentity.suffixText(props, \"AlarmTopic\"),\n monitoringConfiguration.snsTopicArn,\n );\n const alarms = [\n {\n name: `${app}-execution-failed`,\n description: `${app}-${stage} job failed `,\n metric: this.stateMachine.metricFailed({\n period: Duration.hours(1),\n statistic: \"sum\",\n }),\n },\n {\n name: `${app}-timeout`,\n description: `${app}-${stage} job timed out `,\n metric: this.stateMachine.metricTimedOut({\n period: Duration.hours(1),\n statistic: \"sum\",\n }),\n },\n ];\n\n alarms.forEach(({ name, description, metric }) => {\n const alarm = new Alarm(scope, name, {\n alarmDescription: description,\n actionsEnabled: true,\n metric: metric,\n // default for comparisonOperator is GreaterThanOrEqualToThreshold\n threshold: 1,\n evaluationPeriods: 1,\n treatMissingData: TreatMissingData.NOT_BREACHING,\n });\n alarm.addAlarmAction(new SnsAction(alarmTopic));\n AppIdentity.taggedConstruct({ app }, alarm);\n });\n }\n\n // Tag all constructs with correct app tag\n [cluster, task, taskDefinition, this.stateMachine].forEach((c) => AppIdentity.taggedConstruct({ app }, c));\n\n new CfnOutput(scope, `${id}-StateMachineArnOutput`, {\n value: this.stateMachine.stateMachineArn,\n });\n }\n}\n"]}
1
+ {"version":3,"file":"ecs-task.js","sourceRoot":"","sources":["../../../src/constructs/ecs/ecs-task.ts"],"names":[],"mappings":"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","sourcesContent":["import { CfnOutput, Duration } from \"aws-cdk-lib\";\nimport { Alarm, TreatMissingData } from \"aws-cdk-lib/aws-cloudwatch\";\nimport { SnsAction } from \"aws-cdk-lib/aws-cloudwatch-actions\";\nimport type { ISecurityGroup, ISubnet, IVpc } from \"aws-cdk-lib/aws-ec2\";\nimport type { IRepository } from \"aws-cdk-lib/aws-ecr\";\nimport {\n Cluster,\n Compatibility,\n ContainerImage,\n CpuArchitecture,\n FargatePlatformVersion,\n LogDrivers,\n OperatingSystemFamily,\n TaskDefinition,\n} from \"aws-cdk-lib/aws-ecs\";\nimport type { ContainerDefinition, ContainerInsights, RepositoryImageProps } from \"aws-cdk-lib/aws-ecs\";\nimport { Effect, PolicyStatement } from \"aws-cdk-lib/aws-iam\";\nimport { Topic } from \"aws-cdk-lib/aws-sns\";\nimport { DefinitionBody, IntegrationPattern, JsonPath, StateMachine, Timeout } from \"aws-cdk-lib/aws-stepfunctions\";\nimport type { TaskEnvironmentVariable } from \"aws-cdk-lib/aws-stepfunctions-tasks\";\nimport { EcsFargateLaunchTarget, EcsRunTask } from \"aws-cdk-lib/aws-stepfunctions-tasks\";\nimport { Construct } from \"constructs\";\nimport type { NoMonitoring } from \"../cloudwatch\";\nimport type { GuStack } from \"../core\";\nimport { AppIdentity } from \"../core\";\nimport { GuGetDistributablePolicyStatement } from \"../iam\";\n\n/**\n * Configuration to determine what container to use for the task\n * For example, to run the task in the latest node container:\n *\n * ```typescript\n * const containerConfiguration = {\n * id: 'node:latest'\n * }\n * ```\n *\n * Alternatively you can specify a repository and version, for example for an ECR repository:\n * ```typescript\n * import { Repository } from \"aws-cdk-lib/aws-ecr\";\n * const repository = new Repository(scope, `${app}-repository`, {\n repositoryName: app,\n });\n * const containerConfiguration = {\n * repository: Repository.fromRepositoryArn(\"<repository arn>\"),\n * version: '1'\n * }\n * ```\n */\n\nexport type RepositoryContainer = {\n repository: IRepository;\n version: string;\n type: \"repository\";\n};\n\nexport type RegistryContainer = {\n id?: string;\n imageProps?: RepositoryImageProps;\n type: \"registry\";\n};\n\nexport type ContainerConfiguration = RepositoryContainer | RegistryContainer;\n\nexport type GuEcsTaskMonitoringProps = { snsTopicArn: string; noMonitoring: false };\n\n/**\n * Configuration options for the [[`GuEcsTask`]] pattern.\n *\n * Note it is recommended to use GuVpc.subnetsFromParameterFixedNumber for the subnets prop rather than\n * GuVpc.subnetsFromParameter, as using the latter can result a custom resource being required\n *\n * See [[`ContainerConfiguration`]] for details of how to configure the container used to run the task.\n *\n * `taskTimeoutInMinutes` does what is says on the tin. The default timeout is 15 minutes.\n *\n * The `taskCommand` prop allows you to specify a command to run when the task starts (this can also be done via a CMD statement in\n * your Dockerfile). For example:\n *\n * const props = {\n * //other props\n * taskCommand: `aws s3 cp s3://${distbucket}/${stack}/${stage}/${app}/task.sh . && ./task.sh\n }\n *\n * It is advisable to configure alarms for when the job fails/times out. To do this specify the alarmSnsTopicArn prop.\n *\n * `customTaskPolicies` allows your task to interact with other AWS services. By default a task\n * will have read access to the distribution bucket for your account.\n *\n * You can specify security groups to apply to task using the `securityGroups` prop.\n *\n * You can also set the memory and cpu units for your task. See https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task_definition_parameters.html#task_size\n * for further details.\n *\n * If you want to pass input from the step function into your EcsTask you can do so via the `environmentOverrides` prop, which allows you to wire up\n * step function input JSON to environment variables set on the container. For example,\n * const props = {\n * ...otherProps\n * environmentOverrides: [\n {\n name: \"VERSION\",\n value: JsonPath.stringAt(\"$.version\"),\n },\n }\n * With the above override, your task will attempt to find a `version` property in the JSON input passed to the step function, and apply it to the\n * VERSION environment variable. Alternatively, you could hard code a value for the variable in CDK.\n * See https://docs.aws.amazon.com/step-functions/latest/dg/connect-ecs.html for further detail and other override options - this construct currently\n * only supports environment variables.\n */\nexport interface GuEcsTaskProps extends AppIdentity {\n vpc: IVpc;\n subnets: ISubnet[];\n assignPublicIp?: boolean;\n containerConfiguration: ContainerConfiguration;\n taskTimeoutInMinutes?: number;\n cpu?: number;\n memory?: number;\n taskCommand?: string;\n monitoringConfiguration: NoMonitoring | GuEcsTaskMonitoringProps;\n securityGroups?: ISecurityGroup[];\n customTaskPolicies?: PolicyStatement[];\n environmentOverrides?: TaskEnvironmentVariable[];\n storage?: number;\n /**\n * Whether to give the task IAM role access to the account's dist bucket.\n * This is enabled by default to avoid breaking changes, but consumers of this pattern\n * that pull a container image that doesn't need extra dependencies from S3\n * shoud set this value to `false`.\n */\n enableDistributablePolicy?: boolean;\n\n /**\n * The CloudWatch Container Insights setting\n *\n * @see https://docs.aws.amazon.com/AmazonECS/latest/developerguide/cloudwatch-container-insights.html\n */\n containerInsights: ContainerInsights;\n}\n\n/**\n * Containers can be specified either via a repository and version or by container id (in which case it will\n * be fetched from docker hub).\n */\nconst getContainer = (config: ContainerConfiguration) => {\n if (config.type == \"repository\") {\n return ContainerImage.fromEcrRepository(config.repository, config.version);\n } else {\n return ContainerImage.fromRegistry(config.id ?? \"ubuntu:jammy\", config.imageProps);\n }\n};\n\n/**\n * Pattern which creates all of the resources needed for a fargate task\n *\n * The task will be wrapped in a step function to allow for easier triggering and alarming on failure.\n *\n * For all configuration options, see [[`GuEcsTaskProps`]].\n *\n * Note that if your task reliably completes in less than 15 minutes then you should probably use a [[`GuLambda`]] instead. This\n * pattern was mainly created to work around the 15 minute lambda timeout.\n *\n */\nexport class GuEcsTask extends Construct {\n public readonly stateMachine: StateMachine;\n public readonly taskDefinition: TaskDefinition;\n public readonly containerDefinition: ContainerDefinition;\n public readonly task: EcsRunTask;\n\n constructor(scope: GuStack, id: string, props: GuEcsTaskProps) {\n super(scope, id);\n\n const {\n app,\n\n // see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ecs-taskdefinition.html#cfn-ecs-taskdefinition-cpu for details\n cpu = 2048, // 2 cores and from 4-16GB memory\n memory = 4096, // 4GB\n storage, // default is 20 GB when not provided in props\n containerConfiguration,\n taskCommand,\n taskTimeoutInMinutes = 15,\n customTaskPolicies,\n vpc,\n subnets,\n monitoringConfiguration,\n securityGroups = [],\n environmentOverrides,\n enableDistributablePolicy = true,\n containerInsights,\n } = props;\n\n if (storage && storage < 21) {\n throw new Error(\n \"Storage must be at least 21. See https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ecs-taskdefinition-ephemeralstorage.html\",\n );\n }\n\n const { stack, stage } = scope;\n\n const cluster = new Cluster(scope, `${id}-Cluster`, {\n clusterName: `${app}-cluster-${stage}`,\n enableFargateCapacityProviders: true,\n vpc,\n containerInsightsV2: containerInsights,\n });\n\n const taskDefinition = new TaskDefinition(scope, `${id}-TaskDefinition`, {\n compatibility: Compatibility.FARGATE,\n cpu: cpu.toString(),\n memoryMiB: memory.toString(),\n family: `${stack}-${stage}-${app}`,\n ephemeralStorageGiB: storage,\n runtimePlatform: {\n cpuArchitecture: CpuArchitecture.ARM64,\n operatingSystemFamily: OperatingSystemFamily.of(\"LINUX\"),\n },\n });\n this.taskDefinition = taskDefinition;\n\n const containerDefinition = taskDefinition.addContainer(`${id}-TaskContainer`, {\n image: getContainer(containerConfiguration),\n entryPoint: taskCommand ? [\"/bin/sh\"] : undefined,\n command: taskCommand ? [\"-c\", taskCommand] : undefined, // if unset, falls back to CMD in docker file, or no command will be run\n cpu,\n memoryLimitMiB: memory,\n logging: LogDrivers.awsLogs({\n streamPrefix: app,\n logRetention: 14,\n }),\n readonlyRootFilesystem: true,\n });\n this.containerDefinition = containerDefinition;\n\n if (enableDistributablePolicy) {\n const distPolicy = new GuGetDistributablePolicyStatement(scope, { app });\n taskDefinition.addToTaskRolePolicy(distPolicy);\n }\n\n // these policies are needed for guard duty runtime monitoring\n // See https://docs.aws.amazon.com/guardduty/latest/ug/prereq-runtime-monitoring-ecs-support.html#before-enable-runtime-monitoring-ecs\n const getAuthTokenPolicy = new PolicyStatement({\n effect: Effect.ALLOW,\n actions: [\"ecr:GetAuthorizationToken\"],\n resources: [\"*\"],\n });\n const guardDutyContainerPolicy = new PolicyStatement({\n effect: Effect.ALLOW,\n actions: [\"ecr:BatchCheckLayerAvailability\", \"ecr:GetDownloadUrlForLayer\", \"ecr:BatchGetImage\"],\n // See https://docs.aws.amazon.com/guardduty/latest/ug/runtime-monitoring-ecr-repository-gdu-agent.html\n // note that if you are using a region other than eu-west-1 you'll need to add extra repositories here\n resources: [\"arn:aws:ecr:eu-west-1:694911143906:repository/aws-guardduty-agent-fargate\"],\n });\n\n taskDefinition.addToExecutionRolePolicy(getAuthTokenPolicy);\n taskDefinition.addToExecutionRolePolicy(guardDutyContainerPolicy);\n\n (customTaskPolicies ?? []).forEach((p) => taskDefinition.addToTaskRolePolicy(p));\n\n const task = new EcsRunTask(scope, `${id}-task`, {\n cluster,\n launchTarget: new EcsFargateLaunchTarget({\n platformVersion: FargatePlatformVersion.LATEST,\n }),\n taskDefinition,\n subnets: { subnets },\n assignPublicIp: false,\n integrationPattern: IntegrationPattern.RUN_JOB,\n resultPath: JsonPath.DISCARD,\n taskTimeout: Timeout.duration(Duration.minutes(taskTimeoutInMinutes)),\n securityGroups,\n containerOverrides: [\n {\n containerDefinition: containerDefinition,\n environment: environmentOverrides,\n },\n ],\n });\n this.task = task;\n\n this.stateMachine = new StateMachine(scope, `${id}-StateMachine`, {\n definitionBody: DefinitionBody.fromChainable(task),\n stateMachineName: `${app}-${stage}`,\n });\n\n if (!monitoringConfiguration.noMonitoring) {\n const alarmTopic = Topic.fromTopicArn(\n scope,\n AppIdentity.suffixText(props, \"AlarmTopic\"),\n monitoringConfiguration.snsTopicArn,\n );\n const alarms = [\n {\n name: `${app}-execution-failed`,\n description: `${app}-${stage} job failed `,\n metric: this.stateMachine.metricFailed({\n period: Duration.hours(1),\n statistic: \"sum\",\n }),\n },\n {\n name: `${app}-timeout`,\n description: `${app}-${stage} job timed out `,\n metric: this.stateMachine.metricTimedOut({\n period: Duration.hours(1),\n statistic: \"sum\",\n }),\n },\n ];\n\n alarms.forEach(({ name, description, metric }) => {\n const alarm = new Alarm(scope, name, {\n alarmDescription: description,\n actionsEnabled: true,\n metric: metric,\n // default for comparisonOperator is GreaterThanOrEqualToThreshold\n threshold: 1,\n evaluationPeriods: 1,\n treatMissingData: TreatMissingData.NOT_BREACHING,\n });\n alarm.addAlarmAction(new SnsAction(alarmTopic));\n AppIdentity.taggedConstruct({ app }, alarm);\n });\n }\n\n // Tag all constructs with correct app tag\n [cluster, task, taskDefinition, this.stateMachine].forEach((c) => AppIdentity.taggedConstruct({ app }, c));\n\n new CfnOutput(scope, `${id}-StateMachineArnOutput`, {\n value: this.stateMachine.stateMachineArn,\n });\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"anghammarad.js","sourceRoot":"","sources":["../../../../src/constructs/iam/policies/anghammarad.ts"],"names":[],"mappings":";;;AAAA,wDAAqE;AAErE,qCAAyD;AACzD,+CAA8C;AAE9C;;;;;;GAMG;AACH,MAAa,yBAA0B,SAAQ,2BAAa;IAG1D,YAAoB,KAAc;QAChC,MAAM,yBAAyB,GAAG,kCAA2B,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;QAEjF,KAAK,CAAC,KAAK,EAAE,2BAA2B,EAAE;YACxC,OAAO,EAAE,CAAC,aAAa,CAAC;YACxB,SAAS,EAAE,CAAC,yBAAyB,CAAC,aAAa,CAAC;SACrD,CAAC,CAAC;IACL,CAAC;IAEM,MAAM,CAAC,WAAW,CAAC,KAAc;QACtC,IAAI,CAAC,IAAI,CAAC,QAAQ,IAAI,CAAC,IAAA,qCAAyB,EAAC,KAAK,EAAE,IAAI,CAAC,QAAQ,CAAC,EAAE;YACtE,IAAI,CAAC,QAAQ,GAAG,IAAI,yBAAyB,CAAC,KAAK,CAAC,CAAC;SACtD;QAED,OAAO,IAAI,CAAC,QAAQ,CAAC;IACvB,CAAC;CACF;AAnBD,8DAmBC","sourcesContent":["import { isSingletonPresentInStack } from \"../../../utils/singleton\";\nimport type { GuStack } from \"../../core\";\nimport { GuAnghammaradTopicParameter } from \"../../core\";\nimport { GuAllowPolicy } from \"./base-policy\";\n\n/**\n * Creates an `AWS::IAM::Policy` to grant `sns:Publish` permission to the Anghammarad topic.\n * An `AnghammaradSnsArn` parameter will be automatically added to the stack when needed.\n *\n * @see GuAnghammaradTopicParameter\n * @see https://github.com/guardian/anghammarad\n */\nexport class GuAnghammaradSenderPolicy extends GuAllowPolicy {\n private static instance: GuAnghammaradSenderPolicy | undefined;\n\n private constructor(scope: GuStack) {\n const anghammaradTopicParameter = GuAnghammaradTopicParameter.getInstance(scope);\n\n super(scope, \"GuAnghammaradSenderPolicy\", {\n actions: [\"sns:Publish\"],\n resources: [anghammaradTopicParameter.valueAsString],\n });\n }\n\n public static getInstance(stack: GuStack): GuAnghammaradSenderPolicy {\n if (!this.instance || !isSingletonPresentInStack(stack, this.instance)) {\n this.instance = new GuAnghammaradSenderPolicy(stack);\n }\n\n return this.instance;\n }\n}\n"]}
1
+ {"version":3,"file":"anghammarad.js","sourceRoot":"","sources":["../../../../src/constructs/iam/policies/anghammarad.ts"],"names":[],"mappings":";;;AAAA,wDAAqE;AAErE,qCAAyD;AACzD,+CAA8C;AAE9C;;;;;;GAMG;AACH,MAAa,yBAA0B,SAAQ,2BAAa;IAG1D,YAAoB,KAAc;QAChC,MAAM,yBAAyB,GAAG,kCAA2B,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;QAEjF,KAAK,CAAC,KAAK,EAAE,2BAA2B,EAAE;YACxC,OAAO,EAAE,CAAC,aAAa,CAAC;YACxB,SAAS,EAAE,CAAC,yBAAyB,CAAC,aAAa,CAAC;SACrD,CAAC,CAAC;IACL,CAAC;IAEM,MAAM,CAAC,WAAW,CAAC,KAAc;QACtC,IAAI,CAAC,IAAI,CAAC,QAAQ,IAAI,CAAC,IAAA,qCAAyB,EAAC,KAAK,EAAE,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;YACvE,IAAI,CAAC,QAAQ,GAAG,IAAI,yBAAyB,CAAC,KAAK,CAAC,CAAC;QACvD,CAAC;QAED,OAAO,IAAI,CAAC,QAAQ,CAAC;IACvB,CAAC;CACF;AAnBD,8DAmBC","sourcesContent":["import { isSingletonPresentInStack } from \"../../../utils/singleton\";\nimport type { GuStack } from \"../../core\";\nimport { GuAnghammaradTopicParameter } from \"../../core\";\nimport { GuAllowPolicy } from \"./base-policy\";\n\n/**\n * Creates an `AWS::IAM::Policy` to grant `sns:Publish` permission to the Anghammarad topic.\n * An `AnghammaradSnsArn` parameter will be automatically added to the stack when needed.\n *\n * @see GuAnghammaradTopicParameter\n * @see https://github.com/guardian/anghammarad\n */\nexport class GuAnghammaradSenderPolicy extends GuAllowPolicy {\n private static instance: GuAnghammaradSenderPolicy | undefined;\n\n private constructor(scope: GuStack) {\n const anghammaradTopicParameter = GuAnghammaradTopicParameter.getInstance(scope);\n\n super(scope, \"GuAnghammaradSenderPolicy\", {\n actions: [\"sns:Publish\"],\n resources: [anghammaradTopicParameter.valueAsString],\n });\n }\n\n public static getInstance(stack: GuStack): GuAnghammaradSenderPolicy {\n if (!this.instance || !isSingletonPresentInStack(stack, this.instance)) {\n this.instance = new GuAnghammaradSenderPolicy(stack);\n }\n\n return this.instance;\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"describe-ec2.js","sourceRoot":"","sources":["../../../../src/constructs/iam/policies/describe-ec2.ts"],"names":[],"mappings":";;;AAAA,iDAA8D;AAC9D,wDAAqE;AAErE,+CAAyC;AAEzC,MAAa,mBAAoB,SAAQ,sBAAQ;IAG/C,YAAoB,KAAc;QAChC,KAAK,CAAC,KAAK,EAAE,mBAAmB,EAAE;YAChC,UAAU,EAAE,qBAAqB;YACjC,UAAU,EAAE;gBACV,IAAI,yBAAe,CAAC;oBAClB,MAAM,EAAE,gBAAM,CAAC,KAAK;oBACpB,OAAO,EAAE;wBACP,0CAA0C;wBAC1C,uCAAuC;wBACvC,kBAAkB;wBAClB,uBAAuB;qBACxB;oBACD,SAAS,EAAE,CAAC,GAAG,CAAC;iBACjB,CAAC;aACH;SACF,CAAC,CAAC;IACL,CAAC;IAEM,MAAM,CAAC,WAAW,CAAC,KAAc;QACtC,IAAI,CAAC,IAAI,CAAC,QAAQ,IAAI,CAAC,IAAA,qCAAyB,EAAC,KAAK,EAAE,IAAI,CAAC,QAAQ,CAAC,EAAE;YACtE,IAAI,CAAC,QAAQ,GAAG,IAAI,mBAAmB,CAAC,KAAK,CAAC,CAAC;SAChD;QAED,OAAO,IAAI,CAAC,QAAQ,CAAC;IACvB,CAAC;CACF;AA5BD,kDA4BC","sourcesContent":["import { Effect, PolicyStatement } from \"aws-cdk-lib/aws-iam\";\nimport { isSingletonPresentInStack } from \"../../../utils/singleton\";\nimport type { GuStack } from \"../../core\";\nimport { GuPolicy } from \"./base-policy\";\n\nexport class GuDescribeEC2Policy extends GuPolicy {\n private static instance: GuPolicy | undefined;\n\n private constructor(scope: GuStack) {\n super(scope, \"DescribeEC2Policy\", {\n policyName: \"describe-ec2-policy\",\n statements: [\n new PolicyStatement({\n effect: Effect.ALLOW,\n actions: [\n \"autoscaling:DescribeAutoScalingInstances\",\n \"autoscaling:DescribeAutoScalingGroups\",\n \"ec2:DescribeTags\",\n \"ec2:DescribeInstances\",\n ],\n resources: [\"*\"],\n }),\n ],\n });\n }\n\n public static getInstance(stack: GuStack): GuDescribeEC2Policy {\n if (!this.instance || !isSingletonPresentInStack(stack, this.instance)) {\n this.instance = new GuDescribeEC2Policy(stack);\n }\n\n return this.instance;\n }\n}\n"]}
1
+ {"version":3,"file":"describe-ec2.js","sourceRoot":"","sources":["../../../../src/constructs/iam/policies/describe-ec2.ts"],"names":[],"mappings":";;;AAAA,iDAA8D;AAC9D,wDAAqE;AAErE,+CAAyC;AAEzC,MAAa,mBAAoB,SAAQ,sBAAQ;IAG/C,YAAoB,KAAc;QAChC,KAAK,CAAC,KAAK,EAAE,mBAAmB,EAAE;YAChC,UAAU,EAAE,qBAAqB;YACjC,UAAU,EAAE;gBACV,IAAI,yBAAe,CAAC;oBAClB,MAAM,EAAE,gBAAM,CAAC,KAAK;oBACpB,OAAO,EAAE;wBACP,0CAA0C;wBAC1C,uCAAuC;wBACvC,kBAAkB;wBAClB,uBAAuB;qBACxB;oBACD,SAAS,EAAE,CAAC,GAAG,CAAC;iBACjB,CAAC;aACH;SACF,CAAC,CAAC;IACL,CAAC;IAEM,MAAM,CAAC,WAAW,CAAC,KAAc;QACtC,IAAI,CAAC,IAAI,CAAC,QAAQ,IAAI,CAAC,IAAA,qCAAyB,EAAC,KAAK,EAAE,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;YACvE,IAAI,CAAC,QAAQ,GAAG,IAAI,mBAAmB,CAAC,KAAK,CAAC,CAAC;QACjD,CAAC;QAED,OAAO,IAAI,CAAC,QAAQ,CAAC;IACvB,CAAC;CACF;AA5BD,kDA4BC","sourcesContent":["import { Effect, PolicyStatement } from \"aws-cdk-lib/aws-iam\";\nimport { isSingletonPresentInStack } from \"../../../utils/singleton\";\nimport type { GuStack } from \"../../core\";\nimport { GuPolicy } from \"./base-policy\";\n\nexport class GuDescribeEC2Policy extends GuPolicy {\n private static instance: GuPolicy | undefined;\n\n private constructor(scope: GuStack) {\n super(scope, \"DescribeEC2Policy\", {\n policyName: \"describe-ec2-policy\",\n statements: [\n new PolicyStatement({\n effect: Effect.ALLOW,\n actions: [\n \"autoscaling:DescribeAutoScalingInstances\",\n \"autoscaling:DescribeAutoScalingGroups\",\n \"ec2:DescribeTags\",\n \"ec2:DescribeInstances\",\n ],\n resources: [\"*\"],\n }),\n ],\n });\n }\n\n public static getInstance(stack: GuStack): GuDescribeEC2Policy {\n if (!this.instance || !isSingletonPresentInStack(stack, this.instance)) {\n this.instance = new GuDescribeEC2Policy(stack);\n }\n\n return this.instance;\n }\n}\n"]}
@@ -14,7 +14,7 @@ const kinesisActions = [
14
14
  const kinesisEnhancedFanOutActions = ["SubscribeToShard", "DescribeStreamConsumer"];
15
15
  const actionsOnAllTables = [
16
16
  "Scan",
17
- "CreateTable",
17
+ "CreateTable", // Allow KCL creating the lease, metrics, and coordinator tables - see https://github.com/guardian/cdk/pull/2578#discussion_r1954061397
18
18
  "DescribeTable",
19
19
  "GetItem",
20
20
  "PutItem",
@@ -1 +1 @@
1
- {"version":3,"file":"kcl.js","sourceRoot":"","sources":["../../../../src/constructs/iam/policies/kcl.ts"],"names":[],"mappings":";;;AAAA,iDAA8D;AAE9D,+CAAyC;AAOzC,MAAM,cAAc,GAAa;IAC/B,gBAAgB;IAChB,uBAAuB;IACvB,wBAAwB;IACxB,YAAY;IACZ,kBAAkB;IAClB,YAAY;CACb,CAAC;AAEF,MAAM,4BAA4B,GAAa,CAAC,kBAAkB,EAAE,wBAAwB,CAAC,CAAC;AAE9F,MAAM,kBAAkB,GAAa;IACnC,MAAM;IACN,aAAa;IACb,eAAe;IACf,SAAS;IACT,SAAS;IACT,YAAY;IACZ,YAAY;CACb,CAAC;AAEF,MAAM,2BAA2B,GAAa,CAAC,aAAa,CAAC,CAAC;AAE9D;;;;;;GAMG;AACH,MAAa,WAAY,SAAQ,sBAAQ;IACvC,YAAY,KAAc,EAAE,EAAU,EAAE,KAAqB;QAC3D,SAAS,KAAK,CAAC,UAAkB,EAAE,OAAiB,EAAE,SAAmB;YACvE,OAAO,IAAI,yBAAe,CAAC;gBACzB,MAAM,EAAE,gBAAM,CAAC,KAAK;gBACpB,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,UAAU,IAAI,CAAC,EAAE,CAAC;gBACjD,SAAS,EAAE,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,WAAW,UAAU,IAAI,KAAK,CAAC,MAAM,IAAI,KAAK,CAAC,OAAO,IAAI,CAAC,EAAE,CAAC;aAC/F,CAAC,CAAC;QACL,CAAC;QAED,SAAS,aAAa,CAAC,OAAiB,EAAE,iBAA2B;YACnE,OAAO,KAAK,CACV,UAAU,EACV,OAAO,EACP,iBAAiB,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,SAAS,IAAI,EAAE,CAAC,CACjD,CAAC;QACJ,CAAC;QAED,MAAM,UAAU,GAAG,KAAK,CAAC,eAAe,CAAC;QACzC,MAAM,YAAY,GAAG,GAAG,KAAK,CAAC,eAAe,oBAAoB,CAAC;QAClE,MAAM,gBAAgB,GAAG,GAAG,KAAK,CAAC,eAAe,mBAAmB,CAAC;QAErE,KAAK,CAAC,KAAK,EAAE,EAAE,EAAE;YACf,UAAU,EAAE;gBACV,KAAK,CAAC,SAAS,EAAE,cAAc,EAAE,CAAC,UAAU,KAAK,CAAC,UAAU,EAAE,CAAC,CAAC;gBAChE,KAAK,CAAC,SAAS,EAAE,4BAA4B,EAAE,CAAC,UAAU,KAAK,CAAC,UAAU,aAAa,CAAC,CAAC;gBACzF,aAAa,CAAC,kBAAkB,EAAE,CAAC,UAAU,EAAE,YAAY,EAAE,gBAAgB,CAAC,CAAC;gBAC/E,aAAa,CAAC,2BAA2B,EAAE,CAAC,UAAU,CAAC,CAAC;gBACxD,aAAa,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,GAAG,UAAU,UAAU,CAAC,CAAC;gBACnD,KAAK,CAAC,YAAY,EAAE,CAAC,eAAe,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC;aAC9C;SACF,CAAC,CAAC;IACL,CAAC;CACF;AAjCD,kCAiCC","sourcesContent":["import { Effect, PolicyStatement } from \"aws-cdk-lib/aws-iam\";\nimport type { GuStack } from \"../../core\";\nimport { GuPolicy } from \"./base-policy\";\n\nexport interface KCLApplication {\n streamName: string;\n applicationName: string;\n}\n\nconst kinesisActions: string[] = [\n \"DescribeStream\",\n \"DescribeStreamSummary\",\n \"RegisterStreamConsumer\",\n \"GetRecords\",\n \"GetShardIterator\",\n \"ListShards\",\n];\n\nconst kinesisEnhancedFanOutActions: string[] = [\"SubscribeToShard\", \"DescribeStreamConsumer\"];\n\nconst actionsOnAllTables: string[] = [\n \"Scan\",\n \"CreateTable\", // Allow KCL creating the lease, metrics, and coordinator tables - see https://github.com/guardian/cdk/pull/2578#discussion_r1954061397\n \"DescribeTable\",\n \"GetItem\",\n \"PutItem\",\n \"UpdateItem\",\n \"DeleteItem\",\n];\n\nconst additionalLeaseTableActions: string[] = [\"UpdateTable\"];\n\n/**\n * Creates an `AWS::IAM::Policy` to grant all the required permissions for the Kinesis Client Library\n * (https://github.com/awslabs/amazon-kinesis-client) - specifically for KCL v3, which requires many\n * additional permissions over KCL v2.\n *\n * @see https://docs.aws.amazon.com/streams/latest/dev/kcl-iam-permissions.html\n */\nexport class GuKCLPolicy extends GuPolicy {\n constructor(scope: GuStack, id: string, props: KCLApplication) {\n function allow(actionType: string, actions: string[], resources: string[]): PolicyStatement {\n return new PolicyStatement({\n effect: Effect.ALLOW,\n actions: actions.map((a) => `${actionType}:${a}`),\n resources: resources.map((r) => `arn:aws:${actionType}:${scope.region}:${scope.account}:${r}`),\n });\n }\n\n function allowDynamoDB(actions: string[], tableOrIndexNames: string[]): PolicyStatement {\n return allow(\n \"dynamodb\",\n actions,\n tableOrIndexNames.map((name) => `table/${name}`),\n );\n }\n\n const leaseTable = props.applicationName;\n const metricsTable = `${props.applicationName}-WorkerMetricStats`;\n const coordinatorTable = `${props.applicationName}-CoordinatorState`;\n\n super(scope, id, {\n statements: [\n allow(\"kinesis\", kinesisActions, [`stream/${props.streamName}`]),\n allow(\"kinesis\", kinesisEnhancedFanOutActions, [`stream/${props.streamName}/consumer/*`]),\n allowDynamoDB(actionsOnAllTables, [leaseTable, metricsTable, coordinatorTable]),\n allowDynamoDB(additionalLeaseTableActions, [leaseTable]),\n allowDynamoDB([\"Query\"], [`${leaseTable}/index/*`]),\n allow(\"cloudwatch\", [\"PutMetricData\"], [\"*\"]),\n ],\n });\n }\n}\n"]}
1
+ {"version":3,"file":"kcl.js","sourceRoot":"","sources":["../../../../src/constructs/iam/policies/kcl.ts"],"names":[],"mappings":";;;AAAA,iDAA8D;AAE9D,+CAAyC;AAOzC,MAAM,cAAc,GAAa;IAC/B,gBAAgB;IAChB,uBAAuB;IACvB,wBAAwB;IACxB,YAAY;IACZ,kBAAkB;IAClB,YAAY;CACb,CAAC;AAEF,MAAM,4BAA4B,GAAa,CAAC,kBAAkB,EAAE,wBAAwB,CAAC,CAAC;AAE9F,MAAM,kBAAkB,GAAa;IACnC,MAAM;IACN,aAAa,EAAE,uIAAuI;IACtJ,eAAe;IACf,SAAS;IACT,SAAS;IACT,YAAY;IACZ,YAAY;CACb,CAAC;AAEF,MAAM,2BAA2B,GAAa,CAAC,aAAa,CAAC,CAAC;AAE9D;;;;;;GAMG;AACH,MAAa,WAAY,SAAQ,sBAAQ;IACvC,YAAY,KAAc,EAAE,EAAU,EAAE,KAAqB;QAC3D,SAAS,KAAK,CAAC,UAAkB,EAAE,OAAiB,EAAE,SAAmB;YACvE,OAAO,IAAI,yBAAe,CAAC;gBACzB,MAAM,EAAE,gBAAM,CAAC,KAAK;gBACpB,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,UAAU,IAAI,CAAC,EAAE,CAAC;gBACjD,SAAS,EAAE,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,WAAW,UAAU,IAAI,KAAK,CAAC,MAAM,IAAI,KAAK,CAAC,OAAO,IAAI,CAAC,EAAE,CAAC;aAC/F,CAAC,CAAC;QACL,CAAC;QAED,SAAS,aAAa,CAAC,OAAiB,EAAE,iBAA2B;YACnE,OAAO,KAAK,CACV,UAAU,EACV,OAAO,EACP,iBAAiB,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,SAAS,IAAI,EAAE,CAAC,CACjD,CAAC;QACJ,CAAC;QAED,MAAM,UAAU,GAAG,KAAK,CAAC,eAAe,CAAC;QACzC,MAAM,YAAY,GAAG,GAAG,KAAK,CAAC,eAAe,oBAAoB,CAAC;QAClE,MAAM,gBAAgB,GAAG,GAAG,KAAK,CAAC,eAAe,mBAAmB,CAAC;QAErE,KAAK,CAAC,KAAK,EAAE,EAAE,EAAE;YACf,UAAU,EAAE;gBACV,KAAK,CAAC,SAAS,EAAE,cAAc,EAAE,CAAC,UAAU,KAAK,CAAC,UAAU,EAAE,CAAC,CAAC;gBAChE,KAAK,CAAC,SAAS,EAAE,4BAA4B,EAAE,CAAC,UAAU,KAAK,CAAC,UAAU,aAAa,CAAC,CAAC;gBACzF,aAAa,CAAC,kBAAkB,EAAE,CAAC,UAAU,EAAE,YAAY,EAAE,gBAAgB,CAAC,CAAC;gBAC/E,aAAa,CAAC,2BAA2B,EAAE,CAAC,UAAU,CAAC,CAAC;gBACxD,aAAa,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,GAAG,UAAU,UAAU,CAAC,CAAC;gBACnD,KAAK,CAAC,YAAY,EAAE,CAAC,eAAe,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC;aAC9C;SACF,CAAC,CAAC;IACL,CAAC;CACF;AAjCD,kCAiCC","sourcesContent":["import { Effect, PolicyStatement } from \"aws-cdk-lib/aws-iam\";\nimport type { GuStack } from \"../../core\";\nimport { GuPolicy } from \"./base-policy\";\n\nexport interface KCLApplication {\n streamName: string;\n applicationName: string;\n}\n\nconst kinesisActions: string[] = [\n \"DescribeStream\",\n \"DescribeStreamSummary\",\n \"RegisterStreamConsumer\",\n \"GetRecords\",\n \"GetShardIterator\",\n \"ListShards\",\n];\n\nconst kinesisEnhancedFanOutActions: string[] = [\"SubscribeToShard\", \"DescribeStreamConsumer\"];\n\nconst actionsOnAllTables: string[] = [\n \"Scan\",\n \"CreateTable\", // Allow KCL creating the lease, metrics, and coordinator tables - see https://github.com/guardian/cdk/pull/2578#discussion_r1954061397\n \"DescribeTable\",\n \"GetItem\",\n \"PutItem\",\n \"UpdateItem\",\n \"DeleteItem\",\n];\n\nconst additionalLeaseTableActions: string[] = [\"UpdateTable\"];\n\n/**\n * Creates an `AWS::IAM::Policy` to grant all the required permissions for the Kinesis Client Library\n * (https://github.com/awslabs/amazon-kinesis-client) - specifically for KCL v3, which requires many\n * additional permissions over KCL v2.\n *\n * @see https://docs.aws.amazon.com/streams/latest/dev/kcl-iam-permissions.html\n */\nexport class GuKCLPolicy extends GuPolicy {\n constructor(scope: GuStack, id: string, props: KCLApplication) {\n function allow(actionType: string, actions: string[], resources: string[]): PolicyStatement {\n return new PolicyStatement({\n effect: Effect.ALLOW,\n actions: actions.map((a) => `${actionType}:${a}`),\n resources: resources.map((r) => `arn:aws:${actionType}:${scope.region}:${scope.account}:${r}`),\n });\n }\n\n function allowDynamoDB(actions: string[], tableOrIndexNames: string[]): PolicyStatement {\n return allow(\n \"dynamodb\",\n actions,\n tableOrIndexNames.map((name) => `table/${name}`),\n );\n }\n\n const leaseTable = props.applicationName;\n const metricsTable = `${props.applicationName}-WorkerMetricStats`;\n const coordinatorTable = `${props.applicationName}-CoordinatorState`;\n\n super(scope, id, {\n statements: [\n allow(\"kinesis\", kinesisActions, [`stream/${props.streamName}`]),\n allow(\"kinesis\", kinesisEnhancedFanOutActions, [`stream/${props.streamName}/consumer/*`]),\n allowDynamoDB(actionsOnAllTables, [leaseTable, metricsTable, coordinatorTable]),\n allowDynamoDB(additionalLeaseTableActions, [leaseTable]),\n allowDynamoDB([\"Query\"], [`${leaseTable}/index/*`]),\n allow(\"cloudwatch\", [\"PutMetricData\"], [\"*\"]),\n ],\n });\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"log-shipping.js","sourceRoot":"","sources":["../../../../src/constructs/iam/policies/log-shipping.ts"],"names":[],"mappings":";;;AAAA,wDAAqE;AAErE,qCAA0D;AAC1D,+CAA8C;AAE9C,MAAa,mBAAoB,SAAQ,2BAAa;IAGpD,YAAoB,KAAc;QAChC,KAAK,CAAC,KAAK,EAAE,qBAAqB,EAAE;YAClC,OAAO,EAAE,CAAC,mBAAmB,EAAE,cAAc,CAAC;YAC9C,SAAS,EAAE;gBACT,mBAAmB,KAAK,CAAC,MAAM,IAAI,KAAK,CAAC,OAAO,WAC9C,mCAA4B,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,aAClD,EAAE;aACH;SACF,CAAC,CAAC;IACL,CAAC;IAEM,MAAM,CAAC,WAAW,CAAC,KAAc;QACtC,IAAI,CAAC,IAAI,CAAC,QAAQ,IAAI,CAAC,IAAA,qCAAyB,EAAC,KAAK,EAAE,IAAI,CAAC,QAAQ,CAAC,EAAE;YACtE,IAAI,CAAC,QAAQ,GAAG,IAAI,mBAAmB,CAAC,KAAK,CAAC,CAAC;SAChD;QAED,OAAO,IAAI,CAAC,QAAQ,CAAC;IACvB,CAAC;CACF;AArBD,kDAqBC","sourcesContent":["import { isSingletonPresentInStack } from \"../../../utils/singleton\";\nimport type { GuStack } from \"../../core\";\nimport { GuLoggingStreamNameParameter } from \"../../core\";\nimport { GuAllowPolicy } from \"./base-policy\";\n\nexport class GuLogShippingPolicy extends GuAllowPolicy {\n private static instance: GuLogShippingPolicy | undefined;\n\n private constructor(scope: GuStack) {\n super(scope, \"GuLogShippingPolicy\", {\n actions: [\"kinesis:Describe*\", \"kinesis:Put*\"],\n resources: [\n `arn:aws:kinesis:${scope.region}:${scope.account}:stream/${\n GuLoggingStreamNameParameter.getInstance(scope).valueAsString\n }`,\n ],\n });\n }\n\n public static getInstance(stack: GuStack): GuLogShippingPolicy {\n if (!this.instance || !isSingletonPresentInStack(stack, this.instance)) {\n this.instance = new GuLogShippingPolicy(stack);\n }\n\n return this.instance;\n }\n}\n"]}
1
+ {"version":3,"file":"log-shipping.js","sourceRoot":"","sources":["../../../../src/constructs/iam/policies/log-shipping.ts"],"names":[],"mappings":";;;AAAA,wDAAqE;AAErE,qCAA0D;AAC1D,+CAA8C;AAE9C,MAAa,mBAAoB,SAAQ,2BAAa;IAGpD,YAAoB,KAAc;QAChC,KAAK,CAAC,KAAK,EAAE,qBAAqB,EAAE;YAClC,OAAO,EAAE,CAAC,mBAAmB,EAAE,cAAc,CAAC;YAC9C,SAAS,EAAE;gBACT,mBAAmB,KAAK,CAAC,MAAM,IAAI,KAAK,CAAC,OAAO,WAC9C,mCAA4B,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,aAClD,EAAE;aACH;SACF,CAAC,CAAC;IACL,CAAC;IAEM,MAAM,CAAC,WAAW,CAAC,KAAc;QACtC,IAAI,CAAC,IAAI,CAAC,QAAQ,IAAI,CAAC,IAAA,qCAAyB,EAAC,KAAK,EAAE,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;YACvE,IAAI,CAAC,QAAQ,GAAG,IAAI,mBAAmB,CAAC,KAAK,CAAC,CAAC;QACjD,CAAC;QAED,OAAO,IAAI,CAAC,QAAQ,CAAC;IACvB,CAAC;CACF;AArBD,kDAqBC","sourcesContent":["import { isSingletonPresentInStack } from \"../../../utils/singleton\";\nimport type { GuStack } from \"../../core\";\nimport { GuLoggingStreamNameParameter } from \"../../core\";\nimport { GuAllowPolicy } from \"./base-policy\";\n\nexport class GuLogShippingPolicy extends GuAllowPolicy {\n private static instance: GuLogShippingPolicy | undefined;\n\n private constructor(scope: GuStack) {\n super(scope, \"GuLogShippingPolicy\", {\n actions: [\"kinesis:Describe*\", \"kinesis:Put*\"],\n resources: [\n `arn:aws:kinesis:${scope.region}:${scope.account}:stream/${\n GuLoggingStreamNameParameter.getInstance(scope).valueAsString\n }`,\n ],\n });\n }\n\n public static getInstance(stack: GuStack): GuLogShippingPolicy {\n if (!this.instance || !isSingletonPresentInStack(stack, this.instance)) {\n this.instance = new GuLogShippingPolicy(stack);\n }\n\n return this.instance;\n }\n}\n"]}
@@ -26,7 +26,14 @@ declare const GuParameterStoreReadPolicy_base: {
26
26
  * configuration. See [[`ReadParametersByPath`]] and [[`ReadParametersByName`]] for more details.
27
27
  */
28
28
  export declare class GuParameterStoreReadPolicy extends GuParameterStoreReadPolicy_base {
29
- constructor(scope: GuStack, props: AppIdentity);
29
+ /**
30
+ * A record of existing instances of this construct, per {@link GuStack}.
31
+ * This allows us to implement singleton like behaviour.
32
+ * @private
33
+ */
34
+ private static instances;
35
+ private constructor();
36
+ static getInstance(stack: GuStack, props: AppIdentity): GuParameterStoreReadPolicy;
30
37
  }
31
38
  export {};
32
39
  //# sourceMappingURL=parameter-store-read.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"parameter-store-read.d.ts","sourceRoot":"","sources":["../../../../src/constructs/iam/policies/parameter-store-read.ts"],"names":[],"mappings":"AAAA,OAAO,EAAU,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAE9D,OAAO,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AACvD,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAEzC;;;GAGG;AACH,qBAAa,oBAAqB,SAAQ,eAAe;gBAC3C,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,WAAW;CAO/C;AAED;;;;GAIG;AACH,qBAAa,oBAAqB,SAAQ,eAAe;gBAC3C,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,WAAW;CAS/C;;;;;;AACD;;;GAGG;AACH,qBAAa,0BAA2B,SAAQ,+BAA6B;gBAC/D,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,WAAW;CAO/C"}
1
+ {"version":3,"file":"parameter-store-read.d.ts","sourceRoot":"","sources":["../../../../src/constructs/iam/policies/parameter-store-read.ts"],"names":[],"mappings":"AAAA,OAAO,EAAU,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAE9D,OAAO,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AACvD,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAEzC;;;GAGG;AACH,qBAAa,oBAAqB,SAAQ,eAAe;gBAC3C,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,WAAW;CAO/C;AAED;;;;GAIG;AACH,qBAAa,oBAAqB,SAAQ,eAAe;gBAC3C,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,WAAW;CAS/C;;;;;;AACD;;;GAGG;AACH,qBAAa,0BAA2B,SAAQ,+BAA6B;IAC3E;;;;OAIG;IACH,OAAO,CAAC,MAAM,CAAC,SAAS,CAAoE;IAE5F,OAAO;WAQO,WAAW,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,WAAW,GAAG,0BAA0B;CAiB1F"}
@@ -47,6 +47,27 @@ class GuParameterStoreReadPolicy extends (0, app_aware_construct_1.GuAppAwareCon
47
47
  ...props,
48
48
  });
49
49
  }
50
+ static getInstance(stack, props) {
51
+ const maybeStackInstances = this.instances.get(stack);
52
+ if (!maybeStackInstances) {
53
+ const instance = new GuParameterStoreReadPolicy(stack, props);
54
+ this.instances.set(stack, new Map([[props.app, instance]]));
55
+ return instance;
56
+ }
57
+ const maybeInstance = maybeStackInstances.get(props.app);
58
+ if (!maybeInstance) {
59
+ const instance = new GuParameterStoreReadPolicy(stack, props);
60
+ this.instances.set(stack, maybeStackInstances.set(props.app, instance));
61
+ return instance;
62
+ }
63
+ return maybeInstance;
64
+ }
50
65
  }
51
66
  exports.GuParameterStoreReadPolicy = GuParameterStoreReadPolicy;
67
+ /**
68
+ * A record of existing instances of this construct, per {@link GuStack}.
69
+ * This allows us to implement singleton like behaviour.
70
+ * @private
71
+ */
72
+ GuParameterStoreReadPolicy.instances = new Map();
52
73
  //# sourceMappingURL=parameter-store-read.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"parameter-store-read.js","sourceRoot":"","sources":["../../../../src/constructs/iam/policies/parameter-store-read.ts"],"names":[],"mappings":";;;AAAA,iDAA8D;AAC9D,kFAA+E;AAE/E,+CAAyC;AAEzC;;;GAGG;AACH,MAAa,oBAAqB,SAAQ,yBAAe;IACvD,YAAY,KAAc,EAAE,KAAkB;QAC5C,KAAK,CAAC;YACJ,MAAM,EAAE,gBAAM,CAAC,KAAK;YACpB,OAAO,EAAE,CAAC,yBAAyB,CAAC;YACpC,SAAS,EAAE,CAAC,eAAe,KAAK,CAAC,MAAM,IAAI,KAAK,CAAC,OAAO,cAAc,KAAK,CAAC,KAAK,IAAI,KAAK,CAAC,KAAK,IAAI,KAAK,CAAC,GAAG,EAAE,CAAC;SACjH,CAAC,CAAC;IACL,CAAC;CACF;AARD,oDAQC;AAED;;;;GAIG;AACH,MAAa,oBAAqB,SAAQ,yBAAe;IACvD,YAAY,KAAc,EAAE,KAAkB;QAC5C,KAAK,CAAC;YACJ,MAAM,EAAE,gBAAM,CAAC,KAAK;YACpB,OAAO,EAAE,CAAC,mBAAmB,EAAE,kBAAkB,CAAC;YAClD,SAAS,EAAE;gBACT,eAAe,KAAK,CAAC,MAAM,IAAI,KAAK,CAAC,OAAO,cAAc,KAAK,CAAC,KAAK,IAAI,KAAK,CAAC,KAAK,IAAI,KAAK,CAAC,GAAG,IAAI;aACtG;SACF,CAAC,CAAC;IACL,CAAC;CACF;AAVD,oDAUC;AACD;;;GAGG;AACH,MAAa,0BAA2B,SAAQ,IAAA,yCAAmB,EAAC,sBAAQ,CAAC;IAC3E,YAAY,KAAc,EAAE,KAAkB;QAC5C,KAAK,CAAC,KAAK,EAAE,oBAAoB,EAAE;YACjC,UAAU,EAAE,6BAA6B;YACzC,UAAU,EAAE,CAAC,IAAI,oBAAoB,CAAC,KAAK,EAAE,KAAK,CAAC,EAAE,IAAI,oBAAoB,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;YAC5F,GAAG,KAAK;SACT,CAAC,CAAC;IACL,CAAC;CACF;AARD,gEAQC","sourcesContent":["import { Effect, PolicyStatement } from \"aws-cdk-lib/aws-iam\";\nimport { GuAppAwareConstruct } from \"../../../utils/mixin/app-aware-construct\";\nimport type { AppIdentity, GuStack } from \"../../core\";\nimport { GuPolicy } from \"./base-policy\";\n\n/**\n * This is helpful for reading all private configuration for a given app. For example, the\n * [simple-configuration](https://github.com/guardian/simple-configuration) library requires these permissions.\n */\nexport class ReadParametersByPath extends PolicyStatement {\n constructor(scope: GuStack, props: AppIdentity) {\n super({\n effect: Effect.ALLOW,\n actions: [\"ssm:GetParametersByPath\"],\n resources: [`arn:aws:ssm:${scope.region}:${scope.account}:parameter/${scope.stage}/${scope.stack}/${props.app}`],\n });\n }\n}\n\n/**\n * This is helpful for accessing specific pieces of private configuration. For example, the\n * [play-secret-rotation](https://github.com/guardian/play-secret-rotation) library requires `ssm:GetParameters`\n * permissions.\n */\nexport class ReadParametersByName extends PolicyStatement {\n constructor(scope: GuStack, props: AppIdentity) {\n super({\n effect: Effect.ALLOW,\n actions: [\"ssm:GetParameters\", \"ssm:GetParameter\"],\n resources: [\n `arn:aws:ssm:${scope.region}:${scope.account}:parameter/${scope.stage}/${scope.stack}/${props.app}/*`,\n ],\n });\n }\n}\n/**\n * Grants read-only permissions for Parameter Store. These permissions are typically used for accessing private\n * configuration. See [[`ReadParametersByPath`]] and [[`ReadParametersByName`]] for more details.\n */\nexport class GuParameterStoreReadPolicy extends GuAppAwareConstruct(GuPolicy) {\n constructor(scope: GuStack, props: AppIdentity) {\n super(scope, \"ParameterStoreRead\", {\n policyName: \"parameter-store-read-policy\",\n statements: [new ReadParametersByPath(scope, props), new ReadParametersByName(scope, props)],\n ...props,\n });\n }\n}\n"]}
1
+ {"version":3,"file":"parameter-store-read.js","sourceRoot":"","sources":["../../../../src/constructs/iam/policies/parameter-store-read.ts"],"names":[],"mappings":";;;AAAA,iDAA8D;AAC9D,kFAA+E;AAE/E,+CAAyC;AAEzC;;;GAGG;AACH,MAAa,oBAAqB,SAAQ,yBAAe;IACvD,YAAY,KAAc,EAAE,KAAkB;QAC5C,KAAK,CAAC;YACJ,MAAM,EAAE,gBAAM,CAAC,KAAK;YACpB,OAAO,EAAE,CAAC,yBAAyB,CAAC;YACpC,SAAS,EAAE,CAAC,eAAe,KAAK,CAAC,MAAM,IAAI,KAAK,CAAC,OAAO,cAAc,KAAK,CAAC,KAAK,IAAI,KAAK,CAAC,KAAK,IAAI,KAAK,CAAC,GAAG,EAAE,CAAC;SACjH,CAAC,CAAC;IACL,CAAC;CACF;AARD,oDAQC;AAED;;;;GAIG;AACH,MAAa,oBAAqB,SAAQ,yBAAe;IACvD,YAAY,KAAc,EAAE,KAAkB;QAC5C,KAAK,CAAC;YACJ,MAAM,EAAE,gBAAM,CAAC,KAAK;YACpB,OAAO,EAAE,CAAC,mBAAmB,EAAE,kBAAkB,CAAC;YAClD,SAAS,EAAE;gBACT,eAAe,KAAK,CAAC,MAAM,IAAI,KAAK,CAAC,OAAO,cAAc,KAAK,CAAC,KAAK,IAAI,KAAK,CAAC,KAAK,IAAI,KAAK,CAAC,GAAG,IAAI;aACtG;SACF,CAAC,CAAC;IACL,CAAC;CACF;AAVD,oDAUC;AACD;;;GAGG;AACH,MAAa,0BAA2B,SAAQ,IAAA,yCAAmB,EAAC,sBAAQ,CAAC;IAQ3E,YAAoB,KAAc,EAAE,KAAkB;QACpD,KAAK,CAAC,KAAK,EAAE,oBAAoB,EAAE;YACjC,UAAU,EAAE,6BAA6B;YACzC,UAAU,EAAE,CAAC,IAAI,oBAAoB,CAAC,KAAK,EAAE,KAAK,CAAC,EAAE,IAAI,oBAAoB,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;YAC5F,GAAG,KAAK;SACT,CAAC,CAAC;IACL,CAAC;IAEM,MAAM,CAAC,WAAW,CAAC,KAAc,EAAE,KAAkB;QAC1D,MAAM,mBAAmB,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QACtD,IAAI,CAAC,mBAAmB,EAAE,CAAC;YACzB,MAAM,QAAQ,GAAG,IAAI,0BAA0B,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;YAC9D,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;YAC5D,OAAO,QAAQ,CAAC;QAClB,CAAC;QAED,MAAM,aAAa,GAAG,mBAAmB,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACzD,IAAI,CAAC,aAAa,EAAE,CAAC;YACnB,MAAM,QAAQ,GAAG,IAAI,0BAA0B,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;YAC9D,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,EAAE,mBAAmB,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC,CAAC;YACxE,OAAO,QAAQ,CAAC;QAClB,CAAC;QAED,OAAO,aAAa,CAAC;IACvB,CAAC;;AAhCH,gEAiCC;AAhCC;;;;GAIG;AACY,oCAAS,GAA0D,IAAI,GAAG,EAAE,CAAC","sourcesContent":["import { Effect, PolicyStatement } from \"aws-cdk-lib/aws-iam\";\nimport { GuAppAwareConstruct } from \"../../../utils/mixin/app-aware-construct\";\nimport type { AppIdentity, GuStack } from \"../../core\";\nimport { GuPolicy } from \"./base-policy\";\n\n/**\n * This is helpful for reading all private configuration for a given app. For example, the\n * [simple-configuration](https://github.com/guardian/simple-configuration) library requires these permissions.\n */\nexport class ReadParametersByPath extends PolicyStatement {\n constructor(scope: GuStack, props: AppIdentity) {\n super({\n effect: Effect.ALLOW,\n actions: [\"ssm:GetParametersByPath\"],\n resources: [`arn:aws:ssm:${scope.region}:${scope.account}:parameter/${scope.stage}/${scope.stack}/${props.app}`],\n });\n }\n}\n\n/**\n * This is helpful for accessing specific pieces of private configuration. For example, the\n * [play-secret-rotation](https://github.com/guardian/play-secret-rotation) library requires `ssm:GetParameters`\n * permissions.\n */\nexport class ReadParametersByName extends PolicyStatement {\n constructor(scope: GuStack, props: AppIdentity) {\n super({\n effect: Effect.ALLOW,\n actions: [\"ssm:GetParameters\", \"ssm:GetParameter\"],\n resources: [\n `arn:aws:ssm:${scope.region}:${scope.account}:parameter/${scope.stage}/${scope.stack}/${props.app}/*`,\n ],\n });\n }\n}\n/**\n * Grants read-only permissions for Parameter Store. These permissions are typically used for accessing private\n * configuration. See [[`ReadParametersByPath`]] and [[`ReadParametersByName`]] for more details.\n */\nexport class GuParameterStoreReadPolicy extends GuAppAwareConstruct(GuPolicy) {\n /**\n * A record of existing instances of this construct, per {@link GuStack}.\n * This allows us to implement singleton like behaviour.\n * @private\n */\n private static instances: Map<GuStack, Map<string, GuParameterStoreReadPolicy>> = new Map();\n\n private constructor(scope: GuStack, props: AppIdentity) {\n super(scope, \"ParameterStoreRead\", {\n policyName: \"parameter-store-read-policy\",\n statements: [new ReadParametersByPath(scope, props), new ReadParametersByName(scope, props)],\n ...props,\n });\n }\n\n public static getInstance(stack: GuStack, props: AppIdentity): GuParameterStoreReadPolicy {\n const maybeStackInstances = this.instances.get(stack);\n if (!maybeStackInstances) {\n const instance = new GuParameterStoreReadPolicy(stack, props);\n this.instances.set(stack, new Map([[props.app, instance]]));\n return instance;\n }\n\n const maybeInstance = maybeStackInstances.get(props.app);\n if (!maybeInstance) {\n const instance = new GuParameterStoreReadPolicy(stack, props);\n this.instances.set(stack, maybeStackInstances.set(props.app, instance));\n return instance;\n }\n\n return maybeInstance;\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"ssm-ssh.js","sourceRoot":"","sources":["../../../../src/constructs/iam/policies/ssm-ssh.ts"],"names":[],"mappings":";;;AAAA,wDAAqE;AAErE,+CAA8C;AAE9C;;;;;;;;;;GAUG;AACH,MAAa,cAAe,SAAQ,2BAAa;IAG/C,YAAoB,KAAc;QAChC,KAAK,CAAC,KAAK,EAAE,cAAc,EAAE;YAC3B,UAAU,EAAE,gBAAgB;YAC5B,OAAO,EAAE;gBACP,gCAAgC;gBAChC,2BAA2B;gBAC3B,yBAAyB;gBACzB,yBAAyB;gBACzB,yBAAyB;gBACzB,uBAAuB;gBACvB,+BAA+B;gBAC/B,8BAA8B;gBAC9B,gCAAgC;gBAChC,gCAAgC;gBAChC,kCAAkC;gBAClC,+BAA+B;gBAC/B,gCAAgC;gBAChC,6BAA6B;aAC9B;YAED,8GAA8G;YAC9G,SAAS,EAAE,CAAC,GAAG,CAAC;SACjB,CAAC,CAAC;IACL,CAAC;IAEM,MAAM,CAAC,WAAW,CAAC,KAAc;QACtC,IAAI,CAAC,IAAI,CAAC,QAAQ,IAAI,CAAC,IAAA,qCAAyB,EAAC,KAAK,EAAE,IAAI,CAAC,QAAQ,CAAC,EAAE;YACtE,IAAI,CAAC,QAAQ,GAAG,IAAI,cAAc,CAAC,KAAK,CAAC,CAAC;SAC3C;QAED,OAAO,IAAI,CAAC,QAAQ,CAAC;IACvB,CAAC;CACF;AAnCD,wCAmCC","sourcesContent":["import { isSingletonPresentInStack } from \"../../../utils/singleton\";\nimport type { GuStack } from \"../../core\";\nimport { GuAllowPolicy } from \"./base-policy\";\n\n/**\n * A minimal policy enabling SSM+SSH access to EC2 instances.\n *\n * This is favoured over the AWS Managed Policy `AmazonSSMManagedInstanceCore`,\n * `AmazonSSMManagedInstanceCore` provides read access to all SSM Parameters.\n * This is not required for SSM+SSH, and given our usage of SSM Parameters for configuration, is not following least privilege.\n * Access to SSM Parameters should be scoped to the Stack, Stage, and Application.\n *\n * @see https://docs.aws.amazon.com/aws-managed-policy/latest/reference/AmazonSSMManagedInstanceCore.html\n * @see https://github.com/guardian/ssm-scala\n */\nexport class GuSsmSshPolicy extends GuAllowPolicy {\n private static instance: GuSsmSshPolicy | undefined;\n\n private constructor(scope: GuStack) {\n super(scope, \"SsmSshPolicy\", {\n policyName: \"ssm-ssh-policy\",\n actions: [\n \"ec2messages:AcknowledgeMessage\",\n \"ec2messages:DeleteMessage\",\n \"ec2messages:FailMessage\",\n \"ec2messages:GetEndpoint\",\n \"ec2messages:GetMessages\",\n \"ec2messages:SendReply\",\n \"ssm:UpdateInstanceInformation\",\n \"ssm:ListInstanceAssociations\",\n \"ssm:DescribeInstanceProperties\",\n \"ssm:DescribeDocumentParameters\",\n \"ssmmessages:CreateControlChannel\",\n \"ssmmessages:CreateDataChannel\",\n \"ssmmessages:OpenControlChannel\",\n \"ssmmessages:OpenDataChannel\",\n ],\n\n // TODO can this be scoped to the stack, stage, and application? If so, it won't make sense to be a singleton.\n resources: [\"*\"],\n });\n }\n\n public static getInstance(stack: GuStack): GuSsmSshPolicy {\n if (!this.instance || !isSingletonPresentInStack(stack, this.instance)) {\n this.instance = new GuSsmSshPolicy(stack);\n }\n\n return this.instance;\n }\n}\n"]}
1
+ {"version":3,"file":"ssm-ssh.js","sourceRoot":"","sources":["../../../../src/constructs/iam/policies/ssm-ssh.ts"],"names":[],"mappings":";;;AAAA,wDAAqE;AAErE,+CAA8C;AAE9C;;;;;;;;;;GAUG;AACH,MAAa,cAAe,SAAQ,2BAAa;IAG/C,YAAoB,KAAc;QAChC,KAAK,CAAC,KAAK,EAAE,cAAc,EAAE;YAC3B,UAAU,EAAE,gBAAgB;YAC5B,OAAO,EAAE;gBACP,gCAAgC;gBAChC,2BAA2B;gBAC3B,yBAAyB;gBACzB,yBAAyB;gBACzB,yBAAyB;gBACzB,uBAAuB;gBACvB,+BAA+B;gBAC/B,8BAA8B;gBAC9B,gCAAgC;gBAChC,gCAAgC;gBAChC,kCAAkC;gBAClC,+BAA+B;gBAC/B,gCAAgC;gBAChC,6BAA6B;aAC9B;YAED,8GAA8G;YAC9G,SAAS,EAAE,CAAC,GAAG,CAAC;SACjB,CAAC,CAAC;IACL,CAAC;IAEM,MAAM,CAAC,WAAW,CAAC,KAAc;QACtC,IAAI,CAAC,IAAI,CAAC,QAAQ,IAAI,CAAC,IAAA,qCAAyB,EAAC,KAAK,EAAE,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;YACvE,IAAI,CAAC,QAAQ,GAAG,IAAI,cAAc,CAAC,KAAK,CAAC,CAAC;QAC5C,CAAC;QAED,OAAO,IAAI,CAAC,QAAQ,CAAC;IACvB,CAAC;CACF;AAnCD,wCAmCC","sourcesContent":["import { isSingletonPresentInStack } from \"../../../utils/singleton\";\nimport type { GuStack } from \"../../core\";\nimport { GuAllowPolicy } from \"./base-policy\";\n\n/**\n * A minimal policy enabling SSM+SSH access to EC2 instances.\n *\n * This is favoured over the AWS Managed Policy `AmazonSSMManagedInstanceCore`,\n * `AmazonSSMManagedInstanceCore` provides read access to all SSM Parameters.\n * This is not required for SSM+SSH, and given our usage of SSM Parameters for configuration, is not following least privilege.\n * Access to SSM Parameters should be scoped to the Stack, Stage, and Application.\n *\n * @see https://docs.aws.amazon.com/aws-managed-policy/latest/reference/AmazonSSMManagedInstanceCore.html\n * @see https://github.com/guardian/ssm-scala\n */\nexport class GuSsmSshPolicy extends GuAllowPolicy {\n private static instance: GuSsmSshPolicy | undefined;\n\n private constructor(scope: GuStack) {\n super(scope, \"SsmSshPolicy\", {\n policyName: \"ssm-ssh-policy\",\n actions: [\n \"ec2messages:AcknowledgeMessage\",\n \"ec2messages:DeleteMessage\",\n \"ec2messages:FailMessage\",\n \"ec2messages:GetEndpoint\",\n \"ec2messages:GetMessages\",\n \"ec2messages:SendReply\",\n \"ssm:UpdateInstanceInformation\",\n \"ssm:ListInstanceAssociations\",\n \"ssm:DescribeInstanceProperties\",\n \"ssm:DescribeDocumentParameters\",\n \"ssmmessages:CreateControlChannel\",\n \"ssmmessages:CreateDataChannel\",\n \"ssmmessages:OpenControlChannel\",\n \"ssmmessages:OpenDataChannel\",\n ],\n\n // TODO can this be scoped to the stack, stage, and application? If so, it won't make sense to be a singleton.\n resources: [\"*\"],\n });\n }\n\n public static getInstance(stack: GuStack): GuSsmSshPolicy {\n if (!this.instance || !isSingletonPresentInStack(stack, this.instance)) {\n this.instance = new GuSsmSshPolicy(stack);\n }\n\n return this.instance;\n }\n}\n"]}
@@ -35,7 +35,7 @@ class GuInstanceRole extends (0, app_aware_construct_1.GuAppAwareConstruct)(role
35
35
  const policies = [
36
36
  ...sharedPolicies,
37
37
  new policies_1.GuGetDistributablePolicy(scope, props),
38
- new policies_1.GuParameterStoreReadPolicy(scope, props),
38
+ policies_1.GuParameterStoreReadPolicy.getInstance(scope, props),
39
39
  ...(props.additionalPolicies ?? []),
40
40
  ];
41
41
  policies.forEach((p) => p.attachToRole(this));
@@ -1 +1 @@
1
- {"version":3,"file":"instance-role.js","sourceRoot":"","sources":["../../../../src/constructs/iam/roles/instance-role.ts"],"names":[],"mappings":";;;AAAA,iDAAuD;AACvD,kFAA+E;AAE/E,0CAKqB;AAErB,iDAAqD;AACrD,mCAAiC;AAgBjC;;;;;;;;;;;;;GAaG;AACH,MAAa,cAAe,SAAQ,IAAA,yCAAmB,EAAC,cAAM,CAAC;IAC7D,YAAY,KAAc,EAAE,KAAiC;QAC3D,KAAK,CAAC,KAAK,EAAE,cAAc,EAAE;YAC3B,IAAI,EAAE,GAAG;YACT,SAAS,EAAE,IAAI,0BAAgB,CAAC,mBAAmB,CAAC;YACpD,GAAG,KAAK;SACT,CAAC,CAAC;QAEH,MAAM,cAAc,GAAG;YACrB,wBAAc,CAAC,WAAW,CAAC,KAAK,CAAC;YACjC,8BAAmB,CAAC,WAAW,CAAC,KAAK,CAAC;YACtC,GAAG,CAAC,KAAK,CAAC,kBAAkB,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,8BAAmB,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC;SAC9E,CAAC;QAEF,MAAM,QAAQ,GAAG;YACf,GAAG,cAAc;YACjB,IAAI,mCAAwB,CAAC,KAAK,EAAE,KAAK,CAAC;YAC1C,IAAI,qCAA0B,CAAC,KAAK,EAAE,KAAK,CAAC;YAC5C,GAAG,CAAC,KAAK,CAAC,kBAAkB,IAAI,EAAE,CAAC;SACpC,CAAC;QAEF,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC;IAChD,CAAC;CACF;AAvBD,wCAuBC","sourcesContent":["import { ServicePrincipal } from \"aws-cdk-lib/aws-iam\";\nimport { GuAppAwareConstruct } from \"../../../utils/mixin/app-aware-construct\";\nimport type { AppIdentity, GuStack } from \"../../core\";\nimport {\n GuDescribeEC2Policy,\n GuGetDistributablePolicy,\n GuLogShippingPolicy,\n GuParameterStoreReadPolicy,\n} from \"../policies\";\nimport type { GuPolicy } from \"../policies\";\nimport { GuSsmSshPolicy } from \"../policies/ssm-ssh\";\nimport { GuRole } from \"./roles\";\n\nexport interface GuInstanceRoleProps {\n /**\n * By default, instances are given permissions to write to Kinesis. Set to\n * 'true' to prevent this. Note, disabling will prevent not just application\n * logs being shipped but also anything else - for example, automatic log\n * shipping of Cloud Init and other logs by the cdk-base role in your AMI.\n */\n withoutLogShipping?: boolean;\n\n additionalPolicies?: GuPolicy[];\n}\n\nexport type GuInstanceRolePropsWithApp = GuInstanceRoleProps & AppIdentity;\n\n/**\n * Creates an IAM role with common policies that are needed by most Guardian applications.\n *\n * More specifically:\n * 1. Allows for `ssh` access to an EC2 instance via [ssm-scala](https://github.com/guardian/ssm-scala) (instead of standard `ssh`).\n * 2. Allows EC2 instances to download an artifact from AWS S3, for application deployment.\n * 3. Allows EC2 instances to download private configuration from AWS Parameter Store. See [[`GuParameterStoreReadPolicy`]]\n * for specific details.\n * 4. Allows EC2 instances to write logs into our central ELK stack via Kinesis.\n *\n * If additional IAM permissions are required, create custom policies and pass them in via the `additionalPolicies` prop.\n *\n * If log shipping is not required, opt out by setting the `withoutLogShipping` prop to `true`.\n */\nexport class GuInstanceRole extends GuAppAwareConstruct(GuRole) {\n constructor(scope: GuStack, props: GuInstanceRolePropsWithApp) {\n super(scope, \"InstanceRole\", {\n path: \"/\",\n assumedBy: new ServicePrincipal(\"ec2.amazonaws.com\"),\n ...props,\n });\n\n const sharedPolicies = [\n GuSsmSshPolicy.getInstance(scope),\n GuDescribeEC2Policy.getInstance(scope),\n ...(props.withoutLogShipping ? [] : [GuLogShippingPolicy.getInstance(scope)]),\n ];\n\n const policies = [\n ...sharedPolicies,\n new GuGetDistributablePolicy(scope, props),\n new GuParameterStoreReadPolicy(scope, props),\n ...(props.additionalPolicies ?? []),\n ];\n\n policies.forEach((p) => p.attachToRole(this));\n }\n}\n"]}
1
+ {"version":3,"file":"instance-role.js","sourceRoot":"","sources":["../../../../src/constructs/iam/roles/instance-role.ts"],"names":[],"mappings":";;;AAAA,iDAAuD;AACvD,kFAA+E;AAE/E,0CAKqB;AAErB,iDAAqD;AACrD,mCAAiC;AAgBjC;;;;;;;;;;;;;GAaG;AACH,MAAa,cAAe,SAAQ,IAAA,yCAAmB,EAAC,cAAM,CAAC;IAC7D,YAAY,KAAc,EAAE,KAAiC;QAC3D,KAAK,CAAC,KAAK,EAAE,cAAc,EAAE;YAC3B,IAAI,EAAE,GAAG;YACT,SAAS,EAAE,IAAI,0BAAgB,CAAC,mBAAmB,CAAC;YACpD,GAAG,KAAK;SACT,CAAC,CAAC;QAEH,MAAM,cAAc,GAAG;YACrB,wBAAc,CAAC,WAAW,CAAC,KAAK,CAAC;YACjC,8BAAmB,CAAC,WAAW,CAAC,KAAK,CAAC;YACtC,GAAG,CAAC,KAAK,CAAC,kBAAkB,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,8BAAmB,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC;SAC9E,CAAC;QAEF,MAAM,QAAQ,GAAG;YACf,GAAG,cAAc;YACjB,IAAI,mCAAwB,CAAC,KAAK,EAAE,KAAK,CAAC;YAC1C,qCAA0B,CAAC,WAAW,CAAC,KAAK,EAAE,KAAK,CAAC;YACpD,GAAG,CAAC,KAAK,CAAC,kBAAkB,IAAI,EAAE,CAAC;SACpC,CAAC;QAEF,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC;IAChD,CAAC;CACF;AAvBD,wCAuBC","sourcesContent":["import { ServicePrincipal } from \"aws-cdk-lib/aws-iam\";\nimport { GuAppAwareConstruct } from \"../../../utils/mixin/app-aware-construct\";\nimport type { AppIdentity, GuStack } from \"../../core\";\nimport {\n GuDescribeEC2Policy,\n GuGetDistributablePolicy,\n GuLogShippingPolicy,\n GuParameterStoreReadPolicy,\n} from \"../policies\";\nimport type { GuPolicy } from \"../policies\";\nimport { GuSsmSshPolicy } from \"../policies/ssm-ssh\";\nimport { GuRole } from \"./roles\";\n\nexport interface GuInstanceRoleProps {\n /**\n * By default, instances are given permissions to write to Kinesis. Set to\n * 'true' to prevent this. Note, disabling will prevent not just application\n * logs being shipped but also anything else - for example, automatic log\n * shipping of Cloud Init and other logs by the cdk-base role in your AMI.\n */\n withoutLogShipping?: boolean;\n\n additionalPolicies?: GuPolicy[];\n}\n\nexport type GuInstanceRolePropsWithApp = GuInstanceRoleProps & AppIdentity;\n\n/**\n * Creates an IAM role with common policies that are needed by most Guardian applications.\n *\n * More specifically:\n * 1. Allows for `ssh` access to an EC2 instance via [ssm-scala](https://github.com/guardian/ssm-scala) (instead of standard `ssh`).\n * 2. Allows EC2 instances to download an artifact from AWS S3, for application deployment.\n * 3. Allows EC2 instances to download private configuration from AWS Parameter Store. See [[`GuParameterStoreReadPolicy`]]\n * for specific details.\n * 4. Allows EC2 instances to write logs into our central ELK stack via Kinesis.\n *\n * If additional IAM permissions are required, create custom policies and pass them in via the `additionalPolicies` prop.\n *\n * If log shipping is not required, opt out by setting the `withoutLogShipping` prop to `true`.\n */\nexport class GuInstanceRole extends GuAppAwareConstruct(GuRole) {\n constructor(scope: GuStack, props: GuInstanceRolePropsWithApp) {\n super(scope, \"InstanceRole\", {\n path: \"/\",\n assumedBy: new ServicePrincipal(\"ec2.amazonaws.com\"),\n ...props,\n });\n\n const sharedPolicies = [\n GuSsmSshPolicy.getInstance(scope),\n GuDescribeEC2Policy.getInstance(scope),\n ...(props.withoutLogShipping ? [] : [GuLogShippingPolicy.getInstance(scope)]),\n ];\n\n const policies = [\n ...sharedPolicies,\n new GuGetDistributablePolicy(scope, props),\n GuParameterStoreReadPolicy.getInstance(scope, props),\n ...(props.additionalPolicies ?? []),\n ];\n\n policies.forEach((p) => p.attachToRole(this));\n }\n}\n"]}