Skip to content

Allow entering a bucket name not returned by ListBuckets - #782

Open
kojiwell wants to merge 1 commit into
RCOSDP:developfrom
kojiwell:feature/s3compatsigv4-manual-bucket-name
Open

Allow entering a bucket name not returned by ListBuckets#782
kojiwell wants to merge 1 commit into
RCOSDP:developfrom
kojiwell:feature/s3compatsigv4-manual-bucket-name

Conversation

@kojiwell

@kojiwell kojiwell commented Aug 31, 2026

Copy link
Copy Markdown

Purpose

The bucket picker in the S3 Compatible Storage (SigV4) add-on only offers buckets returned by ListBuckets, and ListBuckets returns only the buckets that the configured credentials own. A bucket shared from another account is therefore impossible to select through the UI, even when the credentials have full access to it.

The save endpoint, however, never cross-checks the submitted name against that listing. set_config in addons/base/generic_views.py passes request.json['selected'] straight to set_folder, and validation consists of bucket_exists() (HeadBucket) and get_bucket_location_or_error() (GetBucketLocation); get_bucket_names() is reached only from get_folders() and is not on the save path. We confirmed this by calling the endpoint directly:

Request to PUT /api/v1/project/<pid>/s3compatsigv4/settings/ Result
{"selected":{"id":"<bucket shared from another account>"}} 200, folder.name = "<bucket> (us-east-1)"
{"selected":{"id":"<bucket owned by the credentials>"}} (positive control) 200
{"selected":{"id":"<name that does not exist>"}} (negative control) 500 InvalidFolderError

The negative control fails, so the success is not validation being bypassed — the bucket is genuinely found reachable. The server already accepts such a bucket; the UI simply has no way to send its name. This PR adds that input path, with no server-side change.

We hit this while testing GakuNin RDM. The test plan calls for a second authorizer accessing the same bucket. On AWS you would add a second IAM user or a second access key for the same identity, and the bucket owner would be unchanged, so the bucket would still be listed. Our S3-compatible storage enforces one key per identity, so the second authorizer had to be an account with a different owner. Cross-owner sharing itself works — a bucket policy grants reads, writes and deletes — and the only remaining obstacle was that the UI could not select the bucket.

Note that this is not specific to any storage vendor: ListBuckets returning owned buckets only is the same on AWS S3, so the identical configuration on AWS is equally unselectable today.

Changes

Four files, +50 / −0 — purely additive. No server-side code, no model or API change, and the base ViewModel (website/static/js/folderPickerNodeConfig.js) is untouched.

  • addons/s3compatsigv4/static/s3compatsigv4NodeConfig.js — adds useManualBucketName and manualBucketName observables, and wraps onPickFolder.
  • addons/s3compatsigv4/templates/s3compatsigv4_node_settings.mako — adds a checkbox below the bucket grid that reveals a text input.
  • addons/translations/en/LC_MESSAGES/messages.po — new msgid Enter bucket name.
  • addons/translations/ja/LC_MESSAGES/messages.po — Japanese translation バケット名を入力.

Behaviour:

  • The typed name is written into the existing selected observable as {id, name, path}, so it reuses the current submission path unchanged — _serializeSettings() is ko.toJS(this) and sends the whole ViewModel, exactly as a grid selection does.
  • While the field is empty, selected is left null. The confirmation block and its Save button are already bound to visible: currentDisplay() == PICKER && selected(), so the Save button simply does not render until a name is typed. No separate disable logic was needed.
  • Picking a bucket from the grid clears the checkbox, so the two inputs stay mutually exclusive.
  • The grid itself and the Treebeard configuration are not modified. We deliberately avoided injecting a synthetic row into the grid data, which would have required changes to the rendering logic.

Screenshots

The grid lists only rdm-exatest2, the bucket these credentials own. The bucket shared from the other account, rdm-test, is absent — this is the problem. The new checkbox is shown unticked, and with nothing selected there is no Save button:

proposal_ui_1_picker

Ticked and filled in. The existing confirmation block and Save button appear, exactly as they would for a bucket picked from the grid:

proposal_ui_3_typed

Saved:

proposal_ui_4_saved

QA Notes

  • Does this change require a data migration? No. Nothing about the stored NodeSettings changes — a manually named bucket is persisted exactly the same way a picked one is.

  • Level of risk: low. The diff is additive only (+50 / −0). No permissions code is touched, and no server-side, model, or API code is touched. The only change to the pre-existing path is that picking a bucket from the grid now additionally sets useManualBucketName(false); with the checkbox left unticked, the pane behaves as it does today.

  • How can QA verify? Through the UI: a project's Add-onsS3 Compatible Storage (SigV4)Change.

    Quick check — needs only one ordinary S3 account:

    1. Tick Enter bucket name. A text field appears and no Save button is shown.
    2. Type the name of a bucket that is listed in the grid. Connect "<name>"? and the Save button appear; saving succeeds exactly as picking the row does.
    3. Type a name that does not exist and save. The save is rejected (InvalidFolderError) and the existing setting is unchanged.
    4. Tick the box, type something, then click a row in the grid. The checkbox clears, the field disappears, and the row selection takes effect.

    Full scenario — needs two S3 accounts with different owners:

    1. Account A creates bucket X and puts an object in it.
    2. Grant account B access to X with a bucket policy.
    3. Connect the add-on with account B's credentials. X does not appear in the grid — this is the problem being fixed.
    4. Tick Enter bucket name, type X, and save. The save succeeds.
    5. The Files tab shows X and A's object; upload, download and delete work as far as the policy allows.
  • What features or workflows might this change impact? Only the bucket selection pane of this add-on. The Files tab, WaterButler, and the stored settings are unaffected.

  • How will this impact performance? Not at all. No new requests are issued; the HeadBucket / GetBucketLocation validation already ran on save.

  • Tests. No unit test is included. This repository has no per-provider ViewModel test suite — website/static/js/tests/addons/ covers the base classes (folderPickerNodeConfig, oauthAddonNodeConfig, …) but no provider-specific config — so there was no existing suite to extend. We are happy to add one if you would like, and glad to follow a pattern you prefer.

Documentation

No API change and no API versioning, so no developer.osf.io changelog entry is needed.

The change introduces one new user-facing string, and the Japanese translation is included in this PR. If there is user-facing documentation describing the bucket selection pane, it may be worth a line about the new option — please point us at it and we will propose the wording.

Side Effects

None known.

The one behavioural change to the pre-existing path is that choosing a bucket from the grid now also clears the checkbox, which is required for the two inputs to be mutually exclusive.

Worth stating explicitly: this change makes a bucket selectable; it does not grant any permission. Using a bucket shared from another account still requires a grant on the storage side. The change cannot widen access — the same HeadBucket and GetBucketLocation validation applies to a typed name as to a picked one, and both run with the credentials the user already supplied.

Related providers (not included)

Three other providers use the same picker structure and would take the identical change:

Provider Files
Amazon S3 addons/s3/static/s3NodeConfig.js, addons/s3/templates/s3_node_settings.mako
S3 Compatible Storage addons/s3compat/static/s3compatNodeConfig.js, addons/s3compat/templates/s3compat_node_settings.mako
Oracle Cloud Infrastructure addons/s3compatb3/static/s3compatb3NodeConfig.js, addons/s3compatb3/templates/s3compatb3_node_settings.mako

(s3compatinstitutions is not applicable — it has no node-level picker and is configured from the admin console.)

We limited this PR to s3compatsigv4 because the back ends for the others are not available in our test environment and we could not exercise the change against them. We would rather demonstrate it on one provider than ship edits we have not run. If you would like the other three included, please let us know and we will add them to this PR.

Ticket

None. This is an external contribution, arising from GakuNin RDM interoperability testing rather than from a tracked ticket.

The bucket picker only offers buckets from ListBuckets, which returns
only the buckets the credentials own. A bucket shared from another
account is therefore unselectable even when it is fully accessible.

The save endpoint does not cross-check that listing -- it validates with
HeadBucket and GetBucketLocation -- so it already accepts such a bucket.
Add a checkbox below the grid that reveals a text field and writes the
typed name into the existing `selected` observable, reusing the current
submission path. While the field is empty `selected` stays null, so the
Save button remains hidden.

Scope is limited to s3compatsigv4. s3, s3compat and s3compatb3 share the
same picker structure and could take the same change.
@hide24
hide24 removed the request for review from tishin-endou September 7, 2026 00:53
@hide24
hide24 requested a review from tishin-endou September 7, 2026 00:54

@yacchin1205 yacchin1205 left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

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.

3 participants