2016-09-26 18:48:55 +00:00
|
|
|
package service
|
2016-08-28 03:59:17 +00:00
|
|
|
|
|
|
|
import (
|
2016-09-01 04:51:38 +00:00
|
|
|
"bytes"
|
2021-09-14 12:11:07 +00:00
|
|
|
"context"
|
2016-08-28 03:59:17 +00:00
|
|
|
"encoding/json"
|
Add read replica testing helpers and fix non-sso login bug (#4908)
not set on the INSERT.
- OUT: Only sets the ID on the passed session and returns it. (`CreatedAt`, `AccessedAt`, are not set.)
New version:
```go
func (ds *Datastore) NewSession(ctx context.Context, userID uint, sessionKey string) (*fleet.Session, error) {
sqlStatement := `
INSERT INTO sessions (
user_id,
` + "`key`" + `
)
VALUES(?,?)
`
result, err := ds.writer.ExecContext(ctx, sqlStatement, userID, sessionKey)
if err != nil {
return nil, ctxerr.Wrap(ctx, err, "inserting session")
}
id, _ := result.LastInsertId() // cannot fail with the mysql driver
return ds.sessionByID(ctx, ds.writer, uint(id))
}
```
- IN: Define arguments that are truly used when creating a session.
- OUT: Load and return the fleet.Session struct with all values set (using the `ds.writer` to support read replicas correctly).
PS: The new `NewSession` version mimics what we already do with other entities, like policies (`Datastore.NewGlobalPolicy`).
2022-04-04 23:52:05 +00:00
|
|
|
"errors"
|
2016-08-28 03:59:17 +00:00
|
|
|
"fmt"
|
2016-09-01 04:51:38 +00:00
|
|
|
"io"
|
2016-08-28 03:59:17 +00:00
|
|
|
"net/http"
|
|
|
|
"net/http/httptest"
|
2016-09-26 17:14:39 +00:00
|
|
|
"strconv"
|
2016-08-28 03:59:17 +00:00
|
|
|
"testing"
|
Add read replica testing helpers and fix non-sso login bug (#4908)
not set on the INSERT.
- OUT: Only sets the ID on the passed session and returns it. (`CreatedAt`, `AccessedAt`, are not set.)
New version:
```go
func (ds *Datastore) NewSession(ctx context.Context, userID uint, sessionKey string) (*fleet.Session, error) {
sqlStatement := `
INSERT INTO sessions (
user_id,
` + "`key`" + `
)
VALUES(?,?)
`
result, err := ds.writer.ExecContext(ctx, sqlStatement, userID, sessionKey)
if err != nil {
return nil, ctxerr.Wrap(ctx, err, "inserting session")
}
id, _ := result.LastInsertId() // cannot fail with the mysql driver
return ds.sessionByID(ctx, ds.writer, uint(id))
}
```
- IN: Define arguments that are truly used when creating a session.
- OUT: Load and return the fleet.Session struct with all values set (using the `ds.writer` to support read replicas correctly).
PS: The new `NewSession` version mimics what we already do with other entities, like policies (`Datastore.NewGlobalPolicy`).
2022-04-04 23:52:05 +00:00
|
|
|
"time"
|
2016-08-28 03:59:17 +00:00
|
|
|
|
2021-11-24 20:56:54 +00:00
|
|
|
"github.com/fleetdm/fleet/v4/pkg/fleethttp"
|
2021-06-26 04:46:51 +00:00
|
|
|
"github.com/fleetdm/fleet/v4/server/fleet"
|
2021-08-04 13:40:04 +00:00
|
|
|
"github.com/fleetdm/fleet/v4/server/mock"
|
2021-06-06 22:07:29 +00:00
|
|
|
|
2016-09-01 04:51:38 +00:00
|
|
|
"github.com/stretchr/testify/assert"
|
2016-09-26 17:14:39 +00:00
|
|
|
"github.com/stretchr/testify/require"
|
2016-08-28 03:59:17 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
func TestLogin(t *testing.T) {
|
2021-07-05 13:17:31 +00:00
|
|
|
ds, users, server := setupAuthTest(t)
|
2022-01-13 19:57:44 +00:00
|
|
|
loginTests := []struct {
|
2021-06-24 20:42:29 +00:00
|
|
|
email string
|
2016-08-28 03:59:17 +00:00
|
|
|
status int
|
|
|
|
password string
|
|
|
|
}{
|
|
|
|
{
|
2021-06-24 20:42:29 +00:00
|
|
|
email: "admin1@example.com",
|
2016-09-29 02:44:05 +00:00
|
|
|
password: testUsers["admin1"].PlaintextPassword,
|
2016-08-28 03:59:17 +00:00
|
|
|
status: http.StatusOK,
|
|
|
|
},
|
2016-10-11 16:22:11 +00:00
|
|
|
{
|
2021-06-24 20:42:29 +00:00
|
|
|
email: "user1@example.com",
|
2016-10-11 16:22:11 +00:00
|
|
|
password: testUsers["user1"].PlaintextPassword,
|
|
|
|
status: http.StatusOK,
|
|
|
|
},
|
2016-08-28 03:59:17 +00:00
|
|
|
{
|
2021-06-24 20:42:29 +00:00
|
|
|
email: "nosuchuser@example.com",
|
2016-08-28 03:59:17 +00:00
|
|
|
password: "nosuchuser",
|
|
|
|
status: http.StatusUnauthorized,
|
|
|
|
},
|
|
|
|
{
|
2021-06-24 20:42:29 +00:00
|
|
|
email: "admin1@example.com",
|
2016-08-28 03:59:17 +00:00
|
|
|
password: "badpassword",
|
|
|
|
status: http.StatusUnauthorized,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, tt := range loginTests {
|
2016-09-01 04:51:38 +00:00
|
|
|
// test sessions
|
2021-06-24 20:42:29 +00:00
|
|
|
testUser := users[tt.email]
|
2016-09-01 04:51:38 +00:00
|
|
|
|
2016-09-08 01:24:11 +00:00
|
|
|
params := loginRequest{
|
2021-06-24 20:42:29 +00:00
|
|
|
Email: tt.email,
|
2016-09-01 04:51:38 +00:00
|
|
|
Password: tt.password,
|
2016-08-28 03:59:17 +00:00
|
|
|
}
|
2016-09-08 01:24:11 +00:00
|
|
|
j, err := json.Marshal(¶ms)
|
2016-09-14 18:40:51 +00:00
|
|
|
assert.Nil(t, err)
|
|
|
|
|
2021-09-15 19:27:53 +00:00
|
|
|
requestBody := io.NopCloser(bytes.NewBuffer(j))
|
2022-04-05 15:35:53 +00:00
|
|
|
resp, err := http.Post(server.URL+"/api/latest/fleet/login", "application/json", requestBody)
|
2016-12-30 00:40:12 +00:00
|
|
|
require.Nil(t, err)
|
2016-09-14 18:40:51 +00:00
|
|
|
assert.Equal(t, tt.status, resp.StatusCode)
|
2016-08-28 03:59:17 +00:00
|
|
|
|
2022-01-13 19:57:44 +00:00
|
|
|
jsn := struct {
|
2021-06-06 22:07:29 +00:00
|
|
|
User *fleet.User `json:"user"`
|
2016-12-30 00:40:12 +00:00
|
|
|
Token string `json:"token"`
|
|
|
|
Err []map[string]string `json:"errors,omitempty"`
|
2016-08-28 03:59:17 +00:00
|
|
|
}{}
|
2016-09-14 18:40:51 +00:00
|
|
|
err = json.NewDecoder(resp.Body).Decode(&jsn)
|
2016-12-30 00:40:12 +00:00
|
|
|
require.Nil(t, err)
|
2016-08-28 03:59:17 +00:00
|
|
|
|
|
|
|
if tt.status != http.StatusOK {
|
2016-09-14 18:40:51 +00:00
|
|
|
assert.NotEqual(t, "", jsn.Err)
|
2016-08-28 03:59:17 +00:00
|
|
|
continue // skip remaining tests
|
|
|
|
}
|
|
|
|
|
2016-10-11 16:22:11 +00:00
|
|
|
require.NotNil(t, jsn.User)
|
2021-06-24 20:42:29 +00:00
|
|
|
assert.Equal(t, tt.email, jsn.User.Email)
|
2016-08-28 03:59:17 +00:00
|
|
|
|
2016-09-01 04:51:38 +00:00
|
|
|
// ensure that a session was created for our test user and stored
|
2021-09-14 12:11:07 +00:00
|
|
|
sessions, err := ds.ListSessionsForUser(context.Background(), testUser.ID)
|
2016-09-01 04:51:38 +00:00
|
|
|
assert.Nil(t, err)
|
|
|
|
assert.Len(t, sessions, 1)
|
|
|
|
|
|
|
|
// ensure the session key is not blank
|
|
|
|
assert.NotEqual(t, "", sessions[0].Key)
|
|
|
|
|
|
|
|
// test logout
|
2022-04-05 15:35:53 +00:00
|
|
|
req, _ := http.NewRequest("POST", server.URL+"/api/latest/fleet/logout", nil)
|
2016-09-08 01:24:11 +00:00
|
|
|
req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", jsn.Token))
|
2021-11-24 20:56:54 +00:00
|
|
|
client := fleethttp.NewClient()
|
2016-09-01 04:51:38 +00:00
|
|
|
resp, err = client.Do(req)
|
2016-09-26 17:14:39 +00:00
|
|
|
require.Nil(t, err)
|
|
|
|
assert.Equal(t, http.StatusOK, resp.StatusCode, strconv.Itoa(tt.status))
|
2016-09-14 18:40:51 +00:00
|
|
|
|
2023-10-27 18:28:54 +00:00
|
|
|
_, err = io.ReadAll(resp.Body)
|
2016-09-14 18:40:51 +00:00
|
|
|
assert.Nil(t, err)
|
|
|
|
|
2016-09-01 04:51:38 +00:00
|
|
|
// ensure that our user's session was deleted from the store
|
2021-09-14 12:11:07 +00:00
|
|
|
sessions, err = ds.ListSessionsForUser(context.Background(), testUser.ID)
|
2020-02-19 02:11:16 +00:00
|
|
|
assert.Nil(t, err)
|
2016-09-01 04:51:38 +00:00
|
|
|
assert.Len(t, sessions, 0)
|
2016-08-28 03:59:17 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-08-04 13:40:04 +00:00
|
|
|
func setupAuthTest(t *testing.T) (fleet.Datastore, map[string]fleet.User, *httptest.Server) {
|
|
|
|
ds := new(mock.Store)
|
|
|
|
var users []*fleet.User
|
|
|
|
sessions := make(map[string]*fleet.Session)
|
2021-09-14 12:11:07 +00:00
|
|
|
ds.NewUserFunc = func(ctx context.Context, user *fleet.User) (*fleet.User, error) {
|
2021-08-04 13:40:04 +00:00
|
|
|
users = append(users, user)
|
|
|
|
return user, nil
|
|
|
|
}
|
2021-09-14 12:11:07 +00:00
|
|
|
ds.SessionByKeyFunc = func(ctx context.Context, key string) (*fleet.Session, error) {
|
2021-08-04 13:40:04 +00:00
|
|
|
return sessions[key], nil
|
|
|
|
}
|
2021-09-14 12:11:07 +00:00
|
|
|
ds.MarkSessionAccessedFunc = func(ctx context.Context, session *fleet.Session) error {
|
Add read replica testing helpers and fix non-sso login bug (#4908)
not set on the INSERT.
- OUT: Only sets the ID on the passed session and returns it. (`CreatedAt`, `AccessedAt`, are not set.)
New version:
```go
func (ds *Datastore) NewSession(ctx context.Context, userID uint, sessionKey string) (*fleet.Session, error) {
sqlStatement := `
INSERT INTO sessions (
user_id,
` + "`key`" + `
)
VALUES(?,?)
`
result, err := ds.writer.ExecContext(ctx, sqlStatement, userID, sessionKey)
if err != nil {
return nil, ctxerr.Wrap(ctx, err, "inserting session")
}
id, _ := result.LastInsertId() // cannot fail with the mysql driver
return ds.sessionByID(ctx, ds.writer, uint(id))
}
```
- IN: Define arguments that are truly used when creating a session.
- OUT: Load and return the fleet.Session struct with all values set (using the `ds.writer` to support read replicas correctly).
PS: The new `NewSession` version mimics what we already do with other entities, like policies (`Datastore.NewGlobalPolicy`).
2022-04-04 23:52:05 +00:00
|
|
|
s := sessions[session.Key]
|
|
|
|
s.AccessedAt = time.Now()
|
|
|
|
sessions[session.Key] = s
|
2021-08-04 13:40:04 +00:00
|
|
|
return nil
|
|
|
|
}
|
2021-09-14 12:11:07 +00:00
|
|
|
ds.UserByIDFunc = func(ctx context.Context, id uint) (*fleet.User, error) {
|
Add read replica testing helpers and fix non-sso login bug (#4908)
not set on the INSERT.
- OUT: Only sets the ID on the passed session and returns it. (`CreatedAt`, `AccessedAt`, are not set.)
New version:
```go
func (ds *Datastore) NewSession(ctx context.Context, userID uint, sessionKey string) (*fleet.Session, error) {
sqlStatement := `
INSERT INTO sessions (
user_id,
` + "`key`" + `
)
VALUES(?,?)
`
result, err := ds.writer.ExecContext(ctx, sqlStatement, userID, sessionKey)
if err != nil {
return nil, ctxerr.Wrap(ctx, err, "inserting session")
}
id, _ := result.LastInsertId() // cannot fail with the mysql driver
return ds.sessionByID(ctx, ds.writer, uint(id))
}
```
- IN: Define arguments that are truly used when creating a session.
- OUT: Load and return the fleet.Session struct with all values set (using the `ds.writer` to support read replicas correctly).
PS: The new `NewSession` version mimics what we already do with other entities, like policies (`Datastore.NewGlobalPolicy`).
2022-04-04 23:52:05 +00:00
|
|
|
for _, user := range users {
|
|
|
|
if user.ID == id {
|
|
|
|
return user, nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil, errors.New("user not found")
|
2021-08-04 13:40:04 +00:00
|
|
|
}
|
2021-09-14 12:11:07 +00:00
|
|
|
ds.ListUsersFunc = func(ctx context.Context, opt fleet.UserListOptions) ([]*fleet.User, error) {
|
2021-08-04 13:40:04 +00:00
|
|
|
return users, nil
|
|
|
|
}
|
2021-09-14 12:11:07 +00:00
|
|
|
ds.ListSessionsForUserFunc = func(ctx context.Context, id uint) ([]*fleet.Session, error) {
|
Add read replica testing helpers and fix non-sso login bug (#4908)
not set on the INSERT.
- OUT: Only sets the ID on the passed session and returns it. (`CreatedAt`, `AccessedAt`, are not set.)
New version:
```go
func (ds *Datastore) NewSession(ctx context.Context, userID uint, sessionKey string) (*fleet.Session, error) {
sqlStatement := `
INSERT INTO sessions (
user_id,
` + "`key`" + `
)
VALUES(?,?)
`
result, err := ds.writer.ExecContext(ctx, sqlStatement, userID, sessionKey)
if err != nil {
return nil, ctxerr.Wrap(ctx, err, "inserting session")
}
id, _ := result.LastInsertId() // cannot fail with the mysql driver
return ds.sessionByID(ctx, ds.writer, uint(id))
}
```
- IN: Define arguments that are truly used when creating a session.
- OUT: Load and return the fleet.Session struct with all values set (using the `ds.writer` to support read replicas correctly).
PS: The new `NewSession` version mimics what we already do with other entities, like policies (`Datastore.NewGlobalPolicy`).
2022-04-04 23:52:05 +00:00
|
|
|
var userSessions []*fleet.Session
|
2021-08-04 13:40:04 +00:00
|
|
|
for _, session := range sessions {
|
|
|
|
if session.UserID == id {
|
Add read replica testing helpers and fix non-sso login bug (#4908)
not set on the INSERT.
- OUT: Only sets the ID on the passed session and returns it. (`CreatedAt`, `AccessedAt`, are not set.)
New version:
```go
func (ds *Datastore) NewSession(ctx context.Context, userID uint, sessionKey string) (*fleet.Session, error) {
sqlStatement := `
INSERT INTO sessions (
user_id,
` + "`key`" + `
)
VALUES(?,?)
`
result, err := ds.writer.ExecContext(ctx, sqlStatement, userID, sessionKey)
if err != nil {
return nil, ctxerr.Wrap(ctx, err, "inserting session")
}
id, _ := result.LastInsertId() // cannot fail with the mysql driver
return ds.sessionByID(ctx, ds.writer, uint(id))
}
```
- IN: Define arguments that are truly used when creating a session.
- OUT: Load and return the fleet.Session struct with all values set (using the `ds.writer` to support read replicas correctly).
PS: The new `NewSession` version mimics what we already do with other entities, like policies (`Datastore.NewGlobalPolicy`).
2022-04-04 23:52:05 +00:00
|
|
|
userSessions = append(userSessions, session)
|
2021-08-04 13:40:04 +00:00
|
|
|
}
|
|
|
|
}
|
Add read replica testing helpers and fix non-sso login bug (#4908)
not set on the INSERT.
- OUT: Only sets the ID on the passed session and returns it. (`CreatedAt`, `AccessedAt`, are not set.)
New version:
```go
func (ds *Datastore) NewSession(ctx context.Context, userID uint, sessionKey string) (*fleet.Session, error) {
sqlStatement := `
INSERT INTO sessions (
user_id,
` + "`key`" + `
)
VALUES(?,?)
`
result, err := ds.writer.ExecContext(ctx, sqlStatement, userID, sessionKey)
if err != nil {
return nil, ctxerr.Wrap(ctx, err, "inserting session")
}
id, _ := result.LastInsertId() // cannot fail with the mysql driver
return ds.sessionByID(ctx, ds.writer, uint(id))
}
```
- IN: Define arguments that are truly used when creating a session.
- OUT: Load and return the fleet.Session struct with all values set (using the `ds.writer` to support read replicas correctly).
PS: The new `NewSession` version mimics what we already do with other entities, like policies (`Datastore.NewGlobalPolicy`).
2022-04-04 23:52:05 +00:00
|
|
|
return userSessions, nil
|
2021-08-04 13:40:04 +00:00
|
|
|
}
|
2021-09-14 12:11:07 +00:00
|
|
|
ds.SessionByIDFunc = func(ctx context.Context, id uint) (*fleet.Session, error) {
|
2021-08-04 13:40:04 +00:00
|
|
|
for _, session := range sessions {
|
|
|
|
if session.ID == id {
|
|
|
|
return session, nil
|
|
|
|
}
|
|
|
|
}
|
Add read replica testing helpers and fix non-sso login bug (#4908)
not set on the INSERT.
- OUT: Only sets the ID on the passed session and returns it. (`CreatedAt`, `AccessedAt`, are not set.)
New version:
```go
func (ds *Datastore) NewSession(ctx context.Context, userID uint, sessionKey string) (*fleet.Session, error) {
sqlStatement := `
INSERT INTO sessions (
user_id,
` + "`key`" + `
)
VALUES(?,?)
`
result, err := ds.writer.ExecContext(ctx, sqlStatement, userID, sessionKey)
if err != nil {
return nil, ctxerr.Wrap(ctx, err, "inserting session")
}
id, _ := result.LastInsertId() // cannot fail with the mysql driver
return ds.sessionByID(ctx, ds.writer, uint(id))
}
```
- IN: Define arguments that are truly used when creating a session.
- OUT: Load and return the fleet.Session struct with all values set (using the `ds.writer` to support read replicas correctly).
PS: The new `NewSession` version mimics what we already do with other entities, like policies (`Datastore.NewGlobalPolicy`).
2022-04-04 23:52:05 +00:00
|
|
|
return nil, errors.New("session not found")
|
2021-08-04 13:40:04 +00:00
|
|
|
}
|
2021-09-14 12:11:07 +00:00
|
|
|
ds.DestroySessionFunc = func(ctx context.Context, session *fleet.Session) error {
|
2021-08-04 13:40:04 +00:00
|
|
|
delete(sessions, session.Key)
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
usersMap, server := RunServerForTestsWithDS(t, ds)
|
2021-09-14 12:11:07 +00:00
|
|
|
ds.UserByEmailFunc = func(ctx context.Context, email string) (*fleet.User, error) {
|
2021-08-04 13:40:04 +00:00
|
|
|
user := usersMap[email]
|
|
|
|
return &user, nil
|
|
|
|
}
|
Add read replica testing helpers and fix non-sso login bug (#4908)
not set on the INSERT.
- OUT: Only sets the ID on the passed session and returns it. (`CreatedAt`, `AccessedAt`, are not set.)
New version:
```go
func (ds *Datastore) NewSession(ctx context.Context, userID uint, sessionKey string) (*fleet.Session, error) {
sqlStatement := `
INSERT INTO sessions (
user_id,
` + "`key`" + `
)
VALUES(?,?)
`
result, err := ds.writer.ExecContext(ctx, sqlStatement, userID, sessionKey)
if err != nil {
return nil, ctxerr.Wrap(ctx, err, "inserting session")
}
id, _ := result.LastInsertId() // cannot fail with the mysql driver
return ds.sessionByID(ctx, ds.writer, uint(id))
}
```
- IN: Define arguments that are truly used when creating a session.
- OUT: Load and return the fleet.Session struct with all values set (using the `ds.writer` to support read replicas correctly).
PS: The new `NewSession` version mimics what we already do with other entities, like policies (`Datastore.NewGlobalPolicy`).
2022-04-04 23:52:05 +00:00
|
|
|
ds.NewSessionFunc = func(ctx context.Context, userID uint, sessionKey string) (*fleet.Session, error) {
|
|
|
|
session := &fleet.Session{
|
|
|
|
UserID: userID,
|
|
|
|
Key: sessionKey,
|
|
|
|
AccessedAt: time.Now(),
|
|
|
|
}
|
|
|
|
sessions[sessionKey] = session
|
2021-08-04 13:40:04 +00:00
|
|
|
return session, nil
|
|
|
|
}
|
2022-12-23 16:05:16 +00:00
|
|
|
ds.NewActivityFunc = func(ctx context.Context, user *fleet.User, activity fleet.ActivityDetails) error {
|
2022-12-21 17:29:51 +00:00
|
|
|
return nil
|
|
|
|
}
|
2021-08-04 13:40:04 +00:00
|
|
|
return ds, usersMap, server
|
2021-07-08 15:50:43 +00:00
|
|
|
}
|
|
|
|
|
2021-07-16 18:28:13 +00:00
|
|
|
func getTestAdminToken(t *testing.T, server *httptest.Server) string {
|
2023-11-06 17:03:42 +00:00
|
|
|
return getTestUserToken(t, server, "admin1")
|
|
|
|
}
|
|
|
|
|
|
|
|
func getTestUserToken(t *testing.T, server *httptest.Server, testUserId string) string {
|
|
|
|
testUser := testUsers[testUserId]
|
2021-07-16 18:28:13 +00:00
|
|
|
|
|
|
|
params := loginRequest{
|
|
|
|
Email: testUser.Email,
|
|
|
|
Password: testUser.PlaintextPassword,
|
2021-07-05 13:17:31 +00:00
|
|
|
}
|
2021-07-16 18:28:13 +00:00
|
|
|
j, err := json.Marshal(¶ms)
|
|
|
|
assert.Nil(t, err)
|
|
|
|
|
2021-09-15 19:27:53 +00:00
|
|
|
requestBody := io.NopCloser(bytes.NewBuffer(j))
|
2022-04-05 15:35:53 +00:00
|
|
|
resp, err := http.Post(server.URL+"/api/latest/fleet/login", "application/json", requestBody)
|
2021-07-16 18:28:13 +00:00
|
|
|
require.Nil(t, err)
|
|
|
|
assert.Equal(t, http.StatusOK, resp.StatusCode)
|
|
|
|
|
2022-01-13 19:57:44 +00:00
|
|
|
jsn := struct {
|
2021-07-16 18:28:13 +00:00
|
|
|
User *fleet.User `json:"user"`
|
|
|
|
Token string `json:"token"`
|
|
|
|
Err []map[string]string `json:"errors,omitempty"`
|
|
|
|
}{}
|
|
|
|
err = json.NewDecoder(resp.Body).Decode(&jsn)
|
|
|
|
require.Nil(t, err)
|
|
|
|
|
|
|
|
return jsn.Token
|
2021-07-05 13:17:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestNoHeaderErrorsDifferently(t *testing.T) {
|
|
|
|
_, _, server := setupAuthTest(t)
|
|
|
|
|
2022-04-05 15:35:53 +00:00
|
|
|
req, _ := http.NewRequest("GET", server.URL+"/api/latest/fleet/users", nil)
|
2021-11-24 20:56:54 +00:00
|
|
|
client := fleethttp.NewClient()
|
2021-07-05 13:17:31 +00:00
|
|
|
resp, err := client.Do(req)
|
|
|
|
require.Nil(t, err)
|
2021-08-04 13:40:04 +00:00
|
|
|
defer resp.Body.Close()
|
2021-07-05 13:17:31 +00:00
|
|
|
assert.Equal(t, http.StatusUnauthorized, resp.StatusCode)
|
Add UUID to Fleet errors and clean up error msgs (#10411)
#8129
Apart from fixing the issue in #8129, this change also introduces UUIDs
to Fleet errors. To be able to match a returned error from the API to a
error in the Fleet logs. See
https://fleetdm.slack.com/archives/C019WG4GH0A/p1677780622769939 for
more context.
Samples with the changes in this PR:
```
curl -k -H "Authorization: Bearer $TEST_TOKEN" -H 'Content-Type:application/json' "https://localhost:8080/api/v1/fleet/sso" -d ''
{
"message": "Bad request",
"errors": [
{
"name": "base",
"reason": "Expected JSON Body"
}
],
"uuid": "a01f6e10-354c-4ff0-b96e-1f64adb500b0"
}
```
```
curl -k -H "Authorization: Bearer $TEST_TOKEN" -H 'Content-Type:application/json' "https://localhost:8080/api/v1/fleet/sso" -d 'asd'
{
"message": "Bad request",
"errors": [
{
"name": "base",
"reason": "json decoder error"
}
],
"uuid": "5f716a64-7550-464b-a1dd-e6a505a9f89d"
}
```
```
curl -k -X GET -H "Authorization: Bearer badtoken" "https://localhost:8080/api/latest/fleet/teams"
{
"message": "Authentication required",
"errors": [
{
"name": "base",
"reason": "Authentication required"
}
],
"uuid": "efe45bc0-f956-4bf9-ba4f-aa9020a9aaaf"
}
```
```
curl -k -X PATCH -H "Authorization: Bearer $TEST_TOKEN" "https://localhost:8080/api/latest/fleet/users/14" -d '{"name": "Manuel2", "password": "what", "new_password": "p4ssw0rd.12345"}'
{
"message": "Authorization header required",
"errors": [
{
"name": "base",
"reason": "Authorization header required"
}
],
"uuid": "57f78cd0-4559-464f-9df7-36c9ef7c89b3"
}
```
```
curl -k -X PATCH -H "Authorization: Bearer $TEST_TOKEN" "https://localhost:8080/api/latest/fleet/users/14" -d '{"name": "Manuel2", "password": "what", "new_password": "p4ssw0rd.12345"}'
{
"message": "Permission Denied",
"uuid": "7f0220ad-6de7-4faf-8b6c-8d7ff9d2ca06"
}
```
- [X] Changes file added for user-visible changes in `changes/` or
`orbit/changes/`.
See [Changes
files](https://fleetdm.com/docs/contributing/committing-changes#changes-files)
for more information.
- [X] Documented any API changes (docs/Using-Fleet/REST-API.md or
docs/Contributing/API-for-contributors.md)
- ~[ ] Documented any permissions changes~
- ~[ ] Input data is properly validated, `SELECT *` is avoided, SQL
injection is prevented (using placeholders for values in statements)~
- ~[ ] Added support on fleet's osquery simulator `cmd/osquery-perf` for
new osquery data ingestion features.~
- [X] Added/updated tests
- [X] Manual QA for all new/changed functionality
- For Orbit and Fleet Desktop changes:
- [X] Manual QA must be performed in the three main OSs, macOS, Windows
and Linux.
- ~[ ] Auto-update manual QA, from released version of component to new
version (see [tools/tuf/test](../tools/tuf/test/README.md)).~
2023-03-13 16:44:06 +00:00
|
|
|
jsn := struct {
|
|
|
|
Message string `json:"message"`
|
|
|
|
Errs []map[string]string `json:"errors,omitempty"`
|
|
|
|
UUID string `json:"uuid"`
|
|
|
|
}{}
|
|
|
|
err = json.NewDecoder(resp.Body).Decode(&jsn)
|
|
|
|
require.NoError(t, err)
|
|
|
|
assert.Equal(t, "Authorization header required", jsn.Message)
|
|
|
|
require.Len(t, jsn.Errs, 1)
|
|
|
|
assert.Equal(t, "base", jsn.Errs[0]["name"])
|
|
|
|
assert.Equal(t, "Authorization header required", jsn.Errs[0]["reason"])
|
|
|
|
assert.NotEmpty(t, jsn.UUID)
|
2021-07-05 13:17:31 +00:00
|
|
|
|
2022-04-05 15:35:53 +00:00
|
|
|
req, _ = http.NewRequest("GET", server.URL+"/api/latest/fleet/users", nil)
|
2021-07-05 13:17:31 +00:00
|
|
|
req.Header.Add("Authorization", "Bearer AAAA")
|
|
|
|
resp, err = client.Do(req)
|
Add UUID to Fleet errors and clean up error msgs (#10411)
#8129
Apart from fixing the issue in #8129, this change also introduces UUIDs
to Fleet errors. To be able to match a returned error from the API to a
error in the Fleet logs. See
https://fleetdm.slack.com/archives/C019WG4GH0A/p1677780622769939 for
more context.
Samples with the changes in this PR:
```
curl -k -H "Authorization: Bearer $TEST_TOKEN" -H 'Content-Type:application/json' "https://localhost:8080/api/v1/fleet/sso" -d ''
{
"message": "Bad request",
"errors": [
{
"name": "base",
"reason": "Expected JSON Body"
}
],
"uuid": "a01f6e10-354c-4ff0-b96e-1f64adb500b0"
}
```
```
curl -k -H "Authorization: Bearer $TEST_TOKEN" -H 'Content-Type:application/json' "https://localhost:8080/api/v1/fleet/sso" -d 'asd'
{
"message": "Bad request",
"errors": [
{
"name": "base",
"reason": "json decoder error"
}
],
"uuid": "5f716a64-7550-464b-a1dd-e6a505a9f89d"
}
```
```
curl -k -X GET -H "Authorization: Bearer badtoken" "https://localhost:8080/api/latest/fleet/teams"
{
"message": "Authentication required",
"errors": [
{
"name": "base",
"reason": "Authentication required"
}
],
"uuid": "efe45bc0-f956-4bf9-ba4f-aa9020a9aaaf"
}
```
```
curl -k -X PATCH -H "Authorization: Bearer $TEST_TOKEN" "https://localhost:8080/api/latest/fleet/users/14" -d '{"name": "Manuel2", "password": "what", "new_password": "p4ssw0rd.12345"}'
{
"message": "Authorization header required",
"errors": [
{
"name": "base",
"reason": "Authorization header required"
}
],
"uuid": "57f78cd0-4559-464f-9df7-36c9ef7c89b3"
}
```
```
curl -k -X PATCH -H "Authorization: Bearer $TEST_TOKEN" "https://localhost:8080/api/latest/fleet/users/14" -d '{"name": "Manuel2", "password": "what", "new_password": "p4ssw0rd.12345"}'
{
"message": "Permission Denied",
"uuid": "7f0220ad-6de7-4faf-8b6c-8d7ff9d2ca06"
}
```
- [X] Changes file added for user-visible changes in `changes/` or
`orbit/changes/`.
See [Changes
files](https://fleetdm.com/docs/contributing/committing-changes#changes-files)
for more information.
- [X] Documented any API changes (docs/Using-Fleet/REST-API.md or
docs/Contributing/API-for-contributors.md)
- ~[ ] Documented any permissions changes~
- ~[ ] Input data is properly validated, `SELECT *` is avoided, SQL
injection is prevented (using placeholders for values in statements)~
- ~[ ] Added support on fleet's osquery simulator `cmd/osquery-perf` for
new osquery data ingestion features.~
- [X] Added/updated tests
- [X] Manual QA for all new/changed functionality
- For Orbit and Fleet Desktop changes:
- [X] Manual QA must be performed in the three main OSs, macOS, Windows
and Linux.
- ~[ ] Auto-update manual QA, from released version of component to new
version (see [tools/tuf/test](../tools/tuf/test/README.md)).~
2023-03-13 16:44:06 +00:00
|
|
|
require.NoError(t, err)
|
2021-07-05 13:17:31 +00:00
|
|
|
assert.Equal(t, http.StatusUnauthorized, resp.StatusCode)
|
Add UUID to Fleet errors and clean up error msgs (#10411)
#8129
Apart from fixing the issue in #8129, this change also introduces UUIDs
to Fleet errors. To be able to match a returned error from the API to a
error in the Fleet logs. See
https://fleetdm.slack.com/archives/C019WG4GH0A/p1677780622769939 for
more context.
Samples with the changes in this PR:
```
curl -k -H "Authorization: Bearer $TEST_TOKEN" -H 'Content-Type:application/json' "https://localhost:8080/api/v1/fleet/sso" -d ''
{
"message": "Bad request",
"errors": [
{
"name": "base",
"reason": "Expected JSON Body"
}
],
"uuid": "a01f6e10-354c-4ff0-b96e-1f64adb500b0"
}
```
```
curl -k -H "Authorization: Bearer $TEST_TOKEN" -H 'Content-Type:application/json' "https://localhost:8080/api/v1/fleet/sso" -d 'asd'
{
"message": "Bad request",
"errors": [
{
"name": "base",
"reason": "json decoder error"
}
],
"uuid": "5f716a64-7550-464b-a1dd-e6a505a9f89d"
}
```
```
curl -k -X GET -H "Authorization: Bearer badtoken" "https://localhost:8080/api/latest/fleet/teams"
{
"message": "Authentication required",
"errors": [
{
"name": "base",
"reason": "Authentication required"
}
],
"uuid": "efe45bc0-f956-4bf9-ba4f-aa9020a9aaaf"
}
```
```
curl -k -X PATCH -H "Authorization: Bearer $TEST_TOKEN" "https://localhost:8080/api/latest/fleet/users/14" -d '{"name": "Manuel2", "password": "what", "new_password": "p4ssw0rd.12345"}'
{
"message": "Authorization header required",
"errors": [
{
"name": "base",
"reason": "Authorization header required"
}
],
"uuid": "57f78cd0-4559-464f-9df7-36c9ef7c89b3"
}
```
```
curl -k -X PATCH -H "Authorization: Bearer $TEST_TOKEN" "https://localhost:8080/api/latest/fleet/users/14" -d '{"name": "Manuel2", "password": "what", "new_password": "p4ssw0rd.12345"}'
{
"message": "Permission Denied",
"uuid": "7f0220ad-6de7-4faf-8b6c-8d7ff9d2ca06"
}
```
- [X] Changes file added for user-visible changes in `changes/` or
`orbit/changes/`.
See [Changes
files](https://fleetdm.com/docs/contributing/committing-changes#changes-files)
for more information.
- [X] Documented any API changes (docs/Using-Fleet/REST-API.md or
docs/Contributing/API-for-contributors.md)
- ~[ ] Documented any permissions changes~
- ~[ ] Input data is properly validated, `SELECT *` is avoided, SQL
injection is prevented (using placeholders for values in statements)~
- ~[ ] Added support on fleet's osquery simulator `cmd/osquery-perf` for
new osquery data ingestion features.~
- [X] Added/updated tests
- [X] Manual QA for all new/changed functionality
- For Orbit and Fleet Desktop changes:
- [X] Manual QA must be performed in the three main OSs, macOS, Windows
and Linux.
- ~[ ] Auto-update manual QA, from released version of component to new
version (see [tools/tuf/test](../tools/tuf/test/README.md)).~
2023-03-13 16:44:06 +00:00
|
|
|
err = json.NewDecoder(resp.Body).Decode(&jsn)
|
|
|
|
require.NoError(t, err)
|
|
|
|
assert.Equal(t, "Authentication required", jsn.Message)
|
|
|
|
require.Len(t, jsn.Errs, 1)
|
|
|
|
assert.Equal(t, "base", jsn.Errs[0]["name"])
|
|
|
|
assert.Equal(t, "Authentication required", jsn.Errs[0]["reason"])
|
|
|
|
assert.NotEmpty(t, jsn.UUID)
|
2021-07-05 13:17:31 +00:00
|
|
|
}
|