diff --git a/core/capabilities/vault/capability_test.go b/core/capabilities/vault/capability_test.go index 4b92a8eaeb3..7cb9cd29811 100644 --- a/core/capabilities/vault/capability_test.go +++ b/core/capabilities/vault/capability_test.go @@ -28,6 +28,9 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/logger" ) +const capabilityTestWorkflowOwner = "0x0001020304050607080900010203040506070809" +const capabilityTestWorkflowOwnerAlt = "0x1111111111111111111111111111111111111111" + func newTestRequestLifecycleTracker(t *testing.T) *RequestLifecycleTracker { t.Helper() tr, err := NewRequestLifecycleTracker(logger.TestLogger(t)) @@ -47,7 +50,7 @@ func TestCapability_CapabilityCall(t *testing.T) { require.NoError(t, err) servicetest.Run(t, capability) - owner := "testowner" + owner := capabilityTestWorkflowOwner workflowID := "test-workflow-id" workflowExecutionID := "test-workflow-execution-id" referenceID := "test-reference-id" @@ -144,7 +147,7 @@ func TestCapability_CapabilityCall_DuringSubscriptionPhase(t *testing.T) { require.NoError(t, err) servicetest.Run(t, capability) - owner := "testowner" + owner := capabilityTestWorkflowOwner workflowID := "test-workflow-id" referenceID := "0" @@ -637,7 +640,7 @@ func TestCapability_CapabilityCall_ForwardsRequestGetSecretsIdentity(t *testing. Id: &vault.SecretIdentifier{ Key: "Foo", Namespace: "Bar", - Owner: "owner", + Owner: capabilityTestWorkflowOwner, }, Result: &vault.SecretResponse_Data{ Data: &vault.SecretData{EncryptedValue: "encrypted-value"}, @@ -804,7 +807,7 @@ func TestCapability_CapabilityCall_ReturnsIncorrectType(t *testing.T) { require.NoError(t, err) servicetest.Run(t, capability) - owner := "testowner" + owner := capabilityTestWorkflowOwner workflowID := "test-workflow-id" workflowExecutionID := "test-workflow-execution-id" referenceID := "test-reference-id" @@ -878,7 +881,7 @@ func TestCapability_CapabilityCall_TimeOut(t *testing.T) { require.NoError(t, err) servicetest.Run(t, capability) - owner := "testowner" + owner := capabilityTestWorkflowOwner workflowID := "test-workflow-id" workflowExecutionID := "test-workflow-execution-id" referenceID := "test-reference-id" @@ -1062,7 +1065,7 @@ func TestCapability_CRUD(t *testing.T) { Id: &vault.SecretIdentifier{ Key: "a", Namespace: "Bar", - Owner: "a", + Owner: capabilityTestWorkflowOwnerAlt, }, EncryptedValue: encryptedSecret, }, @@ -1263,7 +1266,7 @@ func TestCapability_CRUD(t *testing.T) { Id: &vault.SecretIdentifier{ Key: "w", Namespace: "na", - Owner: "random", + Owner: capabilityTestWorkflowOwnerAlt, }, EncryptedValue: encryptedSecret, }, @@ -1458,7 +1461,7 @@ func TestCapability_CRUD(t *testing.T) { { Key: "Foo", Namespace: "", - Owner: "random", + Owner: owner, }, }, } @@ -1524,7 +1527,7 @@ func TestCapability_CRUD(t *testing.T) { call: func(t *testing.T, capability *Capability) (*vaulttypes.Response, error) { req := &vault.ListSecretIdentifiersRequest{ RequestId: "", - Owner: "owner", + Owner: capabilityTestWorkflowOwner, Namespace: "namespace", } return capability.ListSecretIdentifiers(t.Context(), req) diff --git a/core/capabilities/vault/gw_handler_test.go b/core/capabilities/vault/gw_handler_test.go index c1aa26659a7..054b47d65a9 100644 --- a/core/capabilities/vault/gw_handler_test.go +++ b/core/capabilities/vault/gw_handler_test.go @@ -25,6 +25,13 @@ import ( connector_mocks "github.com/smartcontractkit/chainlink/v2/core/services/gateway/connector/mocks" ) +const ( + gwTestOwnerA = "0xAb5801a7D398351b8bE11C439e05C5B3259aeC9B" + gwTestOwnerALower = "0xab5801a7d398351b8be11c439e05c5b3259aec9b" + gwTestOwnerB = "0x1111111111111111111111111111111111111111" + gwTestOwnerC = "0x2222222222222222222222222222222222222222" +) + func TestGatewayHandler_HandleGatewayMessage(t *testing.T) { lggr := logger.TestLogger(t) ctx := t.Context() @@ -47,12 +54,12 @@ func TestGatewayHandler_HandleGatewayMessage(t *testing.T) { setupMocks: func(ss *vaulttypesmocks.SecretsService, gc *connector_mocks.GatewayConnector, ra *vaultcapmocks.Authorizer) { ra.EXPECT().AuthorizeRequest(mock.Anything, mock.MatchedBy(func(req jsonrpc.Request[json.RawMessage]) bool { return req.Method == vaulttypes.MethodSecretsCreate && req.ID == "1" - })).Return(authResult("", "0xabc"), nil) + })).Return(authResult("", gwTestOwnerA), nil) ss.EXPECT().CreateSecrets(mock.Anything, mock.MatchedBy(func(req *vaultcommon.CreateSecretsRequest) bool { return len(req.EncryptedSecrets) == 1 && req.EncryptedSecrets[0].Id.Key == "test-secret" && - req.EncryptedSecrets[0].Id.Owner == "0xAbC" && - req.RequestId == "0xabc"+vaulttypes.RequestIDSeparator+"1" + req.EncryptedSecrets[0].Id.Owner == gwTestOwnerA && + req.RequestId == gwTestOwnerA+vaulttypes.RequestIDSeparator+"1" })).Return(&vaulttypes.Response{ID: "test-secret"}, nil) gc.On("SendToGateway", mock.Anything, "gateway-1", mock.MatchedBy(func(resp *jsonrpc.Response[json.RawMessage]) bool { @@ -69,7 +76,7 @@ func TestGatewayHandler_HandleGatewayMessage(t *testing.T) { { Id: &vaultcommon.SecretIdentifier{ Key: "test-secret", - Owner: "0xAbC", + Owner: gwTestOwnerA, }, EncryptedValue: "encrypted-value", }, @@ -86,12 +93,12 @@ func TestGatewayHandler_HandleGatewayMessage(t *testing.T) { setupMocks: func(ss *vaulttypesmocks.SecretsService, gc *connector_mocks.GatewayConnector, ra *vaultcapmocks.Authorizer) { ra.EXPECT().AuthorizeRequest(mock.Anything, mock.MatchedBy(func(req jsonrpc.Request[json.RawMessage]) bool { return req.Method == vaulttypes.MethodSecretsCreate && req.ID == "1" - })).Return(authResult("org-1", "0xworkflow"), nil) + })).Return(authResult("org-1", gwTestOwnerC), nil) ss.EXPECT().CreateSecrets(mock.Anything, mock.MatchedBy(func(req *vaultcommon.CreateSecretsRequest) bool { return len(req.EncryptedSecrets) == 1 && req.EncryptedSecrets[0].Id.Key == "test-secret" && - req.EncryptedSecrets[0].Id.Owner == "0xworkflow" && - req.RequestId == "0xworkflow"+vaulttypes.RequestIDSeparator+"1" + req.EncryptedSecrets[0].Id.Owner == gwTestOwnerC && + req.RequestId == gwTestOwnerC+vaulttypes.RequestIDSeparator+"1" })).Return(&vaulttypes.Response{ID: "test-secret"}, nil) gc.On("SendToGateway", mock.Anything, "gateway-1", mock.MatchedBy(func(resp *jsonrpc.Response[json.RawMessage]) bool { @@ -107,7 +114,7 @@ func TestGatewayHandler_HandleGatewayMessage(t *testing.T) { { Id: &vaultcommon.SecretIdentifier{ Key: "test-secret", - Owner: "0xworkflow", + Owner: gwTestOwnerC, }, EncryptedValue: "encrypted-value", }, @@ -127,12 +134,12 @@ func TestGatewayHandler_HandleGatewayMessage(t *testing.T) { req.ID == "1" && req.Auth == "" && req.Params != nil - })).Return(authResult("org-1", "0xworkflow"), nil) + })).Return(authResult("org-1", gwTestOwnerC), nil) ss.EXPECT().CreateSecrets(mock.Anything, mock.MatchedBy(func(req *vaultcommon.CreateSecretsRequest) bool { return len(req.EncryptedSecrets) == 1 && req.EncryptedSecrets[0].Id.Key == "test-secret" && - req.EncryptedSecrets[0].Id.Owner == "0xworkflow" && - req.RequestId == "0xworkflow"+vaulttypes.RequestIDSeparator+"1" + req.EncryptedSecrets[0].Id.Owner == gwTestOwnerC && + req.RequestId == gwTestOwnerC+vaulttypes.RequestIDSeparator+"1" })).Return(&vaulttypes.Response{ID: "test-secret"}, nil) gc.On("SendToGateway", mock.Anything, "gateway-1", mock.MatchedBy(func(resp *jsonrpc.Response[json.RawMessage]) bool { @@ -145,8 +152,9 @@ func TestGatewayHandler_HandleGatewayMessage(t *testing.T) { Params: func() *json.RawMessage { rid := "org-1" + vaulttypes.RequestIDSeparator + "1" raw := json.RawMessage(fmt.Sprintf( - `{"request_id":%q,"encrypted_secrets":[{"id":{"key":"test-secret","owner":"0xworkflow"},"encrypted_value":"encrypted-value"}]}`, + `{"request_id":%q,"encrypted_secrets":[{"id":{"key":"test-secret","owner":%q},"encrypted_value":"encrypted-value"}]}`, rid, + gwTestOwnerC, )) return &raw }(), @@ -156,7 +164,7 @@ func TestGatewayHandler_HandleGatewayMessage(t *testing.T) { { name: "failure - service error", setupMocks: func(ss *vaulttypesmocks.SecretsService, gc *connector_mocks.GatewayConnector, ra *vaultcapmocks.Authorizer) { - ra.EXPECT().AuthorizeRequest(mock.Anything, mock.Anything).Return(authResult("", "0xabc"), nil) + ra.EXPECT().AuthorizeRequest(mock.Anything, mock.Anything).Return(authResult("", gwTestOwnerA), nil) ss.EXPECT().CreateSecrets(mock.Anything, mock.Anything).Return(nil, errors.New("service error")) gc.On("SendToGateway", mock.Anything, "gateway-1", mock.MatchedBy(func(resp *jsonrpc.Response[json.RawMessage]) bool { @@ -174,7 +182,7 @@ func TestGatewayHandler_HandleGatewayMessage(t *testing.T) { { Id: &vaultcommon.SecretIdentifier{ Key: "test-secret", - Owner: "0xAbC", + Owner: gwTestOwnerA, }, EncryptedValue: "encrypted-value", }, @@ -223,13 +231,13 @@ func TestGatewayHandler_HandleGatewayMessage(t *testing.T) { setupMocks: func(ss *vaulttypesmocks.SecretsService, gc *connector_mocks.GatewayConnector, ra *vaultcapmocks.Authorizer) { ra.EXPECT().AuthorizeRequest(mock.Anything, mock.MatchedBy(func(req jsonrpc.Request[json.RawMessage]) bool { return req.Method == vaulttypes.MethodSecretsDelete && req.ID == "1" - })).Return(authResult("", "0xabc"), nil) + })).Return(authResult("", gwTestOwnerA), nil) ss.EXPECT().DeleteSecrets(mock.Anything, mock.MatchedBy(func(req *vaultcommon.DeleteSecretsRequest) bool { return len(req.Ids) == 1 && req.Ids[0].Key == "Foo" && req.Ids[0].Namespace == "Bar" && - req.Ids[0].Owner == "0xAbC" && - req.RequestId == "0xabc"+vaulttypes.RequestIDSeparator+"1" + req.Ids[0].Owner == gwTestOwnerA && + req.RequestId == gwTestOwnerA+vaulttypes.RequestIDSeparator+"1" })).Return(&vaulttypes.Response{ID: "test-secret"}, nil) gc.On("SendToGateway", mock.Anything, "gateway-1", mock.MatchedBy(func(resp *jsonrpc.Response[json.RawMessage]) bool { @@ -246,7 +254,7 @@ func TestGatewayHandler_HandleGatewayMessage(t *testing.T) { { Key: "Foo", Namespace: "Bar", - Owner: "0xAbC", + Owner: gwTestOwnerA, }, }, }) @@ -261,12 +269,12 @@ func TestGatewayHandler_HandleGatewayMessage(t *testing.T) { setupMocks: func(ss *vaulttypesmocks.SecretsService, gc *connector_mocks.GatewayConnector, ra *vaultcapmocks.Authorizer) { ra.EXPECT().AuthorizeRequest(mock.Anything, mock.MatchedBy(func(req jsonrpc.Request[json.RawMessage]) bool { return req.Method == vaulttypes.MethodSecretsUpdate && req.ID == "1" - })).Return(authResult("org-1", "0xworkflow"), nil) + })).Return(authResult("org-1", gwTestOwnerC), nil) ss.EXPECT().UpdateSecrets(mock.Anything, mock.MatchedBy(func(req *vaultcommon.UpdateSecretsRequest) bool { return len(req.EncryptedSecrets) == 1 && req.EncryptedSecrets[0].Id.Key == "updated-secret" && - req.EncryptedSecrets[0].Id.Owner == "0xworkflow" && - req.RequestId == "0xworkflow"+vaulttypes.RequestIDSeparator+"1" + req.EncryptedSecrets[0].Id.Owner == gwTestOwnerC && + req.RequestId == gwTestOwnerC+vaulttypes.RequestIDSeparator+"1" })).Return(&vaulttypes.Response{ID: "updated-secret"}, nil) gc.On("SendToGateway", mock.Anything, "gateway-1", mock.MatchedBy(func(resp *jsonrpc.Response[json.RawMessage]) bool { @@ -282,7 +290,7 @@ func TestGatewayHandler_HandleGatewayMessage(t *testing.T) { { Id: &vaultcommon.SecretIdentifier{ Key: "updated-secret", - Owner: "0xworkflow", + Owner: gwTestOwnerC, }, EncryptedValue: "encrypted-value", }, @@ -299,13 +307,13 @@ func TestGatewayHandler_HandleGatewayMessage(t *testing.T) { setupMocks: func(ss *vaulttypesmocks.SecretsService, gc *connector_mocks.GatewayConnector, ra *vaultcapmocks.Authorizer) { ra.EXPECT().AuthorizeRequest(mock.Anything, mock.MatchedBy(func(req jsonrpc.Request[json.RawMessage]) bool { return req.Method == vaulttypes.MethodSecretsDelete && req.ID == "1" - })).Return(authResult("org-1", "0xworkflow"), nil) + })).Return(authResult("org-1", gwTestOwnerC), nil) ss.EXPECT().DeleteSecrets(mock.Anything, mock.MatchedBy(func(req *vaultcommon.DeleteSecretsRequest) bool { return len(req.Ids) == 1 && req.Ids[0].Key == "Foo" && req.Ids[0].Namespace == "Bar" && - req.Ids[0].Owner == "0xworkflow" && - req.RequestId == "0xworkflow"+vaulttypes.RequestIDSeparator+"1" + req.Ids[0].Owner == gwTestOwnerC && + req.RequestId == gwTestOwnerC+vaulttypes.RequestIDSeparator+"1" })).Return(&vaulttypes.Response{ID: "test-secret"}, nil) gc.On("SendToGateway", mock.Anything, "gateway-1", mock.MatchedBy(func(resp *jsonrpc.Response[json.RawMessage]) bool { @@ -321,7 +329,7 @@ func TestGatewayHandler_HandleGatewayMessage(t *testing.T) { { Key: "Foo", Namespace: "Bar", - Owner: "0xworkflow", + Owner: gwTestOwnerC, }, }, }) @@ -336,10 +344,10 @@ func TestGatewayHandler_HandleGatewayMessage(t *testing.T) { setupMocks: func(ss *vaulttypesmocks.SecretsService, gc *connector_mocks.GatewayConnector, ra *vaultcapmocks.Authorizer) { ra.EXPECT().AuthorizeRequest(mock.Anything, mock.MatchedBy(func(req jsonrpc.Request[json.RawMessage]) bool { return req.Method == vaulttypes.MethodSecretsList && req.ID == "1" - })).Return(authResult("org-1", "0xworkflow"), nil) + })).Return(authResult("org-1", gwTestOwnerC), nil) ss.EXPECT().ListSecretIdentifiers(mock.Anything, mock.MatchedBy(func(req *vaultcommon.ListSecretIdentifiersRequest) bool { - return req.RequestId == "0xworkflow"+vaulttypes.RequestIDSeparator+"1" && - req.Owner == "0xworkflow" && + return req.RequestId == gwTestOwnerC+vaulttypes.RequestIDSeparator+"1" && + req.Owner == gwTestOwnerC && req.Namespace == "ns" })).Return(&vaulttypes.Response{ID: "test-secret"}, nil) @@ -352,7 +360,7 @@ func TestGatewayHandler_HandleGatewayMessage(t *testing.T) { ID: "1", Params: func() *json.RawMessage { params, _ := json.Marshal(vaultcommon.ListSecretIdentifiersRequest{ - Owner: "0xworkflow", + Owner: gwTestOwnerC, Namespace: "ns", }) raw := json.RawMessage(params) @@ -380,7 +388,7 @@ func TestGatewayHandler_HandleGatewayMessage(t *testing.T) { { Id: &vaultcommon.SecretIdentifier{ Key: "test-secret", - Owner: "0xAbC", + Owner: gwTestOwnerA, }, EncryptedValue: "encrypted-value", }, @@ -408,10 +416,10 @@ func TestGatewayHandler_HandleGatewayMessage(t *testing.T) { return parsed.RequestId == "1" && len(parsed.EncryptedSecrets) == 1 && parsed.EncryptedSecrets[0].Id != nil && - parsed.EncryptedSecrets[0].Id.Owner == "0xAbC" - })).Return(authResult("", "0xabc"), nil) + parsed.EncryptedSecrets[0].Id.Owner == gwTestOwnerA + })).Return(authResult("", gwTestOwnerA), nil) ss.EXPECT().CreateSecrets(mock.Anything, mock.MatchedBy(func(req *vaultcommon.CreateSecretsRequest) bool { - return req.RequestId == "0xabc"+vaulttypes.RequestIDSeparator+"1" + return req.RequestId == gwTestOwnerA+vaulttypes.RequestIDSeparator+"1" })).Return(&vaulttypes.Response{ID: "test-secret"}, nil) gc.On("SendToGateway", mock.Anything, "gateway-1", mock.MatchedBy(func(resp *jsonrpc.Response[json.RawMessage]) bool { @@ -420,15 +428,15 @@ func TestGatewayHandler_HandleGatewayMessage(t *testing.T) { }, request: &jsonrpc.Request[json.RawMessage]{ Method: vaulttypes.MethodSecretsCreate, - ID: "0xDef" + vaulttypes.RequestIDSeparator + "1", + ID: gwTestOwnerB + vaulttypes.RequestIDSeparator + "1", Params: func() *json.RawMessage { params, _ := json.Marshal(vaultcommon.CreateSecretsRequest{ - RequestId: "0xDef" + vaulttypes.RequestIDSeparator + "1", + RequestId: gwTestOwnerB + vaulttypes.RequestIDSeparator + "1", EncryptedSecrets: []*vaultcommon.EncryptedSecret{ { Id: &vaultcommon.SecretIdentifier{ Key: "test-secret", - Owner: "0xAbC", + Owner: gwTestOwnerA, }, EncryptedValue: "encrypted-value", }, @@ -443,7 +451,7 @@ func TestGatewayHandler_HandleGatewayMessage(t *testing.T) { { name: "failure - auth layer rejects cross-owner mutation", setupMocks: func(ss *vaulttypesmocks.SecretsService, gc *connector_mocks.GatewayConnector, ra *vaultcapmocks.Authorizer) { - ra.EXPECT().AuthorizeRequest(mock.Anything, mock.Anything).Return(authResult("", "0xdef"), nil) + ra.EXPECT().AuthorizeRequest(mock.Anything, mock.Anything).Return(authResult("", gwTestOwnerB), nil) gc.On("SendToGateway", mock.Anything, "gateway-1", mock.MatchedBy(func(resp *jsonrpc.Response[json.RawMessage]) bool { return resp.Error != nil && resp.Error.Code == api.ToJSONRPCErrorCode(api.HandlerError) && @@ -459,7 +467,7 @@ func TestGatewayHandler_HandleGatewayMessage(t *testing.T) { { Id: &vaultcommon.SecretIdentifier{ Key: "test-secret", - Owner: "0xabc", + Owner: gwTestOwnerALower, }, EncryptedValue: "encrypted-value", }, diff --git a/core/capabilities/vault/validator.go b/core/capabilities/vault/validator.go index ca9b58a56c5..c710c707243 100644 --- a/core/capabilities/vault/validator.go +++ b/core/capabilities/vault/validator.go @@ -8,6 +8,7 @@ import ( "regexp" "strconv" + "github.com/ethereum/go-ethereum/common" "github.com/smartcontractkit/tdh2/go/tdh2/tdh2easy" vaultcommon "github.com/smartcontractkit/chainlink-common/pkg/capabilities/actions/vault" @@ -84,12 +85,12 @@ func (r *RequestValidator) validateWriteRequest(ctx context.Context, publicKey * return errors.New("Encrypted Secret at index [" + strconv.Itoa(idx) + "] doesn't have owner as the label. Error: " + err.Error()) } } - _, ok := uniqueIDs[vaulttypes.KeyFor(req.Id)] + _, ok := uniqueIDs[vaultutils.KeyFor(req.Id)] if ok { return errors.New("duplicate secret ID found at index " + strconv.Itoa(idx) + ": " + req.Id.String()) } - uniqueIDs[vaulttypes.KeyFor(req.Id)] = true + uniqueIDs[vaultutils.KeyFor(req.Id)] = true } return nil @@ -123,6 +124,9 @@ func (r *RequestValidator) ValidateSecretIdentifier(ctx context.Context, idKey s if !isValidIDComponent(idKey) || !isValidIDComponent(idOwner) || (idNamespace != "" && !isValidIDComponent(idNamespace)) { return errors.New("key, owner and namespace must only contain alphanumeric characters") } + if !common.IsHexAddress(idOwner) { + return errors.New("owner must be a valid Ethereum address") + } // TODO orgID https://smartcontract-it.atlassian.net/browse/CRE-1707 ctx = contexts.WithCRE(ctx, contexts.CRE{Owner: idOwner}) @@ -180,7 +184,7 @@ func (r *RequestValidator) ValidateListSecretIdentifiersRequest(ctx context.Cont if request.RequestId == "" || request.Owner == "" { return errors.New("requestID or owner must not be empty") } - if err := r.ValidateSecretIdentifier(ctx, request.Owner, request.Owner, request.Namespace); err != nil { + if err := r.ValidateSecretIdentifier(ctx, "_", request.Owner, request.Namespace); err != nil { return fmt.Errorf("invalid secret identifier: %w", err) } return nil @@ -203,12 +207,12 @@ func (r *RequestValidator) ValidateDeleteSecretsRequest(ctx context.Context, req return fmt.Errorf("invalid secret identifier at index %d: %w", idx, err) } - _, ok := uniqueIDs[vaulttypes.KeyFor(id)] + _, ok := uniqueIDs[vaultutils.KeyFor(id)] if ok { return errors.New("duplicate secret ID found at index " + strconv.Itoa(idx) + ": " + id.String()) } - uniqueIDs[vaulttypes.KeyFor(id)] = true + uniqueIDs[vaultutils.KeyFor(id)] = true } return nil } diff --git a/core/capabilities/vault/validator_test.go b/core/capabilities/vault/validator_test.go index d80d59890e1..20b87208aaf 100644 --- a/core/capabilities/vault/validator_test.go +++ b/core/capabilities/vault/validator_test.go @@ -16,6 +16,9 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/capabilities/vault/vaultutils" ) +const testWorkflowOwner = "0x0001020304050607080900010203040506070809" +const testWorkflowOwnerAlt = "0x1111111111111111111111111111111111111111" + func generateTestKeys(t *testing.T) (*tdh2easy.PublicKey, []*tdh2easy.PrivateShare) { t.Helper() _, pk, shares, err := tdh2easy.GenerateKeys(1, 3) @@ -335,10 +338,25 @@ func TestRequestValidator_ValidateCreateSecretsRequest_FallsBackToSecretOwnerFor require.NoError(t, err) } +func TestValidateSecretIdentifier_RejectsNonAddressOwner(t *testing.T) { + t.Parallel() + validator := NewRequestValidator( + limits.NewUpperBoundLimiter(100), + limits.NewUpperBoundLimiter(1024*pkgconfig.Byte), + limits.NewUpperBoundLimiter(64*pkgconfig.Byte), + limits.NewUpperBoundLimiter(64*pkgconfig.Byte), + limits.NewUpperBoundLimiter(64*pkgconfig.Byte), + ) + + err := validator.ValidateSecretIdentifier(t.Context(), "mykey", "owner1", "main") + require.Error(t, err) + require.ErrorContains(t, err, "owner must be a valid Ethereum address") +} + func TestValidateSecretIdentifier(t *testing.T) { const ( keyLimit = 10 * pkgconfig.Byte - ownerLimit = 10 * pkgconfig.Byte + ownerLimit = 64 * pkgconfig.Byte nsLimit = 10 * pkgconfig.Byte ) validator := NewRequestValidator( @@ -359,19 +377,19 @@ func TestValidateSecretIdentifier(t *testing.T) { { name: "valid identifier", key: "mykey", - owner: "owner1", + owner: testWorkflowOwner, namespace: "main", }, { name: "empty namespace is allowed", key: "mykey", - owner: "owner1", + owner: testWorkflowOwner, namespace: "", }, { name: "empty key", key: "", - owner: "owner1", + owner: testWorkflowOwner, namespace: "main", errSubstr: "key cannot be empty", }, @@ -385,14 +403,14 @@ func TestValidateSecretIdentifier(t *testing.T) { { name: "invalid chars in key", key: "key-invalid", - owner: "owner1", + owner: testWorkflowOwner, namespace: "main", errSubstr: "must only contain alphanumeric characters", }, { name: "invalid chars in namespace", key: "mykey", - owner: "owner1", + owner: testWorkflowOwner, namespace: "bad.ns", errSubstr: "must only contain alphanumeric characters", }, @@ -406,39 +424,26 @@ func TestValidateSecretIdentifier(t *testing.T) { { name: "key at limit", key: "tenbytekey", // exactly 10 bytes - owner: "owner1", + owner: testWorkflowOwner, namespace: "main", }, { name: "key exceeds limit", key: "tenbytekey1", // 11 bytes - owner: "owner1", + owner: testWorkflowOwner, namespace: "main", errSubstr: "key exceeds maximum length", }, - { - name: "owner at limit", - key: "mykey", - owner: "owner12345", // exactly 10 bytes - namespace: "main", - }, - { - name: "owner exceeds limit", - key: "mykey", - owner: "owner123456", // 11 bytes - namespace: "main", - errSubstr: "owner exceeds maximum length", - }, { name: "namespace at limit", key: "mykey", - owner: "owner1", + owner: testWorkflowOwner, namespace: "tenbytekey", // exactly 10 bytes }, { name: "namespace exceeds limit", key: "mykey", - owner: "owner1", + owner: testWorkflowOwner, namespace: "tenbytekey1", // 11 bytes errSubstr: "namespace exceeds maximum length", }, @@ -457,10 +462,23 @@ func TestValidateSecretIdentifier(t *testing.T) { } } +func TestValidateSecretIdentifier_OwnerExceedsLengthLimit(t *testing.T) { + validator := NewRequestValidator( + limits.NewUpperBoundLimiter(100), + limits.NewUpperBoundLimiter(1024*pkgconfig.Byte), + limits.NewUpperBoundLimiter(64*pkgconfig.Byte), + limits.NewUpperBoundLimiter(41*pkgconfig.Byte), + limits.NewUpperBoundLimiter(64*pkgconfig.Byte), + ) + err := validator.ValidateSecretIdentifier(t.Context(), "mykey", testWorkflowOwner, "main") + require.Error(t, err) + require.ErrorContains(t, err, "owner exceeds maximum length") +} + func TestValidateSecretIdentifier_OwnerSpecificKeyLimit(t *testing.T) { const ( defaultKeyLimit = 5 * pkgconfig.Byte - privilegedOwner = "privilegedowner" + privilegedOwner = testWorkflowOwnerAlt privilegedLimit = 20 * pkgconfig.Byte ) @@ -469,7 +487,7 @@ func TestValidateSecretIdentifier_OwnerSpecificKeyLimit(t *testing.T) { limits.NewUpperBoundLimiter(1024*pkgconfig.Byte), &ownerOverrideLimiter{ defaultBound: defaultKeyLimit, - overrides: map[string]pkgconfig.Size{privilegedOwner: privilegedLimit}, + overrides: map[string]pkgconfig.Size{normalizeOwner(privilegedOwner): privilegedLimit}, }, limits.NewUpperBoundLimiter(64*pkgconfig.Byte), limits.NewUpperBoundLimiter(64*pkgconfig.Byte), @@ -478,7 +496,7 @@ func TestValidateSecretIdentifier_OwnerSpecificKeyLimit(t *testing.T) { longKey := "averylongkeyname" // 16 bytes: exceeds default (5) but within privileged (20) // Regular owner cannot use the long key - err := validator.ValidateSecretIdentifier(t.Context(), longKey, "owner1", "main") + err := validator.ValidateSecretIdentifier(t.Context(), longKey, testWorkflowOwner, "main") require.Error(t, err) require.ErrorContains(t, err, "key exceeds maximum length") @@ -490,7 +508,7 @@ func TestValidateSecretIdentifier_OwnerSpecificKeyLimit(t *testing.T) { func TestRequestValidator_IdentifierLengths(t *testing.T) { const ( keyLimit = 5 * pkgconfig.Byte - ownerLimit = 6 * pkgconfig.Byte + ownerLimit = 64 * pkgconfig.Byte nsLimit = 4 * pkgconfig.Byte ) validator := NewRequestValidator( @@ -528,35 +546,28 @@ func TestRequestValidator_IdentifierLengths(t *testing.T) { }{ { name: "all fields at limit", - key: "abcde", // 5 bytes - owner: "owner1", // 6 bytes - namespace: "main", // 4 bytes + key: "abcde", // 5 bytes + owner: testWorkflowOwner, + namespace: "main", // 4 bytes }, { name: "key exceeds limit", key: "abcdef", // 6 bytes - owner: "owner1", + owner: testWorkflowOwner, namespace: "main", errSubstr: "key exceeds maximum length", }, - { - name: "owner exceeds limit", - key: "mykey", - owner: "owner12", // 7 bytes - namespace: "main", - errSubstr: "owner exceeds maximum length", - }, { name: "namespace exceeds limit", key: "mykey", - owner: "owner1", + owner: testWorkflowOwner, namespace: "mains", // 5 bytes errSubstr: "namespace exceeds maximum length", }, { name: "invalid chars in key", key: "key-1", - owner: "owner1", + owner: testWorkflowOwner, namespace: "main", errSubstr: "must only contain alphanumeric characters", }, @@ -596,14 +607,14 @@ func TestValidateGetSecretsRequest(t *testing.T) { { name: "valid single request", requests: []*vaultcommon.SecretRequest{ - {Id: validID("mykey", "owner1", "main")}, + {Id: validID("mykey", testWorkflowOwner, "main")}, }, }, { name: "valid multiple requests", requests: []*vaultcommon.SecretRequest{ - {Id: validID("key1", "owner1", "main")}, - {Id: validID("key2", "owner2", "main")}, + {Id: validID("key1", testWorkflowOwner, "main")}, + {Id: validID("key2", testWorkflowOwnerAlt, "main")}, }, }, { @@ -616,7 +627,7 @@ func TestValidateGetSecretsRequest(t *testing.T) { requests: func() []*vaultcommon.SecretRequest { reqs := make([]*vaultcommon.SecretRequest, 9) // MaxBatchSize-1 = 9 for i := range reqs { - reqs[i] = &vaultcommon.SecretRequest{Id: validID(fmt.Sprintf("key%d", i), "owner1", "main")} + reqs[i] = &vaultcommon.SecretRequest{Id: validID(fmt.Sprintf("key%d", i), testWorkflowOwner, "main")} } return reqs }(), @@ -626,7 +637,7 @@ func TestValidateGetSecretsRequest(t *testing.T) { requests: func() []*vaultcommon.SecretRequest { reqs := make([]*vaultcommon.SecretRequest, 10) // MaxBatchSize = 10 for i := range reqs { - reqs[i] = &vaultcommon.SecretRequest{Id: validID(fmt.Sprintf("key%d", i), "owner1", "main")} + reqs[i] = &vaultcommon.SecretRequest{Id: validID(fmt.Sprintf("key%d", i), testWorkflowOwner, "main")} } return reqs }(), @@ -642,21 +653,21 @@ func TestValidateGetSecretsRequest(t *testing.T) { { name: "empty key", requests: []*vaultcommon.SecretRequest{ - {Id: validID("", "owner1", "main")}, + {Id: validID("", testWorkflowOwner, "main")}, }, errSubstr: "secret ID must have key set at index", }, { name: "key with invalid characters (hyphen) is rejected", requests: []*vaultcommon.SecretRequest{ - {Id: validID("key-invalid", "owner1", "main")}, + {Id: validID("key-invalid", testWorkflowOwner, "main")}, }, errSubstr: "must only contain alphanumeric characters", }, { name: "key with invalid characters (slash) is rejected", requests: []*vaultcommon.SecretRequest{ - {Id: validID("key/name", "owner1", "main")}, + {Id: validID("key/name", testWorkflowOwner, "main")}, }, errSubstr: "must only contain alphanumeric characters", }, @@ -670,22 +681,22 @@ func TestValidateGetSecretsRequest(t *testing.T) { { name: "invalid chars in namespace", requests: []*vaultcommon.SecretRequest{ - {Id: validID("key1", "owner1", "bad.ns")}, + {Id: validID("key1", testWorkflowOwner, "bad.ns")}, }, errSubstr: "invalid secret identifier at index 0", }, { name: "invalid identifier at second index", requests: []*vaultcommon.SecretRequest{ - {Id: validID("key1", "owner1", "main")}, - {Id: validID("key-bad", "owner1", "main")}, + {Id: validID("key1", testWorkflowOwner, "main")}, + {Id: validID("key-bad", testWorkflowOwner, "main")}, }, errSubstr: "invalid secret identifier at index 1", }, { name: "empty owner at second index", requests: []*vaultcommon.SecretRequest{ - {Id: validID("key1", "owner1", "main")}, + {Id: validID("key1", testWorkflowOwner, "main")}, {Id: validID("key2", "", "main")}, }, errSubstr: "invalid secret identifier at index 1", @@ -693,7 +704,7 @@ func TestValidateGetSecretsRequest(t *testing.T) { { name: "nil id at second index", requests: []*vaultcommon.SecretRequest{ - {Id: validID("key1", "owner1", "main")}, + {Id: validID("key1", testWorkflowOwner, "main")}, {Id: nil}, }, errSubstr: "secret ID must have id set at index 1", @@ -701,15 +712,15 @@ func TestValidateGetSecretsRequest(t *testing.T) { { name: "empty key at second index", requests: []*vaultcommon.SecretRequest{ - {Id: validID("key1", "owner1", "main")}, - {Id: validID("", "owner1", "main")}, + {Id: validID("key1", testWorkflowOwner, "main")}, + {Id: validID("", testWorkflowOwner, "main")}, }, errSubstr: "secret ID must have key set at index 1", }, { name: "empty namespace accepted", requests: []*vaultcommon.SecretRequest{ - {Id: validID("mykey", "owner1", "")}, + {Id: validID("mykey", testWorkflowOwner, "")}, }, }, } @@ -728,7 +739,7 @@ func TestValidateGetSecretsRequest(t *testing.T) { } func TestValidateGetSecretsRequest_OwnerLengthPerBatchItem(t *testing.T) { - const ownerLimit = 6 * pkgconfig.Byte + const ownerLimit = 41 * pkgconfig.Byte // valid workflow owners are 42 bytes with 0x prefix validator := NewRequestValidator( limits.NewUpperBoundLimiter(10), limits.NewUpperBoundLimiter(1024*pkgconfig.Byte), @@ -737,15 +748,14 @@ func TestValidateGetSecretsRequest_OwnerLengthPerBatchItem(t *testing.T) { limits.NewUpperBoundLimiter(64*pkgconfig.Byte), ) - // First item is within the owner length limit; second item exceeds it. err := validator.ValidateGetSecretsRequest(t.Context(), &vaultcommon.GetSecretsRequest{ Requests: []*vaultcommon.SecretRequest{ - {Id: &vaultcommon.SecretIdentifier{Key: "mykey", Owner: "owner1", Namespace: "main"}}, // 6 bytes - {Id: &vaultcommon.SecretIdentifier{Key: "mykey", Owner: "owner12", Namespace: "main"}}, // 7 bytes + {Id: &vaultcommon.SecretIdentifier{Key: "mykey", Owner: testWorkflowOwner, Namespace: "main"}}, + {Id: &vaultcommon.SecretIdentifier{Key: "mykey", Owner: testWorkflowOwnerAlt, Namespace: "main"}}, }, }) require.Error(t, err) - require.ErrorContains(t, err, "invalid secret identifier at index 1") + require.ErrorContains(t, err, "invalid secret identifier at index 0") require.ErrorContains(t, err, "owner exceeds maximum length") } @@ -762,8 +772,8 @@ func TestValidateGetSecretsRequest_KeyLengthPerBatchItem(t *testing.T) { // First item is within the key length limit; second item exceeds it. err := validator.ValidateGetSecretsRequest(t.Context(), &vaultcommon.GetSecretsRequest{ Requests: []*vaultcommon.SecretRequest{ - {Id: &vaultcommon.SecretIdentifier{Key: "abcde", Owner: "owner1", Namespace: "main"}}, // 5 bytes - {Id: &vaultcommon.SecretIdentifier{Key: "abcdef", Owner: "owner1", Namespace: "main"}}, // 6 bytes + {Id: &vaultcommon.SecretIdentifier{Key: "abcde", Owner: testWorkflowOwner, Namespace: "main"}}, // 5 bytes + {Id: &vaultcommon.SecretIdentifier{Key: "abcdef", Owner: testWorkflowOwner, Namespace: "main"}}, // 6 bytes }, }) require.Error(t, err) @@ -774,7 +784,7 @@ func TestValidateGetSecretsRequest_KeyLengthPerBatchItem(t *testing.T) { func TestValidateGetSecretsRequest_OwnerSpecificKeyLimit(t *testing.T) { const ( defaultKeyLimit = 5 * pkgconfig.Byte - privilegedOwner = "privilegedowner" + privilegedOwner = testWorkflowOwnerAlt privilegedLimit = 20 * pkgconfig.Byte ) @@ -783,7 +793,7 @@ func TestValidateGetSecretsRequest_OwnerSpecificKeyLimit(t *testing.T) { limits.NewUpperBoundLimiter(1024*pkgconfig.Byte), &ownerOverrideLimiter{ defaultBound: defaultKeyLimit, - overrides: map[string]pkgconfig.Size{privilegedOwner: privilegedLimit}, + overrides: map[string]pkgconfig.Size{normalizeOwner(privilegedOwner): privilegedLimit}, }, limits.NewUpperBoundLimiter(64*pkgconfig.Byte), limits.NewUpperBoundLimiter(64*pkgconfig.Byte), @@ -800,7 +810,7 @@ func TestValidateGetSecretsRequest_OwnerSpecificKeyLimit(t *testing.T) { } // Regular owner is rejected because the key exceeds their limit - err := validator.ValidateGetSecretsRequest(t.Context(), makeRequest(longKey, "regularowner")) + err := validator.ValidateGetSecretsRequest(t.Context(), makeRequest(longKey, testWorkflowOwner)) require.Error(t, err) require.ErrorContains(t, err, "key exceeds maximum length") @@ -812,7 +822,7 @@ func TestValidateGetSecretsRequest_OwnerSpecificKeyLimit(t *testing.T) { func TestValidateGetSecretsRequest_OwnerSpecificNamespaceLimit(t *testing.T) { const ( defaultNsLimit = 5 * pkgconfig.Byte - privilegedOwner = "privilegedowner" + privilegedOwner = testWorkflowOwnerAlt privilegedLimit = 20 * pkgconfig.Byte ) @@ -823,7 +833,7 @@ func TestValidateGetSecretsRequest_OwnerSpecificNamespaceLimit(t *testing.T) { limits.NewUpperBoundLimiter(64*pkgconfig.Byte), &ownerOverrideLimiter{ defaultBound: defaultNsLimit, - overrides: map[string]pkgconfig.Size{privilegedOwner: privilegedLimit}, + overrides: map[string]pkgconfig.Size{normalizeOwner(privilegedOwner): privilegedLimit}, }, ) @@ -838,7 +848,7 @@ func TestValidateGetSecretsRequest_OwnerSpecificNamespaceLimit(t *testing.T) { } // Regular owner is rejected because the namespace exceeds their limit - err := validator.ValidateGetSecretsRequest(t.Context(), makeRequest(longNamespace, "regularowner")) + err := validator.ValidateGetSecretsRequest(t.Context(), makeRequest(longNamespace, testWorkflowOwner)) require.Error(t, err) require.ErrorContains(t, err, "namespace exceeds maximum length") @@ -850,7 +860,7 @@ func TestValidateGetSecretsRequest_OwnerSpecificNamespaceLimit(t *testing.T) { func TestRequestValidator_OwnerSpecificCiphertextLimit(t *testing.T) { const ( defaultLimit = 10 * pkgconfig.Byte - privilegedOwner = "privilegedowner" + privilegedOwner = testWorkflowOwnerAlt privilegedLimit = 20 * pkgconfig.Byte ) @@ -858,7 +868,7 @@ func TestRequestValidator_OwnerSpecificCiphertextLimit(t *testing.T) { limits.NewUpperBoundLimiter(100), &ownerOverrideLimiter{ defaultBound: defaultLimit, - overrides: map[string]pkgconfig.Size{privilegedOwner: privilegedLimit}, + overrides: map[string]pkgconfig.Size{normalizeOwner(privilegedOwner): privilegedLimit}, }, limits.NewUpperBoundLimiter(64*pkgconfig.Byte), limits.NewUpperBoundLimiter(64*pkgconfig.Byte), @@ -885,7 +895,7 @@ func TestRequestValidator_OwnerSpecificCiphertextLimit(t *testing.T) { } // Regular owner is rejected because 15 bytes exceeds their 10-byte limit - err := validator.ValidateCreateSecretsRequest(t.Context(), nil, makeRequest("req-1", "regularowner"), false) + err := validator.ValidateCreateSecretsRequest(t.Context(), nil, makeRequest("req-1", testWorkflowOwner), false) require.Error(t, err) require.ErrorContains(t, err, "ciphertext size exceeds maximum allowed size") @@ -939,7 +949,7 @@ func TestRequestValidator_PreservesEmptyNamespaceOnStructs(t *testing.T) { ) t.Run("GetSecretsRequest", func(t *testing.T) { - id := &vaultcommon.SecretIdentifier{Key: "k", Owner: "owner1", Namespace: ""} + id := &vaultcommon.SecretIdentifier{Key: "k", Owner: testWorkflowOwner, Namespace: ""} req := &vaultcommon.GetSecretsRequest{Requests: []*vaultcommon.SecretRequest{{Id: id}}} require.NoError(t, validator.ValidateGetSecretsRequest(t.Context(), req)) assert.Empty(t, id.Namespace) @@ -959,14 +969,14 @@ func TestRequestValidator_PreservesEmptyNamespaceOnStructs(t *testing.T) { }) t.Run("DeleteSecretsRequest", func(t *testing.T) { - id := &vaultcommon.SecretIdentifier{Key: "k", Owner: "owner1", Namespace: ""} + id := &vaultcommon.SecretIdentifier{Key: "k", Owner: testWorkflowOwner, Namespace: ""} req := &vaultcommon.DeleteSecretsRequest{RequestId: "rid", Ids: []*vaultcommon.SecretIdentifier{id}} require.NoError(t, validator.ValidateDeleteSecretsRequest(t.Context(), req)) assert.Empty(t, id.Namespace) }) t.Run("ListSecretIdentifiersRequest", func(t *testing.T) { - req := &vaultcommon.ListSecretIdentifiersRequest{RequestId: "rid", Owner: "owner1", Namespace: ""} + req := &vaultcommon.ListSecretIdentifiersRequest{RequestId: "rid", Owner: testWorkflowOwner, Namespace: ""} require.NoError(t, validator.ValidateListSecretIdentifiersRequest(t.Context(), req)) assert.Empty(t, req.Namespace) }) diff --git a/core/capabilities/vault/vaulttypes/types.go b/core/capabilities/vault/vaulttypes/types.go index 2f3d43fa02b..ce778e6f6c0 100644 --- a/core/capabilities/vault/vaulttypes/types.go +++ b/core/capabilities/vault/vaulttypes/types.go @@ -2,17 +2,12 @@ package vaulttypes import ( "context" - "encoding/binary" "encoding/json" "fmt" "time" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/crypto" - ocr2types "github.com/smartcontractkit/libocr/offchainreporting2plus/types" "google.golang.org/protobuf/proto" - "github.com/smartcontractkit/chainlink-common/keystore/corekeys/ocr2key" vaultcommon "github.com/smartcontractkit/chainlink-common/pkg/capabilities/actions/vault" ) @@ -68,19 +63,6 @@ type SecretsService interface { GetPublicKey(ctx context.Context, request *vaultcommon.GetPublicKeyRequest) (*vaultcommon.GetPublicKeyResponse, error) } -// NormalizeNamespace returns DefaultNamespace when namespace is empty. -func NormalizeNamespace(namespace string) string { - if namespace == "" { - return DefaultNamespace - } - return namespace -} - -func KeyFor(id *vaultcommon.SecretIdentifier) string { - namespace := NormalizeNamespace(id.Namespace) - return fmt.Sprintf("%s::%s::%s", id.Owner, namespace, id.Key) -} - type Request struct { Payload proto.Message ResponseChan chan *Response @@ -151,59 +133,3 @@ func (r *Response) RequestID() string { func (r *Response) String() string { return fmt.Sprintf("Response { ID: %s, Error: %s, Payload: %s, Format: %s }", r.ID, r.Error, string(r.Payload), r.Format) } - -func ValidateSignatures(resp *SignedOCRResponse, allowedSigners []common.Address, minRequired int) error { - if len(resp.Context) < 64 { - return fmt.Errorf("context too short: expected min 64 bytes, got %d bytes", len(resp.Context)) - } - - if len(resp.Signatures) < minRequired { - return fmt.Errorf("not enough signatures: expected min %d, got %d", minRequired, len(resp.Signatures)) - } - - // The context contains: - // 0:32 -> config digest - // 32:64 -> epoch + round, namely: - // - 0:27 -> zero padding - // - 27:31 -> sequence number (big endian uint32) - // - 31:32 -> zero round value - // 64:96 -> extra hash (not used by the vault plugin) - cd, epochRound := resp.Context[:32], resp.Context[32:64] - configDigest, err := ocr2types.BytesToConfigDigest(cd) - if err != nil { - return fmt.Errorf("invalid config digest in signature: %w", err) - } - - epoch := binary.BigEndian.Uint32(epochRound[27:31]) - round := epochRound[31] - - fullHash := ocr2key.ReportToSigData(ocr2types.ReportContext{ - ReportTimestamp: ocr2types.ReportTimestamp{ - ConfigDigest: configDigest, - Epoch: epoch, - Round: round, - }, - }, []byte(resp.Payload)) - - validSigners := map[common.Address]bool{} - for _, s := range resp.Signatures { - signerPubkey, err := crypto.SigToPub(fullHash, s) - if err != nil { - return fmt.Errorf("invalid signature: %w", err) - } - signerAddr := crypto.PubkeyToAddress(*signerPubkey) - - for _, as := range allowedSigners { - if as.Hex() == signerAddr.Hex() { - validSigners[signerAddr] = true - break - } - } - - if len(validSigners) >= minRequired { - return nil - } - } - - return fmt.Errorf("only %d valid signatures, need at least %d", len(validSigners), minRequired) -} diff --git a/core/capabilities/vault/vaulttypes/types_test.go b/core/capabilities/vault/vaulttypes/types_test.go deleted file mode 100644 index a281333c97a..00000000000 --- a/core/capabilities/vault/vaulttypes/types_test.go +++ /dev/null @@ -1,12 +0,0 @@ -package vaulttypes - -import ( - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestNormalizeNamespace(t *testing.T) { - assert.Equal(t, DefaultNamespace, NormalizeNamespace("")) - assert.Equal(t, "custom", NormalizeNamespace("custom")) -} diff --git a/core/capabilities/vault/vaultutils/identifier.go b/core/capabilities/vault/vaultutils/identifier.go new file mode 100644 index 00000000000..e26b9d2e825 --- /dev/null +++ b/core/capabilities/vault/vaultutils/identifier.go @@ -0,0 +1,46 @@ +package vaultutils + +import ( + "fmt" + + "github.com/ethereum/go-ethereum/common" + + vaultcommon "github.com/smartcontractkit/chainlink-common/pkg/capabilities/actions/vault" + "github.com/smartcontractkit/chainlink/v2/core/capabilities/vault/vaulttypes" +) + +// NormalizeNamespace returns DefaultNamespace when namespace is empty. +func NormalizeNamespace(namespace string) string { + if namespace == "" { + return vaulttypes.DefaultNamespace + } + return namespace +} + +// NormalizeWorkflowOwnerAddress canonicalizes a workflow owner to EIP-55 checksum form. +// This matches read paths (workflow secrets fetch, confidential relay) that look up +// secrets using common.HexToAddress(owner).Hex(). +func NormalizeWorkflowOwnerAddress(owner string) string { + return common.HexToAddress(owner).Hex() +} + +// KeyFor returns the storage key for a secret identifier. +func KeyFor(id *vaultcommon.SecretIdentifier) string { + namespace := NormalizeNamespace(id.Namespace) + owner := NormalizeWorkflowOwnerAddress(id.Owner) + return fmt.Sprintf("%s::%s::%s", owner, namespace, id.Key) +} + +// CanonicalSecretIdentifier returns a copy of id with namespace defaulting and owner +// normalized to EIP-55 checksum form for consistent storage keys and metadata. +func CanonicalSecretIdentifier(id *vaultcommon.SecretIdentifier) *vaultcommon.SecretIdentifier { + if id == nil { + return nil + } + namespace := NormalizeNamespace(id.Namespace) + return &vaultcommon.SecretIdentifier{ + Key: id.Key, + Owner: NormalizeWorkflowOwnerAddress(id.Owner), + Namespace: namespace, + } +} diff --git a/core/capabilities/vault/vaultutils/identifier_test.go b/core/capabilities/vault/vaultutils/identifier_test.go new file mode 100644 index 00000000000..de45e40ec4c --- /dev/null +++ b/core/capabilities/vault/vaultutils/identifier_test.go @@ -0,0 +1,32 @@ +package vaultutils + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + vaultcommon "github.com/smartcontractkit/chainlink-common/pkg/capabilities/actions/vault" + "github.com/smartcontractkit/chainlink/v2/core/capabilities/vault/vaulttypes" +) + +func TestNormalizeNamespace(t *testing.T) { + assert.Equal(t, vaulttypes.DefaultNamespace, NormalizeNamespace("")) + assert.Equal(t, "custom", NormalizeNamespace("custom")) +} + +func TestNormalizeWorkflowOwnerAddress(t *testing.T) { + t.Parallel() + checksummed := "0xAb5801a7D398351b8bE11C439e05C5B3259aeC9B" + require.Equal(t, checksummed, NormalizeWorkflowOwnerAddress("0xab5801a7d398351b8be11c439e05c5b3259aec9b")) +} + +func TestCanonicalSecretIdentifier(t *testing.T) { + t.Parallel() + checksummed := "0xAb5801a7D398351b8bE11C439e05C5B3259aeC9B" + id := CanonicalSecretIdentifier(&vaultcommon.SecretIdentifier{ + Key: "k", Owner: "0xab5801a7d398351b8be11c439e05c5b3259aec9b", Namespace: "", + }) + require.Equal(t, checksummed, id.Owner) + require.Equal(t, vaulttypes.DefaultNamespace, id.Namespace) +} diff --git a/core/capabilities/vault/vaultutils/signatures.go b/core/capabilities/vault/vaultutils/signatures.go new file mode 100644 index 00000000000..570a6a5c217 --- /dev/null +++ b/core/capabilities/vault/vaultutils/signatures.go @@ -0,0 +1,69 @@ +package vaultutils + +import ( + "encoding/binary" + "fmt" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/crypto" + ocr2types "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + + "github.com/smartcontractkit/chainlink-common/keystore/corekeys/ocr2key" + "github.com/smartcontractkit/chainlink/v2/core/capabilities/vault/vaulttypes" +) + +func ValidateSignatures(resp *vaulttypes.SignedOCRResponse, allowedSigners []common.Address, minRequired int) error { + if len(resp.Context) < 64 { + return fmt.Errorf("context too short: expected min 64 bytes, got %d bytes", len(resp.Context)) + } + + if len(resp.Signatures) < minRequired { + return fmt.Errorf("not enough signatures: expected min %d, got %d", minRequired, len(resp.Signatures)) + } + + // The context contains: + // 0:32 -> config digest + // 32:64 -> epoch + round, namely: + // - 0:27 -> zero padding + // - 27:31 -> sequence number (big endian uint32) + // - 31:32 -> zero round value + // 64:96 -> extra hash (not used by the vault plugin) + cd, epochRound := resp.Context[:32], resp.Context[32:64] + configDigest, err := ocr2types.BytesToConfigDigest(cd) + if err != nil { + return fmt.Errorf("invalid config digest in signature: %w", err) + } + + epoch := binary.BigEndian.Uint32(epochRound[27:31]) + round := epochRound[31] + + fullHash := ocr2key.ReportToSigData(ocr2types.ReportContext{ + ReportTimestamp: ocr2types.ReportTimestamp{ + ConfigDigest: configDigest, + Epoch: epoch, + Round: round, + }, + }, []byte(resp.Payload)) + + validSigners := map[common.Address]bool{} + for _, s := range resp.Signatures { + signerPubkey, err := crypto.SigToPub(fullHash, s) + if err != nil { + return fmt.Errorf("invalid signature: %w", err) + } + signerAddr := crypto.PubkeyToAddress(*signerPubkey) + + for _, as := range allowedSigners { + if as.Hex() == signerAddr.Hex() { + validSigners[signerAddr] = true + break + } + } + + if len(validSigners) >= minRequired { + return nil + } + } + + return fmt.Errorf("only %d valid signatures, need at least %d", len(validSigners), minRequired) +} diff --git a/core/capabilities/vault/models_test.go b/core/capabilities/vault/vaultutils/signatures_test.go similarity index 91% rename from core/capabilities/vault/models_test.go rename to core/capabilities/vault/vaultutils/signatures_test.go index 95dfea8c1db..38959524fba 100644 --- a/core/capabilities/vault/models_test.go +++ b/core/capabilities/vault/vaultutils/signatures_test.go @@ -1,4 +1,4 @@ -package vault +package vaultutils import ( "encoding/hex" @@ -10,7 +10,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/capabilities/vault/vaulttypes" ) -func Test_ValidateSignatures_Valid(t *testing.T) { +func TestValidateSignatures_Valid(t *testing.T) { ctx, err := hex.DecodeString("000ec4f6a2ba011e909eccf64628855b848e08876a1edd938a1372a9e51adff100000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000") require.NoError(t, err) sig1, err := hex.DecodeString("d1067844e2849b404d903730c4cae19f090d53a578a1e8dc16ecbdc0285c1f186599108abbe0073b78bc148a6504907474ed3a6881df917e6d142cff70acfb5900") @@ -34,11 +34,11 @@ func Test_ValidateSignatures_Valid(t *testing.T) { common.HexToAddress("0xefd5bdb6c3256f04489a6ca32654d547297f48b9"), } - err = vaulttypes.ValidateSignatures(&resp, allowedAddr, 1) + err = ValidateSignatures(&resp, allowedAddr, 1) require.NoError(t, err) } -func Test_ValidateSignatures_InsufficientSignatures(t *testing.T) { +func TestValidateSignatures_InsufficientSignatures(t *testing.T) { ctx, err := hex.DecodeString("000ec4f6a2ba011e909eccf64628855b848e08876a1edd938a1372a9e51adff100000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000") require.NoError(t, err) sig1, err := hex.DecodeString("d1067844e2849b404d903730c4cae19f090d53a578a1e8dc16ecbdc0285c1f186599108abbe0073b78bc148a6504907474ed3a6881df917e6d142cff70acfb5900") @@ -58,11 +58,11 @@ func Test_ValidateSignatures_InsufficientSignatures(t *testing.T) { common.HexToAddress("0xefd5bdb6c3256f04489a6ca32654d547297f48b9"), } - err = vaulttypes.ValidateSignatures(&resp, allowedAddr, 2) + err = ValidateSignatures(&resp, allowedAddr, 2) require.ErrorContains(t, err, "not enough signatures: expected min 2, got 1") } -func Test_ValidateSignatures_DoesntCountDuplicates(t *testing.T) { +func TestValidateSignatures_DoesntCountDuplicates(t *testing.T) { ctx, err := hex.DecodeString("000ec4f6a2ba011e909eccf64628855b848e08876a1edd938a1372a9e51adff100000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000") require.NoError(t, err) sig1, err := hex.DecodeString("d1067844e2849b404d903730c4cae19f090d53a578a1e8dc16ecbdc0285c1f186599108abbe0073b78bc148a6504907474ed3a6881df917e6d142cff70acfb5900") @@ -83,11 +83,11 @@ func Test_ValidateSignatures_DoesntCountDuplicates(t *testing.T) { common.HexToAddress("0xefd5bdb6c3256f04489a6ca32654d547297f48b9"), } - err = vaulttypes.ValidateSignatures(&resp, allowedAddr, 2) + err = ValidateSignatures(&resp, allowedAddr, 2) require.ErrorContains(t, err, "only 1 valid signatures, need at least 2") } -func Test_ValidateSignatures_InvalidSignature(t *testing.T) { +func TestValidateSignatures_InvalidSignature(t *testing.T) { ctx, err := hex.DecodeString("00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000") require.NoError(t, err) sig1, err := hex.DecodeString("d1067844e2849b404d903730c4cae19f090d53a578a1e8dc16ecbdc0285c1f186599108abbe0073b78bc148a6504907474ed3a6881df917e6d142cff70acfb5900") @@ -110,6 +110,6 @@ func Test_ValidateSignatures_InvalidSignature(t *testing.T) { common.HexToAddress("0xefd5bdb6c3256f04489a6ca32654d547297f48b9"), } - err = vaulttypes.ValidateSignatures(&resp, allowedAddr, 2) + err = ValidateSignatures(&resp, allowedAddr, 2) require.ErrorContains(t, err, "only 0 valid signatures, need at least 2") } diff --git a/core/services/gateway/handlers/vault/aggregator.go b/core/services/gateway/handlers/vault/aggregator.go index dd658f3ff48..66bc7b86b64 100644 --- a/core/services/gateway/handlers/vault/aggregator.go +++ b/core/services/gateway/handlers/vault/aggregator.go @@ -19,6 +19,7 @@ import ( jsonrpc "github.com/smartcontractkit/chainlink-common/pkg/jsonrpc2" "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink/v2/core/capabilities/vault/vaulttypes" + "github.com/smartcontractkit/chainlink/v2/core/capabilities/vault/vaultutils" ) type baseAggregator struct { @@ -230,7 +231,7 @@ func (a *baseAggregator) validateUsingSignatures(don capabilities.DON, nodes []c signers = append(signers, common.BytesToAddress(n.Signer[0:20])) } - err = vaulttypes.ValidateSignatures(r, signers, int(don.F+1)) + err = vaultutils.ValidateSignatures(r, signers, int(don.F+1)) if err != nil { return nil, fmt.Errorf("failed to validate signatures: %w", err) } diff --git a/core/services/gateway/handlers/vault/handler_test.go b/core/services/gateway/handlers/vault/handler_test.go index 1572214f868..4f01585fd8f 100644 --- a/core/services/gateway/handlers/vault/handler_test.go +++ b/core/services/gateway/handlers/vault/handler_test.go @@ -277,7 +277,7 @@ func TestVaultHandler_HandleJSONRPCUserMessage(t *testing.T) { donConfig, don, nil, - &stubAuthorizer{result: vaultcap.NewAuthResult("org-1", "0xworkflow", "digest-1", clock.Now().Add(time.Minute).Unix())}, + &stubAuthorizer{result: vaultcap.NewAuthResult("org-1", allowlistWorkflowOwner, "digest-1", clock.Now().Add(time.Minute).Unix())}, nil, lggr, clock, @@ -285,7 +285,7 @@ func TestVaultHandler_HandleJSONRPCUserMessage(t *testing.T) { ) require.NoError(t, err) - rawPayload := json.RawMessage(`{"request_id":"test_request_id","encrypted_secrets":[{"id":{"key":"test_id","owner":"0xworkflow","namespace":"default"},"encrypted_value":"abc123"}]}`) + rawPayload := json.RawMessage(`{"request_id":"test_request_id","encrypted_secrets":[{"id":{"key":"test_id","owner":"` + allowlistWorkflowOwner + `","namespace":"default"},"encrypted_value":"abc123"}]}`) var forwarded jsonrpc.Request[json.RawMessage] don.On("SendToNode", mock.Anything, mock.Anything, mock.Anything).Run(func(args mock.Arguments) { @@ -304,7 +304,7 @@ func TestVaultHandler_HandleJSONRPCUserMessage(t *testing.T) { require.NotNil(t, forwarded.Params) var forwardedCreateRequest vaultcommon.CreateSecretsRequest require.NoError(t, json.Unmarshal(*forwarded.Params, &forwardedCreateRequest)) - require.Equal(t, "0xworkflow"+vaulttypes.RequestIDSeparator+"1", forwardedCreateRequest.RequestId) + require.Equal(t, allowlistWorkflowOwner+vaulttypes.RequestIDSeparator+"1", forwardedCreateRequest.RequestId) }) t.Run("rejects create when ciphertext label does not match identifier owner", func(t *testing.T) { diff --git a/core/services/ocr2/plugins/vault/kvstore.go b/core/services/ocr2/plugins/vault/kvstore.go index 1e27d263d10..7b579d6c3d5 100644 --- a/core/services/ocr2/plugins/vault/kvstore.go +++ b/core/services/ocr2/plugins/vault/kvstore.go @@ -11,7 +11,7 @@ import ( "google.golang.org/protobuf/proto" "github.com/smartcontractkit/chainlink-common/pkg/capabilities/actions/vault" - "github.com/smartcontractkit/chainlink/v2/core/capabilities/vault/vaulttypes" + "github.com/smartcontractkit/chainlink/v2/core/capabilities/vault/vaultutils" ) const ( @@ -68,7 +68,7 @@ func (s *KVStore) GetSecret(ctx context.Context, id *vault.SecretIdentifier) (*v return nil, nil } - b, err := s.reader.Read([]byte(keyPrefix + vaulttypes.KeyFor(id))) + b, err := s.reader.Read([]byte(keyPrefix + vaultutils.KeyFor(id))) if err != nil { return nil, fmt.Errorf("failed to read secret: %w", err) } @@ -87,6 +87,7 @@ func (s *KVStore) GetSecret(ctx context.Context, id *vault.SecretIdentifier) (*v func (s *KVStore) GetMetadata(ctx context.Context, owner string) (*vault.StoredMetadata, error) { defer s.trackDuration(ctx, "GetMetadata", time.Now()) + owner = vaultutils.NormalizeWorkflowOwnerAddress(owner) b, err := s.reader.Read([]byte(metadataPrefix + owner)) if err != nil { return nil, fmt.Errorf("failed to read metadata: %w", err) @@ -123,6 +124,7 @@ func (s *KVStore) WriteMetadata(ctx context.Context, owner string, metadata *vau if metadata == nil { return errors.New("metadata cannot be nil") } + owner = vaultutils.NormalizeWorkflowOwnerAddress(owner) b, err := proto.Marshal(metadata) if err != nil { return fmt.Errorf("failed to marshal metadata: %w", err) @@ -150,7 +152,7 @@ func (s *KVStore) metadataContainsID(ctx context.Context, id *vault.SecretIdenti } for _, i := range md.SecretIdentifiers { - if vaulttypes.KeyFor(id) == vaulttypes.KeyFor(i) { + if vaultutils.KeyFor(id) == vaultutils.KeyFor(i) { return true, nil } } @@ -173,7 +175,7 @@ func (s *KVStore) addIDToMetadata(ctx context.Context, id *vault.SecretIdentifie } } else { for _, i := range md.SecretIdentifiers { - if vaulttypes.KeyFor(id) == vaulttypes.KeyFor(i) { + if vaultutils.KeyFor(id) == vaultutils.KeyFor(i) { // Nothing to do, early exit. return nil } @@ -206,7 +208,7 @@ func (s *KVStore) removeIDFromMetadata(ctx context.Context, id *vault.SecretIden si := []*vault.SecretIdentifier{} var found bool for _, i := range md.SecretIdentifiers { - if vaulttypes.KeyFor(id) == vaulttypes.KeyFor(i) { + if vaultutils.KeyFor(id) == vaultutils.KeyFor(i) { found = true } else { si = append(si, i) @@ -214,7 +216,7 @@ func (s *KVStore) removeIDFromMetadata(ctx context.Context, id *vault.SecretIden } if !found { - return fmt.Errorf("id %s not found in metadata for owner %s", vaulttypes.KeyFor(id), id.Owner) + return fmt.Errorf("id %s not found in metadata for owner %s", vaultutils.KeyFor(id), id.Owner) } newMd := &vault.StoredMetadata{ @@ -238,7 +240,7 @@ func (s *KVStore) WriteSecret(ctx context.Context, id *vault.SecretIdentifier, s return fmt.Errorf("failed to marshal secret: %w", err) } - err = s.writer.Write([]byte(keyPrefix+vaulttypes.KeyFor(id)), b) + err = s.writer.Write([]byte(keyPrefix+vaultutils.KeyFor(id)), b) if err != nil { return fmt.Errorf("failed to write secret: %w", err) } @@ -260,7 +262,7 @@ func (s *KVStore) DeleteSecret(ctx context.Context, id *vault.SecretIdentifier) return fmt.Errorf("failed to remove id from metadata: %w", err) } - err = s.writer.Delete([]byte(keyPrefix + vaulttypes.KeyFor(id))) + err = s.writer.Delete([]byte(keyPrefix + vaultutils.KeyFor(id))) if err != nil { return fmt.Errorf("failed to delete secret: %w", err) } diff --git a/core/services/ocr2/plugins/vault/kvstore_test.go b/core/services/ocr2/plugins/vault/kvstore_test.go index 391f4554e40..f2e1eb68ea1 100644 --- a/core/services/ocr2/plugins/vault/kvstore_test.go +++ b/core/services/ocr2/plugins/vault/kvstore_test.go @@ -14,8 +14,20 @@ import ( "google.golang.org/protobuf/types/known/emptypb" "github.com/smartcontractkit/chainlink-common/pkg/capabilities/actions/vault" + + "github.com/smartcontractkit/chainlink/v2/core/capabilities/vault/vaultutils" ) +const testKVOwner = "0x0000000000000000000000000000000000000001" + +func kvMetadataKey(owner string) string { + return metadataPrefix + vaultutils.NormalizeWorkflowOwnerAddress(owner) +} + +func kvSecretKey(id *vault.SecretIdentifier) string { + return keyPrefix + vaultutils.KeyFor(id) +} + func newTestMetrics(t *testing.T) *pluginMetrics { t.Helper() m, err := newPluginMetrics("test") @@ -104,13 +116,13 @@ func TestKVStore_Secrets(t *testing.T) { kv := &kv{ m: make(map[string]response), } - kv.m["Metadata::owner"] = response{ + kv.m[kvMetadataKey(testKVOwner)] = response{ err: errors.New("not found"), } store := newTestWriteStore(t, kv) id := &vault.SecretIdentifier{ - Owner: "owner", + Owner: testKVOwner, Namespace: "main", Key: "secret1", } @@ -122,21 +134,21 @@ func TestKVStore_Secrets(t *testing.T) { EncryptedSecret: []byte("encrypted data"), }) require.NoError(t, err) - kv.m["Key::owner::main::secret1"] = response{ + kv.m[kvSecretKey(id)] = response{ data: d, } d, err = proto.Marshal(&vault.StoredMetadata{ SecretIdentifiers: []*vault.SecretIdentifier{id}, }) require.NoError(t, err) - kv.m["Metadata::owner"] = response{ + kv.m[kvMetadataKey(testKVOwner)] = response{ data: d, } s, err := store.GetSecret(t.Context(), id) require.NoError(t, err) assert.Equal(t, s.EncryptedSecret, []byte("encrypted data")) - delete(kv.m, "Metadata::owner") + delete(kv.m, kvMetadataKey(testKVOwner)) s, err = store.GetSecret(t.Context(), id) assert.Nil(t, s) require.NoError(t, err) @@ -160,7 +172,7 @@ func TestKVStore_DeleteSecrets(t *testing.T) { store := newTestWriteStore(t, kv) id := &vault.SecretIdentifier{ - Owner: "owner", + Owner: testKVOwner, Namespace: "main", Key: "secret1", } @@ -172,18 +184,18 @@ func TestKVStore_DeleteSecrets(t *testing.T) { err = store.DeleteSecret(t.Context(), id) require.NoError(t, err) - md, err := store.GetMetadata(t.Context(), "owner") + md, err := store.GetMetadata(t.Context(), testKVOwner) require.NoError(t, err) assert.Empty(t, md.SecretIdentifiers) } func TestKVStore_Metadata(t *testing.T) { - owner := "owner" + owner := testKVOwner kv := &kv{ m: make(map[string]response), } - kv.m["Metadata::"+owner] = response{ + kv.m[kvMetadataKey(owner)] = response{ err: errors.New("not found"), } store := newTestWriteStore(t, kv) @@ -192,7 +204,7 @@ func TestKVStore_Metadata(t *testing.T) { require.ErrorContains(t, err, "not found") id := &vault.SecretIdentifier{ - Owner: "owner", + Owner: testKVOwner, Namespace: "main", Key: "secret1", } @@ -200,7 +212,7 @@ func TestKVStore_Metadata(t *testing.T) { SecretIdentifiers: []*vault.SecretIdentifier{id}, }) require.NoError(t, err) - kv.m["Metadata::owner"] = response{ + kv.m[kvMetadataKey(owner)] = response{ data: d, } m, err := store.GetMetadata(t.Context(), owner) @@ -208,7 +220,7 @@ func TestKVStore_Metadata(t *testing.T) { assert.Len(t, m.SecretIdentifiers, 1) assert.True(t, proto.Equal(m.SecretIdentifiers[0], id)) - delete(kv.m, "Metadata::"+owner) + delete(kv.m, kvMetadataKey(owner)) m, err = store.GetMetadata(t.Context(), owner) assert.Nil(t, m) require.NoError(t, err) @@ -216,12 +228,12 @@ func TestKVStore_Metadata(t *testing.T) { m = &vault.StoredMetadata{ SecretIdentifiers: []*vault.SecretIdentifier{ { - Owner: "owner", + Owner: testKVOwner, Namespace: "main", Key: "secret2", }, { - Owner: "owner", + Owner: testKVOwner, Namespace: "main", Key: "secret3", }, @@ -235,7 +247,7 @@ func TestKVStore_Metadata(t *testing.T) { assert.True(t, proto.Equal(m, gotM)) newKey := &vault.SecretIdentifier{ - Owner: "owner", + Owner: testKVOwner, Namespace: "main", Key: "secret3", } @@ -248,14 +260,14 @@ func TestKVStore_Metadata(t *testing.T) { } func TestKVStore_Metadata_Delete(t *testing.T) { - owner := "owner" + owner := testKVOwner kv := &kv{ m: make(map[string]response), } store := newTestWriteStore(t, kv) id := &vault.SecretIdentifier{ - Owner: "owner", + Owner: testKVOwner, Namespace: "main", Key: "secret1", } @@ -263,7 +275,7 @@ func TestKVStore_Metadata_Delete(t *testing.T) { SecretIdentifiers: []*vault.SecretIdentifier{id}, }) require.NoError(t, err) - kv.m["Metadata::owner"] = response{ + kv.m[kvMetadataKey(owner)] = response{ data: d, } @@ -276,12 +288,12 @@ func TestKVStore_Metadata_Delete(t *testing.T) { assert.Empty(t, m.SecretIdentifiers) err = store.removeIDFromMetadata(t.Context(), id) - require.ErrorContains(t, err, "not found in metadata for owner owner") + require.ErrorContains(t, err, "not found in metadata for owner "+testKVOwner) - delete(kv.m, "Metadata::owner") + delete(kv.m, kvMetadataKey(owner)) err = store.removeIDFromMetadata(t.Context(), id) - require.ErrorContains(t, err, "no metadata found for owner owner") + require.ErrorContains(t, err, "no metadata found for owner "+testKVOwner) } func TestKVStore_InconsistentWrites(t *testing.T) { @@ -291,7 +303,7 @@ func TestKVStore_InconsistentWrites(t *testing.T) { store := newTestWriteStore(t, kv) id := &vault.SecretIdentifier{ - Owner: "owner", + Owner: testKVOwner, Namespace: "main", Key: "secret1", } @@ -300,14 +312,14 @@ func TestKVStore_InconsistentWrites(t *testing.T) { EncryptedSecret: []byte("encrypted data"), }) require.NoError(t, err) - kv.m["Key::owner::main::secret1"] = response{ + kv.m[kvSecretKey(id)] = response{ data: d, } d, err = proto.Marshal(&vault.StoredMetadata{ SecretIdentifiers: []*vault.SecretIdentifier{id}, }) require.NoError(t, err) - kv.m["Metadata::owner"] = response{ + kv.m[kvMetadataKey(testKVOwner)] = response{ data: d, } s, err := store.GetSecret(t.Context(), id) @@ -316,7 +328,7 @@ func TestKVStore_InconsistentWrites(t *testing.T) { // Simulate a delete which was inconsistent; // we deleted the metadata record but not the secret iteslf. - delete(kv.m, "Metadata::owner") + delete(kv.m, kvMetadataKey(testKVOwner)) // Now fetching the secret should fail s, err = store.GetSecret(t.Context(), id) @@ -329,7 +341,7 @@ func TestKVStore_InconsistentWrites(t *testing.T) { }) require.NoError(t, err) - md, err := store.GetMetadata(t.Context(), "owner") + md, err := store.GetMetadata(t.Context(), testKVOwner) require.NoError(t, err) assert.Len(t, md.SecretIdentifiers, 1) diff --git a/core/services/ocr2/plugins/vault/plugin.go b/core/services/ocr2/plugins/vault/plugin.go index 25371012c76..563403399a9 100644 --- a/core/services/ocr2/plugins/vault/plugin.go +++ b/core/services/ocr2/plugins/vault/plugin.go @@ -1008,7 +1008,7 @@ func (r *ReportingPlugin) observeCreateSecrets(ctx context.Context, reader ReadK if sr.Id == nil { key = "" } else { - key = vaulttypes.KeyFor(sr.Id) + key = vaultutils.KeyFor(sr.Id) } requestsCountForID[key]++ } @@ -1049,8 +1049,8 @@ func (r *ReportingPlugin) observeCreateSecretRequest(ctx context.Context, _ Read return id, err } - if requestsCountForID[vaulttypes.KeyFor(secretRequest.Id)] > 1 { - return id, newUserError("duplicate request for secret identifier " + vaulttypes.KeyFor(id)) + if requestsCountForID[vaultutils.KeyFor(secretRequest.Id)] > 1 { + return id, newUserError("duplicate request for secret identifier " + vaultutils.KeyFor(id)) } if ierr := r.validator.ValidateCiphertextSize(ctx, secretRequest.Id.Owner, secretRequest.EncryptedValue); ierr != nil { @@ -1087,7 +1087,7 @@ func (r *ReportingPlugin) observeUpdateSecrets(ctx context.Context, reader ReadK if sr.Id == nil { key = "" } else { - key = vaulttypes.KeyFor(sr.Id) + key = vaultutils.KeyFor(sr.Id) } requestsCountForID[key]++ } @@ -1213,7 +1213,7 @@ func (r *ReportingPlugin) observeDeleteSecrets(ctx context.Context, reader ReadK if sr == nil { key = "" } else { - key = vaulttypes.KeyFor(sr) + key = vaultutils.KeyFor(sr) } requestsCountForID[key]++ } @@ -1254,8 +1254,8 @@ func (r *ReportingPlugin) observeDeleteSecretRequest(ctx context.Context, reader return id, err } - if requestsCountForID[vaulttypes.KeyFor(identifier)] > 1 { - return id, newUserError("duplicate request for secret identifier " + vaulttypes.KeyFor(id)) + if requestsCountForID[vaultutils.KeyFor(identifier)] > 1 { + return id, newUserError("duplicate request for secret identifier " + vaultutils.KeyFor(id)) } ss, err := reader.GetSecret(ctx, id) @@ -1284,13 +1284,11 @@ func (r *ReportingPlugin) validateSecretIdentifier(ctx context.Context, id *vaul return nil, newUserError(err.Error()) } - newID := &vaultcommon.SecretIdentifier{ + return vaultutils.CanonicalSecretIdentifier(&vaultcommon.SecretIdentifier{ Key: id.Key, Owner: id.Owner, Namespace: namespace, - } - - return newID, nil + }), nil } func newUserError(msg string) *userError { @@ -1508,7 +1506,7 @@ func (r *ReportingPlugin) validateGetSecretsObservation(ctx context.Context, o * if err := r.validator.ValidateSecretIdentifier(ctx, secretResponse.Id.Key, secretResponse.Id.Owner, secretResponse.Id.Namespace); err != nil { return fmt.Errorf("GetSecrets response contains invalid secret identifier: %w", err) } - key := vaulttypes.KeyFor(secretResponse.Id) + key := vaultutils.KeyFor(secretResponse.Id) if _, ok := respMap[key]; ok { return fmt.Errorf("duplicate response found for item %s", key) } @@ -1568,12 +1566,12 @@ func (r *ReportingPlugin) validateCreateSecretsObservation(ctx context.Context, if err := r.validator.ValidateSecretIdentifier(ctx, s.Id.Key, s.Id.Owner, s.Id.Namespace); err != nil { return fmt.Errorf("CreateSecrets request contains invalid secret identifier: %w", err) } - _, ok := idSet[vaulttypes.KeyFor(s.Id)] + _, ok := idSet[vaultutils.KeyFor(s.Id)] if ok { return fmt.Errorf("CreateSecrets requests cannot contain duplicate request for a given secret identifier: %s", s.Id) } - idSet[vaulttypes.KeyFor(s.Id)] = true + idSet[vaultutils.KeyFor(s.Id)] = true if err := r.validator.ValidateCiphertextSize(ctx, s.Id.Owner, s.EncryptedValue); err != nil { return fmt.Errorf("CreateSecrets request: %w", err) @@ -1612,12 +1610,12 @@ func (r *ReportingPlugin) validateUpdateSecretsObservation(ctx context.Context, if err := r.validator.ValidateSecretIdentifier(ctx, s.Id.Key, s.Id.Owner, s.Id.Namespace); err != nil { return fmt.Errorf("UpdateSecrets request contains invalid secret identifier: %w", err) } - _, ok := idSet[vaulttypes.KeyFor(s.Id)] + _, ok := idSet[vaultutils.KeyFor(s.Id)] if ok { return fmt.Errorf("UpdateSecrets requests cannot contain duplicate request for a given secret identifier: %s", s.Id) } - idSet[vaulttypes.KeyFor(s.Id)] = true + idSet[vaultutils.KeyFor(s.Id)] = true if err := r.validator.ValidateCiphertextSize(ctx, s.Id.Owner, s.EncryptedValue); err != nil { return fmt.Errorf("UpdateSecrets request: %w", err) @@ -1656,12 +1654,12 @@ func (r *ReportingPlugin) validateDeleteSecretsObservation(ctx context.Context, if err := r.validator.ValidateSecretIdentifier(ctx, id.Key, id.Owner, id.Namespace); err != nil { return fmt.Errorf("DeleteSecrets request contains invalid secret identifier: %w", err) } - _, ok := idSet[vaulttypes.KeyFor(id)] + _, ok := idSet[vaultutils.KeyFor(id)] if ok { return fmt.Errorf("DeleteSecrets requests cannot contain duplicate request for a given secret identifier: %s", id) } - idSet[vaulttypes.KeyFor(id)] = true + idSet[vaultutils.KeyFor(id)] = true } for _, r := range o.GetDeleteSecretsResponse().Responses { @@ -1680,8 +1678,8 @@ func (r *ReportingPlugin) validateListSecretIdentifiersObservation(ctx context.C return errors.New("ListSecretIdentifiers observation must have both request and response") } - // Passing in owner as key since Validate requires a non-empty key but list secret doesn't have a key - if err := r.validator.ValidateSecretIdentifier(ctx, listReq.Owner, listReq.Owner, listReq.Namespace); err != nil { + // List requests only carry an owner, not a secret key. + if err := r.validator.ValidateSecretIdentifier(ctx, "_", listReq.Owner, listReq.Namespace); err != nil { return fmt.Errorf("ListSecretIdentifiers request contains invalid secret identifier: %w", err) } @@ -1995,7 +1993,7 @@ func (r *ReportingPlugin) stateTransitionGetSecrets(ctx context.Context, chosen reqs := first.GetGetSecretsRequest().Requests idToReqs := map[string]*vaultcommon.SecretRequest{} for _, req := range reqs { - idToReqs[vaulttypes.KeyFor(req.Id)] = req + idToReqs[vaultutils.KeyFor(req.Id)] = req } newReqs := make([]*vaultcommon.SecretRequest, 0, len(idToReqs)) @@ -2018,7 +2016,7 @@ func (r *ReportingPlugin) stateTransitionGetSecrets(ctx context.Context, chosen for _, resp := range chosen { getSecretsResp := resp.GetGetSecretsResponse() for _, rsp := range getSecretsResp.Responses { - key := vaulttypes.KeyFor(rsp.Id) + key := vaultutils.KeyFor(rsp.Id) mergedResp, ok := idToAggResponse[key] if !ok { resp := &vaultcommon.SecretResponse{ @@ -2099,7 +2097,7 @@ func (r *ReportingPlugin) stateTransitionCreateSecrets(ctx context.Context, stor req := first.GetCreateSecretsRequest().EncryptedSecrets idToReqs := map[string]*vaultcommon.EncryptedSecret{} for _, r := range req { - idToReqs[vaulttypes.KeyFor(r.Id)] = r + idToReqs[vaultutils.KeyFor(r.Id)] = r } if !r.optimizationsEnabled(ctx) { @@ -2123,7 +2121,7 @@ func (r *ReportingPlugin) stateTransitionCreateSecrets(ctx context.Context, stor resp := first.GetCreateSecretsResponse() idToResps := map[string]*vaultcommon.CreateSecretResponse{} for _, r := range resp.Responses { - idToResps[vaulttypes.KeyFor(r.Id)] = r + idToResps[vaultutils.KeyFor(r.Id)] = r } sortedResps := []*vaultcommon.CreateSecretResponse{} @@ -2151,7 +2149,7 @@ func (r *ReportingPlugin) stateTransitionCreateSecrets(ctx context.Context, stor Error: errorMsg, }) } else { - r.lggr.Debugw("successfully wrote secret to key value store", "method", "CreateSecrets", "key", vaulttypes.KeyFor(req.Id), "requestID", reqID) + r.lggr.Debugw("successfully wrote secret to key value store", "method", "CreateSecrets", "key", vaultutils.KeyFor(req.Id), "requestID", reqID) sortedResps = append(sortedResps, resp) } } @@ -2167,6 +2165,9 @@ func (r *ReportingPlugin) stateTransitionCreateSecretsRequest(ctx context.Contex if resp.GetError() != "" { return resp, newUserError(resp.GetError()) } + if req.Id != nil { + req.Id = vaultutils.CanonicalSecretIdentifier(req.Id) + } encryptedSecret, err := hex.DecodeString(req.EncryptedValue) if err != nil { @@ -2220,7 +2221,7 @@ func (r *ReportingPlugin) stateTransitionUpdateSecrets(ctx context.Context, stor req := first.GetUpdateSecretsRequest().EncryptedSecrets idToReqs := map[string]*vaultcommon.EncryptedSecret{} for _, r := range req { - idToReqs[vaulttypes.KeyFor(r.Id)] = r + idToReqs[vaultutils.KeyFor(r.Id)] = r } if !r.optimizationsEnabled(ctx) { @@ -2244,7 +2245,7 @@ func (r *ReportingPlugin) stateTransitionUpdateSecrets(ctx context.Context, stor resp := first.GetUpdateSecretsResponse() idToResps := map[string]*vaultcommon.UpdateSecretResponse{} for _, r := range resp.Responses { - idToResps[vaulttypes.KeyFor(r.Id)] = r + idToResps[vaultutils.KeyFor(r.Id)] = r } sortedResps := []*vaultcommon.UpdateSecretResponse{} @@ -2270,7 +2271,7 @@ func (r *ReportingPlugin) stateTransitionUpdateSecrets(ctx context.Context, stor Error: errorMsg, }) } else { - r.lggr.Debugw("successfully wrote secret to key value store", "method", "UpdateSecrets", "key", vaulttypes.KeyFor(req.Id), "requestID", reqID) + r.lggr.Debugw("successfully wrote secret to key value store", "method", "UpdateSecrets", "key", vaultutils.KeyFor(req.Id), "requestID", reqID) sortedResps = append(sortedResps, resp) } } @@ -2286,6 +2287,9 @@ func (r *ReportingPlugin) stateTransitionUpdateSecretsRequest(ctx context.Contex if resp.GetError() != "" { return resp, newUserError(resp.GetError()) } + if req.Id != nil { + req.Id = vaultutils.CanonicalSecretIdentifier(req.Id) + } encryptedSecret, err := hex.DecodeString(req.EncryptedValue) if err != nil { @@ -2324,7 +2328,7 @@ func (r *ReportingPlugin) stateTransitionDeleteSecrets(ctx context.Context, stor req := first.GetDeleteSecretsRequest().Ids idToReqs := map[string]*vaultcommon.SecretIdentifier{} for _, r := range req { - idToReqs[vaulttypes.KeyFor(r)] = r + idToReqs[vaultutils.KeyFor(r)] = r } if !r.optimizationsEnabled(ctx) { @@ -2348,7 +2352,7 @@ func (r *ReportingPlugin) stateTransitionDeleteSecrets(ctx context.Context, stor resp := first.GetDeleteSecretsResponse() idToResps := map[string]*vaultcommon.DeleteSecretResponse{} for _, r := range resp.Responses { - idToResps[vaulttypes.KeyFor(r.Id)] = r + idToResps[vaultutils.KeyFor(r.Id)] = r } sortedResps := []*vaultcommon.DeleteSecretResponse{} @@ -2374,7 +2378,7 @@ func (r *ReportingPlugin) stateTransitionDeleteSecrets(ctx context.Context, stor Error: errorMsg, }) } else { - r.lggr.Debugw("successfully deleted secret in key value store", "method", "DeleteSecrets", "key", vaulttypes.KeyFor(req), "requestId", reqID) + r.lggr.Debugw("successfully deleted secret in key value store", "method", "DeleteSecrets", "key", vaultutils.KeyFor(req), "requestId", reqID) sortedResps = append(sortedResps, resp) } } @@ -2390,6 +2394,7 @@ func (r *ReportingPlugin) stateTransitionDeleteSecretsRequest(ctx context.Contex if resp.GetError() != "" { return resp, newUserError(resp.GetError()) } + id = vaultutils.CanonicalSecretIdentifier(id) err := store.DeleteSecret(ctx, id) if err != nil { diff --git a/core/services/ocr2/plugins/vault/plugin_test.go b/core/services/ocr2/plugins/vault/plugin_test.go index cc5754d9344..98ccf47c6c9 100644 --- a/core/services/ocr2/plugins/vault/plugin_test.go +++ b/core/services/ocr2/plugins/vault/plugin_test.go @@ -44,6 +44,15 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/logger" ) +const pluginTestWorkflowOwner = "0x0001020304050607080900010203040506070809" +const pluginTestZeroOwner = "0x0000000000000000000000000000000000000000" +const pluginTestListOwner = "0x000000000000000000000000000000000000000F" +const pluginTestTooLongKey = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" // 65 bytes + +func pluginMetadataKey(owner string) string { + return metadataPrefix + vaultutils.NormalizeWorkflowOwnerAddress(owner) +} + func testRequestLifecycleTracker(t *testing.T, lggr logger.Logger) *vaultcap.RequestLifecycleTracker { t.Helper() lc, err := vaultcap.NewRequestLifecycleTracker(lggr) @@ -303,7 +312,7 @@ func TestPlugin_Observation_NothingInBatch(t *testing.T) { func TestPlugin_Observation_GetSecretsRequest_OmitsRequestWhenOptimizationsEnabled(t *testing.T) { r := newTestReportingPlugin(t, withVaultOptimizationsEnabled()) - id := &vaultcommon.SecretIdentifier{Owner: "owner", Namespace: "main", Key: "secret"} + id := &vaultcommon.SecretIdentifier{Owner: pluginTestWorkflowOwner, Namespace: "main", Key: "secret"} p := &vaultcommon.GetSecretsRequest{ Requests: []*vaultcommon.SecretRequest{{Id: id}}, } @@ -329,7 +338,7 @@ func TestPlugin_Observation_PendingQueueEnabled_EmptyPendingQueue(t *testing.T) r := newTestReportingPlugin(t, withStore(store), withVaultOptimizationsEnabled()) id := &vaultcommon.SecretIdentifier{ - Owner: "owner", + Owner: pluginTestWorkflowOwner, Namespace: "main", Key: "my_secret", } @@ -388,7 +397,7 @@ func TestPlugin_Observation_PendingQueueEnabled_WithPendingQueueProvided(t *test r := newTestReportingPlugin(t, withStore(store), withVaultOptimizationsEnabled()) id := &vaultcommon.SecretIdentifier{ - Owner: "owner", + Owner: pluginTestWorkflowOwner, Namespace: "main", Key: "my_secret", } @@ -467,7 +476,7 @@ func TestPlugin_Observation_PendingQueueEnabled_ItemBothInPendingQueueAndLocalQu r := newTestReportingPlugin(t, withStore(store)) id := &vaultcommon.SecretIdentifier{ - Owner: "owner", + Owner: pluginTestWorkflowOwner, Namespace: "main", Key: "my_secret", } @@ -608,7 +617,7 @@ func TestPrepareObservationPendingQueueBlobs_packsManySmallItemsInOneObservation r := newTestReportingPlugin(t, withStore(store), withVaultOptimizationsEnabled()) id := &vaultcommon.SecretIdentifier{ - Owner: "owner", + Owner: pluginTestWorkflowOwner, Namespace: "main", Key: "my_secret", } @@ -659,7 +668,7 @@ func TestPrepareObservationPendingQueueBlobs_flushesAndContinuesWhenBatchFull(t pubK, _, err := box.GenerateKey(rand.Reader) require.NoError(t, err) pks := hex.EncodeToString(pubK[:]) - id := &vaultcommon.SecretIdentifier{Owner: "owner", Namespace: "main", Key: "my_secret"} + id := &vaultcommon.SecretIdentifier{Owner: pluginTestWorkflowOwner, Namespace: "main", Key: "my_secret"} p := &vaultcommon.GetSecretsRequest{ Requests: []*vaultcommon.SecretRequest{{Id: id, EncryptionKeys: []string{pks}}}, } @@ -705,7 +714,7 @@ func TestPrepareObservationPendingQueueBlobs_truncatesWhenHandleCountExceeded(t pubK, _, err := box.GenerateKey(rand.Reader) require.NoError(t, err) pks := hex.EncodeToString(pubK[:]) - id := &vaultcommon.SecretIdentifier{Owner: "owner", Namespace: "main", Key: "my_secret"} + id := &vaultcommon.SecretIdentifier{Owner: pluginTestWorkflowOwner, Namespace: "main", Key: "my_secret"} p := &vaultcommon.GetSecretsRequest{ Requests: []*vaultcommon.SecretRequest{{Id: id, EncryptionKeys: []string{pks}}}, } @@ -743,7 +752,7 @@ func TestPrepareObservationPendingQueueBlobs_errorWhenSingleItemTooLarge(t *test pubK, _, err := box.GenerateKey(rand.Reader) require.NoError(t, err) pks := hex.EncodeToString(pubK[:]) - id := &vaultcommon.SecretIdentifier{Owner: "owner", Namespace: "main", Key: "my_secret"} + id := &vaultcommon.SecretIdentifier{Owner: pluginTestWorkflowOwner, Namespace: "main", Key: "my_secret"} p := &vaultcommon.GetSecretsRequest{ Requests: []*vaultcommon.SecretRequest{{Id: id, EncryptionKeys: []string{pks}}}, } @@ -813,7 +822,7 @@ func TestPlugin_Observation_PendingQueueEnabled_BroadcastsPendingQueueBlobsInPar r := newTestReportingPlugin(t, withStore(store), withMaxBlobPayloadBytes(310)) id := &vaultcommon.SecretIdentifier{ - Owner: "owner", + Owner: pluginTestWorkflowOwner, Namespace: "main", Key: "my_secret", } @@ -871,7 +880,7 @@ func TestPlugin_Observation_PendingQueueEnabled_BroadcastBlobError(t *testing.T) r := newTestReportingPlugin(t, withStore(store), withLggr(lggr)) id := &vaultcommon.SecretIdentifier{ - Owner: "owner", + Owner: pluginTestWorkflowOwner, Namespace: "main", Key: "my_secret", } @@ -935,7 +944,7 @@ func TestPlugin_Observation_GetSecretsRequest_SecretIdentifierInvalid(t *testing name: "id is too long", maxIDLen: 10, id: &vaultcommon.SecretIdentifier{ - Owner: "owner", + Owner: pluginTestWorkflowOwner, Key: "hello", Namespace: "world", }, @@ -945,7 +954,7 @@ func TestPlugin_Observation_GetSecretsRequest_SecretIdentifierInvalid(t *testing name: "namespace exceeds maximum length", maxNamespaceLen: 3, id: &vaultcommon.SecretIdentifier{ - Owner: "owner", + Owner: pluginTestWorkflowOwner, Key: "hello", Namespace: "world", }, @@ -955,7 +964,7 @@ func TestPlugin_Observation_GetSecretsRequest_SecretIdentifierInvalid(t *testing name: "key exceeds maximum length", maxKeyLen: 3, id: &vaultcommon.SecretIdentifier{ - Owner: "owner", + Owner: pluginTestWorkflowOwner, Key: "hello", Namespace: "world", }, @@ -1031,7 +1040,7 @@ func TestPlugin_Observation_GetSecretsRequest_ResponseUsesCanonicalIdentifier(t r := newTestReportingPlugin(t, withKeys(pk, shares[0])) id := &vaultcommon.SecretIdentifier{ - Owner: "owner", + Owner: pluginTestWorkflowOwner, Namespace: "main", Key: "my_secret", } @@ -1040,13 +1049,16 @@ func TestPlugin_Observation_GetSecretsRequest_ResponseUsesCanonicalIdentifier(t } plaintext := []byte("my-secret-value") - ciphertext, err := tdh2easy.Encrypt(pk, plaintext) + var label [32]byte + ownerAddress := common.HexToAddress(pluginTestWorkflowOwner) + copy(label[12:], ownerAddress.Bytes()) + ciphertext, err := tdh2easy.EncryptWithLabel(pk, plaintext, label) require.NoError(t, err) ciphertextBytes, err := ciphertext.Marshal() require.NoError(t, err) createdID := &vaultcommon.SecretIdentifier{ - Owner: "owner", + Owner: pluginTestWorkflowOwner, Namespace: "main", Key: "my_secret", } @@ -1225,7 +1237,7 @@ func TestPlugin_Observation_GetSecretsRequest_SecretDoesNotExist(t *testing.T) { m: make(map[string]response), } id := &vaultcommon.SecretIdentifier{ - Owner: "owner", + Owner: pluginTestWorkflowOwner, Namespace: "main", Key: "my_secret", } @@ -1276,7 +1288,7 @@ func TestPlugin_Observation_GetSecretsRequest_SecretExistsButIsIncorrect(t *test r := newTestReportingPlugin(t, withLggr(lggr), withKeys(pk, shares[0])) id := &vaultcommon.SecretIdentifier{ - Owner: "owner", + Owner: pluginTestWorkflowOwner, Namespace: "main", Key: "my_secret", } @@ -1343,7 +1355,7 @@ func TestPlugin_Observation_GetSecretsRequest_PublicKeyIsInvalid(t *testing.T) { r := newTestReportingPlugin(t, withKeys(pk, shares[0])) id := &vaultcommon.SecretIdentifier{ - Owner: "owner", + Owner: pluginTestZeroOwner, Namespace: "main", Key: "my_secret", } @@ -1408,7 +1420,7 @@ func TestPlugin_Observation_GetSecretsRequest_SecretLabelIsInvalid(t *testing.T) r := newTestReportingPlugin(t, withKeys(pk, shares[0])) id := &vaultcommon.SecretIdentifier{ - Owner: "owner", + Owner: pluginTestZeroOwner, Namespace: "main", Key: "my_secret", } @@ -1418,7 +1430,7 @@ func TestPlugin_Observation_GetSecretsRequest_SecretLabelIsInvalid(t *testing.T) plaintext := []byte("my-secret-value") var label [32]byte - ownerAddress := common.HexToAddress("0x0001020304050607080900010203040506070809") + ownerAddress := common.HexToAddress(pluginTestWorkflowOwner) copy(label[12:], ownerAddress.Bytes()) // left-pad with 12 zero ciphertext, err := tdh2easy.EncryptWithLabel(pk, plaintext, label) require.NoError(t, err) @@ -1694,7 +1706,7 @@ func TestPlugin_Observation_CreateSecretsRequest_SecretIdentifierInvalid(t *test name: "id is too long", maxIDLen: 10, id: &vaultcommon.SecretIdentifier{ - Owner: "owner", + Owner: pluginTestWorkflowOwner, Key: "hello", Namespace: "world", }, @@ -1704,7 +1716,7 @@ func TestPlugin_Observation_CreateSecretsRequest_SecretIdentifierInvalid(t *test name: "namespace exceeds maximum length", maxNamespaceLen: 3, id: &vaultcommon.SecretIdentifier{ - Owner: "owner", + Owner: pluginTestWorkflowOwner, Key: "hello", Namespace: "world", }, @@ -1714,7 +1726,7 @@ func TestPlugin_Observation_CreateSecretsRequest_SecretIdentifierInvalid(t *test name: "key exceeds maximum length", maxKeyLen: 3, id: &vaultcommon.SecretIdentifier{ - Owner: "owner", + Owner: pluginTestWorkflowOwner, Key: "hello", Namespace: "world", }, @@ -1792,7 +1804,7 @@ func TestPlugin_Observation_CreateSecretsRequest_DisallowsDuplicateRequests(t *t m: make(map[string]response), } id := &vaultcommon.SecretIdentifier{ - Owner: "owner", + Owner: pluginTestWorkflowOwner, Namespace: "main", Key: "my_secret", } @@ -1845,7 +1857,7 @@ func TestPlugin_Observation_CreateSecretsRequest_DisallowsDuplicateRequests(t *t func TestPlugin_StateTransition_CreateSecretsRequest_CorrectlyTracksLimits(t *testing.T) { _, pk, shares, err := tdh2easy.GenerateKeys(1, 3) require.NoError(t, err) - r := newTestReportingPlugin(t, withBatchSize(10), withMaxIdentifierLengths(30, 30, 30), withKeys(pk, shares[0])) + r := newTestReportingPlugin(t, withBatchSize(10), withMaxIdentifierLengths(64, 30, 30), withKeys(pk, shares[0])) seqNr := uint64(1) rdr := &kv{ @@ -1859,7 +1871,7 @@ func TestPlugin_StateTransition_CreateSecretsRequest_CorrectlyTracksLimits(t *te require.NoError(t, err) id1 := &vaultcommon.SecretIdentifier{ - Owner: "owner", + Owner: pluginTestZeroOwner, Namespace: "main", Key: "my_secret", } @@ -1882,7 +1894,7 @@ func TestPlugin_StateTransition_CreateSecretsRequest_CorrectlyTracksLimits(t *te } id2 := &vaultcommon.SecretIdentifier{ - Owner: "owner", + Owner: pluginTestZeroOwner, Namespace: "main", Key: "my_secret2", } @@ -1949,7 +1961,7 @@ func TestPlugin_Observation_CreateSecretsRequest_InvalidCiphertext(t *testing.T) } id := &vaultcommon.SecretIdentifier{ - Owner: "owner", + Owner: pluginTestWorkflowOwner, Namespace: "main", Key: "secret", } @@ -2000,7 +2012,7 @@ func TestPlugin_Observation_CreateSecretsRequest_InvalidCiphertext_TooLong(t *te } id := &vaultcommon.SecretIdentifier{ - Owner: "owner", + Owner: pluginTestWorkflowOwner, Namespace: "main", Key: "secret", } @@ -2058,7 +2070,7 @@ func TestPlugin_Observation_CreateSecretsRequest_InvalidCiphertext_EncryptedWith } id := &vaultcommon.SecretIdentifier{ - Owner: "owner", + Owner: pluginTestZeroOwner, Namespace: "main", Key: "secret", } @@ -2240,7 +2252,7 @@ func TestPlugin_StateTransition_CreateSecretsRequest_TooManySecretsForOwner(t *t m: make(map[string]response), } id := &vaultcommon.SecretIdentifier{ - Owner: "owner", + Owner: pluginTestZeroOwner, Namespace: "main", Key: "secret", } @@ -2248,7 +2260,7 @@ func TestPlugin_StateTransition_CreateSecretsRequest_TooManySecretsForOwner(t *t err = kvstore.WriteMetadata(t.Context(), id.Owner, &vaultcommon.StoredMetadata{ SecretIdentifiers: []*vaultcommon.SecretIdentifier{ { - Owner: "owner", + Owner: pluginTestZeroOwner, Namespace: "main", Key: "secret2", }, @@ -2301,7 +2313,7 @@ func TestPlugin_StateTransition_CreateSecretsRequest_TooManySecretsForOwner(t *t o := os.Outcomes[0] assert.Len(t, o.GetCreateSecretsResponse().Responses, 1) - assert.Contains(t, o.GetCreateSecretsResponse().Responses[0].Error, "owner has reached maximum number of secrets") + assert.Contains(t, o.GetCreateSecretsResponse().Responses[0].Error, "has reached maximum number of secrets") } func TestPlugin_StateTransition_CreateSecretsRequest_SecretExistsForKey(t *testing.T) { @@ -2314,7 +2326,7 @@ func TestPlugin_StateTransition_CreateSecretsRequest_SecretExistsForKey(t *testi m: make(map[string]response), } id := &vaultcommon.SecretIdentifier{ - Owner: "owner", + Owner: pluginTestZeroOwner, Namespace: "main", Key: "secret", } @@ -2382,7 +2394,7 @@ func TestPlugin_Observation_CreateSecretsRequest_Success(t *testing.T) { m: make(map[string]response), } id := &vaultcommon.SecretIdentifier{ - Owner: "owner", + Owner: pluginTestZeroOwner, Namespace: "main", Key: "secret", } @@ -2667,7 +2679,7 @@ func marshalObservations(t *testing.T, observations ...observation) []byte { } for _, ob := range observations { o := &vaultcommon.Observation{ - Id: vaulttypes.KeyFor(ob.id), + Id: vaultutils.KeyFor(ob.id), } switch tr := ob.req.(type) { case *vaultcommon.GetSecretsRequest: @@ -2741,7 +2753,7 @@ func TestPlugin_StateTransition_InsufficientObservations(t *testing.T) { } id1 := &vaultcommon.SecretIdentifier{ - Owner: "owner", + Owner: pluginTestWorkflowOwner, Namespace: "main", Key: "secret", } @@ -2872,7 +2884,7 @@ func TestPlugin_ValidateObservations_InvalidObservations(t *testing.T) { } id1 := &vaultcommon.SecretIdentifier{ - Owner: "owner", + Owner: pluginTestWorkflowOwner, Namespace: "main", Key: "secret", } @@ -2940,7 +2952,7 @@ func TestPlugin_ValidateObservations_RequiresObservedIDsInPendingQueue(t *testin } id := &vaultcommon.SecretIdentifier{ - Owner: "owner", + Owner: pluginTestWorkflowOwner, Namespace: "main", Key: "secret", } @@ -2951,7 +2963,7 @@ func TestPlugin_ValidateObservations_RequiresObservedIDsInPendingQueue(t *testin anyd, err := anypb.New(d) require.NoError(t, err) id2 := &vaultcommon.SecretIdentifier{ - Owner: "owner", + Owner: pluginTestWorkflowOwner, Namespace: "main", Key: "secret2", } @@ -2966,15 +2978,15 @@ func TestPlugin_ValidateObservations_RequiresObservedIDsInPendingQueue(t *testin require.NoError(t, err) err = newTestWriteStore(t, kv).WritePendingQueue(t.Context(), []*vaultcommon.StoredPendingQueueItem{ - {Id: vaulttypes.KeyFor(id), Item: anyd}, - {Id: vaulttypes.KeyFor(id2), Item: anyg}, + {Id: vaultutils.KeyFor(id), Item: anyd}, + {Id: vaultutils.KeyFor(id2), Item: anyg}, }, ) require.NoError(t, err) // Observation id not present in the pending queue must be rejected. unknown := &vaultcommon.SecretIdentifier{ - Owner: "owner", + Owner: pluginTestWorkflowOwner, Namespace: "main", Key: "unknown", } @@ -3042,7 +3054,7 @@ func TestPlugin_ValidateObservations_DisallowsDuplicateBlobHandles(t *testing.T) m: make(map[string]response), } - id := &vaultcommon.SecretIdentifier{Owner: "owner", Namespace: "main", Key: "secret"} + id := &vaultcommon.SecretIdentifier{Owner: pluginTestWorkflowOwner, Namespace: "main", Key: "secret"} req := &vaultcommon.GetSecretsRequest{Requests: []*vaultcommon.SecretRequest{{Id: id}}} anyMsg, err := anypb.New(req) require.NoError(t, err) @@ -3088,7 +3100,7 @@ func TestPlugin_StateTransition_ShasDontMatch(t *testing.T) { } id := &vaultcommon.SecretIdentifier{ - Owner: "owner", + Owner: pluginTestWorkflowOwner, Namespace: "main", Key: "secret", } @@ -3151,7 +3163,7 @@ func TestPlugin_StateTransition_AggregatesValidationErrors(t *testing.T) { } id := &vaultcommon.SecretIdentifier{ - Owner: "owner", + Owner: pluginTestWorkflowOwner, Namespace: "main", Key: "secret", } @@ -3209,7 +3221,7 @@ func TestPlugin_StateTransition_GetSecretsRequest_CombinesShares(t *testing.T) { } id := &vaultcommon.SecretIdentifier{ - Owner: "owner", + Owner: pluginTestWorkflowOwner, Namespace: "main", Key: "secret", } @@ -3332,7 +3344,7 @@ func TestPlugin_StateTransition_GetSecretsRequest_CombinesBinaryShares(t *testin } id := &vaultcommon.SecretIdentifier{ - Owner: "owner", + Owner: pluginTestWorkflowOwner, Namespace: "main", Key: "secret", } @@ -3456,7 +3468,7 @@ func TestPlugin_StateTransition_GetSecretsRequest_CapsSharesAtTwoFPlusOne(t *tes } id := &vaultcommon.SecretIdentifier{ - Owner: "owner", + Owner: pluginTestWorkflowOwner, Namespace: "main", Key: "secret", } @@ -3544,7 +3556,7 @@ func TestPlugin_StateTransition_GetSecretsRequest_DoesNotCapSharesWhenOptimizati r := newTestReportingPlugin(t, withKeys(pk, shares[0]), withOnchainCfg(4, 1)) id := &vaultcommon.SecretIdentifier{ - Owner: "owner", + Owner: pluginTestWorkflowOwner, Namespace: "main", Key: "secret", } @@ -3598,7 +3610,7 @@ func TestPlugin_StateTransition_GetSecretsRequest_OmitsOutcomeRequestWhenOptimiz require.NoError(t, err) r := newTestReportingPlugin(t, withKeys(pk, shares[0]), withOnchainCfg(4, 1), withVaultOptimizationsEnabled()) - id := &vaultcommon.SecretIdentifier{Owner: "owner", Namespace: "main", Key: "secret"} + id := &vaultcommon.SecretIdentifier{Owner: pluginTestWorkflowOwner, Namespace: "main", Key: "secret"} req := &vaultcommon.GetSecretsRequest{Requests: []*vaultcommon.SecretRequest{{Id: id}}} resp := &vaultcommon.GetSecretsResponse{ Responses: []*vaultcommon.SecretResponse{ @@ -3641,7 +3653,7 @@ func TestPlugin_PrepareLegacyObservationPendingQueueBlobs_oneBlobPerItem(t *test store := requests.NewStore[*vaulttypes.Request]() r := newTestReportingPlugin(t, withStore(store)) - id := &vaultcommon.SecretIdentifier{Owner: "owner", Namespace: "main", Key: "my_secret"} + id := &vaultcommon.SecretIdentifier{Owner: pluginTestWorkflowOwner, Namespace: "main", Key: "my_secret"} pubK, _, err := box.GenerateKey(rand.Reader) require.NoError(t, err) pks := hex.EncodeToString(pubK[:]) @@ -3682,7 +3694,7 @@ func TestPlugin_StateTransition_CreateSecretsRequest_WritesSecrets(t *testing.T) rs := newTestReadStore(t, kv) id := &vaultcommon.SecretIdentifier{ - Owner: "owner", + Owner: pluginTestWorkflowOwner, Namespace: "main", Key: "secret", } @@ -3895,7 +3907,7 @@ func TestPlugin_StateTransition_CreateSecrets_ResponseOwnerMatchesStoredIdentifi func TestPlugin_Reports(t *testing.T) { value := "encrypted-value" id := &vaultcommon.SecretIdentifier{ - Owner: "owner", + Owner: pluginTestWorkflowOwner, Namespace: "main", Key: "secret", } @@ -3917,7 +3929,7 @@ func TestPlugin_Reports(t *testing.T) { }, } expectedOutcome1 := &vaultcommon.Outcome{ - Id: vaulttypes.KeyFor(id), + Id: vaultutils.KeyFor(id), RequestType: vaultcommon.RequestType_CREATE_SECRETS, Request: &vaultcommon.Outcome_CreateSecretsRequest{ CreateSecretsRequest: req, @@ -3928,7 +3940,7 @@ func TestPlugin_Reports(t *testing.T) { } id2 := &vaultcommon.SecretIdentifier{ - Owner: "owner", + Owner: pluginTestWorkflowOwner, Namespace: "main", Key: "secret2", } @@ -3948,7 +3960,7 @@ func TestPlugin_Reports(t *testing.T) { }, } expectedOutcome2 := &vaultcommon.Outcome{ - Id: vaulttypes.KeyFor(id2), + Id: vaultutils.KeyFor(id2), RequestType: vaultcommon.RequestType_GET_SECRETS, Request: &vaultcommon.Outcome_GetSecretsRequest{ GetSecretsRequest: req2, @@ -3981,7 +3993,7 @@ func TestPlugin_Reports(t *testing.T) { require.NoError(t, err) assert.True(t, proto.Equal(&vaultcommon.ReportInfo{ - Id: vaulttypes.KeyFor(id), + Id: vaultutils.KeyFor(id), Format: vaultcommon.ReportFormat_REPORT_FORMAT_JSON, RequestType: vaultcommon.RequestType_CREATE_SECRETS, }, info1)) @@ -3994,7 +4006,7 @@ func TestPlugin_Reports(t *testing.T) { info2, err := extractReportInfo(o2.ReportWithInfo) require.NoError(t, err) assert.True(t, proto.Equal(&vaultcommon.ReportInfo{ - Id: vaulttypes.KeyFor(id2), + Id: vaultutils.KeyFor(id2), Format: vaultcommon.ReportFormat_REPORT_FORMAT_PROTOBUF, RequestType: vaultcommon.RequestType_GET_SECRETS, }, info2)) @@ -4037,7 +4049,7 @@ func TestPlugin_Observation_UpdateSecretsRequest_SecretIdentifierInvalid(t *test name: "id is too long", maxIDLen: 10, id: &vaultcommon.SecretIdentifier{ - Owner: "owner", + Owner: pluginTestWorkflowOwner, Key: "hello", Namespace: "world", }, @@ -4047,7 +4059,7 @@ func TestPlugin_Observation_UpdateSecretsRequest_SecretIdentifierInvalid(t *test name: "namespace exceeds maximum length", maxNamespaceLen: 3, id: &vaultcommon.SecretIdentifier{ - Owner: "a", + Owner: pluginTestZeroOwner, Key: "b", Namespace: "world", }, @@ -4057,7 +4069,7 @@ func TestPlugin_Observation_UpdateSecretsRequest_SecretIdentifierInvalid(t *test name: "key exceeds maximum length", maxKeyLen: 3, id: &vaultcommon.SecretIdentifier{ - Owner: "a", + Owner: pluginTestZeroOwner, Namespace: "b", Key: "hello", }, @@ -4128,14 +4140,14 @@ func TestPlugin_Observation_UpdateSecretsRequest_SecretIdentifierInvalid(t *test } func TestPlugin_Observation_UpdateSecretsRequest_DisallowsDuplicateRequests(t *testing.T) { - r := newTestReportingPlugin(t, withMaxIdentifierLengths(30, 30, 30)) + r := newTestReportingPlugin(t, withMaxIdentifierLengths(64, 30, 30)) seqNr := uint64(1) rdr := &kv{ m: make(map[string]response), } id := &vaultcommon.SecretIdentifier{ - Owner: "owner", + Owner: pluginTestWorkflowOwner, Namespace: "main", Key: "my_secret", } @@ -4194,7 +4206,7 @@ func TestPlugin_Observation_UpdateSecretsRequest_InvalidCiphertext(t *testing.T) } id := &vaultcommon.SecretIdentifier{ - Owner: "owner", + Owner: pluginTestWorkflowOwner, Namespace: "main", Key: "secret", } @@ -4245,7 +4257,7 @@ func TestPlugin_Observation_UpdateSecretsRequest_InvalidCiphertext_TooLong(t *te } id := &vaultcommon.SecretIdentifier{ - Owner: "owner", + Owner: pluginTestWorkflowOwner, Namespace: "main", Key: "secret", } @@ -4303,7 +4315,7 @@ func TestPlugin_Observation_UpdateSecretsRequest_InvalidCiphertext_EncryptedWith } id := &vaultcommon.SecretIdentifier{ - Owner: "owner", + Owner: pluginTestZeroOwner, Namespace: "main", Key: "secret", } @@ -4364,7 +4376,7 @@ func TestPlugin_StateTransition_UpdateSecretsRequest_SecretDoesntExist(t *testin rs := newTestReadStore(t, kv) id := &vaultcommon.SecretIdentifier{ - Owner: "owner", + Owner: pluginTestWorkflowOwner, Namespace: "main", Key: "secret", } @@ -4433,7 +4445,7 @@ func TestPlugin_StateTransition_UpdateSecretsRequest_WritesSecrets(t *testing.T) r := newTestReportingPlugin(t, withLggr(lggr), withKeys(pk, shares[0]), withOnchainCfg(4, 1)) id := &vaultcommon.SecretIdentifier{ - Owner: "owner", + Owner: pluginTestWorkflowOwner, Namespace: "main", Key: "secret", } @@ -4447,10 +4459,10 @@ func TestPlugin_StateTransition_UpdateSecretsRequest_WritesSecrets(t *testing.T) require.NoError(t, err) kv := &kv{ m: map[string]response{ - keyPrefix + vaulttypes.KeyFor(id): { + keyPrefix + vaultutils.KeyFor(id): { data: secret, }, - metadataPrefix + "owner": { + metadataPrefix + vaultutils.NormalizeWorkflowOwnerAddress(pluginTestWorkflowOwner): { data: metadata, }, }, @@ -4521,7 +4533,7 @@ func TestPlugin_StateTransition_UpdateSecretsRequest_WritesSecrets(t *testing.T) func TestPlugin_Reports_UpdateSecretsRequest(t *testing.T) { value := "encrypted-value" id := &vaultcommon.SecretIdentifier{ - Owner: "owner", + Owner: pluginTestWorkflowOwner, Namespace: "main", Key: "secret", } @@ -4543,7 +4555,7 @@ func TestPlugin_Reports_UpdateSecretsRequest(t *testing.T) { }, } expectedOutcome := &vaultcommon.Outcome{ - Id: vaulttypes.KeyFor(id), + Id: vaultutils.KeyFor(id), RequestType: vaultcommon.RequestType_UPDATE_SECRETS, Request: &vaultcommon.Outcome_UpdateSecretsRequest{ UpdateSecretsRequest: req, @@ -4576,7 +4588,7 @@ func TestPlugin_Reports_UpdateSecretsRequest(t *testing.T) { require.NoError(t, err) assert.True(t, proto.Equal(&vaultcommon.ReportInfo{ - Id: vaulttypes.KeyFor(id), + Id: vaultutils.KeyFor(id), Format: vaultcommon.ReportFormat_REPORT_FORMAT_JSON, RequestType: vaultcommon.RequestType_UPDATE_SECRETS, }, info1)) @@ -4587,10 +4599,10 @@ func TestPlugin_Reports_UpdateSecretsRequest(t *testing.T) { } func TestPlugin_Observation_DeleteSecrets(t *testing.T) { - r := newTestReportingPlugin(t, withMaxIdentifierLengths(30, 30, 30)) + r := newTestReportingPlugin(t, withMaxIdentifierLengths(64, 30, 30)) id := &vaultcommon.SecretIdentifier{ - Owner: "foo", + Owner: pluginTestListOwner, Namespace: "main", Key: "item4", } @@ -4611,10 +4623,10 @@ func TestPlugin_Observation_DeleteSecrets(t *testing.T) { seqNr := uint64(1) rdr := &kv{ m: map[string]response{ - metadataPrefix + "foo": response{ + pluginMetadataKey(pluginTestListOwner): response{ data: mdb, }, - keyPrefix + vaulttypes.KeyFor(id): response{ + keyPrefix + vaultutils.KeyFor(id): response{ data: ssb, }, }, @@ -4654,14 +4666,14 @@ func TestPlugin_Observation_DeleteSecrets(t *testing.T) { } func TestPlugin_Observation_DeleteSecrets_IdDoesntExist(t *testing.T) { - r := newTestReportingPlugin(t, withMaxIdentifierLengths(30, 30, 30)) + r := newTestReportingPlugin(t, withMaxIdentifierLengths(64, 30, 30)) seqNr := uint64(1) rdr := &kv{ m: map[string]response{}, } id := &vaultcommon.SecretIdentifier{ - Owner: "foo", + Owner: pluginTestListOwner, Namespace: "main", Key: "item4", } @@ -4700,14 +4712,14 @@ func TestPlugin_Observation_DeleteSecrets_IdDoesntExist(t *testing.T) { } func TestPlugin_Observation_DeleteSecrets_InvalidRequestDuplicateIds(t *testing.T) { - r := newTestReportingPlugin(t, withMaxIdentifierLengths(30, 30, 30)) + r := newTestReportingPlugin(t, withMaxIdentifierLengths(64, 30, 30)) seqNr := uint64(1) rdr := &kv{ m: map[string]response{}, } id := &vaultcommon.SecretIdentifier{ - Owner: "foo", + Owner: pluginTestListOwner, Namespace: "main", Key: "item4", } @@ -4757,7 +4769,7 @@ func TestPlugin_StateTransition_DeleteSecretsRequest(t *testing.T) { r := newTestReportingPlugin(t, withLggr(lggr), withKeys(pk, shares[0]), withOnchainCfg(4, 1)) id := &vaultcommon.SecretIdentifier{ - Owner: "foo", + Owner: pluginTestListOwner, Namespace: "main", Key: "item4", } @@ -4778,10 +4790,10 @@ func TestPlugin_StateTransition_DeleteSecretsRequest(t *testing.T) { seqNr := uint64(1) rdr := &kv{ m: map[string]response{ - metadataPrefix + "foo": response{ + pluginMetadataKey(pluginTestListOwner): response{ data: mdb, }, - keyPrefix + vaulttypes.KeyFor(id): response{ + keyPrefix + vaultutils.KeyFor(id): response{ data: ssb, }, }, @@ -4846,7 +4858,7 @@ func TestPlugin_StateTransition_DeleteSecretsRequest_SecretDoesNotExist(t *testi r := newTestReportingPlugin(t, withLggr(lggr), withKeys(pk, shares[0]), withOnchainCfg(4, 1)) id := &vaultcommon.SecretIdentifier{ - Owner: "foo", + Owner: pluginTestListOwner, Namespace: "main", Key: "item4", } @@ -4859,7 +4871,7 @@ func TestPlugin_StateTransition_DeleteSecretsRequest_SecretDoesNotExist(t *testi seqNr := uint64(1) rdr := &kv{ m: map[string]response{ - metadataPrefix + "foo": response{ + pluginMetadataKey(pluginTestListOwner): response{ data: mdb, }, }, @@ -4919,7 +4931,7 @@ func TestPlugin_StateTransition_DeleteSecretsRequest_SecretDoesNotExist(t *testi func TestPlugin_Reports_DeleteSecretsRequest(t *testing.T) { id := &vaultcommon.SecretIdentifier{ - Owner: "owner", + Owner: pluginTestWorkflowOwner, Namespace: "main", Key: "secret", } @@ -4937,7 +4949,7 @@ func TestPlugin_Reports_DeleteSecretsRequest(t *testing.T) { }, } expectedOutcome := &vaultcommon.Outcome{ - Id: vaulttypes.KeyFor(id), + Id: vaultutils.KeyFor(id), RequestType: vaultcommon.RequestType_DELETE_SECRETS, Request: &vaultcommon.Outcome_DeleteSecretsRequest{ DeleteSecretsRequest: req, @@ -4970,7 +4982,7 @@ func TestPlugin_Reports_DeleteSecretsRequest(t *testing.T) { require.NoError(t, err) assert.True(t, proto.Equal(&vaultcommon.ReportInfo{ - Id: vaulttypes.KeyFor(id), + Id: vaultutils.KeyFor(id), Format: vaultcommon.ReportFormat_REPORT_FORMAT_JSON, RequestType: vaultcommon.RequestType_DELETE_SECRETS, }, info1)) @@ -4981,7 +4993,7 @@ func TestPlugin_Reports_DeleteSecretsRequest(t *testing.T) { } func TestPlugin_Observation_ListSecretIdentifiers_OwnerRequired(t *testing.T) { - r := newTestReportingPlugin(t, withMaxIdentifierLengths(30, 30, 30)) + r := newTestReportingPlugin(t, withMaxIdentifierLengths(64, 30, 30)) seqNr := uint64(1) rdr := &kv{ @@ -5019,22 +5031,22 @@ func TestPlugin_Observation_ListSecretIdentifiers_OwnerRequired(t *testing.T) { } func TestPlugin_Observation_ListSecretIdentifiers_NoNamespaceProvided(t *testing.T) { - r := newTestReportingPlugin(t, withMaxIdentifierLengths(30, 30, 30)) + r := newTestReportingPlugin(t, withMaxIdentifierLengths(64, 30, 30)) md := &vaultcommon.StoredMetadata{ SecretIdentifiers: []*vaultcommon.SecretIdentifier{ { - Owner: "foo", + Owner: pluginTestListOwner, Namespace: "main", Key: "item4", }, { - Owner: "foo", + Owner: pluginTestListOwner, Namespace: "secondary", Key: "item2", }, { - Owner: "foo", + Owner: pluginTestListOwner, Namespace: "main", Key: "item3", }, @@ -5046,14 +5058,14 @@ func TestPlugin_Observation_ListSecretIdentifiers_NoNamespaceProvided(t *testing seqNr := uint64(1) rdr := &kv{ m: map[string]response{ - metadataPrefix + "foo": response{ + pluginMetadataKey(pluginTestListOwner): response{ data: mdb, }, }, } p := &vaultcommon.ListSecretIdentifiersRequest{ RequestId: "request-id", - Owner: "foo", + Owner: pluginTestListOwner, } anyp, err := anypb.New(p) require.NoError(t, err) @@ -5079,17 +5091,17 @@ func TestPlugin_Observation_ListSecretIdentifiers_NoNamespaceProvided(t *testing resp := o.GetListSecretIdentifiersResponse() expectedIdentifiers := []*vaultcommon.SecretIdentifier{ { - Owner: "foo", + Owner: pluginTestListOwner, Namespace: "main", Key: "item3", }, { - Owner: "foo", + Owner: pluginTestListOwner, Namespace: "main", Key: "item4", }, { - Owner: "foo", + Owner: pluginTestListOwner, Namespace: "secondary", Key: "item2", }, @@ -5103,22 +5115,22 @@ func TestPlugin_Observation_ListSecretIdentifiers_NoNamespaceProvided(t *testing } func TestPlugin_Observation_ListSecretIdentifiers_FilterByNamespace(t *testing.T) { - r := newTestReportingPlugin(t, withMaxIdentifierLengths(30, 30, 30)) + r := newTestReportingPlugin(t, withMaxIdentifierLengths(64, 30, 30)) md := &vaultcommon.StoredMetadata{ SecretIdentifiers: []*vaultcommon.SecretIdentifier{ { - Owner: "foo", + Owner: pluginTestListOwner, Namespace: "main", Key: "item4", }, { - Owner: "foo", + Owner: pluginTestListOwner, Namespace: "secondary", Key: "item2", }, { - Owner: "foo", + Owner: pluginTestListOwner, Namespace: "main", Key: "item3", }, @@ -5130,14 +5142,14 @@ func TestPlugin_Observation_ListSecretIdentifiers_FilterByNamespace(t *testing.T seqNr := uint64(1) rdr := &kv{ m: map[string]response{ - metadataPrefix + "foo": response{ + pluginMetadataKey(pluginTestListOwner): response{ data: mdb, }, }, } p := &vaultcommon.ListSecretIdentifiersRequest{ RequestId: "request-id", - Owner: "foo", + Owner: pluginTestListOwner, Namespace: "main", } anyp, err := anypb.New(p) @@ -5164,12 +5176,12 @@ func TestPlugin_Observation_ListSecretIdentifiers_FilterByNamespace(t *testing.T resp := o.GetListSecretIdentifiersResponse() expectedIdentifiers := []*vaultcommon.SecretIdentifier{ { - Owner: "foo", + Owner: pluginTestListOwner, Namespace: "main", Key: "item3", }, { - Owner: "foo", + Owner: pluginTestListOwner, Namespace: "main", Key: "item4", }, @@ -5186,7 +5198,7 @@ func TestPlugin_Observation_ListSecretIdentifiers_ListsSecretsForRequestOwner(t r := newTestReportingPlugin( t, withMaxSecretsPerOwner(5), - withMaxIdentifierLengths(30, 30, 30), + withMaxIdentifierLengths(64, 30, 30), ) const workflowOwner = "0x1111111111111111111111111111111111111111" @@ -5225,7 +5237,7 @@ func TestPlugin_Observation_ListSecretIdentifiers_ListsSecretsForRequestOwner(t } func TestPlugin_Observation_ListSecretIdentifiers_DoesNotFallbackWhenGateDisabled(t *testing.T) { - r := newTestReportingPlugin(t, withMaxSecretsPerOwner(5), withMaxIdentifierLengths(30, 30, 30)) + r := newTestReportingPlugin(t, withMaxSecretsPerOwner(5), withMaxIdentifierLengths(64, 30, 30)) const ( orgID = "org-list" @@ -5265,13 +5277,13 @@ func TestPlugin_Observation_ListSecretIdentifiers_DoesNotFallbackWhenGateDisable func TestPlugin_Reports_ListSecretIdentifiersRequest(t *testing.T) { id := &vaultcommon.SecretIdentifier{ - Owner: "owner", + Owner: pluginTestWorkflowOwner, Namespace: "main", Key: "secret", } req := &vaultcommon.ListSecretIdentifiersRequest{ RequestId: "request-id", - Owner: "owner", + Owner: pluginTestWorkflowOwner, } resp := &vaultcommon.ListSecretIdentifiersResponse{ Identifiers: []*vaultcommon.SecretIdentifier{ @@ -5279,7 +5291,7 @@ func TestPlugin_Reports_ListSecretIdentifiersRequest(t *testing.T) { }, } expectedOutcome := &vaultcommon.Outcome{ - Id: vaulttypes.KeyFor(id), + Id: vaultutils.KeyFor(id), RequestType: vaultcommon.RequestType_LIST_SECRET_IDENTIFIERS, Request: &vaultcommon.Outcome_ListSecretIdentifiersRequest{ ListSecretIdentifiersRequest: req, @@ -5312,7 +5324,7 @@ func TestPlugin_Reports_ListSecretIdentifiersRequest(t *testing.T) { require.NoError(t, err) assert.True(t, proto.Equal(&vaultcommon.ReportInfo{ - Id: vaulttypes.KeyFor(id), + Id: vaultutils.KeyFor(id), Format: vaultcommon.ReportFormat_REPORT_FORMAT_JSON, RequestType: vaultcommon.RequestType_LIST_SECRET_IDENTIFIERS, }, info1)) @@ -5335,12 +5347,12 @@ func TestPlugin_StateTransition_ListSecretIdentifiers(t *testing.T) { rs := newTestReadStore(t, kv) id := &vaultcommon.SecretIdentifier{ - Owner: "owner", + Owner: pluginTestWorkflowOwner, Namespace: "main", Key: "secret", } req := &vaultcommon.ListSecretIdentifiersRequest{ - Owner: "owner", + Owner: pluginTestWorkflowOwner, Namespace: "main", RequestId: "request-id", } @@ -5420,7 +5432,7 @@ func TestPlugin_StateTransition_StoresPendingQueue(t *testing.T) { r := newTestReportingPlugin( t, withMaxSecretsPerOwner(5), - withMaxIdentifierLengths(30, 30, 30), + withMaxIdentifierLengths(64, 30, 30), withKeys(pk, shares[0]), withOnchainCfg(4, 1), ) @@ -5431,7 +5443,7 @@ func TestPlugin_StateTransition_StoresPendingQueue(t *testing.T) { } req := &vaultcommon.ListSecretIdentifiersRequest{ - Owner: "owner", + Owner: pluginTestWorkflowOwner, Namespace: "main", RequestId: "request-id", } @@ -5439,7 +5451,7 @@ func TestPlugin_StateTransition_StoresPendingQueue(t *testing.T) { require.NoError(t, err) req = &vaultcommon.ListSecretIdentifiersRequest{ - Owner: "owner", + Owner: pluginTestWorkflowOwner, Namespace: "production", RequestId: "request-id2", } @@ -5447,7 +5459,7 @@ func TestPlugin_StateTransition_StoresPendingQueue(t *testing.T) { require.NoError(t, err) req = &vaultcommon.ListSecretIdentifiersRequest{ - Owner: "owner", + Owner: pluginTestWorkflowOwner, Namespace: "staging", RequestId: "request-id3", } @@ -5455,7 +5467,7 @@ func TestPlugin_StateTransition_StoresPendingQueue(t *testing.T) { require.NoError(t, err) req = &vaultcommon.ListSecretIdentifiersRequest{ - Owner: "owner", + Owner: pluginTestWorkflowOwner, Namespace: "testnet", RequestId: "request-id4", } @@ -5562,7 +5574,7 @@ func TestPlugin_StateTransition_StoresPendingQueue_AllConsensusItems(t *testing. require.NoError(t, err) req1 := &vaultcommon.ListSecretIdentifiersRequest{ - Owner: "owner", + Owner: pluginTestWorkflowOwner, Namespace: "main", RequestId: "request-id", } @@ -5570,7 +5582,7 @@ func TestPlugin_StateTransition_StoresPendingQueue_AllConsensusItems(t *testing. require.NoError(t, err) req2 := &vaultcommon.ListSecretIdentifiersRequest{ - Owner: "owner", + Owner: pluginTestWorkflowOwner, Namespace: "production", RequestId: "request-id2", } @@ -5578,7 +5590,7 @@ func TestPlugin_StateTransition_StoresPendingQueue_AllConsensusItems(t *testing. require.NoError(t, err) req3 := &vaultcommon.ListSecretIdentifiersRequest{ - Owner: "owner", + Owner: pluginTestWorkflowOwner, Namespace: "staging", RequestId: "request-id3", } @@ -5586,7 +5598,7 @@ func TestPlugin_StateTransition_StoresPendingQueue_AllConsensusItems(t *testing. require.NoError(t, err) req4 := &vaultcommon.ListSecretIdentifiersRequest{ - Owner: "owner", + Owner: pluginTestWorkflowOwner, Namespace: "testnet", RequestId: "request-id4", } @@ -5690,7 +5702,7 @@ func TestPlugin_StateTransition_StoresPendingQueue_AllConsensusItems(t *testing. r := newTestReportingPlugin( t, withBatchSize(1), - withMaxIdentifierLengths(30, 30, 30), + withMaxIdentifierLengths(64, 30, 30), withKeys(pk, shares[0]), withOnchainCfg(4, 1), withVaultOptimizationsEnabled(), @@ -5704,7 +5716,7 @@ func TestPlugin_StateTransition_StoresPendingQueue_AllConsensusItems(t *testing. r := newTestReportingPlugin( t, withBatchSize(1), - withMaxIdentifierLengths(30, 30, 30), + withMaxIdentifierLengths(64, 30, 30), withKeys(pk, shares[0]), withOnchainCfg(4, 1), ) @@ -5720,7 +5732,7 @@ func TestPlugin_StateTransition_OutcomesStoppedByPrecursorWireSize(t *testing.T) require.NoError(t, err) buildListObs := func(obsID string) *vaultcommon.Observation { - req := &vaultcommon.ListSecretIdentifiersRequest{Owner: "owner", Namespace: "main", RequestId: obsID} + req := &vaultcommon.ListSecretIdentifiersRequest{Owner: pluginTestWorkflowOwner, Namespace: "main", RequestId: obsID} resp := &vaultcommon.ListSecretIdentifiersResponse{Success: true, Identifiers: []*vaultcommon.SecretIdentifier{}, Error: ""} return &vaultcommon.Observation{ Id: obsID, @@ -5772,7 +5784,7 @@ func TestPlugin_StateTransition_OutcomesNotStoppedByPrecursorWireSizeWhenOptimiz require.NoError(t, err) buildListObs := func(obsID string) *vaultcommon.Observation { - req := &vaultcommon.ListSecretIdentifiersRequest{Owner: "owner", Namespace: "main", RequestId: obsID} + req := &vaultcommon.ListSecretIdentifiersRequest{Owner: pluginTestWorkflowOwner, Namespace: "main", RequestId: obsID} resp := &vaultcommon.ListSecretIdentifiersResponse{Success: true, Identifiers: []*vaultcommon.SecretIdentifier{}, Error: ""} return &vaultcommon.Observation{ Id: obsID, @@ -5836,7 +5848,7 @@ func TestPlugin_ValidateObservation_WireSizeExceedsMax(t *testing.T) { func TestPlugin_StateTransition_StoresPendingQueue_DoesntDoubleCountObservationsFromOneNode(t *testing.T) { _, pk, shares, err := tdh2easy.GenerateKeys(1, 3) require.NoError(t, err) - r := newTestReportingPlugin(t, withMaxIdentifierLengths(30, 30, 30), withKeys(pk, shares[0]), withOnchainCfg(4, 1)) + r := newTestReportingPlugin(t, withMaxIdentifierLengths(64, 30, 30), withKeys(pk, shares[0]), withOnchainCfg(4, 1)) seqNr := uint64(1) rdr := &kv{ @@ -5844,7 +5856,7 @@ func TestPlugin_StateTransition_StoresPendingQueue_DoesntDoubleCountObservations } req1 := &vaultcommon.ListSecretIdentifiersRequest{ - Owner: "owner", + Owner: pluginTestWorkflowOwner, Namespace: "main", RequestId: "request-id", } @@ -5910,7 +5922,7 @@ func TestPlugin_ValidateObservation_AcceptsFullPendingQueueObservation(t *testin require.NoError(t, err) batchSize := 1 // MaxBatchSize=1, so 2*batchSize=2 is the intended max pending queue items - r := newTestReportingPlugin(t, withBatchSize(batchSize), withMaxIdentifierLengths(30, 30, 30), withKeys(pk, shares[0]), withOnchainCfg(4, 1)) + r := newTestReportingPlugin(t, withBatchSize(batchSize), withMaxIdentifierLengths(64, 30, 30), withKeys(pk, shares[0]), withOnchainCfg(4, 1)) seqNr := uint64(1) rdr := &kv{ @@ -5918,7 +5930,7 @@ func TestPlugin_ValidateObservation_AcceptsFullPendingQueueObservation(t *testin } req1 := &vaultcommon.ListSecretIdentifiersRequest{ - Owner: "owner", + Owner: pluginTestWorkflowOwner, Namespace: "main", RequestId: "request-id", } @@ -5965,7 +5977,7 @@ func TestPlugin_ValidateObservation_AcceptsFullPendingQueueObservation(t *testin func TestPlugin_ValidateObservation_GetSecretsRequest(t *testing.T) { _, pk, shares, err := tdh2easy.GenerateKeys(1, 3) require.NoError(t, err) - r := newTestReportingPlugin(t, withMaxIdentifierLengths(30, 30, 30), withKeys(pk, shares[0]), withOnchainCfg(4, 1)) + r := newTestReportingPlugin(t, withMaxIdentifierLengths(64, 30, 30), withKeys(pk, shares[0]), withOnchainCfg(4, 1)) seqNr := uint64(1) rdr := &kv{ @@ -5973,7 +5985,7 @@ func TestPlugin_ValidateObservation_GetSecretsRequest(t *testing.T) { } id := &vaultcommon.SecretIdentifier{ - Owner: "owner", + Owner: pluginTestWorkflowOwner, Namespace: "main", Key: "secret", } @@ -6187,7 +6199,7 @@ func TestPlugin_ValidateObservation_GetSecretsRequest(t *testing.T) { }, }, { - Id: &vaultcommon.SecretIdentifier{Owner: "owner", Namespace: "main", Key: "secret2"}, + Id: &vaultcommon.SecretIdentifier{Owner: pluginTestWorkflowOwner, Namespace: "main", Key: "secret2"}, Result: &vaultcommon.SecretResponse_Error{ Error: "foo", }, @@ -6267,7 +6279,7 @@ func TestPlugin_ValidateObservation_GetSecretsRequest(t *testing.T) { resp = &vaultcommon.GetSecretsResponse{ Responses: []*vaultcommon.SecretResponse{ {Id: id, Result: &vaultcommon.SecretResponse_Error{Error: "err"}}, - {Id: &vaultcommon.SecretIdentifier{Owner: "owner", Namespace: "main", Key: "secret2"}, Result: &vaultcommon.SecretResponse_Error{Error: "err"}}, + {Id: &vaultcommon.SecretIdentifier{Owner: pluginTestWorkflowOwner, Namespace: "main", Key: "secret2"}, Result: &vaultcommon.SecretResponse_Error{Error: "err"}}, }, } @@ -6304,13 +6316,13 @@ func TestPlugin_ValidateObservation_GetSecrets_MismatchedResponseOwnerRejected(t r := newTestReportingPlugin( t, withMaxRequestBatchSize(10), - withMaxIdentifierLengths(30, 30, 30), + withMaxIdentifierLengths(64, 30, 30), withKeys(pk, shares[0]), withOnchainCfg(4, 1), ) - workflowOwner := "workflowowner" - orgID := "org_abc123def456ghi" + workflowOwner := pluginTestWorkflowOwner + orgID := "0xBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB" secretID := &vaultcommon.SecretIdentifier{ Owner: workflowOwner, Namespace: "main", @@ -6352,13 +6364,13 @@ func TestPlugin_ValidateObservation_GetSecrets_MismatchedResponseOwnerRejected(t func TestPlugin_ValidateObservation_PanicsOnEmptyShares(t *testing.T) { _, pk, shares, err := tdh2easy.GenerateKeys(1, 3) require.NoError(t, err) - r := newTestReportingPlugin(t, withMaxIdentifierLengths(30, 30, 30), withKeys(pk, shares[0]), withOnchainCfg(4, 1)) + r := newTestReportingPlugin(t, withMaxIdentifierLengths(64, 30, 30), withKeys(pk, shares[0]), withOnchainCfg(4, 1)) seqNr := uint64(1) rdr := &kv{m: make(map[string]response)} id := &vaultcommon.SecretIdentifier{ - Owner: "owner", + Owner: pluginTestWorkflowOwner, Namespace: "main", Key: "secret", } @@ -6442,13 +6454,13 @@ func TestPlugin_ValidateObservation_PanicsOnEmptyShares(t *testing.T) { func TestPlugin_ValidateObservation_NilSecretIdentifier(t *testing.T) { _, pk, shares, err := tdh2easy.GenerateKeys(1, 3) require.NoError(t, err) - r := newTestReportingPlugin(t, withMaxIdentifierLengths(30, 30, 30), withKeys(pk, shares[0]), withOnchainCfg(4, 1)) + r := newTestReportingPlugin(t, withMaxIdentifierLengths(64, 30, 30), withKeys(pk, shares[0]), withOnchainCfg(4, 1)) seqNr := uint64(1) bf := &blobber{} id := &vaultcommon.SecretIdentifier{ - Owner: "owner", + Owner: pluginTestWorkflowOwner, Namespace: "main", Key: "secret", } @@ -6675,7 +6687,7 @@ func TestPlugin_ValidateObservation_CiphertextSize(t *testing.T) { r := newTestReportingPlugin( t, withMaxCiphertextLengthBytes(10), - withMaxIdentifierLengths(30, 30, 30), + withMaxIdentifierLengths(64, 30, 30), withKeys(pk, shares[0]), withOnchainCfg(4, 1), ) @@ -6684,7 +6696,7 @@ func TestPlugin_ValidateObservation_CiphertextSize(t *testing.T) { bf := &blobber{} id := &vaultcommon.SecretIdentifier{ - Owner: "owner", + Owner: pluginTestWorkflowOwner, Namespace: "main", Key: "secret", } @@ -6879,7 +6891,7 @@ func TestPlugin_ValidateObservation_CiphertextSize(t *testing.T) { } func TestPlugin_ValidateObservation_SecretIdentifierValidation(t *testing.T) { - validID := &vaultcommon.SecretIdentifier{Owner: "owner", Namespace: "main", Key: "secret"} + validID := &vaultcommon.SecretIdentifier{Owner: pluginTestWorkflowOwner, Namespace: "main", Key: "secret"} validCiphertext := hex.EncodeToString(make([]byte, 5)) type testCase struct { @@ -6988,7 +7000,7 @@ func TestPlugin_ValidateObservation_SecretIdentifierValidation(t *testing.T) { }, { name: "GetSecrets empty key in request passes (not validated)", - obs: makeGetSecretsObs(&vaultcommon.SecretIdentifier{Owner: "owner", Namespace: "main", Key: ""}), + obs: makeGetSecretsObs(&vaultcommon.SecretIdentifier{Owner: pluginTestWorkflowOwner, Namespace: "main", Key: ""}), errSubstr: "", }, { @@ -6998,7 +7010,7 @@ func TestPlugin_ValidateObservation_SecretIdentifierValidation(t *testing.T) { }, { name: "GetSecrets empty namespace in request passes (not validated)", - obs: makeGetSecretsObs(&vaultcommon.SecretIdentifier{Owner: "owner", Namespace: "", Key: "secret"}), + obs: makeGetSecretsObs(&vaultcommon.SecretIdentifier{Owner: pluginTestWorkflowOwner, Namespace: "", Key: "secret"}), errSubstr: "", }, { @@ -7008,12 +7020,12 @@ func TestPlugin_ValidateObservation_SecretIdentifierValidation(t *testing.T) { }, { name: "GetSecrets namespace too long in request passes (not validated)", - obs: makeGetSecretsObs(&vaultcommon.SecretIdentifier{Owner: "owner", Namespace: "toolongnamespace", Key: "secret"}), + obs: makeGetSecretsObs(&vaultcommon.SecretIdentifier{Owner: pluginTestWorkflowOwner, Namespace: "toolongnamespace", Key: "secret"}), errSubstr: "", }, { name: "GetSecrets key too long in request passes (not validated)", - obs: makeGetSecretsObs(&vaultcommon.SecretIdentifier{Owner: "owner", Namespace: "main", Key: "toolongkey123"}), + obs: makeGetSecretsObs(&vaultcommon.SecretIdentifier{Owner: pluginTestWorkflowOwner, Namespace: "main", Key: pluginTestTooLongKey}), errSubstr: "", }, // --- CreateSecrets --- @@ -7024,7 +7036,7 @@ func TestPlugin_ValidateObservation_SecretIdentifierValidation(t *testing.T) { }, { name: "CreateSecrets empty key rejected", - obs: makeCreateSecretsObs(&vaultcommon.SecretIdentifier{Owner: "owner", Namespace: "main", Key: ""}, validCiphertext), + obs: makeCreateSecretsObs(&vaultcommon.SecretIdentifier{Owner: pluginTestWorkflowOwner, Namespace: "main", Key: ""}, validCiphertext), errSubstr: "key cannot be empty", }, { @@ -7034,17 +7046,17 @@ func TestPlugin_ValidateObservation_SecretIdentifierValidation(t *testing.T) { }, { name: "CreateSecrets empty namespace accepted", - obs: makeCreateSecretsObs(&vaultcommon.SecretIdentifier{Owner: "owner", Namespace: "", Key: "secret"}, validCiphertext), + obs: makeCreateSecretsObs(&vaultcommon.SecretIdentifier{Owner: pluginTestWorkflowOwner, Namespace: "", Key: "secret"}, validCiphertext), errSubstr: "", }, { - name: "CreateSecrets owner too long rejected", + name: "CreateSecrets invalid owner rejected", obs: makeCreateSecretsObs(&vaultcommon.SecretIdentifier{Owner: "toolongowner", Namespace: "main", Key: "secret"}, validCiphertext), - errSubstr: "owner exceeds maximum length", + errSubstr: "owner must be a valid Ethereum address", }, { name: "CreateSecrets key too long rejected", - obs: makeCreateSecretsObs(&vaultcommon.SecretIdentifier{Owner: "owner", Namespace: "main", Key: "toolongkey123"}, validCiphertext), + obs: makeCreateSecretsObs(&vaultcommon.SecretIdentifier{Owner: pluginTestWorkflowOwner, Namespace: "main", Key: pluginTestTooLongKey}, validCiphertext), errSubstr: "key exceeds maximum length", }, // --- UpdateSecrets --- @@ -7055,7 +7067,7 @@ func TestPlugin_ValidateObservation_SecretIdentifierValidation(t *testing.T) { }, { name: "UpdateSecrets empty key rejected", - obs: makeUpdateSecretsObs(&vaultcommon.SecretIdentifier{Owner: "owner", Namespace: "main", Key: ""}, validCiphertext), + obs: makeUpdateSecretsObs(&vaultcommon.SecretIdentifier{Owner: pluginTestWorkflowOwner, Namespace: "main", Key: ""}, validCiphertext), errSubstr: "key cannot be empty", }, { @@ -7065,17 +7077,17 @@ func TestPlugin_ValidateObservation_SecretIdentifierValidation(t *testing.T) { }, { name: "UpdateSecrets empty namespace accepted", - obs: makeUpdateSecretsObs(&vaultcommon.SecretIdentifier{Owner: "owner", Namespace: "", Key: "secret"}, validCiphertext), + obs: makeUpdateSecretsObs(&vaultcommon.SecretIdentifier{Owner: pluginTestWorkflowOwner, Namespace: "", Key: "secret"}, validCiphertext), errSubstr: "", }, { name: "UpdateSecrets namespace too long rejected", - obs: makeUpdateSecretsObs(&vaultcommon.SecretIdentifier{Owner: "owner", Namespace: "toolongnamespace", Key: "secret"}, validCiphertext), + obs: makeUpdateSecretsObs(&vaultcommon.SecretIdentifier{Owner: pluginTestWorkflowOwner, Namespace: "toolongnamespace", Key: "secret"}, validCiphertext), errSubstr: "namespace exceeds maximum length", }, { name: "UpdateSecrets key too long rejected", - obs: makeUpdateSecretsObs(&vaultcommon.SecretIdentifier{Owner: "owner", Namespace: "main", Key: "toolongkey123"}, validCiphertext), + obs: makeUpdateSecretsObs(&vaultcommon.SecretIdentifier{Owner: pluginTestWorkflowOwner, Namespace: "main", Key: pluginTestTooLongKey}, validCiphertext), errSubstr: "key exceeds maximum length", }, // --- DeleteSecrets --- @@ -7086,7 +7098,7 @@ func TestPlugin_ValidateObservation_SecretIdentifierValidation(t *testing.T) { }, { name: "DeleteSecrets empty key rejected", - obs: makeDeleteSecretsObs(&vaultcommon.SecretIdentifier{Owner: "owner", Namespace: "main", Key: ""}), + obs: makeDeleteSecretsObs(&vaultcommon.SecretIdentifier{Owner: pluginTestWorkflowOwner, Namespace: "main", Key: ""}), errSubstr: "key cannot be empty", }, { @@ -7096,43 +7108,43 @@ func TestPlugin_ValidateObservation_SecretIdentifierValidation(t *testing.T) { }, { name: "DeleteSecrets empty namespace accepted", - obs: makeDeleteSecretsObs(&vaultcommon.SecretIdentifier{Owner: "owner", Namespace: "", Key: "secret"}), + obs: makeDeleteSecretsObs(&vaultcommon.SecretIdentifier{Owner: pluginTestWorkflowOwner, Namespace: "", Key: "secret"}), errSubstr: "", }, { - name: "DeleteSecrets owner too long rejected", + name: "DeleteSecrets invalid owner rejected", obs: makeDeleteSecretsObs(&vaultcommon.SecretIdentifier{Owner: "toolongowner", Namespace: "main", Key: "secret"}), - errSubstr: "owner exceeds maximum length", + errSubstr: "owner must be a valid Ethereum address", }, { name: "DeleteSecrets key too long rejected", - obs: makeDeleteSecretsObs(&vaultcommon.SecretIdentifier{Owner: "owner", Namespace: "main", Key: "toolongkey123"}), + obs: makeDeleteSecretsObs(&vaultcommon.SecretIdentifier{Owner: pluginTestWorkflowOwner, Namespace: "main", Key: pluginTestTooLongKey}), errSubstr: "key exceeds maximum length", }, // --- ListSecretIdentifiers --- { name: "ListSecretIdentifiers valid owner and namespace passes", - obs: makeListObs("owner", "main"), + obs: makeListObs(pluginTestWorkflowOwner, "main"), errSubstr: "", }, { name: "ListSecretIdentifiers empty owner rejected", obs: makeListObs("", "main"), - errSubstr: "key cannot be empty", + errSubstr: "owner cannot be empty", }, { name: "ListSecretIdentifiers empty namespace accepted", - obs: makeListObs("owner", ""), + obs: makeListObs(pluginTestWorkflowOwner, ""), errSubstr: "", }, { - name: "ListSecretIdentifiers owner too long rejected", + name: "ListSecretIdentifiers invalid owner rejected", obs: makeListObs("toolongowner", "main"), - errSubstr: "owner exceeds maximum length", + errSubstr: "owner must be a valid Ethereum address", }, { name: "ListSecretIdentifiers namespace too long rejected", - obs: makeListObs("owner", "toolongnamespace"), + obs: makeListObs(pluginTestWorkflowOwner, "toolongnamespace"), errSubstr: "namespace exceeds maximum length", }, } @@ -7142,7 +7154,7 @@ func TestPlugin_ValidateObservation_SecretIdentifierValidation(t *testing.T) { // Use small limits (10 bytes) to trigger length errors on identifiers above. r := newTestReportingPlugin( t, - withMaxIdentifierLengths(10, 10, 10), + withMaxIdentifierLengths(64, 10, 64), withOnchainCfg(4, 1), ) @@ -7212,12 +7224,12 @@ func TestPlugin_StateTransition_PendingQueueEnabled_NewQuora_NotGetRequest(t *te rs := newTestReadStore(t, kv) id := &vaultcommon.SecretIdentifier{ - Owner: "owner", + Owner: pluginTestWorkflowOwner, Namespace: "main", Key: "secret", } req := &vaultcommon.ListSecretIdentifiersRequest{ - Owner: "owner", + Owner: pluginTestWorkflowOwner, Namespace: "main", RequestId: "request-id", } @@ -7271,7 +7283,7 @@ func TestPlugin_StateTransition_PendingQueueEnabled_GetRequest(t *testing.T) { rs := newTestReadStore(t, kv) id := &vaultcommon.SecretIdentifier{ - Owner: "owner", + Owner: pluginTestWorkflowOwner, Namespace: "main", Key: "secret", } @@ -7360,7 +7372,7 @@ func TestPlugin_MaxShareSize(t *testing.T) { func makeObservation(t *testing.T, reqType vaultcommon.RequestType, count int) *vaultcommon.Observation { ids := make([]*vaultcommon.SecretIdentifier, count) for i := range ids { - ids[i] = &vaultcommon.SecretIdentifier{Owner: "owner", Namespace: "main", Key: "secret" + string(rune('0'+i))} + ids[i] = &vaultcommon.SecretIdentifier{Owner: pluginTestWorkflowOwner, Namespace: "main", Key: "secret" + string(rune('0'+i))} } switch reqType { @@ -7463,7 +7475,7 @@ func TestPlugin_ValidateObservation_RequestBatchLimit(t *testing.T) { t, withBatchSize(10), withMaxRequestBatchSize(maxRequestBatchSize), - withMaxIdentifierLengths(30, 30, 30), + withMaxIdentifierLengths(64, 30, 30), withKeys(pk, shares[0]), withOnchainCfg(4, 1), ) @@ -7503,20 +7515,20 @@ func TestPlugin_ValidateObservation_ListSecretIdentifiersExceedsMaxSecretsPerOwn t, withBatchSize(10), withMaxSecretsPerOwner(maxSecretsPerOwner), - withMaxIdentifierLengths(30, 30, 30), + withMaxIdentifierLengths(64, 30, 30), withKeys(pk, shares[0]), withOnchainCfg(4, 1), ) listReq := &vaultcommon.ListSecretIdentifiersRequest{ - Owner: "owner", + Owner: pluginTestWorkflowOwner, Namespace: "main", RequestId: "request-1", } identifiers := make([]*vaultcommon.SecretIdentifier, maxSecretsPerOwner+1) for i := range identifiers { - identifiers[i] = &vaultcommon.SecretIdentifier{Owner: "owner", Namespace: "main", Key: fmt.Sprintf("secret%d", i)} + identifiers[i] = &vaultcommon.SecretIdentifier{Owner: pluginTestWorkflowOwner, Namespace: "main", Key: fmt.Sprintf("secret%d", i)} } observation := &vaultcommon.Observation{ diff --git a/core/services/ocr2/plugins/vault/transmitter_test.go b/core/services/ocr2/plugins/vault/transmitter_test.go index 8b09091a563..5c3782f7e83 100644 --- a/core/services/ocr2/plugins/vault/transmitter_test.go +++ b/core/services/ocr2/plugins/vault/transmitter_test.go @@ -15,6 +15,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/capabilities/consensus/requests" "github.com/smartcontractkit/chainlink-common/pkg/services/servicetest" "github.com/smartcontractkit/chainlink/v2/core/capabilities/vault/vaulttypes" + "github.com/smartcontractkit/chainlink/v2/core/capabilities/vault/vaultutils" "github.com/smartcontractkit/chainlink/v2/core/logger" ) @@ -43,7 +44,7 @@ func TestTransmitter(t *testing.T) { err := store.Add(&vaulttypes.Request{ Payload: req1, ResponseChan: ch, - IDVal: vaulttypes.KeyFor(id1), + IDVal: vaultutils.KeyFor(id1), }) require.NoError(t, err) @@ -57,7 +58,7 @@ func TestTransmitter(t *testing.T) { }, } expectedOutcome1 := &vault.Outcome{ - Id: vaulttypes.KeyFor(id1), + Id: vaultutils.KeyFor(id1), RequestType: vault.RequestType_GET_SECRETS, Request: &vault.Outcome_GetSecretsRequest{ GetSecretsRequest: req1, @@ -95,5 +96,5 @@ func TestTransmitter(t *testing.T) { resp := <-ch assert.Equal(t, report.ReportWithInfo.Report, types.Report(resp.Payload)) assert.Equal(t, "REPORT_FORMAT_PROTOBUF", resp.Format) - assert.Equal(t, vaulttypes.KeyFor(id1), resp.ID) + assert.Equal(t, vaultutils.KeyFor(id1), resp.ID) }