Files
threshold/internal/daemon/cluster/connstate_test.go
T
Jeff Mitchell 163ce184b8 KMS-PKI Workers (#3101)
This adds a new mechanism for worker authentication that uses the
third-party arbitration of the original KMS flow by leveraging
recently-added capabilities in nodeenrollment to support a registration
wrapper. This allows for workers to be registered to the system with
just a name and a matching wrapper, while at the same time allowing
these workers to be used for private Vault access and multi-hop as they
contain per-worker encryption keys and support rotation.

Nodes using this mode will generate and rotate credentials in-memory
(using another recently added nodeenrollment capability) so will have a
new set of keys on every startup. This has the side effect of ensuring
that there is never a conflict or re-use of these credentials.

Note that the normal test worker flow was using the now-deprecated KMS
method; there is still a test that uses this (explicitly) but all other
tests using test workers that did not specify a specific PKI flow now
actually use this mechanism. This means there is fairly decent test
coverage in a general sense, plus the specific tests updated/added for
this feature.

This also adds a new KMS type that can be used to have
distinct KMSes for upstream authentication vs. accepting from
downstream.
2023-03-30 16:20:28 -04:00

78 lines
2.0 KiB
Go

// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0
package cluster
import (
"context"
"net"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"google.golang.org/protobuf/types/known/structpb"
)
type testConn struct {
net.Conn
st *structpb.Struct
}
func (c *testConn) ClientState() *structpb.Struct {
return c.st
}
func TestWorkerConnectionInfo(t *testing.T) {
connInfo := []*WorkerConnectionInfo{
{WorkerId: "something"},
{UpstreamAddress: "something"},
{BoundaryVersion: "something"},
{Name: "something"},
{Description: "something"},
{PublicAddr: "something"},
{OperationalState: "something"},
{
WorkerId: "something",
UpstreamAddress: "something else",
BoundaryVersion: "something yet more",
Name: "some name",
Description: "some description",
PublicAddr: "some addr",
OperationalState: "some state",
},
}
for _, c := range connInfo {
st, err := c.AsConnectionStateStruct()
assert.NoError(t, err)
got, err := GetWorkerInfoFromStateMap(context.Background(), &testConn{st: st})
require.NoError(t, err)
assert.Equal(t, c, got)
}
}
func TestWorkerConnectionInfo_errors(t *testing.T) {
t.Run("wrong connection type", func(t *testing.T) {
c, _ := net.Pipe()
got, err := GetWorkerInfoFromStateMap(context.Background(), c)
assert.ErrorContains(t, err, "conn is not a state provider")
assert.Nil(t, got)
})
t.Run("no state on connection", func(t *testing.T) {
got, err := GetWorkerInfoFromStateMap(context.Background(), &testConn{})
assert.ErrorContains(t, err, "no state attached")
assert.Nil(t, got)
})
t.Run("wrong type in struct", func(t *testing.T) {
st, err := structpb.NewStruct(map[string]interface{}{
"worker_id": 1.2480,
})
require.NoError(t, err)
require.NotNil(t, st)
got, err := GetWorkerInfoFromStateMap(context.Background(), &testConn{st: st})
assert.ErrorContains(t, err, "'worker_id' expected type 'string'")
assert.Nil(t, got)
})
}