diff --git a/cmd/akash/deployment.go b/cmd/akash/deployment.go index 321944254b..84b8deb985 100644 --- a/cmd/akash/deployment.go +++ b/cmd/akash/deployment.go @@ -178,8 +178,8 @@ func closeDeployment(session session.Session, cmd *cobra.Command, args []string) func sendManifestCommand() *cobra.Command { cmd := &cobra.Command{ - Use: "sendmani [manifest] [lease]", - Short: "send manifest to lease provider", + Use: "sendmani [manifest] [deployment]", + Short: "send manifest to all deployment providers", Args: cobra.ExactArgs(2), RunE: session.WithSession( session.RequireKey(session.RequireNode(sendManifest))), @@ -207,24 +207,25 @@ func sendManifest(session session.Session, cmd *cobra.Command, args []string) er return err } - leaseAddr, err := keys.ParseLeasePath(args[1]) + depAddr, err := keys.ParseDeploymentPath(args[1]) if err != nil { return err } - lease, err := session.QueryClient().Lease(session.Ctx(), leaseAddr.ID()) + leases, err := session.QueryClient().DeploymentLeases(session.Ctx(), depAddr.ID()) if err != nil { return err } - provider, err := session.QueryClient().Provider(session.Ctx(), lease.Provider) - if err != nil { - return err - } - - err = manifest.Send(mani, signer, provider, lease.Deployment) - if err != nil { - return err + for _, lease := range leases.Items { + provider, err := session.QueryClient().Provider(session.Ctx(), lease.Provider) + if err != nil { + return err + } + err = manifest.Send(mani, signer, provider, lease.Deployment) + if err != nil { + return err + } } return nil } diff --git a/manifest/manifest_test.go b/manifest/manifest_test.go index e310190c04..9b8420f2a5 100644 --- a/manifest/manifest_test.go +++ b/manifest/manifest_test.go @@ -6,10 +6,13 @@ import ( "net/http/httptest" "testing" + "github.com/ovrclk/akash/provider/session" + qmocks "github.com/ovrclk/akash/query/mocks" "github.com/ovrclk/akash/sdl" "github.com/ovrclk/akash/testutil" "github.com/ovrclk/akash/types" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" crypto "github.com/tendermint/go-crypto" ) @@ -36,7 +39,7 @@ func TestSignManifest(t *testing.T) { assert.Equal(t, mr.Signature, gotmr.Signature) assert.Equal(t, mr.Deployment, gotmr.Deployment) - err = VerifyRequestSig(gotmr) + _, err = verifySignature(gotmr) assert.NoError(t, err) } @@ -55,7 +58,7 @@ func TestVerifySig(t *testing.T) { mr, _, err := SignManifest(mani, signer, deployment) assert.NoError(t, err) - err = VerifyRequestSig(mr) + _, err = verifySignature(mr) assert.NoError(t, err) } @@ -81,7 +84,7 @@ func TestVerifySig_InvalidSig(t *testing.T) { mr.Key = otherMr.Key - err = VerifyRequestSig(mr) + _, err = verifySignature(mr) assert.Error(t, err) } @@ -130,3 +133,61 @@ func TestDoPost(t *testing.T) { err = post(ts.URL, buf) assert.NoError(t, err) } + +func TestVerifyDeploymentTennant(t *testing.T) { + info, kmgr := testutil.NewNamedKey(t) + signer := testutil.Signer(t, kmgr) + tenant := info.Address() + deployment := testutil.Deployment(tenant, 1) + providerID := testutil.Address(t) + provider := testutil.Provider(providerID, 4) + client := &qmocks.Client{} + client.On("Deployment", + mock.Anything, + []byte(deployment.Address)).Return(deployment, nil) + sess := session.New(testutil.Logger(), provider, nil, client) + mani := &types.Manifest{} + mreq, _, err := SignManifest(mani, signer, deployment.Address) + require.NoError(t, err) + err = verifyDeploymentTennant(mreq, sess, info.Address()) + assert.NoError(t, err) +} + +func TestVerifyDeploymentTennant_InvalidKey(t *testing.T) { + info, kmgr := testutil.NewNamedKey(t) + signer := testutil.Signer(t, kmgr) + tenant := info.Address() + deployment := testutil.Deployment(tenant, 1) + providerID := testutil.Address(t) + provider := testutil.Provider(providerID, 4) + client := &qmocks.Client{} + client.On("Deployment", + mock.Anything, + []byte(deployment.Address)).Return(deployment, nil) + sess := session.New(testutil.Logger(), provider, nil, client) + mani := &types.Manifest{} + mreq, _, err := SignManifest(mani, signer, deployment.Address) + require.NoError(t, err) + err = verifyDeploymentTennant(mreq, sess, info.Address()) + assert.NoError(t, err) +} + +func TestVerifyRequest(t *testing.T) { + info, kmgr := testutil.NewNamedKey(t) + signer := testutil.Signer(t, kmgr) + tenant := info.Address() + deployment := testutil.Deployment(tenant, 1) + providerID := testutil.Address(t) + provider := testutil.Provider(providerID, 4) + client := &qmocks.Client{} + client.On("Deployment", + mock.Anything, + []byte(deployment.Address)).Return(deployment, nil) + sess := session.New(testutil.Logger(), provider, nil, client) + mani := &types.Manifest{} + mreq, _, err := SignManifest(mani, signer, deployment.Address) + require.NoError(t, err) + + err = VerifyRequest(mreq, sess) + assert.NoError(t, err) +} diff --git a/manifest/verify.go b/manifest/verify.go index 5d0aad3155..8625a303f1 100644 --- a/manifest/verify.go +++ b/manifest/verify.go @@ -2,16 +2,30 @@ package manifest import ( "bytes" + "context" "errors" "github.com/gogo/protobuf/jsonpb" + "github.com/ovrclk/akash/provider/session" "github.com/ovrclk/akash/types" crypto "github.com/tendermint/go-crypto" ) var ErrInvalidSignature = errors.New("Invalid signature") +var ErrInvalidKey = errors.New("Key is not deployment owner") -func VerifyRequestSig(mr *types.ManifestRequest) error { +func VerifyRequest(mr *types.ManifestRequest, session session.Session) error { + address, err := verifySignature(mr) + if err != nil { + return err + } + if err := verifyDeploymentTennant(mr, session, address); err != nil { + return err + } + return nil +} + +func verifySignature(mr *types.ManifestRequest) (crypto.Address, error) { buf := bytes.Buffer{} marshaler := jsonpb.Marshaler{} baseReq := &types.ManifestRequest{ @@ -19,22 +33,32 @@ func VerifyRequestSig(mr *types.ManifestRequest) error { Manifest: mr.Manifest, } if err := marshaler.Marshal(&buf, baseReq); err != nil { - return err + return nil, err } key, err := crypto.PubKeyFromBytes(mr.Key) if err != nil { - return err + return nil, err } sig, err := crypto.SignatureFromBytes(mr.Signature) if err != nil { - return err + return nil, err } if !key.VerifyBytes(buf.Bytes(), sig) { - return ErrInvalidSignature + return nil, ErrInvalidSignature } + return key.Address(), err +} +func verifyDeploymentTennant(mr *types.ManifestRequest, session session.Session, address crypto.Address) error { + dep, err := session.Query().Deployment(context.TODO(), mr.Deployment) + if err != nil { + return err + } + if eq := bytes.Compare(dep.Tenant, address); eq != 0 { + return ErrInvalidKey + } return nil } diff --git a/provider/manifest/debug.test b/provider/manifest/debug.test new file mode 100755 index 0000000000..6b7a2f8704 Binary files /dev/null and b/provider/manifest/debug.test differ diff --git a/provider/manifest/handler.go b/provider/manifest/handler.go index 4e56ca4b82..d72bc2d7d6 100644 --- a/provider/manifest/handler.go +++ b/provider/manifest/handler.go @@ -146,7 +146,7 @@ loop: case req := <-h.mreqch: // Manifest received. Validate signature, look up state, add ManifestRequest, check state for completion. - if err := manifestUtil.VerifyRequestSig(req.value); err != nil { + if err := manifestUtil.VerifyRequest(req.value, h.session); err != nil { req.ch <- err break } diff --git a/provider/manifest/handler_test.go b/provider/manifest/handler_test.go index 328709180a..7390bf5b24 100644 --- a/provider/manifest/handler_test.go +++ b/provider/manifest/handler_test.go @@ -55,7 +55,10 @@ func TestHandler_leaseFirst(t *testing.T) { type testfn func(manifest.Handler, event.Bus, *types.ManifestRequest, *types.Lease, *types.DeploymentGroup) func withHandler(t *testing.T, fn testfn) { - tenant := testutil.Address(t) + info, kmgr := testutil.NewNamedKey(t) + signer := testutil.Signer(t, kmgr) + tenant := info.Address() + deployment := testutil.Deployment(tenant, 1) dgroup := testutil.DeploymentGroups(deployment.Address, 2).Items[0] order := testutil.Order(deployment.Address, dgroup.Seq, 3) @@ -91,8 +94,6 @@ func withHandler(t *testing.T, fn testfn) { Manifest: mani, } - _, kmgr := testutil.NewNamedKey(t) - signer := testutil.Signer(t, kmgr) mreq, _, err = manifestUtil.SignManifest(mani, signer, deployment.Address) require.NoError(t, err)