Reputation: 3440
I am scouring the documentation, and it only provides pseudo-code of the credentials for v3 (e.g. const client = new S3Client(clientParams)
How do I initialize an S3Client with the bucket and credentials to perform a getSignedUrl request? Any resources pointing me in the right direction would be most helpful. I've even searched YouTube, SO, etc and I can't find any specific info on v3. Even the documentation and examples doesn't provide the actual code to use credentials. Thanks!
As an aside, do I have to include the fake folder structure in the filename, or can I just use the actual filename? For example: bucket/folder1/folder2/uniqueFilename.zip or uniqueFilename.zip
Here's the code I have so far: (Keep in mind I was returning the wasabiObjKey
to ensure I was getting the correct file name. I am. It's the client, GetObjectCommand, and getSignedUrl that I'm having issues with.
exports.getPresignedUrl = functions.https.onCall(async (data, ctx) => {
const wasabiObjKey = `${data.bucket_prefix ? `${data.bucket_prefix}/` : ''}${data.uid.replace(/-/g, '_').toLowerCase()}${data.variation ? `_${data.variation.replace(/\./g, '').toLowerCase()}` : ''}.zip`
const { S3Client, GetObjectCommand } = require('@aws-sdk/client-s3')
const s3 = new S3Client({
bucketEndpoint: functions.config().s3_bucket.name,
region: functions.config().s3_bucket.region,
credentials: {
secretAccessKey: functions.config().s3.secret,
accessKeyId: functions.config().s3.access_key
}
})
const command = new GetObjectCommand({
Bucket: functions.config().s3_bucket.name,
Key: wasabiObjKey,
})
const { getSignedUrl } = require("@aws-sdk/s3-request-presigner")
const url = getSignedUrl(s3, command, { expiresIn: 60 })
return wasabiObjKey
})
Upvotes: 34
Views: 67572
Reputation: 29
Although the original question wasn't related directly to the use of credentials with authenticated Cognito user pool, I think it will be the case for others, like me.
I was looking for an answer to use the credentials in the Java AWS SDK v3 and set in the web browser. I found a VERY EASY solution in the AWS SDK for JavaScript v3 Guide.
This solution applies to modular app and you need to install two packages: the @aws-sdk/credential-providers and the @aws-sdk/client-cognito-identity. It is straightforward and you don't even need to worry about storing the credentials.
import { CognitoIdentityProviderClient } from "@aws-sdk/client-cognito-identity-provider";
import { fromCognitoIdentityPool } from "@aws-sdk/credential-providers";
// Get the Amazon Cognito ID token for the user. 'getToken()' below.
let idToken = getToken();
let COGNITO_ID = "COGNITO_ID"; // 'COGNITO_ID' has the format 'cognito-idp.REGION.amazonaws.com/COGNITO_USER_POOL_ID'
let loginData = {
[COGNITO_ID]: idToken,
};
const s3Client = new S3Client({
region: REGION,
credentials: fromCognitoIdentityPool({
clientConfig: { region: REGION }, // Configure the underlying CognitoIdentityClient.
identityPoolId: 'IDENTITY_POOL_ID',
logins: loginData
})
});
// Strips the token ID from the URL after authentication.
window.getToken = function () {
var idtoken = window.location.href;
var idtoken1 = idtoken.split("=")[1];
var idtoken2 = idtoken1.split("&")[0];
var idtoken3 = idtoken2.split("&")[0];
return idtoken3;
};
Likewise, if you would want to generate the credentials from a JWT from another provider, you can use the credentials-providers package with fromWebToken()
.
Upvotes: 0
Reputation: 5240
There is a credential chain that provides credentials to your API calls from the SDK https://docs.aws.amazon.com/sdk-for-javascript/v3/developer-guide/setting-credentials-node.html
Loaded from AWS Identity and Access Management (IAM) roles for Amazon EC2
Loaded from the shared credentials file (~/.aws/credentials)
Loaded from environment variables
Loaded from a JSON file on disk
Other credential-provider classes provided by the JavaScript SDK
You can embed the credential inside your source code but it's not the prefered way
new S3Client(configuration: S3ClientConfig): S3Client
Where S3ClientConfig contain a credentials
property
https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/clients/client-s3/modules/credentials.html
const { S3Client,GetObjectCommand } = require("@aws-sdk/client-s3");
let client = new S3Client({
region:'ap-southeast-1',
credentials:{
accessKeyId:'',
secretAccessKey:''
}
});
(async () => {
const response = await client.send(new GetObjectCommand({Bucket:"BucketNameHere",Key:"ObjectNameHere"}));
console.log(response);
})();
Sample answer
'$metadata': {
httpStatusCode: 200,
requestId: undefined,
extendedRequestId: '7kwrFkEp3lEnLU+OtxjrgdmS6gQmvPdbnqqR7I8P/rdFrUPBkdKYPYykWivuHPXCF1IHgjCIbe8=',
cfId: undefined,
attempts: 1,
totalRetryDelay: 0
},
Upvotes: 62
Reputation: 1764
This answer is basically the same as what's been said above, but for anyone who's migrating from v2 to v3 and not moving to the new modular model, you will find that your existing clients don't immediately work, because the expected credentials format is different. If you previously had…
new AWS.CloudWatch({
apiVersion: '2010-08-01',
region: event.region,
credentials: new AWS.Credentials(
role.Credentials.AccessKeyId,
role.Credentials.SecretAccessKey,
role.Credentials.SessionToken,
)
})
…you'll have to replace new AWS.Credentials
with an object:
new CloudWatch({
apiVersion: '2010-08-01',
region: event.region,
credentials: {
accessKeyId: role.Credentials.AccessKeyId,
secretAccessKey: role.Credentials.SecretAccessKey,
sessionToken: role.Credentials.SessionToken,
},
});
Upvotes: 4
Reputation: 301
Here's a simple approach I use (in Deno) for testing (in case you don't want to go the signedUrl approach and just let the SDK do the heavy lifting for you):
import { config as env } from 'https://deno.land/x/dotenv/mod.ts' // https://github.com/pietvanzoen/deno-dotenv
import { S3Client, ListObjectsV2Command } from 'https://cdn.skypack.dev/@aws-sdk/client-s3' // https://github.com/aws/aws-sdk-js-v3
const {AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY} = env()
// https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/clients/client-s3/modules/credentials.html
const credentials = {
accessKeyId: AWS_ACCESS_KEY_ID,
secretAccessKey: AWS_SECRET_ACCESS_KEY,
}
// https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/clients/client-s3/interfaces/s3clientconfig.html
const config = {
region: 'ap-southeast-1',
credentials,
}
// https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/clients/client-s3/classes/s3client.html
const client = new S3Client(config)
export async function list() {
// https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/clients/client-s3/interfaces/listobjectsv2commandinput.html
const input = {
Bucket: 'BucketNameHere'
}
// https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/clients/client-s3/classes/command.html
const cmd = new ListObjectsV2Command(input)
// https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/clients/client-s3/classes/listobjectsv2command.html
return await client.send(cmd)
}
Upvotes: 12