Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
7b629f1
first draft of az oidc module
TylerMizuyabu May 28, 2024
8d22d8a
added azure github secret configuration option for oidc
TylerMizuyabu May 28, 2024
e3ec571
removed some comments
TylerMizuyabu May 28, 2024
97bf42e
fmted
TylerMizuyabu May 28, 2024
c4c76d2
fixed bad references
TylerMizuyabu May 28, 2024
9335553
fixed variable validation
TylerMizuyabu May 28, 2024
47a871c
fixed variable validation
TylerMizuyabu May 28, 2024
fae167c
fixed variable reference
TylerMizuyabu May 28, 2024
44a2303
fixed variable validation
TylerMizuyabu May 28, 2024
4ca15af
fixed data source reference
TylerMizuyabu May 28, 2024
f13fef1
fix variable reference
TylerMizuyabu May 29, 2024
74ba55a
trying something
TylerMizuyabu May 29, 2024
e983ade
trying something else
TylerMizuyabu May 29, 2024
8bb1fb0
trying something else
TylerMizuyabu May 29, 2024
28a7206
fixed default encryption scope variable
TylerMizuyabu May 29, 2024
7a6c642
I can't believe I have to work around another terraform provider bug
TylerMizuyabu May 29, 2024
24e27c5
change it from being a set
TylerMizuyabu May 29, 2024
ebbab31
changed to a map
TylerMizuyabu May 29, 2024
752da7f
fix role keys
TylerMizuyabu May 29, 2024
5f18f53
fixing outputs
TylerMizuyabu May 29, 2024
c6162cd
changed some secrest to variables
TylerMizuyabu May 30, 2024
65739c5
added keyvault reader
TylerMizuyabu May 30, 2024
d0f31dc
changed contributor permissions to owner
TylerMizuyabu May 30, 2024
aa9ac65
adding storage account contributor
TylerMizuyabu May 30, 2024
83006a4
terraform-docs: automated action
github-actions[bot] May 30, 2024
550e100
making kv_name optional so user's can bring a different secret store …
TylerMizuyabu May 30, 2024
408a843
forgot to index
TylerMizuyabu May 30, 2024
515a8a2
terraform-docs: automated action
github-actions[bot] May 30, 2024
b413c13
Update modules/github-azure-oidc/oidc.tf
TylerMizuyabu May 31, 2024
c4123c9
Update modules/github-azure-oidc/oidc.tf
TylerMizuyabu May 31, 2024
cfbbb05
Update modules/github-azure-oidc/storage.tf
TylerMizuyabu May 31, 2024
e0af781
Update modules/github-azure-oidc/storage.tf
TylerMizuyabu May 31, 2024
1602e30
Update modules/github-azure-oidc/variables.tf
TylerMizuyabu May 31, 2024
36b189d
Update modules/github-foundations/azure-oidc-variables.tf
TylerMizuyabu May 31, 2024
ea12349
Update modules/github-foundations/azure-oidc-variables.tf
TylerMizuyabu May 31, 2024
3e973af
update input description and set defaults for sa tier and redundancy …
TylerMizuyabu May 31, 2024
0c13d92
terraform-docs: automated action
github-actions[bot] May 31, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 70 additions & 0 deletions modules/github-azure-oidc/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
## Requirements

| Name | Version |
|------|---------|
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 1.6 |
| <a name="requirement_azurerm"></a> [azurerm](#requirement\_azurerm) | >=3.0.0 |
| <a name="requirement_google-beta"></a> [google-beta](#requirement\_google-beta) | >= 3.77 |
| <a name="requirement_random"></a> [random](#requirement\_random) | >= 3.6 |

## Providers

| Name | Version |
|------|---------|
| <a name="provider_azurerm"></a> [azurerm](#provider\_azurerm) | >=3.0.0 |

## Modules

No modules.

## Resources

| Name | Type |
|------|------|
| [azurerm_federated_identity_credential.bootstrap_drift_credentials](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/federated_identity_credential) | resource |
| [azurerm_federated_identity_credential.bootstrap_pull_request_credentials](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/federated_identity_credential) | resource |
| [azurerm_federated_identity_credential.organization_drift_credentials](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/federated_identity_credential) | resource |
| [azurerm_federated_identity_credential.organization_pull_request_credentials](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/federated_identity_credential) | resource |
| [azurerm_resource_group.github_foundations_rg](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/resource_group) | resource |
| [azurerm_role_assignment.bootstrap_role_assignment](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/role_assignment) | resource |
| [azurerm_role_assignment.organization_role_assignment](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/role_assignment) | resource |
| [azurerm_storage_account.github_foundations_sa](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/storage_account) | resource |
| [azurerm_storage_container.github_foundations_tf_state_container](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/storage_container) | resource |
| [azurerm_storage_container.github_foundations_tf_state_encrypted_container](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/storage_container) | resource |
| [azurerm_storage_encryption_scope.encryption_scope](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/storage_encryption_scope) | resource |
| [azurerm_user_assigned_identity.bootstrap_identity](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/user_assigned_identity) | resource |
| [azurerm_user_assigned_identity.organization_identity](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/user_assigned_identity) | resource |
| [azurerm_client_config.current](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/data-sources/client_config) | data source |
| [azurerm_key_vault.key_vault](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/data-sources/key_vault) | data source |
| [azurerm_resource_group.github_foundations_rg](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/data-sources/resource_group) | data source |

## Inputs

| Name | Description | Type | Default | Required |
|------|-------------|------|---------|:--------:|
| <a name="input_drift_detection_branch_name"></a> [drift\_detection\_branch\_name](#input\_drift\_detection\_branch\_name) | The name of the branch to use for drift detection. | `string` | n/a | yes |
| <a name="input_github_foundations_organization_name"></a> [github\_foundations\_organization\_name](#input\_github\_foundations\_organization\_name) | The name of the organization that the github foundation repos will be under. | `string` | n/a | yes |
| <a name="input_kv_name"></a> [kv\_name](#input\_kv\_name) | The name of the key vault to use for github foundation secrets. If storing secrets to authenticate against github in a different way then this does not need to be set. (Optional) | `string` | `""` | no |
| <a name="input_kv_resource_group"></a> [kv\_resource\_group](#input\_kv\_resource\_group) | The name of the resource group that the key vault is in. If empty it will default to the github foundations resource group. | `string` | n/a | yes |
| <a name="input_rg_create"></a> [rg\_create](#input\_rg\_create) | Create the resource group. When set to false it uses the `rg_name` input to reference an existing resource group. Defaults to true. | `bool` | `true` | no |
| <a name="input_rg_location"></a> [rg\_location](#input\_rg\_location) | The location of the resource group to create the github foundation azure resources in. | `string` | n/a | yes |
| <a name="input_rg_name"></a> [rg\_name](#input\_rg\_name) | The name of the resource group to create the github foundation azure resources in. | `string` | n/a | yes |
| <a name="input_sa_name"></a> [sa\_name](#input\_sa\_name) | The name of the storage account for github foundations. | `string` | n/a | yes |
| <a name="input_sa_replication_type"></a> [sa\_replication\_type](#input\_sa\_replication\_type) | The replication type of the storage account for github foundations. Valid options are LRS, GRS, RAGRS, ZRS, GZRS, and RA\_GZRS. Defaults to GRS. | `string` | `"GRS"` | no |
| <a name="input_sa_tier"></a> [sa\_tier](#input\_sa\_tier) | The tier of the storage account for github foundations. Valid options are Standard and Premium. Defaults to Standard. | `string` | `"Standard"` | no |
| <a name="input_tf_state_container"></a> [tf\_state\_container](#input\_tf\_state\_container) | The name of the container to store the terraform state file(s) in. | `string` | `"tfstate"` | no |
| <a name="input_tf_state_container_anonymous_access_level"></a> [tf\_state\_container\_anonymous\_access\_level](#input\_tf\_state\_container\_anonymous\_access\_level) | The anonymous access level of the container to store the terraform state file(s) in. | `string` | `"private"` | no |
| <a name="input_tf_state_container_default_encryption_scope"></a> [tf\_state\_container\_default\_encryption\_scope](#input\_tf\_state\_container\_default\_encryption\_scope) | The default encryption scope of the container to store the terraform state file(s) in. | <pre>object({<br> name = string<br> source = string<br> key_vault_key_id = optional(string)<br> })</pre> | <pre>{<br> "name": "",<br> "source": "",<br> "storage_account_id": ""<br>}</pre> | no |
| <a name="input_tf_state_container_encryption_scope_override_enabled"></a> [tf\_state\_container\_encryption\_scope\_override\_enabled](#input\_tf\_state\_container\_encryption\_scope\_override\_enabled) | Whether or not the encryption scope override is enabled for the container to store the terraform state file(s) in. Defaults to false | `bool` | `false` | no |

## Outputs

| Name | Description |
|------|-------------|
| <a name="output_bootstrap_client_id"></a> [bootstrap\_client\_id](#output\_bootstrap\_client\_id) | Bootstrap repository client id for authenticating with oidc. |
| <a name="output_container_name"></a> [container\_name](#output\_container\_name) | Terraform state container name. |
| <a name="output_organization_client_id"></a> [organization\_client\_id](#output\_organization\_client\_id) | Organizations repository client id for authenticating with oidc. |
| <a name="output_resource_group"></a> [resource\_group](#output\_resource\_group) | Resource group name. |
| <a name="output_sa_name"></a> [sa\_name](#output\_sa\_name) | Terraform state container storage account name. |
| <a name="output_subscription_id"></a> [subscription\_id](#output\_subscription\_id) | Azure subscription id for authenticating with oidc. |
| <a name="output_tenant_id"></a> [tenant\_id](#output\_tenant\_id) | Azure tenant id for authenticating with oidc. |
109 changes: 109 additions & 0 deletions modules/github-azure-oidc/oidc.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
locals {
default_audience_name = "api://AzureADTokenExchange"
github_issuer_url = "https://token.actions.githubusercontent.com"

bootstrap_repo_name = "bootstrap"
organizations_repo_name = "organizations"

state_file_access_roles = {
"container-${local.tf_state_container.name}-write" = {
scope = "${local.tf_state_container.resource_manager_id}"
role_definition_name = "Storage Blob Data Contributor"
},
"storage-account-${azurerm_storage_account.github_foundations_sa.name}-contributor" = {
scope = "${azurerm_storage_account.github_foundations_sa.id}"
role_definition_name = "Storage Account Contributor"
}
}

bootstrap_project_roles = local.state_file_access_roles

organizations_project_roles = merge(
local.state_file_access_roles,
var.kv_name != "" ? {
"keyvault-${data.azurerm_key_vault.key_vault[0].name}-secret-read" = {
scope = "${data.azurerm_key_vault.key_vault[0].id}"
role_definition_name = "Key Vault Secrets User"
}
}: {},
var.kv_name != "" ? {
"keyvault-${data.azurerm_key_vault.key_vault[0].name}-vault-read" = {
scope = "${data.azurerm_key_vault.key_vault[0].id}"
role_definition_name = "Key Vault Reader"
}
}: {}
)
}

data "azurerm_client_config" "current" {}

data "azurerm_key_vault" "key_vault" {
count = var.kv_name != "" ? 1 : 0
name = var.kv_name
resource_group_name = var.kv_resource_group != "" ? var.kv_resource_group : local.github_foundations_rg.name
}

/**
* User assigned identities and roles for github state bucket and federated identity setup
*/
resource "azurerm_user_assigned_identity" "bootstrap_identity" {
location = local.github_foundations_rg.location
resource_group_name = local.github_foundations_rg.name
name = "${local.bootstrap_repo_name}-identity"
}

resource "azurerm_role_assignment" "bootstrap_role_assignment" {
for_each = local.bootstrap_project_roles
scope = each.value.scope
role_definition_name = each.value.role_definition_name
principal_id = azurerm_user_assigned_identity.bootstrap_identity.principal_id
}

resource "azurerm_user_assigned_identity" "organization_identity" {
location = local.github_foundations_rg.location
resource_group_name = local.github_foundations_rg.name
name = "${local.organizations_repo_name}-identity"
}

resource "azurerm_role_assignment" "organization_role_assignment" {
for_each = local.organizations_project_roles
scope = each.value.scope
role_definition_name = each.value.role_definition_name
principal_id = azurerm_user_assigned_identity.organization_identity.principal_id
}

resource "azurerm_federated_identity_credential" "bootstrap_pull_request_credentials" {
name = "${var.github_foundations_organization_name}-${local.bootstrap_repo_name}-pr-credentials"
resource_group_name = local.github_foundations_rg.name
audience = [local.default_audience_name]
issuer = local.github_issuer_url
parent_id = azurerm_user_assigned_identity.bootstrap_identity.id
subject = "repo:${var.github_foundations_organization_name}/${local.bootstrap_repo_name}:pull_request"
}

resource "azurerm_federated_identity_credential" "bootstrap_drift_credentials" {
name = "${var.github_foundations_organization_name}-${local.bootstrap_repo_name}-drift-credentials"
resource_group_name = local.github_foundations_rg.name
audience = [local.default_audience_name]
issuer = local.github_issuer_url
parent_id = azurerm_user_assigned_identity.bootstrap_identity.id
subject = "repo:${var.github_foundations_organization_name}/${local.bootstrap_repo_name}:ref:refs/heads/${var.drift_detection_branch_name}"
}

resource "azurerm_federated_identity_credential" "organization_pull_request_credentials" {
name = "${var.github_foundations_organization_name}-${local.organizations_repo_name}-pr-credentials"
resource_group_name = local.github_foundations_rg.name
audience = [local.default_audience_name]
issuer = local.github_issuer_url
parent_id = azurerm_user_assigned_identity.organization_identity.id
subject = "repo:${var.github_foundations_organization_name}/${local.organizations_repo_name}:pull_request"
}

resource "azurerm_federated_identity_credential" "organization_drift_credentials" {
name = "${var.github_foundations_organization_name}-${local.organizations_repo_name}-drift-credentials"
resource_group_name = local.github_foundations_rg.name
audience = [local.default_audience_name]
issuer = local.github_issuer_url
parent_id = azurerm_user_assigned_identity.organization_identity.id
subject = "repo:${var.github_foundations_organization_name}/${local.organizations_repo_name}:ref:refs/heads/${var.drift_detection_branch_name}"
}
34 changes: 34 additions & 0 deletions modules/github-azure-oidc/outputs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
output "resource_group" {
description = "Resource group name."
value = local.github_foundations_rg.name
}

output "bootstrap_client_id" {
description = "Bootstrap repository client id for authenticating with oidc."
value = azurerm_user_assigned_identity.bootstrap_identity.client_id
}

output "organization_client_id" {
description = "Organizations repository client id for authenticating with oidc."
value = azurerm_user_assigned_identity.organization_identity.client_id
}

output "tenant_id" {
description = "Azure tenant id for authenticating with oidc."
value = data.azurerm_client_config.current.tenant_id
}

output "subscription_id" {
description = "Azure subscription id for authenticating with oidc."
value = data.azurerm_client_config.current.subscription_id
}

output "sa_name" {
description = "Terraform state container storage account name."
value = azurerm_storage_account.github_foundations_sa.name
}

output "container_name" {
description = "Terraform state container name."
value = local.tf_state_container.name
}
17 changes: 17 additions & 0 deletions modules/github-azure-oidc/resource_group.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
locals {
github_foundations_rg = (
var.rg_create
? try(azurerm_resource_group.github_foundations_rg[0], null)
: try(data.azurerm_resource_group.github_foundations_rg[0], null)
)
}

data "azurerm_resource_group" "github_foundations_rg" {
count = var.rg_create ? 0 : 1
name = var.rg_name
}
resource "azurerm_resource_group" "github_foundations_rg" {
count = var.rg_create ? 1 : 0
name = var.rg_name
location = var.rg_location
}
36 changes: 36 additions & 0 deletions modules/github-azure-oidc/storage.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
locals {
default_encryption_scope = var.tf_state_container_default_encryption_scope.name != "" ? azurerm_storage_encryption_scope.encryption_scope[0].name : null
tf_state_container = local.default_encryption_scope == null ? azurerm_storage_container.github_foundations_tf_state_container[0] : azurerm_storage_container.github_foundations_tf_state_encrypted_container[0]
}

resource "azurerm_storage_account" "github_foundations_sa" {
name = var.sa_name
resource_group_name = local.github_foundations_rg.name
location = local.github_foundations_rg.location
account_tier = var.sa_tier
account_replication_type = var.sa_replication_type
}

resource "azurerm_storage_encryption_scope" "encryption_scope" {
count = var.tf_state_container_default_encryption_scope.name != "" ? 1 : 0
name = var.tf_state_container_default_encryption_scope.name
storage_account_id = azurerm_storage_account.github_foundations_sa.id
source = var.tf_state_container_default_encryption_scope.source
key_vault_key_id = var.tf_state_container_default_encryption_scope.key_vault_key_id
}

resource "azurerm_storage_container" "github_foundations_tf_state_container" {
count = local.default_encryption_scope == null ? 1 : 0
name = var.tf_state_container
storage_account_name = azurerm_storage_account.github_foundations_sa.name
container_access_type = var.tf_state_container_anonymous_access_level
}

resource "azurerm_storage_container" "github_foundations_tf_state_encrypted_container" {
count = local.default_encryption_scope != null ? 1 : 0
name = var.tf_state_container
storage_account_name = azurerm_storage_account.github_foundations_sa.name
container_access_type = var.tf_state_container_anonymous_access_level
default_encryption_scope = local.default_encryption_scope
encryption_scope_override_enabled = var.tf_state_container_encryption_scope_override_enabled
}
Loading