[ 
https://issues.apache.org/jira/browse/CAMEL-10280?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=15458117#comment-15458117
 ] 

Stefan Fussenegger commented on CAMEL-10280:
--------------------------------------------

Not sure I understand what you mean by "add a control before creating the topic 
and if we have an ARN". Isn't that what {{if (configuration.getTopicArn() == 
null)}} is? This - i.e. supporting configuration of ARN - was added in 2.18 by 
CAMEL-9844, see [SnsEndpoint in 
master|https://github.com/apache/camel/blob/41fca5724a9bb45175f9fe32692da84520b976f6/components/camel-aws/src/main/java/org/apache/camel/component/aws/sns/SnsEndpoint.java#L92]

However, I have a problem with configuring an ARN like 
{{arn:aws:sns:us-east-1:123456789012:mytopic}}: You have to hard-code the 
region and account into it. Typically you want to rely on the AWS client 
configured values for that. For instance, people would want to run staging and 
production in different regions or different accounts in order to not interfere 
with each other. In this scenario, all ARNs would have to be changed which is 
unfortunate.

I would like to use a name - as it is already possible - however without 
requiring the {{CreateTopic}} permission. Our use-case is that SNS topics are 
created by a CloudFormation stack and thus are expected to exist. Thus a 
non-existing topic clearly is an indication of a misconfiguration. Currently, 
the camel component will create a topic and happily post to it, even though all 
subscribers are subscribed to a different topic. That again is unfortunate.

Imho, the easiest way to fix this is using a read-only API call to check if the 
topic exists before trying to create one. This is exactly what [the 
SqsEndpoint|https://github.com/apache/camel/blob/41fca5724a9bb45175f9fe32692da84520b976f6/components/camel-aws/src/main/java/org/apache/camel/component/aws/sqs/SqsEndpoint.java#L137]
 does right now using {{ListQueues}}. This is why I used {{ListTopics}} in my 
snippet above. I've also opted to ignore permission issues so it remains 
backward compatible and works with only {{CreateTopic}} too.

The complete code of {{SnsEndpoint.doStart()}} would look like this:

{code:java}
    @Override
    public void doStart() throws Exception {
        super.doStart();
        snsClient = configuration.getAmazonSNSClient() != null
            ? configuration.getAmazonSNSClient() : createSNSClient();
        
        // Override the setting Endpoint from url
        if (ObjectHelper.isNotEmpty(configuration.getAmazonSNSEndpoint())) {
            LOG.trace("Updating the SNS region with : {} " + 
configuration.getAmazonSNSEndpoint());
            snsClient.setEndpoint(configuration.getAmazonSNSEndpoint());
        }

        if (configuration.getTopicArn() == null) {
                // list topics and return URL of an existing topic
                try {
                        String nextToken = null;
                        final String arnSuffix = ":" + 
configuration.getTopicName();
                        do {
                                final ListTopicsResult response = 
snsClient.listTopics(nextToken);
                                nextToken = response.getNextToken();

                                for (final Topic topic : response.getTopics()) {
                                        if 
(topic.getTopicArn().endsWith(arnSuffix)) {
                                                
configuration.setTopicArn(topic.getTopicArn());
                                                break;
                                        }
                                }

                        } while (nextToken != null);
                } catch (final AuthorizationErrorException e) {
                        // not sure this is the right exception to catch
                        LOG.trace("Not able to list topics due to insufficient 
permissions");
                }
        }

        if (configuration.getTopicArn() == null) {
            // creates a new topic, or returns the URL of an existing one
            CreateTopicRequest request = new 
CreateTopicRequest(configuration.getTopicName());

            LOG.trace("Creating topic [{}] with request [{}]...", 
configuration.getTopicName(), request);

            CreateTopicResult result = snsClient.createTopic(request);
            configuration.setTopicArn(result.getTopicArn());

            LOG.trace("Topic created with Amazon resource name: {}", 
configuration.getTopicArn());
        }
        
        if (ObjectHelper.isNotEmpty(configuration.getPolicy())) {
            LOG.trace("Updating topic [{}] with policy [{}]", 
configuration.getTopicArn(), configuration.getPolicy());
            
            snsClient.setTopicAttributes(new 
SetTopicAttributesRequest(configuration.getTopicArn(), "Policy", 
configuration.getPolicy()));
            
            LOG.trace("Topic policy updated");
        }
        
    }
{code}

> Don't require create privileges to publish to named SNS topic
> -------------------------------------------------------------
>
>                 Key: CAMEL-10280
>                 URL: https://issues.apache.org/jira/browse/CAMEL-10280
>             Project: Camel
>          Issue Type: Improvement
>          Components: camel-aws
>    Affects Versions: 2.17.3, 2.18.0
>            Reporter: Stefan Fussenegger
>            Assignee: Andrea Cosentino
>
> If a topic already exists, the {{SnsEndpoint}} still requires privileges for 
> the (idempotent) {{CreateTopic}} operation to resolve the name to an ARN.
> In comparison, the {{SqsEndpoint}} uses the {{ListQueues}} operation to check 
> for an existing queue before trying to create a queue.
> Providing an ARN instead of a name bypasses the issue (added to 2.18 in 
> CAMEL-9844). Using an ARN instead of a name isn't always practical though.



--
This message was sent by Atlassian JIRA
(v6.3.4#6332)

Reply via email to