Skip to content

Instantly share code, notes, and snippets.

@akira345
Last active July 24, 2024 03:02
Show Gist options
  • Save akira345/5a0e91c384c2b14dc1074094722619da to your computer and use it in GitHub Desktop.
Save akira345/5a0e91c384c2b14dc1074094722619da to your computer and use it in GitHub Desktop.
CloudFrontKeyValueStoreをつかったリダイレクト設定ラムダ
import cf from 'cloudfront';
const kvsId = '<CloudFrontKeyValueStoreのID>';
// This fails if the key value store is not associated with the function
const kvsHandle = cf.kvs(kvsId);
// async functionになるので注意!
async function handler(event) {
// CloudFrontから渡ってくるヘッダからホスト名取得
const key = event.request.headers.host.value;
let value = "google.com"; // デフォルトリダイレクト先
try {
value = await kvsHandle.get(key);
} catch (err) {
console.log(`Kvs key lookup failed for ${key}: ${err}`);
}
var response = {
statusCode: 301,
statusDescription: 'Moved Permanently',
headers: {
'location': { value: `https://${value}/` } // リダイレクト先URL
}
};
return response;
}
{
"PK": {
"S": "REDIRECTS"
},
"redirectSettings": {
"L": [
{
"M": {
"CloudFrontID": {
"S": "リダイレクト元CloudFrontID"
},
"DomainZoneId": {
"S": "リダイレクト元R53ZoneID"
},
"FromDomainName": {
"S": "from.test.dosmania.link"
},
"ToDomainName": {
"S": "to.test.dosmania.link"
}
}
}
]
}
}
import { DynamoDBClient, GetItemCommand } from "@aws-sdk/client-dynamodb";
import { CloudFrontClient, UpdateDistributionCommand, GetDistributionConfigCommand } from "@aws-sdk/client-cloudfront";
import { Route53Client, ChangeResourceRecordSetsCommand } from "@aws-sdk/client-route-53";
import { CloudFrontKeyValueStoreClient, PutKeyCommand, DescribeKeyValueStoreCommand } from "@aws-sdk/client-cloudfront-keyvaluestore";
import "@aws-sdk/signature-v4-crt";
const ddbClient = new DynamoDBClient();
const cloudFrontClient = new CloudFrontClient();
const route53Client = new Route53Client();
const keyValueStoreClient = new CloudFrontKeyValueStoreClient();
export const handler = async (event) => {
const tableName = 'redirectTable';
const partitionKey = 'REDIRECTS';
const cloudFrontKeyValueStoreARN = '<CloudFrontKeyValueStoreのARN>';
const cloudFrontFunctionARN = '<CloudFrontFunctionsのARN>';
// DynamoDBからredirectSettingsを取得
const params = {
TableName: tableName,
Key: {
'PK': { S: partitionKey }
}
};
try {
const data = await ddbClient.send(new GetItemCommand(params));
const redirectSettings = data.Item.redirectSettings.L;
for (const setting of redirectSettings) {
// 設定配列データ読み込み
const cloudFrontID = setting.M.CloudFrontID.S;
const fromDomainName = setting.M.FromDomainName.S;
const fromDomainZoneId = setting.M.DomainZoneId.S;
const toDomainName = setting.M.ToDomainName.S;
console.log("start!");
// CloudFrontKeyValueStoreにキーと値をセット
// セットする前に最新のバージョンを取得する必要がある。
const ret = await keyValueStoreClient.send(new DescribeKeyValueStoreCommand({
KvsARN: cloudFrontKeyValueStoreARN
}));
// console.log(JSON.stringify(ret,null,2));
await keyValueStoreClient.send(new PutKeyCommand({
IfMatch:ret.ETag, // 現在のバージョン番号
KvsARN: cloudFrontKeyValueStoreARN,
Key: fromDomainName,
Value: toDomainName
}));
console.log("値セット完了!");
// CloudFront FunctionsをViewer Requestにアタッチ
// 現在のCloudFront設定読み込み
const distributionConfig = await cloudFrontClient.send(new GetDistributionConfigCommand({
Id: cloudFrontID
}));
// console.log(JSON.stringify(distributionConfig,null,2));
// 現在のデフォルトキャッシュビヘイビアのviewer-requestにリダイレクト用CloudFrontFunctionsをアッタッチする
distributionConfig.DistributionConfig.DefaultCacheBehavior.FunctionAssociations = {
Quantity: 1,
Items: [
{
FunctionARN: cloudFrontFunctionARN,
EventType: "viewer-request"
}
]
};
// CloudFront設定反映
const cloudFrontInfo = await cloudFrontClient.send(new UpdateDistributionCommand({
Id: cloudFrontID,
IfMatch: distributionConfig.ETag,
DistributionConfig: distributionConfig.DistributionConfig
}));
// const CloudFrontDistributionId = cloudFrontInfo.Distribution.Id;
// 設定を反映するとCloudFrontドメイン名が変わるので最新をセット
const CloudFrontDomainName= cloudFrontInfo.Distribution.DomainName ;
// Route 53のAレコードを設定
await route53Client.send(new ChangeResourceRecordSetsCommand({
HostedZoneId: fromDomainZoneId,
ChangeBatch: {
Changes: [{
Action: 'UPSERT',
ResourceRecordSet: {
Name: fromDomainName,
Type: 'A',
AliasTarget: {
HostedZoneId: 'Z2FDTNDATAQYW2', // CloudFrontのHosted Zone ID
DNSName: CloudFrontDomainName,
EvaluateTargetHealth: false
}
}
}]
}
}));
console.log(`ドメイン${fromDomainName} から ${toDomainName} へのリダイレクト設定完了!`);
}
console.log("正常終了!");
} catch (error) {
console.error(error);
throw new Error('Error processing redirect settings');
}
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment