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  }