serverless framework에서 s3-persistence-adapter를 완전히 설정

14808 단어 serverless알렉사

개요



교통량 조사의 달인라는 알렉사 스킬로 사용자별 최고 기록을 저장하는 기능을 추가했습니다.
이번은 s3에 보존하는 방법으로 해 보았습니다만, 권한 주위에서 빠졌으므로 참고까지 정리합니다.

전제


  • serverless framerowk로 다양한 리소스를 완전히 관리합니다.
  • S3 bucket
  • lambda의 IAM policy
  • lambda 소스 코드


  • 결론



    먼저, 제대로 움직였을 때의 코드를 기재합니다.

    index.ts
    
    // importとs3の設定
    import * as Adapter from 'ask-sdk-s3-persistence-adapter';
    const s3PersistenceAdapter = new Adapter.S3PersistenceAdapter({
         bucketName: `${process.env.SERVICE_NAME}-${process.env.ENV}`
     })
    
    ---
    
    // s3を操作する関数
    async function getScore(handlerInput: Alexa.HandlerInput): Promise<number> {
      const attributes = await handlerInput.attributesManager.getPersistentAttributes();
      if (Object.keys(attributes).length > 0) {
        return attributes.score;
      }
      return 0;
    }
    
    async function saveScore(handlerInput: Alexa.HandlerInput) {
      const sessionAttributes = handlerInput.attributesManager.getSessionAttributes() as QuestionAttributes;
      const persistentAttributes = {
        score: sessionAttributes.counter - 1
      };
      handlerInput.attributesManager.setPersistentAttributes(persistentAttributes);
      await handlerInput.attributesManager.savePersistentAttributes();
    }
    
    ---
    // メインのHandler
    const AnswerHandler = {
      canHandle(handlerInput: Alexa.HandlerInput) {
        const request = handlerInput.requestEnvelope.request;
        return request.type === 'IntentRequest'
          && request.intent.name === 'AnswerIntent';
      },
      async handle(handlerInput: Alexa.HandlerInput) {
          ...(省略)...
    
          //最高記録をs3から取得し、記録更新していたら更新する
          let score = await getScore(handlerInput)
          const isNewScore = score < attributes.counter
          if (isNewScore) {
            await saveScore(handlerInput);
          }
    
          ...(省略)...
    
          return handlerInput.responseBuilder
            .speak(gameOverText(attributes, isNewScore)) //gameOverText()は終了時のメッセージを組み立てる
            .withShouldEndSession(true)
            .getResponse();
    
    }
    
    
    

    serverless.yml
    service:
      name: sample-app
    
    custom:
      defaultStage: dev
    
    provider:
      name: aws
      region: ap-northeast-1
      runtime: nodejs8.10
      stage: ${opt:stage, self:custom.defaultStage}
      environment:
        ENV: ${opt:stage, self:custom.defaultStage}
        SERVICE_NAME: ${self:service.name}
      iamRoleStatements:
        - Effect: "Allow"
          Action:
            - "s3:*"
          Resource:
            - "arn:aws:s3:::${self:service.name}-${self:provider.stage}*"
    resources:
      Resources:
        Bucket:
          Type: AWS::S3::Bucket
          Properties:
            BucketName: ${self:service.name}-${self:provider.stage}
    
    

    NG집



    s3을 조작하기 위해 lambda에게 부여하는 IAM 권한으로 상당히 빠졌습니다.
    serverless framework에서는 iamRoleStatements에서 설명할 수 있습니다.

    NG1 : 리소스에서 bucket 이름 만



    serverless.yml
      iamRoleStatements:
        - Effect: "Allow"
          Action:
            - "s3:*"
          Resource:
            - "arn:aws:s3:::${self:service.name}-${self:provider.stage}"
    
    

    error.log
    Error handled: Could not save item (amzn1.ask.account.yyy) to bucket (ZZZ): Access Denied
    

    bucket에 대한 조작만이 허가되어 있어 object에 대한 조작을 할 수 없기 때문이군요. 이것은 이해한다.

    NG2: 모든 객체 허용



    serverless.yml
      iamRoleStatements:
        - Effect: "Allow"
          Action:
            - "s3:*"
          Resource:
            - "arn:aws:s3:::${self:service.name}-${self:provider.stage}/*"
    
    

    error.log
    Error handled: Could not read item (amzn1.ask.account.yyy) from bucket (ZZZ): Access Denied
    

    이것은 풀 수 없다 ....
    수수께끼.

    NG3: action을 get과 put만으로 제한



    serverless.yml
      iamRoleStatements:
        - Effect: "Allow"
          Action:
            - "s3:GetObject"
            - "s3:PutObject"
          Resource:
            - "arn:aws:s3:::${self:service.name}-${self:provider.stage}*"
    
    

    error.log
    Error handled: Could not read item (amzn1.ask.account.yyy) from bucket (ZZZ): Access Denied
    

    이것도 풀 수 없다 ....

    기타



    IAM Policy Simulator 에서 IAM Policy를 만들고,
    Get과 Put을 해 보면, 괜찮을 것 같고-수수께끼.
    {
        "Version": "2012-10-17",
        "Statement": [
            {
                "Action": [
                    "s3:GetObject",
                    "s3:PutObject"
                ],
                "Resource": [
                    "arn:aws:s3:::sample-bucket*"
                ],
                "Effect": "Allow"
            }
        ]
    }
    

    좋은 웹페이지 즐겨찾기