Skip to main content
Service Catalog Version 0.118.1Last updated in version 0.98.0

IAM Users and IAM Groups

View Source Release Notes

Overview

This service contains Terraform code to provision and manage best practices set of IAM Groups for permissions management, and configuring IAM Users that take advantage of those groups.

This feature exists in account-baseline-security, but having a separate module to manage IAM Users and Groups is useful for large scale organizations that frequently:

  • Onboard and offboard new users
  • Add and remove AWS accounts in their org

The rationale behind this change comes from addressing two issues:

  • The cadence of changes for IAM users and groups in the security account is considerably higher than the other things that are managed in account-baseline-security (e.g., consider CloudTrail, which should only be configured once in the lifetime of the account).

  • account-baseline-security is, by nature, a heavy module that manages tons of resources. Having to go through the plan and apply cycle for all those resources can be very painful, especially for large orgs that need to onboard/offboard user frequently.

Features

  • Provision IAM users with default set of IAM Groups, passwords, and access keys.

  • Manage a best practices set of IAM Groups for managing different permissions levels in your AWS Account.

  • Provision IAM Groups that manage cross account IAM Role access to other accounts in your AWS Organization.

Learn

note

This repo is a part of the Gruntwork Service Catalog, a collection of reusable, battle-tested, production ready infrastructure code. If you’ve never used the Service Catalog before, make sure to read How to use the Gruntwork Service Catalog!

Core concepts

Repo organization

  • modules: the main implementation code for this repo, broken down into multiple standalone, orthogonal submodules.
  • examples: This folder contains working examples of how to use the submodules.
  • test: Automated tests for the modules and examples.

Deploy

Non-production deployment (quick start for learning)

If you just want to try this repo out for experimenting and learning, check out the following resources:

Production deployment

If you want to deploy this repo in production, check out the following resources:

Sample Usage

main.tf

# ------------------------------------------------------------------------------------------------------
# DEPLOY GRUNTWORK'S IAM-USERS-AND-GROUPS MODULE
# ------------------------------------------------------------------------------------------------------

module "iam_users_and_groups" {

source = "git::git@github.com:gruntwork-io/terraform-aws-service-catalog.git//modules/landingzone/iam-users-and-groups?ref=v0.118.1"

# ----------------------------------------------------------------------------------------------------
# REQUIRED VARIABLES
# ----------------------------------------------------------------------------------------------------

# The AWS Account ID the template should be operated on. This avoids
# misconfiguration errors caused by environment variables.
aws_account_id = <string>

# ----------------------------------------------------------------------------------------------------
# OPTIONAL VARIABLES
# ----------------------------------------------------------------------------------------------------

# A list of IAM permissions (e.g. ec2:*) that will be added to an IAM Group
# for doing automated deployments. NOTE: If
# var.should_create_iam_group_auto_deploy is true, the list must have at least
# one element (e.g. '*').
auto_deploy_permissions = []

# The ARN of a KMS CMK used to encrypt CloudTrail logs. If set, the logs group
# will include permissions to decrypt using this CMK.
cloudtrail_kms_key_arn = null

# The name of the IAM group that will grant access to all external AWS
# accounts in var.iam_groups_for_cross_account_access.
cross_account_access_all_group_name = "_all-accounts"

# A feature flag to enable or disable the IAM Groups module.
enable_iam_groups = true

# When destroying this user, destroy even if it has non-Terraform-managed IAM
# access keys, login profile, or MFA devices. Without force_destroy a user
# with non-Terraform-managed access keys and login profile will fail to be
# destroyed.
force_destroy_users = false

# A list of AWS services for which the developers IAM Group will receive full
# permissions. See https://goo.gl/ZyoHlz to find the IAM Service name. For
# example, to grant developers access only to EC2 and Amazon Machine Learning,
# use the value ["ec2","machinelearning"]. Do NOT add iam to the list of
# services, or that will grant Developers de facto admin access. If you need
# to grant iam privileges, just grant the user Full Access.
iam_group_developers_permitted_services = []

# The name of the IAM Group that allows automated deployment by graning the
# permissions specified in var.auto_deploy_permissions.
iam_group_name_auto_deploy = "_machine.ecs-auto-deploy"

# The name to be used for the IAM Group that grants read/write access to all
# billing features in AWS.
iam_group_name_billing = "billing"

# The name to be used for the IAM Group that grants IAM Users a reasonable set
# of permissions for developers.
iam_group_name_developers = "developers"

# The name to be used for the IAM Group that grants full access to all AWS
# resources.
iam_group_name_full_access = "full-access"

# The name to be used for the IAM Group that grants IAM administrative access.
# Effectively grants administrator access.
iam_group_name_iam_admin = "iam-admin"

# The name to be used for the IAM Group that grants IAM Users the permissions
# to manage their own IAM User account.
iam_group_name_iam_user_self_mgmt = "iam-user-self-mgmt"

# The name to be used for the IAM Group that grants read access to CloudTrail,
# AWS Config, and CloudWatch in AWS.
iam_group_name_logs = "logs"

# The name to be used for the IAM Group that grants read-only access to all
# AWS resources.
iam_group_name_read_only = "read-only"

# The name of the IAM Group that allows access to AWS Support.
iam_group_name_support = "support"

# The name to be used for the IAM Group that grants IAM Users the permissions
# to use existing IAM Roles when launching AWS Resources. This does NOT grant
# the permission to create new IAM Roles.
iam_group_name_use_existing_iam_roles = "use-existing-iam-roles"

# The list of names to be used for the IAM Group that enables its members to
# SSH as a sudo user into any server configured with the ssh-grunt Gruntwork
# module. Pass in multiple to configure multiple different IAM groups to
# control different groupings of access at the server level. Pass in empty
# list to disable creation of the IAM groups.
iam_group_names_ssh_grunt_sudo_users = ["ssh-grunt-sudo-users"]

# The name to be used for the IAM Group that enables its members to SSH as a
# non-sudo user into any server configured with the ssh-grunt Gruntwork
# module. Pass in multiple to configure multiple different IAM groups to
# control different groupings of access at the server level. Pass in empty
# list to disable creation of the IAM groups.
iam_group_names_ssh_grunt_users = ["ssh-grunt-users"]

# This variable is used to create groups that allow IAM users to assume roles
# in your other AWS accounts. It should be a list of objects, where each
# object has the fields 'group_name', which will be used as the name of the
# IAM group, and 'iam_role_arns', which is a list of ARNs of IAM Roles that
# you can assume when part of that group. For each entry in the list of
# objects, we will create an IAM group that allows users to assume the given
# IAM role(s) in the other AWS account. This allows you to define all your IAM
# users in one account (e.g. the users account) and to grant them access to
# certain IAM roles in other accounts (e.g. the stage, prod, audit accounts).
iam_groups_for_cross_account_access = []

# The name to be used for the IAM Policy that grants IAM Users the permissions
# to manage their own IAM User account.
iam_policy_iam_user_self_mgmt = "iam-user-self-mgmt"

# The tags to apply to all the IAM role resources.
iam_role_tags = {}

# The maximum allowable session duration, in seconds, for the credentials you
# get when assuming the IAM roles created by this module. This variable
# applies to all IAM roles created by this module that are intended for people
# to use, such as allow-read-only-access-from-other-accounts. For IAM roles
# that are intended for machine users, such as
# allow-auto-deploy-from-other-accounts, see
# var.max_session_duration_machine_users.
max_session_duration_human_users = 43200

# The maximum allowable session duration, in seconds, for the credentials you
# get when assuming the IAM roles created by this module. This variable
# applies to all IAM roles created by this module that are intended for
# machine users, such as allow-auto-deploy-from-other-accounts. For IAM roles
# that are intended for human users, such as
# allow-read-only-access-from-other-accounts, see
# var.max_session_duration_human_users.
max_session_duration_machine_users = 3600

# Password minimum length.
minimum_password_length = 16

# Force the user to reset their password on initial login. Only used for users
# with create_login_profile set to true.
password_reset_required = true

# Should we create the IAM Group for auto-deploy? Allows automated deployment
# by granting the permissions specified in var.auto_deploy_permissions. (true
# or false)
should_create_iam_group_auto_deploy = false

# Should we create the IAM Group for billing? Allows read-write access to
# billing features only. (true or false)
should_create_iam_group_billing = false

# Should we create the IAM Group for access to all external AWS accounts?
should_create_iam_group_cross_account_access_all = true

# Should we create the IAM Group for developers? The permissions of that group
# are specified via var.iam_group_developers_permitted_services. (true or
# false)
should_create_iam_group_developers = false

# Should we create the IAM Group for full access? Allows full access to all
# AWS resources. (true or false)
should_create_iam_group_full_access = true

# Should we create the IAM Group for IAM administrator access? Allows users to
# manage all IAM entities, effectively granting administrator access. (true or
# false)
should_create_iam_group_iam_admin = false

# Should we create the IAM Group for logs? Allows read access to CloudTrail,
# AWS Config, and CloudWatch. If var.cloudtrail_kms_key_arn is set, will also
# give decrypt access to a KMS CMK. (true or false)
should_create_iam_group_logs = false

# Should we create the IAM Group for read-only? Allows read-only access to all
# AWS resources. (true or false)
should_create_iam_group_read_only = false

# Should we create the IAM Group for support? Allows support access
# (AWSupportAccess). (true or false)
should_create_iam_group_support = false

# Should we create the IAM Group for use-existing-iam-roles? Allow launching
# AWS resources with existing IAM Roles, but no ability to create new IAM
# Roles. (true or false)
should_create_iam_group_use_existing_iam_roles = false

# Should we create the IAM Group for user self-management? Allows users to
# manage their own IAM user accounts, but not other IAM users. (true or false)
should_create_iam_group_user_self_mgmt = true

# Should we require that all IAM Users use Multi-Factor Authentication for
# both AWS API calls and the AWS Web Console? (true or false)
should_require_mfa = true

# A map of users to create. The keys are the user names and the values are an
# object with the optional keys 'groups' (a list of IAM groups to add the user
# to), 'tags' (a map of tags to apply to the user), 'pgp_key' (either a
# base-64 encoded PGP public key, or a keybase username in the form
# keybase:username, used to encrypt the user's credentials; required if
# create_login_profile or create_access_keys is true), 'create_login_profile'
# (if set to true, create a password to login to the AWS Web Console),
# 'create_access_keys' (if set to true, create access keys for the user),
# 'path' (the path), and 'permissions_boundary' (the ARN of the policy that is
# used to set the permissions boundary for the user).
users = {}

}


Reference

Required

aws_account_idstringrequired

The AWS Account ID the template should be operated on. This avoids misconfiguration errors caused by environment variables.

Optional

auto_deploy_permissionslist(string)optional

A list of IAM permissions (e.g. ec2:) that will be added to an IAM Group for doing automated deployments. NOTE: If should_create_iam_group_auto_deploy is true, the list must have at least one element (e.g. '').

[]

The ARN of a KMS CMK used to encrypt CloudTrail logs. If set, the logs group will include permissions to decrypt using this CMK.

null

The name of the IAM group that will grant access to all external AWS accounts in iam_groups_for_cross_account_access.

"_all-accounts"
enable_iam_groupsbooloptional

A feature flag to enable or disable the IAM Groups module.

true

When destroying this user, destroy even if it has non-Terraform-managed IAM access keys, login profile, or MFA devices. Without force_destroy a user with non-Terraform-managed access keys and login profile will fail to be destroyed.

false

A list of AWS services for which the developers IAM Group will receive full permissions. See https://goo.gl/ZyoHlz to find the IAM Service name. For example, to grant developers access only to EC2 and Amazon Machine Learning, use the value ['ec2','machinelearning']. Do NOT add iam to the list of services, or that will grant Developers de facto admin access. If you need to grant iam privileges, just grant the user Full Access.

[]

The name of the IAM Group that allows automated deployment by graning the permissions specified in auto_deploy_permissions.

"_machine.ecs-auto-deploy"

The name to be used for the IAM Group that grants read/write access to all billing features in AWS.

"billing"

The name to be used for the IAM Group that grants IAM Users a reasonable set of permissions for developers.

"developers"

The name to be used for the IAM Group that grants full access to all AWS resources.

"full-access"

The name to be used for the IAM Group that grants IAM administrative access. Effectively grants administrator access.

"iam-admin"

The name to be used for the IAM Group that grants IAM Users the permissions to manage their own IAM User account.

"iam-user-self-mgmt"
iam_group_name_logsstringoptional

The name to be used for the IAM Group that grants read access to CloudTrail, AWS Config, and CloudWatch in AWS.

"logs"

The name to be used for the IAM Group that grants read-only access to all AWS resources.

"read-only"

The name of the IAM Group that allows access to AWS Support.

"support"

The name to be used for the IAM Group that grants IAM Users the permissions to use existing IAM Roles when launching AWS Resources. This does NOT grant the permission to create new IAM Roles.

"use-existing-iam-roles"

The list of names to be used for the IAM Group that enables its members to SSH as a sudo user into any server configured with the ssh-grunt Gruntwork module. Pass in multiple to configure multiple different IAM groups to control different groupings of access at the server level. Pass in empty list to disable creation of the IAM groups.

[
"ssh-grunt-sudo-users"
]

The name to be used for the IAM Group that enables its members to SSH as a non-sudo user into any server configured with the ssh-grunt Gruntwork module. Pass in multiple to configure multiple different IAM groups to control different groupings of access at the server level. Pass in empty list to disable creation of the IAM groups.

[
"ssh-grunt-users"
]
iam_groups_for_cross_account_accesslist(object(…))optional

This variable is used to create groups that allow IAM users to assume roles in your other AWS accounts. It should be a list of objects, where each object has the fields 'group_name', which will be used as the name of the IAM group, and 'iam_role_arns', which is a list of ARNs of IAM Roles that you can assume when part of that group. For each entry in the list of objects, we will create an IAM group that allows users to assume the given IAM role(s) in the other AWS account. This allows you to define all your IAM users in one account (e.g. the users account) and to grant them access to certain IAM roles in other accounts (e.g. the stage, prod, audit accounts).

list(object({
group_name = string
iam_role_arns = list(string)
}))
[]
Example
   default = [
{
group_name = "stage-full-access"
iam_role_arns = ["arn:aws:iam::123445678910:role/mgmt-full-access"]
},
{
group_name = "prod-read-only-access"
iam_role_arns = [
"arn:aws:iam::9876543210:role/prod-read-only-ec2-access",
"arn:aws:iam::9876543210:role/prod-read-only-rds-access"
]
}
]

The name to be used for the IAM Policy that grants IAM Users the permissions to manage their own IAM User account.

"iam-user-self-mgmt"
iam_role_tagsmap(string)optional

The tags to apply to all the IAM role resources.

{}

The maximum allowable session duration, in seconds, for the credentials you get when assuming the IAM roles created by this module. This variable applies to all IAM roles created by this module that are intended for people to use, such as allow-read-only-access-from-other-accounts. For IAM roles that are intended for machine users, such as allow-auto-deploy-from-other-accounts, see max_session_duration_machine_users.

43200

The maximum allowable session duration, in seconds, for the credentials you get when assuming the IAM roles created by this module. This variable applies to all IAM roles created by this module that are intended for machine users, such as allow-auto-deploy-from-other-accounts. For IAM roles that are intended for human users, such as allow-read-only-access-from-other-accounts, see max_session_duration_human_users.

3600

Password minimum length.

16

Force the user to reset their password on initial login. Only used for users with create_login_profile set to true.

true

Should we create the IAM Group for auto-deploy? Allows automated deployment by granting the permissions specified in auto_deploy_permissions. (true or false)

false

Should we create the IAM Group for billing? Allows read-write access to billing features only. (true or false)

false

Should we create the IAM Group for access to all external AWS accounts?

true

Should we create the IAM Group for developers? The permissions of that group are specified via iam_group_developers_permitted_services. (true or false)

false

Should we create the IAM Group for full access? Allows full access to all AWS resources. (true or false)

true

Should we create the IAM Group for IAM administrator access? Allows users to manage all IAM entities, effectively granting administrator access. (true or false)

false

Should we create the IAM Group for logs? Allows read access to CloudTrail, AWS Config, and CloudWatch. If cloudtrail_kms_key_arn is set, will also give decrypt access to a KMS CMK. (true or false)

false

Should we create the IAM Group for read-only? Allows read-only access to all AWS resources. (true or false)

false

Should we create the IAM Group for support? Allows support access (AWSupportAccess). (true or false)

false

Should we create the IAM Group for use-existing-iam-roles? Allow launching AWS resources with existing IAM Roles, but no ability to create new IAM Roles. (true or false)

false

Should we create the IAM Group for user self-management? Allows users to manage their own IAM user accounts, but not other IAM users. (true or false)

true
should_require_mfabooloptional

Should we require that all IAM Users use Multi-Factor Authentication for both AWS API calls and the AWS Web Console? (true or false)

true
usersanyoptional

A map of users to create. The keys are the user names and the values are an object with the optional keys 'groups' (a list of IAM groups to add the user to), 'tags' (a map of tags to apply to the user), 'pgp_key' (either a base-64 encoded PGP public key, or a keybase username in the form keybase:username, used to encrypt the user's credentials; required if create_login_profile or create_access_keys is true), 'create_login_profile' (if set to true, create a password to login to the AWS Web Console), 'create_access_keys' (if set to true, create access keys for the user), 'path' (the path), and 'permissions_boundary' (the ARN of the policy that is used to set the permissions boundary for the user).

Any types represent complex values of variable type. For details, please consult `variables.tf` in the source repo.
{}
Example
   users = {
alice = {
groups = ["user-self-mgmt", "developers", "ssh-sudo-users"]
}

bob = {
path = "/"
groups = ["user-self-mgmt", "ops", "admins"]
tags = {
foo = "bar"
}
}

carol = {
groups = ["user-self-mgmt", "developers", "ssh-users"]
pgp_key = "keybase:carol_on_keybase"
create_login_profile = true
create_access_keys = true
}
}

Details

Ideally, this would be a map of (string, object), but object does not support optional properties, and we want
users to be able to specify, say, tags for some users, but not for others. We can't use a map(any) either, as that
would require the values to all have the same type, and due to optional parameters, that wouldn't work either. So,
we have to lamely fall back to any.