Last active
July 24, 2024 03:02
-
-
Save akira345/5a0e91c384c2b14dc1074094722619da to your computer and use it in GitHub Desktop.
CloudFrontKeyValueStoreをつかったリダイレクト設定ラムダ
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"PK": { | |
"S": "REDIRECTS" | |
}, | |
"redirectSettings": { | |
"L": [ | |
{ | |
"M": { | |
"CloudFrontID": { | |
"S": "リダイレクト元CloudFrontID" | |
}, | |
"DomainZoneId": { | |
"S": "リダイレクト元R53ZoneID" | |
}, | |
"FromDomainName": { | |
"S": "from.test.dosmania.link" | |
}, | |
"ToDomainName": { | |
"S": "to.test.dosmania.link" | |
} | |
} | |
} | |
] | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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