diff --git a/terraform/aws/github/backend-vars/main.tfvars b/terraform/aws/oidc/backend-vars/main.tfvars similarity index 94% rename from terraform/aws/github/backend-vars/main.tfvars rename to terraform/aws/oidc/backend-vars/main.tfvars index 214ea4529..fec398449 100755 --- a/terraform/aws/github/backend-vars/main.tfvars +++ b/terraform/aws/oidc/backend-vars/main.tfvars @@ -17,4 +17,4 @@ bucket = "portefaix-tfstates" region = "eu-west-1" dynamodb_table = "portefaix-tfstate-lock" -key = "github/terraform.tfstate" +key = "oidc/terraform.tfstate" diff --git a/terraform/aws/github/backend.tf b/terraform/aws/oidc/backend.tf similarity index 100% rename from terraform/aws/github/backend.tf rename to terraform/aws/oidc/backend.tf diff --git a/terraform/aws/oidc/data.tf b/terraform/aws/oidc/data.tf new file mode 100644 index 000000000..63e8f7955 --- /dev/null +++ b/terraform/aws/oidc/data.tf @@ -0,0 +1,46 @@ +# Copyright (C) Nicolas Lamirault +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# SPDX-License-Identifier: Apache-2.0 + +data "tls_certificate" "tfcloud" { + url = local.tfcloud_url +} + +data "aws_iam_policy_document" "tfcloud" { + statement { + effect = "Allow" + actions = ["sts:AssumeRoleWithWebIdentity"] + + principals { + type = "Federated" + identifiers = [aws_iam_openid_connect_provider.tfcloud.arn] + } + + condition { + test = "StringEquals" + variable = format("%s:aud", var.tfcloud_hostname) + values = [local.tfcloud_workload_identity_audience] + } + + condition { + test = "StringLike" + variable = format("%s:sub", var.tfcloud_hostname) + values = [ + format("organization:%s:project:*:workspace:*:run_phase:plan", var.organization), + format("organization:%s:project:*:workspace:*:run_phase:apply", var.organization), + ] + } + } +} diff --git a/terraform/aws/github/locals.tf b/terraform/aws/oidc/locals.tf similarity index 75% rename from terraform/aws/github/locals.tf rename to terraform/aws/oidc/locals.tf index 65cf0ee75..6acf78773 100644 --- a/terraform/aws/github/locals.tf +++ b/terraform/aws/oidc/locals.tf @@ -15,8 +15,12 @@ # SPDX-License-Identifier: Apache-2.0 locals { + tfcloud_url = format("https://%s", var.tfcloud_hostname) + tfcloud_workload_identity_audience = "aws.workload.identity" + + oidc_policy = "arn:aws:iam::aws:policy/AdministratorAccess" + tags = merge(var.tags, { - Service = "Github", - Role = "OIDC", + Service = "OIDC", }) } diff --git a/terraform/aws/github/main.tf b/terraform/aws/oidc/main.tf similarity index 91% rename from terraform/aws/github/main.tf rename to terraform/aws/oidc/main.tf index 2b3695adc..b71405a7a 100644 --- a/terraform/aws/github/main.tf +++ b/terraform/aws/oidc/main.tf @@ -22,5 +22,9 @@ terraform { source = "hashicorp/aws" version = "5.30.0" } + tls = { + source = "hashicorp/tls" + version = "4.0.5" + } } } diff --git a/terraform/aws/github/oidc.tf b/terraform/aws/oidc/oidc.tf similarity index 63% rename from terraform/aws/github/oidc.tf rename to terraform/aws/oidc/oidc.tf index 232368790..0138e1f21 100644 --- a/terraform/aws/github/oidc.tf +++ b/terraform/aws/oidc/oidc.tf @@ -34,8 +34,30 @@ module "iam_github_oidc_role" { ] policies = { - AdministratorAccess = "arn:aws:iam::aws:policy/AdministratorAccess" + AdministratorAccess = local.oidc_policy } tags = local.tags } + +resource "aws_iam_openid_connect_provider" "tfcloud" { + url = local.tfcloud_url + client_id_list = [local.tfcloud_workload_identity_audience] + thumbprint_list = [data.tls_certificate.tfcloud.certificates[0].sha1_fingerprint] + + tags = local.tags +} + +resource "aws_iam_role" "tfcloud" { + name = format("PortefaixTFCloud-%s", var.organization) + description = "IAM role that can be assumed by Terraform Cloud" + + assume_role_policy = data.aws_iam_policy_document.tfcloud.json + + tags = local.tags +} + +resource "aws_iam_role_policy_attachment" "tfcloud" { + role = aws_iam_role.tfcloud.name + policy_arn = local.oidc_policy +} diff --git a/terraform/aws/github/outputs.tf b/terraform/aws/oidc/outputs.tf similarity index 100% rename from terraform/aws/github/outputs.tf rename to terraform/aws/oidc/outputs.tf diff --git a/terraform/aws/github/provider.tf b/terraform/aws/oidc/provider.tf similarity index 100% rename from terraform/aws/github/provider.tf rename to terraform/aws/oidc/provider.tf diff --git a/terraform/aws/github/tfvars/main.tfvars b/terraform/aws/oidc/tfvars/main.tfvars similarity index 97% rename from terraform/aws/github/tfvars/main.tfvars rename to terraform/aws/oidc/tfvars/main.tfvars index a7a8ce7d4..d79cca674 100755 --- a/terraform/aws/github/tfvars/main.tfvars +++ b/terraform/aws/oidc/tfvars/main.tfvars @@ -24,6 +24,8 @@ region = "eu-west-1" github_repo = "portefaix/portefaix-infrastructure" +organization = "portefaix" + ############################################################################# # Commons diff --git a/terraform/aws/github/variables.tf b/terraform/aws/oidc/variables.tf similarity index 84% rename from terraform/aws/github/variables.tf rename to terraform/aws/oidc/variables.tf index fa29ab3f2..418b545fe 100644 --- a/terraform/aws/github/variables.tf +++ b/terraform/aws/oidc/variables.tf @@ -33,13 +33,24 @@ variable "default_tags" { } ############################################################################# -# Github +# OIDC variable "github_repo" { type = string description = "Github repository" } +variable "tfcloud_hostname" { + type = string + description = "URL of Terraform cloud" + default = "app.terraform.io" +} + +variable "organization" { + type = string + description = "Name of the Terraform Cloud organization" +} + ############################################################################# # Commons diff --git a/terraform/aws/terraform-cloud/variables.tf b/terraform/aws/terraform-cloud/variables.tf index d247b73f6..4c9af0c7d 100644 --- a/terraform/aws/terraform-cloud/variables.tf +++ b/terraform/aws/terraform-cloud/variables.tf @@ -73,14 +73,19 @@ variable "github_oauth_token" { description = "Github token for Terraform Cloud" } -variable "access_key" { - type = string - description = "AWS access key" -} +# variable "access_key" { +# type = string +# description = "AWS access key" +# } + +# variable "secret_key" { +# type = string +# description = "AWS secret key" +# } -variable "secret_key" { +variable "aws_role_arn" { type = string - description = "AWS secret key" + description = "AWS Role ARN for Terraform Cloud" } variable "slack_webhook_url" { diff --git a/terraform/aws/terraform-cloud/workspaces.tf b/terraform/aws/terraform-cloud/workspaces.tf index ec6904c92..7dace711a 100644 --- a/terraform/aws/terraform-cloud/workspaces.tf +++ b/terraform/aws/terraform-cloud/workspaces.tf @@ -42,27 +42,27 @@ resource "tfe_workspace" "aws" { tag_names = each.value.tags } -resource "tfe_variable" "aws_acces_key" { - for_each = tfe_workspace.aws +# resource "tfe_variable" "aws_acces_key" { +# for_each = tfe_workspace.aws - key = "AWS_ACCESS_KEY_ID" - value = var.access_key - category = "env" - sensitive = "true" - workspace_id = each.value.id - description = "The AWS access key" -} +# key = "AWS_ACCESS_KEY_ID" +# value = var.access_key +# category = "env" +# sensitive = "true" +# workspace_id = each.value.id +# description = "The AWS access key" +# } -resource "tfe_variable" "aws_secret_key" { - for_each = tfe_workspace.aws +# resource "tfe_variable" "aws_secret_key" { +# for_each = tfe_workspace.aws - key = "AWS_SECRET_ACCESS_KEY" - value = var.secret_key - category = "env" - sensitive = "true" - workspace_id = each.value.id - description = "The AWS secret key" -} +# key = "AWS_SECRET_ACCESS_KEY" +# value = var.secret_key +# category = "env" +# sensitive = "true" +# workspace_id = each.value.id +# description = "The AWS secret key" +# } resource "tfe_variable" "slack_webhook_url" { key = "TF_VAR_slack_webhook_url" @@ -107,3 +107,25 @@ resource "tfe_variable" "org_email_domain" { workspace_id = tfe_workspace.aws[each.value].id description = "Organization email domain" } + +resource "tfe_variable" "tfcloud_oidc" { + for_each = tfe_workspace.aws + + key = "TFC_AWS_PROVIDER_AUTH" + value = "true" + category = "env" + sensitive = "true" + workspace_id = each.value.id + description = "Enable Terraform Cloud OIDC" +} + +resource "tfe_variable" "aws_role_arn" { + for_each = tfe_workspace.aws + + key = "TFC_AWS_RUN_ROLE_ARN" + value = var.aws_role_arn + category = "env" + sensitive = "true" + workspace_id = each.value.id + description = "The AWS access key" +} diff --git a/terraform/aws/vpc/modules/vpc/vpc.tf b/terraform/aws/vpc/modules/vpc/vpc.tf index 06f3e9364..623b0c082 100644 --- a/terraform/aws/vpc/modules/vpc/vpc.tf +++ b/terraform/aws/vpc/modules/vpc/vpc.tf @@ -29,8 +29,7 @@ module "vpc" { single_nat_gateway = true enable_dns_hostnames = true - reuse_nat_ips = true - # external_nat_ip_ids = data.aws_eip.igw.*.id + reuse_nat_ips = true external_nat_ip_ids = [for gw in data.aws_eip.igw : gw].id tags = merge({