AWSのAPI Gatewayで独自ドメイン名を使うの難しかった (Regional)
自分には初見で難しすぎたのでメモ。
- 東京リージョン
- 証明書はLet's Encrypt
- ドメイン名はお名前ドットコムで取得
AWSの画面や内容は現時点のものです。よく変わるので注意。
最初に備考
- この記事では、APIのエンドポイントタイプはRegionalであること前提です。Lambdaの画面から作成したAPIのエンドポイントタイプが、デフォルトでRegionalだったからです。
- APIのエンドポイントタイプは、API Gatewayコンソールのトップ画面でAPIごとの右上の歯車アイコンから変えられます。
- いろいろと反映されるまでに待ち時間があります。時間に余裕があるときにやった方がいいです。
では始めます。
手順1. ドメイン名を用意
先にドメイン名を用意しておきます。この記事では、あらかじめ『お名前ドットコム』で買っていたものを使います。
手順2. Route 53にホストゾーン作成
API Gatewayにドメイン名を設定するには、API Gatewayの『カスタムドメイン名』機能を使います。カスタムドメイン名を設定するには、対象のドメインをAmazon Route 53でルーティングできるようにしておく必要があるみたいです。
まず、Route 53のコンソールの『Create Hosted Zone』からホストゾーンを作成します。『Create Hosted Zone』ボタンを押すと、↓のような入力欄が出てきます。
入力内容は以下の通りです。
- Domain Name ...あらかじめ用意しておいたドメイン名を正しく入力。
- Comment ... コメント。必要なら入力。
- Type ... 『Public Hosted Zone』を選択。
下部の『Create』ボタンを押すと、ホストゾーンが作成されます。
作成されたホストゾーンには、デフォルトで NS
と SOA
のレコードが登録されてます。
NS
の Value
には、AWSのDNSサーバーが4つ分設定されてるはずです。この NS
の値を、ドメインの管理画面 (ここではお名前ドットコム) からドメインのネームサーバーとして設定します。
お名前ドットコムだと↓こんな感じです。複数設定できたので、全部設定しました。
ネームサーバーの変更は、私の時は反映されるまでに数時間かかりました。
これが終わったら左メニューの『Hosted zones』からホストゾーン一覧に戻り、一覧右端の『Hosted Zone ID』をメモしておきます。 後で使います。
手順3. SSL証明書を用意
API Gatewayのカスタムドメイン名の設定時には、必ずSSL証明書が必要みたいです。
この記事では、Let's Encryptで事前に作成しておいた証明書を使います。当ブログの以下の記事で作成した証明書をそのまま使いました。
Squidで立てたHTTPSプロキシをLet's Encryptする - キリウ君が読まないノート
次の手順で証明書の本文が必要になるので、Let's Encryptで作成された cert.pem
/ privkey.pem
/ chain.pem
の3ファイルの場所を確認しておきます。
手順4. Certificate ManagerにSSL証明書をインポート
API Gatewayのカスタムドメイン名で使用できるようにするために、SSL証明書をAWS Certificate Managerにインポートします。この記事ではAPIのエンドポイントがRegionalなので、APIと同じリージョンでCertificate Managerを操作します。
Certificate Managerのコンソールを開き、『証明書のインポート』ボタンを探します。管理してる証明書が一つも無い場合、チュートリアルかウィザードみたいな画面が出てきますが、適当にボタンを押したらその中のどこかにあったと思います。
『証明書のインポート』ボタンを押すと、↓のような入力画面が出てきます。
入力内容は以下の通りです。
- 証明書本文 ...
cert.pem
の中身をそのままコピペ。 - 証明書のプライベートキー ...
privkey.pem
の中身をそのままコピペ。 - 証明書チェーン ...
chain.pem
の中身をそのままコピペ。
コピペするときは全文をコピペします。-----BEGIN なんとか-----
から -----END なんとか-----
を含む全文です。
入力したら右下の『レビューとインポート』ボタンを押します。正しく入力できていれば、証明書をインポートできるはずです。
手順5. API Gatewayでカスタムドメイン名を作成
API Gatewayのコンソールのトップ画面で、左メニューの『カスタムドメイン名』からカスタムドメイン名の画面を開きます。
『カスタムドメイン名の作成』ボタンを押すと、↓のような入力欄が出てきます。
入力内容は以下の通りです。
- HTTP or WebSocket ... 作成したAPIに合わせる。この記事ではHTTPS。
- ドメイン名 ... ドメイン名を正しく入力。証明書を作成したドメイン名と必ず合わせる。
- エンドポイントの設定 ... APIのエンドポイントタイプに合わせる。ここではRegional。
- ACM証明書 ... 先程インポートした証明書を選択する。(us-east-1 のみ) とありますが、たぶんそれはエッジ最適化の場合だけです。Regionalなら気にしなくてOKです。
入力したら下部の『保存』を押して保存します。保存すると↓のように『ターゲットドメイン名』『ホストゾーンID』が表示されます。
この時、初めて使うACM証明書だと初期化処理が始まりますが、私のところでは数十分かかりました。
カスタムドメイン名を作成したら、下部の『編集』からベースパスマッピングを入力して、カスタムドメイン名とAPIとそのステージを紐づけます。
例えばパスに『api』を入力した場合、API内のパスが /user/update
ならば、実際のURLは https://ドメイン名/api/user/update
になります。
以下のサイト様が詳しく解説されてらしたので、読んでみてください。
Amazon API Gateway を独自ドメインで利用する | DevelopersIO
手順6. Route 53にエイリアスのAレコード追加
最後です。Route 53を使って、ドメイン名の向き先をAPI Gatewayに変更します。
[2020-03-03 追記] 以下は古い記述です。最近はRoute 53の画面からの操作だけで可能っぽいです。(エイリアスでAPI GatewayのURLを選択すれば、自動でホストゾーンIDが設定されるはず。)
やることはエイリアスのAレコードを作成するだけなのですが、ここだけはAWSコンソール (画面) からだと無理なので、AWS CLIを使う必要があります。
正確には画面からAレコードを作ること自体はできるのですが、それだと任意のホストゾーンIDを設定することができず、API Gatewayのカスタムドメイン名と結び付けられないみたいです。
まず、AWS CLIのコマンドでRoute 53にAレコードを作成するために、リクエスト内容を書いたjsonファイルを作成します。内容は以下の通りです。
次にこのjsonファイルをパラメータにして、以下のコマンドを実行します。
※なお、Windowsだとコマンド実行時に 'ascii' codec can't encode characters in position 71-75: ordinal not in range(128)
と言われて面倒くさくなったので、ここだけAmazon Linuxから行いました。
『ホストゾーンID』が二つ出てきてややこしいのですが、jsonファイルに書くホストゾーンIDは『カスタムドメイン名の画面に表示されてるホストゾーンID』、コマンドの hosted-zone-id
オプションに指定するホストゾーンIDは『Route 53で作成したホストゾーンのホストゾーンID』です。
この項の内容は公式の以下ページにも載ってるので、ピンとこなかったら見てみてください。
AWS CLI を使用して Amazon Route 53 でシンプルなリソースレコードセットを作成する
コマンド実行時に Error parsing parameter '--change-batch': Expected: '=', received: 'EOF' for input
エラーが出た場合は、たぶんファイルのパスを間違えてます。ファイルパスは file://
で指定しないとダメみたいです。
コマンド成功すれば、"Status": "PENDING"
とか書かれたレスポンスが返ってくるはずです。
ドメイン名でAPIを叩いてみる
めげずに全部設定したら、curl
などでドメイン名のURLでAPIを叩いてみます。
- レスポンスが全く無かったら、まだRoute 53の設定が反映されてないと思います。一晩くらい置くと解決しました。
- SSLエラーが発生したら、『証明書を取得したドメイン名』と『Route 53にAレコード作成したドメイン名』および『カスタムドメイン名に設定したドメイン名』が同じになっているか確認します。勝手にサブドメイン名とか付けちゃだめです。(やらかした)
API Gatewayっぽいレスポンスが返ってきたら、ちゃんと設定できてます。
以上です。難しかった。