Skip to content

Commit

Permalink
feat: TPLAT-344 aws dynamic provider credentials (#1)
Browse files Browse the repository at this point in the history
* feat: added aws oidc iam identity provider

* feat: added aws iam role definition

* feat: added terraform dynamic credentials setup

* docs: added instructions how to use this module

* terraform-docs: automated action

* fix: file line endings
* chore: renamed vars.tf to variables.tf files

Signed-off-by: leonsteinhaeuser <[email protected]>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
  • Loading branch information
leonsteinhaeuser and github-actions[bot] authored Sep 18, 2023
1 parent 0e7f667 commit 6e211da
Show file tree
Hide file tree
Showing 16 changed files with 588 additions and 47 deletions.
82 changes: 82 additions & 0 deletions .terraform.lock.hcl

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

143 changes: 96 additions & 47 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,70 +1,119 @@
# terraform-module-template

A template repository to provide a basic setup for Terraform modules.

## Module structure

The module structure is based on the [Terraform module documentation](https://www.terraform.io/docs/modules/index.html#standard-module-structure). The following tree shows the structure of the module.

```txt
├── .gitignore
├── LICENSE
├── README.md
├── docs
│ └── README.md
├── examples
│ ├── complete
│ │ ├── main.tf
│ │ ├── outputs.tf
│ │ ├── variables.tf
│ │ └── versions.tf
│ ├── minimal
│ │ ├── main.tf
│ │ ├── outputs.tf
│ │ ├── variables.tf
│ │ └── versions.tf
├── main.tf
├── outputs.tf
├── variables.tf
└── versions.tf
# Terraform AWS dynamic provider credentials

This module creates a dynamic credentials setup between AWS and Terraform Cloud (project). It creates an IAM policy, IAM role, and IAM role policy attachment. It also creates a Terraform Cloud variable set with the AWS configurations. For more information on dynamic provider credentials, see [Dynamic Provider Credentials](https://developer.hashicorp.com/terraform/cloud-docs/workspaces/dynamic-provider-credentials).

## Usage

```terraform
// one-time credentials to setup the dynamic credentials
// this is the only time you need to provide credentials
// after this, the dynamic credentials will be used.
// If the setup was successful, `access_key` and `secret_key` should be removed.
provider "aws" {
region = var.aws_region
access_key = var.access_key
secret_key = var.secret_key
}
module "aws_dynamic_provider_credentials" {
source = "tagesspiegel/dynamic-provider-credentials/aws"
version = "1.0.0"
tfc_organization = "my-org"
tfc_project = "my-project"
tfc_workspaces = [{
name_override = "my-project-auth"
workspace = "*"
run_phase = "*"
policies = [
{
Effect = "Allow"
Action = [
"ec2:*"
]
Resource = "*"
},
{
Effect = "Allow"
Action = [
"ram:*"
]
Resource = "*"
},
{
Effect = "Allow"
Action = [
"cloudwatch:*"
]
Resource = "*"
},
{
Effect = "Allow"
Action = [
"logs:*"
]
Resource = "*"
},
{
Effect = "Allow"
Action = [
"kms:*"
]
Resource = "*"
}
]
}]
}
```

## Working with this template

In order to use this template, you can use the GitHub template feature. This will create a new repository based on this template. After that, you can clone the repository and start working on it.

### Creating a new repository based on this template

To get started with this template, you have to navigate https://github.com/new and select the Tagesspiegel organization. After that, you can select the `terraform-module-template` repository, enter a name for your new repository and click on `Create repository`. Please note that you have to define a name for your new repository that is not already taken and follows the naming conventions (`terraform-<provider>-<name>`).

![Create GitHub repository based on template](docs/github_create_repository.png)

If everything worked as expected, you should now have a new repository based on this template. You can now clone the repository and start working on it.

<!-- BEGIN_TF_DOCS -->
## Requirements

| Name | Version |
|------|---------|
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | ~> 1.5.6 |
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | ~> 5.3.0 |

## Providers

No providers.
| Name | Version |
|------|---------|
| <a name="provider_tfe"></a> [tfe](#provider\_tfe) | 0.48.0 |

## Modules

No modules.
| Name | Source | Version |
|------|--------|---------|
| <a name="module_aws_identity_provider"></a> [aws\_identity\_provider](#module\_aws\_identity\_provider) | ./modules/iam_identity_provider | n/a |
| <a name="module_aws_tfc_dynamic_credentials_iam_roles"></a> [aws\_tfc\_dynamic\_credentials\_iam\_roles](#module\_aws\_tfc\_dynamic\_credentials\_iam\_roles) | ./modules/iam_roles | n/a |

## Resources

No resources.
| Name | Type |
|------|------|
| [tfe_project_variable_set.tfc_project](https://registry.terraform.io/providers/hashicorp/tfe/latest/docs/resources/project_variable_set) | resource |
| [tfe_variable.tfe_aws_provider_auth](https://registry.terraform.io/providers/hashicorp/tfe/latest/docs/resources/variable) | resource |
| [tfe_variable.tfe_aws_provider_auth_arn](https://registry.terraform.io/providers/hashicorp/tfe/latest/docs/resources/variable) | resource |
| [tfe_variable_set.tfc_aws_dynamic_credentials](https://registry.terraform.io/providers/hashicorp/tfe/latest/docs/resources/variable_set) | resource |
| [tfe_project.tfc_project](https://registry.terraform.io/providers/hashicorp/tfe/latest/docs/data-sources/project) | data source |

## Inputs

No inputs.
| Name | Description | Type | Default | Required |
|------|-------------|------|---------|:--------:|
| <a name="input_tfc_aws_audience"></a> [tfc\_aws\_audience](#input\_tfc\_aws\_audience) | AWS audience | `string` | `"aws.workload.identity"` | no |
| <a name="input_tfc_hostname"></a> [tfc\_hostname](#input\_tfc\_hostname) | The hostname of the TFC or TFE instance you'd like to use with AWS | `string` | `"app.terraform.io"` | no |
| <a name="input_tfc_organization"></a> [tfc\_organization](#input\_tfc\_organization) | Name of the organization | `string` | n/a | yes |
| <a name="input_tfc_project"></a> [tfc\_project](#input\_tfc\_project) | Name of the terraform cloud/enterprise project | `string` | n/a | yes |
| <a name="input_tfc_workspaces"></a> [tfc\_workspaces](#input\_tfc\_workspaces) | List of workspaces to create IAM roles for | <pre>list(object({<br> name_override = string<br> workspace = string<br> run_phase = string<br> policies = list(object({<br> Effect = string<br> Action = list(string)<br> Resource = string<br> }))<br> }))</pre> | n/a | yes |

## Outputs

No outputs.
<!-- END_TF_DOCS -->
| Name | Description |
|------|-------------|
| <a name="output_aws_tfc_audience"></a> [aws\_tfc\_audience](#output\_aws\_tfc\_audience) | n/a |
| <a name="output_full_names"></a> [full\_names](#output\_full\_names) | A list of all 'full\_name' values |
| <a name="output_oidc_claims"></a> [oidc\_claims](#output\_oidc\_claims) | A map of 'full\_name' as key and 'openid\_claims' as value |
| <a name="output_role_arns"></a> [role\_arns](#output\_role\_arns) | A map of 'full\_name' as key and 'role\_arn' as value |
<!-- END_TF_DOCS -->
66 changes: 66 additions & 0 deletions main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
// import the aws oidc identity provider module
// this module allows us to authenticate from terraform cloud to aws using oidc
module "aws_identity_provider" {
source = "./modules/iam_identity_provider"
tfc_organization = var.tfc_organization
tfc_aws_audience = var.tfc_aws_audience
tfc_hostname = var.tfc_hostname
}

// aws iam roles that are created to grant permissions to terraform cloud
module "aws_tfc_dynamic_credentials_iam_roles" {
source = "./modules/iam_roles"

depends_on = [
module.aws_identity_provider
]

for_each = { for workspace in var.tfc_workspaces : "${workspace.name_override}" => workspace }

tfc_organization_name = var.tfc_organization
tfc_project_name = var.tfc_project

tfc_oidc_provider_arn = module.aws_identity_provider.aws_oidc_tfc_provider_arn
tfc_oidc_provider_client_id_list = module.aws_identity_provider.aws_oidc_tfc_provider_client_id_list

aws_iam_role_name_override = each.value.name_override
tfc_workspace_name = each.value.workspace
tfc_run_phase = each.value.run_phase
aws_iam_custom_policies = each.value.policies
}

// create a variable set
resource "tfe_variable_set" "tfc_aws_dynamic_credentials" {
name = "aws-dynamic-credentials-${var.tfc_project}"
description = "AWS dynamic credentials"
organization = var.tfc_organization
}

// get the project id
data "tfe_project" "tfc_project" {
name = var.tfc_project
organization = var.tfc_organization
}

// assign the variable set to the project
resource "tfe_project_variable_set" "tfc_project" {
variable_set_id = tfe_variable_set.tfc_aws_dynamic_credentials.id
project_id = data.tfe_project.tfc_project.id
}

// create the variables
resource "tfe_variable" "tfe_aws_provider_auth" {
key = "TFC_AWS_PROVIDER_AUTH"
value = "true"
category = "env"
description = "AWS provider auth"
variable_set_id = tfe_variable_set.tfc_aws_dynamic_credentials.id
}

resource "tfe_variable" "tfe_aws_provider_auth_arn" {
key = "TFC_AWS_RUN_ROLE_ARN"
value = module.aws_tfc_dynamic_credentials_iam_roles["${var.tfc_project}-auth"].role_arn
category = "env"
description = "AWS provider auth"
variable_set_id = tfe_variable_set.tfc_aws_dynamic_credentials.id
}
63 changes: 63 additions & 0 deletions modules/iam_identity_provider/.terraform.lock.hcl

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 6e211da

Please sign in to comment.