diff --git a/lib/auth/session_access.go b/lib/auth/session_access.go index e526d23ac5a..882ac1c7b4b 100644 --- a/lib/auth/session_access.go +++ b/lib/auth/session_access.go @@ -98,7 +98,15 @@ type SessionAccessContext struct { func (ctx *SessionAccessContext) GetIdentifier(fields []string) (interface{}, error) { if fields[0] == "user" { if len(fields) == 2 || len(fields) == 3 { - switch fields[1] { + checkedFieldIdx := 1 + // Unify the format. Moderated session originally skipped the spec field (user.roles was used instead of + // user.spec.roles) which was not aligned with how our roles filtering works. + // Here we try support both cases. We don't want to modify the original fields slice, + // as that would change the reported error message (see return below). + if len(fields) == 3 && fields[1] == "spec" { + checkedFieldIdx = 2 + } + switch fields[checkedFieldIdx] { case "name": return ctx.Username, nil case "roles": diff --git a/lib/auth/session_access_test.go b/lib/auth/session_access_test.go index bf3658d50b4..2645860437a 100644 --- a/lib/auth/session_access_test.go +++ b/lib/auth/session_access_test.go @@ -73,6 +73,46 @@ func successStartTestCase(t *testing.T) startTestCase { } } +func successStartTestCaseSpec(t *testing.T) startTestCase { + hostRole, err := types.NewRole("host", types.RoleSpecV5{}) + require.NoError(t, err) + participantRole, err := types.NewRole("participant", types.RoleSpecV5{}) + require.NoError(t, err) + + hostRole.SetSessionRequirePolicies([]*types.SessionRequirePolicy{{ + Filter: "contains(user.spec.roles, \"participant\")", + Kinds: []string{string(types.SSHSessionKind), string(types.KubernetesSessionKind)}, + Count: 2, + OnLeave: types.OnSessionLeaveTerminate, + Modes: []string{"peer"}, + }}) + + participantRole.SetSessionJoinPolicies([]*types.SessionJoinPolicy{{ + Roles: []string{hostRole.GetName()}, + Kinds: []string{string(types.SSHSessionKind), string(types.KubernetesSessionKind)}, + Modes: []string{"*"}, + }}) + + return startTestCase{ + name: "success with spec", + host: []types.Role{hostRole}, + sessionKinds: []types.SessionKind{types.SSHSessionKind, types.KubernetesSessionKind}, + participants: []SessionAccessContext{ + { + Username: "participant", + Roles: []types.Role{participantRole}, + Mode: "peer", + }, + { + Username: "participant2", + Roles: []types.Role{participantRole}, + Mode: "peer", + }, + }, + expected: []bool{true, true}, + } +} + func failCountStartTestCase(t *testing.T) startTestCase { hostRole, err := types.NewRole("host", types.RoleSpecV5{}) require.NoError(t, err) @@ -173,6 +213,7 @@ func failFilterStartTestCase(t *testing.T) startTestCase { func TestSessionAccessStart(t *testing.T) { testCases := []startTestCase{ successStartTestCase(t), + successStartTestCaseSpec(t), failCountStartTestCase(t), failFilterStartTestCase(t), succeedDiscardPolicySetStartTestCase(t),