如何使用 AWS CDK 将 "PolicyDocument" 对象附加到 TopicPolicy?

How do I attach a "PolicyDocument" object to a TopicPolicy using the AWS CDK?

对不起,这是我第一次问关于堆栈溢出的问题。我会尽力使这一点尽可能清楚。

问题:

我在尝试使用 AWS CDK 合成堆栈时遇到此问题 command line error。我使用 C# 作为我的语言,只是在我的本地机器上玩。

根据 this 文档构建我的主题策略对象时,我似乎没有传递 "policy document" 对象。在文档中,在 "CfnTopicPolicyProps (interface)" 下它显示了一个 topics 对象和一个 policyDocument 对象可以被包含。但是,在 Visual Studio 中,当我查看接口的定义时,它只包含 topics 对象。我在下面包括了我对接口的使用以及一些 类、接口及其父接口的定义。我是一个相对较新的开发人员,但我完全无法解释。我在这里错过了什么?

提前感谢大家提供的任何帮助或建议。

CLI 错误输出

C:\MyRepository\awsCdkApp1>cdk synth Test-Stack-1
Unhandled Exception: Amazon.JSII.Runtime.JsiiException: While synthesizing Test-Stack-1/topicPolicy/Resource: Supplied properties not correct for "CfnTopicPolicyProps"
  policyDocument: required but missing
   at Amazon.JSII.Runtime.Services.Client.TryDeserialize[TResponse](String responseJson)
   at Amazon.JSII.Runtime.Services.Client.ReceiveResponse[TResponse]()
   at Amazon.JSII.Runtime.Deputy.DeputyBase.<InvokeMethodCore>g__GetResult|18_0[T](<>c__DisplayClass18_0`1& )
   at Amazon.JSII.Runtime.Deputy.DeputyBase.InvokeMethodCore[T](JsiiMethodAttribute methodAttribute, Object[] arguments, Func`3 beginFunc, Func`3 invokeFunc)
   at Amazon.JSII.Runtime.Deputy.DeputyBase.InvokeInstanceMethod[T](Object[] arguments, String methodName)
   at Amazon.CDK.App.Run()
   at HelloCdk.Program.Main(String[] args) in C:\MyRepository/Program.cs:line 19
(node:16396) UnhandledPromiseRejectionWarning: Error: EPIPE: broken pipe, write
    at Object.writeSync (fs.js:569:3)
    at t.SyncStdio.writeBuffer (C:\Users\username\AppData\Local\Tempk3fctka.rty\jsii-runtime.js:1:165352)
    at t.SyncStdio.writeLine (C:\Users\username\AppData\Local\Tempk3fctka.rty\jsii-runtime.js:1:164892)
    at t.InputOutput.write (C:\Users\username\AppData\Local\Tempk3fctka.rty\jsii-runtime.js:1:164341)
    at t.KernelHost.writeError (C:\Users\username\AppData\Local\Tempk3fctka.rty\jsii-runtime.js:1:79440)
    at i.then.catch.e (C:\Users\username\AppData\Local\Tempk3fctka.rty\jsii-runtime.js:1:79101)
(node:16396) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
(node:16396) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
Subprocess exited with error 3762504530

接口使用率:

var topic = new Topic(this, "myTopic", new TopicProps
        {
            DisplayName = "myTopic",
            TopicName = "myTopic"
        });

        var topicRef = TopicRef.Import(this, "reference", new TopicRefProps
        {
            TopicArn = topic.TopicArn,
            TopicName = topic.TopicName,
        });

        var policyStatement1 = new PolicyStatement(0);
        policyStatement1.Describe("Default");
        policyStatement1.AddAwsPrincipal("*");
        policyStatement1.AddActions("- SNS:Publish\n " +
                                   "- SNS:RemovePermission\n" +
                                   "- SNS:SetTopicAttributes\n" +
                                   "- SNS:DeleteTopic\n" +
                                   "- SNS:ListSubscriptionsByTopic\n" +
                                   "- SNS:GetTopicAttributes\n" +
                                   "- SNS:Receive\n" +
                                   "- SNS:AddPermission\n" +
                                   "- SNS:Subscribe\n");
        policyStatement1.AddCondition("StringEquals", "sOmEtHiNg");
        policyStatement1.AddResource(topic.TopicArn);

        var policyStatement2 = new PolicyStatement(0);
        policyStatement2.Describe("ProviderBucketAllow");
        policyStatement2.AddAwsPrincipal("*");
        policyStatement2.AddAction("- SNS:Publish");
        policyStatement2.AddCondition("StringEquals", @"sOmEtHiNg");
        policyStatement2.AddResource(topic.TopicArn);

        var policyDocument = new PolicyDocument("PolicyDocument");
        policyDocument.AddStatement(policyStatement1);
        policyDocument.AddStatement(policyStatement2);

        //Generate the topic policy resource
        var topicPolicy = new TopicPolicy(this, "topicPolicy", new TopicPolicyProps
        {
            //Here is where I would imagine I pass the policyDocument Object?
            //If I try to pass policyDocument, I get a ton of errors...
            Topics = new[] {topicRef}
        });

TopicRefProps 定义:

using Amazon.JSII.Runtime.Deputy;

namespace Amazon.CDK.AWS.SNS
{
    public class TopicRefProps : DeputyBase, ITopicRefProps
    {
        public TopicRefProps();

        [JsiiProperty("topicArn", "{\"primitive\":\"string\"}", true)]
        public string TopicArn { get; set; }
        [JsiiProperty("topicName", "{\"primitive\":\"string\"}", true)]
        public string TopicName { get; set; }
    }
}

ITopicRefProps 定义:

using Amazon.JSII.Runtime.Deputy;

namespace Amazon.CDK.AWS.SNS
{
    [JsiiInterface(typeof(ITopicRefProps), "@aws-cdk/aws-sns.TopicRefProps")]
    public interface ITopicRefProps
    {
        [JsiiProperty("topicArn", "{\"primitive\":\"string\"}", false)]
        string TopicArn { get; set; }
        [JsiiProperty("topicName", "{\"primitive\":\"string\"}", false)]
        string TopicName { get; set; }
    }
}

DeputyBase 定义:

using System;
using System.Runtime.CompilerServices;

namespace Amazon.JSII.Runtime.Deputy
{
    public abstract class DeputyBase
    {
        protected DeputyBase(DeputyProps props = null);
        protected DeputyBase(ByRefValue reference);

        public ByRefValue Reference { get; }

        protected static T GetStaticProperty<T>(Type type, [CallerMemberName] string propertyName = null);
        protected static T InvokeStaticMethod<T>(Type type, object[] arguments, [CallerMemberName] string methodName = null);
        protected static void InvokeStaticVoidMethod(Type type, object[] arguments, [CallerMemberName] string methodName = null);
        protected static void SetStaticProperty<T>(Type type, T value, [CallerMemberName] string propertyName = null);
        protected T GetInstanceProperty<T>([CallerMemberName] string propertyName = null);
        protected T InvokeInstanceMethod<T>(object[] arguments, [CallerMemberName] string methodName = null);
        protected void InvokeInstanceVoidMethod(object[] arguments, [CallerMemberName] string methodName = null);
        protected void SetInstanceProperty<T>(T value, [CallerMemberName] string propertyName = null);

        public sealed class DeputyProps
        {
            public DeputyProps(object[] arguments = null);

            public object[] Arguments { get; }
        }
    }
}

这里有几件事...

  1. Topic class 是有效的 TopicRef,所以你不应该在这里跳 TopicRef.import 舞。
  2. 您可以使用 Topic#addToResourcePolicyTopic 的政策添加声明,而不是自己创建 TopicPolicy 资源。

因此您的代码最终可能会是这样的:

var topic = new Topic(this, "myTopic", new TopicProps
{
    DisplayName = "myTopic",
    TopicName = "myTopic"
});

topic.AddToResourcePolicy(new PolicyStatement()
    .Describe("Default")
    .AddAwsPrincipal("*")
    .AddActions("sns:Publish",
                "sns:RemovePermission",
                "sns:SetTopicAttributes",
                "sns:DeleteTopic",
                "sns:ListSubscriptionsByTopic",
                "sns:GetTopicAttributes",
                "sns:Receive",
                "sns:AddPermission",
                "sns:Subscribe")
    .AddCondition("StringEquals", /* needs to be a map of condition key to value */);
topic.AddToResourcePolicy(new PolicyStatement()
    .Describe("ProviderBucketAllow")
    .AddAwsPrincipal("*")
    .AddAction("sns:Publish")
    .AddCondition("StringEquals", /* needs to be a map of condition key to value */);