Documentation
¶
Overview ¶
Package forgekit is what source adapters share: reading a repository address in each of the forms people write one, deciding whether a connection covers it, and building the credential core clones with.
Not an adapter. Each forge's own package decides what its addresses look like and what it calls the parts; this package only does the parsing and the arithmetic they would otherwise each repeat.
Index ¶
- Constants
- func APIURLField(def string) api.Field
- func CABundle(pem string) ([]byte, error)
- func CAField() api.Field
- func CheckKnownHosts(text string) error
- func CheckSSHKey(key, passphrase secret.Value) error
- func Covers(hosts []string, scope []string, repoHost string, path []string) int
- func Decode(raw json.RawMessage, into any) error
- func HTTPClient(caBundle []byte) *http.Client
- func HTTPSURL(host, port, path string) string
- func HostField(def string) api.Field
- func HostOf(setting string) string
- func Limit(n int) int
- func Matches(fullName, query string) bool
- func MethodField(options ...api.Option) api.Field
- func NextLink(header string) string
- func OAuthFields(help string) []api.Field
- func SCPURL(user, host, port, path string) string
- func SSHCredential(repo RepoURL, sshHost string, key, passphrase secret.Value, knownHosts string) api.GitCredential
- func SSHFields(knownHostsHelp string) []api.Field
- func ScopeField(label, help, placeholder string) api.Field
- func ScopeSegments(scope string) []string
- func StatusError(provider string, status int) error
- func TokenCredential(username string, token secret.Value, caBundle []byte) api.GitCredential
- func TokenField(label, help string, shown ...string) api.Field
- func UsernameField(help, placeholder string, shown ...string) api.Field
- type Client
- type OAuth
- func (o OAuth) BeginDevice(ctx context.Context, now time.Time) (api.Authorization, error)
- func (o OAuth) BeginWeb(req api.AuthorizationRequest, extra url.Values) (api.Authorization, error)
- func (o OAuth) CompleteWeb(ctx context.Context, req api.AuthorizationCompletion, now time.Time) (api.AuthorizationResult, error)
- func (o OAuth) Fresh(ctx context.Context, t Tokens, now time.Time) (Tokens, bool, error)
- func (o OAuth) PollDevice(ctx context.Context, flow secret.Value, now time.Time) (api.AuthorizationResult, error)
- type RepoURL
- type Settings
- type Tokens
Constants ¶
const ( FieldAccessToken = "access_token" FieldRefreshToken = "refresh_token" FieldTokenExpiresAt = "token_expires_at" )
The credential fields an oauth connection keeps, written by core from an AuthorizationResult or a GitCredential.Rotated and handed back in Configure.
const ( MethodToken = "token" MethodSSH = "ssh" MethodApp = "app" MethodOAuth = "oauth" MethodServicePrincipal = "service_principal" )
The methods a connection can authenticate with (api.SourceCapabilities.Method).
const ( FieldToken = "token" FieldSSHPrivateKey = "ssh_private_key" FieldSSHPassphrase = "ssh_passphrase" FieldClientSecret = "client_secret" )
The credential fields the shared methods use. A forge adds its own beside them (a GitHub App's private key).
Variables ¶
This section is empty.
Functions ¶
func APIURLField ¶
func CABundle ¶
CABundle reads a PEM bundle setting and refuses one with no certificate in it. Empty is fine: the system's roots alone.
func CheckKnownHosts ¶
CheckKnownHosts refuses known_hosts text that pins nothing. An SSH connection without a pinned host key would trust whoever answers, which is how a network attacker reads the repository (api.GitCredential.KnownHosts).
func CheckSSHKey ¶
CheckSSHKey refuses a private key Pando cannot use, at configuration rather than at the first deploy. Nothing about the key is put in the error.
func Covers ¶
Covers scores how specifically a connection for host, limited to scope, covers a repository path. Zero is not at all. One is the whole host; each scope segment that matches adds one, so the narrowest connection wins (api.SourceAdapter.Covers). Names are compared without case, as every forge Pando knows treats owner names.
hosts lists every host the connection answers for — "dev.azure.com" and "ssh.dev.azure.com" are one Azure DevOps — and path is the repository path with any host-specific prefix already removed by the caller.
func Decode ¶
func Decode(raw json.RawMessage, into any) error
Decode reads raw configuration into a forge's settings struct, which embeds Settings.
func HTTPClient ¶
HTTPClient is a client for a forge's API that trusts caBundle beside the system's roots.
func HostOf ¶
HostOf reads the host out of a host setting, which people write as "github.com", "https://gitlab.acme.internal" or "gitlab.acme.internal:8443". The port is dropped: a connection is for a host, whichever port it is reached on.
func Matches ¶
Matches reports whether a repository's full name matches a listing query: every word in the query appears in it, without case.
func NextLink ¶
NextLink reads the rel="next" address out of a Link header. The address may itself hold commas — ?affiliation=owner,collaborator — so the header is read entry by entry from each "<", never split on ",".
func OAuthFields ¶
OAuthFields are the OAuth application's client ID and secret.
func SCPURL ¶
SCPURL is the scp-like SSH address of a repository on host at path, for the default port. With a port it is the ssh:// form, which is the only one that can carry one.
func SSHCredential ¶
func SSHCredential(repo RepoURL, sshHost string, key, passphrase secret.Value, knownHosts string) api.GitCredential
SSHCredential is an SSH key, for the repository at repoURL. An HTTPS address is turned into the SSH one for the same path on sshHost, since a deploy key cannot be used over HTTPS; sshHost is the host's own when empty.
func ScopeField ¶
func ScopeSegments ¶
ScopeSegments splits a scope setting — "acme", "acme/platform", "acme/Payments" — into its parts, ignoring slashes at either end.
func StatusError ¶
StatusError turns a forge's HTTP status into a message a person can act on (R-105), or nil for a success.
A forge refusing the connection's credential is an adapter failure, never AUTH_* or PERM_*: those are answered 401 and 403, which say the person calling Pando is not signed in or not allowed, and a client acts on that.
func TokenCredential ¶
TokenCredential is HTTPS basic authentication with a token as the password.
Types ¶
type Client ¶
type Client struct {
HTTP *http.Client
// Provider names the forge in messages.
Provider string
// Authorize sets the request's credentials.
Authorize func(*http.Request)
}
Client calls a forge's JSON API.
type OAuth ¶
type OAuth struct {
// Provider names the provider in messages: "GitHub", "GitLab".
Provider string
ClientID string
ClientSecret secret.Value
// DeviceURL is the device authorization endpoint (RFC 8628). Empty when
// the provider has none.
DeviceURL string
// AuthorizeURL and TokenURL are the authorization code endpoints.
AuthorizeURL string
TokenURL string
Scopes []string
// BasicClientAuth sends the client ID and secret as HTTP basic
// authentication to the token endpoint rather than in the form, for a
// provider that accepts only that (Bitbucket Cloud).
BasicClientAuth bool
// HTTP is the client to call the provider with.
HTTP *http.Client
}
OAuth is one provider's OAuth 2.0 endpoints and client.
func (OAuth) BeginDevice ¶
BeginDevice starts a device authorization.
func (OAuth) BeginWeb ¶
func (o OAuth) BeginWeb(req api.AuthorizationRequest, extra url.Values) (api.Authorization, error)
BeginWeb makes the URL to send the person's browser to, with a PKCE challenge whose verifier is the flow core keeps.
func (OAuth) CompleteWeb ¶
func (o OAuth) CompleteWeb(ctx context.Context, req api.AuthorizationCompletion, now time.Time) (api.AuthorizationResult, error)
CompleteWeb exchanges the code the callback received.
type RepoURL ¶
type RepoURL struct {
// SSH says the address is an SSH one: ssh://host/path or git@host:path.
SSH bool
// Host is the host name, lowercased, without a port.
Host string
// Port is the port, if one was written.
Port string
// User is the user in an SSH address, usually "git".
User string
// Path is the repository's path on the host with no leading slash and no
// trailing ".git": "acme/api", "acme/platform/api",
// "v3/acme/Payments/api" for an Azure DevOps SSH address.
Path string
}
RepoURL is a repository address, read.
func ParseRepoURL ¶
ParseRepoURL reads https://host/owner/repo(.git), ssh://user@host[:port]/owner/repo(.git) and the scp-like user@host:owner/repo(.git).
type Settings ¶
type Settings struct {
Method string `json:"method"`
// Host is the forge's host: "github.com", "gitlab.acme.internal".
Host string `json:"host"`
// Scope limits the connection to an owner, group, workspace or project
// on the host. Empty is the whole host.
Scope string `json:"scope"`
// APIURL overrides where the forge's API is, for a self-managed one
// whose API is not where the forge's default says.
APIURL string `json:"api_url"`
// Username goes beside a token, for hosts that want one.
Username string `json:"username"`
KnownHosts string `json:"known_hosts"`
CABundle string `json:"ca_bundle"`
ClientID string `json:"client_id"`
// Credentials are filled in by core from adapter_credentials (O-20);
// never stored in config.
Credentials map[string]secret.Value `json:"credentials"`
}
Settings are the settings every source adapter shares. A forge's own settings struct embeds it.
func (Settings) Credential ¶
Credential is one credential field, or the zero value.
type Tokens ¶
Tokens is what an oauth connection was configured with.
func TokensFrom ¶
TokensFrom reads the stored token fields out of a connection's credentials.