183 lines
4.2 KiB
Go
183 lines
4.2 KiB
Go
package singleprocess
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/golang/protobuf/proto"
|
|
"github.com/golang/protobuf/ptypes/empty"
|
|
"github.com/mr-tron/base58"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
"golang.org/x/crypto/blake2b"
|
|
"google.golang.org/grpc/codes"
|
|
"google.golang.org/grpc/status"
|
|
|
|
"github.com/hashicorp/vagrant/internal/server/proto/vagrant_server"
|
|
)
|
|
|
|
func TestServiceAuth(t *testing.T) {
|
|
// Create our server
|
|
impl, err := New(WithDB(testDB(t)))
|
|
require.NoError(t, err)
|
|
|
|
t.Run("create and validate a token", func(t *testing.T) {
|
|
s := impl.(*service)
|
|
|
|
md := map[string]string{
|
|
"addr": "test",
|
|
}
|
|
|
|
token, err := s.NewLoginToken(DefaultKeyId, md, nil)
|
|
require.NoError(t, err)
|
|
|
|
require.True(t, len(token) > 5)
|
|
t.Logf("token: %s", token)
|
|
|
|
tt, body, err := s.DecodeToken(token)
|
|
require.NoError(t, err)
|
|
|
|
assert.True(t, body.Login)
|
|
assert.False(t, body.Invite)
|
|
assert.Equal(t, DefaultUser, body.User)
|
|
assert.Equal(t, md, tt.Metadata)
|
|
|
|
err = s.Authenticate(context.Background(), token, "test", nil)
|
|
require.NoError(t, err)
|
|
|
|
// Now corrupt the token and check that validation fails
|
|
data := []byte(token)
|
|
|
|
data[len(data)-2] = data[len(data)-2] + 1
|
|
_, _, err = s.DecodeToken(string(data))
|
|
require.Error(t, err)
|
|
|
|
// Generate a legit token with an unknown key though
|
|
})
|
|
|
|
t.Run("entrypoint token can only access entrypoint APIs", func(t *testing.T) {
|
|
s := impl.(*service)
|
|
|
|
token, err := s.NewLoginToken(DefaultKeyId, nil, &vagrant_server.Token_Entrypoint{})
|
|
require.NoError(t, err)
|
|
|
|
{
|
|
err := s.Authenticate(context.Background(), token, "EntrypointConfig", nil)
|
|
require.NoError(t, err)
|
|
}
|
|
|
|
{
|
|
err := s.Authenticate(context.Background(), token, "UpsertDeployment", nil)
|
|
require.Error(t, err)
|
|
}
|
|
})
|
|
|
|
t.Run("rejects tokens signed with unknown keys", func(t *testing.T) {
|
|
s := impl.(*service)
|
|
|
|
md := map[string]string{
|
|
"addr": "test",
|
|
}
|
|
|
|
token, err := s.NewLoginToken(DefaultKeyId, md, nil)
|
|
require.NoError(t, err)
|
|
|
|
require.True(t, len(token) > 5)
|
|
t.Logf("token: %s", token)
|
|
|
|
tt, body, err := s.DecodeToken(token)
|
|
require.NoError(t, err)
|
|
bodyData, err := proto.Marshal(body)
|
|
require.NoError(t, err)
|
|
|
|
h, err := blake2b.New256([]byte("abcdabcdabcdabcadacdacdaaa"))
|
|
require.NoError(t, err)
|
|
|
|
h.Write(bodyData)
|
|
|
|
tt.Signature = h.Sum(nil)
|
|
|
|
ttData, err := proto.Marshal(tt)
|
|
require.NoError(t, err)
|
|
|
|
var buf bytes.Buffer
|
|
buf.WriteString(tokenMagic)
|
|
buf.Write(ttData)
|
|
|
|
rogue := base58.Encode(buf.Bytes())
|
|
|
|
_, _, err = s.DecodeToken(rogue)
|
|
require.Error(t, err)
|
|
})
|
|
|
|
t.Run("exchange an invite token", func(t *testing.T) {
|
|
s := impl.(*service)
|
|
|
|
invite, err := s.NewInviteToken(2*time.Second, DefaultKeyId, nil, nil)
|
|
require.NoError(t, err)
|
|
|
|
lt, err := s.ExchangeInvite(DefaultKeyId, invite)
|
|
require.NoError(t, err)
|
|
|
|
_, body, err := s.DecodeToken(lt)
|
|
require.NoError(t, err)
|
|
|
|
assert.True(t, body.Login)
|
|
|
|
time.Sleep(3 * time.Second)
|
|
|
|
_, err = s.ExchangeInvite(DefaultKeyId, invite)
|
|
require.Error(t, err)
|
|
})
|
|
|
|
t.Run("exchange an entrypoint invite token", func(t *testing.T) {
|
|
s := impl.(*service)
|
|
|
|
entry := &vagrant_server.Token_Entrypoint{DeploymentId: "foo"}
|
|
|
|
invite, err := s.NewInviteToken(2*time.Second, DefaultKeyId, nil, entry)
|
|
require.NoError(t, err)
|
|
|
|
lt, err := s.ExchangeInvite(DefaultKeyId, invite)
|
|
require.NoError(t, err)
|
|
|
|
_, body, err := s.DecodeToken(lt)
|
|
require.NoError(t, err)
|
|
|
|
assert.True(t, body.Login)
|
|
assert.NotNil(t, body.Entrypoint)
|
|
assert.Equal(t, entry.DeploymentId, body.Entrypoint.DeploymentId)
|
|
|
|
time.Sleep(3 * time.Second)
|
|
|
|
_, err = s.ExchangeInvite(DefaultKeyId, invite)
|
|
require.Error(t, err)
|
|
})
|
|
}
|
|
|
|
func TestServiceBootstrapToken(t *testing.T) {
|
|
ctx := context.Background()
|
|
require := require.New(t)
|
|
|
|
// Create our server
|
|
impl, err := New(WithDB(testDB(t)))
|
|
require.NoError(err)
|
|
|
|
{
|
|
// Initial bootstrap should return a token
|
|
resp, err := impl.BootstrapToken(ctx, &empty.Empty{})
|
|
require.NoError(err)
|
|
require.NotEmpty(resp.Token)
|
|
}
|
|
|
|
{
|
|
// Subs calls should fail
|
|
resp, err := impl.BootstrapToken(ctx, &empty.Empty{})
|
|
require.Error(err)
|
|
require.Equal(codes.PermissionDenied, status.Code(err))
|
|
require.Nil(resp)
|
|
}
|
|
}
|