【发布时间】:2019-12-06 06:38:44
【问题描述】:
问题的执行摘要。我有一个存储桶,我们称之为存储桶 A,它在一个帐户中设置了默认的客户 KMS 密钥(将调用 id:1111111),我们将其称为 123。在该存储桶中有两个对象,它们都在同一个帐户下此存储桶内的路径。它们具有相同的 KMS 密钥 ID 和相同的所有者。当我尝试将这些同步到另一个帐户中的新存储桶 B 时,让我们使用帐户 456,其中一个已成功同步,但另一个未成功同步,而是我得到:
An error occurred (AccessDenied) when calling the CopyObject operation: Access Denied
以前有没有人见过这种不一致的行为?我说不一致是因为它们之间的访问权限绝对没有区别,但是一个成功而另一个不成功。注意:为简单起见,我的摘要说明了两个对象,但在我的一个真实案例中,有 30 个对象,其中 2 个正在复制,其余的失败,并且在其他一些路径中出现不同的混合结果。
以下描述了一些条件——一些数据为了安全而被混淆,但以一致的方式:
存储桶 A (com.mycompany.datalake.us-east-1) 存储桶策略:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowAccess",
"Effect": "Allow",
"Principal": {
"AWS": [
"arn:aws:iam::123:root",
"arn:aws:iam::456:root"
]
},
"Action": [
"s3:PutObjectTagging",
"s3:PutObjectAcl",
"s3:PutObject",
"s3:ListBucket",
"s3:GetObject"
],
"Resource": [
"arn:aws:s3:::com.mycompany.datalake.us-east-1/security=0/*",
"arn:aws:s3:::com.mycompany.datalake.us-east-1"
]
},
{
"Sid": "DenyIfNotGrantingFullAccess",
"Effect": "Deny",
"Principal": {
"AWS": [
"arn:aws:iam::123:root",
"arn:aws:iam::456:root"
]
},
"Action": "s3:PutObject",
"Resource": [
"arn:aws:s3:::com.mycompany.datalake.us-east-1/security=0/*",
"arn:aws:s3:::com.mycompany.datalake.us-east-1"
],
"Condition": {
"StringNotLike": {
"s3:x-amz-acl": "bucket-owner-full-control"
}
}
},
{
"Sid": "DenyIfNotUsingExpectedKmsKey",
"Effect": "Deny",
"Principal": {
"AWS": [
"arn:aws:iam::123:root",
"arn:aws:iam::456:root"
]
},
"Action": "s3:PutObject",
"Resource": [
"arn:aws:s3:::com.mycompany.datalake.us-east-1/security=0/*",
"arn:aws:s3:::com.mycompany.datalake.us-east-1"
],
"Condition": {
"StringNotLike": {
"s3:x-amz-server-side-encryption-aws-kms-key-id": "arn:aws:kms:us-east-1:123:key/1111111"
}
}
}
]
}
同样在源帐户中,我创建了一个假定角色,我称之为datalake_full_access_role:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:ListBucket",
"s3:GetObject"
],
"Resource": [
"arn:aws:s3:::com.mycompany.datalake.us-east-1/security=0/*",
"arn:aws:s3:::com.mycompany.datalake.us-east-1"
]
}
]
}
与账户 456 有 Trusted 关系。另外值得一提的是,目前 KMS 密钥 1111111 的策略是完全开放的:
{
"Version": "2012-10-17",
"Id": "key-default-1",
"Statement": [
{
"Sid": "Enable IAM User Permissions",
"Effect": "Allow",
"Principal": {
"AWS": "*"
},
"Action": "kms:*",
"Resource": "*"
},
{
"Effect": "Allow",
"Principal": {
"AWS": "*"
},
"Action": [
"kms:Encrypt*",
"kms:Decrypt*",
"kms:ReEncrypt*",
"kms:GenerateDataKey*",
"kms:Describe*"
],
"Resource": "*"
}
]
}
现在对于账户 456 中的目标存储桶 B (mycompany-us-west-2-datalake),存储桶策略:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AccountBasedAccess",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::456:root"
},
"Action": "s3:*",
"Resource": [
"arn:aws:s3:::mycompany-us-west-2-datalake",
"arn:aws:s3:::mycompany-us-west-2-datalake/*"
]
}
]
}
为了进行迁移(同步),我在 456 账户中配置了一个 EC2 实例,并为其附加了一个实例配置文件,该配置文件附加了以下策略:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "sts:AssumeRole",
"Resource": "arn:aws:iam::123:role/datalake_full_access_role"
}
]
}
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"kms:DescribeKey",
"kms:ReEncrypt*",
"kms:CreateGrant",
"kms:Decrypt"
],
"Resource": [
"arn:aws:kms:us-east-1:123:key/1111111"
]
}
]
}
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:ListBucket"
],
"Resource": [
"arn:aws:s3:::com.mycompany.datalake.us-east-1",
"arn:aws:s3:::com.mycompany.datalake.us-east-1/security=0/*"
]
}
]
}
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "s3:*",
"Resource": [
"arn:aws:s3:::mycompany-us-west-2-datalake",
"arn:aws:s3:::mycompany-us-west-2-datalake/*"
]
}
]
}
现在我在 EC2 实例上安装最新的 aws 版本:
$ aws --version
aws-cli/1.16.297 Python/3.5.2 Linux/4.4.0-1098-aws botocore/1.13.33
然后运行我的同步命令:
aws s3 sync s3://com.mycompany.datalake.us-east-1 s3://mycompany-us-west-2-datalake --source-region us-east-1 --region us-west-2 --acl bucket-owner-full-control --exclude '*' --include '*/zone=raw/Event/*' --no-progress
我相信我已经完成了我的功课,这一切都应该有效,并且对于几个对象它可以,但不是全部,我现在没有什么可以尝试的了。注意我已经 100% 成功地同步到 EC2 实例上的本地目录,然后通过以下两个调用从本地目录到新存储桶:
aws s3 sync s3://com.mycompany.datalake.us-east-1 datalake --source-region us-east-1 --exclude '*' --include '*/zone=raw/Event/*' --no-progress
aws s3 sync datalake s3://mycompany-us-west-2-datalake --region us-west-2 --acl bucket-owner-full-control --exclude '*' --include '*/zone=raw/Event/*' --no-progress
这绝对没有意义,因为从访问 POV 来看没有区别。下面看一下源桶中两个对象的属性,一个成功,一个失败:
成功的对象:
Owner
Dev.Awsmaster
Last modified
Jan 12, 2019 10:11:48 AM GMT-0800
Etag
12ab34
Storage class
Standard
Server-side encryption
AWS-KMS
KMS key ID
arn:aws:kms:us-east-1:123:key/1111111
Size
9.2 MB
Key
security=0/zone=raw/Event/11_96152d009794494efeeae49ed10da653.avro
失败的对象:
Owner
Dev.Awsmaster
Last modified
Jan 12, 2019 10:05:26 AM GMT-0800
Etag
45cd67
Storage class
Standard
Server-side encryption
AWS-KMS
KMS key ID
arn:aws:kms:us-east-1:123:key/1111111
Size
3.2 KB
Key
security=0/zone=raw/Event/05_6913583e47f457e9e25e9ea05cc9c7bb.avro
附录:在查看了几个案例后,我开始看到一个模式。我认为当对象太小时可能会出现问题。在分析的 10 个目录中,有 10 个目录成功同步了一些但不是所有对象,所有成功的对象大小都在 8MB 或更大,而所有失败的对象都在 8MB 以下。当 KMS 混合使用时,这可能是 aws s3 sync 的错误吗?我想知道我是否可以调整 ~/.aws/config 以便它可以解决这个问题?
【问题讨论】:
-
这么大的问题
-
Arunmainthan,我知道尝试将私有存储桶从旧帐户迁移到新帐户时会涉及很多事情,尤其是在涉及 KMS 加密时。对于使用 AES-256 加密的私有存储桶,我已经为我们公司多次这样做了,我相信我在使用 KMS 时添加了额外的特殊酱汁,它“部分”工作。实际上,某些前缀目录中的所有对象都可以毫无问题地复制,并且它们都使用具有相同对象所有者的相同 KMS 密钥。我找不到某些对象失败的任何合乎逻辑的原因。
-
快速提问@Starlton,这都是关于静态加密的吗?或者如果您使用控制台下载加密文件,它会被加密吗?
-
S3 使用服务器端加密。如果您有权下载对象,则下载的文件将未加密。
标签: amazon-s3