Fix key principals not being used when identity files are being used (#11609)

This commit is contained in:
Alex McGrath 2022-04-07 10:20:59 +01:00 committed by GitHub
parent 52e7ace91a
commit 32cb76e26a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 60 additions and 1 deletions

View file

@ -226,6 +226,10 @@ type Config struct {
// against Teleport client and obtaining credentials from elsewhere.
SkipLocalAuth bool
// UseKeyPrincipals forces the use of the username from the key principals rather than using
// the current user username.
UseKeyPrincipals bool
// Agent is used when SkipLocalAuth is true
Agent agent.Agent
@ -2166,7 +2170,7 @@ func (tc *TeleportClient) getProxySSHPrincipal() string {
proxyPrincipal = tc.JumpHosts[0].Username
}
// see if we already have a signed key in the cache, we'll use that instead
if !tc.Config.SkipLocalAuth && tc.localAgent != nil {
if (!tc.Config.SkipLocalAuth || tc.UseKeyPrincipals) && tc.localAgent != nil {
signers, err := tc.localAgent.Signers()
if err != nil || len(signers) == 0 {
return proxyPrincipal

View file

@ -17,12 +17,16 @@ limitations under the License.
package client
import (
"io"
"os"
"testing"
"github.com/gravitational/teleport/api/client/webclient"
"github.com/gravitational/teleport/lib/defaults"
"github.com/gravitational/teleport/lib/utils"
"github.com/gravitational/trace"
"golang.org/x/crypto/ssh"
"golang.org/x/crypto/ssh/agent"
"github.com/stretchr/testify/require"
"gopkg.in/check.v1"
@ -499,6 +503,53 @@ func TestApplyProxySettings(t *testing.T) {
}
}
type mockAgent struct {
// Agent is embedded to avoid redeclaring all interface methods.
// Only the Signers method is implemented by testAgent.
agent.Agent
ValidPrincipals []string
}
type mockSigner struct {
ValidPrincipals []string
}
func (s *mockSigner) PublicKey() ssh.PublicKey {
return &ssh.Certificate{
ValidPrincipals: s.ValidPrincipals,
}
}
func (s *mockSigner) Sign(rand io.Reader, b []byte) (*ssh.Signature, error) {
return nil, trace.Errorf("mockSigner does not implement Sign")
}
// Signers implements agent.Agent.Signers.
func (m *mockAgent) Signers() ([]ssh.Signer, error) {
return []ssh.Signer{&mockSigner{ValidPrincipals: m.ValidPrincipals}}, nil
}
func TestNewClient_UseKeyPrincipals(t *testing.T) {
cfg := &Config{
Username: "xyz",
HostLogin: "xyz",
WebProxyAddr: "localhost",
SkipLocalAuth: true,
UseKeyPrincipals: true, // causes VALID to be returned, as key was used
Agent: &mockAgent{ValidPrincipals: []string{"VALID"}},
AuthMethods: []ssh.AuthMethod{ssh.Password("xyz") /* placeholder authmethod */},
}
client, err := NewClient(cfg)
require.NoError(t, err)
require.Equal(t, "VALID", client.getProxySSHPrincipal(), "ProxySSHPrincipal mismatch")
cfg.UseKeyPrincipals = false // causes xyz to be returned as key was not used
client, err = NewClient(cfg)
require.NoError(t, err)
require.Equal(t, "xyz", client.getProxySSHPrincipal(), "ProxySSHPrincipal mismatch")
}
func TestParseSearchKeywords(t *testing.T) {
t.Parallel()

View file

@ -1910,6 +1910,10 @@ func makeClient(cf *CLIConf, useProfileLogin bool) (*client.TeleportClient, erro
if cf.IdentityFileIn != "" {
// Ignore local authentication methods when identity file is provided
c.SkipLocalAuth = true
// Force the use of the certificate principals so Unix
// username does not get used when logging in
c.UseKeyPrincipals = hostLogin == ""
var (
key *client.Key
identityAuth ssh.AuthMethod