# Service accounts and non-human identities

Govern application, automation and AI-agent identities through ownership, purpose, federation boundaries and retirement plans.

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

## Non-human identities still need owners

A Harbor build job accesses an application repository. An accountable team and technical role may own it, but the identity is not a human account. Record purpose, environment, resource, permission and retirement conditions. Leaving an ownerless account because the automation still runs hides risk. Do not blindly apply human MFA workflows to service identities; assess machine authentication through appropriate keys, managed identity or federation context. Microsoft terminology is used only within its product context, not as a universal object model for all providers.

## Short-lived credentials need scoped trust

Federation can reduce long-lived secrets without automatically narrowing a broad trust relationship. Specify which issuer, subject and audience are accepted for the workload and environment. Trusting only an organization name can expose access to unintended repositories or workflows. Harbor reviews declared evidence for these boundaries; it obtains no real OIDC token and verifies no signature. The local policy desk is not a federation engine either. Do not treat a federation-enabled flag as an assurance result without separately reviewing trust scope and verification behavior.

## Rotation is a migration

Creating a new key does not end use of the old one. Plan consumers, deployment order, observation, rollback and revocation of the prior key. Keep real key values out of tickets and learning files; use secure references. Harbor asks which consumer migrated to which revision and when the old access path was checked. Even automatic rotation needs review for failed consumers and forgotten copies. The desired evidence is not merely key creation but an authorized, verified migration and termination of the prior path. This exercise generates or revokes no actual credentials.

## Task boundaries for agents and automation

An AI agent’s tool use still sits within workload identity and authorization boundaries. A natural-language instruction does not grant unlimited operations on data sources. Design reading, writing and approval-dependent steps separately, with task-appropriate records, consumption limits and human approval scope. Harbor assigns the agent only listed actions on a synthetic resource; the local model executes no tools. Retirement review covers workflows, federation trust and unused grants together. Business ownership must remain clear even when software selects its next step dynamically.

## Working sequence

1. Record the workload and accountable team.
2. Define resource, action and environment scope.
3. Review federation trust boundaries.
4. Separate consumer migration and old-path revocation evidence.
5. Record retirement triggers and ownership.

## 1. Running but ownerless

Being inventoried does not establish purpose or ownership. Without an owner and narrow business need, permissions cannot be justified or retirement planned responsibly.

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

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

### Corrected implementation
```js
s => s.accountListed === true &&
  s.ownerNamed === true &&
  s.purposeScoped === true &&
  s.retirementPlanned === true
```

### Synthetic input and actual model output
```json
{
  "before": [
    {
      "name": "documented-case",
      "input": {
        "accountListed": true,
        "ownerNamed": true,
        "purposeScoped": true,
        "retirementPlanned": true
      },
      "expected": true,
      "observed": true,
      "matched": true
    },
    {
      "name": "missing-ownerNamed",
      "input": {
        "accountListed": true,
        "ownerNamed": false,
        "purposeScoped": true,
        "retirementPlanned": true
      },
      "expected": false,
      "observed": true,
      "matched": false
    },
    {
      "name": "missing-purposeScoped",
      "input": {
        "accountListed": true,
        "ownerNamed": true,
        "purposeScoped": false,
        "retirementPlanned": true
      },
      "expected": false,
      "observed": true,
      "matched": false
    }
  ],
  "after": [
    {
      "name": "documented-case",
      "input": {
        "accountListed": true,
        "ownerNamed": true,
        "purposeScoped": true,
        "retirementPlanned": true
      },
      "expected": true,
      "observed": true,
      "matched": true
    },
    {
      "name": "missing-ownerNamed",
      "input": {
        "accountListed": true,
        "ownerNamed": false,
        "purposeScoped": true,
        "retirementPlanned": true
      },
      "expected": false,
      "observed": false,
      "matched": true
    },
    {
      "name": "missing-purposeScoped",
      "input": {
        "accountListed": true,
        "ownerNamed": true,
        "purposeScoped": false,
        "retirementPlanned": true
      },
      "expected": false,
      "observed": false,
      "matched": true
    }
  ]
}
```

## 2. Federation enabled

A federation indicator does not establish correct issuer, subject and audience boundaries. Require evidence for each; the model validates no real token or signature.

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

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

### Corrected implementation
```js
s => s.federationEnabled === true &&
  s.issuerBound === true &&
  s.subjectBound === true &&
  s.audienceBound === true
```

### Synthetic input and actual model output
```json
{
  "before": [
    {
      "name": "documented-case",
      "input": {
        "federationEnabled": true,
        "issuerBound": true,
        "subjectBound": true,
        "audienceBound": true
      },
      "expected": true,
      "observed": true,
      "matched": true
    },
    {
      "name": "missing-subjectBound",
      "input": {
        "federationEnabled": true,
        "issuerBound": true,
        "subjectBound": false,
        "audienceBound": true
      },
      "expected": false,
      "observed": true,
      "matched": false
    },
    {
      "name": "missing-audienceBound",
      "input": {
        "federationEnabled": true,
        "issuerBound": true,
        "subjectBound": true,
        "audienceBound": false
      },
      "expected": false,
      "observed": true,
      "matched": false
    }
  ],
  "after": [
    {
      "name": "documented-case",
      "input": {
        "federationEnabled": true,
        "issuerBound": true,
        "subjectBound": true,
        "audienceBound": true
      },
      "expected": true,
      "observed": true,
      "matched": true
    },
    {
      "name": "missing-subjectBound",
      "input": {
        "federationEnabled": true,
        "issuerBound": true,
        "subjectBound": false,
        "audienceBound": true
      },
      "expected": false,
      "observed": false,
      "matched": true
    },
    {
      "name": "missing-audienceBound",
      "input": {
        "federationEnabled": true,
        "issuerBound": true,
        "subjectBound": true,
        "audienceBound": false
      },
      "expected": false,
      "observed": false,
      "matched": true
    }
  ]
}
```

## 3. New key created

A new key does not establish consumer migration or revocation of the old one. Rotation remains incomplete without verified migration and rollback context.

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

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

### Corrected implementation
```js
s => s.newKeyCreated === true &&
  s.consumersMigrated === true &&
  s.oldKeyRevoked === true &&
  s.rollbackReviewed === true
```

### Synthetic input and actual model output
```json
{
  "before": [
    {
      "name": "documented-case",
      "input": {
        "newKeyCreated": true,
        "consumersMigrated": true,
        "oldKeyRevoked": true,
        "rollbackReviewed": true
      },
      "expected": true,
      "observed": true,
      "matched": true
    },
    {
      "name": "missing-consumersMigrated",
      "input": {
        "newKeyCreated": true,
        "consumersMigrated": false,
        "oldKeyRevoked": true,
        "rollbackReviewed": true
      },
      "expected": false,
      "observed": true,
      "matched": false
    },
    {
      "name": "missing-oldKeyRevoked",
      "input": {
        "newKeyCreated": true,
        "consumersMigrated": true,
        "oldKeyRevoked": false,
        "rollbackReviewed": true
      },
      "expected": false,
      "observed": true,
      "matched": false
    }
  ],
  "after": [
    {
      "name": "documented-case",
      "input": {
        "newKeyCreated": true,
        "consumersMigrated": true,
        "oldKeyRevoked": true,
        "rollbackReviewed": true
      },
      "expected": true,
      "observed": true,
      "matched": true
    },
    {
      "name": "missing-consumersMigrated",
      "input": {
        "newKeyCreated": true,
        "consumersMigrated": false,
        "oldKeyRevoked": true,
        "rollbackReviewed": true
      },
      "expected": false,
      "observed": false,
      "matched": true
    },
    {
      "name": "missing-oldKeyRevoked",
      "input": {
        "newKeyCreated": true,
        "consumersMigrated": true,
        "oldKeyRevoked": false,
        "rollbackReviewed": true
      },
      "expected": false,
      "observed": false,
      "matched": true
    }
  ]
}
```

## Exit evidence

- Workload inventory with owner, purpose, environment and permissions.
- Federation-boundary, consumer-migration and retirement record.

## References

- [Microsoft Entra · Workload identities overview](https://learn.microsoft.com/en-us/entra/workload-id/workload-identities-overview)
- [RFC 9700 · OAuth 2.0 Security Best Current Practice · January 2025](https://www.rfc-editor.org/rfc/rfc9700.html)
