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 }