Amazon Connectにカレンダー機能が追加されたのですが、土日以外に日本独自の祝日や会社都合による休業日などの対応が必要です。
年末が近づいてきて毎年この時期になると次年度のカレンダー更新が必要で、忙しい最中での対応が少し面倒です。
カレンダーとにらめっこしながらUIで登録していけばいいのですが、人手でやるのでダブルチェックが必要だったり、ケアレスミスがあったりします。
もし日付を間違えて設定して、本来休みなのに電話がつながってしまったら企業のイメージダウンや売り上げにも大きく影響します。
そんなリスクやストレスとはおさらばしたい。ということで、AWSのIaC(CDK)とSSM Parameter Storeを組み合わせて、この面倒な作業を「完全自動化」してしまうことにしました。
なぜ自動化するのか
やりたいことはシンプルです。
Amazon Connectでのカレンダー登録について手動作業をなくすこと。
毎年変わる祝日データを外部(SSM Parameter Store)に保存してあとはCDKのデプロイ一発で反映させます。
全体の仕掛け
構成はこんな感じです。
主にはAWS CDKとLambda、そして祝日データを保存するSSM Parameter Storeです。
| コンポーネント | 役割 |
|---|---|
| AWS CDK | 全体の指揮者。リソース定義とデプロイを一元管理 |
| SSM Parameter Store | 祝日リスト(JSON)の保管場所。コードを汚さずにデータだけ変えられるのが最大のメリット。 |
| Lambda | ConnectのAPIを叩いて、SSMのデータを反映 |
| Custom Resource | デプロイ時にLambdaを呼び出して、初期設定を済ませるための仕掛け。 |
ポイントは、祝日データを「動的な場所」に置いておくことですね。
これで、コードの修正とデータの更新を切り離せます。
実装ステップ
1. 祝日データの置き場所を作る
まずは反映すべき祝日データとなる祝日リストをSSM Parameter Storeに突っ込みます。
名前は適当に /connect/holiday/jp/list にします。
以下のようなJSONを文字列として登録するだけなので、簡単です。
[
{"date": "2024-01-01", "name": "元日"},
{"date": "2024-01-08", "name": "成人の日"},
{"date": "2024-02-11", "name": "建国記念の日"}
// ... 可能であれば翌年以降も入れておく
]
2. 反映用Lambdaを書く
次に、Connectの設定を書き換えるLambdaを用意します。
やっていることは単純で、SSMから取ってきたデータを元に update_hours_of_operation を叩くだけ。
update_holiday_hilo.py
import boto3
import json
import os
connect_client = boto3.client('connect')
ssm_client = boto3.client('ssm')
def lambda_handler(event, context):
# 1. 環境変数からID類を取得
instance_id = os.environ.get('CONNECT_INSTANCE_ID')
hours_of_operation_id = os.environ.get('HOURS_OF_OPERATION_ID')
# 2. SSM Parameter Storeから祝日JSONを取得
holiday_param_path = '/connect/holiday/jp/list'
response = ssm_client.get_parameter(Name=holiday_param_path)
holiday_data = json.loads(response['Parameter']['Value'])
# 3. Connectに設定するConfigを作成
# 本当は既存設定(平日など)を取得してマージする必要がありますが、
# ここでは祝日設定(FixedTimezone)に絞って書いています。
holiday_config = []
for holiday in holiday_data:
holiday_config.append({
'Day': 'SATURDAY', # 必須なので適当な曜日を指定
'Start': {'Hours': 0, 'Minutes': 0},
'End': {'Hours': 0, 'Minutes': 0},
'FixedTimezone': {
'StartTime': {'Hours': 0, 'Minutes': 0},
'EndTime': {'Hours': 0, 'Minutes': 0},
'Start': holiday['date'], # YYYY-MM-DD
'End': holiday['date']
}
})
# 4. APIを叩いて更新!
# connect_client.update_hours_of_operation(...)
return {'status': 'Success', 'message': f'Updated with {len(holiday_data)} holidays.'}
忘れがちな権限周りですが、このLambdaには ssm:GetParameter と connect:UpdateHoursOfOperation が必須です。
3. CDKで自動実行を仕込む
ここが今回の要、CDKの実装です。
デプロイした瞬間に設定まで完了していてほしいので、Custom Resource を使ってLambdaを起動させます。
app.py (CDK)
from aws_cdk import (
aws_connect as connect,
aws_lambda as lambda_,
aws_iam as iam,
aws_custom_resources as cr, # 重要
Stack
)
# ... (中略) ...
class ConnectHolidayStack(Stack):
def __init__(self, scope, id, **kwargs):
super().__init__(scope, id, **kwargs)
connect_instance_id = "arn:aws:connect:..."
# 1. Hours of Operation の箱を作る
hilo = connect.CfnHoursOfOperation(
self, "JapanHolidayHilo",
instance_arn=connect_instance_id,
name="Japan Holiday Hours",
time_zone="Asia/Tokyo",
config=[
# 平日の設定などをここに書く
]
)
# 2. 更新用Lambdaの定義
hilo_updater = lambda_.Function(
self, "HiloUpdaterFunction",
runtime=lambda_.Runtime.PYTHON_3_11,
handler="update_holiday_hilo.lambda_handler",
code=lambda_.Code.from_asset("lambda_src"),
environment={
"CONNECT_INSTANCE_ID": connect_instance_id,
"HOURS_OF_OPERATION_ID": hilo.ref
}
)
# ※ IAMロールの付与などは適宜行ってください
# 3. Custom Resourceでデプロイ時にLambdaをキック!
cr.AwsCustomResource(
self, "InitialHolidayConfigurator",
on_create=cr.AwsSdkCall(
service="Lambda",
action="invoke",
parameters={
"FunctionName": hilo_updater.function_name,
"Payload": json.dumps({"Action": "InitialConfig"})
},
physical_resource_id=cr.PhysicalResourceId.of("InitialHolidayConfig")
),
policy=cr.AwsCustomResourcePolicy.from_statements([
iam.PolicyStatement(
actions=["lambda:InvokeFunction"],
resources=[hilo_updater.function_arn]
)
])
)
自動化の結果
cdk deploy を叩くとあっという間にすべてが終わりました。
Amazon Connectの管理画面を開くと、そこにはSSMに入れた通りの祝日設定が綺麗に反映されています。
あとはEventBridgeでこのLambdaを年イチで定期実行するようにしておけば、もうカレンダーを登録する作業は不要で反映の確認だけです。
Hours of Operationの設定はIaC管理しにくい部分ですが、SSM PSとLambdaを組み合わせればここまで柔軟にできます。