Work with Amazon S3 Multi-Region Access Points by using the SDK for Kotlin
Amazon S3 Multi-Region Access Points provide a global endpoint that applications can use to fulfill requests from Amazon S3 buckets located in multiple AWS Regions. You can use Multi-Region Access Points to build multi-Region applications with the same architecture used in a single Region, and then run those applications anywhere in the world.
The Amazon S3 User Guide contains more background information about Multi-Region Access Points.
Work with Multi-Region Access Points
To create a Multi-Region Access Point, start by specifying one bucket in each AWS Region that you want to serve requests. The following snippet creates two buckets.
The following function creates two buckets to work with the Multi-Region Access Point. One bucket
is in Region us-east-1
and the other is in Region
us-west-1
.
The creation of the S3 client that passed in as the first argument is shown in the first example under Work with objects and Multi-Region Access Points.
suspend fun setUpTwoBuckets( s3: S3Client, bucketName1: String, bucketName2: String, ) { println("Create two buckets in different regions.") // The shared aws config file configures the default Region to be us-east-1. s3.createBucket( CreateBucketRequest { bucket = bucketName1 }, ) s3.waitUntilBucketExists { bucket = bucketName1 } println(" Bucket [$bucketName1] created.") // Override the S3Client to work with us-west-1 for the second bucket. s3.withConfig { region = "us-west-1" }.use { s3West -> s3West.createBucket( CreateBucketRequest { bucket = bucketName2 createBucketConfiguration = CreateBucketConfiguration { locationConstraint = BucketLocationConstraint.UsWest1 } }, ) s3West.waitUntilBucketExists { bucket = bucketName2 } println(" Bucket [$bucketName2] created.") } }
You use the Kotlin SDK's S3 control client
Add a dependency on the S3 control artifact as shown in the following snippet.
... implementation("aws.sdk.kotlin:s3control:
1.0.52
") ...
The previous snippet shows the use of version
1.0.52
. Replace
1.0.52
with the latest
version
Configure the S3 control client to work with AWS Region us-west-2
as
shown in the following code. All S3 control client operations must target the
us-west-2
region.
suspend fun createS3ControlClient(): S3ControlClient { // Configure your S3ControlClient to send requests to US West (Oregon). val s3Control = S3ControlClient.fromEnvironment { region = "us-west-2" } return s3Control }
Use the S3 control client to create a Multi-Region Access Point by specifying the bucket names (created previously) as shown in the following code.
suspend fun createMrap( s3Control: S3ControlClient, accountIdParam: String, bucketName1: String, bucketName2: String, mrapName: String, ): String { println("Creating MRAP ...") val createMrapResponse: CreateMultiRegionAccessPointResponse = s3Control.createMultiRegionAccessPoint { accountId = accountIdParam clientToken = UUID.randomUUID().toString() details { name = mrapName regions = listOf( Region { bucket = bucketName1 }, Region { bucket = bucketName2 }, ) } } val requestToken: String? = createMrapResponse.requestTokenArn // Use the request token to check for the status of the CreateMultiRegionAccessPoint operation. if (requestToken != null) { waitForSucceededStatus(s3Control, requestToken, accountIdParam) println("MRAP created") } val getMrapResponse = s3Control.getMultiRegionAccessPoint( input = GetMultiRegionAccessPointRequest { accountId = accountIdParam name = mrapName }, ) val mrapAlias = getMrapResponse.accessPoint?.alias return "arn:aws:s3::$accountIdParam:accesspoint/$mrapAlias" }
Because the creation of a Multi-Region Access Point is an asynchronous operation, you use the token that
you receive from the immediate response to check on the status of the creation process.
After the status check returns a success message, you can use the
GetMultiRegionAccessPoint
operation to get the Multi-Region Access Point's alias. The
alias is the last component of the ARN, which you need for object-level operations.
Use the DescribeMultiRegionAccessPointOperation
to check the
status of the last operation. After the requestStatus
value becomes
"SUCCEEDED", you can work with the Multi-Region Access Point.
suspend fun waitForSucceededStatus( s3Control: S3ControlClient, requestToken: String, accountIdParam: String, timeBetweenChecks: Duration = 1.minutes, ) { var describeResponse: DescribeMultiRegionAccessPointOperationResponse describeResponse = s3Control.describeMultiRegionAccessPointOperation( input = DescribeMultiRegionAccessPointOperationRequest { accountId = accountIdParam requestTokenArn = requestToken }, ) var status: String? = describeResponse.asyncOperation?.requestStatus while (status != "SUCCEEDED") { delay(timeBetweenChecks) describeResponse = s3Control.describeMultiRegionAccessPointOperation( input = DescribeMultiRegionAccessPointOperationRequest { accountId = accountIdParam requestTokenArn = requestToken }, ) status = describeResponse.asyncOperation?.requestStatus println(status) } }
Work with objects and Multi-Region Access Points
You use the S3 client
Operations with Multi-Region Access Points are signed with the Asymmetric Sigv4 (Sigv4a) signing algorithm. Support for Sigv4a in the AWS SDK for Kotlin currently requires signing with the CRT signer which is a separate dependency. To configure support for Sigv4a, add the following dependencies to your project.
... implementation("aws.smithy.kotlin:aws-signing-crt:
1.0.10
") implementation("aws.smithy.kotlin:http-auth-aws:1.0.10
") implementation("aws.sdk.kotlin:s3:1.0.52
") ...
The previous snippet shows the use of version 1.0.10
.
Replace 1.0.10
with the latest
version
After you add the dependencies, configure the S3 client to use the Sigv4a signing algorithm as shown in the following code.
suspend fun createS3Client(): S3Client { // Configure your S3Client to use the Asymmetric Sigv4 (Sigv4a) signing algorithm. val sigV4AScheme = SigV4AsymmetricAuthScheme(CrtAwsSigner) val s3 = S3Client.fromEnvironment { authSchemes = listOf(sigV4AScheme) } return s3 }
After you configure the S3 client, operations that S3 supports for Multi-Region Access
Points work the same. The only difference is that the bucket parameter must be the ARN
of the Multi-Region Access Point. You can get the ARN from the Amazon S3 console or programmatically as shown
previously in the createMrap
function that returns an ARN.
The following code example shows the ARN used in a GetObject
operation.
suspend fun getObjectFromMrap( s3: S3Client, mrapArn: String, keyName: String, ): String? { val request = GetObjectRequest { bucket = mrapArn // Use the ARN instead of the bucket name for object operations. key = keyName } var stringObj: String? = null s3.getObject(request) { resp -> stringObj = resp.body?.decodeToString() if (stringObj != null) { println("Successfully read $keyName from $mrapArn") } } return stringObj }