This guide will walk you through integrating Common Fate with Entra (Formerly Azure AD). By the end of this guide, you’ll have a functioning integration with Common Fate, allowing it to provision access to Entra Groups.

Entra Setup

To configure the Microsoft Entra integration, follow these steps to create an App Registration in your Azure console.

To add an app registration to your tenant:

  1. Sign in to the Microsoft Entra admin center as at least a Cloud Application Administrator.
  2. Browse to Identity > Applications > App Registrations.
  3. Select New registration.
  4. Enter a name e.g ‘Common Fate’
  5. For Supported account types, select Accounts in this organizational directory only (should be selected by default).
  6. Click Register

You will now be on the app registration overview page.

  1. Browse to API permissions
  2. Under Configured permissions, select Microsoft Graph
  3. Select the following permissions Group.Read.All, User.Read.All, GroupMember.ReadWrite.All
  4. Remove the permission User.Read
  5. Click Update permissions

You will now create a client secret.

  1. Browse to Certificates & secrets > Client secrets
  2. Click New client secret
  3. Give it an optional description and configure the expiry as required. Be sure to set a reminder to renew the secret before it expires.
  4. Click Add

You will need to create a new SecretString in SSM Parameter Store and then use the path when configuring your deployment in Terraform.

You can use the AWS CLI to create a secret in the region you are deploying to. We recommend naming these "/<namespace>/<stage>/<secret name>".

aws ssm put-parameter \
    --name "/common-fate/prod/entra-client-secret" \
    --value "mySecretValue" \
    --type "SecureString"

Configuring Common Fate

In this section, you will register the Entra integration with your Common Fate deployment. At the end of this section you should have Common Fate ready to provision access. You’ll need to have set up the Common Fate Application Configuration repository using our Terraform provider.

Navigate to the overview page of your app registration, find the client id (Application (client) ID) and the tenant id (Directory (tenant) ID)

Inside your Application Configuration repository, add the following module:

resource "commonfate_entra_integration" "entra" {
  name                      = "Entra"
  tenant_id                 = "<Your Entra tenant id>"
  client_id                 = "<Your Entra client id>"
  client_secret_secret_path = "/common-fate/prod/entra-client-secret"
}

Apply the changes. If the apply succeeds, you should see the integration appear on the settings page in the web dashboard.

Provisioning access to Entra Groups

To grant and revoke access to Entra Groups, Common Fate uses a service called the Provisioner. The Provisioner is an internal service and is not user-facing. In default deployments, there is a provisioner builtin to the main stack which can be configured using blocks.

To configure the builtin Provisioner for Entra Groups, add the provisioner_entra_config config block as per the example below:

module "common-fate-deployment" {
  source = "common-fate/common-fate-deployment/aws"
  version = "1.22.0"

  provisioner_entra_config = {
    tenant_id                 = "<Your Entra tenant id>"
    client_id                 = "<Your Entra client id>"
    client_secret_secret_path = "/common-fate/prod/entra-client-secret"
  }
}

You’ll additionally need to add the following Provisioner registration inside your Application Configuration repository:

resource "commonfate_webhook_provisioner" "prod" {
 url = "http://common-fate-prod-builtin-provisioner.common-fate-prod-builtin.internal:9999"
  capabilities = [
    {
      target_type = "Entra::Group"
      role_type   = "Entra::GroupRole"
      belonging_to = {
        type = "Entra::Tenant"
        id   = "<Your Entra tenant id>"
      }
    },
  ]
}

You can now create an access workflow and availabilities:

resource "commonfate_access_workflow" "entra" {
  name                     = "entra"
  access_duration_seconds  = 60 * 60 * 2
  try_extend_after_seconds = 60 * 60
  priority                 = 1
}

resource "commonfate_entra_group_selector" "select_all" {
  id        = "example"
  name      = "Example"
  tenant_id = "abcd-1234-abcd-1234"
  when      = "true"
}


resource "commonfate_entra_group_availabilities" "demo" {
  workflow_id             = commonfate_access_workflow.entra.id
  entra_group_selector_id = commonfate_entra_group_selector.select_all.id
  tenant_id               = "<Your Entra tenant id>"
}

Entra group selectors

To make Entra groups available for Just-In-Time (JIT) access you can add a commonfate_entra_group_selector Selector resource to your Common Fate application Terraform code. As shown below, the when clause in the resource is a Cedar expression. You can use any Cedar operator in the when clause, such as && and || to combine conditions.

You’ll need to use the commonfate_entra_group_selector in conjunction with a commonfate_entra_group_availabilities and commonfate_access_workflow resources, as shown above.

We’ve included some examples below.

Select a group by ID

resource "commonfate_entra_group_selector" "example" {
  id        = "example"
  name      = "Example"
  tenant_id = "abcd-1234-abcd-1234"
  when                = <<EOT
  resource == Entra::Group::"abcd-1234-abcd-1234"
  EOT
}

Select multiple groups by ID

resource "commonfate_entra_group_selector" "example" {
  id        = "example"
  name      = "Example"
  tenant_id = "abcd-1234-abcd-1234"
  when                = <<EOT
  resource == Entra::Group::"abcd-1234-abcd-1234" || resource == Entra::Group::"efgh-5678-efgh-5678"
  EOT
}

Select a group based on a naming pattern

Select groups with a name ending in -prod:

resource "commonfate_entra_group_selector" "example" {
  id        = "example"
  name      = "Example"
  tenant_id = "abcd-1234-abcd-1234"
  when                = <<EOT
  resource.name like "*-prod"
  EOT
}

Select groups with a name beginning with Develop:

resource "commonfate_entra_group_selector" "example" {
  id        = "example"
  name      = "Example"
  tenant_id = "abcd-1234-abcd-1234"
  when                = <<EOT
  resource.name like "Develop*"
  EOT
}