Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions core/capabilities/vault/capability.go
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,9 @@ func validateWriteRequest(publicKey *tdh2easy.PublicKey, id string, encryptedSec
uniqueIDs := map[string]bool{}
cipherText := &tdh2easy.Ciphertext{}
for idx, req := range encryptedSecrets {
if req == nil {
return errors.New("encrypted secret must not be nil at index " + strconv.Itoa(idx))
}
if req.Id == nil {
return errors.New("secret ID must not be nil at index " + strconv.Itoa(idx))
}
Expand Down Expand Up @@ -269,6 +272,9 @@ func ValidateDeleteSecretsRequest(request *vaultcommon.DeleteSecretsRequest) err

uniqueIDs := map[string]bool{}
for idx, id := range request.Ids {
if id == nil {
return errors.New("secret ID must not be nil at index " + strconv.Itoa(idx))
}
if id.Key == "" || id.Namespace == "" || id.Owner == "" {
return errors.New("secret ID must have key, namespace and owner set at index " + strconv.Itoa(idx) + ": " + id.String())
}
Expand Down
4 changes: 2 additions & 2 deletions core/services/gateway/handlers/vault/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -484,7 +484,7 @@ func (h *handler) handleSecretsCreate(ctx context.Context, ar *activeRequest) er
}
createSecretsRequest.RequestId = ar.req.ID
for _, secretItem := range createSecretsRequest.EncryptedSecrets {
if secretItem.Id != nil && secretItem.Id.Namespace == "" {
if secretItem != nil && secretItem.Id != nil && secretItem.Id.Namespace == "" {
secretItem.Id.Namespace = vaulttypes.DefaultNamespace
}
}
Expand Down Expand Up @@ -516,7 +516,7 @@ func (h *handler) handleSecretsUpdate(ctx context.Context, ar *activeRequest) er

updateSecretsRequest.RequestId = ar.req.ID
for _, secretItem := range updateSecretsRequest.EncryptedSecrets {
if secretItem.Id != nil && secretItem.Id.Namespace == "" {
if secretItem != nil && secretItem.Id != nil && secretItem.Id.Namespace == "" {
secretItem.Id.Namespace = vaulttypes.DefaultNamespace
}
}
Expand Down
103 changes: 103 additions & 0 deletions core/services/gateway/handlers/vault/handler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,45 @@ func TestVaultHandler_HandleJSONRPCUserMessage(t *testing.T) {
wg.Wait()
})

t.Run("nil EncryptedSecrets inside CreateSecrets body", func(t *testing.T) {
var wg sync.WaitGroup
h, callback, _, _ := setupHandler(t)
emptyCreateSecretsRequest := &vaultcommon.CreateSecretsRequest{
RequestId: "test_request_id",
EncryptedSecrets: []*vaultcommon.EncryptedSecret{
nil,
{
EncryptedValue: "abc123", // should be a valid hex string
},
},
}
emptyParams, err := json.Marshal(emptyCreateSecretsRequest)
require.NoError(t, err)

requestID := "1"
validJSONRequest := jsonrpc.Request[json.RawMessage]{
ID: requestID,
Method: vaulttypes.MethodSecretsCreate,
Params: (*json.RawMessage)(&emptyParams),
}

wg.Add(1)
go func() {
defer wg.Done()
resp, err2 := callback.Wait(t.Context())
assert.NoError(t, err2)
var secretsResponse jsonrpc.Response[vaultcommon.CreateSecretsResponse]
err2 = json.Unmarshal(resp.RawResponse, &secretsResponse)
assert.NoError(t, err2)
assert.Equal(t, validJSONRequest.ID, secretsResponse.ID, "Request ID should match")
assert.ErrorContains(t, secretsResponse.Error, "encrypted secret must not be nil")
}()

err = h.HandleJSONRPCUserMessage(t.Context(), validJSONRequest, callback)
require.NoError(t, err)
wg.Wait()
})

t.Run("no id inside CreateSecrets.EncryptedSecrets body", func(t *testing.T) {
var wg sync.WaitGroup
h, callback, _, _ := setupHandler(t)
Expand Down Expand Up @@ -291,6 +330,70 @@ func TestVaultHandler_HandleJSONRPCUserMessage(t *testing.T) {
wg.Wait()
})

t.Run("nil id in delete secrets", func(t *testing.T) {
var wg sync.WaitGroup
h, callback, _, _ := setupHandler(t)

id := &vaultcommon.SecretIdentifier{
Key: "foo",
Namespace: "default",
Owner: owner,
}
reqData := &vaultcommon.DeleteSecretsRequest{
RequestId: "id",
Ids: []*vaultcommon.SecretIdentifier{
nil,
id,
},
}
reqDataBytes, err := json.Marshal(reqData)
require.NoError(t, err)
requestID := "1"
validJSONRequest := jsonrpc.Request[json.RawMessage]{
ID: requestID,
Method: vaulttypes.MethodSecretsDelete,
Params: (*json.RawMessage)(&reqDataBytes),
}

responseData := &vaultcommon.DeleteSecretsResponse{
Responses: []*vaultcommon.DeleteSecretResponse{
{
Id: id,
Success: true,
},
},
}
resultBytes, err := json.Marshal(responseData)
require.NoError(t, err)
expectedRequestID := owner + vaulttypes.RequestIDSeparator + requestID
response := jsonrpc.Response[json.RawMessage]{
ID: expectedRequestID,
Result: (*json.RawMessage)(&resultBytes),
Method: vaulttypes.MethodSecretsDelete,
}
resultBytes, err = json.Marshal(responseData)
require.NoError(t, err)

wg.Add(1)
go func() {
defer wg.Done()
resp, err2 := callback.Wait(t.Context())
assert.NoError(t, err2)
var secretsResponse jsonrpc.Response[vaultcommon.DeleteSecretsResponse]
err2 = json.Unmarshal(resp.RawResponse, &secretsResponse)
assert.NoError(t, err2)
assert.Equal(t, validJSONRequest.ID, secretsResponse.ID, "Request ID should match")
assert.ErrorContains(t, secretsResponse.Error,"secret ID must not be nil")
}()

err = h.HandleJSONRPCUserMessage(t.Context(), validJSONRequest, callback)
require.NoError(t, err)

err = h.HandleNodeMessage(t.Context(), &response, NodeOne.Address)
require.NoError(t, err)
wg.Wait()
})

t.Run("happy path - list secret identifiers", func(t *testing.T) {
var wg sync.WaitGroup
h, callback, don, _ := setupHandler(t)
Expand Down
18 changes: 18 additions & 0 deletions core/services/ocr2/plugins/vault/kvstore.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ func NewWriteStore(writer ocr3_1types.KeyValueReadWriter) *KVStore {
}

func (s *KVStore) GetSecret(id *vault.SecretIdentifier) (*vault.StoredSecret, error) {
if id == nil {
return nil, errors.New("id cannot be nil")
}
found, err := s.metadataContainsID(id)
if err != nil {
return nil, fmt.Errorf("failed to check if metadata contains id: %w", err)
Expand Down Expand Up @@ -118,6 +121,9 @@ func (s *KVStore) WriteMetadata(owner string, metadata *vault.StoredMetadata) er
}

func (s *KVStore) metadataContainsID(id *vault.SecretIdentifier) (bool, error) {
if id == nil {
return false, errors.New("id cannot be nil")
}
md, err := s.GetMetadata(id.Owner)
if err != nil {
return false, fmt.Errorf("failed to get metadata for owner %s: %w", id.Owner, err)
Expand All @@ -137,6 +143,9 @@ func (s *KVStore) metadataContainsID(id *vault.SecretIdentifier) (bool, error) {
}

func (s *KVStore) addIDToMetadata(id *vault.SecretIdentifier) error {
if id == nil {
return errors.New("id cannot be nil")
}
md, err := s.GetMetadata(id.Owner)
if err != nil {
return fmt.Errorf("failed to get metadata for owner %s: %w", id.Owner, err)
Expand Down Expand Up @@ -166,6 +175,9 @@ func (s *KVStore) addIDToMetadata(id *vault.SecretIdentifier) error {
}

func (s *KVStore) removeIDFromMetadata(id *vault.SecretIdentifier) error {
if id == nil {
return errors.New("id cannot be nil")
}
md, err := s.GetMetadata(id.Owner)
if err != nil {
return fmt.Errorf("failed to get metadata for owner %s: %w", id.Owner, err)
Expand Down Expand Up @@ -201,6 +213,9 @@ func (s *KVStore) removeIDFromMetadata(id *vault.SecretIdentifier) error {
}

func (s *KVStore) WriteSecret(id *vault.SecretIdentifier, secret *vault.StoredSecret) error {
if id == nil {
return errors.New("id cannot be nil")
}
b, err := proto.Marshal(secret)
if err != nil {
return fmt.Errorf("failed to marshal secret: %w", err)
Expand All @@ -219,6 +234,9 @@ func (s *KVStore) WriteSecret(id *vault.SecretIdentifier, secret *vault.StoredSe
}

func (s *KVStore) DeleteSecret(id *vault.SecretIdentifier) error {
if id == nil {
return errors.New("id cannot be nil")
}
err := s.removeIDFromMetadata(id)
if err != nil {
return fmt.Errorf("failed to remove id from metadata: %w", err)
Expand Down
Loading