This blog shows you how to configure OpenID Connect-based Workforce Identity Federation with Microsoft Entra ID using Terraform. This blog complements the Console and gcloud guides provided by Google Cloud.
Find the examples on GitHub
Workforce Identity Federation
Workforce Identity Federation allows users to sign in to Google Cloud using their Entra ID credential without provisioning users in Cloud Identity. The user is represented by a federated credential such as principal://iam.googleapis.com/locations/global/workforcePools/xebia/subject/f46266f9-fe00-4c0f-abd0-4be85e79bcba
.
You control the actual ID token attribute mapping. Therefore, you are free to map the
subject
attribute to provide human-readable IAM principals:../subject/laurens.knoll@xebia.com
. Take note of the security implications of using these fields.
To federate credentials the following resources are created: – Entra ID Application (Application Registration + Enterprise application) to provide ID tokens – Google Cloud Workforce Identity Pool + Provider to associate your Google Cloud Organization with your Entra ID directory – Google Cloud IAM policies to grant federated credentials permissions
Create Entra ID application to provide ID tokens
First, the Entra ID application is set up to provide ID tokens to the Google Cloud Workforce Identity Federation Pool Provider.
resource "azuread_application" "workforce_identity_federation" {
display_name = "Google Workforce Identity Federation"
..
web {
implicit_grant {
id_token_issuance_enabled = true
}
}
..
}
resource "azuread_application_redirect_uris" "workforce_identity_federation_web" {
application_id = azuread_application.workforce_identity_federation.id
type = "Web"
redirect_uris = ["https://auth.cloud.google/signin-callback/${google_iam_workforce_pool_provider.example_oidc_code.name}"]
}
Second, the application is configured to include the default scopes requested: openid
, email
and profile
.
resource "azuread_application_api_access" "workforce_identity_federation" {
application_id = azuread_application.workforce_identity_federation.id
api_client_id = data.azuread_application_published_app_ids.well_known.result["MicrosoftGraph"]
scope_ids = [
data.azuread_service_principal.msgraph.oauth2_permission_scope_ids["openid"],
data.azuread_service_principal.msgraph.oauth2_permission_scope_ids["email"],
data.azuread_service_principal.msgraph.oauth2_permission_scope_ids["profile"],
]
}
Optionally, the application is configured to include group memberships.
resource "azuread_application" "workforce_identity_federation" {
display_name = "Google Workforce Identity Federation"
..
group_membership_claims = ["SecurityGroup"]
optional_claims {
id_token {
name = "groups"
}
}
..
}
Finally, a client secret is configured to support the Authorization code flow. Note that this secret expires in 2 years by default.
resource "azuread_application_password" "workforce_identity_federation" {
application_id = azuread_application.workforce_identity_federation.id
rotate_when_changed = {
secret_version = "v1"
}
}
Associate Google Cloud with your Entra ID directory
First the Workforce Identity Federation Provider is associated with the Microsoft Entra ID application using the authorization code flow.
resource "google_iam_workforce_pool_provider" "example_oidc_code" {
workforce_pool_id = google_iam_workforce_pool.example_oidc.workforce_pool_id
location = "global"
provider_id = "code"
..
oidc {
issuer_uri = "https://login.microsoftonline.com/${var.tenant_id}/v2.0"
client_id = azuread_application.workforce_identity_federation.client_id
client_secret {
value {
plain_text = azuread_application_password.workforce_identity_federation.value
}
}
web_sso_config {
response_type = "CODE"
assertion_claims_behavior = "MERGE_USER_INFO_OVER_ID_TOKEN_CLAIMS"
}
}
..
}
Workforce Identity Federation supports both authorization code flow and implicit flow. Authorization code flow is considered most secure, because tokens are returned in a separate, secure backend transaction instead of via the browser. As a result, ID tokens exchanged via authorization code flow can be of any size whereas in implicit flow the browser URL size limits come into play. Do note that authorization code flow uses a client secret, which you’ll need to rotate regularly.
Finally, the ID token attributes are mapped to the federated Google credential using Google’s recommended mapping.
resource "google_iam_workforce_pool_provider" "example_oidc_code" {
workforce_pool_id = google_iam_workforce_pool.example_oidc.workforce_pool_id
location = "global"
provider_id = "code"
..
attribute_mapping = {
"google.subject" = "assertion.sub"
"google.display_name" = "assertion.preferred_username"
"google.groups" = "assertion.groups"
}
..
}
Unsure about the attribute values to use? Request an example token using OIDC Debugger -or similar- to explore the attributes.
Grant federated users Google Cloud permissions
Finally you grant Google Cloud permissions to your federated users using the principal://
and principalSet://
principal identifier.
# All identities in workforce identity pool can browse the organization resource hierarchy
resource "google_organization_iam_member" "organization_browser_example_oidc" {
org_id = var.organization_id
role = "roles/browser"
member = "principalSet://iam.googleapis.com/${google_iam_workforce_pool.example_oidc.name}/*"
}
# Specific user can manage buckets in project
resource "google_project_iam_member" "project_storage_admin_example_oidc_user_x" {
project = var.project_id
role = "roles/storage.admin"
member = "principal://iam.googleapis.com/${google_iam_workforce_pool.example_oidc.name}/subject/f46266f9-fe00-4c0f-abd0-4be85e79bcba"
}
Conclusion
Workforce Identity Federation is a promising service to simplify identity management. The service comes with many options that are reliably managed as code using Terraform. Use the examples to kick-start your set up and simplify identity management in your organization.