mirror of
https://github.com/drakkan/sftpgo.git
synced 2024-11-22 07:30:25 +00:00
85a47810ff
Before these changes we implictly set S3ForcePathStyle if an endpoint was provided. This can cause issues with some S3 compatible object storages and must be explicitly set now. AWS is also deprecating this setting https://aws.amazon.com/it/blogs/aws/amazon-s3-path-deprecation-plan-the-rest-of-the-story/
292 lines
9.9 KiB
Go
292 lines
9.9 KiB
Go
package vfs
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"github.com/drakkan/sftpgo/v2/kms"
|
|
"github.com/drakkan/sftpgo/v2/sdk"
|
|
"github.com/drakkan/sftpgo/v2/util"
|
|
)
|
|
|
|
// ValidatorHelper implements methods we need for Filesystem.ValidateConfig.
|
|
// It is implemented by vfs.Folder and dataprovider.User
|
|
type ValidatorHelper interface {
|
|
GetGCSCredentialsFilePath() string
|
|
GetEncryptionAdditionalData() string
|
|
}
|
|
|
|
// Filesystem defines filesystem details
|
|
type Filesystem struct {
|
|
RedactedSecret string `json:"-"`
|
|
Provider sdk.FilesystemProvider `json:"provider"`
|
|
S3Config S3FsConfig `json:"s3config,omitempty"`
|
|
GCSConfig GCSFsConfig `json:"gcsconfig,omitempty"`
|
|
AzBlobConfig AzBlobFsConfig `json:"azblobconfig,omitempty"`
|
|
CryptConfig CryptFsConfig `json:"cryptconfig,omitempty"`
|
|
SFTPConfig SFTPFsConfig `json:"sftpconfig,omitempty"`
|
|
}
|
|
|
|
// SetEmptySecretsIfNil sets the secrets to empty if nil
|
|
func (f *Filesystem) SetEmptySecretsIfNil() {
|
|
if f.S3Config.AccessSecret == nil {
|
|
f.S3Config.AccessSecret = kms.NewEmptySecret()
|
|
}
|
|
if f.GCSConfig.Credentials == nil {
|
|
f.GCSConfig.Credentials = kms.NewEmptySecret()
|
|
}
|
|
if f.AzBlobConfig.AccountKey == nil {
|
|
f.AzBlobConfig.AccountKey = kms.NewEmptySecret()
|
|
}
|
|
if f.AzBlobConfig.SASURL == nil {
|
|
f.AzBlobConfig.SASURL = kms.NewEmptySecret()
|
|
}
|
|
if f.CryptConfig.Passphrase == nil {
|
|
f.CryptConfig.Passphrase = kms.NewEmptySecret()
|
|
}
|
|
if f.SFTPConfig.Password == nil {
|
|
f.SFTPConfig.Password = kms.NewEmptySecret()
|
|
}
|
|
if f.SFTPConfig.PrivateKey == nil {
|
|
f.SFTPConfig.PrivateKey = kms.NewEmptySecret()
|
|
}
|
|
}
|
|
|
|
// SetNilSecretsIfEmpty set the secrets to nil if empty.
|
|
// This is useful before rendering as JSON so the empty fields
|
|
// will not be serialized.
|
|
func (f *Filesystem) SetNilSecretsIfEmpty() {
|
|
if f.S3Config.AccessSecret != nil && f.S3Config.AccessSecret.IsEmpty() {
|
|
f.S3Config.AccessSecret = nil
|
|
}
|
|
if f.GCSConfig.Credentials != nil && f.GCSConfig.Credentials.IsEmpty() {
|
|
f.GCSConfig.Credentials = nil
|
|
}
|
|
if f.AzBlobConfig.AccountKey != nil && f.AzBlobConfig.AccountKey.IsEmpty() {
|
|
f.AzBlobConfig.AccountKey = nil
|
|
}
|
|
if f.AzBlobConfig.SASURL != nil && f.AzBlobConfig.SASURL.IsEmpty() {
|
|
f.AzBlobConfig.SASURL = nil
|
|
}
|
|
if f.CryptConfig.Passphrase != nil && f.CryptConfig.Passphrase.IsEmpty() {
|
|
f.CryptConfig.Passphrase = nil
|
|
}
|
|
if f.SFTPConfig.Password != nil && f.SFTPConfig.Password.IsEmpty() {
|
|
f.SFTPConfig.Password = nil
|
|
}
|
|
if f.SFTPConfig.PrivateKey != nil && f.SFTPConfig.PrivateKey.IsEmpty() {
|
|
f.SFTPConfig.PrivateKey = nil
|
|
}
|
|
}
|
|
|
|
// IsEqual returns true if the fs is equal to other
|
|
func (f *Filesystem) IsEqual(other *Filesystem) bool {
|
|
if f.Provider != other.Provider {
|
|
return false
|
|
}
|
|
switch f.Provider {
|
|
case sdk.S3FilesystemProvider:
|
|
return f.S3Config.isEqual(&other.S3Config)
|
|
case sdk.GCSFilesystemProvider:
|
|
return f.GCSConfig.isEqual(&other.GCSConfig)
|
|
case sdk.AzureBlobFilesystemProvider:
|
|
return f.AzBlobConfig.isEqual(&other.AzBlobConfig)
|
|
case sdk.CryptedFilesystemProvider:
|
|
return f.CryptConfig.isEqual(&other.CryptConfig)
|
|
case sdk.SFTPFilesystemProvider:
|
|
return f.SFTPConfig.isEqual(&other.SFTPConfig)
|
|
default:
|
|
return true
|
|
}
|
|
}
|
|
|
|
// Validate verifies the FsConfig matching the configured provider and sets all other
|
|
// Filesystem.*Config to their zero value if successful
|
|
func (f *Filesystem) Validate(helper ValidatorHelper) error {
|
|
switch f.Provider {
|
|
case sdk.S3FilesystemProvider:
|
|
if err := f.S3Config.Validate(); err != nil {
|
|
return util.NewValidationError(fmt.Sprintf("could not validate s3config: %v", err))
|
|
}
|
|
if err := f.S3Config.EncryptCredentials(helper.GetEncryptionAdditionalData()); err != nil {
|
|
return util.NewValidationError(fmt.Sprintf("could not encrypt s3 access secret: %v", err))
|
|
}
|
|
f.GCSConfig = GCSFsConfig{}
|
|
f.AzBlobConfig = AzBlobFsConfig{}
|
|
f.CryptConfig = CryptFsConfig{}
|
|
f.SFTPConfig = SFTPFsConfig{}
|
|
return nil
|
|
case sdk.GCSFilesystemProvider:
|
|
if err := f.GCSConfig.Validate(helper.GetGCSCredentialsFilePath()); err != nil {
|
|
return util.NewValidationError(fmt.Sprintf("could not validate GCS config: %v", err))
|
|
}
|
|
f.S3Config = S3FsConfig{}
|
|
f.AzBlobConfig = AzBlobFsConfig{}
|
|
f.CryptConfig = CryptFsConfig{}
|
|
f.SFTPConfig = SFTPFsConfig{}
|
|
return nil
|
|
case sdk.AzureBlobFilesystemProvider:
|
|
if err := f.AzBlobConfig.Validate(); err != nil {
|
|
return util.NewValidationError(fmt.Sprintf("could not validate Azure Blob config: %v", err))
|
|
}
|
|
if err := f.AzBlobConfig.EncryptCredentials(helper.GetEncryptionAdditionalData()); err != nil {
|
|
return util.NewValidationError(fmt.Sprintf("could not encrypt Azure blob account key: %v", err))
|
|
}
|
|
f.S3Config = S3FsConfig{}
|
|
f.GCSConfig = GCSFsConfig{}
|
|
f.CryptConfig = CryptFsConfig{}
|
|
f.SFTPConfig = SFTPFsConfig{}
|
|
return nil
|
|
case sdk.CryptedFilesystemProvider:
|
|
if err := f.CryptConfig.Validate(); err != nil {
|
|
return util.NewValidationError(fmt.Sprintf("could not validate Crypt fs config: %v", err))
|
|
}
|
|
if err := f.CryptConfig.EncryptCredentials(helper.GetEncryptionAdditionalData()); err != nil {
|
|
return util.NewValidationError(fmt.Sprintf("could not encrypt Crypt fs passphrase: %v", err))
|
|
}
|
|
f.S3Config = S3FsConfig{}
|
|
f.GCSConfig = GCSFsConfig{}
|
|
f.AzBlobConfig = AzBlobFsConfig{}
|
|
f.SFTPConfig = SFTPFsConfig{}
|
|
return nil
|
|
case sdk.SFTPFilesystemProvider:
|
|
if err := f.SFTPConfig.Validate(); err != nil {
|
|
return util.NewValidationError(fmt.Sprintf("could not validate SFTP fs config: %v", err))
|
|
}
|
|
if err := f.SFTPConfig.EncryptCredentials(helper.GetEncryptionAdditionalData()); err != nil {
|
|
return util.NewValidationError(fmt.Sprintf("could not encrypt SFTP fs credentials: %v", err))
|
|
}
|
|
f.S3Config = S3FsConfig{}
|
|
f.GCSConfig = GCSFsConfig{}
|
|
f.AzBlobConfig = AzBlobFsConfig{}
|
|
f.CryptConfig = CryptFsConfig{}
|
|
return nil
|
|
default:
|
|
f.Provider = sdk.LocalFilesystemProvider
|
|
f.S3Config = S3FsConfig{}
|
|
f.GCSConfig = GCSFsConfig{}
|
|
f.AzBlobConfig = AzBlobFsConfig{}
|
|
f.CryptConfig = CryptFsConfig{}
|
|
f.SFTPConfig = SFTPFsConfig{}
|
|
return nil
|
|
}
|
|
}
|
|
|
|
// HasRedactedSecret returns true if configured the filesystem configuration has a redacted secret
|
|
func (f *Filesystem) HasRedactedSecret() bool {
|
|
// TODO move vfs specific code into each *FsConfig struct
|
|
switch f.Provider {
|
|
case sdk.S3FilesystemProvider:
|
|
if f.S3Config.AccessSecret.IsRedacted() {
|
|
return true
|
|
}
|
|
case sdk.GCSFilesystemProvider:
|
|
if f.GCSConfig.Credentials.IsRedacted() {
|
|
return true
|
|
}
|
|
case sdk.AzureBlobFilesystemProvider:
|
|
if f.AzBlobConfig.AccountKey.IsRedacted() {
|
|
return true
|
|
}
|
|
case sdk.CryptedFilesystemProvider:
|
|
if f.CryptConfig.Passphrase.IsRedacted() {
|
|
return true
|
|
}
|
|
case sdk.SFTPFilesystemProvider:
|
|
if f.SFTPConfig.Password.IsRedacted() {
|
|
return true
|
|
}
|
|
if f.SFTPConfig.PrivateKey.IsRedacted() {
|
|
return true
|
|
}
|
|
}
|
|
|
|
return false
|
|
}
|
|
|
|
// HideConfidentialData hides filesystem confidential data
|
|
func (f *Filesystem) HideConfidentialData() {
|
|
switch f.Provider {
|
|
case sdk.S3FilesystemProvider:
|
|
f.S3Config.AccessSecret.Hide()
|
|
case sdk.GCSFilesystemProvider:
|
|
f.GCSConfig.Credentials.Hide()
|
|
case sdk.AzureBlobFilesystemProvider:
|
|
f.AzBlobConfig.AccountKey.Hide()
|
|
f.AzBlobConfig.SASURL.Hide()
|
|
case sdk.CryptedFilesystemProvider:
|
|
f.CryptConfig.Passphrase.Hide()
|
|
case sdk.SFTPFilesystemProvider:
|
|
f.SFTPConfig.Password.Hide()
|
|
f.SFTPConfig.PrivateKey.Hide()
|
|
}
|
|
}
|
|
|
|
// GetACopy returns a filesystem copy
|
|
func (f *Filesystem) GetACopy() Filesystem {
|
|
f.SetEmptySecretsIfNil()
|
|
fs := Filesystem{
|
|
Provider: f.Provider,
|
|
S3Config: S3FsConfig{
|
|
S3FsConfig: sdk.S3FsConfig{
|
|
Bucket: f.S3Config.Bucket,
|
|
Region: f.S3Config.Region,
|
|
AccessKey: f.S3Config.AccessKey,
|
|
AccessSecret: f.S3Config.AccessSecret.Clone(),
|
|
Endpoint: f.S3Config.Endpoint,
|
|
StorageClass: f.S3Config.StorageClass,
|
|
KeyPrefix: f.S3Config.KeyPrefix,
|
|
UploadPartSize: f.S3Config.UploadPartSize,
|
|
UploadConcurrency: f.S3Config.UploadConcurrency,
|
|
DownloadPartSize: f.S3Config.DownloadPartSize,
|
|
DownloadConcurrency: f.S3Config.DownloadConcurrency,
|
|
DownloadPartMaxTime: f.S3Config.DownloadPartMaxTime,
|
|
ForcePathStyle: f.S3Config.ForcePathStyle,
|
|
},
|
|
},
|
|
GCSConfig: GCSFsConfig{
|
|
GCSFsConfig: sdk.GCSFsConfig{
|
|
Bucket: f.GCSConfig.Bucket,
|
|
CredentialFile: f.GCSConfig.CredentialFile,
|
|
Credentials: f.GCSConfig.Credentials.Clone(),
|
|
AutomaticCredentials: f.GCSConfig.AutomaticCredentials,
|
|
StorageClass: f.GCSConfig.StorageClass,
|
|
KeyPrefix: f.GCSConfig.KeyPrefix,
|
|
},
|
|
},
|
|
AzBlobConfig: AzBlobFsConfig{
|
|
AzBlobFsConfig: sdk.AzBlobFsConfig{
|
|
Container: f.AzBlobConfig.Container,
|
|
AccountName: f.AzBlobConfig.AccountName,
|
|
AccountKey: f.AzBlobConfig.AccountKey.Clone(),
|
|
Endpoint: f.AzBlobConfig.Endpoint,
|
|
SASURL: f.AzBlobConfig.SASURL.Clone(),
|
|
KeyPrefix: f.AzBlobConfig.KeyPrefix,
|
|
UploadPartSize: f.AzBlobConfig.UploadPartSize,
|
|
UploadConcurrency: f.AzBlobConfig.UploadConcurrency,
|
|
UseEmulator: f.AzBlobConfig.UseEmulator,
|
|
AccessTier: f.AzBlobConfig.AccessTier,
|
|
},
|
|
},
|
|
CryptConfig: CryptFsConfig{
|
|
CryptFsConfig: sdk.CryptFsConfig{
|
|
Passphrase: f.CryptConfig.Passphrase.Clone(),
|
|
},
|
|
},
|
|
SFTPConfig: SFTPFsConfig{
|
|
SFTPFsConfig: sdk.SFTPFsConfig{
|
|
Endpoint: f.SFTPConfig.Endpoint,
|
|
Username: f.SFTPConfig.Username,
|
|
Password: f.SFTPConfig.Password.Clone(),
|
|
PrivateKey: f.SFTPConfig.PrivateKey.Clone(),
|
|
Prefix: f.SFTPConfig.Prefix,
|
|
DisableCouncurrentReads: f.SFTPConfig.DisableCouncurrentReads,
|
|
BufferSize: f.SFTPConfig.BufferSize,
|
|
},
|
|
},
|
|
}
|
|
if len(f.SFTPConfig.Fingerprints) > 0 {
|
|
fs.SFTPConfig.Fingerprints = make([]string, len(f.SFTPConfig.Fingerprints))
|
|
copy(fs.SFTPConfig.Fingerprints, f.SFTPConfig.Fingerprints)
|
|
}
|
|
return fs
|
|
}
|