Two client certificates with different serial numbers, different keys and even different full subjects can still resolve to a single policy file, because the server is not looking at any of that. It reads a name out of the certificate and opens the matching client-config file. If both certificates carry the same name, the second one inherits the first one's policy the moment it connects.

The collision is created at enrollment and only discovered at connect time, usually as a device receiving an address or route set that belongs to another machine. Preventing it means agreeing on which field the server maps, then reserving that value before anything is signed.

Your certificate tooling will not warn you, because uniqueness inside X.509 and uniqueness of an OpenVPN policy name are different requirements enforced by different systems.

The server looks up a name, not a fingerprint

With the usual certificate-based mapping, the server takes the common name from the presented certificate and looks for a file of that name in its client-config directory. That file can pin a static address, push routes or apply per-client firewall marks. The lookup is a string match against a filename, so case, spacing and punctuation all matter.

Some deployments deliberately swap the mapping so an authenticated username takes over from the common name, and then the username is what has to be unique. Either way, the value that selects policy is the value you reserve. Decide which one it is before issuing anything; guessing after a collision costs more than asking.

Where two authorities fit the same name

An organisation that accepts certificates from more than one issuing authority runs two independent enrollment processes writing into one namespace. Each authority's own uniqueness rules apply inside itself, so both can legitimately issue for the same common name without either noticing anything wrong.

Serial numbers do not help. X.509 requires a serial to be unique within its issuer's scope, which is a property of that authority's bookkeeping rather than a global device identity. A subject check is also a different test from a common-name check: two certificates can share a CN while differing in organisational unit, and therefore carry distinct subjects. Every one of those properties can hold while the server still maps both certificates onto one filename.

The OpenSSL CA documentation covers the unique_subject setting that governs its own database opinion, and the honest starting point is to read your issuing configuration rather than assume a particular EasyRSA or OpenSSL default applies.

Reserve the effective name before signing

Keep a registry that maps a device to its approved record and from there to an exact policy filename, so a name is allocated once and stays allocated. The reservation has to be atomic, which in practice means a database constraint or a lock wrapped around the allocate-then-sign step, not a spreadsheet two people edit.

Then make the check part of issuance: refuse to sign when the requested name already exists, and include every authority the server trusts in that check, because a name reserved by the other authority is just as taken. A rejected request with a clear reason is cheaper than a ticket about a device that keeps getting someone else's static address.

Renewal reuses a name on purpose

Reissuing for an existing device should produce a new serial under the same policy name, and that is legitimate reuse rather than a collision. What has to be decided in advance is the overlap: whether old and new certificates may be valid simultaneously, and how the old credential gets retired.

Do not reach for duplicate-cn to solve this. That server option governs concurrent connections presenting the same name; it does not lock enrollment, and enabling it does not make one shared static address safe for two machines at once. Revocation normally identifies a certificate by issuer and serial, so retiring the old credential need not invalidate its replacement as long as the server receives and enforces the right revocation data.

Confirm the mapping with the tools on the box

Before handing a device its new credential, read the name out of the certificate the way the server will, then compare that with the policy file you expect to be selected.

openssl x509 -in device42.crt -noout -subject -nameopt sep_multiline
ls -l /etc/openvpn/ccd/device42
grep -n "duplicate-cn" /etc/openvpn/server.conf

The first command prints subject fields separately, which makes a stray organisational unit or a doubled space visible immediately. The second confirms that a policy file exists under exactly that name, and the third shows whether the server is configured to permit several sessions on one name. Run all three against a fresh certificate before it leaves the enrollment step, while a mistake still costs a signature instead of an incident. Keep the output with the ticket so the next person can see which name the server was actually given.

Finish with a real connection and compare the assigned address and pushed routes against the policy file rather than against what you meant to write. If two devices report the same static address, the registry has a collision that no certificate inspection will ever reveal.

Ebitabo ebifaananyi