docs(cloud): say what attaching does to a credential's blast radius - #171
Merged
Conversation
`cloud.attachTo` resolves the owner's box by LISTING the provider's servers with
the attaching project's own token. That is the whole mechanism, and it forces a
consequence the config never stated: the owner's box has to be visible to the
attacher's credential, so both projects must share one provider project. On
Hetzner a Cloud API token is scoped to a project with Read or Read & Write and
has no per-resource scoping, and a deploy needs write.
So setting `attachTo` hands this project's CI write access over every server in
that provider project. Three apps that each owned one box become three pipelines
that each reach all three, plus anything else in the project. The old docstring
said "requires read access via the same HCLOUD_TOKEN", which understates it twice
over: the access needed is write, and the reach is the whole project rather than
the one box.
The reverse is worth stating too, because it is the other half of the same
decision: an app kept in its own provider project cannot be attached at all.
Isolation and co-hosting are mutually exclusive here, and that belongs in the
docs as a deliberate trade rather than something found out afterwards.
`describeCredentialReach()` attributes every server a credential can enumerate to
a project, keeping the owner's boxes and this project's own separate from the
ones nobody asked to reach - only that last number is an argument against
attaching, so collapsing them would bury the point. `formatCredentialReach()`
renders it as sorted plan lines, and stays quiet with a single summary line when
the reach really is just the two projects being joined; a warning that fires
every time is a warning that gets skipped.
Both are pure and structurally typed over `{ name, labels }` rather than a
Hetzner server, so any driver that can enumerate what its credential sees can
report a radius. That is deliberate groundwork for the issue's point that the
driver interface should not assume one all-powerful token is the only shape.
Refs #169, #167
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Addresses #169 (three of its four acceptance criteria; the fourth is called out below).
What was wrong
cloud.attachTofinds the owner's box by listing the provider's servers with the attaching project's own token. That listing is the whole mechanism, and it forces something the config never said: the owner's box must be visible to the attacher's credential, so both projects have to share one provider project. On Hetzner a Cloud API token is project-scoped with Read or Read & Write, has no per-resource scoping, and a deploy needs write.The old docstring said "Requires read access via the same
HCLOUD_TOKEN", which understates it twice: the access needed is write, and the reach is the whole provider project, not the one box.loghqCI reaches theloghqboxloghqCI reachesstatushq,bughq,stacks,localtunnelsbughqCI reaches thebughqboxbughqCI reaches all of the aboveAnd the other half of the same decision, now stated: per-project isolation and attaching are mutually exclusive. An app kept in its own provider project cannot be attached at all, because its token cannot see the owner's box.
What this adds
attachTodocstring now states the radius, the write requirement, and the mutual exclusivity.docs/config.mdsection, "Attaching to another project's server", sinceattachToappeared nowhere indocs/at all.describeCredentialReach()attributes every server a credential can enumerate to a project, keeping the owner's boxes and this project's own separate from the ones nobody asked to reach. Only that last number is an argument against attaching, so collapsing them would bury the point.formatCredentialReach()renders sorted, run-to-run stable plan lines, and stays quiet with one summary line when the reach really is just the two projects being joined. A warning that fires every time is a warning that gets skipped.Both are pure and structurally typed over
{ name, labels }rather than a Hetzner server, so any driver that can enumerate what its credential sees can report a radius.Acceptance criteria
attachTodocuments that it requires the same provider project and what that grantsOn that last box
I did not change the
CloudDriverinterface. Hetzner cannot express a narrower credential at all, so the only honest way to design that seam is against a provider that can (AWS IAM), and guessing the shape from the provider that cannot is how you get an abstraction that fits nobody. Making the reporting provider-agnostic is the part that is useful today and does not need that guess; I would rather leave the interface change to whoever does it against a real second credential model.Verification
loghqtostatushqreports 4 servers reachable that neither project owns4005 pass, 0 fail;typecheckclean;lint0 errors 0 warningsRelated: #168 / #170 covers the port collision on the same shared box.