mirror of
https://github.com/kanidm/kanidm.git
synced 2025-02-23 12:37:00 +01:00
Rewrite "choosing a domain", add other considerations (#3147)
Co-authored-by: Firstyear <william@blackhats.net.au>
This commit is contained in:
parent
bc55313d87
commit
5c9eb87a75
|
@ -1,96 +1,346 @@
|
||||||
# Choosing a Domain Name
|
# Choosing a Domain Name
|
||||||
|
|
||||||
Through out this book, Kanidm will make reference to a "domain name". This is your chosen DNS domain
|
This book makes many references to a "domain name". This is the DNS domain name
|
||||||
name that you intend to use for Kanidm. Choosing this domain name however is not simple as there are
|
that you intend to use for Kanidm.
|
||||||
a number of considerations you need to be careful of.
|
|
||||||
|
This isn't always simple, and this chapter covers the key issues to consider
|
||||||
|
when choosing a domain.
|
||||||
|
|
||||||
> [!WARNING]
|
> [!WARNING]
|
||||||
>
|
>
|
||||||
> Incorrect choice of the domain name may have security impacts on your Kanidm instance, not limited
|
> **Bad choices** of domain name may have security impacts on your Kanidm
|
||||||
> to credential phishing, theft, session leaks and more. It is critical you follow the advice in
|
> instance, not limited to credential phishing, theft, session leaks and more.
|
||||||
> this chapter.
|
>
|
||||||
|
> **Changing** domain name is hard to do – it not only means reconfiguring all
|
||||||
|
> LDAP and OAuth clients, but will also break all registered WebAuthn
|
||||||
|
> credentials for all users (which are bound to an `Origin`).
|
||||||
|
>
|
||||||
|
> It's critical that you consider and follow the advice in this chapter, and
|
||||||
|
> aim to get it right the first time.
|
||||||
|
>
|
||||||
|
> You'll save yourself a lot of work later!
|
||||||
|
|
||||||
|
<!-- -->
|
||||||
|
|
||||||
|
> [!TIP]
|
||||||
|
>
|
||||||
|
> We believe these practices are applicable *regardless* of your organisation's
|
||||||
|
> size (even if your Kanidm instance is just for you!), or if you think your
|
||||||
|
> organisation is not "important enough" to be the target of attacks.
|
||||||
|
>
|
||||||
|
> While some suggestions may seem "extreme" or "paranoid", they generally come
|
||||||
|
> from Kanidm's authors' collective decades of experience managing, maintaining,
|
||||||
|
> and securing networks and systems at both very large and very small
|
||||||
|
> organisations both inside and outside the technology industry.
|
||||||
|
|
||||||
## Considerations
|
## Considerations
|
||||||
|
|
||||||
### Domain Ownership
|
### Use a domain under your exclusive control
|
||||||
|
|
||||||
It is recommended you use a domain name within a domain that you own. While many examples list
|
You should always use a domain name that you've registered and directly control
|
||||||
`example.com` throughout this book, it is not recommended to use this outside of testing. Another
|
its DNS.
|
||||||
example of risky domain to use is `local`. While it seems appealing to use these, because you do not
|
|
||||||
have unique ownership of these domains, if you move your machine to a foreign network, it is
|
|
||||||
possible you may leak credentials or other cookies to these domains. TLS in a majority of cases can
|
|
||||||
and will protect you from such leaks however, but it should not always be relied upon as a sole line
|
|
||||||
of defence.
|
|
||||||
|
|
||||||
Failure to use a unique domain you own, may allow DNS hijacking or other credential leaks in some
|
While `example.com` and top-level domains ending in `.example` appear throughout
|
||||||
circumstances.
|
this book, [these are examples only][rfc2606]. You should **not** use this
|
||||||
|
outside of testing.
|
||||||
|
|
||||||
### Subdomains
|
[rfc2606]: https://datatracker.ietf.org/doc/html/rfc2606
|
||||||
|
|
||||||
Due to how web browsers and webauthn work, any matching domain name or subdomain of an effective
|
You'll need a registered domain for a CA (certificate authority) to issue you a
|
||||||
domain may have access to cookies within a browser session. An example is that `host.a.example.com`
|
TLS certificate which is widely accepted by browsers. This will also **prevent**
|
||||||
has access to cookies from `a.example.com` and `example.com`.
|
those same CAs from issuing a certificate for that domain to *someone else*.
|
||||||
|
|
||||||
For this reason your Kanidm host (or hosts) should be on a unique subdomain, with no other services
|
If you use a domain controlled by someone else (eg: a Dynamic DNS provider, or
|
||||||
registered under that subdomain. For example, consider `idm.example.com` as a subdomain for
|
your cloud provider), they could take over that domain *whenever they like*.
|
||||||
exclusive use of Kanidm. This is _inverse_ to Active Directory which often has its domain name
|
They could also use control of DNS or email to convince a CA to issue a
|
||||||
selected to be the parent (toplevel) domain (`example.com`).
|
certificate for that domain.
|
||||||
|
|
||||||
Failure to use a unique subdomain may allow cookies to leak to other entities within your domain,
|
*Any party who holds a valid certificate for the domain can steal or issue
|
||||||
and may allow webauthn to be used on entities you did not intend for which may or may not lead to
|
credentials.*
|
||||||
some phishing scenarios.
|
|
||||||
|
|
||||||
## Examples
|
### Avoid non-public and reserved domains
|
||||||
|
|
||||||
### Good Domain Names
|
Avoid using "made-up" (eg: `.lan`) or reserved domains (eg:
|
||||||
|
[`.local`][dot-local]), because your clients may leak credentials if they move
|
||||||
|
to another network, aren't connected to a VPN, or if it
|
||||||
|
[collides with new TLDs][name-collision].
|
||||||
|
|
||||||
Consider we own `kanidm.com`. If we were to run geographical instances, and have testing
|
Properly-configured TLS can prevent *most* (but not all) leakage, but defence in
|
||||||
environments the following domain and hostnames could be used.
|
depth is best.
|
||||||
|
|
||||||
#### Production Domain Name
|
This will also ensure your infrastructure is accessible regardless of your
|
||||||
|
users' local network conditions.
|
||||||
|
|
||||||
- origin: `https://idm.kanidm.com`
|
[dot-local]: https://www.rfc-editor.org/rfc/rfc6762.html#section-3
|
||||||
- domain name: `idm.kanidm.com`
|
[name-collision]: https://en.wikipedia.org/wiki/Top-level_domain#Reserved_domains
|
||||||
- host names: `australia.idm.kanidm.com`, `newzealand.idm.kanidm.com`
|
|
||||||
|
|
||||||
This allows us to have named geographical instances such as `https://australia.idm.kanidm.com` which
|
### Domain authorities
|
||||||
still works with webauthn and cookies which are transferable between instances.
|
|
||||||
|
|
||||||
It is critical no other hosts are registered under this domain name.
|
Domain authorities can set their own eligibility policies for registering a
|
||||||
|
top-level domain. They may also allow a third-party to challenge your claim to
|
||||||
|
a top-level domain, subject to a dispute resolution policy. These policies may
|
||||||
|
change over time for commercial or political reasons.
|
||||||
|
|
||||||
#### Testing Domain Name
|
If your domain is on a ccTLD (country TLD), it may be de-registered should that
|
||||||
|
country cease to exist (eg: [as for `.io`][dot-io]).
|
||||||
|
|
||||||
- origin: `https://idm.dev.kanidm.com`
|
[dot-io]: https://www.theverge.com/2024/10/8/24265441/uk-treaty-end-io-domain-chagos-islands
|
||||||
- domain name: `idm.dev.kanidm.com`
|
|
||||||
- host names: `australia.idm.dev.kanidm.com`, `newzealand.idm.dev.kanidm.com`
|
|
||||||
|
|
||||||
Note that due to the name being `idm.dev.kanidm.com` vs `idm.kanidm.com`, the testing instance is
|
### Top-level domains containing "kanidm"
|
||||||
not a subdomain of production, meaning the cookies and webauthn tokens can NOT be transferred
|
|
||||||
between them. This provides proper isolation between the instances.
|
|
||||||
|
|
||||||
### Bad Domain Names
|
We ask that you **do not** use the word `kanidm` as part of your instance's
|
||||||
|
*top-level* (or [public suffix][ps]) domain, eg: `contosokanidm.example`.
|
||||||
|
|
||||||
`idm.local` - This is a bad example as `.local` is an mDNS domain name suffix which means that
|
Use something like `auth`, `idm`, `login` or `sso` instead – they're shorter,
|
||||||
client machines if they visit another network _may_ try to contact `idm.local` believing they are on
|
too!
|
||||||
their usual network. If TLS certificate verification were disabled, this would allow leaking of
|
|
||||||
credentials.
|
|
||||||
|
|
||||||
`kanidm.com` - This is bad because the use of the top level domain means that any subdomain can
|
We're OK with you using `kanidm` in a *subdomain* to point to your Kanidm
|
||||||
access the cookies issued by `kanidm.com`, effectively leaking them to all other hosts.
|
instance, eg: `kanidm.example.com`.
|
||||||
|
|
||||||
Second instance overlap:
|
We've worked hard to build this project, and using its name in conjunction with
|
||||||
|
an organisation *not* associated with the project dilutes the name's branding
|
||||||
|
value.
|
||||||
|
|
||||||
#### Production
|
### Subdomains and Origin policy
|
||||||
|
|
||||||
- origin: `https://idm.kanidm.com`
|
Browsers allow a server on a subdomain to use intra-domain resources, and access
|
||||||
- domain name: `idm.kanidm.com`
|
and set credentials and cookies from all of its parents until a
|
||||||
|
[public suffix][ps]. This can allow a malicious or compromised service to attack
|
||||||
|
other services which share a parent domain.
|
||||||
|
|
||||||
#### Testing
|
[ps]: https://publicsuffix.org/
|
||||||
|
|
||||||
- origin: `https://dev.idm.kanidm.com`
|
Public suffix rules are *mostly* predictable, but has some exceptional cases.
|
||||||
- domain name: `dev.idm.kanidm.com`
|
For example:
|
||||||
|
|
||||||
While the production instance has a valid and well defined subdomain that doesn't conflict, because
|
* `host.a.example.com` can access and set cookies for:
|
||||||
the dev instance is a subdomain of production, it allows production cookies to leak to dev. Dev
|
|
||||||
instances may have weaker security controls in some cases which can then allow compromise of the
|
* `host.a.example.com` (itself)
|
||||||
production instance.
|
* `a.example.com`
|
||||||
|
* `example.com`
|
||||||
|
|
||||||
|
But **not** the public suffix `.com`.
|
||||||
|
|
||||||
|
* `host.a.example.qld.gov.au` can access and set cookies for:
|
||||||
|
|
||||||
|
* `host.a.example.qld.gov.au` (itself)
|
||||||
|
* `a.example.qld.gov.au`
|
||||||
|
* `example.qld.gov.au`
|
||||||
|
|
||||||
|
But **not** any public suffix:
|
||||||
|
|
||||||
|
* `qld.gov.au` (Queensland state government)
|
||||||
|
* `gov.au` (Australian federal government)
|
||||||
|
* `.au` (Australia)
|
||||||
|
|
||||||
|
* `host.a.example.nsw.gov.au` can access and set cookies for:
|
||||||
|
|
||||||
|
* `host.a.example.nsw.gov.au` (itself)
|
||||||
|
* `a.example.nsw.gov.au`
|
||||||
|
* `example.nsw.gov.au`
|
||||||
|
* `nsw.gov.au` ([NSW state government has opted out][nsw-optout])
|
||||||
|
|
||||||
|
But **not** any public suffix:
|
||||||
|
|
||||||
|
* `gov.au` (Australian federal government)
|
||||||
|
* `.au` (Australia)
|
||||||
|
|
||||||
|
[nsw-optout]: https://bugzilla.mozilla.org/show_bug.cgi?id=547985
|
||||||
|
|
||||||
|
This can be an issue if Kanidm shares a domain with:
|
||||||
|
|
||||||
|
* applications which serve raw, user-supplied data in APIs (eg: blob/file
|
||||||
|
storage and [Matrix homeservers][matrix-csp])
|
||||||
|
* third-party servers *outside* of your organisation's control (eg: SaaS apps)
|
||||||
|
* anything which can be deployed to with minimal oversight (eg: a web host that
|
||||||
|
allows uploading content via unencrypted FTP)
|
||||||
|
|
||||||
|
[matrix-csp]: https://github.com/element-hq/synapse/blob/develop/README.rst#security-note
|
||||||
|
|
||||||
|
### Avoid wildcard and widely-scoped certificates
|
||||||
|
|
||||||
|
CAs can issue wildcard TLS certificates, which apply to all subdomains in the
|
||||||
|
same domain (eg: `*.example.com`).
|
||||||
|
|
||||||
|
This is used by some organisations to avoid leaking information about what
|
||||||
|
services exist on a domain in certificate transparency logs. However, this
|
||||||
|
information will exposed *anyway* whenever a client makes a DNS query.
|
||||||
|
|
||||||
|
If a service is issued a wildcard TLS certificate which *also* covers a Kanidm
|
||||||
|
installation on the same domain, any DNS hijacking could let that service
|
||||||
|
impersonate Kanidm to those clients, and steal credentials.
|
||||||
|
|
||||||
|
While DNS-over-HTTPS generally prevents local hijacking, it's
|
||||||
|
[possible for a network to disable it when automatically enabled][disable-doh],
|
||||||
|
or just block it entirely.
|
||||||
|
|
||||||
|
[disable-doh]: https://support.mozilla.org/en-US/kb/canary-domain-use-application-dnsnet
|
||||||
|
|
||||||
|
Sharing a single certificate between many services increases the risk that the
|
||||||
|
private key may be exposed, and broadens the impact scope.
|
||||||
|
|
||||||
|
### Separate production and testing environments
|
||||||
|
|
||||||
|
If running more than one instance of Kanidm, ensure that no two deployments
|
||||||
|
share the same subdomain. This prevents credential and cookie transfers between
|
||||||
|
the two environments. For example:
|
||||||
|
|
||||||
|
* Production: `idm.example.com`
|
||||||
|
* Testing: `idm-test.example.com`
|
||||||
|
|
||||||
|
If you instead had an instance of Kanidm at `idm.example.com` for production and
|
||||||
|
another at `test.idm.example.com` for testing, then the test instance could
|
||||||
|
access the credentials and cookies of the production environment.
|
||||||
|
|
||||||
|
This also prevents credentials intended for the test environment from being used
|
||||||
|
in production (where there may be stricter controls).
|
||||||
|
|
||||||
|
### Regional deployments
|
||||||
|
|
||||||
|
You could have multiple instances of Kanidm configured with replication, with a
|
||||||
|
single domain name and origin (eg: `idm.example.com`).
|
||||||
|
|
||||||
|
You could then make regional instances accessible from different host names (eg:
|
||||||
|
`au.idm.example.com` and `nz.idm.example.com`).
|
||||||
|
|
||||||
|
This allows credentials and cookies to be freely transferred between hosts that
|
||||||
|
are part of a single environment.
|
||||||
|
|
||||||
|
## Recommendations
|
||||||
|
|
||||||
|
For **maximum** security, your Kanidm domain name should be a subdomain of a
|
||||||
|
top-level domain (or domain under a [public suffix][ps]) that has no other
|
||||||
|
services assigned it, eg:
|
||||||
|
|
||||||
|
* Origin: `https://idm.exampleauth.example`
|
||||||
|
* Domain name: `idm.exampleauth.example`
|
||||||
|
|
||||||
|
When using [OAuth 2.0/OpenID Connect](./integrations/oauth2.md), there is no
|
||||||
|
need for a client app to share a top-level domain with Kanidm, because the app
|
||||||
|
does not need to share cookies.
|
||||||
|
|
||||||
|
Large public auth providers (eg: Google, Meta, Microsoft) work the same way with
|
||||||
|
both first and third-party apps.
|
||||||
|
|
||||||
|
If you have strict security controls for all apps on your top-level domain, you
|
||||||
|
could run Kanidm on a subdomain of your main domain, eg:
|
||||||
|
|
||||||
|
* Origin: `https://idm.example.com`
|
||||||
|
* Domain name: `idm.example.com`
|
||||||
|
|
||||||
|
But running Kanidm on a *separate* top-level domain makes it much easier to
|
||||||
|
restrict changes that *could* affect your IDM infrastructure.
|
||||||
|
|
||||||
|
> [!NOTE]
|
||||||
|
>
|
||||||
|
> This is the **inverse** of the common Active Directory practice of using the
|
||||||
|
> organisation's primary top-level domain directly, eg: `example.com`.
|
||||||
|
|
||||||
|
### Multi-environment and regional deployments
|
||||||
|
|
||||||
|
If we were to run regional instances, and have a separate testing environment,
|
||||||
|
the following domain and hostnames could be used:
|
||||||
|
|
||||||
|
#### Production environment
|
||||||
|
|
||||||
|
- Origin: `https://idm.example.com`
|
||||||
|
- Domain name: `idm.example.com`
|
||||||
|
- Host names: `australia.idm.example.com`, `newzealand.idm.example.com`
|
||||||
|
|
||||||
|
This allows us to have named regional instances such as
|
||||||
|
`https://australia.idm.example.com` which still works with WebAuthn and cookies
|
||||||
|
which are transferable between instances.
|
||||||
|
|
||||||
|
It is critical no other hosts are registered under `idm.example.com`.
|
||||||
|
|
||||||
|
#### Testing environment
|
||||||
|
|
||||||
|
- Origin: `https://idm-test.example.com`
|
||||||
|
- Domain name: `idm-test.example.com`
|
||||||
|
- Host names: `australia.idm-test.example.com`, `newzealand.idm-test.example.com`
|
||||||
|
|
||||||
|
This puts the testing instance under a separate subdomain of the top-level
|
||||||
|
domain to production (`idm.example.com`), so cookies and WebAuthn tokens can
|
||||||
|
**not** be transferred between them.
|
||||||
|
|
||||||
|
This provides proper isolation between the instances.
|
||||||
|
|
||||||
|
## Bad domain names
|
||||||
|
|
||||||
|
Domains you should avoid:
|
||||||
|
|
||||||
|
<dl>
|
||||||
|
|
||||||
|
<dt>
|
||||||
|
|
||||||
|
`idm.local`
|
||||||
|
|
||||||
|
</dt>
|
||||||
|
|
||||||
|
<dd>
|
||||||
|
|
||||||
|
The `.local` top-level domain is [reserved for multicast DNS][dot-local].
|
||||||
|
|
||||||
|
If a client visits another network, it _may_ try to contact `idm.local`
|
||||||
|
believing it is on its usual network. If TLS certificate verification were
|
||||||
|
disabled (or not configured correctly), this would leak credentials.
|
||||||
|
|
||||||
|
</dd>
|
||||||
|
|
||||||
|
<dt>
|
||||||
|
|
||||||
|
`example.com`
|
||||||
|
|
||||||
|
</dt>
|
||||||
|
|
||||||
|
<dd>
|
||||||
|
|
||||||
|
Using the top-level domain directly allows any subdomain of that domain to
|
||||||
|
access credentials and cookies intended for Kanidm.
|
||||||
|
|
||||||
|
</dd>
|
||||||
|
|
||||||
|
<dt>
|
||||||
|
|
||||||
|
`idm.example.nsw.gov.au`
|
||||||
|
|
||||||
|
</dt>
|
||||||
|
|
||||||
|
<dd>
|
||||||
|
|
||||||
|
[`nsw.gov.au` has opted out of being a public suffix][nsw-optout], so all
|
||||||
|
domains under that suffix (except `schools.nsw.gov.au`) share origin and
|
||||||
|
cookies.
|
||||||
|
|
||||||
|
</dd>
|
||||||
|
|
||||||
|
<dt>
|
||||||
|
|
||||||
|
`idm.examplekanidm.example`
|
||||||
|
|
||||||
|
</dt>
|
||||||
|
|
||||||
|
<dd>
|
||||||
|
|
||||||
|
Kanidm is the brand for this project.
|
||||||
|
|
||||||
|
</dd>
|
||||||
|
|
||||||
|
</dl>
|
||||||
|
|
||||||
|
### Multi-instance with overlap
|
||||||
|
|
||||||
|
* Production:
|
||||||
|
* Origin: `https://idm.example.com`
|
||||||
|
* Domain name: `idm.example.com`
|
||||||
|
|
||||||
|
* Testing:
|
||||||
|
* Origin: `https://test.idm.example.com`
|
||||||
|
* Domain name: `test.idm.example.com`
|
||||||
|
|
||||||
|
While the production instance has a valid and well defined subdomain that
|
||||||
|
doesn't conflict, because the testing instance is a subdomain of production, it
|
||||||
|
allows production cookies to leak to the testing environment.
|
||||||
|
|
||||||
|
Testing environments may have weaker security controls in some cases which can
|
||||||
|
then allow compromise of services using the production instance.
|
||||||
|
|
Loading…
Reference in a new issue