diff --git a/modules/github-azure-oidc/README.md b/modules/github-azure-oidc/README.md new file mode 100644 index 0000000..7774967 --- /dev/null +++ b/modules/github-azure-oidc/README.md @@ -0,0 +1,70 @@ +## Requirements + +| Name | Version | +|------|---------| +| [terraform](#requirement\_terraform) | >= 1.6 | +| [azurerm](#requirement\_azurerm) | >=3.0.0 | +| [google-beta](#requirement\_google-beta) | >= 3.77 | +| [random](#requirement\_random) | >= 3.6 | + +## Providers + +| Name | Version | +|------|---------| +| [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 | +|------|-------------|------|---------|:--------:| +| [drift\_detection\_branch\_name](#input\_drift\_detection\_branch\_name) | The name of the branch to use for drift detection. | `string` | n/a | yes | +| [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 | +| [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 | +| [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 | +| [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 | +| [rg\_location](#input\_rg\_location) | The location of the resource group to create the github foundation azure resources in. | `string` | n/a | yes | +| [rg\_name](#input\_rg\_name) | The name of the resource group to create the github foundation azure resources in. | `string` | n/a | yes | +| [sa\_name](#input\_sa\_name) | The name of the storage account for github foundations. | `string` | n/a | yes | +| [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 | +| [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 | +| [tf\_state\_container](#input\_tf\_state\_container) | The name of the container to store the terraform state file(s) in. | `string` | `"tfstate"` | no | +| [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 | +| [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. |
object({
name = string
source = string
key_vault_key_id = optional(string)
})
|
{
"name": "",
"source": "",
"storage_account_id": ""
}
| no | +| [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 | +|------|-------------| +| [bootstrap\_client\_id](#output\_bootstrap\_client\_id) | Bootstrap repository client id for authenticating with oidc. | +| [container\_name](#output\_container\_name) | Terraform state container name. | +| [organization\_client\_id](#output\_organization\_client\_id) | Organizations repository client id for authenticating with oidc. | +| [resource\_group](#output\_resource\_group) | Resource group name. | +| [sa\_name](#output\_sa\_name) | Terraform state container storage account name. | +| [subscription\_id](#output\_subscription\_id) | Azure subscription id for authenticating with oidc. | +| [tenant\_id](#output\_tenant\_id) | Azure tenant id for authenticating with oidc. | \ No newline at end of file diff --git a/modules/github-azure-oidc/oidc.tf b/modules/github-azure-oidc/oidc.tf new file mode 100644 index 0000000..10a1865 --- /dev/null +++ b/modules/github-azure-oidc/oidc.tf @@ -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}" +} diff --git a/modules/github-azure-oidc/outputs.tf b/modules/github-azure-oidc/outputs.tf new file mode 100644 index 0000000..d26968a --- /dev/null +++ b/modules/github-azure-oidc/outputs.tf @@ -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 +} \ No newline at end of file diff --git a/modules/github-azure-oidc/resource_group.tf b/modules/github-azure-oidc/resource_group.tf new file mode 100644 index 0000000..9632e1a --- /dev/null +++ b/modules/github-azure-oidc/resource_group.tf @@ -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 +} \ No newline at end of file diff --git a/modules/github-azure-oidc/storage.tf b/modules/github-azure-oidc/storage.tf new file mode 100644 index 0000000..ba6181f --- /dev/null +++ b/modules/github-azure-oidc/storage.tf @@ -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 +} \ No newline at end of file diff --git a/modules/github-azure-oidc/variables.tf b/modules/github-azure-oidc/variables.tf new file mode 100644 index 0000000..73434c5 --- /dev/null +++ b/modules/github-azure-oidc/variables.tf @@ -0,0 +1,94 @@ +# Resource Group Variables +variable "rg_create" { + description = "Create the resource group. When set to false it uses the `rg_name` input to reference an existing resource group. Defaults to true." + type = bool + default = true +} + +variable "rg_name" { + type = string + description = "The name of the resource group to create the github foundation azure resources in." +} + +variable "rg_location" { + type = string + description = "The location of the resource group to create the github foundation azure resources in." +} + +#Storage Variables +variable "sa_name" { + type = string + description = "The name of the storage account for github foundations." +} + +variable "sa_tier" { + type = string + description = "The tier of the storage account for github foundations. Valid options are Standard and Premium. Defaults to Standard." + default = "Standard" +} + +variable "sa_replication_type" { + type = string + description = "The replication type of the storage account for github foundations. Valid options are LRS, GRS, RAGRS, ZRS, GZRS, and RA_GZRS. Defaults to GRS." + default = "GRS" +} + +variable "tf_state_container" { + type = string + description = "The name of the container to store the terraform state file(s) in." + default = "tfstate" +} + +variable "tf_state_container_anonymous_access_level" { + type = string + description = "The anonymous access level of the container to store the terraform state file(s) in." + default = "private" +} + +variable "tf_state_container_encryption_scope_override_enabled" { + type = bool + description = "Whether or not the encryption scope override is enabled for the container to store the terraform state file(s) in. Defaults to false" + default = false +} + +variable "tf_state_container_default_encryption_scope" { + type = object({ + name = string + source = string + key_vault_key_id = optional(string) + }) + description = "The default encryption scope of the container to store the terraform state file(s) in." + default = { + name = "" + source = "" + storage_account_id = "" + } + validation { + condition = var.tf_state_container_default_encryption_scope.name == "" || var.tf_state_container_default_encryption_scope.source != "Microsoft.KeyVault" || (var.tf_state_container_default_encryption_scope.source == "Microsoft.KeyVault" && var.tf_state_container_default_encryption_scope.key_vault_key_id == null) + error_message = "Key vault key id must be set when source is \"Microsoft.KeyVault\"." + } +} + +#Key Vault Variables +variable "kv_name" { + type = string + description = "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)" + default = "" +} + +variable "kv_resource_group" { + type = string + description = "The name of the resource group that the key vault is in. If empty it will default to the github foundations resource group." +} + +#Federated Identity Credentials Varialbes + +variable "github_foundations_organization_name" { + type = string + description = "The name of the organization that the github foundation repos will be under." +} + +variable "drift_detection_branch_name" { + type = string + description = "The name of the branch to use for drift detection." +} diff --git a/modules/github-azure-oidc/versions.tf b/modules/github-azure-oidc/versions.tf new file mode 100644 index 0000000..d34e8d7 --- /dev/null +++ b/modules/github-azure-oidc/versions.tf @@ -0,0 +1,17 @@ +terraform { + required_version = ">= 1.6" + required_providers { + azurerm = { + source = "hashicorp/azurerm" + version = ">=3.0.0" #tftest + } + google-beta = { + source = "hashicorp/google-beta" + version = ">= 3.77" # tftest + } + random = { + source = "hashicorp/random" + version = ">= 3.6" # tftest + } + } +} diff --git a/modules/github-foundations/README.md b/modules/github-foundations/README.md index c5c70c7..b96a1b6 100644 --- a/modules/github-foundations/README.md +++ b/modules/github-foundations/README.md @@ -24,11 +24,18 @@ | Name | Type | |------|------| | [github_actions_organization_secret.custom_oidc_organization_secret](https://registry.terraform.io/providers/integrations/github/latest/docs/resources/actions_organization_secret) | resource | +| [github_actions_organization_secret.tenant_id](https://registry.terraform.io/providers/integrations/github/latest/docs/resources/actions_organization_secret) | resource | | [github_actions_organization_secret.workload_identity_provider](https://registry.terraform.io/providers/integrations/github/latest/docs/resources/actions_organization_secret) | resource | +| [github_actions_organization_variable.container_name](https://registry.terraform.io/providers/integrations/github/latest/docs/resources/actions_organization_variable) | resource | | [github_actions_organization_variable.custom_oidc_organization_variable](https://registry.terraform.io/providers/integrations/github/latest/docs/resources/actions_organization_variable) | resource | +| [github_actions_organization_variable.resource_group_name](https://registry.terraform.io/providers/integrations/github/latest/docs/resources/actions_organization_variable) | resource | +| [github_actions_organization_variable.storage_account_name](https://registry.terraform.io/providers/integrations/github/latest/docs/resources/actions_organization_variable) | resource | +| [github_actions_organization_variable.subscription_id](https://registry.terraform.io/providers/integrations/github/latest/docs/resources/actions_organization_variable) | resource | | [github_actions_organization_variable.tf_state_bucket_location](https://registry.terraform.io/providers/integrations/github/latest/docs/resources/actions_organization_variable) | resource | | [github_actions_organization_variable.tf_state_bucket_name](https://registry.terraform.io/providers/integrations/github/latest/docs/resources/actions_organization_variable) | resource | | [github_actions_organization_variable.tf_state_bucket_project_id](https://registry.terraform.io/providers/integrations/github/latest/docs/resources/actions_organization_variable) | resource | +| [github_actions_secret.bootstrap_managed_identity_client_id](https://registry.terraform.io/providers/integrations/github/latest/docs/resources/actions_secret) | resource | +| [github_actions_secret.organization_managed_identity_client_id](https://registry.terraform.io/providers/integrations/github/latest/docs/resources/actions_secret) | resource | | [github_actions_secret.organization_workload_identity_sa](https://registry.terraform.io/providers/integrations/github/latest/docs/resources/actions_secret) | resource | | [github_actions_secret.repository_secret](https://registry.terraform.io/providers/integrations/github/latest/docs/resources/actions_secret) | resource | | [github_actions_variable.gcp_secret_manager_project_id](https://registry.terraform.io/providers/integrations/github/latest/docs/resources/actions_variable) | resource | @@ -49,7 +56,7 @@ | [account\_type](#input\_account\_type) | The type of GitHub account being used. Should be one of either `Personal`, `Organization`, or `Enterprise`. | `string` | n/a | yes | | [bootstrap\_repository\_name](#input\_bootstrap\_repository\_name) | The name of the bootstrap repository. | `string` | `"bootstrap"` | no | | [foundation\_devs\_team\_name](#input\_foundation\_devs\_team\_name) | The name of the foundation developers team. | `string` | `"foundation-devs"` | no | -| [oidc\_configuration](#input\_oidc\_configuration) | n/a |
object({
gcp = optional(object({
workload_identity_provider_name_secret_name = optional(string)
workload_identity_provider_name = string

organization_workload_identity_sa_secret_name = optional(string)
organization_workload_identity_sa = string

gcp_secret_manager_project_id_variable_name = optional(string)
gcp_secret_manager_project_id = string

gcp_tf_state_bucket_project_id_variable_name = optional(string)
gcp_tf_state_bucket_project_id = string

bucket_name_variable_name = optional(string)
bucket_name = string

bucket_location_variable_name = optional(string)
bucket_location = string
}))
custom = optional(object({
organization_secrets = map(string)
organization_variables = map(string)
repository_secrets = map(map(string))
repository_variables = map(map(string))
}))
})
| n/a | yes | +| [oidc\_configuration](#input\_oidc\_configuration) | n/a |
object({
gcp = optional(object({
workload_identity_provider_name_secret_name = optional(string)
workload_identity_provider_name = string

organization_workload_identity_sa_secret_name = optional(string)
organization_workload_identity_sa = string

gcp_secret_manager_project_id_variable_name = optional(string)
gcp_secret_manager_project_id = string

gcp_tf_state_bucket_project_id_variable_name = optional(string)
gcp_tf_state_bucket_project_id = string

bucket_name_variable_name = optional(string)
bucket_name = string

bucket_location_variable_name = optional(string)
bucket_location = string
}))
azure = optional(object({
bootstrap_client_id_variable_name = optional(string)
bootstrap_client_id = string

organization_client_id_variable_name = optional(string)
organization_client_id = string

tenant_id_variable_name = optional(string)
tenant_id = string

subscription_id_variable_name = optional(string)
subscription_id = string

resource_group_name_variable_name = optional(string)
resource_group_name = string

storage_account_name_variable_name = optional(string)
storage_account_name = string

container_name_variable_name = optional(string)
container_name = string
}))
custom = optional(object({
organization_secrets = map(string)
organization_variables = map(string)
repository_secrets = map(map(string))
repository_variables = map(map(string))
}))
})
| n/a | yes | | [organizations\_repository\_name](#input\_organizations\_repository\_name) | The name of the organizations repository. | `string` | `"organizations"` | no | | [readme\_path](#input\_readme\_path) | Local Path to the README file in your current codebase. Pushed to the github foundation repository. | `string` | `""` | no | diff --git a/modules/github-foundations/azure-oidc-variables.tf b/modules/github-foundations/azure-oidc-variables.tf new file mode 100644 index 0000000..7592b3a --- /dev/null +++ b/modules/github-foundations/azure-oidc-variables.tf @@ -0,0 +1,75 @@ +resource "github_actions_secret" "organization_managed_identity_client_id" { + count = var.oidc_configuration.azure != null ? 1 : 0 + + repository = github_repository.organizations_repo.name + secret_name = coalesce(var.oidc_configuration.azure.organization_client_id_variable_name, "AZURE_CLIENT_ID") + plaintext_value = var.oidc_configuration.azure.organization_client_id +} + +resource "github_actions_secret" "bootstrap_managed_identity_client_id" { + count = var.oidc_configuration.azure != null ? 1 : 0 + + repository = github_repository.bootstrap_repo.name + secret_name = coalesce(var.oidc_configuration.azure.bootstrap_client_id_variable_name, "AZURE_CLIENT_ID") + plaintext_value = var.oidc_configuration.azure.bootstrap_client_id +} + +resource "github_actions_organization_secret" "tenant_id" { + count = var.oidc_configuration.azure != null ? 1 : 0 + + secret_name = coalesce(var.oidc_configuration.azure.tenant_id_variable_name, "AZURE_TENANT_ID") + plaintext_value = var.oidc_configuration.azure.tenant_id + visibility = "selected" + selected_repository_ids = [ + github_repository.bootstrap_repo.repo_id, + github_repository.organizations_repo.repo_id + ] +} + +resource "github_actions_organization_variable" "subscription_id" { + count = var.oidc_configuration.azure != null ? 1 : 0 + + variable_name = coalesce(var.oidc_configuration.azure.subscription_id_variable_name, "AZURE_SUBSCRIPTION_ID") + value = var.oidc_configuration.azure.subscription_id + visibility = "selected" + selected_repository_ids = [ + github_repository.bootstrap_repo.repo_id, + github_repository.organizations_repo.repo_id + ] +} + +resource "github_actions_organization_variable" "resource_group_name" { + count = var.oidc_configuration.azure != null ? 1 : 0 + + variable_name = coalesce(var.oidc_configuration.azure.resource_group_name_variable_name, "AZURE_RESOURCE_GROUP_NAME") + value = var.oidc_configuration.azure.resource_group_name + visibility = "selected" + selected_repository_ids = [ + github_repository.bootstrap_repo.repo_id, + github_repository.organizations_repo.repo_id + ] +} + +resource "github_actions_organization_variable" "storage_account_name" { + count = var.oidc_configuration.azure != null ? 1 : 0 + + variable_name = coalesce(var.oidc_configuration.azure.storage_account_name_variable_name, "AZURE_STORAGE_ACCOUNT_NAME") + value = var.oidc_configuration.azure.storage_account_name + visibility = "selected" + selected_repository_ids = [ + github_repository.bootstrap_repo.repo_id, + github_repository.organizations_repo.repo_id + ] +} + +resource "github_actions_organization_variable" "container_name" { + count = var.oidc_configuration.azure != null ? 1 : 0 + + variable_name = coalesce(var.oidc_configuration.azure.container_name_variable_name, "AZURE_CONTAINER_NAME") + value = var.oidc_configuration.azure.container_name + visibility = "selected" + selected_repository_ids = [ + github_repository.bootstrap_repo.repo_id, + github_repository.organizations_repo.repo_id + ] +} diff --git a/modules/github-foundations/variables.tf b/modules/github-foundations/variables.tf index fe9583e..bffd7f8 100644 --- a/modules/github-foundations/variables.tf +++ b/modules/github-foundations/variables.tf @@ -43,6 +43,28 @@ variable "oidc_configuration" { bucket_location_variable_name = optional(string) bucket_location = string })) + azure = optional(object({ + bootstrap_client_id_variable_name = optional(string) + bootstrap_client_id = string + + organization_client_id_variable_name = optional(string) + organization_client_id = string + + tenant_id_variable_name = optional(string) + tenant_id = string + + subscription_id_variable_name = optional(string) + subscription_id = string + + resource_group_name_variable_name = optional(string) + resource_group_name = string + + storage_account_name_variable_name = optional(string) + storage_account_name = string + + container_name_variable_name = optional(string) + container_name = string + })) custom = optional(object({ organization_secrets = map(string) organization_variables = map(string) @@ -51,7 +73,7 @@ variable "oidc_configuration" { })) }) validation { - condition = var.oidc_configuration.gcp != null || var.oidc_configuration.custom != null + condition = var.oidc_configuration.gcp != null || var.oidc_configuration.custom != null || var.oidc_configuration.azure != null error_message = "At least one oidc_configuration must be set." } }