Skip to content

Commit

Permalink
satellite/wasm: support restricting full access grants to paths
Browse files Browse the repository at this point in the history
Change-Id: Id6d4fa41db068d32e7c0d542d9d8805fba927fc6
  • Loading branch information
jtolio committed Mar 26, 2021
1 parent 527b7eb commit 2ddbaf1
Show file tree
Hide file tree
Showing 7 changed files with 87 additions and 12 deletions.
4 changes: 2 additions & 2 deletions cmd/uplink/cmd/setup.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,12 @@ import (
"github.com/spf13/cobra"
"github.com/zeebo/errs"

"storj.io/common/grant"
"storj.io/private/cfgstruct"
"storj.io/private/process"
"storj.io/storj/cmd/internal/wizard"
"storj.io/uplink"
"storj.io/uplink/backcomp"
"storj.io/uplink/private/access2"
)

var (
Expand Down Expand Up @@ -110,7 +110,7 @@ func cmdSetup(cmd *cobra.Command, args []string) (err error) {
access, err = backcomp.RequestAccessWithPassphraseAndConcurrency(ctx, uplinkConfig, satelliteAddress, apiKeyString, passphrase, uint8(setupCfg.PBKDFConcurrency))
}
if err != nil {
_, err2 := access2.ParseAccess(apiKeyString)
_, err2 := grant.ParseAccess(apiKeyString)
if err2 == nil {
err2 = Error.New("API key appears to be an access grant: try running `uplink import` instead")
}
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ require (
golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e
google.golang.org/api v0.20.0 // indirect
gopkg.in/segmentio/analytics-go.v3 v3.1.0
storj.io/common v0.0.0-20210324105846-0a39fd4f6781
storj.io/common v0.0.0-20210325225810-6cd9934a276a
storj.io/drpc v0.0.20
storj.io/monkit-jaeger v0.0.0-20210225162224-66fb37637bf6
storj.io/private v0.0.0-20210203200143-9d2ec06f0d3c
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -949,8 +949,8 @@ sourcegraph.com/sqs/pbtypes v0.0.0-20180604144634-d3ebe8f20ae4/go.mod h1:ketZ/q3
storj.io/common v0.0.0-20200424175742-65ac59022f4f/go.mod h1:pZyXiIE7bGETIRXtfs0nICqMwp7PM8HqnDuyUeldNA0=
storj.io/common v0.0.0-20201026135900-1aaeec90670b/go.mod h1:GqdmNf3fLm2UZX/7Zr0BLFCJ4gFjgm6eHrk/fnmr5jQ=
storj.io/common v0.0.0-20210208122718-577b1f8a0a0f/go.mod h1:b8XP/TdW8OyTZ/J2BDFOIE9KojSUNZgImBFZI99zS04=
storj.io/common v0.0.0-20210324105846-0a39fd4f6781 h1:T6cGTZ/iTIaj9tUP82frn64JiTWGA/dvNGGASIOOzA4=
storj.io/common v0.0.0-20210324105846-0a39fd4f6781/go.mod h1:Udjm4roy/lhL7PHDWlNVhuVxlohcPiyHMeuigw94SDE=
storj.io/common v0.0.0-20210325225810-6cd9934a276a h1:p0v9vSI6WafbtGQwtH5dA+wsrEJ10hXN9O6r9IF/O4s=
storj.io/common v0.0.0-20210325225810-6cd9934a276a/go.mod h1:Udjm4roy/lhL7PHDWlNVhuVxlohcPiyHMeuigw94SDE=
storj.io/drpc v0.0.11/go.mod h1:TiFc2obNjL9/3isMW1Rpxjy8V9uE0B2HMeMFGiiI7Iw=
storj.io/drpc v0.0.14/go.mod h1:82nfl+6YwRwF6UG31cEWWUqv/FaKvP5SGqUvoqTxCMA=
storj.io/drpc v0.0.16/go.mod h1:zdmQ93nx4Z35u11pQ+GAnBy4DGOK3HJCSOfeh2RryTo=
Expand Down
6 changes: 3 additions & 3 deletions satellite/console/consolewasm/access.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ import (
"crypto/sha256"

"storj.io/common/encryption"
"storj.io/common/grant"
"storj.io/common/macaroon"
"storj.io/common/storj"
"storj.io/common/uuid"
"storj.io/uplink/private/access2"
)

// GenAccessGrant creates a new access grant and returns it serialized form.
Expand All @@ -33,11 +33,11 @@ func GenAccessGrant(satelliteNodeURL, apiKey, encryptionPassphrase, projectID st
return "", err
}

encAccess := access2.NewEncryptionAccessWithDefaultKey(key)
encAccess := grant.NewEncryptionAccessWithDefaultKey(key)
encAccess.SetDefaultPathCipher(storj.EncAESGCM)
encAccess.LimitTo(parsedAPIKey)

accessString, err := (&access2.Access{
accessString, err := (&grant.Access{
SatelliteAddress: satelliteNodeURL,
APIKey: parsedAPIKey,
EncAccess: encAccess,
Expand Down
35 changes: 35 additions & 0 deletions satellite/console/consolewasm/restrict.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// Copyright (C) 2020 Storj Labs, Inc.
// See LICENSE for copying information.

package consolewasm

import (
"strings"

"storj.io/common/grant"
)

// RestrictGrant restricts an access grant with the permissions and paths and returns a new access grant.
func RestrictGrant(accessGrant string, paths []string, permission Permission) (string, error) {
access, err := grant.ParseAccess(accessGrant)
if err != nil {
return "", err
}

prefixes := make([]grant.SharePrefix, 0, len(paths))
for _, path := range paths {
parts := strings.SplitN(path, "/", 2)
prefix := grant.SharePrefix{Bucket: parts[0]}
if len(parts) > 1 {
prefix.Prefix = parts[1]
}
prefixes = append(prefixes, prefix)
}

restricted, err := access.Restrict(grant.Permission(permission), prefixes...)
if err != nil {
return "", err
}

return restricted.Serialize()
}
33 changes: 33 additions & 0 deletions satellite/console/wasm/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ func main() {
js.Global().Set("generateAccessGrant", generateAccessGrant())
js.Global().Set("setAPIKeyPermission", setAPIKeyPermission())
js.Global().Set("newPermission", newPermission())
js.Global().Set("restrictGrant", restrictGrant())
<-make(chan bool)
}

Expand Down Expand Up @@ -81,6 +82,38 @@ func setAPIKeyPermission() js.Func {
}))
}

// restrictGrant restricts an access grant with the permissions and paths and returns a new access grant.
func restrictGrant() js.Func {
return js.FuncOf(responseHandler(func(this js.Value, args []js.Value) (interface{}, error) {
if len(args) < 3 {
return nil, errs.New("not enough arguments. Need 3, but only %d supplied. The order of arguments are: access grant, paths, and permission object.", len(args))
}
accessGrant := args[0].String()

// convert array of paths to go []string type
pathsObj := args[1]
if ok := pathsObj.InstanceOf(js.Global().Get("Array")); !ok {
return nil, errs.New("invalid data type. Expect Array, Got %s", pathsObj.Type().String())
}
paths, err := parseArrayOfStrings(pathsObj)
if err != nil {
return nil, err
}

// convert js permission to go permission type
permissionJS := args[2]
if permissionJS.Type() != js.TypeObject {
return nil, errs.New("invalid argument type. Expect %s, Got %s", js.TypeObject.String(), permissionJS.Type().String())
}
permission, err := parsePermission(permissionJS)
if err != nil {
return nil, err
}

return console.RestrictGrant(accessGrant, paths, permission)
}))
}

// newPermission creates a new permission object.
func newPermission() js.Func {
return js.FuncOf(responseHandler(func(this js.Value, args []js.Value) (interface{}, error) {
Expand Down
15 changes: 11 additions & 4 deletions web/satellite/static/wasm/accessGrant.worker.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,15 +35,14 @@ self.onmessage = function (event) {

self.postMessage(result);
break;
case 'SetPermission':
case 'SetPermission': // fallthrough
case 'RestrictGrant':
const isDownload = data.isDownload;
const isUpload = data.isUpload;
const isList = data.isList;
const isDelete = data.isDelete;
const buckets = data.buckets;
const notBefore = data.notBefore;
const notAfter = data.notAfter;
apiKey = data.apiKey;

let permission = self.newPermission().value;

Expand All @@ -54,7 +53,15 @@ self.onmessage = function (event) {
permission.NotBefore = notBefore;
permission.NotAfter = notAfter;

result = self.setAPIKeyPermission(apiKey, buckets, permission);
if (data.type == "SetPermission") {
const buckets = data.buckets;
apiKey = data.apiKey;
result = self.setAPIKeyPermission(apiKey, buckets, permission);
} else {
const paths = data.paths;
const accessGrant = data.grant;
result = self.restrictGrant(accessGrant, paths, permission);
}

self.postMessage(result);
break;
Expand Down

0 comments on commit 2ddbaf1

Please sign in to comment.