Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add EFS transit encryption and authorization config options for ECS task definition #13136

Merged
merged 23 commits into from
Jun 24, 2020
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
a2e0a3e
Update ECS task def resource schema
jukie May 2, 2020
384fb86
Update EFS volume config to account for transit encryption
jukie May 2, 2020
ecd240d
Update acceptance tests to use transit encryption
jukie May 2, 2020
3fdfdfb
Update website docs for EFS volume config options
jukie May 2, 2020
8a69551
"Update acceptance tests to use transit encryption"
jukie May 3, 2020
9cc8178
Merge remote-tracking branch 'upstream/master' into 12809-efs-vol-conf
jukie May 20, 2020
69b738b
Add EFS Access Point config schema and tests
jukie May 20, 2020
4d1ac27
Use bool values intsead
jukie May 20, 2020
98edb56
Add docs for authorization config
jukie May 20, 2020
c8bdc0e
Apply linting and remove extraneous change
jukie May 20, 2020
eb2c35f
Better align schema keys with api names
jukie Jun 10, 2020
ad54a93
Merge remote-tracking branch 'upstream/master' into 12809-efs-vol-conf
jukie Jun 10, 2020
3a8a596
Add new schemas to volume hash
jukie Jun 10, 2020
ff3457a
Update tests and fix encryption port
jukie Jun 10, 2020
fd9d5a8
Remove default root directory path and fix auth config hash
jukie Jun 10, 2020
099a608
Update website/docs/r/ecs_task_definition.html.markdown
jukie Jun 10, 2020
db5d4d4
Update website/docs/r/ecs_task_definition.html.markdown
jukie Jun 10, 2020
aa20722
Update website/docs/r/ecs_task_definition.html.markdown
jukie Jun 10, 2020
a6b19f4
Apply suggestions from code review
jukie Jun 10, 2020
e676776
Ignore root_directory if authorization_config is used
jukie Jun 10, 2020
68a9800
Add validator functions for EFSAuthorizationConfigIAM and EFSTransitE…
jukie Jun 11, 2020
4c5c6e4
Fix typo in function name
jukie Jun 11, 2020
b18cda5
Rebase from master
jukie Jun 20, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 48 additions & 1 deletion aws/resource_aws_ecs_task_definition.go
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,37 @@ func resourceAwsEcsTaskDefinition() *schema.Resource {
Type: schema.TypeString,
ForceNew: true,
Optional: true,
Default: "/",
},
"transit_encryption": {
Type: schema.TypeString,
ForceNew: true,
Optional: true,
jukie marked this conversation as resolved.
Show resolved Hide resolved
jukie marked this conversation as resolved.
Show resolved Hide resolved
},
"transit_encryption_port": {
Type: schema.TypeInt,
ForceNew: true,
Optional: true,
ValidateFunc: validation.IsPortNumber,
},
"authorization_config": {
Type: schema.TypeList,
Optional: true,
jukie marked this conversation as resolved.
Show resolved Hide resolved
ForceNew: true,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"access_point_id": {
Type: schema.TypeString,
ForceNew: true,
Optional: true,
},
"iam": {
Type: schema.TypeString,
ForceNew: true,
Optional: true,
jukie marked this conversation as resolved.
Show resolved Hide resolved
},
},
},
},
},
},
Expand Down Expand Up @@ -600,6 +630,23 @@ func resourceAwsEcsTaskDefinitionVolumeHash(v interface{}) int {
if v, ok := m["root_directory"]; ok && v.(string) != "" {
buf.WriteString(fmt.Sprintf("%s-", v.(string)))
}

if v, ok := m["transit_encryption"]; ok && v.(string) != "" {
buf.WriteString(fmt.Sprintf("%s-", v.(string)))
}
if v, ok := m["transit_encryption_port"]; ok && v.(int) > 0 {
buf.WriteString(fmt.Sprintf("%d-", v.(int)))
}
if v, ok := m["authorization_config"]; ok && len(v.([]interface{})) > 0 && v.([]interface{})[0] != nil {
m := v.([]interface{})[0].(map[string]interface{})
if v, ok := m["access_point_id"]; ok && v.(string) != "" {
buf.WriteString(fmt.Sprintf("%s-", v.(string)))
}
if v, ok := m["iam"]; ok && v.(string) != "" {
buf.WriteString(fmt.Sprintf("%s-", v.(string)))
}
}

}

return hashcode.String(buf.String())
Expand Down
138 changes: 138 additions & 0 deletions aws/resource_aws_ecs_task_definition_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,61 @@ func TestAccAWSEcsTaskDefinition_withEFSVolume(t *testing.T) {
})
}

func TestAccAWSEcsTaskDefinition_withTransitEncryptionEFSVolume(t *testing.T) {
var def ecs.TaskDefinition

tdName := acctest.RandomWithPrefix("tf-acc-td-with-efs-volume")
resourceName := "aws_ecs_task_definition.test"
resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckAWSEcsTaskDefinitionDestroy,
Steps: []resource.TestStep{
{
Config: testAccAWSEcsTaskDefinitionWithTransitEncryptionEFSVolume(tdName, "ENABLED", 2999),
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSEcsTaskDefinitionExists(resourceName, &def),
resource.TestCheckResourceAttr(resourceName, "volume.#", "1"),
),
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateIdFunc: testAccAWSEcsTaskDefinitionImportStateIdFunc(resourceName),
ImportStateVerify: true,
},
},
})
}

func TestAccAWSEcsTaskDefinition_withEFSAccessPoint(t *testing.T) {
var def ecs.TaskDefinition

tdName := acctest.RandomWithPrefix("tf-acc-td-with-efs-volume")
resourceName := "aws_ecs_task_definition.test"

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckAWSEcsTaskDefinitionDestroy,
Steps: []resource.TestStep{
{
Config: testAccAWSEcsTaskDefinitionWitEFSAccessPoint(tdName, "DISABLED"),
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSEcsTaskDefinitionExists(resourceName, &def),
resource.TestCheckResourceAttr(resourceName, "volume.#", "1"),
),
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateIdFunc: testAccAWSEcsTaskDefinitionImportStateIdFunc(resourceName),
ImportStateVerify: true,
},
},
})
}

func TestAccAWSEcsTaskDefinition_withTaskScopedDockerVolume(t *testing.T) {
var def ecs.TaskDefinition

Expand Down Expand Up @@ -1506,6 +1561,89 @@ TASK_DEFINITION
`, tdName, rDir)
}

func testAccAWSEcsTaskDefinitionWithTransitEncryptionEFSVolume(tdName, tEnc string, tEncPort int) string {
return fmt.Sprintf(`
resource "aws_efs_file_system" "test" {
creation_token = %[1]q
}

resource "aws_ecs_task_definition" "test" {
family = %[1]q

container_definitions = <<TASK_DEFINITION
[
{
"name": "sleep",
"image": "busybox",
"cpu": 10,
"command": ["sleep","360"],
"memory": 10,
"essential": true
}
]
TASK_DEFINITION

volume {
name = %[1]q

efs_volume_configuration {
file_system_id = "${aws_efs_file_system.test.id}"
root_directory = "/home/test"
transit_encryption = %[2]q
transit_encryption_port = %[3]d

}
}
}
`, tdName, tEnc, tEncPort)
}

func testAccAWSEcsTaskDefinitionWitEFSAccessPoint(tdName, useIam string) string {
return fmt.Sprintf(`
resource "aws_efs_file_system" "test" {
creation_token = %[1]q
}

resource "aws_efs_access_point" "test" {
file_system_id = "${aws_efs_file_system.test.id}"
posix_user {
gid = 1001
uid = 1001
}
}

resource "aws_ecs_task_definition" "test" {
family = %[1]q

container_definitions = <<TASK_DEFINITION
[
{
"name": "sleep",
"image": "busybox",
"cpu": 10,
"command": ["sleep","360"],
"memory": 10,
"essential": true
}
]
TASK_DEFINITION

volume {
name = %[1]q

efs_volume_configuration {
file_system_id = "${aws_efs_file_system.test.id}"
transit_encryption = "ENABLED"
transit_encryption_port = 2999
authorization_config {
access_point_id = "${aws_efs_access_point.test.id}"
iam = %[2]q
}
}
}
}
`, tdName, useIam)
}
func testAccAWSEcsTaskDefinitionWithTaskRoleArn(roleName, policyName, tdName string) string {
return fmt.Sprintf(`
resource "aws_iam_role" "test" {
Expand Down
51 changes: 50 additions & 1 deletion aws/structure.go
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,27 @@ func expandEcsVolumes(configured []interface{}) ([]*ecs.Volume, error) {
if v, ok := config["root_directory"].(string); ok && v != "" {
jukie marked this conversation as resolved.
Show resolved Hide resolved
l.EfsVolumeConfiguration.RootDirectory = aws.String(v)
}

if v, ok := config["transit_encryption"].(string); ok && v != "" {
l.EfsVolumeConfiguration.TransitEncryption = aws.String(v)
}

if v, ok := config["transit_encryption_port"].(int); ok && v > 0 {
l.EfsVolumeConfiguration.TransitEncryptionPort = aws.Int64(int64(v))
}
authConfig, ok := config["authorization_config"].([]interface{})
if ok && len(authConfig) > 0 {
authconfig := authConfig[0].(map[string]interface{})
l.EfsVolumeConfiguration.AuthorizationConfig = &ecs.EFSAuthorizationConfig{}

if v, ok := authconfig["access_point_id"].(string); ok && v != "" {
l.EfsVolumeConfiguration.AuthorizationConfig.AccessPointId = aws.String(v)
}

if v, ok := authconfig["iam"].(string); ok && v != "" {
l.EfsVolumeConfiguration.AuthorizationConfig.Iam = aws.String(v)
}
}
}

volumes = append(volumes, l)
Expand Down Expand Up @@ -745,9 +766,37 @@ func flattenEFSVolumeConfiguration(config *ecs.EFSVolumeConfiguration) []interfa
m["file_system_id"] = aws.StringValue(v)
}

if v := config.RootDirectory; v != nil {
if v := config.RootDirectory; v != nil && aws.StringValue(v) != "/" {
m["root_directory"] = aws.StringValue(v)
}

if v := config.TransitEncryption; v != nil {
m["transit_encryption"] = aws.StringValue(v)
}

if v := config.TransitEncryptionPort; v != nil {
m["transit_encryption_port"] = int(aws.Int64Value(v))
}

if v := config.AuthorizationConfig; v != nil {
m["authorization_config"] = flattenEFSVolumeAuthorizationConfig(v)
}
}

items = append(items, m)
return items
}

func flattenEFSVolumeAuthorizationConfig(config *ecs.EFSAuthorizationConfig) []interface{} {
var items []interface{}
m := make(map[string]interface{})
if config != nil {
if v := config.AccessPointId; v != nil {
m["access_point_id"] = aws.StringValue(v)
}
if v := config.Iam; v != nil {
m["iam"] = aws.StringValue(v)
}
}

items = append(items, m)
Expand Down
18 changes: 15 additions & 3 deletions website/docs/r/ecs_task_definition.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -159,10 +159,15 @@ resource "aws_ecs_task_definition" "service" {

#### EFS Volume Configuration Arguments

For more information, see [Specifying an EFS volume in your Task Definition Developer Guide](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/using_efs.html)
For more information, see [Specifying an EFS volume in your Task Definition Developer Guide](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/efs-volumes.html#specify-efs-config)

* `file_system_id` - (Required) The ID of the EFS File System.
* `root_directory` - (Optional) The path to mount on the host
jukie marked this conversation as resolved.
Show resolved Hide resolved
* `transit_encryption` - (Optional) Boolean whether to use transit encryption.
jukie marked this conversation as resolved.
Show resolved Hide resolved
* `transit_encryption_port` - (Optional) The port to use for transit encryption. If you do not specify a transit encryption port, it will use the port selection strategy that the Amazon EFS mount helper uses.
* `authorization_config` - (Optional) The authorization configuration details for the Amazon EFS file system.
* `access_point_id` - The access point ID to use. If an access point is specified, the root directory value will be relative to the directory set for the access point. If specified, transit encryption must be enabled in the EFSVolumeConfiguration.
* `iam_enabled` - Boolean for whether or not to use the Amazon ECS task IAM role defined in a task definition when mounting the Amazon EFS file system. If enabled, transit encryption must be enabled in the EFSVolumeConfiguration.
jukie marked this conversation as resolved.
Show resolved Hide resolved

##### Example Usage

Expand All @@ -175,13 +180,20 @@ resource "aws_ecs_task_definition" "service" {
name = "service-storage"

efs_volume_configuration {
file_system_id = aws_efs_file_system.fs.id
root_directory = "/opt/data"
file_system_id = "${aws_efs_file_system.fs.id}"
jukie marked this conversation as resolved.
Show resolved Hide resolved
root_directory = "/opt/data"
transit_encryption = true
jukie marked this conversation as resolved.
Show resolved Hide resolved
transit_encryption_port = 2999
authorization_config {
access_point_id = "${aws_efs_access_point.test.id}"
jukie marked this conversation as resolved.
Show resolved Hide resolved
iam_enabled = true
jukie marked this conversation as resolved.
Show resolved Hide resolved
}
}
}
}
```


#### Placement Constraints Arguments

* `type` - (Required) The type of constraint. Use `memberOf` to restrict selection to a group of valid candidates.
Expand Down