//nolint:testpackage // absent is what these wordings are read by package ssh import "testing" // What a session says besides its report on the file that was asked // for: sftp echoes the command it is running, and ssh warns about an // identity file it cannot find in the words of a missing file even // though the session goes on to authenticate. const ( echoed = `sftp> get .ssh/authorized_keys "/tmp/keyfunc/authorized_keys" ` warning = `Warning: Identity file /gone not accessible: ` + "No such file or directory.\n" ) // TestAbsenceIsReadOnlyFromWhatSFTPSaidAboutAuthorizedKeys holds the // wordings the OpenSSH client was seen to use against a real server: // a file it cannot find is reported one way, naming the path the // server expanded, and everything else it says is a failure. func TestAbsenceIsReadOnlyFromWhatSFTPSaidAboutAuthorizedKeys(t *testing.T) { t.Parallel() sessions := map[string]struct { said string want bool }{ "the file is not there": { said: echoed + `File "/home/someone/.ssh/authorized_keys" not found.` + "\n", want: true, }, "the file is not there, named as it was asked for": { said: echoed + `File ".ssh/authorized_keys" not found.` + "\n", want: true, }, "the file is not there and an identity file is not either": { said: warning + echoed + `File "/home/someone/.ssh/authorized_keys" not found.` + "\n", want: true, }, "the file is there and cannot be read": { said: echoed + `remote open "/home/someone/.ssh/authorized_keys": ` + "Permission denied\n", want: false, }, "only an identity file is not there": { said: warning + echoed + `remote open "/home/someone/.ssh/authorized_keys": ` + "Permission denied\n", want: false, }, "some other file is not there": { said: echoed + `File "/home/someone/.ssh/known_hosts" not found.` + "\n", want: false, }, "the connection did not come up": { said: "ssh: connect to host example.com port 22: " + "Connection refused\nConnection closed\n", want: false, }, } for name, session := range sessions { t.Run(name, func(t *testing.T) { t.Parallel() if absent(session.said) != session.want { t.Errorf( "read as absent: %t, wanted %t, from:\n%s", !session.want, session.want, session.said, ) } }) } }