fix(providers): allow git clone/fetch via default GitHub provider#2317
fix(providers): allow git clone/fetch via default GitHub provider#2317russellb wants to merge 4 commits into
Conversation
The github.com:443 git-transport endpoint used the read-only access preset, which expands to GET/HEAD/OPTIONS only. Git smart HTTP requires a POST to */git-upload-pack for clone and fetch, so the L7 proxy denied those operations and `gh repo clone` / `git clone https://...` failed. Replace the preset with explicit rules that permit the read-only methods plus POST */git-upload-pack, so clone/fetch work while push (git-receive-pack) stays blocked. Enabling push still requires an explicit policy proposal. Why allowing this POST is still read-only: in git's smart HTTP protocol POST is an RPC transport, not a write. A clone/fetch does GET */info/refs (ref discovery) followed by POST */git-upload-pack, whose body is only the client's want/have negotiation; the server responds with a packfile and nothing on the server is modified (data flows server -> client). The service names are from the server's perspective: git-upload-pack = the server uploads a pack to the client (a read/ download), while git-receive-pack = the server receives a pack from the client (the actual write/push). The new rule is scoped to */git-upload-pack only, so push (git-receive-pack) and arbitrary POSTs to github.com remain denied. Add a provider-profile regression test and a rego enforcement test covering ref discovery, upload-pack (allowed), and receive-pack (denied). Closes NVIDIA#1769 Signed-off-by: Russell Bryant <rbryant@redhat.com>
|
Thanks @russellb lgtm at first glance. Having Gator do its thing anyway. |
PR Review StatusValidation: This PR directly implements confirmed bug #1769 with a concentrated Provider V2/L7 policy change. The proposed Head SHA: Thanks @johntmyers. I checked the implementation beyond your first-glance LGTM, including canonical path handling, OPA matching, provider-policy composition, and the existing Fern guidance. Three author changes remain:
Docs: Missing for this direct user-visible default-provider behavior change. Next state: |
Pin the exact allowed rule set for the built-in github git-transport endpoint in both the provider-profile and composed-policy tests, so a broader or additional POST rule (e.g. POST **) that could enable push via git-receive-pack fails the test instead of passing a substring check. Add an e2e test that attaches the built-in github provider and clones a public repo over HTTPS, exercising provider attachment, effective-policy composition, TLS interception, and real git behavior. Update the Providers V2 docs so the github.com git-transport endpoint shows explicit clone/fetch rules instead of the stale read-only preset. Refs NVIDIA#1769 Signed-off-by: Russell Bryant <rbryant@redhat.com>
|
Pushed afb0205 addressing the three items. 1. Exact rule-set regression. 2. Real clone/fetch e2e. Added 3. Docs. Updated |
johntmyers
left a comment
There was a problem hiding this comment.
gator-agent
PR Review Status
Validation: This PR remains project-valid because it directly fixes confirmed Provider V2/L7 bug #1769 while keeping Git push denied by default.
Head SHA: afb0205f6978abca804e2951b18fba065ee9d21a
Thanks @russellb. I verified the three updates you described: the profile and composed-policy tests now pin the exact allow set, the new E2E attaches the built-in GitHub provider and performs a real HTTPS clone, and the existing Fern provider page now explains clone/fetch versus push. Those prior requests are resolved.
Review findings:
- One blocking E2E isolation issue remains in the inline review: the helper deletes a gateway-global setting without preserving its prior state and without guarding concurrent workers.
Docs: Updated in docs/sandboxes/providers-v2.mdx; no navigation change is needed because the page is already under the existing sandboxes navigation folder.
Next state: gator:in-review. Please restore the setting's exact prior value/presence and serialize this gateway-global mutation, then push a new head for re-review.
| stub.UpdateConfig( | ||
| openshell_pb2.UpdateConfigRequest( | ||
| setting_key="providers_v2_enabled", | ||
| delete_setting=True, |
There was a problem hiding this comment.
gator-agent
Warning: This unconditionally deletes the gateway-global providers_v2_enabled setting. When E2E targets an existing or shared gateway where the setting was explicitly true or false, this leaves the gateway altered and can affect concurrent or subsequent tests. Read the prior state with GetGatewayConfig, restore its exact value or absence in finally, and ensure this gateway-global mutation cannot race parallel E2E workers (for example, with a serialized suite fixture or a dedicated gateway).
There was a problem hiding this comment.
Fixed in dc397b8. _providers_v2_enabled is now a fixture that:
- Reads prior state via
GetGatewayConfigand restores the exact value or absence infinally.GetGatewayConfigreturns known keys even when unset (emptySettingValue), so it treats the setting as present only when the value oneof is actually set; on a gateway where it was unset, teardown deletes it rather than leaving it altered. - Serializes the gateway-global mutation across xdist workers with an exclusive
fcntl.flockon the run's shared base temp dir (getbasetemp().parent), held for the whole test so the read-modify-restore can't interleave.
Verified green end-to-end (clone + clean teardown) against an ephemeral Podman-backed gateway.
The clone e2e enables the gateway-global providers_v2_enabled setting. Restore its exact prior value (or absence) captured via GetGatewayConfig instead of unconditionally deleting it, and serialize the mutation across xdist workers with an exclusive file lock on the run's shared base temp dir, so a shared or pre-configured gateway is left untouched and parallel workers cannot race the read-modify-restore. Refs NVIDIA#1769 Signed-off-by: Russell Bryant <rbryant@redhat.com>
johntmyers
left a comment
There was a problem hiding this comment.
gator-agent
PR Review Status
Validation: This PR remains project-valid because it fixes confirmed Provider V2/L7 bug #1769 with a narrow smart-HTTP upload-pack rule while keeping push and arbitrary POSTs denied.
Head SHA: dc397b892cd00b890aec3a4f9aa7cb3dc257a7bf
Thanks @russellb. I checked the isolation update you described. Reading GetGatewayConfig and restoring the exact prior value or absence resolves the state-restoration half of the prior finding. The remaining concurrency issue is in the inline review: the advisory lock is acquired only by this fixture, while other xdist workers use the same gateway without acquiring it and can observe the temporary global setting.
Review findings:
- One blocking E2E isolation finding remains in the batched inline review.
Security: The exact provider/composed-policy assertions and OPA coverage preserve default deny: git-upload-pack is allowed, while git-receive-pack and unrelated POSTs remain denied. Credential handling is unchanged.
Docs: Updated in docs/sandboxes/providers-v2.mdx; no navigation change is needed because the existing folder navigation already includes this page.
Next state: gator:in-review. Please use a suite-wide shared/exclusive gateway-config guard or run this test against an isolated gateway/serial phase, then push a new head for re-review.
| key = "providers_v2_enabled" | ||
| lock_path = tmp_path_factory.getbasetemp().parent / "providers-v2-setting.lock" | ||
| with lock_path.open("w") as lock_file: | ||
| fcntl.flock(lock_file, fcntl.LOCK_EX) |
There was a problem hiding this comment.
gator-agent
Warning (CWE-362): This lock only coordinates tests that acquire the same lock, but no other xdist tests do. Every worker connects to the same gateway, so another worker can create a provider-attached sandbox while providers_v2_enabled is transiently true and receive a different effective policy; a concurrent external change can also be overwritten during restoration. Please use a suite-wide autouse shared/exclusive gateway-config guard, or run this test against an isolated gateway/serial phase. The exact prior-value restoration here is otherwise correct.
There was a problem hiding this comment.
Fixed in b1d100b. Replaced the per-fixture lock with a suite-wide readers-writer guard so the exclusivity actually covers other workers:
- New autouse
_gateway_config_guardine2e/python/conftest.py: every test takes a sharedflockon a gateway-config lock file in the run's shared base temp dir; a test markedexclusive_gateway_configtakes an exclusive lock instead. - The clone test is marked
exclusive_gateway_config, so while it enables and restoresproviders_v2_enabledno other xdist worker is mid-test — none can create a sandbox and observe the transient global.providers_v2_enableddepends on the guard so the exclusive lock is held before the mutation. - Exact prior-value/absence restoration via
GetGatewayConfigis retained.
Deadlock isn't possible by construction (one lock per test, always released at test end, no nesting). Verified green against an ephemeral Podman gateway: the exclusive clone test passes, and the shared-lock path runs without guard error on the other provider tests.
The clone e2e's per-fixture lock only coordinated fixtures that acquired it; other xdist workers hit the same gateway without it and could observe the transiently-enabled providers_v2_enabled global during their own sandbox creation (CWE-362). Add an autouse readers-writer guard in conftest: every test holds a shared lock on the gateway config, and a test marked exclusive_gateway_config holds an exclusive lock. Mark the clone test exclusive so no other worker is mid-test while it enables and restores the gateway-global setting. Exact prior-value restoration is retained. Refs NVIDIA#1769 Signed-off-by: Russell Bryant <rbryant@redhat.com>
Summary
The default GitHub provider blocked
gh repo clone/git clone https://…inside sandboxes. This makes clone/fetch work while keeping push blocked by default.Related Issue
Closes #1769
Changes
providers/github.yaml: replace theaccess: read-onlypreset on thegithub.com:443git-transport endpoint with explicit rules —GET/HEAD/OPTIONS **plusPOST /**/git-upload-pack. The read-only preset only expands toGET/HEAD/OPTIONS, but git smart HTTP needsPOSTto*/git-upload-packfor clone/fetch.git-receive-pack) stays denied; enabling it still requires an explicit policy proposal. The twoapi.github.comREST/GraphQL endpoints remainread-only.openshell-providers) and a rego enforcement test (openshell-supervisor-network) covering ref discovery,git-upload-pack(allowed), andgit-receive-pack(denied); update the two existing tests that asserted "all github endpoints read-only".Why allowing this POST is still read-only
In git's smart HTTP protocol,
POSTis an RPC transport, not a write. A clone/fetch isGET */info/refs(ref discovery) followed byPOST */git-upload-pack, whose body is only the client's want/have negotiation; the server replies with a packfile and nothing on the server is modified (data flows server → client). The service names are from the server's perspective:git-upload-pack= the server uploads a pack to the client (a read/download), whilegit-receive-pack= the server receives a pack from the client (the actual write/push). The new rule is scoped to*/git-upload-packonly, so push and arbitrary POSTs togithub.comremain denied.Testing
openshell-providers,openshell-supervisor-network, andopenshell-servertargeted tests pass (new + updated regression tests green)Checklist