refactor: make secrets optional for storage bucket (#3353)

This commit is contained in:
Damian Debkowski authored and GitHub committed 2023-07-19 14:32:33 -07:00
1 parent 86b2f4b90a
commit e285a8ef6f
7 files changed
+379 -69

No files matched your search

@@ -0,0 +1,36 @@
-- Copyright (c) HashiCorp, Inc.
-- SPDX-License-Identifier: MPL-2.0
begin;
drop view storage_plugin_storage_bucket_with_secret;
alter table storage_plugin_storage_bucket
drop constraint if exists secrets_hmac_must_not_be_empty,
alter column secrets_hmac drop not null;
create view storage_plugin_storage_bucket_with_secret as
select
spsb.public_id,
spsb.scope_id,
spsb.name,
spsb.description,
spsb.create_time,
spsb.update_time,
spsb.version,
spsb.plugin_id,
spsb.bucket_name,
spsb.bucket_prefix,
spsb.worker_filter,
spsb.attributes,
spsb.secrets_hmac,
spsbs.secrets_encrypted,
spsbs.key_id
from storage_plugin_storage_bucket spsb
left join storage_plugin_storage_bucket_secret spsbs
on spsbs.storage_bucket_id = spsb.public_id;
comment on view storage_plugin_storage_bucket_with_secret is
'storage_plugin_storage_bucket_with_secret is a view where each row contains a storage bucket. '
'Encrypted secret and hmac value is not returned if a secret is not associated with the storage bucket.';
commit;
+34 -23
View File
@@ -17,6 +17,7 @@ import (
plgpb "github.com/hashicorp/boundary/sdk/pbs/plugin"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
"google.golang.org/protobuf/types/known/structpb"
"google.golang.org/protobuf/types/known/timestamppb"
)
@@ -121,8 +122,8 @@ func (l *LoopbackStorage) onCreateStorageBucket(ctx context.Context, req *plgpb.
if req.GetBucket() == nil {
return nil, status.Errorf(codes.InvalidArgument, "%s: missing storage bucket", op)
}
if req.GetBucket().GetSecrets() == nil {
return nil, status.Errorf(codes.InvalidArgument, "%s: missing secrets", op)
if req.GetBucket().GetAttributes() == nil {
return nil, status.Errorf(codes.InvalidArgument, "%s: missing attributes", op)
}
l.m.Lock()
defer l.m.Unlock()
@@ -134,9 +135,15 @@ func (l *LoopbackStorage) onCreateStorageBucket(ctx context.Context, req *plgpb.
return nil, status.Errorf(err.ErrCode, err.ErrMsg)
}
}
secrets := req.GetBucket().GetSecrets()
if secrets == nil {
secrets = &structpb.Struct{
Fields: make(map[string]*structpb.Value),
}
}
return &plgpb.OnCreateStorageBucketResponse{
Persisted: &storagebuckets.StorageBucketPersisted{
Data: req.GetBucket().GetSecrets(),
Data: secrets,
},
}, nil
}
@@ -149,8 +156,8 @@ func (l *LoopbackStorage) onUpdateStorageBucket(ctx context.Context, req *plgpb.
if req.GetNewBucket() == nil {
return nil, status.Errorf(codes.InvalidArgument, "%s: missing storage bucket", op)
}
if req.Persisted == nil {
return nil, status.Errorf(codes.InvalidArgument, "%s: missing secrets", op)
if req.GetNewBucket().GetAttributes() == nil {
return nil, status.Errorf(codes.InvalidArgument, "%s: missing attributes", op)
}
l.m.Lock()
defer l.m.Unlock()
@@ -162,16 +169,20 @@ func (l *LoopbackStorage) onUpdateStorageBucket(ctx context.Context, req *plgpb.
return nil, status.Errorf(err.ErrCode, "%s: %s", op, err.ErrMsg)
}
}
var sec *storagebuckets.StorageBucketPersisted
if req.NewBucket.Secrets != nil {
sec = &storagebuckets.StorageBucketPersisted{
Data: req.GetNewBucket().GetSecrets(),
}
var secrets *structpb.Struct
if req.GetNewBucket().GetSecrets() != nil {
secrets = req.GetNewBucket().GetSecrets()
} else if req.GetPersisted().GetData() != nil {
secrets = req.GetPersisted().GetData()
} else {
sec = req.Persisted
secrets = &structpb.Struct{
Fields: make(map[string]*structpb.Value),
}
}
return &plgpb.OnUpdateStorageBucketResponse{
Persisted: sec,
Persisted: &storagebuckets.StorageBucketPersisted{
Data: secrets,
},
}, nil
}
@@ -183,8 +194,8 @@ func (l *LoopbackStorage) onDeleteStorageBucket(ctx context.Context, req *plgpb.
if req.GetBucket() == nil {
return nil, status.Errorf(codes.InvalidArgument, "%s: missing storage bucket", op)
}
if req.Persisted == nil {
return nil, status.Errorf(codes.InvalidArgument, "%s: missing secrets", op)
if req.GetBucket().GetAttributes() == nil {
return nil, status.Errorf(codes.InvalidArgument, "%s: missing attributes", op)
}
return &plgpb.OnDeleteStorageBucketResponse{}, nil
}
@@ -197,8 +208,8 @@ func (l *LoopbackStorage) validatePermissions(ctx context.Context, req *plgpb.Va
if req.GetBucket() == nil {
return nil, status.Errorf(codes.InvalidArgument, "%s: missing storage bucket", op)
}
if req.GetBucket().GetSecrets() == nil {
return nil, status.Errorf(codes.InvalidArgument, "%s: missing secrets", op)
if req.GetBucket().GetAttributes() == nil {
return nil, status.Errorf(codes.InvalidArgument, "%s: missing attributes", op)
}
l.m.Lock()
defer l.m.Unlock()
@@ -221,8 +232,8 @@ func (l *LoopbackStorage) headObject(ctx context.Context, req *plgpb.HeadObjectR
if req.GetBucket() == nil {
return nil, status.Errorf(codes.InvalidArgument, "$%s: missing storage bucket", op)
}
if req.GetBucket().GetSecrets() == nil {
return nil, status.Errorf(codes.InvalidArgument, "%s: missing secrets", op)
if req.GetBucket().GetAttributes() == nil {
return nil, status.Errorf(codes.InvalidArgument, "%s: missing attributes", op)
}
if req.GetKey() == "" {
return nil, status.Errorf(codes.InvalidArgument, "%s; missing object key", op)
@@ -261,8 +272,8 @@ func (l *LoopbackStorage) getObject(req *plgpb.GetObjectRequest, stream plgpb.St
if req.GetBucket() == nil {
return status.Errorf(codes.InvalidArgument, "%s: missing storage bucket", op)
}
if req.GetBucket().GetSecrets() == nil {
return status.Errorf(codes.InvalidArgument, "%s: missing secrets", op)
if req.GetBucket().GetAttributes() == nil {
return status.Errorf(codes.InvalidArgument, "%s: missing attributes", op)
}
if req.GetKey() == "" {
return status.Errorf(codes.InvalidArgument, "%s; missing object key", op)
@@ -317,12 +328,12 @@ func (l *LoopbackStorage) putObject(ctx context.Context, req *plgpb.PutObjectReq
if req.GetBucket() == nil {
return nil, status.Errorf(codes.InvalidArgument, "%s: missing storage bucket", op)
}
if req.GetBucket().GetAttributes() == nil {
return nil, status.Errorf(codes.InvalidArgument, "%s: missing attributes", op)
}
if req.GetBucket().GetBucketName() == "" {
return nil, status.Errorf(codes.InvalidArgument, "%s: missing bucket name", op)
}
if req.GetBucket().GetSecrets() == nil {
return nil, status.Errorf(codes.InvalidArgument, "%s: missing secrets", op)
}
if req.GetKey() == "" {
return nil, status.Errorf(codes.InvalidArgument, "%s; missing object key", op)
}
+284 -18
View File
@@ -63,7 +63,7 @@ func TestLoopbackOnCreateStorageBucket(t *testing.T) {
expectedErr: codes.InvalidArgument,
},
{
name: "missing secrets",
name: "missing attributes",
request: &plgpb.OnCreateStorageBucketRequest{
Bucket: &storagebuckets.StorageBucket{
BucketName: "aws_s3_mock",
@@ -77,6 +77,11 @@ func TestLoopbackOnCreateStorageBucket(t *testing.T) {
Bucket: &storagebuckets.StorageBucket{
BucketName: "bucket_dne",
Secrets: secrets,
Attributes: &structpb.Struct{
Fields: map[string]*structpb.Value{
"endpoint": structpb.NewStringValue("0.0.0.0"),
},
},
},
},
expectedErr: codes.NotFound,
@@ -87,16 +92,39 @@ func TestLoopbackOnCreateStorageBucket(t *testing.T) {
Bucket: &storagebuckets.StorageBucket{
BucketName: "aws_s3_err",
Secrets: secrets,
Attributes: &structpb.Struct{
Fields: map[string]*structpb.Value{
"endpoint": structpb.NewStringValue("0.0.0.0"),
},
},
},
},
expectedErr: codes.PermissionDenied,
},
{
name: "valid credentials",
name: "valid without credentials",
request: &plgpb.OnCreateStorageBucketRequest{
Bucket: &storagebuckets.StorageBucket{
BucketName: "aws_s3_mock",
Attributes: &structpb.Struct{
Fields: map[string]*structpb.Value{
"endpoint": structpb.NewStringValue("0.0.0.0"),
},
},
},
},
},
{
name: "valid with credentials",
request: &plgpb.OnCreateStorageBucketRequest{
Bucket: &storagebuckets.StorageBucket{
BucketName: "aws_s3_mock",
Secrets: secrets,
Attributes: &structpb.Struct{
Fields: map[string]*structpb.Value{
"endpoint": structpb.NewStringValue("0.0.0.0"),
},
},
},
},
},
@@ -164,11 +192,10 @@ func TestLoopbackOnUpdateStorageBucket(t *testing.T) {
expectedErr: codes.InvalidArgument,
},
{
name: "missing secrets",
name: "missing attributes",
request: &plgpb.OnUpdateStorageBucketRequest{
NewBucket: &storagebuckets.StorageBucket{
BucketName: "aws_s3_mock",
Secrets: secrets,
},
},
expectedErr: codes.InvalidArgument,
@@ -179,6 +206,11 @@ func TestLoopbackOnUpdateStorageBucket(t *testing.T) {
NewBucket: &storagebuckets.StorageBucket{
BucketName: "bucket_dne",
Secrets: secrets,
Attributes: &structpb.Struct{
Fields: map[string]*structpb.Value{
"endpoint": structpb.NewStringValue("0.0.0.0"),
},
},
},
Persisted: persisted,
},
@@ -190,17 +222,40 @@ func TestLoopbackOnUpdateStorageBucket(t *testing.T) {
NewBucket: &storagebuckets.StorageBucket{
BucketName: "aws_s3_err",
Secrets: secrets,
Attributes: &structpb.Struct{
Fields: map[string]*structpb.Value{
"endpoint": structpb.NewStringValue("0.0.0.0"),
},
},
},
Persisted: persisted,
},
expectedErr: codes.PermissionDenied,
},
{
name: "valid credentials",
name: "valid without credentials",
request: &plgpb.OnUpdateStorageBucketRequest{
NewBucket: &storagebuckets.StorageBucket{
BucketName: "aws_s3_mock",
Attributes: &structpb.Struct{
Fields: map[string]*structpb.Value{
"endpoint": structpb.NewStringValue("0.0.0.0"),
},
},
},
},
},
{
name: "valid with credentials",
request: &plgpb.OnUpdateStorageBucketRequest{
NewBucket: &storagebuckets.StorageBucket{
BucketName: "aws_s3_mock",
Secrets: secrets,
Attributes: &structpb.Struct{
Fields: map[string]*structpb.Value{
"endpoint": structpb.NewStringValue("0.0.0.0"),
},
},
},
Persisted: persisted,
},
@@ -259,21 +314,38 @@ func TestLoopbackOnDeleteStorageBucket(t *testing.T) {
expectedErr: codes.InvalidArgument,
},
{
name: "missing secrets",
name: "missing attributes",
request: &plgpb.OnDeleteStorageBucketRequest{
Bucket: &storagebuckets.StorageBucket{
BucketName: "aws_s3_mock",
Secrets: secrets,
},
},
expectedErr: codes.InvalidArgument,
},
{
name: "valid credentials",
name: "valid without credentials",
request: &plgpb.OnDeleteStorageBucketRequest{
Bucket: &storagebuckets.StorageBucket{
BucketName: "aws_s3_mock",
Attributes: &structpb.Struct{
Fields: map[string]*structpb.Value{
"endpoint": structpb.NewStringValue("0.0.0.0"),
},
},
},
},
},
{
name: "valid with credentials",
request: &plgpb.OnDeleteStorageBucketRequest{
Bucket: &storagebuckets.StorageBucket{
BucketName: "aws_s3_mock",
Secrets: secrets,
Attributes: &structpb.Struct{
Fields: map[string]*structpb.Value{
"endpoint": structpb.NewStringValue("0.0.0.0"),
},
},
},
Persisted: persisted,
},
@@ -336,7 +408,7 @@ func TestLoopbackValidatePermissions(t *testing.T) {
expectedErr: codes.InvalidArgument,
},
{
name: "missing secrets",
name: "missing attributes",
request: &plgpb.ValidatePermissionsRequest{
Bucket: &storagebuckets.StorageBucket{
BucketName: "aws_s3_mock",
@@ -350,6 +422,11 @@ func TestLoopbackValidatePermissions(t *testing.T) {
Bucket: &storagebuckets.StorageBucket{
BucketName: "bucket_dne",
Secrets: secrets,
Attributes: &structpb.Struct{
Fields: map[string]*structpb.Value{
"endpoint": structpb.NewStringValue("0.0.0.0"),
},
},
},
},
expectedErr: codes.NotFound,
@@ -360,16 +437,39 @@ func TestLoopbackValidatePermissions(t *testing.T) {
Bucket: &storagebuckets.StorageBucket{
BucketName: "aws_s3_err",
Secrets: secrets,
Attributes: &structpb.Struct{
Fields: map[string]*structpb.Value{
"endpoint": structpb.NewStringValue("0.0.0.0"),
},
},
},
},
expectedErr: codes.PermissionDenied,
},
{
name: "valid credentials",
name: "valid without credentials",
request: &plgpb.ValidatePermissionsRequest{
Bucket: &storagebuckets.StorageBucket{
BucketName: "aws_s3_mock",
Attributes: &structpb.Struct{
Fields: map[string]*structpb.Value{
"endpoint": structpb.NewStringValue("0.0.0.0"),
},
},
},
},
},
{
name: "valid with credentials",
request: &plgpb.ValidatePermissionsRequest{
Bucket: &storagebuckets.StorageBucket{
BucketName: "aws_s3_mock",
Secrets: secrets,
Attributes: &structpb.Struct{
Fields: map[string]*structpb.Value{
"endpoint": structpb.NewStringValue("0.0.0.0"),
},
},
},
},
},
@@ -443,8 +543,9 @@ func TestLoopbackHeadObject(t *testing.T) {
expectedErr: codes.InvalidArgument,
},
{
name: "missing secrets",
name: "missing attributes",
request: &plgpb.HeadObjectRequest{
Key: "mock_object",
Bucket: &storagebuckets.StorageBucket{
BucketName: "aws_s3_mock",
},
@@ -457,6 +558,11 @@ func TestLoopbackHeadObject(t *testing.T) {
Bucket: &storagebuckets.StorageBucket{
BucketName: "aws_s3_mock",
Secrets: secrets,
Attributes: &structpb.Struct{
Fields: map[string]*structpb.Value{
"endpoint": structpb.NewStringValue("0.0.0.0"),
},
},
},
},
expectedErr: codes.InvalidArgument,
@@ -468,6 +574,11 @@ func TestLoopbackHeadObject(t *testing.T) {
Bucket: &storagebuckets.StorageBucket{
BucketName: "invalid_bucket",
Secrets: secrets,
Attributes: &structpb.Struct{
Fields: map[string]*structpb.Value{
"endpoint": structpb.NewStringValue("0.0.0.0"),
},
},
},
},
expectedErr: codes.NotFound,
@@ -479,6 +590,11 @@ func TestLoopbackHeadObject(t *testing.T) {
Bucket: &storagebuckets.StorageBucket{
BucketName: "aws_s3_mock",
Secrets: secrets,
Attributes: &structpb.Struct{
Fields: map[string]*structpb.Value{
"endpoint": structpb.NewStringValue("0.0.0.0"),
},
},
},
},
expectedErr: codes.NotFound,
@@ -490,10 +606,30 @@ func TestLoopbackHeadObject(t *testing.T) {
Bucket: &storagebuckets.StorageBucket{
BucketName: "aws_s3_err",
Secrets: secrets,
Attributes: &structpb.Struct{
Fields: map[string]*structpb.Value{
"endpoint": structpb.NewStringValue("0.0.0.0"),
},
},
},
},
expectedErr: codes.PermissionDenied,
},
{
name: "head retrieved without secrets",
request: &plgpb.HeadObjectRequest{
Key: "mock_object",
Bucket: &storagebuckets.StorageBucket{
BucketName: "aws_s3_mock",
Attributes: &structpb.Struct{
Fields: map[string]*structpb.Value{
"endpoint": structpb.NewStringValue("0.0.0.0"),
},
},
},
},
expectedObj: mockStorageMapData["aws_s3_mock"]["mock_object"],
},
{
name: "head retrieved",
request: &plgpb.HeadObjectRequest{
@@ -501,6 +637,11 @@ func TestLoopbackHeadObject(t *testing.T) {
Bucket: &storagebuckets.StorageBucket{
BucketName: "aws_s3_mock",
Secrets: secrets,
Attributes: &structpb.Struct{
Fields: map[string]*structpb.Value{
"endpoint": structpb.NewStringValue("0.0.0.0"),
},
},
},
},
expectedObj: mockStorageMapData["aws_s3_mock"]["mock_object"],
@@ -578,8 +719,9 @@ func TestLoopbackGetObject(t *testing.T) {
expectedErr: codes.InvalidArgument,
},
{
name: "missing secrets",
name: "missing attributes",
request: &plgpb.GetObjectRequest{
Key: "mock_object",
Bucket: &storagebuckets.StorageBucket{
BucketName: "aws_s3_mock",
},
@@ -592,6 +734,11 @@ func TestLoopbackGetObject(t *testing.T) {
Bucket: &storagebuckets.StorageBucket{
BucketName: "aws_s3_mock",
Secrets: secrets,
Attributes: &structpb.Struct{
Fields: map[string]*structpb.Value{
"endpoint": structpb.NewStringValue("0.0.0.0"),
},
},
},
},
expectedErr: codes.InvalidArgument,
@@ -603,6 +750,11 @@ func TestLoopbackGetObject(t *testing.T) {
Bucket: &storagebuckets.StorageBucket{
BucketName: "invalid_bucket",
Secrets: secrets,
Attributes: &structpb.Struct{
Fields: map[string]*structpb.Value{
"endpoint": structpb.NewStringValue("0.0.0.0"),
},
},
},
},
expectedErr: codes.NotFound,
@@ -614,6 +766,11 @@ func TestLoopbackGetObject(t *testing.T) {
Bucket: &storagebuckets.StorageBucket{
BucketName: "aws_s3_mock",
Secrets: secrets,
Attributes: &structpb.Struct{
Fields: map[string]*structpb.Value{
"endpoint": structpb.NewStringValue("0.0.0.0"),
},
},
},
},
expectedErr: codes.NotFound,
@@ -625,6 +782,11 @@ func TestLoopbackGetObject(t *testing.T) {
Bucket: &storagebuckets.StorageBucket{
BucketName: "aws_s3_err",
Secrets: secrets,
Attributes: &structpb.Struct{
Fields: map[string]*structpb.Value{
"endpoint": structpb.NewStringValue("0.0.0.0"),
},
},
},
},
expectedErr: codes.PermissionDenied,
@@ -636,11 +798,31 @@ func TestLoopbackGetObject(t *testing.T) {
Bucket: &storagebuckets.StorageBucket{
BucketName: "aws_s3_mock",
Secrets: secrets,
Attributes: &structpb.Struct{
Fields: map[string]*structpb.Value{
"endpoint": structpb.NewStringValue("0.0.0.0"),
},
},
},
ChunkSize: 3,
},
expectedObj: mockStorageMapData["aws_s3_mock"]["mock_object"],
},
{
name: "object retrieved without secrets",
request: &plgpb.GetObjectRequest{
Key: "mock_object",
Bucket: &storagebuckets.StorageBucket{
BucketName: "aws_s3_mock",
Attributes: &structpb.Struct{
Fields: map[string]*structpb.Value{
"endpoint": structpb.NewStringValue("0.0.0.0"),
},
},
},
},
expectedObj: mockStorageMapData["aws_s3_mock"]["mock_object"],
},
{
name: "object retrieved",
request: &plgpb.GetObjectRequest{
@@ -648,6 +830,11 @@ func TestLoopbackGetObject(t *testing.T) {
Bucket: &storagebuckets.StorageBucket{
BucketName: "aws_s3_mock",
Secrets: secrets,
Attributes: &structpb.Struct{
Fields: map[string]*structpb.Value{
"endpoint": structpb.NewStringValue("0.0.0.0"),
},
},
},
},
expectedObj: mockStorageMapData["aws_s3_mock"]["mock_object"],
@@ -733,17 +920,19 @@ func TestLoopbackPutObject(t *testing.T) {
expectedErr: codes.InvalidArgument,
},
{
name: "missing-bucket-name",
request: &plgpb.PutObjectRequest{
Bucket: &storagebuckets.StorageBucket{},
},
name: "missing attributes",
expectedErr: codes.InvalidArgument,
},
{
name: "missing-secrets",
name: "missing-bucket-name",
request: &plgpb.PutObjectRequest{
Bucket: &storagebuckets.StorageBucket{
BucketName: "object_store",
Attributes: &structpb.Struct{
Fields: map[string]*structpb.Value{
"endpoint": structpb.NewStringValue("0.0.0.0"),
},
},
},
},
expectedErr: codes.InvalidArgument,
@@ -758,6 +947,11 @@ func TestLoopbackPutObject(t *testing.T) {
"SECRET_KEY_ID": structpb.NewStringValue("secret_key_id"),
},
},
Attributes: &structpb.Struct{
Fields: map[string]*structpb.Value{
"endpoint": structpb.NewStringValue("0.0.0.0"),
},
},
},
},
expectedErr: codes.InvalidArgument,
@@ -772,6 +966,11 @@ func TestLoopbackPutObject(t *testing.T) {
"SECRET_KEY_ID": structpb.NewStringValue("secret_key_id"),
},
},
Attributes: &structpb.Struct{
Fields: map[string]*structpb.Value{
"endpoint": structpb.NewStringValue("0.0.0.0"),
},
},
},
Key: "test-file",
},
@@ -787,6 +986,11 @@ func TestLoopbackPutObject(t *testing.T) {
"SECRET_KEY_ID": structpb.NewStringValue("secret_key_id"),
},
},
Attributes: &structpb.Struct{
Fields: map[string]*structpb.Value{
"endpoint": structpb.NewStringValue("0.0.0.0"),
},
},
},
Key: "test-file",
Path: path.Join(td, "test-file"),
@@ -803,6 +1007,11 @@ func TestLoopbackPutObject(t *testing.T) {
"SECRET_KEY_ID": structpb.NewStringValue("secret_key_id"),
},
},
Attributes: &structpb.Struct{
Fields: map[string]*structpb.Value{
"endpoint": structpb.NewStringValue("0.0.0.0"),
},
},
},
Key: "test-directory",
Path: path.Join(td, "test-directory"),
@@ -824,6 +1033,11 @@ func TestLoopbackPutObject(t *testing.T) {
"SECRET_KEY_ID": structpb.NewStringValue("secret_key_id"),
},
},
Attributes: &structpb.Struct{
Fields: map[string]*structpb.Value{
"endpoint": structpb.NewStringValue("0.0.0.0"),
},
},
},
Key: "test-bucket-not-found",
Path: path.Join(td, "test-bucket-not-found"),
@@ -845,6 +1059,11 @@ func TestLoopbackPutObject(t *testing.T) {
"SECRET_KEY_ID": structpb.NewStringValue("secret_key_id"),
},
},
Attributes: &structpb.Struct{
Fields: map[string]*structpb.Value{
"endpoint": structpb.NewStringValue("0.0.0.0"),
},
},
},
Key: "mock_object",
Path: path.Join(td, "test-bucket-not-found"),
@@ -866,6 +1085,11 @@ func TestLoopbackPutObject(t *testing.T) {
"SECRET_KEY_ID": structpb.NewStringValue("secret_key_id"),
},
},
Attributes: &structpb.Struct{
Fields: map[string]*structpb.Value{
"endpoint": structpb.NewStringValue("0.0.0.0"),
},
},
},
Key: "test-empty-object-data",
Path: path.Join(td, "test-empty-object-data"),
@@ -888,6 +1112,11 @@ func TestLoopbackPutObject(t *testing.T) {
"SECRET_KEY_ID": structpb.NewStringValue("secret_key_id"),
},
},
Attributes: &structpb.Struct{
Fields: map[string]*structpb.Value{
"endpoint": structpb.NewStringValue("0.0.0.0"),
},
},
},
Key: "foo/bar/zoo/mocked_object",
Path: path.Join(td, "test-valid-object-dir-in-key"),
@@ -903,6 +1132,32 @@ func TestLoopbackPutObject(t *testing.T) {
}(),
expectedContent: "TEST OBJ WITH DIR IN KEY!",
},
{
name: "valid object without credentials",
request: &plgpb.PutObjectRequest{
Bucket: &storagebuckets.StorageBucket{
BucketName: "object_store",
BucketPrefix: "/filtered/",
Attributes: &structpb.Struct{
Fields: map[string]*structpb.Value{
"endpoint": structpb.NewStringValue("0.0.0.0"),
},
},
},
Key: "mocked_object_no_credentials",
Path: path.Join(td, "test-valid-without-credentials"),
},
file: func() *os.File {
file, err := os.Create(path.Join(td, "test-valid-without-credentials"))
require.NoError(err)
n, err := file.WriteString("TEST OBJ WITH NO CREDENTIALS!")
require.NoError(err)
require.Equal(len("TEST OBJ WITH NO CREDENTIALS!"), n)
require.NoError(file.Close())
return file
}(),
expectedContent: "TEST OBJ WITH NO CREDENTIALS!",
},
{
name: "valid object w/ prefix",
request: &plgpb.PutObjectRequest{
@@ -914,6 +1169,11 @@ func TestLoopbackPutObject(t *testing.T) {
"SECRET_KEY_ID": structpb.NewStringValue("secret_key_id"),
},
},
Attributes: &structpb.Struct{
Fields: map[string]*structpb.Value{
"endpoint": structpb.NewStringValue("0.0.0.0"),
},
},
},
Key: "mocked_object",
Path: path.Join(td, "test-valid-object-prefix"),
@@ -984,12 +1244,18 @@ func TestLoopbackStoragePlugin(t *testing.T) {
"SECRET_ACCESS_KEY": structpb.NewStringValue("secret_access_key"),
},
}
attributes := &structpb.Struct{
Fields: map[string]*structpb.Value{
"endpoint": structpb.NewStringValue("0.0.0.0"),
},
}
objectData := "THIS IS A MOCKED OBJECT"
bucket := &storagebuckets.StorageBucket{
BucketName: "aws_s3_mock",
BucketPrefix: "/filtered/path/",
Secrets: secrets,
Attributes: attributes,
}
file, err := os.Create(path.Join(td, "test-put-object"))
@@ -69,7 +69,7 @@ message StorageBucket {
bytes attributes = 12;
// secrets_hmac is a sha256-hmac of the unencrypted secrets stored in the db.
// @inject_tag: `gorm:"not_null"`
// @inject_tag: `gorm:"default:null"`
bytes secrets_hmac = 13;
}
+2 -2
View File
@@ -68,8 +68,8 @@ type StorageBucket struct {
// @inject_tag: `gorm:"not_null"`
Attributes []byte `protobuf:"bytes,12,opt,name=attributes,proto3" json:"attributes,omitempty" gorm:"not_null"`
// secrets_hmac is a sha256-hmac of the unencrypted secrets stored in the db.
// @inject_tag: `gorm:"not_null"`
SecretsHmac []byte `protobuf:"bytes,13,opt,name=secrets_hmac,json=secretsHmac,proto3" json:"secrets_hmac,omitempty" gorm:"not_null"`
// @inject_tag: `gorm:"default:null"`
SecretsHmac []byte `protobuf:"bytes,13,opt,name=secrets_hmac,json=secretsHmac,proto3" json:"secrets_hmac,omitempty" gorm:"default:null"`
}
func (x *StorageBucket) Reset() {
+7 -6
View File
@@ -3,24 +3,25 @@ module github.com/hashicorp/boundary/plugins/boundary/mains/aws
go 1.20
require (
github.com/hashicorp/boundary-plugin-aws v0.1.6
github.com/hashicorp/boundary-plugin-aws v0.1.8
github.com/hashicorp/boundary/sdk v0.0.33
)
require (
github.com/aws/aws-sdk-go v1.44.214 // indirect
github.com/aws/aws-sdk-go-v2 v1.17.7 // indirect
github.com/aws/aws-sdk-go-v2 v1.18.0 // indirect
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.10 // indirect
github.com/aws/aws-sdk-go-v2/config v1.18.19 // indirect
github.com/aws/aws-sdk-go-v2/credentials v1.13.18 // indirect
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.1 // indirect
github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.31 // indirect
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.25 // indirect
github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.33 // indirect
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.27 // indirect
github.com/aws/aws-sdk-go-v2/internal/ini v1.3.32 // indirect
github.com/aws/aws-sdk-go-v2/internal/v4a v1.0.23 // indirect
github.com/aws/aws-sdk-go-v2/service/ec2 v1.99.0 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.9.11 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.1.26 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.25 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.27 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.14.0 // indirect
github.com/aws/aws-sdk-go-v2/service/s3 v1.31.1 // indirect
github.com/aws/aws-sdk-go-v2/service/sso v1.12.6 // indirect
@@ -39,7 +40,7 @@ require (
github.com/hashicorp/go-kms-wrapping/v2 v2.0.9 // indirect
github.com/hashicorp/go-multierror v1.1.1 // indirect
github.com/hashicorp/go-plugin v1.4.9 // indirect
github.com/hashicorp/go-secure-stdlib/awsutil v0.1.6 // indirect
github.com/hashicorp/go-secure-stdlib/awsutil v0.2.2 // indirect
github.com/hashicorp/go-secure-stdlib/base62 v0.1.2 // indirect
github.com/hashicorp/go-secure-stdlib/pluginutil/v2 v2.0.4 // indirect
github.com/hashicorp/go-uuid v1.0.3 // indirect
+15 -19
View File
@@ -2,11 +2,12 @@ github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJ
github.com/Masterminds/semver/v3 v3.2.0 h1:3MEsd0SM6jqZojhjLWWeBY+Kcjy9i6MQAeY7YgDP83g=
github.com/Masterminds/sprig/v3 v3.2.3 h1:eL2fZNezLomi0uOLqjQoN6BfsDD+fyLtgbJMAj9n6YA=
github.com/armon/go-radix v1.0.0 h1:F4z6KzEeeQIMeLFa97iZU6vupzoecKdU5TX24SNppXI=
github.com/aws/aws-sdk-go v1.30.27/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0=
github.com/aws/aws-sdk-go v1.34.0/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0=
github.com/aws/aws-sdk-go v1.44.214 h1:YzDuC+9UtrAOUkItlK7l3BvKI9o6qAog9X8i289HORc=
github.com/aws/aws-sdk-go v1.44.214/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go-v2 v1.17.7 h1:CLSjnhJSTSogvqUGhIC6LqFKATMRexcxLZ0i/Nzk9Eg=
github.com/aws/aws-sdk-go-v2 v1.17.7/go.mod h1:uzbQtefpm44goOPmdKyAlXSNcwlRgF3ePWVW6EtJvvw=
github.com/aws/aws-sdk-go-v2 v1.18.0 h1:882kkTpSFhdgYRKVZ/VCgf7sd0ru57p2JCxz4/oN5RY=
github.com/aws/aws-sdk-go-v2 v1.18.0/go.mod h1:uzbQtefpm44goOPmdKyAlXSNcwlRgF3ePWVW6EtJvvw=
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.10 h1:dK82zF6kkPeCo8J1e+tGx4JdvDIQzj7ygIoLg8WMuGs=
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.10/go.mod h1:VeTZetY5KRJLuD/7fkQXMU6Mw7H5m/KP2J5Iy9osMno=
github.com/aws/aws-sdk-go-v2/config v1.18.19 h1:AqFK6zFNtq4i1EYu+eC7lcKHYnZagMn6SW171la0bGw=
@@ -15,20 +16,25 @@ github.com/aws/aws-sdk-go-v2/credentials v1.13.18 h1:EQMdtHwz0ILTW1hoP+EwuWhwCG1
github.com/aws/aws-sdk-go-v2/credentials v1.13.18/go.mod h1:vnwlwjIe+3XJPBYKu1et30ZPABG3VaXJYr8ryohpIyM=
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.1 h1:gt57MN3liKiyGopcqgNzJb2+d9MJaKT/q1OksHNXVE4=
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.1/go.mod h1:lfUx8puBRdM5lVVMQlwt2v+ofiG/X6Ms+dy0UkG/kXw=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.31 h1:sJLYcS+eZn5EeNINGHSCRAwUJMFVqklwkH36Vbyai7M=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.31/go.mod h1:QT0BqUvX1Bh2ABdTGnjqEjvjzrCfIniM9Sc8zn9Yndo=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.25 h1:1mnRASEKnkqsntcxHaysxwgVoUUp5dkiB+l3llKnqyg=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.33 h1:kG5eQilShqmJbv11XL1VpyDbaEJzWxd4zRiCG30GSn4=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.33/go.mod h1:7i0PF1ME/2eUPFcjkVIwq+DOygHEoK92t5cDqNgYbIw=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.25/go.mod h1:zBHOPwhBc3FlQjQJE/D3IfPWiWaQmT06Vq9aNukDo0k=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.27 h1:vFQlirhuM8lLlpI7imKOMsjdQLuN9CPi+k44F/OFVsk=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.27/go.mod h1:UrHnn3QV/d0pBZ6QBAEQcqFLf8FAzLmoUfPVIueOvoM=
github.com/aws/aws-sdk-go-v2/internal/ini v1.3.32 h1:p5luUImdIqywn6JpQsW3tq5GNOxKmOnEpybzPx+d1lk=
github.com/aws/aws-sdk-go-v2/internal/ini v1.3.32/go.mod h1:XGhIBZDEgfqmFIugclZ6FU7v75nHhBDtzuB4xB/tEi4=
github.com/aws/aws-sdk-go-v2/internal/v4a v1.0.23 h1:DWYZIsyqagnWL00f8M/SOr9fN063OEQWn9LLTbdYXsk=
github.com/aws/aws-sdk-go-v2/internal/v4a v1.0.23/go.mod h1:uIiFgURZbACBEQJfqTZPb/jxO7R+9LeoHUFudtIdeQI=
github.com/aws/aws-sdk-go-v2/service/ec2 v1.99.0 h1:NXi4pNJWjAaiI56P1Rl8DC9A4jMNRE00WNBsDua5WRg=
github.com/aws/aws-sdk-go-v2/service/ec2 v1.99.0/go.mod h1:L3ZT0N/vBsw77mOAawXmRnREpEjcHd2v5Hzf7AkIH8M=
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.9.11 h1:y2+VQzC6Zh2ojtV2LoC0MNwHWc6qXv/j2vrQtlftkdA=
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.9.11/go.mod h1:iV4q2hsqtNECrfmlXyord9u4zyuFEJX9eLgLpSPzWA8=
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.1.26 h1:CeuSeq/8FnYpPtnuIeLQEEvDv9zUjneuYi8EghMBdwQ=
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.1.26/go.mod h1:2UqAAwMUXKeRkAHIlDJqvMVgOWkUi/AUXPk/YIe+Dg4=
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.25 h1:5LHn8JQ0qvjD9L9JhMtylnkcw7j05GDZqM9Oin6hpr0=
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.25/go.mod h1:/95IA+0lMnzW6XzqYJRpjjsAbKEORVeO0anQqjd2CNU=
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.27 h1:0iKliEXAcCa2qVtRs7Ot5hItA2MsufrphbRFlz1Owxo=
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.27/go.mod h1:EOwBD4J4S5qYszS5/3DpkejfuK+Z5/1uzICfPaZLtqw=
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.14.0 h1:e2ooMhpYGhDnBfSvIyusvAwX7KexuZaHbQY2Dyei7VU=
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.14.0/go.mod h1:bh2E0CXKZsQN+faiKVqC40vfNMAWheoULBCnEgO9K+8=
github.com/aws/aws-sdk-go-v2/service/s3 v1.31.1 h1:PJH4I+qYjPXclKRbVCW47iYUvtXEh1u6YmDhn5J8VQE=
@@ -46,7 +52,6 @@ github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ3
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
github.com/fatih/color v1.14.1 h1:qfhVLaG5s+nCROl1zJsZRxFeYrHLqWroPOQ8BWiNb4w=
github.com/fatih/color v1.14.1/go.mod h1:2oHN61fhTpgcxD3TSWCgKDiH1+x4OiDVVGH8WlgGZGg=
@@ -62,8 +67,8 @@ github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeN
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/hashicorp/boundary-plugin-aws v0.1.6 h1:JfEWdmz44iJmXvOZYl3UCBbyzP5m73eIlOpSu3jjos4=
github.com/hashicorp/boundary-plugin-aws v0.1.6/go.mod h1:nZFpoJ5OHE21s3tH9zxjOsA4vm8gMbykmeL728a+K4I=
github.com/hashicorp/boundary-plugin-aws v0.1.8 h1:A/GvBUvo85+wvRXt4f3qSPzEEvXeQDdjFSBFMBCNAoc=
github.com/hashicorp/boundary-plugin-aws v0.1.8/go.mod h1:2cScmnFh5SCQWYtUKkA+6FcGXui1sU/lu2bPcEZ9RQk=
github.com/hashicorp/boundary/sdk v0.0.33 h1:kHaVZ3b9j1QvYlG+vhAgrbXh8/+Rq2qlUIs8fKMQH7k=
github.com/hashicorp/boundary/sdk v0.0.33/go.mod h1:jn9j5mM8v2pOk8aLeJNIszdm7WBf4gRSP68iy8Iu5Q0=
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
@@ -75,7 +80,6 @@ github.com/hashicorp/eventlogger/filters/encrypt v0.1.8-0.20230428153751-cca4458
github.com/hashicorp/eventlogger/filters/encrypt v0.1.8-0.20230428153751-cca445805f24/go.mod h1:EQPLoX6CONA9BSYUovTQBHfPGE91g7wOxv03sO29FzY=
github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ=
github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48=
github.com/hashicorp/go-hclog v0.16.2/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=
github.com/hashicorp/go-hclog v1.5.0 h1:bI2ocEMgcVlz55Oj1xZNBsVi900c7II+fWDyV9o+13c=
github.com/hashicorp/go-hclog v1.5.0/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M=
github.com/hashicorp/go-kms-wrapping/plugin/v2 v2.0.4 h1:8z+Zi0uLYXONkxwWb/D7O5t1IUucB6Ft3uvSOa950bM=
@@ -85,8 +89,8 @@ github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+l
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
github.com/hashicorp/go-plugin v1.4.9 h1:ESiK220/qE0aGxWdzKIvRH69iLiuN/PjoLTm69RoWtU=
github.com/hashicorp/go-plugin v1.4.9/go.mod h1:viDMjcLJuDui6pXb8U4HVfb8AamCWhHGUjr2IrTF67s=
github.com/hashicorp/go-secure-stdlib/awsutil v0.1.6 h1:W9WN8p6moV1fjKLkeqEgkAMu5rauy9QeYDAmIaPuuiA=
github.com/hashicorp/go-secure-stdlib/awsutil v0.1.6/go.mod h1:MpCPSPGLDILGb4JMm94/mMi3YysIqsXzGCzkEZjcjXg=
github.com/hashicorp/go-secure-stdlib/awsutil v0.2.2 h1:kWg2vyKl7BRXrNxYziqDJ55n+vtOQ1QsGORjzoeB+uM=
github.com/hashicorp/go-secure-stdlib/awsutil v0.2.2/go.mod h1:oKHSQs4ivIfZ3fbXGQOop1XuDfdSb8RIsWTGaAanSfg=
github.com/hashicorp/go-secure-stdlib/base62 v0.1.1/go.mod h1:EdWO6czbmthiwZ3/PUsDV+UD1D5IRU4ActiaWGwt0Yw=
github.com/hashicorp/go-secure-stdlib/base62 v0.1.2 h1:ET4pqyjiGmY09R5y+rSd70J2w45CtbWDNvGqWp/R3Ng=
github.com/hashicorp/go-secure-stdlib/base62 v0.1.2/go.mod h1:EdWO6czbmthiwZ3/PUsDV+UD1D5IRU4ActiaWGwt0Yw=
@@ -123,14 +127,10 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
@@ -167,7 +167,6 @@ github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
@@ -207,12 +206,9 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=