Compare commits

..

8 Commits

Author SHA1 Message Date
Evan Simkowitz a4ac8be3da attempt to fix the dockerfile for macos 2024-08-28 12:32:41 -07:00
Sujal Goswami fd707dd857 Add devconatainer config file for easy development using VS Code. 2024-08-28 00:17:58 +05:30
Sujal Goswami 71fcc7a542 Update .dockerignore
Co-authored-by: Evan Simkowitz <esimkowitz@users.noreply.github.com>
2024-08-26 15:02:36 +05:30
Sujal Goswami 702446cba8 Update .dockerignore
Co-authored-by: Evan Simkowitz <esimkowitz@users.noreply.github.com>
2024-08-26 15:02:27 +05:30
Sujal Goswami 15acdcc850 Update .dockerignore
Co-authored-by: Evan Simkowitz <esimkowitz@users.noreply.github.com>
2024-08-26 15:02:03 +05:30
Sujal Goswami fc053b06ae Update .dockerignore
Co-authored-by: Evan Simkowitz <esimkowitz@users.noreply.github.com>
2024-08-26 15:01:45 +05:30
Sujal Goswami 37ba95bbe7 Update .dockerignore
Co-authored-by: Evan Simkowitz <esimkowitz@users.noreply.github.com>
2024-08-26 15:01:26 +05:30
Sujal Goswami a5e6885597 chore: containerize project by adding Docker configuration files and ignore unnecessary files 2024-08-26 00:00:48 +05:30
16 changed files with 183 additions and 234 deletions
+16
View File
@@ -0,0 +1,16 @@
{
"name": "Wave Terminal Dev Container",
"dockerComposeFile": "../docker-compose.yml",
"service": "wave",
"workspaceFolder": "/app/waveterm",
"customizations": {
"vscode": {
"settings": {
"terminal.integrated.shell.linux": "/bin/bash",
"extensions": ["golang.go", "dbaeumer.vscode-eslint", "esbenp.prettier-vscode"]
}
}
},
"runServices": ["dbus"],
"postAttachCommand": "scripthaus run webpack-watch"
}
+21
View File
@@ -0,0 +1,21 @@
# Ignore node_modules and other dependencies
node_modules
.yarn
# Ignore build directories
build
dist
# Ignore logs and temporary files
logs
*.log
*.tmp
# Ignore test and coverage files
coverage
test-results
# Ignore OS-specific files
.DS_Store
Thumbs.db
+1 -2
View File
@@ -23,9 +23,8 @@ jobs:
- uses: dashcamio/testdriver@main
id: testdriver
with:
version: v3.9.0
version: v3.6.5
key: ${{secrets.DASHCAM_API}}
os: mac
prerun: |
cd ~/actions-runner/_work/testdriver/testdriver/
brew install go
+28 -36
View File
@@ -1,37 +1,29 @@
version: 3.8.0
steps:
- prompt: "Focus electron"
commands:
- command: focus-application
name: Electron
- command: hover-text
description: Get started CTA
text: Get Started
action: click
- command: hover-text
description: Settings button
text: Settings
action: click
- command: hover-text
description: font size 13
text: 13px
action: click
- command: hover-text
description: font size 12
text: 12px
action: click
- command: hover-text
description: theme selector
text: Dark
action: click
- command: hover-text
description: theme color white
text: Light
action: click
- command: hover-text
description: workspace
text: workspace-1
action: click
- command: assert
expect: the terminal is white
steps:
- step:
- command: focus-application
name: Electron
- command: hover-text
text: Get Started
action: click
- command: hover-text
text: Settings
action: click
- command: hover-text
text: 13px
action: click
- command: hover-text
text: 12px
action: click
- command: hover-text
text: Dark
action: click
- command: hover-text
text: Light
action: click
- command: hover-text
text: workspace-1
action: click
- step:
- command: assert
expect: the terminal is white
+25
View File
@@ -0,0 +1,25 @@
FROM ubuntu:latest
WORKDIR /app
RUN apt update && \
apt install -y golang-go nodejs npm libgtk2.0-0t64 libgtk-3-0t64 libgbm-dev libnotify-dev libnss3 libxss1 libasound2t64 libxtst6 xauth xvfb && \
npm install -g corepack
RUN corepack enable && \
yarn install
RUN git clone https://github.com/scripthaus-dev/scripthaus.git
WORKDIR /app/scripthaus
RUN CGO_ENABLED=1 go build -o scripthaus cmd/main.go && \
cp scripthaus /usr/local/bin
WORKDIR /app
RUN mkdir waveterm
WORKDIR /app/waveterm
COPY . .
ENV GOFLAGS="-buildvcs=false"
ENV DISPLAY=":0"
RUN useradd -ms /bin/bash wave
+18
View File
@@ -0,0 +1,18 @@
version: '3.8'
services:
wave:
build:
context: .
dockerfile: Dockerfile
container_name: waveterminal
environment:
- DISPLAY=${DISPLAY}
- NODE_ENV=development
volumes:
- /tmp/.X11-unix:/tmp/.X11-unix
- .:/app/waveterm
stdin_open: true
tty: true
ports:
- "3000:3000"
-14
View File
@@ -134,28 +134,14 @@ github.com/zeebo/xxh3 v1.0.2/go.mod h1:5NWz9Sef7zIDm2JHfFlcQvNekmcEl9ekUZQQKCYaD
gitlab.com/nyarla/go-crypt v0.0.0-20160106005555-d9a5dc2b789b/go.mod h1:T3BPAOm2cqquPa0MKWeNkmOM5RQsRhkrwMWonFMN7fE=
go.mongodb.org/mongo-driver v1.7.5/go.mod h1:VXEWRZ6URJIkUq2SCAyapmhH0ZLRBP+FT4xhp5Zvxng=
go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
golang.org/x/exp v0.0.0-20230315142452-642cacee5cc0/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA=
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
golang.org/x/oauth2 v0.1.0/go.mod h1:G9FE4dLTsbXUu90h/Pf85g4w1D+SSAgR+q46nJZ8M4A=
golang.org/x/sync v0.2.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE=
golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.9.1/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc=
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8=
google.golang.org/api v0.106.0/go.mod h1:2Ts0XTHNVWxypznxWOYUeI4g3WdP9Pk2Qk58+a/O9MY=
google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
+1 -1
View File
@@ -101,7 +101,7 @@
"react-split-it": "^2.0.0",
"style-loader": "4.0.0",
"typescript": "^5.5.4",
"webpack": "^5.94.0",
"webpack": "^5.93.0",
"webpack-bundle-analyzer": "^4.10.2",
"webpack-cli": "^5.1.4",
"webpack-dev-server": "^5.0.4",
+2 -2
View File
@@ -76,7 +76,7 @@ function buildWaveShell {
}
function buildWaveSrv {
# adds -extldflags=-static, *only* on linux (macos does not support fully static binaries) to avoid a glibc dependency
(cd wavesrv; CGO_ENABLED=1 GOARCH=$1 go build -tags "osusergo,netcgo,sqlite_omit_load_extension" -ldflags "-linkmode 'external' -extldflags=-static $GO_LDFLAGS -X main.WaveVersion=$WAVESRV_VERSION" -o ../bin/wavesrv.$1 ./cmd)
(cd wavesrv; CGO_ENABLED=1 GOARCH=$1 go build -tags "osusergo,netgo,sqlite_omit_load_extension" -ldflags "-linkmode 'external' -extldflags=-static $GO_LDFLAGS -X main.WaveVersion=$WAVESRV_VERSION" -o ../bin/wavesrv.$1 ./cmd)
}
buildWaveShell darwin amd64
buildWaveShell darwin arm64
@@ -90,7 +90,7 @@ yarn run electron-builder -c electron-builder.config.js -l -p never
# @scripthaus command build-wavesrv
WAVESRV_VERSION=$(node -e 'console.log(require("./version.js"))')
cd wavesrv
CGO_ENABLED=1 go build -tags "osusergo,netcgo,sqlite_omit_load_extension" -ldflags "-X main.BuildTime=$(date +'%Y%m%d%H%M') -X main.WaveVersion=$WAVESRV_VERSION" -o ../bin/wavesrv ./cmd
CGO_ENABLED=1 go build -tags "osusergo,netgo,sqlite_omit_load_extension" -ldflags "-X main.BuildTime=$(date +'%Y%m%d%H%M') -X main.WaveVersion=$WAVESRV_VERSION" -o ../bin/wavesrv ./cmd
```
```bash
-24
View File
@@ -18,7 +18,6 @@ import (
"os/exec"
"regexp"
"sort"
"strconv"
"strings"
"syscall"
"unicode/utf8"
@@ -674,26 +673,3 @@ func GetFirstLine(s string) string {
}
return s[0:idx]
}
func TrimQuotes(s string) (string, bool) {
if len(s) > 2 && s[0] == '"' {
trimmed, err := strconv.Unquote(s)
if err != nil {
return s, false
}
return trimmed, true
}
return s, false
}
func TryTrimQuotes(s string) string {
trimmed, _ := TrimQuotes(s)
return trimmed
}
func ReplaceQuotes(s string, shouldReplace bool) string {
if shouldReplace {
return strconv.Quote(s)
}
return s
}
+3 -4
View File
@@ -17,12 +17,12 @@ require (
github.com/jmoiron/sqlx v1.3.5
github.com/kevinburke/ssh_config v1.2.0
github.com/mattn/go-sqlite3 v1.14.16
github.com/sashabaranov/go-openai v1.30.0
github.com/sashabaranov/go-openai v1.9.0
github.com/sawka/txwrap v0.1.2
github.com/wavetermdev/waveterm/waveshell v0.0.0
golang.org/x/crypto v0.24.0
golang.org/x/crypto v0.17.0
golang.org/x/mod v0.10.0
golang.org/x/sys v0.21.0
golang.org/x/sys v0.15.0
mvdan.cc/sh/v3 v3.7.0
)
@@ -30,7 +30,6 @@ require (
github.com/google/go-querystring v1.1.0 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/go-multierror v1.1.1 // indirect
github.com/skeema/knownhosts v1.3.0 // indirect
go.uber.org/atomic v1.7.0 // indirect
)
-8
View File
@@ -51,12 +51,8 @@ github.com/rogpeppe/go-internal v1.10.1-0.20230524175051-ec119421bb97 h1:3RPlVWz
github.com/rogpeppe/go-internal v1.10.1-0.20230524175051-ec119421bb97/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA=
github.com/sashabaranov/go-openai v1.9.0 h1:NoiO++IISxxJ1pRc0n7uZvMGMake0G+FJ1XPwXtprsA=
github.com/sashabaranov/go-openai v1.9.0/go.mod h1:lj5b/K+zjTSFxVLijLSTDZuP7adOgerWeFyZLUhAKRg=
github.com/sashabaranov/go-openai v1.30.0 h1:fHv9urGxABfm885xGWsXFSk5cksa+8dJ4jGli/UQQcI=
github.com/sashabaranov/go-openai v1.30.0/go.mod h1:lj5b/K+zjTSFxVLijLSTDZuP7adOgerWeFyZLUhAKRg=
github.com/sawka/txwrap v0.1.2 h1:v8xS0Z1LE7/6vMZA81PYihI+0TSR6Zm1MalzzBIuXKc=
github.com/sawka/txwrap v0.1.2/go.mod h1:T3nlw2gVpuolo6/XEetvBbk1oMXnY978YmBFy1UyHvw=
github.com/skeema/knownhosts v1.3.0 h1:AM+y0rI04VksttfwjkSTNQorvGqmwATnvnAHpSgc0LY=
github.com/skeema/knownhosts v1.3.0/go.mod h1:sPINvnADmT/qYH1kfv+ePMmOBTH6Tbl7b5LvTDjFK7M=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
@@ -67,15 +63,11 @@ go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw=
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k=
golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI=
golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM=
golang.org/x/mod v0.10.0 h1:lFO9qtOdlre5W1jxS3r/4szv2/6iXxScdzjoBMXNhYk=
golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws=
golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4=
golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+2 -2
View File
@@ -190,7 +190,7 @@ func RunCompletionStream(ctx context.Context, opts *sstore.OpenAIOptsType, promp
pk := packet.MakeOpenAIPacket()
pk.Index = choice.Index
pk.Text = choice.Delta.Content
pk.FinishReason = string(choice.FinishReason)
pk.FinishReason = choice.FinishReason
rtn <- pk
}
}
@@ -209,7 +209,7 @@ func marshalResponse(resp openaiapi.ChatCompletionResponse) []*packet.OpenAIPack
choicePk := packet.MakeOpenAIPacket()
choicePk.Index = choice.Index
choicePk.Text = choice.Message.Content
choicePk.FinishReason = string(choice.FinishReason)
choicePk.FinishReason = choice.FinishReason
rtn = append(rtn, choicePk)
}
return rtn
+3 -5
View File
@@ -1314,15 +1314,14 @@ func (wsh *WaveshellProc) RunInstall(autoInstall bool) {
wsh.WriteToPtyBuffer("*error: cannot install on a local remote\n")
return
}
sapi, err := shellapi.MakeShellApi(wsh.GetShellType())
_, err = shellapi.MakeShellApi(packet.ShellType_bash)
if err != nil {
wsh.WriteToPtyBuffer("*error: %v\n", err)
return
}
if wsh.Client == nil {
remoteDisplayName := fmt.Sprintf("%s [%s]", remoteCopy.RemoteAlias, remoteCopy.RemoteCanonicalName)
sshAuthSock, _ := exec.CommandContext(makeClientCtx, sapi.GetLocalShellPath(), "-c", "echo \"${SSH_AUTH_SOCK}\"").CombinedOutput()
client, err := ConnectToClient(makeClientCtx, remoteCopy.SSHOpts, remoteDisplayName, strings.TrimSpace(string(sshAuthSock)))
client, err := ConnectToClient(makeClientCtx, remoteCopy.SSHOpts, remoteDisplayName)
if err != nil {
statusErr := fmt.Errorf("ssh cannot connect to client: %w", err)
wsh.setInstallErrorStatus(statusErr)
@@ -1615,8 +1614,7 @@ func (wsh *WaveshellProc) createWaveshellSession(clientCtx context.Context, remo
wsSession = shexec.CmdWrap{Cmd: ecmd}
} else if wsh.Client == nil {
remoteDisplayName := fmt.Sprintf("%s [%s]", remoteCopy.RemoteAlias, remoteCopy.RemoteCanonicalName)
sshAuthSock, _ := exec.CommandContext(clientCtx, sapi.GetLocalShellPath(), "-c", "echo \"${SSH_AUTH_SOCK}\"").CombinedOutput()
client, err := ConnectToClient(clientCtx, remoteCopy.SSHOpts, remoteDisplayName, strings.TrimSpace(string(sshAuthSock)))
client, err := ConnectToClient(clientCtx, remoteCopy.SSHOpts, remoteDisplayName)
if err != nil {
return nil, fmt.Errorf("ssh cannot connect to client: %w", err)
}
+29 -123
View File
@@ -22,23 +22,18 @@ import (
"time"
"github.com/kevinburke/ssh_config"
"github.com/skeema/knownhosts"
"github.com/wavetermdev/waveterm/waveshell/pkg/base"
"github.com/wavetermdev/waveterm/waveshell/pkg/utilfn"
"github.com/wavetermdev/waveterm/wavesrv/pkg/scbus"
"github.com/wavetermdev/waveterm/wavesrv/pkg/sstore"
"github.com/wavetermdev/waveterm/wavesrv/pkg/userinput"
"golang.org/x/crypto/ssh"
"golang.org/x/crypto/ssh/agent"
xknownhosts "golang.org/x/crypto/ssh/knownhosts"
"golang.org/x/crypto/ssh/knownhosts"
)
type UserInputCancelError struct {
Err error
}
type HostKeyAlgorithms = func(hostWithPort string) (algos []string)
func (uice UserInputCancelError) Error() string {
return uice.Err.Error()
}
@@ -70,7 +65,7 @@ func createDummySigner() ([]ssh.Signer, error) {
// they were successes. An error in this function prevents any other
// keys from being attempted. But if there's an error because of a dummy
// file, the library can still try again with a new key.
func createPublicKeyCallback(connCtx context.Context, sshKeywords *SshKeywords, passphrase string, authSockSignersExt []ssh.Signer, agentClient agent.ExtendedAgent) func() ([]ssh.Signer, error) {
func createPublicKeyCallback(connCtx context.Context, sshKeywords *SshKeywords, passphrase string) func() ([]ssh.Signer, error) {
var identityFiles []string
existingKeys := make(map[string][]byte)
@@ -88,19 +83,7 @@ func createPublicKeyCallback(connCtx context.Context, sshKeywords *SshKeywords,
// require pointer to modify list in closure
identityFilesPtr := &identityFiles
var authSockSigners []ssh.Signer
authSockSigners = append(authSockSigners, authSockSignersExt...)
authSockSignersPtr := &authSockSigners
return func() ([]ssh.Signer, error) {
// try auth sock
if len(*authSockSignersPtr) != 0 {
authSockSigner := (*authSockSignersPtr)[0]
*authSockSignersPtr = (*authSockSignersPtr)[1:]
return []ssh.Signer{authSockSigner}, nil
}
// try manual identity files
if len(*identityFilesPtr) == 0 {
return nil, fmt.Errorf("no identity files remaining")
}
@@ -112,24 +95,6 @@ func createPublicKeyCallback(connCtx context.Context, sshKeywords *SshKeywords,
// skip this key and try with the next
return createDummySigner()
}
unencryptedPrivateKey, err := ssh.ParseRawPrivateKey(privateKey)
if err == nil {
signer, err := ssh.NewSignerFromKey(unencryptedPrivateKey)
if err == nil {
if sshKeywords.AddKeysToAgent && agentClient != nil {
agentClient.Add(agent.AddedKey{
PrivateKey: unencryptedPrivateKey,
})
}
return []ssh.Signer{signer}, err
}
}
if _, ok := err.(*ssh.PassphraseMissingError); !ok {
// skip this key and try with the next
return createDummySigner()
}
signer, err := ssh.ParsePrivateKey(privateKey)
if err == nil {
return []ssh.Signer{signer}, err
@@ -139,17 +104,9 @@ func createPublicKeyCallback(connCtx context.Context, sshKeywords *SshKeywords,
return createDummySigner()
}
unencryptedPrivateKey, err = ssh.ParseRawPrivateKeyWithPassphrase(privateKey, []byte(passphrase))
signer, err = ssh.ParsePrivateKeyWithPassphrase(privateKey, []byte(passphrase))
if err == nil {
signer, err := ssh.NewSignerFromKey(unencryptedPrivateKey)
if err == nil {
if sshKeywords.AddKeysToAgent && agentClient != nil {
agentClient.Add(agent.AddedKey{
PrivateKey: unencryptedPrivateKey,
})
}
return []ssh.Signer{signer}, err
}
return []ssh.Signer{signer}, err
}
if err != x509.IncorrectPasswordError && err.Error() != "bcrypt_pbkdf: empty password" {
// skip this key and try with the next
@@ -175,22 +132,11 @@ func createPublicKeyCallback(connCtx context.Context, sshKeywords *SshKeywords,
// trying keys
return nil, UserInputCancelError{Err: err}
}
unencryptedPrivateKey, err = ssh.ParseRawPrivateKeyWithPassphrase(privateKey, []byte([]byte(response.Text)))
signer, err = ssh.ParsePrivateKeyWithPassphrase(privateKey, []byte(response.Text))
if err != nil {
// skip this key and try with the next
return createDummySigner()
}
signer, err = ssh.NewSignerFromKey(unencryptedPrivateKey)
if err != nil {
// skip this key and try with the next
return createDummySigner()
}
if sshKeywords.AddKeysToAgent && agentClient != nil {
agentClient.Add(agent.AddedKey{
PrivateKey: unencryptedPrivateKey,
})
}
return []ssh.Signer{signer}, err
}
}
@@ -410,7 +356,7 @@ func lineContainsMatch(line []byte, matches [][]byte) bool {
return false
}
func createHostKeyCallback(opts *sstore.SSHOpts) (ssh.HostKeyCallback, HostKeyAlgorithms, error) {
func createHostKeyCallback(opts *sstore.SSHOpts) (ssh.HostKeyCallback, error) {
ssh_config.ReloadConfigs()
rawUserKnownHostsFiles, _ := ssh_config.GetStrict(opts.SSHHost, "UserKnownHostsFile")
userKnownHostsFiles := strings.Fields(rawUserKnownHostsFiles) // TODO - smarter splitting escaped spaces and quotes
@@ -419,7 +365,7 @@ func createHostKeyCallback(opts *sstore.SSHOpts) (ssh.HostKeyCallback, HostKeyAl
osUser, err := user.Current()
if err != nil {
return nil, nil, err
return nil, err
}
var unexpandedKnownHostsFiles []string
if osUser.Username == "root" {
@@ -435,7 +381,7 @@ func createHostKeyCallback(opts *sstore.SSHOpts) (ssh.HostKeyCallback, HostKeyAl
// there are no good known hosts files
if len(knownHostsFiles) == 0 {
return nil, nil, fmt.Errorf("no known_hosts files provided by ssh. defaults are overridden")
return nil, fmt.Errorf("no known_hosts files provided by ssh. defaults are overridden")
}
var unreadableFiles []string
@@ -444,10 +390,9 @@ func createHostKeyCallback(opts *sstore.SSHOpts) (ssh.HostKeyCallback, HostKeyAl
// incorrectly. if a problem file is found, it is removed from our list
// and we try again
var basicCallback ssh.HostKeyCallback
var hostKeyAlgorithms HostKeyAlgorithms
for basicCallback == nil && len(knownHostsFiles) > 0 {
var err error
keyDb, err := knownhosts.NewDB(knownHostsFiles...)
basicCallback, err = knownhosts.New(knownHostsFiles...)
if serr, ok := err.(*os.PathError); ok {
badFile := serr.Path
unreadableFiles = append(unreadableFiles, badFile)
@@ -458,26 +403,18 @@ func createHostKeyCallback(opts *sstore.SSHOpts) (ssh.HostKeyCallback, HostKeyAl
}
}
if len(okFiles) >= len(knownHostsFiles) {
return nil, nil, fmt.Errorf("problem file (%s) doesn't exist. this should not be possible", badFile)
return nil, fmt.Errorf("problem file (%s) doesn't exist. this should not be possible", badFile)
}
knownHostsFiles = okFiles
} else if err != nil {
// TODO handle obscure problems if possible
return nil, nil, fmt.Errorf("known_hosts formatting error: %+v", err)
} else {
basicCallback = keyDb.HostKeyCallback()
hostKeyAlgorithms = keyDb.HostKeyAlgorithms
return nil, fmt.Errorf("known_hosts formatting error: %+v", err)
}
}
if basicCallback == nil {
basicCallback = func(hostname string, remote net.Addr, key ssh.PublicKey) error {
return &xknownhosts.KeyError{}
}
// need to return nil here to avoid null pointer from attempting to call
// the one provided by the db if nothing was found
hostKeyAlgorithms = func(hostWithPort string) (algos []string) {
return nil
return &knownhosts.KeyError{}
}
}
@@ -486,21 +423,21 @@ func createHostKeyCallback(opts *sstore.SSHOpts) (ssh.HostKeyCallback, HostKeyAl
if err == nil {
// success
return nil
} else if _, ok := err.(*xknownhosts.RevokedError); ok {
} else if _, ok := err.(*knownhosts.RevokedError); ok {
// revoked credentials are refused outright
return err
} else if _, ok := err.(*xknownhosts.KeyError); !ok {
} else if _, ok := err.(*knownhosts.KeyError); !ok {
// this is an unknown error (note the !ok is opposite of usual)
return err
}
serr, _ := err.(*xknownhosts.KeyError)
serr, _ := err.(*knownhosts.KeyError)
if len(serr.Want) == 0 {
// the key was not found
// try to write to a file that could be read
err := fmt.Errorf("placeholder, should not be returned") // a null value here can cause problems with empty slice
for _, filename := range knownHostsFiles {
newLine := xknownhosts.Line([]string{xknownhosts.Normalize(hostname)}, key)
newLine := knownhosts.Line([]string{knownhosts.Normalize(hostname)}, key)
getUserVerification := createUnknownKeyVerifier(filename, hostname, remote.String(), key)
err = writeToKnownHosts(filename, newLine, getUserVerification)
if err == nil {
@@ -515,7 +452,7 @@ func createHostKeyCallback(opts *sstore.SSHOpts) (ssh.HostKeyCallback, HostKeyAl
// should catch cases where there is no known_hosts file
if err != nil {
for _, filename := range unreadableFiles {
newLine := xknownhosts.Line([]string{xknownhosts.Normalize(hostname)}, key)
newLine := knownhosts.Line([]string{knownhosts.Normalize(hostname)}, key)
getUserVerification := createMissingKnownHostsVerifier(filename, hostname, remote.String(), key)
err = writeToKnownHosts(filename, newLine, getUserVerification)
if err == nil {
@@ -565,7 +502,7 @@ func createHostKeyCallback(opts *sstore.SSHOpts) (ssh.HostKeyCallback, HostKeyAl
return fmt.Errorf("remote host identification has changed")
}
updatedCallback, err := xknownhosts.New(knownHostsFiles...)
updatedCallback, err := knownhosts.New(knownHostsFiles...)
if err != nil {
return err
}
@@ -573,7 +510,7 @@ func createHostKeyCallback(opts *sstore.SSHOpts) (ssh.HostKeyCallback, HostKeyAl
return updatedCallback(hostname, remote, key)
}
return waveHostKeyCallback, hostKeyAlgorithms, nil
return waveHostKeyCallback, nil
}
func DialContext(ctx context.Context, network string, addr string, config *ssh.ClientConfig) (*ssh.Client, error) {
@@ -589,8 +526,8 @@ func DialContext(ctx context.Context, network string, addr string, config *ssh.C
return ssh.NewClient(c, chans, reqs), nil
}
func ConnectToClient(connCtx context.Context, opts *sstore.SSHOpts, remoteDisplayName string, sshAuthSock string) (*ssh.Client, error) {
sshConfigKeywords, err := findSshConfigKeywords(opts.SSHHost, sshAuthSock)
func ConnectToClient(connCtx context.Context, opts *sstore.SSHOpts, remoteDisplayName string) (*ssh.Client, error) {
sshConfigKeywords, err := findSshConfigKeywords(opts.SSHHost)
if err != nil {
return nil, err
}
@@ -600,17 +537,7 @@ func ConnectToClient(connCtx context.Context, opts *sstore.SSHOpts, remoteDispla
return nil, err
}
conn, err := net.Dial("unix", sshKeywords.IdentityAgent)
var authSockSigners []ssh.Signer
var agentClient agent.ExtendedAgent
if err != nil {
log.Printf("Failed to open Identity Agent Socket: %v", err)
} else {
agentClient = agent.NewClient(conn)
authSockSigners, _ = agentClient.Signers()
}
publicKeyCallback := ssh.PublicKeysCallback(createPublicKeyCallback(connCtx, sshKeywords, opts.SSHPassword, authSockSigners, agentClient))
publicKeyCallback := ssh.PublicKeysCallback(createPublicKeyCallback(connCtx, sshKeywords, opts.SSHPassword))
keyboardInteractive := ssh.KeyboardInteractive(createCombinedKbdInteractiveChallenge(connCtx, opts.SSHPassword, remoteDisplayName))
passwordCallback := ssh.PasswordCallback(createCombinedPasswordCallbackPrompt(connCtx, opts.SSHPassword, remoteDisplayName))
@@ -625,7 +552,7 @@ func ConnectToClient(connCtx context.Context, opts *sstore.SSHOpts, remoteDispla
// exclude gssapi-with-mic and hostbased until implemented
authMethodMap := map[string]ssh.AuthMethod{
"publickey": ssh.RetryableAuthMethod(publicKeyCallback, len(sshKeywords.IdentityFile)+len(authSockSigners)),
"publickey": ssh.RetryableAuthMethod(publicKeyCallback, len(sshKeywords.IdentityFile)),
"keyboard-interactive": ssh.RetryableAuthMethod(keyboardInteractive, attemptsAllowed),
"password": ssh.RetryableAuthMethod(passwordCallback, attemptsAllowed),
}
@@ -649,18 +576,17 @@ func ConnectToClient(connCtx context.Context, opts *sstore.SSHOpts, remoteDispla
authMethods = append(authMethods, authMethod)
}
hostKeyCallback, hostKeyAlgorithms, err := createHostKeyCallback(opts)
hostKeyCallback, err := createHostKeyCallback(opts)
if err != nil {
return nil, err
}
networkAddr := sshKeywords.HostName + ":" + sshKeywords.Port
clientConfig := &ssh.ClientConfig{
User: sshKeywords.User,
Auth: authMethods,
HostKeyCallback: hostKeyCallback,
HostKeyAlgorithms: hostKeyAlgorithms(networkAddr),
User: sshKeywords.User,
Auth: authMethods,
HostKeyCallback: hostKeyCallback,
}
networkAddr := sshKeywords.HostName + ":" + sshKeywords.Port
return DialContext(connCtx, "tcp", networkAddr, clientConfig)
}
@@ -674,8 +600,6 @@ type SshKeywords struct {
PasswordAuthentication bool
KbdInteractiveAuthentication bool
PreferredAuthentications []string
AddKeysToAgent bool
IdentityAgent string
}
func combineSshKeywords(opts *sstore.SSHOpts, configKeywords *SshKeywords) (*SshKeywords, error) {
@@ -725,8 +649,6 @@ func combineSshKeywords(opts *sstore.SSHOpts, configKeywords *SshKeywords) (*Ssh
sshKeywords.PasswordAuthentication = configKeywords.PasswordAuthentication
sshKeywords.KbdInteractiveAuthentication = configKeywords.KbdInteractiveAuthentication
sshKeywords.PreferredAuthentications = configKeywords.PreferredAuthentications
sshKeywords.AddKeysToAgent = configKeywords.AddKeysToAgent
sshKeywords.IdentityAgent = configKeywords.IdentityAgent
return sshKeywords, nil
}
@@ -734,7 +656,7 @@ func combineSshKeywords(opts *sstore.SSHOpts, configKeywords *SshKeywords) (*Ssh
// note that a `var == "yes"` will default to false
// but `var != "no"` will default to true
// when given unexpected strings
func findSshConfigKeywords(hostPattern string, sshAuthSock string) (*SshKeywords, error) {
func findSshConfigKeywords(hostPattern string) (*SshKeywords, error) {
ssh_config.ReloadConfigs()
sshKeywords := &SshKeywords{}
var err error
@@ -789,21 +711,5 @@ func findSshConfigKeywords(hostPattern string, sshAuthSock string) (*SshKeywords
}
sshKeywords.PreferredAuthentications = strings.Split(preferredAuthenticationsRaw, ",")
addKeysToAgentRaw, err := ssh_config.GetStrict(hostPattern, "AddKeysToAgent")
if err != nil {
return nil, err
}
sshKeywords.AddKeysToAgent = (strings.ToLower(addKeysToAgentRaw) == "yes")
identityAgentRaw, err := ssh_config.GetStrict(hostPattern, "IdentityAgent")
if err != nil {
return nil, err
}
if identityAgentRaw == "" {
sshKeywords.IdentityAgent = base.ExpandHomeDir(utilfn.TryTrimQuotes(strings.TrimSpace(string(sshAuthSock))))
} else {
sshKeywords.IdentityAgent = base.ExpandHomeDir(utilfn.TryTrimQuotes(identityAgentRaw))
}
return sshKeywords, nil
}
+34 -13
View File
@@ -3974,6 +3974,26 @@ __metadata:
languageName: node
linkType: hard
"@types/eslint-scope@npm:^3.7.3":
version: 3.7.7
resolution: "@types/eslint-scope@npm:3.7.7"
dependencies:
"@types/eslint": "npm:*"
"@types/estree": "npm:*"
checksum: 10c0/a0ecbdf2f03912679440550817ff77ef39a30fa8bfdacaf6372b88b1f931828aec392f52283240f0d648cf3055c5ddc564544a626bcf245f3d09fcb099ebe3cc
languageName: node
linkType: hard
"@types/eslint@npm:*":
version: 8.56.6
resolution: "@types/eslint@npm:8.56.6"
dependencies:
"@types/estree": "npm:*"
"@types/json-schema": "npm:*"
checksum: 10c0/52124f0868b14f21b4c8c21cb3c6065e0671df3f64c0bb3d37efe12e41b3434f478461f5ba0dabf368cd927ddc9b36d5592e7f61b939463576ab69c3bf8f3b12
languageName: node
linkType: hard
"@types/estree-jsx@npm:^1.0.0":
version: 1.0.3
resolution: "@types/estree-jsx@npm:1.0.3"
@@ -4055,7 +4075,7 @@ __metadata:
languageName: node
linkType: hard
"@types/json-schema@npm:^7.0.8, @types/json-schema@npm:^7.0.9":
"@types/json-schema@npm:*, @types/json-schema@npm:^7.0.8, @types/json-schema@npm:^7.0.9":
version: 7.0.15
resolution: "@types/json-schema@npm:7.0.15"
checksum: 10c0/a996a745e6c5d60292f36731dd41341339d4eeed8180bb09226e5c8d23759067692b1d88e5d91d72ee83dfc00d3aca8e7bd43ea120516c17922cbcb7c3e252db
@@ -5231,7 +5251,7 @@ __metadata:
languageName: node
linkType: hard
"braces@npm:^3.0.3, braces@npm:~3.0.2":
"braces@npm:^3.0.2, braces@npm:~3.0.2":
version: 3.0.3
resolution: "braces@npm:3.0.3"
dependencies:
@@ -6750,7 +6770,7 @@ __metadata:
languageName: node
linkType: hard
"enhanced-resolve@npm:^5.17.1":
"enhanced-resolve@npm:^5.17.0":
version: 5.17.1
resolution: "enhanced-resolve@npm:5.17.1"
dependencies:
@@ -9542,12 +9562,12 @@ __metadata:
linkType: hard
"micromatch@npm:^4.0.2, micromatch@npm:^4.0.4":
version: 4.0.8
resolution: "micromatch@npm:4.0.8"
version: 4.0.5
resolution: "micromatch@npm:4.0.5"
dependencies:
braces: "npm:^3.0.3"
braces: "npm:^3.0.2"
picomatch: "npm:^2.3.1"
checksum: 10c0/166fa6eb926b9553f32ef81f5f531d27b4ce7da60e5baf8c021d043b27a388fb95e46a8038d5045877881e673f8134122b59624d5cecbd16eb50a42e7a6b5ca8
checksum: 10c0/3d6505b20f9fa804af5d8c596cb1c5e475b9b0cd05f652c5b56141cf941bd72adaeb7a436fda344235cef93a7f29b7472efc779fcdb83b478eab0867b95cdeff
languageName: node
linkType: hard
@@ -12700,7 +12720,7 @@ __metadata:
tsx-control-statements: "npm:^5.1.1"
typescript: "npm:^5.5.4"
uuid: "npm:^9.0.1"
webpack: "npm:^5.94.0"
webpack: "npm:^5.93.0"
webpack-bundle-analyzer: "npm:^4.10.2"
webpack-cli: "npm:^5.1.4"
webpack-dev-server: "npm:^5.0.4"
@@ -12887,10 +12907,11 @@ __metadata:
languageName: node
linkType: hard
"webpack@npm:^5.94.0":
version: 5.94.0
resolution: "webpack@npm:5.94.0"
"webpack@npm:^5.93.0":
version: 5.93.0
resolution: "webpack@npm:5.93.0"
dependencies:
"@types/eslint-scope": "npm:^3.7.3"
"@types/estree": "npm:^1.0.5"
"@webassemblyjs/ast": "npm:^1.12.1"
"@webassemblyjs/wasm-edit": "npm:^1.12.1"
@@ -12899,7 +12920,7 @@ __metadata:
acorn-import-attributes: "npm:^1.9.5"
browserslist: "npm:^4.21.10"
chrome-trace-event: "npm:^1.0.2"
enhanced-resolve: "npm:^5.17.1"
enhanced-resolve: "npm:^5.17.0"
es-module-lexer: "npm:^1.2.1"
eslint-scope: "npm:5.1.1"
events: "npm:^3.2.0"
@@ -12919,7 +12940,7 @@ __metadata:
optional: true
bin:
webpack: bin/webpack.js
checksum: 10c0/b4d1b751f634079bd177a89eef84d80fa5bb8d6fc15d72ab40fc2b9ca5167a79b56585e1a849e9e27e259803ee5c4365cb719e54af70a43c06358ec268ff4ebf
checksum: 10c0/f0c72f1325ff57a4cc461bb978e6e1296f2a7d45c9765965271aa686ccdd448512956f4d7fdcf8c164d073af046c5a0aba17ce85ea98e33e5e2bfbfe13aa5808
languageName: node
linkType: hard