Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 20 additions & 5 deletions lib/client/keyagent.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,14 +89,29 @@ func agentIsPresent() bool {

// agentSupportsSSHCertificates checks if the running agent supports SSH certificates.
// This detection implementation is as described in RFD 18 and works by simply checking for
// presence of gpg-agent which is a common agent known to not support SSH certificates.
func agentSupportsSSHCertificates() bool {
// presence of gpg-agent or 1password which are common agents known to not support SSH certificates.
func agentSupportsSSHCertificates(goos string) bool {
agent := os.Getenv(teleport.SSHAuthSock)
return !strings.Contains(agent, "gpg-agent")

if strings.Contains(agent, "gpg-agent") {
return false
}

// Platform specific socket locations for 1Password are described here:
// https://developer.1password.com/docs/ssh/agent/compatibility/#working-with-ssh-clients
if goos == "linux" && strings.Contains(agent, ".1password/agent.sock") {
return false
}

if goos == "darwin" && strings.Contains(agent, "Library/Group Containers/2BUA8C4S2C.com.1password/t/agent.sock") {
return false
}

return true
}

func shouldAddKeysToAgent(addKeysToAgent string) bool {
return (addKeysToAgent == AddKeysToAgentAuto && agentSupportsSSHCertificates()) || addKeysToAgent == AddKeysToAgentOnly || addKeysToAgent == AddKeysToAgentYes
return (addKeysToAgent == AddKeysToAgentAuto && agentSupportsSSHCertificates(runtime.GOOS)) || addKeysToAgent == AddKeysToAgentOnly || addKeysToAgent == AddKeysToAgentYes
}

// LocalAgentConfig contains parameters for creating the local keys agent.
Expand Down Expand Up @@ -144,7 +159,7 @@ func NewLocalAgent(conf LocalAgentConfig) (a *LocalKeyAgent, err error) {
} else {
log.DebugContext(context.Background(), "Skipping connection to the local ssh-agent.")

if !agentSupportsSSHCertificates() && agentIsPresent() {
if !agentSupportsSSHCertificates(runtime.GOOS) && agentIsPresent() {
log.WarnContext(context.Background(), `Certificate was not loaded into agent because the agent at SSH_AUTH_SOCK does not appear
to support SSH certificates. To force load the certificate into the running agent, use
the --add-keys-to-agent=yes flag.`)
Expand Down
66 changes: 66 additions & 0 deletions lib/client/keyagent_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -888,3 +888,69 @@ func (s *KeyAgentTestSuite) newKeyAgent(t *testing.T) *LocalKeyAgent {
require.NoError(t, err)
return keyAgent
}

func TestAgentSupportsSSHCertificates(t *testing.T) {
tests := []struct {
name string
sshAuthSock string
goos string
wantSupports bool
}{
{
name: "empty socket path",
sshAuthSock: "",
goos: "os does not matter",
wantSupports: true,
},
{
name: "standard ssh-agent",
sshAuthSock: "/tmp/ssh-XXXXXX/agent.12345",
goos: "os does not matter",
wantSupports: true,
},
{
name: "gpg-agent",
sshAuthSock: "/run/user/1000/gnupg/S.gpg-agent.ssh",
goos: "os does not matter",
wantSupports: false,
},
{
name: "gpg-agent in home",
sshAuthSock: "/home/user/.gnupg/gpg-agent.sock",
goos: "os does not matter",
wantSupports: false,
},
{
name: "1password agent on linux",
sshAuthSock: "/home/user/.1password/agent.sock",
goos: "linux",
wantSupports: false,
},
{
name: "1password linux path ignored on darwin",
sshAuthSock: "/home/user/.1password/agent.sock",
goos: "darwin",
wantSupports: true,
},
{
name: "1password agent on darwin",
sshAuthSock: "/Users/user/Library/Group Containers/2BUA8C4S2C.com.1password/t/agent.sock",
goos: "darwin",
wantSupports: false,
},
{
name: "1password darwin path ignored on linux",
sshAuthSock: "/Users/user/Library/Group Containers/2BUA8C4S2C.com.1password/t/agent.sock",
goos: "linux",
wantSupports: true,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Setenv(teleport.SSHAuthSock, tt.sshAuthSock)
got := agentSupportsSSHCertificates(tt.goos)
assert.Equal(t, tt.wantSupports, got)
})
}
}
Loading