You've already forked go-semantic-release
fix(*): Vendored project dependencies
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
This commit is contained in:
99
vendor/github.com/skeema/knownhosts/README.md
generated
vendored
Normal file
99
vendor/github.com/skeema/knownhosts/README.md
generated
vendored
Normal file
@@ -0,0 +1,99 @@
|
||||
# knownhosts: enhanced Golang SSH known_hosts management
|
||||
|
||||
[](https://github.com/skeema/knownhosts/actions)
|
||||
[](https://pkg.go.dev/github.com/skeema/knownhosts)
|
||||
|
||||
|
||||
> This repo is brought to you by [Skeema](https://github.com/skeema/skeema), a
|
||||
> declarative pure-SQL schema management system for MySQL and MariaDB. Our
|
||||
> premium products include extensive [SSH tunnel](https://www.skeema.io/docs/options/#ssh)
|
||||
> functionality, which internally makes use of this package.
|
||||
|
||||
Go provides excellent functionality for OpenSSH known_hosts files in its
|
||||
external package [golang.org/x/crypto/ssh/knownhosts](https://pkg.go.dev/golang.org/x/crypto/ssh/knownhosts).
|
||||
However, that package is somewhat low-level, making it difficult to implement full known_hosts management similar to command-line `ssh`'s behavior for `StrictHostKeyChecking=no` configuration.
|
||||
|
||||
This repo ([github.com/skeema/knownhosts](https://github.com/skeema/knownhosts)) is a thin wrapper package around [golang.org/x/crypto/ssh/knownhosts](https://pkg.go.dev/golang.org/x/crypto/ssh/knownhosts), adding functions which provide the following functionality:
|
||||
|
||||
* Look up known_hosts public keys for any given host
|
||||
* Auto-populate ssh.ClientConfig.HostKeyAlgorithms easily based on known_hosts
|
||||
* Write new known_hosts entries to an io.Writer
|
||||
* Determine if an ssh.HostKeyCallback's error corresponds to a host whose key has changed (indicating potential MitM attack) vs a host that just isn't known yet
|
||||
|
||||
## How host key lookup works
|
||||
|
||||
Although [golang.org/x/crypto/ssh/knownhosts](https://pkg.go.dev/golang.org/x/crypto/ssh/knownhosts) doesn't directly expose a way to query its known_host map, we use a subtle trick to do so: invoke the HostKeyCallback with a valid host but a bogus key. The resulting KeyError allows us to determine which public keys are actually present for that host.
|
||||
|
||||
By using this technique, [github.com/skeema/knownhosts](https://github.com/skeema/knownhosts) doesn't need to duplicate or re-implement any of the actual known_hosts management from [golang.org/x/crypto/ssh/knownhosts](https://pkg.go.dev/golang.org/x/crypto/ssh/knownhosts).
|
||||
|
||||
## Populating ssh.ClientConfig.HostKeyAlgorithms based on known_hosts
|
||||
|
||||
Hosts often have multiple public keys, each of a different type (algorithm). This can be [problematic](https://github.com/golang/go/issues/29286) in [golang.org/x/crypto/ssh/knownhosts](https://pkg.go.dev/golang.org/x/crypto/ssh/knownhosts): if a host's first public key is *not* in known_hosts, but a key of a different type *is*, the HostKeyCallback returns an error. The solution is to populate `ssh.ClientConfig.HostKeyAlgorithms` based on the algorithms of the known_hosts entries for that host, but
|
||||
[golang.org/x/crypto/ssh/knownhosts](https://pkg.go.dev/golang.org/x/crypto/ssh/knownhosts)
|
||||
does not provide an obvious way to do so.
|
||||
|
||||
This package uses its host key lookup trick in order to make ssh.ClientConfig.HostKeyAlgorithms easy to populate:
|
||||
|
||||
```golang
|
||||
import (
|
||||
"golang.org/x/crypto/ssh"
|
||||
"github.com/skeema/knownhosts"
|
||||
)
|
||||
|
||||
func sshConfigForHost(hostWithPort string) (*ssh.ClientConfig, error) {
|
||||
kh, err := knownhosts.New("/home/myuser/.ssh/known_hosts")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
config := &ssh.ClientConfig{
|
||||
User: "myuser",
|
||||
Auth: []ssh.AuthMethod{ /* ... */ },
|
||||
HostKeyCallback: kh.HostKeyCallback(), // or, equivalently, use ssh.HostKeyCallback(kh)
|
||||
HostKeyAlgorithms: kh.HostKeyAlgorithms(hostWithPort),
|
||||
}
|
||||
return config, nil
|
||||
}
|
||||
```
|
||||
|
||||
## Writing new known_hosts entries
|
||||
|
||||
If you wish to mimic the behavior of OpenSSH's `StrictHostKeyChecking=no` or `StrictHostKeyChecking=ask`, this package provides a few functions to simplify this task. For example:
|
||||
|
||||
```golang
|
||||
sshHost := "yourserver.com:22"
|
||||
khPath := "/home/myuser/.ssh/known_hosts"
|
||||
kh, err := knownhosts.New(khPath)
|
||||
if err != nil {
|
||||
log.Fatal("Failed to read known_hosts: ", err)
|
||||
}
|
||||
|
||||
// Create a custom permissive hostkey callback which still errors on hosts
|
||||
// with changed keys, but allows unknown hosts and adds them to known_hosts
|
||||
cb := ssh.HostKeyCallback(func(hostname string, remote net.Addr, key ssh.PublicKey) error {
|
||||
err := kh(hostname, remote, key)
|
||||
if knownhosts.IsHostKeyChanged(err) {
|
||||
return fmt.Errorf("REMOTE HOST IDENTIFICATION HAS CHANGED for host %s! This may indicate a MitM attack.", hostname)
|
||||
} else if knownhosts.IsHostUnknown(err) {
|
||||
f, ferr := os.OpenFile(khPath, os.O_APPEND|os.O_WRONLY, 0600)
|
||||
if ferr == nil {
|
||||
defer f.Close()
|
||||
ferr = knownhosts.WriteKnownHost(f, hostname, remote, key)
|
||||
}
|
||||
if ferr == nil {
|
||||
log.Printf("Added host %s to known_hosts\n", hostname)
|
||||
} else {
|
||||
log.Printf("Failed to add host %s to known_hosts: %v\n", hostname, ferr)
|
||||
}
|
||||
return nil // permit previously-unknown hosts (warning: may be insecure)
|
||||
}
|
||||
return err
|
||||
})
|
||||
|
||||
config := &ssh.ClientConfig{
|
||||
User: "myuser",
|
||||
Auth: []ssh.AuthMethod{ /* ... */ },
|
||||
HostKeyCallback: cb,
|
||||
HostKeyAlgorithms: kh.HostKeyAlgorithms(sshHost),
|
||||
}
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user