github.com/mweagle/Sparta@v1.15.0/aws/cloudformation/resources/sesLambdaEventSourceResource.go (about)

     1  package resources
     2  
     3  import (
     4  	"encoding/json"
     5  	"strings"
     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/ses"
    10  	gocf "github.com/mweagle/go-cloudformation"
    11  	"github.com/sirupsen/logrus"
    12  )
    13  
    14  // SESLambdaEventSourceResourceAction represents an SES rule action
    15  // TODO - specialized types for Actions
    16  type SESLambdaEventSourceResourceAction struct {
    17  	ActionType       *gocf.StringExpr
    18  	ActionProperties map[string]interface{}
    19  }
    20  
    21  func (action *SESLambdaEventSourceResourceAction) toReceiptAction(logger *logrus.Logger) *ses.ReceiptAction {
    22  	actionProperties := action.ActionProperties
    23  	switch action.ActionType.Literal {
    24  	case "LambdaAction":
    25  		action := &ses.ReceiptAction{
    26  			LambdaAction: &ses.LambdaAction{
    27  				FunctionArn:    aws.String(actionProperties["FunctionArn"].(string)),
    28  				InvocationType: aws.String("Event"),
    29  			},
    30  		}
    31  		if val, exists := actionProperties["InvocationType"]; exists {
    32  			action.LambdaAction.InvocationType = aws.String(val.(string))
    33  		}
    34  		if val, exists := actionProperties["TopicArn"]; exists {
    35  			action.LambdaAction.TopicArn = aws.String(val.(string))
    36  		}
    37  		return action
    38  	case "S3Action":
    39  		action := &ses.ReceiptAction{
    40  			S3Action: &ses.S3Action{
    41  				BucketName: aws.String(actionProperties["BucketName"].(string)),
    42  			},
    43  		}
    44  		if val, exists := actionProperties["KmsKeyArn"]; exists {
    45  			action.S3Action.KmsKeyArn = aws.String(val.(string))
    46  		}
    47  		if val, exists := actionProperties["ObjectKeyPrefix"]; exists {
    48  			action.S3Action.ObjectKeyPrefix = aws.String(val.(string))
    49  		}
    50  		if val, exists := actionProperties["TopicArn"]; exists {
    51  			action.S3Action.TopicArn = aws.String(val.(string))
    52  		}
    53  		return action
    54  	default:
    55  		logger.Error("No SESLmabdaEventSourceResourceAction marshaler found for action: " + action.ActionType.Literal)
    56  	}
    57  	return nil
    58  }
    59  
    60  // SESLambdaEventSourceResourceRule stores settings necessary to configure an SES
    61  // inbound rule
    62  type SESLambdaEventSourceResourceRule struct {
    63  	Name        *gocf.StringExpr
    64  	Actions     []*SESLambdaEventSourceResourceAction
    65  	ScanEnabled *gocf.BoolExpr `json:",omitempty"`
    66  	Enabled     *gocf.BoolExpr `json:",omitempty"`
    67  	Recipients  []*gocf.StringExpr
    68  	TLSPolicy   *gocf.StringExpr `json:",omitempty"`
    69  }
    70  
    71  func ensureSESRuleSetName(ruleSetName string, svc *ses.SES, logger *logrus.Logger) error {
    72  	describeInput := &ses.DescribeReceiptRuleSetInput{
    73  		RuleSetName: aws.String(ruleSetName),
    74  	}
    75  	var opError error
    76  	describeRuleSet, describeRuleSetErr := svc.DescribeReceiptRuleSet(describeInput)
    77  	if nil != describeRuleSetErr {
    78  		if strings.Contains(describeRuleSetErr.Error(), "RuleSetDoesNotExist") {
    79  			createRuleSet := &ses.CreateReceiptRuleSetInput{
    80  				RuleSetName: aws.String(ruleSetName),
    81  			}
    82  			logger.WithFields(logrus.Fields{
    83  				"createRuleSet": createRuleSet,
    84  			}).Info("Creating Sparta SES Rule set")
    85  			_, opError = svc.CreateReceiptRuleSet(createRuleSet)
    86  		}
    87  	} else {
    88  		logger.WithFields(logrus.Fields{
    89  			"describeRuleSet": describeRuleSet,
    90  		}).Info("SES Rule Set already exists")
    91  	}
    92  	return opError
    93  }
    94  
    95  // SESLambdaEventSourceResourceRequest defines the request properties to configure
    96  // SES
    97  type SESLambdaEventSourceResourceRequest struct {
    98  	RuleSetName *gocf.StringExpr
    99  	Rules       []*SESLambdaEventSourceResourceRule
   100  }
   101  
   102  // SESLambdaEventSourceResource handles configuring SES configuration
   103  type SESLambdaEventSourceResource struct {
   104  	gocf.CloudFormationCustomResource
   105  	SESLambdaEventSourceResourceRequest
   106  }
   107  
   108  func (command SESLambdaEventSourceResource) updateSESRules(areRulesActive bool,
   109  	session *session.Session,
   110  	event *CloudFormationLambdaEvent,
   111  	logger *logrus.Logger) (map[string]interface{}, error) {
   112  
   113  	unmarshalErr := json.Unmarshal(event.ResourceProperties, &command)
   114  	if unmarshalErr != nil {
   115  		return nil, unmarshalErr
   116  	}
   117  
   118  	svc := ses.New(session)
   119  	opError := ensureSESRuleSetName(command.RuleSetName.Literal, svc, logger)
   120  	if nil == opError {
   121  		for _, eachRule := range command.Rules {
   122  			if areRulesActive {
   123  				createReceiptRule := &ses.CreateReceiptRuleInput{
   124  					RuleSetName: aws.String(command.RuleSetName.Literal),
   125  					Rule: &ses.ReceiptRule{
   126  						Name:        aws.String(eachRule.Name.Literal),
   127  						Recipients:  make([]*string, 0),
   128  						Actions:     make([]*ses.ReceiptAction, 0),
   129  						ScanEnabled: aws.Bool(eachRule.ScanEnabled.Literal),
   130  						TlsPolicy:   aws.String(eachRule.TLSPolicy.Literal),
   131  						Enabled:     aws.Bool(eachRule.Enabled.Literal),
   132  					},
   133  				}
   134  				for _, eachAction := range eachRule.Actions {
   135  					createReceiptRule.Rule.Actions = append(createReceiptRule.Rule.Actions, eachAction.toReceiptAction(logger))
   136  				}
   137  
   138  				_, opError = svc.CreateReceiptRule(createReceiptRule)
   139  			} else {
   140  				// Delete them...
   141  				deleteReceiptRule := &ses.DeleteReceiptRuleInput{
   142  					RuleSetName: aws.String(command.RuleSetName.Literal),
   143  					RuleName:    aws.String(eachRule.Name.Literal),
   144  				}
   145  				_, opError = svc.DeleteReceiptRule(deleteReceiptRule)
   146  			}
   147  			if nil != opError {
   148  				return nil, opError
   149  			}
   150  		}
   151  	}
   152  	return nil, opError
   153  }
   154  
   155  // IAMPrivileges returns the IAM privs for this custom action
   156  func (command *SESLambdaEventSourceResource) IAMPrivileges() []string {
   157  	return []string{"ses:CreateReceiptRuleSet",
   158  		"ses:CreateReceiptRule",
   159  		"ses:DeleteReceiptRule",
   160  		"ses:DeleteReceiptRuleSet",
   161  		"ses:DescribeReceiptRuleSet"}
   162  }
   163  
   164  // Create implements the custom resource create operation
   165  func (command SESLambdaEventSourceResource) Create(awsSession *session.Session,
   166  	event *CloudFormationLambdaEvent,
   167  	logger *logrus.Logger) (map[string]interface{}, error) {
   168  	return command.updateSESRules(true, awsSession, event, logger)
   169  }
   170  
   171  // Update implements the custom resource update operation
   172  func (command SESLambdaEventSourceResource) Update(awsSession *session.Session,
   173  	event *CloudFormationLambdaEvent,
   174  	logger *logrus.Logger) (map[string]interface{}, error) {
   175  	return command.updateSESRules(true, awsSession, event, logger)
   176  }
   177  
   178  // Delete implements the custom resource delete operation
   179  func (command SESLambdaEventSourceResource) Delete(awsSession *session.Session,
   180  	event *CloudFormationLambdaEvent,
   181  	logger *logrus.Logger) (map[string]interface{}, error) {
   182  	return command.updateSESRules(false, awsSession, event, logger)
   183  }