From eb1e7c8093d4c641ba95eb008fbb92a094dbada4 Mon Sep 17 00:00:00 2001 From: Brian Joerger Date: Mon, 16 Oct 2023 12:30:50 -0700 Subject: [PATCH] Fix hardware key support for sso web login (#33433) --- e | 2 +- lib/auth/auth_with_roles.go | 52 ++++++++++++++++++++++++++++++++++--- lib/auth/github.go | 13 +++++----- 3 files changed, 57 insertions(+), 10 deletions(-) diff --git a/e b/e index 02aee97987b02..1cc62ca2429dd 160000 --- a/e +++ b/e @@ -1 +1 @@ -Subproject commit 02aee97987b020075f18e99c1d3dade0af0d78bc +Subproject commit 1cc62ca2429dd9b9d129a8db49e40e9b09831671 diff --git a/lib/auth/auth_with_roles.go b/lib/auth/auth_with_roles.go index 8f62709df791d..86dde343cad2c 100644 --- a/lib/auth/auth_with_roles.go +++ b/lib/auth/auth_with_roles.go @@ -3580,6 +3580,11 @@ func (a *ServerWithRoles) CreateOIDCAuthRequest(ctx context.Context, req types.O } } + // Only the Proxy service can create web sessions via OIDC connector. + if req.CreateWebSession && !a.hasBuiltinRole(types.RoleProxy) { + return nil, trace.AccessDenied("this request can be only executed by a proxy") + } + oidcReq, err := a.authServer.CreateOIDCAuthRequest(ctx, req) if err != nil { emitSSOLoginFailureEvent(a.CloseContext(), a.authServer.emitter, events.LoginMethodOIDC, err, req.SSOTestFlow) @@ -3600,7 +3605,17 @@ func (a *ServerWithRoles) GetOIDCAuthRequest(ctx context.Context, id string) (*t func (a *ServerWithRoles) ValidateOIDCAuthCallback(ctx context.Context, q url.Values) (*OIDCAuthResponse, error) { // auth callback is it's own authz, no need to check extra permissions - return a.authServer.ValidateOIDCAuthCallback(ctx, q) + resp, err := a.authServer.ValidateOIDCAuthCallback(ctx, q) + if err != nil { + return nil, trace.Wrap(err) + } + + // Only the Proxy service can create web sessions via OIDC connector. + if resp.Session != nil && !a.hasBuiltinRole(types.RoleProxy) { + return nil, trace.AccessDenied("this request can be only executed by a proxy") + } + + return resp, nil } func (a *ServerWithRoles) DeleteOIDCConnector(ctx context.Context, connectorID string) error { @@ -3665,6 +3680,11 @@ func (a *ServerWithRoles) CreateSAMLAuthRequest(ctx context.Context, req types.S } } + // Only the Proxy service can create web sessions via SAML connector. + if req.CreateWebSession && !a.hasBuiltinRole(types.RoleProxy) { + return nil, trace.AccessDenied("this request can be only executed by a proxy") + } + samlReq, err := a.authServer.CreateSAMLAuthRequest(ctx, req) if err != nil { emitSSOLoginFailureEvent(a.CloseContext(), a.authServer.emitter, events.LoginMethodSAML, err, req.SSOTestFlow) @@ -3677,7 +3697,17 @@ func (a *ServerWithRoles) CreateSAMLAuthRequest(ctx context.Context, req types.S // ValidateSAMLResponse validates SAML auth response. func (a *ServerWithRoles) ValidateSAMLResponse(ctx context.Context, re string, connectorID string) (*SAMLAuthResponse, error) { // auth callback is it's own authz, no need to check extra permissions - return a.authServer.ValidateSAMLResponse(ctx, re, connectorID) + resp, err := a.authServer.ValidateSAMLResponse(ctx, re, connectorID) + if err != nil { + return nil, trace.Wrap(err) + } + + // Only the Proxy service can create web sessions via SAML connector. + if resp.Session != nil && !a.hasBuiltinRole(types.RoleProxy) { + return nil, trace.AccessDenied("this request can be only executed by a proxy") + } + + return resp, nil } // GetSAMLAuthRequest returns SAML auth request if found. @@ -3799,6 +3829,11 @@ func (a *ServerWithRoles) CreateGithubAuthRequest(ctx context.Context, req types } } + // Only the Proxy service can create web sessions via Github connector. + if req.CreateWebSession && !a.hasBuiltinRole(types.RoleProxy) { + return nil, trace.AccessDenied("this request can be only executed by a proxy") + } + githubReq, err := a.authServer.CreateGithubAuthRequest(ctx, req) if err != nil { emitSSOLoginFailureEvent(a.authServer.closeCtx, a.authServer.emitter, events.LoginMethodGithub, err, req.SSOTestFlow) @@ -3818,7 +3853,18 @@ func (a *ServerWithRoles) GetGithubAuthRequest(ctx context.Context, stateToken s } func (a *ServerWithRoles) ValidateGithubAuthCallback(ctx context.Context, q url.Values) (*GithubAuthResponse, error) { - return a.authServer.ValidateGithubAuthCallback(ctx, q) + // auth callback is it's own authz, no need to check extra permissions + resp, err := a.authServer.ValidateGithubAuthCallback(ctx, q) + if err != nil { + return nil, trace.Wrap(err) + } + + // Only the Proxy service can create web sessions via Github connector. + if resp.Session != nil && !a.hasBuiltinRole(types.RoleProxy) { + return nil, trace.AccessDenied("this request can be only executed by a proxy") + } + + return resp, nil } // EmitAuditEvent emits a single audit event diff --git a/lib/auth/github.go b/lib/auth/github.go index 072a81b93ef3f..94cbf8ad90fa8 100644 --- a/lib/auth/github.go +++ b/lib/auth/github.go @@ -646,12 +646,13 @@ func (a *Server) validateGithubAuthCallback(ctx context.Context, diagCtx *SSODia // If the request is coming from a browser, create a web session. if req.CreateWebSession { session, err := a.CreateWebSessionFromReq(ctx, types.NewWebSessionRequest{ - User: userState.GetName(), - Roles: userState.GetRoles(), - Traits: userState.GetTraits(), - SessionTTL: params.SessionTTL, - LoginTime: a.clock.Now().UTC(), - LoginIP: req.ClientLoginIP, + User: userState.GetName(), + Roles: userState.GetRoles(), + Traits: userState.GetTraits(), + SessionTTL: params.SessionTTL, + LoginTime: a.clock.Now().UTC(), + LoginIP: req.ClientLoginIP, + AttestWebSession: true, }) if err != nil { return nil, trace.Wrap(err, "Failed to create web session.")