github.com/minamijoyo/terraform@v0.7.8-0.20161029001309-18b3736ba44b/builtin/providers/aws/resource_aws_cloudtrail_test.go (about)

     1  package aws
     2  
     3  import (
     4  	"fmt"
     5  	"log"
     6  	"testing"
     7  
     8  	"github.com/aws/aws-sdk-go/aws"
     9  	"github.com/aws/aws-sdk-go/service/cloudtrail"
    10  	"github.com/hashicorp/terraform/helper/acctest"
    11  	"github.com/hashicorp/terraform/helper/resource"
    12  	"github.com/hashicorp/terraform/terraform"
    13  )
    14  
    15  func TestAccAWSCloudTrail_basic(t *testing.T) {
    16  	var trail cloudtrail.Trail
    17  	cloudTrailRandInt := acctest.RandInt()
    18  
    19  	resource.Test(t, resource.TestCase{
    20  		PreCheck:     func() { testAccPreCheck(t) },
    21  		Providers:    testAccProviders,
    22  		CheckDestroy: testAccCheckAWSCloudTrailDestroy,
    23  		Steps: []resource.TestStep{
    24  			resource.TestStep{
    25  				Config: testAccAWSCloudTrailConfig(cloudTrailRandInt),
    26  				Check: resource.ComposeTestCheckFunc(
    27  					testAccCheckCloudTrailExists("aws_cloudtrail.foobar", &trail),
    28  					resource.TestCheckResourceAttr("aws_cloudtrail.foobar", "include_global_service_events", "true"),
    29  					testAccCheckCloudTrailLogValidationEnabled("aws_cloudtrail.foobar", false, &trail),
    30  					testAccCheckCloudTrailKmsKeyIdEquals("aws_cloudtrail.foobar", "", &trail),
    31  				),
    32  			},
    33  			resource.TestStep{
    34  				Config: testAccAWSCloudTrailConfigModified(cloudTrailRandInt),
    35  				Check: resource.ComposeTestCheckFunc(
    36  					testAccCheckCloudTrailExists("aws_cloudtrail.foobar", &trail),
    37  					resource.TestCheckResourceAttr("aws_cloudtrail.foobar", "s3_key_prefix", "/prefix"),
    38  					resource.TestCheckResourceAttr("aws_cloudtrail.foobar", "include_global_service_events", "false"),
    39  					testAccCheckCloudTrailLogValidationEnabled("aws_cloudtrail.foobar", false, &trail),
    40  					testAccCheckCloudTrailKmsKeyIdEquals("aws_cloudtrail.foobar", "", &trail),
    41  				),
    42  			},
    43  		},
    44  	})
    45  }
    46  
    47  func TestAccAWSCloudTrail_enable_logging(t *testing.T) {
    48  	var trail cloudtrail.Trail
    49  	cloudTrailRandInt := acctest.RandInt()
    50  
    51  	resource.Test(t, resource.TestCase{
    52  		PreCheck:     func() { testAccPreCheck(t) },
    53  		Providers:    testAccProviders,
    54  		CheckDestroy: testAccCheckAWSCloudTrailDestroy,
    55  		Steps: []resource.TestStep{
    56  			resource.TestStep{
    57  				Config: testAccAWSCloudTrailConfig(cloudTrailRandInt),
    58  				Check: resource.ComposeTestCheckFunc(
    59  					testAccCheckCloudTrailExists("aws_cloudtrail.foobar", &trail),
    60  					// AWS will create the trail with logging turned off.
    61  					// Test that "enable_logging" default works.
    62  					testAccCheckCloudTrailLoggingEnabled("aws_cloudtrail.foobar", true, &trail),
    63  					testAccCheckCloudTrailLogValidationEnabled("aws_cloudtrail.foobar", false, &trail),
    64  					testAccCheckCloudTrailKmsKeyIdEquals("aws_cloudtrail.foobar", "", &trail),
    65  				),
    66  			},
    67  			resource.TestStep{
    68  				Config: testAccAWSCloudTrailConfigModified(cloudTrailRandInt),
    69  				Check: resource.ComposeTestCheckFunc(
    70  					testAccCheckCloudTrailExists("aws_cloudtrail.foobar", &trail),
    71  					testAccCheckCloudTrailLoggingEnabled("aws_cloudtrail.foobar", false, &trail),
    72  					testAccCheckCloudTrailLogValidationEnabled("aws_cloudtrail.foobar", false, &trail),
    73  					testAccCheckCloudTrailKmsKeyIdEquals("aws_cloudtrail.foobar", "", &trail),
    74  				),
    75  			},
    76  			resource.TestStep{
    77  				Config: testAccAWSCloudTrailConfig(cloudTrailRandInt),
    78  				Check: resource.ComposeTestCheckFunc(
    79  					testAccCheckCloudTrailExists("aws_cloudtrail.foobar", &trail),
    80  					testAccCheckCloudTrailLoggingEnabled("aws_cloudtrail.foobar", true, &trail),
    81  					testAccCheckCloudTrailLogValidationEnabled("aws_cloudtrail.foobar", false, &trail),
    82  					testAccCheckCloudTrailKmsKeyIdEquals("aws_cloudtrail.foobar", "", &trail),
    83  				),
    84  			},
    85  		},
    86  	})
    87  }
    88  
    89  func TestAccAWSCloudTrail_is_multi_region(t *testing.T) {
    90  	var trail cloudtrail.Trail
    91  	cloudTrailRandInt := acctest.RandInt()
    92  
    93  	resource.Test(t, resource.TestCase{
    94  		PreCheck:     func() { testAccPreCheck(t) },
    95  		Providers:    testAccProviders,
    96  		CheckDestroy: testAccCheckAWSCloudTrailDestroy,
    97  		Steps: []resource.TestStep{
    98  			resource.TestStep{
    99  				Config: testAccAWSCloudTrailConfig(cloudTrailRandInt),
   100  				Check: resource.ComposeTestCheckFunc(
   101  					testAccCheckCloudTrailExists("aws_cloudtrail.foobar", &trail),
   102  					resource.TestCheckResourceAttr("aws_cloudtrail.foobar", "is_multi_region_trail", "false"),
   103  					testAccCheckCloudTrailLogValidationEnabled("aws_cloudtrail.foobar", false, &trail),
   104  					testAccCheckCloudTrailKmsKeyIdEquals("aws_cloudtrail.foobar", "", &trail),
   105  				),
   106  			},
   107  			resource.TestStep{
   108  				Config: testAccAWSCloudTrailConfigMultiRegion(cloudTrailRandInt),
   109  				Check: resource.ComposeTestCheckFunc(
   110  					testAccCheckCloudTrailExists("aws_cloudtrail.foobar", &trail),
   111  					resource.TestCheckResourceAttr("aws_cloudtrail.foobar", "is_multi_region_trail", "true"),
   112  					testAccCheckCloudTrailLogValidationEnabled("aws_cloudtrail.foobar", false, &trail),
   113  					testAccCheckCloudTrailKmsKeyIdEquals("aws_cloudtrail.foobar", "", &trail),
   114  				),
   115  			},
   116  			resource.TestStep{
   117  				Config: testAccAWSCloudTrailConfig(cloudTrailRandInt),
   118  				Check: resource.ComposeTestCheckFunc(
   119  					testAccCheckCloudTrailExists("aws_cloudtrail.foobar", &trail),
   120  					resource.TestCheckResourceAttr("aws_cloudtrail.foobar", "is_multi_region_trail", "false"),
   121  					testAccCheckCloudTrailLogValidationEnabled("aws_cloudtrail.foobar", false, &trail),
   122  					testAccCheckCloudTrailKmsKeyIdEquals("aws_cloudtrail.foobar", "", &trail),
   123  				),
   124  			},
   125  		},
   126  	})
   127  }
   128  
   129  func TestAccAWSCloudTrail_logValidation(t *testing.T) {
   130  	var trail cloudtrail.Trail
   131  	cloudTrailRandInt := acctest.RandInt()
   132  
   133  	// TODO: Add test for KMS Key ID
   134  	// once https://github.com/hashicorp/terraform/pull/3928 is merged
   135  	resource.Test(t, resource.TestCase{
   136  		PreCheck:     func() { testAccPreCheck(t) },
   137  		Providers:    testAccProviders,
   138  		CheckDestroy: testAccCheckAWSCloudTrailDestroy,
   139  		Steps: []resource.TestStep{
   140  			resource.TestStep{
   141  				Config: testAccAWSCloudTrailConfig_logValidation(cloudTrailRandInt),
   142  				Check: resource.ComposeTestCheckFunc(
   143  					testAccCheckCloudTrailExists("aws_cloudtrail.foobar", &trail),
   144  					resource.TestCheckResourceAttr("aws_cloudtrail.foobar", "s3_key_prefix", ""),
   145  					resource.TestCheckResourceAttr("aws_cloudtrail.foobar", "include_global_service_events", "true"),
   146  					testAccCheckCloudTrailLogValidationEnabled("aws_cloudtrail.foobar", true, &trail),
   147  					testAccCheckCloudTrailKmsKeyIdEquals("aws_cloudtrail.foobar", "", &trail),
   148  				),
   149  			},
   150  			resource.TestStep{
   151  				Config: testAccAWSCloudTrailConfig_logValidationModified(cloudTrailRandInt),
   152  				Check: resource.ComposeTestCheckFunc(
   153  					testAccCheckCloudTrailExists("aws_cloudtrail.foobar", &trail),
   154  					resource.TestCheckResourceAttr("aws_cloudtrail.foobar", "s3_key_prefix", ""),
   155  					resource.TestCheckResourceAttr("aws_cloudtrail.foobar", "include_global_service_events", "true"),
   156  					testAccCheckCloudTrailLogValidationEnabled("aws_cloudtrail.foobar", false, &trail),
   157  					testAccCheckCloudTrailKmsKeyIdEquals("aws_cloudtrail.foobar", "", &trail),
   158  				),
   159  			},
   160  		},
   161  	})
   162  }
   163  
   164  func TestAccAWSCloudTrail_tags(t *testing.T) {
   165  	var trail cloudtrail.Trail
   166  	var trailTags []*cloudtrail.Tag
   167  	var trailTagsModified []*cloudtrail.Tag
   168  	cloudTrailRandInt := acctest.RandInt()
   169  
   170  	resource.Test(t, resource.TestCase{
   171  		PreCheck:     func() { testAccPreCheck(t) },
   172  		Providers:    testAccProviders,
   173  		CheckDestroy: testAccCheckAWSCloudTrailDestroy,
   174  		Steps: []resource.TestStep{
   175  			resource.TestStep{
   176  				Config: testAccAWSCloudTrailConfig_tags(cloudTrailRandInt),
   177  				Check: resource.ComposeTestCheckFunc(
   178  					testAccCheckCloudTrailExists("aws_cloudtrail.foobar", &trail),
   179  					resource.TestCheckResourceAttr("aws_cloudtrail.foobar", "tags.%", "2"),
   180  					testAccCheckCloudTrailLoadTags(&trail, &trailTags),
   181  					testAccCheckCloudTrailCheckTags(&trailTags, map[string]string{"Foo": "moo", "Pooh": "hi"}),
   182  					testAccCheckCloudTrailLogValidationEnabled("aws_cloudtrail.foobar", false, &trail),
   183  					testAccCheckCloudTrailKmsKeyIdEquals("aws_cloudtrail.foobar", "", &trail),
   184  				),
   185  			},
   186  			resource.TestStep{
   187  				Config: testAccAWSCloudTrailConfig_tagsModified(cloudTrailRandInt),
   188  				Check: resource.ComposeTestCheckFunc(
   189  					testAccCheckCloudTrailExists("aws_cloudtrail.foobar", &trail),
   190  					resource.TestCheckResourceAttr("aws_cloudtrail.foobar", "tags.%", "3"),
   191  					testAccCheckCloudTrailLoadTags(&trail, &trailTagsModified),
   192  					testAccCheckCloudTrailCheckTags(&trailTagsModified, map[string]string{"Foo": "moo", "Moo": "boom", "Pooh": "hi"}),
   193  					testAccCheckCloudTrailLogValidationEnabled("aws_cloudtrail.foobar", false, &trail),
   194  					testAccCheckCloudTrailKmsKeyIdEquals("aws_cloudtrail.foobar", "", &trail),
   195  				),
   196  			},
   197  			resource.TestStep{
   198  				Config: testAccAWSCloudTrailConfig_tagsModifiedAgain(cloudTrailRandInt),
   199  				Check: resource.ComposeTestCheckFunc(
   200  					testAccCheckCloudTrailExists("aws_cloudtrail.foobar", &trail),
   201  					resource.TestCheckResourceAttr("aws_cloudtrail.foobar", "tags.%", "0"),
   202  					testAccCheckCloudTrailLoadTags(&trail, &trailTagsModified),
   203  					testAccCheckCloudTrailCheckTags(&trailTagsModified, map[string]string{}),
   204  					testAccCheckCloudTrailLogValidationEnabled("aws_cloudtrail.foobar", false, &trail),
   205  					testAccCheckCloudTrailKmsKeyIdEquals("aws_cloudtrail.foobar", "", &trail),
   206  				),
   207  			},
   208  		},
   209  	})
   210  }
   211  
   212  func testAccCheckCloudTrailExists(n string, trail *cloudtrail.Trail) resource.TestCheckFunc {
   213  	return func(s *terraform.State) error {
   214  		rs, ok := s.RootModule().Resources[n]
   215  		if !ok {
   216  			return fmt.Errorf("Not found: %s", n)
   217  		}
   218  
   219  		conn := testAccProvider.Meta().(*AWSClient).cloudtrailconn
   220  		params := cloudtrail.DescribeTrailsInput{
   221  			TrailNameList: []*string{aws.String(rs.Primary.ID)},
   222  		}
   223  		resp, err := conn.DescribeTrails(&params)
   224  		if err != nil {
   225  			return err
   226  		}
   227  		if len(resp.TrailList) == 0 {
   228  			return fmt.Errorf("Trail not found")
   229  		}
   230  		*trail = *resp.TrailList[0]
   231  
   232  		return nil
   233  	}
   234  }
   235  
   236  func testAccCheckCloudTrailLoggingEnabled(n string, desired bool, trail *cloudtrail.Trail) resource.TestCheckFunc {
   237  	return func(s *terraform.State) error {
   238  		rs, ok := s.RootModule().Resources[n]
   239  		if !ok {
   240  			return fmt.Errorf("Not found: %s", n)
   241  		}
   242  
   243  		conn := testAccProvider.Meta().(*AWSClient).cloudtrailconn
   244  		params := cloudtrail.GetTrailStatusInput{
   245  			Name: aws.String(rs.Primary.ID),
   246  		}
   247  		resp, err := conn.GetTrailStatus(&params)
   248  
   249  		if err != nil {
   250  			return err
   251  		}
   252  		if *resp.IsLogging != desired {
   253  			return fmt.Errorf("Expected logging status %t, given %t", desired, *resp.IsLogging)
   254  		}
   255  
   256  		return nil
   257  	}
   258  }
   259  
   260  func testAccCheckCloudTrailLogValidationEnabled(n string, desired bool, trail *cloudtrail.Trail) resource.TestCheckFunc {
   261  	return func(s *terraform.State) error {
   262  		rs, ok := s.RootModule().Resources[n]
   263  		if !ok {
   264  			return fmt.Errorf("Not found: %s", n)
   265  		}
   266  
   267  		if trail.LogFileValidationEnabled == nil {
   268  			return fmt.Errorf("No LogFileValidationEnabled attribute present in trail: %s", trail)
   269  		}
   270  
   271  		if *trail.LogFileValidationEnabled != desired {
   272  			return fmt.Errorf("Expected log validation status %t, given %t", desired,
   273  				*trail.LogFileValidationEnabled)
   274  		}
   275  
   276  		// local state comparison
   277  		enabled, ok := rs.Primary.Attributes["enable_log_file_validation"]
   278  		if !ok {
   279  			return fmt.Errorf("No enable_log_file_validation attribute defined for %s, expected %t",
   280  				n, desired)
   281  		}
   282  		desiredInString := fmt.Sprintf("%t", desired)
   283  		if enabled != desiredInString {
   284  			return fmt.Errorf("Expected log validation status %s, saved %s", desiredInString, enabled)
   285  		}
   286  
   287  		return nil
   288  	}
   289  }
   290  
   291  func testAccCheckCloudTrailKmsKeyIdEquals(n string, desired string, trail *cloudtrail.Trail) resource.TestCheckFunc {
   292  	return func(s *terraform.State) error {
   293  		rs, ok := s.RootModule().Resources[n]
   294  		if !ok {
   295  			return fmt.Errorf("Not found: %s", n)
   296  		}
   297  
   298  		if desired != "" && trail.KmsKeyId == nil {
   299  			return fmt.Errorf("No KmsKeyId attribute present in trail: %s, expected %s",
   300  				trail, desired)
   301  		}
   302  
   303  		// work around string pointer
   304  		var kmsKeyIdInString string
   305  		if trail.KmsKeyId == nil {
   306  			kmsKeyIdInString = ""
   307  		} else {
   308  			kmsKeyIdInString = *trail.KmsKeyId
   309  		}
   310  
   311  		if kmsKeyIdInString != desired {
   312  			return fmt.Errorf("Expected KMS Key ID %q to equal %q",
   313  				*trail.KmsKeyId, desired)
   314  		}
   315  
   316  		kmsKeyId, ok := rs.Primary.Attributes["kms_key_id"]
   317  		if desired != "" && !ok {
   318  			return fmt.Errorf("No kms_key_id attribute defined for %s", n)
   319  		}
   320  		if kmsKeyId != desired {
   321  			return fmt.Errorf("Expected KMS Key ID %q, saved %q", desired, kmsKeyId)
   322  		}
   323  
   324  		return nil
   325  	}
   326  }
   327  
   328  func testAccCheckAWSCloudTrailDestroy(s *terraform.State) error {
   329  	conn := testAccProvider.Meta().(*AWSClient).cloudtrailconn
   330  
   331  	for _, rs := range s.RootModule().Resources {
   332  		if rs.Type != "aws_cloudtrail" {
   333  			continue
   334  		}
   335  
   336  		params := cloudtrail.DescribeTrailsInput{
   337  			TrailNameList: []*string{aws.String(rs.Primary.ID)},
   338  		}
   339  
   340  		resp, err := conn.DescribeTrails(&params)
   341  
   342  		if err == nil {
   343  			if len(resp.TrailList) != 0 &&
   344  				*resp.TrailList[0].Name == rs.Primary.ID {
   345  				return fmt.Errorf("CloudTrail still exists: %s", rs.Primary.ID)
   346  			}
   347  		}
   348  	}
   349  
   350  	return nil
   351  }
   352  
   353  func testAccCheckCloudTrailLoadTags(trail *cloudtrail.Trail, tags *[]*cloudtrail.Tag) resource.TestCheckFunc {
   354  	return func(s *terraform.State) error {
   355  		conn := testAccProvider.Meta().(*AWSClient).cloudtrailconn
   356  		input := cloudtrail.ListTagsInput{
   357  			ResourceIdList: []*string{trail.TrailARN},
   358  		}
   359  		out, err := conn.ListTags(&input)
   360  		if err != nil {
   361  			return err
   362  		}
   363  		log.Printf("[DEBUG] Received CloudTrail tags during test: %s", out)
   364  		if len(out.ResourceTagList) > 0 {
   365  			*tags = out.ResourceTagList[0].TagsList
   366  		}
   367  		log.Printf("[DEBUG] Loading CloudTrail tags into a var: %s", *tags)
   368  		return nil
   369  	}
   370  }
   371  
   372  func testAccAWSCloudTrailConfig(cloudTrailRandInt int) string {
   373  	return fmt.Sprintf(`
   374  resource "aws_cloudtrail" "foobar" {
   375      name = "tf-trail-foobar-%d"
   376      s3_bucket_name = "${aws_s3_bucket.foo.id}"
   377  }
   378  
   379  resource "aws_s3_bucket" "foo" {
   380  	bucket = "tf-test-trail-%d"
   381  	force_destroy = true
   382  	policy = <<POLICY
   383  {
   384  	"Version": "2012-10-17",
   385  	"Statement": [
   386  		{
   387  			"Sid": "AWSCloudTrailAclCheck",
   388  			"Effect": "Allow",
   389  			"Principal": "*",
   390  			"Action": "s3:GetBucketAcl",
   391  			"Resource": "arn:aws:s3:::tf-test-trail-%d"
   392  		},
   393  		{
   394  			"Sid": "AWSCloudTrailWrite",
   395  			"Effect": "Allow",
   396  			"Principal": "*",
   397  			"Action": "s3:PutObject",
   398  			"Resource": "arn:aws:s3:::tf-test-trail-%d/*",
   399  			"Condition": {
   400  				"StringEquals": {
   401  					"s3:x-amz-acl": "bucket-owner-full-control"
   402  				}
   403  			}
   404  		}
   405  	]
   406  }
   407  POLICY
   408  }
   409  `, cloudTrailRandInt, cloudTrailRandInt, cloudTrailRandInt, cloudTrailRandInt)
   410  }
   411  
   412  func testAccAWSCloudTrailConfigModified(cloudTrailRandInt int) string {
   413  	return fmt.Sprintf(`
   414  resource "aws_cloudtrail" "foobar" {
   415      name = "tf-trail-foobar-%d"
   416      s3_bucket_name = "${aws_s3_bucket.foo.id}"
   417      s3_key_prefix = "/prefix"
   418      include_global_service_events = false
   419      enable_logging = false
   420  }
   421  
   422  resource "aws_s3_bucket" "foo" {
   423  	bucket = "tf-test-trail-%d"
   424  	force_destroy = true
   425  	policy = <<POLICY
   426  {
   427  	"Version": "2012-10-17",
   428  	"Statement": [
   429  		{
   430  			"Sid": "AWSCloudTrailAclCheck",
   431  			"Effect": "Allow",
   432  			"Principal": "*",
   433  			"Action": "s3:GetBucketAcl",
   434  			"Resource": "arn:aws:s3:::tf-test-trail-%d"
   435  		},
   436  		{
   437  			"Sid": "AWSCloudTrailWrite",
   438  			"Effect": "Allow",
   439  			"Principal": "*",
   440  			"Action": "s3:PutObject",
   441  			"Resource": "arn:aws:s3:::tf-test-trail-%d/*",
   442  			"Condition": {
   443  				"StringEquals": {
   444  					"s3:x-amz-acl": "bucket-owner-full-control"
   445  				}
   446  			}
   447  		}
   448  	]
   449  }
   450  POLICY
   451  }
   452  `, cloudTrailRandInt, cloudTrailRandInt, cloudTrailRandInt, cloudTrailRandInt)
   453  }
   454  
   455  func testAccAWSCloudTrailConfigMultiRegion(cloudTrailRandInt int) string {
   456  	return fmt.Sprintf(`
   457  resource "aws_cloudtrail" "foobar" {
   458      name = "tf-trail-foobar-%d"
   459      s3_bucket_name = "${aws_s3_bucket.foo.id}"
   460      is_multi_region_trail = true
   461  }
   462  
   463  resource "aws_s3_bucket" "foo" {
   464  	bucket = "tf-test-trail-%d"
   465  	force_destroy = true
   466  	policy = <<POLICY
   467  {
   468  	"Version": "2012-10-17",
   469  	"Statement": [
   470  		{
   471  			"Sid": "AWSCloudTrailAclCheck",
   472  			"Effect": "Allow",
   473  			"Principal": "*",
   474  			"Action": "s3:GetBucketAcl",
   475  			"Resource": "arn:aws:s3:::tf-test-trail-%d"
   476  		},
   477  		{
   478  			"Sid": "AWSCloudTrailWrite",
   479  			"Effect": "Allow",
   480  			"Principal": "*",
   481  			"Action": "s3:PutObject",
   482  			"Resource": "arn:aws:s3:::tf-test-trail-%d/*",
   483  			"Condition": {
   484  				"StringEquals": {
   485  					"s3:x-amz-acl": "bucket-owner-full-control"
   486  				}
   487  			}
   488  		}
   489  	]
   490  }
   491  POLICY
   492  }
   493  `, cloudTrailRandInt, cloudTrailRandInt, cloudTrailRandInt, cloudTrailRandInt)
   494  }
   495  
   496  func testAccAWSCloudTrailConfig_logValidation(cloudTrailRandInt int) string {
   497  	return fmt.Sprintf(`
   498  resource "aws_cloudtrail" "foobar" {
   499      name = "tf-acc-trail-log-validation-test-%d"
   500      s3_bucket_name = "${aws_s3_bucket.foo.id}"
   501      is_multi_region_trail = true
   502      include_global_service_events = true
   503      enable_log_file_validation = true
   504  }
   505  
   506  resource "aws_s3_bucket" "foo" {
   507  	bucket = "tf-test-trail-%d"
   508  	force_destroy = true
   509  	policy = <<POLICY
   510  {
   511  	"Version": "2012-10-17",
   512  	"Statement": [
   513  		{
   514  			"Sid": "AWSCloudTrailAclCheck",
   515  			"Effect": "Allow",
   516  			"Principal": "*",
   517  			"Action": "s3:GetBucketAcl",
   518  			"Resource": "arn:aws:s3:::tf-test-trail-%d"
   519  		},
   520  		{
   521  			"Sid": "AWSCloudTrailWrite",
   522  			"Effect": "Allow",
   523  			"Principal": "*",
   524  			"Action": "s3:PutObject",
   525  			"Resource": "arn:aws:s3:::tf-test-trail-%d/*",
   526  			"Condition": {
   527  				"StringEquals": {
   528  					"s3:x-amz-acl": "bucket-owner-full-control"
   529  				}
   530  			}
   531  		}
   532  	]
   533  }
   534  POLICY
   535  }
   536  `, cloudTrailRandInt, cloudTrailRandInt, cloudTrailRandInt, cloudTrailRandInt)
   537  }
   538  
   539  func testAccAWSCloudTrailConfig_logValidationModified(cloudTrailRandInt int) string {
   540  	return fmt.Sprintf(`
   541  resource "aws_cloudtrail" "foobar" {
   542      name = "tf-acc-trail-log-validation-test-%d"
   543      s3_bucket_name = "${aws_s3_bucket.foo.id}"
   544      include_global_service_events = true
   545  }
   546  
   547  resource "aws_s3_bucket" "foo" {
   548  	bucket = "tf-test-trail-%d"
   549  	force_destroy = true
   550  	policy = <<POLICY
   551  {
   552  	"Version": "2012-10-17",
   553  	"Statement": [
   554  		{
   555  			"Sid": "AWSCloudTrailAclCheck",
   556  			"Effect": "Allow",
   557  			"Principal": "*",
   558  			"Action": "s3:GetBucketAcl",
   559  			"Resource": "arn:aws:s3:::tf-test-trail-%d"
   560  		},
   561  		{
   562  			"Sid": "AWSCloudTrailWrite",
   563  			"Effect": "Allow",
   564  			"Principal": "*",
   565  			"Action": "s3:PutObject",
   566  			"Resource": "arn:aws:s3:::tf-test-trail-%d/*",
   567  			"Condition": {
   568  				"StringEquals": {
   569  					"s3:x-amz-acl": "bucket-owner-full-control"
   570  				}
   571  			}
   572  		}
   573  	]
   574  }
   575  POLICY
   576  }
   577  `, cloudTrailRandInt, cloudTrailRandInt, cloudTrailRandInt, cloudTrailRandInt)
   578  }
   579  
   580  var testAccAWSCloudTrailConfig_tags_tpl = `
   581  resource "aws_cloudtrail" "foobar" {
   582      name = "tf-acc-trail-log-validation-test-%d"
   583      s3_bucket_name = "${aws_s3_bucket.foo.id}"
   584      %s
   585  }
   586  
   587  resource "aws_s3_bucket" "foo" {
   588  	bucket = "tf-test-trail-%d"
   589  	force_destroy = true
   590  	policy = <<POLICY
   591  {
   592  	"Version": "2012-10-17",
   593  	"Statement": [
   594  		{
   595  			"Sid": "AWSCloudTrailAclCheck",
   596  			"Effect": "Allow",
   597  			"Principal": "*",
   598  			"Action": "s3:GetBucketAcl",
   599  			"Resource": "arn:aws:s3:::tf-test-trail-%d"
   600  		},
   601  		{
   602  			"Sid": "AWSCloudTrailWrite",
   603  			"Effect": "Allow",
   604  			"Principal": "*",
   605  			"Action": "s3:PutObject",
   606  			"Resource": "arn:aws:s3:::tf-test-trail-%d/*",
   607  			"Condition": {
   608  				"StringEquals": {
   609  					"s3:x-amz-acl": "bucket-owner-full-control"
   610  				}
   611  			}
   612  		}
   613  	]
   614  }
   615  POLICY
   616  }
   617  `
   618  
   619  func testAccAWSCloudTrailConfig_tags(cloudTrailRandInt int) string {
   620  	tagsString := `tags {
   621  		Foo = "moo"
   622  		Pooh = "hi"
   623  	}`
   624  	return fmt.Sprintf(testAccAWSCloudTrailConfig_tags_tpl,
   625  		cloudTrailRandInt,
   626  		tagsString,
   627  		cloudTrailRandInt,
   628  		cloudTrailRandInt,
   629  		cloudTrailRandInt)
   630  }
   631  
   632  func testAccAWSCloudTrailConfig_tagsModified(cloudTrailRandInt int) string {
   633  	tagsString := `tags {
   634  		Foo = "moo"
   635  		Pooh = "hi"
   636  		Moo = "boom"
   637  	}`
   638  	return fmt.Sprintf(testAccAWSCloudTrailConfig_tags_tpl,
   639  		cloudTrailRandInt,
   640  		tagsString,
   641  		cloudTrailRandInt,
   642  		cloudTrailRandInt,
   643  		cloudTrailRandInt)
   644  }
   645  
   646  func testAccAWSCloudTrailConfig_tagsModifiedAgain(cloudTrailRandInt int) string {
   647  	return fmt.Sprintf(testAccAWSCloudTrailConfig_tags_tpl,
   648  		cloudTrailRandInt, "", cloudTrailRandInt, cloudTrailRandInt, cloudTrailRandInt)
   649  }