Last updated: Jan 26, 2024
Reading timeยท4 min
The easiest way to import an existing S3 bucket into a CDK stack is to use the static fromBucketName method on the Bucket class.
import * as iam from 'aws-cdk-lib/aws-iam'; import * as s3 from 'aws-cdk-lib/aws-s3'; import * as cdk from 'aws-cdk-lib'; export class CdkStarterStack extends cdk.Stack { constructor(scope: cdk.App, id: string, props?: cdk.StackProps) { super(scope, id, props); const importedBucketFromName = s3.Bucket.fromBucketName( this, 'imported-bucket-from-name', 'YOUR_EXTERNAL_BUCKET_NAME', ); console.log('bucket name ๐', importedBucketFromName.bucketName); console.log('bucket arn ๐', importedBucketFromName.bucketArn); // ๐ using methods on the imported bucket importedBucketFromName.grantRead(new iam.AccountRootPrincipal()); } }
We used the fromBucketName
static method to import an external
S3 Bucket by name.
After we have imported the bucket into our CDK stack, we can use the associated methods. For example, to grant read permissions to a Lambda function.
If I synthesize the stack with npx aws-cdk synth
command, we can see that CDK
is able to infer the bucket name based on our input to the fromBucketName
method.
The only unresolved value is the partition, which CDK is not able to infer from the bucket name.
You could pass the bucket's name to your CDK stack as an environment variable, in CDK context, or via a parameter.
In order to import an existing S3 bucket by ARN in AWS CDK, we have to use the static fromBucketArn method on the Bucket class.
import * as s3 from 'aws-cdk-lib/aws-s3'; import * as cdk from 'aws-cdk-lib'; export class CdkStarterStack extends cdk.Stack { constructor(scope: cdk.App, id: string, props?: cdk.StackProps) { super(scope, id, props); const importedBucketFromArn = s3.Bucket.fromBucketArn( this, 'imported-bucket-from-arn', 'arn:aws:s3:::YOUR_EXTERNAL_BUCKET_NAME', ); console.log('bucket name ๐', importedBucketFromArn.bucketName); console.log('bucket arn ๐', importedBucketFromArn.bucketArn); } }
We used the fromBucketArn
static method to import an external S3 bucket into
our CDK stack.
Same as with fromBucketName
, we can use the methods associated with the class
after we've imported the bucket.
Based on the ARN we passed in the call to fromBucketArn
, CDK is able to infer
the bucket name and bucket ARN at synthesis time:
In order to import an existing S3 bucket by Attributes in CDK, we have to use the static fromBucketAttributes method on the Bucket class.
import * as s3 from 'aws-cdk-lib/aws-s3'; import * as cdk from 'aws-cdk-lib'; export class CdkStarterStack extends cdk.Stack { constructor(scope: cdk.App, id: string, props?: cdk.StackProps) { super(scope, id, props); const importedBucketFromAttributes = s3.Bucket.fromBucketAttributes( this, 'imported-bucket-from-attributes', { bucketArn: 'arn:aws:s3:::YOUR_EXTERNAL_BUCKET_NAME', region: 'SOME_OTHER_REGION', }, ); console.log('bucket name ๐', importedBucketFromAttributes.bucketName); console.log('bucket arn ๐', importedBucketFromAttributes.bucketArn); } }
You would use the fromBucketAttributes
method if the region name of the
external bucket differs from the region the CDK stack is configured for.
By default, the region
property for the bucket is inferred from the CDK
stack's region.
Since the region of the bucket is not present in the ARN, there isn't a good way for CDK to infer it, other than to assume the bucket's region is the same as the CDK stack's region.
To import existing resources in CDK we have to use the static fromResource*
methods on the resource's construct, for instance:
the S3 Bucket construct exposes the fromBucketArn, fromBucketName and fromBucketAttributes static methods
the Dynamodb Table construct exposes the fromTableArn, fromTableName and fromTableAttributes static methods
the Lambda Function construct exposes the fromFunctionArn, fromFunctionAttributes static methods
As a general rule of thumb, we use the fromResourceName
and fromResourceArn
methods unless we don't have access to the name
or ARN
of the resource, in
which case we use the fromResourceAttributes
method.
To import an existing bucket by name into a CDK stack, we can use the fromBucketName static method:
const existingBucketFromName = s3.Bucket.fromBucketName( this, 'bucket-from-name-id', 'YOUR_BUCKET_NAME', ); console.log('existingBucketFromName ๐ ', existingBucketFromName.bucketName);
If I now run the cdk synth
command, we can see that the value is resolved at
synthesis time.
To import an existing bucket by ARN we can use the fromBucketArn static method.
const existingBucketFromArn = s3.Bucket.fromBucketArn( this, 'bucket-from-arn-id', 'YOUR_BUCKET_ARN', );
And to import an existing bucket from Attributes, we use the fromBucketAttributes static method.
const existingBucketFromAttributes = s3.Bucket.fromBucketAttributes( this, 'bucket-from-attributes-id', { region: 'us-east-1', bucketArn: 'arn:aws:s3:::YOUR_BUCKET_NAME', }, );
All of the above methods resolve at synthesis time.
Most Level 2 Constructs
implement at least 2 of the 3 fromResource*
methods.
For example, to import an existing Dynamodb table by name, we have to use the fromTableName static method.
const existingTableFromName = dynamodb.Table.fromTableName( this, 'table-from-name-id', 'YOUR_TABLE_NAME', ); console.log('existingTableFromName ๐ ', existingTableFromName.tableName);
The value again resolves at synthesis time.
To import an existing table from ARN we have to use the fromTableArn static method:
const existingTableFromArn = dynamodb.Table.fromTableArn('YOUR_TABLE_ARN');
And to import an existing table from attributes we have to use the fromTableAttributes static method.
const existingTableFromAttributes = dynamodb.Table.fromTableAttributes( this, 'table-from-attributes-id', { tableName: 'YOUR_TABLE_NAME', }, );
It's quite repetitive once we know what the naming convention of the methods is.
Most of the time we end up using the fromResourceName
and fromResourceArn
methods, and resort to using fromResourceAttributes
when we don't have the
name or the ARN of the resource.
You can learn more about the related topics by checking out the following tutorials: