Skip to content

Latest commit

 

History

History
276 lines (228 loc) · 12.2 KB

README.md

File metadata and controls

276 lines (228 loc) · 12.2 KB

terraform-azuread-github-oidc

Semantic Release

Terraform module to setup GitHub OIDC in Microsoft Azure, creating an Azure AD application, service principal, and federated identities.

Module Usage

# This Terraform code creates a GitHub OIDC application in Azure AD and sets up federated credentials for a GitHub repository.
# The code creates an Azure AD application with API access permissions, assigns subscription roles to the service principal, and creates federated credentials for specified branches, tags, and environments.
# The code also creates GitHub secrets and environment secrets for the federated credentials, and sets up Dependabot secrets for the Azure AD application.
# The variables for the code include the Azure AD application name, API access permissions, subscription roles, GitHub repository owner and name, branches, tags, environments, and pull request settings.
# The code uses the GitHub OIDC module to create the Azure AD application and federated credentials.

# Define variables for the code
variable "azure_application_name" {
  description = "Name of the Azure AD application"
  type        = string
  default     = "github-oidc-test"
}

variable "azure_application_api_access" {
  description = "List of API access permissions for the Azure AD application"
  type = list(object({
    api_name          = string
    role_permissions  = list(string)
    scope_permissions = list(string)
  }))
  default = [{
    api_name          = "MicrosoftGraph"
    role_permissions  = ["Chat.Create", "Chat.Read.All", "Chat.ReadBasic.All"]
    scope_permissions = ["Chat.Create", "Chat.Read"]
  }]
}

variable "azure_service_principal_subscription_roles" {
  description = "List of subscription roles to assign to the service principal"
  type        = set(string)
  default     = ["Contributor"] # allow access to the subscription and the subscriptions RBAC
}

variable "github_repository_owner" {
  description = "Owner of the GitHub repository"
  type        = string
  default     = "infinite-automations"
}

variable "github_repository_name" {
  description = "Name of the GitHub repository"
  type        = string
  default     = "terraform-azuread-github-oidc"
}

variable "github_repository_branches" {
  description = "List of branches to create federated credentials for"
  type        = set(string)
  default     = ["main"]
}

variable "github_repository_tags" {
  description = "List of tags to create federated credentials for"
  type        = set(string)
  default     = ["1.0.0", "1.1.0"]
}

variable "github_repository_environments" {
  description = "List of environments to create federated credentials for"
  type        = set(string)
  default     = ["test", "prod"]
}

variable "github_repository_pull_request" {
  description = "Create federated credentials for pull requests"
  type        = bool
  default     = true
}

variable "github_token" {
  description = "GitHub token for writing the secret"
  type        = string
  sensitive   = true
  default     = null
}

# Define locals for the code
locals {

  set_secrets = nonsensitive(var.github_token == null)
  secret_envs = local.set_secrets ? [] : toset(var.github_repository_environments)
}

# Use the GitHub OIDC module to create the Azure AD application and federated credentials
module "github-oidc" {
  source = "../.."

  azure_application_name                     = var.azure_application_name
  azure_application_api_access               = var.azure_application_api_access
  azure_service_principal_subscription_roles = var.azure_service_principal_subscription_roles
  github_repository_owner                    = var.github_repository_owner
  github_repository_name                     = var.github_repository_name
  github_repository_branches                 = var.github_repository_branches
  github_repository_tags                     = var.github_repository_tags
  github_repository_environments             = var.github_repository_environments
  github_repository_pull_request             = var.github_repository_pull_request
}

# Create GitHub secrets for the federated credentials
resource "github_actions_secret" "tenant-id" {
  count           = local.set_secrets ? 0 : 1
  repository      = var.github_repository_name
  secret_name     = "ARM_TENANT_ID"
  plaintext_value = module.github-oidc.tenant_id
}

resource "github_actions_secret" "subscription-id" {
  count           = local.set_secrets ? 0 : 1
  repository      = var.github_repository_name
  secret_name     = "ARM_SUBSCRIPTION_ID"
  plaintext_value = module.github-oidc.subscription_id
}

resource "github_actions_secret" "client-id" {
  count           = local.set_secrets ? 0 : 1
  repository      = var.github_repository_name
  secret_name     = "ARM_CLIENT_ID"
  plaintext_value = module.github-oidc.client_id
}

# Create GitHub environment secrets for the federated credentials
resource "github_actions_environment_secret" "tenant-id" {
  for_each        = local.secret_envs
  repository      = var.github_repository_name
  environment     = each.key
  secret_name     = "ARM_TENANT_ID"
  plaintext_value = module.github-oidc.tenant_id
}

resource "github_actions_environment_secret" "subscription-id" {
  for_each        = local.secret_envs
  repository      = var.github_repository_name
  environment     = each.key
  secret_name     = "ARM_SUBSCRIPTION_ID"
  plaintext_value = module.github-oidc.subscription_id
}

resource "github_actions_environment_secret" "client-id" {
  for_each        = local.secret_envs
  repository      = var.github_repository_name
  environment     = each.key
  secret_name     = "ARM_CLIENT_ID"
  plaintext_value = module.github-oidc.client_id
}

# Set up Dependabot secrets for the Azure AD application
resource "github_dependabot_secret" "tenant-id" {
  count           = local.set_secrets ? 0 : 1
  repository      = var.github_repository_name
  secret_name     = "ARM_TENANT_ID"
  plaintext_value = module.github-oidc.tenant_id
}
resource "github_dependabot_secret" "subscription-id" {
  count           = local.set_secrets ? 0 : 1
  repository      = var.github_repository_name
  secret_name     = "ARM_SUBSCRIPTION_ID"
  plaintext_value = module.github-oidc.subscription_id
}

resource "github_dependabot_secret" "client-id" {
  count           = local.set_secrets ? 0 : 1
  repository      = var.github_repository_name
  secret_name     = "ARM_CLIENT_ID"
  plaintext_value = module.github-oidc.client_id
}

For a detailed documentation see the full example

Github Workflow Example

name: Deploy using OIDC

# choose any triggers
on:
  push:
    branches: ["main"]
  pull_request:
    branches: ["main"]

# permissions required
# oidc requires to cretate id-tokens
permissions:
  contents: read
  id-token: write

# environment variables to set
# can also be set on job level
env:
  ARM_USE_OIDC: true
  ARM_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
  ARM_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
  ARM_SUBSCRIPTION_ID: ${{ secrets.AZURE_SUBSCRIPTION_ID }}

# sample
jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Deploy
        uses: "infinite-automations/terraform-all-in-one@v1"

Requirements

Name Version
terraform ~>1.0
azuread >=2.45.0
azurerm >=3.78.0

Providers

Name Version
azuread >=2.45.0
azurerm >=3.78.0

Resources

Name Type
azuread_application.this resource
azuread_application_api_access.this resource
azuread_application_federated_identity_credential.branch resource
azuread_application_federated_identity_credential.environment resource
azuread_application_federated_identity_credential.pull-request resource
azuread_application_federated_identity_credential.tag resource
azuread_service_principal.this resource
azurerm_role_assignment.this resource

Inputs

Name Description Type Default Required
azure_application_name Name of the Azure AD application string n/a yes
github_repository_name Name of the GitHub repository string n/a yes
github_repository_owner Owner of the GitHub repository string n/a yes
azure_application_api_access List of API access permissions for the Azure AD application
list(object({
api_name = string
role_permissions = list(string)
scope_permissions = list(string)
}))
[] no
azure_owner_object_id Azure AD application owner object ID string null no
azure_service_principal_subscription_roles Set of subscription roles to assign to the service principal set(string) [] no
azure_subscription_id Azure subscription ID string null no
github_repository_branches List of branches to create federated credentials for set(string) [] no
github_repository_environments List of environments to create federated credentials for set(string) [] no
github_repository_pull_request Create federated credentials for pull requests bool false no
github_repository_tags List of tags to create federated credentials for set(string) [] no

Outputs

Name Description
azuread_application AzureAD application created
azuread_application_owner AzureAD application owner
azuread_service_principal AzureAD principal created
client_id AzureAD client ID
subscription_id Azure subscription ID
tenant_id Azure tenant ID

Changelog

See the Changelog file for details