diff --git a/aws/resource_aws_lambda_permission.go b/aws/resource_aws_lambda_permission.go index 005f4dbc3b4..0ab996fc354 100644 --- a/aws/resource_aws_lambda_permission.go +++ b/aws/resource_aws_lambda_permission.go @@ -30,6 +30,12 @@ func resourceAwsLambdaPermission() *schema.Resource { ForceNew: true, ValidateFunc: validateLambdaPermissionAction, }, + "event_source_token": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + ValidateFunc: validateLambdaPermissionEventSourceToken, + }, "function_name": { Type: schema.TypeString, Required: true, @@ -105,6 +111,9 @@ func resourceAwsLambdaPermissionCreate(d *schema.ResourceData, meta interface{}) StatementId: aws.String(statementId), } + if v, ok := d.GetOk("event_source_token"); ok { + input.EventSourceToken = aws.String(v.(string)) + } if v, ok := d.GetOk("qualifier"); ok { input.Qualifier = aws.String(v.(string)) } @@ -257,6 +266,7 @@ func resourceAwsLambdaPermissionRead(d *schema.ResourceData, meta interface{}) e if stringEquals, ok := statement.Condition["StringEquals"]; ok { d.Set("source_account", stringEquals["AWS:SourceAccount"]) + d.Set("event_source_token", stringEquals["lambda:EventSourceToken"]) } if arnLike, ok := statement.Condition["ArnLike"]; ok { diff --git a/aws/resource_aws_lambda_permission_test.go b/aws/resource_aws_lambda_permission_test.go index e8fd3bd9612..682e9d054b3 100644 --- a/aws/resource_aws_lambda_permission_test.go +++ b/aws/resource_aws_lambda_permission_test.go @@ -49,6 +49,13 @@ func TestLambdaPermissionUnmarshalling(t *testing.T) { v.Statement[0].Condition["StringEquals"]["AWS:SourceAccount"], expectedSourceAccount) } + + expectedEventSourceToken := "test-event-source-token" + if v.Statement[0].Condition["StringEquals"]["lambda:EventSourceToken"] != expectedEventSourceToken { + t.Fatalf("Expected Event Source Token to match (%q != %q)", + v.Statement[0].Condition["StringEquals"]["lambda:EventSourceToken"], + expectedEventSourceToken) + } } func TestLambdaPermissionGetQualifierFromLambdaAliasOrVersionArn_alias(t *testing.T) { @@ -178,6 +185,7 @@ func TestAccAWSLambdaPermission_basic(t *testing.T) { resource.TestCheckResourceAttr("aws_lambda_permission.allow_cloudwatch", "statement_id", "AllowExecutionFromCloudWatch"), resource.TestCheckResourceAttr("aws_lambda_permission.allow_cloudwatch", "qualifier", ""), resource.TestMatchResourceAttr("aws_lambda_permission.allow_cloudwatch", "function_name", funcArnRe), + resource.TestCheckResourceAttr("aws_lambda_permission.allow_cloudwatch", "event_source_token", "test-event-source-token"), ), }, }, @@ -551,6 +559,7 @@ resource "aws_lambda_permission" "allow_cloudwatch" { action = "lambda:InvokeFunction" function_name = "${aws_lambda_function.test_lambda.arn}" principal = "events.amazonaws.com" + event_source_token = "test-event-source-token" } resource "aws_lambda_function" "test_lambda" { @@ -901,7 +910,7 @@ var testLambdaPolicy = []byte(`{ "Statement": [ { "Condition": { - "StringEquals": {"AWS:SourceAccount": "319201112229"}, + "StringEquals": {"AWS:SourceAccount": "319201112229", "lambda:EventSourceToken": "test-event-source-token"}, "ArnLike":{"AWS:SourceArn":"arn:aws:events:eu-west-1:319201112229:rule/RunDaily"} }, "Action": "lambda:InvokeFunction", diff --git a/aws/validators.go b/aws/validators.go index 8d19c976251..f26861d3471 100644 --- a/aws/validators.go +++ b/aws/validators.go @@ -413,6 +413,24 @@ func validateLambdaPermissionAction(v interface{}, k string) (ws []string, error return } +func validateLambdaPermissionEventSourceToken(v interface{}, k string) (ws []string, errors []error) { + // https://docs.aws.amazon.com/lambda/latest/dg/API_AddPermission.html + value := v.(string) + + if len(value) > 256 { + errors = append(errors, fmt.Errorf("%q cannot be longer than 256 characters: %q", k, value)) + } + + pattern := `^[a-zA-Z0-9._\-]+$` + if !regexp.MustCompile(pattern).MatchString(value) { + errors = append(errors, fmt.Errorf( + "%q doesn't comply with restrictions (%q): %q", + k, pattern, value)) + } + + return +} + func validateAwsAccountId(v interface{}, k string) (ws []string, errors []error) { value := v.(string) diff --git a/aws/validators_test.go b/aws/validators_test.go index 94756c1b75e..1c4d3434766 100644 --- a/aws/validators_test.go +++ b/aws/validators_test.go @@ -266,6 +266,32 @@ func TestValidateLambdaPermissionAction(t *testing.T) { } } +func TestValidateLambdaPermissionEventSourceToken(t *testing.T) { + validTokens := []string{ + "amzn1.ask.skill.80c92c86-e6dd-4c4b-8d0d-000000000000", + "test-event-source-token", + strings.Repeat(".", 256), + } + for _, v := range validTokens { + _, errors := validateLambdaPermissionEventSourceToken(v, "event_source_token") + if len(errors) != 0 { + t.Fatalf("%q should be a valid Lambda permission event source token", v) + } + } + + invalidTokens := []string{ + "!", + "test event source token", + strings.Repeat(".", 257), + } + for _, v := range invalidTokens { + _, errors := validateLambdaPermissionEventSourceToken(v, "event_source_token") + if len(errors) == 0 { + t.Fatalf("%q should be an invalid Lambda permission event source token", v) + } + } +} + func TestValidateAwsAccountId(t *testing.T) { validNames := []string{ "123456789012", diff --git a/website/docs/r/lambda_permission.html.markdown b/website/docs/r/lambda_permission.html.markdown index f957ef8ba36..bb1dfe28475 100644 --- a/website/docs/r/lambda_permission.html.markdown +++ b/website/docs/r/lambda_permission.html.markdown @@ -132,6 +132,7 @@ resource "aws_lambda_permission" "lambda_permission" { ## Argument Reference * `action` - (Required) The AWS Lambda action you want to allow in this statement. (e.g. `lambda:InvokeFunction`) + * `event_source_token` - (Optional) The Event Source Token to validate. Used with [Alexa Skills][1]. * `function_name` - (Required) Name of the Lambda function whose resource policy you are updating * `principal` - (Required) The principal who is getting this permission. e.g. `s3.amazonaws.com`, an AWS account ID, or any valid AWS service principal @@ -148,3 +149,5 @@ resource "aws_lambda_permission" "lambda_permission" { [here](http://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-control-access-using-iam-policies-to-invoke-api.html). * `statement_id` - (Optional) A unique statement identifier. By default generated by Terraform. * `statement_id_prefix` - (Optional) A statement identifier prefix. Terraform will generate a unique suffix. Conflicts with `statement_id`. + +[1]: https://developer.amazon.com/docs/custom-skills/host-a-custom-skill-as-an-aws-lambda-function.html#use-aws-cli