@jaypie/constructs 1.2.49 → 1.2.51

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.
@@ -1,9 +1,11 @@
1
1
  import { Role } from "aws-cdk-lib/aws-iam";
2
2
  import { Construct } from "constructs";
3
3
  export interface JaypieGitHubDeployRoleProps {
4
+ ecr?: boolean;
4
5
  oidcProviderArn?: string;
5
6
  output?: boolean | string;
6
7
  repoRestriction?: string;
8
+ sponsor?: string;
7
9
  }
8
10
  export declare class JaypieGitHubDeployRole extends Construct {
9
11
  private readonly _role;
@@ -981,12 +981,16 @@ function exportEnvName$1(name, env = process.env) {
981
981
  }
982
982
  class JaypieEnvSecret extends constructs.Construct {
983
983
  constructor(scope, idOrEnvKey, props) {
984
- // Check if idOrEnvKey should be treated as envKey:
985
- // - No props provided OR props.envKey is not set
986
- // - 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);
987
990
  const treatAsEnvKey = (!props || props.envKey === undefined) &&
988
- typeof process.env[idOrEnvKey] === "string" &&
989
- process.env[idOrEnvKey] !== "";
991
+ (looksLikeEnvKey ||
992
+ (typeof process.env[idOrEnvKey] === "string" &&
993
+ process.env[idOrEnvKey] !== ""));
990
994
  const id = treatAsEnvKey ? `EnvSecret_${idOrEnvKey}` : idOrEnvKey;
991
995
  super(scope, id);
992
996
  const { consumer = checkEnvIsConsumer$1(), envKey: envKeyProp, export: exportParam, generateSecretString, provider = checkEnvIsProvider$1(), removalPolicy, roleTag, vendorTag, value, } = props || {};
@@ -3295,23 +3299,33 @@ class JaypieExpressLambda extends JaypieLambda {
3295
3299
  }
3296
3300
  }
3297
3301
 
3302
+ const ECR_PUSH_ACTIONS = [
3303
+ "ecr:BatchCheckLayerAvailability",
3304
+ "ecr:BatchGetImage",
3305
+ "ecr:CompleteLayerUpload",
3306
+ "ecr:CreateRepository",
3307
+ "ecr:DescribeRepositories",
3308
+ "ecr:InitiateLayerUpload",
3309
+ "ecr:PutImage",
3310
+ "ecr:UploadLayerPart",
3311
+ ];
3298
3312
  class JaypieGitHubDeployRole extends constructs.Construct {
3299
3313
  constructor(scope, id = "GitHubDeployRole", props = {}) {
3300
3314
  super(scope, id);
3301
- const { oidcProviderArn = cdk.Fn.importValue(CDK$2.IMPORT.OIDC_PROVIDER), output = true, repoRestriction: propsRepoRestriction, } = props;
3315
+ const { ecr = true, oidcProviderArn = cdk.Fn.importValue(CDK$2.IMPORT.OIDC_PROVIDER), output = true, repoRestriction: propsRepoRestriction, sponsor: propsSponsor, } = props;
3302
3316
  // Extract account ID from the scope
3303
3317
  const accountId = cdk.Stack.of(this).account;
3304
- // Resolve repoRestriction from props or environment variables
3318
+ // Resolve repoRestriction and sponsor from props or environment variables
3319
+ const envRepo = process.env.CDK_ENV_REPO || process.env.PROJECT_REPO;
3320
+ const envRepoOrganization = envRepo ? envRepo.split("/")[0] : undefined;
3305
3321
  let repoRestriction = propsRepoRestriction;
3306
3322
  if (!repoRestriction) {
3307
- const envRepo = process.env.CDK_ENV_REPO || process.env.PROJECT_REPO;
3308
- if (!envRepo) {
3323
+ if (!envRepoOrganization) {
3309
3324
  throw new errors.ConfigurationError("No repoRestriction provided. Set repoRestriction prop, CDK_ENV_REPO, or PROJECT_REPO environment variable");
3310
3325
  }
3311
- // Extract organization from owner/repo format and create org-wide restriction
3312
- const organization = envRepo.split("/")[0];
3313
- repoRestriction = `repo:${organization}/*:*`;
3326
+ repoRestriction = `repo:${envRepoOrganization}/*:*`;
3314
3327
  }
3328
+ const sponsor = propsSponsor || process.env.PROJECT_SPONSOR || envRepoOrganization;
3315
3329
  // Create the IAM role
3316
3330
  this._role = new awsIam.Role(this, "GitHubActionsRole", {
3317
3331
  assumedBy: new awsIam.FederatedPrincipal(oidcProviderArn, {
@@ -3359,6 +3373,22 @@ class JaypieGitHubDeployRole extends constructs.Construct {
3359
3373
  "arn:aws:iam::*:role/cdk-readOnlyRole",
3360
3374
  ],
3361
3375
  }));
3376
+ // Grant ECR auth + push scoped to <sponsor>-* repositories
3377
+ if (ecr) {
3378
+ if (!sponsor) {
3379
+ throw new errors.ConfigurationError("Cannot grant default ECR permissions without a sponsor. Set sponsor prop, PROJECT_SPONSOR, CDK_ENV_REPO, or PROJECT_REPO, or pass `ecr: false`");
3380
+ }
3381
+ this._role.addToPolicy(new awsIam.PolicyStatement({
3382
+ actions: ["ecr:GetAuthorizationToken"],
3383
+ effect: awsIam.Effect.ALLOW,
3384
+ resources: ["*"],
3385
+ }));
3386
+ this._role.addToPolicy(new awsIam.PolicyStatement({
3387
+ actions: ECR_PUSH_ACTIONS,
3388
+ effect: awsIam.Effect.ALLOW,
3389
+ resources: [`arn:aws:ecr:*:${accountId}:repository/${sponsor}-*`],
3390
+ }));
3391
+ }
3362
3392
  // Export the ARN of the role
3363
3393
  if (output !== false) {
3364
3394
  const outputId = typeof output === "string" ? output : "GitHubActionsRoleArn";