Skip to content

Commit

Permalink
Merge pull request #29 from cisagov/feature/rework-for-env-specific-a…
Browse files Browse the repository at this point in the history
…ccess

Rework to allow for specific access to only selected assessment environments
  • Loading branch information
jsf9k authored Oct 10, 2024
2 parents 1a1738a + b142488 commit 371d552
Show file tree
Hide file tree
Showing 7 changed files with 200 additions and 38 deletions.
30 changes: 23 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,12 +62,20 @@ No modules.
| Name | Type |
|------|------|
| [aws_iam_group.assessment_provisioners](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_group) | resource |
| [aws_iam_group_policy_attachment.assessment_provisioners](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_group_policy_attachment) | resource |
| [aws_iam_policy.provision_assessment](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource |
| [aws_iam_group.assessment_provisioners_no_backend](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_group) | resource |
| [aws_iam_group_policy_attachment.assessment_provisioners_backend](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_group_policy_attachment) | resource |
| [aws_iam_group_policy_attachment.assessment_provisioners_base](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_group_policy_attachment) | resource |
| [aws_iam_group_policy_attachment.assessment_provisioners_no_backend](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_group_policy_attachment) | resource |
| [aws_iam_group_policy_attachment.assessment_provisioners_no_backend_base](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_group_policy_attachment) | resource |
| [aws_iam_policy.provision_assessment_backend](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource |
| [aws_iam_policy.provision_assessment_base](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource |
| [aws_iam_policy.provision_assessment_no_backend](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource |
| [aws_iam_user_group_membership.assessment_provisioners](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_user_group_membership) | resource |
| [aws_caller_identity.default](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity) | data source |
| [aws_caller_identity.users](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity) | data source |
| [aws_iam_policy_document.provision_assessment](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source |
| [aws_iam_policy_document.provision_assessment_backend](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source |
| [aws_iam_policy_document.provision_assessment_base](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source |
| [aws_iam_policy_document.provision_assessment_no_backend](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source |
| [aws_organizations_organization.cool](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/organizations_organization) | data source |
| [terraform_remote_state.dns_certboto](https://registry.terraform.io/providers/hashicorp/terraform/latest/docs/data-sources/remote_state) | data source |
| [terraform_remote_state.images_parameterstore-production](https://registry.terraform.io/providers/hashicorp/terraform/latest/docs/data-sources/remote_state) | data source |
Expand All @@ -83,20 +91,28 @@ No modules.
| Name | Description | Type | Default | Required |
|------|-------------|------|---------|:--------:|
| assessment\_provisioners\_group\_name | The name of the IAM group whose members are allowed to provision assessment environments. | `string` | `"assessment_provisioners"` | no |
| assessment\_provisioners\_no\_backend\_group\_name | The name of the IAM group whose members are allowed to provision assessment environments but do not have general access to the Terraform backend. | `string` | `"assessment_provisioners_no_backend"` | no |
| aws\_region | The AWS region to deploy into (e.g. us-east-1). | `string` | `"us-east-1"` | no |
| provision\_assessment\_policy\_description | The description to associate with the IAM policy in the Users account that allows the assessment provisioner group to assume all roles needed in order to provision assessment environments. | `string` | `"Allows the assessment provisioner group to assume all roles needed in order to provision assessment environments."` | no |
| provision\_assessment\_policy\_name | The name of the IAM policy in the Users account that allows the assessment provisioner group to assume all roles needed in order to provision assessment environments. | `string` | `"AssumeProvisionAssessment"` | no |
| provision\_assessment\_backend\_policy\_description | The description to associate with the IAM policy in the Users account that allows assumption of all non-assessment roles needed in order to provision assessment environments. | `string` | `"Allows assumption of all non-assessment roles needed in order to provision assessment environments."` | no |
| provision\_assessment\_backend\_policy\_name | The name of the IAM policy in the Users account that allows assumption of all non-assessment roles needed in order to provision assessment environments. | `string` | `"AssumeProvisionAssessmentBackend"` | no |
| provision\_assessment\_base\_policy\_description | The description to associate with the IAM policy in the Users account that allows assumption of all assessment roles needed in order to provision assessment environments. | `string` | `"Allows assumption of all assessment roles needed in order to provision assessment environments."` | no |
| provision\_assessment\_base\_policy\_name | The name of the IAM policy in the Users account that allows the assessment provisioner group to assume all assessment roles needed in order to provision assessment environments. | `string` | `"AssumeProvisionAssessment"` | no |
| provision\_assessment\_no\_backend\_policy\_description | The description to associate with the IAM policy in the Users account that allows assumption of all non-assessment roles needed in order to provision assessment environments, with the exception of Terraform backend access. | `string` | `"Allows assumption of all non-assessment roles needed in order to provision assessment environments, with the exception of backend access."` | no |
| provision\_assessment\_no\_backend\_policy\_name | The name of the IAM policy in the Users account that allows assumption of all non-assessment roles needed in order to provision assessment environments, with the exception of Terraform backend access. | `string` | `"AssumeProvisionAssessmentNoBackend"` | no |
| provision\_assessment\_role\_name | The name of the IAM role in assessment accounts that includes all permissions necessary to provision the assessment environment in that account. If this role does not exist in an account, an assessment environment cannot be provisioned in that account. | `string` | `"ProvisionAccount"` | no |
| startstopssmsession\_role\_name | The name of the IAM role in assessment accounts that includes all permissions necessary to start and stop an SSM session in that account. | `string` | `"StartStopSSMSession"` | no |
| tags | Tags to apply to all AWS resources created. | `map(string)` | `{}` | no |
| users | A list containing the usernames of users that exist in the Users account who are allowed to provision assessment environments. Example: [ "firstname1.lastname1", "firstname2.lastname2" ]. | `list(string)` | n/a | yes |
| users | A map. The keys are the names of users that exist in the Users account and are to be allowed to provision assessment environments. The values are maps with a single key, "backend\_access", which is a boolean value indicating whether or not the user should have general Terraform backend access. Example: {"firstname1.lastname1" = {backend\_access = true}}, {"firstname2.lastname2" = {backend\_access = false}}. | `map(object({ backend_access = bool }))` | n/a | yes |

## Outputs ##

| Name | Description |
|------|-------------|
| assessment\_provisioners\_backend\_policy | The IAM policy in the Users account that allows assumption of all non-assessment roles needed in order to provision assessment environments. |
| assessment\_provisioners\_base\_policy | The IAM policy in the Users account that allows assumption of all assessment roles needed in order to provision assessment environments. |
| assessment\_provisioners\_group | The IAM group whose members are allowed to provision assessment environments. |
| assessment\_provisioners\_policy | The IAM policy in the Users account that allows the assessment provisioners group to assume the provisioning role in assessment accounts. |
| assessment\_provisioners\_no\_backend\_group | The IAM group whose members are allowed to provision assessment environments but do not have general access to the Terraform backend. |
| assessment\_provisioners\_no\_backend\_policy | The IAM policy in the Users account that allows assumption of all non-assessment roles needed in order to provision assessment environments, with the exception of Terraform backend access. |
<!-- END_TF_DOCS -->

## Notes ##
Expand Down
4 changes: 2 additions & 2 deletions group_membership.tf
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
# Put assessment provisioner users in the appropriate group.
resource "aws_iam_user_group_membership" "assessment_provisioners" {
provider = aws.users
for_each = toset(var.users)
for_each = var.users

groups = [
aws_iam_group.assessment_provisioners.name
each.value.backend_access ? aws_iam_group.assessment_provisioners.name : aws_iam_group.assessment_provisioners_no_backend.name
]
user = each.key
}
43 changes: 40 additions & 3 deletions groups.tf
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,47 @@ resource "aws_iam_group" "assessment_provisioners" {
name = var.assessment_provisioners_group_name
}

# Attach the policy that allows assumption of the provisioners role.
resource "aws_iam_group_policy_attachment" "assessment_provisioners" {
# Attach the policy that allows assumption of all assessment roles
# needed in order to provision assessment environments.
resource "aws_iam_group_policy_attachment" "assessment_provisioners_base" {
provider = aws.users

group = aws_iam_group.assessment_provisioners.name
policy_arn = aws_iam_policy.provision_assessment.arn
policy_arn = aws_iam_policy.provision_assessment_base.arn
}

# Attach the policy that allows assumption of all non-assessment roles
# needed in order to provision assessment environments.
resource "aws_iam_group_policy_attachment" "assessment_provisioners_backend" {
provider = aws.users

group = aws_iam_group.assessment_provisioners.name
policy_arn = aws_iam_policy.provision_assessment_backend.arn
}

# An IAM group for assessment environment provisioners without general
# access to the Terraform backend.
resource "aws_iam_group" "assessment_provisioners_no_backend" {
provider = aws.users

name = var.assessment_provisioners_no_backend_group_name
}

# Attach the policy that allows assumption of all assessment roles
# needed in order to provision assessment environments.
resource "aws_iam_group_policy_attachment" "assessment_provisioners_no_backend_base" {
provider = aws.users

group = aws_iam_group.assessment_provisioners_no_backend.name
policy_arn = aws_iam_policy.provision_assessment_base.arn
}

# Attach the policy that allows assumption of all non-assessment roles
# needed in order to provision assessment environments, with the
# exception of Terraform backend access.
resource "aws_iam_group_policy_attachment" "assessment_provisioners_no_backend" {
provider = aws.users

group = aws_iam_group.assessment_provisioners_no_backend.name
policy_arn = aws_iam_policy.provision_assessment_no_backend.arn
}
12 changes: 8 additions & 4 deletions locals.tf
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ locals {
# would need to be created in appropriate repositories, then used in
# cisagov/cool-assessment-terraform and also included below.
# See https://github.com/cisagov/cool-assessment-terraform/issues/133.
required_non_assessment_roles = [
required_non_assessment_roles_no_backend = [
data.terraform_remote_state.dns_certboto.outputs.provisioncertificatereadroles_role.arn,
data.terraform_remote_state.images_parameterstore-production.outputs.parameterstorereadonly_role.arn,
data.terraform_remote_state.images_parameterstore-production.outputs.provisionparameterstorereadroles_role.arn,
Expand All @@ -57,13 +57,17 @@ locals {
data.terraform_remote_state.master.outputs.organizationsreadonly_role.arn,
data.terraform_remote_state.sharedservices-production.outputs.provisionaccount_role.arn,
data.terraform_remote_state.sharedservices-staging.outputs.provisionaccount_role.arn,
data.terraform_remote_state.terraform.outputs.access_terraform_backend_role.arn,
data.terraform_remote_state.terraform.outputs.provisionaccount_role.arn,
]
required_non_assessment_roles_backend = concat(local.required_non_assessment_roles_no_backend, [
data.terraform_remote_state.terraform.outputs.access_terraform_backend_role.arn,
])

# Create set of prohibited non-assessment account provision roles.
prohibited_non_assessment_provision_roles = setsubtract(local.all_non_assessment_provision_roles, local.required_non_assessment_roles)
prohibited_non_assessment_provision_roles_no_backend = setsubtract(local.all_non_assessment_provision_roles, local.required_non_assessment_roles_no_backend)
prohibited_non_assessment_provision_roles_backend = setsubtract(local.all_non_assessment_provision_roles, local.required_non_assessment_roles_backend)

# Create comprehensive set of prohibited non-assessment account roles.
prohibited_non_assessment_roles = setunion(local.prohibited_non_assessment_provision_roles, local.all_non_assessment_startstopssmsession_roles)
prohibited_non_assessment_roles_no_backend = setunion(local.prohibited_non_assessment_provision_roles_no_backend, local.all_non_assessment_startstopssmsession_roles)
prohibited_non_assessment_roles_backend = setunion(local.prohibited_non_assessment_provision_roles_backend, local.all_non_assessment_startstopssmsession_roles)
}
21 changes: 18 additions & 3 deletions outputs.tf
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,22 @@ output "assessment_provisioners_group" {
value = aws_iam_group.assessment_provisioners
}

output "assessment_provisioners_policy" {
description = "The IAM policy in the Users account that allows the assessment provisioners group to assume the provisioning role in assessment accounts."
value = aws_iam_policy.provision_assessment
output "assessment_provisioners_no_backend_group" {
description = "The IAM group whose members are allowed to provision assessment environments but do not have general access to the Terraform backend."
value = aws_iam_group.assessment_provisioners_no_backend
}

output "assessment_provisioners_backend_policy" {
description = "The IAM policy in the Users account that allows assumption of all non-assessment roles needed in order to provision assessment environments."
value = aws_iam_policy.provision_assessment_backend
}

output "assessment_provisioners_base_policy" {
description = "The IAM policy in the Users account that allows assumption of all assessment roles needed in order to provision assessment environments."
value = aws_iam_policy.provision_assessment_base
}

output "assessment_provisioners_no_backend_policy" {
description = "The IAM policy in the Users account that allows assumption of all non-assessment roles needed in order to provision assessment environments, with the exception of Terraform backend access."
value = aws_iam_policy.provision_assessment_no_backend
}
83 changes: 71 additions & 12 deletions policies.tf
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
# The policy document that allows assumption of all roles needed in order to
# provision assessment environments. It also specifically denies assumption
# of non-required non-assessment account provisioning roles.
data "aws_iam_policy_document" "provision_assessment" {
# The policy document that allows assumption of the assessment roles
# needed in order to provision assessment environments.
data "aws_iam_policy_document" "provision_assessment_base" {
statement {
actions = [
"sts:AssumeRole",
Expand All @@ -27,7 +26,13 @@ data "aws_iam_policy_document" "provision_assessment" {

sid = "AllowAssessmentAccountRoles"
}
}

# The policy document that allows assumption of all non-assessment
# roles needed in order to provision assessment environments. It also
# specifically denies assumption of non-required non-assessment
# account provisioning roles.
data "aws_iam_policy_document" "provision_assessment_backend" {
statement {
actions = [
"sts:AssumeRole",
Expand All @@ -36,7 +41,7 @@ data "aws_iam_policy_document" "provision_assessment" {

effect = "Allow"

resources = local.required_non_assessment_roles
resources = local.required_non_assessment_roles_backend

sid = "AllowRequiredNonAssessmentAccountRoles"
}
Expand All @@ -49,18 +54,72 @@ data "aws_iam_policy_document" "provision_assessment" {

effect = "Deny"

resources = local.prohibited_non_assessment_roles
resources = local.prohibited_non_assessment_roles_backend

sid = "DenyNonAssessmentAccountRoles"
}
}

# The policy that allows assumption of all roles needed in order to provision
# assessment environments.
resource "aws_iam_policy" "provision_assessment" {
# The policy document that allows assumption of all non-assessment
# roles needed in order to provision assessment environments with the
# exception of Terraform backend access. It also specifically denies
# assumption of non-required non-assessment account provisioning
# roles.
data "aws_iam_policy_document" "provision_assessment_no_backend" {
statement {
actions = [
"sts:AssumeRole",
"sts:TagSession",
]

effect = "Allow"

resources = local.required_non_assessment_roles_no_backend

sid = "AllowRequiredNonAssessmentAccountRolesNoBackend"
}

statement {
actions = [
"sts:AssumeRole",
"sts:TagSession",
]

effect = "Deny"

resources = local.prohibited_non_assessment_roles_no_backend

sid = "DenyNonAssessmentAccountRolesNoBackend"
}
}

# The policy that allows assumption of all assessment roles needed in
# order to provision assessment environments.
resource "aws_iam_policy" "provision_assessment_base" {
provider = aws.users

description = var.provision_assessment_base_policy_description
name = var.provision_assessment_base_policy_name
policy = data.aws_iam_policy_document.provision_assessment_base.json
}

# The policy that allows assumption of all non-assessment roles needed
# in order to provision assessment environments.
resource "aws_iam_policy" "provision_assessment_backend" {
provider = aws.users

description = var.provision_assessment_backend_policy_description
name = var.provision_assessment_backend_policy_name
policy = data.aws_iam_policy_document.provision_assessment_backend.json
}

# The policy that allows assumption of all non-assessment roles needed
# in order to provision assessment environments with the exception of
# Terraform backend access.
resource "aws_iam_policy" "provision_assessment_no_backend" {
provider = aws.users

description = var.provision_assessment_policy_description
name = var.provision_assessment_policy_name
policy = data.aws_iam_policy_document.provision_assessment.json
description = var.provision_assessment_no_backend_policy_description
name = var.provision_assessment_no_backend_policy_name
policy = data.aws_iam_policy_document.provision_assessment_no_backend.json
}
Loading

0 comments on commit 371d552

Please sign in to comment.