Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: SSO MFA - Teleport Connect #48036

Merged
merged 12 commits into from
Nov 7, 2024
579 changes: 336 additions & 243 deletions gen/proto/go/teleport/lib/teleterm/v1/tshd_events_service.pb.go

Large diffs are not rendered by default.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

107 changes: 106 additions & 1 deletion gen/proto/ts/teleport/lib/teleterm/v1/tshd_events_service_pb.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions lib/client/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -495,6 +495,9 @@ type Config struct {
// MFAPromptConstructor is a custom MFA prompt constructor to use when prompting for MFA.
MFAPromptConstructor func(cfg *libmfa.PromptConfig) mfa.Prompt

// SSOMFACeremonyConstructor is a custom SSO MFA ceremony constructor.
SSOMFACeremonyConstructor func(rd *sso.Redirector) mfa.SSOMFACeremony

// CustomHardwareKeyPrompt is a custom hardware key prompt to use when asking
// for a hardware key PIN, touch, etc.
// If empty, a default CLI prompt is used.
Expand Down
4 changes: 4 additions & 0 deletions lib/client/mfa.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,5 +98,9 @@ func (tc *TeleportClient) NewSSOMFACeremony(ctx context.Context) (mfa.SSOMFACere
return nil, trace.Wrap(err)
}

if tc.SSOMFACeremonyConstructor != nil {
return tc.SSOMFACeremonyConstructor(rd), nil
}

return sso.NewCLIMFACeremony(rd), nil
}
25 changes: 25 additions & 0 deletions lib/client/sso/ceremony.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (
"github.com/gravitational/trace"

"github.com/gravitational/teleport/api/client/proto"
"github.com/gravitational/teleport/api/mfa"
"github.com/gravitational/teleport/lib/auth/authclient"
)

Expand Down Expand Up @@ -125,3 +126,27 @@ func NewCLIMFACeremony(rd *Redirector) *MFACeremony {
},
}
}

// NewConnectMFACeremony creates a new Teleport Connect SSO ceremony from the given redirector.
func NewConnectMFACeremony(rd *Redirector) mfa.SSOMFACeremony {
return &MFACeremony{
close: rd.Close,
ClientCallbackURL: rd.ClientCallbackURL,
HandleRedirect: func(ctx context.Context, redirectURL string) error {
// Connect handles redirect on the Electron side.
return nil
},
GetCallbackMFAToken: func(ctx context.Context) (string, error) {
loginResp, err := rd.WaitForResponse(ctx)
if err != nil {
return "", trace.Wrap(err)
}

if loginResp.MFAToken == "" {
return "", trace.BadParameter("login response for SSO MFA flow missing MFA token")
}

return loginResp.MFAToken, nil
},
}
}
2 changes: 2 additions & 0 deletions lib/teleterm/clusters/cluster_gateways.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import (
"github.com/gravitational/teleport/api/mfa"
"github.com/gravitational/teleport/lib/client"
libmfa "github.com/gravitational/teleport/lib/client/mfa"
"github.com/gravitational/teleport/lib/client/sso"
"github.com/gravitational/teleport/lib/teleterm/api/uri"
"github.com/gravitational/teleport/lib/teleterm/gateway"
"github.com/gravitational/teleport/lib/tlsca"
Expand All @@ -52,6 +53,7 @@ type CreateGatewayParams struct {
// CreateGateway creates a gateway
func (c *Cluster) CreateGateway(ctx context.Context, params CreateGatewayParams) (gateway.Gateway, error) {
c.clusterClient.MFAPromptConstructor = params.MFAPromptConstructor
c.clusterClient.SSOMFACeremonyConstructor = sso.NewConnectMFACeremony

switch {
case params.TargetURI.IsDB():
Expand Down
4 changes: 3 additions & 1 deletion lib/teleterm/daemon/daemon.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ import (
api "github.com/gravitational/teleport/gen/proto/go/teleport/lib/teleterm/v1"
"github.com/gravitational/teleport/lib/auth/authclient"
"github.com/gravitational/teleport/lib/client"
"github.com/gravitational/teleport/lib/client/sso"
dtauthn "github.com/gravitational/teleport/lib/devicetrust/authn"
"github.com/gravitational/teleport/lib/teleterm/api/uri"
"github.com/gravitational/teleport/lib/teleterm/clusters"
Expand Down Expand Up @@ -265,6 +266,8 @@ func (s *Service) ResolveClusterURI(uri uri.ResourceURI) (*clusters.Cluster, *cl
// Custom MFAPromptConstructor gets removed during the calls to Login and LoginPasswordless RPCs.
// Those RPCs assume that the default CLI prompt is in use.
clusterClient.MFAPromptConstructor = s.NewMFAPromptConstructor(cluster.URI)
clusterClient.SSOMFACeremonyConstructor = sso.NewConnectMFACeremony

return cluster, clusterClient, nil
}

Expand Down Expand Up @@ -1101,7 +1104,6 @@ func (s *Service) GetUserPreferences(ctx context.Context, clusterURI uri.Resourc
preferences, err = userpreferences.Get(ctx, rootAuthClient, leafAuthClient)
return trace.Wrap(err)
})

if err != nil {
return nil, trace.Wrap(err)
}
Expand Down
Loading
Loading