以编程方式验证 SNS 主题权限以将消息发送到 SQS(使用 IAM?)
Programmatically verify SNS topic permission to send messages to SQS (using IAM?)
我目前正在使用 C#,但我相信这个问题在任何 AWS SDK 中都是一样的。
我正在尝试以编程方式验证主题是否可以将消息发送到队列(实际上并不是尝试添加权限,只是检查它是否存在)。
到目前为止,我找到的唯一方法是扫描队列策略以查找与主题 ARN 匹配的语句,即..:
policy.Statements.Any(
statement =>
statement.Effect == Statement.StatementEffect.Allow
&& statement.Principals.Any(
principal => string.Equals(
principal.Id,
Principal.AllUsers.Id,
StringComparison.OrdinalIgnoreCase))
&& statement.Actions.Any(
identifier => string.Equals(
identifier.ActionName,
SQSActionIdentifiers.SendMessage.ActionName,
StringComparison.OrdinalIgnoreCase))
&& statement.Resources.Any(resource => resource.Id == queueArn)
&& statement.Conditions.Any(
condition =>
(string.Equals(
condition.Type,
ConditionFactory.StringComparisonType.StringLike.ToString(),
StringComparison.OrdinalIgnoreCase)
|| string.Equals(
condition.Type,
ConditionFactory.StringComparisonType.StringEquals.ToString(),
StringComparison.OrdinalIgnoreCase)
|| string.Equals(
condition.Type,
ConditionFactory.ArnComparisonType.ArnEquals.ToString(),
StringComparison.OrdinalIgnoreCase)
|| string.Equals(
condition.Type,
ConditionFactory.ArnComparisonType.ArnLike.ToString(),
StringComparison.OrdinalIgnoreCase))
&& string.Equals(
condition.ConditionKey,
ConditionFactory.SOURCE_ARN_CONDITION_KEY,
StringComparison.OrdinalIgnoreCase)
&& condition.Values.Contains(topicArn)))
顺便说一句,这类似于调用 SubscribeQueueAsync 时在 AWS SDK 中完成的方式(请参阅 corresponding code on github)。
我对这种方法的问题是它感觉起来有多脆弱。例如,如果条件有通配符怎么办?如果存在针对特定主体而不是所有主体的授权怎么办?
所以我想我可能会使用 IAM,特别是 SimulatePrincipalPolicy or SimulateCustomPolicy。它们可以用于此吗?
我是这样想的:
var simulatePrincipalPolicyRequest = new SimulatePrincipalPolicyRequest
{
ActionNames = { SQSActionIdentifiers.SendMessage.ActionName },
ResourceArns = { queueArn },
PolicySourceArn = topicArn
};
var response = await _iamService.SimulatePrincipalPolicyAsync(
request: simulatePrincipalPolicyRequest,
cancellationToken: cancellationToken);
本来可以的,但结果是 Amazon.IdentityManagement.Model.InvalidInputException : Could not extract entity from ARN : arn:aws:sns:eu-west-1:<accountid>:<topicname>
。
我想这可能与 CallerArn 属性 有关?我注意到发件人帐户 ID 的用户密钥在队列从主题接收的消息中似乎总是相同的 (AIDA******************)。
不确定我正在尝试的是否可行...
开箱即用,您不能使用 SimulatePrincipalPolicy
(docs) 检查服务是否具有 IAM 权限:
The entity can be an IAM user, group, or role. If you specify a user, then the simulation also includes all of the policies that are attached to groups that the user belongs to.
如果您查看 SimulatePolicyRequest
class 的 CallerArn
property,您会得到:
You can specify only the ARN of an IAM user. You cannot specify the
ARN of an assumed role, federated user, or a service principal.
我使用 powershell SDK 对此进行了测试 - 它在 .net 上运行并得到了同样的错误。
Test-IAMPrincipalPolicy -ActionName 'sqs:SendMessage' -PolicySourceArn arn:aws:sns:::sim-test -ResourceArn arn:aws:sqs:::sim-test
Test-IAMPrincipalPolicy : Could not extract entity from ARN : arn:aws:sns:::sim-test
可能的解决方案
该函数确实与 SNS 的 IAM Service Roles. You can create a service role in IAM that delegates 权限一起使用,以将消息发送到 SQS。如果您能够为 SNS 创建服务角色,那么您将能够使用 SimulatePrincipalPolicy 函数。
我在 PS 中再次测试了这个。首先,我在 IAM 控制台中创建了服务角色:
- 单击左侧菜单中的角色。
- 单击“创建角色”按钮
- Select AWS 服务
- 点击社交网络
- 它只会展示一个用例 ("Allow SNS to call CloudWatch") - 别担心,我们稍后可以清理它。
- 点击"Next:Permissions"
- 点击"Next:Review"
- 点击"Create Role"
您现在已将某些 CloudWatch 权限委托给 SNS。我们将在几秒钟内删除它,但现在我至少可以调用该函数,传入策略 ARN:
Test-IAMPrincipalPolicy -ActionName 'sqs:SendMessage' -PolicySourceArn arn:aws:iam:::role/sim-test-servicerole -ResourceArn arn:aws:sqs:::sim-test
EvalActionName : sqs:SendMessage
EvalDecision : implicitDeny
EvalDecisionDetails : {}
EvalResourceName : arn:aws:sqs:::sim-test
MatchedStatements : {}
MissingContextValues : {}
OrganizationsDecisionDetail :
ResourceSpecificResults : {arn:aws:sqs:::sim-test}
请注意,EvalDecision 是 implicitDeny。
现在您可以编辑创建的角色。删除Cloudwatch策略,添加相关SQS策略,再次测试:
EvalActionName : sqs:SendMessage
EvalDecision : allowed
EvalDecisionDetails : {}
EvalResourceName : arn:aws:sqs:::sim-test
MatchedStatements : {AmazonSQSFullAccess}
MissingContextValues : {}
OrganizationsDecisionDetail :
ResourceSpecificResults : {arn:aws:sqs:::sim-test}
如果您不能t/won设置 SNS 的服务角色,那么我认为唯一的方法就是像您已经完成的那样抓取策略。
更新
经过进一步测试,虽然上面的功能可以正常运行,但实际上我无法让SNS登陆SQS!所以这是一个误报,我认为你又回到了抓取政策的地方。
我目前正在使用 C#,但我相信这个问题在任何 AWS SDK 中都是一样的。
我正在尝试以编程方式验证主题是否可以将消息发送到队列(实际上并不是尝试添加权限,只是检查它是否存在)。
到目前为止,我找到的唯一方法是扫描队列策略以查找与主题 ARN 匹配的语句,即..:
policy.Statements.Any(
statement =>
statement.Effect == Statement.StatementEffect.Allow
&& statement.Principals.Any(
principal => string.Equals(
principal.Id,
Principal.AllUsers.Id,
StringComparison.OrdinalIgnoreCase))
&& statement.Actions.Any(
identifier => string.Equals(
identifier.ActionName,
SQSActionIdentifiers.SendMessage.ActionName,
StringComparison.OrdinalIgnoreCase))
&& statement.Resources.Any(resource => resource.Id == queueArn)
&& statement.Conditions.Any(
condition =>
(string.Equals(
condition.Type,
ConditionFactory.StringComparisonType.StringLike.ToString(),
StringComparison.OrdinalIgnoreCase)
|| string.Equals(
condition.Type,
ConditionFactory.StringComparisonType.StringEquals.ToString(),
StringComparison.OrdinalIgnoreCase)
|| string.Equals(
condition.Type,
ConditionFactory.ArnComparisonType.ArnEquals.ToString(),
StringComparison.OrdinalIgnoreCase)
|| string.Equals(
condition.Type,
ConditionFactory.ArnComparisonType.ArnLike.ToString(),
StringComparison.OrdinalIgnoreCase))
&& string.Equals(
condition.ConditionKey,
ConditionFactory.SOURCE_ARN_CONDITION_KEY,
StringComparison.OrdinalIgnoreCase)
&& condition.Values.Contains(topicArn)))
顺便说一句,这类似于调用 SubscribeQueueAsync 时在 AWS SDK 中完成的方式(请参阅 corresponding code on github)。
我对这种方法的问题是它感觉起来有多脆弱。例如,如果条件有通配符怎么办?如果存在针对特定主体而不是所有主体的授权怎么办?
所以我想我可能会使用 IAM,特别是 SimulatePrincipalPolicy or SimulateCustomPolicy。它们可以用于此吗?
我是这样想的:
var simulatePrincipalPolicyRequest = new SimulatePrincipalPolicyRequest
{
ActionNames = { SQSActionIdentifiers.SendMessage.ActionName },
ResourceArns = { queueArn },
PolicySourceArn = topicArn
};
var response = await _iamService.SimulatePrincipalPolicyAsync(
request: simulatePrincipalPolicyRequest,
cancellationToken: cancellationToken);
本来可以的,但结果是 Amazon.IdentityManagement.Model.InvalidInputException : Could not extract entity from ARN : arn:aws:sns:eu-west-1:<accountid>:<topicname>
。
我想这可能与 CallerArn 属性 有关?我注意到发件人帐户 ID 的用户密钥在队列从主题接收的消息中似乎总是相同的 (AIDA******************)。
不确定我正在尝试的是否可行...
开箱即用,您不能使用 SimulatePrincipalPolicy
(docs) 检查服务是否具有 IAM 权限:
The entity can be an IAM user, group, or role. If you specify a user, then the simulation also includes all of the policies that are attached to groups that the user belongs to.
如果您查看 SimulatePolicyRequest
class 的 CallerArn
property,您会得到:
You can specify only the ARN of an IAM user. You cannot specify the ARN of an assumed role, federated user, or a service principal.
我使用 powershell SDK 对此进行了测试 - 它在 .net 上运行并得到了同样的错误。
Test-IAMPrincipalPolicy -ActionName 'sqs:SendMessage' -PolicySourceArn arn:aws:sns:::sim-test -ResourceArn arn:aws:sqs:::sim-test
Test-IAMPrincipalPolicy : Could not extract entity from ARN : arn:aws:sns:::sim-test
可能的解决方案 该函数确实与 SNS 的 IAM Service Roles. You can create a service role in IAM that delegates 权限一起使用,以将消息发送到 SQS。如果您能够为 SNS 创建服务角色,那么您将能够使用 SimulatePrincipalPolicy 函数。
我在 PS 中再次测试了这个。首先,我在 IAM 控制台中创建了服务角色:
- 单击左侧菜单中的角色。
- 单击“创建角色”按钮
- Select AWS 服务
- 点击社交网络
- 它只会展示一个用例 ("Allow SNS to call CloudWatch") - 别担心,我们稍后可以清理它。
- 点击"Next:Permissions"
- 点击"Next:Review"
- 点击"Create Role"
您现在已将某些 CloudWatch 权限委托给 SNS。我们将在几秒钟内删除它,但现在我至少可以调用该函数,传入策略 ARN:
Test-IAMPrincipalPolicy -ActionName 'sqs:SendMessage' -PolicySourceArn arn:aws:iam:::role/sim-test-servicerole -ResourceArn arn:aws:sqs:::sim-test
EvalActionName : sqs:SendMessage
EvalDecision : implicitDeny
EvalDecisionDetails : {}
EvalResourceName : arn:aws:sqs:::sim-test
MatchedStatements : {}
MissingContextValues : {}
OrganizationsDecisionDetail :
ResourceSpecificResults : {arn:aws:sqs:::sim-test}
请注意,EvalDecision 是 implicitDeny。
现在您可以编辑创建的角色。删除Cloudwatch策略,添加相关SQS策略,再次测试:
EvalActionName : sqs:SendMessage
EvalDecision : allowed
EvalDecisionDetails : {}
EvalResourceName : arn:aws:sqs:::sim-test
MatchedStatements : {AmazonSQSFullAccess}
MissingContextValues : {}
OrganizationsDecisionDetail :
ResourceSpecificResults : {arn:aws:sqs:::sim-test}
如果您不能t/won设置 SNS 的服务角色,那么我认为唯一的方法就是像您已经完成的那样抓取策略。
更新
经过进一步测试,虽然上面的功能可以正常运行,但实际上我无法让SNS登陆SQS!所以这是一个误报,我认为你又回到了抓取政策的地方。