From fdbfb100f12408c65af1d18b011072697ea6e69d Mon Sep 17 00:00:00 2001 From: Pier-Hugues Pellerin Date: Mon, 21 Jan 2019 09:07:32 -0500 Subject: [PATCH] Instead of blacklisting chars in the resource name for cloudformation use whitelisting. (#10087) (#10120) * Instead of blacklisting chars in the resource name for cloudformation use whitelisting. Only [a-zA-Z0-9] are permitted as resource name Fixes: #9420 (cherry picked from commit 56c685719f25cfea3fff9dcab176cd37f394feb2) --- CHANGELOG.next.asciidoc | 1 + .../functionbeat/provider/aws/cli_manager.go | 21 ++++++++++--------- .../provider/aws/cli_manager_test.go | 5 +++++ .../provider/aws/cloudwatch_logs.go | 4 ++-- x-pack/functionbeat/provider/aws/sqs.go | 2 +- 5 files changed, 20 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.next.asciidoc b/CHANGELOG.next.asciidoc index df8fb8b4bc9c..bb64d26146d5 100644 --- a/CHANGELOG.next.asciidoc +++ b/CHANGELOG.next.asciidoc @@ -41,6 +41,7 @@ https://github.com/elastic/beats/compare/v6.6.0...6.x[Check the HEAD diff] *Functionbeat* - The CLI will now log CloudFormation Stack events. {issue}8912[8912] +- Correctly normalize Cloudformation resource name. {issue}10087[10087] ==== Bugfixes diff --git a/x-pack/functionbeat/provider/aws/cli_manager.go b/x-pack/functionbeat/provider/aws/cli_manager.go index 1a50af5bad65..630fa92c2d46 100644 --- a/x-pack/functionbeat/provider/aws/cli_manager.go +++ b/x-pack/functionbeat/provider/aws/cli_manager.go @@ -9,6 +9,7 @@ import ( "encoding/base64" "errors" "fmt" + "regexp" "github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go-v2/aws/external" @@ -26,13 +27,13 @@ const ( // AWS lambda currently support go 1.x as a runtime. runtime = "go1.x" handlerName = "functionbeat" - - // invalidChars for resource name - invalidChars = ":-/" ) -// AWSLambdaFunction add 'dependsOn' as a serializable parameters, for no good reason it's -// not supported. +// Chars for resource name anything else will be replaced. +var validChars = regexp.MustCompile("[^a-zA-Z0-9]") + +// AWSLambdaFunction add 'dependsOn' as a serializable parameters, goformation doesn't currently +// serialize this field. type AWSLambdaFunction struct { *cloudformation.AWSLambdaFunction DependsOn []string @@ -71,7 +72,7 @@ func (c *CLIManager) template(function installer, name, codeLoc string) *cloudfo lambdaConfig := function.LambdaConfig() prefix := func(s string) string { - return "fnb" + name + s + return normalizeResourceName("fnb" + name + s) } // AWS variables references:. @@ -86,7 +87,7 @@ func (c *CLIManager) template(function installer, name, codeLoc string) *cloudfo // Create the roles for the lambda. template := cloudformation.NewTemplate() // doc: https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iam-role.html - template.Resources["IAMRoleLambdaExecution"] = &cloudformation.AWSIAMRole{ + template.Resources[prefix("")+"IAMRoleLambdaExecution"] = &cloudformation.AWSIAMRole{ AssumeRolePolicyDocument: map[string]interface{}{ "Statement": []interface{}{ map[string]interface{}{ @@ -149,14 +150,14 @@ func (c *CLIManager) template(function installer, name, codeLoc string) *cloudfo }, DeadLetterConfig: dlc, FunctionName: name, - Role: cloudformation.GetAtt("IAMRoleLambdaExecution", "Arn"), + Role: cloudformation.GetAtt(prefix("")+"IAMRoleLambdaExecution", "Arn"), Runtime: runtime, Handler: handlerName, MemorySize: lambdaConfig.MemorySize.Megabytes(), ReservedConcurrentExecutions: lambdaConfig.Concurrency, Timeout: int(lambdaConfig.Timeout.Seconds()), }, - DependsOn: []string{"IAMRoleLambdaExecution"}, + DependsOn: []string{prefix("") + "IAMRoleLambdaExecution"}, } // Create the log group for the specific function lambda. @@ -366,7 +367,7 @@ func mergeTemplate(to, from *cloudformation.Template) error { } func normalizeResourceName(s string) string { - return common.RemoveChars(s, invalidChars) + return validChars.ReplaceAllString(s, "") } func checksum(data []byte) string { diff --git a/x-pack/functionbeat/provider/aws/cli_manager_test.go b/x-pack/functionbeat/provider/aws/cli_manager_test.go index 418cb1550130..ef7bd36c6b88 100644 --- a/x-pack/functionbeat/provider/aws/cli_manager_test.go +++ b/x-pack/functionbeat/provider/aws/cli_manager_test.go @@ -59,6 +59,11 @@ func TestNormalize(t *testing.T) { candidate: "hello", expected: "hello", }, + { + title: "when the string contains underscore", + candidate: "/var/log-alpha/tmp:ok_moreok", + expected: "varlogalphatmpokmoreok", + }, } for _, test := range tests { diff --git a/x-pack/functionbeat/provider/aws/cloudwatch_logs.go b/x-pack/functionbeat/provider/aws/cloudwatch_logs.go index 01e0d9043aa9..ded21d6f7d92 100644 --- a/x-pack/functionbeat/provider/aws/cloudwatch_logs.go +++ b/x-pack/functionbeat/provider/aws/cloudwatch_logs.go @@ -165,7 +165,7 @@ func (r *AWSLogsSubscriptionFilter) AWSCloudFormationType() string { // Template returns the cloudformation template for configuring the service with the specified triggers. func (c *CloudwatchLogs) Template() *cloudformation.Template { prefix := func(suffix string) string { - return "fnb" + c.config.Name + suffix + return normalizeResourceName("fnb" + c.config.Name + suffix) } template := cloudformation.NewTemplate() @@ -197,7 +197,7 @@ func (c *CloudwatchLogs) Template() *cloudformation.Template { } // doc: https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-logs-subscriptionfilter.html - template.Resources[prefix("SubscriptionFilter"+normalizeResourceName(string(trigger.LogGroupName)))] = &AWSLogsSubscriptionFilter{ + template.Resources[prefix("SF")+normalizeResourceName(string(trigger.LogGroupName))] = &AWSLogsSubscriptionFilter{ DestinationArn: cloudformation.GetAtt(prefix(""), "Arn"), FilterPattern: trigger.FilterPattern, LogGroupName: string(trigger.LogGroupName), diff --git a/x-pack/functionbeat/provider/aws/sqs.go b/x-pack/functionbeat/provider/aws/sqs.go index fd7a93c07a8f..5b377fdd9187 100644 --- a/x-pack/functionbeat/provider/aws/sqs.go +++ b/x-pack/functionbeat/provider/aws/sqs.go @@ -87,7 +87,7 @@ func (s *SQS) Template() *cloudformation.Template { template := cloudformation.NewTemplate() prefix := func(suffix string) string { - return "fnb" + s.config.Name + suffix + return normalizeResourceName("fnb" + s.config.Name + suffix) } for _, trigger := range s.config.Triggers {