AWS S3 Bucket getSignedUrl() giving me error Cannot read properties of undefined (reading 'clone') - amazon-web-services

const S3 = require('aws-sdk/clients/s3');
const { getSignedUrl } = require("#aws-sdk/s3-request-presigner");
const { S3Client, GetObjectCommand } = require("#aws-sdk/client-s3");
dotenv.config();
const bucketName = process.env.AWS_BUCKET_NAME
const region = process.env.AWS_BUCKET_REGION
const accessKeyId = process.env.AWS_ACCESS_KEY
const secretAccessKey = process.env.AWS_SECRET_KEY
const s3 = new S3({
region,
accessKeyId,
secretAccessKey
})
router.get("/:id", async (req, res) => {
try {
const post = await Post.findById(req.params.id);
const getObjectParams = {
Bucket: bucketName,
Key: post.photo,
}
const command = new GetObjectCommand(getObjectParams);
const url = await getSignedUrl(s3, command, { expiresIn: 3600 });
post.imageUrl = url
res.status(200).json(post);
} catch (err) {
console.error('errorrr', err);
res.status(500).json(err);
}
});
Here is my code I've console logged post, getObjectParams, command and everything is there but when I console log url it's not logging and when I console.log errorrr it logs Cannot read properties of undefined (reading 'clone')
What is the issue here?
I think issue is with function getSignedUrl, but not sure what it is

Related

Print the JSON value from AWS S3 bucket in Lambda function

What is the way to get the response body of the uploaded JSON file to the lambda function to print it?
I used the following code but it is specified for Content Type. Any suggestions for this please?
// console.log('Loading function');
const aws = require('aws-sdk');
const s3 = new aws.S3({ apiVersion: '2006-03-01' });
exports.handler = async (event, context) => {
//console.log('Received event:', JSON.stringify(event, null, 2));
// Get the object from the event and show its content type
const bucket = event.Records[0].s3.bucket.name;
const key = decodeURIComponent(event.Records[0].s3.object.key.replace(/\+/g, ' '));
const params = {
Bucket: bucket,
Key: key,
};
try {
const { ContentType } = await s3.getObject(params).promise();
console.log('CONTENT TYPE:', ContentType);
console.log('Body: ', );
console.log("response: " + "I want to print the response body here when a JSON file uploaded")
return ContentType;
} catch (err) {
console.log(err);
const message = `Error getting object ${key} from bucket ${bucket}. Error : ` + err;
console.log(message);
throw new Error(message);
}
};
return value of getObject contains Body field.
const { ContentType, Body } = await s3.getObject(params).promise();
console.log('CONTENT TYPE:', ContentType);
console.log('Body: ', Body);

Error while trying to verify file in aws s3 using cypress

Cypress.Commands.add('verifyfilesinS3', (filename) => {
const AWS = require('aws-sdk');
var fileExists;
AWS.config.update({
accessKeyId: "",
accessSecretKey: "",
region: ""
});
const s3 = new AWS.S3();
const params = {
Bucket: "",
Key: ""
};
const result = s3.headObject(params, (err, data) => { // Check if the file exists
if (err) {
if (err.code === 'NotFound') {
console.log(`File "${params.Key}" does not exist in the "${params.Bucket}" bucket.`);
fileExists = 0
} else {
console.error(err);
fileExists = err
}
} else {
fileExists = 2
console.log(`File "${params.Key}" exists in the "${params.Bucket}" bucket.`);
}
});
return fileExists;
});
I am first trying to directly hardcode the values and test but still fails with the error "CredentialsError: Missing credentials in config, if using AWS_CONFIG_FILE, set AWS_SDK_LOAD_CONFIG=1"
enter image description here
When I run the same code individually in node.js , it works as expected.

Download document from Amazon S3 and send to Xero

I am exploring how to download document from Amazon S3 and then save it as an attachment on a Xero Invoice. Can I have help on this task?
I am referencing my code using these two links:
API
Link
createInvoiceAttachmentByFileName
https://xeroapi.github.io/xero-node/accounting/index.html#api-Accounting-createInvoiceAttachmentByFileName
s3 getObject
https://www.tabnine.com/code/javascript/functions/aws-sdk/S3/getObject
Error: I keep receiving this error while sending it to Xero.
TypeError: body.on is not a function
Main
const sendInvoicesResponse = await xeroService.sendDocument(
mappedDocumentData,
integration.tenant.id,
);
const downloadedDocument = await awsService.downloadDocument(document.key);
await xeroService.sendAttachmentToInvoice(
integration.tenant.id,
sendInvoicesResponse.body.invoices[0].invoiceID,
document.name,
downloadedDocument.data,
downloadedDocument.mimetype,
);
AWS Service
module.exports.downloadDocument = async (key) => {
try {
const getParams = {
Bucket: config.aws.documentsBucket, // your bucket name,
Key: key,
};
const file = await s3.getObject(getParams).promise();
return {
data: file.Body,
mimetype: file.ContentType,
};
} catch (error) {
logger.error(`download document from AWS fail | message=${message}`);
throw new Error(message);
}
};
In Xero
module.exports.sendAttachmentToInvoice = async (
tenantId,
invoiceId,
fileName,
body,
contentType,
includeOnline = true,
) => {
try {
return client.accountingApi.createInvoiceAttachmentByFileName(
tenantId,
invoiceId,
fileName,
body,
includeOnline,
{
headers: {
'Content-Type': contentType,
},
},
);
} catch (error) {
logger.error(`attaching file attachment to xero fail | message=${message}`);
throw new Error(message);
}
};

AWS Cognito client SDK v3 returns 'byteLength' of undefined when running Admin disable user command

I am trying to disable users from my node JS backend using the AWS SDK v3. everything works normally except for the disable/enable user command.
I have tried everything I know but here is my code snippet:
const aws_creds = {
accessKeyId: process.env.ACCESS_KEY_ID,
secretAccessKey: process.env.SECRET_ACCESS_KEY,
};
const cognitoConfig = {
region: process.env.REGION,
credentials: aws_creds,
};
const cognito_v3 = new CognitoIdentityProviderClient(cognitoConfig);
Then in my route I am running this try / catch block
try {
if (status === "enable") {
const enableUserCommand = new AdminEnableUserCommand(userDetails);
const enableUserResults = await cognito_v3.send(enableUserCommand);
return res.status(200).json(enableUserResults);
}
const disableUserCommand = new AdminDisableUserCommand(userDetails);
const disableUserResults = await cognito_v3.send(disableUserCommand);
return res.status(200).json(disableUserResults);
} catch (err) {
console.log(err);
return res.status(400).json(err);
}
However, the err console log returns this:
TypeError: Cannot read property 'byteLength' of undefined
at Object.fromArrayBuffer (C:\Users\SER-01\Documents\ctr\simsim\simsim-backend\lambdas\simsim-auth\node_modules\#aws-sdk\util-buffer-from\dist\cjs\index.js:6:60)
at castSourceData (C:\Users\SER-01\Documents\ctr\simsim\simsim-backend\lambdas\simsim-auth\node_modules\#aws-sdk\hash-node\dist\cjs\index.js:29:31)
at Hash.update (C:\Users\SER-01\Documents\ctr\simsim\simsim-backend\lambdas\simsim-auth\node_modules\#aws-sdk\hash-node\dist\cjs\index.js:12:26)
at hmac (C:\Users\SER-01\Documents\ctr\simsim\simsim-backend\lambdas\simsim-auth\node_modules\#aws-sdk\signature-v4\dist\cjs\credentialDerivation.js:60:10)
at Object.getSigningKey (C:\Users\SER-01\Documents\ctr\simsim\simsim-backend\lambdas\simsim-auth\node_modules\#aws-sdk\signature-v4\dist\cjs\credentialDerivation.js:32:29)
at SignatureV4.getSigningKey (C:\Users\SER-01\Documents\ctr\simsim\simsim-backend\lambdas\simsim-auth\node_modules\#aws-sdk\signature-v4\dist\cjs\SignatureV4.js:139:39)
at SignatureV4.signRequest (C:\Users\SER-01\Documents\ctr\simsim\simsim-backend\lambdas\simsim-auth\node_modules\#aws-sdk\signature-v4\dist\cjs\SignatureV4.js:98:73)
at async C:\Users\SER-01\Documents\ctr\simsim\simsim-backend\lambdas\simsim-auth\node_modules\#aws-sdk\middleware-signing\dist\cjs\middleware.js:14:22
at async StandardRetryStrategy.retry (C:\Users\SER-01\Documents\ctr\simsim\simsim-backend\lambdas\simsim-auth\node_modules\#aws-sdk\middleware-retry\dist\cjs\defaultStrategy.js:56:46)
at async C:\Users\SER-01\Documents\ctr\simsim\simsim-backend\lambdas\simsim-auth\node_modules\#aws-sdk\middleware-logger\dist\cjs\loggerMiddleware.js:6:22
at async C:\Users\SER-01\Documents\ctr\simsim\simsim-backend\lambdas\simsim-auth\src\routes\auth.js:232:33 {
'$metadata': { attempts: 1, totalRetryDelay: 0 }
}
Any idea why?

How to Get Signed S3 Url in AWS-SDK JS Version 3?

I am following the proposed solution by Trivikr for adding support for s3.getSignedUrl api which is not currently available in newer v3. I am trying to make a signed url for getting an object from bucket.
Just for convenience, the code is being added below:
const { S3, GetObjectCommand } = require("#aws-sdk/client-s3"); // 1.0.0-gamma.2 version
const { S3RequestPresigner } = require("#aws-sdk/s3-request-presigner"); // 0.1.0-preview.2 version
const { createRequest } = require("#aws-sdk/util-create-request"); // 0.1.0-preview.2 version
const { formatUrl } = require("#aws-sdk/util-format-url"); // 0.1.0-preview.1 //version
const fetch = require("node-fetch");
(async () => {
try {
const region = "us-east-1";
const Bucket = `SOME_BUCKET_NAME`;
const Key = `SOME_KEY_VALUE`;
const credentials = {
accessKeyId: ACCESS_KEY_HERE,
secretAccessKey: SECRET_KEY_HERE,
sessionToken: SESSION_TOKEN_HERE
};
const S3Client = new S3({ region, credentials, signatureVersion: 'v4' });
console.log('1'); // for quick debugging
const signer = new S3RequestPresigner({ ...S3Client.config });
console.log('2')
const request = await createRequest(
S3Client,
new GetObjectCommand({ Key, Bucket })
);
console.log('3');
let signedUrl = formatUrl(await signer.presign(request));
console.log(signedUrl);
let response = await fetch(signedUrl);
console.log("Response", response);
}catch(e) {
console.error(e);
}
I successfully create S3Client and signer but on creating request, I get the following error:
clientStack.concat(...).filter is not a function
Anything wrong I am doing?
Please also note that I am using webpack for bundling
Just add my example in TypeScript:
import { S3Client, GetObjectCommand, S3ClientConfig } from '#aws-sdk/client-s3';
import { getSignedUrl } from '#aws-sdk/s3-request-presigner';
const s3Configuration: S3ClientConfig = {
credentials: {
accessKeyId: '<ACCESS_KEY_ID>',
secretAccessKey: '<SECRET_ACCESS_KEY>'
},
region: '<REGION>',
};
const s3 = new S3Client(s3Configuration);
const command = new GetObjectCommand({Bucket: '<BUCKET>', Key: '<KEY>' });
const url = await getSignedUrl(s3, command, { expiresIn: 15 * 60 }); // expires in seconds
console.log('Presigned URL: ', url);
RESOLVED
I ended up successfully making the signed urls by installing the beta versions rather than preview (default) ones