Skip to main content

How to use S3 with Bun

· 2 min read
Ivan Barlog
AWS Solutions Architect @ BeeSolve

When I was trying Bun S3 client for the first time I was surprised that there is no option to pass AWS profile name as credentials. This post is just a quick memo for me to remember how this can be achieved.

The Bun's documentation describes that if you want to use S3 client you need to provide both accessKeyId and secretAccessKey. This seems a bit impractical for the first glance for usage in local development.

When we try to follow security best practice we probably don't want to generate long lived AWS credentials, nor we want to store those on disk or even within the code.

The best practice in my opinion is to use IAM Identity Center + AWS SSO like this:

aws sso login --profile main

This command when set up properly generates short lived credentials. We can then access these credentials by using AWS_PROFILE=main environment variable.

In order to use credentials defined by profile in AWS SDK S3 Client we still need to use AWS Credential Providers library like this:

import { S3Client } from "@aws-sdk/client-s3";
import { fromIni } from "@aws-sdk/credential-providers";

const s3Client = new S3Client({
credentials: fromIni({
profile: 'main'
})
});

Unfortunately this is not the option with Bun's client. However we can reuse @aws-sdk/credential-providers to achieve the same thing like this:

import { fromIni } from "@aws-sdk/credential-providers";
import { s3 } from "bun";

const {
accessKeyId,
secretAccessKey,
sessionToken,
} = await fromIni({ profile: "main" })();

// read file from S3
const file = s3.file("s3-key", {
accessKeyId,
secretAccessKey,
sessionToken,
bucket: "your-bucket-name", // might be set through AWS_BUCKET or S3_BUCKET environment variable
});

// write file to S3 - yes, write returns promise
await Bun.s3.write("test.txt", "test data", {
accessKeyId,
secretAccessKey,
sessionToken,
bucket: "your-bucket-name", // might be set through AWS_BUCKET or S3_BUCKET environment variable
region: "eu-central-1", // do not forget to provide region if not set via AWS_REGION or S3_REGION environment variable
}),

That's all. Go build stuff now!