Reputation: 2730
I can't seem to get the auth correct.
I've created the buckets in use on AWS S3.
I've created access key and secret on both AWS and entered them as environment variables on Heroku as specified here.
I've verified that access key is visible in config log.
What am I missing?
I'm currently trying this on localhost hence the condition where I update the config manually, but later on I want the server code to run on Heroku.
Client side:
async upload(adId: string, file: File) {
const url = this.baseUrl + `api/image/${adId}`
const fileName = this.createUniqueFileName(adId, file)
const data = { fileName: fileName, fileType: file.type }
const response = await axios.post(url, data, { headers: { 'Content-Type': 'application/json' } }) // Fetch a signed AWS S3 url from ad-keeper
const formData = new FormData()
formData.append(fileName, file)
const awsS3Response = await axios.put(response.data.signedUrl, formData, { headers: { 'Content-Type': 'multipart/form-data' } }) // Upload file to AWS S3 bucket
return awsS3Response.status === 200
}
Server side:
app.post('/api/image/:adId', (request, response) => {
const s3 = new aws.S3()
if (request.headers.host.includes('localhost')) {
aws.config.update({ region: localHostAwsConfig.region, accessKeyId: localHostAwsConfig.accessKeyId, secretAccessKey: localHostAwsConfig.secretAccessKey })
}
const fileName = request.body.fileName
const fileType = request.body.fileType
const bucketName = process.env.AWS_S3_BUCKET_NAME || "localhost-bucket"
const params = {
Bucket: bucketName,
Key: fileName,
Expires: 60,
ContentType: fileType,
ACL: 'public-read'
}
console.log(aws.config)
s3.getSignedUrl('putObject', params, (error, data) => {
if (error) {
console.log(error)
return response.status(500).end() // Server call ends up here
}
const imageUrl = `https://${bucketName}.s3.amazonaws.com/${fileName}`
adSource.setImageUrl(request.params.adId, imageUrl)
return response.json({ signedRequest: data, imageUrl: imageUrl })
});
});
Printing config:
Config {
credentials: Credentials {
expired: false,
expireTime: null,
refreshCallbacks: [],
accessKeyId: '<ACCESS_KEY>',
sessionToken: undefined
},
credentialProvider: CredentialProviderChain {
providers: [
[Function],
[Function],
[Function],
[Function],
[Function],
[Function]
],
resolveCallbacks: []
},
region: 'eu-north-1',
logger: null,
apiVersions: {},
apiVersion: null,
endpoint: undefined,
httpOptions: { timeout: 120000 },
maxRetries: undefined,
maxRedirects: 10,
paramValidation: true,
sslEnabled: true,
s3ForcePathStyle: false,
s3BucketEndpoint: false,
s3DisableBodySigning: true,
computeChecksums: true,
convertResponseTypes: true,
correctClockSkew: false,
customUserAgent: null,
dynamoDbCrc32: true,
systemClockOffset: 0,
signatureVersion: null,
signatureCache: true,
retryDelayOptions: {},
useAccelerateEndpoint: false,
clientSideMonitoring: false,
endpointDiscoveryEnabled: false,
endpointCacheSize: 1000,
hostPrefixEnabled: true
}
Printing error:
Error: connect ETIMEDOUT 169.254.169.254:80
at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1054:14) {
message: 'Missing credentials in config',
errno: 'ETIMEDOUT',
code: 'CredentialsError',
syscall: 'connect',
address: '169.254.169.254',
port: 80,
time: 2019-05-15T15:11:01.789Z,
originalError: {
message: 'Could not load credentials from any providers',
errno: 'ETIMEDOUT',
code: 'CredentialsError',
syscall: 'connect',
address: '169.254.169.254',
port: 80,
time: 2019-05-15T15:11:01.789Z,
originalError: {
errno: 'ETIMEDOUT',
code: 'ETIMEDOUT',
syscall: 'connect',
address: '169.254.169.254',
port: 80,
message: 'connect ETIMEDOUT 169.254.169.254:80'
}
}
}
Upvotes: 2
Views: 9579
Reputation: 78823
You should invoke aws.config.update()
with the credentials before executing s3 = new aws.S3()
. The config update will not bind to the S3 object otherwise, and it will use the default credentials chain.
Also make sure that the access key and secret key are correct, but I don't think that's the issue here.
Upvotes: 4