【AWS】Lambdaを用いて、Route53にAレコードを登録する
技術約6分で読めます

この記事でわかること
- Lambda から Route 53 に A レコードを登録する実装コード(AWS SDK v3)
- 必要な IAM 権限と、本番ではどこまで絞れるか
- API Gateway 経由だと event.body が文字列になって踏む落とし穴
- 入力を検証せずにレコード名にする危うさ
Route 53 でドメイン(ホストゾーン)を取得済みであること。AWS コンソールに入れて、Lambda 関数と IAM ロールを作成できる権限があれば十分です。
概要
今回は、「Lambda を用いて、Route 53 に A レコードを登録する」というテーマで記事を書いてみました。
ポイント
取得済みのドメインに対して、IP アドレスを元にした A レコードを動的に登録していきます。用途としては IP アドレスを固定にできないときなどです。
(例)127-0-0-1.example.com / 127-0-0-2.example.com
導入手順
Lambda を作成する
あまり経験がない方は Lambda の入門(公式ドキュメント) を参照いただけると良いと思います。
注意
下のコードは
require を使った CommonJS 形式なので、ファイル名を index.mjs から index.js に変更してください(コンソールの既定は index.mjs = ESM です)。.mjs のまま行くなら、require を import { Route53Client, ChangeResourceRecordSetsCommand } from "@aws-sdk/client-route-53"; に、exports.handler を export const handler に書き換えてください。Role について
Lambda にアタッチする Role には AmazonRoute53FullAccess のポリシーを付与しておいてください。付与されていないと A レコードを作成する権限がなく、エラーになります。
Tips
AmazonRoute53FullAccess は全ホストゾーンを好きにいじれる権限です。手元で試す分には楽ですが、本番では対象のホストゾーンに絞ったインラインポリシーにしてください。必要なのは route53:ChangeResourceRecordSets だけで、Resource を arn:aws:route53:::hostedzone/対象ID に限定できます。Lambda の処理
const { Route53Client, ChangeResourceRecordSetsCommand } = require("@aws-sdk/client-route-53");
exports.handler = async function (event, context) {
// Route53への接続
const route53 = new Route53Client();
// 変更を行うドメイン名とhostedzone IDを入力
const hostedZoneId = '********';
const recordName = 'example.com';
// IPアドレスを取得
const newIpAddress = event.body.address;
//レコード名を作成('.'->'\u2019へ正規化した上で結合)
const newRecordName=newIpAddress.replace(/\./g, '-')+'.'+recordName
// Aレコードの変更リクエストを作成
const changeBatch = {
Changes: [
{
Action: 'UPSERT',
ResourceRecordSet: {
Name: newRecordName,
Type: 'A',
TTL: 300,
ResourceRecords: [
{ Value: newIpAddress }
]
}
}
]
};
// レコードの変更を実行
try {
const command = new ChangeResourceRecordSetsCommand({
HostedZoneId: hostedZoneId,
ChangeBatch: changeBatch
});
const response = await route53.send(command);
console.log(response);
return {
statusCode: 200,
body: JSON.stringify(response)
};
} catch (error) {
console.error(error);
return {
statusCode: 500,
body: JSON.stringify(error.message)
};
}
};test を実行する
送られてきた IP アドレスの . を - に変換した文字列をドメインの頭につける形で、A レコードを登録します。次の JSON でテストを行います。
{
"body": {
"address": "127.0.0.1"
}
}注意
このコードはテストイベントを前提にしています。コンソールのテストでは
event.body がオブジェクトのまま届くので event.body.address で取れますが、API Gateway 経由で呼ぶと event.body は文字列になり、undefined になります。実運用では const { address } = JSON.parse(event.body) のようにパースしてください。重要
入力をそのままレコード名にしないこと。上のコードは受け取った文字列を検証せずに DNS レコード名にしています。外部から叩けるエンドポイントにするなら、IP アドレスの形式かどうかを先に検査してください(例:
/^\d{1,3}(\.\d{1,3}){3}$/ で弾く)。そうしないと意図しないサブドメインを自由に作られます。実行結果の確認
Route 53 で自分が選択したホストゾーン(example.com)に A レコードが登録されていたら OK です。
参考リンク
おわりに
今回の記事では、Lambda で Route 53 に A レコードを登録してみたい時に、Lambda にどんな処理を書けばいいのか記述をしました。
今回の内容を応用すれば、IPアドレスの変更等を検知した場合や、EC2の起動を検知した場合などに、Aレコードを新しく登録もしくは更新するなどもできると思います。
更新履歴
- タイトルと本文の誤記を修正(Lamda→Lambda、exaple.com→example.com)。見出しの番号を削除し、導入手順の下に各ステップを入れ子にする形に修正。コード内の壊れていたコメントを修正。API Gateway 経由だと event.body が文字列になる件、入力を検証せずにレコード名にしている件、最小権限の IAM ポリシー、ESM/CommonJS の違いを補足。引用ブロックを callout に変更し、裸 URL をタイトル付きリンクに変更。
- 記事内リンクと OGP Description の修正


