Я пытаюсь загрузить файлы из корзины S3 поставщика в мою корзину S3, используя boto3. Я использую службу sts, чтобы взять на себя роль для доступа к корзине поставщика s3. Я могу подключиться к корзине поставщиков и получить список корзин. Я сталкиваюсь с ошибкой CopyObject operation: Access Denied
при копировании в корзину. Вот мой сценарий
session = boto3.session.Session(profile_name = "s3_transfer")
sts_client = session.client("sts", verify=False)
assumed_role_object = sts_client.assume_role(
RoleArn = "arn:aws:iam::<accountid>:role/assumedrole",
RoleSessionName = "transfer_session",
ExternalId = "<ID>",
DurationSeconds=18000,
)
creds = assumed_role_object["Credentials"]
src_s3 = boto3.client(
"s3",
aws_access_key_id=creds["AccessKeyId"],
aws_secret_access_key=creds["SecretAccessKey"],
aws_session_token=creds["SessionToken"],
verify=False,
)
paginator =src_s3.get_paginator("list_objects_v2")
# testing with just 2 items.
# TODO: Remove MaxItems once script works.
pages = paginator.paginate(
Bucket = "ven_bucket", Prefix = "client", PaginationConfig = {"MaxItems": 2, "PageSize": 1000}
)
dest_s3 = session.client("s3", verify=False)
for page in pages:
for obj in page["Contents"]:
src_key = obj["Key"]
des_key = dest_prefix + src_key[len(src_prefix) :]
src = {"Bucket": "ven_bucket", "Key": src_key}
print(src)
print(des_key)
dest_s3.copy(src, "my-bucket", des_key, SourceClient=src_s3)
Строка dest_s3.copy...
- это место, где я получаю сообщение об ошибке. У меня есть следующая политика моего пользователя aws, позволяющая копировать в мое ведро
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor1",
"Effect": "Allow",
"Action": [
"s3:*"
],
"Resource": [
"arn:aws:s3:::my-bucket/*",
"arn:aws:s3:::my-bucket/"
]
}
]
}
Я получаю следующую ошибку при запуске вышеуказанного скрипта.
botocore.exceptions.ClientError: An error occurred (AccessDenied) when calling the CopyObject operation: Access Denied
@jarmod Я могу получить доступ к объекту в исходном сегменте, используя эти учетные данные. И из политики учетной записи пользователя я также должен иметь возможность копировать в целевую учетную запись, если я что-то не упустил. Я могу загрузить файлы из источника на свой локальный компьютер, а затем загрузить их в место назначения, используя эти учетные данные. Тогда ошибка возникает при попытке скопировать напрямую из источника в пункт назначения.
Если учетные данные, которые вы используете для копии, имеют доступ к исходным объектам, то почему вы используете временные учетные данные STS для перечисления исходных объектов (используя src_s3)?
Доступ @jarmod к корзине с исходным кодом осуществляется через предполагаемую роль sts.
Если я неправильно прочитал ваш код, доступ к исходному сегменту для операции копирования не использует кредиты STS. Он использует кредиты s3_transfer. Операция копирования использует один набор кредитов (и только один), и это кредиты, связанные с клиентом dest_s3.
@jarmod Я использую кредиты sts, чтобы взять на себя роль, и запросить временные кредиты. Затем я использую эти временные кредиты для создания исходного клиента s3. Если это не так, можете ли вы показать, как я должен переписать это? Спасибо.
Давайте продолжить обсуждение в чате.
принятый ответ сработал для вас? Можете ли вы опубликовать обновленный код, пожалуйста?
@saadi У меня было 2 клиента s3, один из которых был подключен к учетной записи src, а другой — к целевой учетной записи. Затем я загружаю файл from из src с помощью клиента src, а затем загружаю его в цель с помощью целевого клиента.
Команду CopyObject()
можно использовать для копирования объектов между сегментами без загрузки/выгрузки. По сути, два сегмента S3 взаимодействуют друг с другом и передают данные.
Эту команду также можно использовать для копирования между корзинами в разных регионах и разных учетных записях AWS.
Если вы хотите копировать между корзины, принадлежащие разным учетным записям AWS, вам нужно будет использовать единый набор учетных данных, который имеет:
GetObject
разрешение на исходное ведроPutObject
разрешение на целевое ведроТакже обратите внимание, что команда CopyObject()
— это отправлено на целевой счет. Сегмент назначения фактически извлекает объекты из исходной корзины.
Судя по вашему описанию, ваш код получение роли из другого аккаунта для получения разрешения на чтение в исходном сегменте. К сожалению, этого недостаточно для команды CopyObject()
, потому что команда должна быть отправлена в корзину назначения. (Да, это немного сложно понять из документации. Вот почему исходное ведро имеет конкретное имя, а не целевое ведро.)
Следовательно, в вашей ситуации, чтобы иметь возможность копировать объекты, вам потребуется использовать набор учетных данных из Account-B
(пункт назначения), у которого также есть разрешение на чтение из Bucket-A
(источника). Для этого поставщику потребуется изменить политику корзины, связанный с Bucket-A
.
Если они не хотят этого делать, то ваш единственный вариант — загрузить объекты, используя предполагаемую роль, а затем отдельно загрузить файлы в свою корзину, используя учетные данные из вашей собственной Account-B
.
Учетные данные, которые вы используете для вызова операции копирования, должны иметь доступ к объекту в исходном сегменте и к объекту в сегменте назначения.