Skip to content

Commit

Permalink
Merge pull request #885 from portefaix/feat/tfcloud-oidc-aws
Browse files Browse the repository at this point in the history
Terraform Cloud OIDC with AWS
  • Loading branch information
nlamirault authored Dec 8, 2023
2 parents 6a79d8d + 8ff85c0 commit f4b6a07
Show file tree
Hide file tree
Showing 13 changed files with 146 additions and 31 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,4 @@
bucket = "portefaix-tfstates"
region = "eu-west-1"
dynamodb_table = "portefaix-tfstate-lock"
key = "github/terraform.tfstate"
key = "oidc/terraform.tfstate"
File renamed without changes.
46 changes: 46 additions & 0 deletions terraform/aws/oidc/data.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# Copyright (C) Nicolas Lamirault <[email protected]>
#
# 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),
]
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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",
})
}
4 changes: 4 additions & 0 deletions terraform/aws/github/main.tf → terraform/aws/oidc/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,9 @@ terraform {
source = "hashicorp/aws"
version = "5.30.0"
}
tls = {
source = "hashicorp/tls"
version = "4.0.5"
}
}
}
24 changes: 23 additions & 1 deletion terraform/aws/github/oidc.tf → terraform/aws/oidc/oidc.tf
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ region = "eu-west-1"

github_repo = "portefaix/portefaix-infrastructure"

organization = "portefaix"

#############################################################################
# Commons

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
17 changes: 11 additions & 6 deletions terraform/aws/terraform-cloud/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -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" {
Expand Down
58 changes: 40 additions & 18 deletions terraform/aws/terraform-cloud/workspaces.tf
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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"
}
3 changes: 1 addition & 2 deletions terraform/aws/vpc/modules/vpc/vpc.tf
Original file line number Diff line number Diff line change
Expand Up @@ -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({
Expand Down

0 comments on commit f4b6a07

Please sign in to comment.