foxygoat / git-scripts

0 stars 1 forks source link

Create credential helper for github orgs #3

Closed camh- closed 4 years ago

camh- commented 4 years ago

Credential helpers provide authentication credentials for a credential context. A credential context is a host or repository specified in a git config file that says what username to use for that context - host or repository. However the man page for gitcredentials(1) says under the CREDENTIAL CONTEXTS section:

If the "pattern" URL does include a path component, then this too must match exactly [...] https://example.com/bar/baz.git [...] will not match a config entry for https://example.com/bar

When we use GitHub we often want to to this because https://example.com/bar is really https://github.com/org. We may use different accounts for different organisations so we want to select credentials with a context of a subpath of a repository, which is explicitly not supported.

We can get around this by writing a credential helper (see git-credential(1)) that reads the host and path and then successively looks up shorter paths in the git config until it finds a matching context, and then chains to another git-credential helper substituting the username found in that context.

For store and erase operations, we can pass straight through to the chained helper. For get operations, we'll need to do this lookup.

A sample git config fragment for how this would work:

[credential]
    helper = subpath store
[credential "https://github.com/org1"]
    username = org1-username
[credential "https://github.com/org2"]
    username = org2-username
[credential "https://github.com/"]
    username = public-username

This assumes the credential helper is called subpath (git-credential-subpath as a program on the path), and you would normally use the store credential helper.

If the repository https://github.com/org1/repo1 were being used, the credential context would be https://github.com/ as per git's built-in rules. When the subpath helper is called, it would look at the git config for https://github.com/org1 (stripping /repo from the path) to see if that exist. If it does, it takes the username from the config. If not, it keep stripping each component of the path until there are none left. If no matches at all, it just passes through the original request to the chained helper.

camh- commented 4 years ago

This has been done in https://github.com/foxygoat/git-scripts/pull/5