Skip to content

Commit

Permalink
Merge pull request #4826 from oasisprotocol/nhynes/backport-4821
Browse files Browse the repository at this point in the history
[BACKPORT/22.1.x] go/oasis-node: allow km private peers
  • Loading branch information
nhynes authored Jun 28, 2022
2 parents 24b1f61 + 5536589 commit fe17af7
Show file tree
Hide file tree
Showing 8 changed files with 69 additions and 8 deletions.
1 change: 1 addition & 0 deletions .changelog/4821.feature.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
go/oasis-node: allow km to have private peers
11 changes: 11 additions & 0 deletions go/oasis-test-runner/oasis/args.go
Original file line number Diff line number Diff line change
Expand Up @@ -408,6 +408,17 @@ func (args *argBuilder) workerKeymanagerMayGenerate() *argBuilder {
return args
}

func (args *argBuilder) workerKeymanagerPrivatePeerPubKeys(peerPKs []string) *argBuilder {
for _, pk := range peerPKs {
args.vec = append(args.vec, Argument{
Name: keymanager.CfgPrivatePeerPubKeys,
Values: []string{pk},
MultiValued: true,
})
}
return args
}

func (args *argBuilder) workerSentryEnabled() *argBuilder {
args.vec = append(args.vec, Argument{Name: workerSentry.CfgEnabled})
return args
Expand Down
10 changes: 10 additions & 0 deletions go/oasis-test-runner/oasis/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ import (
runtimeRegistry "github.com/oasisprotocol/oasis-core/go/runtime/registry"
)

const (
clientIdentitySeedTemplate = "ekiden node client %d"
)

// Client is an Oasis client node.
type Client struct {
*Node
Expand Down Expand Up @@ -70,6 +74,12 @@ func (net *Network) NewClient(cfg *ClientCfg) (*Client, error) {
cfg.RuntimeProvisioner = runtimeRegistry.RuntimeProvisionerUnconfined
}

// Pre-provision the node identity so that we can identify the entity.
err = host.setProvisionedIdentity(false, fmt.Sprintf(clientIdentitySeedTemplate, len(net.clients)))
if err != nil {
return nil, fmt.Errorf("oasis/client: failed to provision node identity: %w", err)
}

client := &Client{
Node: host,
runtimes: cfg.Runtimes,
Expand Down
3 changes: 3 additions & 0 deletions go/oasis-test-runner/oasis/fixture.go
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,8 @@ type KeymanagerFixture struct {
CrashPointsProbability float64 `json:"crash_points_probability,omitempty"`

LogWatcherHandlerFactories []log.WatcherHandlerFactory `json:"-"`

PrivatePeerPubKeys []string `json:"private_peer_pub_keys,omitempty"`
}

// Create instantiates the key manager described by the fixture.
Expand Down Expand Up @@ -353,6 +355,7 @@ func (f *KeymanagerFixture) Create(net *Network) (*Keymanager, error) {
Runtime: runtime,
Policy: policy,
SentryIndices: f.Sentries,
PrivatePeerPubKeys: f.PrivatePeerPubKeys,
})
}

Expand Down
7 changes: 7 additions & 0 deletions go/oasis-test-runner/oasis/keymanager.go
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,8 @@ type Keymanager struct { // nolint: maligned
p2pPort uint16

mayGenerate bool

privatePeerPubKeys []string
}

// KeymanagerCfg is the Oasis key manager provisioning configuration.
Expand All @@ -173,6 +175,9 @@ type KeymanagerCfg struct {
Runtime *Runtime
Policy *KeymanagerPolicy
RuntimeProvisioner string

// PrivatePeerPubKeys is a list of base64-encoded libp2p public keys of peers who may call non-public methods.
PrivatePeerPubKeys []string
}

// IdentityKeyPath returns the paths to the node's identity key.
Expand Down Expand Up @@ -270,6 +275,7 @@ func (km *Keymanager) AddArgs(args *argBuilder) error {
runtimeSGXLoader(km.net.cfg.RuntimeSGXLoaderBinary).
runtimePath(km.runtime).
workerKeymanagerRuntimeID(km.runtime.ID()).
workerKeymanagerPrivatePeerPubKeys(km.privatePeerPubKeys).
configureDebugCrashPoints(km.crashPointsProbability).
tendermintSupplementarySanity(km.supplementarySanityInterval).
appendNetwork(km.net).
Expand Down Expand Up @@ -336,6 +342,7 @@ func (net *Network) NewKeymanager(cfg *KeymanagerCfg) (*Keymanager, error) {
workerClientPort: host.getProvisionedPort(nodePortClient),
p2pPort: host.getProvisionedPort(nodePortP2P),
mayGenerate: len(net.keymanagers) == 0,
privatePeerPubKeys: cfg.PrivatePeerPubKeys,
}

net.keymanagers = append(net.keymanagers, km)
Expand Down
7 changes: 5 additions & 2 deletions go/oasis-test-runner/oasis/oasis.go
Original file line number Diff line number Diff line change
Expand Up @@ -334,8 +334,11 @@ func (n *Node) setProvisionedIdentity(persistTLS bool, seed string) error {
return err
}

if err := n.entity.addNode(nodeSigner); err != nil {
return err
if n.entity != nil {
// Client nodes may need a provisioned identity. They never need an entity, however.
if err := n.entity.addNode(nodeSigner); err != nil {
return err
}
}

n.nodeSigner = nodeSigner
Expand Down
23 changes: 23 additions & 0 deletions go/worker/keymanager/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,23 @@ package keymanager

import (
"context"
"encoding/base64"
"fmt"

core "github.com/libp2p/go-libp2p-core"
flag "github.com/spf13/pflag"
"github.com/spf13/viper"

"github.com/oasisprotocol/oasis-core/go/common"
"github.com/oasisprotocol/oasis-core/go/common/crypto/signature"
"github.com/oasisprotocol/oasis-core/go/common/logging"
"github.com/oasisprotocol/oasis-core/go/common/node"
ias "github.com/oasisprotocol/oasis-core/go/ias/api"
"github.com/oasisprotocol/oasis-core/go/keymanager/api"
"github.com/oasisprotocol/oasis-core/go/runtime/localstorage"
runtimeRegistry "github.com/oasisprotocol/oasis-core/go/runtime/registry"
workerCommon "github.com/oasisprotocol/oasis-core/go/worker/common"
p2pAPI "github.com/oasisprotocol/oasis-core/go/worker/common/p2p"
"github.com/oasisprotocol/oasis-core/go/worker/keymanager/p2p"
"github.com/oasisprotocol/oasis-core/go/worker/registration"
)
Expand All @@ -26,6 +29,8 @@ const (
CfgRuntimeID = "worker.keymanager.runtime.id"
// CfgMayGenerate allows the enclave to generate a master secret.
CfgMayGenerate = "worker.keymanager.may_generate"
// CfgPrivatePeerPks allows adding manual, unadvertised peers that can call protected methods.
CfgPrivatePeerPubKeys = "worker.keymanager.private_peer_pub_keys"
)

// Flags has the configuration flags.
Expand Down Expand Up @@ -59,6 +64,7 @@ func New(
initCh: make(chan struct{}),
initTickerCh: nil,
accessList: make(map[core.PeerID]map[common.Namespace]struct{}),
privatePeers: make(map[core.PeerID]struct{}),
accessListByRuntime: make(map[common.Namespace][]core.PeerID),
commonWorker: commonWorker,
backend: backend,
Expand All @@ -70,6 +76,22 @@ func New(
return w, nil
}

for _, b64pk := range viper.GetStringSlice(CfgPrivatePeerPubKeys) {
pkBytes, err := base64.StdEncoding.DecodeString(b64pk)
if err != nil {
return nil, fmt.Errorf("oasis/keymanager: `%s` is not a base64-encoded public key (%w)", b64pk, err)
}
var pk signature.PublicKey
if err = pk.UnmarshalBinary(pkBytes); err != nil {
return nil, fmt.Errorf("oasis/keymanager: `%s` is not a public key (%w)", b64pk, err)
}
peerID, err := p2pAPI.PublicKeyToPeerID(pk)
if err != nil {
return nil, fmt.Errorf("oasis/keymanager: `%s` can not be converted to a peer id (%w)", b64pk, err)
}
w.privatePeers[peerID] = struct{}{}
}

var runtimeID common.Namespace
if err := runtimeID.UnmarshalHex(viper.GetString(CfgRuntimeID)); err != nil {
return nil, fmt.Errorf("worker/keymanager: failed to parse runtime ID: %w", err)
Expand Down Expand Up @@ -115,6 +137,7 @@ func New(
func init() {
Flags.String(CfgRuntimeID, "", "Key manager Runtime ID")
Flags.Bool(CfgMayGenerate, false, "Key manager may generate new master secret")
Flags.StringSlice(CfgPrivatePeerPubKeys, []string{}, "b64-encoded public keys of unadvertised peers that may call protected methods")

_ = viper.BindPFlags(Flags)
}
15 changes: 9 additions & 6 deletions go/worker/keymanager/worker.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ type Worker struct { // nolint: maligned

accessList map[core.PeerID]map[common.Namespace]struct{}
accessListByRuntime map[common.Namespace][]core.PeerID
privatePeers map[core.PeerID]struct{}

commonWorker *workerCommon.Worker
roleProvider registration.RoleProvider
Expand Down Expand Up @@ -174,12 +175,14 @@ func (w *Worker) CallEnclave(ctx context.Context, data []byte) ([]byte, error) {
case getPublicKeyRequestMethod:
// Anyone can get public keys.
default:
// Defer to access control to check the policy.
w.RLock()
_, allowed := w.accessList[peerID]
w.RUnlock()
if !allowed {
return nil, fmt.Errorf("not authorized")
if _, privatePeered := w.privatePeers[peerID]; !privatePeered {
// Defer to access control to check the policy.
w.RLock()
_, allowed := w.accessList[peerID]
w.RUnlock()
if !allowed {
return nil, fmt.Errorf("not authorized")
}
}
}

Expand Down

0 comments on commit fe17af7

Please sign in to comment.