How can I use Amazon Web Services policy statement in my Java application?

1.3k views Asked by At

I want to send Amazon SNS Messages to Amazon SQS Queues from the backend Java application. According to SNS Developer Guide (http://docs.aws.amazon.com/sns/latest/dg/sns-dg.pdf), in the section "Sending Amazon SNS Messages to Amazon SQS Queues", under the topic - "Step 2. Give permission to the Amazon SNS topic to send messages to the Amazon SQS queue", it is written as,

If you wanted to create the policy document yourself, you would create a policy like the following. The policy allows MyTopic to send messages to MyQueue.

{
  "Version":"2012-10-17",
  "Statement":[
  {
    "Sid":"MySQSPolicy001",
    "Effect":"Allow",
    "Principal":"*",
    "Action":"sqs:SendMessage",
    "Resource":"arn:aws:sqs:us-east-1:123456789012:MyQueue",
    "Condition":{
                  "ArnEquals":{
                     "aws:SourceArn":"arn:aws:sns:us-east-1:123456789012:MyTopic"
                   }
              }
         }
    ]
}

My doubt is how to use this policy document(.json file if I am not wrong) in my java application and where to use it exactly? Because I must set a policy on the queue that allows the Amazon SNS topic to perform the sqs:SendMessage action. TIA.

2

There are 2 answers

8
Messa On BEST ANSWER

You don't have to do it in a Java application.

Go to AWS console, select IAM service, choose a user (or create one) and then, under Permissions, you attach Policies.

This is how it looks like:

AWS IAM Policy screenshot

Policies (the JSON documents) can be chosen from a list, generated using a wizard or entered manually (that's what you want).

1
yonran On

Here is a Java example for creating an SNS topic and SQS queue, subscribing the SQS queue to the SNS topic, giving SNS the permission to send messages to the queue, sending a message to SNS, and reading it from the queue.

import com.amazonaws.ClientConfiguration;
import com.amazonaws.auth.DefaultAWSCredentialsProviderChain;
import com.amazonaws.auth.policy.Condition;
import com.amazonaws.auth.policy.Policy;
import com.amazonaws.auth.policy.Principal;
import com.amazonaws.auth.policy.Resource;
import com.amazonaws.auth.policy.Statement;
import com.amazonaws.auth.policy.actions.SQSActions;
import com.amazonaws.regions.Region;
import com.amazonaws.regions.RegionUtils;
import com.amazonaws.services.sns.AmazonSNS;
import com.amazonaws.services.sns.AmazonSNSClient;
import com.amazonaws.services.sqs.AmazonSQS;
import com.amazonaws.services.sqs.AmazonSQSClient;
import com.amazonaws.services.sqs.model.CreateQueueRequest;
import com.amazonaws.services.sqs.model.Message;
import com.amazonaws.services.sqs.model.ReceiveMessageRequest;
import com.amazonaws.services.sqs.model.ReceiveMessageResult;
import com.amazonaws.services.sqs.model.SetQueueAttributesRequest;

import java.util.Arrays;
import java.util.Optional;

public class CreateSnsAndSqs {
    private static final String SNS_TOPIC = "my-sns-topic";
    private static final String SQS_NAME = "my-sqs-queue";

    public static void main(String... argv) {
        String regionName = Optional.ofNullable(System.getenv("AWS_DEFAULT_REGION")).orElse("us-east-1");
        Region region = RegionUtils.getRegion(regionName);
        ClientConfiguration clientConfiguration = new ClientConfiguration();
        // AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY
        DefaultAWSCredentialsProviderChain credentialsChain = new DefaultAWSCredentialsProviderChain();
        AmazonSNS sns = region.createClient(AmazonSNSClient.class, credentialsChain, clientConfiguration);
        AmazonSQS sqs = region.createClient(AmazonSQSClient.class, credentialsChain, clientConfiguration);
        String sqsUrl = sqs.createQueue(new CreateQueueRequest(SQS_NAME)).getQueueUrl();
        String snsTopicArn = sns.createTopic(SNS_TOPIC).getTopicArn();
        String sqsArn = sqs.getQueueAttributes(sqsUrl, Arrays.asList("QueueArn")).getAttributes().get("QueueArn");
        String sqsSubscriptionArn = sns.subscribe(snsTopicArn, "sqs", sqsArn).getSubscriptionArn();
        Policy allowSnsToPostToSqsPolicy = new Policy("allow sns " + snsTopicArn + " to send to queue", Arrays.asList(
                new Statement(Statement.Effect.Allow)
                        .withPrincipals(Principal.All)
                        .withActions(SQSActions.SendMessage)
                        .withResources(new Resource(sqsArn))
                        .withConditions(new Condition().withType("ArnEquals").withConditionKey("aws:SourceArn").withValues(snsTopicArn))
        ));
        sqs.setQueueAttributes(new SetQueueAttributesRequest().withQueueUrl(sqsUrl).addAttributesEntry("Policy", allowSnsToPostToSqsPolicy.toJson()));
        String sqsSubscriptionArn = sns.subscribe(snsTopicArn, "sqs", sqsArn).getSubscriptionArn();
        sns.publish(snsTopicArn, "Hello world");
        ReceiveMessageResult receiveResp = sqs.receiveMessage(new ReceiveMessageRequest(sqsUrl).withWaitTimeSeconds(10));
        for (Message message: receiveResp.getMessages()) {
            System.out.println("Received message " + message.getBody());
            sqs.deleteMessage(sqsUrl, message.getReceiptHandle());
        }
        System.out.println("Deleting");
        sns.deleteTopic(snsTopicArn);
        sqs.deleteQueue(sqsUrl);
    }
}

It prints the message to the console like this:

Received message {
  "Type" : "Notification",
  "MessageId" : "add8d56a-19e6-5806-9424-9a2a796f8f94",
  "TopicArn" : "arn:aws:sns:us-east-1:111111111111:my-sns-topic",
  "Message" : "Hello world",
  "Timestamp" : "2016-02-19T00:14:01.973Z",
  "SignatureVersion" : "1",
  "Signature" : "XXXaLONGSIGNATUREXXX",
  "SigningCertURL" : "https://sns.us-east-1.amazonaws.com/SimpleNotificationService-bb750dd426d95ee9390147a5624348ee.pem",
  "UnsubscribeURL" : "https://sns.us-east-1.amazonaws.com/?Action=Unsubscribe&SubscriptionArn=arn:aws:sns:us-east-1:111111111111:my-sns-topic:5e4d08a2-bcdb-4943-afef-5b7b02e30d5a"
}
Deleting