Domanda

With the following code, I can add a permission using my AWS account number but the queue does not receive any messages from SNS.

AddPermissionRequest addPermissionRequest = new AddPermissionRequest();
addPermissionRequest.ActionName.Add("SendMessage");
addPermissionRequest.ActionName.Add("ReceiveMessage");
addPermissionRequest.QueueUrl = queueUrl;
addPermissionRequest.Label = General.IpAddressAWSFriendly;
addPermissionRequest.AWSAccountId.Add(AWS_ACCOUNT_ID);
sqs.AddPermission(addPermissionRequest);

But, when I try to set the permission via a wildcard (*) for everybody:

addPermissionRequest.AWSAccountId.Add("*");

it gives me an error. If I manually add the permission in the AWS SQS console and specify

SendMessage
ReceiveMessage

for the allowed actions and for the principle, I set it to "everybody", the queue does receive messages from my SNS topic. So, obviously, I'm doing something wrong but I don't see it anymore.

Any help would be great! I wish Amazon would have examples, the example that comes with the SDK does not show anything about setting policies or permissions. Nothing is shown in the online documentation, either. Frustrating.

È stato utile?

Soluzione

Fortunately, I figured it out myself since I received no responses here. I really wish Amazon would provide better documentation for C# developers on the .Net framework and not just for script kiddies.

Anyways, I ended up creating a full blown Policy object and passed that to the SQS. I used the AWS SDK v1.5 version and not the newer 2.0 (in beta right now) simply because it works for now and I was too lazy to change it to the newer 2.0 version.

Here is the bit of code you will need to programmatically create a policy in C# for an SQS Queue with a condition to only use that queue with an SNS topic:

        // 4. Set the queue policy to allow SNS to publish messages
        ActionIdentifier[] actions = new ActionIdentifier[2];
        actions[0] = SQSActionIdentifiers.SendMessage;
        actions[1] = SQSActionIdentifiers.ReceiveMessage;
        Policy sqsPolicy = new Policy()
            .WithStatements(new Statement(Statement.StatementEffect.Allow)
                                .WithPrincipals(Principal.AllUsers)
                                .WithResources(new Resource(queueArn))
                                .WithConditions(ConditionFactory.NewSourceArnCondition(_AWSSNSArn))
                                .WithActionIdentifiers(actions));
        SetQueueAttributesRequest setQueueAttributesRequest = new SetQueueAttributesRequest();
        List<Amazon.SQS.Model.Attribute> attributes = new List<Amazon.SQS.Model.Attribute>();
        Amazon.SQS.Model.Attribute attribute = new Amazon.SQS.Model.Attribute();
        attribute.Name = "Policy";
        attribute.Value = sqsPolicy.ToJson();
        attributes.Add(attribute);
        setQueueAttributesRequest.QueueUrl = queueUrl;
        setQueueAttributesRequest.Attribute = attributes;
        sqs.SetQueueAttributes(setQueueAttributesRequest);

I hope this helps someone.

Altri suggerimenti

Previous created the permission without the resource which did not work as expected. Here is a correction to get the arn:

    public static String TestQueueCreate(String name) {

        AmazonSQSClient sqs = new AmazonSQSClient(region: Amazon.RegionEndpoint.USEast1);
        CreateQueueResponse create = sqs.CreateQueue(name);

        String arn = sqs.GetQueueAttributes(create.QueueUrl, new List<String>() { "QueueArn" }).Attributes["QueueArn"];

        Policy policy = new Policy() {
            Statements = new List<Statement>() {
                new Statement(StatementEffect.Allow) {
                    Principals = new List<Principal>() { new Principal("*") },
                    Actions = new List<ActionIdentifier>() {
                        new ActionIdentifier("SQS:ReceiveMessage"),
                        new ActionIdentifier("SQS:SendMessage")
                    },
                    Resources = new List<Resource>() { new Resource(arn) }
                }
            },

        };

        Dictionary<String,String> queueAttributes = new Dictionary<String, String>();
        queueAttributes.Add(QueueAttributeName.Policy.ToString(), policy.ToJson());
        sqs.SetQueueAttributes(new SetQueueAttributesRequest(create.QueueUrl, queueAttributes));

        return create.QueueUrl;
    }

Here's how to do it in Clojure with amazonica:

(require '[amazonica.aws.sqs :as sqs]
         '[amazonica.core :as aws)
(import '(com.amazonaws.auth.policy Statement Statement$Effect
                                    Principal
                                    Policy
                                    Resource
                                    Condition
                                    Action)
        '(com.amazonaws.auth.policy.actions SQSActions)
        '(com.amazonaws.auth.policy.conditions ConditionFactory))

(aws/defcredential "access-key" "secret-key" "us-east-1")

(def topic-arn "arn:aws:sns:us-east-1:123:foo")
(def queue-url "https://sqs.us-east-1.amazonaws.com/123/bar")
(def queue-arn (-> queue-url sqs/get-queue-attributes :QueueArn))

(def policy (Policy.
                   (str queue-arn "/SQSDefaultPolicy")
                   [(doto (Statement. Statement$Effect/Allow)
                       (.setPrincipals [Principal/AllUsers])
                       (.setResources [(Resource. queue-arn)])
                       (.setConditions [(ConditionFactory/newSourceArnCondition topic-arn)])
                       (.setActions [SQSActions/SendMessage]))]))

(sqs/set-queue-attributes queue-url {"Policy" (.toJson policy)})

Here is how I create a queue on the fly with anonymous read access. Just add additional ActionIdentifiers as needed:

    public static String TestQueueCreate(String name) {

        AmazonSQSClient sqs = new AmazonSQSClient(region: Amazon.RegionEndpoint.USEast1);
        CreateQueueResponse create = sqs.CreateQueue(name);

        Policy policy = new Policy() {
            Statements = new List<Statement>() {
                new Statement(StatementEffect.Allow) {
                    Principals = new List<Principal>() { Principal.AllUsers },
                    Actions = new List<ActionIdentifier>() { SQSActionIdentifiers.ReceiveMessage }
                }
            }
        };

        Dictionary<String,String> queueAttributes = new Dictionary<String, String>();
        queueAttributes.Add(QueueAttributeName.Policy.ToString(), policy.ToJson());
        sqs.SetQueueAttributes(new SetQueueAttributesRequest(create.QueueUrl, queueAttributes));

        return create.QueueUrl;
    }
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top