【发布时间】:2020-09-16 00:31:33
【问题描述】:
我正在测试使用 javascript 显示来自 s3 存储桶的图像,然后再将其作为应用程序的一部分。
我有一个 s3 存储桶(非公开),以这篇文章命名:IMAGE-BUCKET 创建了一个身份角色:GET-IMAGE。 我暂时授予了对 GET-IMAGE 角色的完全 s3 访问权限。 我为存储桶定义了 CORS。 在测试时,我禁用了浏览器缓存。
3 个问题:
- 当从 html/脚本如下。
- 如果我将特定图像公开,则会显示该图像 -- 图像数量过多时会出现问题。
- 如果我将整个存储桶公开,则不会显示图像
Cognito 身份似乎无法访问存储桶,或者下面的脚本中存在问题。
此外,将存储桶设置为公开也不起作用,除非每个图像也设置为公开。此存储桶将被私人使用,因此这只是故障排除时的问题。
我已将 AmazonS3FullAccess 附加到 GET-IMAGE,我还添加了以下策略:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AccessS3BucketIMAGEBUCKET",
"Action": [
"s3:GetObject",
"s3:PutObject",
"s3:ListBucket"
],
"Effect": "Allow",
"Resource": "*"
}
]
}
使用来自 AWS 文档的 html 和脚本(修改):
<script src="https://sdk.amazonaws.com/js/aws-sdk-2.487.0.js"></script>
<script>
var albumBucketName = 'IMAGE-BUCKET';
// Initialize the Amazon Cognito credentials provider for GET-IMAGE:
AWS.config.region = 'us-east-1'; // Region
AWS.config.credentials = new AWS.CognitoIdentityCredentials({
IdentityPoolId: 'us-east-1:43ba4c15-ab2f-8880-93be-xxx',
});
// Create a new service object
var s3 = new AWS.S3({
apiVersion: '2006-03-01',
params: { Bucket: albumBucketName }
});
// A utility function to create HTML.
function getHtml(template) {
return template.join('\n');
}
// Show the photos that exist in an album.
function viewAlbum(albumName) {
var albumPhotosKey = '/';
s3.listObjects(function (err, data) {
if (err) {
return alert('There was an error viewing your album: ' + err.message);
}
// 'this' references the AWS.Response instance that represents the response
var href = this.request.httpRequest.endpoint.href;
var bucketUrl = href + albumBucketName + '/';
var photos = data.Contents.map(function (photo) {
var photoKey = photo.Key;
var photoUrl = bucketUrl + encodeURIComponent(photoKey);
return getHtml([
'<span>',
'<div>',
'<br/>',
'<img style="width:128px;height:128px;" src="' + photoUrl + '"/>',
'</div>',
'<div>',
'<span>',
photoKey.replace(albumPhotosKey, ''),
'</span>',
'</div>',
'</span>',
]);
});
var message = photos.length ?
'<p>The following photos are present.</p>' :
'<p>There are no photos in this album.</p>';
var htmlTemplate = [
'<div>',
'<button onclick="listAlbums()">',
'Back To Albums',
'</button>',
'</div>',
'<h2>',
'Album: ' + albumName,
'</h2>',
message,
'<div>',
getHtml(photos),
'</div>',
'<h2>',
'End of Album: ' + albumName,
'</h2>',
'<div>',
'<button onclick="listAlbums()">',
'Back To Albums',
'</button>',
'</div>',
]
document.getElementById('viewer').innerHTML = getHtml(htmlTemplate);
document.getElementsByTagName('img')[0].setAttribute('style', 'display:none;');
});
}
</script>
</head>
<body>
<h1>Photo Album Viewer</h1>
<div id="viewer" />
<button onclick="viewAlbum('');">View All Images</button>
</body>
</html>
更新: 如果我在 S3 存储桶策略中授予公开读取权限:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "PublicRead",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::IMAGE-BUCKET/*"
}
]
}
它允许访问每个图像;解决问题#2 和#3。 但这使得桶基本上是公开的。
如果我将 Bucket 策略更改为限制为 Cognito 身份,如下更改主体,我再次无法通过 html/script 访问图像,出现 403 错误。
"Principal": {
"AWS": "arn:aws:iam::547299998870:role/Cognito_GET-IMAGEIDUnauth_Role"
}
更新: 我一直在网上阅读,检查了一些其他相关的帖子...... 我已将其简化为基本组件,这是最新配置。配置应该很简单,根据文档授予对 GET-IMAGE 角色的访问权限:
在 IAM 管理控制台 > 角色 > GET-IMAGE 角色(未经身份验证)下 我添加了一个内联策略:
{
"Sid": "VisualEditor2",
"Effect": "Allow",
"Action": ["s3:GetObject","s3:ListBucket"],
"Resource": "arn:aws:s3:::IMAGE-BUCKET/*"
}
我删除了 Bucket 策略——这不应该是必需的,GET-IMAGE 角色已经拥有访问权限。默认情况下已包含角色信任。 HTML 包含凭据: IdentityPoolId: 'us-east-1:9bfadd6a-xxxx-41d4-xxxx-79ad7347xxa1
这些是最基本的组件,不需要其他任何东西。但是,它不起作用。我公开了其中 1 张图片并显示了该图片,其他图片错误并显示 403 Forbidden。
【问题讨论】:
-
澄清一下,在设置您的身份池时,您是否将 GET-IMAGE 角色分配给 Unuathorized Identities?因此,您在顶部显示的策略已分配给 Cognito_GET-IMAGEIDUnauth_Role?
-
我添加到 s3 Bucket Policy 中的上述策略(在权限选项卡下)。我还为未经授权的 id 分配了 GET-IMAGE 策略。虽然我上面提到的主要 arn 是有效的并且被政策接受,但我认为使用可能不正确。到目前为止,我正在研究但没有取得多大成功。
-
您的 listObjects() 方法不应该将
params对象作为第一个参数吗? -
它是内联的。我找到了指定主体的正确格式,"Principal": { "Federated": "arn:aws:iam::54729999970:role/Cognito_GET-IMAGEIDUnauth_Role" .. 这也不起作用。如果我设置 Principal: "*" ,这一切都有效。另外,bucket policy 不喜欢 "Conditions" ,我试过不同的版本。