以编程方式验证SNS主题权限,以将消息发送到SQS(使用IAM?)

时间:2018-08-17 15:27:09

标签: c# amazon-web-services amazon-sqs amazon-iam amazon-sns

我目前正在使用C#工作,但是我相信在任何AWS开发工具包中都会出现同样的问题。

我正在尝试以编程方式验证某个主题可以将消息发送到队列(实际上并没有尝试添加许可,只是检查它是否存在)。

到目前为止,我发现的唯一方法是扫描队列策略以查找与主题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开发工具包中的完成方式类似(请参见corresponding code on github)。

我对这种方法的问题是感觉如何脆弱。例如,如果条件具有通配符怎么办?如果存在针对特定主体而不是全部主体的授权怎么办?

所以我想我可能会使用IAM,特别是SimulatePrincipalPolicySimulateCustomPolicy。它们可以用于吗?

我认为是这样的:

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属性有关?我注意到,队列从主题(AIDA *****************)接收到的消息中,发件人帐户ID的用户密钥似乎总是相同。< / p>

不知道我在尝试什么...

1 个答案:

答案 0 :(得分:0)

开箱即用,您不能使用SimulatePrincipalPolicydocs)检查服务是否具有IAM权限:

  

该实体可以是IAM用户,组或角色。如果指定用户,则模拟还将包括附加到该用户所属组的所有策略。

如果您查看CallerArn类的SimulatePolicyRequest property,则会得到:

  

您只能指定IAM用户的ARN。您不能指定   假定角色,联合用户或服务主体的ARN。

我使用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

可能的解决方案 该功能确实适用于IAM Service Roles。您可以在IAM中创建服务角色,该角色具有delegates的SNS权限以将消息发送到SQS。如果您可以为SNS创建服务角色,则可以使用SimulatePrincipalPolicy函数。

我再次在PS中对此进行了测试。首先,我在IAM控制台中创建了服务角色:

  • 单击左侧菜单中的“角色”。
  • 点击创建角色按钮
  • 选择AWS服务
  • 点击SNS
  • 它只会显示一个用例(“允许SNS调用CloudWatch”)-不用担心,我们以后可以清理它。
  • 点击“下一步:权限”
  • 点击“下一步:查看”
  • 点击“创建角色”

您现在已将某些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是隐式拒绝。

现在,您可以编辑创建的角色。删除Cloudwatch策略并添加相关的SQS策略并再次测试:

EvalActionName              : sqs:SendMessage
EvalDecision                : allowed
EvalDecisionDetails         : {}
EvalResourceName            : arn:aws:sqs:::sim-test
MatchedStatements           : {AmazonSQSFullAccess}
MissingContextValues        : {}
OrganizationsDecisionDetail :
ResourceSpecificResults     : {arn:aws:sqs:::sim-test}

如果您不能/不会为SNS设置服务角色,那么我认为唯一的方法就是像已经完成的那样抓取策略。

更新

在进一步测试之后,即使上面的功能起作用了,我实际上也无法让SNS进入SQS!因此,这是一个错误的肯定,我认为您将重新取消该政策。

相关问题