diff --git a/cmd/cmd.go b/cmd/cmd.go index 0a52233a01..b2a5047f75 100644 --- a/cmd/cmd.go +++ b/cmd/cmd.go @@ -1,13 +1,13 @@ package cmd import ( + "github.com/buildpacks/pack/internal/sshdialer" "net/http" "net/url" "os" dockerClient "github.com/docker/docker/client" "github.com/heroku/color" - "github.com/matejvasek/sshdialer" "github.com/pkg/errors" "github.com/spf13/cobra" @@ -147,7 +147,7 @@ func initClient(logger logging.Logger, cfg config.Config) (pack.Client, error) { if dockerHost, ok := os.LookupEnv("DOCKER_HOST"); ok { if _url, err := url.Parse(dockerHost); err == nil && _url.Scheme == "ssh" { usesSSH = true - dialer, err := sshdialer.CreateDialContext(_url, "", "") + dialer, err := sshdialer.CreateDialContext(_url, sshdialer.CredentialsConfig{}) if err != nil { return pack.Client{}, err } diff --git a/go.mod b/go.mod index 1a5d57b7e3..59de524029 100644 --- a/go.mod +++ b/go.mod @@ -15,7 +15,6 @@ require ( github.com/google/go-containerregistry v0.6.0 github.com/google/go-github/v30 v30.1.0 github.com/heroku/color v0.0.6 - github.com/matejvasek/sshdialer v0.0.0-20210913152922-123ac509f696 github.com/mattn/go-colorable v0.1.8 // indirect github.com/mitchellh/ioprogress v0.0.0-20180201004757-6a23b12fa88e github.com/moby/sys/mount v0.2.0 // indirect diff --git a/go.sum b/go.sum index 15c582a2dc..19f5c995e9 100644 --- a/go.sum +++ b/go.sum @@ -40,9 +40,8 @@ cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RX cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/Azure/azure-sdk-for-go v16.2.1+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= +github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 h1:w+iIsaOQNcT7OZ575w+acHgRric5iCyQh+xv+KJ4HB8= github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= -github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8= -github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= github.com/Azure/go-autorest v10.8.1+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= github.com/Azure/go-autorest/autorest v0.11.1/go.mod h1:JFgpikqFJ/MleTTxwepExTKnFUKKszPS8UavbQYUMuw= @@ -75,9 +74,8 @@ github.com/Microsoft/hcsshim v0.8.7/go.mod h1:OHd7sQqRFrYd3RmSgbgji+ctCwkbq2wbEY github.com/Microsoft/hcsshim v0.8.9/go.mod h1:5692vkUqntj1idxauYlpoINNKeqCiG6Sg38RRsjT5y8= github.com/Microsoft/hcsshim v0.8.14/go.mod h1:NtVKoYxQuTLx6gEq0L96c9Ju4JbRJ4nY2ow3VK6a9Lg= github.com/Microsoft/hcsshim v0.8.15/go.mod h1:x38A4YbHbdxJtc0sF6oIz+RG0npwSCAvn69iY6URG00= +github.com/Microsoft/hcsshim v0.8.16 h1:8/auA4LFIZFTGrqfKhGBSXwM6/4X1fHa/xniyEHu8ac= github.com/Microsoft/hcsshim v0.8.16/go.mod h1:o5/SZqmR7x9JNKsW3pu+nqHm0MF8vbA+VxGOoXdC600= -github.com/Microsoft/hcsshim v0.8.18 h1:cYnKADiM1869gvBpos3YCteeT6sZLB48lB5dmMMs8Tg= -github.com/Microsoft/hcsshim v0.8.18/go.mod h1:+w2gRZ5ReXQhFOrvSQeNfhrYB/dg3oDwTOcER2fw4I4= github.com/Microsoft/hcsshim/test v0.0.0-20201218223536-d3e5debf77da/go.mod h1:5hlzMzRKMLyo42nCZ9oml8AdTlq/0cvIaBv6tK1RehU= github.com/Microsoft/hcsshim/test v0.0.0-20210227013316-43a75bb4edd3/go.mod h1:mw7qgWloBUl75W/gVH3cQszUg1+gUITj7D6NY7ywVnY= github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= @@ -118,8 +116,6 @@ github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+Ce github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/bitly/go-simplejson v0.5.0/go.mod h1:cXHtHw4XUPsvGaxgjIAn8PhEWG9NfngEKAMDJEczWVA= -github.com/bits-and-blooms/bitset v1.2.0 h1:Kn4yilvwNtMACtf1eYDlG8H77R07mZSPbMjLyS07ChA= -github.com/bits-and-blooms/bitset v1.2.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA= github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM= github.com/blang/semver v3.1.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= @@ -137,7 +133,6 @@ github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/checkpoint-restore/go-criu/v4 v4.1.0/go.mod h1:xUQBLp4RLc5zJtWY++yjOoMoB5lihDt7fai+75m+rGw= -github.com/checkpoint-restore/go-criu/v5 v5.0.0/go.mod h1:cfwC0EG7HMUenopBsUf9d89JlCLQIfgVcNsNN0t6T2M= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= @@ -145,12 +140,10 @@ github.com/cilium/ebpf v0.0.0-20200110133405-4032b1d8aae3/go.mod h1:MA5e5Lr8slmE github.com/cilium/ebpf v0.0.0-20200702112145-1c8d4c9ef775/go.mod h1:7cR51M8ViRLIdUjrmSXlK9pkrsDlLHbO8jiB8X8JnOc= github.com/cilium/ebpf v0.2.0/go.mod h1:To2CFviqOWL/M0gIMsvSMlqe7em/l1ALkX1PyjrX2Qs= github.com/cilium/ebpf v0.4.0/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs= -github.com/cilium/ebpf v0.6.2/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= github.com/containerd/aufs v0.0.0-20200908144142-dab0cbea06f4/go.mod h1:nukgQABAEopAHvB6j7cnP5zJ+/3aVcE7hCYqvIwAHyE= github.com/containerd/aufs v0.0.0-20201003224125-76a6863f2989/go.mod h1:AkGGQs9NM2vtYHaUen+NljV0/baGCAPELGm2q9ZXpWU= @@ -184,10 +177,8 @@ github.com/containerd/containerd v1.5.0-beta.1/go.mod h1:5HfvG1V2FsKesEGQ17k5/T7 github.com/containerd/containerd v1.5.0-beta.3/go.mod h1:/wr9AVtEM7x9c+n0+stptlo/uBBoBORwEx6ardVcmKU= github.com/containerd/containerd v1.5.0-beta.4/go.mod h1:GmdgZd2zA2GYIBZ0w09ZvgqEq8EfBp/m3lcVZIvPHhI= github.com/containerd/containerd v1.5.0-rc.0/go.mod h1:V/IXoMqNGgBlabz3tHD2TWDoTJseu1FGOKuoA4nNb2s= -github.com/containerd/containerd v1.5.1/go.mod h1:0DOxVqwDy2iZvrZp2JUx/E+hS0UNTVn7dJnIOwtYR4g= +github.com/containerd/containerd v1.5.2 h1:MG/Bg1pbmMb61j3wHCFWPxESXHieiKr2xG64px/k8zQ= github.com/containerd/containerd v1.5.2/go.mod h1:0DOxVqwDy2iZvrZp2JUx/E+hS0UNTVn7dJnIOwtYR4g= -github.com/containerd/containerd v1.5.5 h1:q1gxsZsGZ8ddVe98yO6pR21b5xQSMiR61lD0W96pgQo= -github.com/containerd/containerd v1.5.5/go.mod h1:oSTh0QpT1w6jYcGmbiSbxv9OSQYaa88mPyWIuU79zyo= github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= github.com/containerd/continuity v0.0.0-20190815185530-f2a389ac0a02/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= github.com/containerd/continuity v0.0.0-20191127005431-f65d91d395eb/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= @@ -260,8 +251,6 @@ github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:ma github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= -github.com/creack/pty v1.1.11 h1:07n33Z8lZxZ2qwegKbObQohDhXDQxiMMz1NOUGYlesw= -github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/cyphar/filepath-securejoin v0.2.2/go.mod h1:FpkQEhXnPnOthhzymB7CGsFk2G9VLXONKD9G7QGMM+4= github.com/d2g/dhcp4 v0.0.0-20170904100407-a1d1b6c41b1c/go.mod h1:Ct2BUK8SB0YC1SMSibvLzxjeJLnrYEVLULFNiHY9YfQ= github.com/d2g/dhcp4client v1.0.0/go.mod h1:j0hNfjhrt2SxUOw55nL0ATM/z4Yt3t2Kd1mW34z5W5s= @@ -284,7 +273,6 @@ github.com/docker/distribution v2.7.1-0.20190205005809-0d3efadf0154+incompatible github.com/docker/distribution v2.7.1+incompatible h1:a5mlkVzth6W5A4fOsS3D2EO5BUmsJpcB+cRlLU7cSug= github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/docker v1.4.2-0.20190924003213-a8608b5b67c7/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= -github.com/docker/docker v20.10.3+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker v20.10.7+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker v20.10.8+incompatible h1:RVqD337BgQicVCzYrrlhLDWhq6OAD2PJDUg2LsEUvKM= github.com/docker/docker v20.10.8+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= @@ -314,7 +302,6 @@ github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1m github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= @@ -461,9 +448,8 @@ github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3i github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gorilla/handlers v0.0.0-20150720190736-60c7bfde3e33/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ= github.com/gorilla/mux v1.7.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/gorilla/mux v1.7.3 h1:gnP5JzjVOuiZD07fKKToCAOjS0yOpj/qPETTXCCS6hw= github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= -github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= -github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= @@ -560,8 +546,6 @@ github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs= github.com/marstr/guid v1.1.0/go.mod h1:74gB1z2wpxxInTG6yaqA7KrtM0NZ+RbrcqDvYHefzho= -github.com/matejvasek/sshdialer v0.0.0-20210913152922-123ac509f696 h1:PtZFjpazZPVny2tXXwnoTUDgsujpsQQPumv3Bx0dgF4= -github.com/matejvasek/sshdialer v0.0.0-20210913152922-123ac509f696/go.mod h1:M/zTinV+cjb9ZgbP8h1uP65L6l+WAfHB8SuhrL4QgQc= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= @@ -604,9 +588,8 @@ github.com/moby/sys/mountinfo v0.4.0/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2J github.com/moby/sys/mountinfo v0.4.1 h1:1O+1cHA1aujwEwwVMa2Xm2l+gIpUHyd3+D+d7LZh1kM= github.com/moby/sys/mountinfo v0.4.1/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A= github.com/moby/sys/symlink v0.1.0/go.mod h1:GGDODQmbFOjFsXvfLVn3+ZRxkch54RkSiGqsZeMYowQ= +github.com/moby/term v0.0.0-20200312100748-672ec06f55cd h1:aY7OQNf2XqY/JQ6qREWamhI/81os/agb2BAGpcx5yWI= github.com/moby/term v0.0.0-20200312100748-672ec06f55cd/go.mod h1:DdlQx2hp0Ss5/fLikoLlEeIYiATotOjgB//nb973jeo= -github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6 h1:dcztxKSvZ4Id8iPpHERQBbIJfabdt4wUm5qy3wOL2Zc= -github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6/go.mod h1:E2VnQOmVuvZB6UYnnDB0qG5Nq/1tD9acaOpo6xmt0Kw= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= @@ -660,20 +643,17 @@ github.com/opencontainers/runc v0.0.0-20190115041553-12f6a991201f/go.mod h1:qT5X github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= github.com/opencontainers/runc v1.0.0-rc8.0.20190926000215-3e425f80a8c9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= github.com/opencontainers/runc v1.0.0-rc9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= +github.com/opencontainers/runc v1.0.0-rc93 h1:x2UMpOOVf3kQ8arv/EsDGwim8PTNqzL1/EYDr/+scOM= github.com/opencontainers/runc v1.0.0-rc93/go.mod h1:3NOsor4w32B2tC0Zbl8Knk4Wg84SM2ImC1fxBuqJ/H0= -github.com/opencontainers/runc v1.0.1 h1:G18PGckGdAm3yVQRWDVQ1rLSLntiniKJ0cNRT2Tm5gs= -github.com/opencontainers/runc v1.0.1/go.mod h1:aTaHFFwQXuA71CiyxOdFFIorAoemI04suvGRQFzWTD0= github.com/opencontainers/runtime-spec v0.1.2-0.20190507144316-5b71a03e2700/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= github.com/opencontainers/runtime-spec v1.0.1/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= github.com/opencontainers/runtime-spec v1.0.2-0.20190207185410-29686dbc5559/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= github.com/opencontainers/runtime-spec v1.0.3-0.20200929063507-e6143ca7d51d/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= -github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= github.com/opencontainers/runtime-tools v0.0.0-20181011054405-1d69bd0f9c39/go.mod h1:r3f7wjNzSs2extwzU3Y+6pKfobzPh+kKFJ3ofN+3nfs= github.com/opencontainers/selinux v1.6.0/go.mod h1:VVGKuOLlE7v4PJyT6h7mNWvq1rzqiriPsEqVhc+svHE= +github.com/opencontainers/selinux v1.8.0 h1:+77ba4ar4jsCbL1GLbFL8fFM57w6suPfSS9PDLDY7KM= github.com/opencontainers/selinux v1.8.0/go.mod h1:RScLhm78qiWa2gbVCcGkC7tCGdgk3ogry1nUQF8Evvo= -github.com/opencontainers/selinux v1.8.2 h1:c4ca10UMgRcvZ6h0K4HtS15UaVSBEaE+iln2LVpAuGc= -github.com/opencontainers/selinux v1.8.2/go.mod h1:MUIHuUEvKB1wtJjQdOyYRgOnLD2xAPP8dBsCoU0KuF8= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pelletier/go-buffruneio v0.2.0/go.mod h1:JkE26KsDizTr40EUHkXVtNPvgGtbSNq5BcowyYOWdKo= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= @@ -824,6 +804,7 @@ github.com/vishvananda/netns v0.0.0-20180720170159-13995c7128cc/go.mod h1:ZjcWmF github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU= github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0= github.com/willf/bitset v1.1.11-0.20200630133818-d5bec3311243/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4= +github.com/willf/bitset v1.1.11 h1:N7Z7E9UvjW+sGsEl7k/SJrvY2reP1A07MrGuCjIOjRE= github.com/willf/bitset v1.1.11/go.mod h1:83CECat5yLh5zVOf4P1ErAgKA5UDvKtgyUABdr3+MjI= github.com/xanzy/ssh-agent v0.2.1/go.mod h1:mLlQY/MoOhWBj+gOGMQkOeiEvkx+8pJSI+0Bx9h2kr4= github.com/xanzy/ssh-agent v0.3.0 h1:wUMzuKtKilRgBAD1sUb8gOwwRr2FGoBVumcjoOACClI= @@ -856,7 +837,6 @@ go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= -go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= @@ -1082,12 +1062,10 @@ golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210426230700-d19ff857e887/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210819135213-f52c844e1c1c h1:Lyn7+CqXIiC+LOR9aHD6jDK+hPcmAuCfuXztd1v4w1Q= golang.org/x/sys v0.0.0-20210819135213-f52c844e1c1c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= @@ -1109,9 +1087,8 @@ golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxb golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e h1:EHBhcS0mlXEAVwNyO2dLfjToGsyY4j24pTs2ScHnX7s= golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac h1:7zkz7BUtwNFFqcowJ+RIgu2MaV/MapERkDIy+mwPyjs= -golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20181011042414-1f849cf54d09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -1285,9 +1262,8 @@ google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAG google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= google.golang.org/grpc v1.37.1/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/grpc v1.38.0 h1:/9BgsAsa5nWe26HqOlvlgJnqBuktYOLCgjCPqsa56W0= google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.40.0 h1:AGJ0Ih4mHjSeibYkFGh1dD9KJ/eOtZ93I6hoHhukQ5Q= -google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= diff --git a/internal/sshdialer/ssh_dialer.go b/internal/sshdialer/ssh_dialer.go new file mode 100644 index 0000000000..484e969607 --- /dev/null +++ b/internal/sshdialer/ssh_dialer.go @@ -0,0 +1,269 @@ +// NOTE: code here is heavily based on podman code + +package sshdialer + +import ( + "bufio" + "bytes" + "context" + "errors" + "fmt" + "io/ioutil" + "net" + urlPkg "net/url" + "os" + "path/filepath" + "time" + + "github.com/docker/docker/pkg/homedir" + "golang.org/x/crypto/ssh" + "golang.org/x/crypto/ssh/agent" + "golang.org/x/crypto/ssh/knownhosts" +) + +type PasswordCallback func() (string, error) +type PassPhraseCallback func() (string, error) +type HostKeyCallback func(hostPort string, pubKey ssh.PublicKey) error + +type CredentialsConfig struct { + Identity string + PassPhrase string + PasswordCallback PasswordCallback + PassPhraseCallback PassPhraseCallback + HostKeyCallback HostKeyCallback +} + +// CreateDialContext creates DialContext function +// Useful with docker API client as well as with standard Go http client. +func CreateDialContext(url *urlPkg.URL, credentialsConfig CredentialsConfig) (func(ctx context.Context, network, addr string) (net.Conn, error), error) { + return func(ctx context.Context, network, addr string) (net.Conn, error) { + return DialOverSSH(url, credentialsConfig) + }, nil +} + +// Default key names. +var knownKeyNames = []string{"id_rsa", "id_dsa", "id_ecdsa", "id_ecdsa_sk", "id_ed25519", "id_ed25519_sk"} + +// DialOverSSH dials unix socket in the remote machine via ssh tunneling. +// The identity parameter is an optional path to a private key. +// The passPhrase parameter is an optional passPhrase to the identity file +func DialOverSSH(url *urlPkg.URL, credentialsConfig CredentialsConfig) (net.Conn, error) { + var ( + authMethods []ssh.AuthMethod + signers []ssh.Signer + ) + + if pw, found := url.User.Password(); found { + authMethods = append(authMethods, ssh.Password(pw)) + } + + // add signer from explicit identity parameter + if credentialsConfig.Identity != "" { + s, err := publicKey(credentialsConfig.Identity, []byte(credentialsConfig.Identity), credentialsConfig.PassPhraseCallback) + if err != nil { + return nil, fmt.Errorf("failed to parse identity file: %w", err) + } + signers = append(signers, s) + } + + // add signers from ssh-agent + if sock, found := os.LookupEnv("SSH_AUTH_SOCK"); found { + c, err := net.Dial("unix", sock) + if err != nil { + return nil, fmt.Errorf("failed to connect to ssh-agent's socket: %w", err) + } + agentSigners, err := agent.NewClient(c).Signers() + if err != nil { + return nil, fmt.Errorf("failed to get signers from ssh-agent: %w", err) + } + signers = append(signers, agentSigners...) + } + + // if there is no explicit identity file nor keys from ssh-agent then + // add keys with standard name from ~/.ssh/ + if len(signers) == 0 { + var defaultKeyPaths []string + if home, err := os.UserHomeDir(); err == nil { + for _, keyName := range knownKeyNames { + p := filepath.Join(home, ".ssh", keyName) + + fi, err := os.Stat(p) + if err != nil { + continue + } + if fi.Mode().IsRegular() { + defaultKeyPaths = append(defaultKeyPaths, p) + } + } + } + + if len(defaultKeyPaths) == 1 { + s, err := publicKey(defaultKeyPaths[0], []byte(credentialsConfig.PassPhrase), credentialsConfig.PassPhraseCallback) + if err != nil { + return nil, err + } + signers = append(signers, s) + } + } + + if len(signers) > 0 { + var dedup = make(map[string]ssh.Signer) + // Dedup signers based on fingerprint, ssh-agent keys override explicit identity + for _, s := range signers { + fp := ssh.FingerprintSHA256(s.PublicKey()) + //if _, found := dedup[fp]; found { + // key updated + //} + dedup[fp] = s + } + + var uniq []ssh.Signer + for _, s := range dedup { + uniq = append(uniq, s) + } + authMethods = append(authMethods, ssh.PublicKeysCallback(func() ([]ssh.Signer, error) { + return uniq, nil + })) + } + + if len(authMethods) == 0 && credentialsConfig.PasswordCallback != nil { + authMethods = append(authMethods, ssh.PasswordCallback(credentialsConfig.PasswordCallback)) + } + + const sshTimeout = 5 + config := ssh.ClientConfig{ + User: url.User.Username(), + Auth: authMethods, + HostKeyCallback: createHostKeyCallback(credentialsConfig.HostKeyCallback), + HostKeyAlgorithms: []string{ + ssh.KeyAlgoECDSA256, + ssh.KeyAlgoECDSA384, + ssh.KeyAlgoECDSA521, + ssh.KeyAlgoED25519, + ssh.SigAlgoRSASHA2512, + ssh.SigAlgoRSASHA2256, + ssh.KeyAlgoRSA, + ssh.KeyAlgoDSA, + }, + Timeout: sshTimeout * time.Second, + } + + port := url.Port() + if port == "" { + port = "22" + } + + sshClient, err := ssh.Dial("tcp", net.JoinHostPort(url.Hostname(), port), &config) + if err != nil { + return nil, fmt.Errorf("failed to dial ssh: %w", err) + } + conn, err := sshClient.Dial("unix", url.Path) + if err != nil { + err = fmt.Errorf("failed to dial unix socket in the remote: %w", err) + } + + return conn, err +} + +func publicKey(path string, passphrase []byte, passPhraseCallback PassPhraseCallback) (ssh.Signer, error) { + key, err := ioutil.ReadFile(path) + if err != nil { + return nil, fmt.Errorf("failed to read key file: %w", err) + } + + signer, err := ssh.ParsePrivateKey(key) + if err != nil { + var missingPhraseError *ssh.PassphraseMissingError + if ok := errors.As(err, &missingPhraseError); !ok { + return nil, fmt.Errorf("failed to parse private key: %w", err) + } + + if len(passphrase) == 0 && passPhraseCallback != nil { + b, err := passPhraseCallback() + if err != nil { + return nil, err + } + passphrase = []byte(b) + } + + return ssh.ParsePrivateKeyWithPassphrase(key, passphrase) + } + + return signer, nil +} + +func createHostKeyCallback(hostKeyCallback HostKeyCallback) func (hostPort string, remote net.Addr, key ssh.PublicKey) error { + + return func(hostPort string, remote net.Addr, pubKey ssh.PublicKey) error { + + host, port := hostPort, "22" + if _h, _p, err := net.SplitHostPort(host); err == nil { + host, port = _h, _p + } + + knownHosts := filepath.Join(homedir.Get(), ".ssh", "known_hosts") + + _, err := os.Stat(knownHosts) + if err != nil && errors.Is(err, os.ErrNotExist) { + if hostKeyCallback != nil && hostKeyCallback(hostPort, pubKey) == nil { + return nil + } + return errUnknownServerKey + } + + f, err := os.Open(knownHosts) + if err != nil { + return fmt.Errorf("failed to open known_hosts: %w", err) + } + defer f.Close() + + hashhost := knownhosts.HashHostname(host) + + var errs []error + scanner := bufio.NewScanner(f) + for scanner.Scan() { + _, hostPorts, _key, _, _, err := ssh.ParseKnownHosts(scanner.Bytes()) + if err != nil { + errs = append(errs, err) + continue + } + + for _, hp := range hostPorts { + h, p := hp, "22" + if _h, _p, err := net.SplitHostPort(hp); err == nil { + h, p = _h, _p + } + + if (h == host || h == hashhost) && port == p { + if pubKey.Type() != _key.Type() { + errs = append(errs, fmt.Errorf("missmatch in type of a key")) + } + if bytes.Equal(_key.Marshal(), pubKey.Marshal()) { + return nil + } + + return errBadServerKey + } + } + } + + if hostKeyCallback != nil && hostKeyCallback(hostPort, pubKey) == nil { + return nil + } + + if len(errs) > 0 { + return fmt.Errorf("server is not trusted (%v)", errs) + } + + return errUnknownServerKey + } + +} +var ErrBadServerKeyMsg = "server key for given host differs from key in known_host" +var ErrUnknownServerKeyMsg = "server key not found in known_hosts" +var ErrNotImplementedMsg = "not implemented" + +// I would expose those but since ssh pkg doesn't do correct error wrapping it would be entirely futile +var errBadServerKey = errors.New(ErrBadServerKeyMsg) +var errUnknownServerKey = errors.New(ErrUnknownServerKeyMsg) +var errNotImplemented = errors.New(ErrNotImplementedMsg) diff --git a/internal/sshdialer/ssh_dialer_test.go b/internal/sshdialer/ssh_dialer_test.go new file mode 100644 index 0000000000..eb5c0844e1 --- /dev/null +++ b/internal/sshdialer/ssh_dialer_test.go @@ -0,0 +1,671 @@ +package sshdialer_test + +import ( + "context" + "errors" + "fmt" + "github.com/buildpacks/pack/internal/sshdialer" + "github.com/docker/go-connections/nat" + "io" + "io/ioutil" + "net" + "net/http" + "net/url" + "os" + "path/filepath" + "runtime" + "strings" + "sync" + "testing" + "text/template" + "time" + + "github.com/docker/docker/api/types" + "github.com/docker/docker/api/types/container" + "github.com/docker/docker/client" + "github.com/docker/docker/pkg/homedir" + "golang.org/x/crypto/ssh" + "golang.org/x/crypto/ssh/agent" + + th "github.com/buildpacks/pack/testhelpers" +) + +const ( + imageName = "buildpacks/sshdialer-test-img" + containerName = "sshdialer-test-ctr" +) + +var containerIP4 = "unset" +var containerIP6 = "unset" + + +// We need to set up the test container running sshd against which we will run tests. +// This will return IPv4 and IPv6 of the container, +// cleanUp procedure to remove the test container and possibly error. +func prepareSSHServer(t *testing.T) (cleanUp func (), err error) { + t.Helper() + + containerIP4 = "127.0.0.1" + containerIP6 = "::" + + var cleanUps []func() + cleanUp = func() { + for i := range cleanUps { + cleanUps[i]() + } + } + + ctx := context.Background() + + cli, err := client.NewClientWithOpts( + client.FromEnv, + client.WithAPIVersionNegotiation(), + ) + if err != nil { + return + } + + //cli.ImageRemove(ctx, imageName, types.ImageRemoveOptions{Force: true}) + //cli.ContainerRemove(ctx, containerName, types.ContainerRemoveOptions{Force: true}) + + wd, err := os.Getwd() + if err != nil { + return + } + + th.CreateImageFromDir(t, cli, imageName, filepath.Join(wd, "testdata")) + + config := container.Config{ + Image: imageName, + } + + var hostConfig *container.HostConfig + if runtime.GOOS != "linux" { + hostConfig = &container.HostConfig{ + PortBindings: map[nat.Port][]nat.PortBinding{ + "22/tcp": {nat.PortBinding{HostIP: "localhost", HostPort: "22"}}, + "2222/tcp": {nat.PortBinding{HostIP: "localhost", HostPort: "2222"}}, + }, + } + } + ctr, err := cli.ContainerCreate(ctx, &config, hostConfig, nil, nil, containerName) + if err != nil { + return + } + + defer func() { + f := func() {cli.ContainerRemove(ctx, ctr.ID, types.ContainerRemoveOptions{Force: true})} + if err != nil { + f() + } else { + cleanUps = append(cleanUps, f) + } + }() + + ctrStartOpts := types.ContainerStartOptions{} + err = cli.ContainerStart(ctx, ctr.ID, ctrStartOpts) + if err != nil { + return + } + + defer func() { + f := func() {cli.ContainerKill(ctx, ctr.ID, "SIGKILL")} + if err != nil { + f() + } else { + cleanUps = append(cleanUps, f) + } + }() + + var ctrJSON types.ContainerJSON + if runtime.GOOS == "linux" { + ctrJSON, err = cli.ContainerInspect(ctx, ctr.ID) + if err != nil { + return + } + + containerIP4 = ctrJSON.NetworkSettings.IPAddress + containerIP6 = ctrJSON.NetworkSettings.GlobalIPv6Address + } + + // wait for ssh container to start serving ssh + timeoutChan := time.After(time.Second * 10) + for { + select { + case <-timeoutChan: + err = fmt.Errorf("test container failed to start serving ssh") + return + case <-time.After(time.Millisecond * 100): + } + + conn, err := net.Dial("tcp", net.JoinHostPort(containerIP4, "22")) + if err != nil { + continue + } + conn.Close() + + break + } + + return +} + +// function that prepares testing environment and returns clean up function +// this should be used in conjunction with defer: `defer fn()()` +// e.g. sets environment variables or starts mock up services +// it returns clean up procedure that restores old values of environment variables +// or shuts down mock up services +type setUpEnvFn func(t *testing.T) func() + +// combines multiple setUp routines into one setUp routine +func all(fns ...setUpEnvFn) setUpEnvFn { + return func(t *testing.T) func() { + t.Helper() + var cleanUps []func() + for _, fn := range fns { + cleanUps = append(cleanUps, fn(t)) + } + + return func() { + for i := len(cleanUps) - 1; i >= 0; i-- { + cleanUps[i]() + } + } + } +} + +func TestCreateDialer(t *testing.T) { + + defer withoutSSHAgent(t)() + defer withCleanHome(t)() + + cleanUp, err := prepareSSHServer(t) + if err != nil { + t.Fatal(err) + } + defer cleanUp() + + type args struct { + connStr string + credentialConfig sshdialer.CredentialsConfig + } + type testParams struct { + name string + args args + setUpEnv setUpEnvFn + ipv6test bool + errMsg string + } + tests := []testParams{ + { + name: "read password from input", + args: args{ + connStr: fmt.Sprintf("ssh://testuser@%s/home/testuser/test.sock", containerIP4), + credentialConfig: sshdialer.CredentialsConfig{PasswordCallback: func() (string, error) { + return "idkfa", nil + }}, + }, + setUpEnv: all(withoutSSHAgent, withCleanHome, withKnowHosts), + }, + { + name: "password in url", + args: args{connStr: fmt.Sprintf("ssh://testuser:idkfa@%s/home/testuser/test.sock", containerIP4)}, + setUpEnv: all(withoutSSHAgent, withCleanHome, withKnowHosts), + }, + { + name: "password in url non-standard ssh port", + args: args{connStr: fmt.Sprintf("ssh://testuser:idkfa@%s:2222/home/testuser/test.sock", containerIP4)}, + setUpEnv: all(withoutSSHAgent, withCleanHome, withKnowHosts), + }, + { + name: "server key is not in known_hosts (the file doesn't exists)", + args: args{connStr: fmt.Sprintf("ssh://testuser:idkfa@%s/home/testuser/test.sock", containerIP4)}, + setUpEnv: all(withoutSSHAgent, withCleanHome), + errMsg: sshdialer.ErrUnknownServerKeyMsg, + }, + { + name: "server key is not in known_hosts (the file exists)", + args: args{connStr: fmt.Sprintf("ssh://testuser:idkfa@%s/home/testuser/test.sock", containerIP4)}, + setUpEnv: all(withoutSSHAgent, withCleanHome, withEmptyKnownHosts), + errMsg: sshdialer.ErrUnknownServerKeyMsg, + }, + { + name: "server key is not in known_hosts (the filed doesn't exists) - user force trust", + args: args{ + connStr: fmt.Sprintf("ssh://testuser:idkfa@%s/home/testuser/test.sock", containerIP4), + credentialConfig: sshdialer.CredentialsConfig{HostKeyCallback: func(hostPort string, pubKey ssh.PublicKey) error { + return nil + }}, + }, + setUpEnv: all(withoutSSHAgent, withCleanHome), + }, + { + name: "server key is not in known_hosts (the file exists) - user force trust", + args: args{ + connStr: fmt.Sprintf("ssh://testuser:idkfa@%s/home/testuser/test.sock", containerIP4), + credentialConfig: sshdialer.CredentialsConfig{HostKeyCallback: func(hostPort string, pubKey ssh.PublicKey) error { + return nil + }}, + }, + setUpEnv: all(withoutSSHAgent, withCleanHome, withEmptyKnownHosts), + }, + { + name: "server key does not match the respective key in known_host", + args: args{connStr: fmt.Sprintf("ssh://testuser:idkfa@%s/home/testuser/test.sock", containerIP4)}, + setUpEnv: all(withoutSSHAgent, withCleanHome, withBadKnownHosts), + errMsg: sshdialer.ErrBadServerKeyMsg, + }, + { + name: "key from identity parameter", + args: args{ + connStr: fmt.Sprintf("ssh://testuser@%s/home/testuser/test.sock", containerIP4), + credentialConfig: sshdialer.CredentialsConfig{Identity: "testdata/id_ed25519"}, + }, + setUpEnv: all(withoutSSHAgent, withCleanHome, withKnowHosts), + }, + { + name: "key at standard location with need to read passphrase", + args: args{ + connStr: fmt.Sprintf("ssh://testuser@%s/home/testuser/test.sock", containerIP4), + credentialConfig: sshdialer.CredentialsConfig{PassPhraseCallback: func() (string, error) { + return "idfa", nil + }}, + }, + setUpEnv: all(withoutSSHAgent, withCleanHome, withKey(t, "id_rsa"), withKnowHosts), + }, + { + name: "key at standard location with explicitly set passphrase", + args: args{ + connStr: fmt.Sprintf("ssh://testuser@%s/home/testuser/test.sock", containerIP4), + credentialConfig: sshdialer.CredentialsConfig{PassPhrase: "idfa"}, + }, + setUpEnv: all(withoutSSHAgent, withCleanHome, withKey(t, "id_rsa"), withKnowHosts), + }, + { + name: "key at standard location with no passphrase", + args: args{connStr: fmt.Sprintf("ssh://testuser@%s/home/testuser/test.sock", containerIP4)}, + setUpEnv: all(withoutSSHAgent, withCleanHome, withKey(t, "id_ed25519"), withKnowHosts), + }, + { + name: "key from ssh-agent", + args: args{connStr: fmt.Sprintf("ssh://testuser@%s/home/testuser/test.sock", containerIP4)}, + setUpEnv: all(withSSHAgent, withCleanHome, withKnowHosts), + }, + { + name: "password in url with IPv6", + args: args{connStr: fmt.Sprintf("ssh://testuser:idkfa@[%s]/home/testuser/test.sock", containerIP6)}, + setUpEnv: all(withoutSSHAgent, withCleanHome, withKnowHosts), + ipv6test: true, + }, + { + name: "password in url with IPv6 non-standard port", + args: args{connStr: fmt.Sprintf("ssh://testuser:idkfa@[%s]:2222/home/testuser/test.sock", containerIP6)}, + setUpEnv: all(withoutSSHAgent, withCleanHome, withKnowHosts), + ipv6test: true, + }, + } + + for _, ttx := range tests { + tt := ttx + t.Run(tt.name, func(t *testing.T) { + // this test cannot be parallelized as they use process wide environment variable $HOME + if strings.Contains(tt.errMsg, sshdialer.ErrNotImplementedMsg) { + t.Skip("functionality is yet to be implemented") + } + + if tt.ipv6test && containerIP6 == "" { + t.Skip("skipping ipv6 test since test environment doesn't support ipv6 connection") + } + + defer tt.setUpEnv(t)() + + u, err := url.Parse(tt.args.connStr) + if err != nil { + t.Fatal(err) + } + + DialContext, err := sshdialer.CreateDialContext(u, tt.args.credentialConfig) + + th.AssertTrue(t, err == nil) + if err != nil { + return + } + + transport := http.Transport{DialContext: DialContext} + httpClient := http.Client{Transport: &transport} + + resp, err := httpClient.Get("http://docker/") + + if tt.errMsg == "" { + th.AssertTrue(t, err == nil) + } else { + // I wish I could use errors.Is(), + // however foreign code is not wrapping errors thoroughly + th.AssertContains(t, err.Error(), tt.errMsg) + } + if err != nil { + return + } + defer resp.Body.Close() + b, err := io.ReadAll(resp.Body) + th.AssertTrue(t, err == nil) + if err != nil { + return + } + th.AssertEq(t, "Hello there!", string(b)) + }) + } +} + +func cp(src, dest string) error { + srcFs, err := os.Stat(src) + if err != nil { + return fmt.Errorf("the cp() function failed to stat source file: %w", err) + } + + data, err := os.ReadFile(src) + if err != nil { + return fmt.Errorf("the cp() function failed to read source file: %w", err) + } + + _, err = os.Stat(dest) + if err == nil { + return fmt.Errorf("destination file already exists: %w", os.ErrExist) + } + + return os.WriteFile(dest, data, srcFs.Mode()) +} + +// puts key from ./testdata/{keyName} to $HOME/.ssh/{keyName} +// those keys are also supposed to be in authorized_keys of the test container +func withKey(t *testing.T, keyName string) func(t *testing.T) func() { + t.Helper() + + return func(t *testing.T) func() { + t.Helper() + var err error + + home, err := os.UserHomeDir() + if err != nil { + t.Fatal(err) + } + + err = os.MkdirAll(filepath.Join(home, ".ssh"), 0700) + if err != nil { + t.Fatal(err) + } + + keySrc := filepath.Join("testdata", keyName) + keyDest := filepath.Join(home, ".ssh", keyName) + err = cp(keySrc, keyDest) + if err != nil { + t.Fatal(err) + } + + return func() { + os.Remove(keyDest) + } + } +} + +// sets clean temporary $HOME for test +// this prevents interaction with actual user home which may contain .ssh/ +func withCleanHome(t *testing.T) func() { + t.Helper() + homeName := "HOME" + if runtime.GOOS == "windows" { + homeName = "USERPROFILE" + } + tmpDir := t.TempDir() + oldHome, hadHome := os.LookupEnv(homeName) + os.Setenv(homeName, tmpDir) + + return func() { + if hadHome { + os.Setenv(homeName, oldHome) + } else { + os.Unsetenv(homeName) + } + } +} + +// generates `known_hosts` with test container keys and puts it into $HOME/.ssh/known_hosts +func withKnowHosts(t *testing.T) func() { + t.Helper() + knownHosts := filepath.Join(homedir.Get(), ".ssh", "known_hosts") + + err := os.MkdirAll(filepath.Join(homedir.Get(), ".ssh"), 0700) + if err != nil { + t.Fatal(err) + } + + _, err = os.Stat(knownHosts) + if err == nil || !errors.Is(err, os.ErrNotExist) { + t.Fatal("known_hosts already exists") + } + + f, err := os.OpenFile(knownHosts, os.O_CREATE|os.O_WRONLY, 0600) + if err != nil { + t.Fatal(err) + } + defer f.Close() + + // generate known_hosts + serverKeysDir := filepath.Join("testdata", "etc", "ssh") + for _, k := range []string{"ecdsa"} { + keyPath := filepath.Join(serverKeysDir, fmt.Sprintf("ssh_host_%s_key.pub", k)) + key, err := os.ReadFile(keyPath) + if err != nil { + t.Fatal(t) + } + + fmt.Fprintf(f, "%s %s", containerIP4, string(key)) + fmt.Fprintf(f, "[%s]:2222 %s", containerIP4, string(key)) + + if containerIP6 != "" { + fmt.Fprintf(f, "%s %s", containerIP6, string(key)) + fmt.Fprintf(f, "[%s]:2222 %s", containerIP6, string(key)) + } + } + + return func() { + os.Remove(knownHosts) + } +} + +// creates $HOME/.ssh/known_hosts such that is does not match with keys in the test container +func withBadKnownHosts(t *testing.T) func() { + t.Helper() + + knownHosts := filepath.Join(homedir.Get(), ".ssh", "known_hosts") + + err := os.MkdirAll(filepath.Join(homedir.Get(), ".ssh"), 0700) + if err != nil { + t.Fatal(err) + } + + _, err = os.Stat(knownHosts) + if err == nil || !errors.Is(err, os.ErrNotExist) { + t.Fatal("known_hosts already exists") + } + + f, err := os.OpenFile(knownHosts, os.O_CREATE|os.O_WRONLY, 0600) + if err != nil { + t.Fatal(err) + } + defer f.Close() + + knownHostTemplate := `{{range $host := .}}{{$host}} ssh-dss AAAAB3NzaC1kc3MAAACBAKH4ufS3ABVb780oTgEL1eu+pI1p6YOq/1KJn5s3zm+L3cXXq76r5OM/roGEYrXWUDGRtfVpzYTAKoMWuqcVc0AZ2zOdYkoy1fSjJ3MqDGF53QEO3TXIUt3gUzmLOewwmZWle0RgMa9GHccv7XVVIZB36RR68ZEUswLaTnlVhXQ1AAAAFQCl4t/LnY7kuUI+tL2qT2XmxmiyqwAAAIB72XaO+LfyIiqBOaTkQf+5rvH1i6y6LDO1QD9pzGWUYw3y03AEveHJMjW0EjnYBKJjK39wcZNTieRyU54lhH/HWeWABn9NcQ3duEf1WSO/s7SPsFO2R6quqVSsStkqf2Yfdy4fl24mH41olwtNA6ft5nkVfkqrIa51si4jU8fBVAAAAIB8SSvyYBcyMGLUlQjzQqhhhAHer9x/1YbknVz+y5PHJLLjHjMC4ZRfLgNEojvMKQW46Te9Pwnudcwv19ho4F+kkCOfss7xjyH70gQm6Sj76DxClmnnPoSRq3qEAOMy5Oh+7vyzxm68KHqd/aOmUaiT1LgqgViS9+kNdCoVMGAMOg== mvasek@bellatrix +{{$host}} ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBLTxVVaQ93ReqHNlbjg5/nBRpuRuG6JIgNeJXWT1V4Dl+dMMrnad3uJBfyrNpvn8rv2qnn6gMTZVtTbLdo96pG0= mvasek@bellatrix +{{$host}} ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOKymJNQszrxetVffPZRfZGKWK786r0mNcg/Wah4+2wn mvasek@bellatrix +{{$host}} ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC/1/OCwec2Gyv5goNYYvos4iOA+a0NolOGsZA/93jmSArPY1zZS1UWeJ6dDTmxGoL/e7jm9lM6NJY7a/zM0C/GqCNRGR/aCUHBJTIgGtH+79FDKO/LWY6ClGY7Lw8qNgZpugbBw3N3HqTtyb2lELhFLT0FEb+le4WUbryooLK2zsz6DnqV4JvTYyyHcanS0h68iSXC7XbkZchvL99l5LT0gD1oDteBPKKFdNOwIjpMkk/IrbFM24xoNkaTDXN87EpQPQzYDfsoGymprc5OZZ8kzrtErQR+yfuunHfzzqDHWi7ga5pbgkuxNt10djWgCfBRsy07FTEgV0JirS0TCfwTBbqRzdjf3dgi8AP+WtkW3mcv4a1XYeqoBo2o9TbfyiA9kERs79UBN0mCe3KNX3Ns0PvutsRLaHmdJ49eaKWkJ6GgL37aqSlIwTixz2xY3eoDSkqHoZpx6Q1MdpSIl5gGVzlaobM/PNM1jqVdyUj+xpjHyiXwHQMKc3eJna7s8Jc= mvasek@bellatrix +{{end}}` + + tmpl := template.New(knownHostTemplate) + tmpl, err = tmpl.Parse(knownHostTemplate) + if err != nil { + t.Fatal(err) + } + + hosts := make([]string, 0, 4) + hosts = append(hosts, containerIP4, fmt.Sprintf("[%s]:2222", containerIP4)) + if containerIP6 != "" { + hosts = append(hosts, containerIP6, fmt.Sprintf("[%s]:2222", containerIP6)) + } + + err = tmpl.Execute(f, hosts) + if err != nil { + t.Fatal(err) + } + + return func() { + os.Remove(knownHosts) + } +} + +func withEmptyKnownHosts(t *testing.T) func() { + t.Helper() + + knownHosts := filepath.Join(homedir.Get(), ".ssh", "known_hosts") + + err := os.MkdirAll(filepath.Join(homedir.Get(), ".ssh"), 0700) + if err != nil { + t.Fatal(err) + } + + _, err = os.Stat(knownHosts) + if err == nil || !errors.Is(err, os.ErrNotExist) { + t.Fatal("known_hosts already exists") + } + + _, err = os.Create(knownHosts) + if err != nil { + t.Fatal(err) + } + + return func() { + os.Remove(knownHosts) + } +} + +// unsets environment variable so ssh-agent is not used by test +func withoutSSHAgent(t *testing.T) func() { + t.Helper() + oldAuthSock, hadAuthSock := os.LookupEnv("SSH_AUTH_SOCK") + os.Unsetenv("SSH_AUTH_SOCK") + + return func() { + if hadAuthSock { + os.Setenv("SSH_AUTH_SOCK", oldAuthSock) + } else { + os.Unsetenv("SSH_AUTH_SOCK") + } + } +} + +// starts serving ssh-agent on temporary unix socket +// returns clean up routine that stops the server +func withSSHAgent(t *testing.T) func() { + t.Helper() + + key, err := ioutil.ReadFile(filepath.Join("testdata", "id_ed25519")) + if err != nil { + t.Fatal(err) + } + signer, err := ssh.ParsePrivateKey(key) + if err != nil { + t.Fatal(err) + } + + tmpDirForSocket := t.TempDir() + agentSocketPath := filepath.Join(tmpDirForSocket, "agent.sock") + unixListener, err := net.Listen("unix", agentSocketPath) + if err != nil { + t.Fatal(err) + } + os.Setenv("SSH_AUTH_SOCK", agentSocketPath) + + ctx, cancel := context.WithCancel(context.Background()) + errChan := make(chan error, 1) + var wg sync.WaitGroup + + go func() { + for { + conn, err := unixListener.Accept() + if err != nil { + errChan <- err + + return + } + + wg.Add(1) + go func(conn net.Conn) { + defer wg.Done() + go func() { + <-ctx.Done() + conn.Close() + }() + err := agent.ServeAgent(signerAgent{signer}, conn) + if err != nil { + if !errors.Is(err, net.ErrClosed) { + fmt.Fprintf(os.Stderr, "agent.ServeAgent() failed: %v\n", err) + } + } + }(conn) + } + }() + + return func() { + os.Unsetenv("SSH_AUTH_SOCK") + + err := unixListener.Close() + if err != nil { + t.Fatal(err) + } + err = <-errChan + if !errors.Is(err, net.ErrClosed) { + t.Fatal(err) + } + cancel() + wg.Wait() + } +} + +type signerAgent struct { + impl ssh.Signer +} + +func (a signerAgent) List() ([]*agent.Key, error) { + return []*agent.Key{{ + Format: a.impl.PublicKey().Type(), + Blob: a.impl.PublicKey().Marshal(), + }}, nil +} + +func (a signerAgent) Sign(key ssh.PublicKey, data []byte) (*ssh.Signature, error) { + return a.impl.Sign(nil, data) +} + +func (a signerAgent) Add(key agent.AddedKey) error { + panic("implement me") +} + +func (a signerAgent) Remove(key ssh.PublicKey) error { + panic("implement me") +} + +func (a signerAgent) RemoveAll() error { + panic("implement me") +} + +func (a signerAgent) Lock(passphrase []byte) error { + panic("implement me") +} + +func (a signerAgent) Unlock(passphrase []byte) error { + panic("implement me") +} + +func (a signerAgent) Signers() ([]ssh.Signer, error) { + panic("implement me") +} diff --git a/internal/sshdialer/testdata/Dockerfile b/internal/sshdialer/testdata/Dockerfile new file mode 100644 index 0000000000..ab3214788c --- /dev/null +++ b/internal/sshdialer/testdata/Dockerfile @@ -0,0 +1,30 @@ +FROM docker.io/library/golang:1.16 AS builder + +RUN mkdir /workspace/ +COPY main.go go.mod /workspace/ +WORKDIR /workspace/ +ENV CGO_ENABLED=0 +RUN go build -o serve-socket + +FROM docker.io/library/alpine:3.13.6 + +RUN apk --update add --no-cache openssh bash shadow && rm -rf /var/cache/apk/* + +COPY etc/ssh /etc/ssh +RUN chmod og-rwx /etc/ssh/*_key +COPY entrypoint.sh /usr/local/bin + +RUN addgroup testuser && adduser testuser -G testuser -D +RUN echo "root:iddqd" | chpasswd +RUN echo "testuser:idkfa" | chpasswd + +RUN su testuser && mkdir /home/testuser/.ssh/ +COPY --chown=testuser:testuser id_ed25519.pub id_rsa.pub /tmp/ +RUN cat /tmp/id_ed25519.pub /tmp/id_rsa.pub >> /home/testuser/.ssh/authorized_keys + +COPY --from=builder /workspace/serve-socket /usr/local/bin + +EXPOSE 22 +EXPOSE 2222 + +CMD ["entrypoint.sh"] diff --git a/internal/sshdialer/testdata/entrypoint.sh b/internal/sshdialer/testdata/entrypoint.sh new file mode 100755 index 0000000000..9bf7b506b2 --- /dev/null +++ b/internal/sshdialer/testdata/entrypoint.sh @@ -0,0 +1,5 @@ +#!/usr/bin/env bash + +/usr/sbin/sshd + +su - testuser -c '/usr/local/bin/serve-socket "/home/testuser/test.sock"' diff --git a/internal/sshdialer/testdata/etc/ssh/ssh_host_dsa_key b/internal/sshdialer/testdata/etc/ssh/ssh_host_dsa_key new file mode 100644 index 0000000000..b6cfa3ba17 --- /dev/null +++ b/internal/sshdialer/testdata/etc/ssh/ssh_host_dsa_key @@ -0,0 +1,21 @@ +-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABsgAAAAdzc2gtZH +NzAAAAgQDhtFRnJxDyn1xru4PNNnOyvaYlPzt+l8Jwu1PozLsU+2LPJmZQtYXjUl7d7w/P +MklwmwH/4xuQ+YjkaWD8I+4IA4FZfAJjEuTPXJsze48Fefcorg9TkxRxDPk6vetn3TKSuR +YeBpLDq+Dq1vo/2vBM70KahRQDxVNlYdNbiBG5dQAAABUAjg1kaaW8DHwj326XhjKpkoXR +zwEAAACAfSdptBoh5kQHp1ZAMr4EBzH+PMhRf6sdfHhpUOO+4uhRC5hqIgIm3IA1UG8H5V +2Py6xNvIvELX/UVrtzTeqjxZ8+47WKM+j6fTUp3gx+InLq23bD9U43BP+sUcXIs322LUkb +fBoQzWnXx8lkOQzaeofGc4Cg2NIIA5pWewsEACQAAACBAK2mPPqr8PSHjnW9bqv8MEuc3K +qKHuL4a5fGQA5G5upbFxXgB3MtstTtWO27LVD5wrlLOpEz7Lzwv51GUFpxYRTSv49qliKP +c31QAoEjlpST6Jv9JpERGcCTETwNwyH8TH4gx7Ku0JXaysyJH0rn2UTCUAhNmMpiO5tSb5 +PCwK94AAAB6ItbM9KLWzPSAAAAB3NzaC1kc3MAAACBAOG0VGcnEPKfXGu7g802c7K9piU/ +O36XwnC7U+jMuxT7Ys8mZlC1heNSXt3vD88ySXCbAf/jG5D5iORpYPwj7ggDgVl8AmMS5M +9cmzN7jwV59yiuD1OTFHEM+Tq962fdMpK5Fh4GksOr4OrW+j/a8EzvQpqFFAPFU2Vh01uI +Ebl1AAAAFQCODWRppbwMfCPfbpeGMqmShdHPAQAAAIB9J2m0GiHmRAenVkAyvgQHMf48yF +F/qx18eGlQ477i6FELmGoiAibcgDVQbwflXY/LrE28i8Qtf9RWu3NN6qPFnz7jtYoz6Pp9 +NSneDH4icurbdsP1TjcE/6xRxcizfbYtSRt8GhDNadfHyWQ5DNp6h8ZzgKDY0ggDmlZ7Cw +QAJAAAAIEAraY8+qvw9IeOdb1uq/wwS5zcqooe4vhrl8ZADkbm6lsXFeAHcy2y1O1Y7bst +UPnCuUs6kTPsvPC/nUZQWnFhFNK/j2qWIo9zfVACgSOWlJPom/0mkREZwJMRPA3DIfxMfi +DHsq7QldrKzIkfSufZRMJQCE2YymI7m1Jvk8LAr3gAAAAUdboNp8quoeOloagm/Or8qP1d +zwMAAAAQbXZhc2VrQGJlbGxhdHJpeAEC +-----END OPENSSH PRIVATE KEY----- diff --git a/internal/sshdialer/testdata/etc/ssh/ssh_host_dsa_key.pub b/internal/sshdialer/testdata/etc/ssh/ssh_host_dsa_key.pub new file mode 100644 index 0000000000..291a3f583e --- /dev/null +++ b/internal/sshdialer/testdata/etc/ssh/ssh_host_dsa_key.pub @@ -0,0 +1 @@ +ssh-dss AAAAB3NzaC1kc3MAAACBAOG0VGcnEPKfXGu7g802c7K9piU/O36XwnC7U+jMuxT7Ys8mZlC1heNSXt3vD88ySXCbAf/jG5D5iORpYPwj7ggDgVl8AmMS5M9cmzN7jwV59yiuD1OTFHEM+Tq962fdMpK5Fh4GksOr4OrW+j/a8EzvQpqFFAPFU2Vh01uIEbl1AAAAFQCODWRppbwMfCPfbpeGMqmShdHPAQAAAIB9J2m0GiHmRAenVkAyvgQHMf48yFF/qx18eGlQ477i6FELmGoiAibcgDVQbwflXY/LrE28i8Qtf9RWu3NN6qPFnz7jtYoz6Pp9NSneDH4icurbdsP1TjcE/6xRxcizfbYtSRt8GhDNadfHyWQ5DNp6h8ZzgKDY0ggDmlZ7CwQAJAAAAIEAraY8+qvw9IeOdb1uq/wwS5zcqooe4vhrl8ZADkbm6lsXFeAHcy2y1O1Y7bstUPnCuUs6kTPsvPC/nUZQWnFhFNK/j2qWIo9zfVACgSOWlJPom/0mkREZwJMRPA3DIfxMfiDHsq7QldrKzIkfSufZRMJQCE2YymI7m1Jvk8LAr3g= mvasek@bellatrix diff --git a/internal/sshdialer/testdata/etc/ssh/ssh_host_ecdsa_key b/internal/sshdialer/testdata/etc/ssh/ssh_host_ecdsa_key new file mode 100644 index 0000000000..08a9d8c0fa --- /dev/null +++ b/internal/sshdialer/testdata/etc/ssh/ssh_host_ecdsa_key @@ -0,0 +1,9 @@ +-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAaAAAABNlY2RzYS +1zaGEyLW5pc3RwMjU2AAAACG5pc3RwMjU2AAAAQQRDB1fPXY58fSwaqyoj5lCfLtQ/NcIs +grKTA11vypVy9MUCWtdAQIXczmtRMTFCVozk3lwt9M4iKc79nCkkkfyrAAAAsPgat2v4Gr +drAAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBEMHV89djnx9LBqr +KiPmUJ8u1D81wiyCspMDXW/KlXL0xQJa10BAhdzOa1ExMUJWjOTeXC30ziIpzv2cKSSR/K +sAAAAhAIcs2smJGAEKOvzL8Rfz5b1IpQqB8GzxycT3/53XOzaSAAAAEG12YXNla0BiZWxs +YXRyaXgBAgMEBQYH +-----END OPENSSH PRIVATE KEY----- diff --git a/internal/sshdialer/testdata/etc/ssh/ssh_host_ecdsa_key.pub b/internal/sshdialer/testdata/etc/ssh/ssh_host_ecdsa_key.pub new file mode 100644 index 0000000000..922ed1926d --- /dev/null +++ b/internal/sshdialer/testdata/etc/ssh/ssh_host_ecdsa_key.pub @@ -0,0 +1 @@ +ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBEMHV89djnx9LBqrKiPmUJ8u1D81wiyCspMDXW/KlXL0xQJa10BAhdzOa1ExMUJWjOTeXC30ziIpzv2cKSSR/Ks= mvasek@bellatrix diff --git a/internal/sshdialer/testdata/etc/ssh/ssh_host_ed25519_key b/internal/sshdialer/testdata/etc/ssh/ssh_host_ed25519_key new file mode 100644 index 0000000000..914ede587b --- /dev/null +++ b/internal/sshdialer/testdata/etc/ssh/ssh_host_ed25519_key @@ -0,0 +1,7 @@ +-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW +QyNTUxOQAAACAhhd7wuRBaf9R7Q/HQi7lEWoukb/HrYDg394NpeOgsbAAAAJjz02VI89Nl +SAAAAAtzc2gtZWQyNTUxOQAAACAhhd7wuRBaf9R7Q/HQi7lEWoukb/HrYDg394NpeOgsbA +AAAEC9lvHqAASWXcZSm/Rih3V78uMejs+6sc6SOVhaogLwHyGF3vC5EFp/1HtD8dCLuURa +i6Rv8etgODf3g2l46CxsAAAAEG12YXNla0BiZWxsYXRyaXgBAgMEBQ== +-----END OPENSSH PRIVATE KEY----- diff --git a/internal/sshdialer/testdata/etc/ssh/ssh_host_ed25519_key.pub b/internal/sshdialer/testdata/etc/ssh/ssh_host_ed25519_key.pub new file mode 100644 index 0000000000..328d03fc7c --- /dev/null +++ b/internal/sshdialer/testdata/etc/ssh/ssh_host_ed25519_key.pub @@ -0,0 +1 @@ +ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICGF3vC5EFp/1HtD8dCLuURai6Rv8etgODf3g2l46Cxs mvasek@bellatrix diff --git a/internal/sshdialer/testdata/etc/ssh/ssh_host_rsa_key b/internal/sshdialer/testdata/etc/ssh/ssh_host_rsa_key new file mode 100644 index 0000000000..8958a0e2a5 --- /dev/null +++ b/internal/sshdialer/testdata/etc/ssh/ssh_host_rsa_key @@ -0,0 +1,38 @@ +-----BEGIN OPENSSH PRIVATE KEY----- +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 +-----END OPENSSH PRIVATE KEY----- diff --git a/internal/sshdialer/testdata/etc/ssh/ssh_host_rsa_key.pub b/internal/sshdialer/testdata/etc/ssh/ssh_host_rsa_key.pub new file mode 100644 index 0000000000..6276d2d9ae --- /dev/null +++ b/internal/sshdialer/testdata/etc/ssh/ssh_host_rsa_key.pub @@ -0,0 +1 @@ +ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDVUeZF20fM6EJkKZytgl0X1WN09Ndz0eJ30HN7GTRB+cboLXmA7JtuZflhXGBWIfOuulqh0sMJgFa7j6XYM94bmBohrxrVYCGC8RBF8mHT0lxWRVZ3P0DtSaC1vqTd3RDCVhpmstLVJkZiD6KjGiV5vMCz/52bXJ+RJFc1/d8+6HK5s7oAgEwF1ycjPdzC7c1m/qjcuyEVjKbsNpcD8t0fCYxl7YlqSypJtp9trGpnqQiO9ZR46sjpH/e4tYzUFMyKv2KefyJGtzGcC1JUb5DleC9qQ+5kNe/PI8/rqQ5ydPXHwMMdzLg8PRLLO0MiMdZen9cHCoOpZBuGJQFo6N7Jgnqqj1kmesahqKnkDxOUq1oMVLppfWhsfFh635K8DmwqNr9zHfc0uHQVF9ddmaSeAS+uY/2gZf8B6AxNvMT63aQoNTzQzJ7UubFY397xG52JvjWFVNnRTw9lweaAA4xyYZ8DiJWZZz68Rzmhh5jRZKT/NAoFNg2VCw3Dr47upPc= mvasek@bellatrix diff --git a/internal/sshdialer/testdata/etc/ssh/sshd_config b/internal/sshdialer/testdata/etc/ssh/sshd_config new file mode 100644 index 0000000000..95740bbc89 --- /dev/null +++ b/internal/sshdialer/testdata/etc/ssh/sshd_config @@ -0,0 +1,119 @@ +# $OpenBSD: sshd_config,v 1.103 2018/04/09 20:41:22 tj Exp $ + +# This is the sshd server system-wide configuration file. See +# sshd_config(5) for more information. + +# This sshd was compiled with PATH=/bin:/usr/bin:/sbin:/usr/sbin + +# The strategy used for options in the default sshd_config shipped with +# OpenSSH is to specify options with their default value where +# possible, but leave them commented. Uncommented options override the +# default value. + +Port 22 +Port 2222 +AddressFamily any +ListenAddress 0.0.0.0 +ListenAddress :: + +HostKey /etc/ssh/ssh_host_ecdsa_key +HostKey /etc/ssh/ssh_host_ed25519_key +HostKey /etc/ssh/ssh_host_rsa_key +HostKey /etc/ssh/ssh_host_dsa_key + +# Ciphers and keying +#RekeyLimit default none + +# Logging +#SyslogFacility AUTH +#LogLevel INFO + +# Authentication: + +#LoginGraceTime 2m +PermitRootLogin yes +#StrictModes yes +#MaxAuthTries 6 +#MaxSessions 10 + +#PubkeyAuthentication yes + +# The default is to check both .ssh/authorized_keys and .ssh/authorized_keys2 +# but this is overridden so installations will only check .ssh/authorized_keys +AuthorizedKeysFile .ssh/authorized_keys + +#AuthorizedPrincipalsFile none + +#AuthorizedKeysCommand none +#AuthorizedKeysCommandUser nobody + +# For this to work you will also need host keys in /etc/ssh/ssh_known_hosts +#HostbasedAuthentication no +# Change to yes if you don't trust ~/.ssh/known_hosts for +# HostbasedAuthentication +#IgnoreUserKnownHosts no +# Don't read the user's ~/.rhosts and ~/.shosts files +#IgnoreRhosts yes + +# To disable tunneled clear text passwords, change to no here! +PasswordAuthentication yes +#PermitEmptyPasswords no + +# Change to no to disable s/key passwords +#ChallengeResponseAuthentication yes + +# Kerberos options +#KerberosAuthentication no +#KerberosOrLocalPasswd yes +#KerberosTicketCleanup yes +#KerberosGetAFSToken no + +# GSSAPI options +#GSSAPIAuthentication no +#GSSAPICleanupCredentials yes + +# Set this to 'yes' to enable PAM authentication, account processing, +# and session processing. If this is enabled, PAM authentication will +# be allowed through the ChallengeResponseAuthentication and +# PasswordAuthentication. Depending on your PAM configuration, +# PAM authentication via ChallengeResponseAuthentication may bypass +# the setting of "PermitRootLogin without-password". +# If you just want the PAM account and session checks to run without +# PAM authentication, then enable this but set PasswordAuthentication +# and ChallengeResponseAuthentication to 'no'. +#UsePAM no + +#AllowAgentForwarding yes +# Feel free to re-enable these if your use case requires them. +AllowTcpForwarding yes +GatewayPorts no +X11Forwarding no +#X11DisplayOffset 10 +#X11UseLocalhost yes +#PermitTTY yes +#PrintMotd yes +#PrintLastLog yes +#TCPKeepAlive yes +#PermitUserEnvironment no +#Compression delayed +#ClientAliveInterval 0 +#ClientAliveCountMax 3 +#UseDNS no +#PidFile /run/sshd.pid +#MaxStartups 10:30:100 +#PermitTunnel no +#ChrootDirectory none +#VersionAddendum none + +# no default banner path +#Banner none + +# override default of no subsystems +Subsystem sftp /usr/lib/ssh/sftp-server + +# Example of overriding settings on a per-user basis +#Match User anoncvs +# X11Forwarding no +# AllowTcpForwarding no +# PermitTTY no +# ForceCommand cvs server diff --git a/internal/sshdialer/testdata/go.mod b/internal/sshdialer/testdata/go.mod new file mode 100644 index 0000000000..63aed47b89 --- /dev/null +++ b/internal/sshdialer/testdata/go.mod @@ -0,0 +1,3 @@ +module serve-socket + +go 1.16 diff --git a/internal/sshdialer/testdata/id_ed25519 b/internal/sshdialer/testdata/id_ed25519 new file mode 100644 index 0000000000..f04bad68d0 --- /dev/null +++ b/internal/sshdialer/testdata/id_ed25519 @@ -0,0 +1,7 @@ +-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW +QyNTUxOQAAACCVbPGj8U+Zjq5NEgyP2996RFk+lIrXNMYLqLLikeJRJQAAAJjDwa3Yw8Gt +2AAAAAtzc2gtZWQyNTUxOQAAACCVbPGj8U+Zjq5NEgyP2996RFk+lIrXNMYLqLLikeJRJQ +AAAEDti7Y7pPMfJq3Cwztd3ZiM1orRTIibsTH2Y/NQPPFiHpVs8aPxT5mOrk0SDI/b33pE +WT6Uitc0xguosuKR4lElAAAAFHRlc3R1c2VyQGV4YW1wbGUuY29tAQ== +-----END OPENSSH PRIVATE KEY----- diff --git a/internal/sshdialer/testdata/id_ed25519.pub b/internal/sshdialer/testdata/id_ed25519.pub new file mode 100644 index 0000000000..446c7f4bcc --- /dev/null +++ b/internal/sshdialer/testdata/id_ed25519.pub @@ -0,0 +1 @@ +ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJVs8aPxT5mOrk0SDI/b33pEWT6Uitc0xguosuKR4lEl testuser@example.com diff --git a/internal/sshdialer/testdata/id_rsa b/internal/sshdialer/testdata/id_rsa new file mode 100644 index 0000000000..a194f218c3 --- /dev/null +++ b/internal/sshdialer/testdata/id_rsa @@ -0,0 +1,50 @@ +-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jdHIAAAAGYmNyeXB0AAAAGAAAABBqK6VQTJ +8oCGZAMOYnHQg4AAAAEAAAAAEAAAIXAAAAB3NzaC1yc2EAAAADAQABAAACAQDe2RqNezOI +3cRJq+PQYlcASjYRaJgFd/AjAYtB+u8C7C8OkuelIaiYavjUn1+Sx3VOkqSVwA7J7zUzUP +cx/83BjCffvHtXLAmYfxojd9Z7Bh05kV1Ayx7Pn8xEbEkZpffLGrIy98Vs2MYUU7K7JhLO +InkEfD1qolV5IpoIKazkulJEpsdTalrSn53IO0Afa+aayZIG+Fc4RiTHUqk6YcLZQnAcUA +oa6WCC31cIOhbllv83hVwjx9b5ZgX509o/WrBsR2cnL7qemBDJmq4RkL6RVcM0lyaGyMn+ +PfYCXbx4pn3bxdw7An3BS3/O/hTEFLh2tCJc55u7xbKJX265RpKMt/BdU8+VLuA8assVBk +NhDwlLI+jvmC8fzqE7H/PLWO2XgTkMpDybEy2n4+8nRElnj4RB2J+vagiJPZFrr5SWQHMU +D8fHAYvWo0AHPLly+NgkEu2ZRoAV3gRwZm4C8u9tXMNf4UNVcyxpgaylZwxnaiLNjwx6UC +hcA0TAAGPygJ3UJ8D/Gakj3iekOd7Zcl7oE9dzByjIolVaPqXChAjfB8wWSiJ2LZRhVklL +wHm+wKLEpIBhzai4OnF6k4NTyo1wxlfHb90rbyfn6/arUTJX7cU1NFd7cUw0lh+fL/Q15n +JZsd5oCNt3yCTS9fpo9rPPPjCkL+XqUzVVOgbRK5IknwAAB1BqWuTHt/A4IsbG6ieTHPDv +CuxsBR8OlbLcI3+QYoa0KR3fVgJbP4IWx5c/RkzF6+t394a3xkat8CYaQyZOmEcNCB4cAH +qYnFTrEY6Q+zB76THbGPt1/1GQS3Y/UJsum4PYUG9cgT+ckmV7Zuk7Zcd3mP/kpRnDOHX4 +ptKARsD8gCttLUu0UbdFoV/cLqDxvpc4VY2hxV/zP30wrP4w/o4ajvQIPji3QR52K4oQpq +gFy1hitMS7rl/VduX7wQe/xRQeZmln7LywMEhC8IFLJsEFg1IqLPeiVM52GBBH1uBQLPRs +AmiLLeCgP8DGPqwp+AGkWFmlHC+OVDxos0S43WlePgrLfWBfr0z+ezAMLVskkDqtkflZC9 +VbFA7caV+7W508YhXjWf+D0HP48jhjfsX8ZtDyG1hI/zW6l5hDeTAvyNH6f8VJ88P4kKXe +SuvIOcMiBHJKw3lsQb7/bx9byVcy+dLrfttceITm/m+ebK+IYlrmR2qPWwJR43o0l9oyvO +UDahn5qUFFP7HhAEFsg6X03nT200IIaqdc3K7+KfY+OdhP2H33e0e3wbMglgKqd2a4Co/o +LLAq3V8/ViEdxhWZgNruy4AnzVsA18vmLvIk5cEh/jOMkB/O10hCpfRbQp/MEHT5a8BQph +LYNLFLF4WrpSPJwRvNjCbW5IDH0bNh6ochwX0kzv18djPYe1mEhR22MaQMYP3VivXB2A8c +v44dk6dQfzP7qqCYJP+GueGvRpvZTwC86R6wS/ppPCe4mbF0ANgB+x7UqkXzCpJ9CxaPl+ +EpbYmJVaHzWjxfVGWKAX1rZq3wfO0tLwppNkpVvi9ntNPx6frwEUcuiQ0aaF9Jutv3Voxn +qA2wq5koWrUZuvu5GlwADlNhXh6kN2z6MCajGBTJ2KzvN80BnzqrL5LCYMJLWYWma4WYSD +EOIcDeZxBtE23FmJTMf3WcexB6gGCmHoumC7rvnEpjWM2MFct1gzBhKfSciFbjQYxYH/je +OgVyTsGr7ypqbyEAb/Ao4NWD97XV4WDXTmpI239pndEZjYetRUAhESEIG69a6KIPFPLD7m +d2zFONaL6okT8ozr/CAE7Q8z6SPRC5tx4lmFatXGW0i3LjSK90ilw8R9v4Ji7RXVSsWxBd +kqcodchO2w1OWVVo/xqeEmvJKms8uYf2EpZfaCNS7WsZPJYHulwSG9WX0SabYRO+k9w3rj +PjEP9DS6VV/j2TEkCoNhEuR3VF0GlVbfNfFfefsrfH6FmTawW8UFvMYoPNxgH3sZAjvfzx +RGC3Iysvao72wNBIlDowgUPap8A+snUgQZ4YoCefhGSbcPDeuqqx6bDlEUVQkeEARYWgj6 +xek869h045LbDqdKiQbjhBpuIRbe7cjKjIBgG7X2Vl/W7fOMoHN8QOW6Y+Tzohyz8rEmAp +MRgXlqs2hO/LGs28EXBUxKgaaQghzVz/LwGe06bUFRUL0ERaI2wHvM2a/mYgnMYytFeFFG +ICqnF+0dPLeUuoQBT3KWGspGa6tR+ZA11GBCK+7TYZi23e1n0zQptxl1me16q/NGHNfpQf +GEKCML2RzSH+1p9hflIRMN1WQMRzPHu6gTHJkxnlKrTBGgHwAaG7vCEaQTbIcHVnenIjB5 +Fntxr2gEz5dyiKnS52D2uNbJDhUu/Z/hKw8pTmLC7YcZO+wTneFtaZ4AxcMQXG5xF51vjy +Pow72o0M6gL1s6te9BmiYFxfmIWERmJ+mlmR80JSTVFcjma38bWX567gooXTyvd+GvaVIl +mIx6EjdRqe5TK/r+JU92ggcyobTZI6iaYaOBSpi/i4hbpWX6n2RIoN1HYui5CMf2wvQT2F +jFrbmbi24d8xSw6DJeiDXuPVdIdYVqcLWIfAdNgNzVGw2cmagzTLjQrRZlCnpjTY/Uznj1 +J7LivTdju+Pb7rbbxFJqeubnee/1gga2sIk2lgGcgOQmaDI8QMms4Pt47rG2w2hluP054V +m918D7Y3dNNwJnp0G6Wv2Ecyo5A2oS4Jd6g1szn4dW7C6J5vWI8+eZyhW8VIKtDlMOftJX +5DkEeXKrJD8+1WBo2kK2E+sfpzSvHjQQ0jXe39JMnogyNt45batknxLk+llZSNbkWI1IiR +VzB7wkeH/r/zvz+pOSan1PXI0P+JYqEx7PEk4EL5hXwMViMUrZEgGxaMqFdWpjnY3fzA7J +iF4NoP2Gy21bC2KiZ4/3PshSBPprYkAyfkgQZrlgD1+ubcMYYrbVWK/bilyuDv/tQaW0Wi +F4SsQaMRm8X/5wth5CH1M46diExCajv5HKMOuTJ0ML3oJphyuvUpmuvHG+VcU/tgKEDgJM +1FWoLJqgdlNspUZYcQYTU2MH8sQFDNNnn3TFxFfKmdtLxpsKq1OGIuNPJKPGfd9kiUw4kP +HKhZDUt2MpCtjKzl/wyGt+giNUL2t51XAT1eqA4Z1FfFU7ZtSQoZ95JA5VfR1yl8F6rWq8 +MUnDXSP1KUo0fm3Ojh6J25+2w= +-----END OPENSSH PRIVATE KEY----- diff --git a/internal/sshdialer/testdata/id_rsa.pub b/internal/sshdialer/testdata/id_rsa.pub new file mode 100644 index 0000000000..383c923400 --- /dev/null +++ b/internal/sshdialer/testdata/id_rsa.pub @@ -0,0 +1 @@ +ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDe2RqNezOI3cRJq+PQYlcASjYRaJgFd/AjAYtB+u8C7C8OkuelIaiYavjUn1+Sx3VOkqSVwA7J7zUzUPcx/83BjCffvHtXLAmYfxojd9Z7Bh05kV1Ayx7Pn8xEbEkZpffLGrIy98Vs2MYUU7K7JhLOInkEfD1qolV5IpoIKazkulJEpsdTalrSn53IO0Afa+aayZIG+Fc4RiTHUqk6YcLZQnAcUAoa6WCC31cIOhbllv83hVwjx9b5ZgX509o/WrBsR2cnL7qemBDJmq4RkL6RVcM0lyaGyMn+PfYCXbx4pn3bxdw7An3BS3/O/hTEFLh2tCJc55u7xbKJX265RpKMt/BdU8+VLuA8assVBkNhDwlLI+jvmC8fzqE7H/PLWO2XgTkMpDybEy2n4+8nRElnj4RB2J+vagiJPZFrr5SWQHMUD8fHAYvWo0AHPLly+NgkEu2ZRoAV3gRwZm4C8u9tXMNf4UNVcyxpgaylZwxnaiLNjwx6UChcA0TAAGPygJ3UJ8D/Gakj3iekOd7Zcl7oE9dzByjIolVaPqXChAjfB8wWSiJ2LZRhVklLwHm+wKLEpIBhzai4OnF6k4NTyo1wxlfHb90rbyfn6/arUTJX7cU1NFd7cUw0lh+fL/Q15nJZsd5oCNt3yCTS9fpo9rPPPjCkL+XqUzVVOgbRK5Iknw== testuser@example.com diff --git a/internal/sshdialer/testdata/main.go b/internal/sshdialer/testdata/main.go new file mode 100644 index 0000000000..5d2bf107ae --- /dev/null +++ b/internal/sshdialer/testdata/main.go @@ -0,0 +1,33 @@ +package main + +import ( + "context" + "net" + "net/http" + "os" + "os/signal" + "syscall" + "time" +) + +// simple HTTP server to verify that tunneling works +func main() { + sigs := make(chan os.Signal, 1) + signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM) + + unixListener, err := net.Listen("unix", os.Args[1]) + if err != nil { + panic(err) + } + var handler http.HandlerFunc = func(w http.ResponseWriter, req *http.Request) { + w.WriteHeader(200) + w.Write([]byte("Hello there!")) + } + server := http.Server{Handler: handler} + go func() { + <-sigs + shutdownCtx, _ := context.WithTimeout(context.Background(), time.Second*5) + server.Shutdown(shutdownCtx) + }() + server.Serve(unixListener) +}