[AWS] Serverless Frameworkで独自ドメインをSSL付きで設定する

Serverless FrameworkでRESTFulAPIを作成すると、通常だと以下のようにAWS側で用意されたドメインを利用するわけですが、

https://d-hhlj8cxjl7.execute-api.us-east-1.amazonaws.com/dev/welcome

今回は次のようにこちらで用意したドメインでリクエストを可能にします。

https://api.blog.katsubemakito.net/api/welcome

これはServerless Frameworkのプラグインserverless-domain-manager」を導入することで比較的簡単に実現できます。

事前準備

Serverless Framework?

基本的な利用方法については過去の記事をご覧くださいませ。 blog.katsubemakito.net

Route53にドメインを設定

独自ドメインをRoute53にドメインをセットしておきます。今回は新しく「api.blog.katsubemakito.net」という名前のホストゾーンを作成しました。

ドメインの詳しい設定については割愛します。

SSL証明書を作成

AWSのマネジメントコンソールのにログインし、ACM(AWS Certificate Manager)に移動、右上にあるリージョンを確認、必要があれば変更します。基本的にLambdaを実行するリージョンと同じ物を選択すればよいのですが、CloudFront(edge)での配信を希望する場合は「バージニア北部(us-east-1)」を指定します。

証明書のリクエストをクリック。

「パブリック証明書のリクエスト」を選択しボタンをクリック。

ドメイン名を入力し「次へ」をクリック。

DNSの検証」を選択し「次へ」をクリック。このあとタグ付ける画面が出てきますが必要に応じて設定してください。

ステップ5まで来たら「Route53でのレコードの作成」をクリックします。

最初の一覧画面に戻ったら「検証保留中」の部分が「発行済」に切り替わったら作成完了です。数分程度で完了します。

独自ドメインを設定

ここから本題です。

プロジェクトの作成

今回は「hello2」という名前でプロジェクトを作成しました。ここではJavaScript(Node.js)を選択していますが何でもかまいません。

$ serverless
Serverless: No project detected. Do you want to create a new one? Yes
Serverless: What do you want to make? AWS Node.js
Serverless: What do you want to call this project? hello2

Project successfully created in 'hello2' folder.

作成されたプロジェクト用フォルダの下に移動し、package.jsonを作成するためにnpm initを実行します。

$ cd hello2
$ npm init

プラグインのインストール

npmでプラグインをインストールします。package.jsonにも記録されているか確認しておきます。

$ npm install serverless-domain-manager --save-dev

serverless-domain-managerの詳細は以下を参照ください。 github.com

handler.jsを準備

ほぼデフォルトのままです。メッセージの内容を簡略化しています。Lambda関数の処理自体は独自ドメインの設定とは直接関係ありませんのでこれまで通り自由に記述できます。

'use strict';

module.exports.hello = async event => {
  return {
    statusCode: 200,
    body: JSON.stringify(
      {
        message: 'Welcome to MyDomain',
      },
      null,
      2
    ),
  };
};

serverless.ymlを設定

プロジェクトの設定ファイルである「serverless.yml」の下の方にplugins以下の項目を書き足します。domainNameやcertificateNameなどの値は環境に合わせて変更してください。

service: hello2
provider:
  name: aws
  runtime: nodejs12.x
functions:
  hello:
    handler: handler.hello
    events:
      - http:
          path: welcome
          method: get
plugins:
  - serverless-domain-manager
custom:
  customDomain:
    domainName: api.blog.katsubemakito.net
    stage: dev
    basePath: api
    certificateName: 'api.blog.katsubemakito.net'
    createRoute53Record: true
    endpointType: 'regional'
    securityPolicy: tls_1_2

各項目の意味は以下になります。domainNameは必ず指定する必要があり、他の項目は任意です。

項目名 初期値 說明
domainName - 設定したい独自ドメイン
stage provider.stageで設定した値 対象のステージを指定
basePath (なし) APIのendpointで利用するベース部分を指定
certificateName (domainNameに近い物) ACMで作成したドメイン
createRoute53Record true プラグインがRroute53にレコード作成を行うか
endpointType edge endpointの形式をregionaledgeを指定
securityPolicy tls_1_2 セキュリティポリシーtls_1_0tls_1_2を指定

この他の項目はプラグインのドキュメントを参照してください。

AWSドメイン設定を反映する

serverless.ymlの編集が終わったらserverless create_domainを実行します。実行結果が返ってくると完了まで40分くらいかかるとありますのでしばし待ちます。

$ serverless create_domain
Serverless: Custom domain api.blog.katsubemakito.net was created.
            New domains may take up to 40 minutes to be initialized.

ただ、何度か試しに実行するといずれも数分〜10分程度で利用できたので、状況によってはすぐに終わりそうですね。

AWSへデプロイ

最後に通常通りデプロイすれば完了です。

$ serverless deploy

途中、これまで通りamazonaws.comドメインのendpointsも作成されます。こちらの利用も引き続き可能です。

endpoints:
  GET - https://4lei1rl4ti.execute-api.us-east-1.amazonaws.com/dev/welcome

最後にプラグインの実行結果が表示されます。

Serverless Domain Manager Summary
Domain Name
  api.blog.katsubemakito.net
Distribution Domain Name
  Target Domain: d-hhlj8cxjl7.execute-api.us-east-1.amazonaws.com
  Hosted Zone Id: Z1UJRXOUMOOFQ8

実行する

早速curlでリクエストを飛ばしてみます。無事に実行されていることが確認できました。

$ curl https://api.blog.katsubemakito.net/api/welcome    
{
  "message": "Welcome to MyDomain"
}

amazonaws.comの方も同様に実行可能ですね。

$ curl https://4lei1rl4ti.execute-api.us-east-1.amazonaws.com/dev/welcome
{
  "message": "Welcome to MyDomain"
}

独自ドメインを削除する

設定した独自ドメインは以下のコマンド一発で削除できます。一瞬で反映されますので実行は慎重に。

$ serverless delete_domain
Serverless: Custom domain api.blog.katsubemakito.net was deleted.

curlで確かめるとほぼ一瞬で消えてなくなりました。

$ curl https://api.blog.katsubemakito.net/api/welcome                    
curl: (6) Could not resolve host: api.blog.katsubemakito.net

もう一度同じ独自ドメインを設定したくなった場合はserverless create_domainした後にデプロイします。デプロイを忘れると永遠に403が返ってきますのでご注意を。

$ serverless create_domain
$ serverless deploy

参考ページ