Route53にNSレコードと証明書CNAMEを登録するシェル

# やりたいこと
AWSコンソールから取得したドメイン(ネイキッドドメイン)のホストゾーンに、CloudFormationで作成した本番&検証用ドメインを登録する作業を自動化したい。
# コード全文
```
#!/bin/bash

# NSレコードを既存のホストゾーンに登録する関数
register_ns_records_in_naked_hosted_zone() {
  CREATE_HOSTED_ZONE_NAME=$1

  # 作成したホストゾーンのホストゾーンIDを取得
  CREATE_HOSTED_ZONE_ID=$(aws route53 list-hosted-zones-by-name \
    --dns-name $CREATE_HOSTED_ZONE_NAME \
    --query "HostedZones[0].Id" \
    --output text | sed 's|/hostedzone/||')

  if [ -z "$CREATE_HOSTED_ZONE_ID" ]; then
    echo "ホストゾーンIDが見つかりません。ホストゾーン名を確認してください。"
    exit 1
  fi

  # ホストゾーンのNSレコードを取得
  NS_RECORDS=$(aws route53 list-resource-record-sets --hosted-zone-id $CREATE_HOSTED_ZONE_ID \
    --query "ResourceRecordSets[?Type=='NS'].ResourceRecords[*].Value" \
    --output text )

　# ネイキッドのホストゾーンIDの取得
  NAKED_HOSTED_ZONE_ID=$(aws route53 list-hosted-zones-by-name \
    --dns-name $NAKED_HOSTED_ZONE_NAME \
    --query "HostedZones[0].Id" \
    --output text  sed 's|/hostedzone/||')

  # NSレコードを既存のホストゾーンに追加
  CHANGE_BATCH_NS=$(
    cat <<EOF
    {
      "Changes": [
        {
          "Action": "CREATE",
          "ResourceRecordSet": {
            "Name": "$CREATE_HOSTED_ZONE_NAME",
            "Type": "NS",
            "TTL": 172800,
            "ResourceRecords": [
              $(for ns in $NS_RECORDS; do echo "{\"Value\": \"$ns\"},"; done | sed '$ s/,$//')
            ]
          }
        }
      ]
    }
EOF
  )

  aws route53 change-resource-record-sets \
    --hosted-zone-id $NAKED_HOSTED_ZONE_ID \
    --change-batch "$CHANGE_BATCH_NS" 

  echo "NSレコードを既存のホストゾーンに追加しました。"
}

# ACMのCNAMEレコードを既存のホストゾーンに登録する関数
register_all_acm_cname_in_naked_hosted_zone() {
  # バージニア北部リージョンでACM証明書リストを取得
  ACM_CERTIFICATE_ARNS=$(aws acm list-certificates \
    --region us-east-1 \
    --query "CertificateSummaryList[*].CertificateArn" \
    --output text)

  if [ -z "$ACM_CERTIFICATE_ARNS" ]; then
    echo "ACM証明書が見つかりません。"
    exit 1
  fi

  NAKED_HOSTED_ZONE_ID=$(aws route53 list-hosted-zones-by-name \
    --dns-name $NAKED_HOSTED_ZONE_NAME \
    --query "HostedZones[0].Id" \
    --output text | sed 's|/hostedzone/||')

  for ACM_CERTIFICATE_ARN in $ACM_CERTIFICATE_ARNS; do
    # 各ACM証明書のCNAMEレコードを取得
    ACM_CNAME=$(aws acm describe-certificate \
      --certificate-arn $ACM_CERTIFICATE_ARN \
      --region us-east-1 \
      --query "Certificate.DomainValidationOptions[0].ResourceRecord" \
      --output json)

    if [ -z "$ACM_CNAME" ]; then
      echo "ACMのCNAMEレコードが見つかりません。証明書ARN: $ACM_CERTIFICATE_ARN"
      continue
    fi

    # ACM CNAMEレコードを既存のホストゾーンに追加
    CHANGE_BATCH_ACM=$(
      cat <<EOF
      {
        "Changes": [
          {
            "Action": "CREATE",
            "ResourceRecordSet": {
              "Name": "$(echo $ACM_CNAME | jq -r .Name)",
              "Type": "CNAME",
              "TTL": 300,
              "ResourceRecords": [
                {
                  "Value": "$(echo $ACM_CNAME | jq -r .Value)"
                }
              ]
            }
          }
        ]
      }
EOF
    )

    aws route53 change-resource-record-sets \
      --hosted-zone-id $NAKED_HOSTED_ZONE_ID \
      --change-batch "$CHANGE_BATCH_ACM"

    echo "ACM証明書($ACM_CERTIFICATE_ARN)のCNAMEレコードを登録しました。"
  done
}

# NSレコードを登録
if [ $NAKED_DOMAIN_NAME != $MAIN_DOMAIN_NAME ]; then
register_ns_records_in_naked_hosted_zone $MAIN_DOMAIN_NAME
fi
register_ns_records_in_naked_hosted_zone $SUB_DOMAIN_NAME
# ACM CNAMEレコードを登録
register_all_acm_cname_in_naked_hosted_zone
```

# 解説
CLIでホストゾーンにレコードを登録するにはホストゾーンのIDが必要なため、下記で取得。
>ホストゾーン名は関数実行の引数で指定
```
  # 作成したホストゾーンのホストゾーンIDを取得
  CREATE_HOSTED_ZONE_ID=$(aws route53 list-hosted-zones-by-name \
    --dns-name $CREATE_HOSTED_ZONE_NAME \
    --query "HostedZones[0].Id" \
    --output text | sed 's|/hostedzone/||')

  if [ -z "$CREATE_HOSTED_ZONE_ID" ]; then
    echo "ホストゾーンIDが見つかりません。ホストゾーン名を確認してください。"
    exit 1
  fi

　# ネイキッドのホストゾーンIDの取得
  NAKED_HOSTED_ZONE_ID=$(aws route53 list-hosted-zones-by-name \
    --dns-name $NAKED_HOSTED_ZONE_NAME \
    --query "HostedZones[0].Id" \
    --output text  sed 's|/hostedzone/||')
```

証明書は環境に存在するもの全てを登録する想定でARNを取得。
```
  for ACM_CERTIFICATE_ARN in $ACM_CERTIFICATE_ARNS; do
    # 各ACM証明書のCNAMEレコードを取得
    ACM_CNAME=$(aws acm describe-certificate \
      --certificate-arn $ACM_CERTIFICATE_ARN \
      --region us-east-1 \
      --query "Certificate.DomainValidationOptions[0].ResourceRecord" \
      --output json)

    if [ -z "$ACM_CNAME" ]; then
      echo "ACMのCNAMEレコードが見つかりません。証明書ARN: $ACM_CERTIFICATE_ARN"
      continue
    fi
```

ホストゾーンに登録
```
  aws route53 change-resource-record-sets \
    --hosted-zone-id $NAKED_HOSTED_ZONE_ID \
    --change-batch "$CHANGE_BATCH_NS" 

    aws route53 change-resource-record-sets \
      --hosted-zone-id $NAKED_HOSTED_ZONE_ID \
      --change-batch "$CHANGE_BATCH_ACM"
```