diff --git a/README.md b/README.md index fc8ff96..950226a 100644 --- a/README.md +++ b/README.md @@ -75,20 +75,16 @@ module "ec2_test" { ### User Data ```hcl-terraform -user_data = [ - { - path = { - folder_name = "linux", - file_name = "test.sh" - } - vars = { - test-var1 = "test1", - test-var2 = "test2" - } - }, - ... - ] - + user_data = templatefile("${path.module}/../../shellscripts/linux/ud-os-join-ad.sh", { + aws_region = var.aws_region + domain_name = local.domain_name + dom_disname = local.dom_disname + ou_env = var.lin_prod_ou_env + linux_admins_ad_group = var.linux_admins_ad_group + domain_join_user_name = var.domain_join_user_name + sm_djuser_path = "${var.ad_secrets_path}${var.domain_join_user_name}" + is_asg = "false" + }) ``` ### Security Groups @@ -175,7 +171,7 @@ module "ad2" { | Name | Source | Version | |------|--------|---------| -| [security\_group](#module\_security\_group) | github.com/Coalfire-CF/terraform-aws-securitygroup | n/a | +| [security\_group](#module\_security\_group) | github.com/Coalfire-CF/terraform-aws-securitygroup | v1.0.0 | ## Resources @@ -216,12 +212,12 @@ module "ad2" { | [egress\_rules](#input\_egress\_rules) | The list of rules for egress traffic. Required fields for each rule are 'protocol', 'from\_port', 'to\_port', and at least one of 'cidr\_blocks', 'ipv6\_cidr\_blocks', 'security\_groups', 'self', or 'prefix\_list\_sg'. Optional fields are 'description' and those not used from the previous list |
list(object({| `[]` | no | | [get\_password\_data](#input\_get\_password\_data) | Whether or not to allow retrieval of the local admin password | `bool` | `false` | no | | [global\_tags](#input\_global\_tags) | a map of strings that contains global level tags | `map(string)` | n/a | yes | +| [http\_tokens](#input\_http\_tokens) | Whether or not the metadata service requires session tokens, required=IMDSv2, optional=IMDSv1 | `any` | `"required"` | no | | [iam\_policies](#input\_iam\_policies) | A list of the iam policy ARNs to attach to the IAM role | `list(string)` | `[]` | no | | [iam\_profile](#input\_iam\_profile) | A variable to attach an existing iam profile to the ec2 instance(s) created | `string` | `""` | no | | [ingress\_rules](#input\_ingress\_rules) | The list of rules for ingress traffic. Required fields for each rule are 'protocol', 'from\_port', 'to\_port', and at least one of 'cidr\_blocks', 'ipv6\_cidr\_blocks', 'security\_groups', 'self', or 'prefix\_list\_sg'. Optional fields are 'description' and those not used from the previous list |
protocol = string
from_port = string
to_port = string
cidr_blocks = optional(list(string), [])
ipv6_cidr_blocks = optional(list(string), [])
prefix_list_ids = optional(list(string), [])
security_groups = optional(list(string), [])
self = optional(bool)
description = optional(string, "Managed by Terraform")
}))
list(object({| `[]` | no | | [instance\_count](#input\_instance\_count) | Number of instances to launch | `number` | `1` | no | | [keys\_to\_grant](#input\_keys\_to\_grant) | A list of kms keys to grant permissions to for the role created. | `list(string)` | `[]` | no | -| [module\_depends\_on](#input\_module\_depends\_on) | A variable to simulate the depends on feature that resources have | `any` | `null` | no | | [name](#input\_name) | The name of the ec2 instance | `string` | n/a | yes | | [private\_ip](#input\_private\_ip) | The private ip for the instance | `string` | `null` | no | | [root\_volume\_size](#input\_root\_volume\_size) | The size of the root ebs volume on the ec2 instances created | `string` | n/a | yes | @@ -231,7 +227,7 @@ module "ad2" { | [subnet\_ids](#input\_subnet\_ids) | A list of the subnets to be used when provisioning ec2 instances. If instance count is 1, only the first subnet will be used | `list(string)` | n/a | yes | | [tags](#input\_tags) | A mapping of tags to assign to the resource | `map(string)` | `{}` | no | | [target\_group\_arns](#input\_target\_group\_arns) | A list of aws\_alb\_target\_group ARNs, for use with Application Load Balancing | `list(string)` | `[]` | no | -| [user\_data](#input\_user\_data) | The user data to provide when launching the instance. Do not pass gzip-compressed data via this argument; see user\_data\_base64 instead | `string` | `null` | no | +| [user\_data](#input\_user\_data) | The User Data script to run | `string` | `null` | no | | [user\_data\_base64](#input\_user\_data\_base64) | Can be used instead of user\_data to pass base64-encoded binary data directly. Use this instead of user\_data whenever the value is not a valid UTF-8 string. For example, gzip-encoded user data must be base64-encoded and passed via this argument to avoid corruption | `string` | `null` | no | | [user\_data\_replace\_on\_change](#input\_user\_data\_replace\_on\_change) | When used in combination with user\_data or user\_data\_base64 will trigger a destroy and recreate when set to true. Defaults to false if not set | `bool` | `null` | no | | [vpc\_id](#input\_vpc\_id) | The id of the vpc where resources are being created | `string` | n/a | yes | diff --git a/examples/simple/main.tf b/examples/simple/main.tf index 803bc55..af3bf1d 100644 --- a/examples/simple/main.tf +++ b/examples/simple/main.tf @@ -33,6 +33,17 @@ module "ec2_test" { ec2_key_pair = "ec2-module-test" ebs_kms_key_arn = aws_kms_key.ebs_key.arn + user_data = templatefile("${path.module}/../../shellscripts/linux/ud-os-join-ad.sh", { + aws_region = var.aws_region + domain_name = local.domain_name + dom_disname = local.dom_disname + ou_env = var.lin_prod_ou_env + linux_admins_ad_group = var.linux_admins_ad_group + domain_join_user_name = var.domain_join_user_name + sm_djuser_path = "${var.ad_secrets_path}${var.domain_join_user_name}" + is_asg = "false" + }) + # EBS ebs_volumes = [ { diff --git a/examples/simple/userdata/ud-os-join-ad.sh b/examples/simple/userdata/ud-os-join-ad.sh new file mode 100644 index 0000000..a1092d4 --- /dev/null +++ b/examples/simple/userdata/ud-os-join-ad.sh @@ -0,0 +1,124 @@ +#!/bin/bash -xe +# Send the following variables from terraform: +#${aws_region} +#${is_asg} - True/False - Auto Scaling Group? +#${domain_name} - Domain Name: example.com +#${dom_disname} - dc=local,dc=fastramp,dc=internal +#${ou_env} - OU=Linux,OU=Production,OU=Management,OU=Servers +#${linux_admins_ad_group} - linuxadmins +#${domain_join_user_name} - svc_dj +#${sm_djuser_path} - /production/mgmt/ad/svc_dj + +set -o nounset + +linux_admins_ad_group=${linux_admins_ad_group} + +# Get IMDSv2 token +TOKEN=$(curl -X PUT 'http://169.254.169.254/latest/api/token' -H 'X-aws-ec2-metadata-token-ttl-seconds: 21600') + +# IF ASG is set - tag instanceID to compname and append, then check for 15 char length +instanceID=$(curl -H "X-aws-ec2-metadata-token: $TOKEN" -s "http://169.254.169.254/1.0/meta-data/instance-id") +hostname="$(aws ec2 describe-tags --region ${aws_region} --filters "Name=resource-id, Values=$instanceID" "Name=key, Values=Name" | jq -r '.Tags[].Value')" + +# Truncate hostname to meet AD 15-char. requirement +if ${is_asg} ; then + instanceIDAppnd=$(curl -H "X-aws-ec2-metadata-token: $TOKEN" -s "http://169.254.169.254/1.0/meta-data/instance-id" | cut -c 3-) + hostname=$(echo "$hostname" | cut -c1-6) + hostname="$hostname-$instanceIDAppnd" + hostname=$(echo "$hostname" | cut -c1-15) +else + hostname=$(echo "$hostname" | cut -c1-15) +fi + +# Set hostname via hostnamectl set-hostname +echo "Setting hostname to $hostname.${domain_name}" +hostnamectl set-hostname "$hostname"."${domain_name}" --no-ask-password + +# Set the new host name in /etc/hosts or rsyslog doesn't log new hostname. +sed -i "/127.0.0.1/i\127.0.0.1 $hostname $hostname.${domain_name}" /etc/hosts + +# Bounce rsyslogd to grab the new hostname. +systemctl restart rsyslog + +# Set default realm for Ubuntu +domain_upper=$(echo "${domain_name}" | tr '[:lower:]' '[:upper:]') +if [[ $(uname -a | tr '[:upper:]' '[:lower:]') =~ "ubuntu" ]]; then + cat > /etc/krb5.conf <
protocol = string
from_port = string
to_port = string
cidr_blocks = optional(list(string), [])
ipv6_cidr_blocks = optional(list(string), [])
prefix_list_ids = optional(list(string), [])
security_groups = optional(list(string), [])
self = optional(bool)
description = optional(string, "Managed by Terraform")
}))