72 lines
3.5 KiB
Go
72 lines
3.5 KiB
Go
package githubauth
|
|
|
|
import "strings"
|
|
|
|
const (
|
|
CredentialBrokerURLEnv = "KANDEV_GITHUB_CREDENTIAL_BROKER_URL"
|
|
CredentialHelperPathEnv = "KANDEV_GITHUB_CREDENTIAL_HELPER_PATH"
|
|
CredentialCLIShimDirEnv = "KANDEV_GITHUB_CLI_SHIM_DIR"
|
|
CredentialCLIBashEnvEnv = "KANDEV_GITHUB_CLI_BASH_ENV"
|
|
CredentialParentBashEnv = "KANDEV_GITHUB_PARENT_BASH_ENV"
|
|
CredentialLeaseEnv = "KANDEV_GITHUB_CREDENTIAL_LEASE"
|
|
CredentialReissueCapabilityEnv = "KANDEV_GITHUB_CREDENTIAL_REISSUE_CAPABILITY"
|
|
CredentialTaskIDEnv = "KANDEV_GITHUB_CREDENTIAL_TASK_ID"
|
|
CredentialSessionIDEnv = "KANDEV_GITHUB_CREDENTIAL_SESSION_ID"
|
|
CredentialRepositoryEnv = "KANDEV_GITHUB_CREDENTIAL_REPOSITORY_ID"
|
|
CredentialOwnerEnv = "KANDEV_GITHUB_CREDENTIAL_OWNER"
|
|
CredentialRepoEnv = "KANDEV_GITHUB_CREDENTIAL_REPO"
|
|
CredentialHostEnv = "KANDEV_GITHUB_CREDENTIAL_HOST"
|
|
CredentialScopesEnv = "KANDEV_GITHUB_CREDENTIAL_SCOPES"
|
|
|
|
// HostGitHubCredentialHelperMarker identifies helpers generated by the
|
|
// local executor bridge. It is intentionally part of the command value so
|
|
// cleanup can preserve user-owned helpers with the same gh command shape.
|
|
HostGitHubCredentialHelperMarker = "kandev-host-gh-bridge"
|
|
|
|
ManagedGitCredentialHelper = `!"${KANDEV_GITHUB_CREDENTIAL_HELPER_PATH}" git-credential`
|
|
LegacyShimGitCredentialHelper = `!"${KANDEV_GITHUB_CLI_SHIM_DIR}/agentctl" git-credential`
|
|
LegacyGitCredentialHelper = "!agentctl git-credential"
|
|
CLIBashEnvFilename = "bash-env.sh"
|
|
)
|
|
|
|
// CanonicalCredentialPath is the comparison form every side of the credential
|
|
// broker reduces scope paths to: no trailing slashes and no ".git" suffix.
|
|
// Scope paths are derived from clone URLs, which carry the suffix, while the
|
|
// `gh` CLI shim asks for a bare "/<owner>/<repo>" — without one canonical form
|
|
// the two spellings of the same repository never match. Callers pass an already
|
|
// unescaped path; this only normalizes spelling, it does not validate, and it
|
|
// is used only for comparison: a lease scope keeps the exact path its provider
|
|
// resolver was issued for.
|
|
//
|
|
// The function is idempotent. A repository literally named ".git" is not a
|
|
// valid name on GitHub and is unsupported here: "/acme/.git" reduces to
|
|
// "/acme" rather than round-tripping.
|
|
func CanonicalCredentialPath(raw string) string {
|
|
trimmed := strings.TrimRight(strings.TrimSpace(raw), "/")
|
|
if trimmed == "" {
|
|
return strings.TrimSpace(raw)
|
|
}
|
|
if withoutSuffix := strings.TrimRight(strings.TrimSuffix(trimmed, ".git"), "/"); withoutSuffix != "" {
|
|
return withoutSuffix
|
|
}
|
|
return trimmed
|
|
}
|
|
|
|
// IsHostGitHubCredentialHelper reports whether a Git helper command belongs
|
|
// to the local host GitHub bridge. The marker is the ownership boundary;
|
|
// command shape alone is not sufficient because users may select the same gh
|
|
// executable and operation themselves.
|
|
func IsHostGitHubCredentialHelper(value string) bool {
|
|
return strings.Contains(value, ": "+HostGitHubCredentialHelperMarker+";")
|
|
}
|
|
|
|
// IsHostGitHubCredentialHelperEntry reports ownership for a host-scoped
|
|
// credential helper entry. Callers can use it while filtering Git's indexed
|
|
// environment block without removing unrelated hosts or generic helpers.
|
|
func IsHostGitHubCredentialHelperEntry(key, value string) bool {
|
|
key = strings.ToLower(strings.TrimSpace(key))
|
|
return strings.HasPrefix(key, "credential.https://") &&
|
|
strings.HasSuffix(key, ".helper") &&
|
|
IsHostGitHubCredentialHelper(value)
|
|
}
|