@jaypie/constructs 1.2.48 → 1.2.50

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.
@@ -46,6 +46,15 @@ interface JaypieHostedZoneProps {
46
46
  * Each record will be created as a JaypieDnsRecord construct
47
47
  */
48
48
  records?: JaypieHostedZoneRecordProps[];
49
+ /**
50
+ * Control the CloudWatch Logs resource policy that grants Route53 permission
51
+ * to write query logs. Defaults to `true`, which ensures a single
52
+ * stack-level wildcard policy covering every `/aws/route53/*` log group.
53
+ * Set to `false` to skip creating a managed policy (useful when an
54
+ * account-wide policy is provisioned externally).
55
+ * @default true
56
+ */
57
+ queryLoggingPolicy?: boolean;
49
58
  }
50
59
  export declare class JaypieHostedZone extends Construct {
51
60
  readonly hostedZone: IHostedZone;
@@ -0,0 +1,12 @@
1
+ import { CfnResourcePolicy } from "aws-cdk-lib/aws-logs";
2
+ import { Construct } from "constructs";
3
+ /**
4
+ * Create (or return the existing) stack-level CloudWatch Logs resource policy
5
+ * that grants Route53 permission to write query logs to any `/aws/route53/*`
6
+ * log group in the stack's account and region.
7
+ *
8
+ * Consolidates what would otherwise be one `AWS::Logs::ResourcePolicy` per
9
+ * hosted zone into a single wildcard policy, keeping the stack well clear of
10
+ * the 10-resource-policy-per-region account quota.
11
+ */
12
+ export declare function ensureRoute53QueryLoggingPolicy(scope: Construct): CfnResourcePolicy;
@@ -5,6 +5,7 @@ export { constructTagger } from "./constructTagger";
5
5
  export { envHostname, HostConfig } from "./envHostname";
6
6
  export { extendDatadogRole, ExtendDatadogRoleOptions, } from "./extendDatadogRole";
7
7
  export { clearAllCertificateCaches, clearCertificateCache, resolveCertificate, ResolveCertificateOptions, } from "./resolveCertificate";
8
+ export { ensureRoute53QueryLoggingPolicy } from "./ensureRoute53QueryLoggingPolicy";
8
9
  export { isEnv, isProductionEnv, isSandboxEnv } from "./isEnv";
9
10
  export { isValidHostname } from "./isValidHostname";
10
11
  export { isValidSubdomain } from "./isValidSubdomain";
@@ -11,12 +11,12 @@ var datadogCdkConstructsV2 = require('datadog-cdk-constructs-v2');
11
11
  var errors = require('@jaypie/errors');
12
12
  var awsIam = require('aws-cdk-lib/aws-iam');
13
13
  var acm = require('aws-cdk-lib/aws-certificatemanager');
14
+ var logs = require('aws-cdk-lib/aws-logs');
14
15
  var lambda = require('aws-cdk-lib/aws-lambda');
15
16
  var logDestinations = require('aws-cdk-lib/aws-logs-destinations');
16
17
  var s3n = require('aws-cdk-lib/aws-s3-notifications');
17
18
  var sqs = require('aws-cdk-lib/aws-sqs');
18
19
  var lambdaEventSources = require('aws-cdk-lib/aws-lambda-event-sources');
19
- var logs = require('aws-cdk-lib/aws-logs');
20
20
  var awsEvents = require('aws-cdk-lib/aws-events');
21
21
  var awsEventsTargets = require('aws-cdk-lib/aws-events-targets');
22
22
  var cloudfront = require('aws-cdk-lib/aws-cloudfront');
@@ -57,12 +57,12 @@ var route53__namespace = /*#__PURE__*/_interopNamespaceDefault(route53);
57
57
  var route53Targets__namespace = /*#__PURE__*/_interopNamespaceDefault(route53Targets);
58
58
  var secretsmanager__namespace = /*#__PURE__*/_interopNamespaceDefault(secretsmanager);
59
59
  var acm__namespace = /*#__PURE__*/_interopNamespaceDefault(acm);
60
+ var logs__namespace = /*#__PURE__*/_interopNamespaceDefault(logs);
60
61
  var lambda__namespace = /*#__PURE__*/_interopNamespaceDefault(lambda);
61
62
  var logDestinations__namespace = /*#__PURE__*/_interopNamespaceDefault(logDestinations);
62
63
  var s3n__namespace = /*#__PURE__*/_interopNamespaceDefault(s3n);
63
64
  var sqs__namespace = /*#__PURE__*/_interopNamespaceDefault(sqs);
64
65
  var lambdaEventSources__namespace = /*#__PURE__*/_interopNamespaceDefault(lambdaEventSources);
65
- var logs__namespace = /*#__PURE__*/_interopNamespaceDefault(logs);
66
66
  var cloudfront__namespace = /*#__PURE__*/_interopNamespaceDefault(cloudfront);
67
67
  var origins__namespace = /*#__PURE__*/_interopNamespaceDefault(origins);
68
68
  var wafv2__namespace = /*#__PURE__*/_interopNamespaceDefault(wafv2);
@@ -587,6 +587,40 @@ function clearAllCertificateCaches() {
587
587
  // but stacks going out of scope will be garbage collected anyway
588
588
  }
589
589
 
590
+ const SINGLETON_ID = "JaypieRoute53QueryLoggingPolicy";
591
+ const ROUTE53_LOG_GROUP_PREFIX = "/aws/route53";
592
+ const ROUTE53_SERVICE_PRINCIPAL = "route53.amazonaws.com";
593
+ /**
594
+ * Create (or return the existing) stack-level CloudWatch Logs resource policy
595
+ * that grants Route53 permission to write query logs to any `/aws/route53/*`
596
+ * log group in the stack's account and region.
597
+ *
598
+ * Consolidates what would otherwise be one `AWS::Logs::ResourcePolicy` per
599
+ * hosted zone into a single wildcard policy, keeping the stack well clear of
600
+ * the 10-resource-policy-per-region account quota.
601
+ */
602
+ function ensureRoute53QueryLoggingPolicy(scope) {
603
+ const stack = cdk.Stack.of(scope);
604
+ const existing = stack.node.tryFindChild(SINGLETON_ID);
605
+ if (existing)
606
+ return existing;
607
+ const policyDocument = {
608
+ Version: "2012-10-17",
609
+ Statement: [
610
+ {
611
+ Effect: "Allow",
612
+ Principal: { Service: ROUTE53_SERVICE_PRINCIPAL },
613
+ Action: ["logs:CreateLogStream", "logs:PutLogEvents"],
614
+ Resource: `arn:${stack.partition}:logs:${stack.region}:${stack.account}:log-group:${ROUTE53_LOG_GROUP_PREFIX}/*:*`,
615
+ },
616
+ ],
617
+ };
618
+ return new logs.CfnResourcePolicy(stack, SINGLETON_ID, {
619
+ policyName: `${stack.stackName}-Route53QueryLogging`,
620
+ policyDocument: JSON.stringify(policyDocument),
621
+ });
622
+ }
623
+
590
624
  /**
591
625
  * Check if the current environment matches the given environment
592
626
  */
@@ -947,12 +981,16 @@ function exportEnvName$1(name, env = process.env) {
947
981
  }
948
982
  class JaypieEnvSecret extends constructs.Construct {
949
983
  constructor(scope, idOrEnvKey, props) {
950
- // Check if idOrEnvKey should be treated as envKey:
951
- // - No props provided OR props.envKey is not set
952
- // - AND idOrEnvKey exists as a non-empty string in process.env
984
+ // Shorthand detection: treat idOrEnvKey as envKey when envKey prop is
985
+ // not set and idOrEnvKey either looks like a SCREAMING_SNAKE_CASE env
986
+ // var name or is already present in process.env. Convention-based
987
+ // detection ensures missing env vars still go through envKey validation
988
+ // instead of silently creating an empty secret.
989
+ const looksLikeEnvKey = /^[A-Z][A-Z0-9_]*$/.test(idOrEnvKey);
953
990
  const treatAsEnvKey = (!props || props.envKey === undefined) &&
954
- typeof process.env[idOrEnvKey] === "string" &&
955
- process.env[idOrEnvKey] !== "";
991
+ (looksLikeEnvKey ||
992
+ (typeof process.env[idOrEnvKey] === "string" &&
993
+ process.env[idOrEnvKey] !== ""));
956
994
  const id = treatAsEnvKey ? `EnvSecret_${idOrEnvKey}` : idOrEnvKey;
957
995
  super(scope, id);
958
996
  const { consumer = checkEnvIsConsumer$1(), envKey: envKeyProp, export: exportParam, generateSecretString, provider = checkEnvIsProvider$1(), removalPolicy, roleTag, vendorTag, value, } = props || {};
@@ -3344,9 +3382,6 @@ class JaypieGitHubDeployRole extends constructs.Construct {
3344
3382
  }
3345
3383
  }
3346
3384
 
3347
- const SERVICE = {
3348
- ROUTE53: "route53.amazonaws.com",
3349
- };
3350
3385
  /**
3351
3386
  * Check if a string is a valid hostname
3352
3387
  */
@@ -3412,8 +3447,13 @@ class JaypieHostedZone extends constructs.Construct {
3412
3447
  if (project) {
3413
3448
  cdk__namespace.Tags.of(this.logGroup).add(CDK$2.TAG.PROJECT, project);
3414
3449
  }
3415
- // Grant Route 53 permissions to write to the log group
3416
- this.logGroup.grantWrite(new awsIam.ServicePrincipal(SERVICE.ROUTE53));
3450
+ // Grant Route53 permission to write query logs via a single stack-level
3451
+ // resource policy. Per-zone policies exhaust the CloudWatch Logs
3452
+ // 10-policy-per-region account quota (issue #311).
3453
+ const queryLoggingPolicy = props.queryLoggingPolicy ?? true;
3454
+ if (queryLoggingPolicy) {
3455
+ ensureRoute53QueryLoggingPolicy(this);
3456
+ }
3417
3457
  // Add destination based on configuration
3418
3458
  if (destination !== false) {
3419
3459
  const lambdaDestination = destination === true
@@ -4901,6 +4941,7 @@ exports.clearSecretsCache = clearSecretsCache;
4901
4941
  exports.constructEnvName = constructEnvName;
4902
4942
  exports.constructStackName = constructStackName;
4903
4943
  exports.constructTagger = constructTagger;
4944
+ exports.ensureRoute53QueryLoggingPolicy = ensureRoute53QueryLoggingPolicy;
4904
4945
  exports.envHostname = envHostname;
4905
4946
  exports.extendDatadogRole = extendDatadogRole;
4906
4947
  exports.isEnv = isEnv;