ansible sns - why is subscriber optional - amazon-web-services

When I am subscribing a lambda function to an SNS topic through either the aws console or aws cli there is a column shown in the subscription information called "subscriber". It does contain my account id.
I don't seem to be able to control this field through the cli or console however I can through ansible:
---
- name: set up topic and subscribe lambda
sns_topic:
name: "topic_name"
state: present
display_name: "Display Name"
subscriptions:
- endpoint: "arn:aws:lambda:ap-southeast-2:123456789:function:functionName"
protocol: "lambda"
subscriber: 123456789
The subscriber field is optional, however SNS messages do not seem to reach lambda without it.
What is this field for?
Can I subscribe Lambdas in other accounts to my SNS topic?
How can I effect change in this field with AWS CLI?
Why is it optional in Ansible 2.4

Couldn't find reference to ghost field i.e. subscriber.
Maybe it was supported in older sdk/api and now has been dropped.
Reseach:
I don't see subscriber field in the console when subscribing lambda. Image below
Even through CLI, there is no such field
Link for SNS Subscribe command through CLI documentation.
[Extra Research]: Even the java sdk asks for only three parameters in order to subscribe
subscribe(String topicArn, String protocol, String endpoint)
Java doc link

Related

Using AWS CLI to enable encryption for SNS topic

is there a way to use the AWS CLI to modify attributes of an SNS topic ?
I'm trying to enable Encryption for an SNS topic but the documentation presented here
https://docs.aws.amazon.com/sns/latest/dg/sns-enable-encryption-for-topic.html
only specifies 2 methods:
Using the AWS Console
Using the Java AWS SDK
Here is what you are looking for:
https://docs.aws.amazon.com/cli/latest/reference/sns/set-topic-attributes.html
--attribute-name (string)
A map of attributes with their corresponding values.
The following attribute applies only to server-side-encryption :
KmsMasterKeyId - The ID of an AWS-managed customer master key (CMK) for Amazon SNS or a custom CMK. For more information, see Key Terms . For more examples, see KeyId in the AWS Key Management Service API Reference .
Use set-topic-attribute command.
Example:
aws sns set-topic-attributes --topic-arn arn:aws:sns:us-west-2:123456789012:MyTopic --attribute-name KmsMasterKeyId --attribute-value arn:aws:kms:us-east-2:111122223333:alias/ExampleAlias
You can also use the key id, key id arn or just alias name for the attribute value.

How to get ARN for SNS Topic created using cloud formation?

I have created SNS using cloud formation like this -
MYSNS:
Type: AWS::SNS::Topic
Properties:
DisplayName: "MYSNS"
TopicName: "MYSNS"
Now, I want to publish message to this topic using Java but
snsClient.publish(snsARN, snsEvent);
sns client requires ARN to publish the event. How I can get SNS Topic ARN?
Edit 1: Post deployment we can get the ARN, but don't want this way.
Ex - We can get SQS url by it's Name using SQS Client like this -
sqsClient.getQueueUrl(dlqName).getQueueUrl(); I am looking for similar way in case of SNS.
You can construct the ARN yourself:
arn:aws:sns:<region>:<account>:MYSNS
You can try this in cloudformation template to get the created SNS's ARN
!Ref MYSNS

Find Cloudwatch log group for a given resource

I'm creating a logs aggregator lambda to send Cloudwatch logs to a private log analysis service. Given the number of resources used by my employer, it was decided to create a subscription lambda that handles log group subscription to the aggregator.
The solution works fine, but it requires to manually search a resource's log group via amazon console and then invoke the subscription lambda with it.
My question:
Is there a way to, given a resource arn, find which log group is mapped to it? Since I'm using Cloudformation to create resources it is easy to export a resource's arn.
UPDATE
To present an example:
Let's say I have the following arn:
arn:aws:appsync:<REGION>:<ACCOUNTID>apis/z3pihpr4gfbzhflthkyjjh6yvu
which is an Appsync GraphQL API.
What I want it a method (using te API or some automated solution) to get the Cloudwatch log group of that resource.
You can try the describe-log-groups command. It is available on the cli, must also be there on the API.
To get the names of the log groups you can go with:
aws logs describe-log-groups --query 'logGroups[*].logGroupName' --log-group-name-prefix '/aws/appsync/[name-of-the-resource]'
Output will look like this:
[
"/aws/appsync/[name-of-your-resource]"
]

CloudWatch alarm to SNS in different region

I'm trying to notify an SNS topic from a CloudWatch alarm that's in a different region. The reason is that I want SMS alerting, which isn't available in the region where my services are. If I enter the ARN of the subscription and save the changes in the console, I get "There was an error saving the alarm. Please try again." Trying again does not help. Using a topic in the local region does work, but that's not what I need.
Is there a way to notify a topic in a different region? If not, is there another easy way I can achieve my goal?
Didn't find any docs that explicitly say this can't be done but tried to set an SNS from us-east-1 as an action of an alarm in eu-west-1 using the CLI and I got this:
An error occurred (ValidationError) when calling the PutMetricAlarm operation: Invalid region us-east-1 specified. Only eu-west-1 is supported.
So I'll assume it's not supported.
To get the functionality you need you can use AWS Lambda. Lets say your service is in a region where SMS is not supported, I'll use eu-central-1 as an example.
Setup would go like this:
[us-east-1] Create your SNS topic that can send SMS messages, in the region where SMS is supported.
[eu-central-1 Create a lambda function that sends messages to the SNS topic from step 1 in the region where your service is.
[eu-central-1] Create an SNS topic in the region where your service is.
For the SNS topic configure subscription with AWS Lambda protocol and point it to lambda from step 2.
[eu-central-1] Create your alarm in the region where your service is and put the SNS topic from step 3 as an action.
To add to #Tartaglia's answer, here's the source of such a lambda function using Python 3, cobbled together from various sources because I don't have time to do it properly:
import json
import logging
import boto3
logger = logging.getLogger()
logger.setLevel(logging.INFO)
session = boto3.Session(region_name='eu-west-1') # EU (Ireland)
sns_client = session.client('sns')
def lambda_handler(event, context):
logger.info('Received event: %s', event)
for record in event['Records']:
sns_message = record['Sns']
response = sns_client.publish(
TopicArn='YOUR TOPIC ARN HERE',
Subject=sns_message.get('Subject', None),
Message=sns_message.get('Message', None))
logger.info('Publish response: %s', response)
return 'OK'

Alternative to updating SNS subscriptions using AWS CloudFormation

There's an AWS CloudFormation stack which defines an SNS topic and an SNS subscription. In another Ansible task, I want to update another subscription, but this isn't possible as SNS subscriptions can't be updated.
Using Ansible to perform CloudFormation. What are the alternatives?
Club AWS CLI with Ansible and then execute plays which contain AWS CLI content?
Create a custom module in Ansible using boto? But this would be difficult as I should store SNS ARN's and give those to the custom module.
Ansible v2.0 added support of an sns_topic module. You can provide a name or ARN of an existing SNS topic to converge. You also probably want to set purge_subscriptions to False so any existing subscriptions are not removed.
- name: Update SNS topic subscriptions
sns_topic:
name: "my-topic"
purge_subscriptions: False
subscriptions:
- endpoint: "some-email#example.com"
protocol: "email"
http://docs.ansible.com/ansible/sns_topic_module.html