diff --git a/CHANGELOG.next.asciidoc b/CHANGELOG.next.asciidoc index b9820f7b53e8..b54f185eed5f 100644 --- a/CHANGELOG.next.asciidoc +++ b/CHANGELOG.next.asciidoc @@ -341,6 +341,7 @@ https://github.com/elastic/beats/compare/v7.0.0-alpha2...master[Check the HEAD d - Export automation templates used to create functions. {pull}11923[11923] - Configurable Amazon endpoint. {pull}12369[12369] - Add timeout option to reference configuration. {pull}13351[13351] +- Configurable tags for Lambda functions. {pull}13352[13352] *Winlogbeat* diff --git a/x-pack/functionbeat/_meta/beat.reference.yml b/x-pack/functionbeat/_meta/beat.reference.yml index 1dc3348e69cb..da3a100fb260 100644 --- a/x-pack/functionbeat/_meta/beat.reference.yml +++ b/x-pack/functionbeat/_meta/beat.reference.yml @@ -50,6 +50,10 @@ functionbeat.provider.aws.functions: # Dead letter queue configuration, this must be set to an ARN pointing to a SQS queue. #dead_letter_config.target_arn: + # Tags are key-value pairs attached to the function. + #tags: + # department: ops + # Optional fields that you can specify to add additional information to the # output. Fields can be scalar values, arrays, dictionaries, or any nested # combination of these. @@ -98,6 +102,10 @@ functionbeat.provider.aws.functions: # Dead letter queue configuration, this must be set to an ARN pointing to a SQS queue. #dead_letter_config.target_arn: + # Tags are key-value pairs attached to the function. + #tags: + # department: ops + # Optional fields that you can specify to add additional information to the # output. Fields can be scalar values, arrays, dictionaries, or any nested # combination of these. @@ -151,6 +159,10 @@ functionbeat.provider.aws.functions: # Dead letter queue configuration, this must be set to an ARN pointing to a SQS queue. #dead_letter_config.target_arn: + # Tags are key-value pairs attached to the function. + #tags: + # department: ops + # Optional fields that you can specify to add additional information to the # output. Fields can be scalar values, arrays, dictionaries, or any nested # combination of these. diff --git a/x-pack/functionbeat/functionbeat.reference.yml b/x-pack/functionbeat/functionbeat.reference.yml index 279572367516..5f485481c68a 100644 --- a/x-pack/functionbeat/functionbeat.reference.yml +++ b/x-pack/functionbeat/functionbeat.reference.yml @@ -50,6 +50,10 @@ functionbeat.provider.aws.functions: # Dead letter queue configuration, this must be set to an ARN pointing to a SQS queue. #dead_letter_config.target_arn: + # Tags are key-value pairs attached to the function. + #tags: + # department: ops + # Optional fields that you can specify to add additional information to the # output. Fields can be scalar values, arrays, dictionaries, or any nested # combination of these. @@ -98,6 +102,10 @@ functionbeat.provider.aws.functions: # Dead letter queue configuration, this must be set to an ARN pointing to a SQS queue. #dead_letter_config.target_arn: + # Tags are key-value pairs attached to the function. + #tags: + # department: ops + # Optional fields that you can specify to add additional information to the # output. Fields can be scalar values, arrays, dictionaries, or any nested # combination of these. @@ -151,6 +159,10 @@ functionbeat.provider.aws.functions: # Dead letter queue configuration, this must be set to an ARN pointing to a SQS queue. #dead_letter_config.target_arn: + # Tags are key-value pairs attached to the function. + #tags: + # department: ops + # Optional fields that you can specify to add additional information to the # output. Fields can be scalar values, arrays, dictionaries, or any nested # combination of these. diff --git a/x-pack/functionbeat/manager/aws/template_builder.go b/x-pack/functionbeat/manager/aws/template_builder.go index 28df63fb7cf4..89352c78a5c3 100644 --- a/x-pack/functionbeat/manager/aws/template_builder.go +++ b/x-pack/functionbeat/manager/aws/template_builder.go @@ -165,6 +165,15 @@ func (d *defaultTemplateBuilder) template(function installer, name, codeLoc stri } } + var tags []cloudformation.Tag + for name, val := range lambdaConfig.Tags { + tag := cloudformation.Tag{ + Key: name, + Value: val, + } + tags = append(tags, tag) + } + // Create the lambda // Doc: https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lambda-function.html template.Resources[prefix("")] = &AWSLambdaFunction{ @@ -190,6 +199,7 @@ func (d *defaultTemplateBuilder) template(function installer, name, codeLoc stri MemorySize: lambdaConfig.MemorySize.Megabytes(), ReservedConcurrentExecutions: lambdaConfig.Concurrency, Timeout: int(lambdaConfig.Timeout.Seconds()), + Tags: tags, }, DependsOn: dependsOn, } diff --git a/x-pack/functionbeat/provider/aws/aws/config.go b/x-pack/functionbeat/provider/aws/aws/config.go index 0571e3ce932c..feed4712cbfa 100644 --- a/x-pack/functionbeat/provider/aws/aws/config.go +++ b/x-pack/functionbeat/provider/aws/aws/config.go @@ -7,8 +7,10 @@ package aws import ( "fmt" "regexp" + "strings" "time" "unicode" + "unicode/utf8" humanize "github.com/dustin/go-humanize" @@ -49,6 +51,7 @@ type LambdaConfig struct { Timeout time.Duration `config:"timeout" validate:"nonzero,positive"` Role string `config:"role"` VPCConfig *vpcConfig `config:"virtual_private_cloud"` + Tags map[string]string `config:"tags"` } // Validate checks a LambdaConfig @@ -65,7 +68,7 @@ func (c *LambdaConfig) Validate() error { return fmt.Errorf("invalid role: '%s', name must match pattern %s", c.Role, arnRolePattern) } - return nil + return validateTags(c.Tags) } type deadLetterConfig struct { @@ -77,6 +80,27 @@ type vpcConfig struct { SubnetIDs []string `config:"subnet_ids" validate:"required"` } +func validateTags(tags map[string]string) error { + for key, val := range tags { + if strings.HasPrefix(key, "aws:") { + return fmt.Errorf("key '%s' cannot be prefixed with 'aws:'", key) + } + if strings.HasPrefix(val, "aws:") { + return fmt.Errorf("value '%s' cannot be prefixed with 'aws:'", val) + } + keyLen := utf8.RuneCountInString(key) + if keyLen > 127 { + return fmt.Errorf("too long key; expected 127 chars, but got %d", keyLen) + } + valLen := utf8.RuneCountInString(val) + if valLen > 255 { + return fmt.Errorf("too long value; expected 255 chars, but got %d", valLen) + } + } + + return nil +} + // MemSizeFactor64 implements a human understandable format for bytes but also make sure that all // values used are a factory of 64. type MemSizeFactor64 int