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  }