S3バケットからローカルマシンにファイルをコピーしようとしています:
aws s3 cp s3://my-bucket-name/audio-0b7ea3d0-13ab-4c7c-ac66-1bec2e572c14.wav ./
fatal error: An error occurred (403) when calling the HeadObject operation: Forbidden
私が確認したこと:
aws-cli/1.11.13 Python/3.5.2 Linux/4.4.0-75-generic botocore/1.4.70
を使用していますバケットポリシーは、広くオープンなアクセスを許可することを目的としています。
{
"Sid": "AdminAccess",
"Effect": "Allow",
"Principal": "*",
"Action": [
"s3:*"
],
"Resource": [
"arn:aws:s3:::my-bucket-name",
"arn:aws:s3:::my-bucket-name/*"
]
}
このオブジェクトをどのようにアップロードしましたか?
AWS Signature v4署名済みアップロードポリシーを使用して、クライアントブラウザーのウェブアプリからAWSに直接このオブジェクトをアップロードしました。
オブジェクトのプロパティを見ると、オブジェクトの所有者が「匿名」であり、「匿名」ユーザーがこのオブジェクトに対する完全な権限を持っていることがわかります。
これが、このオブジェクトにアクセスできない(認証されている)理由です。例:「匿名」ユーザーには完全な許可があるため、Webブラウザーを使用してGET経由でアクセスできます。これは設計どおりに機能しています。 S3バケットはファイルをアップロードするためのもので、ファイルは一般消費者が利用できるようになります。
したがって、ファイルがアップロードポリシーでPOSTされると、結果の所有者は「匿名」になります。
この場合、 acl=bucket-owner-full-control
は、バケットの所有者がオブジェクトを制御できるように、オブジェクトのアップロード中に使用する必要があります。これを行うと、所有者は「匿名」のままになりますが、バケット所有者(私)に完全な許可が与えられ、その後AWS CLIを介してオブジェクトにアクセスできるようになります。
ご了承ください acl=ec2-bundle-read
は、実際には最新のAWS SDKにハードコーディングされたデフォルトです。 https://github.com/aws/aws-sdk-Java/blob/7844c64cf248aed889811bf2e871ad6b276a89ca/aws-Java-sdk-ec2/src/main/Java/com/amazonaws/services/ec2/util/S3UploadPolicyを参照してください.Java#L77
使用するためにS3UploadPolicy.Javaを自分のコードベース(完全に移植可能な小さなユーティリティクラスであることが判明)にコピーして変更する必要がありましたacl=bucket-owner-full-control
。そして、これによりAWS CLI経由でアップロードされたオブジェクトを管理できることを確認しました。
私の場合、3人の正規ユーザー(A1
、A2
、A3
)と3つのアカウント(canonical_user_account_A1
、canonical_user_account_A2
、canonical_user_account_A3
)があり、 R1
にある1つのIAMロール(A3
)。
ファイルはA2
のバケットにあり、ファイルの所有者はcanonical_user_account_A1
です(これは意図的です)。ファイルを一覧表示しようとしてもエラーは発生しませんでした[〜#〜] but [〜#〜]そのうちの1つをダウンロードしようとしたとき
fatal error: An error occurred (403) when calling the HeadObject operation: Forbidden
List
およびGet
パーミッションをR1
にバケットポリシーおよびロールパーミッションに追加しました。アカウントがバケットでなかった場合、これでは十分ではありません。所有者は、他のアカウントのユーザーにget
(ダウンロード)ファイルを許可できません。そのため、ファイルをアップロードするときは次のことを確認する必要がありました。
access_control_policy = {
'Grants': [
{
'Grantee': {
'ID': canonical_user_account_A2,
'Type': 'CanonicalUser'
},
'Permission': 'READ'
},
{
'Grantee': {
'ID': canonical_user_account_A3,
'Type': 'CanonicalUser'
},
'Permission': 'READ'
},
],
'Owner': {
'ID': canonical_user_account_A1
}
}
upload_extra_args = {'ACL': 'bucket-owner-full-control'}
s3_client.upload_file(file_path, bucket_name, s3_file_path, ExtraArgs=upload_extra_args)
s3_client.put_object_acl(AccessControlPolicy=access_control_policy, Bucket=bucket_name, Key=s3_file_path)
これにより、canonical_user_account_A2
とcanonical_user_account_A3
の両方がファイルを読み取ってダウンロードできるようになります。
私の場合、S3に接続しようとしたマシンが現在のシステムから遠く離れたシステム時間であった場合、上記のエラーが発生しました。正しい時間を設定するのが役立ちました。
セキュリティ上の理由でファイルが存在しない場合でも、AWS S3はForbidden(403)を返します。ダウンロード中に適切なs3パスを指定したことを確認してください。
それについてもっと読むことができます こちら
以前にアップロードしたものをs3からダウンロードしようとしたときに、同様の権限の問題が発生しました。 bucketポリシーと、アップロード時の資格情報の設定方法とアクセス権の付与方法とは関係ありませんアップロードの。問題を解決するいくつかの方法の詳細については、 this を参照してください。