* all: run gofumpt https://github.com/mvdan/gofumpt The main appeal for me here is that my (and many other peoples') editors run this on save, so doing a single diff here keeps other diffs minimal. * .github/workflows: add gofumpt checker
547 lines
12 KiB
Go
547 lines
12 KiB
Go
package e2e_test
|
|
|
|
import (
|
|
"encoding/base64"
|
|
"fmt"
|
|
"html/template"
|
|
"os"
|
|
"path"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/google/uuid"
|
|
)
|
|
|
|
const yamlConfigTemplate = `
|
|
version: "1.0"
|
|
pipes:
|
|
- from:
|
|
- username: "password_simple"
|
|
to:
|
|
host: host-password:2222
|
|
username: "user"
|
|
ignore_hostkey: true
|
|
- from:
|
|
- username: "^password_.*_regex$"
|
|
username_regex_match: true
|
|
to:
|
|
host: host-password:2222
|
|
username: "user"
|
|
known_hosts_data:
|
|
# github.com
|
|
- fDF8RjRwTmVveUZHVEVHcEIyZ3A4RGE0WlE4TGNVPXxycVZYNU0rWTJoS0dteFphcVFBb0syRHp1TEE9IHNzaC1lZDI1NTE5IEFBQUFDM056YUMxbFpESTFOVEU1QUFBQUlPTXFxbmtWenJtMFNkRzZVT29xS0xzYWJnSDVDOW9rV2kwZGgybDlHS0psCg==
|
|
- {{ .KnownHostsKey }}
|
|
- {{ .KnownHostsPass }}
|
|
- from:
|
|
- username: "^password_(.+?)_regex_expand$"
|
|
username_regex_match: true
|
|
to:
|
|
host: host-password:2222
|
|
username: "$1"
|
|
known_hosts_data: {{ .KnownHostsPass }}
|
|
- from:
|
|
- username: "publickey_simple"
|
|
authorized_keys: {{ .AuthorizedKeys_Simple }}
|
|
to:
|
|
host: host-publickey:2222
|
|
username: "user"
|
|
private_key: {{ .PrivateKey }}
|
|
known_hosts_data: {{ .KnownHostsKey }}
|
|
- from:
|
|
- username: "cert"
|
|
trusted_user_ca_keys: {{ .TrustedUserCAKeys }}
|
|
to:
|
|
host: host-publickey:2222
|
|
username: "user"
|
|
ignore_hostkey: true
|
|
private_key: {{ .PrivateKey }}
|
|
- from:
|
|
- groupname: "testgroup"
|
|
authorized_keys: {{ .AuthorizedKeys_Simple }}
|
|
to:
|
|
host: host-publickey:2222
|
|
username: "user"
|
|
private_key: {{ .PrivateKey }}
|
|
known_hosts_data: {{ .KnownHostsKey }}
|
|
- from:
|
|
- groupname: "testgroup"
|
|
to:
|
|
host: host-password:2222
|
|
username: "user"
|
|
ignore_hostkey: true
|
|
- from:
|
|
- username: ".*"
|
|
username_regex_match: true
|
|
authorized_keys:
|
|
- {{ .AuthorizedKeys_Simple }}
|
|
- {{ .AuthorizedKeys_Catchall }}
|
|
to:
|
|
host: host-publickey:2222
|
|
username: "user"
|
|
ignore_hostkey: true
|
|
private_key: {{ .PrivateKey }}
|
|
`
|
|
|
|
func TestYaml(t *testing.T) {
|
|
yamldir, err := os.MkdirTemp("", "")
|
|
if err != nil {
|
|
t.Fatalf("Failed to create temp dir: %v", err)
|
|
}
|
|
|
|
yamlfile, err := os.OpenFile(path.Join(yamldir, "config.yaml"), os.O_RDWR|os.O_CREATE, 0o400)
|
|
if err != nil {
|
|
t.Fatalf("Failed to create temp file: %v", err)
|
|
}
|
|
|
|
{
|
|
// simple key
|
|
if err := runCmdAndWait("rm", "-f", path.Join(yamldir, "id_rsa_simple")); err != nil {
|
|
t.Errorf("failed to remove id_rsa: %v", err)
|
|
}
|
|
|
|
if err := runCmdAndWait(
|
|
"ssh-keygen",
|
|
"-N",
|
|
"",
|
|
"-f",
|
|
path.Join(yamldir, "id_rsa_simple"),
|
|
); err != nil {
|
|
t.Errorf("failed to generate private key: %v", err)
|
|
}
|
|
|
|
// catch all key
|
|
if err := runCmdAndWait("rm", "-f", path.Join(yamldir, "id_rsa_catchall")); err != nil {
|
|
t.Errorf("failed to remove id_rsa: %v", err)
|
|
}
|
|
|
|
if err := runCmdAndWait(
|
|
"ssh-keygen",
|
|
"-N",
|
|
"",
|
|
"-f",
|
|
path.Join(yamldir, "id_rsa_catchall"),
|
|
); err != nil {
|
|
t.Errorf("failed to generate private key: %v", err)
|
|
}
|
|
|
|
// upstream key
|
|
if err := runCmdAndWait("rm", "-f", path.Join(yamldir, "id_rsa")); err != nil {
|
|
t.Errorf("failed to remove id_rsa: %v", err)
|
|
}
|
|
|
|
if err := runCmdAndWait(
|
|
"ssh-keygen",
|
|
"-N",
|
|
"",
|
|
"-f",
|
|
path.Join(yamldir, "id_rsa"),
|
|
); err != nil {
|
|
t.Errorf("failed to generate private key: %v", err)
|
|
}
|
|
|
|
if err := runCmdAndWait(
|
|
"/bin/cp",
|
|
path.Join(yamldir, "id_rsa.pub"),
|
|
"/publickey_authorized_keys/authorized_keys",
|
|
); err != nil {
|
|
t.Errorf("failed to copy public key: %v", err)
|
|
}
|
|
|
|
// ssh ca
|
|
if err := runCmdAndWait(
|
|
"ssh-keygen",
|
|
"-N",
|
|
"",
|
|
"-f",
|
|
path.Join(yamldir, "ca_key"),
|
|
); err != nil {
|
|
t.Errorf("failed to generate ca key: %v", err)
|
|
}
|
|
|
|
if err := runCmdAndWait(
|
|
"ssh-keygen",
|
|
"-N",
|
|
"",
|
|
"-f",
|
|
path.Join(yamldir, "user_ca_key"),
|
|
); err != nil {
|
|
t.Errorf("failed to generate user ca key: %v", err)
|
|
}
|
|
|
|
if err := runCmdAndWait(
|
|
"ssh-keygen",
|
|
"-s",
|
|
path.Join(yamldir, "ca_key"),
|
|
"-I",
|
|
"cert",
|
|
"-n",
|
|
"cert",
|
|
"-V",
|
|
"+1w",
|
|
path.Join(yamldir, "user_ca_key.pub"),
|
|
); err != nil {
|
|
t.Errorf("failed to sign user ca key: %v", err)
|
|
}
|
|
|
|
}
|
|
|
|
knownHostsKeyData, err := runAndGetStdout(
|
|
"ssh-keyscan",
|
|
"-p",
|
|
"2222",
|
|
"host-publickey",
|
|
)
|
|
if err != nil {
|
|
t.Errorf("failed to run ssh-keyscan: %v", err)
|
|
}
|
|
|
|
knownHostsPassData, err := runAndGetStdout(
|
|
"ssh-keyscan",
|
|
"-p",
|
|
"2222",
|
|
"host-password",
|
|
)
|
|
if err != nil {
|
|
t.Errorf("failed to run ssh-keyscan : %v", err)
|
|
}
|
|
if err := template.Must(template.New("yaml").Parse(yamlConfigTemplate)).ExecuteTemplate(yamlfile, "yaml", struct {
|
|
KnownHostsKey string
|
|
KnownHostsPass string
|
|
PrivateKey string
|
|
|
|
AuthorizedKeys_Simple string
|
|
AuthorizedKeys_Catchall string
|
|
|
|
TrustedUserCAKeys string
|
|
}{
|
|
KnownHostsKey: base64.StdEncoding.EncodeToString(knownHostsKeyData),
|
|
KnownHostsPass: base64.StdEncoding.EncodeToString(knownHostsPassData),
|
|
PrivateKey: path.Join(yamldir, "id_rsa"),
|
|
|
|
AuthorizedKeys_Simple: path.Join(yamldir, "id_rsa_simple.pub"),
|
|
AuthorizedKeys_Catchall: path.Join(yamldir, "id_rsa_catchall.pub"),
|
|
|
|
TrustedUserCAKeys: path.Join(yamldir, "ca_key.pub"),
|
|
}); err != nil {
|
|
t.Fatalf("Failed to write yaml file %v", err)
|
|
}
|
|
|
|
// dump config.yaml to stdout
|
|
_ = runCmdAndWait("cat", "-n", path.Join(yamldir, "config.yaml"))
|
|
|
|
piperaddr, piperport := nextAvailablePiperAddress()
|
|
|
|
piper, _, _, err := runCmd("/sshpiperd/sshpiperd",
|
|
"-p",
|
|
piperport,
|
|
"/sshpiperd/plugins/yaml",
|
|
"--config",
|
|
yamlfile.Name(),
|
|
)
|
|
if err != nil {
|
|
t.Errorf("failed to run sshpiperd: %v", err)
|
|
}
|
|
|
|
defer killCmd(piper)
|
|
waitForEndpointReady(piperaddr)
|
|
|
|
t.Run("password_simple", func(t *testing.T) {
|
|
randtext := uuid.New().String()
|
|
targetfie := uuid.New().String()
|
|
|
|
c, stdin, stdout, err := runCmd(
|
|
"ssh",
|
|
"-v",
|
|
"-o",
|
|
"StrictHostKeyChecking=no",
|
|
"-o",
|
|
"UserKnownHostsFile=/dev/null",
|
|
"-p",
|
|
piperport,
|
|
"-l",
|
|
"password_simple",
|
|
"127.0.0.1",
|
|
fmt.Sprintf(`sh -c "echo -n %v > /shared/%v"`, randtext, targetfie),
|
|
)
|
|
if err != nil {
|
|
t.Errorf("failed to ssh to piper, %v", err)
|
|
}
|
|
|
|
defer killCmd(c)
|
|
|
|
enterPassword(stdin, stdout, "pass")
|
|
|
|
time.Sleep(time.Second) // wait for file flush
|
|
|
|
checkSharedFileContent(t, targetfie, randtext)
|
|
})
|
|
|
|
t.Run("password_regex", func(t *testing.T) {
|
|
randtext := uuid.New().String()
|
|
targetfie := uuid.New().String()
|
|
|
|
c, stdin, stdout, err := runCmd(
|
|
"ssh",
|
|
"-v",
|
|
"-o",
|
|
"StrictHostKeyChecking=no",
|
|
"-o",
|
|
"UserKnownHostsFile=/dev/null",
|
|
"-p",
|
|
piperport,
|
|
"-l",
|
|
"password_XXX_regex",
|
|
"127.0.0.1",
|
|
fmt.Sprintf(`sh -c "echo -n %v > /shared/%v"`, randtext, targetfie),
|
|
)
|
|
if err != nil {
|
|
t.Errorf("failed to ssh to piper, %v", err)
|
|
}
|
|
|
|
defer killCmd(c)
|
|
|
|
enterPassword(stdin, stdout, "pass")
|
|
|
|
time.Sleep(time.Second) // wait for file flush
|
|
|
|
checkSharedFileContent(t, targetfie, randtext)
|
|
})
|
|
|
|
t.Run("password_regex_expand", func(t *testing.T) {
|
|
randtext := uuid.New().String()
|
|
targetfie := uuid.New().String()
|
|
|
|
c, stdin, stdout, err := runCmd(
|
|
"ssh",
|
|
"-v",
|
|
"-o",
|
|
"StrictHostKeyChecking=no",
|
|
"-o",
|
|
"UserKnownHostsFile=/dev/null",
|
|
"-p",
|
|
piperport,
|
|
"-l",
|
|
"password_user_regex_expand",
|
|
"127.0.0.1",
|
|
fmt.Sprintf(`sh -c "echo -n %v > /shared/%v"`, randtext, targetfie),
|
|
)
|
|
if err != nil {
|
|
t.Errorf("failed to ssh to piper, %v", err)
|
|
}
|
|
|
|
defer killCmd(c)
|
|
|
|
enterPassword(stdin, stdout, "pass")
|
|
|
|
time.Sleep(time.Second) // wait for file flush
|
|
|
|
checkSharedFileContent(t, targetfie, randtext)
|
|
})
|
|
|
|
t.Run("publickey_simple", func(t *testing.T) {
|
|
randtext := uuid.New().String()
|
|
targetfie := uuid.New().String()
|
|
|
|
c, _, _, err := runCmd(
|
|
"ssh",
|
|
"-v",
|
|
"-o",
|
|
"StrictHostKeyChecking=no",
|
|
"-o",
|
|
"UserKnownHostsFile=/dev/null",
|
|
"-p",
|
|
piperport,
|
|
"-l",
|
|
"publickey_simple",
|
|
"-i",
|
|
path.Join(yamldir, "id_rsa_simple"),
|
|
"127.0.0.1",
|
|
fmt.Sprintf(`sh -c "echo -n %v > /shared/%v"`, randtext, targetfie),
|
|
)
|
|
if err != nil {
|
|
t.Errorf("failed to ssh to piper, %v", err)
|
|
}
|
|
|
|
defer killCmd(c)
|
|
|
|
time.Sleep(time.Second) // wait for file flush
|
|
|
|
checkSharedFileContent(t, targetfie, randtext)
|
|
})
|
|
|
|
t.Run("catch_all", func(t *testing.T) {
|
|
randtext := uuid.New().String()
|
|
targetfie := uuid.New().String()
|
|
|
|
c, _, _, err := runCmd(
|
|
"ssh",
|
|
"-v",
|
|
"-o",
|
|
"StrictHostKeyChecking=no",
|
|
"-o",
|
|
"UserKnownHostsFile=/dev/null",
|
|
"-p",
|
|
piperport,
|
|
"-l",
|
|
"anyusername",
|
|
"-i",
|
|
path.Join(yamldir, "id_rsa_catchall"),
|
|
"127.0.0.1",
|
|
fmt.Sprintf(`sh -c "echo -n %v > /shared/%v"`, randtext, targetfie),
|
|
)
|
|
if err != nil {
|
|
t.Errorf("failed to ssh to piper, %v", err)
|
|
}
|
|
|
|
defer killCmd(c)
|
|
|
|
time.Sleep(time.Second) // wait for file flush
|
|
|
|
checkSharedFileContent(t, targetfie, randtext)
|
|
})
|
|
|
|
t.Run("publickey_simple_withmultiple_keyfile", func(t *testing.T) {
|
|
randtext := uuid.New().String()
|
|
targetfie := uuid.New().String()
|
|
|
|
wrongkeydir, err := os.MkdirTemp("", "")
|
|
if err != nil {
|
|
t.Errorf("failed to create temp key file: %v", err)
|
|
}
|
|
|
|
wrongkeyfile := path.Join(wrongkeydir, "key")
|
|
|
|
if err := runCmdAndWait(
|
|
"ssh-keygen",
|
|
"-N",
|
|
"",
|
|
"-f",
|
|
wrongkeyfile,
|
|
); err != nil {
|
|
t.Errorf("failed to generate key: %v", err)
|
|
}
|
|
|
|
c, _, _, err := runCmd(
|
|
"ssh",
|
|
"-v",
|
|
"-o",
|
|
"StrictHostKeyChecking=no",
|
|
"-o",
|
|
"UserKnownHostsFile=/dev/null",
|
|
"-p",
|
|
piperport,
|
|
"-l",
|
|
"publickey_simple",
|
|
"-i",
|
|
wrongkeyfile,
|
|
"-i",
|
|
path.Join(yamldir, "id_rsa_simple"),
|
|
"127.0.0.1",
|
|
fmt.Sprintf(`sh -c "echo -n %v > /shared/%v"`, randtext, targetfie),
|
|
)
|
|
if err != nil {
|
|
t.Errorf("failed to ssh to piper, %v", err)
|
|
}
|
|
|
|
defer killCmd(c)
|
|
|
|
time.Sleep(time.Second) // wait for file flush
|
|
|
|
checkSharedFileContent(t, targetfie, randtext)
|
|
})
|
|
|
|
t.Run("ssh_cert", func(t *testing.T) {
|
|
randtext := uuid.New().String()
|
|
targetfie := uuid.New().String()
|
|
|
|
c, _, _, err := runCmd(
|
|
"ssh",
|
|
"-v",
|
|
"-o",
|
|
"StrictHostKeyChecking=no",
|
|
"-o",
|
|
"UserKnownHostsFile=/dev/null",
|
|
"-o",
|
|
fmt.Sprintf("CertificateFile=%v", path.Join(yamldir, "user_ca_key-cert.pub")),
|
|
"-p",
|
|
piperport,
|
|
"-l",
|
|
"cert",
|
|
"-i",
|
|
path.Join(yamldir, "user_ca_key"),
|
|
"127.0.0.1",
|
|
fmt.Sprintf(`sh -c "echo -n %v > /shared/%v"`, randtext, targetfie),
|
|
)
|
|
if err != nil {
|
|
t.Errorf("failed to ssh to piper, %v", err)
|
|
}
|
|
|
|
defer killCmd(c)
|
|
|
|
time.Sleep(time.Second) // wait for file flush
|
|
|
|
checkSharedFileContent(t, targetfie, randtext)
|
|
})
|
|
|
|
t.Run("group_routing_key", func(t *testing.T) {
|
|
randtext := uuid.New().String()
|
|
targetfie := uuid.New().String()
|
|
|
|
c, _, _, err := runCmd(
|
|
"ssh",
|
|
"-v",
|
|
"-o",
|
|
"StrictHostKeyChecking=no",
|
|
"-o",
|
|
"UserKnownHostsFile=/dev/null",
|
|
"-p",
|
|
piperport,
|
|
"-l",
|
|
"testgroupuser",
|
|
"-i",
|
|
path.Join(yamldir, "id_rsa_simple"),
|
|
"127.0.0.1",
|
|
fmt.Sprintf(`sh -c "echo -n %v > /shared/%v"`, randtext, targetfie),
|
|
)
|
|
if err != nil {
|
|
t.Errorf("failed to ssh to piper, %v", err)
|
|
}
|
|
|
|
defer killCmd(c)
|
|
|
|
time.Sleep(time.Second) // wait for file flush
|
|
|
|
checkSharedFileContent(t, targetfie, randtext)
|
|
})
|
|
|
|
t.Run("group_routing_password", func(t *testing.T) {
|
|
randtext := uuid.New().String()
|
|
targetfie := uuid.New().String()
|
|
|
|
c, stdin, stdout, err := runCmd(
|
|
"ssh",
|
|
"-v",
|
|
"-o",
|
|
"StrictHostKeyChecking=no",
|
|
"-o",
|
|
"UserKnownHostsFile=/dev/null",
|
|
"-p",
|
|
piperport,
|
|
"-l",
|
|
"testgroupuser",
|
|
"127.0.0.1",
|
|
fmt.Sprintf(`sh -c "echo -n %v > /shared/%v"`, randtext, targetfie),
|
|
)
|
|
if err != nil {
|
|
t.Errorf("failed to ssh to piper, %v", err)
|
|
}
|
|
|
|
defer killCmd(c)
|
|
|
|
enterPassword(stdin, stdout, "pass")
|
|
|
|
time.Sleep(time.Second) // wait for file flush
|
|
|
|
checkSharedFileContent(t, targetfie, randtext)
|
|
})
|
|
}
|