我正在尝试向s3中的现有帐户授予权限。
该存储桶由该帐户拥有,但该数据是从另一个帐户的存储桶中复制的。
当我尝试使用以下命令授予权限时:
aws s3api put-object-acl --bucket <bucket_name> --key <folder_name> --profile <original_account_profile> --grant-full-control emailaddress=<destination_account_email>
我收到错误:
An error occurred (NoSuchKey) when calling the PutObjectAcl operation: The specified key does not exist.
如果我在单个文件上执行该操作,则命令成功。
如何使其适用于完整文件夹?
答案 0 :(得分:8)
这只能通过使用管道来实现。试试 -
aws s3 ls s3://bucket/path/ --recursive | awk '{cmd="aws s3api put-object-acl --acl bucket-owner-full-control --bucket bucket --key "$4; system(cmd)}'
答案 1 :(得分:4)
其他答案也可以,但是最快的方法是将aws s3 cp
命令与选项--metadata-directive REPLACE
一起使用,如下所示:
aws s3 cp --recursive --acl bucket-owner-full-control s3://bucket/folder s3://bucket/folder --metadata-directive REPLACE
这给出了50Mib / s至80Mib / s的速度。
John R评论的答案,该评论建议使用“虚拟”选项,例如--storage-class STANDARD
。尽管这样做有效,但复制速度却只有5Mib / s至11mb / s。
尝试此操作的灵感来自AWS关于以下主题的支持文章:https://aws.amazon.com/premiumsupport/knowledge-center/s3-object-change-anonymous-ownership/
注意:如果您遇到某些对象的“拒绝访问”,这可能是因为您将AWS凭证用于存储桶拥有账户,而将凭证用于复制文件的账户。 / p>
答案 2 :(得分:3)
您需要为每个对象单独运行命令。
您可以使用以下方法缩短流程:
aws s3 cp --acl bucket-owner-full-control --metadata Key=Value --profile <original_account_profile> s3://bucket/path s3://bucket/path
也就是说,您将文件复制到自己,但使用添加的ACL授予存储桶拥有者权限。
如果您有子目录,请添加--recursive
。
答案 3 :(得分:0)
使用python递归设置权限
#!/usr/bin/env python
import boto3
import sys
client = boto3.client('s3')
BUCKET='enter-bucket-name'
def process_s3_objects(prefix):
"""Get a list of all keys in an S3 bucket."""
kwargs = {'Bucket': BUCKET, 'Prefix': prefix}
failures = []
while_true = True
while while_true:
resp = client.list_objects_v2(**kwargs)
for obj in resp['Contents']:
try:
print(obj['Key'])
set_acl(obj['Key'])
kwargs['ContinuationToken'] = resp['NextContinuationToken']
except KeyError:
while_true = False
except Exception:
failures.append(obj["Key"])
continue
print "failures :", failures
def set_acl(key):
client.put_object_acl(
GrantFullControl="id=%s" % get_account_canonical_id,
Bucket=BUCKET,
Key=key
)
def get_account_canonical_id():
return client.list_buckets()["Owner"]["ID"]
process_s3_objects(sys.argv[1])
答案 4 :(得分:0)
这种方式的python代码效率更高,否则将花费更长的时间。
import boto3
import sys
client = boto3.client('s3')
BUCKET='mybucket'
def process_s3_objects(prefix):
"""Get a list of all keys in an S3 bucket."""
kwargs = {'Bucket': BUCKET, 'Prefix': prefix}
failures = []
while_true = True
while while_true:
resp = client.list_objects_v2(**kwargs)
for obj in resp['Contents']:
try:
set_acl(obj['Key'])
except KeyError:
while_true = False
except Exception:
failures.append(obj["Key"])
continue
kwargs['ContinuationToken'] = resp['NextContinuationToken']
print ("failures :"+ failures)
def set_acl(key):
print(key)
client.put_object_acl(
ACL='bucket-owner-full-control',
Bucket=BUCKET,
Key=key
)
def get_account_canonical_id():
return client.list_buckets()["Owner"]["ID"]
process_s3_objects(sys.argv[1])
答案 5 :(得分:0)
这是我唯一的 if let response = response{
for item in response.mapItems{
print("map item returned: \(item.placemark)")
if let region = item.placemark.region as? CLCircularRegion{
print("region.center: \(region.center)")
let annotation = MKPointAnnotation()
annotation.coordinate = region.center
annotation.title = item.name
self.mapView.addAnnotation(annotation)
}
}
解决方案。
powershell
答案 6 :(得分:0)
我使用这个 Linux Bash shell oneliner 递归地更改 ACL:
aws s3 ls s3://bucket --recursive | cut -c 32- | xargs -n 1 -d '\n' -- aws s3api put-object-acl --acl public-read --bucket bukcet --key
即使文件名包含 () 字符也能工作。
答案 7 :(得分:0)
我在获取一个相当大的存储桶中的日志对象的所有权时遇到了类似的问题。 对象总数 - 3,290,956 总大小 1.4 TB。
我能找到的解决方案对于这么多对象来说太慢了。我最终编写了一些代码,这些代码能够比
快几倍地完成这项工作 <块引用>aws s3 cp
您需要安装要求:
pip install pathos boto3 click
#!/usr/bin/env python3
import logging
import os
import sys
import boto3
import botocore
import click
from time import time
from botocore.config import Config
from pathos.pools import ThreadPool as Pool
logger = logging.getLogger(__name__)
streamformater = logging.Formatter("[*] %(levelname)s: %(asctime)s: %(message)s")
logstreamhandler = logging.StreamHandler()
logstreamhandler.setFormatter(streamformater)
def _set_log_level(ctx, param, value):
if value:
ctx.ensure_object(dict)
ctx.obj["log_level"] = value
logger.setLevel(value)
if value <= 20:
logger.info(f"Logger set to {logging.getLevelName(logger.getEffectiveLevel())}")
return value
@click.group(chain=False)
@click.version_option(version='0.1.0')
@click.pass_context
def cli(ctx):
"""
Take object ownership of S3 bucket objects.
"""
ctx.ensure_object(dict)
ctx.obj["aws_config"] = Config(
retries={
'max_attempts': 10,
'mode': 'standard'
}
)
@cli.command("own")
@click.argument("bucket", type=click.STRING)
@click.argument("prefix", type=click.STRING, default="/")
@click.option("--profile", type=click.STRING, default="default", envvar="AWS_DEFAULT_PROFILE", help="Configuration profile from ~/.aws/{credentials,config}")
@click.option("--region", type=click.STRING, default="us-east-1", envvar="AWS_DEFAULT_REGION", help="AWS region")
@click.option("--threads", "-t", type=click.INT, default=40, help="Threads to use")
@click.option("--loglevel", "log_level", hidden=True, flag_value=logging.INFO, callback=_set_log_level, expose_value=False, is_eager=True, default=True)
@click.option("--verbose", "-v", "log_level", flag_value=logging.DEBUG, callback=_set_log_level, expose_value=False, is_eager=True, help="Increase log_level")
@click.pass_context
def command_own(ctx, *args, **kwargs):
ctx.obj.update(kwargs)
profile_name = ctx.obj.get("profile")
region = ctx.obj.get("region")
bucket = ctx.obj.get("bucket")
prefix = ctx.obj.get("prefix").lstrip("/")
threads = ctx.obj.get("threads")
pool = Pool(nodes=threads)
logger.addHandler(logstreamhandler)
logger.info(f"Getting ownership of all objects in s3://{bucket}/{prefix}")
start = time()
try:
SESSION: boto3.Session = boto3.session.Session(profile_name=profile_name)
except botocore.exceptions.ProfileNotFound as e:
logger.warning(f"Profile {profile_name} was not found.")
logger.warning(f"Falling back to environment variables for AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY and AWS_SESSION_TOKEN")
AWS_ACCESS_KEY_ID = os.environ.get("AWS_ACCESS_KEY_ID", "")
AWS_SECRET_ACCESS_KEY = os.environ.get("AWS_SECRET_ACCESS_KEY", "")
AWS_SESSION_TOKEN = os.environ.get("AWS_SESSION_TOKEN", "")
if AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY:
if AWS_SESSION_TOKEN:
SESSION: boto3.Session = boto3.session.Session(aws_access_key_id=AWS_ACCESS_KEY_ID, aws_secret_access_key=AWS_SECRET_ACCESS_KEY,
aws_session_token=AWS_SESSION_TOKEN)
else:
SESSION: boto3.Session = boto3.session.Session(aws_access_key_id=AWS_ACCESS_KEY_ID, aws_secret_access_key=AWS_SECRET_ACCESS_KEY)
else:
logger.error("Unable to find AWS credentials.")
sys.exit(1)
s3c = SESSION.client('s3', config=ctx.obj["aws_config"])
def bucket_keys(Bucket, Prefix='', StartAfter='', Delimiter='/'):
Prefix = Prefix[1:] if Prefix.startswith(Delimiter) else Prefix
if not StartAfter:
del StartAfter
if Prefix.endswith(Delimiter):
StartAfter = Prefix
del Delimiter
for page in s3c.get_paginator('list_objects_v2').paginate(Bucket=Bucket, Prefix=Prefix):
for content in page.get('Contents', ()):
yield content['Key']
def worker(key):
logger.info(f"Processing: {key}")
s3c.copy_object(Bucket=bucket, Key=key,
CopySource={'Bucket': bucket, 'Key': key},
ACL='bucket-owner-full-control',
StorageClass="STANDARD"
)
object_keys = bucket_keys(bucket, prefix)
pool.map(worker, object_keys)
end = time()
logger.info(f"Completed for {end - start:.2f} seconds.")
if __name__ == '__main__':
cli()
用法:
get_object_ownership.py own -v my-big-aws-logs-bucket /prefix
上面提到的存储桶使用 40 个线程处理了大约 7 个小时。
<块引用>[*] 信息:2021-08-05 19:53:55,542:完成 25320.45 秒。
在相同的数据子集上使用 AWS cli 与此工具进行更多速度比较:
<块引用>aws s3 cp --recursive --acl bucket-owner-full-control --metadata-directive 53.59s 用户 7.24s 系统 20% cpu 5:02.42 总计
对比
<块引用>[*] 信息:2021-08-06 09:07:43,506:完成 49.09 秒。
答案 8 :(得分:-3)
aws s3api put-object-acl --bucket bucketname_example_3636 --key bigdirectories2_noglacier / bkpy_workspace_sda4.tar --acl bucket-owner-full-control
aws s3 ls s3:// bucketname_example_3636 --recursive> listoffile.txt
sed's /^(.*)$/ aws s3api put-object-acl --bucket bucketname_example_3636 --key \ 1 --acl bucket-owner-full-control / g'listoffile.txt> listoffile_v2.txt ;
sed'1 i \#!/ bin / bash'listoffile_v2.txt> listoffile_v3.txt;
cp listoffile_v3.txt listoffile_v3.sh;
chmod u + x listoffile_v3.sh;
listoffile_v3.sh;