Skip to content

Commit 5ac0111

Browse files
committed
Added support for AWS Govcloud DoD shard
1 parent d3daecb commit 5ac0111

16 files changed

+296
-52
lines changed

aws/constants.go

+10-2
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,23 @@ package aws
33
var AwsConfig = map[string]map[string]string{
44
"aws": {
55
"accountId": "414351767826",
6+
"awsNamespace": "aws",
67
"logDeliveryIamArn": "arn:aws:iam::414351767826:role/SaasUsageDeliveryRole-prod-IAMRole-3PLHICCRR1TK",
78
"unityCatalogueIamArn": "arn:aws:iam::414351767826:role/unity-catalog-prod-UCMasterRole-14S5ZJVKOTYTL",
89
},
910
"aws-us-gov": {
1011
"accountId": "044793339203",
12+
"awsNamespace": "aws-us-gov",
1113
"logDeliveryIamArn": "arn:aws-us-gov:iam::044793339203:role/SaasUsageDeliveryRole-prod-aws-gov-IAMRole-L4QM0RCHYQ1G",
1214
"unityCatalogueIamArn": "arn:aws-us-gov:iam::044793339203:role/unity-catalog-prod-UCMasterRole-1QRFA8SGY15OJ",
1315
},
16+
"aws-us-gov-dod": {
17+
"accountId": "170661010020",
18+
"awsNamespace": "aws-us-gov",
19+
"logDeliveryIamArn": "arn:aws-us-gov:iam::170661010020:role/SaasUsageDeliveryRole-prod-aws-gov-dod-IAMRole-1DMEHBYR8VC5P",
20+
"unityCatalogueIamArn": "arn:aws-us-gov:iam::170661010020:role/unity-catalog-prod-UCMasterRole-1DI6DL6ZP26AS",
21+
},
1422
}
1523

16-
var AwsPartitions = []string{"aws", "aws-us-gov"}
17-
var AwsPartitionsValidationError = "aws_partition must be either 'aws' or 'aws-us-gov'"
24+
var AwsPartitions = []string{"aws", "aws-us-gov", "aws-us-gov-dod"}
25+
var AwsPartitionsValidationError = "aws_partition must be either 'aws' or 'aws-us-gov' or 'aws-us-gov-dod'"

aws/data_aws_assume_role_policy.go

+2-1
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ func DataAwsAssumeRolePolicy() common.Resource {
3434
externalID := d.Get("external_id").(string)
3535
awsPartition := d.Get("aws_partition").(string)
3636
databricksAwsAccountId := d.Get("databricks_account_id").(string)
37+
awsNamespace := AwsConfig[awsPartition]["awsNamespace"]
3738

3839
if databricksAwsAccountId == "" {
3940
databricksAwsAccountId = AwsConfig[awsPartition]["accountId"]
@@ -51,7 +52,7 @@ func DataAwsAssumeRolePolicy() common.Resource {
5152
},
5253
},
5354
Principal: map[string]string{
54-
"AWS": fmt.Sprintf("arn:%s:iam::%s:root", awsPartition, databricksAwsAccountId),
55+
"AWS": fmt.Sprintf("arn:%s:iam::%s:root", awsNamespace, databricksAwsAccountId),
5556
},
5657
},
5758
},

aws/data_aws_assume_role_policy_test.go

+33
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,22 @@ func TestDataAwsAssumeRolePolicyGov(t *testing.T) {
3636
assert.Lenf(t, j, 306, "Strange length for policy: %s", j)
3737
}
3838

39+
func TestDataAwsAssumeRolePolicyGovDoD(t *testing.T) {
40+
d, err := qa.ResourceFixture{
41+
Read: true,
42+
Resource: DataAwsAssumeRolePolicy(),
43+
NonWritable: true,
44+
ID: ".",
45+
HCL: `
46+
aws_partition = "aws-us-gov-dod"
47+
external_id = "abc"
48+
`,
49+
}.Apply(t)
50+
assert.NoError(t, err)
51+
j := d.Get("json")
52+
assert.Lenf(t, j, 306, "Strange length for policy: %s", j)
53+
}
54+
3955
func TestDataAwsAssumeRolePolicyLogDelivery(t *testing.T) {
4056
d, err := qa.ResourceFixture{
4157
Read: true,
@@ -68,3 +84,20 @@ func TestDataAwsAssumeRolePolicyLogDeliveryGov(t *testing.T) {
6884
j := d.Get("json")
6985
assert.Lenf(t, j, 362, "Strange length for policy: %s", j)
7086
}
87+
88+
func TestDataAwsAssumeRolePolicyLogDeliveryGovDoD(t *testing.T) {
89+
d, err := qa.ResourceFixture{
90+
Read: true,
91+
Resource: DataAwsAssumeRolePolicy(),
92+
NonWritable: true,
93+
ID: ".",
94+
HCL: `
95+
aws_partition = "aws-us-gov-dod"
96+
external_id = "abc"
97+
for_log_delivery = true
98+
`,
99+
}.Apply(t)
100+
assert.NoError(t, err)
101+
j := d.Get("json")
102+
assert.Lenf(t, j, 367, "Strange length for policy: %s", j)
103+
}

aws/data_aws_bucket_policy.go

+4-3
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ func DataAwsBucketPolicy() common.Resource {
1818
bucket := d.Get("bucket").(string)
1919
awsPartition := d.Get("aws_partition").(string)
2020
databricksAwsAccountId := AwsConfig[awsPartition]["accountId"]
21+
awsNamespace := AwsConfig[awsPartition]["awsNamespace"]
2122

2223
if databricksAwsAccountId == "" {
2324
databricksAwsAccountId = AwsConfig[awsPartition]["accountId"]
@@ -37,11 +38,11 @@ func DataAwsBucketPolicy() common.Resource {
3738
"s3:GetBucketLocation",
3839
},
3940
Resources: []string{
40-
fmt.Sprintf("arn:%s:s3:::%s/*", awsPartition, bucket),
41-
fmt.Sprintf("arn:%s:s3:::%s", awsPartition, bucket),
41+
fmt.Sprintf("arn:%s:s3:::%s/*", awsNamespace, bucket),
42+
fmt.Sprintf("arn:%s:s3:::%s", awsNamespace, bucket),
4243
},
4344
Principal: map[string]string{
44-
"AWS": fmt.Sprintf("arn:%s:iam::%s:root", awsPartition, databricksAwsAccountId),
45+
"AWS": fmt.Sprintf("arn:%s:iam::%s:root", awsNamespace, databricksAwsAccountId),
4546
},
4647
},
4748
},

aws/data_aws_bucket_policy_test.go

+16
Original file line numberDiff line numberDiff line change
@@ -69,3 +69,19 @@ func TestDataAwsBucketPolicyPartitionGov(t *testing.T) {
6969
j := d.Get("json")
7070
assert.Lenf(t, j, 461, "Strange length for policy: %s", j)
7171
}
72+
73+
func TestDataAwsBucketPolicyPartitionGovDoD(t *testing.T) {
74+
d, err := qa.ResourceFixture{
75+
Read: true,
76+
Resource: DataAwsBucketPolicy(),
77+
NonWritable: true,
78+
ID: ".",
79+
HCL: `
80+
bucket = "abc"
81+
aws_partition = "aws-us-gov-dod"
82+
`,
83+
}.Apply(t)
84+
assert.NoError(t, err)
85+
j := d.Get("json")
86+
assert.Lenf(t, j, 461, "Strange length for policy: %s", j)
87+
}

aws/data_aws_crossaccount_policy.go

+23-24
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ func DataAwsCrossaccountPolicy() common.Resource {
2727
if !slices.Contains(AwsPartitions, data.AwsPartition) {
2828
return errors.New(AwsPartitionsValidationError)
2929
}
30-
30+
awsNamespace := AwsConfig[data.AwsPartition]["awsNamespace"]
3131
if !slices.Contains([]string{"managed", "customer", "restricted"}, data.PolicyType) {
3232
return fmt.Errorf("policy_type must be either 'managed', 'customer' or 'restricted'")
3333
}
@@ -151,7 +151,7 @@ func DataAwsCrossaccountPolicy() common.Resource {
151151
"iam:CreateServiceLinkedRole",
152152
"iam:PutRolePolicy",
153153
},
154-
Resources: fmt.Sprintf("arn:%s:iam::*:role/aws-service-role/spot.amazonaws.com/AWSServiceRoleForEC2Spot", data.AwsPartition),
154+
Resources: fmt.Sprintf("arn:%s:iam::*:role/aws-service-role/spot.amazonaws.com/AWSServiceRoleForEC2Spot", awsNamespace),
155155
Condition: map[string]map[string]string{
156156
"StringLike": {
157157
"iam:AWSServiceName": "spot.amazonaws.com",
@@ -174,7 +174,6 @@ func DataAwsCrossaccountPolicy() common.Resource {
174174
if data.PolicyType == "restricted" {
175175
region := data.Region
176176
aws_account_id := data.AwsAccountId
177-
awsPartition := data.AwsPartition
178177
vpc_id := data.VpcId
179178
security_group_id := data.SecurityGroupId
180179
policy.Statements = append(policy.Statements,
@@ -186,7 +185,7 @@ func DataAwsCrossaccountPolicy() common.Resource {
186185
"ec2:DisassociateIamInstanceProfile",
187186
"ec2:ReplaceIamInstanceProfileAssociation",
188187
},
189-
Resources: fmt.Sprintf("arn:%s:ec2:%s:%s:instance/*", awsPartition, region, aws_account_id),
188+
Resources: fmt.Sprintf("arn:%s:ec2:%s:%s:instance/*", awsNamespace, region, aws_account_id),
190189
Condition: map[string]map[string]string{
191190
"StringEquals": {
192191
"ec2:ResourceTag/Vendor": "Databricks",
@@ -198,8 +197,8 @@ func DataAwsCrossaccountPolicy() common.Resource {
198197
Effect: "Allow",
199198
Actions: "ec2:RunInstances",
200199
Resources: []string{
201-
fmt.Sprintf("arn:%s:ec2:%s:%s:volume/*", awsPartition, region, aws_account_id),
202-
fmt.Sprintf("arn:%s:ec2:%s:%s:instance/*", awsPartition, region, aws_account_id),
200+
fmt.Sprintf("arn:%s:ec2:%s:%s:volume/*", awsNamespace, region, aws_account_id),
201+
fmt.Sprintf("arn:%s:ec2:%s:%s:instance/*", awsNamespace, region, aws_account_id),
203202
},
204203
Condition: map[string]map[string]string{
205204
"StringEquals": {
@@ -211,7 +210,7 @@ func DataAwsCrossaccountPolicy() common.Resource {
211210
Sid: "AllowEc2RunInstanceImagePerTag",
212211
Effect: "Allow",
213212
Actions: "ec2:RunInstances",
214-
Resources: fmt.Sprintf("arn:%s:ec2:%s:%s:image/*", awsPartition, region, aws_account_id),
213+
Resources: fmt.Sprintf("arn:%s:ec2:%s:%s:image/*", awsNamespace, region, aws_account_id),
215214
Condition: map[string]map[string]string{
216215
"StringEquals": {
217216
"aws:ResourceTag/Vendor": "Databricks",
@@ -223,13 +222,13 @@ func DataAwsCrossaccountPolicy() common.Resource {
223222
Effect: "Allow",
224223
Actions: "ec2:RunInstances",
225224
Resources: []string{
226-
fmt.Sprintf("arn:%s:ec2:%s:%s:network-interface/*", awsPartition, region, aws_account_id),
227-
fmt.Sprintf("arn:%s:ec2:%s:%s:subnet/*", awsPartition, region, aws_account_id),
228-
fmt.Sprintf("arn:%s:ec2:%s:%s:security-group/*", awsPartition, region, aws_account_id),
225+
fmt.Sprintf("arn:%s:ec2:%s:%s:network-interface/*", awsNamespace, region, aws_account_id),
226+
fmt.Sprintf("arn:%s:ec2:%s:%s:subnet/*", awsNamespace, region, aws_account_id),
227+
fmt.Sprintf("arn:%s:ec2:%s:%s:security-group/*", awsNamespace, region, aws_account_id),
229228
},
230229
Condition: map[string]map[string]string{
231230
"StringEquals": {
232-
"ec2:vpc": fmt.Sprintf("arn:%s:ec2:%s:%s:vpc/%s", awsPartition, region, aws_account_id, vpc_id),
231+
"ec2:vpc": fmt.Sprintf("arn:%s:ec2:%s:%s:vpc/%s", awsNamespace, region, aws_account_id, vpc_id),
233232
},
234233
},
235234
},
@@ -238,19 +237,19 @@ func DataAwsCrossaccountPolicy() common.Resource {
238237
Effect: "Allow",
239238
Actions: "ec2:RunInstances",
240239
NotResources: []string{
241-
fmt.Sprintf("arn:%s:ec2:%s:%s:image/*", awsPartition, region, aws_account_id),
242-
fmt.Sprintf("arn:%s:ec2:%s:%s:network-interface/*", awsPartition, region, aws_account_id),
243-
fmt.Sprintf("arn:%s:ec2:%s:%s:subnet/*", awsPartition, region, aws_account_id),
244-
fmt.Sprintf("arn:%s:ec2:%s:%s:security-group/*", awsPartition, region, aws_account_id),
245-
fmt.Sprintf("arn:%s:ec2:%s:%s:volume/*", awsPartition, region, aws_account_id),
246-
fmt.Sprintf("arn:%s:ec2:%s:%s:instance/*", awsPartition, region, aws_account_id),
240+
fmt.Sprintf("arn:%s:ec2:%s:%s:image/*", awsNamespace, region, aws_account_id),
241+
fmt.Sprintf("arn:%s:ec2:%s:%s:network-interface/*", awsNamespace, region, aws_account_id),
242+
fmt.Sprintf("arn:%s:ec2:%s:%s:subnet/*", awsNamespace, region, aws_account_id),
243+
fmt.Sprintf("arn:%s:ec2:%s:%s:security-group/*", awsNamespace, region, aws_account_id),
244+
fmt.Sprintf("arn:%s:ec2:%s:%s:volume/*", awsNamespace, region, aws_account_id),
245+
fmt.Sprintf("arn:%s:ec2:%s:%s:instance/*", awsNamespace, region, aws_account_id),
247246
},
248247
},
249248
&awsIamPolicyStatement{
250249
Sid: "EC2TerminateInstancesTag",
251250
Effect: "Allow",
252251
Actions: "ec2:TerminateInstances",
253-
Resources: fmt.Sprintf("arn:%s:ec2:%s:%s:instance/*", awsPartition, region, aws_account_id),
252+
Resources: fmt.Sprintf("arn:%s:ec2:%s:%s:instance/*", awsNamespace, region, aws_account_id),
254253
Condition: map[string]map[string]string{
255254
"StringEquals": {
256255
"ec2:ResourceTag/Vendor": "Databricks",
@@ -265,8 +264,8 @@ func DataAwsCrossaccountPolicy() common.Resource {
265264
"ec2:DetachVolume",
266265
},
267266
Resources: []string{
268-
fmt.Sprintf("arn:%s:ec2:%s:%s:instance/*", awsPartition, region, aws_account_id),
269-
fmt.Sprintf("arn:%s:ec2:%s:%s:volume/*", awsPartition, region, aws_account_id),
267+
fmt.Sprintf("arn:%s:ec2:%s:%s:instance/*", awsNamespace, region, aws_account_id),
268+
fmt.Sprintf("arn:%s:ec2:%s:%s:volume/*", awsNamespace, region, aws_account_id),
270269
},
271270
Condition: map[string]map[string]string{
272271
"StringEquals": {
@@ -278,7 +277,7 @@ func DataAwsCrossaccountPolicy() common.Resource {
278277
Sid: "EC2CreateVolumeByTag",
279278
Effect: "Allow",
280279
Actions: "ec2:CreateVolume",
281-
Resources: fmt.Sprintf("arn:%s:ec2:%s:%s:volume/*", awsPartition, region, aws_account_id),
280+
Resources: fmt.Sprintf("arn:%s:ec2:%s:%s:volume/*", awsNamespace, region, aws_account_id),
282281
Condition: map[string]map[string]string{
283282
"StringEquals": {
284283
"aws:RequestTag/Vendor": "Databricks",
@@ -290,7 +289,7 @@ func DataAwsCrossaccountPolicy() common.Resource {
290289
Effect: "Allow",
291290
Actions: "ec2:DeleteVolume",
292291
Resources: []string{
293-
fmt.Sprintf("arn:%s:ec2:%s:%s:volume/*", awsPartition, region, aws_account_id),
292+
fmt.Sprintf("arn:%s:ec2:%s:%s:volume/*", awsNamespace, region, aws_account_id),
294293
},
295294
Condition: map[string]map[string]string{
296295
"StringEquals": {
@@ -307,10 +306,10 @@ func DataAwsCrossaccountPolicy() common.Resource {
307306
"ec2:RevokeSecurityGroupEgress",
308307
"ec2:RevokeSecurityGroupIngress",
309308
},
310-
Resources: fmt.Sprintf("arn:%s:ec2:%s:%s:security-group/%s", awsPartition, region, aws_account_id, security_group_id),
309+
Resources: fmt.Sprintf("arn:%s:ec2:%s:%s:security-group/%s", awsNamespace, region, aws_account_id, security_group_id),
311310
Condition: map[string]map[string]string{
312311
"StringEquals": {
313-
"ec2:vpc": fmt.Sprintf("arn:%s:ec2:%s:%s:vpc/%s", awsPartition, region, aws_account_id, vpc_id),
312+
"ec2:vpc": fmt.Sprintf("arn:%s:ec2:%s:%s:vpc/%s", awsNamespace, region, aws_account_id, vpc_id),
314313
},
315314
},
316315
},

aws/data_aws_crossaccount_policy_test.go

+21-2
Original file line numberDiff line numberDiff line change
@@ -540,13 +540,32 @@ func TestDataAwsCrossAccountRestrictedPolicyPartitionGov(t *testing.T) {
540540
aws_account_id = "123456789012"
541541
aws_partition = "aws-us-gov"
542542
vpc_id = "vpc-12345678"
543-
region = "us-west-2"
543+
region = "us-gov-west-1"
544+
security_group_id = "sg-12345678"`,
545+
ID: ".",
546+
}.Apply(t)
547+
assert.NoError(t, err)
548+
j := d.Get("json")
549+
assert.Lenf(t, j, 5963, "Strange length for policy: %s", j)
550+
}
551+
552+
func TestDataAwsCrossAccountRestrictedPolicyPartitionGovDoD(t *testing.T) {
553+
d, err := qa.ResourceFixture{
554+
Read: true,
555+
Resource: DataAwsCrossaccountPolicy(),
556+
NonWritable: true,
557+
HCL: `
558+
policy_type = "restricted"
559+
aws_account_id = "123456789012"
560+
aws_partition = "aws-us-gov-dod"
561+
vpc_id = "vpc-12345678"
562+
region = "us-gov-west-1"
544563
security_group_id = "sg-12345678"`,
545564
ID: ".",
546565
}.Apply(t)
547566
assert.NoError(t, err)
548567
j := d.Get("json")
549-
assert.Lenf(t, j, 5879, "Strange length for policy: %s", j)
568+
assert.Lenf(t, j, 5963, "Strange length for policy: %s", j)
550569
}
551570

552571
func TestDataAwsCrossAccountInvalidPolicy(t *testing.T) {

aws/data_aws_unity_catalog_assume_role_policy.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ func DataAwsUnityCatalogAssumeRolePolicy() common.Resource {
2424
if !slices.Contains(AwsPartitions, data.AwsPartition) {
2525
return errors.New(AwsPartitionsValidationError)
2626
}
27-
27+
awsNamespace := AwsConfig[data.AwsPartition]["awsNamespace"]
2828
if data.UnityCatalogIamArn == "" {
2929
data.UnityCatalogIamArn = AwsConfig[data.AwsPartition]["unityCatalogueIamArn"]
3030
}
@@ -51,11 +51,11 @@ func DataAwsUnityCatalogAssumeRolePolicy() common.Resource {
5151
Actions: "sts:AssumeRole",
5252
Condition: map[string]map[string]string{
5353
"ArnLike": {
54-
"aws:PrincipalArn": fmt.Sprintf("arn:%s:iam::%s:role/%s", data.AwsPartition, data.AwsAccountId, data.RoleName),
54+
"aws:PrincipalArn": fmt.Sprintf("arn:%s:iam::%s:role/%s", awsNamespace, data.AwsAccountId, data.RoleName),
5555
},
5656
},
5757
Principal: map[string]string{
58-
"AWS": fmt.Sprintf("arn:%s:iam::%s:root", data.AwsPartition, data.AwsAccountId),
58+
"AWS": fmt.Sprintf("arn:%s:iam::%s:root", awsNamespace, data.AwsAccountId),
5959
},
6060
},
6161
},

aws/data_aws_unity_catalog_assume_role_policy_test.go

+49
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,55 @@ func TestDataAwsUnityCatalogAssumeRolePolicyGovWithoutUcArn(t *testing.T) {
153153
compareJSON(t, j, p)
154154
}
155155

156+
func TestDataAwsUnityCatalogAssumeRolePolicyGovDoDWithoutUcArn(t *testing.T) {
157+
d, err := qa.ResourceFixture{
158+
Read: true,
159+
Resource: DataAwsUnityCatalogAssumeRolePolicy(),
160+
NonWritable: true,
161+
ID: ".",
162+
HCL: `
163+
aws_account_id = "123456789098"
164+
aws_partition = "aws-us-gov-dod"
165+
role_name = "databricks-role"
166+
external_id = "12345"
167+
`,
168+
}.Apply(t)
169+
assert.NoError(t, err)
170+
j := d.Get("json").(string)
171+
p := `{
172+
"Version": "2012-10-17",
173+
"Statement": [
174+
{
175+
"Sid": "UnityCatalogAssumeRole",
176+
"Effect": "Allow",
177+
"Action": "sts:AssumeRole",
178+
"Principal": {
179+
"AWS": "arn:aws-us-gov:iam::170661010020:role/unity-catalog-prod-UCMasterRole-1DI6DL6ZP26AS"
180+
},
181+
"Condition": {
182+
"StringEquals": {
183+
"sts:ExternalId": "12345"
184+
}
185+
}
186+
},
187+
{
188+
"Sid": "ExplicitSelfRoleAssumption",
189+
"Effect": "Allow",
190+
"Action": "sts:AssumeRole",
191+
"Principal": {
192+
"AWS": "arn:aws-us-gov:iam::123456789098:root"
193+
},
194+
"Condition": {
195+
"ArnLike": {
196+
"aws:PrincipalArn": "arn:aws-us-gov:iam::123456789098:role/databricks-role"
197+
}
198+
}
199+
}
200+
]
201+
}`
202+
compareJSON(t, j, p)
203+
}
204+
156205
func TestDataAwsUnityCatalogAssumeRolePolicyInvalidPartition(t *testing.T) {
157206
qa.ResourceFixture{
158207
Read: true,

0 commit comments

Comments
 (0)