Skip to content

Commit

Permalink
reorganisation of resources
Browse files Browse the repository at this point in the history
  • Loading branch information
agjmills committed Aug 23, 2024
1 parent d0170a9 commit 6c93be3
Show file tree
Hide file tree
Showing 9 changed files with 167 additions and 138 deletions.
45 changes: 45 additions & 0 deletions accounts_production.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# Create an account
resource "aws_organizations_account" "production" {
name = "Production"
email = "[email protected]"
iam_user_access_to_billing = "ALLOW"

parent_id = aws_organizations_organizational_unit.workloads_production.id
}

# Assume the OrganizationAccountAccessRole to jump into the sub-account, and create resources.
provider "aws" {
alias = "production"
region = "eu-west-2"

default_tags {
tags = local.tags
}

assume_role {
role_arn = "arn:aws:iam::${aws_organizations_account.production.id}:role/OrganizationAccountAccessRole"
}

allowed_account_ids = [
aws_organizations_account.production.id
]
}

# Create an S3 bucket and DynamoDB table to allow for Terraform State Locking
module "production_terraform_state" {
source = "./modules/terraform_state"
providers = {
aws = aws.production
}
depends_on = [aws_organizations_account.production]
}

# Create an OIDC provider to allow GitHub actions to assume an appropriate role
module "production_github_oidc" {
source = "./modules/github_oidc"
allowed_repositories = ["alexmills-uk/*:*"]
providers = {
aws = aws.production
}
depends_on = [aws_organizations_account.production]
}
45 changes: 7 additions & 38 deletions main.tf
Original file line number Diff line number Diff line change
@@ -1,46 +1,15 @@
provider "aws" {
region = var.region
}

resource "aws_organizations_account" "production" {
name = "Production"
email = "[email protected]"
iam_user_access_to_billing = "ALLOW"

locals {
tags = {
Name = "Production"
Owner = "AlexMills-UK"
Role = "production"
}

parent_id = aws_organizations_organizational_unit.workloads_production.id
}

provider "aws" {
alias = "production"
region = "eu-west-2"

default_tags {
tags = {
Repository = "github.com/alexmills-uk/aws-organisation"
Owner = "platform-team"
Owner = "AlexMills-UK"
Role = "production"
Terraform = "true"
}
}

assume_role {
role_arn = "arn:aws:iam::${aws_organizations_account.production.id}:role/OrganizationAccountAccessRole"
}

allowed_account_ids = [
aws_organizations_account.production.id
]
}
provider "aws" {
region = var.region

module "production_terraform_state" {
source = "./modules/terraform_state"
providers = {
aws = aws.production
default_tags {
tags = local.tags
}
depends_on = [aws_organizations_account.production]
}
59 changes: 59 additions & 0 deletions modules/github_oidc/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = ">=5.0.0"
}
}
}

resource "aws_iam_openid_connect_provider" "github" {
url = "https://token.actions.githubusercontent.com"

client_id_list = [
"sts.amazonaws.com",
]

thumbprint_list = [
"6938fd4d98bab03faadb97b34396831e3780aea1",
]
}

data "aws_iam_policy_document" "github_oidc_assume_role" {
statement {
effect = "Allow"
actions = ["sts:AssumeRoleWithWebIdentity"]

principals {
type = "Federated"
identifiers = ["arn:aws:iam::${data.aws_caller_identity.current.account_id}:oidc-provider/token.actions.githubusercontent.com"]
}

condition {
test = "StringEquals"
variable = "token.actions.githubusercontent.com:aud"
values = ["sts.amazonaws.com"]
}

condition {
test = "StringLike"
variable = "token.actions.githubusercontent.com:sub"
values = [
for repository in var.allowed_repositories : "repo:${repository}"
]
}
}
}

resource "aws_iam_role" "github_oidc_role" {
name = "github-deployment"
path = "/github-oidc/"
assume_role_policy = data.aws_iam_policy_document.github_oidc_assume_role.json
}

# Ideally, this the policy attached should be more tightly scoped as AdministratorAccess is quite a wide permission set.
# Alternatively, use SCPs to limit the scope of AdministratorAccess.
resource "aws_iam_role_policy_attachment" "github_oidc_role_policy" {
role = aws_iam_role.github_oidc_role.name
policy_arn = "arn:aws:iam::aws:policy/AdministratorAccess"
}
4 changes: 4 additions & 0 deletions modules/github_oidc/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
variable "allowed_repositories" {
type = list(string)
description = "A list of GitHub repositories that are allowed to assume this AWS role. Must be in the format {organisation/username}/{repository}:{branch}."
}
51 changes: 2 additions & 49 deletions modules/terraform_state/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = ">= 4.0.0"
version = ">=5.0.0"
}
}
}
Expand All @@ -28,51 +28,4 @@ resource "aws_dynamodb_table" "this" {
name = "LockID"
type = "S"
}
}

resource "aws_iam_openid_connect_provider" "github" {
url = "https://token.actions.githubusercontent.com"

client_id_list = [
"sts.amazonaws.com",
]

thumbprint_list = [
"6938fd4d98bab03faadb97b34396831e3780aea1",
]
}

data "aws_iam_policy_document" "github_oidc_assume_role" {
statement {
effect = "Allow"
actions = ["sts:AssumeRoleWithWebIdentity"]

principals {
type = "Federated"
identifiers = ["arn:aws:iam::${data.aws_caller_identity.current.account_id}:oidc-provider/token.actions.githubusercontent.com"]
}

condition {
test = "StringEquals"
variable = "token.actions.githubusercontent.com:aud"
values = ["sts.amazonaws.com"]
}

condition {
test = "StringLike"
variable = "token.actions.githubusercontent.com:sub"
values = ["repo:alexmills-uk/*:*"]
}
}
}

resource "aws_iam_role" "github_oidc_role" {
name = "github-deployment"
path = "/github-oidc/"
assume_role_policy = data.aws_iam_policy_document.github_oidc_assume_role.json
}

resource "aws_iam_role_policy_attachment" "github_oidc_role_policy" {
role = aws_iam_role.github_oidc_role.name
policy_arn = "arn:aws:iam::aws:policy/AdministratorAccess"
}
}
52 changes: 1 addition & 51 deletions sso.tf
Original file line number Diff line number Diff line change
@@ -1,51 +1 @@
data "aws_ssoadmin_instances" "this" {}

resource "aws_identitystore_group" "administrators" {
identity_store_id = tolist(data.aws_ssoadmin_instances.this.identity_store_ids)[0]
display_name = "Administrators"
description = "Administrators of the AWS Organisation"
}

resource "aws_identitystore_user" "alexm" {
identity_store_id = tolist(data.aws_ssoadmin_instances.this.identity_store_ids)[0]

display_name = "Alex Mills"
user_name = "alexm"

name {
given_name = "Alex"
family_name = "Mills"
}

emails {
value = "[email protected]"
}
}

resource "aws_identitystore_group_membership" "alexm_administrators" {
identity_store_id = tolist(data.aws_ssoadmin_instances.this.identity_store_ids)[0]
group_id = aws_identitystore_group.administrators.group_id
member_id = aws_identitystore_user.alexm.user_id
}

resource "aws_ssoadmin_permission_set" "admin_permissionset" {
name = "AdministratorAccess"
instance_arn = tolist(data.aws_ssoadmin_instances.this.arns)[0]
}

resource "aws_ssoadmin_managed_policy_attachment" "administrator_managed_policy_attachment" {
instance_arn = tolist(data.aws_ssoadmin_instances.this.arns)[0]
managed_policy_arn = "arn:aws:iam::aws:policy/AdministratorAccess"
permission_set_arn = aws_ssoadmin_permission_set.admin_permissionset.arn
}

resource "aws_ssoadmin_account_assignment" "admin_role_assignment" {
for_each = { for account in data.aws_organizations_organization.org.accounts : account.id => account }

instance_arn = tolist(data.aws_ssoadmin_instances.this.arns)[0]
principal_id = aws_identitystore_group.administrators.group_id
principal_type = "GROUP"
target_type = "AWS_ACCOUNT"
target_id = each.key
permission_set_arn = aws_ssoadmin_permission_set.admin_permissionset.arn
}
data "aws_ssoadmin_instances" "this" {}
17 changes: 17 additions & 0 deletions sso_groups.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
resource "aws_identitystore_group" "administrators" {
identity_store_id = tolist(data.aws_ssoadmin_instances.this.identity_store_ids)[0]
display_name = "Administrators"
description = "Administrators of the AWS Organisation"
}

# Assign the Administrators group to every account
resource "aws_ssoadmin_account_assignment" "admin_role_assignment" {
for_each = { for account in data.aws_organizations_organization.org.accounts : account.id => account }

instance_arn = tolist(data.aws_ssoadmin_instances.this.arns)[0]
principal_id = aws_identitystore_group.administrators.group_id
principal_type = "GROUP"
target_type = "AWS_ACCOUNT"
target_id = each.key
permission_set_arn = aws_ssoadmin_permission_set.admin_permissionset.arn
}
10 changes: 10 additions & 0 deletions sso_permissions.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
resource "aws_ssoadmin_permission_set" "admin_permissionset" {
name = "AdministratorAccess"
instance_arn = tolist(data.aws_ssoadmin_instances.this.arns)[0]
}

resource "aws_ssoadmin_managed_policy_attachment" "administrator_managed_policy_attachment" {
instance_arn = tolist(data.aws_ssoadmin_instances.this.arns)[0]
managed_policy_arn = "arn:aws:iam::aws:policy/AdministratorAccess"
permission_set_arn = aws_ssoadmin_permission_set.admin_permissionset.arn
}
22 changes: 22 additions & 0 deletions sso_users.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
resource "aws_identitystore_user" "alexm" {
identity_store_id = tolist(data.aws_ssoadmin_instances.this.identity_store_ids)[0]

display_name = "Alex Mills"
user_name = "alexm"

name {
given_name = "Alex"
family_name = "Mills"
}

emails {
value = "[email protected]"
}
}

# Add the user above to the Administrators group
resource "aws_identitystore_group_membership" "alexm_administrators" {
identity_store_id = tolist(data.aws_ssoadmin_instances.this.identity_store_ids)[0]
group_id = aws_identitystore_group.administrators.group_id
member_id = aws_identitystore_user.alexm.user_id
}

0 comments on commit 6c93be3

Please sign in to comment.