|
1 | 1 | package test
|
2 | 2 |
|
3 | 3 | import (
|
| 4 | + "fmt" |
4 | 5 | "testing"
|
5 | 6 |
|
| 7 | + "github.com/aws/aws-sdk-go/service/s3" |
6 | 8 | "github.com/chanzuckerberg/cztack/testutil"
|
| 9 | + "github.com/gruntwork-io/terratest/modules/aws" |
7 | 10 | "github.com/gruntwork-io/terratest/modules/terraform"
|
| 11 | + "github.com/stretchr/testify/require" |
8 | 12 | )
|
9 | 13 |
|
10 |
| -func TestPrivateBucket(t *testing.T) { |
| 14 | +func TestPrivateBucketDefaults(t *testing.T) { |
11 | 15 |
|
12 |
| - project := testutil.UniqueId() |
13 |
| - env := testutil.UniqueId() |
14 |
| - service := testutil.UniqueId() |
15 |
| - owner := testutil.UniqueId() |
| 16 | + test := &testutil.Test{ |
| 17 | + Options: func(t *testing.T) *terraform.Options { |
| 18 | + project := testutil.UniqueId() |
| 19 | + env := testutil.UniqueId() |
| 20 | + service := testutil.UniqueId() |
| 21 | + owner := testutil.UniqueId() |
16 | 22 |
|
17 |
| - bucketName := testutil.UniqueId() |
| 23 | + bucketName := testutil.UniqueId() |
18 | 24 |
|
19 |
| - options := testutil.Options( |
20 |
| - testutil.DefaultRegion, |
21 |
| - map[string]interface{}{ |
22 |
| - "project": project, |
23 |
| - "env": env, |
24 |
| - "service": service, |
25 |
| - "owner": owner, |
| 25 | + return testutil.Options( |
| 26 | + testutil.DefaultRegion, |
| 27 | + map[string]interface{}{ |
| 28 | + "project": project, |
| 29 | + "env": env, |
| 30 | + "service": service, |
| 31 | + "owner": owner, |
26 | 32 |
|
27 |
| - "bucket_name": bucketName, |
| 33 | + "bucket_name": bucketName, |
| 34 | + }, |
| 35 | + ) |
28 | 36 | },
|
29 |
| - ) |
30 | 37 |
|
31 |
| - defer terraform.Destroy(t, options) |
32 |
| - testutil.Run(t, options) |
| 38 | + Validate: func(t *testing.T, options *terraform.Options) { |
| 39 | + r := require.New(t) |
| 40 | + region := options.EnvVars["AWS_DEFAULT_REGION"] |
| 41 | + bucket := options.Vars["bucket_name"].(string) |
| 42 | + outputs := terraform.OutputAll(t, options) |
| 43 | + bucketArn := outputs["arn"].(string) |
| 44 | + |
| 45 | + // some assertions built into terratest |
| 46 | + aws.AssertS3BucketExists(t, region, bucket) |
| 47 | + aws.AssertS3BucketPolicyExists(t, region, bucket) |
| 48 | + aws.AssertS3BucketVersioningExists(t, region, bucket) |
| 49 | + |
| 50 | + bucketPolicy := aws.GetS3BucketPolicy(t, region, bucket) |
| 51 | + policy, err := testutil.UnmarshalS3BucketPolicy(bucketPolicy) |
| 52 | + r.NoError(err) |
| 53 | + r.NotNil(policy) |
| 54 | + |
| 55 | + r.Len(policy.Statement, 1) |
| 56 | + r.Equal(policy.Statement[0].Effect, "Deny") |
| 57 | + r.Equal(policy.Statement[0].Principal, "*") |
| 58 | + r.Equal(policy.Statement[0].Action, "*") |
| 59 | + r.Len(policy.Statement[0].Condition, 1) |
| 60 | + r.Equal(policy.Statement[0].Condition["Bool"]["aws:SecureTransport"], "false") |
| 61 | + |
| 62 | + // get a client to query for other assertions |
| 63 | + s3Client := aws.NewS3Client(t, region) |
| 64 | + |
| 65 | + acl, err := s3Client.GetBucketAcl(&s3.GetBucketAclInput{ |
| 66 | + Bucket: &bucket, |
| 67 | + }) |
| 68 | + |
| 69 | + r.NoError(err) |
| 70 | + r.Len(acl.Grants, 1) |
| 71 | + |
| 72 | + r.Equal("CanonicalUser", *acl.Grants[0].Grantee.Type) |
| 73 | + r.Equal("FULL_CONTROL", *acl.Grants[0].Permission) |
| 74 | + |
| 75 | + enc, err := s3Client.GetBucketEncryption(&s3.GetBucketEncryptionInput{ |
| 76 | + Bucket: &bucket, |
| 77 | + }) |
| 78 | + r.NoError(err) |
| 79 | + |
| 80 | + r.NotNil(enc.ServerSideEncryptionConfiguration) |
| 81 | + r.Len(enc.ServerSideEncryptionConfiguration.Rules, 1) |
| 82 | + |
| 83 | + block, err := s3Client.GetPublicAccessBlock(&s3.GetPublicAccessBlockInput{ |
| 84 | + Bucket: &bucket, |
| 85 | + }) |
| 86 | + r.NoError(err) |
| 87 | + r.NotNil(block) |
| 88 | + r.True(*block.PublicAccessBlockConfiguration.BlockPublicAcls) |
| 89 | + r.True(*block.PublicAccessBlockConfiguration.BlockPublicPolicy) |
| 90 | + r.True(*block.PublicAccessBlockConfiguration.IgnorePublicAcls) |
| 91 | + r.True(*block.PublicAccessBlockConfiguration.RestrictPublicBuckets) |
| 92 | + |
| 93 | + // policy simulations |
| 94 | + |
| 95 | + objectArn := fmt.Sprintf("%s/foo", bucketArn) |
| 96 | + |
| 97 | + sims := []struct { |
| 98 | + action string |
| 99 | + secureTransport bool |
| 100 | + arn string |
| 101 | + result string |
| 102 | + }{ |
| 103 | + // deny when not using https |
| 104 | + {"s3:ListBucket", false, bucketArn, "explicitDeny"}, |
| 105 | + // allow with https |
| 106 | + {"s3:ListBucket", true, bucketArn, "allowed"}, |
| 107 | + // deny when not using https |
| 108 | + {"s3:GetObject", false, objectArn, "explicitDeny"}, |
| 109 | + // allow with https |
| 110 | + {"s3:GetObject", true, objectArn, "allowed"}, |
| 111 | + } |
| 112 | + |
| 113 | + for _, test := range sims { |
| 114 | + resp := testutil.S3SimulateRequest(t, region, test.action, test.arn, bucketPolicy, test.secureTransport) |
| 115 | + r.Equal(test.result, *resp.EvalDecision) |
| 116 | + } |
| 117 | + }, |
| 118 | + } |
| 119 | + |
| 120 | + test.Run(t) |
33 | 121 | }
|
0 commit comments