Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SSH-based auth for llb.Git operations #1782

Merged
merged 4 commits into from
Nov 16, 2020

Conversation

alexcb
Copy link
Collaborator

@alexcb alexcb commented Nov 6, 2020

This PR implements ssh-based authentication for git operations and fixes #1564

It provides the ability to make use of the sshforwarding from the client, and introduces the ability to specify known_host entries.

Here's an example client to illustrate how to use the new Git source options:

alpine := llb.Image("docker.io/library/alpine:latest")

// Example of fetching a git source that is fetched over https (this is existing functionality)
openGitState := llb.Git("github.com/alexcb/acbutils", "master")
openGitMount := llb.AddMount("/git-src", openGitState, llb.Readonly)


// Example of fetching from a non-standard private repo (new functionality)

// step 1, specify the expected entry for known_hosts (can be fetched with ssh-keyscan -t rsa 192.168.0.116 )
myServerKey := "192.168.0.116 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC9aa+HfOctyCxO0ruREnLg4FRTMEdm8zixIDDgzEHBCvOrHnxOjo7UTd7fkOh21sYOT7B8bULEfeDCh5H2fF5yg14XewI/USa6jAx3bjMgT3FwXa7Oi267fNXC6pbTEp/gyWSQcmpQHuOup+MhjoMLhuQv9u8FwE8U6ahvwEoQ6qOLsECSUp6OHTg326bxHsGFAyzi4Cq3a6OxUTb8bhWe56HUxI0h9PgbrnY9FsQzAHjBGp3BPy7rqTW20ON36TOIQsLDoRcLNrP4lz3oBlzCcSgLhkNgpth+FOKw52mveCVs7EnmoI8GLH22hh0BTzhgL9EFG81O5RBIFOmoSFmGKSADVBtI4z4tWxL8zw/gVRY7W+peoVsGGtAx8uFQIGnHFzuBFxCO6gPwGvYUsETNF3bgaBurfceqAOvOEtk0u4N5g5M9pIgfZmpde+Ubh8BIwkYFtoJM6CchO23sZIlVm3o3aoBhJi/MShANS4ckvoEybbugQVdS3ZaRw/8P0ek="

// step 2, specify the git repo to clone, and tell buildkit to make an ssh mount available along 
// with the expected server host key
privateGitState2 := llb.Git("alex@192.168.0.116:my/test/path/testrepo.git", "master",
    llb.MountSSHSock(), llb.KnownSSHHosts(myServerKey))
privateGitMount2 := llb.AddMount("/git-src", privateGitState2, llb.Readonly)

// then add the git source to a Run command:
state := alpine.
    Run(llb.Args([]string{"ls", "/git-src"}), openGitMount).
    Run(llb.Args([]string{"ls", "/git-src"}), privateGitMount).
    Root()

@alexcb alexcb marked this pull request as draft November 9, 2020 18:24
@alexcb alexcb force-pushed the acb-other-git-user branch 2 times, most recently from 7378134 to e186e4a Compare November 10, 2020 23:54
- fixes assumption that ssh git clones must be via the `git` user.
- allows passing the SSH_AUTH_SOCK from the client to GitSource
- allows passing a known_host entry for ssh

Signed-off-by: Alex Couture-Beil <alex@earthly.dev>
@alexcb alexcb changed the title Allow cloning git repo over ssh with non-git username SSH-based auth for llb.Git operations Nov 11, 2020
@alexcb alexcb marked this pull request as ready for review November 11, 2020 04:02
@@ -201,7 +201,7 @@ func Git(remote, ref string, opts ...GitOption) State {
url := ""

for _, prefix := range []string{
"http://", "https://", "git://", "git@",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Without this change, when I do

llb.Git("git@github.com:earthly/earthly.git", "main")

it causes the string to get trimmed into github.com:earthly/earthly.git, which then causes buildkit to attempt to parse the string as if it were a URL (in https://github.com/moby/buildkit/pull/1782/files#diff-dc3734c7af40d455fbd22d64b372bf572aa7314209bafc3d5f1f809203186d6eL27 )

which ultimately gives me the error: failed to load cache key: parse https://github.com:earthly/earthly.git: invalid port ":earthly" after host.

I wonder if there's a way we could reproduce this error via an integration test to show that this fixes the issue? I don't know enough about buildkit's integrating testing to add one (but would be keen on learning with some help).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the reason why AttrFullRemoteURL was added I believe that should be used instead to get this info.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll back out this change, and try using AttrFullRemoteURL in a follow up PR.

Signed-off-by: Alex Couture-Beil <alex@earthly.dev>
"strings"

"github.com/pkg/errors"
)

// sshGitRegexp is used to detect if the git repo uses ssh
// e.g. git@... or otheruser@nonstandardgithost.com:my/really/strange/repo.git
var sshGitRegexp, _ = regexp.Compile("[a-z0-9_]+@[^/]+:.+")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if these changes are related to the rest of the PR. The identifier logic is copied from Docker description https://github.com/moby/moby/blob/master/pkg/urlutil/urlutil.go#L21 and need to be aware of the ambiguity concerns (eg. @ could be valid for HTTP as well) and maybe change docs. I'd rather handle that separately. @thaJeztah

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's correct that it's not related to mounting the ssh socket, i'll back this change out in this PR, then open a new one to tackle the issue of using a non-git username for ssh cloning.

source/git/gitsource.go Show resolved Hide resolved

func MountSSHSock() GitOption {
return gitOptionFunc(func(gi *GitInfo) {
gi.MountSSHSock = true
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be the ssh id, not a bool. If identifier is SSH based it should be set automatically.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

great point, changed this to a string which is now passed from the client.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If identifier is SSH based it should be set automatically.

That part does not look addressed yet.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I missed that part, i'm working on implementing it as well as a ssh keyscan for when no keys are supplied.

@@ -201,7 +201,7 @@ func Git(remote, ref string, opts ...GitOption) State {
url := ""

for _, prefix := range []string{
"http://", "https://", "git://", "git@",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the reason why AttrFullRemoteURL was added I believe that should be used instead to get this info.

source/git/gitsource.go Outdated Show resolved Hide resolved
source/git/gitsource.go Outdated Show resolved Hide resolved
source/git/gitsource.go Outdated Show resolved Hide resolved
 - back out changes to changing the git url
 - fix gid
 - ignore global ssh config option when specifying known hosts

Signed-off-by: Alex Couture-Beil <alex@earthly.dev>
@alexcb alexcb force-pushed the acb-other-git-user branch 4 times, most recently from 402307a to 2596b6f Compare November 13, 2020 03:22
Signed-off-by: Alex Couture-Beil <alex@earthly.dev>
Copy link
Member

@tonistiigi tonistiigi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As discussed in slack, please follow-up with PRs that make the auth default on ssh URL and fix the URL parsing issue you discovered.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Support SSH-based auth for llb.Git operations
3 participants