Skip to content
academia.sh

Lesson 14 / 21

Directory Services

Measuring the central identity repository as a trust root: 13 of 16 systems being bound to a single repository, the chain from root to login holding 9, 8, or 2 items depending on connection mode, a 12-hour outage stopping 609 account logins across 13 systems, the third replica rescuing no new system, and 646 items needing manual renewal when integrity breaks.

Published Updated

In this lesson

  • Names the central identity repository as a trust root and derives the number of systems bound to it
  • Counts the chain from root to login item by item, by connection mode
  • Separates the systems replication rescues from the items renewed when integrity breaks
Contents

The previous topic bound who a public key belongs to into a chain: certificate, intermediate authority, root. The chain was counted and the items that fall when the root breaks were derived. The question left open at the close was this — the key’s owner was bound to a name, but who that name is inside the organization, which team it sits in, which systems it can log into, and how that is enforced across thousands of machines was never asked. This topic takes up that question at enterprise scale and measures it with the same three columns.

The first mechanism is the bottommost one: how does the organization know who exists. If every system keeps its own account list, a person joining means opening records on however many systems, and a person leaving means closing however many records — and a record that is not closed leaves an opening no one can see. The mechanism that collects this load in one place is the directory service: a queryable central identity repository that holds user, device, and service accounts in a single tree. What this lesson measures is not what the directory does, but how many things depend on it.

The Central Repository As a Root

EI1: the central identity repository is a trust root; every system bound to it assumes from the outset that the record the repository returns is correct, and does not verify it on its own. EI2: there is a chain of items running from root to use; every item in the chain must be correct at the same time — if one is broken, login either stops or returns the wrong result. EI3: replication multiplies the root’s availability, not its correctness — more copies shorten outage time, not the impact of an integrity break. EI4: a system left outside the root escapes both the root’s outages and its oversight.

This course’s three columns are the same in this topic too: the trust root is named, the number of items that must be correct at the same time from root to use is counted, and how many items fall if the root breaks and what renewal costs is written down. The directory’s query syntax, tree schema, and replication protocol are not measured here; what is measured is these three numbers.

Sixteen Systems, One Repository

The inventory below is a model: the systems of the organization running the fictional regional measurement network, and how each one connects to the central repository. There is no real organization, no real directory product, and no real account.

// identity/directory.mjs — how the systems of the fictional regional measurement network connect
// to the central identity repository (model): no real organization, no real directory product,
// and no real account. No randomness.

// EI1: the central identity repository is a trust root; every system bound to it assumes from
// the outset that the record the repository holds is correct.
// Columns: mode = connection mode (directory: asks on every login; cache: keeps the last
// successful check for a while; local: keeps its own account store), accounts = number of
// accounts logging into that system, refs = number of directory replicas in the system's
// configuration, secret = number of the system's own service-account secrets in the directory.
export const SYSTEM = `
  reading-collector        directory   34   2   1
  validator                directory   12   2   1
  billing                  directory   48   1   2
  work-order                directory   61   1   1
  field-mobile-endpoint     cache      140   2   1
  branch-workstation        cache       96   2   1
  warehouse-terminal        cache       18   1   1
  maintenance-scheduler     directory   22   1   1
  measurement-archive       directory    9   2   1
  reporting-portal          directory   55   1   1
  network-switch            directory   14   2   0
  vpn-endpoint               directory   27   2   0
  printer-pool              cache       73   1   0
  legacy-scada-console      local        6   0   0
  firmware-server           local        4   0   0
  backup-console            local        3   0   0`
  .trim().split("\n").map((r) => {
    const p = r.trim().split(/\s+/);
    return { name: p[0], mode: p[1], accounts: +p[2], refs: +p[3], secret: +p[4] };
  });

// EI2: every use bound to the root sets up a chain of items running from root to use; every
// item in the chain must be correct at the same time. Each item records which modes require it.
export const CHAIN = [
  { item: "account record exists",       mode: ["directory", "cache"] },
  { item: "account active",              mode: ["directory", "cache"] },
  { item: "password verifier",           mode: ["directory", "cache"] },
  { item: "group membership",            mode: ["directory", "cache"] },
  { item: "attribute mapping",           mode: ["directory", "cache"] },
  { item: "live connection to directory", mode: ["directory"] },
  { item: "channel protection",          mode: ["directory", "cache"] },
  { item: "name resolution",             mode: ["directory", "cache"] },
  { item: "clock synchronization",       mode: ["directory", "cache"] },
  { item: "local account store",         mode: ["local"] },
  { item: "local password record",       mode: ["local"] },
];

export const MODE = ["directory", "cache", "local"];
export const chainLength = (mode) => CHAIN.filter((c) => c.mode.includes(mode)).length;
// identity/tally.mjs — the central identity repository counted as a trust root: how many items
// the chain holds, how many systems stop logging in when the repository goes down, how many
// systems replication rescues, and how many items renewal costs if the root breaks.
import { SYSTEM, CHAIN, MODE, chainLength } from "./directory.mjs";

const print = (w, ...c) => console.log(c.map((v, i) =>
  (w[i] < 0 ? String(v).padEnd(-w[i]) : String(v).padStart(w[i]))).join(""));
const sum = (f, s = SYSTEM) => s.reduce((a, x) => a + f(x), 0);
const bound = SYSTEM.filter((s) => s.mode !== "local");

console.log(`${SYSTEM.length} systems, ${sum((s) => s.accounts)} account logins, ` +
  `${bound.length} systems bound to a single repository, ${SYSTEM.length - bound.length} systems with their own repository`);

const A = [-10, 9, 10, 8, 8, 8];
console.log("\n1. chain length and load by connection mode");
print(A, "mode", "systems", "accounts", "chain", "items", "secret");
for (const m of MODE) {
  const s = SYSTEM.filter((x) => x.mode === m);
  print(A, m, s.length, sum((x) => x.accounts, s), chainLength(m),
    s.length * chainLength(m), sum((x) => x.secret, s));
}
print(A, "total", SYSTEM.length, sum((s) => s.accounts), "-",
  sum((s) => chainLength(s.mode)), sum((s) => s.secret));

const B = [-10, 11, 15, 11, 13];
console.log("\n2. when the repository is unreachable (single copy)");
print(B, "outage", "down sys", "down accounts", "up sys", "up accounts");
for (const hour of [1, 4, 12, 48]) {
  const down = SYSTEM.filter((s) => s.mode === "directory" ||
    (s.mode === "cache" && hour > 8));
  print(B, `${hour} h`, down.length, sum((s) => s.accounts, down),
    SYSTEM.length - down.length, sum((s) => s.accounts) - sum((s) => s.accounts, down));
}

const C = [-10, 11, 11, 15];
console.log("\n3. how many systems does replication rescue in a 12-hour outage");
print(C, "copies", "rescued", "down", "down accounts");
for (const copies of [1, 2, 3]) {
  const rescued = SYSTEM.filter((s) => s.mode !== "local" && s.refs >= 2 && copies >= 2);
  const down = bound.filter((s) => !rescued.includes(s));
  print(C, `${copies}`, rescued.length, down.length, sum((s) => s.accounts, down));
}

const D = [-24, 8, 8, 20];
console.log("\n4. if the root breaks (repository integrity is compromised): items lost and renewal");
const accounts = sum((s) => s.accounts, bound);
const rows = [
  ["directory-bound systems", bound.length, bound.length, "remapped"],
  ["account logins", accounts, accounts, "passwords reset"],
  ["service account secrets", sum((s) => s.secret), sum((s) => s.secret), "manually changed"],
  ["group membership checks", bound.length, bound.length, "manually verified"],
  ["locally stored systems", SYSTEM.length - bound.length, 0, "unaffected"],
];
print(D, "item", "count", "lost", "renewal");
for (const r of rows) print(D, ...r);
console.log(`total manually renewed items ${rows.reduce((a, r) => a + r[2], 0)}, ` +
  `chain item definitions ${CHAIN.length}`);
16 systems, 622 account logins, 13 systems bound to a single repository, 3 systems with their own repository

1. chain length and load by connection mode
mode        systems  accounts   chain   items  secret
directory         9       282       9      81       8
cache             4       327       8      32       3
local             3        13       2       6       0
total            16       622       -     119      11

2. when the repository is unreachable (single copy)
outage       down sys  down accounts     up sys  up accounts
1 h                 9            282          7          340
4 h                 9            282          7          340
12 h               13            609          3           13
48 h               13            609          3           13

3. how many systems does replication rescue in a 12-hour outage
copies        rescued       down  down accounts
1                   0         13            609
2                   7          6            277
3                   7          6            277

4. if the root breaks (repository integrity is compromised): items lost and renewal
item                       count    lost             renewal
directory-bound systems       13      13            remapped
account logins               609     609     passwords reset
service account secrets       11      11    manually changed
group membership checks       13      13   manually verified
locally stored systems         3       0          unaffected
total manually renewed items 646, chain item definitions 11

Numbers are of the measurement kind; their inputs are EI1–EI4 and the inventory values.

How Many Items the Chain Holds

The first table splits chain length by connection mode. On a system that asks the repository on every login, the chain is nine items: the record existing, being active, the password verifier holding, group membership being correct, attributes mapping to the fields the system expects, a live connection to the repository, the channel being protected, the name resolving, and the two sides’ clocks being close enough. None of these is a “security feature”; all nine are ordinary items required for login to work, and if one breaks, login stops.

On a system that verifies from cache, the chain drops to eight, because the live-connection item falls away. This one-item difference produces the whole difference in the second table. On a system that keeps its own repository, the chain is two — the local account list and the local password record. The total item count for sixteen systems is 119; this is the number of independent conditions that must be simultaneously correct for the event “a person can log into a system” to occur in the organization.

A two-item chain looks short, but the second half of EI4 is here. The six, four, and three accounts on the three locally-stored systems are bound to no central record: when a person leaves, the central record is closed, and the account on these three systems stays open. A short chain buys resilience to outages and lack of oversight together.

The Chain’s Items Outside the Repository

Not all nine items live in the repository, and this distinction draws the root’s boundary. Five are inside the repository: the record’s existence, its activeness, the password verifier, group membership, and attribute mapping. The remaining four are not in the repository — the live connection belongs to the network, channel protection to the certificate, name resolution to the name service, and clock synchronization to the time source. On a system verifying from cache, this ratio is five to three.

Each of these four items carries its own root. Channel protection rests on the chain of trust measured in the previous topic: encrypting the connection to the repository alone is not enough — the far end must be proven, with a certificate chain, to actually be the repository. On an unverified channel, even if the repository holds the correct record, someone else can answer the query. Name resolution is the same kind of dependency: the system asks another service to turn the repository’s name into an address, and does not verify that service’s answer.

Clock synchronization is the quietest item on the list, and the whole of the next lesson is built on it. The validity of a timed proof depends on the two sides’ clocks being close enough; when the clocks drift apart, login stops even though no account has changed at all. A trust root is as fragile as the number of items outside itself: in this model there are four separate items that can stop login even while the repository itself works perfectly, and none of them is under the directory administrator’s control.

When the Repository Goes Down

The second table counts down systems by outage length. In the first hour, nine systems and 282 account logins stop; the four systems verifying from cache keep working and 327 accounts are unaffected. After the eighth hour, the cache window closes: down systems rise to 13, down accounts to 609. The three still-up systems have 13 accounts in total.

The real number here is not 13, it is the gap between the two states. When the outage lasts one hour, the affected share of accounts is 282/622; when it lasts twelve hours, it is 609/622. The cache window directly sets the organization’s outage resilience, and this window is a security setting: the longer it is, the longer a disabled account keeps working. The same number cuts both ways at once — eight hours is both the time rescued during an outage and the time a disabled account stays valid.

What Replication Rescues and What It Does Not

The third table turns the first half of EI3 into a number. With a single copy, none of the 13 bound systems is rescued in a twelve-hour outage. Adding a second copy rescues seven systems, six stay down, and down accounts drop from 609 to 277. Adding a third copy leaves the table unchanged: still seven rescued, still six down.

The reason the third copy adds nothing is not in the repository — it is in the systems’ configuration. Six systems have a single configured reference address; even if a second copy sits on the network, those systems never ask it. Replication is a property of the repository; resilience is a property of client configuration, and the first cannot be measured until the second is written. The item that decides how many systems get rescued is not the copy count, but how many systems recognize the second reference.

Renewal If the Root Breaks

The fourth table is the second half of EI3. An outage and an integrity break are different events: an outage is temporary and leaves nothing behind once fixed, while an integrity break is permanent. If the repository’s records could be altered, who is a member of which group and which password verifier is valid are no longer known.

The renewal bill has four items: remapping 13 systems, resetting the passwords of 609 account logins, manually changing 11 service-account secrets, and manually verifying the group memberships of 13 systems. Total: 646 items. Of these, 609 touch people and can be done in parallel; 11 are service-account secrets, and each carries the risk of stopping a system’s operation, so they are done one at a time. The number that sets the renewal window’s length is not 609, it is 11.

More decisive than the size of the bill is when it gets issued. An integrity break does not announce itself like an outage: the repository keeps working, logins succeed, and no system raises an error. Knowing a break happened depends on comparing the records against an independent copy; without such a comparison, the 646-item renewal decision cannot be made, because the event requiring renewal is not known to have happened. The cost of a root break does not accrue at renewal — it accrues in every login made during the time the break goes unnoticed.

The three locally-stored systems come out to zero in this table. This does not mean those three systems are safe; they have their own roots, and that root is outside this measurement. Being outside a root does not mean escaping breakage — it means adding a separate breaking point.

Summary

  • The central identity repository is a trust root: 13 of 16 systems and 609 of 622 account logins are bound to a single repository.
  • The chain from root to login is 9, 8, and 2 items depending on connection mode; all 119 total items must be correct at the same time.
  • The number of down systems during an outage is set by the cache window: 9 systems and 282 accounts in the first hour, 13 systems and 609 accounts by the twelfth hour.
  • Replication multiplies availability, not correctness; the third copy rescues no new system, because 6 systems have a single reference defined in their configuration.
  • If integrity breaks, 646 items are renewed by hand; the window’s length is set not by the 609 passwords, but by the 11 service-account secrets changed one at a time.

Next Step

This lesson counted what the repository says about who exists, but a record existing does not show that a person is actually there right now. Querying the repository on every login produces the dependency seen in the second table; enterprise networks instead produce a timed proof from a single verification, and that proof is presented instead of the password on every subsequent access. The service producing the proof has its own key, and that key is a new root. The next lesson measures ticket-based authentication on this axis: how many steps the flow takes, which step proves which claim, how many items fall if the ticket-granting service’s key is compromised, and how many steps renewing that key takes.

To keep your progress and take notes, Log in

My notes

Log in to take notes.

Start typing to search.

↑↓ ↵ Esc navigate · open · close