Skip to content

Commit 654d7d2

Browse files
feat: Add support for credentialSpecs on container definition to enable Windows gMSA (#368)
* feat(container): Add support for credentialSpecs to enable Windows gMSA * Update modules/container-definition/variables.tf Co-authored-by: Bryant Biggs <bryantbiggs@gmail.com> * propogate to all instances from root variables.tf * propogate to all instances from root variables.tf * original format * original format * original format * original format * reformat * added wrapper main * reorder alphabetical * ignore tf naming convention * fix: final wrapper * apply pre-commit --------- Co-authored-by: Bryant Biggs <bryantbiggs@gmail.com>
1 parent b8e6335 commit 654d7d2

File tree

9 files changed

+19
-6
lines changed

9 files changed

+19
-6
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

modules/container-definition/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,7 @@ No modules.
147147
| <a name="input_command"></a> [command](#input\_command) | The command that's passed to the container | `list(string)` | `null` | no |
148148
| <a name="input_cpu"></a> [cpu](#input\_cpu) | The number of cpu units to reserve for the container. This is optional for tasks using Fargate launch type and the total amount of `cpu` of all containers in a task will need to be lower than the task-level cpu value | `number` | `null` | no |
149149
| <a name="input_create_cloudwatch_log_group"></a> [create\_cloudwatch\_log\_group](#input\_create\_cloudwatch\_log\_group) | Determines whether a log group is created by this module. If not, AWS will automatically create one if logging is enabled | `bool` | `true` | no |
150+
| <a name="input_credentialSpecs"></a> [credentialSpecs](#input\_credentialSpecs) | Specs for Credentials for gMSA (Windows containers). | `list(string)` | `null` | no |
150151
| <a name="input_dependsOn"></a> [dependsOn](#input\_dependsOn) | The dependencies defined for container startup and shutdown. A container can contain multiple dependencies. When a dependency is defined for container startup, for container shutdown it is reversed. The condition can be one of START, COMPLETE, SUCCESS or HEALTHY | <pre>list(object({<br/> condition = string<br/> containerName = string<br/> }))</pre> | `null` | no |
151152
| <a name="input_disableNetworking"></a> [disableNetworking](#input\_disableNetworking) | When this parameter is true, networking is disabled within the container | `bool` | `null` | no |
152153
| <a name="input_dnsSearchDomains"></a> [dnsSearchDomains](#input\_dnsSearchDomains) | Container DNS search domains. A list of DNS search domains that are presented to the container | `list(string)` | `null` | no |

modules/container-definition/main.tf

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ locals {
3939
definition = {
4040
command = var.command
4141
cpu = var.cpu
42+
credentialSpecs = var.credentialSpecs
4243
dependsOn = var.dependsOn
4344
disableNetworking = local.is_not_windows ? var.disableNetworking : null
4445
dnsSearchDomains = local.is_not_windows ? var.dnsSearchDomains : null

modules/container-definition/variables.tf

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,13 @@ variable "cpu" {
3434
default = null
3535
}
3636

37+
# tflint-ignore: terraform_naming_convention
38+
variable "credentialSpecs" {
39+
description = "Specs for Credentials for gMSA (Windows containers)."
40+
type = list(string)
41+
default = null
42+
}
43+
3744
# tflint-ignore: terraform_naming_convention
3845
variable "dependsOn" {
3946
description = "The dependencies defined for container startup and shutdown. A container can contain multiple dependencies. When a dependency is defined for container startup, for container shutdown it is reversed. The condition can be one of START, COMPLETE, SUCCESS or HEALTHY"

modules/service/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,7 @@ module "ecs_service" {
238238
| <a name="input_availability_zone_rebalancing"></a> [availability\_zone\_rebalancing](#input\_availability\_zone\_rebalancing) | ECS automatically redistributes tasks within a service across Availability Zones (AZs) to mitigate the risk of impaired application availability due to underlying infrastructure failures and task lifecycle activities. The valid values are `ENABLED` and `DISABLED`. Defaults to `DISABLED` | `string` | `null` | no |
239239
| <a name="input_capacity_provider_strategy"></a> [capacity\_provider\_strategy](#input\_capacity\_provider\_strategy) | Capacity provider strategies to use for the service. Can be one or more | <pre>map(object({<br/> base = optional(number)<br/> capacity_provider = string<br/> weight = optional(number)<br/> }))</pre> | `null` | no |
240240
| <a name="input_cluster_arn"></a> [cluster\_arn](#input\_cluster\_arn) | ARN of the ECS cluster where the resources will be provisioned | `string` | `""` | no |
241-
| <a name="input_container_definitions"></a> [container\_definitions](#input\_container\_definitions) | A map of valid [container definitions](http://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_ContainerDefinition.html). Please note that you should only provide values that are part of the container definition document | <pre>map(object({<br/> create = optional(bool, true)<br/> operating_system_family = optional(string)<br/> tags = optional(map(string))<br/><br/> # Container definition<br/> command = optional(list(string))<br/> cpu = optional(number)<br/> dependsOn = optional(list(object({<br/> condition = string<br/> containerName = string<br/> })))<br/> disableNetworking = optional(bool)<br/> dnsSearchDomains = optional(list(string))<br/> dnsServers = optional(list(string))<br/> dockerLabels = optional(map(string))<br/> dockerSecurityOptions = optional(list(string))<br/> # enable_execute_command = optional(bool, false) Set in standalone variable<br/> entrypoint = optional(list(string))<br/> environment = optional(list(object({<br/> name = string<br/> value = string<br/> })))<br/> environmentFiles = optional(list(object({<br/> type = string<br/> value = string<br/> })))<br/> essential = optional(bool)<br/> extraHosts = optional(list(object({<br/> hostname = string<br/> ipAddress = string<br/> })))<br/> firelensConfiguration = optional(object({<br/> options = optional(map(string))<br/> type = optional(string)<br/> }))<br/> healthCheck = optional(object({<br/> command = optional(list(string), [])<br/> interval = optional(number, 30)<br/> retries = optional(number, 3)<br/> startPeriod = optional(number)<br/> timeout = optional(number, 5)<br/> }))<br/> hostname = optional(string)<br/> image = optional(string)<br/> interactive = optional(bool)<br/> links = optional(list(string))<br/> linuxParameters = optional(object({<br/> capabilities = optional(object({<br/> add = optional(list(string))<br/> drop = optional(list(string))<br/> }))<br/> devices = optional(list(object({<br/> containerPath = optional(string)<br/> hostPath = optional(string)<br/> permissions = optional(list(string))<br/> })))<br/> initProcessEnabled = optional(bool)<br/> maxSwap = optional(number)<br/> sharedMemorySize = optional(number)<br/> swappiness = optional(number)<br/> tmpfs = optional(list(object({<br/> containerPath = string<br/> mountOptions = optional(list(string))<br/> size = number<br/> })))<br/> }))<br/> logConfiguration = optional(object({<br/> logDriver = optional(string)<br/> options = optional(map(string))<br/> secretOptions = optional(list(object({<br/> name = string<br/> valueFrom = string<br/> })))<br/> }))<br/> memory = optional(number)<br/> memoryReservation = optional(number)<br/> mountPoints = optional(list(object({<br/> containerPath = optional(string)<br/> readOnly = optional(bool)<br/> sourceVolume = optional(string)<br/> })))<br/> name = optional(string)<br/> portMappings = optional(list(object({<br/> appProtocol = optional(string)<br/> containerPort = optional(number)<br/> containerPortRange = optional(string)<br/> hostPort = optional(number)<br/> name = optional(string)<br/> protocol = optional(string)<br/> })))<br/> privileged = optional(bool)<br/> pseudoTerminal = optional(bool)<br/> readonlyRootFilesystem = optional(bool)<br/> repositoryCredentials = optional(object({<br/> credentialsParameter = optional(string)<br/> }))<br/> resourceRequirements = optional(list(object({<br/> type = string<br/> value = string<br/> })))<br/> restartPolicy = optional(object({<br/> enabled = optional(bool)<br/> ignoredExitCodes = optional(list(number))<br/> restartAttemptPeriod = optional(number)<br/> })<br/> )<br/> secrets = optional(list(object({<br/> name = string<br/> valueFrom = string<br/> })))<br/> startTimeout = optional(number, 30)<br/> stopTimeout = optional(number, 120)<br/> systemControls = optional(list(object({<br/> namespace = optional(string)<br/> value = optional(string)<br/> })))<br/> ulimits = optional(list(object({<br/> hardLimit = number<br/> name = string<br/> softLimit = number<br/> })))<br/> user = optional(string)<br/> versionConsistency = optional(string)<br/> volumesFrom = optional(list(object({<br/> readOnly = optional(bool)<br/> sourceContainer = optional(string)<br/> })))<br/> workingDirectory = optional(string)<br/><br/> # Cloudwatch Log Group<br/> service = optional(string)<br/> enable_cloudwatch_logging = optional(bool)<br/> create_cloudwatch_log_group = optional(bool)<br/> cloudwatch_log_group_name = optional(string)<br/> cloudwatch_log_group_use_name_prefix = optional(bool)<br/> cloudwatch_log_group_class = optional(string)<br/> cloudwatch_log_group_retention_in_days = optional(number)<br/> cloudwatch_log_group_kms_key_id = optional(string)<br/> }))</pre> | `{}` | no |
241+
| <a name="input_container_definitions"></a> [container\_definitions](#input\_container\_definitions) | A map of valid [container definitions](http://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_ContainerDefinition.html). Please note that you should only provide values that are part of the container definition document | <pre>map(object({<br/> create = optional(bool, true)<br/> operating_system_family = optional(string)<br/> tags = optional(map(string))<br/><br/> # Container definition<br/> command = optional(list(string))<br/> cpu = optional(number)<br/> credentialSpecs = optional(list(string))<br/> dependsOn = optional(list(object({<br/> condition = string<br/> containerName = string<br/> })))<br/> disableNetworking = optional(bool)<br/> dnsSearchDomains = optional(list(string))<br/> dnsServers = optional(list(string))<br/> dockerLabels = optional(map(string))<br/> dockerSecurityOptions = optional(list(string))<br/> # enable_execute_command = optional(bool, false) Set in standalone variable<br/> entrypoint = optional(list(string))<br/> environment = optional(list(object({<br/> name = string<br/> value = string<br/> })))<br/> environmentFiles = optional(list(object({<br/> type = string<br/> value = string<br/> })))<br/> essential = optional(bool)<br/> extraHosts = optional(list(object({<br/> hostname = string<br/> ipAddress = string<br/> })))<br/> firelensConfiguration = optional(object({<br/> options = optional(map(string))<br/> type = optional(string)<br/> }))<br/> healthCheck = optional(object({<br/> command = optional(list(string), [])<br/> interval = optional(number, 30)<br/> retries = optional(number, 3)<br/> startPeriod = optional(number)<br/> timeout = optional(number, 5)<br/> }))<br/> hostname = optional(string)<br/> image = optional(string)<br/> interactive = optional(bool)<br/> links = optional(list(string))<br/> linuxParameters = optional(object({<br/> capabilities = optional(object({<br/> add = optional(list(string))<br/> drop = optional(list(string))<br/> }))<br/> devices = optional(list(object({<br/> containerPath = optional(string)<br/> hostPath = optional(string)<br/> permissions = optional(list(string))<br/> })))<br/> initProcessEnabled = optional(bool)<br/> maxSwap = optional(number)<br/> sharedMemorySize = optional(number)<br/> swappiness = optional(number)<br/> tmpfs = optional(list(object({<br/> containerPath = string<br/> mountOptions = optional(list(string))<br/> size = number<br/> })))<br/> }))<br/> logConfiguration = optional(object({<br/> logDriver = optional(string)<br/> options = optional(map(string))<br/> secretOptions = optional(list(object({<br/> name = string<br/> valueFrom = string<br/> })))<br/> }))<br/> memory = optional(number)<br/> memoryReservation = optional(number)<br/> mountPoints = optional(list(object({<br/> containerPath = optional(string)<br/> readOnly = optional(bool)<br/> sourceVolume = optional(string)<br/> })))<br/> name = optional(string)<br/> portMappings = optional(list(object({<br/> appProtocol = optional(string)<br/> containerPort = optional(number)<br/> containerPortRange = optional(string)<br/> hostPort = optional(number)<br/> name = optional(string)<br/> protocol = optional(string)<br/> })))<br/> privileged = optional(bool)<br/> pseudoTerminal = optional(bool)<br/> readonlyRootFilesystem = optional(bool)<br/> repositoryCredentials = optional(object({<br/> credentialsParameter = optional(string)<br/> }))<br/> resourceRequirements = optional(list(object({<br/> type = string<br/> value = string<br/> })))<br/> restartPolicy = optional(object({<br/> enabled = optional(bool)<br/> ignoredExitCodes = optional(list(number))<br/> restartAttemptPeriod = optional(number)<br/> })<br/> )<br/> secrets = optional(list(object({<br/> name = string<br/> valueFrom = string<br/> })))<br/> startTimeout = optional(number, 30)<br/> stopTimeout = optional(number, 120)<br/> systemControls = optional(list(object({<br/> namespace = optional(string)<br/> value = optional(string)<br/> })))<br/> ulimits = optional(list(object({<br/> hardLimit = number<br/> name = string<br/> softLimit = number<br/> })))<br/> user = optional(string)<br/> versionConsistency = optional(string)<br/> volumesFrom = optional(list(object({<br/> readOnly = optional(bool)<br/> sourceContainer = optional(string)<br/> })))<br/> workingDirectory = optional(string)<br/><br/> # Cloudwatch Log Group<br/> service = optional(string)<br/> enable_cloudwatch_logging = optional(bool)<br/> create_cloudwatch_log_group = optional(bool)<br/> cloudwatch_log_group_name = optional(string)<br/> cloudwatch_log_group_use_name_prefix = optional(bool)<br/> cloudwatch_log_group_class = optional(string)<br/> cloudwatch_log_group_retention_in_days = optional(number)<br/> cloudwatch_log_group_kms_key_id = optional(string)<br/> }))</pre> | `{}` | no |
242242
| <a name="input_cpu"></a> [cpu](#input\_cpu) | Number of cpu units used by the task. If the `requires_compatibilities` is `FARGATE` this field is required | `number` | `1024` | no |
243243
| <a name="input_create"></a> [create](#input\_create) | Determines whether resources will be created (affects all resources) | `bool` | `true` | no |
244244
| <a name="input_create_iam_role"></a> [create\_iam\_role](#input\_create\_iam\_role) | Determines whether the ECS service IAM role should be created | `bool` | `true` | no |

modules/service/main.tf

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -814,6 +814,7 @@ module "container_definition" {
814814
# Container Definition
815815
command = each.value.command
816816
cpu = each.value.cpu
817+
credentialSpecs = each.value.credentialSpecs
817818
dependsOn = each.value.dependsOn
818819
disableNetworking = each.value.disableNetworking
819820
dnsSearchDomains = each.value.dnsSearchDomains

modules/service/variables.tf

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -475,8 +475,9 @@ variable "container_definitions" {
475475
tags = optional(map(string))
476476

477477
# Container definition
478-
command = optional(list(string))
479-
cpu = optional(number)
478+
command = optional(list(string))
479+
cpu = optional(number)
480+
credentialSpecs = optional(list(string))
480481
dependsOn = optional(list(object({
481482
condition = string
482483
containerName = string

variables.tf

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -445,8 +445,9 @@ variable "services" {
445445
tags = optional(map(string))
446446

447447
# Container definition
448-
command = optional(list(string))
449-
cpu = optional(number)
448+
command = optional(list(string))
449+
cpu = optional(number)
450+
credentialSpecs = optional(list(string))
450451
dependsOn = optional(list(object({
451452
condition = string
452453
containerName = string

wrappers/container-definition/main.tf

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ module "wrapper" {
1111
command = try(each.value.command, var.defaults.command, null)
1212
cpu = try(each.value.cpu, var.defaults.cpu, null)
1313
create_cloudwatch_log_group = try(each.value.create_cloudwatch_log_group, var.defaults.create_cloudwatch_log_group, true)
14+
credentialSpecs = try(each.value.credentialSpecs, var.defaults.credentialSpecs, null)
1415
dependsOn = try(each.value.dependsOn, var.defaults.dependsOn, null)
1516
disableNetworking = try(each.value.disableNetworking, var.defaults.disableNetworking, null)
1617
dnsSearchDomains = try(each.value.dnsSearchDomains, var.defaults.dnsSearchDomains, null)

0 commit comments

Comments
 (0)