oxidecomputer / oxidecomputer/omicron

instance create sagas look up multiple things by name multiple times

Open
#1,536 3 comments 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

security
Dominant language
Rust
Stars
572
Forks
97
Avg merge
2d 12h
Merged PRs (30d)
96

Description

There are three places in the instance-create saga where we look up things by name well into the saga:

  1. Towards the end, when we go to attach disks (or detach them, during undo), we use Nexus::instance_attach_disk()/Nexus::instance_detach_disk() and pass along the organization_name, project_name, instance_name, and disk_name from the instance create request. This causes a new lookup of the organization/project/instance/disk path. That seems bad: there's no guarantee that it will find the same disk (or instance or project or organization, for that matter). So we might attach or detach the wrong disk, or we might fail spuriously.
  2. At the end, during instance_ensure(), we look up the instance by name in order to call Nexus::instance_set_runtime(). This could find a different instance than the one we created. We should be able to use the instance_id stored from a previous action instead.
  3. In sic_delete_instance_record, the undo action for the (early) create-instance-record action, we look up the instance name that we created. We should use the instance id instead.

RFD 192 talks about this:

When Nexus receives an API request, we’ll usually want to resolve the name to an id up front and do most internal work using ids. Otherwise, we can wind up with nasty concurrency issues (i.e., serializability violations) if somebody renames a resource while we’re working on it. This can lead to security vulnerabilities, if we were to do an access check of some resource and then somebody renames it and we wind up operating on a different resource than the one we checked.

In terms of fixing: my first thought here is to do the lookup of organization and project once early in the saga to get the project_id. Then (again, still early in the saga) look up anything else we need (like all the disks) using LookupPath(...).project_id(...).disk_name(...) and store their ids. Thereafter, we can always use the ids.

We'll probably want to change Nexus::instance_attach_disk() and Nexus::instance_detach_disk() to accept an authz::Instance and authz::Disk (and have the lookups done in the caller).

Then I think we can remove the "instance_name" output from any saga action (so we're not ever tempted to use the instance name). We can also remove organization_name and project_name from the Params (for the same reason).

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the instance-create saga and the three paths described: disk attach/detach, instance_ensure, and sic_delete_instance_record. Read RFD 192 alongside Nexus::instance_attach_disk(), Nexus::instance_detach_disk(), and the relevant saga actions. Done means lookups occur early, later operations use stored ids, and name fields and Params entries identified for removal are no longer used.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
api, backend
Issue type
Refactor
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.