UNPKG

aws-cdk-lib

Version:

Version 2 of the AWS Cloud Development Kit library

2 lines (1 loc) 18.5 kB
"use strict";var _a,_b,_c;Object.defineProperty(exports,"__esModule",{value:!0}),exports.RepositoryEncryption=exports.TagMutability=exports.Repository=exports.RepositoryBase=void 0;var jsiiDeprecationWarnings=()=>{var tmp=require("../../.warnings.jsii.js");return jsiiDeprecationWarnings=()=>tmp,tmp};const JSII_RTTI_SYMBOL_1=Symbol.for("jsii.rtti");var os_1=()=>{var tmp=require("os");return os_1=()=>tmp,tmp},ecr_generated_1=()=>{var tmp=require("./ecr.generated");return ecr_generated_1=()=>tmp,tmp},lifecycle_1=()=>{var tmp=require("./lifecycle");return lifecycle_1=()=>tmp,tmp},events=()=>{var tmp=require("../../aws-events");return events=()=>tmp,tmp},iam=()=>{var tmp=require("../../aws-iam");return iam=()=>tmp,tmp},core_1=()=>{var tmp=require("../../core");return core_1=()=>tmp,tmp},auto_delete_images_provider_generated_1=()=>{var tmp=require("../../custom-resource-handlers/dist/aws-ecr/auto-delete-images-provider.generated");return auto_delete_images_provider_generated_1=()=>tmp,tmp};const AUTO_DELETE_IMAGES_RESOURCE_TYPE="Custom::ECRAutoDeleteImages",AUTO_DELETE_IMAGES_TAG="aws-cdk:auto-delete-images";class RepositoryBase extends core_1().Resource{constructor(){super(...arguments),this.REPO_PULL_ACTIONS=["ecr:BatchCheckLayerAvailability","ecr:GetDownloadUrlForLayer","ecr:BatchGetImage"],this.REPO_PUSH_ACTIONS=["ecr:CompleteLayerUpload","ecr:UploadLayerPart","ecr:InitiateLayerUpload","ecr:BatchCheckLayerAvailability","ecr:PutImage"]}get repositoryUri(){return this.repositoryUriForTag()}repositoryUriForTag(tag){const tagSuffix=tag?`:${tag}`:"";return this.repositoryUriWithSuffix(tagSuffix)}repositoryUriForDigest(digest){const digestSuffix=digest?`@${digest}`:"";return this.repositoryUriWithSuffix(digestSuffix)}repositoryUriForTagOrDigest(tagOrDigest){return tagOrDigest?.startsWith("sha256:")?this.repositoryUriForDigest(tagOrDigest):this.repositoryUriForTag(tagOrDigest)}repositoryUriWithSuffix(suffix){const parts=this.stack.splitArn(this.repositoryArn,core_1().ArnFormat.SLASH_RESOURCE_NAME);return`${parts.account}.dkr.ecr.${parts.region}.${this.stack.urlSuffix}/${this.repositoryName}${suffix}`}onCloudTrailEvent(id,options={}){try{jsiiDeprecationWarnings().aws_cdk_lib_aws_events_OnEventOptions(options)}catch(error){throw process.env.JSII_DEBUG!=="1"&&error.name==="DeprecationError"&&Error.captureStackTrace(error,this.onCloudTrailEvent),error}const rule=new(events()).Rule(this,id,options);return rule.addTarget(options.target),rule.addEventPattern({source:["aws.ecr"],detailType:["AWS API Call via CloudTrail"],detail:{requestParameters:{repositoryName:[this.repositoryName]}}}),rule}onCloudTrailImagePushed(id,options={}){try{jsiiDeprecationWarnings().aws_cdk_lib_aws_ecr_OnCloudTrailImagePushedOptions(options)}catch(error){throw process.env.JSII_DEBUG!=="1"&&error.name==="DeprecationError"&&Error.captureStackTrace(error,this.onCloudTrailImagePushed),error}const rule=this.onCloudTrailEvent(id,options);return rule.addEventPattern({detail:{eventName:["PutImage"],requestParameters:{imageTag:options.imageTag?[options.imageTag]:void 0}}}),rule}onImageScanCompleted(id,options={}){try{jsiiDeprecationWarnings().aws_cdk_lib_aws_ecr_OnImageScanCompletedOptions(options)}catch(error){throw process.env.JSII_DEBUG!=="1"&&error.name==="DeprecationError"&&Error.captureStackTrace(error,this.onImageScanCompleted),error}const rule=new(events()).Rule(this,id,options);return rule.addTarget(options.target),rule.addEventPattern({source:["aws.ecr"],detailType:["ECR Image Scan"],detail:{"repository-name":[this.repositoryName],"scan-status":["COMPLETE"],"image-tags":options.imageTags??void 0}}),rule}onEvent(id,options={}){try{jsiiDeprecationWarnings().aws_cdk_lib_aws_events_OnEventOptions(options)}catch(error){throw process.env.JSII_DEBUG!=="1"&&error.name==="DeprecationError"&&Error.captureStackTrace(error,this.onEvent),error}const rule=new(events()).Rule(this,id,options);return rule.addEventPattern({source:["aws.ecr"],detail:{"repository-name":[this.repositoryName]}}),rule.addTarget(options.target),rule}grant(grantee,...actions){try{jsiiDeprecationWarnings().aws_cdk_lib_aws_iam_IGrantable(grantee)}catch(error){throw process.env.JSII_DEBUG!=="1"&&error.name==="DeprecationError"&&Error.captureStackTrace(error,this.grant),error}const crossAccountPrincipal=this.unsafeCrossAccountResourcePolicyPrincipal(grantee);if(crossAccountPrincipal){const crossAccountPrincipalStack=core_1().Stack.of(crossAccountPrincipal),roleTag=`${crossAccountPrincipalStack.stackName}_${crossAccountPrincipal.node.addr}`;return core_1().Tags.of(crossAccountPrincipal).add("aws-cdk:id",roleTag),this.addToResourcePolicy(new(iam()).PolicyStatement({actions,principals:[new(iam()).AccountPrincipal(crossAccountPrincipalStack.account)],conditions:{StringEquals:{"aws:PrincipalTag/aws-cdk:id":roleTag}}})),iam().Grant.addToPrincipal({grantee,actions,resourceArns:[this.repositoryArn],scope:this})}else return iam().Grant.addToPrincipalOrResource({grantee,actions,resourceArns:[this.repositoryArn],resourceSelfArns:[],resource:this})}grantRead(grantee){try{jsiiDeprecationWarnings().aws_cdk_lib_aws_iam_IGrantable(grantee)}catch(error){throw process.env.JSII_DEBUG!=="1"&&error.name==="DeprecationError"&&Error.captureStackTrace(error,this.grantRead),error}return this.grant(grantee,"ecr:DescribeRepositories","ecr:DescribeImages")}grantPull(grantee){try{jsiiDeprecationWarnings().aws_cdk_lib_aws_iam_IGrantable(grantee)}catch(error){throw process.env.JSII_DEBUG!=="1"&&error.name==="DeprecationError"&&Error.captureStackTrace(error,this.grantPull),error}const ret=this.grant(grantee,...this.REPO_PULL_ACTIONS);return iam().Grant.addToPrincipal({grantee,actions:["ecr:GetAuthorizationToken"],resourceArns:["*"],scope:this}),ret}grantPush(grantee){try{jsiiDeprecationWarnings().aws_cdk_lib_aws_iam_IGrantable(grantee)}catch(error){throw process.env.JSII_DEBUG!=="1"&&error.name==="DeprecationError"&&Error.captureStackTrace(error,this.grantPush),error}const ret=this.grant(grantee,...this.REPO_PUSH_ACTIONS);return iam().Grant.addToPrincipal({grantee,actions:["ecr:GetAuthorizationToken"],resourceArns:["*"],scope:this}),ret}grantPullPush(grantee){try{jsiiDeprecationWarnings().aws_cdk_lib_aws_iam_IGrantable(grantee)}catch(error){throw process.env.JSII_DEBUG!=="1"&&error.name==="DeprecationError"&&Error.captureStackTrace(error,this.grantPullPush),error}const ret=this.grant(grantee,...this.REPO_PULL_ACTIONS,...this.REPO_PUSH_ACTIONS);return iam().Grant.addToPrincipal({grantee,actions:["ecr:GetAuthorizationToken"],resourceArns:["*"],scope:this}),ret}unsafeCrossAccountResourcePolicyPrincipal(grantee){const principal=grantee.grantPrincipal,principalAccount=principal.principalAccount;if(!principalAccount)return;const repoAndPrincipalAccountCompare=core_1().Token.compareStrings(this.env.account,principalAccount);if(repoAndPrincipalAccountCompare===core_1().TokenComparison.BOTH_UNRESOLVED||repoAndPrincipalAccountCompare===core_1().TokenComparison.SAME||!iam().principalIsOwnedResource(principal))return;const principalStack=core_1().Stack.of(principal);if(!this.stack.dependencies.includes(principalStack))return principal}}exports.RepositoryBase=RepositoryBase,_a=JSII_RTTI_SYMBOL_1,RepositoryBase[_a]={fqn:"aws-cdk-lib.aws_ecr.RepositoryBase",version:"2.160.0"};class Repository extends RepositoryBase{static fromRepositoryAttributes(scope,id,attrs){try{jsiiDeprecationWarnings().aws_cdk_lib_aws_ecr_RepositoryAttributes(attrs)}catch(error){throw process.env.JSII_DEBUG!=="1"&&error.name==="DeprecationError"&&Error.captureStackTrace(error,this.fromRepositoryAttributes),error}class Import extends RepositoryBase{constructor(){super(...arguments),this.repositoryName=attrs.repositoryName,this.repositoryArn=attrs.repositoryArn}addToResourcePolicy(_statement){return{statementAdded:!1}}}return new Import(scope,id)}static fromRepositoryArn(scope,id,repositoryArn){if(core_1().Token.isUnresolved(repositoryArn))throw new Error('"repositoryArn" is a late-bound value, and therefore "repositoryName" is required. Use `fromRepositoryAttributes` instead');validateRepositoryArn();const repositoryName=repositoryArn.split("/").slice(1).join("/");class Import extends RepositoryBase{constructor(){super(...arguments),this.repositoryName=repositoryName,this.repositoryArn=repositoryArn}addToResourcePolicy(_statement){return{statementAdded:!1}}}return new Import(scope,id,{environmentFromArn:repositoryArn});function validateRepositoryArn(){const splitArn=repositoryArn.split(":");if(!splitArn[splitArn.length-1].startsWith("repository/"))throw new Error(`Repository arn should be in the format 'arn:<PARTITION>:ecr:<REGION>:<ACCOUNT>:repository/<NAME>', got ${repositoryArn}.`)}}static fromRepositoryName(scope,id,repositoryName){class Import extends RepositoryBase{constructor(){super(...arguments),this.repositoryName=repositoryName,this.repositoryArn=Repository.arnForLocalRepository(repositoryName,scope)}addToResourcePolicy(_statement){return{statementAdded:!1}}}return new Import(scope,id)}static arnForLocalRepository(repositoryName,scope,account){return core_1().Stack.of(scope).formatArn({account,service:"ecr",resource:"repository",resourceName:repositoryName})}static validateRepositoryName(physicalName){const repositoryName=physicalName;if(!repositoryName||core_1().Token.isUnresolved(repositoryName))return;const errors=[];if((repositoryName.length<2||repositoryName.length>256)&&errors.push("Repository name must be at least 2 and no more than 256 characters"),/^(?:[a-z0-9]+(?:[._-][a-z0-9]+)*\/)*[a-z0-9]+(?:[._-][a-z0-9]+)*$/.test(repositoryName)||errors.push("Repository name must start with a letter and can only contain lowercase letters, numbers, hyphens, underscores, periods and forward slashes"),errors.length>0)throw new Error(`Invalid ECR repository name (value: ${repositoryName})${os_1().EOL}${errors.join(os_1().EOL)}`)}constructor(scope,id,props={}){super(scope,id,{physicalName:props.repositoryName}),this.lifecycleRules=new Array;try{jsiiDeprecationWarnings().aws_cdk_lib_aws_ecr_RepositoryProps(props)}catch(error){throw process.env.JSII_DEBUG!=="1"&&error.name==="DeprecationError"&&Error.captureStackTrace(error,Repository),error}Repository.validateRepositoryName(this.physicalName);const resource=new(ecr_generated_1()).CfnRepository(this,"Resource",{repositoryName:this.physicalName,repositoryPolicyText:core_1().Lazy.any({produce:()=>this.policyDocument}),lifecyclePolicy:core_1().Lazy.any({produce:()=>this.renderLifecyclePolicy()}),imageScanningConfiguration:props.imageScanOnPush!==void 0?{scanOnPush:props.imageScanOnPush}:void 0,imageTagMutability:props.imageTagMutability||void 0,encryptionConfiguration:this.parseEncryption(props),emptyOnDelete:props.emptyOnDelete});if(this._resource=resource,resource.applyRemovalPolicy(props.removalPolicy),this.registryId=props.lifecycleRegistryId,props.lifecycleRules&&props.lifecycleRules.forEach(this.addLifecycleRule.bind(this)),this.repositoryName=this.getResourceNameAttribute(resource.ref),this.repositoryArn=this.getResourceArnAttribute(resource.attrArn,{service:"ecr",resource:"repository",resourceName:this.physicalName}),props.emptyOnDelete&&props.removalPolicy!==core_1().RemovalPolicy.DESTROY)throw new Error("Cannot use 'emptyOnDelete' property on a repository without setting removal policy to 'DESTROY'.");if(props.emptyOnDelete==null&&props.autoDeleteImages){if(props.removalPolicy!==core_1().RemovalPolicy.DESTROY)throw new Error("Cannot use 'autoDeleteImages' property on a repository without setting removal policy to 'DESTROY'.");this.enableAutoDeleteImages()}this.node.addValidation({validate:()=>this.policyDocument?.validateForResourcePolicy()??[]})}addToResourcePolicy(statement){try{jsiiDeprecationWarnings().aws_cdk_lib_aws_iam_PolicyStatement(statement)}catch(error){throw process.env.JSII_DEBUG!=="1"&&error.name==="DeprecationError"&&Error.captureStackTrace(error,this.addToResourcePolicy),error}return statement.resources.length&&core_1().Annotations.of(this).addWarningV2("@aws-cdk/aws-ecr:noResourceStatements","ECR resource policy does not allow resource statements."),this.policyDocument===void 0&&(this.policyDocument=new(iam()).PolicyDocument),this.policyDocument.addStatements(statement),{statementAdded:!0,policyDependable:this.policyDocument}}addLifecycleRule(rule){try{jsiiDeprecationWarnings().aws_cdk_lib_aws_ecr_LifecycleRule(rule)}catch(error){throw process.env.JSII_DEBUG!=="1"&&error.name==="DeprecationError"&&Error.captureStackTrace(error,this.addLifecycleRule),error}if(rule.tagStatus===void 0&&(rule={...rule,tagStatus:rule.tagPrefixList===void 0&&rule.tagPatternList===void 0?lifecycle_1().TagStatus.ANY:lifecycle_1().TagStatus.TAGGED}),rule.tagStatus===lifecycle_1().TagStatus.TAGGED&&(rule.tagPrefixList===void 0||rule.tagPrefixList.length===0)&&(rule.tagPatternList===void 0||rule.tagPatternList.length===0))throw new Error("TagStatus.Tagged requires the specification of a tagPrefixList or a tagPatternList");if(rule.tagStatus!==lifecycle_1().TagStatus.TAGGED&&(rule.tagPrefixList!==void 0||rule.tagPatternList!==void 0))throw new Error("tagPrefixList and tagPatternList can only be specified when tagStatus is set to Tagged");if(rule.tagPrefixList!==void 0&&rule.tagPatternList!==void 0)throw new Error("Both tagPrefixList and tagPatternList cannot be specified together in a rule");if(rule.tagPatternList!==void 0&&rule.tagPatternList.forEach(pattern=>{const splitPatternLength=pattern.split("*").length;if(splitPatternLength>5)throw new Error(`A tag pattern cannot contain more than four wildcard characters (*), pattern: ${pattern}, counts: ${splitPatternLength-1}`)}),rule.maxImageAge!==void 0==(rule.maxImageCount!==void 0))throw new Error(`Life cycle rule must contain exactly one of 'maxImageAge' and 'maxImageCount', got: ${JSON.stringify(rule)}`);if(rule.tagStatus===lifecycle_1().TagStatus.ANY&&this.lifecycleRules.filter(r=>r.tagStatus===lifecycle_1().TagStatus.ANY).length>0)throw new Error("Life cycle can only have one TagStatus.Any rule");this.lifecycleRules.push({...rule})}renderLifecyclePolicy(){const stack=core_1().Stack.of(this);let lifecyclePolicyText;if(!(this.lifecycleRules.length===0&&!this.registryId))return this.lifecycleRules.length>0&&(lifecyclePolicyText=JSON.stringify(stack.resolve({rules:this.orderedLifecycleRules().map(renderLifecycleRule)}))),{lifecyclePolicyText,registryId:this.registryId}}orderedLifecycleRules(){if(this.lifecycleRules.length===0)return[];const prioritizedRules=this.lifecycleRules.filter(r=>r.rulePriority!==void 0&&r.tagStatus!==lifecycle_1().TagStatus.ANY),autoPrioritizedRules=this.lifecycleRules.filter(r=>r.rulePriority===void 0&&r.tagStatus!==lifecycle_1().TagStatus.ANY),anyRules=this.lifecycleRules.filter(r=>r.tagStatus===lifecycle_1().TagStatus.ANY);if(anyRules.length>0&&anyRules[0].rulePriority!==void 0&&autoPrioritizedRules.length>0)throw new Error("Cannot combine prioritized TagStatus.Any rule with unprioritized rules. Remove rulePriority from the 'Any' rule.");const prios=prioritizedRules.map(r=>r.rulePriority);let autoPrio=(prios.length>0?Math.max(...prios):0)+1;const ret=new Array;for(const rule of prioritizedRules.concat(autoPrioritizedRules).concat(anyRules))ret.push({...rule,rulePriority:rule.rulePriority??autoPrio++});return validateAnyRuleLast(ret),ret}parseEncryption(props){const encryptionType=props.encryption??(props.encryptionKey?RepositoryEncryption.KMS:RepositoryEncryption.AES_256);if(encryptionType!==RepositoryEncryption.KMS&&props.encryptionKey)throw new Error(`encryptionKey is specified, so 'encryption' must be set to KMS (value: ${encryptionType.value})`);if(encryptionType!==RepositoryEncryption.AES_256){if(encryptionType===RepositoryEncryption.KMS)return{encryptionType:"KMS",kmsKey:props.encryptionKey?.keyArn};throw new Error(`Unexpected 'encryptionType': ${encryptionType}`)}}enableAutoDeleteImages(){const firstTime=core_1().Stack.of(this).node.tryFindChild(`${AUTO_DELETE_IMAGES_RESOURCE_TYPE}CustomResourceProvider`)===void 0,provider=auto_delete_images_provider_generated_1().AutoDeleteImagesProvider.getOrCreateProvider(this,AUTO_DELETE_IMAGES_RESOURCE_TYPE,{useCfnResponseWrapper:!1,description:`Lambda function for auto-deleting images in ${this.repositoryName} repository.`});firstTime&&provider.addToRolePolicy({Effect:"Allow",Action:["ecr:BatchDeleteImage","ecr:DescribeRepositories","ecr:ListImages","ecr:ListTagsForResource"],Resource:[`arn:${core_1().Aws.PARTITION}:ecr:${core_1().Stack.of(this).region}:${core_1().Stack.of(this).account}:repository/*`],Condition:{StringEquals:{["ecr:ResourceTag/"+AUTO_DELETE_IMAGES_TAG]:"true"}}}),new(core_1()).CustomResource(this,"AutoDeleteImagesCustomResource",{resourceType:AUTO_DELETE_IMAGES_RESOURCE_TYPE,serviceToken:provider.serviceToken,properties:{RepositoryName:this.repositoryName}}).node.addDependency(this),core_1().Tags.of(this._resource).add(AUTO_DELETE_IMAGES_TAG,"true")}}exports.Repository=Repository,_b=JSII_RTTI_SYMBOL_1,Repository[_b]={fqn:"aws-cdk-lib.aws_ecr.Repository",version:"2.160.0"};function validateAnyRuleLast(rules){const anyRules=rules.filter(r=>r.tagStatus===lifecycle_1().TagStatus.ANY);if(anyRules.length===1){const maxPrio=Math.max(...rules.map(r=>r.rulePriority));if(anyRules[0].rulePriority!==maxPrio)throw new Error(`TagStatus.Any rule must have highest priority, has ${anyRules[0].rulePriority} which is smaller than ${maxPrio}`)}}function renderLifecycleRule(rule){return{rulePriority:rule.rulePriority,description:rule.description,selection:{tagStatus:rule.tagStatus||lifecycle_1().TagStatus.ANY,tagPrefixList:rule.tagPrefixList,tagPatternList:rule.tagPatternList,countType:rule.maxImageAge!==void 0?CountType.SINCE_IMAGE_PUSHED:CountType.IMAGE_COUNT_MORE_THAN,countNumber:rule.maxImageAge?.toDays()??rule.maxImageCount,countUnit:rule.maxImageAge!==void 0?"days":void 0},action:{type:"expire"}}}var CountType;(function(CountType2){CountType2.IMAGE_COUNT_MORE_THAN="imageCountMoreThan",CountType2.SINCE_IMAGE_PUSHED="sinceImagePushed"})(CountType||(CountType={}));var TagMutability;(function(TagMutability2){TagMutability2.MUTABLE="MUTABLE",TagMutability2.IMMUTABLE="IMMUTABLE"})(TagMutability||(exports.TagMutability=TagMutability={}));class RepositoryEncryption{constructor(value){this.value=value}}exports.RepositoryEncryption=RepositoryEncryption,_c=JSII_RTTI_SYMBOL_1,RepositoryEncryption[_c]={fqn:"aws-cdk-lib.aws_ecr.RepositoryEncryption",version:"2.160.0"},RepositoryEncryption.AES_256=new RepositoryEncryption("AES256"),RepositoryEncryption.KMS=new RepositoryEncryption("KMS");