Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions docs/spec.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -1680,6 +1680,16 @@
"boolean"
]
},
"sshKnownHosts": {
"items": {
"type": [
"string"
]
},
"type": [
"array"
]
},
"url": {
"type": [
"string"
Expand Down
16 changes: 11 additions & 5 deletions source_git.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,11 @@ import (
)

type SourceGit struct {
URL string `yaml:"url" json:"url"`
Commit string `yaml:"commit" json:"commit"`
KeepGitDir bool `yaml:"keepGitDir,omitempty" json:"keepGitDir,omitempty"`
Auth GitAuth `yaml:"auth,omitempty" json:"auth,omitempty"`
URL string `yaml:"url" json:"url"`
Commit string `yaml:"commit" json:"commit"`
KeepGitDir bool `yaml:"keepGitDir,omitempty" json:"keepGitDir,omitempty"`
Auth GitAuth `yaml:"auth,omitempty" json:"auth,omitempty"`
SSHKnownHosts []string `yaml:"sshKnownHosts,omitempty" json:"sshKnownHosts,omitempty"`
}

type GitAuth struct {
Expand Down Expand Up @@ -116,6 +117,10 @@ func (src *SourceGit) baseState(opts fetchOptions) llb.State {
gOpts = append(gOpts, WithConstraints(opts.Constraints...))
gOpts = append(gOpts, &src.Auth)

for _, host := range src.SSHKnownHosts {
gOpts = append(gOpts, llb.KnownSSHHosts(host))
}

return llb.Git(src.URL, src.Commit, gOpts...)
}

Expand Down Expand Up @@ -156,7 +161,8 @@ func (src *SourceGit) processBuildArgs(lex *shell.Lex, args map[string]string, a
if err != nil {
errs = append(errs, err)
}
if len(errs) > 1 {

if len(errs) > 0 {
Comment thread
cpuguy83 marked this conversation as resolved.
return fmt.Errorf("failed to process build args for git source: %w", stderrors.Join(errs...))
}
return nil
Expand Down
26 changes: 26 additions & 0 deletions source_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,20 @@ func TestSourceGitSSH(t *testing.T) {
checkGitOp(t, ops, &src)
})

t.Run("with known hosts", func(t *testing.T) {
knownHosts := "github.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC7"
src := Source{
Git: &SourceGit{
URL: fmt.Sprintf("user@%s:test.git", addr),
Commit: t.Name(),
SSHKnownHosts: []string{knownHosts},
},
}

ops := getSourceOp(ctx, t, src)
checkGitOp(t, ops, &src)
})

}

func TestSourceGitHTTP(t *testing.T) {
Expand Down Expand Up @@ -1061,6 +1075,18 @@ func checkGitOp(t *testing.T, ops []*pb.Op, src *Source) {
}
assert.Check(t, cmp.Equal(op.Attrs["git.mountsshsock"], ssh), op)
}

// Check known hosts if set
if len(src.Git.SSHKnownHosts) > 0 {
// BuildKit's KnownSSHHosts option may add formatting like newlines
actualKnownHosts := op.Attrs["git.knownsshhosts"]
expectedKnownHosts := strings.Join(src.Git.SSHKnownHosts, "\n")

// Remove trailing whitespace for comparison since BuildKit may add formatting
actualTrimmed := strings.TrimSpace(actualKnownHosts)
expectedTrimmed := strings.TrimSpace(expectedKnownHosts)
assert.Check(t, cmp.Equal(actualTrimmed, expectedTrimmed), "Expected: %q, Got: %q", expectedKnownHosts, actualKnownHosts)
}
}

func checkGitAuth(t *testing.T, m map[string]*pb.Op, ops []*pb.Op, src *Source, expectedNumSecrets, expectedNumSSH int) {
Expand Down
22 changes: 22 additions & 0 deletions website/docs/sources.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,28 @@ git auth section (shown below with default values):
Note: These are secret names which are used to reference the secrets provided
by the client, not the actual secret values.

#### SSH Known Hosts

For SSH-based git URLs, you can specify known SSH host keys to improve security
and avoid Trust-On-First-Use (TOFU) behavior. When known hosts are provided,
the SSH connection will verify the host key against the specified keys and fail
if they don't match.

```yaml
someSource1:
git:
url: git@github.com:myOrg/myRepo.git
commit: 1234567890abcdef
sshKnownHosts:
- github.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC7vbqbLJofwIHMHnSVPP0k+aLU6X5OtN6a1r9K4kS...
- github.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOMqqnkVzrm0SdG6UOoqKLsabgH5C9okWi0dh2l9GKJl
```

When known hosts are not specified, BuildKit will use Trust-On-First-Use (TOFU)
behavior, where it will connect to the SSH server, retrieve the host key, and
use that for the connection. Specifying known hosts avoids this extra connection
and provides better security by ensuring you're connecting to the expected server.

### HTTP

HTTP sources fetch a file from an HTTP URL. The HTTP source type is considered to be a "file" source.
Expand Down