gitproxycreds

package
v0.0.7 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 27, 2026 License: MIT Imports: 9 Imported by: 0

Documentation

Overview

Package gitproxycreds interposes a git interception proxy between a sandbox and the forge.

It decorates an executor.WorkspaceCredentialSource. The inner source leases the forge credential exactly as before; this one keeps that credential on the hub, mints a pkg/gitproxy session against it, and hands the sandbox a session token plus a rewritten repository URL. The sandbox's git then talks to the proxy, and the proxy decides — per ref, on the push's own command list — whether an update is inside the branch allowlist.

What changes for the sandbox

Nothing it can observe except the URL. The credential is still delivered as an HTTP basic header scoped to the repository's origin by executor.GitCredentialEnv, still never written to disk and never placed in an argv. Because the proxy's URL preserves the "owner/name" path (gitproxy.Minted.RepoURL), executor.Workspace.RepoPath keeps returning the same value, so grant matching and every audit row that names a repository are unaffected.

Why the decorator, and not a flag on the inner source

Interception is a property of the deployment, not of a grant: the same GitHub grant is correct whether or not a hub routes through a proxy. Wrapping keeps pkg/executor/gitcreds solely about "which grant authorises this repository" and leaves "and how does the sandbox reach it" here, where an operator turns it on and off.

What a leaked token is worth

The session token is worth the policy below, until its run is done with it, against one repository, through one proxy: push to refs/heads/cloop/**, create and update only, and fetch. It is worth nothing against github.com directly. The PAT it stands in for is worth every repository the token is scoped to, in every direction, from anywhere, until someone revokes it.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Refusing added in v0.0.5

func Refusing(reason string) executor.WorkspaceCredentialSource

Refusing returns a source that refuses every workspace with executor.ErrWorkspaceUnavailable, saying why.

It is what a process whose configuration asks for the git proxy puts in front of a driver when that process cannot route through one — the proxy failed to start in `cloop ui`, or the process is not `cloop ui` at all and so never runs one (Task 20349). Handing the undecorated source back instead would deliver the forge credential into every sandbox while the configuration says it cannot happen.

It refuses rather than standing in for "no source" because the two read differently downstream: no source means "this hub has no broker", whose remedy is a grant, while this means "the proxy the operator configured is not in the path", whose remedy is the proxy.

Types

type HeldSource added in v0.0.3

type HeldSource interface {
	ForProxiedWorkspace(ctx context.Context, projectID string, w executor.Workspace) (executor.WorkspaceAccess, func(), error)
}

HeldSource is implemented by an inner source that can lease a credential knowing a git proxy, not the executor, will hold it. gitcreds.BrokerSource does; see its ForProxiedWorkspace for what that changes.

Discovered by type assertion rather than added to executor.WorkspaceCredentialSource, because only this decorator has anything to say through it and every other implementation — the fakes in driver tests included — would otherwise have to grow a method that means nothing to them.

type RecordedSource added in v0.0.5

type RecordedSource interface {
	LeasesRecorded() bool
}

RecordedSource is implemented by an inner source whose leases are recorded durably, so a hub process other than the one that issued one can take it over (Task 20390). Only a session standing on such a lease is minted Durable: a record of one standing on a lease nobody can take over would be a record nothing could restore.

Discovered by type assertion for the reason HeldSource is.

type RefreshingSource added in v0.0.5

type RefreshingSource interface {
	// RefreshWorkspaceCredential renews cred, whose password the session
	// presents as held. It returns the renewed credential and the function
	// that ends the one it replaced; an error wrapping
	// executor.ErrCredentialRefused is final.
	RefreshWorkspaceCredential(ctx context.Context, cred executor.GitCredential, held string) (executor.GitCredential, func(), error)
}

RefreshingSource is implemented by an inner source whose credentials expire on a clock the hub knows and can be re-minted before they do — gitcreds.BrokerSource, for a GitHub App grant (Task 20375).

Discovered by type assertion for the reason HeldSource is.

type Source

type Source struct {
	// Inner leases the real forge credential. Required.
	Inner executor.WorkspaceCredentialSource
	// Registry mints the sessions. Required, and must be the same registry the
	// running proxy authenticates against — sessions live in its memory, so a
	// registry in another process could not authenticate what this one mints.
	Registry *gitproxy.Registry
	// Policy is applied to every session. The zero value means
	// WriteBackPolicy plus fetch; see New.
	Policy gitproxy.Policy
	// TTL bounds a session. Zero means gitproxy.DefaultSessionTTL.
	TTL time.Duration
	// ExecutorID is the executor sessions are minted for, recorded on the
	// audit row so a proxy event can be joined to a dispatch.
	ExecutorID string
	// Actor is the audit identity recorded on the mint.
	Actor string
	// RenewEvery overrides how often a session a driver still holds is
	// looked at for renewal. Zero is gitproxy.RenewTick of TTL; tests
	// shorten it.
	RenewEvery time.Duration
}

Source is an executor.WorkspaceCredentialSource that routes through a proxy.

func New

func New(inner executor.WorkspaceCredentialSource, reg *gitproxy.Registry, policy gitproxy.Policy,
	ttl time.Duration, executorID, actor string) (*Source, error)

New returns a source that routes w through reg, or an error when it would be unusable.

The default policy is WriteBackPolicy with fetch added: create and update under refs/heads/cloop/**, no deletes, and the read half a provisioning fetch needs. Fetch is on because with a proxy interposed the *clone* also goes through it — that is the point, since it is what keeps the forge credential off the sandbox for both halves of the round trip.

func (*Source) ForWorkspace

func (s *Source) ForWorkspace(ctx context.Context, projectID string, w executor.Workspace) (executor.WorkspaceAccess, func(), error)

ForWorkspace implements executor.WorkspaceCredentialSource.

The inner lease — the forge credential the hub holds — lives as long as the session, and is released when the session ends: closed, reaped after its TTL, or closed with the hub. It used to be released when the driver was done delivering, which for a github_app grant destroyed the installation token at GitHub while the session went on presenting it upstream: every later git operation through the session met a dead token, and on Kubernetes, which delivers before the init container fetches, the fetch itself did (Task 20349).

The release function handed to the driver is therefore about the *session*. It is always non-nil, and it ends the session — which releases the inner lease with it — whether or not the sandbox used it (Task 20422). A driver calls it when it is done with the credential: once the fetch is over for a run that pushes nothing back, and once the workload is terminal and its write-back has run or been abandoned for one that does — the remote driver parks it on the handle until then, the Kubernetes driver keeps it with the workspace Secret. A session the sandbox had used used to keep its TTL after that, 60 minutes by default and up to 12 hours, for anything that had lifted its token out of the sandbox to use. A run longer than the TTL keeps its session through the hub renewing it while the run lives (Registry.Renew), not through a longer TTL.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL