mirror of
https://github.com/gravitational/teleport
synced 2024-10-20 17:23:22 +00:00
Add context.Context to AuthenticateWebUser and AuthenticateSSHUser (#14754)
Updates auth.ClientI to require that both methods take a context.Context as the first argument. Context propogation required some additional call sites to ensure the proper context is plumbed down to the auth.ClientI calls.
This commit is contained in:
parent
c063a186e1
commit
adc37b4ba3
|
@ -574,7 +574,7 @@ func (s *APIServer) authenticateWebUser(auth ClientI, w http.ResponseWriter, r *
|
|||
return nil, trace.Wrap(err)
|
||||
}
|
||||
req.Username = p.ByName("user")
|
||||
sess, err := auth.AuthenticateWebUser(req)
|
||||
sess, err := auth.AuthenticateWebUser(r.Context(), req)
|
||||
if err != nil {
|
||||
return nil, trace.Wrap(err)
|
||||
}
|
||||
|
@ -587,7 +587,7 @@ func (s *APIServer) authenticateSSHUser(auth ClientI, w http.ResponseWriter, r *
|
|||
return nil, trace.Wrap(err)
|
||||
}
|
||||
req.Username = p.ByName("user")
|
||||
return auth.AuthenticateSSHUser(req)
|
||||
return auth.AuthenticateSSHUser(r.Context(), req)
|
||||
}
|
||||
|
||||
// changePassword updates users password based on the old password.
|
||||
|
|
|
@ -19,13 +19,14 @@ import (
|
|||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/gravitational/trace"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/gravitational/teleport/api/client/proto"
|
||||
"github.com/gravitational/teleport/api/constants"
|
||||
"github.com/gravitational/teleport/api/types"
|
||||
"github.com/gravitational/teleport/lib/auth/mocku2f"
|
||||
"github.com/gravitational/teleport/lib/defaults"
|
||||
"github.com/gravitational/trace"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
wanlib "github.com/gravitational/teleport/lib/auth/webauthn"
|
||||
)
|
||||
|
@ -408,6 +409,7 @@ const sshPubKey = `ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzd
|
|||
func TestServer_AuthenticateUser_mfaDevices(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
ctx := context.Background()
|
||||
svr := newTestTLSServer(t)
|
||||
authServer := svr.Auth()
|
||||
mfa := configureForMFA(t, svr)
|
||||
|
@ -428,7 +430,7 @@ func TestServer_AuthenticateUser_mfaDevices(t *testing.T) {
|
|||
makeRun := func(authenticate func(*Server, AuthenticateUserRequest) error) func(t *testing.T) {
|
||||
return func(t *testing.T) {
|
||||
// 1st step: acquire challenge
|
||||
challenge, err := authServer.CreateAuthenticateChallenge(context.Background(), &proto.CreateAuthenticateChallengeRequest{
|
||||
challenge, err := authServer.CreateAuthenticateChallenge(ctx, &proto.CreateAuthenticateChallengeRequest{
|
||||
Request: &proto.CreateAuthenticateChallengeRequest_UserCredentials{UserCredentials: &proto.UserCredentials{
|
||||
Username: username,
|
||||
Password: []byte(password),
|
||||
|
@ -460,7 +462,7 @@ func TestServer_AuthenticateUser_mfaDevices(t *testing.T) {
|
|||
}
|
||||
}
|
||||
t.Run(test.name+"/ssh", makeRun(func(s *Server, req AuthenticateUserRequest) error {
|
||||
_, err := s.AuthenticateSSHUser(AuthenticateSSHRequest{
|
||||
_, err := s.AuthenticateSSHUser(ctx, AuthenticateSSHRequest{
|
||||
AuthenticateUserRequest: req,
|
||||
PublicKey: []byte(sshPubKey),
|
||||
TTL: 24 * time.Hour,
|
||||
|
@ -468,7 +470,7 @@ func TestServer_AuthenticateUser_mfaDevices(t *testing.T) {
|
|||
return err
|
||||
}))
|
||||
t.Run(test.name+"/web", makeRun(func(s *Server, req AuthenticateUserRequest) error {
|
||||
_, err := s.AuthenticateWebUser(req)
|
||||
_, err := s.AuthenticateWebUser(ctx, req)
|
||||
return err
|
||||
}))
|
||||
}
|
||||
|
@ -557,7 +559,7 @@ func TestServer_Authenticate_passwordless(t *testing.T) {
|
|||
{
|
||||
name: "ssh",
|
||||
authenticate: func(t *testing.T, resp *wanlib.CredentialAssertionResponse) {
|
||||
loginResp, err := proxyClient.AuthenticateSSHUser(AuthenticateSSHRequest{
|
||||
loginResp, err := proxyClient.AuthenticateSSHUser(ctx, AuthenticateSSHRequest{
|
||||
AuthenticateUserRequest: AuthenticateUserRequest{
|
||||
Webauthn: resp,
|
||||
},
|
||||
|
@ -573,7 +575,7 @@ func TestServer_Authenticate_passwordless(t *testing.T) {
|
|||
{
|
||||
name: "web",
|
||||
authenticate: func(t *testing.T, resp *wanlib.CredentialAssertionResponse) {
|
||||
session, err := proxyClient.AuthenticateWebUser(AuthenticateUserRequest{
|
||||
session, err := proxyClient.AuthenticateWebUser(ctx, AuthenticateUserRequest{
|
||||
Webauthn: resp,
|
||||
})
|
||||
require.NoError(t, err, "Failed to perform passwordless authentication")
|
||||
|
@ -584,7 +586,7 @@ func TestServer_Authenticate_passwordless(t *testing.T) {
|
|||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
// Fail a login attempt so have a non-empty list of attempts.
|
||||
_, err := proxyClient.AuthenticateSSHUser(AuthenticateSSHRequest{
|
||||
_, err := proxyClient.AuthenticateSSHUser(ctx, AuthenticateSSHRequest{
|
||||
AuthenticateUserRequest: AuthenticateUserRequest{
|
||||
Username: user,
|
||||
Webauthn: &wanlib.CredentialAssertionResponse{}, // bad response
|
||||
|
@ -678,7 +680,7 @@ func TestServer_Authenticate_nonPasswordlessRequiresUsername(t *testing.T) {
|
|||
}
|
||||
|
||||
// SSH.
|
||||
_, err = proxyClient.AuthenticateSSHUser(AuthenticateSSHRequest{
|
||||
_, err = proxyClient.AuthenticateSSHUser(ctx, AuthenticateSSHRequest{
|
||||
AuthenticateUserRequest: req,
|
||||
PublicKey: []byte(sshPubKey),
|
||||
TTL: 24 * time.Hour,
|
||||
|
@ -687,13 +689,13 @@ func TestServer_Authenticate_nonPasswordlessRequiresUsername(t *testing.T) {
|
|||
require.Contains(t, err.Error(), test.wantErr)
|
||||
|
||||
// Web.
|
||||
_, err = proxyClient.AuthenticateWebUser(req)
|
||||
_, err = proxyClient.AuthenticateWebUser(ctx, req)
|
||||
require.Error(t, err, "Web authentication expected fail (missing username)")
|
||||
require.Contains(t, err.Error(), test.wantErr)
|
||||
|
||||
// Get one right so we don't lock the user between tests.
|
||||
req.Username = username
|
||||
_, err = proxyClient.AuthenticateWebUser(req)
|
||||
_, err = proxyClient.AuthenticateWebUser(ctx, req)
|
||||
require.NoError(t, err, "Web authentication expected to succeed")
|
||||
})
|
||||
}
|
||||
|
|
|
@ -190,7 +190,7 @@ func TestSessions(t *testing.T) {
|
|||
user := "user1"
|
||||
pass := []byte("abc123")
|
||||
|
||||
_, err := s.a.AuthenticateWebUser(AuthenticateUserRequest{
|
||||
_, err := s.a.AuthenticateWebUser(ctx, AuthenticateUserRequest{
|
||||
Username: user,
|
||||
Pass: &PassCreds{Password: pass},
|
||||
})
|
||||
|
@ -202,7 +202,7 @@ func TestSessions(t *testing.T) {
|
|||
err = s.a.UpsertPassword(user, pass)
|
||||
require.NoError(t, err)
|
||||
|
||||
ws, err := s.a.AuthenticateWebUser(AuthenticateUserRequest{
|
||||
ws, err := s.a.AuthenticateWebUser(ctx, AuthenticateUserRequest{
|
||||
Username: user,
|
||||
Pass: &PassCreds{Password: pass},
|
||||
})
|
||||
|
@ -242,7 +242,7 @@ func TestAuthenticateSSHUser(t *testing.T) {
|
|||
pass := []byte("abc123")
|
||||
|
||||
// Try to login as an unknown user.
|
||||
_, err = s.a.AuthenticateSSHUser(AuthenticateSSHRequest{
|
||||
_, err = s.a.AuthenticateSSHUser(ctx, AuthenticateSSHRequest{
|
||||
AuthenticateUserRequest: AuthenticateUserRequest{
|
||||
Username: user,
|
||||
Pass: &PassCreds{Password: pass},
|
||||
|
@ -267,7 +267,7 @@ func TestAuthenticateSSHUser(t *testing.T) {
|
|||
require.NoError(t, err)
|
||||
|
||||
// Login to the root cluster.
|
||||
resp, err := s.a.AuthenticateSSHUser(AuthenticateSSHRequest{
|
||||
resp, err := s.a.AuthenticateSSHUser(ctx, AuthenticateSSHRequest{
|
||||
AuthenticateUserRequest: AuthenticateUserRequest{
|
||||
Username: user,
|
||||
Pass: &PassCreds{Password: pass},
|
||||
|
@ -305,7 +305,7 @@ func TestAuthenticateSSHUser(t *testing.T) {
|
|||
require.Equal(t, *gotID, wantID)
|
||||
|
||||
// Login to the leaf cluster.
|
||||
resp, err = s.a.AuthenticateSSHUser(AuthenticateSSHRequest{
|
||||
resp, err = s.a.AuthenticateSSHUser(ctx, AuthenticateSSHRequest{
|
||||
AuthenticateUserRequest: AuthenticateUserRequest{
|
||||
Username: user,
|
||||
Pass: &PassCreds{Password: pass},
|
||||
|
@ -349,7 +349,7 @@ func TestAuthenticateSSHUser(t *testing.T) {
|
|||
require.NoError(t, err)
|
||||
|
||||
// Login specifying a valid kube cluster. It should appear in the TLS cert.
|
||||
resp, err = s.a.AuthenticateSSHUser(AuthenticateSSHRequest{
|
||||
resp, err = s.a.AuthenticateSSHUser(ctx, AuthenticateSSHRequest{
|
||||
AuthenticateUserRequest: AuthenticateUserRequest{
|
||||
Username: user,
|
||||
Pass: &PassCreds{Password: pass},
|
||||
|
@ -380,7 +380,7 @@ func TestAuthenticateSSHUser(t *testing.T) {
|
|||
|
||||
// Login without specifying kube cluster. A registered one should be picked
|
||||
// automatically.
|
||||
resp, err = s.a.AuthenticateSSHUser(AuthenticateSSHRequest{
|
||||
resp, err = s.a.AuthenticateSSHUser(ctx, AuthenticateSSHRequest{
|
||||
AuthenticateUserRequest: AuthenticateUserRequest{
|
||||
Username: user,
|
||||
Pass: &PassCreds{Password: pass},
|
||||
|
@ -424,7 +424,7 @@ func TestAuthenticateSSHUser(t *testing.T) {
|
|||
require.NoError(t, err)
|
||||
|
||||
// Login specifying a valid kube cluster. It should appear in the TLS cert.
|
||||
resp, err = s.a.AuthenticateSSHUser(AuthenticateSSHRequest{
|
||||
resp, err = s.a.AuthenticateSSHUser(ctx, AuthenticateSSHRequest{
|
||||
AuthenticateUserRequest: AuthenticateUserRequest{
|
||||
Username: user,
|
||||
Pass: &PassCreds{Password: pass},
|
||||
|
@ -455,7 +455,7 @@ func TestAuthenticateSSHUser(t *testing.T) {
|
|||
|
||||
// Login without specifying kube cluster. A registered one should be picked
|
||||
// automatically.
|
||||
resp, err = s.a.AuthenticateSSHUser(AuthenticateSSHRequest{
|
||||
resp, err = s.a.AuthenticateSSHUser(ctx, AuthenticateSSHRequest{
|
||||
AuthenticateUserRequest: AuthenticateUserRequest{
|
||||
Username: user,
|
||||
Pass: &PassCreds{Password: pass},
|
||||
|
@ -487,7 +487,7 @@ func TestAuthenticateSSHUser(t *testing.T) {
|
|||
require.Equal(t, *gotID, wantID)
|
||||
|
||||
// Login specifying an invalid kube cluster. This should fail.
|
||||
_, err = s.a.AuthenticateSSHUser(AuthenticateSSHRequest{
|
||||
_, err = s.a.AuthenticateSSHUser(ctx, AuthenticateSSHRequest{
|
||||
AuthenticateUserRequest: AuthenticateUserRequest{
|
||||
Username: user,
|
||||
Pass: &PassCreds{Password: pass},
|
||||
|
@ -503,11 +503,12 @@ func TestAuthenticateSSHUser(t *testing.T) {
|
|||
func TestUserLock(t *testing.T) {
|
||||
t.Parallel()
|
||||
s := newAuthSuite(t)
|
||||
ctx := context.Background()
|
||||
|
||||
username := "user1"
|
||||
pass := []byte("abc123")
|
||||
|
||||
_, err := s.a.AuthenticateWebUser(AuthenticateUserRequest{
|
||||
_, err := s.a.AuthenticateWebUser(ctx, AuthenticateUserRequest{
|
||||
Username: username,
|
||||
Pass: &PassCreds{Password: pass},
|
||||
})
|
||||
|
@ -520,7 +521,7 @@ func TestUserLock(t *testing.T) {
|
|||
require.NoError(t, err)
|
||||
|
||||
// successful log in
|
||||
ws, err := s.a.AuthenticateWebUser(AuthenticateUserRequest{
|
||||
ws, err := s.a.AuthenticateWebUser(ctx, AuthenticateUserRequest{
|
||||
Username: username,
|
||||
Pass: &PassCreds{Password: pass},
|
||||
})
|
||||
|
@ -531,7 +532,7 @@ func TestUserLock(t *testing.T) {
|
|||
s.a.SetClock(fakeClock)
|
||||
|
||||
for i := 0; i <= defaults.MaxLoginAttempts; i++ {
|
||||
_, err = s.a.AuthenticateWebUser(AuthenticateUserRequest{
|
||||
_, err = s.a.AuthenticateWebUser(ctx, AuthenticateUserRequest{
|
||||
Username: username,
|
||||
Pass: &PassCreds{Password: []byte("wrong pass")},
|
||||
})
|
||||
|
@ -545,7 +546,7 @@ func TestUserLock(t *testing.T) {
|
|||
// advance time and make sure we can login again
|
||||
fakeClock.Advance(defaults.AccountLockInterval + time.Second)
|
||||
|
||||
_, err = s.a.AuthenticateWebUser(AuthenticateUserRequest{
|
||||
_, err = s.a.AuthenticateWebUser(ctx, AuthenticateUserRequest{
|
||||
Username: username,
|
||||
Pass: &PassCreds{Password: pass},
|
||||
})
|
||||
|
|
|
@ -386,24 +386,24 @@ func (a *ServerWithRoles) UpdateSessionTracker(ctx context.Context, req *proto.U
|
|||
|
||||
// AuthenticateWebUser authenticates web user, creates and returns a web session
|
||||
// in case authentication is successful
|
||||
func (a *ServerWithRoles) AuthenticateWebUser(req AuthenticateUserRequest) (types.WebSession, error) {
|
||||
func (a *ServerWithRoles) AuthenticateWebUser(ctx context.Context, req AuthenticateUserRequest) (types.WebSession, error) {
|
||||
// authentication request has it's own authentication, however this limits the requests
|
||||
// types to proxies to make it harder to break
|
||||
if !a.hasBuiltinRole(types.RoleProxy) {
|
||||
return nil, trace.AccessDenied("this request can be only executed by a proxy")
|
||||
}
|
||||
return a.authServer.AuthenticateWebUser(req)
|
||||
return a.authServer.AuthenticateWebUser(ctx, req)
|
||||
}
|
||||
|
||||
// AuthenticateSSHUser authenticates SSH console user, creates and returns a pair of signed TLS and SSH
|
||||
// short lived certificates as a result
|
||||
func (a *ServerWithRoles) AuthenticateSSHUser(req AuthenticateSSHRequest) (*SSHLoginResponse, error) {
|
||||
func (a *ServerWithRoles) AuthenticateSSHUser(ctx context.Context, req AuthenticateSSHRequest) (*SSHLoginResponse, error) {
|
||||
// authentication request has it's own authentication, however this limits the requests
|
||||
// types to proxies to make it harder to break
|
||||
if !a.hasBuiltinRole(types.RoleProxy) {
|
||||
return nil, trace.AccessDenied("this request can be only executed by a proxy")
|
||||
}
|
||||
return a.authServer.AuthenticateSSHUser(req)
|
||||
return a.authServer.AuthenticateSSHUser(ctx, req)
|
||||
}
|
||||
|
||||
func (a *ServerWithRoles) GetSessions(namespace string) ([]session.Session, error) {
|
||||
|
|
|
@ -887,9 +887,9 @@ func (c *Client) CreateWebSession(ctx context.Context, user string) (types.WebSe
|
|||
|
||||
// AuthenticateWebUser authenticates web user, creates and returns web session
|
||||
// in case if authentication is successful
|
||||
func (c *Client) AuthenticateWebUser(req AuthenticateUserRequest) (types.WebSession, error) {
|
||||
func (c *Client) AuthenticateWebUser(ctx context.Context, req AuthenticateUserRequest) (types.WebSession, error) {
|
||||
out, err := c.PostJSON(
|
||||
context.TODO(),
|
||||
ctx,
|
||||
c.Endpoint("users", req.Username, "web", "authenticate"),
|
||||
req,
|
||||
)
|
||||
|
@ -901,9 +901,9 @@ func (c *Client) AuthenticateWebUser(req AuthenticateUserRequest) (types.WebSess
|
|||
|
||||
// AuthenticateSSHUser authenticates SSH console user, creates and returns a pair of signed TLS and SSH
|
||||
// short lived certificates as a result
|
||||
func (c *Client) AuthenticateSSHUser(req AuthenticateSSHRequest) (*SSHLoginResponse, error) {
|
||||
func (c *Client) AuthenticateSSHUser(ctx context.Context, req AuthenticateSSHRequest) (*SSHLoginResponse, error) {
|
||||
out, err := c.PostJSON(
|
||||
context.TODO(),
|
||||
ctx,
|
||||
c.Endpoint("users", req.Username, "ssh", "authenticate"),
|
||||
req,
|
||||
)
|
||||
|
@ -1716,10 +1716,10 @@ type ClientI interface {
|
|||
GenerateHostCerts(context.Context, *proto.HostCertsRequest) (*proto.Certs, error)
|
||||
// AuthenticateWebUser authenticates web user, creates and returns web session
|
||||
// in case if authentication is successful
|
||||
AuthenticateWebUser(req AuthenticateUserRequest) (types.WebSession, error)
|
||||
AuthenticateWebUser(ctx context.Context, req AuthenticateUserRequest) (types.WebSession, error)
|
||||
// AuthenticateSSHUser authenticates SSH console user, creates and returns a pair of signed TLS and SSH
|
||||
// short lived certificates as a result
|
||||
AuthenticateSSHUser(req AuthenticateSSHRequest) (*SSHLoginResponse, error)
|
||||
// short-lived certificates as a result
|
||||
AuthenticateSSHUser(ctx context.Context, req AuthenticateSSHRequest) (*SSHLoginResponse, error)
|
||||
|
||||
// ProcessKubeCSR processes CSR request against Kubernetes CA, returns
|
||||
// signed certificate if successful.
|
||||
|
|
|
@ -21,6 +21,9 @@ import (
|
|||
"errors"
|
||||
"time"
|
||||
|
||||
"github.com/gravitational/trace"
|
||||
"golang.org/x/crypto/ssh"
|
||||
|
||||
"github.com/gravitational/teleport/api/client/proto"
|
||||
"github.com/gravitational/teleport/api/constants"
|
||||
"github.com/gravitational/teleport/api/types"
|
||||
|
@ -29,8 +32,6 @@ import (
|
|||
"github.com/gravitational/teleport/lib/events"
|
||||
"github.com/gravitational/teleport/lib/services"
|
||||
"github.com/gravitational/teleport/lib/utils"
|
||||
"github.com/gravitational/trace"
|
||||
"golang.org/x/crypto/ssh"
|
||||
)
|
||||
|
||||
// AuthenticateUserRequest is a request to authenticate interactive user
|
||||
|
@ -294,10 +295,9 @@ func (s *Server) authenticatePasswordless(ctx context.Context, req AuthenticateU
|
|||
// AuthenticateWebUser authenticates web user, creates and returns a web session
|
||||
// if authentication is successful. In case the existing session ID is used to authenticate,
|
||||
// returns the existing session instead of creating a new one
|
||||
func (s *Server) AuthenticateWebUser(req AuthenticateUserRequest) (types.WebSession, error) {
|
||||
func (s *Server) AuthenticateWebUser(ctx context.Context, req AuthenticateUserRequest) (types.WebSession, error) {
|
||||
username := req.Username // Empty if passwordless.
|
||||
|
||||
ctx := context.TODO()
|
||||
authPref, err := s.GetAuthPreference(ctx)
|
||||
if err != nil {
|
||||
return nil, trace.Wrap(err)
|
||||
|
@ -430,10 +430,9 @@ func AuthoritiesToTrustedCerts(authorities []types.CertAuthority) []TrustedCerts
|
|||
|
||||
// AuthenticateSSHUser authenticates an SSH user and returns SSH and TLS
|
||||
// certificates for the public key in req.
|
||||
func (s *Server) AuthenticateSSHUser(req AuthenticateSSHRequest) (*SSHLoginResponse, error) {
|
||||
func (s *Server) AuthenticateSSHUser(ctx context.Context, req AuthenticateSSHRequest) (*SSHLoginResponse, error) {
|
||||
username := req.Username // Empty if passwordless.
|
||||
|
||||
ctx := context.TODO()
|
||||
authPref, err := s.GetAuthPreference(ctx)
|
||||
if err != nil {
|
||||
return nil, trace.Wrap(err)
|
||||
|
|
|
@ -1274,14 +1274,14 @@ func TestWebSessionWithoutAccessRequest(t *testing.T) {
|
|||
},
|
||||
}
|
||||
// authentication attempt fails with no password set up
|
||||
_, err = proxy.AuthenticateWebUser(req)
|
||||
_, err = proxy.AuthenticateWebUser(ctx, req)
|
||||
require.True(t, trace.IsAccessDenied(err))
|
||||
|
||||
err = clt.UpsertPassword(user, pass)
|
||||
require.NoError(t, err)
|
||||
|
||||
// success with password set up
|
||||
ws, err := proxy.AuthenticateWebUser(req)
|
||||
ws, err := proxy.AuthenticateWebUser(ctx, req)
|
||||
require.NoError(t, err)
|
||||
require.NotEqual(t, ws, "")
|
||||
|
||||
|
@ -1390,7 +1390,7 @@ func TestWebSessionMultiAccessRequests(t *testing.T) {
|
|||
// Create a web session and client for the user.
|
||||
proxyClient, err := tt.server.NewClient(TestBuiltin(types.RoleProxy))
|
||||
require.NoError(t, err)
|
||||
baseWebSession, err := proxyClient.AuthenticateWebUser(AuthenticateUserRequest{
|
||||
baseWebSession, err := proxyClient.AuthenticateWebUser(ctx, AuthenticateUserRequest{
|
||||
Username: username,
|
||||
Pass: &PassCreds{
|
||||
Password: password,
|
||||
|
@ -1560,14 +1560,14 @@ func TestWebSessionWithApprovedAccessRequestAndSwitchback(t *testing.T) {
|
|||
err = clt.UpsertPassword(user, pass)
|
||||
require.NoError(t, err)
|
||||
|
||||
ws, err := proxy.AuthenticateWebUser(req)
|
||||
ws, err := proxy.AuthenticateWebUser(ctx, req)
|
||||
require.NoError(t, err)
|
||||
|
||||
web, err := tt.server.NewClientFromWebSession(ws)
|
||||
require.NoError(t, err)
|
||||
|
||||
initialRole := newUser.GetRoles()[0]
|
||||
initialSession, err := web.GetWebSessionInfo(context.TODO(), user, ws.GetName())
|
||||
initialSession, err := web.GetWebSessionInfo(ctx, user, ws.GetName())
|
||||
require.NoError(t, err)
|
||||
|
||||
// Create a approved access request.
|
||||
|
@ -1578,10 +1578,10 @@ func TestWebSessionWithApprovedAccessRequestAndSwitchback(t *testing.T) {
|
|||
accessReq.SetAccessExpiry(tt.clock.Now().Add(time.Minute * 10))
|
||||
accessReq.SetState(types.RequestState_APPROVED)
|
||||
|
||||
err = clt.CreateAccessRequest(context.Background(), accessReq)
|
||||
err = clt.CreateAccessRequest(ctx, accessReq)
|
||||
require.NoError(t, err)
|
||||
|
||||
sess1, err := web.ExtendWebSession(context.TODO(), WebSessionReq{
|
||||
sess1, err := web.ExtendWebSession(ctx, WebSessionReq{
|
||||
User: user,
|
||||
PrevSessionID: ws.GetName(),
|
||||
AccessRequestID: accessReq.GetMetadata().Name,
|
||||
|
@ -1623,7 +1623,7 @@ func TestWebSessionWithApprovedAccessRequestAndSwitchback(t *testing.T) {
|
|||
require.Empty(t, cmp.Diff(certRequests(sess1.GetTLSCert()), []string{accessReq.GetName()}))
|
||||
|
||||
// Test switch back to default role and expiry.
|
||||
sess2, err := web.ExtendWebSession(context.TODO(), WebSessionReq{
|
||||
sess2, err := web.ExtendWebSession(ctx, WebSessionReq{
|
||||
User: user,
|
||||
PrevSessionID: ws.GetName(),
|
||||
Switchback: true,
|
||||
|
@ -2308,7 +2308,7 @@ func TestCertificateFormat(t *testing.T) {
|
|||
require.NoError(t, err)
|
||||
|
||||
// authentication attempt fails with password auth only
|
||||
re, err := proxyClient.AuthenticateSSHUser(AuthenticateSSHRequest{
|
||||
re, err := proxyClient.AuthenticateSSHUser(ctx, AuthenticateSSHRequest{
|
||||
AuthenticateUserRequest: AuthenticateUserRequest{
|
||||
Username: user.GetName(),
|
||||
Pass: &PassCreds{
|
||||
|
@ -2408,21 +2408,21 @@ func TestAuthenticateWebUserOTP(t *testing.T) {
|
|||
require.NoError(t, err)
|
||||
|
||||
// authentication attempt fails with wrong password
|
||||
_, err = proxy.AuthenticateWebUser(AuthenticateUserRequest{
|
||||
_, err = proxy.AuthenticateWebUser(ctx, AuthenticateUserRequest{
|
||||
Username: user,
|
||||
OTP: &OTPCreds{Password: []byte("wrong123"), Token: validToken},
|
||||
})
|
||||
require.True(t, trace.IsAccessDenied(err))
|
||||
|
||||
// authentication attempt fails with wrong otp
|
||||
_, err = proxy.AuthenticateWebUser(AuthenticateUserRequest{
|
||||
_, err = proxy.AuthenticateWebUser(ctx, AuthenticateUserRequest{
|
||||
Username: user,
|
||||
OTP: &OTPCreds{Password: pass, Token: "wrong123"},
|
||||
})
|
||||
require.True(t, trace.IsAccessDenied(err))
|
||||
|
||||
// authentication attempt fails with password auth only
|
||||
_, err = proxy.AuthenticateWebUser(AuthenticateUserRequest{
|
||||
_, err = proxy.AuthenticateWebUser(ctx, AuthenticateUserRequest{
|
||||
Username: user,
|
||||
Pass: &PassCreds{
|
||||
Password: pass,
|
||||
|
@ -2431,7 +2431,7 @@ func TestAuthenticateWebUserOTP(t *testing.T) {
|
|||
require.True(t, trace.IsAccessDenied(err))
|
||||
|
||||
// authentication succeeds
|
||||
ws, err := proxy.AuthenticateWebUser(AuthenticateUserRequest{
|
||||
ws, err := proxy.AuthenticateWebUser(ctx, AuthenticateUserRequest{
|
||||
Username: user,
|
||||
OTP: &OTPCreds{Password: pass, Token: validToken},
|
||||
})
|
||||
|
@ -2480,7 +2480,7 @@ func TestLoginAttempts(t *testing.T) {
|
|||
},
|
||||
}
|
||||
// authentication attempt fails with bad password
|
||||
_, err = proxy.AuthenticateWebUser(req)
|
||||
_, err = proxy.AuthenticateWebUser(ctx, req)
|
||||
require.True(t, trace.IsAccessDenied(err))
|
||||
|
||||
// creates first failed login attempt
|
||||
|
@ -2490,7 +2490,7 @@ func TestLoginAttempts(t *testing.T) {
|
|||
|
||||
// try second time with wrong pass
|
||||
req.Pass.Password = pass
|
||||
_, err = proxy.AuthenticateWebUser(req)
|
||||
_, err = proxy.AuthenticateWebUser(ctx, req)
|
||||
require.NoError(t, err)
|
||||
|
||||
// clears all failed attempts after success
|
||||
|
@ -2583,7 +2583,7 @@ func TestLoginNoLocalAuth(t *testing.T) {
|
|||
require.NoError(t, err)
|
||||
|
||||
// Make sure access is denied for web login.
|
||||
_, err = tt.server.Auth().AuthenticateWebUser(AuthenticateUserRequest{
|
||||
_, err = tt.server.Auth().AuthenticateWebUser(ctx, AuthenticateUserRequest{
|
||||
Username: user,
|
||||
Pass: &PassCreds{
|
||||
Password: pass,
|
||||
|
@ -2594,7 +2594,7 @@ func TestLoginNoLocalAuth(t *testing.T) {
|
|||
// Make sure access is denied for SSH login.
|
||||
_, pub, err := native.GenerateKeyPair()
|
||||
require.NoError(t, err)
|
||||
_, err = tt.server.Auth().AuthenticateSSHUser(AuthenticateSSHRequest{
|
||||
_, err = tt.server.Auth().AuthenticateSSHUser(ctx, AuthenticateSSHRequest{
|
||||
AuthenticateUserRequest: AuthenticateUserRequest{
|
||||
Username: user,
|
||||
Pass: &PassCreds{
|
||||
|
|
|
@ -1561,20 +1561,14 @@ func (h *Handler) createWebSession(w http.ResponseWriter, r *http.Request, p htt
|
|||
|
||||
switch cap.GetSecondFactor() {
|
||||
case constants.SecondFactorOff:
|
||||
webSession, err = h.auth.AuthWithoutOTP(req.User, req.Pass, clientMeta)
|
||||
webSession, err = h.auth.AuthWithoutOTP(r.Context(), req.User, req.Pass, clientMeta)
|
||||
case constants.SecondFactorOTP, constants.SecondFactorOn:
|
||||
webSession, err = h.auth.AuthWithOTP(
|
||||
req.User, req.Pass, req.SecondFactorToken, clientMeta,
|
||||
)
|
||||
webSession, err = h.auth.AuthWithOTP(r.Context(), req.User, req.Pass, req.SecondFactorToken, clientMeta)
|
||||
case constants.SecondFactorOptional:
|
||||
if req.SecondFactorToken == "" {
|
||||
webSession, err = h.auth.AuthWithoutOTP(
|
||||
req.User, req.Pass, clientMeta,
|
||||
)
|
||||
webSession, err = h.auth.AuthWithoutOTP(r.Context(), req.User, req.Pass, clientMeta)
|
||||
} else {
|
||||
webSession, err = h.auth.AuthWithOTP(
|
||||
req.User, req.Pass, req.SecondFactorToken, clientMeta,
|
||||
)
|
||||
webSession, err = h.auth.AuthWithOTP(r.Context(), req.User, req.Pass, req.SecondFactorToken, clientMeta)
|
||||
}
|
||||
default:
|
||||
return nil, trace.AccessDenied("unknown second factor type: %q", cap.GetSecondFactor())
|
||||
|
@ -1599,7 +1593,7 @@ func (h *Handler) createWebSession(w http.ResponseWriter, r *http.Request, p htt
|
|||
return nil, trace.Wrap(err)
|
||||
}
|
||||
|
||||
ctx, err := h.auth.newSessionContext(req.User, webSession.GetName())
|
||||
ctx, err := h.auth.newSessionContext(r.Context(), req.User, webSession.GetName())
|
||||
if err != nil {
|
||||
h.log.WithError(err).Warnf("Access attempt denied for user %q.", req.User)
|
||||
return nil, trace.AccessDenied("need auth")
|
||||
|
@ -1626,7 +1620,7 @@ func clientMetaFromReq(r *http.Request) *auth.ForwardedClientMetadata {
|
|||
// {"message": "ok"}
|
||||
//
|
||||
func (h *Handler) deleteSession(w http.ResponseWriter, r *http.Request, _ httprouter.Params, ctx *SessionContext) (interface{}, error) {
|
||||
err := h.logout(w, ctx)
|
||||
err := h.logout(r.Context(), w, ctx)
|
||||
if err != nil {
|
||||
return nil, trace.Wrap(err)
|
||||
}
|
||||
|
@ -1634,8 +1628,8 @@ func (h *Handler) deleteSession(w http.ResponseWriter, r *http.Request, _ httpro
|
|||
return OK(), nil
|
||||
}
|
||||
|
||||
func (h *Handler) logout(w http.ResponseWriter, ctx *SessionContext) error {
|
||||
if err := ctx.Invalidate(); err != nil {
|
||||
func (h *Handler) logout(ctx context.Context, w http.ResponseWriter, scx *SessionContext) error {
|
||||
if err := scx.Invalidate(ctx); err != nil {
|
||||
return trace.Wrap(err)
|
||||
}
|
||||
ClearSession(w)
|
||||
|
@ -1730,7 +1724,7 @@ func (h *Handler) changeUserAuthentication(w http.ResponseWriter, r *http.Reques
|
|||
}
|
||||
|
||||
sess := res.WebSession
|
||||
ctx, err := h.auth.newSessionContext(sess.GetUser(), sess.GetName())
|
||||
ctx, err := h.auth.newSessionContext(r.Context(), sess.GetUser(), sess.GetName())
|
||||
if err != nil {
|
||||
return nil, trace.Wrap(err)
|
||||
}
|
||||
|
@ -1878,7 +1872,7 @@ func (h *Handler) mfaLoginFinish(w http.ResponseWriter, r *http.Request, p httpr
|
|||
}
|
||||
|
||||
clientMeta := clientMetaFromReq(r)
|
||||
cert, err := h.auth.AuthenticateSSHUser(*req, clientMeta)
|
||||
cert, err := h.auth.AuthenticateSSHUser(r.Context(), *req, clientMeta)
|
||||
if err != nil {
|
||||
return nil, trace.Wrap(err)
|
||||
}
|
||||
|
@ -1902,7 +1896,7 @@ func (h *Handler) mfaLoginFinishSession(w http.ResponseWriter, r *http.Request,
|
|||
}
|
||||
|
||||
clientMeta := clientMetaFromReq(r)
|
||||
session, err := h.auth.AuthenticateWebUser(req, clientMeta)
|
||||
session, err := h.auth.AuthenticateWebUser(r.Context(), req, clientMeta)
|
||||
if err != nil {
|
||||
return nil, trace.AccessDenied("bad auth credentials")
|
||||
}
|
||||
|
@ -1913,7 +1907,7 @@ func (h *Handler) mfaLoginFinishSession(w http.ResponseWriter, r *http.Request,
|
|||
return nil, trace.Wrap(err)
|
||||
}
|
||||
|
||||
ctx, err := h.auth.newSessionContext(user, session.GetName())
|
||||
ctx, err := h.auth.newSessionContext(r.Context(), user, session.GetName())
|
||||
if err != nil {
|
||||
return nil, trace.AccessDenied("need auth")
|
||||
}
|
||||
|
@ -2577,13 +2571,13 @@ func (h *Handler) createSSHCert(w http.ResponseWriter, r *http.Request, p httpro
|
|||
|
||||
switch cap.GetSecondFactor() {
|
||||
case constants.SecondFactorOff:
|
||||
cert, err = h.auth.GetCertificateWithoutOTP(*req, clientMeta)
|
||||
cert, err = h.auth.GetCertificateWithoutOTP(r.Context(), *req, clientMeta)
|
||||
case constants.SecondFactorOTP, constants.SecondFactorOn, constants.SecondFactorOptional:
|
||||
// convert legacy requests to new parameter here. remove once migration to TOTP is complete.
|
||||
if req.HOTPToken != "" {
|
||||
req.OTPToken = req.HOTPToken
|
||||
}
|
||||
cert, err = h.auth.GetCertificateWithOTP(*req, clientMeta)
|
||||
cert, err = h.auth.GetCertificateWithOTP(r.Context(), *req, clientMeta)
|
||||
default:
|
||||
return nil, trace.AccessDenied("unknown second factor type: %q", cap.GetSecondFactor())
|
||||
}
|
||||
|
|
|
@ -19,13 +19,14 @@ package web
|
|||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/gravitational/trace"
|
||||
"github.com/julienschmidt/httprouter"
|
||||
|
||||
"github.com/gravitational/teleport/api/client/proto"
|
||||
wanlib "github.com/gravitational/teleport/lib/auth/webauthn"
|
||||
"github.com/gravitational/teleport/lib/client"
|
||||
"github.com/gravitational/teleport/lib/httplib"
|
||||
"github.com/gravitational/teleport/lib/services"
|
||||
"github.com/gravitational/trace"
|
||||
"github.com/julienschmidt/httprouter"
|
||||
)
|
||||
|
||||
// changePasswordReq is a request to change user password
|
||||
|
@ -88,7 +89,7 @@ func (h *Handler) createAuthenticateChallengeWithPassword(w http.ResponseWriter,
|
|||
})
|
||||
if err != nil && trace.IsAccessDenied(err) {
|
||||
// logout in case of access denied
|
||||
logoutErr := h.logout(w, ctx)
|
||||
logoutErr := h.logout(r.Context(), w, ctx)
|
||||
if logoutErr != nil {
|
||||
return nil, trace.Wrap(logoutErr)
|
||||
}
|
||||
|
|
|
@ -26,11 +26,11 @@ import (
|
|||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/gravitational/teleport/api/breaker"
|
||||
"golang.org/x/crypto/ssh"
|
||||
"golang.org/x/crypto/ssh/agent"
|
||||
|
||||
"github.com/gravitational/teleport"
|
||||
"github.com/gravitational/teleport/api/breaker"
|
||||
apiclient "github.com/gravitational/teleport/api/client"
|
||||
"github.com/gravitational/teleport/api/client/proto"
|
||||
"github.com/gravitational/teleport/api/types"
|
||||
|
@ -106,8 +106,8 @@ func (c *SessionContext) RemoveCloser(closer io.Closer) {
|
|||
|
||||
// Invalidate invalidates this context by removing the underlying session
|
||||
// and closing all underlying closers
|
||||
func (c *SessionContext) Invalidate() error {
|
||||
return c.parent.invalidateSession(c)
|
||||
func (c *SessionContext) Invalidate(ctx context.Context) error {
|
||||
return c.parent.invalidateSession(ctx, c)
|
||||
}
|
||||
|
||||
func (c *SessionContext) validateBearerToken(ctx context.Context, token string) error {
|
||||
|
@ -555,10 +555,11 @@ func (s *sessionCache) clearExpiredSessions(ctx context.Context) {
|
|||
// AuthWithOTP authenticates the specified user with the given password and OTP token.
|
||||
// Returns a new web session if successful.
|
||||
func (s *sessionCache) AuthWithOTP(
|
||||
ctx context.Context,
|
||||
user, pass, otpToken string,
|
||||
clientMeta *auth.ForwardedClientMetadata,
|
||||
) (types.WebSession, error) {
|
||||
return s.proxyClient.AuthenticateWebUser(auth.AuthenticateUserRequest{
|
||||
return s.proxyClient.AuthenticateWebUser(ctx, auth.AuthenticateUserRequest{
|
||||
Username: user,
|
||||
Pass: &auth.PassCreds{Password: []byte(pass)},
|
||||
OTP: &auth.OTPCreds{
|
||||
|
@ -572,9 +573,9 @@ func (s *sessionCache) AuthWithOTP(
|
|||
// AuthWithoutOTP authenticates the specified user with the given password.
|
||||
// Returns a new web session if successful.
|
||||
func (s *sessionCache) AuthWithoutOTP(
|
||||
user, pass string, clientMeta *auth.ForwardedClientMetadata,
|
||||
ctx context.Context, user, pass string, clientMeta *auth.ForwardedClientMetadata,
|
||||
) (types.WebSession, error) {
|
||||
return s.proxyClient.AuthenticateWebUser(auth.AuthenticateUserRequest{
|
||||
return s.proxyClient.AuthenticateWebUser(ctx, auth.AuthenticateUserRequest{
|
||||
Username: user,
|
||||
Pass: &auth.PassCreds{
|
||||
Password: []byte(pass),
|
||||
|
@ -584,7 +585,7 @@ func (s *sessionCache) AuthWithoutOTP(
|
|||
}
|
||||
|
||||
func (s *sessionCache) AuthenticateWebUser(
|
||||
req *client.AuthenticateWebUserRequest, clientMeta *auth.ForwardedClientMetadata,
|
||||
ctx context.Context, req *client.AuthenticateWebUserRequest, clientMeta *auth.ForwardedClientMetadata,
|
||||
) (types.WebSession, error) {
|
||||
authReq := auth.AuthenticateUserRequest{
|
||||
Username: req.User,
|
||||
|
@ -593,14 +594,14 @@ func (s *sessionCache) AuthenticateWebUser(
|
|||
if req.WebauthnAssertionResponse != nil {
|
||||
authReq.Webauthn = req.WebauthnAssertionResponse
|
||||
}
|
||||
return s.proxyClient.AuthenticateWebUser(authReq)
|
||||
return s.proxyClient.AuthenticateWebUser(ctx, authReq)
|
||||
}
|
||||
|
||||
// GetCertificateWithoutOTP returns a new user certificate for the specified request.
|
||||
func (s *sessionCache) GetCertificateWithoutOTP(
|
||||
c client.CreateSSHCertReq, clientMeta *auth.ForwardedClientMetadata,
|
||||
ctx context.Context, c client.CreateSSHCertReq, clientMeta *auth.ForwardedClientMetadata,
|
||||
) (*auth.SSHLoginResponse, error) {
|
||||
return s.proxyClient.AuthenticateSSHUser(auth.AuthenticateSSHRequest{
|
||||
return s.proxyClient.AuthenticateSSHUser(ctx, auth.AuthenticateSSHRequest{
|
||||
AuthenticateUserRequest: auth.AuthenticateUserRequest{
|
||||
Username: c.User,
|
||||
Pass: &auth.PassCreds{
|
||||
|
@ -619,9 +620,9 @@ func (s *sessionCache) GetCertificateWithoutOTP(
|
|||
// GetCertificateWithOTP returns a new user certificate for the specified request.
|
||||
// The request is used with the given OTP token.
|
||||
func (s *sessionCache) GetCertificateWithOTP(
|
||||
c client.CreateSSHCertReq, clientMeta *auth.ForwardedClientMetadata,
|
||||
ctx context.Context, c client.CreateSSHCertReq, clientMeta *auth.ForwardedClientMetadata,
|
||||
) (*auth.SSHLoginResponse, error) {
|
||||
return s.proxyClient.AuthenticateSSHUser(auth.AuthenticateSSHRequest{
|
||||
return s.proxyClient.AuthenticateSSHUser(ctx, auth.AuthenticateSSHRequest{
|
||||
AuthenticateUserRequest: auth.AuthenticateUserRequest{
|
||||
Username: c.User,
|
||||
OTP: &auth.OTPCreds{
|
||||
|
@ -639,8 +640,7 @@ func (s *sessionCache) GetCertificateWithOTP(
|
|||
}
|
||||
|
||||
func (s *sessionCache) AuthenticateSSHUser(
|
||||
c client.AuthenticateSSHUserRequest,
|
||||
clientMeta *auth.ForwardedClientMetadata,
|
||||
ctx context.Context, c client.AuthenticateSSHUserRequest, clientMeta *auth.ForwardedClientMetadata,
|
||||
) (*auth.SSHLoginResponse, error) {
|
||||
authReq := auth.AuthenticateUserRequest{
|
||||
Username: c.User,
|
||||
|
@ -658,7 +658,7 @@ func (s *sessionCache) AuthenticateSSHUser(
|
|||
Token: c.TOTPCode,
|
||||
}
|
||||
}
|
||||
return s.proxyClient.AuthenticateSSHUser(auth.AuthenticateSSHRequest{
|
||||
return s.proxyClient.AuthenticateSSHUser(ctx, auth.AuthenticateSSHRequest{
|
||||
AuthenticateUserRequest: authReq,
|
||||
PublicKey: c.PubKey,
|
||||
CompatibilityMode: c.Compatibility,
|
||||
|
@ -687,28 +687,28 @@ func (s *sessionCache) validateSession(ctx context.Context, user, sessionID stri
|
|||
if !trace.IsNotFound(err) {
|
||||
return nil, trace.Wrap(err)
|
||||
}
|
||||
return s.newSessionContext(user, sessionID)
|
||||
return s.newSessionContext(ctx, user, sessionID)
|
||||
}
|
||||
|
||||
func (s *sessionCache) invalidateSession(ctx *SessionContext) error {
|
||||
defer ctx.Close()
|
||||
clt, err := ctx.GetClient()
|
||||
func (s *sessionCache) invalidateSession(ctx context.Context, scx *SessionContext) error {
|
||||
defer scx.Close()
|
||||
clt, err := scx.GetClient()
|
||||
if err != nil {
|
||||
return trace.Wrap(err)
|
||||
}
|
||||
// Delete just the session - leave the bearer token to linger to avoid
|
||||
// failing a client query still using the old token.
|
||||
err = clt.WebSessions().Delete(context.TODO(), types.DeleteWebSessionRequest{
|
||||
User: ctx.user,
|
||||
SessionID: ctx.session.GetName(),
|
||||
err = clt.WebSessions().Delete(ctx, types.DeleteWebSessionRequest{
|
||||
User: scx.user,
|
||||
SessionID: scx.session.GetName(),
|
||||
})
|
||||
if err != nil && !trace.IsNotFound(err) {
|
||||
return trace.Wrap(err)
|
||||
}
|
||||
if err := clt.DeleteUserAppSessions(context.TODO(), &proto.DeleteUserAppSessionsRequest{Username: ctx.user}); err != nil {
|
||||
if err := clt.DeleteUserAppSessions(ctx, &proto.DeleteUserAppSessionsRequest{Username: scx.user}); err != nil {
|
||||
return trace.Wrap(err)
|
||||
}
|
||||
if err := s.releaseResources(ctx.GetUser(), ctx.session.GetName()); err != nil {
|
||||
if err := s.releaseResources(scx.GetUser(), scx.session.GetName()); err != nil {
|
||||
return trace.Wrap(err)
|
||||
}
|
||||
return nil
|
||||
|
@ -793,8 +793,8 @@ func (s *sessionCache) upsertSessionContext(user string) *sessionResources {
|
|||
}
|
||||
|
||||
// newSessionContext creates a new web session context for the specified user/session ID
|
||||
func (s *sessionCache) newSessionContext(user, sessionID string) (*SessionContext, error) {
|
||||
session, err := s.proxyClient.AuthenticateWebUser(auth.AuthenticateUserRequest{
|
||||
func (s *sessionCache) newSessionContext(ctx context.Context, user, sessionID string) (*SessionContext, error) {
|
||||
session, err := s.proxyClient.AuthenticateWebUser(ctx, auth.AuthenticateUserRequest{
|
||||
Username: user,
|
||||
Session: &auth.SessionCreds{
|
||||
ID: sessionID,
|
||||
|
|
Loading…
Reference in a new issue