In LDAPv3, where does a directory server publish the object class and attribute type definitions it enforces?
answer
- schema is readable as data
- an entry points at its own rules
- one operational attribute holds the pointer
- the subentry carries objectClasses and attributeTypes
- ask for operational attributes by name
basics
~10 sA directory server publishes its schema as an ordinary entry, the subschema subentry. Each entry's operational attribute subschemaSubentry holds that subentry's Distinguished Name, and the subentry carries objectClasses, attributeTypes, matchingRules and the rest.
solid answer
~40 sA directory server publishes its own schema as data, readable over the same protocol as the entries it governs. Every entry carries the operational attribute `subschemaSubentry (2.5.18.10)`, whose single value is the Distinguished Name of the subschema subentry that governs that entry. The subentry holds the definitions in multi-valued attributes: `objectClasses`, `attributeTypes`, `matchingRules`, `matchingRuleUse`, `ldapSyntaxes`, `dITContentRules`, `dITStructureRules` and `nameForms`. Both the pointer and the definition attributes are operational, so a client has to name them explicitly in its read — a request for all user attributes comes back without them, which is why clients often conclude the server publishes no schema when it does.
code
ldif · 7 lines# the entry named by an entry's subschemaSubentry value
dn: cn=schema
objectClasses: ( 2.5.6.6 NAME 'person' SUP top STRUCTURAL
MUST ( sn $ cn )
MAY ( userPassword $ telephoneNumber $ seeAlso $ description ) )
objectClasses: ( 2.5.6.9 NAME 'groupOfNames' SUP top STRUCTURAL
MUST ( member $ cn ) )go deeper
Recall that a directory's schema is not hidden in a configuration file: it is published as an entry a client can read with the same operations it uses for ordinary data.
Explain the two hops — subschemaSubentry on the entry names a DN, and that entry's objectClasses and attributeTypes values are the definitions — and add why neither appears unless it is requested by name.
Demonstrate the diagnostic habit: before blaming a directory server for refusing a write, read the definitions it actually publishes rather than the ones your documentation assumes it has.
The leverage is tooling that reads the published schema instead of restating it. Every hardcoded copy of a class definition is a second source of truth that will drift from the server's.
## The schema is data A directory server does not keep its schema in a private format that only its administrators can see. It publishes the definitions as attributes of an ordinary entry, reachable with the same read a client uses for any other entry. That is the property worth remembering: **the rules a write is checked against are readable over the protocol the write arrives on**, so a client can discover what is allowed rather than hardcode a copy of it. ## Two hops to the definitions 1. **Read the pointer.** Every entry carries the operational attribute `subschemaSubentry (2.5.18.10)`, a single Distinguished Name naming the subschema subentry in force for that entry. It sits on the entry rather than at one fixed well-known name because different parts of one tree may be governed by different subentries. 2. **Read that entry.** Its definition attributes carry the schema, one value per class, type or rule, written in the same form the specification uses to publish them. Both hops hit the same obstacle: these are operational attributes, and operational attributes are excluded from the default result set. A client that reads an entry and asks for everything gets the user attributes back and nothing else. The attributes must be named in the request, and the commonest false conclusion in this area — *the server publishes no schema* — is almost always this rule in action. ## What the subentry holds | Attribute type | What it publishes | |---|---| | `objectClasses` | class definitions: OID, name, kind, `SUP`, `MUST` and `MAY` | | `attributeTypes` | type definitions: OID, name, `SYNTAX`, `EQUALITY` and the flags | | `matchingRules` | the matching rules those type definitions name | | `matchingRuleUse` | which attribute types each rule may be applied to | | `ldapSyntaxes` | the value syntaxes the server has in force | | `dITContentRules` | which auxiliary classes and attributes a structural class may take here | | `dITStructureRules` and `nameForms` | the structure and naming rules published alongside them | The first two answer nearly every practical question. `objectClasses` is where you read the exact `MUST` and `MAY` lists a refused write was measured against; `attributeTypes` is where you read whether a type is `SINGLE-VALUE`, which syntax its values must fit, and which matching rule decides duplicates. ## Not the root DSE The subschema subentry is often confused with the root DSE, and they answer different questions. The root DSE describes the **server**: what it supports and which parts of the tree it holds. The subschema subentry describes the **rules entries are held to**. A client bootstrapping against an unfamiliar directory usually reads both, but reading one does not give you the other, and the schema pointer is per-entry precisely because the answer can differ across one tree. ## What it is worth in practice - **Diagnosis.** When a write is refused, read the definition the server actually publishes rather than the one your documentation describes. The two disagree more often than people expect, because estates extend their schema locally. - **Tooling.** A client that reads `objectClasses` and `attributeTypes` can build its input validation, or render a form, from the directory's own rules, and will follow them when they change. - **One source of truth.** Every hardcoded copy of a class definition inside an application is a second source of truth, and it will drift from the server's. The drift is invisible until a write starts being refused in production and the application insists the entry is valid. - **Import safety.** A bulk load that checks each row against the published definitions before writing fails on the first row locally instead of part way through the load remotely. ## The shape to remember An entry says what it is (`objectClass`), the classes say what it may hold (`MUST` and `MAY`), the type definitions say what each value may be, and `subschemaSubentry` says where all of that is written down. Four steps, and the last one closes the loop by making the rules as readable as the data they govern.
- How does a client actually read the definitions once it holds the subentry's Distinguished Name?By reading that entry and naming the definition attributes it wants — `objectClasses`, `attributeTypes` and the rest — because they are operational and are left out of the default result set. What comes back is the definition string itself, one value per class or type, which the client parses instead of hardcoding its own copy.
- Is the subschema subentry the same thing as the root DSE?No. The root DSE is the server's own capability entry, reporting what it supports and which parts of the tree it holds. The subschema subentry holds schema definitions. Different parts of one tree may be governed by different subentries, which is why the pointer sits on each entry rather than at a single fixed name.
saying these in an interview costs you the question
- Says schema lives only in server configuration, unreadable over the protocol.
- Assumes an attribute missing from a result does not exist on the entry.
- Thinks one well-known DN always holds the schema for every entry.
- Confuses the root DSE's capability attributes with schema definitions.
- Believes clients must hardcode the class definitions they expect.