From 23662ce1a117e426717e036bdc65e582c1e4048c Mon Sep 17 00:00:00 2001 From: badra001 Date: Mon, 1 Mar 2021 12:35:12 -0500 Subject: [PATCH] initial --- .gitignore | 13 +++ .pre-commit-config.yaml | 17 ++++ CHANGELOG.md | 4 + data.tf | 23 +++++ locals.tf | 32 +++++++ main.tf | 119 ++++++++++++++++++++++++++ policies.tf | 15 ++++ prefixes.tf | 12 +++ provider.ldap.tf | 7 ++ templates/iam-role-ldif.east-west.tpl | 13 +++ templates/iam-role-ldif.ew.tpl | 1 + templates/iam-role-ldif.gov.tpl | 1 + templates/iam-role-ldif.govcloud.tpl | 13 +++ variables.common.tf | 26 ++++++ variables.tf | 90 +++++++++++++++++++ version.tf | 3 + 16 files changed, 389 insertions(+) create mode 100644 .gitignore create mode 100644 .pre-commit-config.yaml create mode 100644 CHANGELOG.md create mode 100644 data.tf create mode 100644 locals.tf create mode 100644 main.tf create mode 100644 policies.tf create mode 100644 prefixes.tf create mode 100644 provider.ldap.tf create mode 100644 templates/iam-role-ldif.east-west.tpl create mode 120000 templates/iam-role-ldif.ew.tpl create mode 120000 templates/iam-role-ldif.gov.tpl create mode 100644 templates/iam-role-ldif.govcloud.tpl create mode 100644 variables.common.tf create mode 100644 variables.tf create mode 100644 version.tf diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f4873d7 --- /dev/null +++ b/.gitignore @@ -0,0 +1,13 @@ +# Local .terraform directories +**/.terraform/* + +# .tfstate files +*.tfstate +*.tfstate.* + +# .tfvars files +*.tfvars + +.terraform/* +logs +common/README.md diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..85f5ae4 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,17 @@ +repos: +- repo: https://github.com/antonbabenko/pre-commit-terraform + rev: v1.31.0 + hooks: +# - id: terraform_validate + - id: terraform_fmt + - id: terraform_docs_replace + args: ['table'] + exclude: common/*.tf + exclude: version.tf + +- repo: https://github.com/pre-commit/pre-commit-hooks + rev: v3.1.0 + hooks: + - id: check-symlinks + - id: detect-aws-credentials + - id: detect-private-key diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..e59245c --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,4 @@ +# Versions + +* v1.0.0 -- 20210301 + - initial creation diff --git a/data.tf b/data.tf new file mode 100644 index 0000000..30905b7 --- /dev/null +++ b/data.tf @@ -0,0 +1,23 @@ +data "aws_caller_identity" "current" {} + +data "aws_arn" "current" { + arn = data.aws_caller_identity.current.arn +} + +data "aws_region" "current" {} + +# output "caller_account_id" { +# value = data.aws_caller_identity.current.account_id +# } +# +# output "account_caller_arn" { +# value = data.aws_caller_identity.current.arn +# } +# +# output "account_caller_arn_partition" { +# value = data.aws_arn.current.partition +# } +# +# output "account_region"name" { +# value = data.aws_region.current.name +# } diff --git a/locals.tf b/locals.tf new file mode 100644 index 0000000..7d873ea --- /dev/null +++ b/locals.tf @@ -0,0 +1,32 @@ +locals { + policies = { + "ced-edde" = [ + aws_iam_policy.policy_app.arn, + ] + } + policies_flat = { for e in keys(local.policies) : e => flatten(local.policies[e]) } + policies_count = { for e in keys(local.policies) : e => length(local.policies_flat[e]) } + + # for automatic ldap creation of group + bocappdata_auth = var.aws_environment == "govcloud" ? "Cloud_AWSGovCloud_Auth" : "Cloud_AWS_Auth" + bocappdata_fullauth = { + "ced-edde" = format("gov.census.tco:%s=%s,%s", local.bocappdata_auth, aws_iam_role.role_app.arn, data.terraform_remote_state.common.outputs.inf_saml_provider) + } + region = var.region + # ldap_init = { for e in keys(local.policies) : lookup(var.ldap_init,e,e) => true } + + ldap_exists = { + "ced-edde" = fileexists("setup/${aws_iam_role.role_app.name}.ldif") + } +} + +#--- +# application stuff +#--- +locals { + app_name = "ced-edde" + role_name = format("r-%v", local.app_name) + policy_name = format("p-%v", local.app_name) + ec2_role_name = format("r-ec2-%v", local.app_name) + ec2_policy_name = format("p-ec2-%v-%v", local.app_name, "transcribe") +} diff --git a/main.tf b/main.tf new file mode 100644 index 0000000..de83bb7 --- /dev/null +++ b/main.tf @@ -0,0 +1,119 @@ +/* +* # About aws-iam-role +* +* # Usage +* +* ```hcl +* module "myrole" { +* source = "git@github.e.it.census.gov:terraform-modules/aws-iam-role.gi" +* +* role_name = "my-role" +* saml_provider_arn = "aws:aws-us-gov:iam:1234567890:saml/X" +* enable_ldap_creation = true +* assume_policy_document = data.terraform_remote_state.common.outputs.saml_assume_json +* ec2_assume_policy_document = "X" +* attached_policies = ["arn1", "arn2"] +* ldap_user = "cn=myuser,ou=Application,o=U.S. Census Bureau,c=US" +* ldap_password = "password1234$$" +* +* # optional +* ec2_role_name = "my-role-other" +* enable_instance_role = false +* ec2_attached_policies = [] +* ldap_host = "ldap.e.tco.census.gov" +* ldap_port = 389 +* } +* ``` +*/ + +locals { + account_id = var.account_id != "" ? var.account_id : data.aws_caller_identity.current.account_id + region = data.aws_region.current.name + account_environment = data.aws_arn.current.partition == "aws-us-gov" ? "gov" : "ew" + + _ec2_role_name = var.ec2_role_name != "" ? var.ec2_role_name : var.role_name + role_name = format("%v%v", lookup(local._prefixes, "role", ""), var.role_name) + saml_string = var.saml_provider_arn != "" ? "SAML" : "" + role_description = format("%vRole for %v", local.saml_string, var.role_name) + policy_name = format("%v%v", lookup(local._prefixes, "policy", ""), var.role_name) + ec2_role_name = format("%v-ec2-%v", lookup(local._prefixes, "role", ""), local._ec2_role_name) + ec2_policy_name = format("%v-ec2-%v", lookup(local._prefixes, "policy", ""), local._ec2_role_name) + + ldap_exists = fileexists("${path.root}/setup/${aws_iam_role.role_app.name}.ldif") + bocappdata_auth = local.account_environment == "gov" ? "Cloud_AWSGovCloud_Auth" : "Cloud_AWS_Auth" + bocappdata_fullauth = format("gov.census.tco:%v=%v,%v", local.bocappdata_auth, aws_iam_role.role.arn, var.saml_provider_arn) + + enable_ldap = var.enable_ldap_creation && var.ldap_user != "" && var.ldap_password != "" && var.saml_provider_arn != "" + + base_tags = { + "boc:tf_module_version" = local._module_version + "boc:created_by" = "terraform" + } +} + +resource "aws_iam_role" "role" { + name = local.role_name + description = local.role_description + force_detach_policies = false + max_session_duration = 3600 + # assume_role_policy = data.terraform_remote_state.common.outputs.inf_saml_assume_policy_document + assume_role_policy = var.assume_policy_document + + tags = merge( + var.tags, + local.base_tags, + lookup(var.component_tags, "role", {}), + map("Name", local.role_name) + ) +} + +resource "aws_iam_role_policy_attachment" "role" { + for_each = toset(var.attached_policies) + role = aws_iam_role.role.name + policy_arn = each.value +} + +data "template_file" "role" { + template = file("${path.module}/templates/iam-role-ldif.${local.account_environment}.tpl") + vars = { + role_name = aws_iam_role.role.name + role_arn = aws_iam_role.role.arn + account_id = local.account_id + saml_provider_arn = var.saml_provider_arn + aws_environment = local.account_environment + } +} + +resource "null_resource" "role_ldif" { + count = local.enable_ldap ? 1 : 0 + provisioner "local-exec" { + command = "test -d ${path.root}/setup || mkdir ${path.root}/setup" + } + provisioner "local-exec" { + command = "echo '${data.template_file.role.rendered}' > ${path.root}/setup/${aws_iam_role.role.name}.ldif" + } + provisioner "local-exec" { + command = "echo 'Once complete, execute tf-apply again to create LDAP group'" + } +} + +resource "ldap_object" "role" { + count = local.ldap_exists && local.enable_ldap ? 1 : 0 + provider = ldap + dn = format("cn=%s,ou=%s,ou=AWS,ou=Cloud,ou=Application,o=U.S. Census Bureau,c=US", aws_iam_role.role.name, local.account_id) + object_classes = [ + "top", + "bocGroup", + "groupOfNames", + ] + attributes = [ + { description = format("%s account=%s type=%s", aws_iam_role.role.name, local.account_id, local.account_environment) }, + { cn = aws_iam_role.role.name }, + { bocApplicationData = format("gov.census.tco:CPASS_FullPath=Cloud %s %s", local.account_environment, local.account_id) }, + { bocApplicationData = "gov.census.tco:CPASS_APP=CloudServices" }, + { bocApplicationData = local.bocappdata_fullauth }, + ] + lifecycle { + ignore_changes = [object_classes, attributes] + } +} diff --git a/policies.tf b/policies.tf new file mode 100644 index 0000000..726d3b6 --- /dev/null +++ b/policies.tf @@ -0,0 +1,15 @@ +#---- +# STS: ec2 assume +#--- +data "aws_iam_policy_document" "ec2_assume" { + statement { + sid = "AWSEC2AssumeRole" + effect = "Allow" + actions = ["sts:AssumeRole"] + + principals { + type = "Service" + identifiers = ["ec2.amazonaws.com"] + } + } +} diff --git a/prefixes.tf b/prefixes.tf new file mode 100644 index 0000000..fafcbde --- /dev/null +++ b/prefixes.tf @@ -0,0 +1,12 @@ +locals { + _prefixes = { + "efs" = "v-efs-" + "s3" = "v-s3-" + "ebs" = "v-ebs-" + "kms" = "k-kms-" + "role" = "r-" + "policy" = "p-" + "security-group" = "" + # "security-group" = "sg-" + } +} diff --git a/provider.ldap.tf b/provider.ldap.tf new file mode 100644 index 0000000..a23be2b --- /dev/null +++ b/provider.ldap.tf @@ -0,0 +1,7 @@ +provider "ldap" { + ldap_host = var.ldap_host + ldap_port = var.ldap_port + use_tls = true + bind_user = var.ldap_user + bind_password = var.ldap_password +} diff --git a/templates/iam-role-ldif.east-west.tpl b/templates/iam-role-ldif.east-west.tpl new file mode 100644 index 0000000..eaa395e --- /dev/null +++ b/templates/iam-role-ldif.east-west.tpl @@ -0,0 +1,13 @@ +# fields: role_name role_arn account_id saml_provider_arn aws_environment + +# ${role_name}, ${account_id}, AWS, Cloud, Application, U.S. Census Bureau, US +dn: cn=${role_name},ou=${account_id},ou=AWS,ou=Cloud,ou=Application,o=U.S. Census Bureau,c=US +description: ${role_name} ( ${account_id} ) +cn: ${role_name} +bocApplicationData: gov.census.tco:CPASS_FullPath=Cloud ${aws_environment} ${account_id} +bocApplicationData: gov.census.tco:CPASS_APP=CloudServices +bocApplicationData: gov.census.tco:Cloud_AWS_Auth=${role_arn},${saml_provider_arn} +#bocApplicationData: gov.census.tco:Cloud_AWSGovCloud_Auth=${role_arn},${saml_provider_arn} +objectClass: groupOfNames +objectClass: bocGroup +objectClass: Top diff --git a/templates/iam-role-ldif.ew.tpl b/templates/iam-role-ldif.ew.tpl new file mode 120000 index 0000000..65f8fca --- /dev/null +++ b/templates/iam-role-ldif.ew.tpl @@ -0,0 +1 @@ +iam-role-ldif.east-west.tpl \ No newline at end of file diff --git a/templates/iam-role-ldif.gov.tpl b/templates/iam-role-ldif.gov.tpl new file mode 120000 index 0000000..753ee41 --- /dev/null +++ b/templates/iam-role-ldif.gov.tpl @@ -0,0 +1 @@ +iam-role-ldif.govcloud.tpl \ No newline at end of file diff --git a/templates/iam-role-ldif.govcloud.tpl b/templates/iam-role-ldif.govcloud.tpl new file mode 100644 index 0000000..7499c8d --- /dev/null +++ b/templates/iam-role-ldif.govcloud.tpl @@ -0,0 +1,13 @@ +# fields: role_name role_arn account_id saml_provider_arn aws_environment + +# ${role_name}, ${account_id}, AWS, Cloud, Application, U.S. Census Bureau, US +dn: cn=${role_name},ou=${account_id},ou=AWS,ou=Cloud,ou=Application,o=U.S. Census Bureau,c=US +description: ${role_name} ( ${account_id} ) +cn: ${role_name} +bocApplicationData: gov.census.tco:CPASS_FullPath=Cloud ${aws_environment} ${account_id} +bocApplicationData: gov.census.tco:CPASS_APP=CloudServices +#bocApplicationData: gov.census.tco:Cloud_AWS_Auth=${role_arn},${saml_provider_arn} +bocApplicationData: gov.census.tco:Cloud_AWSGovCloud_Auth=${role_arn},${saml_provider_arn} +objectClass: groupOfNames +objectClass: bocGroup +objectClass: Top diff --git a/variables.common.tf b/variables.common.tf new file mode 100644 index 0000000..2f1a864 --- /dev/null +++ b/variables.common.tf @@ -0,0 +1,26 @@ +#--- +# account info +#--- +variable "account_id" { + description = "AWS Account ID (default will pull from current user)" + type = string + default = "" +} + +variable "account_alias" { + description = "AWS Account Alias" + type = string + default = "" +} + +variable "override_prefixes" { + description = "Override built-in prefixes by component (role, policy). This should be used primarily for common infrastructure things" + type = map(string) + default = {} +} + +variable "tags" { + description = "AWS Tags to apply to appropriate resources (S3, KMS). Do not include safeguard tags here, use the data_safeguard field for such things." + type = map(string) + default = {} +} diff --git a/variables.tf b/variables.tf new file mode 100644 index 0000000..5f5dae8 --- /dev/null +++ b/variables.tf @@ -0,0 +1,90 @@ +#--- +# application stuff +#--- +#locals { +# app_name = "ced-edde" +# role_name = format("r-%v", local.app_name) +# policy_name = format("p-%v", local.app_name) +# ec2_role_name = format("r-ec2-%v", local.app_name) +# ec2_policy_name = format("p-ec2-%v-%v", local.app_name, "transcribe") +#} + +variable "role_name" { + description = "Role/application name without prefix" + type = string +} + +variable "ec2_role_name" { + description = "EC2 instace Role/application name without prefix" + type = string + default = "" +} + +variable "saml_provider_arn" { + description = "ARN of SAML Provider" + type = string + default = "" +} + +variable "enable_ldap_creation" { + description = "Flag to enable/disable LDAP object creation for role group (for SAML only). Also requires LDAP credentials." + type = boolean + default = false +} + +variable "enable_instance_role" { + description = "Flag to enable the creation of a partner EC2 instance role with specific policies and optionally a different name" + type = boolean + default = false +} + +variable "assume_policy_document" { + description = "JSON policy document for role to assume (i.e., the SAML assume document)" + type = string + default = "" +} + +variable "ec2_assume_policy_document" { + description = "JSON policy document for EC2 instance role (default is sts:AssumeRole for ec2 service)" + type = string + default = "" +} + +variable "attached_policies" { + description = "List of IAM Policy ARNs to attach to this role" + type = list(string) + default = [] +} + +variable "ec2_attached_policies" { + description = "List of IAM Policy ARNs to attach to this EC2 instance role" + type = list(string) + default = [] +} + +#--- +# ldap +#--- +variable "ldap_user" { + description = "LDAP user for writing data into eDirectory or Active Directory" + type = string + default = "" +} + +variable "ldap_password" { + description = "LDAP password for ldap_user for writing data into eDirectory or Active Directory" + type = string + default = "" +} + +variable "ldap_host" { + description = "LDAP Hostname (default is for eBOCAS)" + type = string + default = "ldap.e.tco.census.gov" +} + +variable "ldap_port" { + description = "LDAP port (default is 389 but also using STARTTLS)" + type = number + default = 389 +} diff --git a/version.tf b/version.tf new file mode 100644 index 0000000..fa2705b --- /dev/null +++ b/version.tf @@ -0,0 +1,3 @@ +locals { + _module_version = "1.0.0" +}