Reputation: 1
AWS-hosted Alexa skills offer 3 lambda functions, one S3 bucket and one DynamoDB database; but give you very little control over the databases and ultimately they are constrained in size.
I want to extend the S3 storage offered by Amazon for my Alexa Skill to additionally use my personal AWS S3 storage. Using this weblink I have managed to add my personal DynamoDB additionally to the single database offered by AWS hosting and it seems to work. I now have one DynamoDB database for users and the second for content. This involved setting up a Role in my personal AWS account, with a trust relationship to the ARN for my AWS-hosted lambda function, which allows it to assume the role with permissions to DynamoDB and S3. (I set both up at the same time and DynamoDB works.)
The problem I am encountering is with S3 pre-signed URLs, which I can’t make work. Pre-signed URLs use a required util file:
const AWS = require('aws-sdk');
const s3SigV4Client = new AWS.S3({
signatureVersion: 'v4',
region: process.env.S3_PERSISTENCE_REGION
});
module.exports.getS3PreSignedUrl = function getS3PreSignedUrl(s3ObjectKey) {
const bucketName = process.env.S3_PERSISTENCE_BUCKET;
const s3PreSignedUrl = s3SigV4Client.getSignedUrl('getObject', {
Bucket: bucketName,
Key: s3ObjectKey,
Expires: 60*1 // the Expires is capped for 1 minute
});
console.log(`Util.s3PreSignedUrl: ${s3ObjectKey} URL ${s3PreSignedUrl}`);
return s3PreSignedUrl;
}
As a minimum I need to change the bucket name (highlighted) from the S3_PERSISTENCE_BUCKET to the name of my new bucket in my personal account.; but I want to do this conditionally so that the bulk of my code can call the AWS-hosted S3 bucket, but occasionally I want to be access the additional content in the personally-hosted S3 bucket. As you can see from the code below, I’ve had a few attempts.
async handle(handlerInput) {
const intentName = Alexa.getIntentName(handlerInput.requestEnvelope);
// 1. Assume the AWS resource role using STS AssumeRole Action
const STS = new AWS.STS({ apiVersion: '2011-06-15' });
const credentials = await STS.assumeRole({
RoleArn: 'arn:aws:iam::{{MY ROLE}}',
RoleSessionName: 'AlexaHostedLambdaRole'
}, (err, res) => {
if (err) {
console.log('AssumeRole FAILED: ', err);
throw new Error('Error while assuming role');
}
return res;
}).promise();
// 2. Make a new DynamoDB instance with the assumed role credentials
// and scan the DynamoDB table
const dynamoDB = new AWS.DynamoDB({
apiVersion: '2012-08-10',
accessKeyId: credentials.Credentials.AccessKeyId,
secretAccessKey: credentials.Credentials.SecretAccessKey,
sessionToken: credentials.Credentials.SessionToken
});
var params = {
TableName: "AlexaHostedTable",
Key: {
memory_id: { S: "00002" },
}
};
const tableData = await dynamoDB.getItem(params, function (err, data) {
if (err) {
console.log('getItem FAILED', err);
throw new Error('Error while getting Item from DynamoDB');
} else {
return data;}
}).promise();
// 3. Make a new S3 instance with the assumed role credentials
const s3Two = new AWS.S3({
apiVersion: '2012-08-10',
accessKeyId: credentials.Credentials.AccessKeyId,
secretAccessKey: credentials.Credentials.SecretAccessKey,
sessionToken: credentials.Credentials.SessionToken
});
// ... Use table data as required ...
var audioUrl = Util.getS3PreSignedUrl({{..PREFIX..}}tableData.Item.file.S +".mp3").replace(/&/g,'&'); //Marker
// const Util2 = require('./util2.js'); // pre-signs URLs from personal S3 bucket
var audioUrl2 = Util.getS3PreSignedUrl(tableData.Item.file.S +".mp3").replace(/&/g,'&'); //Marker
speakOutput ='Introductory text blah blah blah'+`<audio src="${audioUrl}"/>`+`<audio src="${audioUrl2}"/>`+'Suffix text blah blah blah'; // Marker
console.log ("speakOutput: ", speakOutput);
return handlerInput.responseBuilder
.speak(speakOutput)
.reprompt('add a reprompt if you want to keep the session open for the user to respond')
.getResponse();
}
};
I have tried:
With the current version of the code, the references to the old bucket will work. Alexa appears to created pre-signed URLs to the bucket, but I think this is a red herring as they don't work.
Upvotes: 0
Views: 39