diff --git a/.changelog/5764.cfg.md b/.changelog/5764.cfg.md new file mode 100644 index 00000000000..68bd01184c5 --- /dev/null +++ b/.changelog/5764.cfg.md @@ -0,0 +1,5 @@ +Support only `entity_id` to be specified in configuration + +Instead of the need to specify the path to the entire entity descriptor, the +node configuration can now specify only `registration.entity_id`, the entity +public key. diff --git a/go/common/predicates.go b/go/common/predicates.go index 38febfb55ae..d9deaa47a13 100644 --- a/go/common/predicates.go +++ b/go/common/predicates.go @@ -1,12 +1,21 @@ package common -// ExactlyOneTrue returns true iff exactly one of the passed conditions is true. -func ExactlyOneTrue(conds ...bool) bool { +func countTrue(conds ...bool) int { total := 0 for _, c := range conds { if c { total++ } } - return total == 1 + return total +} + +// ExactlyOneTrue returns true iff exactly one of the passed conditions is true. +func ExactlyOneTrue(conds ...bool) bool { + return countTrue(conds...) == 1 +} + +// AtMostOneTrue returns true iff at most one of the passed conditions is true. +func AtMostOneTrue(conds ...bool) bool { + return countTrue(conds...) <= 1 } diff --git a/go/oasis-test-runner/oasis/byzantine.go b/go/oasis-test-runner/oasis/byzantine.go index 68be49be5a6..2a523893ef3 100644 --- a/go/oasis-test-runner/oasis/byzantine.go +++ b/go/oasis-test-runner/oasis/byzantine.go @@ -2,7 +2,6 @@ package oasis import ( "fmt" - "path/filepath" "strconv" beacon "github.com/oasisprotocol/oasis-core/go/beacon/api" @@ -74,8 +73,8 @@ func (worker *Byzantine) ModifyConfig() error { worker.AddSeedNodesToConfig() if !worker.entity.isDebugTestEntity { - dir := worker.entity.dir.String() - worker.Config.Registration.Entity = filepath.Join(dir, "entity.json") + entityID, _ := worker.entity.ID().MarshalText() // Cannot fail. + worker.Config.Registration.EntityID = string(entityID) } return nil diff --git a/go/oasis-test-runner/oasis/compute.go b/go/oasis-test-runner/oasis/compute.go index 3920036e35b..7d4e60557a4 100644 --- a/go/oasis-test-runner/oasis/compute.go +++ b/go/oasis-test-runner/oasis/compute.go @@ -159,8 +159,8 @@ func (worker *Compute) ModifyConfig() error { worker.Config.P2P.Port = worker.p2pPort if !worker.entity.isDebugTestEntity { - dir := worker.entity.dir.String() - worker.Config.Registration.Entity = filepath.Join(dir, "entity.json") + entityID, _ := worker.entity.ID().MarshalText() // Cannot fail. + worker.Config.Registration.EntityID = string(entityID) } worker.Config.Mode = config.ModeCompute diff --git a/go/oasis-test-runner/oasis/keymanager.go b/go/oasis-test-runner/oasis/keymanager.go index 3b3fff1b98b..baf30c4baa8 100644 --- a/go/oasis-test-runner/oasis/keymanager.go +++ b/go/oasis-test-runner/oasis/keymanager.go @@ -288,8 +288,8 @@ func (km *Keymanager) ModifyConfig() error { km.Config.P2P.Port = km.p2pPort if !km.entity.isDebugTestEntity { - dir := km.entity.dir.String() - km.Config.Registration.Entity = filepath.Join(dir, "entity.json") + entityID, _ := km.entity.ID().MarshalText() // Cannot fail. + km.Config.Registration.EntityID = string(entityID) } km.Config.Mode = config.ModeKeyManager diff --git a/go/oasis-test-runner/oasis/validator.go b/go/oasis-test-runner/oasis/validator.go index 51f19ad9ad6..4369c492b3e 100644 --- a/go/oasis-test-runner/oasis/validator.go +++ b/go/oasis-test-runner/oasis/validator.go @@ -93,8 +93,8 @@ func (val *Validator) ModifyConfig() error { val.Config.P2P.Port = val.p2pPort if !val.entity.isDebugTestEntity { - dir := val.entity.dir.String() - val.Config.Registration.Entity = filepath.Join(dir, "entity.json") + entityID, _ := val.entity.ID().MarshalText() // Cannot fail. + val.Config.Registration.EntityID = string(entityID) } if len(val.sentries) > 0 { diff --git a/go/worker/registration/config/config.go b/go/worker/registration/config/config.go index e3f1bf9753c..63b857024aa 100644 --- a/go/worker/registration/config/config.go +++ b/go/worker/registration/config/config.go @@ -1,20 +1,46 @@ // Package config implements global configuration options. package config +import ( + "fmt" + + "github.com/oasisprotocol/oasis-core/go/common" + "github.com/oasisprotocol/oasis-core/go/common/crypto/signature" +) + // Config is the registration worker configuration structure. type Config struct { // Entity to use as the node owner in registrations (path to the JSON file). Entity string `yaml:"entity"` + + // EntityID to use as the node owner in registrations (public key). + EntityID string `yaml:"entity_id"` } // Validate validates the configuration settings. func (c *Config) Validate() error { + // Ensure only one of Entity/EntityID is set. + if !common.AtMostOneTrue( + c.Entity != "", + c.EntityID != "", + ) { + return fmt.Errorf("only one of `entity` and `entity_id` must be set") + } + + // Ensure the entity ID is valid if passed. + if c.EntityID != "" { + var id signature.PublicKey + if err := id.UnmarshalText([]byte(c.EntityID)); err != nil { + return fmt.Errorf("malformed entity ID: %w", err) + } + } return nil } // DefaultConfig returns the default configuration settings. func DefaultConfig() Config { return Config{ - Entity: "", + Entity: "", + EntityID: "", } } diff --git a/go/worker/registration/worker.go b/go/worker/registration/worker.go index 1ccc3ece6d5..9c6179831c0 100644 --- a/go/worker/registration/worker.go +++ b/go/worker/registration/worker.go @@ -1025,24 +1025,34 @@ func GetRegistrationSigner(identity *identity.Identity) (signature.PublicKey, si return testEntity.ID, testSigner, nil } - // Load the registration entity descriptor. - f := config.GlobalConfig.Registration.Entity - if f == "" { + // Determine the owning entity ID. + cfgEntityFn := config.GlobalConfig.Registration.Entity + cfgEntityID := config.GlobalConfig.Registration.EntityID + + switch { + case cfgEntityFn != "": + // Attempt to load the entity descriptor. + entity, err := entity.LoadDescriptor(cfgEntityFn) + if err != nil { + return defaultPk, nil, fmt.Errorf("worker/registration: failed to load entity descriptor: %w", err) + } + + return entity.ID, identity.NodeSigner, nil + case cfgEntityID != "": + // Attempt to parse the entity ID. + var entityID signature.PublicKey + if err := entityID.UnmarshalText([]byte(cfgEntityID)); err != nil { + return defaultPk, nil, fmt.Errorf("worker/registration: malformed entity ID: %w", err) + } + + return entityID, identity.NodeSigner, nil + default: // TODO: There are certain configurations (eg: the test client) that // spin up workers, which require a registration worker, but don't // need it, and do not have an owning entity. The registration worker // should not be initialized in this case. return defaultPk, nil, nil } - - // Attempt to load the entity descriptor. - entity, err := entity.LoadDescriptor(f) - if err != nil { - return defaultPk, nil, fmt.Errorf("worker/registration: failed to load entity descriptor: %w", err) - } - - // Registrations are always node-signed. - return entity.ID, identity.NodeSigner, nil } // New constructs a new worker node registration service.