# saif-resources / identity

Creates the standard Forge identity pair for services: a User-Assigned Managed Identity (UAMI) for platform concerns and an Entra ID App Registration for runtime concerns.

## Usage

```hcl
module "identity" {
  source  = "app.terraform.io/SAIFCorp/resources/saif//modules/identity"
  version = "~> 1.0.0"

  providers = {
    azurerm               = azurerm
    azurerm.shared-services = azurerm.shared-services
    azuread               = azuread
  }

  context = module.environment.context
  name    = var.project_id

  # For services needing AI Hub + AI Search access
  ai_hub_roles = true

  # For services calling Document Intelligence prebuilt models on the AI Hub
  document_intelligence_roles = true

  # For Teams bots needing admin-consented Graph scopes
  grant_admin_consent = true
  api_permissions = [
    { api_name = "Microsoft Graph", permission_name = "User.Read", type = "Scope" }
  ]
}
```

## Outputs

| Name       | Description                                                 |
| ---------- | ----------------------------------------------------------- |
| `identity` | Structured object with UAMI and App Registration references |

### Identity Object Shape

```
identity.uami_id / identity.uami_client_id / identity.uami_principal_id
identity.app_client_id / identity.app_object_id
identity.sp_principal_id / identity.sp_object_id
identity.client_secret_kv_ref   — @Microsoft.KeyVault() reference string
identity.client_secret_kv_uri   — versionless secret URI
```

## Required Providers

- `azurerm` (>= 4.0, < 5.0) — with `azurerm.shared-services` alias
- `azuread` (>= 3.0, < 4.0)

<!-- BEGIN_TF_DOCS -->
## Providers

| Name | Version |
|------|---------|
| <a name="provider_azurerm"></a> [azurerm](#provider\_azurerm) | >= 4.0, < 5.0 |
| <a name="provider_azurerm.shared-services"></a> [azurerm.shared-services](#provider\_azurerm.shared-services) | >= 4.0, < 5.0 |

## Inputs

| Name | Description | Type | Default | Required |
|------|-------------|------|---------|:--------:|
| <a name="input_ai_hub_roles"></a> [ai\_hub\_roles](#input\_ai\_hub\_roles) | Whether to grant AI Hub and AI Search roles to the service principal | `bool` | `false` | no |
| <a name="input_api_permissions"></a> [api\_permissions](#input\_api\_permissions) | API permissions to request on the app registration | <pre>list(object({<br/>    api_name        = string<br/>    permission_name = string<br/>    type            = string<br/>  }))</pre> | `[]` | no |
| <a name="input_context"></a> [context](#input\_context) | Platform context from the environment module | `any` | n/a | yes |
| <a name="input_create_client_secret"></a> [create\_client\_secret](#input\_create\_client\_secret) | Whether to create a client secret for the app registration | `bool` | `true` | no |
| <a name="input_document_intelligence_roles"></a> [document\_intelligence\_roles](#input\_document\_intelligence\_roles) | Whether to grant Document Intelligence data-plane access on the AI Hub to the service principal | `bool` | `false` | no |
| <a name="input_enable_agents_sdk"></a> [enable\_agents\_sdk](#input\_enable\_agents\_sdk) | Whether to emit Connections\_\_ServiceConnection\_\_* app settings for the M365 Agents SDK | `bool` | `false` | no |
| <a name="input_enable_oidc"></a> [enable\_oidc](#input\_enable\_oidc) | Whether to emit OpenIdConnectClientId\_{tenant} / OpenIdConnectClientSecret\_{tenant} app settings | `bool` | `false` | no |
| <a name="input_grant_admin_consent"></a> [grant\_admin\_consent](#input\_grant\_admin\_consent) | Whether to grant admin consent for API permissions | `bool` | `false` | no |
| <a name="input_microsoft_app_type"></a> [microsoft\_app\_type](#input\_microsoft\_app\_type) | Bot Framework app type — set to emit MicrosoftApp* app settings. Values: SingleTenant, MultiTenant. | `string` | `null` | no |
| <a name="input_name"></a> [name](#input\_name) | Application name used for identity resources (e.g. project\_id) | `string` | n/a | yes |
| <a name="input_owners"></a> [owners](#input\_owners) | Map of Entra ID object IDs to set as application owners. Keyed by a stable name. Defaults to the current caller. | `map(string)` | `{}` | no |
| <a name="input_redirect_uris"></a> [redirect\_uris](#input\_redirect\_uris) | Redirect URIs for the app registration (e.g. OAuth2 callback URLs) | `list(string)` | `[]` | no |
| <a name="input_resource_group_location"></a> [resource\_group\_location](#input\_resource\_group\_location) | The Azure region for identity resources | `string` | n/a | yes |
| <a name="input_resource_group_name"></a> [resource\_group\_name](#input\_resource\_group\_name) | The resource group for identity resources (UAMI) | `string` | n/a | yes |
| <a name="input_visible_to_users"></a> [visible\_to\_users](#input\_visible\_to\_users) | Whether the enterprise application appears on users' My Apps page. Controls feature\_tags.hide on the service principal. Defaults to hidden, which is correct for APIs, bots, and background consumers; set true only for apps users sign in to directly. | `bool` | `false` | no |
| <a name="input_web_logout_url"></a> [web\_logout\_url](#input\_web\_logout\_url) | Post-logout redirect URL for the app registration | `string` | `null` | no |

## Outputs

| Name | Description |
|------|-------------|
| <a name="output_app_settings"></a> [app\_settings](#output\_app\_settings) | Map of credential-related app settings, controlled by flag variables. Merge into webapp app\_settings. |
| <a name="output_client_secret_value"></a> [client\_secret\_value](#output\_client\_secret\_value) | The app registration client secret value. Sensitive — use only where the actual value is required (e.g. Bot OAuth connections). Prefer identity.client\_secret\_kv\_ref for app settings. |
| <a name="output_identity"></a> [identity](#output\_identity) | Identity bundle — UAMI + App Registration references (no sensitive values) |

## Resources


- resource.azurerm_key_vault_secret.client_secret (/terraform-docs/modules/identity/main.tf#41)
- resource.azurerm_role_assignment.acr_pull (/terraform-docs/modules/identity/main.tf#66)
- resource.azurerm_role_assignment.app_configuration_reader (/terraform-docs/modules/identity/main.tf#76)
- resource.azurerm_role_assignment.client_secret_reader (/terraform-docs/modules/identity/main.tf#50)
- resource.azurerm_role_assignment.cognitive_services_openai_user (/terraform-docs/modules/identity/main.tf#128)
- resource.azurerm_role_assignment.cognitive_services_user (/terraform-docs/modules/identity/main.tf#152)
- resource.azurerm_role_assignment.otel_header_np_sp (/terraform-docs/modules/identity/main.tf#109)
- resource.azurerm_role_assignment.otel_header_np_uami (/terraform-docs/modules/identity/main.tf#93)
- resource.azurerm_role_assignment.otel_header_prod_sp (/terraform-docs/modules/identity/main.tf#117)
- resource.azurerm_role_assignment.otel_header_prod_uami (/terraform-docs/modules/identity/main.tf#101)
- resource.azurerm_role_assignment.search_index_data_reader (/terraform-docs/modules/identity/main.tf#136)
- resource.azurerm_role_assignment.search_service_contributor (/terraform-docs/modules/identity/main.tf#144)
- resource.azurerm_user_assigned_identity.main (/terraform-docs/modules/identity/main.tf#14)    
<!-- END_TF_DOCS -->

---

[View source on GitHub](https://github.com/saif-corp/forge/blob/main/src/terraform/saif-resources/modules/identity/README.md)
