Skip to content

Commit

Permalink
Implement AWS Assumed Roles with MFA for IAM Groups (#1)
Browse files Browse the repository at this point in the history
  • Loading branch information
Andrey Taranik authored and osterman committed Jul 31, 2017
1 parent e54a614 commit 039ad13
Show file tree
Hide file tree
Showing 4 changed files with 278 additions and 1 deletion.
75 changes: 74 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,74 @@
# tf_assumed_roles
# tf_assumed_roles

Provides two IAM roles and two IAM groups assuming these roles

- role and group named as **ops** has Administratror (full) access to AWS resources
- role and group named as **readonly** has ReadOnly access to AWS resources

To give some user Administrator's access just add user to group **ops**

### Module usage

```
module "assumed_roles" {
source = "github.com/cloudposse/tf_assumed_roles"
}
```

### Example usage

```
resource "aws_iam_user" "Alice" {
name = "Alice"
}
resource "aws_iam_user" "Diana" {
name = "Diana"
}
module "assumed_roles" {
source = "github.com/cloudposse/tf_assumed_roles"
admin_group_name = "Admins"
readonly_group_name = "Watchers"
}
# Alice will be in 'ops' group with 'AdministratorAcsess'
#
resource "aws_iam_group_membership" "admin" {
name = "ops-group-membership"
users = ["${aws_iam_user.Alice.name}"]
group = "${module.assumed_roles.group_admin_name}"
}
# Diana will be in 'readonly' group with 'ReadOnlyAccess'
#
resource "aws_iam_group_membership" "readonly" {
name = "ro-group-membership"
users = ["${aws_iam_user.Diana.name}"]
group = "${module.assumed_roles.group_readonly_name}"
}
```

### Argument Reference

- `admin_role_name` - (Optional, default "ops") Name for IAM role with Administrator access
- `admin_group_name` - (Optional, default "ops") Name for group assuming ops role
- `readonly_role_name` - (Optional, default "readonly") Name for IAM role with ReadOnly access
- `readonly_group_name` - (Optional, default "readonly") Name for group assuming readonly IAM role

### Attributes Reference

- `group_admin_id` - the Administrator group's ID.
- `group_admin_arn` - the Amazon Resource Name (ARN) specifying the Administrator group.
- `group_admin_name` - the Administrator group's name.

- `group_readonly_id` - the ReadOnly group's ID.
- `group_readonly_arn` - the Amazon Resource Name (ARN) specifying the ReadOnly group.
- `group_readonly_name` - the ReadOnly group's name.

- `role_admin_arn` - the Amazon Resource Name (ARN) specifying the Administrator role.
- `role_admin_name` - the Administrator role's name.

- `role_readonly_arn` - the Amazon Resource Name (ARN) specifying the ReadOnly role.
- `role_readonly_name` - the ReadOnly role's name.
151 changes: 151 additions & 0 deletions main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
data "aws_caller_identity" "current" {}

data "aws_iam_policy_document" "role_trust" {
statement {
actions = ["sts:AssumeRole"]
principals {
type = "AWS"
identifiers = ["arn:aws:iam::${data.aws_caller_identity.current.account_id}:root"]
}
condition {
test = "Bool"
variable = "aws:MultiFactorAuthPresent"
values = ["true"]
}

}
}

data "aws_iam_policy_document" "assume_role_admin" {
statement {
actions = ["sts:AssumeRole"]
resources = ["${aws_iam_role.admin.arn}"]
}
}
resource "aws_iam_policy" "assume_role_admin" {
name = "AssumeRoleAdmin"
policy = "${data.aws_iam_policy_document.assume_role_admin.json}"
}

data "aws_iam_policy_document" "assume_role_readonly" {
statement {
actions = ["sts:AssumeRole"]
resources = ["${aws_iam_role.readonly.arn}"]
}
}
resource "aws_iam_policy" "assume_role_readonly" {
name = "AssumeRoleReadOnly"
policy = "${data.aws_iam_policy_document.assume_role_readonly.json}"
}

data "aws_iam_policy_document" "manage_mfa" {
statement {
sid = "AllowUsersToCreateEnableResyncDeleteTheirOwnVirtualMFADevice"
actions = [
"iam:CreateVirtualMFADevice",
"iam:EnableMFADevice",
"iam:ResyncMFADevice",
"iam:DeleteVirtualMFADevice"
]
resources = [
"arn:aws:iam::${data.aws_caller_identity.current.account_id}:mfa/&{aws:username}",
"arn:aws:iam::${data.aws_caller_identity.current.account_id}:user/&{aws:username}"
]
}
statement {
sid = "AllowUsersToDeactivateTheirOwnVirtualMFADevice"
actions = [
"iam:DeactivateMFADevice"
]
resources = [
"arn:aws:iam::${data.aws_caller_identity.current.account_id}:mfa/&{aws:username}",
"arn:aws:iam::${data.aws_caller_identity.current.account_id}:user/&{aws:username}"
]
condition {
test = "Bool"
variable = "aws:MultiFactorAuthPresent"
values = ["true"]
}
}
statement {
sid = "AllowUsersToListMFADevicesandUsersForConsole"
actions = [
"iam:ListMFADevices",
"iam:ListVirtualMFADevices",
"iam:ListUsers"
]
resources = [
"*"
]
}
}
resource "aws_iam_policy" "manage_mfa" {
name = "AllowUsersToDeactivateTheirOwnVirtualMFADevice"
policy = "${data.aws_iam_policy_document.manage_mfa.json}"
}

data "aws_iam_policy_document" "allow_change_password" {
statement {
actions = ["iam:ChangePassword"]
resources = ["arn:aws:iam::${data.aws_caller_identity.current.account_id}:user/&{aws:username}"]
}
statement {
actions = ["iam:GetAccountPasswordPolicy"]
resources = ["*"]
}
}
resource "aws_iam_policy" "allow_change_password" {
name = "AllowChangePassword"
policy = "${data.aws_iam_policy_document.allow_change_password.json}"
}


resource "aws_iam_group" "admin" {
name = "${var.admin_group_name}"
}
resource "aws_iam_group_policy_attachment" "assume_role_admin" {
group = "${aws_iam_group.admin.name}"
policy_arn = "${aws_iam_policy.assume_role_admin.arn}"
}
resource "aws_iam_group_policy_attachment" "manage_mfa_admin" {
group = "${aws_iam_group.admin.name}"
policy_arn = "${aws_iam_policy.manage_mfa.arn}"
}
resource "aws_iam_group_policy_attachment" "allow_chage_password_admin" {
group = "${aws_iam_group.admin.name}"
policy_arn = "${aws_iam_policy.allow_change_password.arn}"
}

resource "aws_iam_group" "readonly" {
name = "${var.readonly_group_name}"
}
resource "aws_iam_group_policy_attachment" "assume_role_readonly" {
group = "${aws_iam_group.readonly.name}"
policy_arn = "${aws_iam_policy.assume_role_readonly.arn}"
}
resource "aws_iam_group_policy_attachment" "manage_mfa_readonly" {
group = "${aws_iam_group.readonly.name}"
policy_arn = "${aws_iam_policy.manage_mfa.arn}"
}
resource "aws_iam_group_policy_attachment" "allow_change_password_readonly" {
group = "${aws_iam_group.readonly.name}"
policy_arn = "${aws_iam_policy.allow_change_password.arn}"
}

resource "aws_iam_role" "admin" {
name = "${var.admin_role_name}"
assume_role_policy = "${data.aws_iam_policy_document.role_trust.json}"
}
resource "aws_iam_role_policy_attachment" "admin" {
role = "${aws_iam_role.admin.name}"
policy_arn = "arn:aws:iam::aws:policy/AdministratorAccess"
}

resource "aws_iam_role" "readonly" {
name = "${var.readonly_role_name}"
assume_role_policy = "${data.aws_iam_policy_document.role_trust.json}"
}
resource "aws_iam_role_policy_attachment" "readonly" {
role = "${aws_iam_role.readonly.name}"
policy_arn = "arn:aws:iam::aws:policy/ReadOnlyAccess"
}
38 changes: 38 additions & 0 deletions outputs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Groups output information
#
output "group_admin_id" {
value = "${aws_iam_group.admin.id}"
}
output "group_admin_arn" {
value = "${aws_iam_group.admin.arn}"
}
output "group_admin_name" {
value = "${aws_iam_group.admin.name}"
}

output "group_readonly_id" {
value = "${aws_iam_group.readonly.id}"
}
output "group_readonly_arn" {
value = "${aws_iam_group.readonly.arn}"
}
output "group_readonly_name" {
value = "${aws_iam_group.readonly.name}"
}

# Roles output information
#
output "role_admin_arn" {
value = "${aws_iam_role.admin.arn}"
}
output "role_admin_name" {
value = "${aws_iam_role.admin.name}"
}

output "role_readonly_arn" {
value = "${aws_iam_role.readonly.arn}"
}
output "role_readonly_name" {
value = "${aws_iam_role.readonly.name}"
}

15 changes: 15 additions & 0 deletions variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
variable "admin_group_name" {
default = "ops"
}

variable "admin_role_name" {
default = "ops"
}

variable "readonly_group_name" {
default = "readonly"
}

variable "readonly_role_name" {
default = "readonly"
}

0 comments on commit 039ad13

Please sign in to comment.