mirror of
https://github.com/fleetdm/fleet
synced 2026-05-06 06:48:54 +00:00
Related to #7053, this uses the SSO config added in #7140 to enable JIT provisioning for premium instances.
235 lines
5.9 KiB
Go
235 lines
5.9 KiB
Go
package fleet
|
|
|
|
import (
|
|
"fmt"
|
|
"testing"
|
|
|
|
"github.com/fleetdm/fleet/v4/server/ptr"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
"golang.org/x/crypto/bcrypt"
|
|
)
|
|
|
|
func TestValidatePassword(t *testing.T) {
|
|
passwordTests := []struct {
|
|
Password, Email string
|
|
Admin, PasswordReset bool
|
|
}{
|
|
{"foobar", "mike@fleet.co", true, false},
|
|
{"bar0baz!?", "jason@fleet.co", true, false},
|
|
}
|
|
|
|
for _, tt := range passwordTests {
|
|
user := newTestUser(t, tt.Password, tt.Email)
|
|
|
|
err := user.ValidatePassword(tt.Password)
|
|
assert.Nil(t, err)
|
|
|
|
err = user.ValidatePassword("different")
|
|
assert.NotNil(t, err)
|
|
}
|
|
}
|
|
|
|
func newTestUser(t *testing.T, password, email string) *User {
|
|
var (
|
|
salt = "test-salt"
|
|
cost = 10
|
|
)
|
|
withSalt := []byte(fmt.Sprintf("%s%s", password, salt))
|
|
hashed, _ := bcrypt.GenerateFromPassword(withSalt, cost)
|
|
return &User{
|
|
Salt: salt,
|
|
Password: hashed,
|
|
Email: email,
|
|
}
|
|
}
|
|
|
|
func TestUserPasswordRequirements(t *testing.T) {
|
|
passwordTests := []struct {
|
|
password string
|
|
wantErr bool
|
|
}{
|
|
{
|
|
password: "foobar",
|
|
wantErr: true,
|
|
},
|
|
{
|
|
password: "foobarbaz",
|
|
wantErr: true,
|
|
},
|
|
{
|
|
password: "foobarbaz!",
|
|
wantErr: true,
|
|
},
|
|
{
|
|
password: "foobarbaz!3",
|
|
wantErr: true,
|
|
},
|
|
{
|
|
password: "foobarbaz!3!",
|
|
},
|
|
}
|
|
|
|
for _, tt := range passwordTests {
|
|
t.Run(tt.password, func(t *testing.T) {
|
|
err := ValidatePasswordRequirements(tt.password)
|
|
if tt.wantErr {
|
|
assert.NotNil(t, err)
|
|
} else {
|
|
assert.Nil(t, err)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestSaltAndHashPassword(t *testing.T) {
|
|
passwordTests := []string{"foobar!!", "bazbing!!"}
|
|
keySize := 24
|
|
cost := 10
|
|
|
|
for _, pwd := range passwordTests {
|
|
hashed, salt, err := saltAndHashPassword(keySize, pwd, cost)
|
|
require.NoError(t, err)
|
|
|
|
saltAndPass := []byte(fmt.Sprintf("%s%s", pwd, salt))
|
|
err = bcrypt.CompareHashAndPassword(hashed, saltAndPass)
|
|
require.NoError(t, err)
|
|
|
|
err = bcrypt.CompareHashAndPassword(hashed, []byte(fmt.Sprint("invalidpassword", salt)))
|
|
require.Error(t, err)
|
|
}
|
|
}
|
|
|
|
func TestAdminCreateValidate(t *testing.T) {
|
|
testCases := []struct {
|
|
payload UserPayload
|
|
// if errContains is empty then no error is expected
|
|
errContains []string
|
|
}{
|
|
{
|
|
payload: UserPayload{},
|
|
errContains: []string{"name", "email", "password"},
|
|
},
|
|
{
|
|
payload: UserPayload{Name: ptr.String(""), Email: ptr.String(""), Password: ptr.String("")},
|
|
errContains: []string{"name", "email", "password"},
|
|
},
|
|
{
|
|
payload: UserPayload{Name: ptr.String("Foo"), Email: ptr.String(""), Password: ptr.String("")},
|
|
errContains: []string{"email", "password"},
|
|
},
|
|
{
|
|
payload: UserPayload{Name: ptr.String("Foo"), Email: ptr.String("foo@example.com"), Password: ptr.String("")},
|
|
errContains: []string{"password"},
|
|
},
|
|
{
|
|
payload: UserPayload{Name: ptr.String("Foo"), Email: ptr.String("foo@example.com"), Password: ptr.String("foo")},
|
|
errContains: []string{"password"},
|
|
},
|
|
{
|
|
payload: UserPayload{Name: ptr.String("Foo"), Email: ptr.String("foo@example.com"), Password: ptr.String("Foofoofoo1337#"), InviteToken: ptr.String("foo")},
|
|
errContains: []string{"invite_token"},
|
|
},
|
|
{
|
|
payload: UserPayload{Name: ptr.String("Foo"), Email: ptr.String("foo@example.com"), Password: ptr.String("Foofoofoo1337#")},
|
|
errContains: nil,
|
|
},
|
|
}
|
|
|
|
for _, tc := range testCases {
|
|
t.Run("", func(t *testing.T) {
|
|
err := tc.payload.VerifyAdminCreate()
|
|
if len(tc.errContains) == 0 {
|
|
require.NoError(t, err)
|
|
} else {
|
|
ierr := err.(*InvalidArgumentError)
|
|
require.Equal(t, len(tc.errContains), len(*ierr))
|
|
for _, expected := range tc.errContains {
|
|
assertContainsErrorName(t, *ierr, expected)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestInviteCreateValidate(t *testing.T) {
|
|
testCases := []struct {
|
|
payload UserPayload
|
|
// if errContains is empty then no error is expected
|
|
errContains []string
|
|
}{
|
|
{
|
|
payload: UserPayload{},
|
|
errContains: []string{"name", "email", "password", "invite_token"},
|
|
},
|
|
{
|
|
payload: UserPayload{Name: ptr.String(""), Email: ptr.String(""), Password: ptr.String("")},
|
|
errContains: []string{"name", "email", "password", "invite_token"},
|
|
},
|
|
{
|
|
payload: UserPayload{Name: ptr.String("Foo"), Email: ptr.String(""), Password: ptr.String("")},
|
|
errContains: []string{"email", "password", "invite_token"},
|
|
},
|
|
{
|
|
payload: UserPayload{Name: ptr.String("Foo"), Email: ptr.String("foo@example.com"), Password: ptr.String("")},
|
|
errContains: []string{"password", "invite_token"},
|
|
},
|
|
{
|
|
payload: UserPayload{Name: ptr.String("Foo"), Email: ptr.String("foo@example.com"), Password: ptr.String("foo")},
|
|
errContains: []string{"password", "invite_token"},
|
|
},
|
|
{
|
|
payload: UserPayload{Name: ptr.String("Foo"), Email: ptr.String("foo@example.com"), Password: ptr.String("Foofoofoo1337#"), InviteToken: ptr.String("foo")},
|
|
errContains: nil,
|
|
},
|
|
}
|
|
|
|
for _, tc := range testCases {
|
|
t.Run("", func(t *testing.T) {
|
|
err := tc.payload.VerifyInviteCreate()
|
|
if len(tc.errContains) == 0 {
|
|
require.NoError(t, err)
|
|
} else {
|
|
ierr := err.(*InvalidArgumentError)
|
|
for _, expected := range tc.errContains {
|
|
require.Equal(t, len(tc.errContains), len(*ierr))
|
|
assertContainsErrorName(t, *ierr, expected)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestValidateEmailError(t *testing.T) {
|
|
errCases := []string{
|
|
"invalid",
|
|
"Name Surname <test@example.com>",
|
|
"test.com",
|
|
"",
|
|
}
|
|
|
|
for _, c := range errCases {
|
|
require.Error(t, ValidateEmail(c))
|
|
}
|
|
}
|
|
|
|
func TestValidateEmail(t *testing.T) {
|
|
cases := []string{
|
|
"user@example.com",
|
|
"user@example.localhost",
|
|
"user+1@example.com",
|
|
}
|
|
|
|
for _, c := range cases {
|
|
require.NoError(t, ValidateEmail(c))
|
|
}
|
|
}
|
|
|
|
func assertContainsErrorName(t *testing.T, invalid InvalidArgumentError, name string) {
|
|
for _, argErr := range invalid {
|
|
if argErr.name == name {
|
|
return
|
|
}
|
|
}
|
|
t.Errorf("%v does not contain error %s", invalid, name)
|
|
}
|