From d2a3799158a68ff7fb7f26960619f754c849ad77 Mon Sep 17 00:00:00 2001 From: Radek Simko Date: Mon, 25 Jan 2016 18:24:54 +0000 Subject: [PATCH] provider/aws: Add tests for aws_lambda_permission --- .../resource_aws_lambda_permission_test.go | 640 ++++++++++++++++++ 1 file changed, 640 insertions(+) create mode 100644 builtin/providers/aws/resource_aws_lambda_permission_test.go diff --git a/builtin/providers/aws/resource_aws_lambda_permission_test.go b/builtin/providers/aws/resource_aws_lambda_permission_test.go new file mode 100644 index 000000000..69f85d3e6 --- /dev/null +++ b/builtin/providers/aws/resource_aws_lambda_permission_test.go @@ -0,0 +1,640 @@ +package aws + +import ( + "encoding/json" + "fmt" + "log" + "regexp" + "testing" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/service/lambda" + "github.com/hashicorp/terraform/helper/resource" + "github.com/hashicorp/terraform/terraform" +) + +func TestLambdaPermissionUnmarshalling(t *testing.T) { + v := LambdaPolicy{} + err := json.Unmarshal(testLambdaPolicy, &v) + if err != nil { + t.Fatalf("Expected no error when unmarshalling: %s", err) + } + + expectedSid := "36fe77d9-a4ae-13fb-8beb-5dc6821d5291" + if v.Statement[0].Sid != expectedSid { + t.Fatalf("Expected Sid to match (%q != %q)", v.Statement[0].Sid, expectedSid) + } + + expectedFunctionName := "arn:aws:lambda:eu-west-1:319201112229:function:myCustomFunction" + if v.Statement[0].Resource != expectedFunctionName { + t.Fatalf("Expected function name to match (%q != %q)", v.Statement[0].Resource, expectedFunctionName) + } + + expectedAction := "lambda:InvokeFunction" + if v.Statement[0].Action != expectedAction { + t.Fatalf("Expected Action to match (%q != %q)", v.Statement[0].Action, expectedAction) + } + + expectedPrincipal := "events.amazonaws.com" + if v.Statement[0].Principal["Service"] != expectedPrincipal { + t.Fatalf("Expected Principal to match (%q != %q)", v.Statement[0].Principal["Service"], expectedPrincipal) + } + + expectedSourceAccount := "319201112229" + if v.Statement[0].Condition["StringEquals"]["AWS:SourceAccount"] != expectedSourceAccount { + t.Fatalf("Expected Source Account to match (%q != %q)", + v.Statement[0].Condition["StringEquals"]["AWS:SourceAccount"], + expectedSourceAccount) + } +} + +func TestLambdaPermissionGetQualifierFromLambdaAliasOrVersionArn_alias(t *testing.T) { + arnWithAlias := "arn:aws:lambda:us-west-2:187636751137:function:lambda_function_name:testalias" + expectedQualifier := "testalias" + qualifier, err := getQualifierFromLambdaAliasOrVersionArn(arnWithAlias) + if err != nil { + t.Fatalf("Expected no error when getting qualifier: %s", err) + } + if qualifier != expectedQualifier { + t.Fatalf("Expected qualifier to match (%q != %q)", qualifier, expectedQualifier) + } +} + +func TestLambdaPermissionGetQualifierFromLambdaAliasOrVersionArn_version(t *testing.T) { + arnWithVersion := "arn:aws:lambda:us-west-2:187636751137:function:lambda_function_name:223" + expectedQualifier := "223" + qualifier, err := getQualifierFromLambdaAliasOrVersionArn(arnWithVersion) + if err != nil { + t.Fatalf("Expected no error when getting qualifier: %s", err) + } + if qualifier != expectedQualifier { + t.Fatalf("Expected qualifier to match (%q != %q)", qualifier, expectedQualifier) + } +} + +func TestLambdaPermissionGetQualifierFromLambdaAliasOrVersionArn_invalid(t *testing.T) { + invalidArn := "arn:aws:lambda:us-west-2:187636751137:function:lambda_function_name" + qualifier, err := getQualifierFromLambdaAliasOrVersionArn(invalidArn) + if err == nil { + t.Fatalf("Expected error when getting qualifier") + } + if qualifier != "" { + t.Fatalf("Expected qualifier to be empty (%q)", qualifier) + } + + // with trailing colon + invalidArn = "arn:aws:lambda:us-west-2:187636751137:function:lambda_function_name:" + qualifier, err = getQualifierFromLambdaAliasOrVersionArn(invalidArn) + if err == nil { + t.Fatalf("Expected error when getting qualifier") + } + if qualifier != "" { + t.Fatalf("Expected qualifier to be empty (%q)", qualifier) + } +} + +func TestLambdaPermissionGetFunctionNameFromLambdaArn_invalid(t *testing.T) { + invalidArn := "arn:aws:lambda:us-west-2:187636751137:function:" + fn, err := getFunctionNameFromLambdaArn(invalidArn) + if err == nil { + t.Fatalf("Expected error when parsing invalid ARN (%q)", invalidArn) + } + if fn != "" { + t.Fatalf("Expected empty string when parsing invalid ARN (%q)", invalidArn) + } +} + +func TestLambdaPermissionGetFunctionNameFromLambdaArn_valid(t *testing.T) { + validArn := "arn:aws:lambda:us-west-2:187636751137:function:lambda_function_name" + fn, err := getFunctionNameFromLambdaArn(validArn) + if err != nil { + t.Fatalf("Expected no error (%q): %q", validArn, err) + } + expectedFunctionname := "lambda_function_name" + if fn != expectedFunctionname { + t.Fatalf("Expected Lambda function name to match (%q != %q)", + validArn, expectedFunctionname) + } + + // With qualifier + validArn = "arn:aws:lambda:us-west-2:187636751137:function:lambda_function_name:12" + fn, err = getFunctionNameFromLambdaArn(validArn) + if err != nil { + t.Fatalf("Expected no error (%q): %q", validArn, err) + } + expectedFunctionname = "lambda_function_name" + if fn != expectedFunctionname { + t.Fatalf("Expected Lambda function name to match (%q != %q)", + validArn, expectedFunctionname) + } +} + +func TestAccAWSLambdaPermission_basic(t *testing.T) { + var statement LambdaPolicyStatement + endsWithFuncName := regexp.MustCompile(":function:lambda_function_name_perm$") + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSLambdaPermissionDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccAWSLambdaPermissionConfig, + Check: resource.ComposeTestCheckFunc( + testAccCheckLambdaPermissionExists("aws_lambda_permission.allow_cloudwatch", &statement), + resource.TestCheckResourceAttr("aws_lambda_permission.allow_cloudwatch", "action", "lambda:InvokeFunction"), + resource.TestCheckResourceAttr("aws_lambda_permission.allow_cloudwatch", "principal", "events.amazonaws.com"), + 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", endsWithFuncName), + ), + }, + }, + }) +} + +func TestAccAWSLambdaPermission_withRawFunctionName(t *testing.T) { + var statement LambdaPolicyStatement + endsWithFuncName := regexp.MustCompile(":function:lambda_function_name_perm_raw_func_name$") + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSLambdaPermissionDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccAWSLambdaPermissionConfig_withRawFunctionName, + Check: resource.ComposeTestCheckFunc( + testAccCheckLambdaPermissionExists("aws_lambda_permission.with_raw_func_name", &statement), + resource.TestCheckResourceAttr("aws_lambda_permission.with_raw_func_name", "action", "lambda:InvokeFunction"), + resource.TestCheckResourceAttr("aws_lambda_permission.with_raw_func_name", "principal", "events.amazonaws.com"), + resource.TestCheckResourceAttr("aws_lambda_permission.with_raw_func_name", "statement_id", "AllowExecutionWithRawFuncName"), + resource.TestMatchResourceAttr("aws_lambda_permission.with_raw_func_name", "function_name", endsWithFuncName), + ), + }, + }, + }) +} + +func TestAccAWSLambdaPermission_withQualifier(t *testing.T) { + var statement LambdaPolicyStatement + endsWithFuncName := regexp.MustCompile(":function:lambda_function_name_perm_qualifier$") + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSLambdaPermissionDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccAWSLambdaPermissionConfig_withQualifier, + Check: resource.ComposeTestCheckFunc( + testAccCheckLambdaPermissionExists("aws_lambda_permission.with_qualifier", &statement), + resource.TestCheckResourceAttr("aws_lambda_permission.with_qualifier", "action", "lambda:InvokeFunction"), + resource.TestCheckResourceAttr("aws_lambda_permission.with_qualifier", "principal", "events.amazonaws.com"), + resource.TestCheckResourceAttr("aws_lambda_permission.with_qualifier", "statement_id", "AllowExecutionWithQualifier"), + resource.TestMatchResourceAttr("aws_lambda_permission.with_qualifier", "function_name", endsWithFuncName), + resource.TestCheckResourceAttr("aws_lambda_permission.with_qualifier", "qualifier", "testalias_perm_qualifier"), + ), + }, + }, + }) +} + +func TestAccAWSLambdaPermission_multiplePerms(t *testing.T) { + var firstStatement LambdaPolicyStatement + var firstStatementModified LambdaPolicyStatement + + var secondStatement LambdaPolicyStatement + var secondStatementModified LambdaPolicyStatement + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSLambdaPermissionDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccAWSLambdaPermissionConfig_multiplePerms, + Check: resource.ComposeTestCheckFunc( + // 1st + testAccCheckLambdaPermissionExists("aws_lambda_permission.first", &firstStatement), + resource.TestCheckResourceAttr("aws_lambda_permission.first", "action", "lambda:InvokeFunction"), + resource.TestCheckResourceAttr("aws_lambda_permission.first", "principal", "events.amazonaws.com"), + resource.TestCheckResourceAttr("aws_lambda_permission.first", "statement_id", "AllowExecutionFirst"), + resource.TestMatchResourceAttr("aws_lambda_permission.first", "function_name", + regexp.MustCompile(":function:lambda_function_name_perm_multiperms$")), + // 2nd + testAccCheckLambdaPermissionExists("aws_lambda_permission.second", &firstStatementModified), + resource.TestCheckResourceAttr("aws_lambda_permission.second", "action", "lambda:*"), + resource.TestCheckResourceAttr("aws_lambda_permission.second", "principal", "events.amazonaws.com"), + resource.TestCheckResourceAttr("aws_lambda_permission.second", "statement_id", "AllowExecutionSecond"), + resource.TestMatchResourceAttr("aws_lambda_permission.second", "function_name", + regexp.MustCompile(":function:lambda_function_name_perm_multiperms$")), + ), + }, + resource.TestStep{ + Config: testAccAWSLambdaPermissionConfig_multiplePermsModified, + Check: resource.ComposeTestCheckFunc( + // 1st + testAccCheckLambdaPermissionExists("aws_lambda_permission.first", &secondStatement), + resource.TestCheckResourceAttr("aws_lambda_permission.first", "action", "lambda:InvokeFunction"), + resource.TestCheckResourceAttr("aws_lambda_permission.first", "principal", "events.amazonaws.com"), + resource.TestCheckResourceAttr("aws_lambda_permission.first", "statement_id", "AllowExecutionFirst"), + resource.TestMatchResourceAttr("aws_lambda_permission.first", "function_name", + regexp.MustCompile(":function:lambda_function_name_perm_multiperms$")), + // 2nd + testAccCheckLambdaPermissionExists("aws_lambda_permission.renamed", &secondStatementModified), + resource.TestCheckResourceAttr("aws_lambda_permission.renamed", "action", "lambda:*"), + resource.TestCheckResourceAttr("aws_lambda_permission.renamed", "principal", "events.amazonaws.com"), + resource.TestCheckResourceAttr("aws_lambda_permission.renamed", "statement_id", "AllowExecutionSecond"), + resource.TestMatchResourceAttr("aws_lambda_permission.renamed", "function_name", + regexp.MustCompile(":function:lambda_function_name_perm_multiperms$")), + ), + }, + }, + }) +} + +func TestAccAWSLambdaPermission_withS3(t *testing.T) { + var statement LambdaPolicyStatement + endsWithFuncName := regexp.MustCompile(":function:lambda_function_name_perm_s3$") + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSLambdaPermissionDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccAWSLambdaPermissionConfig_withS3, + Check: resource.ComposeTestCheckFunc( + testAccCheckLambdaPermissionExists("aws_lambda_permission.with_s3", &statement), + resource.TestCheckResourceAttr("aws_lambda_permission.with_s3", "action", "lambda:InvokeFunction"), + resource.TestCheckResourceAttr("aws_lambda_permission.with_s3", "principal", "s3.amazonaws.com"), + resource.TestCheckResourceAttr("aws_lambda_permission.with_s3", "statement_id", "AllowExecutionFromS3"), + resource.TestMatchResourceAttr("aws_lambda_permission.with_s3", "function_name", endsWithFuncName), + resource.TestCheckResourceAttr("aws_lambda_permission.with_s3", "source_arn", "arn:aws:s3:::tf-acc-towards-lambda"), + ), + }, + }, + }) +} + +func TestAccAWSLambdaPermission_withSNS(t *testing.T) { + var statement LambdaPolicyStatement + endsWithFuncName := regexp.MustCompile(":function:lambda_function_name_perm_sns$") + endsWithTopicName := regexp.MustCompile(":tf-acc-user-updates-topic$") + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSLambdaPermissionDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccAWSLambdaPermissionConfig_withSNS, + Check: resource.ComposeTestCheckFunc( + testAccCheckLambdaPermissionExists("aws_lambda_permission.with_sns", &statement), + resource.TestCheckResourceAttr("aws_lambda_permission.with_sns", "action", "lambda:InvokeFunction"), + resource.TestCheckResourceAttr("aws_lambda_permission.with_sns", "principal", "sns.amazonaws.com"), + resource.TestCheckResourceAttr("aws_lambda_permission.with_sns", "statement_id", "AllowExecutionFromSNS"), + resource.TestMatchResourceAttr("aws_lambda_permission.with_sns", "function_name", endsWithFuncName), + resource.TestMatchResourceAttr("aws_lambda_permission.with_sns", "source_arn", endsWithTopicName), + ), + }, + }, + }) +} + +func testAccCheckLambdaPermissionExists(n string, statement *LambdaPolicyStatement) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[n] + if !ok { + return fmt.Errorf("Not found: %s", n) + } + + conn := testAccProvider.Meta().(*AWSClient).lambdaconn + params := &lambda.GetPolicyInput{ + FunctionName: aws.String(rs.Primary.Attributes["function_name"]), + } + if v, ok := rs.Primary.Attributes["qualifier"]; ok { + params.Qualifier = aws.String(v) + } + + log.Printf("[DEBUG] Looking for Lambda permission: %s", *params) + resp, err := conn.GetPolicy(params) + if err != nil { + return fmt.Errorf("Lambda policy not found: %q", err) + } + + if resp.Policy == nil { + return fmt.Errorf("Received Lambda policy is empty") + } + + policyInBytes := []byte(*resp.Policy) + policy := LambdaPolicy{} + err = json.Unmarshal(policyInBytes, &policy) + if err != nil { + return fmt.Errorf("Error unmarshalling Lambda policy: %s", err) + } + + foundStatement, err := findLambdaPolicyStatementById(&policy, rs.Primary.ID) + if err != nil { + return err + } + + *statement = *foundStatement + + return nil + } +} + +func testAccCheckAWSLambdaPermissionDestroy(s *terraform.State) error { + conn := testAccProvider.Meta().(*AWSClient).lambdaconn + + for _, rs := range s.RootModule().Resources { + if rs.Type != "aws_lambda_permission" { + continue + } + + params := &lambda.GetPolicyInput{ + FunctionName: aws.String(rs.Primary.Attributes["function_name"]), + } + if v, ok := rs.Primary.Attributes["qualifier"]; ok { + params.Qualifier = aws.String(v) + } + + resp, err := conn.GetPolicy(params) + if err == nil { + // No permissions should exist at this point + return fmt.Errorf("Lambda Permission still exists: %s\n%s", + rs.Primary.ID, *resp.Policy) + } + } + + return nil +} + +var testAccAWSLambdaPermissionConfig = ` +resource "aws_lambda_permission" "allow_cloudwatch" { + statement_id = "AllowExecutionFromCloudWatch" + action = "lambda:InvokeFunction" + function_name = "${aws_lambda_function.test_lambda.arn}" + principal = "events.amazonaws.com" +} + +resource "aws_lambda_function" "test_lambda" { + filename = "test-fixtures/lambdatest.zip" + function_name = "lambda_function_name_perm" + role = "${aws_iam_role.iam_for_lambda.arn}" + handler = "exports.handler" +} + +resource "aws_iam_role" "iam_for_lambda" { + name = "iam_for_lambda_perm" + assume_role_policy = <