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

3

请原谅我,这是我第一次在Stack Overflow上提问。我会尽量让问题清晰明了。

问题:

在使用AWS CDK合成堆栈时,我遇到了命令行错误。我使用C#语言,在本地计算机上进行测试。

似乎我在构建基于文档的主题策略对象时未传递“策略文件”对象。在文档的“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\Temp\4k3fctka.rty\jsii-runtime.js:1:165352)
    at t.SyncStdio.writeLine (C:\Users\username\AppData\Local\Temp\4k3fctka.rty\jsii-runtime.js:1:164892)
    at t.InputOutput.write (C:\Users\username\AppData\Local\Temp\4k3fctka.rty\jsii-runtime.js:1:164341)
    at t.KernelHost.writeError (C:\Users\username\AppData\Local\Temp\4k3fctka.rty\jsii-runtime.js:1:79440)
    at i.then.catch.e (C:\Users\username\AppData\Local\Temp\4k3fctka.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; }
        }
    }
}

你能否复制问题中的文字错误信息,而不是链接到屏幕截图?这将有助于其他遇到相同问题的人更轻松地发现该问题,并确保信息在屏幕截图消失时仍然存在... - Romain
@Romain,我已经添加了错误。对于任何混淆之处,我表示歉意。 - AnonProxySwitch
1个回答

4

这里有几个要点...

  1. Topic类是一个有效的TopicRef,所以你不需要在这里执行TopicRef.import操作。
  2. 你可以使用Topic#addToResourcePolicy来向你的Topic策略中添加语句,而不是自己创建一个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 */);

谢谢回复!我已经对我的代码进行了一些重构。即使像您上面所做的那样附加“PolicyStatements”,它仍然会抛出一个错误,说我没有向cfnTopicPolicyProps提供“PolicyDocument”。我没有看到TopicRef类中可以用来添加“PolicyDocument”的方法。我有什么遗漏吗? - AnonProxySwitch
问题出在你创建TopicPolicy对象时,我觉得你并不需要它(因为Topic类已经为你管理了一个TopicPolicy!) - Romain
你百分之百正确。看起来我现在得到了正确的输出。非常感谢你,Romain! - AnonProxySwitch
@AnonProxySwitch,如果这个答案解决了你的问题,请毫不犹豫地接受它! - Romain
非常抱歉,我是 StackOverflow 的新手。再次感谢。 - AnonProxySwitch

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接