mirror of https://github.com/hashicorp/boundary
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
235 lines
8.1 KiB
235 lines
8.1 KiB
package authenticate
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"strings"
|
|
"testing"
|
|
|
|
structpb "github.com/golang/protobuf/ptypes/struct"
|
|
"github.com/hashicorp/boundary/internal/auth"
|
|
"github.com/hashicorp/boundary/internal/auth/password"
|
|
"github.com/hashicorp/boundary/internal/authtoken"
|
|
"github.com/hashicorp/boundary/internal/db"
|
|
pbs "github.com/hashicorp/boundary/internal/gen/controller/api/services"
|
|
"github.com/hashicorp/boundary/internal/iam"
|
|
"github.com/hashicorp/boundary/internal/kms"
|
|
"github.com/hashicorp/boundary/internal/servers/controller/handlers"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
"google.golang.org/grpc/codes"
|
|
)
|
|
|
|
const (
|
|
testPassword = "thetestpassword"
|
|
testLoginName = "default"
|
|
)
|
|
|
|
func TestAuthenticate(t *testing.T) {
|
|
conn, _ := db.TestSetup(t, "postgres")
|
|
rw := db.New(conn)
|
|
wrapper := db.TestWrapper(t)
|
|
kms := kms.TestKms(t, conn, wrapper)
|
|
o, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper))
|
|
|
|
authTokenRepoFn := func() (*authtoken.Repository, error) { return authtoken.NewRepository(rw, rw, kms) }
|
|
iamRepoFn := func() (*iam.Repository, error) { return iam.NewRepository(rw, rw, kms) }
|
|
passwordRepoFn := func() (*password.Repository, error) { return password.NewRepository(rw, rw, kms) }
|
|
am := password.TestAuthMethods(t, conn, o.GetPublicId(), 1)[0]
|
|
|
|
acct, err := password.NewAccount(am.GetPublicId(), password.WithLoginName(testLoginName))
|
|
require.NoError(t, err)
|
|
|
|
pwRepo, err := passwordRepoFn()
|
|
require.NoError(t, err)
|
|
acct, err = pwRepo.CreateAccount(context.Background(), o.GetPublicId(), acct, password.WithPassword(testPassword))
|
|
require.NoError(t, err)
|
|
require.NotNil(t, acct)
|
|
|
|
cases := []struct {
|
|
name string
|
|
request *pbs.AuthenticateRequest
|
|
wantType string
|
|
wantErr error
|
|
}{
|
|
{
|
|
name: "basic",
|
|
request: &pbs.AuthenticateRequest{
|
|
AuthMethodId: am.GetPublicId(),
|
|
TokenType: "token",
|
|
Credentials: func() *structpb.Struct {
|
|
creds := map[string]*structpb.Value{
|
|
"login_name": {Kind: &structpb.Value_StringValue{StringValue: testLoginName}},
|
|
"password": {Kind: &structpb.Value_StringValue{StringValue: testPassword}},
|
|
}
|
|
return &structpb.Struct{Fields: creds}
|
|
}(),
|
|
},
|
|
wantType: "token",
|
|
},
|
|
{
|
|
name: "cookie-type",
|
|
request: &pbs.AuthenticateRequest{
|
|
AuthMethodId: am.GetPublicId(),
|
|
TokenType: "cookie",
|
|
Credentials: func() *structpb.Struct {
|
|
creds := map[string]*structpb.Value{
|
|
"login_name": {Kind: &structpb.Value_StringValue{StringValue: testLoginName}},
|
|
"password": {Kind: &structpb.Value_StringValue{StringValue: testPassword}},
|
|
}
|
|
return &structpb.Struct{Fields: creds}
|
|
}(),
|
|
},
|
|
wantType: "cookie",
|
|
},
|
|
{
|
|
name: "no-token-type",
|
|
request: &pbs.AuthenticateRequest{
|
|
AuthMethodId: am.GetPublicId(),
|
|
Credentials: func() *structpb.Struct {
|
|
creds := map[string]*structpb.Value{
|
|
"login_name": {Kind: &structpb.Value_StringValue{StringValue: testLoginName}},
|
|
"password": {Kind: &structpb.Value_StringValue{StringValue: testPassword}},
|
|
}
|
|
return &structpb.Struct{Fields: creds}
|
|
}(),
|
|
},
|
|
},
|
|
{
|
|
name: "bad-token-type",
|
|
request: &pbs.AuthenticateRequest{
|
|
AuthMethodId: am.GetPublicId(),
|
|
TokenType: "email",
|
|
Credentials: func() *structpb.Struct {
|
|
creds := map[string]*structpb.Value{
|
|
"login_name": {Kind: &structpb.Value_StringValue{StringValue: testLoginName}},
|
|
"password": {Kind: &structpb.Value_StringValue{StringValue: testPassword}},
|
|
}
|
|
return &structpb.Struct{Fields: creds}
|
|
}(),
|
|
},
|
|
wantErr: handlers.ApiErrorWithCode(codes.InvalidArgument),
|
|
},
|
|
{
|
|
name: "no-authmethod",
|
|
request: &pbs.AuthenticateRequest{
|
|
Credentials: func() *structpb.Struct {
|
|
creds := map[string]*structpb.Value{
|
|
"login_name": {Kind: &structpb.Value_StringValue{StringValue: testLoginName}},
|
|
"password": {Kind: &structpb.Value_StringValue{StringValue: testPassword}},
|
|
}
|
|
return &structpb.Struct{Fields: creds}
|
|
}(),
|
|
},
|
|
wantErr: handlers.ApiErrorWithCode(codes.InvalidArgument),
|
|
},
|
|
{
|
|
name: "wrong-password",
|
|
request: &pbs.AuthenticateRequest{
|
|
AuthMethodId: am.GetPublicId(),
|
|
TokenType: "token",
|
|
Credentials: func() *structpb.Struct {
|
|
creds := map[string]*structpb.Value{
|
|
"login_name": {Kind: &structpb.Value_StringValue{StringValue: testLoginName}},
|
|
"password": {Kind: &structpb.Value_StringValue{StringValue: "wrong"}},
|
|
}
|
|
return &structpb.Struct{Fields: creds}
|
|
}(),
|
|
},
|
|
wantErr: handlers.ApiErrorWithCode(codes.Unauthenticated),
|
|
},
|
|
{
|
|
name: "wrong-login-name",
|
|
request: &pbs.AuthenticateRequest{
|
|
AuthMethodId: am.GetPublicId(),
|
|
TokenType: "token",
|
|
Credentials: func() *structpb.Struct {
|
|
creds := map[string]*structpb.Value{
|
|
"login_name": {Kind: &structpb.Value_StringValue{StringValue: "wrong"}},
|
|
"password": {Kind: &structpb.Value_StringValue{StringValue: testPassword}},
|
|
}
|
|
return &structpb.Struct{Fields: creds}
|
|
}(),
|
|
},
|
|
wantErr: handlers.ApiErrorWithCode(codes.Unauthenticated),
|
|
},
|
|
}
|
|
|
|
for _, tc := range cases {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
assert, require := assert.New(t), require.New(t)
|
|
s, err := NewService(kms, passwordRepoFn, iamRepoFn, authTokenRepoFn)
|
|
require.NoError(err)
|
|
|
|
resp, err := s.Authenticate(auth.DisabledAuthTestContext(auth.WithScopeId(o.GetPublicId())), tc.request)
|
|
if tc.wantErr != nil {
|
|
assert.Error(err)
|
|
assert.Truef(errors.Is(err, tc.wantErr), "Got %#v, wanted %#v", err, tc.wantErr)
|
|
return
|
|
}
|
|
require.NoError(err)
|
|
aToken := resp.GetItem()
|
|
assert.NotEmpty(aToken.GetId())
|
|
assert.NotEmpty(aToken.GetToken())
|
|
assert.True(strings.HasPrefix(aToken.GetToken(), aToken.GetId()))
|
|
assert.Equal(am.GetPublicId(), aToken.GetAuthMethodId())
|
|
assert.Equal(aToken.GetCreatedTime(), aToken.GetUpdatedTime())
|
|
assert.Equal(aToken.GetCreatedTime(), aToken.GetApproximateLastUsedTime())
|
|
assert.Equal(acct.GetPublicId(), aToken.GetAccountId())
|
|
assert.Equal(am.GetPublicId(), aToken.GetAuthMethodId())
|
|
assert.Equal(tc.wantType, resp.GetTokenType())
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestAuthenticate_AuthAccountConnectedToIamUser(t *testing.T) {
|
|
assert, require := assert.New(t), require.New(t)
|
|
conn, _ := db.TestSetup(t, "postgres")
|
|
rw := db.New(conn)
|
|
wrapper := db.TestWrapper(t)
|
|
kms := kms.TestKms(t, conn, wrapper)
|
|
o, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper))
|
|
|
|
passwordRepoFn := func() (*password.Repository, error) { return password.NewRepository(rw, rw, kms) }
|
|
authTokenRepoFn := func() (*authtoken.Repository, error) { return authtoken.NewRepository(rw, rw, kms) }
|
|
iamRepoFn := func() (*iam.Repository, error) { return iam.NewRepository(rw, rw, kms) }
|
|
|
|
am := password.TestAuthMethods(t, conn, o.GetPublicId(), 1)[0]
|
|
acct, err := password.NewAccount(am.GetPublicId(), password.WithLoginName(testLoginName))
|
|
require.NoError(err)
|
|
|
|
pwRepo, err := passwordRepoFn()
|
|
require.NoError(err)
|
|
acct, err = pwRepo.CreateAccount(context.Background(), o.GetPublicId(), acct, password.WithPassword(testPassword))
|
|
require.NoError(err)
|
|
|
|
// connected to an account.
|
|
iamRepo, err := iamRepoFn()
|
|
require.NoError(err)
|
|
iamUser, err := iamRepo.LookupUserWithLogin(context.Background(), acct.GetPublicId(), iam.WithAutoVivify(true))
|
|
require.NoError(err)
|
|
|
|
s, err := NewService(kms, passwordRepoFn, iamRepoFn, authTokenRepoFn)
|
|
require.NoError(err)
|
|
resp, err := s.Authenticate(auth.DisabledAuthTestContext(auth.WithScopeId(o.GetPublicId())), &pbs.AuthenticateRequest{
|
|
AuthMethodId: am.GetPublicId(),
|
|
Credentials: func() *structpb.Struct {
|
|
creds := map[string]*structpb.Value{
|
|
"login_name": {Kind: &structpb.Value_StringValue{StringValue: testLoginName}},
|
|
"password": {Kind: &structpb.Value_StringValue{StringValue: testPassword}},
|
|
}
|
|
return &structpb.Struct{Fields: creds}
|
|
}(),
|
|
})
|
|
require.NoError(err)
|
|
|
|
aToken := resp.GetItem()
|
|
assert.Equal(iamUser.GetPublicId(), aToken.GetUserId())
|
|
assert.Equal(am.GetPublicId(), aToken.GetAuthMethodId())
|
|
assert.Equal(acct.GetPublicId(), aToken.GetAccountId())
|
|
|
|
assert.NotEmpty(aToken.GetId())
|
|
assert.NotEmpty(aToken.GetToken())
|
|
assert.True(strings.HasPrefix(aToken.GetToken(), aToken.GetId()))
|
|
}
|