{satellite/console,web/satellite}: get project salt from satellite
Add getSalt to projects api. Add action, GET_SALT, on Store Projects module to make the api request and return the salt string everywhere in the web app that generates an access grant. The Wasm code which is used to create the access grant has been changed to decode the salt as a base64 encoded string. The names of the function calls in the changed Wasm code have also been changed to ensure that access grant creation fails if JS access grant worker code and Wasm code are not the same version. https://github.com/storj/storj-private/issues/64 Change-Id: Ia2bc4cbadad84b066ca1882b042a3f0bb13c783a
This commit is contained in:
parent
1887660678
commit
98fed4bc30
@ -5,7 +5,9 @@ package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/sha256"
|
||||
"database/sql"
|
||||
"encoding/base64"
|
||||
"errors"
|
||||
|
||||
"github.com/zeebo/errs"
|
||||
@ -124,7 +126,10 @@ func GetTestApiKey(satelliteId string) (string, error) {
|
||||
return "", errs.Wrap(err)
|
||||
}
|
||||
|
||||
accessGrant, err := consolewasm.GenAccessGrant(satelliteId, key.Serialize(), password, projectID.String())
|
||||
idHash := sha256.Sum256(projectID[:])
|
||||
base64Salt := base64.StdEncoding.EncodeToString(idHash[:])
|
||||
|
||||
accessGrant, err := consolewasm.GenAccessGrant(satelliteId, key.Serialize(), password, base64Salt)
|
||||
if err != nil {
|
||||
return "", errs.Wrap(err)
|
||||
}
|
||||
|
@ -4,23 +4,22 @@
|
||||
package consolewasm
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"encoding/base64"
|
||||
|
||||
"storj.io/common/encryption"
|
||||
"storj.io/common/grant"
|
||||
"storj.io/common/macaroon"
|
||||
"storj.io/common/storj"
|
||||
"storj.io/common/uuid"
|
||||
)
|
||||
|
||||
// GenAccessGrant creates a new access grant and returns it serialized form.
|
||||
func GenAccessGrant(satelliteNodeURL, apiKey, encryptionPassphrase, projectID string) (string, error) {
|
||||
func GenAccessGrant(satelliteNodeURL, apiKey, encryptionPassphrase, base64EncodedSalt string) (string, error) {
|
||||
parsedAPIKey, err := macaroon.ParseAPIKey(apiKey)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
key, err := DeriveRootKey(encryptionPassphrase, projectID)
|
||||
key, err := DeriveRootKey(encryptionPassphrase, base64EncodedSalt)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
@ -41,14 +40,11 @@ func GenAccessGrant(satelliteNodeURL, apiKey, encryptionPassphrase, projectID st
|
||||
}
|
||||
|
||||
// DeriveRootKey derives the root key portion of the access grant.
|
||||
func DeriveRootKey(encryptionPassphrase, projectID string) (*storj.Key, error) {
|
||||
id, err := uuid.FromString(projectID)
|
||||
func DeriveRootKey(encryptionPassphrase, base64EncodedSalt string) (*storj.Key, error) {
|
||||
const concurrency = 8
|
||||
saltBytes, err := base64.StdEncoding.DecodeString(base64EncodedSalt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
const concurrency = 8
|
||||
salt := sha256.Sum256(id[:])
|
||||
|
||||
return encryption.DeriveRootKey([]byte(encryptionPassphrase), salt[:], "", concurrency)
|
||||
return encryption.DeriveRootKey([]byte(encryptionPassphrase), saltBytes, "", concurrency)
|
||||
}
|
||||
|
@ -4,6 +4,13 @@
|
||||
package consolewasm_test
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/http/cookiejar"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
@ -20,16 +27,27 @@ func TestGenerateAccessGrant(t *testing.T) {
|
||||
testplanet.Run(t, testplanet.Config{
|
||||
SatelliteCount: 1, StorageNodeCount: 0, UplinkCount: 1,
|
||||
}, func(t *testing.T, ctx *testcontext.Context, planet *testplanet.Planet) {
|
||||
client := newTestClient(t, ctx, planet)
|
||||
user := client.defaultUser()
|
||||
uplinkPeer := planet.Uplinks[0]
|
||||
projectID := uplinkPeer.Projects[0].ID
|
||||
|
||||
client.login(user.email, user.password)
|
||||
|
||||
resp, bodyString := client.request(http.MethodGet, fmt.Sprintf("/projects/%s/salt", projectID.String()), nil)
|
||||
require.Equal(t, http.StatusOK, resp.StatusCode)
|
||||
|
||||
var b64Salt string
|
||||
require.NoError(t, json.Unmarshal([]byte(bodyString), &b64Salt))
|
||||
|
||||
satellitePeer := planet.Satellites[0]
|
||||
satelliteNodeURL := satellitePeer.NodeURL().String()
|
||||
|
||||
uplinkPeer := planet.Uplinks[0]
|
||||
apiKeyString := uplinkPeer.Projects[0].APIKey
|
||||
projectID := uplinkPeer.Projects[0].ID.String()
|
||||
|
||||
passphrase := "supersecretpassphrase"
|
||||
|
||||
wasmAccessString, err := console.GenAccessGrant(satelliteNodeURL, apiKeyString, passphrase, projectID)
|
||||
wasmAccessString, err := console.GenAccessGrant(satelliteNodeURL, apiKeyString, passphrase, b64Salt)
|
||||
require.NoError(t, err)
|
||||
|
||||
uplinkCliAccess, err := uplinkPeer.Config.RequestAccessWithPassphrase(ctx, satelliteNodeURL, apiKeyString, passphrase)
|
||||
@ -50,7 +68,7 @@ func TestDefaultAccess(t *testing.T) {
|
||||
satelliteNodeURL := satellitePeer.NodeURL().String()
|
||||
uplinkPeer := planet.Uplinks[0]
|
||||
APIKey := uplinkPeer.APIKey[satellitePeer.ID()]
|
||||
projectID := uplinkPeer.Projects[0].ID.String()
|
||||
projectID := uplinkPeer.Projects[0].ID
|
||||
require.Equal(t, 1, len(uplinkPeer.Projects))
|
||||
|
||||
passphrase := "supersecretpassphrase"
|
||||
@ -58,8 +76,18 @@ func TestDefaultAccess(t *testing.T) {
|
||||
testfilename := "file.txt"
|
||||
testdata := []byte("fun data")
|
||||
|
||||
client := newTestClient(t, ctx, planet)
|
||||
user := client.defaultUser()
|
||||
client.login(user.email, user.password)
|
||||
|
||||
resp, bodyString := client.request(http.MethodGet, fmt.Sprintf("/projects/%s/salt", projectID.String()), nil)
|
||||
require.Equal(t, http.StatusOK, resp.StatusCode)
|
||||
|
||||
var b64Salt string
|
||||
require.NoError(t, json.Unmarshal([]byte(bodyString), &b64Salt))
|
||||
|
||||
// Create an access with the console access grant code that allows full access.
|
||||
access, err := console.GenAccessGrant(satelliteNodeURL, APIKey.Serialize(), passphrase, projectID)
|
||||
access, err := console.GenAccessGrant(satelliteNodeURL, APIKey.Serialize(), passphrase, b64Salt)
|
||||
require.NoError(t, err)
|
||||
newAccess, err := uplink.ParseAccess(access)
|
||||
require.NoError(t, err)
|
||||
@ -80,3 +108,94 @@ func TestDefaultAccess(t *testing.T) {
|
||||
require.NoError(t, uplinkPeer.DeleteBucket(ctx, satellitePeer, testbucket1))
|
||||
})
|
||||
}
|
||||
|
||||
type testClient struct {
|
||||
t *testing.T
|
||||
ctx *testcontext.Context
|
||||
planet *testplanet.Planet
|
||||
client *http.Client
|
||||
}
|
||||
|
||||
func newTestClient(t *testing.T, ctx *testcontext.Context, planet *testplanet.Planet) testClient {
|
||||
jar, err := cookiejar.New(nil)
|
||||
require.NoError(t, err)
|
||||
return testClient{t: t, ctx: ctx, planet: planet, client: &http.Client{Jar: jar}}
|
||||
}
|
||||
|
||||
type registeredUser struct {
|
||||
email string
|
||||
password string
|
||||
}
|
||||
|
||||
func (testClient *testClient) request(method string, path string, data io.Reader) (resp Response, body string) {
|
||||
req, err := http.NewRequestWithContext(testClient.ctx, method, testClient.url(path), data)
|
||||
require.NoError(testClient.t, err)
|
||||
req.Header = map[string][]string{
|
||||
"sec-ch-ua": {`" Not A;Brand";v="99"`, `"Chromium";v="90"`, `"Google Chrome";v="90"`},
|
||||
"sec-ch-ua-mobile": {"?0"},
|
||||
"User-Agent": {"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36"},
|
||||
"Content-Type": {"application/json"},
|
||||
"Accept": {"*/*"},
|
||||
}
|
||||
return testClient.do(req)
|
||||
}
|
||||
|
||||
// Response is a wrapper for http.Request to prevent false-positive with bodyclose check.
|
||||
type Response struct{ *http.Response }
|
||||
|
||||
func (testClient *testClient) do(req *http.Request) (_ Response, body string) {
|
||||
resp, err := testClient.client.Do(req)
|
||||
require.NoError(testClient.t, err)
|
||||
|
||||
data, err := ioutil.ReadAll(resp.Body)
|
||||
require.NoError(testClient.t, err)
|
||||
require.NoError(testClient.t, resp.Body.Close())
|
||||
return Response{resp}, string(data)
|
||||
}
|
||||
|
||||
func (testClient *testClient) url(suffix string) string {
|
||||
return testClient.planet.Satellites[0].ConsoleURL() + "/api/v0" + suffix
|
||||
}
|
||||
|
||||
func (testClient *testClient) toJSON(v interface{}) io.Reader {
|
||||
data, err := json.Marshal(v)
|
||||
require.NoError(testClient.t, err)
|
||||
return strings.NewReader(string(data))
|
||||
}
|
||||
|
||||
func (testClient *testClient) defaultUser() registeredUser {
|
||||
user := testClient.planet.Uplinks[0].User[testClient.planet.Satellites[0].ID()]
|
||||
return registeredUser{
|
||||
email: user.Email,
|
||||
password: user.Password,
|
||||
}
|
||||
}
|
||||
|
||||
func (testClient *testClient) login(email, password string) Response {
|
||||
resp, body := testClient.request(
|
||||
http.MethodPost, "/auth/token",
|
||||
testClient.toJSON(map[string]string{
|
||||
"email": email,
|
||||
"password": password,
|
||||
}))
|
||||
cookie := findCookie(resp, "_tokenKey")
|
||||
require.NotNil(testClient.t, cookie)
|
||||
|
||||
var tokenInfo struct {
|
||||
Token string `json:"token"`
|
||||
}
|
||||
require.NoError(testClient.t, json.Unmarshal([]byte(body), &tokenInfo))
|
||||
require.Equal(testClient.t, http.StatusOK, resp.StatusCode)
|
||||
require.Equal(testClient.t, tokenInfo.Token, cookie.Value)
|
||||
|
||||
return resp
|
||||
}
|
||||
|
||||
func findCookie(response Response, name string) *http.Cookie {
|
||||
for _, c := range response.Cookies() {
|
||||
if c.Name == name {
|
||||
return c
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -4,8 +4,10 @@
|
||||
package consolewasm_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
@ -26,7 +28,7 @@ func TestSetPermissionWithBuckets(t *testing.T) {
|
||||
uplinkPeer := planet.Uplinks[0]
|
||||
APIKey := uplinkPeer.APIKey[satellitePeer.ID()]
|
||||
apiKeyString := APIKey.Serialize()
|
||||
projectID := uplinkPeer.Projects[0].ID.String()
|
||||
projectID := uplinkPeer.Projects[0].ID
|
||||
require.Equal(t, 1, len(uplinkPeer.Projects))
|
||||
passphrase := "supersecretpassphrase"
|
||||
|
||||
@ -80,7 +82,18 @@ func TestSetPermissionWithBuckets(t *testing.T) {
|
||||
}
|
||||
restrictedKey, err := consolewasm.SetPermission(apiKeyString, buckets, readOnlyPermission)
|
||||
require.NoError(t, err)
|
||||
restrictedAccessGrant, err := consolewasm.GenAccessGrant(satelliteNodeURL, restrictedKey.Serialize(), passphrase, projectID)
|
||||
|
||||
client := newTestClient(t, ctx, planet)
|
||||
user := client.defaultUser()
|
||||
client.login(user.email, user.password)
|
||||
|
||||
resp, bodyString := client.request(http.MethodGet, fmt.Sprintf("/projects/%s/salt", projectID.String()), nil)
|
||||
require.Equal(t, http.StatusOK, resp.StatusCode)
|
||||
|
||||
var b64Salt string
|
||||
require.NoError(t, json.Unmarshal([]byte(bodyString), &b64Salt))
|
||||
|
||||
restrictedAccessGrant, err := consolewasm.GenAccessGrant(satelliteNodeURL, restrictedKey.Serialize(), passphrase, b64Salt)
|
||||
require.NoError(t, err)
|
||||
restrictedAccess, err := uplink.ParseAccess(restrictedAccessGrant)
|
||||
require.NoError(t, err)
|
||||
@ -126,7 +139,17 @@ func TestSetPermission_Uplink(t *testing.T) {
|
||||
require.NoError(t, uplinkPeer.Upload(ctx, satellitePeer, testbucket2, testfilename1, testdata))
|
||||
require.NoError(t, uplinkPeer.Upload(ctx, satellitePeer, testbucket2, testfilename2, testdata))
|
||||
|
||||
withAccessKey(ctx, t, planet, passphrase, "only delete", []string{}, consolewasm.Permission{AllowDelete: true}, func(t *testing.T, project *uplink.Project) {
|
||||
client := newTestClient(t, ctx, planet)
|
||||
user := client.defaultUser()
|
||||
client.login(user.email, user.password)
|
||||
|
||||
resp, bodyString := client.request(http.MethodGet, fmt.Sprintf("/projects/%s/salt", uplinkPeer.Projects[0].ID.String()), nil)
|
||||
require.Equal(t, http.StatusOK, resp.StatusCode)
|
||||
|
||||
var b64Salt string
|
||||
require.NoError(t, json.Unmarshal([]byte(bodyString), &b64Salt))
|
||||
|
||||
withAccessKey(ctx, t, planet, passphrase, b64Salt, "only delete", []string{}, consolewasm.Permission{AllowDelete: true}, func(t *testing.T, project *uplink.Project) {
|
||||
// All operation except delete should be restricted
|
||||
_, err = project.CreateBucket(ctx, testbucket2)
|
||||
require.True(t, errors.Is(err, uplink.ErrPermissionDenied))
|
||||
@ -157,7 +180,7 @@ func TestSetPermission_Uplink(t *testing.T) {
|
||||
require.Error(t, err)
|
||||
})
|
||||
|
||||
withAccessKey(ctx, t, planet, passphrase, "only list", []string{testbucket1}, consolewasm.Permission{AllowList: true}, func(t *testing.T, project *uplink.Project) {
|
||||
withAccessKey(ctx, t, planet, passphrase, b64Salt, "only list", []string{testbucket1}, consolewasm.Permission{AllowList: true}, func(t *testing.T, project *uplink.Project) {
|
||||
// All operation except list inside testbucket1 should be restricted
|
||||
_, err = project.CreateBucket(ctx, testbucket2)
|
||||
require.True(t, errors.Is(err, uplink.ErrPermissionDenied))
|
||||
@ -186,7 +209,7 @@ func TestSetPermission_Uplink(t *testing.T) {
|
||||
require.True(t, errors.Is(err, uplink.ErrPermissionDenied))
|
||||
})
|
||||
|
||||
withAccessKey(ctx, t, planet, passphrase, "only upload", []string{testbucket1}, consolewasm.Permission{AllowUpload: true}, func(t *testing.T, project *uplink.Project) {
|
||||
withAccessKey(ctx, t, planet, passphrase, b64Salt, "only upload", []string{testbucket1}, consolewasm.Permission{AllowUpload: true}, func(t *testing.T, project *uplink.Project) {
|
||||
// All operation except upload to the testbucket1 should be restricted
|
||||
_, err = project.CreateBucket(ctx, testbucket2)
|
||||
require.True(t, errors.Is(err, uplink.ErrPermissionDenied))
|
||||
@ -215,7 +238,7 @@ func TestSetPermission_Uplink(t *testing.T) {
|
||||
require.True(t, errors.Is(err, uplink.ErrPermissionDenied))
|
||||
})
|
||||
|
||||
withAccessKey(ctx, t, planet, passphrase, "only download", []string{testbucket1}, consolewasm.Permission{AllowDownload: true}, func(t *testing.T, project *uplink.Project) {
|
||||
withAccessKey(ctx, t, planet, passphrase, b64Salt, "only download", []string{testbucket1}, consolewasm.Permission{AllowDownload: true}, func(t *testing.T, project *uplink.Project) {
|
||||
// All operation except download from testbucket1 should be restricted
|
||||
_, err = project.CreateBucket(ctx, testbucket2)
|
||||
require.True(t, errors.Is(err, uplink.ErrPermissionDenied))
|
||||
@ -244,7 +267,7 @@ func TestSetPermission_Uplink(t *testing.T) {
|
||||
require.True(t, errors.Is(err, uplink.ErrPermissionDenied))
|
||||
})
|
||||
|
||||
withAccessKey(ctx, t, planet, passphrase, "not after", []string{}, consolewasm.Permission{
|
||||
withAccessKey(ctx, t, planet, passphrase, b64Salt, "not after", []string{}, consolewasm.Permission{
|
||||
AllowDownload: true,
|
||||
AllowUpload: true,
|
||||
AllowList: true,
|
||||
@ -278,7 +301,7 @@ func TestSetPermission_Uplink(t *testing.T) {
|
||||
require.True(t, errors.Is(err, uplink.ErrPermissionDenied))
|
||||
})
|
||||
|
||||
withAccessKey(ctx, t, planet, passphrase, "not before", []string{}, consolewasm.Permission{
|
||||
withAccessKey(ctx, t, planet, passphrase, b64Salt, "not before", []string{}, consolewasm.Permission{
|
||||
AllowDownload: true,
|
||||
AllowUpload: true,
|
||||
AllowList: true,
|
||||
@ -312,7 +335,7 @@ func TestSetPermission_Uplink(t *testing.T) {
|
||||
require.True(t, errors.Is(err, uplink.ErrPermissionDenied))
|
||||
})
|
||||
|
||||
withAccessKey(ctx, t, planet, passphrase, "all", []string{}, consolewasm.Permission{
|
||||
withAccessKey(ctx, t, planet, passphrase, b64Salt, "all", []string{}, consolewasm.Permission{
|
||||
AllowDownload: true,
|
||||
AllowUpload: true,
|
||||
AllowList: true,
|
||||
@ -368,7 +391,7 @@ func getAllBuckets(ctx *testcontext.Context, project *uplink.Project) []*uplink.
|
||||
return buckets
|
||||
}
|
||||
|
||||
func withAccessKey(ctx context.Context, t *testing.T, planet *testplanet.Planet, passphrase string, testname string, bucket []string, permissions consolewasm.Permission, fn func(t *testing.T, uplink *uplink.Project)) {
|
||||
func withAccessKey(ctx *testcontext.Context, t *testing.T, planet *testplanet.Planet, passphrase, salt, testname string, bucket []string, permissions consolewasm.Permission, fn func(t *testing.T, uplink *uplink.Project)) {
|
||||
t.Run(testname, func(t *testing.T) {
|
||||
upl := planet.Uplinks[0]
|
||||
sat := planet.Satellites[0]
|
||||
@ -377,7 +400,7 @@ func withAccessKey(ctx context.Context, t *testing.T, planet *testplanet.Planet,
|
||||
restrictedKey, err := consolewasm.SetPermission(apikey.Serialize(), bucket, permissions)
|
||||
require.NoError(t, err)
|
||||
|
||||
restrictedGrant, err := consolewasm.GenAccessGrant(sat.NodeURL().String(), restrictedKey.Serialize(), passphrase, upl.Projects[0].ID.String())
|
||||
restrictedGrant, err := consolewasm.GenAccessGrant(sat.NodeURL().String(), restrictedKey.Serialize(), passphrase, salt)
|
||||
require.NoError(t, err)
|
||||
|
||||
access, err := uplink.ParseAccess(restrictedGrant)
|
||||
|
@ -19,8 +19,8 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
js.Global().Set("deriveAndEncryptRootKey", deriveAndEncryptRootKey())
|
||||
js.Global().Set("generateAccessGrant", generateAccessGrant())
|
||||
js.Global().Set("deriveAndAESEncryptRootKey", deriveAndEncryptRootKey())
|
||||
js.Global().Set("generateNewAccessGrant", generateAccessGrant())
|
||||
js.Global().Set("setAPIKeyPermission", setAPIKeyPermission())
|
||||
js.Global().Set("newPermission", newPermission())
|
||||
js.Global().Set("restrictGrant", restrictGrant())
|
||||
|
@ -234,6 +234,15 @@ export class ProjectsApiGql extends BaseGql implements ProjectsApi {
|
||||
throw new Error('Can not get project daily usage');
|
||||
}
|
||||
|
||||
public async getSalt(projectId: string): Promise<string> {
|
||||
const path = `${this.ROOT_PATH}/${projectId}/salt`;
|
||||
const response = await this.http.get(path);
|
||||
if (response.ok) {
|
||||
return await response.json();
|
||||
}
|
||||
throw new Error('Can not get project salt');
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch owned projects.
|
||||
*
|
||||
|
@ -220,11 +220,13 @@ export default class CreateAccessModal extends Vue {
|
||||
// creates access credentials
|
||||
const satelliteNodeURL = MetaUtils.getMetaContent('satellite-nodeurl');
|
||||
|
||||
const salt = await this.$store.dispatch(PROJECTS_ACTIONS.GET_SALT, this.$store.getters.selectedProject.id);
|
||||
|
||||
this.worker.postMessage({
|
||||
'type': 'GenerateAccess',
|
||||
'apiKey': this.restrictedKey,
|
||||
'passphrase': this.passphrase,
|
||||
'projectID': this.$store.getters.selectedProject.id,
|
||||
'salt': salt,
|
||||
'satelliteNodeURL': satelliteNodeURL,
|
||||
});
|
||||
|
||||
|
@ -90,6 +90,7 @@ import { RouteConfig } from '@/router';
|
||||
import { MetaUtils } from '@/utils/meta';
|
||||
import { AnalyticsEvent } from '@/utils/constants/analyticsEventNames';
|
||||
import { AnalyticsHttpApi } from '@/api/analytics';
|
||||
import { PROJECTS_ACTIONS } from '@/store/modules/projects';
|
||||
|
||||
import VButton from '@/components/common/VButton.vue';
|
||||
import VInput from '@/components/common/VInput.vue';
|
||||
@ -186,12 +187,13 @@ export default class CreatePassphraseStep extends Vue {
|
||||
await this.analytics.eventTriggered(AnalyticsEvent.PASSPHRASE_CREATED);
|
||||
|
||||
const satelliteNodeURL: string = MetaUtils.getMetaContent('satellite-nodeurl');
|
||||
const salt = await this.$store.dispatch(PROJECTS_ACTIONS.GET_SALT, this.$store.getters.selectedProject.id);
|
||||
|
||||
this.worker.postMessage({
|
||||
'type': 'GenerateAccess',
|
||||
'apiKey': this.restrictedKey,
|
||||
'passphrase': this.passphrase,
|
||||
'projectID': this.$store.getters.selectedProject.id,
|
||||
'salt': salt,
|
||||
'satelliteNodeURL': satelliteNodeURL,
|
||||
});
|
||||
|
||||
|
@ -29,6 +29,7 @@ import { Component, Vue } from 'vue-property-decorator';
|
||||
import { RouteConfig } from '@/router';
|
||||
import { MetaUtils } from '@/utils/meta';
|
||||
import { AnalyticsHttpApi } from '@/api/analytics';
|
||||
import { PROJECTS_ACTIONS } from '@/store/modules/projects';
|
||||
|
||||
import VInput from '@/components/common/VInput.vue';
|
||||
import VButton from '@/components/common/VButton.vue';
|
||||
@ -98,12 +99,13 @@ export default class EnterPassphraseStep extends Vue {
|
||||
this.isLoading = true;
|
||||
|
||||
const satelliteNodeURL = MetaUtils.getMetaContent('satellite-nodeurl');
|
||||
const salt = await this.$store.dispatch(PROJECTS_ACTIONS.GET_SALT, this.$store.getters.selectedProject.id);
|
||||
|
||||
this.worker.postMessage({
|
||||
'type': 'GenerateAccess',
|
||||
'apiKey': this.restrictedKey,
|
||||
'passphrase': this.passphrase,
|
||||
'projectID': this.$store.getters.selectedProject.id,
|
||||
'salt': salt,
|
||||
'satelliteNodeURL': satelliteNodeURL,
|
||||
});
|
||||
|
||||
|
@ -56,6 +56,7 @@ import { MetaUtils } from '@/utils/meta';
|
||||
import { AccessGrant, EdgeCredentials } from '@/types/accessGrants';
|
||||
import { ACCESS_GRANTS_ACTIONS } from '@/store/modules/accessGrants';
|
||||
import { AnalyticsHttpApi } from '@/api/analytics';
|
||||
import { PROJECTS_ACTIONS } from '@/store/modules/projects';
|
||||
|
||||
import VModal from '@/components/common/VModal.vue';
|
||||
import VInput from '@/components/common/VInput.vue';
|
||||
@ -147,12 +148,14 @@ export default class OpenBucketModal extends Vue {
|
||||
throw new Error(grantEvent.data.error);
|
||||
}
|
||||
|
||||
const salt = await this.$store.dispatch(PROJECTS_ACTIONS.GET_SALT, this.$store.getters.selectedProject.id);
|
||||
const satelliteNodeURL: string = MetaUtils.getMetaContent('satellite-nodeurl');
|
||||
|
||||
this.worker.postMessage({
|
||||
'type': 'GenerateAccess',
|
||||
'apiKey': grantEvent.data.value,
|
||||
'passphrase': this.passphrase,
|
||||
'projectID': this.$store.getters.selectedProject.id,
|
||||
'salt': salt,
|
||||
'satelliteNodeURL': satelliteNodeURL,
|
||||
});
|
||||
|
||||
|
@ -40,6 +40,7 @@ import { Component, Vue } from 'vue-property-decorator';
|
||||
|
||||
import { APP_STATE_MUTATIONS } from '@/store/mutationConstants';
|
||||
import { ACCESS_GRANTS_ACTIONS } from '@/store/modules/accessGrants';
|
||||
import { PROJECTS_ACTIONS } from '@/store/modules/projects';
|
||||
import { MetaUtils } from '@/utils/meta';
|
||||
import { AccessGrant, EdgeCredentials } from '@/types/accessGrants';
|
||||
|
||||
@ -104,12 +105,13 @@ export default class ShareBucketModal extends Vue {
|
||||
const cleanAPIKey: AccessGrant = await this.$store.dispatch(ACCESS_GRANTS_ACTIONS.CREATE, LINK_SHARING_AG_NAME);
|
||||
|
||||
const satelliteNodeURL = MetaUtils.getMetaContent('satellite-nodeurl');
|
||||
const salt = await this.$store.dispatch(PROJECTS_ACTIONS.GET_SALT, this.$store.getters.selectedProject.id);
|
||||
|
||||
this.worker.postMessage({
|
||||
'type': 'GenerateAccess',
|
||||
'apiKey': cleanAPIKey.secret,
|
||||
'passphrase': this.passphrase,
|
||||
'projectID': this.$store.getters.selectedProject.id,
|
||||
'salt': salt,
|
||||
'satelliteNodeURL': satelliteNodeURL,
|
||||
});
|
||||
|
||||
|
@ -25,6 +25,7 @@ import { RouteConfig } from '@/router';
|
||||
import { OBJECTS_ACTIONS } from '@/store/modules/objects';
|
||||
import { AccessGrant, EdgeCredentials } from '@/types/accessGrants';
|
||||
import { ACCESS_GRANTS_ACTIONS } from '@/store/modules/accessGrants';
|
||||
import { PROJECTS_ACTIONS } from '@/store/modules/projects';
|
||||
import { MetaUtils } from '@/utils/meta';
|
||||
import { AnalyticsHttpApi } from '@/api/analytics';
|
||||
import { AnalyticsEvent } from '@/utils/constants/analyticsEventNames';
|
||||
@ -169,11 +170,13 @@ export default class BucketCreation extends Vue {
|
||||
}
|
||||
|
||||
const satelliteNodeURL: string = MetaUtils.getMetaContent('satellite-nodeurl');
|
||||
const salt = await this.$store.dispatch(PROJECTS_ACTIONS.GET_SALT, this.$store.getters.selectedProject.id);
|
||||
|
||||
this.worker.postMessage({
|
||||
'type': 'GenerateAccess',
|
||||
'apiKey': grantEvent.data.value,
|
||||
'passphrase': this.passphrase,
|
||||
'projectID': this.$store.getters.selectedProject.id,
|
||||
'salt': salt,
|
||||
'satelliteNodeURL': satelliteNodeURL,
|
||||
});
|
||||
|
||||
|
@ -91,6 +91,7 @@ import { Component, Vue, Watch } from 'vue-property-decorator';
|
||||
import { RouteConfig } from '@/router';
|
||||
import { ACCESS_GRANTS_ACTIONS } from '@/store/modules/accessGrants';
|
||||
import { OBJECTS_ACTIONS } from '@/store/modules/objects';
|
||||
import { PROJECTS_ACTIONS } from '@/store/modules/projects';
|
||||
import { AccessGrant, EdgeCredentials } from '@/types/accessGrants';
|
||||
import { MetaUtils } from '@/utils/meta';
|
||||
import { Validator } from '@/utils/validation';
|
||||
@ -222,13 +223,15 @@ export default class BucketsView extends Vue {
|
||||
if (grantEvent.data.error) {
|
||||
throw new Error(grantEvent.data.error);
|
||||
}
|
||||
|
||||
|
||||
const salt = await this.$store.dispatch(PROJECTS_ACTIONS.GET_SALT, this.$store.getters.selectedProject.id);
|
||||
const satelliteNodeURL: string = MetaUtils.getMetaContent('satellite-nodeurl');
|
||||
|
||||
this.worker.postMessage({
|
||||
'type': 'GenerateAccess',
|
||||
'apiKey': this.grantWithPermissions,
|
||||
'passphrase': '',
|
||||
'projectID': this.$store.getters.selectedProject.id,
|
||||
'salt': salt,
|
||||
'satelliteNodeURL': satelliteNodeURL,
|
||||
});
|
||||
|
||||
|
@ -66,6 +66,7 @@ import { OBJECTS_ACTIONS } from '@/store/modules/objects';
|
||||
import { LocalData } from '@/utils/localData';
|
||||
import { EdgeCredentials } from '@/types/accessGrants';
|
||||
import { ACCESS_GRANTS_ACTIONS } from '@/store/modules/accessGrants';
|
||||
import { PROJECTS_ACTIONS } from '@/store/modules/projects';
|
||||
import { APP_STATE_MUTATIONS } from '@/store/mutationConstants';
|
||||
import { MetaUtils } from '@/utils/meta';
|
||||
import { AnalyticsHttpApi } from '@/api/analytics';
|
||||
@ -193,11 +194,13 @@ export default class EncryptData extends Vue {
|
||||
}
|
||||
|
||||
const satelliteNodeURL: string = MetaUtils.getMetaContent('satellite-nodeurl');
|
||||
const salt = await this.$store.dispatch(PROJECTS_ACTIONS.GET_SALT, this.$store.getters.selectedProject.id);
|
||||
|
||||
this.worker.postMessage({
|
||||
'type': 'GenerateAccess',
|
||||
'apiKey': grantEvent.data.value,
|
||||
'passphrase': this.passphrase,
|
||||
'projectID': this.$store.getters.selectedProject.id,
|
||||
'salt': salt,
|
||||
'satelliteNodeURL': satelliteNodeURL,
|
||||
});
|
||||
|
||||
|
@ -22,6 +22,7 @@ import { Component, Vue } from 'vue-property-decorator';
|
||||
import { AnalyticsHttpApi } from '@/api/analytics';
|
||||
import { RouteConfig } from '@/router';
|
||||
import { ACCESS_GRANTS_ACTIONS } from '@/store/modules/accessGrants';
|
||||
import { PROJECTS_ACTIONS } from '@/store/modules/projects';
|
||||
import { AccessGrant, EdgeCredentials } from '@/types/accessGrants';
|
||||
import { AnalyticsEvent } from '@/utils/constants/analyticsEventNames';
|
||||
import { MetaUtils } from '@/utils/meta';
|
||||
@ -140,12 +141,13 @@ export default class UploadFile extends Vue {
|
||||
*/
|
||||
private async generateCredentials(cleanApiKey: string, path: string, areEndless: boolean): Promise<EdgeCredentials> {
|
||||
const satelliteNodeURL = MetaUtils.getMetaContent('satellite-nodeurl');
|
||||
const salt = await this.$store.dispatch(PROJECTS_ACTIONS.GET_SALT, this.$store.getters.selectedProject.id);
|
||||
|
||||
this.worker.postMessage({
|
||||
'type': 'GenerateAccess',
|
||||
'apiKey': cleanApiKey,
|
||||
'passphrase': this.passphrase,
|
||||
'projectID': this.$store.getters.selectedProject.id,
|
||||
'salt': salt,
|
||||
'satelliteNodeURL': satelliteNodeURL,
|
||||
});
|
||||
|
||||
|
@ -29,6 +29,7 @@ export const PROJECTS_ACTIONS = {
|
||||
CLEAR: 'clearProjects',
|
||||
GET_LIMITS: 'getProjectLimits',
|
||||
GET_TOTAL_LIMITS: 'getTotalLimits',
|
||||
GET_SALT: 'getSalt',
|
||||
};
|
||||
|
||||
export const PROJECTS_MUTATIONS = {
|
||||
@ -91,6 +92,7 @@ const {
|
||||
GET_LIMITS,
|
||||
GET_TOTAL_LIMITS,
|
||||
FETCH_OWNED,
|
||||
GET_SALT,
|
||||
} = PROJECTS_ACTIONS;
|
||||
|
||||
const {
|
||||
@ -331,6 +333,9 @@ export function makeProjectsModule(api: ProjectsApi): StoreModule<ProjectsState,
|
||||
|
||||
return limits;
|
||||
},
|
||||
[GET_SALT]: async function (_, projectID: string): Promise<string> {
|
||||
return await api.getSalt(projectID);
|
||||
},
|
||||
[CLEAR]: function({ commit }: ProjectsContext): void {
|
||||
commit(CLEAR_PROJECTS);
|
||||
},
|
||||
|
@ -45,6 +45,14 @@ export interface ProjectsApi {
|
||||
*/
|
||||
getLimits(projectId: string): Promise<ProjectLimits>;
|
||||
|
||||
/**
|
||||
* Get project salt
|
||||
*
|
||||
* @param projectID - project ID
|
||||
* throws Error
|
||||
*/
|
||||
getSalt(projectID: string): Promise<string>;
|
||||
|
||||
/**
|
||||
* Get project limits.
|
||||
*
|
||||
|
@ -35,7 +35,7 @@ self.onmessage = async function (event) {
|
||||
const projectID = data.projectID;
|
||||
const aesKey = data.aesKey;
|
||||
|
||||
result = self.deriveAndEncryptRootKey(passphrase, projectID, aesKey);
|
||||
result = self.deriveAndAESEncryptRootKey(passphrase, projectID, aesKey);
|
||||
self.postMessage(result);
|
||||
}
|
||||
break;
|
||||
@ -43,11 +43,10 @@ self.onmessage = async function (event) {
|
||||
{
|
||||
apiKey = data.apiKey;
|
||||
const passphrase = data.passphrase;
|
||||
const projectID = data.projectID;
|
||||
const salt = data.salt;
|
||||
const nodeURL = data.satelliteNodeURL;
|
||||
|
||||
result = self.generateAccessGrant(nodeURL, apiKey, passphrase, projectID);
|
||||
|
||||
result = self.generateNewAccessGrant(nodeURL, apiKey, passphrase, salt);
|
||||
self.postMessage(result);
|
||||
}
|
||||
break;
|
||||
|
@ -55,6 +55,10 @@ export class ProjectsApiMock implements ProjectsApi {
|
||||
return Promise.resolve(this.mockLimits);
|
||||
}
|
||||
|
||||
getSalt(): Promise<string> {
|
||||
throw new Error('not implemented');
|
||||
}
|
||||
|
||||
getDailyUsage(_projectId: string, _start: Date, _end: Date): Promise<ProjectsStorageBandwidthDaily> {
|
||||
throw new Error('not implemented');
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user