feat(bsr): instantiate BSR session for playback

This commit is contained in:
irenarindos authored and Timothy Messier committed 2023-05-31 12:18:20 +00:00
1 parent 46e1752283
commit e567bb97e6
7 files changed
+673 -83

No files matched your search

+156 -13
View File
@@ -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"
+276
View File
@@ -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)
})
}
}
+236 -3
View File
@@ -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"
-66
View File
@@ -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)
}
+3
View File
@@ -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")
@@ -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)
+2
View File
@@ -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 {