Skip to content

Commit

Permalink
* 2.4.0 -- 2025-07-29
Browse files Browse the repository at this point in the history
  - move things to common
  - make submodule rolesanywhere
  • Loading branch information
badra001 committed Jul 29, 2025
1 parent 092a9b5 commit 0f64499
Show file tree
Hide file tree
Showing 24 changed files with 399 additions and 72 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,5 @@

.terraform/*
logs
X
Y
6 changes: 5 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

* v1.0.1 -- 20210301
- add docs
- comment out ec2* role stuff
- comment out ec2 role stuff
- add check for ldap provider

* v1.0.2 -- 20210402
Expand Down Expand Up @@ -98,3 +98,7 @@ tag: 2.0.1

* 2.3.3 -- 2024-06-17
- enable override_prefixes to actually work

* 2.4.0 -- 2025-07-29
- move things to common
- make submodule rolesanywhere
23 changes: 23 additions & 0 deletions common/data.tf
Original file line number Diff line number Diff line change
@@ -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
# }
26 changes: 26 additions & 0 deletions common/variables.common.tf
Original file line number Diff line number Diff line change
@@ -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 = {}
}
3 changes: 3 additions & 0 deletions common/version.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
locals {
_module_version = "2.4.0"
}
18 changes: 18 additions & 0 deletions common/versions.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# tf 0.13+
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = ">= 3.66.0"
}
ldap = {
source = "trevex/ldap"
version = ">= 0.5.4"
}
external = {
source = "hashicorp/external"
version = ">= 2.2.0"
}
}
required_version = ">= 0.13"
}
23 changes: 0 additions & 23 deletions data.tf

This file was deleted.

1 change: 1 addition & 0 deletions data.tf
13 changes: 13 additions & 0 deletions rolesanywhere/aws_config.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
resource "local_file" "aws_config_file" {
filename = format("%v/%v.%v", "./certs", local.role_name, "aws_config")
file_permission = "0644"
directory_permission = "0755"
content = templatefile("aws_config.tpl", {
account_alias = var.account_alias
role_name = local.role_name
role_arn = aws_iam_role.role.arn
trust_anchor_arn = local.this_trust_arn
profile_arn = aws_rolesanywhere_profile.role.arn
region = var.region
})
}
3 changes: 3 additions & 0 deletions rolesanywhere/aws_config.tpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[profile ${account_alias}.${role_name}]
region = ${region}
credential_process = aws_signing_helper credential-process --certificate CERTPATH/${role_name}.crt --private-key CERTPATH/${role_name}.key --trust-anchor-arn ${trust_anchor_arn} --profile-arn ${profile_arn} --role-arn ${role_arn} --region ${region}
28 changes: 28 additions & 0 deletions rolesanywhere/certificate.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
module "certificate" {
source = "git@github.e.it.census.gov:terraform-modules/aws-certificates//acmpca-iam-rolesanywhere"

role_name = local.role_name
contact_email = var.contact_group_email
certificate_subject_ou = local.certificate_subject_ou["x509Subject/OU"]
validity_days = var.validity_days
}

locals {
this_trust_arn = try(([for k, v in local.trust_ca[var.region] : v if v.ca_name == module.certificate.certificate_authority_name])[0].trust_arn, null)
}

## output "certificate_subject" {
## value = module.certificate.certificate_subject
## }
##
## output "certificate_details" {
## value = module.certificate.certificate_details
## }
##
## output "certificate_issuer_details" {
## value = module.certificate.certificate_issuer_details
## }
##
## output "certificate_issuer_subject" {
## value = module.certificate.certificate_issuer_subject
## }
42 changes: 42 additions & 0 deletions rolesanywhere/data.ssm.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
data "aws_ssm_parameters_by_path" "trust_east" {
provider = aws.east
path = "/enterprise/rolesanywhere/trustanchor/"
recursive = true
}

data "aws_ssm_parameters_by_path" "trust_west" {
provider = aws.west
path = "/enterprise/rolesanywhere/trustanchor/"
recursive = true
}

locals {
trust_east_arns = zipmap(data.aws_ssm_parameters_by_path.trust_east.names, data.aws_ssm_parameters_by_path.trust_east.arns)
trust_east_values = zipmap(data.aws_ssm_parameters_by_path.trust_east.names, nonsensitive(data.aws_ssm_parameters_by_path.trust_east.values))
_trust_east_ca = { for v in data.aws_ssm_parameters_by_path.trust_east.names : v => slice(reverse(split("/", v)), 0, 2) }
trust_east_ca = { for k, v in local._trust_east_ca : k => {
label = k
region = "us-gov-east-1"
ca_name = v[0]
ssm_parameter_name = k
ssm_paraemter_arn = local.trust_east_arns[k]
trust_arn = local.trust_east_values[k]
} }

trust_west_arns = zipmap(data.aws_ssm_parameters_by_path.trust_west.names, data.aws_ssm_parameters_by_path.trust_west.arns)
trust_west_values = zipmap(data.aws_ssm_parameters_by_path.trust_west.names, nonsensitive(data.aws_ssm_parameters_by_path.trust_west.values))
_trust_west_ca = { for v in data.aws_ssm_parameters_by_path.trust_west.names : v => slice(reverse(split("/", v)), 0, 2) }
trust_west_ca = { for k, v in local._trust_west_ca : k => {
label = k
region = "us-gov-west-1"
ca_name = v[0]
ssm_parameter_name = k
ssm_paraemter_arn = local.trust_west_arns[k]
trust_arn = local.trust_west_values[k]
} }

trust_ca = {
"us-gov-east-1" = local.trust_east_ca
"us-gov-west-1" = local.trust_west_ca
}
}
1 change: 1 addition & 0 deletions rolesanywhere/data.tf
16 changes: 16 additions & 0 deletions rolesanywhere/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
locals {
base_tags = {
"boc:tf_module_version" = local._module_version
"boc:created_by" = "terraform"
}
}

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"
account_alias = var.account_alias != "" && var.account_alias != null ? var.account_alias : "none"

role_name = format("%v%v", lookup(local._prefixes, "role", ""), var.role_name)
role_description = var.role_description == "" ? format("%vRole for %v", local.saml_string, var.role_name) : var.role_description
}
9 changes: 9 additions & 0 deletions rolesanywhere/outputs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
output "role_arn" {
description = "Created role ARN"
value = aws_iam_role.role.arn
}

output "role_name" {
description = "Created role name"
value = aws_iam_role.role.name
}
3 changes: 3 additions & 0 deletions rolesanywhere/region.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
locals {
region = var.region
}
95 changes: 95 additions & 0 deletions rolesanywhere/role.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
locals {
certificate_subject_ou = { "x509Subject/OU" = lookup(var.certificate_conditions, "x509Subject/OU", format("IAM RolesAnywhere %v", data.aws_caller_identity.current.account_id)) }
certificate_conditions = merge(
local.certificate_subject_ou,
var.certificate_conditions,
{ "x509Subject/CN" = local.role_name },
)
}

resource "aws_rolesanywhere_profile" "role" {
name = local.role_name
enabled = true
duration_seconds = var.max_session_duration
role_arns = [aws_iam_role.role.arn]

tags = merge(
local.base_tags,
var.tags,
{ Name = local.role_name },
)
}

resource "aws_iam_role" "role" {
name = local.role_name
description = local.role_description
force_detach_policies = local._defaults["force_detach_policies"]
max_session_duration = var.max_session_duration
assume_role_policy = data.aws_iam_policy_document.role_anywhere_assume.json
managed_policy_arns = var.managed_policy_arns


tags = merge(
local.base_tags,
var.tags,
lookup(var.component_tags, "role", {}),
{ Name = local.role_name },
)
}

resource "aws_iam_role_policy_attachment" "role" {
for_each = var.create ? toset(var.attached_policies) : toset([])
role = var.create ? aws_iam_role.role[0].name : ""
policy_arn = each.value
}

resource "aws_iam_role_policy" "role" {
for_each = { for p in var.inline_policies : p.name => p.policy }
role = aws_iam_role.role.arn
name = each.key
policy = each.value
}


data "aws_iam_policy_document" "role_anywhere_assume" {
statement {
sid = "RolesAnywhereTrust"
effect = "Allow"
actions = [
"sts:AssumeRole",
"sts:TagSession",
"sts:SetSourceIdentity",
]
principals {
type = "Service"
identifiers = ["rolesanywhere.amazonaws.com"]
}
condition {
test = "ForAnyValue:StringEquals"
variable = "aws:SourceArn"
values = concat(nonsensitive(data.aws_ssm_parameters_by_path.trust_east.values), nonsensitive(data.aws_ssm_parameters_by_path.trust_west.values))
}
# include condition for certificate
dynamic "condition" {
for_each = local.certificate_conditions
iterator = c
content {
test = "StringEquals"
variable = format("aws:PrincipalTag/%v", c.key)
values = [c.value]
}
}
}
}


## "Condition": {
## "StringEquals": {
## "aws:PrincipalTag/x509Subject/CN": "onpremsrv01",
## "aws:PrincipalTag/x509Subject/OU": "SecOps"
## }
## }
# https://aws.amazon.com/blogs/security/extend-aws-iam-roles-to-workloads-outside-of-aws-with-iam-roles-anywhere/
# https://docs.aws.amazon.com/rolesanywhere/latest/userguide/workload-identities.html
# https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_control-access_monitor.html

1 change: 1 addition & 0 deletions rolesanywhere/variables.common.tf
27 changes: 27 additions & 0 deletions rolesanywhere/variables.rolesanywhere.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
variable "certificate_conditions" {
description = "Map of certificate conditions to be merged with x509Subject/CN={role_name}"
type = map(string)
default = {}
}

variable "contact_group_email" {
description = "Email of contact group"
type = string
}

variable "contact_users" {
description = "Username of contact(s)"
type = list(string)
default = []
}

variable "validity_days" {
description = "Number of days for which the certificate is valid (default: 365, max: 365)"
type = number
default = 365

validation {
condition = var.validity_days > 0 && var.validity_days <= 365
error_message = "validity_days must be between 1 and 365"
}
}
Loading

0 comments on commit 0f64499

Please sign in to comment.