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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 13 additions & 7 deletions integration_test/tests/operations/operationkinds_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
59 changes: 47 additions & 12 deletions pkg/signatory/signatory.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,15 @@ import (
"fmt"
"net"
"net/http"
"slices"
"sort"
"strings"
"sync"

"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"
Expand Down Expand Up @@ -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))
Expand All @@ -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))
Expand All @@ -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))
Expand Down Expand Up @@ -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()
Expand Down
84 changes: 84 additions & 0 deletions pkg/signatory/signatory_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
21 changes: 11 additions & 10 deletions signatory.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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, 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
- endorsement
- attestation
block:
endorsement:
attestation:
Loading