# Access reviews and audit evidence

Turn a periodic approval list into an effective access review. Track indirect permissions, business rationale, applied outcomes and time-bound exceptions.

Original AI-assisted SecNet educational content. Fictional local examples; not a standards provider publication, endorsement or compliance evidence. Page exercises do not create account progress.

Sources checked: 2026-10-21

## Define scope rather than just exporting a list

A Harbor auditor exports an application user list. It may show direct assignments while omitting groups, guests, service identities or temporary privilege. State the review period, source, data date and exclusions. Reviewers need enough context to assess business need; manager and resource-owner roles can differ. Product review types and licensing vary, so this lesson assumes no feature is available in every tenant. The export is a scoped starting record, not comprehensive access evidence. Match the review question to the permissions the source can actually describe.

## Explain approval decisions

Recent sign-in or active-user status alone is not a business need. Explain decisions through task, data sensitivity, owner and duration. A reviewer approving their own access still raises independence questions. Harbor distinguishes retain, remove, request evidence and time-bound exception outcomes. Define nonresponse handling beforehand; automatic removal is not a universal default without considering effects. The exercise grants or removes no real account or employment access. A rationale should let another authorized reviewer understand why that particular permission remains necessary.

## Apply decisions and verify outcomes

A remove decision leaves risk unchanged if never applied. Even an applied result may leave access through nested groups or local application accounts. Record execution ownership, time, failures and authorized re-access testing. Harbor’s local desk illustrates an indirect group grant but does not validate any product’s applied outcomes. Decision completion and effective permission change are separate evidence items. That distinction allows an audit to demonstrate a control outcome rather than merely an approval percentage, while keeping unresolved access paths visible for follow-up.

## Retention, exceptions and triggers

Audit evidence records source revision, reviewer role/person, rationale and outcome without secrets or unnecessary personal data. Retention follows authorized organizational policy; this package sets no universal period. Role moves, contract endings or high-risk changes may trigger review alongside periodic cycles. Exceptions need an explicit risk owner, scope, compensation and expiry. Repeated unjustified extensions should not replace normal access governance. Complete the review with outstanding work, owners and a validation plan rather than treating unanswered or unapplied decisions as successfully closed.

## Working sequence

1. Define scope and source date.
2. Separate direct and indirect grants.
3. Record independent decisions and business rationale.
4. Compare applied outcomes with remaining paths.
5. Complete exceptions and the follow-up review plan.

## 1. The spreadsheet arrived

An export establishes neither indirect access nor complete scope. Collecting approvals without ownership, period and group/application boundaries produces weak evidence.

This code is a local policy model; it does not replace actual authentication, token validation or live permission tests.

### Weak implementation
```js
s => s.listExported === true
```

### Corrected implementation
```js
s => s.listExported === true &&
  s.indirectAccessIncluded === true &&
  s.ownerAssigned === true &&
  s.periodDefined === true
```

### Synthetic input and actual model output
```json
{
  "before": [
    {
      "name": "documented-case",
      "input": {
        "listExported": true,
        "indirectAccessIncluded": true,
        "ownerAssigned": true,
        "periodDefined": true
      },
      "expected": true,
      "observed": true,
      "matched": true
    },
    {
      "name": "missing-indirectAccessIncluded",
      "input": {
        "listExported": true,
        "indirectAccessIncluded": false,
        "ownerAssigned": true,
        "periodDefined": true
      },
      "expected": false,
      "observed": true,
      "matched": false
    },
    {
      "name": "missing-ownerAssigned",
      "input": {
        "listExported": true,
        "indirectAccessIncluded": true,
        "ownerAssigned": false,
        "periodDefined": true
      },
      "expected": false,
      "observed": true,
      "matched": false
    }
  ],
  "after": [
    {
      "name": "documented-case",
      "input": {
        "listExported": true,
        "indirectAccessIncluded": true,
        "ownerAssigned": true,
        "periodDefined": true
      },
      "expected": true,
      "observed": true,
      "matched": true
    },
    {
      "name": "missing-indirectAccessIncluded",
      "input": {
        "listExported": true,
        "indirectAccessIncluded": false,
        "ownerAssigned": true,
        "periodDefined": true
      },
      "expected": false,
      "observed": false,
      "matched": true
    },
    {
      "name": "missing-ownerAssigned",
      "input": {
        "listExported": true,
        "indirectAccessIncluded": true,
        "ownerAssigned": false,
        "periodDefined": true
      },
      "expected": false,
      "observed": false,
      "matched": true
    }
  ]
}
```

## 2. Approve everyone

Approval needs business rationale and required duration. Without independent review, a high approval rate does not establish control effectiveness.

This code is a local policy model; it does not replace actual authentication, token validation or live permission tests.

### Weak implementation
```js
s => s.approved === true
```

### Corrected implementation
```js
s => s.approved === true &&
  s.businessNeedEvidenced === true &&
  s.independentReview === true &&
  s.expiryRecorded === true
```

### Synthetic input and actual model output
```json
{
  "before": [
    {
      "name": "documented-case",
      "input": {
        "approved": true,
        "businessNeedEvidenced": true,
        "independentReview": true,
        "expiryRecorded": true
      },
      "expected": true,
      "observed": true,
      "matched": true
    },
    {
      "name": "missing-businessNeedEvidenced",
      "input": {
        "approved": true,
        "businessNeedEvidenced": false,
        "independentReview": true,
        "expiryRecorded": true
      },
      "expected": false,
      "observed": true,
      "matched": false
    },
    {
      "name": "missing-expiryRecorded",
      "input": {
        "approved": true,
        "businessNeedEvidenced": true,
        "independentReview": true,
        "expiryRecorded": false
      },
      "expected": false,
      "observed": true,
      "matched": false
    }
  ],
  "after": [
    {
      "name": "documented-case",
      "input": {
        "approved": true,
        "businessNeedEvidenced": true,
        "independentReview": true,
        "expiryRecorded": true
      },
      "expected": true,
      "observed": true,
      "matched": true
    },
    {
      "name": "missing-businessNeedEvidenced",
      "input": {
        "approved": true,
        "businessNeedEvidenced": false,
        "independentReview": true,
        "expiryRecorded": true
      },
      "expected": false,
      "observed": false,
      "matched": true
    },
    {
      "name": "missing-expiryRecorded",
      "input": {
        "approved": true,
        "businessNeedEvidenced": true,
        "independentReview": true,
        "expiryRecorded": false
      },
      "expected": false,
      "observed": false,
      "matched": true
    }
  ]
}
```

## 3. Decision recorded

Recording a decision does not establish an applied outcome. Track removal, effective-access revalidation and ownership of residual exceptions separately.

This code is a local policy model; it does not replace actual authentication, token validation or live permission tests.

### Weak implementation
```js
s => s.decisionRecorded === true
```

### Corrected implementation
```js
s => s.decisionRecorded === true &&
  s.removalApplied === true &&
  s.effectiveAccessRetested === true &&
  s.exceptionOwned === true
```

### Synthetic input and actual model output
```json
{
  "before": [
    {
      "name": "documented-case",
      "input": {
        "decisionRecorded": true,
        "removalApplied": true,
        "effectiveAccessRetested": true,
        "exceptionOwned": true
      },
      "expected": true,
      "observed": true,
      "matched": true
    },
    {
      "name": "missing-removalApplied",
      "input": {
        "decisionRecorded": true,
        "removalApplied": false,
        "effectiveAccessRetested": true,
        "exceptionOwned": true
      },
      "expected": false,
      "observed": true,
      "matched": false
    },
    {
      "name": "missing-effectiveAccessRetested",
      "input": {
        "decisionRecorded": true,
        "removalApplied": true,
        "effectiveAccessRetested": false,
        "exceptionOwned": true
      },
      "expected": false,
      "observed": true,
      "matched": false
    }
  ],
  "after": [
    {
      "name": "documented-case",
      "input": {
        "decisionRecorded": true,
        "removalApplied": true,
        "effectiveAccessRetested": true,
        "exceptionOwned": true
      },
      "expected": true,
      "observed": true,
      "matched": true
    },
    {
      "name": "missing-removalApplied",
      "input": {
        "decisionRecorded": true,
        "removalApplied": false,
        "effectiveAccessRetested": true,
        "exceptionOwned": true
      },
      "expected": false,
      "observed": false,
      "matched": true
    },
    {
      "name": "missing-effectiveAccessRetested",
      "input": {
        "decisionRecorded": true,
        "removalApplied": true,
        "effectiveAccessRetested": false,
        "exceptionOwned": true
      },
      "expected": false,
      "observed": false,
      "matched": true
    }
  ]
}
```

## Exit evidence

- Scoped access-review matrix with decision ownership and rationale.
- Execution/revalidation/exception closure record.

## References

- [Microsoft Entra · Plan access reviews](https://learn.microsoft.com/en-us/entra/id-governance/deploy-access-reviews)
- [Microsoft Entra · Revoke user access and session limits](https://learn.microsoft.com/en-us/entra/identity/users/users-revoke-access)
