From e567bb97e6feb4e7922871cd9f2bdc262304a733 Mon Sep 17 00:00:00 2001 From: irenarindos Date: Mon, 8 May 2023 15:49:21 -0400 Subject: [PATCH] feat(bsr): instantiate BSR session for playback --- internal/bsr/bsr.go | 169 +++++++++++- internal/bsr/bsr_open_test.go | 276 +++++++++++++++++++ internal/bsr/container.go | 239 +++++++++++++++- internal/bsr/decode_meta_test.go | 66 ----- internal/bsr/errors.go | 3 + internal/bsr/internal/checksum/sha256sums.go | 1 - internal/bsr/meta.go | 2 + 7 files changed, 673 insertions(+), 83 deletions(-) create mode 100644 internal/bsr/bsr_open_test.go delete mode 100644 internal/bsr/decode_meta_test.go diff --git a/internal/bsr/bsr.go b/internal/bsr/bsr.go index 028b756ae..f87b5d71f 100644 --- a/internal/bsr/bsr.go +++ b/internal/bsr/bsr.go @@ -16,6 +16,7 @@ import ( "github.com/hashicorp/boundary/internal/bsr/internal/is" "github.com/hashicorp/boundary/internal/bsr/kms" "github.com/hashicorp/boundary/internal/storage" + "github.com/hashicorp/go-kms-wrapping/v2/extras/crypto" "google.golang.org/protobuf/proto" ) @@ -43,6 +44,7 @@ func decodeSessionMeta(ctx context.Context, r io.Reader) (*SessionMeta, error) { return nil, fmt.Errorf("%s: missing session meta file: %w", op, ErrInvalidParameter) } + connections := make(map[string]bool) s := &SessionMeta{} user := &User{Scope: Scope{}} target := &Target{Scope: Scope{}} @@ -171,6 +173,10 @@ func decodeSessionMeta(ctx context.Context, r io.Reader) (*SessionMeta, error) { dHost.Catalog.PluginId = v case k == "dynamicHostCatalog_attributes": dHost.Catalog.Attributes = v + + // connections + case k == "connection": + connections[v] = true } } @@ -182,6 +188,7 @@ func decodeSessionMeta(ctx context.Context, r io.Reader) (*SessionMeta, error) { if dHost.PublicId != "" { s.DynamicHost = dHost } + s.connections = connections return s, nil } @@ -303,12 +310,60 @@ func persistBsrSessionKeys(ctx context.Context, keys *kms.Keys, c *container) er // Fields on the underlying container will be populated so that the returned Session can be used for BSR // playback and conversion to formats such as asciinema func OpenSession(ctx context.Context, sessionRecordingId string, f storage.FS, keyUnwrapFn kms.KeyUnwrapCallbackFunc) (*Session, error) { - panic("not implemented") + const op = "bsr.OpenSession" + switch { + case sessionRecordingId == "": + return nil, fmt.Errorf("%s: missing session recording id: %w", op, ErrInvalidParameter) + case f == nil: + return nil, fmt.Errorf("%s: missing storage: %w", op, ErrInvalidParameter) + case keyUnwrapFn == nil: + return nil, fmt.Errorf("%s: missing key unwrap function: %w", op, ErrInvalidParameter) + } + + c, err := f.Open(ctx, fmt.Sprintf(bsrFile, sessionRecordingId)) + if err != nil { + return nil, err + } + + keyPopFn := func(c *container) (*kms.Keys, error) { + return c.loadKeys(ctx, keyUnwrapFn) + } + cc, err := openContainer(ctx, sessionContainer, c, keyPopFn) + if err != nil { + return nil, err + } + + // Load and verify session metadata + sha256Reader, err := crypto.NewSha256SumReader(ctx, cc.metaFile) + if err != nil { + return nil, fmt.Errorf("%s: %w", op, err) + } + sm, err := decodeSessionMeta(ctx, sha256Reader) + if err != nil { + return nil, err + } + err = cc.verifyMetadata(ctx, sha256Reader) + if err != nil { + return nil, err + } + + session := &Session{ + container: cc, + Meta: sm, + } + + return session, nil +} + +// Close closes the Session container. +func (s *Session) Close(ctx context.Context) error { + return s.container.close(ctx) } // ConnectionMeta contains metadata about a connection in a BSR. type ConnectionMeta struct { - Id string + Id string + channels map[string]bool } func (c ConnectionMeta) isValid() bool { @@ -320,6 +375,15 @@ func (c ConnectionMeta) isValid() bool { } } +// Connection is a container in a bsr for a specific connection in a session +// container. It contains the files for the recorded connection. +type Connection struct { + *container + multiplexed bool + + Meta *ConnectionMeta +} + // decodeConnectionMeta will populate the ConnectionMeta for a BSR Connection // TODO Unmarshal without brute force func decodeConnectionMeta(ctx context.Context, r io.Reader) (*ConnectionMeta, error) { @@ -329,8 +393,8 @@ func decodeConnectionMeta(ctx context.Context, r io.Reader) (*ConnectionMeta, er case r == nil: return nil, fmt.Errorf("%s: missing connection meta file: %w", op, ErrInvalidParameter) } - c := &ConnectionMeta{} + channels := make(map[string]bool) scanner := bufio.NewScanner(r) for scanner.Scan() { l := scanner.Text() @@ -345,8 +409,11 @@ func decodeConnectionMeta(ctx context.Context, r io.Reader) (*ConnectionMeta, er switch { case k == "id": c.Id = v + case k == "channel": + channels[v] = true } } + c.channels = channels return c, nil } @@ -385,18 +452,49 @@ func (s *Session) NewConnection(ctx context.Context, meta *ConnectionMeta) (*Con }, nil } -// Close closes the Session container. -func (s *Session) Close(ctx context.Context) error { - return s.container.close(ctx) -} +// OpenConnection will open and validate a BSR connection +func (s *Session) OpenConnection(ctx context.Context, connId string) (*Connection, error) { + const op = "bsr.OpenConnection" + switch { + case connId == "": + return nil, fmt.Errorf("%s: missing connection id: %w", op, ErrInvalidParameter) + case !s.Meta.connections[connId]: + return nil, fmt.Errorf("%s: connection id does not exist within this session: %w", op, ErrInvalidParameter) + } -// Connection is a container in a bsr for a specific connection in a session -// container. It contains the files for the recorded connection. -type Connection struct { - *container - multiplexed bool + c, err := s.container.container.SubContainer(ctx, connId) + if err != nil { + return nil, err + } - Meta *ConnectionMeta + keyPopFn := func(c *container) (*kms.Keys, error) { + return s.keys, nil + } + cc, err := openContainer(ctx, connectionContainer, c, keyPopFn) + if err != nil { + return nil, err + } + + // Load and verify connection metadata + sha256Reader, err := crypto.NewSha256SumReader(ctx, cc.metaFile) + if err != nil { + return nil, fmt.Errorf("%s: %w", op, err) + } + sm, err := decodeConnectionMeta(ctx, sha256Reader) + if err != nil { + return nil, err + } + err = cc.verifyMetadata(ctx, sha256Reader) + if err != nil { + return nil, err + } + + connection := &Connection{ + container: cc, + Meta: sm, + } + + return connection, nil } // ChannelMeta contains metadata about a channel in a BSR. @@ -488,6 +586,51 @@ func (c *Connection) NewChannel(ctx context.Context, meta *ChannelMeta) (*Channe }, nil } +// OpenChannel will open and validate a BSR channel +func (c *Connection) OpenChannel(ctx context.Context, chanId string) (*Channel, error) { + const op = "bsr.OpenChannel" + switch { + case chanId == "": + return nil, fmt.Errorf("%s: missing channel id: %w", op, ErrInvalidParameter) + case !c.Meta.channels[chanId]: + return nil, fmt.Errorf("%s: channel id does not exist within this connection: %w", op, ErrInvalidParameter) + } + + con, err := c.container.container.SubContainer(ctx, chanId) + if err != nil { + return nil, err + } + + keyPopFn := func(cn *container) (*kms.Keys, error) { + return c.keys, nil + } + cc, err := openContainer(ctx, channelContainer, con, keyPopFn) + if err != nil { + return nil, err + } + + // Load and verify channel metadata + sha256Reader, err := crypto.NewSha256SumReader(ctx, cc.metaFile) + if err != nil { + return nil, fmt.Errorf("%s: %w", op, err) + } + sm, err := decodeChannelMeta(ctx, sha256Reader) + if err != nil { + return nil, err + } + err = cc.verifyMetadata(ctx, sha256Reader) + if err != nil { + return nil, err + } + + channel := &Channel{ + container: cc, + Meta: sm, + } + + return channel, nil +} + // NewMessagesWriter creates a writer for recording channel messages. func (c *Connection) NewMessagesWriter(ctx context.Context, dir Direction) (io.Writer, error) { const op = "bsr.(Connection).NewMessagesWriter" diff --git a/internal/bsr/bsr_open_test.go b/internal/bsr/bsr_open_test.go new file mode 100644 index 000000000..b9dfbb7ec --- /dev/null +++ b/internal/bsr/bsr_open_test.go @@ -0,0 +1,276 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package bsr + +import ( + "context" + "fmt" + "testing" + + "github.com/hashicorp/boundary/internal/bsr/internal/fstest" + "github.com/hashicorp/boundary/internal/bsr/kms" + "github.com/hashicorp/boundary/internal/storage" + "github.com/stretchr/testify/require" +) + +func TestPopulateMeta(t *testing.T) { + ctx := context.Background() + + keys, err := kms.CreateKeys(ctx, kms.TestWrapper(t), "session") + require.NoError(t, err) + + sessionId := "session" + sessionProtocol := "TEST" + + // Populate session meta + sessionMeta := TestSessionMeta(sessionId, Protocol((sessionProtocol))) + s, err := NewSession(ctx, sessionMeta, &fstest.MemFS{}, keys, WithSupportsMultiplex(true)) + require.NoError(t, err) + require.NotNil(t, s) + + // Reset meta and populate it from the meta file + s.Meta = &SessionMeta{} + sm, err := decodeSessionMeta(ctx, s.container.meta) + require.NoError(t, err) + s.Meta = sm + require.Equal(t, s.Meta.Id, sessionId) + require.Equal(t, s.Meta.Protocol.ToText(), sessionProtocol) + require.Equal(t, s.Meta.Target, sessionMeta.Target) + require.Equal(t, s.Meta.User, sessionMeta.User) + require.Equal(t, s.Meta.StaticHost, sessionMeta.StaticHost) + + // Populate connection meta + connectionId := "connection" + c, err := s.NewConnection(ctx, &ConnectionMeta{Id: connectionId}) + require.NoError(t, err) + require.NotNil(t, c) + + c.Meta = &ConnectionMeta{} + cm, err := decodeConnectionMeta(ctx, c.container.meta) + require.NoError(t, err) + c.Meta = cm + require.Equal(t, c.Meta.Id, connectionId) + + // Populate channel meta + channelId := "channel" + channelType := "mythical" + ch, err := c.NewChannel(ctx, &ChannelMeta{Id: channelId, Type: channelType}) + require.NoError(t, err) + require.NotNil(t, ch) + + ch.Meta = &ChannelMeta{} + chM, err := decodeChannelMeta(ctx, ch.container.meta) + require.NoError(t, err) + ch.Meta = chM + require.Equal(t, ch.Meta.Id, channelId) + require.Equal(t, ch.Meta.Type, channelType) +} + +func TestOpenBSRMethods(t *testing.T) { + ctx := context.Background() + + keys, err := kms.CreateKeys(ctx, kms.TestWrapper(t), "session") + require.NoError(t, err) + + f := &fstest.MemFS{} + sessionId := "session" + sessionMeta := TestSessionMeta(sessionId, Protocol("test")) + + sesh, err := NewSession(ctx, sessionMeta, f, keys, WithSupportsMultiplex(true)) + require.NoError(t, err) + require.NotNil(t, sesh) + + connectionId := "connection" + connMeta := &ConnectionMeta{Id: connectionId} + conn, err := sesh.NewConnection(ctx, connMeta) + require.NoError(t, err) + require.NotNil(t, conn) + + channelId := "channel" + chanMeta := &ChannelMeta{ + Id: channelId, + Type: "chan", + } + ch, err := conn.NewChannel(ctx, chanMeta) + require.NoError(t, err) + require.NotNil(t, ch) + + ch.Close(ctx) + conn.Close(ctx) + sesh.Close(ctx) + + keyFn := func(w kms.WrappedKeys) (kms.UnwrappedKeys, error) { + u := kms.UnwrappedKeys{ + BsrKey: keys.BsrKey, + PrivKey: keys.PrivKey, + } + return u, nil + } + + opSesh, err := OpenSession(ctx, sessionId, f, keyFn) + require.NoError(t, err) + require.NotNil(t, opSesh) + sesh.Meta.connections = opSesh.Meta.connections + require.Equal(t, opSesh.Meta, sesh.Meta) + + opConn, err := opSesh.OpenConnection(ctx, fmt.Sprintf("connection.%s", connectionId)) + require.NoError(t, err) + require.NotNil(t, opConn) + conn.Meta.channels = opConn.Meta.channels + require.Equal(t, opConn.Meta, conn.Meta) + + opChan, err := opConn.OpenChannel(ctx, fmt.Sprintf("channel.%s", channelId)) + require.NoError(t, err) + require.NotNil(t, opChan) + require.Equal(t, opChan.Meta, ch.Meta) +} + +func TestOpenSession(t *testing.T) { + ctx := context.Background() + + keys, err := kms.CreateKeys(ctx, kms.TestWrapper(t), "session") + require.NoError(t, err) + + keyFn := func(w kms.WrappedKeys) (kms.UnwrappedKeys, error) { + u := kms.UnwrappedKeys{ + BsrKey: keys.BsrKey, + PrivKey: keys.PrivKey, + } + return u, nil + } + + f := &fstest.MemFS{} + sessionId := "session" + + cases := []struct { + name string + id string + f storage.FS + keyFn kms.KeyUnwrapCallbackFunc + wantErr bool + wantErrContains string + }{ + { + name: "no-session-id", + f: f, + keyFn: keyFn, + wantErr: true, + wantErrContains: "bsr.OpenSession: missing session recording id: invalid parameter", + }, + { + name: "no-key-fn", + id: sessionId, + f: f, + wantErr: true, + wantErrContains: "bsr.OpenSession: missing key unwrap function: invalid parameter", + }, + { + name: "no-storage", + id: sessionId, + keyFn: keyFn, + wantErr: true, + wantErrContains: "bsr.OpenSession: missing storage: invalid parameter", + }, + } + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + got, err := OpenSession(ctx, tc.id, tc.f, tc.keyFn) + if tc.wantErr { + require.Error(t, err) + require.ErrorContains(t, err, tc.wantErrContains) + return + } + require.NoError(t, err) + require.NotNil(t, got) + }) + } +} + +func TestOpenConnection(t *testing.T) { + ctx := context.Background() + + connMap := make(map[string]bool) + connMap["connection"] = true + meta := TestSessionMeta("sessionId", Protocol("test")) + meta.connections = connMap + + cases := []struct { + name string + id string + wantErr bool + wantErrContains string + }{ + { + name: "no-conn-id", + wantErr: true, + wantErrContains: "bsr.OpenConnection: missing connection id: invalid parameter", + }, + + { + name: "bad-conn-id", + id: "bogus", + wantErr: true, + wantErrContains: "bsr.OpenConnection: connection id does not exist within this session: invalid parameter", + }, + } + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + sesh := Session{ + Meta: meta, + } + got, err := sesh.OpenConnection(ctx, tc.id) + if tc.wantErr { + require.Error(t, err) + require.ErrorContains(t, err, tc.wantErrContains) + return + } + require.NoError(t, err) + require.NotNil(t, got) + }) + } +} + +func TestOpenChannel(t *testing.T) { + ctx := context.Background() + + chanMap := make(map[string]bool) + chanMap["channel"] = true + + cases := []struct { + name string + id string + wantErr bool + wantErrContains string + }{ + { + name: "no-chan-id", + wantErr: true, + wantErrContains: "bsr.OpenChannel: missing channel id: invalid parameter", + }, + + { + name: "bad-chan-id", + id: "bogus", + wantErr: true, + wantErrContains: "bsr.OpenChannel: channel id does not exist within this connection: invalid parameter", + }, + } + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + conn := Connection{ + Meta: &ConnectionMeta{ + channels: chanMap, + }, + } + got, err := conn.OpenChannel(ctx, tc.id) + if tc.wantErr { + require.Error(t, err) + require.ErrorContains(t, err, tc.wantErrContains) + return + } + require.NoError(t, err) + require.NotNil(t, got) + }) + } +} diff --git a/internal/bsr/container.go b/internal/bsr/container.go index 88ffc81f2..d77e48bb7 100644 --- a/internal/bsr/container.go +++ b/internal/bsr/container.go @@ -4,15 +4,21 @@ package bsr import ( + "bytes" "context" "errors" "fmt" + "io" "github.com/hashicorp/boundary/internal/bsr/internal/checksum" + "github.com/hashicorp/boundary/internal/bsr/internal/is" "github.com/hashicorp/boundary/internal/bsr/internal/journal" "github.com/hashicorp/boundary/internal/bsr/internal/sign" "github.com/hashicorp/boundary/internal/bsr/kms" "github.com/hashicorp/boundary/internal/storage" + wrapping "github.com/hashicorp/go-kms-wrapping/v2" + "github.com/hashicorp/go-kms-wrapping/v2/extras/crypto" + "google.golang.org/protobuf/proto" ) const ( @@ -37,16 +43,22 @@ const ( // Each container has corresponding .meta, .summary, SHA256SUM, and SHA256SUM.sig files. type container struct { container storage.Container - journal *journal.Journal - metaName string + // Fields primarily used for writing + journal *journal.Journal sumName string meta *checksum.File sum *checksum.File checksums *sign.File sigs storage.File - keys *kms.Keys + // Field used for reading + shaSums checksum.Sha256Sums + metaFile storage.File + + // Field used for reading and writing + keys *kms.Keys + metaName string } // newContainer creates a container for the given type backed by the provide storage.Container. @@ -105,6 +117,227 @@ func newContainer(ctx context.Context, t containerType, c storage.Container, key return cc, nil } +type populateKeyFunc func(c *container) (*kms.Keys, error) + +// openContainer will set keys and load and verify the checksums for this container +func openContainer(ctx context.Context, t containerType, c storage.Container, keyGetFunc populateKeyFunc) (*container, error) { + const op = "bsr.openContainer" + switch { + case t == "": + return nil, fmt.Errorf("%s: missing container type: %w", op, ErrInvalidParameter) + case is.Nil(c): + return nil, fmt.Errorf("%s: missing container: %w", op, ErrInvalidParameter) + case is.Nil(keyGetFunc): + return nil, fmt.Errorf("%s: missing key function: %w", op, ErrInvalidParameter) + } + + cc := &container{ + container: c, + } + + keys, err := keyGetFunc(cc) + if err != nil { + return nil, err + } + cc.keys = keys + + err = cc.loadChecksums(ctx) + if err != nil { + return nil, err + } + + // Load the meta file + cc.metaName = fmt.Sprintf(metaFile, t) + mFile, err := cc.container.OpenFile(ctx, cc.metaName) + if err != nil { + return nil, err + } + cc.metaFile = mFile + + return cc, nil +} + +func (c *container) loadChecksums(ctx context.Context) error { + const op = "bsr.(container).loadChecksums" + + // Open and extract checksum signature + checksumsSigFile, err := c.container.OpenFile(ctx, sigFile) + if err != nil { + return err + } + checksumSigBytes := new(bytes.Buffer) + _, err = checksumSigBytes.ReadFrom(checksumsSigFile) + if err != nil { + return err + } + + sig := new(wrapping.SigInfo) + err = proto.Unmarshal(checksumSigBytes.Bytes(), sig) + if err != nil { + return err + } + + // Open and extract checksum file bytes + checksumsFile, err := c.container.OpenFile(ctx, checksumFile) + if err != nil { + return err + } + var checksumsBuffer bytes.Buffer + cTee := io.TeeReader(checksumsFile, &checksumsBuffer) + + checksumBytes := new(bytes.Buffer) + _, err = checksumBytes.ReadFrom(cTee) + if err != nil { + return err + } + + verified, err := c.keys.VerifySignatureWithPubKey(ctx, sig, checksumBytes.Bytes()) + if err != nil { + return err + } + if !verified { + return fmt.Errorf("%s: failed to verify checksums signature: %w", op, ErrSignatureVerification) + } + + // Load checksums + sums, err := checksum.LoadSha256Sums(&checksumsBuffer) + if err != nil { + return err + } + c.shaSums = sums + + return nil +} + +func (c *container) loadKey(ctx context.Context, keyFileName string) (*wrapping.KeyInfo, error) { + keyFile, err := c.container.OpenFile(ctx, keyFileName) + if err != nil { + return nil, err + } + + keyBytes := new(bytes.Buffer) + _, err = keyBytes.ReadFrom(keyFile) + if err != nil { + return nil, err + } + + key := new(wrapping.KeyInfo) + err = proto.Unmarshal(keyBytes.Bytes(), key) + if err != nil { + return nil, err + } + + return key, nil +} + +func (c *container) loadSignature(ctx context.Context, sigFileName string) (*wrapping.SigInfo, error) { + sigFile, err := c.container.OpenFile(ctx, sigFileName) + if err != nil { + return nil, err + } + + sigBytes := new(bytes.Buffer) + _, err = sigBytes.ReadFrom(sigFile) + if err != nil { + return nil, err + } + + signature := new(wrapping.SigInfo) + err = proto.Unmarshal(sigBytes.Bytes(), signature) + if err != nil { + return nil, err + } + + return signature, nil +} + +// loadKeys will load the BSR keys from storage, unmarshal and unwrap them. +// After unwrapping, it will verify the key signature files before setting the keys +// on the container +func (c *container) loadKeys(ctx context.Context, keyUnwrapFn kms.KeyUnwrapCallbackFunc) (*kms.Keys, error) { + const op = "bsr.(container).loadKeys" + + switch { + case keyUnwrapFn == nil: + return nil, fmt.Errorf("%s: missing key unwrap function: %w", op, ErrInvalidParameter) + } + + bsrPubKey, err := c.loadKey(ctx, bsrPubKeyFile) + if err != nil { + return nil, err + } + + wrappedBsrKey, err := c.loadKey(ctx, wrappedBsrKeyFile) + if err != nil { + return nil, err + } + + wrappedPrivKey, err := c.loadKey(ctx, wrappedPrivKeyFile) + if err != nil { + return nil, err + } + + pubKeyBsrSignature, err := c.loadSignature(ctx, pubKeyBsrSignatureFile) + if err != nil { + return nil, err + } + + pubKeySelfSignature, err := c.loadSignature(ctx, pubKeySelfSignatureFile) + if err != nil { + return nil, err + } + + unwrappedKeys, err := keyUnwrapFn(kms.WrappedKeys{ + WrappedBsrKey: wrappedBsrKey, + WrappedPrivKey: wrappedPrivKey, + }) + if err != nil { + return nil, err + } + + keys := &kms.Keys{ + PubKey: bsrPubKey, + BsrKey: unwrappedKeys.BsrKey, + PrivKey: unwrappedKeys.PrivKey, + PubKeyBsrSignature: pubKeyBsrSignature, + PubKeySelfSignature: pubKeySelfSignature, + } + + verified, err := keys.VerifyPubKeySelfSignature(ctx) + if err != nil { + return nil, err + } + if !verified { + return nil, fmt.Errorf("%s: failed to verify public self signed key: %w", op, ErrSignatureVerification) + } + + verified, err = keys.VerifyPubKeyBsrSignature(ctx) + if err != nil { + return nil, err + } + if !verified { + return nil, fmt.Errorf("%s: failed to verify pub key signature: %w", op, ErrSignatureVerification) + } + + return keys, nil +} + +func (c *container) verifyMetadata(ctx context.Context, sha256Reader *crypto.Sha256SumReader) error { + const op = "bsr.(container).verifyMetadata" + metaSum, err := sha256Reader.Sum(ctx, crypto.WithHexEncoding(true)) + if err != nil { + return err + } + expectedMetaSum, err := c.shaSums.Sum(c.metaName) + if err != nil { + return err + } + if !bytes.Equal(expectedMetaSum, metaSum) { + return fmt.Errorf("%s: meta checksum did not match expected value", op) + } + return nil +} + // create creates a new file in the container for writing. func (c *container) create(ctx context.Context, s string, options ...storage.Option) (storage.File, error) { const op = "bsr.(container).create" diff --git a/internal/bsr/decode_meta_test.go b/internal/bsr/decode_meta_test.go deleted file mode 100644 index e5af823ca..000000000 --- a/internal/bsr/decode_meta_test.go +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -package bsr - -import ( - "context" - "testing" - - "github.com/hashicorp/boundary/internal/bsr/internal/fstest" - "github.com/hashicorp/boundary/internal/bsr/kms" - "github.com/stretchr/testify/require" -) - -func TestPopulateMeta(t *testing.T) { - ctx := context.Background() - - keys, err := kms.CreateKeys(ctx, kms.TestWrapper(t), "session") - require.NoError(t, err) - - sessionId := "session" - sessionProtocol := "SSH" - - // Populate session meta - sessionMeta := TestSessionMeta(sessionId, Protocol((sessionProtocol))) - s, err := NewSession(ctx, sessionMeta, &fstest.MemFS{}, keys, WithSupportsMultiplex(true)) - require.NoError(t, err) - require.NotNil(t, s) - - // Reset meta and populate it from the meta file - s.Meta = &SessionMeta{} - sm, err := decodeSessionMeta(ctx, s.container.meta) - require.NoError(t, err) - s.Meta = sm - require.Equal(t, s.Meta.Id, sessionId) - require.Equal(t, s.Meta.Protocol.ToText(), sessionProtocol) - require.Equal(t, s.Meta.Target, sessionMeta.Target) - require.Equal(t, s.Meta.User, sessionMeta.User) - require.Equal(t, s.Meta.StaticHost, sessionMeta.StaticHost) - - // Populate connection meta - connectionId := "connection" - c, err := s.NewConnection(ctx, &ConnectionMeta{Id: connectionId}) - require.NoError(t, err) - require.NotNil(t, c) - - c.Meta = &ConnectionMeta{} - cm, err := decodeConnectionMeta(ctx, c.container.meta) - require.NoError(t, err) - c.Meta = cm - require.Equal(t, c.Meta.Id, connectionId) - - // Populate channel meta - channelId := "channel" - channelType := "mythical" - ch, err := c.NewChannel(ctx, &ChannelMeta{Id: channelId, Type: channelType}) - require.NoError(t, err) - require.NotNil(t, ch) - - ch.Meta = &ChannelMeta{} - chM, err := decodeChannelMeta(ctx, ch.container.meta) - require.NoError(t, err) - ch.Meta = chM - require.Equal(t, ch.Meta.Id, channelId) - require.Equal(t, ch.Meta.Type, channelType) -} diff --git a/internal/bsr/errors.go b/internal/bsr/errors.go index 56923f06f..795931d44 100644 --- a/internal/bsr/errors.go +++ b/internal/bsr/errors.go @@ -20,6 +20,9 @@ var ( // ErrSummaryUnavailable indicates a BSR summary is unavailable ErrSummaryUnavailable = errors.New("summary not available") + // ErrSignatureVerification indicates a failure in verifying a signature + ErrSignatureVerification = errors.New("could not verify signature") + // ErrNotSupported represents an operation that is not supported for a // particular protocol. ErrNotSupported = errors.New("not supported by protocol") diff --git a/internal/bsr/internal/checksum/sha256sums.go b/internal/bsr/internal/checksum/sha256sums.go index 24d968f84..e0c0231d9 100644 --- a/internal/bsr/internal/checksum/sha256sums.go +++ b/internal/bsr/internal/checksum/sha256sums.go @@ -37,7 +37,6 @@ func LoadSha256Sums(r io.Reader) (Sha256Sums, error) { for scanner.Scan() { var sum, file string var ok bool - sum, file, ok = strings.Cut(scanner.Text(), sha256sumSep) if !ok { sum, file, ok = strings.Cut(scanner.Text(), sha256sumBinarySep) diff --git a/internal/bsr/meta.go b/internal/bsr/meta.go index e979fa32c..00d3e5819 100644 --- a/internal/bsr/meta.go +++ b/internal/bsr/meta.go @@ -727,6 +727,8 @@ type SessionMeta struct { StaticCredentialStore []StaticCredentialStore VaultCredentialStore []VaultCredentialStore + + connections map[string]bool } func (s SessionMeta) writeMeta(ctx context.Context, c *container) error {