尝试上传到AWS S3时无法从任何提供商加载凭证

时间:2019-05-15 15:16:30

标签: node.js amazon-web-services heroku amazon-s3 aws-sdk-nodejs

我似乎无法正确获得身份验证。

我已经创建了在AWS S3上使用的存储桶。

我已经在两个AWS上都创建了访问密钥和密钥,并按照here在Heroku上将它们作为环境变量输入。

我已验证访问密钥在配置日志中可见。

我想念什么?

我目前正在localhost上尝试此操作,因此是我手动更新配置的情况,但后来我希望服务器代码在Heroku上运行。

客户端:

   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
    }

服务器端:

   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 })
        });
    });

打印配置:

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
}

打印错误:

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'
    }
  }
}

1 个答案:

答案 0 :(得分:1)

在执行aws.config.update()之前,您应使用凭据 调用s3 = new aws.S3()。否则,配置更新将不会绑定到S3对象,并且将使用默认的凭据链。

还要确保访问密钥和秘密密钥正确,但是我认为这不是问题所在。