Tech Hotoke Blog

IT観音とは私のことです。

【備忘録】AWS:S3 オブジェクトのコピー処理を行った際に VPC endpoints do not support cross-region requests が発生した際の対応

環境

前提

  • コピー対象のobjectは 同一VPC内 かつ 同一リージョン内に存在する

事象

  • 以下のような処理で同一バケット内のobjectを別の階層のobjectにコピーする処理を実行した際に、ステータスコード403 かつ Aws::S3::Errors::AccessDenied: VPC endpoints do not support cross-region requests が発生した
    def backup_objects(bucket, prefix)
      bucket.objects(prefix: prefix).each do |obj|
        next if obj.key.sub(prefix, '').start_with?('bk/')

        backup_key = obj.key.sub(prefix, "#{prefix}bk/")
        bucket.object(backup_key).copy_from(
          copy_source: "#{obj.key}"
        )
        Rails.logger.info "Backup: #{obj.key} -> #{backup_key}"
      end
    end

結論

bucket.object(backup_key).copy_from(copy_source: "#{obj.key}") の引数にバケット名が不足していたこと bucket.object(backup_key).copy_from(copy_source: "#{bucket.name}/#{obj.key}") としたことで解消

プロセス

  • VPC endpoints do not support cross-region requests となっていたため、IAMロールやバケットのアクセスポリシーに問題があるのかと考えたため、ハマった。
  • 冷静に考えると、同一バケットへの処理なので、そんなはずなかった。(すでにIAMロールやバケットのアクセスポリシーが正常に動作している実績があったため)
  • Class: Aws::S3::Object — AWS SDK for Ruby V3 を見ると、bucketの指定が必要であることも確認できた

  • メソッドの引数に不正な値が入る時、 403エラーかつ Aws::S3::Errors::AccessDenied: VPC endpoints do not support cross-region requests が返るということを頭の片隅に置いておく必要がある

    • 存在しないパスに対してコピー処理を実行しているなら、404とかでもいい気がするけどそれは違うのだろうか

補足

  • copy_fromメソッドは 5GB 以上のobjectを処理する場合は、multipart_copy: true を指定する必要がある