강의

멘토링

커뮤니티

인프런 커뮤니티 질문&답변

김명재님의 프로필 이미지
김명재

작성한 질문수

[개정3판] Node.js 교과서 - 기본부터 프로젝트 실습까지

람다 사용하기

람다 접근 에러

작성

·

547

0

너무 자주 잘문드려 죄송합니다...

2023-11-23T13:10:50.588Z 50b59392-754b-4b9c-90a1-ed48e95f40e1 ERROR AccessDenied: Access Denied
at throwDefaultError (/var/task/node_modules/@smithy/smithy-client/dist-cjs/default-error-handler.js:8:22)
at /var/task/node_modules/@smithy/smithy-client/dist-cjs/default-error-handler.js:18:39
at de_GetObjectCommandError (/var/task/node_modules/@aws-sdk/client-s3/dist-cjs/protocols/Aws_restXml.js:4330:20)
at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
at async /var/task/node_modules/@smithy/middleware-serde/dist-cjs/deserializerMiddleware.js:7:24
at async /var/task/node_modules/@aws-sdk/middleware-signing/dist-cjs/awsAuthMiddleware.js:14:20
at async /var/task/node_modules/@smithy/middleware-retry/dist-cjs/retryMiddleware.js:27:46
at async /var/task/node_modules/@aws-sdk/middleware-flexible-checksums/dist-cjs/flexibleChecksumsMiddleware.js:63:20
at async /var/task/node_modules/@aws-sdk/middleware-sdk-s3/dist-cjs/region-redirect-endpoint-middleware.js:14:24
at async /var/task/node_modules/@aws-sdk/middleware-sdk-s3/dist-cjs/region-redirect-middleware.js:9:20 {
'$fault': 'client',
'$metadata': {
httpStatusCode: 403,
requestId: 'S3JVT25F4WT5TH9H',
extendedRequestId: 'i2FSNxeCIH5smb0tHWggtUQ7WWZIvDurOoQ4UGIZ1eVgwIPsJwrNC85V8Oh2XHVpCaFyITlXaaM=',
cfId: undefined,
attempts: 1,
totalRetryDelay: 0
},
Code: 'AccessDenied',
RequestId: 'S3JVT25F4WT5TH9H',
HostId: 'i2FSNxeCIH5smb0tHWggtUQ7WWZIvDurOoQ4UGIZ1eVgwIPsJwrNC85V8Oh2XHVpCaFyITlXaaM='
}

이러한 에러가 발생했습니다. 찾아보니깐 s3 버컷 정책과 관련이 있는 것 같습니다.

{

"Version": "2012-10-17",

"Statement": [

{

"Sid": "AddPerm",

"Effect": "Allow",

"Principal": "*",

"Action": [

"s3:GetObject",

"s3:PutObject"

],

"Resource": "arn:aws:s3:::whatsup1/*"

}

]

}

이게 저의 s3 버캣 정책입니다.

그리고 아래는 aws-upload의 index.js입니다

//이미지 리사이징 라이브러리
const sharp = require("sharp");

const {
  S3Client,
  GetObjectCommand,
  PutObjectCommand,
} = require("@aws-sdk/client-s3");

//함수가 aws 람다에서 돌아가기 때문에 스크릿키랑 아이디를 자동으로 넣어준다 = > 아무것도 넣어줄 필요 x
const s3 = new S3Client();

//람다는 3개의 매개변수를 제공하고 이 함수를 호출해준다.
exports.handler = async (event, context, callback) => {
  const Bucket = event.Records[0].s3.bucket.name;
  const Key = decodeURIComponent(event.Records[0].s3.object.key); //original/리버풀.png
  const filename = Key.split("/").at(-1);
  const ext = Key.split(".").at(-1).toLowerCase();
  const requiredFormat = ext === "jpg" ? "jpeg" : ext;
  console.log("name", filename, "ext", ext);
  try {
    const getObject = await s3.send(new GetObjectCommand({ Bucket, Key }));
    const buffers = [];
    for await (const data of getObject.Body) {
      buffers.push(data);
    }
    const imageBuffer = Buffer.concat(buffers);
    console.log("original", getObject);
    const resizedImage = await sharp(imageBuffer)
      .resize(200, 200, { fit: "inside" })
      .toFormat(requiredFormat)
      .toBuffer();
    await s3.send(
      new PutObjectCommand({
        Bucket,
        Key: `thumb/${filename}`,
        Body: resizedImage,
      })
    );

    console.log("put", resizedImage.length);
    return callback(null, `thumb/${filename}`);
  } catch (error) {
    console.error(error);
    return callback(error);
  }
};

구글링 해보니깐 s3정책들이 비슷하면서 약간씩 다르던데 뭐가 맞는건지 잘 모르겠습니다..

답변 1

0

제로초(조현영)님의 프로필 이미지
제로초(조현영)
지식공유자

image이런 식으로 람다에 s3 접근 권한이 있어야 합니다.

김명재님의 프로필 이미지
김명재
질문자

IAM에서 역할 들어가서 역할 생성 누른 후에 생성하는게 맞나요? 일단 lamda 선택 후 AmazonS3FullAccess 선택해서 생성하면 되는거 아닌가요? 그렇게 만들었는데 람다 권한에 s3가 생기지가 않습니다...

제로초(조현영)님의 프로필 이미지
제로초(조현영)
지식공유자

이미지에 실행 역할 및에 역할 이름 나와있는데 그 역할 누르고 거기에 권한을 추가하셔야 합니다.

김명재님의 프로필 이미지
김명재
질문자

{ "errorType": "NoSuchKey", "errorMessage": "The specified key does not exist.", "name": "NoSuchKey", "$fault": "client", "$metadata": { "httpStatusCode": 404, "requestId": "5WP7H6TJ89PNXY1K", "extendedRequestId": "UX2dQCq5GAsbRwXmK6h2Sm3Y7wV16U2p1hheLNOwmwXmBCpnGQvYM0DXNty1TT6DuZu0zWs4+Ao=", "attempts": 1, "totalRetryDelay": 0 }, "Code": "NoSuchKey", "Key": "original/1700755094030_%C3%A1%C2%84%C2%89%C3%A1%C2%85%C2%B3%C3%A1%C2%84%C2%8F%C3%A1%C2%85%C2%B3%C3%A1%C2%84%C2%85%C3%A1%C2%85%C2%B5%C3%A1%C2%86%C2%AB%C3%A1%C2%84%C2%89%C3%A1%C2%85%C2%A3%C3%A1%C2%86%C2%BA+2023-11-23+%C3%A1%C2%84%C2%8B%C3%A1%C2%85%C2%A9%C3%A1%C2%84%C2%92%C3%A1%C2%85%C2%AE+11.11.21.png", "RequestId": "5WP7H6TJ89PNXY1K", "HostId": "UX2dQCq5GAsbRwXmK6h2Sm3Y7wV16U2p1hheLNOwmwXmBCpnGQvYM0DXNty1TT6DuZu0zWs4+Ao=", "message": "The specified key does not exist.", "stack": [ "NoSuchKey: The specified key does not exist.", " at de_NoSuchKeyRes (/var/task/node_modules/@aws-sdk/client-s3/dist-cjs/protocols/Aws_restXml.js:6082:23)", " at de_GetObjectCommandError (/var/task/node_modules/@aws-sdk/client-s3/dist-cjs/protocols/Aws_restXml.js:4327:25)", " at process.processTicksAndRejections (node:internal/process/task_queues:95:5)", " at async /var/task/node_modules/@smithy/middleware-serde/dist-cjs/deserializerMiddleware.js:7:24", " at async /var/task/node_modules/@aws-sdk/middleware-signing/dist-cjs/awsAuthMiddleware.js:14:20", " at async /var/task/node_modules/@smithy/middleware-retry/dist-cjs/retryMiddleware.js:27:46", " at async /var/task/node_modules/@aws-sdk/middleware-flexible-checksums/dist-cjs/flexibleChecksumsMiddleware.js:63:20", " at async /var/task/node_modules/@aws-sdk/middleware-sdk-s3/dist-cjs/region-redirect-endpoint-middleware.js:14:24", " at async /var/task/node_modules/@aws-sdk/middleware-sdk-s3/dist-cjs/region-redirect-middleware.js:9:20", " at async /var/task/node_modules/@aws-sdk/middleware-logger/dist-cjs/loggerMiddleware.js:7:26" ] }

여기서 말하는 Key가 파일이름 같은데 왜 파일 이름을 못찾는다는 건지 잘 모르겠습니다..

//이미지 리사이징 라이브러리
const sharp = require("sharp");

const {
  S3Client,
  GetObjectCommand,
  PutObjectCommand,
} = require("@aws-sdk/client-s3");

//함수가 aws 람다에서 돌아가기 때문에 스크릿키랑 아이디를 자동으로 넣어준다 = > 아무것도 넣어줄 필요 x
const s3 = new S3Client();

//람다는 3개의 매개변수를 제공하고 이 함수를 호출해준다.
exports.handler = async (event, context, callback) => {
  const Bucket = event.Records[0].s3.bucket.name;
  const Key = decodeURIComponent(event.Records[0].s3.object.key); //original/리버풀.png
  const filename = Key.split("/").at(-1);
  const ext = Key.split(".").at(-1).toLowerCase();
  const requiredFormat = ext === "jpg" ? "jpeg" : ext;
  console.log("name", filename, "ext", ext);
  try {
    const getObject = await s3.send(new GetObjectCommand({ Bucket, Key }));
    const buffers = [];
    for await (const data of getObject.Body) {
      buffers.push(data);
    }
    const imageBuffer = Buffer.concat(buffers);
    console.log("original", getObject);
    const resizedImage = await sharp(imageBuffer)
      .resize(200, 200, { fit: "inside" })
      .toFormat(requiredFormat)
      .toBuffer();
    await s3.send(
      new PutObjectCommand({
        Bucket,
        Key: `thumb/${filename}`,
        Body: resizedImage,
      })
    );

    console.log("put", resizedImage.length);
    return callback(null, `thumb/${filename}`);
  } catch (error) {
    console.error(error);
    return callback(error);
  }
};

이것도 혹시 s3 권한 문제 일까요?
아까 권한 추가 만들때
스크린샷 2023-11-24 오전 1.04.39.png정책 연결로 s3FullAccess로 권한 정책 추가 했는데 인라인 정책 생성으로 만들어야 했나요?

제로초(조현영)님의 프로필 이미지
제로초(조현영)
지식공유자

파일명 영어로 띄어쓰기 없는 것으로 올려보세요

김명재님의 프로필 이미지
김명재
질문자

드디어 됐습니다... 그런데 왜 한글 파일명은 안되는건가요?

제로초(조현영)님의 프로필 이미지
제로초(조현영)
지식공유자

한글도 원래 돼야하긴 합니다. 띄어쓰기는 +를 스페이스로 replace하는 코드를 추가하면 됩니다.

김명재님의 프로필 이미지
김명재

작성한 질문수

질문하기