Skip to content

Commit

Permalink
Move types.NewWebSessionRequest to lib/auth/sessions.go.
Browse files Browse the repository at this point in the history
Move related methods to lib/auth/sessions.go.
  • Loading branch information
Joerger committed Apr 2, 2024
1 parent f9870eb commit 83a8afb
Show file tree
Hide file tree
Showing 3 changed files with 200 additions and 208 deletions.
52 changes: 0 additions & 52 deletions api/types/session.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,6 @@ import (

"github.com/gogo/protobuf/proto"
"github.com/gravitational/trace"

"github.com/gravitational/teleport/api/defaults"
"github.com/gravitational/teleport/api/utils/keys"
)

// WebSessionsGetter provides access to web sessions
Expand Down Expand Up @@ -615,55 +612,6 @@ func (r *WebTokenV3) String() string {
r.GetKind(), r.GetUser(), r.GetToken(), r.Expiry())
}

// CheckAndSetDefaults validates the request and sets defaults.
func (r *NewWebSessionRequest) CheckAndSetDefaults() error {
if r.User == "" {
return trace.BadParameter("user name required")
}
if len(r.Roles) == 0 {
return trace.BadParameter("roles required")
}
if len(r.Traits) == 0 {
return trace.BadParameter("traits required")
}
if r.SessionTTL == 0 {
r.SessionTTL = defaults.CertDuration
}
return nil
}

// NewWebSessionRequest defines a request to create a new user
// web session
// TODO (Joerger): Remove this and replace it with lib/auth.NewWebSessionRequest
// once /e is no longer dependent on this.
type NewWebSessionRequest struct {
// User specifies the user this session is bound to
User string
// LoginIP is an observed IP of the client, it will be embedded into certificates.
LoginIP string
// Roles optionally lists additional user roles
Roles []string
// Traits optionally lists role traits
Traits map[string][]string
// SessionTTL optionally specifies the session time-to-live.
// If left unspecified, the default certificate duration is used.
SessionTTL time.Duration
// LoginTime is the time that this user recently logged in.
LoginTime time.Time
// AccessRequests contains the UUIDs of the access requests currently in use.
AccessRequests []string
// RequestedResourceIDs optionally lists requested resources
RequestedResourceIDs []ResourceID
// AttestWebSession optionally attests the web session to meet private key policy requirements.
// This should only be set to true for web sessions that are purely in the purview of the Proxy
// and Auth services. Users should never have direct access to attested web sessions.
AttestWebSession bool
// PrivateKey is a specific private key to use when generating the web sessions' certificates.
// This should be provided when extending an attested web session in order to maintain the
// session attested status.
PrivateKey *keys.PrivateKey
}

// Check validates the request.
func (r *GetWebSessionRequest) Check() error {
if r.User == "" {
Expand Down
139 changes: 0 additions & 139 deletions lib/auth/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -4606,128 +4606,6 @@ func (a *Server) GetTokens(ctx context.Context, opts ...services.MarshalOption)
return tokens, nil
}

// newWebSessionOpts are WebSession creation options exclusive to Auth.
// These options complement [types.NewWebSessionRequest].
// See [Server.newWebSession].
type newWebSessionOpts struct {
// deviceExtensions are the device extensions to apply to the session.
// Only present on renewals, the original extensions are applied by
// [Server.AugmentWebSessionCertificates].
deviceExtensions *tlsca.DeviceExtensions
}

// newWebSession creates and returns a new web session for the specified request
func (a *Server) newWebSession(
ctx context.Context,
req NewWebSessionRequest,
opts *newWebSessionOpts,
) (types.WebSession, error) {
userState, err := a.GetUserOrLoginState(ctx, req.User)
if err != nil {
return nil, trace.Wrap(err)
}
if req.LoginIP == "" {
// TODO(antonam): consider turning this into error after all use cases are covered (before v14.0 testplan)
log.Debug("Creating new web session without login IP specified.")
}
clusterName, err := a.GetClusterName()
if err != nil {
return nil, trace.Wrap(err)
}
checker, err := services.NewAccessChecker(&services.AccessInfo{
Roles: req.Roles,
Traits: req.Traits,
AllowedResourceIDs: req.RequestedResourceIDs,
}, clusterName.GetClusterName(), a)
if err != nil {
return nil, trace.Wrap(err)
}

netCfg, err := a.GetClusterNetworkingConfig(ctx)
if err != nil {
return nil, trace.Wrap(err)
}

if req.PrivateKey == nil {
req.PrivateKey, err = native.GeneratePrivateKey()
if err != nil {
return nil, trace.Wrap(err)
}
}

sessionTTL := req.SessionTTL
if sessionTTL == 0 {
sessionTTL = checker.AdjustSessionTTL(apidefaults.CertDuration)
}

if req.AttestWebSession {
// Upsert web session attestation data so that this key's certs
// will be marked with the web session private key policy.
webAttData, err := services.NewWebSessionAttestationData(req.PrivateKey.Public())
if err != nil {
return nil, trace.Wrap(err)
}
if err = a.UpsertKeyAttestationData(ctx, webAttData, sessionTTL); err != nil {
return nil, trace.Wrap(err)
}
}

certReq := certRequest{
user: userState,
loginIP: req.LoginIP,
ttl: sessionTTL,
publicKey: req.PrivateKey.MarshalSSHPublicKey(),
checker: checker,
traits: req.Traits,
activeRequests: services.RequestIDs{AccessRequests: req.AccessRequests},
}
var hasDeviceExtensions bool
if opts != nil && opts.deviceExtensions != nil {
// Apply extensions to request.
certReq.deviceExtensions = DeviceExtensions(*opts.deviceExtensions)
hasDeviceExtensions = true
}

certs, err := a.generateUserCert(ctx, certReq)
if err != nil {
return nil, trace.Wrap(err)
}
token, err := utils.CryptoRandomHex(defaults.SessionTokenBytes)
if err != nil {
return nil, trace.Wrap(err)
}
bearerToken, err := utils.CryptoRandomHex(defaults.SessionTokenBytes)
if err != nil {
return nil, trace.Wrap(err)
}
bearerTokenTTL := min(sessionTTL, defaults.BearerTokenTTL)

startTime := a.clock.Now()
if !req.LoginTime.IsZero() {
startTime = req.LoginTime
}

sessionSpec := types.WebSessionSpecV2{
User: req.User,
Priv: req.PrivateKey.PrivateKeyPEM(),
Pub: certs.SSH,
TLSCert: certs.TLS,
Expires: startTime.UTC().Add(sessionTTL),
BearerToken: bearerToken,
BearerTokenExpires: startTime.UTC().Add(bearerTokenTTL),
LoginTime: req.LoginTime,
IdleTimeout: types.Duration(netCfg.GetWebIdleTimeout()),
HasDeviceExtensions: hasDeviceExtensions,
}
UserLoginCount.Inc()

sess, err := types.NewWebSession(token, types.KindWebSession, sessionSpec)
if err != nil {
return nil, trace.Wrap(err)
}
return sess, nil
}

// GetWebSessionInfo returns the web session specified with sessionID for the given user.
// The session is stripped of any authentication details.
// Implements auth.WebUIService
Expand Down Expand Up @@ -6515,23 +6393,6 @@ func (a *Server) ValidateMFAAuthResponse(ctx context.Context, resp *proto.MFAAut
}
}

func (a *Server) upsertWebSession(ctx context.Context, session types.WebSession) error {
if err := a.WebSessions().Upsert(ctx, session); err != nil {
return trace.Wrap(err)
}
token, err := types.NewWebToken(session.GetBearerTokenExpiryTime(), types.WebTokenSpecV3{
User: session.GetUser(),
Token: session.GetBearerToken(),
})
if err != nil {
return trace.Wrap(err)
}
if err := a.WebTokens().Upsert(ctx, token); err != nil {
return trace.Wrap(err)
}
return nil
}

func mergeKeySets(a, b types.CAKeySet) types.CAKeySet {
newKeySet := a.Clone()
newKeySet.SSH = append(newKeySet.SSH, b.SSH...)
Expand Down
Loading

0 comments on commit 83a8afb

Please sign in to comment.