2019-02-08 12:57:35 +00:00
// Copyright (C) 2019 Storj Labs, Inc.
// See LICENSE for copying information.
package uplink
import (
2019-08-05 18:01:20 +01:00
"io/ioutil"
"strings"
2019-04-25 09:17:26 +01:00
"time"
2019-02-08 12:57:35 +00:00
2019-08-05 18:01:20 +01:00
"github.com/zeebo/errs"
"gopkg.in/spacemonkeygo/monkit.v2"
2019-02-08 12:57:35 +00:00
"storj.io/storj/internal/memory"
2019-08-05 18:01:20 +01:00
libuplink "storj.io/storj/lib/uplink"
2019-02-11 11:17:32 +00:00
"storj.io/storj/pkg/peertls/tlsopts"
2019-02-08 12:57:35 +00:00
"storj.io/storj/pkg/storj"
)
2019-08-05 18:01:20 +01:00
var mon = monkit . Package ( )
2019-02-08 12:57:35 +00:00
// RSConfig is a configuration struct that keeps details about default
// redundancy strategy information
type RSConfig struct {
2019-06-19 15:27:44 +01:00
MaxBufferMem memory . Size ` help:"maximum buffer memory (in bytes) to be allocated for read buffers" default:"4MiB" hidden:"true" `
ErasureShareSize memory . Size ` help:"the size of each new erasure share in bytes" default:"256B" hidden:"true" `
MinThreshold int ` help:"the minimum pieces required to recover a segment. k." releaseDefault:"29" devDefault:"4" hidden:"true" `
RepairThreshold int ` help:"the minimum safe pieces before a repair is triggered. m." releaseDefault:"35" devDefault:"6" hidden:"true" `
SuccessThreshold int ` help:"the desired total pieces for a segment. o." releaseDefault:"80" devDefault:"8" hidden:"true" `
MaxThreshold int ` help:"the largest amount of pieces to encode to. n." releaseDefault:"130" devDefault:"10" hidden:"true" `
2019-02-08 12:57:35 +00:00
}
// EncryptionConfig is a configuration struct that keeps details about
// encrypting segments
type EncryptionConfig struct {
2019-08-05 18:01:20 +01:00
DataType int ` help:"Type of encryption to use for content and metadata (2=AES-GCM, 3=SecretBox)" default:"2" `
PathType int ` help:"Type of encryption to use for paths (1=Unencrypted, 2=AES-GCM, 3=SecretBox)" default:"2" `
2019-02-08 12:57:35 +00:00
}
// ClientConfig is a configuration struct for the uplink that controls how
// to talk to the rest of the network.
type ClientConfig struct {
2019-10-23 00:57:24 +01:00
MaxInlineSize memory . Size ` help:"max inline segment size in bytes" default:"4KiB" `
SegmentSize memory . Size ` help:"the size of a segment in bytes" default:"64MiB" `
DialTimeout time . Duration ` help:"timeout for dials" default:"0h2m00s" `
2019-02-08 12:57:35 +00:00
}
// Config uplink configuration
type Config struct {
2019-08-05 18:01:20 +01:00
ScopeConfig
2019-02-08 12:57:35 +00:00
Client ClientConfig
RS RSConfig
Enc EncryptionConfig
2019-02-11 11:17:32 +00:00
TLS tlsopts . Config
2019-02-08 12:57:35 +00:00
}
2019-08-05 18:01:20 +01:00
// ScopeConfig holds information about which scopes exist and are selected.
type ScopeConfig struct {
Scopes map [ string ] string ` internal:"true" `
Scope string ` help:"the serialized scope, or name of the scope to use" default:"" `
Legacy // Holds on to legacy configuration values
}
// Legacy holds deprecated configuration values
type Legacy struct {
Client struct {
APIKey string ` default:"" help:"the api key to use for the satellite (deprecated)" noprefix:"true" deprecated:"true" `
SatelliteAddr string ` releaseDefault:"127.0.0.1:7777" devDefault:"127.0.0.1:10000" help:"the address to use for the satellite (deprecated)" noprefix:"true" `
}
Enc struct {
EncryptionKey string ` help:"the root key for encrypting the data which will be stored in KeyFilePath (deprecated)" setup:"true" deprecated:"true" `
KeyFilepath string ` help:"the path to the file which contains the root key for encrypting the data (deprecated)" deprecated:"true" `
EncAccessFilepath string ` help:"the path to a file containing a serialized encryption access (deprecated)" deprecated:"true" `
}
}
// GetScope returns the appropriate scope for the config.
func ( c ScopeConfig ) GetScope ( ) ( _ * libuplink . Scope , err error ) {
defer mon . Task ( ) ( nil ) ( & err )
// if a scope exists for that name, try to load it.
if data , ok := c . Scopes [ c . Scope ] ; ok && c . Scope != "" {
return libuplink . ParseScope ( data )
}
// Otherwise, try to load the scope name as a serialized scope.
if scope , err := libuplink . ParseScope ( c . Scope ) ; err == nil {
return scope , nil
}
// fall back to trying to load the legacy values.
apiKey , err := libuplink . ParseAPIKey ( c . Legacy . Client . APIKey )
if err != nil {
return nil , err
}
satelliteAddr := c . Legacy . Client . SatelliteAddr
if satelliteAddr == "" {
return nil , errs . New ( "must specify a satellite address" )
}
var encAccess * libuplink . EncryptionAccess
if c . Legacy . Enc . EncAccessFilepath != "" {
data , err := ioutil . ReadFile ( c . Legacy . Enc . EncAccessFilepath )
if err != nil {
return nil , errs . Wrap ( err )
}
encAccess , err = libuplink . ParseEncryptionAccess ( strings . TrimSpace ( string ( data ) ) )
if err != nil {
return nil , err
}
} else {
data := [ ] byte ( c . Legacy . Enc . EncryptionKey )
if c . Legacy . Enc . KeyFilepath != "" {
data , err = ioutil . ReadFile ( c . Legacy . Enc . KeyFilepath )
if err != nil {
return nil , errs . Wrap ( err )
}
}
key , err := storj . NewKey ( data )
if err != nil {
return nil , errs . Wrap ( err )
}
encAccess = libuplink . NewEncryptionAccessWithDefaultKey ( * key )
}
return & libuplink . Scope {
APIKey : apiKey ,
SatelliteAddr : satelliteAddr ,
EncryptionAccess : encAccess ,
} , nil
}
2019-02-08 12:57:35 +00:00
// GetRedundancyScheme returns the configured redundancy scheme for new uploads
func ( c Config ) GetRedundancyScheme ( ) storj . RedundancyScheme {
return storj . RedundancyScheme {
Algorithm : storj . ReedSolomon ,
2019-06-06 19:55:10 +01:00
ShareSize : c . RS . ErasureShareSize . Int32 ( ) ,
2019-02-08 12:57:35 +00:00
RequiredShares : int16 ( c . RS . MinThreshold ) ,
RepairShares : int16 ( c . RS . RepairThreshold ) ,
OptimalShares : int16 ( c . RS . SuccessThreshold ) ,
TotalShares : int16 ( c . RS . MaxThreshold ) ,
}
}
2019-06-06 19:55:10 +01:00
// GetPathCipherSuite returns the cipher suite used for path encryption for bucket objects
func ( c Config ) GetPathCipherSuite ( ) storj . CipherSuite {
2019-07-03 19:07:44 +01:00
return storj . CipherSuite ( c . Enc . PathType )
2019-06-06 19:55:10 +01:00
}
2019-07-03 19:07:44 +01:00
// GetEncryptionParameters returns the configured encryption scheme for new uploads
2019-06-11 18:14:05 +01:00
// Blocksize should align with the stripe size therefore multiples of stripes
// should fit in every encryption block. Instead of lettings users configure this
// multiple value, we hardcode stripesPerBlock as 2 for simplicity.
2019-07-03 19:07:44 +01:00
func ( c Config ) GetEncryptionParameters ( ) storj . EncryptionParameters {
2019-06-11 18:14:05 +01:00
const stripesPerBlock = 2
2019-07-03 19:07:44 +01:00
return storj . EncryptionParameters {
CipherSuite : storj . CipherSuite ( c . Enc . DataType ) ,
BlockSize : c . GetRedundancyScheme ( ) . StripeSize ( ) * stripesPerBlock ,
2019-02-08 12:57:35 +00:00
}
}
2019-05-22 14:57:12 +01:00
2019-06-06 19:55:10 +01:00
// GetSegmentSize returns the segment size set in uplink config
func ( c Config ) GetSegmentSize ( ) memory . Size {
return c . Client . SegmentSize
}