Skip to content

Commit 0fd79c4

Browse files
TylerMizuyabugithub-actions[bot]bzarboni1
authored
Az OIDC (#45)
* Added module to setup azure oidc --------- Signed-off-by: TylerMizuyabu <tyler.mizuyabu@focisolutions.com> Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> Co-authored-by: Ben Zarboni <99673202+bzarboni1@users.noreply.github.com>
1 parent 39648f9 commit 0fd79c4

10 files changed

Lines changed: 483 additions & 2 deletions

File tree

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
## Requirements
2+
3+
| Name | Version |
4+
|------|---------|
5+
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 1.6 |
6+
| <a name="requirement_azurerm"></a> [azurerm](#requirement\_azurerm) | >=3.0.0 |
7+
| <a name="requirement_google-beta"></a> [google-beta](#requirement\_google-beta) | >= 3.77 |
8+
| <a name="requirement_random"></a> [random](#requirement\_random) | >= 3.6 |
9+
10+
## Providers
11+
12+
| Name | Version |
13+
|------|---------|
14+
| <a name="provider_azurerm"></a> [azurerm](#provider\_azurerm) | >=3.0.0 |
15+
16+
## Modules
17+
18+
No modules.
19+
20+
## Resources
21+
22+
| Name | Type |
23+
|------|------|
24+
| [azurerm_federated_identity_credential.bootstrap_drift_credentials](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/federated_identity_credential) | resource |
25+
| [azurerm_federated_identity_credential.bootstrap_pull_request_credentials](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/federated_identity_credential) | resource |
26+
| [azurerm_federated_identity_credential.organization_drift_credentials](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/federated_identity_credential) | resource |
27+
| [azurerm_federated_identity_credential.organization_pull_request_credentials](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/federated_identity_credential) | resource |
28+
| [azurerm_resource_group.github_foundations_rg](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/resource_group) | resource |
29+
| [azurerm_role_assignment.bootstrap_role_assignment](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/role_assignment) | resource |
30+
| [azurerm_role_assignment.organization_role_assignment](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/role_assignment) | resource |
31+
| [azurerm_storage_account.github_foundations_sa](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/storage_account) | resource |
32+
| [azurerm_storage_container.github_foundations_tf_state_container](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/storage_container) | resource |
33+
| [azurerm_storage_container.github_foundations_tf_state_encrypted_container](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/storage_container) | resource |
34+
| [azurerm_storage_encryption_scope.encryption_scope](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/storage_encryption_scope) | resource |
35+
| [azurerm_user_assigned_identity.bootstrap_identity](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/user_assigned_identity) | resource |
36+
| [azurerm_user_assigned_identity.organization_identity](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/user_assigned_identity) | resource |
37+
| [azurerm_client_config.current](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/data-sources/client_config) | data source |
38+
| [azurerm_key_vault.key_vault](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/data-sources/key_vault) | data source |
39+
| [azurerm_resource_group.github_foundations_rg](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/data-sources/resource_group) | data source |
40+
41+
## Inputs
42+
43+
| Name | Description | Type | Default | Required |
44+
|------|-------------|------|---------|:--------:|
45+
| <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 |
46+
| <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 |
47+
| <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 |
48+
| <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 |
49+
| <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 |
50+
| <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 |
51+
| <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 |
52+
| <a name="input_sa_name"></a> [sa\_name](#input\_sa\_name) | The name of the storage account for github foundations. | `string` | n/a | yes |
53+
| <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 |
54+
| <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 |
55+
| <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 |
56+
| <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 |
57+
| <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 |
58+
| <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 |
59+
60+
## Outputs
61+
62+
| Name | Description |
63+
|------|-------------|
64+
| <a name="output_bootstrap_client_id"></a> [bootstrap\_client\_id](#output\_bootstrap\_client\_id) | Bootstrap repository client id for authenticating with oidc. |
65+
| <a name="output_container_name"></a> [container\_name](#output\_container\_name) | Terraform state container name. |
66+
| <a name="output_organization_client_id"></a> [organization\_client\_id](#output\_organization\_client\_id) | Organizations repository client id for authenticating with oidc. |
67+
| <a name="output_resource_group"></a> [resource\_group](#output\_resource\_group) | Resource group name. |
68+
| <a name="output_sa_name"></a> [sa\_name](#output\_sa\_name) | Terraform state container storage account name. |
69+
| <a name="output_subscription_id"></a> [subscription\_id](#output\_subscription\_id) | Azure subscription id for authenticating with oidc. |
70+
| <a name="output_tenant_id"></a> [tenant\_id](#output\_tenant\_id) | Azure tenant id for authenticating with oidc. |

modules/github-azure-oidc/oidc.tf

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
locals {
2+
default_audience_name = "api://AzureADTokenExchange"
3+
github_issuer_url = "https://token.actions.githubusercontent.com"
4+
5+
bootstrap_repo_name = "bootstrap"
6+
organizations_repo_name = "organizations"
7+
8+
state_file_access_roles = {
9+
"container-${local.tf_state_container.name}-write" = {
10+
scope = "${local.tf_state_container.resource_manager_id}"
11+
role_definition_name = "Storage Blob Data Contributor"
12+
},
13+
"storage-account-${azurerm_storage_account.github_foundations_sa.name}-contributor" = {
14+
scope = "${azurerm_storage_account.github_foundations_sa.id}"
15+
role_definition_name = "Storage Account Contributor"
16+
}
17+
}
18+
19+
bootstrap_project_roles = local.state_file_access_roles
20+
21+
organizations_project_roles = merge(
22+
local.state_file_access_roles,
23+
var.kv_name != "" ? {
24+
"keyvault-${data.azurerm_key_vault.key_vault[0].name}-secret-read" = {
25+
scope = "${data.azurerm_key_vault.key_vault[0].id}"
26+
role_definition_name = "Key Vault Secrets User"
27+
}
28+
}: {},
29+
var.kv_name != "" ? {
30+
"keyvault-${data.azurerm_key_vault.key_vault[0].name}-vault-read" = {
31+
scope = "${data.azurerm_key_vault.key_vault[0].id}"
32+
role_definition_name = "Key Vault Reader"
33+
}
34+
}: {}
35+
)
36+
}
37+
38+
data "azurerm_client_config" "current" {}
39+
40+
data "azurerm_key_vault" "key_vault" {
41+
count = var.kv_name != "" ? 1 : 0
42+
name = var.kv_name
43+
resource_group_name = var.kv_resource_group != "" ? var.kv_resource_group : local.github_foundations_rg.name
44+
}
45+
46+
/**
47+
* User assigned identities and roles for github state bucket and federated identity setup
48+
*/
49+
resource "azurerm_user_assigned_identity" "bootstrap_identity" {
50+
location = local.github_foundations_rg.location
51+
resource_group_name = local.github_foundations_rg.name
52+
name = "${local.bootstrap_repo_name}-identity"
53+
}
54+
55+
resource "azurerm_role_assignment" "bootstrap_role_assignment" {
56+
for_each = local.bootstrap_project_roles
57+
scope = each.value.scope
58+
role_definition_name = each.value.role_definition_name
59+
principal_id = azurerm_user_assigned_identity.bootstrap_identity.principal_id
60+
}
61+
62+
resource "azurerm_user_assigned_identity" "organization_identity" {
63+
location = local.github_foundations_rg.location
64+
resource_group_name = local.github_foundations_rg.name
65+
name = "${local.organizations_repo_name}-identity"
66+
}
67+
68+
resource "azurerm_role_assignment" "organization_role_assignment" {
69+
for_each = local.organizations_project_roles
70+
scope = each.value.scope
71+
role_definition_name = each.value.role_definition_name
72+
principal_id = azurerm_user_assigned_identity.organization_identity.principal_id
73+
}
74+
75+
resource "azurerm_federated_identity_credential" "bootstrap_pull_request_credentials" {
76+
name = "${var.github_foundations_organization_name}-${local.bootstrap_repo_name}-pr-credentials"
77+
resource_group_name = local.github_foundations_rg.name
78+
audience = [local.default_audience_name]
79+
issuer = local.github_issuer_url
80+
parent_id = azurerm_user_assigned_identity.bootstrap_identity.id
81+
subject = "repo:${var.github_foundations_organization_name}/${local.bootstrap_repo_name}:pull_request"
82+
}
83+
84+
resource "azurerm_federated_identity_credential" "bootstrap_drift_credentials" {
85+
name = "${var.github_foundations_organization_name}-${local.bootstrap_repo_name}-drift-credentials"
86+
resource_group_name = local.github_foundations_rg.name
87+
audience = [local.default_audience_name]
88+
issuer = local.github_issuer_url
89+
parent_id = azurerm_user_assigned_identity.bootstrap_identity.id
90+
subject = "repo:${var.github_foundations_organization_name}/${local.bootstrap_repo_name}:ref:refs/heads/${var.drift_detection_branch_name}"
91+
}
92+
93+
resource "azurerm_federated_identity_credential" "organization_pull_request_credentials" {
94+
name = "${var.github_foundations_organization_name}-${local.organizations_repo_name}-pr-credentials"
95+
resource_group_name = local.github_foundations_rg.name
96+
audience = [local.default_audience_name]
97+
issuer = local.github_issuer_url
98+
parent_id = azurerm_user_assigned_identity.organization_identity.id
99+
subject = "repo:${var.github_foundations_organization_name}/${local.organizations_repo_name}:pull_request"
100+
}
101+
102+
resource "azurerm_federated_identity_credential" "organization_drift_credentials" {
103+
name = "${var.github_foundations_organization_name}-${local.organizations_repo_name}-drift-credentials"
104+
resource_group_name = local.github_foundations_rg.name
105+
audience = [local.default_audience_name]
106+
issuer = local.github_issuer_url
107+
parent_id = azurerm_user_assigned_identity.organization_identity.id
108+
subject = "repo:${var.github_foundations_organization_name}/${local.organizations_repo_name}:ref:refs/heads/${var.drift_detection_branch_name}"
109+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
output "resource_group" {
2+
description = "Resource group name."
3+
value = local.github_foundations_rg.name
4+
}
5+
6+
output "bootstrap_client_id" {
7+
description = "Bootstrap repository client id for authenticating with oidc."
8+
value = azurerm_user_assigned_identity.bootstrap_identity.client_id
9+
}
10+
11+
output "organization_client_id" {
12+
description = "Organizations repository client id for authenticating with oidc."
13+
value = azurerm_user_assigned_identity.organization_identity.client_id
14+
}
15+
16+
output "tenant_id" {
17+
description = "Azure tenant id for authenticating with oidc."
18+
value = data.azurerm_client_config.current.tenant_id
19+
}
20+
21+
output "subscription_id" {
22+
description = "Azure subscription id for authenticating with oidc."
23+
value = data.azurerm_client_config.current.subscription_id
24+
}
25+
26+
output "sa_name" {
27+
description = "Terraform state container storage account name."
28+
value = azurerm_storage_account.github_foundations_sa.name
29+
}
30+
31+
output "container_name" {
32+
description = "Terraform state container name."
33+
value = local.tf_state_container.name
34+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
locals {
2+
github_foundations_rg = (
3+
var.rg_create
4+
? try(azurerm_resource_group.github_foundations_rg[0], null)
5+
: try(data.azurerm_resource_group.github_foundations_rg[0], null)
6+
)
7+
}
8+
9+
data "azurerm_resource_group" "github_foundations_rg" {
10+
count = var.rg_create ? 0 : 1
11+
name = var.rg_name
12+
}
13+
resource "azurerm_resource_group" "github_foundations_rg" {
14+
count = var.rg_create ? 1 : 0
15+
name = var.rg_name
16+
location = var.rg_location
17+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
locals {
2+
default_encryption_scope = var.tf_state_container_default_encryption_scope.name != "" ? azurerm_storage_encryption_scope.encryption_scope[0].name : null
3+
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]
4+
}
5+
6+
resource "azurerm_storage_account" "github_foundations_sa" {
7+
name = var.sa_name
8+
resource_group_name = local.github_foundations_rg.name
9+
location = local.github_foundations_rg.location
10+
account_tier = var.sa_tier
11+
account_replication_type = var.sa_replication_type
12+
}
13+
14+
resource "azurerm_storage_encryption_scope" "encryption_scope" {
15+
count = var.tf_state_container_default_encryption_scope.name != "" ? 1 : 0
16+
name = var.tf_state_container_default_encryption_scope.name
17+
storage_account_id = azurerm_storage_account.github_foundations_sa.id
18+
source = var.tf_state_container_default_encryption_scope.source
19+
key_vault_key_id = var.tf_state_container_default_encryption_scope.key_vault_key_id
20+
}
21+
22+
resource "azurerm_storage_container" "github_foundations_tf_state_container" {
23+
count = local.default_encryption_scope == null ? 1 : 0
24+
name = var.tf_state_container
25+
storage_account_name = azurerm_storage_account.github_foundations_sa.name
26+
container_access_type = var.tf_state_container_anonymous_access_level
27+
}
28+
29+
resource "azurerm_storage_container" "github_foundations_tf_state_encrypted_container" {
30+
count = local.default_encryption_scope != null ? 1 : 0
31+
name = var.tf_state_container
32+
storage_account_name = azurerm_storage_account.github_foundations_sa.name
33+
container_access_type = var.tf_state_container_anonymous_access_level
34+
default_encryption_scope = local.default_encryption_scope
35+
encryption_scope_override_enabled = var.tf_state_container_encryption_scope_override_enabled
36+
}

0 commit comments

Comments
 (0)