> ## Documentation Index
> Fetch the complete documentation index at: https://docs.keldyn.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Microsoft Entra ID

> Connect Microsoft Entra ID with a read-only app registration so identity, MFA, access-review, and privileged-role evidence stays current automatically.

The Microsoft Entra ID integration connects your tenant to Keldyn's continuous-evidence engine. Once connected, Keldyn reads your user directory, account disable and delete events, Conditional Access MFA posture, sign-in activity, access-review results, Privileged Identity Management (PIM) activations, directory roles, group memberships, and Entitlement Management request approvals on a schedule, and turns them into live evidence for the related controls.

You connect with a **customer-owned app registration** and a client secret. There is no OAuth redirect. Keldyn only ever reads Microsoft Graph; it never writes to your tenant. For Azure subscription, network, and backup evidence, use the separate [Azure](/integrations/azure) integration.

<Note>
  Integrations and automated evidence are typically managed by workspace admins.
  See [Evidence & audits](/evidence-and-audits) for how automated evidence fits
  alongside manual evidence.
</Note>

## What it's used for

Keldyn uses the data it reads from Entra to keep identity and access-governance evidence current. Each refresh updates the evidence and freshness status shown in the integration's **Controls covered** table.

The integration contributes evidence to these ISO 27001 controls:

| Control                                         | Topic                                                           | Coverage |
| ----------------------------------------------- | --------------------------------------------------------------- | -------- |
| **A.5.16** — Identity management                | Account roster and lifecycle state                              | Full     |
| **A.8.5** — Secure authentication               | Conditional Access MFA policy plus a sign-in that satisfied MFA | Full     |
| **A.8.2** — Privileged access rights            | PIM role activations                                            | Full     |
| **A.8.18** — Use of privileged utility programs | Just-in-time privileged role activations                        | Full     |
| **A.5.18** — Access rights                      | Directory roster and disable/delete events                      | Partial  |

It also contributes evidence to these SOC 2 controls:

| Control                                | Topic                                                                                                  | Coverage |
| -------------------------------------- | ------------------------------------------------------------------------------------------------------ | -------- |
| **User listings showing unique IDs**   | Directory object ID and owner email per account                                                        | Full     |
| **Revocation of user access**          | Disable and delete audit events with actor and timestamp                                               | Full     |
| **Multi-factor authentication**        | An enabled Conditional Access policy that requires MFA **and** a successful sign-in that satisfied MFA | Full     |
| **User access reviews**                | Completed access-review decisions with reviewer, decision, and date                                    | Full     |
| **Privilege access restriction**       | PIM activations with requester, timestamp, and approver when approval is configured                    | Full     |
| **Access to critical systems**         | Entitlement Management access-package approvals                                                        | Partial  |
| **Segregation of duties**              | Directory role assignments and group memberships                                                       | Partial  |
| **Boundaries of confidential data**    | Directory roles and group rosters as supporting identity context                                       | Partial  |
| **Organization chart**                 | Manager links when the directory has them                                                              | Partial  |
| **Production environment restriction** | Directory roles and group rosters as supporting identity context                                       | Partial  |

<Info>
  **Full** coverage means the data is the artifact the control asks for.
  **Partial** coverage means the data usefully contributes but does not, on its
  own, replace everything the control requires. For example, revocation evidence
  shows who disabled or deleted an account and when — proving that happened on
  time still needs the HR leaver date. Keldyn labels partial coverage so it
  isn't mistaken for complete coverage.
</Info>

<Warning>
  Multi-factor authentication never completes on the Conditional Access policy
  alone. Keldyn also needs a stored sign-in that shows MFA was actually
  satisfied. A policy named something like “Exempt MFA” does not count unless
  its grant controls require MFA.
</Warning>

## Before you begin

<Steps>
  <Step title="Use an Entra administrator who can consent">
    You need permission to create an app registration
    (`Application Developer`, Application Administrator, or Global
    Administrator) and to **grant admin consent** for application permissions.
    Application permissions do nothing until an admin consents.
  </Step>

  <Step title="Create a dedicated, read-only app">
    Register a dedicated app (for example `KeldynEvidence`) that exists only
    for this integration. Do not reuse an app that already has write
    permissions.
  </Step>

  <Step title="Confirm the Entra licence you need">
    Directory audit logs and sign-in logs need **Entra ID P1**. Access reviews,
    PIM activations, and Entitlement Management need **Entra ID P2**. A fetch
    the licence does not cover is recorded as **Access required** so you can
    evidence that control manually. The rest of the connection keeps working.
  </Step>
</Steps>

## Set up the integration

### 1. Create the app registration

In the [Entra admin center](https://entra.microsoft.com/#view/Microsoft_AAD_RegisteredApps/ApplicationsListBlade) (or [Azure portal app registrations](https://portal.azure.com/#view/Microsoft_AAD_RegisteredApps/ApplicationsListBlade)):

1. Open **Entra ID → App registrations → New registration**.
2. Name the app something stable, such as `KeldynEvidence`.
3. Set **Supported account types** to **Accounts in this organizational directory only** (single tenant).
4. Leave **Redirect URI** empty. This is a client-credentials (service principal) connection; there is no browser sign-in.
5. Select **Register**.

From the app **Overview**, copy:

| Entra label             | Paste into Keldyn as |
| ----------------------- | -------------------- |
| Directory (tenant) ID   | **Tenant ID**        |
| Application (client) ID | **Client (App) ID**  |

Both values are GUIDs. Keldyn rejects anything that is not.

### 2. Create a client secret

On the same app, open **Certificates & secrets → Client secrets → New client secret**.

1. Give it a description such as `keldyn-evidence`.
2. Choose an expiry (12 or 24 months) and set a reminder. An expired secret surfaces as **Reauth required** on the next refresh.
3. Copy the secret **Value** immediately. You will not see it again. That is **Client Secret**.

Do not upload a certificate. Keldyn only accepts a client secret.

### 3. Grant Microsoft Graph application permissions

On the same app, open **API permissions → Add a permission → Microsoft Graph → Application permissions**. Add all of the following, then select **Grant admin consent for \[your tenant]**.

| Permission                       | What Keldyn reads with it                                 |
| -------------------------------- | --------------------------------------------------------- |
| `User.Read.All`                  | User directory, manager links, and deleted users          |
| `Group.Read.All`                 | Group memberships                                         |
| `Directory.Read.All`             | Tenant probe and directory role assignments               |
| `AuditLog.Read.All`              | Account disable/delete events and sign-in logs (needs P1) |
| `Policy.Read.All`                | Conditional Access MFA policies                           |
| `RoleManagement.Read.Directory`  | Directory roles and PIM activations (PIM needs P2)        |
| `AccessReview.Read.All`          | Access-review campaigns (needs P2)                        |
| `EntitlementManagement.Read.All` | Access-package request approvals (needs P2)               |

<Note>
  These are **application** permissions, not delegated user permissions. Keldyn
  authenticates as the app itself with client credentials and never signs in as
  a person.
</Note>

### 4. Connect in Keldyn

<Steps>
  <Step title="Open Integrations">
    In the Keldyn web app, go to **Integrations** and select **Microsoft Entra ID**.
  </Step>

  <Step title="Paste the three values">
    Enter **Tenant ID**, **Client (App) ID**, and **Client Secret**, then select
    **Connect**. Keldyn mints a short-lived Graph token and reads
    `/organization` to confirm the app can see the tenant. The secret is stored
    encrypted and is never shown again.
  </Step>

  <Step title="Run the first sync">
    Select **Sync now** to pull evidence immediately, or wait for the next
    scheduled refresh. The **Controls covered** and **Evidence sources** tables
    then show what was collected and how fresh it is.
  </Step>
</Steps>

<Tip>
  From the integration detail page, **Controls covered** shows whether Entra is
  actively feeding each control and whether the control is satisfied.
  **Evidence sources** shows each data fetch, the controls it covers, and its
  freshness.
</Tip>

Disconnecting in Keldyn does not revoke the app registration. Rotate or delete the client secret in Entra yourself.

## What data Keldyn collects and why

Keldyn requests **read-only** Graph access and never writes to your tenant. It collects only the data below, and only to build control evidence.

| Data collected                        | What it contains                                                                                          | Why Keldyn collects it                                                                    | Refresh |
| ------------------------------------- | --------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------- | ------- |
| **User directory**                    | Active and deleted accounts with unique object ID, owner email, status, and manager when present          | Evidences identity management and unique user listings                                    | Daily   |
| **Account disable and delete events** | Who disabled or deleted an account, the target, and when                                                  | Evidences revocation of user access                                                       | Daily   |
| **Conditional Access MFA policy**     | Enabled policies whose grant controls require MFA, plus registration posture when available               | Evidences that MFA is configured and enforced                                             | Daily   |
| **Sign-in activity**                  | Successful sign-ins and whether MFA was satisfied                                                         | Confirms MFA is working in practice, not just configured                                  | Daily   |
| **Access-review results**             | Completed campaign decisions with reviewer, subject, decision, and date                                   | Evidences that user access reviews actually ran                                           | Daily   |
| **PIM role activations**              | Activated privileged-role assignments with requester, timestamp, and approver when approval is configured | Evidences restricted privileged access                                                    | Hourly  |
| **Directory role assignments**        | Who holds which directory role                                                                            | Supporting evidence for segregation of duties and production-scope access                 | Daily   |
| **Group memberships**                 | Group rosters used to trace group-bound access                                                            | Supporting evidence for the same access-governance controls                               | Daily   |
| **Access-package request approvals**  | Entitlement Management requests with requester, approver, and decision                                    | Contributes to access-to-critical-systems evidence where Entitlement Management is in use | Daily   |

<Note>
  Entra retains directory audit logs and sign-in logs for about 30 days. Keldyn
  **accumulates** lifecycle, sign-in, access-review, PIM, and access-package
  evidence rather than replacing it on each refresh, so a record captured while
  it was live stays available for a longer audit period. The first sync after
  connecting shows only what Entra still holds.
</Note>

## Licences

| Evidence                                                  | Licence     | If the licence or permission is missing              |
| --------------------------------------------------------- | ----------- | ---------------------------------------------------- |
| Account disable/delete events, sign-in activity           | Entra ID P1 | **Access required** — evidence that control manually |
| Access reviews, PIM activations, access-package approvals | Entra ID P2 | **Access required** — evidence that control manually |

A blocked fetch never auto-completes its control. Directory users, Conditional Access policies, directory roles, and group memberships do not need P1/P2.

## Troubleshooting "Access required"

A control shows **Access required** when Graph denies that data source. Common causes include:

* Admin consent was not granted for the matching application permission.
* The tenant does not have Entra ID P1 (audit and sign-in logs) or P2 (access reviews, PIM, Entitlement Management).
* Access reviews, PIM, or Entitlement Management are licensed but not in use, so there is nothing to read yet.
* The app is missing `AuditLog.Read.All`, `AccessReview.Read.All`, `RoleManagement.Read.Directory`, or `EntitlementManagement.Read.All`.

Controls that do not depend on the missing permission continue to refresh. Grant the permission (and admin consent), or add the licence, then run **Sync now** again.

If the client secret is wrong, expired, or revoked, Keldyn marks the connection **Reauth required**. Create a new secret on the same app, select **Update credentials**, and delete the old secret in Entra.

## Rotate credentials

<Steps>
  <Step title="Create a new client secret">
    On the same app registration, create a new client secret and copy its value.
  </Step>

  <Step title="Update credentials in Keldyn">
    Open **Integrations → Microsoft Entra ID**, select **Update credentials**,
    and paste the existing Tenant ID, Client (App) ID, and the new secret.
  </Step>

  <Step title="Delete the old secret">
    After Keldyn shows **Connected**, delete the previous secret in Entra so it
    cannot be reused.
  </Step>
</Steps>

If a secret leaks, revoke it in Entra first. The app can only read directory data, and only while a live secret exists.

## Keeping evidence current

Keldyn refreshes Entra evidence automatically each day. PIM activations also refresh hourly. Evidence that hasn't refreshed within its expected cadence is marked **stale**, and failed pulls are marked **failed** so you can spot gaps. You can trigger an immediate refresh at any time with **Sync now**.

## Next steps

<Card title="Evidence & audits" icon="clipboard-check" href="/evidence-and-audits" arrow={true}>
  Learn how automated integration evidence works alongside manual evidence and
  audits.
</Card>
