github.com/mweagle/Sparta@v1.15.0/aws/cloudformation/resources/snsLambdaEventSourceResource.go (about) 1 package resources 2 3 import ( 4 "encoding/json" 5 "fmt" 6 7 "github.com/aws/aws-sdk-go/aws" 8 "github.com/aws/aws-sdk-go/aws/session" 9 "github.com/aws/aws-sdk-go/service/sns" 10 gocf "github.com/mweagle/go-cloudformation" 11 "github.com/sirupsen/logrus" 12 ) 13 14 // SNSLambdaEventSourceResourceRequest defines the request properties to configure 15 // SNS 16 type SNSLambdaEventSourceResourceRequest struct { 17 LambdaTargetArn *gocf.StringExpr 18 SNSTopicArn *gocf.StringExpr 19 } 20 21 // SNSLambdaEventSourceResource is a simple POC showing how to create custom resources 22 type SNSLambdaEventSourceResource struct { 23 gocf.CloudFormationCustomResource 24 SNSLambdaEventSourceResourceRequest 25 } 26 27 func (command SNSLambdaEventSourceResource) updateRegistration(isTargetActive bool, 28 session *session.Session, 29 event *CloudFormationLambdaEvent, 30 logger *logrus.Logger) (map[string]interface{}, error) { 31 32 unmarshalErr := json.Unmarshal(event.ResourceProperties, &command) 33 if unmarshalErr != nil { 34 return nil, unmarshalErr 35 } 36 37 // Get the current subscriptions... 38 snsSvc := sns.New(session) 39 snsInput := &sns.ListSubscriptionsByTopicInput{ 40 TopicArn: aws.String(command.SNSTopicArn.Literal), 41 } 42 listSubscriptions, listSubscriptionsErr := snsSvc.ListSubscriptionsByTopic(snsInput) 43 if listSubscriptionsErr != nil { 44 return nil, listSubscriptionsErr 45 } 46 var lambdaSubscriptionArn string 47 for _, eachSubscription := range listSubscriptions.Subscriptions { 48 if *eachSubscription.Protocol == "lambda" && 49 *eachSubscription.Endpoint == command.LambdaTargetArn.Literal { 50 if lambdaSubscriptionArn != "" { 51 return nil, fmt.Errorf("multiple SNS %s registrations found for lambda: %s", 52 *snsInput.TopicArn, 53 command.LambdaTargetArn.Literal) 54 } 55 lambdaSubscriptionArn = *eachSubscription.SubscriptionArn 56 } 57 } 58 // Just log it... 59 logger.WithFields(logrus.Fields{ 60 "SNSTopicArn": command.SNSTopicArn, 61 "LambdaArn": command.LambdaTargetArn, 62 "ExistingSubscriptionArn": lambdaSubscriptionArn, 63 }).Info("Current SNS subscription status") 64 65 var opErr error 66 if isTargetActive && lambdaSubscriptionArn == "" { 67 subscribeInput := &sns.SubscribeInput{ 68 Protocol: aws.String("lambda"), 69 TopicArn: aws.String(command.SNSTopicArn.Literal), 70 Endpoint: aws.String(command.LambdaTargetArn.Literal), 71 } 72 _, opErr = snsSvc.Subscribe(subscribeInput) 73 } else if !isTargetActive && lambdaSubscriptionArn != "" { 74 unsubscribeInput := &sns.UnsubscribeInput{ 75 SubscriptionArn: aws.String(lambdaSubscriptionArn), 76 } 77 _, opErr = snsSvc.Unsubscribe(unsubscribeInput) 78 } else { 79 // Just log it... 80 logger.WithFields(logrus.Fields{ 81 "Command": command, 82 }).Info("No SNS operation required") 83 } 84 85 return nil, opErr 86 } 87 88 // IAMPrivileges returns the IAM privs for this custom action 89 func (command *SNSLambdaEventSourceResource) IAMPrivileges() []string { 90 return []string{"sns:ConfirmSubscription", 91 "sns:GetTopicAttributes", 92 "sns:ListSubscriptionsByTopic", 93 "sns:Subscribe", 94 "sns:Unsubscribe"} 95 } 96 97 // Create implements the custom resource create operation 98 func (command SNSLambdaEventSourceResource) Create(awsSession *session.Session, 99 event *CloudFormationLambdaEvent, 100 logger *logrus.Logger) (map[string]interface{}, error) { 101 return command.updateRegistration(true, awsSession, event, logger) 102 } 103 104 // Update implements the custom resource update operation 105 func (command SNSLambdaEventSourceResource) Update(awsSession *session.Session, 106 event *CloudFormationLambdaEvent, 107 logger *logrus.Logger) (map[string]interface{}, error) { 108 return command.updateRegistration(true, awsSession, event, logger) 109 } 110 111 // Delete implements the custom resource delete operation 112 func (command SNSLambdaEventSourceResource) Delete(awsSession *session.Session, 113 event *CloudFormationLambdaEvent, 114 logger *logrus.Logger) (map[string]interface{}, error) { 115 return command.updateRegistration(false, awsSession, event, logger) 116 }