Serverless Framework, AWS SAMを使ってCORSと戦った話

スポンサーリンク
プログラミング

Serverless Framework を使ってCORSと戦っていた話

これは僕が数ヶ月前(確か2018年5, 6月頃)にドキュメントと戦って、頑張っていたものをまとめたものです。

使用言語はGolangです。

数ヶ月前の記憶の片隅から引っ張り出してきてるのでガバガバな点があったら申し訳ないです。

認証をCofnitoで行なっていましたので、その辺の設定とかも書いておきます。

スポンサーリンク

Serverless Frameworkとは

serverless Framework

NodeJS製で、AWSやGCP, Azureなど様々なクラウドサービスが用意しているFaaSに対して、デプロイをするツールです。
プラグインで、ローカルで実行できたり、DynamoDBを建てられたりします。
Serverless Frameworkには1系, 0系とあり、0系はjsonで、1系はymlで設定をかけます。
今は1系が主流です。

CORSとは

オリジン間リソース共有 (CORS)
オリジン間リソース共有 ( Cross-Origin Resource Sharing ) (CORS) は、追加の HTTP ヘッダーを使用して、あるオリジン (ドメイン) で動作しているウェブアプリケーションに、異なるオリジンのサーバーにある選択されたリソースへのアクセスを許可することができる仕組みです。

オリジン間リソース共有といって、違いオリジンのサーバーにあるAPIとかにアクセスできるようにする仕組みです。
ブラウザのセキュリティ対策的なところっぽいです。(これ以上は知らん)

Cookieを使わないとき

functions:
  hoge:
    handler: bin/hoge
    events:
      - http:
          path: /hoge
          method: POST
          cors: true

のように、cors: trueを書いてあげれば大丈夫です。

問題はCookieを使うとき

少しだるいです

functions:
  hoge:
    handler: bin/hoge
    events:
      - http:
          path: /hoge
          method: POST
          cors:
            origin: http://hogehogefugafuga.s3-website-ap-northeast-1.amazonaws.com
            headers:
              - Content-Type
              - X-Amz-Date
              - Authorization
              - X-Api-Key
              - X-Amz-Security-Token
              - X-Amz-User-Agent
            allowCredentials: true

みたいな感じでか書きます。

originにデプロイ先のURLを指定してあげることで、動くようになります。

Cognitoで認証を挟んでる場合

functions:
  hoge:
    handler: bin/hoge
      - http:
          authorizer:
            arn: arn:aws:cognito-idp:ap-northeast-1:hogehogeohgeo:userpool/ap-northeast-1
          path: /hoge
          method: POST
          cors:
            origin: http://hogehogefugafuga.s3-website-ap-northeast-1.amazonaws.com
            headers:
              - Content-Type
              - X-Amz-Date
              - Authorization
              - X-Api-Key
              - X-Amz-Security-Token
              - X-Amz-User-Agent
            allowCredentials: true

このようにCognitoarnを指定します。

ローカルで動かしたいけどどうするの?

ServerlessOfflineを使います。

ymlの銭湯あたりに

plugins:
  - serverless-offline

を追加してあげます。

originのURLを環境によって変えられるようにします。この辺は環境変数とか使ってよしなに

ただこのやり方 NodeJS しか対応してません。

なので、Golangを使いたい場合, SAM CLIを使用する必要があります。

ちなみにServelessFrameworkに元からあるserverless invoke localというコマンドも NodeJs, Python , Javaのランタイムにしか対応しておらず、実際に手元でデバックしたいならsam cliを使うしかないっぽいです。

AWS SAMと戦おう

AWS SAMとは

ドキュメント

AWSが出してるServerless Frameworkみたいなものです。これはymlでかけます。
Goのランタイムにも対応してるので、良いです。

ServelessとSAMどう使い分けたか

この時のプロジェクトが、途中からブラウザで使えるAPIを提供し始める流れになったので、ServerlessFrameworkをデフォで使ってました。
最初からわかっていたらSAM使っていたと思う。

なので、デプロイはServerless、デバッグ用にSAMといった感じにしています。

template.yml

AWSTemplateFormatVersion : '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: hoge

ApiGateway:
  Type: AWS::Serverless::Api
  Properties:
    StageName: dev
    DefinitionBody:
      securityDefinitions:
        cognitoUserPool:
          type: apiKey,
          name: "Auth"
          in: header
          x-amazon-apigateway-authtype: cognito_user_pools
          x-amazon-apigateway-authorizer:
            type: cognito_user_pools
            providerARNs:
              - arn:aws:cognito-idp:ap-northeast-1:hogehoge:userpool/ap-northeast-1
      paths:
        "/":
          get:
            security:
              - cognitoUserPool: []

Resources:
  OrderListFunction:
    Type: AWS::Serverless::Function
    Properties:
      Handler: bin/hoge
      Runtime: go1.x
      Events:
        OrderListResource:
           Type: Api
           Properties:
             Path: /hoge
             Method: POST
             Cors:
              AllowMethods: "'*'"
              AllowHeaders: "'*'"
              AllowOrigin: "'http://localhost:8080'"
              AllowCredentials: "'true'"

みたいに書きます

sam local start-apiするとlocalhost:3000に立ち上がります

これで、ローカルでのデバッグができるようになります。

まとめ

ServerlessFrameworkは便利だけど、Goで触ろうとしていると少し辛いところがあります。
また、AWSのドキュメントがとても読みにくかったり、足りなかったりするので気合いがとても必要です。

あと、ymlのインデントが崩れてたり、タイポしてたりするとserverless frameworkが謎のエラーを出したりするのでとても辛い…

コメント

タイトルとURLをコピーしました