storj/mobile/uplink.go
Jeff Wendling efcdaa43a3
lib/uplink: encryption context (#2349)
* lib/uplink: encryption context

Change-Id: I5c23dca3286a46b713b30c4997e9ae6e630b2280

* lib/uplink: bucket operation examples

Change-Id: Ia0f6e69f365dcff0cf11c731f51b30842bce053b

* lib/uplink: encryption key sharing test cases

Change-Id: I3a172d565f33f4e591402cdcb9460664a7cc7fbe

* fix encrypted path prefix restriction issue

Change-Id: I8f3921f9d52aaf4b84039de608b8cbbc88769554

* implement panics in libuplink encryption code

todo on cipher suite selection as well as an api concern

Change-Id: Ifa39eb3cc4b3443f7d96f9304df9b2ac4ec4085d

* implement GetProjectInfo api call to get salt

Change-Id: Ic5f6b3be9ea35df48c1aa214ab5d355fb328e2cf

* some fixes and accessors for encryption store

Change-Id: I3bb61f6712a037900e2a96e72ad4029ec1d3f718

* general fixes to builds/tests/etc

Change-Id: I9930fa96acb3b221d9a001f8e274af5729cc8a47

* java bindings changes

Change-Id: Ia2bd4c9c69739c8d3154d79616cff1f36fb403b6

* get libuplink examples passing

Change-Id: I828f09a144160e0a5dd932324f78491ae2ec8a07

* fix proto.lock file

Change-Id: I2fbbf4d0976a7d0473c2645e6dcb21aaa3be7651

* fix proto.lock again

Change-Id: I92702cf49e1a340eef6379c2be4f7c4a268112a9

* fix golint issues

Change-Id: I631ff9f43307a58e3b25a58cbb4a4cc2495f5eb6

* more linting fixes

Change-Id: I51f8f30b367b5bca14c94b15417b9a4c9e7aa0ce

* bug fixed by structs bump

Change-Id: Ibb03c691fce7606c35c08721b3ef0781ab48a38a

* retrigger

Change-Id: Ieee0470b6a2d07168a1578552e8e7f271ae93a13

* retrigger

Change-Id: I753d63853171e6a436c104ce176048892eb974c5

* semantic merge conflict

Change-Id: I9419448496de90340569047a6a16a1b858a7978a

* update total to match prod defaults

Change-Id: I693d55c1ebb28b5803ee1d26e9e198decf82308b

* retrigger

Change-Id: I28b74d5d6202f61aa3866fe407d423f6a0a14b9e

* retrigger

Change-Id: I6fd054885c715f602e2cef623fd464c42e88742c

* retrigger

Change-Id: I6a01bae88c72406d4ed5a8f13bf8a2b3c650bd2d
2019-06-27 17:36:51 +00:00

175 lines
5.2 KiB
Go

// Copyright (C) 2019 Storj Labs, Inc.
// See LICENSE for copying information.
package mobile
import (
"fmt"
"storj.io/storj/internal/memory"
libuplink "storj.io/storj/lib/uplink"
"storj.io/storj/pkg/storj"
)
// Config represents configuration options for an Uplink
type Config struct {
// MaxInlineSize determines whether the uplink will attempt to
// store a new object in the satellite's metainfo. Objects at
// or below this size will be marked for inline storage, and
// objects above this size will not. (The satellite may reject
// the inline storage and require remote storage, still.)
MaxInlineSize int64
// MaxMemory is the default maximum amount of memory to be
// allocated for read buffers while performing decodes of
// objects. (This option is overrideable per Bucket if the user
// so desires.) If set to zero, the library default (4 MiB) will
// be used. If set to a negative value, the system will use the
// smallest amount of memory it can.
MaxMemory int64
}
// Uplink represents the main entrypoint to Storj V3. An Uplink connects to
// a specific Satellite and caches connections and resources, allowing one to
// create sessions delineated by specific access controls.
type Uplink struct {
scope
lib *libuplink.Uplink
}
// NewUplink creates a new Uplink. This is the first step to create an uplink
// session with a user specified config or with default config, if nil config.
// Uplink needs also writable temporary directory.
func NewUplink(config *Config, tempDir string) (*Uplink, error) {
scope := rootScope(tempDir)
cfg := &libuplink.Config{}
if config != nil {
cfg.Volatile.TLS.SkipPeerCAWhitelist = true
cfg.Volatile.MaxInlineSize = memory.Size(config.MaxInlineSize)
cfg.Volatile.MaxMemory = memory.Size(config.MaxMemory)
}
lib, err := libuplink.NewUplink(scope.ctx, cfg)
if err != nil {
return nil, safeError(err)
}
return &Uplink{scope, lib}, nil
}
// Close closes the Uplink. This may not do anything at present, but should
// still be called to allow forward compatibility. No Project or Bucket
// objects using this Uplink should be used after calling Close.
func (uplink *Uplink) Close() error {
uplink.cancel()
return safeError(uplink.lib.Close())
}
// Project represents a specific project access session.
type Project struct {
scope
lib *libuplink.Project
}
// OpenProject returns a Project handle with the given APIKey
func (uplink *Uplink) OpenProject(satellite string, apikey string) (*Project, error) {
scope := uplink.scope.child()
key, err := libuplink.ParseAPIKey(apikey)
if err != nil {
return nil, safeError(err)
}
project, err := uplink.lib.OpenProject(scope.ctx, satellite, key)
if err != nil {
return nil, safeError(err)
}
return &Project{scope, project}, nil
}
// Close closes the Project
func (project *Project) Close() error {
defer project.cancel()
return safeError(project.lib.Close())
}
// CreateBucket creates buckets in project
func (project *Project) CreateBucket(bucketName string, opts *BucketConfig) (*BucketInfo, error) {
scope := project.scope.child()
cfg := libuplink.BucketConfig{}
if opts != nil {
cfg.PathCipher = storj.CipherSuite(opts.PathCipher)
cfg.EncryptionParameters = newStorjEncryptionParameters(opts.EncryptionParameters)
cfg.Volatile.RedundancyScheme = newStorjRedundancyScheme(opts.RedundancyScheme)
cfg.Volatile.SegmentsSize = memory.Size(opts.SegmentsSize)
}
bucket, err := project.lib.CreateBucket(scope.ctx, bucketName, &cfg)
if err != nil {
return nil, safeError(err)
}
return newBucketInfo(bucket), nil
}
// OpenBucket returns a Bucket handle with the given EncryptionAccess
// information.
func (project *Project) OpenBucket(bucketName string, encCtx *EncryptionCtx) (*Bucket, error) {
scope := project.scope.child()
bucket, err := project.lib.OpenBucket(scope.ctx, bucketName, encCtx.lib)
if err != nil {
return nil, safeError(err)
}
return &Bucket{bucket.Name, scope, bucket}, nil
}
// GetBucketInfo returns info about the requested bucket if authorized.
func (project *Project) GetBucketInfo(bucketName string) (*BucketInfo, error) {
scope := project.scope.child()
bucket, _, err := project.lib.GetBucketInfo(scope.ctx, bucketName)
if err != nil {
return nil, safeError(err)
}
return newBucketInfo(bucket), nil
}
// ListBuckets will list authorized buckets.
func (project *Project) ListBuckets(cursor string, direction, limit int) (*BucketList, error) {
scope := project.scope.child()
opts := libuplink.BucketListOptions{
Cursor: cursor,
Direction: storj.ListDirection(direction),
Limit: limit,
}
list, err := project.lib.ListBuckets(scope.ctx, &opts)
if err != nil {
return nil, safeError(err)
}
return &BucketList{list}, nil
}
// DeleteBucket deletes a bucket if authorized. If the bucket contains any
// Objects at the time of deletion, they may be lost permanently.
func (project *Project) DeleteBucket(bucketName string) error {
scope := project.scope.child()
err := project.lib.DeleteBucket(scope.ctx, bucketName)
return safeError(err)
}
func safeError(err error) error {
// workaround to avoid gomobile panic because of "hash of unhashable type errs.combinedError"
if err == nil {
return nil
}
return fmt.Errorf("%v", err.Error())
}