Skip to content

docs(design-proposals): add tenant host delegation proposal - #70

Open
mattia-eleuteri wants to merge 1 commit into
cozystack:mainfrom
mattia-eleuteri:proposal/tenant-host-delegation
Open

mattia-eleuteri wants to merge 1 commit into
cozystack:mainfrom
mattia-eleuteri:proposal/tenant-host-delegation

Conversation

@mattia-eleuteri

Copy link
Copy Markdown

Adds a design proposal for delegating Tenant.spec.host to tenants, so a hostname the platform has assigned to a tenant can be set without a cluster-admin.

Today layer 4 of the hostname security model (cozystack-tenant-host-policy) gates spec.host on the caller's identity alone: system:masters or a cozy-* service account. That gate is correct in intent — the value becomes the namespace.cozystack.io/host label that layers 2, 7 and 8 all trust — but it leaves a tenant user with no reachable non-empty value, so every hostname is a manual operation and a component that has already verified DNS ownership has nowhere to record that fact.

The proposal separates applying a verdict from producing one. Cozystack checks a host against a per-tenant allowlist (carried by a namespace.cozystack.io/allowed-hosts namespace annotation, inherited through the existing _namespace channel) and a platform reserved list that no allowlist can override. Ownership verification stays outside admission. Writing the allowlist is itself gated by a new policy, because tenants receive a kubeconfig and apps.cozystack.io/* in their own namespace by design, so a self-written allowlist would be self-signed.

Two points the proposal argues explicitly, since both are easy to get backwards:

  • The accounts that may grant a domain and those that may set spec.host are deliberately disjoint sets. The reserved list is what keeps that disjointness meaningful, not the reverse — with the reserved list empty, a grant account can hand out the platform's own apex.
  • Every hostname comparison normalises case on both operands. The namespace.cozystack.io/host label reaches consumers "normalised by nothing", as external-database-exposure documents independently; a comparison that skipped it would let a granted example.com reach a reserved internal.example.com via svc.INTERNAL.example.com, which downstream consumers then match all-lowercase.

The four open questions at the end are the ones I would most like reviewer input on — in particular whether it is acceptable that a grant is inoperative on Tenant/root (the safe behaviour, but it means a level-1 tenant's own host stays a trusted-caller field), and whether the delegation-seeded entry should be strict-subdomain rather than apex-inclusive.

An implementation exists and is verified against the design, which is where the failure and edge-case lists come from; it is not part of this PR and will be proposed separately once the design has been discussed.

Before review

  • If this revises a merged design proposal: it adds a decision record under that proposal's decisions/ directory, or says below why none is needed.

This is a new proposal, not a revision of a merged one, so there is no design to record a change against. The Decisions section is left empty per the template.

DCO

  • Commits are signed off (git commit --signoff).

Tenant.spec.host is gated on caller identity alone, so on a multi-tenant
platform no non-empty value is reachable by a tenant user: their own
delegated subdomain is refused by the platform's API denylist and their own
domain by the admission policy. Every hostname becomes a support ticket, and
a control panel that has already verified DNS ownership has nowhere to record
that fact.

The proposal separates applying a verdict from producing one: Cozystack
checks a host against a per-tenant allowlist and a platform reserved list,
while ownership verification stays outside admission. Writing the allowlist
is itself gated, so the grant cannot be self-signed by a tenant that holds a
kubeconfig and apps.cozystack.io/* in its own namespace.

Signed-off-by: Mattia Eleuteri <mattia@hidora.io>
Assisted-by: LLM
@coderabbitai

coderabbitai Bot commented Sep 7, 2026

Copy link
Copy Markdown

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Team

Run ID: 21aeb846-8437-4f4a-a8c9-979f1b97ca3c


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@mattia-eleuteri

Copy link
Copy Markdown
Author

Implementation and its verification, opened as a draft so the design can be discussed here first: cozystack/cozystack#4132

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants