From 6f699adaf24522ef063edcb16a0ca6ad46b23c16 Mon Sep 17 00:00:00 2001 From: Petel__ Date: Tue, 23 Sep 2025 10:19:13 -0700 Subject: [PATCH 1/4] add request and operation kind validation --- pkg/signatory/signatory.go | 59 ++++++++++++++++++----- pkg/signatory/signatory_test.go | 84 +++++++++++++++++++++++++++++++++ 2 files changed, 131 insertions(+), 12 deletions(-) diff --git a/pkg/signatory/signatory.go b/pkg/signatory/signatory.go index 967c6db0..93e61713 100644 --- a/pkg/signatory/signatory.go +++ b/pkg/signatory/signatory.go @@ -10,6 +10,7 @@ import ( "fmt" "net" "net/http" + "slices" "sort" "strings" "sync" @@ -17,6 +18,7 @@ import ( "github.com/ecadlabs/gotez/v2/b58" "github.com/ecadlabs/gotez/v2/crypt" "github.com/ecadlabs/gotez/v2/protocol/core" + proto "github.com/ecadlabs/gotez/v2/protocol/latest" "github.com/ecadlabs/signatory/pkg/auth" "github.com/ecadlabs/signatory/pkg/config" "github.com/ecadlabs/signatory/pkg/errors" @@ -652,6 +654,42 @@ func fixupRequests(req []string) { sort.Strings(req) } +func fixupOperations(ops []string) { + for i, o := range ops { + switch o { + case "endorsement": + ops[i] = "attestation" + case "preendorsement": + ops[i] = "preattestation" + case "double_endorsement_evidence": + ops[i] = "double_attestation_evidence" + case "double_preendorsement_evidence": + ops[i] = "double_preattestation_evidence" + } + } + sort.Strings(ops) +} + +func checkRequestKind(allowedKinds []string) error { + avilKinds := proto.ListSignRequests() + for _, kind := range allowedKinds { + if !slices.Contains(avilKinds, kind) { + return fmt.Errorf("invalid request kind `%s` in `allow` list", kind) + } + } + return nil +} + +func checkOperationKind(allowedKinds []string) error { + avilKinds := append(proto.ListOperations(), proto.ListPseudoOperations()...) + for _, kind := range allowedKinds { + if !slices.Contains(avilKinds, kind) { + return fmt.Errorf("invalid operation kind `%s` in `allow.generic` list", kind) + } + } + return nil +} + // PreparePolicy prepares policy data by hashing keys etc func PreparePolicy(src config.TezosConfig) (out Policy, err error) { policy := make(Policy, len(src)) @@ -671,6 +709,9 @@ func PreparePolicy(src config.TezosConfig) (out Policy, err error) { pol.AllowedRequests = append(pol.AllowedRequests, req) } fixupRequests(pol.AllowedRequests) + if err = checkRequestKind(pol.AllowedRequests); err != nil { + return false + } if ops, ok := v.Allow["generic"]; ok { pol.AllowedOps = make([]string, len(ops)) @@ -682,6 +723,9 @@ func PreparePolicy(src config.TezosConfig) (out Policy, err error) { pol.AllowedRequests = make([]string, len(v.AllowedOperations)) copy(pol.AllowedRequests, v.AllowedOperations) fixupRequests(pol.AllowedRequests) + if err = checkRequestKind(pol.AllowedRequests); err != nil { + return false + } } if v.AllowedKinds != nil { pol.AllowedOps = make([]string, len(v.AllowedKinds)) @@ -710,19 +754,10 @@ func PreparePolicy(src config.TezosConfig) (out Policy, err error) { pipe.Close() } - for i, o := range pol.AllowedOps { - switch o { - case "endorsement": - pol.AllowedOps[i] = "attestation" - case "preendorsement": - pol.AllowedOps[i] = "preattestation" - case "double_endorsement_evidence": - pol.AllowedOps[i] = "double_attestation_evidence" - case "double_preendorsement_evidence": - pol.AllowedOps[i] = "double_preattestation_evidence" - } + fixupOperations(pol.AllowedOps) + if err = checkOperationKind(pol.AllowedOps); err != nil { + return false } - sort.Strings(pol.AllowedOps) if v.AuthorizedKeys != nil { keys := v.AuthorizedKeys.List() diff --git a/pkg/signatory/signatory_test.go b/pkg/signatory/signatory_test.go index 40876ef4..79f2cb8e 100644 --- a/pkg/signatory/signatory_test.go +++ b/pkg/signatory/signatory_test.go @@ -516,3 +516,87 @@ func TestListPublicKeys(t *testing.T) { }) } } + +func TestRequestKindCheck(t *testing.T) { + priv, err := crypt.ParsePrivateKey([]byte(privateKey)) + require.NoError(t, err) + pk := priv.Public() + + tezosCfg := hashmap.NewPublicKeyHashMap([]hashmap.PublicKeyKV[*config.TezosPolicy]{ + { + Key: pk.Hash(), + Val: &config.TezosPolicy{ + Allow: map[string][]string{ + "block": nil, + "foo": nil, // invalid request kind + }, + }, + }, + }) + + _, err = signatory.PreparePolicy(tezosCfg) + require.EqualError(t, err, "invalid request kind `foo` in `allow` list") + + tezosCfgValid := hashmap.NewPublicKeyHashMap([]hashmap.PublicKeyKV[*config.TezosPolicy]{ + { + Key: pk.Hash(), + Val: &config.TezosPolicy{ + Allow: map[string][]string{ + "attestation": nil, + "generic": nil, + "block": nil, + "preendorsement": nil, + "attestation_with_dal": nil, + }, + }, + }, + }) + + _, err = signatory.PreparePolicy(tezosCfgValid) + require.NoError(t, err) +} + +func TestOperationKindCheck(t *testing.T) { + priv, err := crypt.ParsePrivateKey([]byte(privateKey)) + require.NoError(t, err) + pk := priv.Public() + + tezosCfg := hashmap.NewPublicKeyHashMap([]hashmap.PublicKeyKV[*config.TezosPolicy]{ + { + Key: pk.Hash(), + Val: &config.TezosPolicy{ + Allow: map[string][]string{ + "generic": {"transaction", "invalid_op"}, // invalid operation kind included + }, + }, + }, + }) + + _, err = signatory.PreparePolicy(tezosCfg) + require.EqualError(t, err, "invalid operation kind `invalid_op` in `allow.generic` list") + + tezosCfgValid := hashmap.NewPublicKeyHashMap([]hashmap.PublicKeyKV[*config.TezosPolicy]{ + { + Key: pk.Hash(), + Val: &config.TezosPolicy{ + Allow: map[string][]string{ + "generic": { + "transaction", + "delegation", + "origination", + "reveal", + "stake", + "unstake", + "finalize_unstake", + "attestation", + "preendorsement", + "ballot", + }, + }, + }, + }, + }) + + _, err = signatory.PreparePolicy(tezosCfgValid) + require.NoError(t, err) +} From fd1cbb4dbdfb72565afbc3e76e3d9a7546e0c3b3 Mon Sep 17 00:00:00 2001 From: Petel__ Date: Tue, 23 Sep 2025 11:17:04 -0700 Subject: [PATCH 2/4] update operation kinds in tests to reflect changes in proto_022_PsRiotum and proto_023_PtSeouLo --- .../tests/operations/operationkinds_test.go | 20 ++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/integration_test/tests/operations/operationkinds_test.go b/integration_test/tests/operations/operationkinds_test.go index 6b2052f1..6dfba740 100644 --- a/integration_test/tests/operations/operationkinds_test.go +++ b/integration_test/tests/operations/operationkinds_test.go @@ -209,13 +209,19 @@ func TestOperationAllowPolicy(t *testing.T) { } func getAllOps() []string { - return []string{"activate_account", "ballot", "dal_attestation", "dal_publish_slot_header", "delegation", - "double_baking_evidence", "double_endorsement_evidence", "double_preendorsement_evidence", "drain_delegate", - "endorsement", "event", "failing_noop", "increase_paid_storage", "origination", "preendorsement", "proposals", - "register_global_constant", "reveal", "sc_rollup_add_messages", "sc_rollup_cement", - "sc_rollup_execute_outbox_message", "sc_rollup_originate", "sc_rollup_publish", "sc_rollup_recover_bond", - "sc_rollup_refute", "sc_rollup_timeout", "seed_nonce_revelation", "set_deposits_limit", "transaction", - "transfer_ticket", "update_consensus_key", "vdf_revelation", "zk_rollup_origination", "zk_rollup_publish", "zk_rollup_update"} + return []string{ // operations available in both proto_022_PsRiotum and proto_023_PtSeouLo + "activate_account", "attestation", "attestation_with_dal", "attestations_aggregate", + "ballot", "dal_entrapment_evidence", "dal_publish_commitment", "delegation", + "double_baking_evidence", "drain_delegate", "failing_noop", "increase_paid_storage", + "origination", "preattestation", "proposals", "register_global_constant", "reveal", + "seed_nonce_revelation", "set_deposits_limit", "signature_prefix", + "smart_rollup_add_messages", "smart_rollup_cement", + "smart_rollup_execute_outbox_message", "smart_rollup_originate", + "smart_rollup_publish", "smart_rollup_recover_bond", "smart_rollup_refute", + "smart_rollup_timeout", "transaction", "transfer_ticket", "update_consensus_key", + "vdf_revelation", "zk_rollup_origination", "zk_rollup_publish", "zk_rollup_update", + "finalize_unstake", "set_delegate_parameters", "stake", "unstake", + } } func getAllOpsExcluding(exclude []string) []string { From 24e2719e2097844327f771b47b9e4ab06baf7393 Mon Sep 17 00:00:00 2001 From: Petel__ Date: Wed, 24 Sep 2025 09:59:57 -0700 Subject: [PATCH 3/4] update example signatory.yaml to reflect new request kinds and new operation kinds --- signatory.yaml | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/signatory.yaml b/signatory.yaml index f60a5add..9ac4365d 100644 --- a/signatory.yaml +++ b/signatory.yaml @@ -64,17 +64,18 @@ tezos: # purposes. log_payloads: true allow: - # List of [block, endorsement, failing_noop, generic, preendorsement] + # List of [attestation, attestation_with_dal, block, generic, preattestation] generic: # List of - # [activate_account, attestation, attestation_with_dal, ballot, dal_publish_commitment, delegation, double_attestation_evidence, - # double_baking_evidence, double_preattestation_evidence, drain_delegate, failing_noop, finalize_unstake, increase_paid_storage, - # origination, preattestation, proposals, register_global_constant, reveal, seed_nonce_revelation, set_delegate_parameters, - # set_deposits_limit, signature_prefix, smart_rollup_add_messages, smart_rollup_cement, smart_rollup_execute_outbox_message, - # smart_rollup_originate, smart_rollup_publish, smart_rollup_recover_bond, smart_rollup_refute, smart_rollup_timeout, stake, - # transaction, transfer_ticket, unstake, update_consensus_key, vdf_revelation, zk_rollup_origination, zk_rollup_publish, - # zk_rollup_update] + # [activate_account, attestation, attestation_with_dal, attestations_aggregate, ballot, dal_entrapment_evidence, + # dal_publish_commitment, delegation, double_baking_evidence, double_consensus_operation_evidence, drain_delegate, + # failing_noop, finalize_unstake, increase_paid_storage, origination, preattestation, preattestations_aggregate, + # proposals, register_global_constant, reveal, seed_nonce_revelation, set_delegate_parameters, + # set_deposits_limit, signature_prefix, smart_rollup_add_messages, smart_rollup_cement, + # smart_rollup_execute_outbox_message, smart_rollup_originate, smart_rollup_publish, smart_rollup_recover_bond, + # smart_rollup_refute, smart_rollup_timeout, stake, transaction, transfer_ticket, unstake, update_companion_key, + # update_consensus_key, vdf_revelation, zk_rollup_origination, zk_rollup_publish, zk_rollup_update] - transaction - - endorsement + - attestation block: - endorsement: + attestation: From d65702c8ddf8ee8d697869c5632884493400ee22 Mon Sep 17 00:00:00 2001 From: Petel__ Date: Wed, 24 Sep 2025 18:53:53 -0700 Subject: [PATCH 4/4] update generic operation list in example signatory.yaml --- signatory.yaml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/signatory.yaml b/signatory.yaml index 9ac4365d..76790e52 100644 --- a/signatory.yaml +++ b/signatory.yaml @@ -67,13 +67,13 @@ tezos: # List of [attestation, attestation_with_dal, block, generic, preattestation] generic: # List of - # [activate_account, attestation, attestation_with_dal, attestations_aggregate, ballot, dal_entrapment_evidence, - # dal_publish_commitment, delegation, double_baking_evidence, double_consensus_operation_evidence, drain_delegate, - # failing_noop, finalize_unstake, increase_paid_storage, origination, preattestation, preattestations_aggregate, - # proposals, register_global_constant, reveal, seed_nonce_revelation, set_delegate_parameters, - # set_deposits_limit, signature_prefix, smart_rollup_add_messages, smart_rollup_cement, - # smart_rollup_execute_outbox_message, smart_rollup_originate, smart_rollup_publish, smart_rollup_recover_bond, - # smart_rollup_refute, smart_rollup_timeout, stake, transaction, transfer_ticket, unstake, update_companion_key, + # [activate_account, attestations_aggregate, ballot, dal_entrapment_evidence, dal_publish_commitment, + # delegation, double_baking_evidence, double_consensus_operation_evidence, drain_delegate, failing_noop, + # finalize_unstake, increase_paid_storage, origination, preattestations_aggregate, proposals, + # register_global_constant, reveal, seed_nonce_revelation, set_delegate_parameters, set_deposits_limit, + # signature_prefix, smart_rollup_add_messages, smart_rollup_cement, smart_rollup_execute_outbox_message, + # smart_rollup_originate, smart_rollup_publish, smart_rollup_recover_bond, smart_rollup_refute, + # smart_rollup_timeout, stake, transaction, transfer_ticket, unstake, update_companion_key, # update_consensus_key, vdf_revelation, zk_rollup_origination, zk_rollup_publish, zk_rollup_update] - transaction - attestation