やりたかったこと
- CloudFrontに設定しているレスポンスヘッダーの値を変更する
- SPAコンテンツをデプロイ時に更新チェック用にと・・・
 
試したこと(NGケース)
- AWS CLIで現在の設定値のJSONを取得
- 変更したいレスポンスヘッダーの値を更新
- JSONで更新に必要な部分の抜粋(ResponseHeadersPolicyConfigの中身だけ使うので)
- ETAG取得
- AWS CLIで更新
用意したコマンド
# 現在の設定を取得
aws cloudfront get-response-headers-policy --id $TATGET_POLICY_ID > config.json
# 書き替え
jq '(.ResponseHeadersPolicy.ResponseHeadersPolicyConfig.CustomHeadersConfig.Items[] | select(.Header == "x-xxxxxxx-id").Value) |= "★変更後の値★"' config.json > update_config_1.json
# 比較
diff -w config.json update_config_1.json
# 更新ファイル準備
jq '.ResponseHeadersPolicy.ResponseHeadersPolicyConfig' update_config_1.json > update_config_2.json
# 更新
ETAG=$(jq -r '.ETag' response_config.json)
aws cloudfront update-response-headers-policy --id $TATGET_POLICY_ID --if-match $ETAG --response-headers-policy-config file://update_response_config_excerpt.json
コマンドの結果
マネジメントコンソールで指定していないセキュリティヘッダーも指定が必要とエラーが発生!
Parameter validation failed:
Missing required parameter in ResponseHeadersPolicyConfig.SecurityHeadersConfig.XSSProtection: "Override"
Missing required parameter in ResponseHeadersPolicyConfig.SecurityHeadersConfig.XSSProtection: "Protection"
Missing required parameter in ResponseHeadersPolicyConfig.SecurityHeadersConfig.FrameOptions: "Override"
Missing required parameter in ResponseHeadersPolicyConfig.SecurityHeadersConfig.FrameOptions: "FrameOption"
Missing required parameter in ResponseHeadersPolicyConfig.SecurityHeadersConfig.ReferrerPolicy: "Override"
Missing required parameter in ResponseHeadersPolicyConfig.SecurityHeadersConfig.ReferrerPolicy: "ReferrerPolicy"
Missing required parameter in ResponseHeadersPolicyConfig.SecurityHeadersConfig.ContentSecurityPolicy: "Override"
Missing required parameter in ResponseHeadersPolicyConfig.SecurityHeadersConfig.ContentSecurityPolicy: "ContentSecurityPolicy"
Missing required parameter in ResponseHeadersPolicyConfig.SecurityHeadersConfig.ContentTypeOptions: "Override"
Missing required parameter in ResponseHeadersPolicyConfig.SecurityHeadersConfig.StrictTransportSecurity: "Override"
Missing required parameter in ResponseHeadersPolicyConfig.SecurityHeadersConfig.StrictTransportSecurity: "AccessControlMaxAgeSec"
エラーの原因と対策
今回は、以下のような更新するJSONを用意していましたが、SecurityHeadersConfigの中の各項目(←ここの箇所)は空なら、項目を削除しなければいけないみたいです。
{
  "Comment": "xxxxxx",
  "Name": "sample-custom-header",
  "SecurityHeadersConfig": {
    "XSSProtection": {}, ←ここ
    "FrameOptions": {}, ←ここ
    "ReferrerPolicy": {}, ←ここ
    "ContentSecurityPolicy": {}, ←ここ
    "ContentTypeOptions": {} ←ここ
  },
  "CustomHeadersConfig": {
    "Quantity": 1,
    "Items": [
      {
        "Header": "x-xxxxxx-id",
        "Value": "X123456Y",
        "Override": false
      }
    ]
  }
}
つまり、用意しないとダメなのは、こんな感じです。(SecurityHeadersConfigは非必須なので消して良いかも)
{
  "Comment": "xxxxxx",
  "Name": "sample-custom-header",
  "SecurityHeadersConfig": {
  },
  "CustomHeadersConfig": {
    "Quantity": 1,
    "Items": [
      {
        "Header": "x-xxxxxx-id",
        "Value": "X123456Y",
        "Override": false
      }
    ]
  }
}
試したこと(OKケース)
- AWS CLIで現在の設定値のJSONを取得
- 変更したいレスポンスヘッダーの値を更新
- JSONで更新に必要な部分の抜粋(ResponseHeadersPolicyConfigの中身だけ使うので)
- セキュリティヘッダーの中身が空の場合は項目を削除
- ETAG取得
- AWS CLIで更新
修正したコマンド
# 現在の設定を取得
aws cloudfront get-response-headers-policy --id $TATGET_POLICY_ID > response_config.json
# 書き替え
jq '(.ResponseHeadersPolicy.ResponseHeadersPolicyConfig.CustomHeadersConfig.Items[] | select(.Header == "x-contents-id").Value) |= "X123456X"' response_config.json > update_response_config_1.json
# 比較
diff -w response_config.json update_response_config_1.json
# 更新ファイル準備
jq '.ResponseHeadersPolicy.ResponseHeadersPolicyConfig' update_response_config_1.json > update_response_config_2.json
# セキュリティ設定で未設定項目は削除
jq '(.SecurityHeadersConfig.XSSProtection | length == 0) as $xss | 
    (.SecurityHeadersConfig.FrameOptions | length == 0) as $frame |
    (.SecurityHeadersConfig.ReferrerPolicy | length == 0) as $referrer |
    (.SecurityHeadersConfig.ContentSecurityPolicy | length == 0) as $csp |
    (.SecurityHeadersConfig.ContentTypeOptions | length == 0) as $content |
    (.SecurityHeadersConfig.StrictTransportSecurity | length == 0) as $sts |
    del(
        if $xss then .SecurityHeadersConfig.XSSProtection else empty end,
        if $frame then .SecurityHeadersConfig.FrameOptions else empty end,
        if $referrer then .SecurityHeadersConfig.ReferrerPolicy else empty end,
        if $csp then .SecurityHeadersConfig.ContentSecurityPolicy else empty end,
        if $content then .SecurityHeadersConfig.ContentTypeOptions else empty end,
        if $sts then .SecurityHeadersConfig.StrictTransportSecurity else empty end
    )' update_response_config_2.json > update_response_config_3.json
# 比較
diff -w update_response_config_2.json update_response_config_3.json
# 更新
ETAG=$(jq -r '.ETag' response_config.json)
aws cloudfront update-response-headers-policy --id $TATGET_POLICY_ID --if-match $ETAG --response-headers-policy-config file://update_response_config_3.json