Skip to content

Commit 9d68b5f

Browse files
committed
Revert "Created check for device trust after MFA before creating web session (#62019) (#63260)"
This reverts commit 64e28c6.
1 parent e97dec3 commit 9d68b5f

5 files changed

Lines changed: 33 additions & 334 deletions

File tree

integration/appaccess/appaccess_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -588,6 +588,7 @@ func testAuditEvents(p *Pack, t *testing.T) {
588588
AppPublicAddr: p.rootAppPublicAddr,
589589
AppName: p.rootAppName,
590590
},
591+
PublicAddr: p.rootAppPublicAddr,
591592
}
592593
return len(cmp.Diff(
593594
expectedEvent,

lib/auth/sessions.go

Lines changed: 32 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -427,6 +427,8 @@ type NewAppSessionRequest struct {
427427
AppURI string
428428
// AppTargetPort signifies that the session is made to a specific port of a multi-port TCP app.
429429
AppTargetPort int
430+
// Identity is the identity of the user.
431+
Identity tlsca.Identity
430432
// ClientAddr is a client (user's) address.
431433
ClientAddr string
432434

@@ -496,8 +498,6 @@ func (a *Server) CreateAppSession(ctx context.Context, req *proto.CreateAppSessi
496498
MFAVerified: verifiedMFADeviceID,
497499
AppName: req.AppName,
498500
AppURI: req.URI,
499-
BotName: identity.BotName,
500-
BotInstanceID: identity.BotInstanceID,
501501
DeviceExtensions: DeviceExtensions(identity.DeviceExtensions),
502502
})
503503
if err != nil {
@@ -543,69 +543,6 @@ func (a *Server) CreateAppSessionFromReq(ctx context.Context, req NewAppSessionR
543543
return nil, trace.Wrap(err)
544544
}
545545

546-
// Audit fields used for both success and failure
547-
sessionStartEvent := &apievents.AppSessionStart{
548-
Metadata: apievents.Metadata{
549-
Type: events.AppSessionStartEvent,
550-
ClusterName: req.ClusterName,
551-
},
552-
ServerMetadata: apievents.ServerMetadata{
553-
ServerVersion: teleport.Version,
554-
ServerID: a.ServerID,
555-
ServerNamespace: apidefaults.Namespace,
556-
},
557-
ConnectionMetadata: apievents.ConnectionMetadata{
558-
RemoteAddr: req.ClientAddr,
559-
},
560-
AppMetadata: apievents.AppMetadata{
561-
AppURI: req.AppURI,
562-
AppPublicAddr: req.PublicAddr,
563-
AppName: req.AppName,
564-
AppTargetPort: uint32(req.AppTargetPort),
565-
},
566-
}
567-
568-
// Enforce device trust early via the AccessChecker.
569-
if err = checker.CheckDeviceAccess(services.AccessState{
570-
DeviceVerified: dtauthz.IsTLSDeviceVerified((*tlsca.DeviceExtensions)(&req.DeviceExtensions)),
571-
EnableDeviceVerification: true,
572-
IsBot: req.BotName != "",
573-
}); err != nil {
574-
userKind := apievents.UserKind_USER_KIND_HUMAN
575-
if req.BotName != "" {
576-
userKind = apievents.UserKind_USER_KIND_BOT
577-
}
578-
579-
userMetadata := apievents.UserMetadata{
580-
User: req.User,
581-
BotName: req.BotName,
582-
BotInstanceID: req.BotInstanceID,
583-
UserKind: userKind,
584-
AWSRoleARN: req.AWSRoleARN,
585-
}
586-
587-
if req.DeviceExtensions.DeviceID != "" {
588-
userMetadata.TrustedDevice = &apievents.DeviceMetadata{
589-
DeviceId: req.DeviceExtensions.DeviceID,
590-
AssetTag: req.DeviceExtensions.AssetTag,
591-
CredentialId: req.DeviceExtensions.CredentialID,
592-
}
593-
}
594-
errMsg := "requires a trusted device"
595-
596-
sessionStartEvent.Metadata.SetCode(events.AppSessionStartFailureCode)
597-
sessionStartEvent.UserMetadata = userMetadata
598-
sessionStartEvent.SessionMetadata = apievents.SessionMetadata{
599-
WithMFA: req.MFAVerified,
600-
}
601-
sessionStartEvent.Error = err.Error()
602-
sessionStartEvent.UserMessage = errMsg
603-
604-
a.emitter.EmitAuditEvent(a.closeCtx, sessionStartEvent)
605-
// err swallowed/obscured on purpose.
606-
return nil, trace.AccessDenied("%s", errMsg)
607-
}
608-
609546
// Create certificate for this session.
610547
priv, err := cryptosuites.GenerateKey(ctx, cryptosuites.GetCurrentSuiteFromAuthPreference(a), cryptosuites.UserTLS)
611548
if err != nil {
@@ -704,16 +641,36 @@ func (a *Server) CreateAppSessionFromReq(ctx context.Context, req NewAppSessionR
704641
userMetadata.User = session.GetUser()
705642
userMetadata.AWSRoleARN = req.AWSRoleARN
706643

707-
sessionStartEvent.Metadata.SetCode(events.AppSessionStartCode)
708-
sessionStartEvent.UserMetadata = userMetadata
709-
sessionStartEvent.SessionMetadata = apievents.SessionMetadata{
710-
SessionID: session.GetName(),
711-
WithMFA: req.MFAVerified,
712-
PrivateKeyPolicy: string(identity.PrivateKeyPolicy),
713-
}
714-
715-
if err := a.emitter.EmitAuditEvent(a.closeCtx, sessionStartEvent); err != nil {
716-
a.logger.WarnContext(ctx, "Failed to emit app session start event", "error", err)
644+
err = a.emitter.EmitAuditEvent(a.closeCtx, &apievents.AppSessionStart{
645+
Metadata: apievents.Metadata{
646+
Type: events.AppSessionStartEvent,
647+
Code: events.AppSessionStartCode,
648+
ClusterName: req.ClusterName,
649+
},
650+
ServerMetadata: apievents.ServerMetadata{
651+
ServerVersion: teleport.Version,
652+
ServerID: a.ServerID,
653+
ServerNamespace: apidefaults.Namespace,
654+
},
655+
SessionMetadata: apievents.SessionMetadata{
656+
SessionID: session.GetName(),
657+
WithMFA: req.MFAVerified,
658+
PrivateKeyPolicy: string(req.Identity.PrivateKeyPolicy),
659+
},
660+
UserMetadata: userMetadata,
661+
ConnectionMetadata: apievents.ConnectionMetadata{
662+
RemoteAddr: req.ClientAddr,
663+
},
664+
PublicAddr: req.PublicAddr,
665+
AppMetadata: apievents.AppMetadata{
666+
AppURI: req.AppURI,
667+
AppPublicAddr: req.PublicAddr,
668+
AppName: req.AppName,
669+
AppTargetPort: uint32(req.AppTargetPort),
670+
},
671+
})
672+
if err != nil {
673+
log.WithError(err).Warn("Failed to emit app session start event")
717674
}
718675

719676
return session, nil

lib/auth/sessions_test.go

Lines changed: 0 additions & 225 deletions
Original file line numberDiff line numberDiff line change
@@ -22,23 +22,13 @@ import (
2222
"time"
2323

2424
"github.com/google/go-cmp/cmp"
25-
"github.com/google/go-cmp/cmp/cmpopts"
26-
"github.com/google/uuid"
27-
"github.com/gravitational/trace"
28-
"github.com/jonboulle/clockwork"
2925
"github.com/stretchr/testify/assert"
3026
"github.com/stretchr/testify/require"
3127

32-
"github.com/gravitational/teleport/api/client/proto"
33-
"github.com/gravitational/teleport/api/constants"
3428
devicepb "github.com/gravitational/teleport/api/gen/proto/go/teleport/devicetrust/v1"
3529
"github.com/gravitational/teleport/api/types"
36-
apievents "github.com/gravitational/teleport/api/types/events"
3730
"github.com/gravitational/teleport/lib/auth"
3831
"github.com/gravitational/teleport/lib/auth/authtest"
39-
"github.com/gravitational/teleport/lib/events"
40-
"github.com/gravitational/teleport/lib/services"
41-
"github.com/gravitational/teleport/lib/tlsca"
4232
)
4333

4434
func TestServer_CreateWebSessionFromReq_deviceWebToken(t *testing.T) {
@@ -95,218 +85,3 @@ func TestServer_CreateWebSessionFromReq_deviceWebToken(t *testing.T) {
9585
}
9686
})
9787
}
98-
99-
func TestCreateAppSession_DeviceTrust(t *testing.T) {
100-
t.Parallel()
101-
102-
fakeClock := clockwork.NewFakeClock()
103-
104-
testAuthServer, err := authtest.NewAuthServer(authtest.AuthServerConfig{
105-
Clock: fakeClock,
106-
Dir: t.TempDir(),
107-
})
108-
require.NoError(t, err)
109-
t.Cleanup(func() { testAuthServer.Close() })
110-
111-
authServer := testAuthServer.AuthServer
112-
113-
tests := []struct {
114-
name string
115-
trustMode string
116-
botName string
117-
deviceExtensions auth.DeviceExtensions
118-
wantErr string
119-
}{
120-
{
121-
name: "Access Denied - Trusted Device Required but Missing",
122-
trustMode: constants.DeviceTrustModeRequired,
123-
deviceExtensions: auth.DeviceExtensions{},
124-
wantErr: "requires a trusted device",
125-
},
126-
{
127-
name: "Success - Trust Optional and Device Missing",
128-
trustMode: constants.DeviceTrustModeOptional,
129-
deviceExtensions: auth.DeviceExtensions{},
130-
},
131-
{
132-
name: "Success - Trust Mode Not Set",
133-
trustMode: "",
134-
deviceExtensions: auth.DeviceExtensions{},
135-
},
136-
{
137-
name: "Success - Trusted Device Required and Provided",
138-
trustMode: constants.DeviceTrustModeRequired,
139-
deviceExtensions: auth.DeviceExtensions{
140-
DeviceID: "macbook-id-123",
141-
AssetTag: "asset-tag-123",
142-
CredentialID: "cred-id-123",
143-
},
144-
},
145-
{
146-
name: "Success - Bot Access with RequiredForHumans and Missing Device",
147-
trustMode: constants.DeviceTrustModeRequiredForHumans,
148-
botName: "example-bot",
149-
deviceExtensions: auth.DeviceExtensions{},
150-
},
151-
{
152-
name: "Access Denied - Bot Access with Device Trust Required",
153-
trustMode: constants.DeviceTrustModeRequired,
154-
botName: "example-bot",
155-
deviceExtensions: auth.DeviceExtensions{},
156-
wantErr: "requires a trusted device",
157-
},
158-
{
159-
name: "Access Denied - Human Access with RequiredForHumans but Missing Device",
160-
trustMode: constants.DeviceTrustModeRequiredForHumans,
161-
botName: "",
162-
deviceExtensions: auth.DeviceExtensions{},
163-
wantErr: "requires a trusted device",
164-
},
165-
}
166-
167-
for _, tt := range tests {
168-
t.Run(tt.name, func(t *testing.T) {
169-
t.Parallel()
170-
ctx := t.Context()
171-
suffix := uuid.NewString()
172-
username := "user-" + suffix
173-
roleName := "role-" + suffix
174-
publicAddr := "www-" + suffix + ".example.com"
175-
176-
role, err := types.NewRole(roleName, types.RoleSpecV6{
177-
Options: types.RoleOptions{
178-
DeviceTrustMode: tt.trustMode,
179-
},
180-
Allow: types.RoleConditions{
181-
AppLabels: types.Labels{"*": []string{"*"}},
182-
},
183-
})
184-
require.NoError(t, err)
185-
_, err = authServer.CreateRole(ctx, role)
186-
require.NoError(t, err)
187-
188-
traits := map[string][]string{
189-
"groups": {"admins", "devs"},
190-
"email": {"alice@example.com"},
191-
}
192-
user, err := types.NewUser(username)
193-
require.NoError(t, err)
194-
user.SetTraits(traits)
195-
user.AddRole(roleName)
196-
_, err = authServer.CreateUser(ctx, user)
197-
require.NoError(t, err)
198-
199-
identity := tlsca.Identity{
200-
Username: username,
201-
BotName: tt.botName,
202-
DeviceExtensions: tlsca.DeviceExtensions(tt.deviceExtensions),
203-
}
204-
205-
cName, err := authServer.GetClusterName()
206-
require.NoError(t, err)
207-
clusterName := cName.GetClusterName()
208-
209-
checker, err := services.NewAccessChecker(&services.AccessInfo{
210-
Username: username,
211-
Roles: user.GetRoles(),
212-
}, clusterName, authServer)
213-
require.NoError(t, err)
214-
215-
req := &proto.CreateAppSessionRequest{
216-
Username: username,
217-
AppName: "example-app",
218-
URI: "http://example.com",
219-
ClusterName: clusterName,
220-
PublicAddr: publicAddr,
221-
}
222-
223-
startTime := fakeClock.Now()
224-
_, err = authServer.CreateAppSession(ctx, req, identity, checker)
225-
endTime := fakeClock.Now()
226-
227-
if tt.wantErr != "" {
228-
require.ErrorContains(t, err, tt.wantErr)
229-
assert.True(t, trace.IsAccessDenied(err), "Expected AccessDenied, got %v", err)
230-
} else {
231-
require.NoError(t, err)
232-
}
233-
234-
logEntries, _, err := testAuthServer.AuditLog.SearchEvents(ctx, events.SearchEventsRequest{
235-
From: startTime.Add(-time.Second),
236-
To: endTime.Add(time.Second),
237-
Limit: 100, // arbitrary, enough to allow for events from concurrent tests
238-
})
239-
require.NoError(t, err)
240-
241-
expectedKind := apievents.UserKind_USER_KIND_HUMAN
242-
if tt.botName != "" {
243-
expectedKind = apievents.UserKind_USER_KIND_BOT
244-
}
245-
246-
expectedEvent := &apievents.AppSessionStart{
247-
Metadata: apievents.Metadata{
248-
Type: events.AppSessionStartEvent,
249-
ClusterName: clusterName,
250-
},
251-
UserMetadata: apievents.UserMetadata{
252-
User: username,
253-
BotName: tt.botName,
254-
UserKind: expectedKind,
255-
},
256-
AppMetadata: apievents.AppMetadata{
257-
AppName: "example-app",
258-
AppURI: "http://example.com",
259-
AppPublicAddr: publicAddr,
260-
},
261-
}
262-
263-
if tt.wantErr == "" {
264-
expectedEvent.Metadata.Code = events.AppSessionStartCode
265-
expectedEvent.SessionMetadata.PrivateKeyPolicy = "none"
266-
} else {
267-
expectedEvent.Metadata.Code = events.AppSessionStartFailureCode
268-
expectedEvent.UserMessage = "requires a trusted device"
269-
expectedEvent.Error = "access to resource requires a trusted device"
270-
}
271-
272-
if tt.deviceExtensions.DeviceID != "" {
273-
expectedEvent.UserMetadata.TrustedDevice = &apievents.DeviceMetadata{
274-
DeviceId: tt.deviceExtensions.DeviceID,
275-
AssetTag: tt.deviceExtensions.AssetTag,
276-
CredentialId: tt.deviceExtensions.CredentialID,
277-
}
278-
}
279-
280-
var eventFound bool
281-
for _, event := range logEntries {
282-
appStart, ok := event.(*apievents.AppSessionStart)
283-
if !ok || appStart.UserMetadata.User != username {
284-
continue
285-
}
286-
287-
eventFound = true
288-
289-
diff := cmp.Diff(expectedEvent, appStart,
290-
cmpopts.IgnoreUnexported(
291-
apievents.AppSessionStart{},
292-
apievents.Metadata{},
293-
apievents.UserMetadata{},
294-
apievents.AppMetadata{},
295-
apievents.SessionMetadata{},
296-
apievents.ConnectionMetadata{},
297-
apievents.ServerMetadata{},
298-
apievents.DeviceMetadata{},
299-
),
300-
cmpopts.IgnoreFields(apievents.Metadata{}, "ID", "Time", "Index"),
301-
cmpopts.IgnoreFields(apievents.ServerMetadata{}, "ServerID", "ServerVersion", "ServerNamespace"),
302-
cmpopts.IgnoreFields(apievents.ConnectionMetadata{}, "RemoteAddr", "Protocol"),
303-
cmpopts.IgnoreFields(apievents.SessionMetadata{}, "SessionID"),
304-
cmpopts.IgnoreFields(apievents.AppSessionStart{}, "PublicAddr"), // deprecated field
305-
)
306-
307-
require.Empty(t, diff, "Audit event mismatch for case: %s\n%s", tt.name, diff)
308-
}
309-
require.True(t, eventFound, "Expected AppSessionStart event was not found in audit log")
310-
})
311-
}
312-
}

lib/services/access_checker.go

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -59,10 +59,6 @@ type AccessChecker interface {
5959
// CheckAccess checks access to the specified resource.
6060
CheckAccess(r AccessCheckable, state AccessState, matchers ...RoleMatcher) error
6161

62-
// CheckDeviceAccess verifies if the current device state satisfies the
63-
// device trust requirements of the user's RoleSet.
64-
CheckDeviceAccess(state AccessState) error
65-
6662
// CheckAccessToRemoteCluster checks access to remote cluster
6763
CheckAccessToRemoteCluster(cluster types.RemoteCluster) error
6864

0 commit comments

Comments
 (0)