github.com/mweagle/Sparta@v1.15.0/aws/cloudformation/resources/cloudWatchLogsLambdaEventSourceResource.go (about) 1 package resources 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "strings" 7 8 "github.com/aws/aws-sdk-go/aws" 9 "github.com/aws/aws-sdk-go/aws/session" 10 "github.com/aws/aws-sdk-go/service/cloudwatchlogs" 11 gocf "github.com/mweagle/go-cloudformation" 12 "github.com/sirupsen/logrus" 13 ) 14 15 // CloudWatchLogsLambdaEventSourceFilter represents a filter for a cloudwatchlogs 16 // stream 17 type CloudWatchLogsLambdaEventSourceFilter struct { 18 Name *gocf.StringExpr 19 Pattern *gocf.StringExpr 20 LogGroupName *gocf.StringExpr 21 } 22 23 // CloudWatchEventSourceResourceRequest is what the UserProperties 24 // should be set to in the CustomResource invocation 25 type CloudWatchEventSourceResourceRequest struct { 26 LambdaTargetArn *gocf.StringExpr 27 Filters []*CloudWatchLogsLambdaEventSourceFilter 28 RoleARN *gocf.StringExpr `json:",omitempty"` 29 } 30 31 // CloudWatchLogsLambdaEventSourceResource is a simple POC showing how to create custom resources 32 type CloudWatchLogsLambdaEventSourceResource struct { 33 gocf.CloudFormationCustomResource 34 CloudWatchEventSourceResourceRequest 35 } 36 37 // IAMPrivileges returns the IAM privs for this custom action 38 func (command *CloudWatchLogsLambdaEventSourceResource) IAMPrivileges() []string { 39 return []string{"logs:DescribeSubscriptionFilters", 40 "logs:DeleteSubscriptionFilter", 41 "logs:PutSubscriptionFilter"} 42 } 43 44 func cloudWatchEventSourceProperties(event *CloudFormationLambdaEvent) (*CloudWatchEventSourceResourceRequest, error) { 45 eventProperties := CloudWatchEventSourceResourceRequest{} 46 unmarshalErr := json.Unmarshal(event.ResourceProperties, &eventProperties) 47 if unmarshalErr != nil { 48 return nil, unmarshalErr 49 } 50 return &eventProperties, nil 51 } 52 53 func (command CloudWatchLogsLambdaEventSourceResource) updateRegistration(isTargetActive bool, 54 session *session.Session, 55 event *CloudFormationLambdaEvent, 56 logger *logrus.Logger) (map[string]interface{}, error) { 57 58 requestProps, requestPropsErr := cloudWatchEventSourceProperties(event) 59 if requestPropsErr != nil { 60 return nil, requestPropsErr 61 } 62 63 var opErr error 64 cwLogsSvc := cloudwatchlogs.New(session) 65 for _, eachFilter := range requestProps.Filters { 66 67 // Always delete the filter by name if we can find it... 68 deleteSubscriptionInput := &cloudwatchlogs.DeleteSubscriptionFilterInput{ 69 FilterName: aws.String(eachFilter.Name.Literal), 70 LogGroupName: aws.String(eachFilter.LogGroupName.Literal), 71 } 72 deleteResult, deleteErr := cwLogsSvc.DeleteSubscriptionFilter(deleteSubscriptionInput) 73 logger.WithFields(logrus.Fields{ 74 "DeleteInput": deleteSubscriptionInput, 75 "Result": deleteResult, 76 "Error": deleteErr, 77 }).Debug("DeleteSubscriptionFilter result") 78 if nil != deleteErr && strings.Contains(deleteErr.Error(), "ResourceNotFoundException") { 79 deleteErr = nil 80 } 81 opErr = deleteErr 82 83 // Conditionally create 84 if isTargetActive && nil == opErr { 85 // Put the subscription filter 86 putSubscriptionInput := &cloudwatchlogs.PutSubscriptionFilterInput{ 87 DestinationArn: aws.String(requestProps.LambdaTargetArn.Literal), 88 FilterName: aws.String(eachFilter.Name.Literal), 89 FilterPattern: aws.String(eachFilter.Pattern.Literal), 90 LogGroupName: aws.String(eachFilter.LogGroupName.Literal), 91 } 92 if nil != requestProps.RoleARN { 93 putSubscriptionInput.RoleArn = aws.String(requestProps.RoleARN.Literal) 94 } 95 _, opErr = cwLogsSvc.PutSubscriptionFilter(putSubscriptionInput) 96 // If there was an error, see if there's a differently named filter for the given 97 // CloudWatchLogs stream. 98 if nil != opErr { 99 describeSubscriptionFilters := &cloudwatchlogs.DescribeSubscriptionFiltersInput{ 100 LogGroupName: aws.String(eachFilter.LogGroupName.Literal), 101 } 102 describeResult, describeResultErr := cwLogsSvc.DescribeSubscriptionFilters(describeSubscriptionFilters) 103 if nil == describeResultErr { 104 opErr = fmt.Errorf("conflict with differently named subscription on prexisting LogGroupName: %s", 105 eachFilter.LogGroupName.Literal) 106 107 logger.WithFields(logrus.Fields{ 108 "DescribeSubscriptionResult": describeResult, 109 "PutSubscriptionInput": putSubscriptionInput, 110 "LogGroupName": eachFilter.LogGroupName, 111 }).Error(opErr.Error()) 112 } 113 } 114 } 115 if nil != opErr { 116 return nil, opErr 117 } 118 } 119 return nil, opErr 120 } 121 122 // Create implements the create operation 123 func (command CloudWatchLogsLambdaEventSourceResource) Create(awsSession *session.Session, 124 event *CloudFormationLambdaEvent, 125 logger *logrus.Logger) (map[string]interface{}, error) { 126 return command.updateRegistration(true, awsSession, event, logger) 127 } 128 129 // Update implements the update operation 130 func (command CloudWatchLogsLambdaEventSourceResource) Update(awsSession *session.Session, 131 event *CloudFormationLambdaEvent, 132 logger *logrus.Logger) (map[string]interface{}, error) { 133 return command.updateRegistration(true, awsSession, event, logger) 134 } 135 136 // Delete implements the delete operation 137 func (command CloudWatchLogsLambdaEventSourceResource) Delete(awsSession *session.Session, 138 event *CloudFormationLambdaEvent, 139 logger *logrus.Logger) (map[string]interface{}, error) { 140 return command.updateRegistration(false, awsSession, event, logger) 141 }