mirror of
https://github.com/drakkan/sftpgo.git
synced 2024-11-21 23:20:24 +00:00
move kms implementation outside the sdk package
Signed-off-by: Nicola Murino <nicola.murino@gmail.com>
This commit is contained in:
parent
bf03eb2a88
commit
0e2d673889
43 changed files with 899 additions and 907 deletions
|
@ -14,8 +14,8 @@ import (
|
||||||
|
|
||||||
"github.com/drakkan/sftpgo/v2/common"
|
"github.com/drakkan/sftpgo/v2/common"
|
||||||
"github.com/drakkan/sftpgo/v2/dataprovider"
|
"github.com/drakkan/sftpgo/v2/dataprovider"
|
||||||
|
"github.com/drakkan/sftpgo/v2/kms"
|
||||||
"github.com/drakkan/sftpgo/v2/sdk"
|
"github.com/drakkan/sftpgo/v2/sdk"
|
||||||
"github.com/drakkan/sftpgo/v2/sdk/kms"
|
|
||||||
"github.com/drakkan/sftpgo/v2/service"
|
"github.com/drakkan/sftpgo/v2/service"
|
||||||
"github.com/drakkan/sftpgo/v2/sftpd"
|
"github.com/drakkan/sftpgo/v2/sftpd"
|
||||||
"github.com/drakkan/sftpgo/v2/version"
|
"github.com/drakkan/sftpgo/v2/version"
|
||||||
|
@ -157,18 +157,19 @@ Please take a look at the usage below to customize the serving parameters`,
|
||||||
Permissions: permissions,
|
Permissions: permissions,
|
||||||
HomeDir: portableDir,
|
HomeDir: portableDir,
|
||||||
Status: 1,
|
Status: 1,
|
||||||
Filters: sdk.UserFilters{
|
},
|
||||||
|
Filters: dataprovider.UserFilters{
|
||||||
|
BaseUserFilters: sdk.BaseUserFilters{
|
||||||
FilePatterns: parsePatternsFilesFilters(),
|
FilePatterns: parsePatternsFilesFilters(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
FsConfig: vfs.Filesystem{
|
FsConfig: vfs.Filesystem{
|
||||||
Provider: sdk.GetProviderByName(portableFsProvider),
|
Provider: sdk.GetProviderByName(portableFsProvider),
|
||||||
S3Config: vfs.S3FsConfig{
|
S3Config: vfs.S3FsConfig{
|
||||||
S3FsConfig: sdk.S3FsConfig{
|
BaseS3FsConfig: sdk.BaseS3FsConfig{
|
||||||
Bucket: portableS3Bucket,
|
Bucket: portableS3Bucket,
|
||||||
Region: portableS3Region,
|
Region: portableS3Region,
|
||||||
AccessKey: portableS3AccessKey,
|
AccessKey: portableS3AccessKey,
|
||||||
AccessSecret: kms.NewPlainSecret(portableS3AccessSecret),
|
|
||||||
Endpoint: portableS3Endpoint,
|
Endpoint: portableS3Endpoint,
|
||||||
StorageClass: portableS3StorageClass,
|
StorageClass: portableS3StorageClass,
|
||||||
ACL: portableS3ACL,
|
ACL: portableS3ACL,
|
||||||
|
@ -177,46 +178,45 @@ Please take a look at the usage below to customize the serving parameters`,
|
||||||
UploadConcurrency: portableS3ULConcurrency,
|
UploadConcurrency: portableS3ULConcurrency,
|
||||||
ForcePathStyle: portableS3ForcePathStyle,
|
ForcePathStyle: portableS3ForcePathStyle,
|
||||||
},
|
},
|
||||||
|
AccessSecret: kms.NewPlainSecret(portableS3AccessSecret),
|
||||||
},
|
},
|
||||||
GCSConfig: vfs.GCSFsConfig{
|
GCSConfig: vfs.GCSFsConfig{
|
||||||
GCSFsConfig: sdk.GCSFsConfig{
|
BaseGCSFsConfig: sdk.BaseGCSFsConfig{
|
||||||
Bucket: portableGCSBucket,
|
Bucket: portableGCSBucket,
|
||||||
Credentials: kms.NewPlainSecret(portableGCSCredentials),
|
|
||||||
AutomaticCredentials: portableGCSAutoCredentials,
|
AutomaticCredentials: portableGCSAutoCredentials,
|
||||||
StorageClass: portableGCSStorageClass,
|
StorageClass: portableGCSStorageClass,
|
||||||
KeyPrefix: portableGCSKeyPrefix,
|
KeyPrefix: portableGCSKeyPrefix,
|
||||||
},
|
},
|
||||||
|
Credentials: kms.NewPlainSecret(portableGCSCredentials),
|
||||||
},
|
},
|
||||||
AzBlobConfig: vfs.AzBlobFsConfig{
|
AzBlobConfig: vfs.AzBlobFsConfig{
|
||||||
AzBlobFsConfig: sdk.AzBlobFsConfig{
|
BaseAzBlobFsConfig: sdk.BaseAzBlobFsConfig{
|
||||||
Container: portableAzContainer,
|
Container: portableAzContainer,
|
||||||
AccountName: portableAzAccountName,
|
AccountName: portableAzAccountName,
|
||||||
AccountKey: kms.NewPlainSecret(portableAzAccountKey),
|
|
||||||
Endpoint: portableAzEndpoint,
|
Endpoint: portableAzEndpoint,
|
||||||
AccessTier: portableAzAccessTier,
|
AccessTier: portableAzAccessTier,
|
||||||
SASURL: kms.NewPlainSecret(portableAzSASURL),
|
|
||||||
KeyPrefix: portableAzKeyPrefix,
|
KeyPrefix: portableAzKeyPrefix,
|
||||||
UseEmulator: portableAzUseEmulator,
|
UseEmulator: portableAzUseEmulator,
|
||||||
UploadPartSize: int64(portableAzULPartSize),
|
UploadPartSize: int64(portableAzULPartSize),
|
||||||
UploadConcurrency: portableAzULConcurrency,
|
UploadConcurrency: portableAzULConcurrency,
|
||||||
},
|
},
|
||||||
|
AccountKey: kms.NewPlainSecret(portableAzAccountKey),
|
||||||
|
SASURL: kms.NewPlainSecret(portableAzSASURL),
|
||||||
},
|
},
|
||||||
CryptConfig: vfs.CryptFsConfig{
|
CryptConfig: vfs.CryptFsConfig{
|
||||||
CryptFsConfig: sdk.CryptFsConfig{
|
Passphrase: kms.NewPlainSecret(portableCryptPassphrase),
|
||||||
Passphrase: kms.NewPlainSecret(portableCryptPassphrase),
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
SFTPConfig: vfs.SFTPFsConfig{
|
SFTPConfig: vfs.SFTPFsConfig{
|
||||||
SFTPFsConfig: sdk.SFTPFsConfig{
|
BaseSFTPFsConfig: sdk.BaseSFTPFsConfig{
|
||||||
Endpoint: portableSFTPEndpoint,
|
Endpoint: portableSFTPEndpoint,
|
||||||
Username: portableSFTPUsername,
|
Username: portableSFTPUsername,
|
||||||
Password: kms.NewPlainSecret(portableSFTPPassword),
|
|
||||||
PrivateKey: kms.NewPlainSecret(portableSFTPPrivateKey),
|
|
||||||
Fingerprints: portableSFTPFingerprints,
|
Fingerprints: portableSFTPFingerprints,
|
||||||
Prefix: portableSFTPPrefix,
|
Prefix: portableSFTPPrefix,
|
||||||
DisableCouncurrentReads: portableSFTPDisableConcurrentReads,
|
DisableCouncurrentReads: portableSFTPDisableConcurrentReads,
|
||||||
BufferSize: portableSFTPDBufferSize,
|
BufferSize: portableSFTPDBufferSize,
|
||||||
},
|
},
|
||||||
|
Password: kms.NewPlainSecret(portableSFTPPassword),
|
||||||
|
PrivateKey: kms.NewPlainSecret(portableSFTPPrivateKey),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -28,24 +28,24 @@ func TestNewActionNotification(t *testing.T) {
|
||||||
}
|
}
|
||||||
user.FsConfig.Provider = sdk.LocalFilesystemProvider
|
user.FsConfig.Provider = sdk.LocalFilesystemProvider
|
||||||
user.FsConfig.S3Config = vfs.S3FsConfig{
|
user.FsConfig.S3Config = vfs.S3FsConfig{
|
||||||
S3FsConfig: sdk.S3FsConfig{
|
BaseS3FsConfig: sdk.BaseS3FsConfig{
|
||||||
Bucket: "s3bucket",
|
Bucket: "s3bucket",
|
||||||
Endpoint: "endpoint",
|
Endpoint: "endpoint",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
user.FsConfig.GCSConfig = vfs.GCSFsConfig{
|
user.FsConfig.GCSConfig = vfs.GCSFsConfig{
|
||||||
GCSFsConfig: sdk.GCSFsConfig{
|
BaseGCSFsConfig: sdk.BaseGCSFsConfig{
|
||||||
Bucket: "gcsbucket",
|
Bucket: "gcsbucket",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
user.FsConfig.AzBlobConfig = vfs.AzBlobFsConfig{
|
user.FsConfig.AzBlobConfig = vfs.AzBlobFsConfig{
|
||||||
AzBlobFsConfig: sdk.AzBlobFsConfig{
|
BaseAzBlobFsConfig: sdk.BaseAzBlobFsConfig{
|
||||||
Container: "azcontainer",
|
Container: "azcontainer",
|
||||||
Endpoint: "azendpoint",
|
Endpoint: "azendpoint",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
user.FsConfig.SFTPConfig = vfs.SFTPFsConfig{
|
user.FsConfig.SFTPConfig = vfs.SFTPFsConfig{
|
||||||
SFTPFsConfig: sdk.SFTPFsConfig{
|
BaseSFTPFsConfig: sdk.BaseSFTPFsConfig{
|
||||||
Endpoint: "sftpendpoint",
|
Endpoint: "sftpendpoint",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,8 +19,8 @@ import (
|
||||||
"golang.org/x/crypto/bcrypt"
|
"golang.org/x/crypto/bcrypt"
|
||||||
|
|
||||||
"github.com/drakkan/sftpgo/v2/dataprovider"
|
"github.com/drakkan/sftpgo/v2/dataprovider"
|
||||||
|
"github.com/drakkan/sftpgo/v2/kms"
|
||||||
"github.com/drakkan/sftpgo/v2/sdk"
|
"github.com/drakkan/sftpgo/v2/sdk"
|
||||||
"github.com/drakkan/sftpgo/v2/sdk/kms"
|
|
||||||
"github.com/drakkan/sftpgo/v2/util"
|
"github.com/drakkan/sftpgo/v2/util"
|
||||||
"github.com/drakkan/sftpgo/v2/vfs"
|
"github.com/drakkan/sftpgo/v2/vfs"
|
||||||
)
|
)
|
||||||
|
@ -731,9 +731,7 @@ func TestPostConnectHook(t *testing.T) {
|
||||||
func TestCryptoConvertFileInfo(t *testing.T) {
|
func TestCryptoConvertFileInfo(t *testing.T) {
|
||||||
name := "name"
|
name := "name"
|
||||||
fs, err := vfs.NewCryptFs("connID1", os.TempDir(), "", vfs.CryptFsConfig{
|
fs, err := vfs.NewCryptFs("connID1", os.TempDir(), "", vfs.CryptFsConfig{
|
||||||
CryptFsConfig: sdk.CryptFsConfig{
|
Passphrase: kms.NewPlainSecret("secret"),
|
||||||
Passphrase: kms.NewPlainSecret("secret"),
|
|
||||||
},
|
|
||||||
})
|
})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
cryptFs := fs.(*vfs.CryptFs)
|
cryptFs := fs.(*vfs.CryptFs)
|
||||||
|
@ -772,9 +770,7 @@ func TestFolderCopy(t *testing.T) {
|
||||||
|
|
||||||
folder.FsConfig = vfs.Filesystem{
|
folder.FsConfig = vfs.Filesystem{
|
||||||
CryptConfig: vfs.CryptFsConfig{
|
CryptConfig: vfs.CryptFsConfig{
|
||||||
CryptFsConfig: sdk.CryptFsConfig{
|
Passphrase: kms.NewPlainSecret("crypto secret"),
|
||||||
Passphrase: kms.NewPlainSecret("crypto secret"),
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
folderCopy = folder.GetACopy()
|
folderCopy = folder.GetACopy()
|
||||||
|
|
|
@ -13,8 +13,8 @@ import (
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
"github.com/drakkan/sftpgo/v2/dataprovider"
|
"github.com/drakkan/sftpgo/v2/dataprovider"
|
||||||
|
"github.com/drakkan/sftpgo/v2/kms"
|
||||||
"github.com/drakkan/sftpgo/v2/sdk"
|
"github.com/drakkan/sftpgo/v2/sdk"
|
||||||
"github.com/drakkan/sftpgo/v2/sdk/kms"
|
|
||||||
"github.com/drakkan/sftpgo/v2/vfs"
|
"github.com/drakkan/sftpgo/v2/vfs"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -419,12 +419,12 @@ func TestCheckParentDirsErrors(t *testing.T) {
|
||||||
FsConfig: vfs.Filesystem{
|
FsConfig: vfs.Filesystem{
|
||||||
Provider: sdk.S3FilesystemProvider,
|
Provider: sdk.S3FilesystemProvider,
|
||||||
S3Config: vfs.S3FsConfig{
|
S3Config: vfs.S3FsConfig{
|
||||||
S3FsConfig: sdk.S3FsConfig{
|
BaseS3FsConfig: sdk.BaseS3FsConfig{
|
||||||
Bucket: "buck",
|
Bucket: "buck",
|
||||||
Region: "us-east-1",
|
Region: "us-east-1",
|
||||||
AccessKey: "key",
|
AccessKey: "key",
|
||||||
AccessSecret: kms.NewPlainSecret("s3secret"),
|
|
||||||
},
|
},
|
||||||
|
AccessSecret: kms.NewPlainSecret("s3secret"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,10 +34,10 @@ import (
|
||||||
"github.com/drakkan/sftpgo/v2/dataprovider"
|
"github.com/drakkan/sftpgo/v2/dataprovider"
|
||||||
"github.com/drakkan/sftpgo/v2/httpclient"
|
"github.com/drakkan/sftpgo/v2/httpclient"
|
||||||
"github.com/drakkan/sftpgo/v2/httpdtest"
|
"github.com/drakkan/sftpgo/v2/httpdtest"
|
||||||
|
"github.com/drakkan/sftpgo/v2/kms"
|
||||||
"github.com/drakkan/sftpgo/v2/logger"
|
"github.com/drakkan/sftpgo/v2/logger"
|
||||||
"github.com/drakkan/sftpgo/v2/mfa"
|
"github.com/drakkan/sftpgo/v2/mfa"
|
||||||
"github.com/drakkan/sftpgo/v2/sdk"
|
"github.com/drakkan/sftpgo/v2/sdk"
|
||||||
"github.com/drakkan/sftpgo/v2/sdk/kms"
|
|
||||||
"github.com/drakkan/sftpgo/v2/util"
|
"github.com/drakkan/sftpgo/v2/util"
|
||||||
"github.com/drakkan/sftpgo/v2/vfs"
|
"github.com/drakkan/sftpgo/v2/vfs"
|
||||||
)
|
)
|
||||||
|
@ -2758,7 +2758,7 @@ func TestBuiltinKeyboardInteractiveAuthentication(t *testing.T) {
|
||||||
configName, _, secret, _, err := mfa.GenerateTOTPSecret(mfa.GetAvailableTOTPConfigNames()[0], user.Username)
|
configName, _, secret, _, err := mfa.GenerateTOTPSecret(mfa.GetAvailableTOTPConfigNames()[0], user.Username)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
user.Password = defaultPassword
|
user.Password = defaultPassword
|
||||||
user.Filters.TOTPConfig = sdk.TOTPConfig{
|
user.Filters.TOTPConfig = dataprovider.UserTOTPConfig{
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
ConfigName: configName,
|
ConfigName: configName,
|
||||||
Secret: kms.NewPlainSecret(secret),
|
Secret: kms.NewPlainSecret(secret),
|
||||||
|
@ -2926,11 +2926,11 @@ func TestSFTPLoopError(t *testing.T) {
|
||||||
FsConfig: vfs.Filesystem{
|
FsConfig: vfs.Filesystem{
|
||||||
Provider: sdk.SFTPFilesystemProvider,
|
Provider: sdk.SFTPFilesystemProvider,
|
||||||
SFTPConfig: vfs.SFTPFsConfig{
|
SFTPConfig: vfs.SFTPFsConfig{
|
||||||
SFTPFsConfig: sdk.SFTPFsConfig{
|
BaseSFTPFsConfig: sdk.BaseSFTPFsConfig{
|
||||||
Endpoint: sftpServerAddr,
|
Endpoint: sftpServerAddr,
|
||||||
Username: user2.Username,
|
Username: user2.Username,
|
||||||
Password: kms.NewPlainSecret(defaultPassword),
|
|
||||||
},
|
},
|
||||||
|
Password: kms.NewPlainSecret(defaultPassword),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -2939,11 +2939,11 @@ func TestSFTPLoopError(t *testing.T) {
|
||||||
|
|
||||||
user2.FsConfig.Provider = sdk.SFTPFilesystemProvider
|
user2.FsConfig.Provider = sdk.SFTPFilesystemProvider
|
||||||
user2.FsConfig.SFTPConfig = vfs.SFTPFsConfig{
|
user2.FsConfig.SFTPConfig = vfs.SFTPFsConfig{
|
||||||
SFTPFsConfig: sdk.SFTPFsConfig{
|
BaseSFTPFsConfig: sdk.BaseSFTPFsConfig{
|
||||||
Endpoint: sftpServerAddr,
|
Endpoint: sftpServerAddr,
|
||||||
Username: user1.Username,
|
Username: user1.Username,
|
||||||
Password: kms.NewPlainSecret(defaultPassword),
|
|
||||||
},
|
},
|
||||||
|
Password: kms.NewPlainSecret(defaultPassword),
|
||||||
}
|
}
|
||||||
|
|
||||||
user1, resp, err := httpdtest.AddUser(user1, http.StatusCreated)
|
user1, resp, err := httpdtest.AddUser(user1, http.StatusCreated)
|
||||||
|
@ -2995,11 +2995,11 @@ func TestNonLocalCrossRename(t *testing.T) {
|
||||||
FsConfig: vfs.Filesystem{
|
FsConfig: vfs.Filesystem{
|
||||||
Provider: sdk.SFTPFilesystemProvider,
|
Provider: sdk.SFTPFilesystemProvider,
|
||||||
SFTPConfig: vfs.SFTPFsConfig{
|
SFTPConfig: vfs.SFTPFsConfig{
|
||||||
SFTPFsConfig: sdk.SFTPFsConfig{
|
BaseSFTPFsConfig: sdk.BaseSFTPFsConfig{
|
||||||
Endpoint: sftpServerAddr,
|
Endpoint: sftpServerAddr,
|
||||||
Username: baseUser.Username,
|
Username: baseUser.Username,
|
||||||
Password: kms.NewPlainSecret(defaultPassword),
|
|
||||||
},
|
},
|
||||||
|
Password: kms.NewPlainSecret(defaultPassword),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -3014,9 +3014,7 @@ func TestNonLocalCrossRename(t *testing.T) {
|
||||||
FsConfig: vfs.Filesystem{
|
FsConfig: vfs.Filesystem{
|
||||||
Provider: sdk.CryptedFilesystemProvider,
|
Provider: sdk.CryptedFilesystemProvider,
|
||||||
CryptConfig: vfs.CryptFsConfig{
|
CryptConfig: vfs.CryptFsConfig{
|
||||||
CryptFsConfig: sdk.CryptFsConfig{
|
Passphrase: kms.NewPlainSecret(defaultPassword),
|
||||||
Passphrase: kms.NewPlainSecret(defaultPassword),
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
MappedPath: mappedPathCrypt,
|
MappedPath: mappedPathCrypt,
|
||||||
|
@ -3117,9 +3115,7 @@ func TestNonLocalCrossRenameNonLocalBaseUser(t *testing.T) {
|
||||||
FsConfig: vfs.Filesystem{
|
FsConfig: vfs.Filesystem{
|
||||||
Provider: sdk.CryptedFilesystemProvider,
|
Provider: sdk.CryptedFilesystemProvider,
|
||||||
CryptConfig: vfs.CryptFsConfig{
|
CryptConfig: vfs.CryptFsConfig{
|
||||||
CryptFsConfig: sdk.CryptFsConfig{
|
Passphrase: kms.NewPlainSecret(defaultPassword),
|
||||||
Passphrase: kms.NewPlainSecret(defaultPassword),
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
MappedPath: mappedPathCrypt,
|
MappedPath: mappedPathCrypt,
|
||||||
|
|
|
@ -11,8 +11,8 @@ import (
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
"github.com/drakkan/sftpgo/v2/dataprovider"
|
"github.com/drakkan/sftpgo/v2/dataprovider"
|
||||||
|
"github.com/drakkan/sftpgo/v2/kms"
|
||||||
"github.com/drakkan/sftpgo/v2/sdk"
|
"github.com/drakkan/sftpgo/v2/sdk"
|
||||||
"github.com/drakkan/sftpgo/v2/sdk/kms"
|
|
||||||
"github.com/drakkan/sftpgo/v2/vfs"
|
"github.com/drakkan/sftpgo/v2/vfs"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -264,7 +264,7 @@ func TestTransferErrors(t *testing.T) {
|
||||||
|
|
||||||
func TestRemovePartialCryptoFile(t *testing.T) {
|
func TestRemovePartialCryptoFile(t *testing.T) {
|
||||||
testFile := filepath.Join(os.TempDir(), "transfer_test_file")
|
testFile := filepath.Join(os.TempDir(), "transfer_test_file")
|
||||||
fs, err := vfs.NewCryptFs("id", os.TempDir(), "", vfs.CryptFsConfig{CryptFsConfig: sdk.CryptFsConfig{Passphrase: kms.NewPlainSecret("secret")}})
|
fs, err := vfs.NewCryptFs("id", os.TempDir(), "", vfs.CryptFsConfig{Passphrase: kms.NewPlainSecret("secret")})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
u := dataprovider.User{
|
u := dataprovider.User{
|
||||||
BaseUser: sdk.BaseUser{
|
BaseUser: sdk.BaseUser{
|
||||||
|
|
|
@ -16,10 +16,10 @@ import (
|
||||||
"github.com/drakkan/sftpgo/v2/ftpd"
|
"github.com/drakkan/sftpgo/v2/ftpd"
|
||||||
"github.com/drakkan/sftpgo/v2/httpclient"
|
"github.com/drakkan/sftpgo/v2/httpclient"
|
||||||
"github.com/drakkan/sftpgo/v2/httpd"
|
"github.com/drakkan/sftpgo/v2/httpd"
|
||||||
|
"github.com/drakkan/sftpgo/v2/kms"
|
||||||
"github.com/drakkan/sftpgo/v2/logger"
|
"github.com/drakkan/sftpgo/v2/logger"
|
||||||
"github.com/drakkan/sftpgo/v2/mfa"
|
"github.com/drakkan/sftpgo/v2/mfa"
|
||||||
"github.com/drakkan/sftpgo/v2/plugin"
|
"github.com/drakkan/sftpgo/v2/plugin"
|
||||||
"github.com/drakkan/sftpgo/v2/sdk/kms"
|
|
||||||
"github.com/drakkan/sftpgo/v2/sftpd"
|
"github.com/drakkan/sftpgo/v2/sftpd"
|
||||||
"github.com/drakkan/sftpgo/v2/smtp"
|
"github.com/drakkan/sftpgo/v2/smtp"
|
||||||
"github.com/drakkan/sftpgo/v2/telemetry"
|
"github.com/drakkan/sftpgo/v2/telemetry"
|
||||||
|
|
|
@ -19,7 +19,7 @@ import (
|
||||||
"github.com/drakkan/sftpgo/v2/httpd"
|
"github.com/drakkan/sftpgo/v2/httpd"
|
||||||
"github.com/drakkan/sftpgo/v2/mfa"
|
"github.com/drakkan/sftpgo/v2/mfa"
|
||||||
"github.com/drakkan/sftpgo/v2/plugin"
|
"github.com/drakkan/sftpgo/v2/plugin"
|
||||||
"github.com/drakkan/sftpgo/v2/sdk/kms"
|
sdkkms "github.com/drakkan/sftpgo/v2/sdk/kms"
|
||||||
"github.com/drakkan/sftpgo/v2/sftpd"
|
"github.com/drakkan/sftpgo/v2/sftpd"
|
||||||
"github.com/drakkan/sftpgo/v2/smtp"
|
"github.com/drakkan/sftpgo/v2/smtp"
|
||||||
"github.com/drakkan/sftpgo/v2/util"
|
"github.com/drakkan/sftpgo/v2/util"
|
||||||
|
@ -467,8 +467,8 @@ func TestPluginsFromEnv(t *testing.T) {
|
||||||
os.Setenv("SFTPGO_PLUGINS__0__ARGS", "arg1,arg2")
|
os.Setenv("SFTPGO_PLUGINS__0__ARGS", "arg1,arg2")
|
||||||
os.Setenv("SFTPGO_PLUGINS__0__SHA256SUM", "0a71ded61fccd59c4f3695b51c1b3d180da8d2d77ea09ccee20dac242675c193")
|
os.Setenv("SFTPGO_PLUGINS__0__SHA256SUM", "0a71ded61fccd59c4f3695b51c1b3d180da8d2d77ea09ccee20dac242675c193")
|
||||||
os.Setenv("SFTPGO_PLUGINS__0__AUTO_MTLS", "1")
|
os.Setenv("SFTPGO_PLUGINS__0__AUTO_MTLS", "1")
|
||||||
os.Setenv("SFTPGO_PLUGINS__0__KMS_OPTIONS__SCHEME", kms.SchemeAWS)
|
os.Setenv("SFTPGO_PLUGINS__0__KMS_OPTIONS__SCHEME", sdkkms.SchemeAWS)
|
||||||
os.Setenv("SFTPGO_PLUGINS__0__KMS_OPTIONS__ENCRYPTED_STATUS", kms.SecretStatusAWS)
|
os.Setenv("SFTPGO_PLUGINS__0__KMS_OPTIONS__ENCRYPTED_STATUS", sdkkms.SecretStatusAWS)
|
||||||
os.Setenv("SFTPGO_PLUGINS__0__AUTH_OPTIONS__SCOPE", "14")
|
os.Setenv("SFTPGO_PLUGINS__0__AUTH_OPTIONS__SCOPE", "14")
|
||||||
t.Cleanup(func() {
|
t.Cleanup(func() {
|
||||||
os.Unsetenv("SFTPGO_PLUGINS__0__TYPE")
|
os.Unsetenv("SFTPGO_PLUGINS__0__TYPE")
|
||||||
|
@ -510,8 +510,8 @@ func TestPluginsFromEnv(t *testing.T) {
|
||||||
require.Equal(t, "arg2", pluginConf.Args[1])
|
require.Equal(t, "arg2", pluginConf.Args[1])
|
||||||
require.Equal(t, "0a71ded61fccd59c4f3695b51c1b3d180da8d2d77ea09ccee20dac242675c193", pluginConf.SHA256Sum)
|
require.Equal(t, "0a71ded61fccd59c4f3695b51c1b3d180da8d2d77ea09ccee20dac242675c193", pluginConf.SHA256Sum)
|
||||||
require.True(t, pluginConf.AutoMTLS)
|
require.True(t, pluginConf.AutoMTLS)
|
||||||
require.Equal(t, kms.SchemeAWS, pluginConf.KMSOptions.Scheme)
|
require.Equal(t, sdkkms.SchemeAWS, pluginConf.KMSOptions.Scheme)
|
||||||
require.Equal(t, kms.SecretStatusAWS, pluginConf.KMSOptions.EncryptedStatus)
|
require.Equal(t, sdkkms.SecretStatusAWS, pluginConf.KMSOptions.EncryptedStatus)
|
||||||
require.Equal(t, 14, pluginConf.AuthOptions.Scope)
|
require.Equal(t, 14, pluginConf.AuthOptions.Scope)
|
||||||
|
|
||||||
configAsJSON, err := json.Marshal(pluginsConf)
|
configAsJSON, err := json.Marshal(pluginsConf)
|
||||||
|
@ -524,8 +524,8 @@ func TestPluginsFromEnv(t *testing.T) {
|
||||||
os.Setenv("SFTPGO_PLUGINS__0__CMD", "plugin_start_cmd1")
|
os.Setenv("SFTPGO_PLUGINS__0__CMD", "plugin_start_cmd1")
|
||||||
os.Setenv("SFTPGO_PLUGINS__0__ARGS", "")
|
os.Setenv("SFTPGO_PLUGINS__0__ARGS", "")
|
||||||
os.Setenv("SFTPGO_PLUGINS__0__AUTO_MTLS", "0")
|
os.Setenv("SFTPGO_PLUGINS__0__AUTO_MTLS", "0")
|
||||||
os.Setenv("SFTPGO_PLUGINS__0__KMS_OPTIONS__SCHEME", kms.SchemeVaultTransit)
|
os.Setenv("SFTPGO_PLUGINS__0__KMS_OPTIONS__SCHEME", sdkkms.SchemeVaultTransit)
|
||||||
os.Setenv("SFTPGO_PLUGINS__0__KMS_OPTIONS__ENCRYPTED_STATUS", kms.SecretStatusVaultTransit)
|
os.Setenv("SFTPGO_PLUGINS__0__KMS_OPTIONS__ENCRYPTED_STATUS", sdkkms.SecretStatusVaultTransit)
|
||||||
err = config.LoadConfig(configDir, confName)
|
err = config.LoadConfig(configDir, confName)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
pluginsConf = config.GetPluginsConfig()
|
pluginsConf = config.GetPluginsConfig()
|
||||||
|
@ -547,8 +547,8 @@ func TestPluginsFromEnv(t *testing.T) {
|
||||||
require.Len(t, pluginConf.Args, 0)
|
require.Len(t, pluginConf.Args, 0)
|
||||||
require.Equal(t, "0a71ded61fccd59c4f3695b51c1b3d180da8d2d77ea09ccee20dac242675c193", pluginConf.SHA256Sum)
|
require.Equal(t, "0a71ded61fccd59c4f3695b51c1b3d180da8d2d77ea09ccee20dac242675c193", pluginConf.SHA256Sum)
|
||||||
require.False(t, pluginConf.AutoMTLS)
|
require.False(t, pluginConf.AutoMTLS)
|
||||||
require.Equal(t, kms.SchemeVaultTransit, pluginConf.KMSOptions.Scheme)
|
require.Equal(t, sdkkms.SchemeVaultTransit, pluginConf.KMSOptions.Scheme)
|
||||||
require.Equal(t, kms.SecretStatusVaultTransit, pluginConf.KMSOptions.EncryptedStatus)
|
require.Equal(t, sdkkms.SecretStatusVaultTransit, pluginConf.KMSOptions.EncryptedStatus)
|
||||||
require.Equal(t, 14, pluginConf.AuthOptions.Scope)
|
require.Equal(t, 14, pluginConf.AuthOptions.Scope)
|
||||||
|
|
||||||
err = os.Remove(configFilePath)
|
err = os.Remove(configFilePath)
|
||||||
|
|
|
@ -15,10 +15,9 @@ import (
|
||||||
passwordvalidator "github.com/wagslane/go-password-validator"
|
passwordvalidator "github.com/wagslane/go-password-validator"
|
||||||
"golang.org/x/crypto/bcrypt"
|
"golang.org/x/crypto/bcrypt"
|
||||||
|
|
||||||
|
"github.com/drakkan/sftpgo/v2/kms"
|
||||||
"github.com/drakkan/sftpgo/v2/logger"
|
"github.com/drakkan/sftpgo/v2/logger"
|
||||||
"github.com/drakkan/sftpgo/v2/mfa"
|
"github.com/drakkan/sftpgo/v2/mfa"
|
||||||
"github.com/drakkan/sftpgo/v2/sdk"
|
|
||||||
"github.com/drakkan/sftpgo/v2/sdk/kms"
|
|
||||||
"github.com/drakkan/sftpgo/v2/util"
|
"github.com/drakkan/sftpgo/v2/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -52,14 +51,14 @@ var (
|
||||||
PermAdminViewEvents}
|
PermAdminViewEvents}
|
||||||
)
|
)
|
||||||
|
|
||||||
// TOTPConfig defines the time-based one time password configuration
|
// AdminTOTPConfig defines the time-based one time password configuration
|
||||||
type TOTPConfig struct {
|
type AdminTOTPConfig struct {
|
||||||
Enabled bool `json:"enabled,omitempty"`
|
Enabled bool `json:"enabled,omitempty"`
|
||||||
ConfigName string `json:"config_name,omitempty"`
|
ConfigName string `json:"config_name,omitempty"`
|
||||||
Secret *kms.Secret `json:"secret,omitempty"`
|
Secret *kms.Secret `json:"secret,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *TOTPConfig) validate(username string) error {
|
func (c *AdminTOTPConfig) validate(username string) error {
|
||||||
if !c.Enabled {
|
if !c.Enabled {
|
||||||
c.ConfigName = ""
|
c.ConfigName = ""
|
||||||
c.Secret = kms.NewEmptySecret()
|
c.Secret = kms.NewEmptySecret()
|
||||||
|
@ -93,11 +92,11 @@ type AdminFilters struct {
|
||||||
// API key auth allows to impersonate this administrator with an API key
|
// API key auth allows to impersonate this administrator with an API key
|
||||||
AllowAPIKeyAuth bool `json:"allow_api_key_auth,omitempty"`
|
AllowAPIKeyAuth bool `json:"allow_api_key_auth,omitempty"`
|
||||||
// Time-based one time passwords configuration
|
// Time-based one time passwords configuration
|
||||||
TOTPConfig TOTPConfig `json:"totp_config,omitempty"`
|
TOTPConfig AdminTOTPConfig `json:"totp_config,omitempty"`
|
||||||
// Recovery codes to use if the user loses access to their second factor auth device.
|
// Recovery codes to use if the user loses access to their second factor auth device.
|
||||||
// Each code can only be used once, you should use these codes to login and disable or
|
// Each code can only be used once, you should use these codes to login and disable or
|
||||||
// reset 2FA for your account
|
// reset 2FA for your account
|
||||||
RecoveryCodes []sdk.RecoveryCode `json:"recovery_codes,omitempty"`
|
RecoveryCodes []RecoveryCode `json:"recovery_codes,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Admin defines a SFTPGo admin
|
// Admin defines a SFTPGo admin
|
||||||
|
@ -403,12 +402,12 @@ func (a *Admin) getACopy() Admin {
|
||||||
filters.TOTPConfig.ConfigName = a.Filters.TOTPConfig.ConfigName
|
filters.TOTPConfig.ConfigName = a.Filters.TOTPConfig.ConfigName
|
||||||
filters.TOTPConfig.Secret = a.Filters.TOTPConfig.Secret.Clone()
|
filters.TOTPConfig.Secret = a.Filters.TOTPConfig.Secret.Clone()
|
||||||
copy(filters.AllowList, a.Filters.AllowList)
|
copy(filters.AllowList, a.Filters.AllowList)
|
||||||
filters.RecoveryCodes = make([]sdk.RecoveryCode, 0)
|
filters.RecoveryCodes = make([]RecoveryCode, 0)
|
||||||
for _, code := range a.Filters.RecoveryCodes {
|
for _, code := range a.Filters.RecoveryCodes {
|
||||||
if code.Secret == nil {
|
if code.Secret == nil {
|
||||||
code.Secret = kms.NewEmptySecret()
|
code.Secret = kms.NewEmptySecret()
|
||||||
}
|
}
|
||||||
filters.RecoveryCodes = append(filters.RecoveryCodes, sdk.RecoveryCode{
|
filters.RecoveryCodes = append(filters.RecoveryCodes, RecoveryCode{
|
||||||
Secret: code.Secret.Clone(),
|
Secret: code.Secret.Clone(),
|
||||||
Used: code.Used,
|
Used: code.Used,
|
||||||
})
|
})
|
||||||
|
|
|
@ -46,12 +46,12 @@ import (
|
||||||
"golang.org/x/crypto/ssh"
|
"golang.org/x/crypto/ssh"
|
||||||
|
|
||||||
"github.com/drakkan/sftpgo/v2/httpclient"
|
"github.com/drakkan/sftpgo/v2/httpclient"
|
||||||
|
"github.com/drakkan/sftpgo/v2/kms"
|
||||||
"github.com/drakkan/sftpgo/v2/logger"
|
"github.com/drakkan/sftpgo/v2/logger"
|
||||||
"github.com/drakkan/sftpgo/v2/metric"
|
"github.com/drakkan/sftpgo/v2/metric"
|
||||||
"github.com/drakkan/sftpgo/v2/mfa"
|
"github.com/drakkan/sftpgo/v2/mfa"
|
||||||
"github.com/drakkan/sftpgo/v2/plugin"
|
"github.com/drakkan/sftpgo/v2/plugin"
|
||||||
"github.com/drakkan/sftpgo/v2/sdk"
|
"github.com/drakkan/sftpgo/v2/sdk"
|
||||||
"github.com/drakkan/sftpgo/v2/sdk/kms"
|
|
||||||
"github.com/drakkan/sftpgo/v2/util"
|
"github.com/drakkan/sftpgo/v2/util"
|
||||||
"github.com/drakkan/sftpgo/v2/vfs"
|
"github.com/drakkan/sftpgo/v2/vfs"
|
||||||
)
|
)
|
||||||
|
@ -1153,7 +1153,7 @@ func HasAdmin() bool {
|
||||||
// AddAdmin adds a new SFTPGo admin
|
// AddAdmin adds a new SFTPGo admin
|
||||||
func AddAdmin(admin *Admin, executor, ipAddress string) error {
|
func AddAdmin(admin *Admin, executor, ipAddress string) error {
|
||||||
admin.Filters.RecoveryCodes = nil
|
admin.Filters.RecoveryCodes = nil
|
||||||
admin.Filters.TOTPConfig = TOTPConfig{
|
admin.Filters.TOTPConfig = AdminTOTPConfig{
|
||||||
Enabled: false,
|
Enabled: false,
|
||||||
}
|
}
|
||||||
err := provider.addAdmin(admin)
|
err := provider.addAdmin(admin)
|
||||||
|
@ -1199,7 +1199,7 @@ func UserExists(username string) (User, error) {
|
||||||
// AddUser adds a new SFTPGo user.
|
// AddUser adds a new SFTPGo user.
|
||||||
func AddUser(user *User, executor, ipAddress string) error {
|
func AddUser(user *User, executor, ipAddress string) error {
|
||||||
user.Filters.RecoveryCodes = nil
|
user.Filters.RecoveryCodes = nil
|
||||||
user.Filters.TOTPConfig = sdk.TOTPConfig{
|
user.Filters.TOTPConfig = UserTOTPConfig{
|
||||||
Enabled: false,
|
Enabled: false,
|
||||||
}
|
}
|
||||||
err := provider.addUser(user)
|
err := provider.addUser(user)
|
||||||
|
@ -1559,7 +1559,7 @@ func validateUserVirtualFolders(user *User) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func validateUserTOTPConfig(c *sdk.TOTPConfig, username string) error {
|
func validateUserTOTPConfig(c *UserTOTPConfig, username string) error {
|
||||||
if !c.Enabled {
|
if !c.Enabled {
|
||||||
c.ConfigName = ""
|
c.ConfigName = ""
|
||||||
c.Secret = kms.NewEmptySecret()
|
c.Secret = kms.NewEmptySecret()
|
||||||
|
|
|
@ -13,7 +13,6 @@ import (
|
||||||
"github.com/cockroachdb/cockroach-go/v2/crdb"
|
"github.com/cockroachdb/cockroach-go/v2/crdb"
|
||||||
|
|
||||||
"github.com/drakkan/sftpgo/v2/logger"
|
"github.com/drakkan/sftpgo/v2/logger"
|
||||||
"github.com/drakkan/sftpgo/v2/sdk"
|
|
||||||
"github.com/drakkan/sftpgo/v2/util"
|
"github.com/drakkan/sftpgo/v2/util"
|
||||||
"github.com/drakkan/sftpgo/v2/vfs"
|
"github.com/drakkan/sftpgo/v2/vfs"
|
||||||
)
|
)
|
||||||
|
@ -1386,7 +1385,7 @@ func getUserFromDbRow(row sqlScanner) (User, error) {
|
||||||
user.Permissions = perms
|
user.Permissions = perms
|
||||||
}
|
}
|
||||||
if filters.Valid {
|
if filters.Valid {
|
||||||
var userFilters sdk.UserFilters
|
var userFilters UserFilters
|
||||||
err = json.Unmarshal([]byte(filters.String), &userFilters)
|
err = json.Unmarshal([]byte(filters.String), &userFilters)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
user.Filters = userFilters
|
user.Filters = userFilters
|
||||||
|
|
|
@ -15,10 +15,10 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/drakkan/sftpgo/v2/kms"
|
||||||
"github.com/drakkan/sftpgo/v2/logger"
|
"github.com/drakkan/sftpgo/v2/logger"
|
||||||
"github.com/drakkan/sftpgo/v2/mfa"
|
"github.com/drakkan/sftpgo/v2/mfa"
|
||||||
"github.com/drakkan/sftpgo/v2/sdk"
|
"github.com/drakkan/sftpgo/v2/sdk"
|
||||||
"github.com/drakkan/sftpgo/v2/sdk/kms"
|
|
||||||
"github.com/drakkan/sftpgo/v2/util"
|
"github.com/drakkan/sftpgo/v2/util"
|
||||||
"github.com/drakkan/sftpgo/v2/vfs"
|
"github.com/drakkan/sftpgo/v2/vfs"
|
||||||
)
|
)
|
||||||
|
@ -79,9 +79,44 @@ var (
|
||||||
permsCreateAny = []string{PermUpload, PermCreateDirs}
|
permsCreateAny = []string{PermUpload, PermCreateDirs}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// RecoveryCode defines a 2FA recovery code
|
||||||
|
type RecoveryCode struct {
|
||||||
|
Secret *kms.Secret `json:"secret"`
|
||||||
|
Used bool `json:"used,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// UserTOTPConfig defines the time-based one time password configuration
|
||||||
|
type UserTOTPConfig struct {
|
||||||
|
Enabled bool `json:"enabled,omitempty"`
|
||||||
|
ConfigName string `json:"config_name,omitempty"`
|
||||||
|
Secret *kms.Secret `json:"secret,omitempty"`
|
||||||
|
// TOTP will be required for the specified protocols.
|
||||||
|
// SSH protocol (SFTP/SCP/SSH commands) will ask for the TOTP passcode if the client uses keyboard interactive
|
||||||
|
// authentication.
|
||||||
|
// FTP have no standard way to support two factor authentication, if you
|
||||||
|
// enable the support for this protocol you have to add the TOTP passcode after the password.
|
||||||
|
// For example if your password is "password" and your one time passcode is
|
||||||
|
// "123456" you have to use "password123456" as password.
|
||||||
|
Protocols []string `json:"protocols,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// UserFilters defines additional restrictions for a user
|
||||||
|
// TODO: rename to UserOptions in v3
|
||||||
|
type UserFilters struct {
|
||||||
|
sdk.BaseUserFilters
|
||||||
|
// Time-based one time passwords configuration
|
||||||
|
TOTPConfig UserTOTPConfig `json:"totp_config,omitempty"`
|
||||||
|
// Recovery codes to use if the user loses access to their second factor auth device.
|
||||||
|
// Each code can only be used once, you should use these codes to login and disable or
|
||||||
|
// reset 2FA for your account
|
||||||
|
RecoveryCodes []RecoveryCode `json:"recovery_codes,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
// User defines a SFTPGo user
|
// User defines a SFTPGo user
|
||||||
type User struct {
|
type User struct {
|
||||||
sdk.BaseUser
|
sdk.BaseUser
|
||||||
|
// Additional restrictions
|
||||||
|
Filters UserFilters `json:"filters"`
|
||||||
// Mapping between virtual paths and virtual folders
|
// Mapping between virtual paths and virtual folders
|
||||||
VirtualFolders []vfs.VirtualFolder `json:"virtual_folders,omitempty"`
|
VirtualFolders []vfs.VirtualFolder `json:"virtual_folders,omitempty"`
|
||||||
// Filesystem configuration details
|
// Filesystem configuration details
|
||||||
|
@ -1168,7 +1203,7 @@ func (u *User) getACopy() User {
|
||||||
copy(perms, v)
|
copy(perms, v)
|
||||||
permissions[k] = perms
|
permissions[k] = perms
|
||||||
}
|
}
|
||||||
filters := sdk.UserFilters{}
|
filters := UserFilters{}
|
||||||
filters.MaxUploadFileSize = u.Filters.MaxUploadFileSize
|
filters.MaxUploadFileSize = u.Filters.MaxUploadFileSize
|
||||||
filters.TLSUsername = u.Filters.TLSUsername
|
filters.TLSUsername = u.Filters.TLSUsername
|
||||||
filters.UserType = u.Filters.UserType
|
filters.UserType = u.Filters.UserType
|
||||||
|
@ -1194,12 +1229,12 @@ func (u *User) getACopy() User {
|
||||||
filters.AllowAPIKeyAuth = u.Filters.AllowAPIKeyAuth
|
filters.AllowAPIKeyAuth = u.Filters.AllowAPIKeyAuth
|
||||||
filters.WebClient = make([]string, len(u.Filters.WebClient))
|
filters.WebClient = make([]string, len(u.Filters.WebClient))
|
||||||
copy(filters.WebClient, u.Filters.WebClient)
|
copy(filters.WebClient, u.Filters.WebClient)
|
||||||
filters.RecoveryCodes = make([]sdk.RecoveryCode, 0, len(u.Filters.RecoveryCodes))
|
filters.RecoveryCodes = make([]RecoveryCode, 0, len(u.Filters.RecoveryCodes))
|
||||||
for _, code := range u.Filters.RecoveryCodes {
|
for _, code := range u.Filters.RecoveryCodes {
|
||||||
if code.Secret == nil {
|
if code.Secret == nil {
|
||||||
code.Secret = kms.NewEmptySecret()
|
code.Secret = kms.NewEmptySecret()
|
||||||
}
|
}
|
||||||
filters.RecoveryCodes = append(filters.RecoveryCodes, sdk.RecoveryCode{
|
filters.RecoveryCodes = append(filters.RecoveryCodes, RecoveryCode{
|
||||||
Secret: code.Secret.Clone(),
|
Secret: code.Secret.Clone(),
|
||||||
Used: code.Used,
|
Used: code.Used,
|
||||||
})
|
})
|
||||||
|
@ -1238,12 +1273,12 @@ func (u *User) getACopy() User {
|
||||||
Status: u.Status,
|
Status: u.Status,
|
||||||
ExpirationDate: u.ExpirationDate,
|
ExpirationDate: u.ExpirationDate,
|
||||||
LastLogin: u.LastLogin,
|
LastLogin: u.LastLogin,
|
||||||
Filters: filters,
|
|
||||||
AdditionalInfo: u.AdditionalInfo,
|
AdditionalInfo: u.AdditionalInfo,
|
||||||
Description: u.Description,
|
Description: u.Description,
|
||||||
CreatedAt: u.CreatedAt,
|
CreatedAt: u.CreatedAt,
|
||||||
UpdatedAt: u.UpdatedAt,
|
UpdatedAt: u.UpdatedAt,
|
||||||
},
|
},
|
||||||
|
Filters: filters,
|
||||||
VirtualFolders: virtualFolders,
|
VirtualFolders: virtualFolders,
|
||||||
FsConfig: u.FsConfig.GetACopy(),
|
FsConfig: u.FsConfig.GetACopy(),
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,8 +18,8 @@ import (
|
||||||
"github.com/drakkan/sftpgo/v2/common"
|
"github.com/drakkan/sftpgo/v2/common"
|
||||||
"github.com/drakkan/sftpgo/v2/dataprovider"
|
"github.com/drakkan/sftpgo/v2/dataprovider"
|
||||||
"github.com/drakkan/sftpgo/v2/httpdtest"
|
"github.com/drakkan/sftpgo/v2/httpdtest"
|
||||||
|
"github.com/drakkan/sftpgo/v2/kms"
|
||||||
"github.com/drakkan/sftpgo/v2/sdk"
|
"github.com/drakkan/sftpgo/v2/sdk"
|
||||||
"github.com/drakkan/sftpgo/v2/sdk/kms"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestBasicFTPHandlingCryptFs(t *testing.T) {
|
func TestBasicFTPHandlingCryptFs(t *testing.T) {
|
||||||
|
|
|
@ -32,10 +32,11 @@ import (
|
||||||
"github.com/drakkan/sftpgo/v2/dataprovider"
|
"github.com/drakkan/sftpgo/v2/dataprovider"
|
||||||
"github.com/drakkan/sftpgo/v2/ftpd"
|
"github.com/drakkan/sftpgo/v2/ftpd"
|
||||||
"github.com/drakkan/sftpgo/v2/httpdtest"
|
"github.com/drakkan/sftpgo/v2/httpdtest"
|
||||||
|
"github.com/drakkan/sftpgo/v2/kms"
|
||||||
"github.com/drakkan/sftpgo/v2/logger"
|
"github.com/drakkan/sftpgo/v2/logger"
|
||||||
"github.com/drakkan/sftpgo/v2/mfa"
|
"github.com/drakkan/sftpgo/v2/mfa"
|
||||||
"github.com/drakkan/sftpgo/v2/sdk"
|
"github.com/drakkan/sftpgo/v2/sdk"
|
||||||
"github.com/drakkan/sftpgo/v2/sdk/kms"
|
sdkkms "github.com/drakkan/sftpgo/v2/sdk/kms"
|
||||||
"github.com/drakkan/sftpgo/v2/sftpd"
|
"github.com/drakkan/sftpgo/v2/sftpd"
|
||||||
"github.com/drakkan/sftpgo/v2/vfs"
|
"github.com/drakkan/sftpgo/v2/vfs"
|
||||||
)
|
)
|
||||||
|
@ -604,7 +605,7 @@ func TestMultiFactorAuth(t *testing.T) {
|
||||||
configName, _, secret, _, err := mfa.GenerateTOTPSecret(mfa.GetAvailableTOTPConfigNames()[0], user.Username)
|
configName, _, secret, _, err := mfa.GenerateTOTPSecret(mfa.GetAvailableTOTPConfigNames()[0], user.Username)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
user.Password = defaultPassword
|
user.Password = defaultPassword
|
||||||
user.Filters.TOTPConfig = sdk.TOTPConfig{
|
user.Filters.TOTPConfig = dataprovider.UserTOTPConfig{
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
ConfigName: configName,
|
ConfigName: configName,
|
||||||
Secret: kms.NewPlainSecret(secret),
|
Secret: kms.NewPlainSecret(secret),
|
||||||
|
@ -1686,7 +1687,7 @@ func TestLoginWithDatabaseCredentials(t *testing.T) {
|
||||||
|
|
||||||
user, _, err := httpdtest.AddUser(u, http.StatusCreated)
|
user, _, err := httpdtest.AddUser(u, http.StatusCreated)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, kms.SecretStatusSecretBox, user.FsConfig.GCSConfig.Credentials.GetStatus())
|
assert.Equal(t, sdkkms.SecretStatusSecretBox, user.FsConfig.GCSConfig.Credentials.GetStatus())
|
||||||
assert.NotEmpty(t, user.FsConfig.GCSConfig.Credentials.GetPayload())
|
assert.NotEmpty(t, user.FsConfig.GCSConfig.Credentials.GetPayload())
|
||||||
assert.Empty(t, user.FsConfig.GCSConfig.Credentials.GetAdditionalData())
|
assert.Empty(t, user.FsConfig.GCSConfig.Credentials.GetAdditionalData())
|
||||||
assert.Empty(t, user.FsConfig.GCSConfig.Credentials.GetKey())
|
assert.Empty(t, user.FsConfig.GCSConfig.Credentials.GetKey())
|
||||||
|
@ -2808,9 +2809,7 @@ func TestNestedVirtualFolders(t *testing.T) {
|
||||||
FsConfig: vfs.Filesystem{
|
FsConfig: vfs.Filesystem{
|
||||||
Provider: sdk.CryptedFilesystemProvider,
|
Provider: sdk.CryptedFilesystemProvider,
|
||||||
CryptConfig: vfs.CryptFsConfig{
|
CryptConfig: vfs.CryptFsConfig{
|
||||||
CryptFsConfig: sdk.CryptFsConfig{
|
Passphrase: kms.NewPlainSecret(defaultPassword),
|
||||||
Passphrase: kms.NewPlainSecret(defaultPassword),
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
MappedPath: mappedPathCrypt,
|
MappedPath: mappedPathCrypt,
|
||||||
|
|
|
@ -83,7 +83,7 @@ func disableAdmin2FA(w http.ResponseWriter, r *http.Request) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
admin.Filters.RecoveryCodes = nil
|
admin.Filters.RecoveryCodes = nil
|
||||||
admin.Filters.TOTPConfig = dataprovider.TOTPConfig{
|
admin.Filters.TOTPConfig = dataprovider.AdminTOTPConfig{
|
||||||
Enabled: false,
|
Enabled: false,
|
||||||
}
|
}
|
||||||
if err := dataprovider.UpdateAdmin(&admin, claims.Username, util.GetIPFromRemoteAddress(r.RemoteAddr)); err != nil {
|
if err := dataprovider.UpdateAdmin(&admin, claims.Username, util.GetIPFromRemoteAddress(r.RemoteAddr)); err != nil {
|
||||||
|
@ -105,7 +105,7 @@ func updateAdmin(w http.ResponseWriter, r *http.Request) {
|
||||||
adminID := admin.ID
|
adminID := admin.ID
|
||||||
totpConfig := admin.Filters.TOTPConfig
|
totpConfig := admin.Filters.TOTPConfig
|
||||||
recoveryCodes := admin.Filters.RecoveryCodes
|
recoveryCodes := admin.Filters.RecoveryCodes
|
||||||
admin.Filters.TOTPConfig = dataprovider.TOTPConfig{}
|
admin.Filters.TOTPConfig = dataprovider.AdminTOTPConfig{}
|
||||||
admin.Filters.RecoveryCodes = nil
|
admin.Filters.RecoveryCodes = nil
|
||||||
err = render.DecodeJSON(r.Body, &admin)
|
err = render.DecodeJSON(r.Body, &admin)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -8,9 +8,8 @@ import (
|
||||||
"github.com/go-chi/render"
|
"github.com/go-chi/render"
|
||||||
|
|
||||||
"github.com/drakkan/sftpgo/v2/dataprovider"
|
"github.com/drakkan/sftpgo/v2/dataprovider"
|
||||||
|
"github.com/drakkan/sftpgo/v2/kms"
|
||||||
"github.com/drakkan/sftpgo/v2/mfa"
|
"github.com/drakkan/sftpgo/v2/mfa"
|
||||||
"github.com/drakkan/sftpgo/v2/sdk"
|
|
||||||
"github.com/drakkan/sftpgo/v2/sdk/kms"
|
|
||||||
"github.com/drakkan/sftpgo/v2/util"
|
"github.com/drakkan/sftpgo/v2/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -81,10 +80,10 @@ func saveTOTPConfig(w http.ResponseWriter, r *http.Request) {
|
||||||
sendAPIResponse(w, r, err, "Invalid token claims", http.StatusBadRequest)
|
sendAPIResponse(w, r, err, "Invalid token claims", http.StatusBadRequest)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
recoveryCodes := make([]sdk.RecoveryCode, 0, 12)
|
recoveryCodes := make([]dataprovider.RecoveryCode, 0, 12)
|
||||||
for i := 0; i < 12; i++ {
|
for i := 0; i < 12; i++ {
|
||||||
code := getNewRecoveryCode()
|
code := getNewRecoveryCode()
|
||||||
recoveryCodes = append(recoveryCodes, sdk.RecoveryCode{Secret: kms.NewPlainSecret(code)})
|
recoveryCodes = append(recoveryCodes, dataprovider.RecoveryCode{Secret: kms.NewPlainSecret(code)})
|
||||||
}
|
}
|
||||||
if claims.hasUserAudience() {
|
if claims.hasUserAudience() {
|
||||||
if err := saveUserTOTPConfig(claims.Username, r, recoveryCodes); err != nil {
|
if err := saveUserTOTPConfig(claims.Username, r, recoveryCodes); err != nil {
|
||||||
|
@ -125,7 +124,7 @@ func getRecoveryCodes(w http.ResponseWriter, r *http.Request) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
recoveryCodes := make([]recoveryCode, 0, 12)
|
recoveryCodes := make([]recoveryCode, 0, 12)
|
||||||
var accountRecoveryCodes []sdk.RecoveryCode
|
var accountRecoveryCodes []dataprovider.RecoveryCode
|
||||||
if claims.hasUserAudience() {
|
if claims.hasUserAudience() {
|
||||||
user, err := dataprovider.UserExists(claims.Username)
|
user, err := dataprovider.UserExists(claims.Username)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -163,11 +162,11 @@ func generateRecoveryCodes(w http.ResponseWriter, r *http.Request) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
recoveryCodes := make([]string, 0, 12)
|
recoveryCodes := make([]string, 0, 12)
|
||||||
accountRecoveryCodes := make([]sdk.RecoveryCode, 0, 12)
|
accountRecoveryCodes := make([]dataprovider.RecoveryCode, 0, 12)
|
||||||
for i := 0; i < 12; i++ {
|
for i := 0; i < 12; i++ {
|
||||||
code := getNewRecoveryCode()
|
code := getNewRecoveryCode()
|
||||||
recoveryCodes = append(recoveryCodes, code)
|
recoveryCodes = append(recoveryCodes, code)
|
||||||
accountRecoveryCodes = append(accountRecoveryCodes, sdk.RecoveryCode{Secret: kms.NewPlainSecret(code)})
|
accountRecoveryCodes = append(accountRecoveryCodes, dataprovider.RecoveryCode{Secret: kms.NewPlainSecret(code)})
|
||||||
}
|
}
|
||||||
if claims.hasUserAudience() {
|
if claims.hasUserAudience() {
|
||||||
user, err := dataprovider.UserExists(claims.Username)
|
user, err := dataprovider.UserExists(claims.Username)
|
||||||
|
@ -200,7 +199,7 @@ func getNewRecoveryCode() string {
|
||||||
return fmt.Sprintf("RC-%v", strings.ToUpper(util.GenerateUniqueID()))
|
return fmt.Sprintf("RC-%v", strings.ToUpper(util.GenerateUniqueID()))
|
||||||
}
|
}
|
||||||
|
|
||||||
func saveUserTOTPConfig(username string, r *http.Request, recoveryCodes []sdk.RecoveryCode) error {
|
func saveUserTOTPConfig(username string, r *http.Request, recoveryCodes []dataprovider.RecoveryCode) error {
|
||||||
user, err := dataprovider.UserExists(username)
|
user, err := dataprovider.UserExists(username)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -220,7 +219,7 @@ func saveUserTOTPConfig(username string, r *http.Request, recoveryCodes []sdk.Re
|
||||||
return dataprovider.UpdateUser(&user, dataprovider.ActionExecutorSelf, util.GetIPFromRemoteAddress(r.RemoteAddr))
|
return dataprovider.UpdateUser(&user, dataprovider.ActionExecutorSelf, util.GetIPFromRemoteAddress(r.RemoteAddr))
|
||||||
}
|
}
|
||||||
|
|
||||||
func saveAdminTOTPConfig(username string, r *http.Request, recoveryCodes []sdk.RecoveryCode) error {
|
func saveAdminTOTPConfig(username string, r *http.Request, recoveryCodes []dataprovider.RecoveryCode) error {
|
||||||
admin, err := dataprovider.AdminExists(username)
|
admin, err := dataprovider.AdminExists(username)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
|
@ -10,8 +10,8 @@ import (
|
||||||
|
|
||||||
"github.com/drakkan/sftpgo/v2/common"
|
"github.com/drakkan/sftpgo/v2/common"
|
||||||
"github.com/drakkan/sftpgo/v2/dataprovider"
|
"github.com/drakkan/sftpgo/v2/dataprovider"
|
||||||
|
"github.com/drakkan/sftpgo/v2/kms"
|
||||||
"github.com/drakkan/sftpgo/v2/sdk"
|
"github.com/drakkan/sftpgo/v2/sdk"
|
||||||
"github.com/drakkan/sftpgo/v2/sdk/kms"
|
|
||||||
"github.com/drakkan/sftpgo/v2/smtp"
|
"github.com/drakkan/sftpgo/v2/smtp"
|
||||||
"github.com/drakkan/sftpgo/v2/util"
|
"github.com/drakkan/sftpgo/v2/util"
|
||||||
"github.com/drakkan/sftpgo/v2/vfs"
|
"github.com/drakkan/sftpgo/v2/vfs"
|
||||||
|
@ -89,7 +89,7 @@ func disableUser2FA(w http.ResponseWriter, r *http.Request) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
user.Filters.RecoveryCodes = nil
|
user.Filters.RecoveryCodes = nil
|
||||||
user.Filters.TOTPConfig = sdk.TOTPConfig{
|
user.Filters.TOTPConfig = dataprovider.UserTOTPConfig{
|
||||||
Enabled: false,
|
Enabled: false,
|
||||||
}
|
}
|
||||||
if err := dataprovider.UpdateUser(&user, claims.Username, util.GetIPFromRemoteAddress(r.RemoteAddr)); err != nil {
|
if err := dataprovider.UpdateUser(&user, claims.Username, util.GetIPFromRemoteAddress(r.RemoteAddr)); err != nil {
|
||||||
|
@ -140,7 +140,7 @@ func updateUser(w http.ResponseWriter, r *http.Request) {
|
||||||
user.FsConfig.GCSConfig = vfs.GCSFsConfig{}
|
user.FsConfig.GCSConfig = vfs.GCSFsConfig{}
|
||||||
user.FsConfig.CryptConfig = vfs.CryptFsConfig{}
|
user.FsConfig.CryptConfig = vfs.CryptFsConfig{}
|
||||||
user.FsConfig.SFTPConfig = vfs.SFTPFsConfig{}
|
user.FsConfig.SFTPConfig = vfs.SFTPFsConfig{}
|
||||||
user.Filters.TOTPConfig = sdk.TOTPConfig{}
|
user.Filters.TOTPConfig = dataprovider.UserTOTPConfig{}
|
||||||
user.Filters.RecoveryCodes = nil
|
user.Filters.RecoveryCodes = nil
|
||||||
user.VirtualFolders = nil
|
user.VirtualFolders = nil
|
||||||
err = render.DecodeJSON(r.Body, &user)
|
err = render.DecodeJSON(r.Body, &user)
|
||||||
|
|
|
@ -45,11 +45,12 @@ import (
|
||||||
"github.com/drakkan/sftpgo/v2/httpclient"
|
"github.com/drakkan/sftpgo/v2/httpclient"
|
||||||
"github.com/drakkan/sftpgo/v2/httpd"
|
"github.com/drakkan/sftpgo/v2/httpd"
|
||||||
"github.com/drakkan/sftpgo/v2/httpdtest"
|
"github.com/drakkan/sftpgo/v2/httpdtest"
|
||||||
|
"github.com/drakkan/sftpgo/v2/kms"
|
||||||
"github.com/drakkan/sftpgo/v2/logger"
|
"github.com/drakkan/sftpgo/v2/logger"
|
||||||
"github.com/drakkan/sftpgo/v2/mfa"
|
"github.com/drakkan/sftpgo/v2/mfa"
|
||||||
"github.com/drakkan/sftpgo/v2/plugin"
|
"github.com/drakkan/sftpgo/v2/plugin"
|
||||||
"github.com/drakkan/sftpgo/v2/sdk"
|
"github.com/drakkan/sftpgo/v2/sdk"
|
||||||
"github.com/drakkan/sftpgo/v2/sdk/kms"
|
sdkkms "github.com/drakkan/sftpgo/v2/sdk/kms"
|
||||||
"github.com/drakkan/sftpgo/v2/sftpd"
|
"github.com/drakkan/sftpgo/v2/sftpd"
|
||||||
"github.com/drakkan/sftpgo/v2/smtp"
|
"github.com/drakkan/sftpgo/v2/smtp"
|
||||||
"github.com/drakkan/sftpgo/v2/util"
|
"github.com/drakkan/sftpgo/v2/util"
|
||||||
|
@ -826,7 +827,7 @@ func TestPermMFADisabled(t *testing.T) {
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
token, err := getJWTAPIUserTokenFromTestServer(defaultUsername, defaultPassword)
|
token, err := getJWTAPIUserTokenFromTestServer(defaultUsername, defaultPassword)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
userTOTPConfig := sdk.TOTPConfig{
|
userTOTPConfig := dataprovider.UserTOTPConfig{
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
ConfigName: configName,
|
ConfigName: configName,
|
||||||
Secret: kms.NewPlainSecret(secret),
|
Secret: kms.NewPlainSecret(secret),
|
||||||
|
@ -867,7 +868,7 @@ func TestPermMFADisabled(t *testing.T) {
|
||||||
rr = executeRequest(req)
|
rr = executeRequest(req)
|
||||||
checkResponseCode(t, http.StatusOK, rr)
|
checkResponseCode(t, http.StatusOK, rr)
|
||||||
|
|
||||||
user.Filters.RecoveryCodes = []sdk.RecoveryCode{
|
user.Filters.RecoveryCodes = []dataprovider.RecoveryCode{
|
||||||
{
|
{
|
||||||
Secret: kms.NewPlainSecret(util.GenerateUniqueID()),
|
Secret: kms.NewPlainSecret(util.GenerateUniqueID()),
|
||||||
},
|
},
|
||||||
|
@ -901,7 +902,7 @@ func TestLoginUserAPITOTP(t *testing.T) {
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
token, err := getJWTAPIUserTokenFromTestServer(defaultUsername, defaultPassword)
|
token, err := getJWTAPIUserTokenFromTestServer(defaultUsername, defaultPassword)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
userTOTPConfig := sdk.TOTPConfig{
|
userTOTPConfig := dataprovider.UserTOTPConfig{
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
ConfigName: configName,
|
ConfigName: configName,
|
||||||
Secret: kms.NewPlainSecret(secret),
|
Secret: kms.NewPlainSecret(secret),
|
||||||
|
@ -968,7 +969,7 @@ func TestLoginAdminAPITOTP(t *testing.T) {
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
altToken, err := getJWTAPITokenFromTestServer(altAdminUsername, altAdminPassword)
|
altToken, err := getJWTAPITokenFromTestServer(altAdminUsername, altAdminPassword)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
adminTOTPConfig := dataprovider.TOTPConfig{
|
adminTOTPConfig := dataprovider.AdminTOTPConfig{
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
ConfigName: configName,
|
ConfigName: configName,
|
||||||
Secret: kms.NewPlainSecret(secret),
|
Secret: kms.NewPlainSecret(secret),
|
||||||
|
@ -1510,13 +1511,13 @@ func TestAddUserInvalidFsConfig(t *testing.T) {
|
||||||
u.FsConfig.S3Config.Bucket = "testbucket"
|
u.FsConfig.S3Config.Bucket = "testbucket"
|
||||||
u.FsConfig.S3Config.Region = "eu-west-1" //nolint:goconst
|
u.FsConfig.S3Config.Region = "eu-west-1" //nolint:goconst
|
||||||
u.FsConfig.S3Config.AccessKey = "access-key" //nolint:goconst
|
u.FsConfig.S3Config.AccessKey = "access-key" //nolint:goconst
|
||||||
u.FsConfig.S3Config.AccessSecret = kms.NewSecret(kms.SecretStatusRedacted, "access-secret", "", "")
|
u.FsConfig.S3Config.AccessSecret = kms.NewSecret(sdkkms.SecretStatusRedacted, "access-secret", "", "")
|
||||||
u.FsConfig.S3Config.Endpoint = "http://127.0.0.1:9000/path?a=b"
|
u.FsConfig.S3Config.Endpoint = "http://127.0.0.1:9000/path?a=b"
|
||||||
u.FsConfig.S3Config.StorageClass = "Standard" //nolint:goconst
|
u.FsConfig.S3Config.StorageClass = "Standard" //nolint:goconst
|
||||||
u.FsConfig.S3Config.KeyPrefix = "/adir/subdir/"
|
u.FsConfig.S3Config.KeyPrefix = "/adir/subdir/"
|
||||||
_, _, err = httpdtest.AddUser(u, http.StatusBadRequest)
|
_, _, err = httpdtest.AddUser(u, http.StatusBadRequest)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
u.FsConfig.S3Config.AccessSecret.SetStatus(kms.SecretStatusPlain)
|
u.FsConfig.S3Config.AccessSecret.SetStatus(sdkkms.SecretStatusPlain)
|
||||||
_, _, err = httpdtest.AddUser(u, http.StatusBadRequest)
|
_, _, err = httpdtest.AddUser(u, http.StatusBadRequest)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
u.FsConfig.S3Config.KeyPrefix = ""
|
u.FsConfig.S3Config.KeyPrefix = ""
|
||||||
|
@ -1560,10 +1561,10 @@ func TestAddUserInvalidFsConfig(t *testing.T) {
|
||||||
u.FsConfig.GCSConfig.Bucket = "abucket"
|
u.FsConfig.GCSConfig.Bucket = "abucket"
|
||||||
u.FsConfig.GCSConfig.StorageClass = "Standard"
|
u.FsConfig.GCSConfig.StorageClass = "Standard"
|
||||||
u.FsConfig.GCSConfig.KeyPrefix = "/somedir/subdir/"
|
u.FsConfig.GCSConfig.KeyPrefix = "/somedir/subdir/"
|
||||||
u.FsConfig.GCSConfig.Credentials = kms.NewSecret(kms.SecretStatusRedacted, "test", "", "") //nolint:goconst
|
u.FsConfig.GCSConfig.Credentials = kms.NewSecret(sdkkms.SecretStatusRedacted, "test", "", "") //nolint:goconst
|
||||||
_, _, err = httpdtest.AddUser(u, http.StatusBadRequest)
|
_, _, err = httpdtest.AddUser(u, http.StatusBadRequest)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
u.FsConfig.GCSConfig.Credentials.SetStatus(kms.SecretStatusPlain)
|
u.FsConfig.GCSConfig.Credentials.SetStatus(sdkkms.SecretStatusPlain)
|
||||||
_, _, err = httpdtest.AddUser(u, http.StatusBadRequest)
|
_, _, err = httpdtest.AddUser(u, http.StatusBadRequest)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
u.FsConfig.GCSConfig.KeyPrefix = "somedir/subdir/" //nolint:goconst
|
u.FsConfig.GCSConfig.KeyPrefix = "somedir/subdir/" //nolint:goconst
|
||||||
|
@ -1571,7 +1572,7 @@ func TestAddUserInvalidFsConfig(t *testing.T) {
|
||||||
u.FsConfig.GCSConfig.AutomaticCredentials = 0
|
u.FsConfig.GCSConfig.AutomaticCredentials = 0
|
||||||
_, _, err = httpdtest.AddUser(u, http.StatusBadRequest)
|
_, _, err = httpdtest.AddUser(u, http.StatusBadRequest)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
u.FsConfig.GCSConfig.Credentials = kms.NewSecret(kms.SecretStatusSecretBox, "invalid", "", "")
|
u.FsConfig.GCSConfig.Credentials = kms.NewSecret(sdkkms.SecretStatusSecretBox, "invalid", "", "")
|
||||||
_, _, err = httpdtest.AddUser(u, http.StatusBadRequest)
|
_, _, err = httpdtest.AddUser(u, http.StatusBadRequest)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
@ -1580,7 +1581,7 @@ func TestAddUserInvalidFsConfig(t *testing.T) {
|
||||||
u.FsConfig.AzBlobConfig.SASURL = kms.NewPlainSecret("http://foo\x7f.com/")
|
u.FsConfig.AzBlobConfig.SASURL = kms.NewPlainSecret("http://foo\x7f.com/")
|
||||||
_, _, err = httpdtest.AddUser(u, http.StatusBadRequest)
|
_, _, err = httpdtest.AddUser(u, http.StatusBadRequest)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
u.FsConfig.AzBlobConfig.SASURL = kms.NewSecret(kms.SecretStatusRedacted, "key", "", "")
|
u.FsConfig.AzBlobConfig.SASURL = kms.NewSecret(sdkkms.SecretStatusRedacted, "key", "", "")
|
||||||
_, _, err = httpdtest.AddUser(u, http.StatusBadRequest)
|
_, _, err = httpdtest.AddUser(u, http.StatusBadRequest)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
u.FsConfig.AzBlobConfig.SASURL = kms.NewEmptySecret()
|
u.FsConfig.AzBlobConfig.SASURL = kms.NewEmptySecret()
|
||||||
|
@ -1590,11 +1591,11 @@ func TestAddUserInvalidFsConfig(t *testing.T) {
|
||||||
u.FsConfig.AzBlobConfig.Container = "container"
|
u.FsConfig.AzBlobConfig.Container = "container"
|
||||||
_, _, err = httpdtest.AddUser(u, http.StatusBadRequest)
|
_, _, err = httpdtest.AddUser(u, http.StatusBadRequest)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
u.FsConfig.AzBlobConfig.AccountKey = kms.NewSecret(kms.SecretStatusRedacted, "key", "", "")
|
u.FsConfig.AzBlobConfig.AccountKey = kms.NewSecret(sdkkms.SecretStatusRedacted, "key", "", "")
|
||||||
u.FsConfig.AzBlobConfig.KeyPrefix = "/amedir/subdir/"
|
u.FsConfig.AzBlobConfig.KeyPrefix = "/amedir/subdir/"
|
||||||
_, _, err = httpdtest.AddUser(u, http.StatusBadRequest)
|
_, _, err = httpdtest.AddUser(u, http.StatusBadRequest)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
u.FsConfig.AzBlobConfig.AccountKey.SetStatus(kms.SecretStatusPlain)
|
u.FsConfig.AzBlobConfig.AccountKey.SetStatus(sdkkms.SecretStatusPlain)
|
||||||
_, _, err = httpdtest.AddUser(u, http.StatusBadRequest)
|
_, _, err = httpdtest.AddUser(u, http.StatusBadRequest)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
u.FsConfig.AzBlobConfig.KeyPrefix = "amedir/subdir/"
|
u.FsConfig.AzBlobConfig.KeyPrefix = "amedir/subdir/"
|
||||||
|
@ -1609,18 +1610,18 @@ func TestAddUserInvalidFsConfig(t *testing.T) {
|
||||||
u.FsConfig.Provider = sdk.CryptedFilesystemProvider
|
u.FsConfig.Provider = sdk.CryptedFilesystemProvider
|
||||||
_, _, err = httpdtest.AddUser(u, http.StatusBadRequest)
|
_, _, err = httpdtest.AddUser(u, http.StatusBadRequest)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
u.FsConfig.CryptConfig.Passphrase = kms.NewSecret(kms.SecretStatusRedacted, "akey", "", "")
|
u.FsConfig.CryptConfig.Passphrase = kms.NewSecret(sdkkms.SecretStatusRedacted, "akey", "", "")
|
||||||
_, _, err = httpdtest.AddUser(u, http.StatusBadRequest)
|
_, _, err = httpdtest.AddUser(u, http.StatusBadRequest)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
u = getTestUser()
|
u = getTestUser()
|
||||||
u.FsConfig.Provider = sdk.SFTPFilesystemProvider
|
u.FsConfig.Provider = sdk.SFTPFilesystemProvider
|
||||||
_, _, err = httpdtest.AddUser(u, http.StatusBadRequest)
|
_, _, err = httpdtest.AddUser(u, http.StatusBadRequest)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
u.FsConfig.SFTPConfig.Password = kms.NewSecret(kms.SecretStatusRedacted, "randompkey", "", "")
|
u.FsConfig.SFTPConfig.Password = kms.NewSecret(sdkkms.SecretStatusRedacted, "randompkey", "", "")
|
||||||
_, _, err = httpdtest.AddUser(u, http.StatusBadRequest)
|
_, _, err = httpdtest.AddUser(u, http.StatusBadRequest)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
u.FsConfig.SFTPConfig.Password = kms.NewEmptySecret()
|
u.FsConfig.SFTPConfig.Password = kms.NewEmptySecret()
|
||||||
u.FsConfig.SFTPConfig.PrivateKey = kms.NewSecret(kms.SecretStatusRedacted, "keyforpkey", "", "")
|
u.FsConfig.SFTPConfig.PrivateKey = kms.NewSecret(sdkkms.SecretStatusRedacted, "keyforpkey", "", "")
|
||||||
_, _, err = httpdtest.AddUser(u, http.StatusBadRequest)
|
_, _, err = httpdtest.AddUser(u, http.StatusBadRequest)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
u.FsConfig.SFTPConfig.PrivateKey = kms.NewPlainSecret("pk")
|
u.FsConfig.SFTPConfig.PrivateKey = kms.NewPlainSecret("pk")
|
||||||
|
@ -1644,7 +1645,7 @@ func TestUserRedactedPassword(t *testing.T) {
|
||||||
u.FsConfig.S3Config.Bucket = "b"
|
u.FsConfig.S3Config.Bucket = "b"
|
||||||
u.FsConfig.S3Config.Region = "eu-west-1"
|
u.FsConfig.S3Config.Region = "eu-west-1"
|
||||||
u.FsConfig.S3Config.AccessKey = "access-key"
|
u.FsConfig.S3Config.AccessKey = "access-key"
|
||||||
u.FsConfig.S3Config.AccessSecret = kms.NewSecret(kms.SecretStatusRedacted, "access-secret", "", "")
|
u.FsConfig.S3Config.AccessSecret = kms.NewSecret(sdkkms.SecretStatusRedacted, "access-secret", "", "")
|
||||||
u.FsConfig.S3Config.Endpoint = "http://127.0.0.1:9000/path?k=m"
|
u.FsConfig.S3Config.Endpoint = "http://127.0.0.1:9000/path?k=m"
|
||||||
u.FsConfig.S3Config.StorageClass = "Standard"
|
u.FsConfig.S3Config.StorageClass = "Standard"
|
||||||
u.FsConfig.S3Config.ACL = "bucket-owner-full-control"
|
u.FsConfig.S3Config.ACL = "bucket-owner-full-control"
|
||||||
|
@ -1667,9 +1668,7 @@ func TestUserRedactedPassword(t *testing.T) {
|
||||||
FsConfig: vfs.Filesystem{
|
FsConfig: vfs.Filesystem{
|
||||||
Provider: sdk.CryptedFilesystemProvider,
|
Provider: sdk.CryptedFilesystemProvider,
|
||||||
CryptConfig: vfs.CryptFsConfig{
|
CryptConfig: vfs.CryptFsConfig{
|
||||||
CryptFsConfig: sdk.CryptFsConfig{
|
Passphrase: kms.NewSecret(sdkkms.SecretStatusRedacted, "crypted-secret", "", ""),
|
||||||
Passphrase: kms.NewSecret(kms.SecretStatusRedacted, "crypted-secret", "", ""),
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -2356,9 +2355,7 @@ func TestUserS3Config(t *testing.T) {
|
||||||
FsConfig: vfs.Filesystem{
|
FsConfig: vfs.Filesystem{
|
||||||
Provider: sdk.CryptedFilesystemProvider,
|
Provider: sdk.CryptedFilesystemProvider,
|
||||||
CryptConfig: vfs.CryptFsConfig{
|
CryptConfig: vfs.CryptFsConfig{
|
||||||
CryptFsConfig: sdk.CryptFsConfig{
|
Passphrase: kms.NewPlainSecret("Crypted-Secret"),
|
||||||
Passphrase: kms.NewPlainSecret("Crypted-Secret"),
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -2366,14 +2363,14 @@ func TestUserS3Config(t *testing.T) {
|
||||||
})
|
})
|
||||||
user, body, err := httpdtest.UpdateUser(user, http.StatusOK, "")
|
user, body, err := httpdtest.UpdateUser(user, http.StatusOK, "")
|
||||||
assert.NoError(t, err, string(body))
|
assert.NoError(t, err, string(body))
|
||||||
assert.Equal(t, kms.SecretStatusSecretBox, user.FsConfig.S3Config.AccessSecret.GetStatus())
|
assert.Equal(t, sdkkms.SecretStatusSecretBox, user.FsConfig.S3Config.AccessSecret.GetStatus())
|
||||||
assert.NotEmpty(t, user.FsConfig.S3Config.AccessSecret.GetPayload())
|
assert.NotEmpty(t, user.FsConfig.S3Config.AccessSecret.GetPayload())
|
||||||
assert.Empty(t, user.FsConfig.S3Config.AccessSecret.GetAdditionalData())
|
assert.Empty(t, user.FsConfig.S3Config.AccessSecret.GetAdditionalData())
|
||||||
assert.Empty(t, user.FsConfig.S3Config.AccessSecret.GetKey())
|
assert.Empty(t, user.FsConfig.S3Config.AccessSecret.GetKey())
|
||||||
assert.Equal(t, 60, user.FsConfig.S3Config.DownloadPartMaxTime)
|
assert.Equal(t, 60, user.FsConfig.S3Config.DownloadPartMaxTime)
|
||||||
if assert.Len(t, user.VirtualFolders, 1) {
|
if assert.Len(t, user.VirtualFolders, 1) {
|
||||||
folder := user.VirtualFolders[0]
|
folder := user.VirtualFolders[0]
|
||||||
assert.Equal(t, kms.SecretStatusSecretBox, folder.FsConfig.CryptConfig.Passphrase.GetStatus())
|
assert.Equal(t, sdkkms.SecretStatusSecretBox, folder.FsConfig.CryptConfig.Passphrase.GetStatus())
|
||||||
assert.NotEmpty(t, folder.FsConfig.CryptConfig.Passphrase.GetPayload())
|
assert.NotEmpty(t, folder.FsConfig.CryptConfig.Passphrase.GetPayload())
|
||||||
assert.Empty(t, folder.FsConfig.CryptConfig.Passphrase.GetAdditionalData())
|
assert.Empty(t, folder.FsConfig.CryptConfig.Passphrase.GetAdditionalData())
|
||||||
assert.Empty(t, folder.FsConfig.CryptConfig.Passphrase.GetKey())
|
assert.Empty(t, folder.FsConfig.CryptConfig.Passphrase.GetKey())
|
||||||
|
@ -2382,7 +2379,7 @@ func TestUserS3Config(t *testing.T) {
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
folder, _, err := httpdtest.GetFolderByName(folderName, http.StatusOK)
|
folder, _, err := httpdtest.GetFolderByName(folderName, http.StatusOK)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, kms.SecretStatusSecretBox, folder.FsConfig.CryptConfig.Passphrase.GetStatus())
|
assert.Equal(t, sdkkms.SecretStatusSecretBox, folder.FsConfig.CryptConfig.Passphrase.GetStatus())
|
||||||
assert.NotEmpty(t, folder.FsConfig.CryptConfig.Passphrase.GetPayload())
|
assert.NotEmpty(t, folder.FsConfig.CryptConfig.Passphrase.GetPayload())
|
||||||
assert.Empty(t, folder.FsConfig.CryptConfig.Passphrase.GetAdditionalData())
|
assert.Empty(t, folder.FsConfig.CryptConfig.Passphrase.GetAdditionalData())
|
||||||
assert.Empty(t, folder.FsConfig.CryptConfig.Passphrase.GetKey())
|
assert.Empty(t, folder.FsConfig.CryptConfig.Passphrase.GetKey())
|
||||||
|
@ -2392,15 +2389,15 @@ func TestUserS3Config(t *testing.T) {
|
||||||
user.ID = 0
|
user.ID = 0
|
||||||
user.CreatedAt = 0
|
user.CreatedAt = 0
|
||||||
user.VirtualFolders = nil
|
user.VirtualFolders = nil
|
||||||
secret := kms.NewSecret(kms.SecretStatusSecretBox, "Server-Access-Secret", "", "")
|
secret := kms.NewSecret(sdkkms.SecretStatusSecretBox, "Server-Access-Secret", "", "")
|
||||||
user.FsConfig.S3Config.AccessSecret = secret
|
user.FsConfig.S3Config.AccessSecret = secret
|
||||||
_, _, err = httpdtest.AddUser(user, http.StatusCreated)
|
_, _, err = httpdtest.AddUser(user, http.StatusCreated)
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
user.FsConfig.S3Config.AccessSecret.SetStatus(kms.SecretStatusPlain)
|
user.FsConfig.S3Config.AccessSecret.SetStatus(sdkkms.SecretStatusPlain)
|
||||||
user, _, err = httpdtest.AddUser(user, http.StatusCreated)
|
user, _, err = httpdtest.AddUser(user, http.StatusCreated)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
initialSecretPayload := user.FsConfig.S3Config.AccessSecret.GetPayload()
|
initialSecretPayload := user.FsConfig.S3Config.AccessSecret.GetPayload()
|
||||||
assert.Equal(t, kms.SecretStatusSecretBox, user.FsConfig.S3Config.AccessSecret.GetStatus())
|
assert.Equal(t, sdkkms.SecretStatusSecretBox, user.FsConfig.S3Config.AccessSecret.GetStatus())
|
||||||
assert.NotEmpty(t, initialSecretPayload)
|
assert.NotEmpty(t, initialSecretPayload)
|
||||||
assert.Empty(t, user.FsConfig.S3Config.AccessSecret.GetAdditionalData())
|
assert.Empty(t, user.FsConfig.S3Config.AccessSecret.GetAdditionalData())
|
||||||
assert.Empty(t, user.FsConfig.S3Config.AccessSecret.GetKey())
|
assert.Empty(t, user.FsConfig.S3Config.AccessSecret.GetKey())
|
||||||
|
@ -2414,7 +2411,7 @@ func TestUserS3Config(t *testing.T) {
|
||||||
user.FsConfig.S3Config.DownloadConcurrency = 4
|
user.FsConfig.S3Config.DownloadConcurrency = 4
|
||||||
user, bb, err := httpdtest.UpdateUser(user, http.StatusOK, "")
|
user, bb, err := httpdtest.UpdateUser(user, http.StatusOK, "")
|
||||||
assert.NoError(t, err, string(bb))
|
assert.NoError(t, err, string(bb))
|
||||||
assert.Equal(t, kms.SecretStatusSecretBox, user.FsConfig.S3Config.AccessSecret.GetStatus())
|
assert.Equal(t, sdkkms.SecretStatusSecretBox, user.FsConfig.S3Config.AccessSecret.GetStatus())
|
||||||
assert.Equal(t, initialSecretPayload, user.FsConfig.S3Config.AccessSecret.GetPayload())
|
assert.Equal(t, initialSecretPayload, user.FsConfig.S3Config.AccessSecret.GetPayload())
|
||||||
assert.Empty(t, user.FsConfig.S3Config.AccessSecret.GetAdditionalData())
|
assert.Empty(t, user.FsConfig.S3Config.AccessSecret.GetAdditionalData())
|
||||||
assert.Empty(t, user.FsConfig.S3Config.AccessSecret.GetKey())
|
assert.Empty(t, user.FsConfig.S3Config.AccessSecret.GetKey())
|
||||||
|
@ -2466,7 +2463,7 @@ func TestUserGCSConfig(t *testing.T) {
|
||||||
err = secret.Decrypt()
|
err = secret.Decrypt()
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, "fake credentials", secret.GetPayload())
|
assert.Equal(t, "fake credentials", secret.GetPayload())
|
||||||
user.FsConfig.GCSConfig.Credentials = kms.NewSecret(kms.SecretStatusSecretBox, "fake encrypted credentials", "", "")
|
user.FsConfig.GCSConfig.Credentials = kms.NewSecret(sdkkms.SecretStatusSecretBox, "fake encrypted credentials", "", "")
|
||||||
user, _, err = httpdtest.UpdateUser(user, http.StatusOK, "")
|
user, _, err = httpdtest.UpdateUser(user, http.StatusOK, "")
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.FileExists(t, credentialFile)
|
assert.FileExists(t, credentialFile)
|
||||||
|
@ -2483,10 +2480,10 @@ func TestUserGCSConfig(t *testing.T) {
|
||||||
user.Password = defaultPassword
|
user.Password = defaultPassword
|
||||||
user.ID = 0
|
user.ID = 0
|
||||||
user.CreatedAt = 0
|
user.CreatedAt = 0
|
||||||
user.FsConfig.GCSConfig.Credentials = kms.NewSecret(kms.SecretStatusSecretBox, "fake credentials", "", "")
|
user.FsConfig.GCSConfig.Credentials = kms.NewSecret(sdkkms.SecretStatusSecretBox, "fake credentials", "", "")
|
||||||
_, _, err = httpdtest.AddUser(user, http.StatusCreated)
|
_, _, err = httpdtest.AddUser(user, http.StatusCreated)
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
user.FsConfig.GCSConfig.Credentials.SetStatus(kms.SecretStatusPlain)
|
user.FsConfig.GCSConfig.Credentials.SetStatus(sdkkms.SecretStatusPlain)
|
||||||
user, body, err := httpdtest.AddUser(user, http.StatusCreated)
|
user, body, err := httpdtest.AddUser(user, http.StatusCreated)
|
||||||
assert.NoError(t, err, string(body))
|
assert.NoError(t, err, string(body))
|
||||||
err = os.RemoveAll(credentialsPath)
|
err = os.RemoveAll(credentialsPath)
|
||||||
|
@ -2531,16 +2528,16 @@ func TestUserAzureBlobConfig(t *testing.T) {
|
||||||
user, _, err = httpdtest.UpdateUser(user, http.StatusOK, "")
|
user, _, err = httpdtest.UpdateUser(user, http.StatusOK, "")
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
initialPayload := user.FsConfig.AzBlobConfig.AccountKey.GetPayload()
|
initialPayload := user.FsConfig.AzBlobConfig.AccountKey.GetPayload()
|
||||||
assert.Equal(t, kms.SecretStatusSecretBox, user.FsConfig.AzBlobConfig.AccountKey.GetStatus())
|
assert.Equal(t, sdkkms.SecretStatusSecretBox, user.FsConfig.AzBlobConfig.AccountKey.GetStatus())
|
||||||
assert.NotEmpty(t, initialPayload)
|
assert.NotEmpty(t, initialPayload)
|
||||||
assert.Empty(t, user.FsConfig.AzBlobConfig.AccountKey.GetAdditionalData())
|
assert.Empty(t, user.FsConfig.AzBlobConfig.AccountKey.GetAdditionalData())
|
||||||
assert.Empty(t, user.FsConfig.AzBlobConfig.AccountKey.GetKey())
|
assert.Empty(t, user.FsConfig.AzBlobConfig.AccountKey.GetKey())
|
||||||
user.FsConfig.AzBlobConfig.AccountKey.SetStatus(kms.SecretStatusSecretBox)
|
user.FsConfig.AzBlobConfig.AccountKey.SetStatus(sdkkms.SecretStatusSecretBox)
|
||||||
user.FsConfig.AzBlobConfig.AccountKey.SetAdditionalData("data")
|
user.FsConfig.AzBlobConfig.AccountKey.SetAdditionalData("data")
|
||||||
user.FsConfig.AzBlobConfig.AccountKey.SetKey("fake key")
|
user.FsConfig.AzBlobConfig.AccountKey.SetKey("fake key")
|
||||||
user, _, err = httpdtest.UpdateUser(user, http.StatusOK, "")
|
user, _, err = httpdtest.UpdateUser(user, http.StatusOK, "")
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, kms.SecretStatusSecretBox, user.FsConfig.AzBlobConfig.AccountKey.GetStatus())
|
assert.Equal(t, sdkkms.SecretStatusSecretBox, user.FsConfig.AzBlobConfig.AccountKey.GetStatus())
|
||||||
assert.Equal(t, initialPayload, user.FsConfig.AzBlobConfig.AccountKey.GetPayload())
|
assert.Equal(t, initialPayload, user.FsConfig.AzBlobConfig.AccountKey.GetPayload())
|
||||||
assert.Empty(t, user.FsConfig.AzBlobConfig.AccountKey.GetAdditionalData())
|
assert.Empty(t, user.FsConfig.AzBlobConfig.AccountKey.GetAdditionalData())
|
||||||
assert.Empty(t, user.FsConfig.AzBlobConfig.AccountKey.GetKey())
|
assert.Empty(t, user.FsConfig.AzBlobConfig.AccountKey.GetKey())
|
||||||
|
@ -2550,7 +2547,7 @@ func TestUserAzureBlobConfig(t *testing.T) {
|
||||||
user.Password = defaultPassword
|
user.Password = defaultPassword
|
||||||
user.ID = 0
|
user.ID = 0
|
||||||
user.CreatedAt = 0
|
user.CreatedAt = 0
|
||||||
secret := kms.NewSecret(kms.SecretStatusSecretBox, "Server-Account-Key", "", "")
|
secret := kms.NewSecret(sdkkms.SecretStatusSecretBox, "Server-Account-Key", "", "")
|
||||||
user.FsConfig.AzBlobConfig.AccountKey = secret
|
user.FsConfig.AzBlobConfig.AccountKey = secret
|
||||||
_, _, err = httpdtest.AddUser(user, http.StatusCreated)
|
_, _, err = httpdtest.AddUser(user, http.StatusCreated)
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
|
@ -2558,7 +2555,7 @@ func TestUserAzureBlobConfig(t *testing.T) {
|
||||||
user, _, err = httpdtest.AddUser(user, http.StatusCreated)
|
user, _, err = httpdtest.AddUser(user, http.StatusCreated)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
initialPayload = user.FsConfig.AzBlobConfig.AccountKey.GetPayload()
|
initialPayload = user.FsConfig.AzBlobConfig.AccountKey.GetPayload()
|
||||||
assert.Equal(t, kms.SecretStatusSecretBox, user.FsConfig.AzBlobConfig.AccountKey.GetStatus())
|
assert.Equal(t, sdkkms.SecretStatusSecretBox, user.FsConfig.AzBlobConfig.AccountKey.GetStatus())
|
||||||
assert.NotEmpty(t, initialPayload)
|
assert.NotEmpty(t, initialPayload)
|
||||||
assert.Empty(t, user.FsConfig.AzBlobConfig.AccountKey.GetAdditionalData())
|
assert.Empty(t, user.FsConfig.AzBlobConfig.AccountKey.GetAdditionalData())
|
||||||
assert.Empty(t, user.FsConfig.AzBlobConfig.AccountKey.GetKey())
|
assert.Empty(t, user.FsConfig.AzBlobConfig.AccountKey.GetKey())
|
||||||
|
@ -2569,7 +2566,7 @@ func TestUserAzureBlobConfig(t *testing.T) {
|
||||||
user.FsConfig.AzBlobConfig.UploadConcurrency = 5
|
user.FsConfig.AzBlobConfig.UploadConcurrency = 5
|
||||||
user, _, err = httpdtest.UpdateUser(user, http.StatusOK, "")
|
user, _, err = httpdtest.UpdateUser(user, http.StatusOK, "")
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, kms.SecretStatusSecretBox, user.FsConfig.AzBlobConfig.AccountKey.GetStatus())
|
assert.Equal(t, sdkkms.SecretStatusSecretBox, user.FsConfig.AzBlobConfig.AccountKey.GetStatus())
|
||||||
assert.NotEmpty(t, initialPayload)
|
assert.NotEmpty(t, initialPayload)
|
||||||
assert.Equal(t, initialPayload, user.FsConfig.AzBlobConfig.AccountKey.GetPayload())
|
assert.Equal(t, initialPayload, user.FsConfig.AzBlobConfig.AccountKey.GetPayload())
|
||||||
assert.Empty(t, user.FsConfig.AzBlobConfig.AccountKey.GetAdditionalData())
|
assert.Empty(t, user.FsConfig.AzBlobConfig.AccountKey.GetAdditionalData())
|
||||||
|
@ -2593,25 +2590,25 @@ func TestUserAzureBlobConfig(t *testing.T) {
|
||||||
user.CreatedAt = 0
|
user.CreatedAt = 0
|
||||||
// sas test for add instead of update
|
// sas test for add instead of update
|
||||||
user.FsConfig.AzBlobConfig = vfs.AzBlobFsConfig{
|
user.FsConfig.AzBlobConfig = vfs.AzBlobFsConfig{
|
||||||
AzBlobFsConfig: sdk.AzBlobFsConfig{
|
BaseAzBlobFsConfig: sdk.BaseAzBlobFsConfig{
|
||||||
Container: user.FsConfig.AzBlobConfig.Container,
|
Container: user.FsConfig.AzBlobConfig.Container,
|
||||||
SASURL: kms.NewPlainSecret("http://127.0.0.1/fake/sass/url"),
|
|
||||||
},
|
},
|
||||||
|
SASURL: kms.NewPlainSecret("http://127.0.0.1/fake/sass/url"),
|
||||||
}
|
}
|
||||||
user, _, err = httpdtest.AddUser(user, http.StatusCreated)
|
user, _, err = httpdtest.AddUser(user, http.StatusCreated)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Nil(t, user.FsConfig.AzBlobConfig.AccountKey)
|
assert.Nil(t, user.FsConfig.AzBlobConfig.AccountKey)
|
||||||
initialPayload = user.FsConfig.AzBlobConfig.SASURL.GetPayload()
|
initialPayload = user.FsConfig.AzBlobConfig.SASURL.GetPayload()
|
||||||
assert.Equal(t, kms.SecretStatusSecretBox, user.FsConfig.AzBlobConfig.SASURL.GetStatus())
|
assert.Equal(t, sdkkms.SecretStatusSecretBox, user.FsConfig.AzBlobConfig.SASURL.GetStatus())
|
||||||
assert.NotEmpty(t, initialPayload)
|
assert.NotEmpty(t, initialPayload)
|
||||||
assert.Empty(t, user.FsConfig.AzBlobConfig.SASURL.GetAdditionalData())
|
assert.Empty(t, user.FsConfig.AzBlobConfig.SASURL.GetAdditionalData())
|
||||||
assert.Empty(t, user.FsConfig.AzBlobConfig.SASURL.GetKey())
|
assert.Empty(t, user.FsConfig.AzBlobConfig.SASURL.GetKey())
|
||||||
user.FsConfig.AzBlobConfig.SASURL.SetStatus(kms.SecretStatusSecretBox)
|
user.FsConfig.AzBlobConfig.SASURL.SetStatus(sdkkms.SecretStatusSecretBox)
|
||||||
user.FsConfig.AzBlobConfig.SASURL.SetAdditionalData("data")
|
user.FsConfig.AzBlobConfig.SASURL.SetAdditionalData("data")
|
||||||
user.FsConfig.AzBlobConfig.SASURL.SetKey("fake key")
|
user.FsConfig.AzBlobConfig.SASURL.SetKey("fake key")
|
||||||
user, _, err = httpdtest.UpdateUser(user, http.StatusOK, "")
|
user, _, err = httpdtest.UpdateUser(user, http.StatusOK, "")
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, kms.SecretStatusSecretBox, user.FsConfig.AzBlobConfig.SASURL.GetStatus())
|
assert.Equal(t, sdkkms.SecretStatusSecretBox, user.FsConfig.AzBlobConfig.SASURL.GetStatus())
|
||||||
assert.Equal(t, initialPayload, user.FsConfig.AzBlobConfig.SASURL.GetPayload())
|
assert.Equal(t, initialPayload, user.FsConfig.AzBlobConfig.SASURL.GetPayload())
|
||||||
assert.Empty(t, user.FsConfig.AzBlobConfig.SASURL.GetAdditionalData())
|
assert.Empty(t, user.FsConfig.AzBlobConfig.SASURL.GetAdditionalData())
|
||||||
assert.Empty(t, user.FsConfig.AzBlobConfig.SASURL.GetKey())
|
assert.Empty(t, user.FsConfig.AzBlobConfig.SASURL.GetKey())
|
||||||
|
@ -2628,16 +2625,16 @@ func TestUserCryptFs(t *testing.T) {
|
||||||
user, _, err = httpdtest.UpdateUser(user, http.StatusOK, "")
|
user, _, err = httpdtest.UpdateUser(user, http.StatusOK, "")
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
initialPayload := user.FsConfig.CryptConfig.Passphrase.GetPayload()
|
initialPayload := user.FsConfig.CryptConfig.Passphrase.GetPayload()
|
||||||
assert.Equal(t, kms.SecretStatusSecretBox, user.FsConfig.CryptConfig.Passphrase.GetStatus())
|
assert.Equal(t, sdkkms.SecretStatusSecretBox, user.FsConfig.CryptConfig.Passphrase.GetStatus())
|
||||||
assert.NotEmpty(t, initialPayload)
|
assert.NotEmpty(t, initialPayload)
|
||||||
assert.Empty(t, user.FsConfig.CryptConfig.Passphrase.GetAdditionalData())
|
assert.Empty(t, user.FsConfig.CryptConfig.Passphrase.GetAdditionalData())
|
||||||
assert.Empty(t, user.FsConfig.CryptConfig.Passphrase.GetKey())
|
assert.Empty(t, user.FsConfig.CryptConfig.Passphrase.GetKey())
|
||||||
user.FsConfig.CryptConfig.Passphrase.SetStatus(kms.SecretStatusSecretBox)
|
user.FsConfig.CryptConfig.Passphrase.SetStatus(sdkkms.SecretStatusSecretBox)
|
||||||
user.FsConfig.CryptConfig.Passphrase.SetAdditionalData("data")
|
user.FsConfig.CryptConfig.Passphrase.SetAdditionalData("data")
|
||||||
user.FsConfig.CryptConfig.Passphrase.SetKey("fake pass key")
|
user.FsConfig.CryptConfig.Passphrase.SetKey("fake pass key")
|
||||||
user, bb, err := httpdtest.UpdateUser(user, http.StatusOK, "")
|
user, bb, err := httpdtest.UpdateUser(user, http.StatusOK, "")
|
||||||
assert.NoError(t, err, string(bb))
|
assert.NoError(t, err, string(bb))
|
||||||
assert.Equal(t, kms.SecretStatusSecretBox, user.FsConfig.CryptConfig.Passphrase.GetStatus())
|
assert.Equal(t, sdkkms.SecretStatusSecretBox, user.FsConfig.CryptConfig.Passphrase.GetStatus())
|
||||||
assert.Equal(t, initialPayload, user.FsConfig.CryptConfig.Passphrase.GetPayload())
|
assert.Equal(t, initialPayload, user.FsConfig.CryptConfig.Passphrase.GetPayload())
|
||||||
assert.Empty(t, user.FsConfig.CryptConfig.Passphrase.GetAdditionalData())
|
assert.Empty(t, user.FsConfig.CryptConfig.Passphrase.GetAdditionalData())
|
||||||
assert.Empty(t, user.FsConfig.CryptConfig.Passphrase.GetKey())
|
assert.Empty(t, user.FsConfig.CryptConfig.Passphrase.GetKey())
|
||||||
|
@ -2647,7 +2644,7 @@ func TestUserCryptFs(t *testing.T) {
|
||||||
user.Password = defaultPassword
|
user.Password = defaultPassword
|
||||||
user.ID = 0
|
user.ID = 0
|
||||||
user.CreatedAt = 0
|
user.CreatedAt = 0
|
||||||
secret := kms.NewSecret(kms.SecretStatusSecretBox, "invalid encrypted payload", "", "")
|
secret := kms.NewSecret(sdkkms.SecretStatusSecretBox, "invalid encrypted payload", "", "")
|
||||||
user.FsConfig.CryptConfig.Passphrase = secret
|
user.FsConfig.CryptConfig.Passphrase = secret
|
||||||
_, _, err = httpdtest.AddUser(user, http.StatusCreated)
|
_, _, err = httpdtest.AddUser(user, http.StatusCreated)
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
|
@ -2655,7 +2652,7 @@ func TestUserCryptFs(t *testing.T) {
|
||||||
user, _, err = httpdtest.AddUser(user, http.StatusCreated)
|
user, _, err = httpdtest.AddUser(user, http.StatusCreated)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
initialPayload = user.FsConfig.CryptConfig.Passphrase.GetPayload()
|
initialPayload = user.FsConfig.CryptConfig.Passphrase.GetPayload()
|
||||||
assert.Equal(t, kms.SecretStatusSecretBox, user.FsConfig.CryptConfig.Passphrase.GetStatus())
|
assert.Equal(t, sdkkms.SecretStatusSecretBox, user.FsConfig.CryptConfig.Passphrase.GetStatus())
|
||||||
assert.NotEmpty(t, initialPayload)
|
assert.NotEmpty(t, initialPayload)
|
||||||
assert.Empty(t, user.FsConfig.CryptConfig.Passphrase.GetAdditionalData())
|
assert.Empty(t, user.FsConfig.CryptConfig.Passphrase.GetAdditionalData())
|
||||||
assert.Empty(t, user.FsConfig.CryptConfig.Passphrase.GetKey())
|
assert.Empty(t, user.FsConfig.CryptConfig.Passphrase.GetKey())
|
||||||
|
@ -2663,7 +2660,7 @@ func TestUserCryptFs(t *testing.T) {
|
||||||
user.FsConfig.CryptConfig.Passphrase.SetKey("pass")
|
user.FsConfig.CryptConfig.Passphrase.SetKey("pass")
|
||||||
user, bb, err = httpdtest.UpdateUser(user, http.StatusOK, "")
|
user, bb, err = httpdtest.UpdateUser(user, http.StatusOK, "")
|
||||||
assert.NoError(t, err, string(bb))
|
assert.NoError(t, err, string(bb))
|
||||||
assert.Equal(t, kms.SecretStatusSecretBox, user.FsConfig.CryptConfig.Passphrase.GetStatus())
|
assert.Equal(t, sdkkms.SecretStatusSecretBox, user.FsConfig.CryptConfig.Passphrase.GetStatus())
|
||||||
assert.NotEmpty(t, initialPayload)
|
assert.NotEmpty(t, initialPayload)
|
||||||
assert.Equal(t, initialPayload, user.FsConfig.CryptConfig.Passphrase.GetPayload())
|
assert.Equal(t, initialPayload, user.FsConfig.CryptConfig.Passphrase.GetPayload())
|
||||||
assert.Empty(t, user.FsConfig.CryptConfig.Passphrase.GetAdditionalData())
|
assert.Empty(t, user.FsConfig.CryptConfig.Passphrase.GetAdditionalData())
|
||||||
|
@ -2696,28 +2693,28 @@ func TestUserSFTPFs(t *testing.T) {
|
||||||
assert.Equal(t, int64(2), user.FsConfig.SFTPConfig.BufferSize)
|
assert.Equal(t, int64(2), user.FsConfig.SFTPConfig.BufferSize)
|
||||||
initialPwdPayload := user.FsConfig.SFTPConfig.Password.GetPayload()
|
initialPwdPayload := user.FsConfig.SFTPConfig.Password.GetPayload()
|
||||||
initialPkeyPayload := user.FsConfig.SFTPConfig.PrivateKey.GetPayload()
|
initialPkeyPayload := user.FsConfig.SFTPConfig.PrivateKey.GetPayload()
|
||||||
assert.Equal(t, kms.SecretStatusSecretBox, user.FsConfig.SFTPConfig.Password.GetStatus())
|
assert.Equal(t, sdkkms.SecretStatusSecretBox, user.FsConfig.SFTPConfig.Password.GetStatus())
|
||||||
assert.NotEmpty(t, initialPwdPayload)
|
assert.NotEmpty(t, initialPwdPayload)
|
||||||
assert.Empty(t, user.FsConfig.SFTPConfig.Password.GetAdditionalData())
|
assert.Empty(t, user.FsConfig.SFTPConfig.Password.GetAdditionalData())
|
||||||
assert.Empty(t, user.FsConfig.SFTPConfig.Password.GetKey())
|
assert.Empty(t, user.FsConfig.SFTPConfig.Password.GetKey())
|
||||||
assert.Equal(t, kms.SecretStatusSecretBox, user.FsConfig.SFTPConfig.PrivateKey.GetStatus())
|
assert.Equal(t, sdkkms.SecretStatusSecretBox, user.FsConfig.SFTPConfig.PrivateKey.GetStatus())
|
||||||
assert.NotEmpty(t, initialPkeyPayload)
|
assert.NotEmpty(t, initialPkeyPayload)
|
||||||
assert.Empty(t, user.FsConfig.SFTPConfig.PrivateKey.GetAdditionalData())
|
assert.Empty(t, user.FsConfig.SFTPConfig.PrivateKey.GetAdditionalData())
|
||||||
assert.Empty(t, user.FsConfig.SFTPConfig.PrivateKey.GetKey())
|
assert.Empty(t, user.FsConfig.SFTPConfig.PrivateKey.GetKey())
|
||||||
user.FsConfig.SFTPConfig.Password.SetStatus(kms.SecretStatusSecretBox)
|
user.FsConfig.SFTPConfig.Password.SetStatus(sdkkms.SecretStatusSecretBox)
|
||||||
user.FsConfig.SFTPConfig.Password.SetAdditionalData("adata")
|
user.FsConfig.SFTPConfig.Password.SetAdditionalData("adata")
|
||||||
user.FsConfig.SFTPConfig.Password.SetKey("fake pwd key")
|
user.FsConfig.SFTPConfig.Password.SetKey("fake pwd key")
|
||||||
user.FsConfig.SFTPConfig.PrivateKey.SetStatus(kms.SecretStatusSecretBox)
|
user.FsConfig.SFTPConfig.PrivateKey.SetStatus(sdkkms.SecretStatusSecretBox)
|
||||||
user.FsConfig.SFTPConfig.PrivateKey.SetAdditionalData("adata")
|
user.FsConfig.SFTPConfig.PrivateKey.SetAdditionalData("adata")
|
||||||
user.FsConfig.SFTPConfig.PrivateKey.SetKey("fake key")
|
user.FsConfig.SFTPConfig.PrivateKey.SetKey("fake key")
|
||||||
user.FsConfig.SFTPConfig.DisableCouncurrentReads = false
|
user.FsConfig.SFTPConfig.DisableCouncurrentReads = false
|
||||||
user, bb, err := httpdtest.UpdateUser(user, http.StatusOK, "")
|
user, bb, err := httpdtest.UpdateUser(user, http.StatusOK, "")
|
||||||
assert.NoError(t, err, string(bb))
|
assert.NoError(t, err, string(bb))
|
||||||
assert.Equal(t, kms.SecretStatusSecretBox, user.FsConfig.SFTPConfig.Password.GetStatus())
|
assert.Equal(t, sdkkms.SecretStatusSecretBox, user.FsConfig.SFTPConfig.Password.GetStatus())
|
||||||
assert.Equal(t, initialPwdPayload, user.FsConfig.SFTPConfig.Password.GetPayload())
|
assert.Equal(t, initialPwdPayload, user.FsConfig.SFTPConfig.Password.GetPayload())
|
||||||
assert.Empty(t, user.FsConfig.SFTPConfig.Password.GetAdditionalData())
|
assert.Empty(t, user.FsConfig.SFTPConfig.Password.GetAdditionalData())
|
||||||
assert.Empty(t, user.FsConfig.SFTPConfig.Password.GetKey())
|
assert.Empty(t, user.FsConfig.SFTPConfig.Password.GetKey())
|
||||||
assert.Equal(t, kms.SecretStatusSecretBox, user.FsConfig.SFTPConfig.PrivateKey.GetStatus())
|
assert.Equal(t, sdkkms.SecretStatusSecretBox, user.FsConfig.SFTPConfig.PrivateKey.GetStatus())
|
||||||
assert.Equal(t, initialPkeyPayload, user.FsConfig.SFTPConfig.PrivateKey.GetPayload())
|
assert.Equal(t, initialPkeyPayload, user.FsConfig.SFTPConfig.PrivateKey.GetPayload())
|
||||||
assert.Empty(t, user.FsConfig.SFTPConfig.PrivateKey.GetAdditionalData())
|
assert.Empty(t, user.FsConfig.SFTPConfig.PrivateKey.GetAdditionalData())
|
||||||
assert.Empty(t, user.FsConfig.SFTPConfig.PrivateKey.GetKey())
|
assert.Empty(t, user.FsConfig.SFTPConfig.PrivateKey.GetKey())
|
||||||
|
@ -2728,7 +2725,7 @@ func TestUserSFTPFs(t *testing.T) {
|
||||||
user.Password = defaultPassword
|
user.Password = defaultPassword
|
||||||
user.ID = 0
|
user.ID = 0
|
||||||
user.CreatedAt = 0
|
user.CreatedAt = 0
|
||||||
secret := kms.NewSecret(kms.SecretStatusSecretBox, "invalid encrypted payload", "", "")
|
secret := kms.NewSecret(sdkkms.SecretStatusSecretBox, "invalid encrypted payload", "", "")
|
||||||
user.FsConfig.SFTPConfig.Password = secret
|
user.FsConfig.SFTPConfig.Password = secret
|
||||||
_, _, err = httpdtest.AddUser(user, http.StatusCreated)
|
_, _, err = httpdtest.AddUser(user, http.StatusCreated)
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
|
@ -2742,7 +2739,7 @@ func TestUserSFTPFs(t *testing.T) {
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
initialPkeyPayload = user.FsConfig.SFTPConfig.PrivateKey.GetPayload()
|
initialPkeyPayload = user.FsConfig.SFTPConfig.PrivateKey.GetPayload()
|
||||||
assert.Nil(t, user.FsConfig.SFTPConfig.Password)
|
assert.Nil(t, user.FsConfig.SFTPConfig.Password)
|
||||||
assert.Equal(t, kms.SecretStatusSecretBox, user.FsConfig.SFTPConfig.PrivateKey.GetStatus())
|
assert.Equal(t, sdkkms.SecretStatusSecretBox, user.FsConfig.SFTPConfig.PrivateKey.GetStatus())
|
||||||
assert.NotEmpty(t, initialPkeyPayload)
|
assert.NotEmpty(t, initialPkeyPayload)
|
||||||
assert.Empty(t, user.FsConfig.SFTPConfig.PrivateKey.GetAdditionalData())
|
assert.Empty(t, user.FsConfig.SFTPConfig.PrivateKey.GetAdditionalData())
|
||||||
assert.Empty(t, user.FsConfig.SFTPConfig.PrivateKey.GetKey())
|
assert.Empty(t, user.FsConfig.SFTPConfig.PrivateKey.GetKey())
|
||||||
|
@ -2750,7 +2747,7 @@ func TestUserSFTPFs(t *testing.T) {
|
||||||
user.FsConfig.SFTPConfig.PrivateKey.SetKey("k")
|
user.FsConfig.SFTPConfig.PrivateKey.SetKey("k")
|
||||||
user, bb, err = httpdtest.UpdateUser(user, http.StatusOK, "")
|
user, bb, err = httpdtest.UpdateUser(user, http.StatusOK, "")
|
||||||
assert.NoError(t, err, string(bb))
|
assert.NoError(t, err, string(bb))
|
||||||
assert.Equal(t, kms.SecretStatusSecretBox, user.FsConfig.SFTPConfig.PrivateKey.GetStatus())
|
assert.Equal(t, sdkkms.SecretStatusSecretBox, user.FsConfig.SFTPConfig.PrivateKey.GetStatus())
|
||||||
assert.NotEmpty(t, initialPkeyPayload)
|
assert.NotEmpty(t, initialPkeyPayload)
|
||||||
assert.Equal(t, initialPkeyPayload, user.FsConfig.SFTPConfig.PrivateKey.GetPayload())
|
assert.Equal(t, initialPkeyPayload, user.FsConfig.SFTPConfig.PrivateKey.GetPayload())
|
||||||
assert.Empty(t, user.FsConfig.SFTPConfig.PrivateKey.GetAdditionalData())
|
assert.Empty(t, user.FsConfig.SFTPConfig.PrivateKey.GetAdditionalData())
|
||||||
|
@ -2882,7 +2879,7 @@ func TestUserHiddenFields(t *testing.T) {
|
||||||
assert.NotEmpty(t, user1.FsConfig.S3Config.AccessSecret.GetPayload())
|
assert.NotEmpty(t, user1.FsConfig.S3Config.AccessSecret.GetPayload())
|
||||||
err = user1.FsConfig.S3Config.AccessSecret.Decrypt()
|
err = user1.FsConfig.S3Config.AccessSecret.Decrypt()
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, kms.SecretStatusPlain, user1.FsConfig.S3Config.AccessSecret.GetStatus())
|
assert.Equal(t, sdkkms.SecretStatusPlain, user1.FsConfig.S3Config.AccessSecret.GetStatus())
|
||||||
assert.Equal(t, u1.FsConfig.S3Config.AccessSecret.GetPayload(), user1.FsConfig.S3Config.AccessSecret.GetPayload())
|
assert.Equal(t, u1.FsConfig.S3Config.AccessSecret.GetPayload(), user1.FsConfig.S3Config.AccessSecret.GetPayload())
|
||||||
assert.Empty(t, user1.FsConfig.S3Config.AccessSecret.GetKey())
|
assert.Empty(t, user1.FsConfig.S3Config.AccessSecret.GetKey())
|
||||||
assert.Empty(t, user1.FsConfig.S3Config.AccessSecret.GetAdditionalData())
|
assert.Empty(t, user1.FsConfig.S3Config.AccessSecret.GetAdditionalData())
|
||||||
|
@ -2896,7 +2893,7 @@ func TestUserHiddenFields(t *testing.T) {
|
||||||
assert.NotEmpty(t, user2.FsConfig.GCSConfig.Credentials.GetPayload())
|
assert.NotEmpty(t, user2.FsConfig.GCSConfig.Credentials.GetPayload())
|
||||||
err = user2.FsConfig.GCSConfig.Credentials.Decrypt()
|
err = user2.FsConfig.GCSConfig.Credentials.Decrypt()
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, kms.SecretStatusPlain, user2.FsConfig.GCSConfig.Credentials.GetStatus())
|
assert.Equal(t, sdkkms.SecretStatusPlain, user2.FsConfig.GCSConfig.Credentials.GetStatus())
|
||||||
assert.Equal(t, u2.FsConfig.GCSConfig.Credentials.GetPayload(), user2.FsConfig.GCSConfig.Credentials.GetPayload())
|
assert.Equal(t, u2.FsConfig.GCSConfig.Credentials.GetPayload(), user2.FsConfig.GCSConfig.Credentials.GetPayload())
|
||||||
assert.Empty(t, user2.FsConfig.GCSConfig.Credentials.GetKey())
|
assert.Empty(t, user2.FsConfig.GCSConfig.Credentials.GetKey())
|
||||||
assert.Empty(t, user2.FsConfig.GCSConfig.Credentials.GetAdditionalData())
|
assert.Empty(t, user2.FsConfig.GCSConfig.Credentials.GetAdditionalData())
|
||||||
|
@ -2910,7 +2907,7 @@ func TestUserHiddenFields(t *testing.T) {
|
||||||
assert.NotEmpty(t, user3.FsConfig.AzBlobConfig.AccountKey.GetPayload())
|
assert.NotEmpty(t, user3.FsConfig.AzBlobConfig.AccountKey.GetPayload())
|
||||||
err = user3.FsConfig.AzBlobConfig.AccountKey.Decrypt()
|
err = user3.FsConfig.AzBlobConfig.AccountKey.Decrypt()
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, kms.SecretStatusPlain, user3.FsConfig.AzBlobConfig.AccountKey.GetStatus())
|
assert.Equal(t, sdkkms.SecretStatusPlain, user3.FsConfig.AzBlobConfig.AccountKey.GetStatus())
|
||||||
assert.Equal(t, u3.FsConfig.AzBlobConfig.AccountKey.GetPayload(), user3.FsConfig.AzBlobConfig.AccountKey.GetPayload())
|
assert.Equal(t, u3.FsConfig.AzBlobConfig.AccountKey.GetPayload(), user3.FsConfig.AzBlobConfig.AccountKey.GetPayload())
|
||||||
assert.Empty(t, user3.FsConfig.AzBlobConfig.AccountKey.GetKey())
|
assert.Empty(t, user3.FsConfig.AzBlobConfig.AccountKey.GetKey())
|
||||||
assert.Empty(t, user3.FsConfig.AzBlobConfig.AccountKey.GetAdditionalData())
|
assert.Empty(t, user3.FsConfig.AzBlobConfig.AccountKey.GetAdditionalData())
|
||||||
|
@ -2924,7 +2921,7 @@ func TestUserHiddenFields(t *testing.T) {
|
||||||
assert.NotEmpty(t, user4.FsConfig.CryptConfig.Passphrase.GetPayload())
|
assert.NotEmpty(t, user4.FsConfig.CryptConfig.Passphrase.GetPayload())
|
||||||
err = user4.FsConfig.CryptConfig.Passphrase.Decrypt()
|
err = user4.FsConfig.CryptConfig.Passphrase.Decrypt()
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, kms.SecretStatusPlain, user4.FsConfig.CryptConfig.Passphrase.GetStatus())
|
assert.Equal(t, sdkkms.SecretStatusPlain, user4.FsConfig.CryptConfig.Passphrase.GetStatus())
|
||||||
assert.Equal(t, u4.FsConfig.CryptConfig.Passphrase.GetPayload(), user4.FsConfig.CryptConfig.Passphrase.GetPayload())
|
assert.Equal(t, u4.FsConfig.CryptConfig.Passphrase.GetPayload(), user4.FsConfig.CryptConfig.Passphrase.GetPayload())
|
||||||
assert.Empty(t, user4.FsConfig.CryptConfig.Passphrase.GetKey())
|
assert.Empty(t, user4.FsConfig.CryptConfig.Passphrase.GetKey())
|
||||||
assert.Empty(t, user4.FsConfig.CryptConfig.Passphrase.GetAdditionalData())
|
assert.Empty(t, user4.FsConfig.CryptConfig.Passphrase.GetAdditionalData())
|
||||||
|
@ -2938,7 +2935,7 @@ func TestUserHiddenFields(t *testing.T) {
|
||||||
assert.NotEmpty(t, user5.FsConfig.SFTPConfig.Password.GetPayload())
|
assert.NotEmpty(t, user5.FsConfig.SFTPConfig.Password.GetPayload())
|
||||||
err = user5.FsConfig.SFTPConfig.Password.Decrypt()
|
err = user5.FsConfig.SFTPConfig.Password.Decrypt()
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, kms.SecretStatusPlain, user5.FsConfig.SFTPConfig.Password.GetStatus())
|
assert.Equal(t, sdkkms.SecretStatusPlain, user5.FsConfig.SFTPConfig.Password.GetStatus())
|
||||||
assert.Equal(t, u5.FsConfig.SFTPConfig.Password.GetPayload(), user5.FsConfig.SFTPConfig.Password.GetPayload())
|
assert.Equal(t, u5.FsConfig.SFTPConfig.Password.GetPayload(), user5.FsConfig.SFTPConfig.Password.GetPayload())
|
||||||
assert.Empty(t, user5.FsConfig.SFTPConfig.Password.GetKey())
|
assert.Empty(t, user5.FsConfig.SFTPConfig.Password.GetKey())
|
||||||
assert.Empty(t, user5.FsConfig.SFTPConfig.Password.GetAdditionalData())
|
assert.Empty(t, user5.FsConfig.SFTPConfig.Password.GetAdditionalData())
|
||||||
|
@ -2948,7 +2945,7 @@ func TestUserHiddenFields(t *testing.T) {
|
||||||
assert.NotEmpty(t, user5.FsConfig.SFTPConfig.PrivateKey.GetPayload())
|
assert.NotEmpty(t, user5.FsConfig.SFTPConfig.PrivateKey.GetPayload())
|
||||||
err = user5.FsConfig.SFTPConfig.PrivateKey.Decrypt()
|
err = user5.FsConfig.SFTPConfig.PrivateKey.Decrypt()
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, kms.SecretStatusPlain, user5.FsConfig.SFTPConfig.PrivateKey.GetStatus())
|
assert.Equal(t, sdkkms.SecretStatusPlain, user5.FsConfig.SFTPConfig.PrivateKey.GetStatus())
|
||||||
assert.Equal(t, u5.FsConfig.SFTPConfig.PrivateKey.GetPayload(), user5.FsConfig.SFTPConfig.PrivateKey.GetPayload())
|
assert.Equal(t, u5.FsConfig.SFTPConfig.PrivateKey.GetPayload(), user5.FsConfig.SFTPConfig.PrivateKey.GetPayload())
|
||||||
assert.Empty(t, user5.FsConfig.SFTPConfig.PrivateKey.GetKey())
|
assert.Empty(t, user5.FsConfig.SFTPConfig.PrivateKey.GetKey())
|
||||||
assert.Empty(t, user5.FsConfig.SFTPConfig.PrivateKey.GetAdditionalData())
|
assert.Empty(t, user5.FsConfig.SFTPConfig.PrivateKey.GetAdditionalData())
|
||||||
|
@ -2996,13 +2993,13 @@ func TestSecretObject(t *testing.T) {
|
||||||
require.True(t, s.IsValid())
|
require.True(t, s.IsValid())
|
||||||
err := s.Encrypt()
|
err := s.Encrypt()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, kms.SecretStatusSecretBox, s.GetStatus())
|
require.Equal(t, sdkkms.SecretStatusSecretBox, s.GetStatus())
|
||||||
require.NotEmpty(t, s.GetPayload())
|
require.NotEmpty(t, s.GetPayload())
|
||||||
require.NotEmpty(t, s.GetKey())
|
require.NotEmpty(t, s.GetKey())
|
||||||
require.True(t, s.IsValid())
|
require.True(t, s.IsValid())
|
||||||
err = s.Decrypt()
|
err = s.Decrypt()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, kms.SecretStatusPlain, s.GetStatus())
|
require.Equal(t, sdkkms.SecretStatusPlain, s.GetStatus())
|
||||||
require.Equal(t, "test data", s.GetPayload())
|
require.Equal(t, "test data", s.GetPayload())
|
||||||
require.Empty(t, s.GetKey())
|
require.Empty(t, s.GetKey())
|
||||||
}
|
}
|
||||||
|
@ -3017,10 +3014,10 @@ func TestSecretObjectCompatibility(t *testing.T) {
|
||||||
localAsJSON, err := json.Marshal(s)
|
localAsJSON, err := json.Marshal(s)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
for _, secretStatus := range []string{kms.SecretStatusSecretBox} {
|
for _, secretStatus := range []string{sdkkms.SecretStatusSecretBox} {
|
||||||
kmsConfig := config.GetKMSConfig()
|
kmsConfig := config.GetKMSConfig()
|
||||||
assert.Empty(t, kmsConfig.Secrets.MasterKeyPath)
|
assert.Empty(t, kmsConfig.Secrets.MasterKeyPath)
|
||||||
if secretStatus == kms.SecretStatusVaultTransit {
|
if secretStatus == sdkkms.SecretStatusVaultTransit {
|
||||||
os.Setenv("VAULT_SERVER_URL", "http://127.0.0.1:8200")
|
os.Setenv("VAULT_SERVER_URL", "http://127.0.0.1:8200")
|
||||||
os.Setenv("VAULT_SERVER_TOKEN", "s.9lYGq83MbgG5KR5kfebXVyhJ")
|
os.Setenv("VAULT_SERVER_TOKEN", "s.9lYGq83MbgG5KR5kfebXVyhJ")
|
||||||
kmsConfig.Secrets.URL = "hashivault://mykey"
|
kmsConfig.Secrets.URL = "hashivault://mykey"
|
||||||
|
@ -3037,20 +3034,20 @@ func TestSecretObjectCompatibility(t *testing.T) {
|
||||||
err = secretClone.Decrypt()
|
err = secretClone.Decrypt()
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, testPayload, secretClone.GetPayload())
|
assert.Equal(t, testPayload, secretClone.GetPayload())
|
||||||
if secretStatus == kms.SecretStatusVaultTransit {
|
if secretStatus == sdkkms.SecretStatusVaultTransit {
|
||||||
// decrypt the local secret now that the provider is vault
|
// decrypt the local secret now that the provider is vault
|
||||||
secretLocal := kms.NewEmptySecret()
|
secretLocal := kms.NewEmptySecret()
|
||||||
err = json.Unmarshal(localAsJSON, secretLocal)
|
err = json.Unmarshal(localAsJSON, secretLocal)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, kms.SecretStatusSecretBox, secretLocal.GetStatus())
|
assert.Equal(t, sdkkms.SecretStatusSecretBox, secretLocal.GetStatus())
|
||||||
assert.Equal(t, 0, secretLocal.GetMode())
|
assert.Equal(t, 0, secretLocal.GetMode())
|
||||||
err = secretLocal.Decrypt()
|
err = secretLocal.Decrypt()
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, testPayload, secretLocal.GetPayload())
|
assert.Equal(t, testPayload, secretLocal.GetPayload())
|
||||||
assert.Equal(t, kms.SecretStatusPlain, secretLocal.GetStatus())
|
assert.Equal(t, sdkkms.SecretStatusPlain, secretLocal.GetStatus())
|
||||||
err = secretLocal.Encrypt()
|
err = secretLocal.Encrypt()
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, kms.SecretStatusSecretBox, secretLocal.GetStatus())
|
assert.Equal(t, sdkkms.SecretStatusSecretBox, secretLocal.GetStatus())
|
||||||
assert.Equal(t, 0, secretLocal.GetMode())
|
assert.Equal(t, 0, secretLocal.GetMode())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3065,7 +3062,7 @@ func TestSecretObjectCompatibility(t *testing.T) {
|
||||||
MasterKeyPath: masterKeyPath,
|
MasterKeyPath: masterKeyPath,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
if secretStatus == kms.SecretStatusVaultTransit {
|
if secretStatus == sdkkms.SecretStatusVaultTransit {
|
||||||
config.Secrets.URL = "hashivault://mykey"
|
config.Secrets.URL = "hashivault://mykey"
|
||||||
}
|
}
|
||||||
err = config.Initialize()
|
err = config.Initialize()
|
||||||
|
@ -3085,22 +3082,22 @@ func TestSecretObjectCompatibility(t *testing.T) {
|
||||||
err = secret.Decrypt()
|
err = secret.Decrypt()
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, testPayload, secret.GetPayload())
|
assert.Equal(t, testPayload, secret.GetPayload())
|
||||||
if secretStatus == kms.SecretStatusVaultTransit {
|
if secretStatus == sdkkms.SecretStatusVaultTransit {
|
||||||
// decrypt the local secret encryped without a master key now that
|
// decrypt the local secret encryped without a master key now that
|
||||||
// the provider is vault and a master key is set.
|
// the provider is vault and a master key is set.
|
||||||
// The provider will not change, the master key will be used
|
// The provider will not change, the master key will be used
|
||||||
secretLocal := kms.NewEmptySecret()
|
secretLocal := kms.NewEmptySecret()
|
||||||
err = json.Unmarshal(localAsJSON, secretLocal)
|
err = json.Unmarshal(localAsJSON, secretLocal)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, kms.SecretStatusSecretBox, secretLocal.GetStatus())
|
assert.Equal(t, sdkkms.SecretStatusSecretBox, secretLocal.GetStatus())
|
||||||
assert.Equal(t, 0, secretLocal.GetMode())
|
assert.Equal(t, 0, secretLocal.GetMode())
|
||||||
err = secretLocal.Decrypt()
|
err = secretLocal.Decrypt()
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, testPayload, secretLocal.GetPayload())
|
assert.Equal(t, testPayload, secretLocal.GetPayload())
|
||||||
assert.Equal(t, kms.SecretStatusPlain, secretLocal.GetStatus())
|
assert.Equal(t, sdkkms.SecretStatusPlain, secretLocal.GetStatus())
|
||||||
err = secretLocal.Encrypt()
|
err = secretLocal.Encrypt()
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, kms.SecretStatusSecretBox, secretLocal.GetStatus())
|
assert.Equal(t, sdkkms.SecretStatusSecretBox, secretLocal.GetStatus())
|
||||||
assert.Equal(t, 1, secretLocal.GetMode())
|
assert.Equal(t, 1, secretLocal.GetMode())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3108,7 +3105,7 @@ func TestSecretObjectCompatibility(t *testing.T) {
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
err = os.Remove(masterKeyPath)
|
err = os.Remove(masterKeyPath)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
if secretStatus == kms.SecretStatusVaultTransit {
|
if secretStatus == sdkkms.SecretStatusVaultTransit {
|
||||||
os.Unsetenv("VAULT_SERVER_URL")
|
os.Unsetenv("VAULT_SERVER_URL")
|
||||||
os.Unsetenv("VAULT_SERVER_TOKEN")
|
os.Unsetenv("VAULT_SERVER_TOKEN")
|
||||||
}
|
}
|
||||||
|
@ -3373,13 +3370,13 @@ func TestEmbeddedFoldersUpdate(t *testing.T) {
|
||||||
FsConfig: vfs.Filesystem{
|
FsConfig: vfs.Filesystem{
|
||||||
Provider: sdk.S3FilesystemProvider,
|
Provider: sdk.S3FilesystemProvider,
|
||||||
S3Config: vfs.S3FsConfig{
|
S3Config: vfs.S3FsConfig{
|
||||||
S3FsConfig: sdk.S3FsConfig{
|
BaseS3FsConfig: sdk.BaseS3FsConfig{
|
||||||
Bucket: "test",
|
Bucket: "test",
|
||||||
Region: "us-east-1",
|
Region: "us-east-1",
|
||||||
AccessKey: "akey",
|
AccessKey: "akey",
|
||||||
AccessSecret: kms.NewPlainSecret("asecret"),
|
Endpoint: "http://127.0.1.1:9090",
|
||||||
Endpoint: "http://127.0.1.1:9090",
|
|
||||||
},
|
},
|
||||||
|
AccessSecret: kms.NewPlainSecret("asecret"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -3399,7 +3396,7 @@ func TestEmbeddedFoldersUpdate(t *testing.T) {
|
||||||
assert.Equal(t, "test", userFolder.FsConfig.S3Config.Bucket)
|
assert.Equal(t, "test", userFolder.FsConfig.S3Config.Bucket)
|
||||||
assert.Equal(t, "us-east-1", userFolder.FsConfig.S3Config.Region)
|
assert.Equal(t, "us-east-1", userFolder.FsConfig.S3Config.Region)
|
||||||
assert.Equal(t, "http://127.0.1.1:9090", userFolder.FsConfig.S3Config.Endpoint)
|
assert.Equal(t, "http://127.0.1.1:9090", userFolder.FsConfig.S3Config.Endpoint)
|
||||||
assert.Equal(t, kms.SecretStatusSecretBox, userFolder.FsConfig.S3Config.AccessSecret.GetStatus())
|
assert.Equal(t, sdkkms.SecretStatusSecretBox, userFolder.FsConfig.S3Config.AccessSecret.GetStatus())
|
||||||
assert.NotEmpty(t, userFolder.FsConfig.S3Config.AccessSecret.GetPayload())
|
assert.NotEmpty(t, userFolder.FsConfig.S3Config.AccessSecret.GetPayload())
|
||||||
assert.Empty(t, userFolder.FsConfig.S3Config.AccessSecret.GetKey())
|
assert.Empty(t, userFolder.FsConfig.S3Config.AccessSecret.GetKey())
|
||||||
assert.Empty(t, userFolder.FsConfig.S3Config.AccessSecret.GetAdditionalData())
|
assert.Empty(t, userFolder.FsConfig.S3Config.AccessSecret.GetAdditionalData())
|
||||||
|
@ -3414,7 +3411,7 @@ func TestEmbeddedFoldersUpdate(t *testing.T) {
|
||||||
assert.Equal(t, "test", folder.FsConfig.S3Config.Bucket)
|
assert.Equal(t, "test", folder.FsConfig.S3Config.Bucket)
|
||||||
assert.Equal(t, "us-east-1", folder.FsConfig.S3Config.Region)
|
assert.Equal(t, "us-east-1", folder.FsConfig.S3Config.Region)
|
||||||
assert.Equal(t, "http://127.0.1.1:9090", folder.FsConfig.S3Config.Endpoint)
|
assert.Equal(t, "http://127.0.1.1:9090", folder.FsConfig.S3Config.Endpoint)
|
||||||
assert.Equal(t, kms.SecretStatusSecretBox, folder.FsConfig.S3Config.AccessSecret.GetStatus())
|
assert.Equal(t, sdkkms.SecretStatusSecretBox, folder.FsConfig.S3Config.AccessSecret.GetStatus())
|
||||||
assert.NotEmpty(t, folder.FsConfig.S3Config.AccessSecret.GetPayload())
|
assert.NotEmpty(t, folder.FsConfig.S3Config.AccessSecret.GetPayload())
|
||||||
assert.Empty(t, folder.FsConfig.S3Config.AccessSecret.GetKey())
|
assert.Empty(t, folder.FsConfig.S3Config.AccessSecret.GetKey())
|
||||||
assert.Empty(t, folder.FsConfig.S3Config.AccessSecret.GetAdditionalData())
|
assert.Empty(t, folder.FsConfig.S3Config.AccessSecret.GetAdditionalData())
|
||||||
|
@ -3432,7 +3429,7 @@ func TestEmbeddedFoldersUpdate(t *testing.T) {
|
||||||
assert.Equal(t, "test", folder.FsConfig.S3Config.Bucket)
|
assert.Equal(t, "test", folder.FsConfig.S3Config.Bucket)
|
||||||
assert.Equal(t, "us-east-1", folder.FsConfig.S3Config.Region)
|
assert.Equal(t, "us-east-1", folder.FsConfig.S3Config.Region)
|
||||||
assert.Equal(t, "http://127.0.1.1:9090", folder.FsConfig.S3Config.Endpoint)
|
assert.Equal(t, "http://127.0.1.1:9090", folder.FsConfig.S3Config.Endpoint)
|
||||||
assert.Equal(t, kms.SecretStatusSecretBox, folder.FsConfig.S3Config.AccessSecret.GetStatus())
|
assert.Equal(t, sdkkms.SecretStatusSecretBox, folder.FsConfig.S3Config.AccessSecret.GetStatus())
|
||||||
assert.NotEmpty(t, folder.FsConfig.S3Config.AccessSecret.GetPayload())
|
assert.NotEmpty(t, folder.FsConfig.S3Config.AccessSecret.GetPayload())
|
||||||
assert.Empty(t, folder.FsConfig.S3Config.AccessSecret.GetKey())
|
assert.Empty(t, folder.FsConfig.S3Config.AccessSecret.GetKey())
|
||||||
assert.Empty(t, folder.FsConfig.S3Config.AccessSecret.GetAdditionalData())
|
assert.Empty(t, folder.FsConfig.S3Config.AccessSecret.GetAdditionalData())
|
||||||
|
@ -3449,7 +3446,7 @@ func TestEmbeddedFoldersUpdate(t *testing.T) {
|
||||||
assert.Equal(t, "test", userFolder.FsConfig.S3Config.Bucket)
|
assert.Equal(t, "test", userFolder.FsConfig.S3Config.Bucket)
|
||||||
assert.Equal(t, "us-east-1", userFolder.FsConfig.S3Config.Region)
|
assert.Equal(t, "us-east-1", userFolder.FsConfig.S3Config.Region)
|
||||||
assert.Equal(t, "http://127.0.1.1:9090", userFolder.FsConfig.S3Config.Endpoint)
|
assert.Equal(t, "http://127.0.1.1:9090", userFolder.FsConfig.S3Config.Endpoint)
|
||||||
assert.Equal(t, kms.SecretStatusSecretBox, userFolder.FsConfig.S3Config.AccessSecret.GetStatus())
|
assert.Equal(t, sdkkms.SecretStatusSecretBox, userFolder.FsConfig.S3Config.AccessSecret.GetStatus())
|
||||||
assert.NotEmpty(t, userFolder.FsConfig.S3Config.AccessSecret.GetPayload())
|
assert.NotEmpty(t, userFolder.FsConfig.S3Config.AccessSecret.GetPayload())
|
||||||
assert.Empty(t, userFolder.FsConfig.S3Config.AccessSecret.GetKey())
|
assert.Empty(t, userFolder.FsConfig.S3Config.AccessSecret.GetKey())
|
||||||
assert.Empty(t, userFolder.FsConfig.S3Config.AccessSecret.GetAdditionalData())
|
assert.Empty(t, userFolder.FsConfig.S3Config.AccessSecret.GetAdditionalData())
|
||||||
|
@ -3775,7 +3772,7 @@ func TestSaveErrors(t *testing.T) {
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
recCode := "recovery code"
|
recCode := "recovery code"
|
||||||
recoveryCodes := []sdk.RecoveryCode{
|
recoveryCodes := []dataprovider.RecoveryCode{
|
||||||
{
|
{
|
||||||
Secret: kms.NewPlainSecret(recCode),
|
Secret: kms.NewPlainSecret(recCode),
|
||||||
Used: false,
|
Used: false,
|
||||||
|
@ -3791,7 +3788,7 @@ func TestSaveErrors(t *testing.T) {
|
||||||
configName, _, secret, _, err := mfa.GenerateTOTPSecret(mfa.GetAvailableTOTPConfigNames()[0], user.Username)
|
configName, _, secret, _, err := mfa.GenerateTOTPSecret(mfa.GetAvailableTOTPConfigNames()[0], user.Username)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
user.Password = u.Password
|
user.Password = u.Password
|
||||||
user.Filters.TOTPConfig = sdk.TOTPConfig{
|
user.Filters.TOTPConfig = dataprovider.UserTOTPConfig{
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
ConfigName: configName,
|
ConfigName: configName,
|
||||||
Secret: kms.NewPlainSecret(secret),
|
Secret: kms.NewPlainSecret(secret),
|
||||||
|
@ -3813,7 +3810,7 @@ func TestSaveErrors(t *testing.T) {
|
||||||
admin, _, err = httpdtest.UpdateAdmin(admin, http.StatusOK)
|
admin, _, err = httpdtest.UpdateAdmin(admin, http.StatusOK)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
admin.Password = a.Password
|
admin.Password = a.Password
|
||||||
admin.Filters.TOTPConfig = dataprovider.TOTPConfig{
|
admin.Filters.TOTPConfig = dataprovider.AdminTOTPConfig{
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
ConfigName: configName,
|
ConfigName: configName,
|
||||||
Secret: kms.NewPlainSecret(secret),
|
Secret: kms.NewPlainSecret(secret),
|
||||||
|
@ -4141,9 +4138,7 @@ func TestFolders(t *testing.T) {
|
||||||
FsConfig: vfs.Filesystem{
|
FsConfig: vfs.Filesystem{
|
||||||
Provider: sdk.CryptedFilesystemProvider,
|
Provider: sdk.CryptedFilesystemProvider,
|
||||||
CryptConfig: vfs.CryptFsConfig{
|
CryptConfig: vfs.CryptFsConfig{
|
||||||
CryptFsConfig: sdk.CryptFsConfig{
|
Passphrase: kms.NewPlainSecret("asecret"),
|
||||||
Passphrase: kms.NewPlainSecret("asecret"),
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -4157,7 +4152,7 @@ func TestFolders(t *testing.T) {
|
||||||
assert.Equal(t, 0, folder1.UsedQuotaFiles)
|
assert.Equal(t, 0, folder1.UsedQuotaFiles)
|
||||||
assert.Equal(t, int64(0), folder1.UsedQuotaSize)
|
assert.Equal(t, int64(0), folder1.UsedQuotaSize)
|
||||||
assert.Equal(t, int64(0), folder1.LastQuotaUpdate)
|
assert.Equal(t, int64(0), folder1.LastQuotaUpdate)
|
||||||
assert.Equal(t, kms.SecretStatusSecretBox, folder1.FsConfig.CryptConfig.Passphrase.GetStatus())
|
assert.Equal(t, sdkkms.SecretStatusSecretBox, folder1.FsConfig.CryptConfig.Passphrase.GetStatus())
|
||||||
assert.NotEmpty(t, folder1.FsConfig.CryptConfig.Passphrase.GetPayload())
|
assert.NotEmpty(t, folder1.FsConfig.CryptConfig.Passphrase.GetPayload())
|
||||||
assert.Empty(t, folder1.FsConfig.CryptConfig.Passphrase.GetAdditionalData())
|
assert.Empty(t, folder1.FsConfig.CryptConfig.Passphrase.GetAdditionalData())
|
||||||
assert.Empty(t, folder1.FsConfig.CryptConfig.Passphrase.GetKey())
|
assert.Empty(t, folder1.FsConfig.CryptConfig.Passphrase.GetKey())
|
||||||
|
@ -4185,7 +4180,7 @@ func TestFolders(t *testing.T) {
|
||||||
if f.Name == folder1.Name {
|
if f.Name == folder1.Name {
|
||||||
found = true
|
found = true
|
||||||
assert.Equal(t, folder1.MappedPath, f.MappedPath)
|
assert.Equal(t, folder1.MappedPath, f.MappedPath)
|
||||||
assert.Equal(t, kms.SecretStatusSecretBox, f.FsConfig.CryptConfig.Passphrase.GetStatus())
|
assert.Equal(t, sdkkms.SecretStatusSecretBox, f.FsConfig.CryptConfig.Passphrase.GetStatus())
|
||||||
assert.NotEmpty(t, f.FsConfig.CryptConfig.Passphrase.GetPayload())
|
assert.NotEmpty(t, f.FsConfig.CryptConfig.Passphrase.GetPayload())
|
||||||
assert.Empty(t, f.FsConfig.CryptConfig.Passphrase.GetAdditionalData())
|
assert.Empty(t, f.FsConfig.CryptConfig.Passphrase.GetAdditionalData())
|
||||||
assert.Empty(t, f.FsConfig.CryptConfig.Passphrase.GetKey())
|
assert.Empty(t, f.FsConfig.CryptConfig.Passphrase.GetKey())
|
||||||
|
@ -4203,7 +4198,7 @@ func TestFolders(t *testing.T) {
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, folder1.Name, f.Name)
|
assert.Equal(t, folder1.Name, f.Name)
|
||||||
assert.Equal(t, folder1.MappedPath, f.MappedPath)
|
assert.Equal(t, folder1.MappedPath, f.MappedPath)
|
||||||
assert.Equal(t, kms.SecretStatusSecretBox, f.FsConfig.CryptConfig.Passphrase.GetStatus())
|
assert.Equal(t, sdkkms.SecretStatusSecretBox, f.FsConfig.CryptConfig.Passphrase.GetStatus())
|
||||||
assert.NotEmpty(t, f.FsConfig.CryptConfig.Passphrase.GetPayload())
|
assert.NotEmpty(t, f.FsConfig.CryptConfig.Passphrase.GetPayload())
|
||||||
assert.Empty(t, f.FsConfig.CryptConfig.Passphrase.GetAdditionalData())
|
assert.Empty(t, f.FsConfig.CryptConfig.Passphrase.GetAdditionalData())
|
||||||
assert.Empty(t, f.FsConfig.CryptConfig.Passphrase.GetKey())
|
assert.Empty(t, f.FsConfig.CryptConfig.Passphrase.GetKey())
|
||||||
|
@ -5086,7 +5081,7 @@ func TestAdminTwoFactorLogin(t *testing.T) {
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
altToken, err := getJWTAPITokenFromTestServer(altAdminUsername, altAdminPassword)
|
altToken, err := getJWTAPITokenFromTestServer(altAdminUsername, altAdminPassword)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
adminTOTPConfig := dataprovider.TOTPConfig{
|
adminTOTPConfig := dataprovider.AdminTOTPConfig{
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
ConfigName: configName,
|
ConfigName: configName,
|
||||||
Secret: kms.NewPlainSecret(secret),
|
Secret: kms.NewPlainSecret(secret),
|
||||||
|
@ -5118,7 +5113,7 @@ func TestAdminTwoFactorLogin(t *testing.T) {
|
||||||
for _, c := range admin.Filters.RecoveryCodes {
|
for _, c := range admin.Filters.RecoveryCodes {
|
||||||
assert.Empty(t, c.Secret.GetAdditionalData())
|
assert.Empty(t, c.Secret.GetAdditionalData())
|
||||||
assert.Empty(t, c.Secret.GetKey())
|
assert.Empty(t, c.Secret.GetKey())
|
||||||
assert.Equal(t, kms.SecretStatusSecretBox, c.Secret.GetStatus())
|
assert.Equal(t, sdkkms.SecretStatusSecretBox, c.Secret.GetStatus())
|
||||||
assert.NotEmpty(t, c.Secret.GetPayload())
|
assert.NotEmpty(t, c.Secret.GetPayload())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5409,7 +5404,7 @@ func TestAdminTOTP(t *testing.T) {
|
||||||
admin.Username = altAdminUsername
|
admin.Username = altAdminUsername
|
||||||
admin.Password = altAdminPassword
|
admin.Password = altAdminPassword
|
||||||
// TOTPConfig will be ignored on add
|
// TOTPConfig will be ignored on add
|
||||||
admin.Filters.TOTPConfig = dataprovider.TOTPConfig{
|
admin.Filters.TOTPConfig = dataprovider.AdminTOTPConfig{
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
ConfigName: "config",
|
ConfigName: "config",
|
||||||
Secret: kms.NewEmptySecret(),
|
Secret: kms.NewEmptySecret(),
|
||||||
|
@ -5478,7 +5473,7 @@ func TestAdminTOTP(t *testing.T) {
|
||||||
checkResponseCode(t, http.StatusBadRequest, rr)
|
checkResponseCode(t, http.StatusBadRequest, rr)
|
||||||
assert.Contains(t, rr.Body.String(), "this passcode was already used")
|
assert.Contains(t, rr.Body.String(), "this passcode was already used")
|
||||||
|
|
||||||
adminTOTPConfig := dataprovider.TOTPConfig{
|
adminTOTPConfig := dataprovider.AdminTOTPConfig{
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
ConfigName: totpGenResp.ConfigName,
|
ConfigName: totpGenResp.ConfigName,
|
||||||
Secret: kms.NewPlainSecret(totpGenResp.Secret),
|
Secret: kms.NewPlainSecret(totpGenResp.Secret),
|
||||||
|
@ -5497,13 +5492,13 @@ func TestAdminTOTP(t *testing.T) {
|
||||||
assert.Empty(t, admin.Filters.TOTPConfig.Secret.GetKey())
|
assert.Empty(t, admin.Filters.TOTPConfig.Secret.GetKey())
|
||||||
assert.Empty(t, admin.Filters.TOTPConfig.Secret.GetAdditionalData())
|
assert.Empty(t, admin.Filters.TOTPConfig.Secret.GetAdditionalData())
|
||||||
assert.NotEmpty(t, admin.Filters.TOTPConfig.Secret.GetPayload())
|
assert.NotEmpty(t, admin.Filters.TOTPConfig.Secret.GetPayload())
|
||||||
assert.Equal(t, kms.SecretStatusSecretBox, admin.Filters.TOTPConfig.Secret.GetStatus())
|
assert.Equal(t, sdkkms.SecretStatusSecretBox, admin.Filters.TOTPConfig.Secret.GetStatus())
|
||||||
admin.Filters.TOTPConfig = dataprovider.TOTPConfig{
|
admin.Filters.TOTPConfig = dataprovider.AdminTOTPConfig{
|
||||||
Enabled: false,
|
Enabled: false,
|
||||||
ConfigName: util.GenerateUniqueID(),
|
ConfigName: util.GenerateUniqueID(),
|
||||||
Secret: kms.NewEmptySecret(),
|
Secret: kms.NewEmptySecret(),
|
||||||
}
|
}
|
||||||
admin.Filters.RecoveryCodes = []sdk.RecoveryCode{
|
admin.Filters.RecoveryCodes = []dataprovider.RecoveryCode{
|
||||||
{
|
{
|
||||||
Secret: kms.NewEmptySecret(),
|
Secret: kms.NewEmptySecret(),
|
||||||
},
|
},
|
||||||
|
@ -5655,7 +5650,7 @@ func TestWebUserTwoFactorLogin(t *testing.T) {
|
||||||
webToken, err := getJWTWebClientTokenFromTestServer(defaultUsername, defaultPassword)
|
webToken, err := getJWTWebClientTokenFromTestServer(defaultUsername, defaultPassword)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
userTOTPConfig := sdk.TOTPConfig{
|
userTOTPConfig := dataprovider.UserTOTPConfig{
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
ConfigName: configName,
|
ConfigName: configName,
|
||||||
Secret: kms.NewPlainSecret(secret),
|
Secret: kms.NewPlainSecret(secret),
|
||||||
|
@ -5685,7 +5680,7 @@ func TestWebUserTwoFactorLogin(t *testing.T) {
|
||||||
for _, c := range user.Filters.RecoveryCodes {
|
for _, c := range user.Filters.RecoveryCodes {
|
||||||
assert.Empty(t, c.Secret.GetAdditionalData())
|
assert.Empty(t, c.Secret.GetAdditionalData())
|
||||||
assert.Empty(t, c.Secret.GetKey())
|
assert.Empty(t, c.Secret.GetKey())
|
||||||
assert.Equal(t, kms.SecretStatusSecretBox, c.Secret.GetStatus())
|
assert.Equal(t, sdkkms.SecretStatusSecretBox, c.Secret.GetStatus())
|
||||||
assert.NotEmpty(t, c.Secret.GetPayload())
|
assert.NotEmpty(t, c.Secret.GetPayload())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6111,7 +6106,7 @@ func TestMFAErrors(t *testing.T) {
|
||||||
rr = executeRequest(req)
|
rr = executeRequest(req)
|
||||||
checkResponseCode(t, http.StatusBadRequest, rr)
|
checkResponseCode(t, http.StatusBadRequest, rr)
|
||||||
// invalid TOTP config name
|
// invalid TOTP config name
|
||||||
userTOTPConfig := sdk.TOTPConfig{
|
userTOTPConfig := dataprovider.UserTOTPConfig{
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
ConfigName: "missing name",
|
ConfigName: "missing name",
|
||||||
Secret: kms.NewPlainSecret(xid.New().String()),
|
Secret: kms.NewPlainSecret(xid.New().String()),
|
||||||
|
@ -6126,7 +6121,7 @@ func TestMFAErrors(t *testing.T) {
|
||||||
checkResponseCode(t, http.StatusBadRequest, rr)
|
checkResponseCode(t, http.StatusBadRequest, rr)
|
||||||
assert.Contains(t, rr.Body.String(), "totp: config name")
|
assert.Contains(t, rr.Body.String(), "totp: config name")
|
||||||
// invalid TOTP secret
|
// invalid TOTP secret
|
||||||
userTOTPConfig = sdk.TOTPConfig{
|
userTOTPConfig = dataprovider.UserTOTPConfig{
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
ConfigName: mfa.GetAvailableTOTPConfigNames()[0],
|
ConfigName: mfa.GetAvailableTOTPConfigNames()[0],
|
||||||
Secret: nil,
|
Secret: nil,
|
||||||
|
@ -6141,7 +6136,7 @@ func TestMFAErrors(t *testing.T) {
|
||||||
checkResponseCode(t, http.StatusBadRequest, rr)
|
checkResponseCode(t, http.StatusBadRequest, rr)
|
||||||
assert.Contains(t, rr.Body.String(), "totp: secret is mandatory")
|
assert.Contains(t, rr.Body.String(), "totp: secret is mandatory")
|
||||||
// no protocol
|
// no protocol
|
||||||
userTOTPConfig = sdk.TOTPConfig{
|
userTOTPConfig = dataprovider.UserTOTPConfig{
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
ConfigName: mfa.GetAvailableTOTPConfigNames()[0],
|
ConfigName: mfa.GetAvailableTOTPConfigNames()[0],
|
||||||
Secret: kms.NewPlainSecret(xid.New().String()),
|
Secret: kms.NewPlainSecret(xid.New().String()),
|
||||||
|
@ -6156,7 +6151,7 @@ func TestMFAErrors(t *testing.T) {
|
||||||
checkResponseCode(t, http.StatusBadRequest, rr)
|
checkResponseCode(t, http.StatusBadRequest, rr)
|
||||||
assert.Contains(t, rr.Body.String(), "totp: specify at least one protocol")
|
assert.Contains(t, rr.Body.String(), "totp: specify at least one protocol")
|
||||||
// invalid protocol
|
// invalid protocol
|
||||||
userTOTPConfig = sdk.TOTPConfig{
|
userTOTPConfig = dataprovider.UserTOTPConfig{
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
ConfigName: mfa.GetAvailableTOTPConfigNames()[0],
|
ConfigName: mfa.GetAvailableTOTPConfigNames()[0],
|
||||||
Secret: kms.NewPlainSecret(xid.New().String()),
|
Secret: kms.NewPlainSecret(xid.New().String()),
|
||||||
|
@ -6171,7 +6166,7 @@ func TestMFAErrors(t *testing.T) {
|
||||||
checkResponseCode(t, http.StatusBadRequest, rr)
|
checkResponseCode(t, http.StatusBadRequest, rr)
|
||||||
assert.Contains(t, rr.Body.String(), "totp: invalid protocol")
|
assert.Contains(t, rr.Body.String(), "totp: invalid protocol")
|
||||||
|
|
||||||
adminTOTPConfig := dataprovider.TOTPConfig{
|
adminTOTPConfig := dataprovider.AdminTOTPConfig{
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
ConfigName: "",
|
ConfigName: "",
|
||||||
Secret: kms.NewPlainSecret("secret"),
|
Secret: kms.NewPlainSecret("secret"),
|
||||||
|
@ -6185,7 +6180,7 @@ func TestMFAErrors(t *testing.T) {
|
||||||
checkResponseCode(t, http.StatusBadRequest, rr)
|
checkResponseCode(t, http.StatusBadRequest, rr)
|
||||||
assert.Contains(t, rr.Body.String(), "totp: config name is mandatory")
|
assert.Contains(t, rr.Body.String(), "totp: config name is mandatory")
|
||||||
|
|
||||||
adminTOTPConfig = dataprovider.TOTPConfig{
|
adminTOTPConfig = dataprovider.AdminTOTPConfig{
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
ConfigName: mfa.GetAvailableTOTPConfigNames()[0],
|
ConfigName: mfa.GetAvailableTOTPConfigNames()[0],
|
||||||
Secret: nil,
|
Secret: nil,
|
||||||
|
@ -6200,10 +6195,10 @@ func TestMFAErrors(t *testing.T) {
|
||||||
assert.Contains(t, rr.Body.String(), "totp: secret is mandatory")
|
assert.Contains(t, rr.Body.String(), "totp: secret is mandatory")
|
||||||
|
|
||||||
// invalid TOTP secret status
|
// invalid TOTP secret status
|
||||||
userTOTPConfig = sdk.TOTPConfig{
|
userTOTPConfig = dataprovider.UserTOTPConfig{
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
ConfigName: mfa.GetAvailableTOTPConfigNames()[0],
|
ConfigName: mfa.GetAvailableTOTPConfigNames()[0],
|
||||||
Secret: kms.NewSecret(kms.SecretStatusRedacted, "", "", ""),
|
Secret: kms.NewSecret(sdkkms.SecretStatusRedacted, "", "", ""),
|
||||||
Protocols: []string{common.ProtocolSSH},
|
Protocols: []string{common.ProtocolSSH},
|
||||||
}
|
}
|
||||||
asJSON, err = json.Marshal(userTOTPConfig)
|
asJSON, err = json.Marshal(userTOTPConfig)
|
||||||
|
@ -6237,15 +6232,15 @@ func TestMFAInvalidSecret(t *testing.T) {
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
user.Password = defaultPassword
|
user.Password = defaultPassword
|
||||||
user.Filters.TOTPConfig = sdk.TOTPConfig{
|
user.Filters.TOTPConfig = dataprovider.UserTOTPConfig{
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
ConfigName: mfa.GetAvailableTOTPConfigNames()[0],
|
ConfigName: mfa.GetAvailableTOTPConfigNames()[0],
|
||||||
Secret: kms.NewSecret(kms.SecretStatusSecretBox, "payload", "key", user.Username),
|
Secret: kms.NewSecret(sdkkms.SecretStatusSecretBox, "payload", "key", user.Username),
|
||||||
Protocols: []string{common.ProtocolSSH, common.ProtocolHTTP},
|
Protocols: []string{common.ProtocolSSH, common.ProtocolHTTP},
|
||||||
}
|
}
|
||||||
user.Filters.RecoveryCodes = append(user.Filters.RecoveryCodes, sdk.RecoveryCode{
|
user.Filters.RecoveryCodes = append(user.Filters.RecoveryCodes, dataprovider.RecoveryCode{
|
||||||
Used: false,
|
Used: false,
|
||||||
Secret: kms.NewSecret(kms.SecretStatusSecretBox, "payload", "key", user.Username),
|
Secret: kms.NewSecret(sdkkms.SecretStatusSecretBox, "payload", "key", user.Username),
|
||||||
})
|
})
|
||||||
err = dataprovider.UpdateUser(&user, "", "")
|
err = dataprovider.UpdateUser(&user, "", "")
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
@ -6310,14 +6305,14 @@ func TestMFAInvalidSecret(t *testing.T) {
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
admin.Password = altAdminPassword
|
admin.Password = altAdminPassword
|
||||||
admin.Filters.TOTPConfig = dataprovider.TOTPConfig{
|
admin.Filters.TOTPConfig = dataprovider.AdminTOTPConfig{
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
ConfigName: mfa.GetAvailableTOTPConfigNames()[0],
|
ConfigName: mfa.GetAvailableTOTPConfigNames()[0],
|
||||||
Secret: kms.NewSecret(kms.SecretStatusSecretBox, "payload", "key", user.Username),
|
Secret: kms.NewSecret(sdkkms.SecretStatusSecretBox, "payload", "key", user.Username),
|
||||||
}
|
}
|
||||||
admin.Filters.RecoveryCodes = append(user.Filters.RecoveryCodes, sdk.RecoveryCode{
|
admin.Filters.RecoveryCodes = append(user.Filters.RecoveryCodes, dataprovider.RecoveryCode{
|
||||||
Used: false,
|
Used: false,
|
||||||
Secret: kms.NewSecret(kms.SecretStatusSecretBox, "payload", "key", user.Username),
|
Secret: kms.NewSecret(sdkkms.SecretStatusSecretBox, "payload", "key", user.Username),
|
||||||
})
|
})
|
||||||
err = dataprovider.UpdateAdmin(&admin, "", "")
|
err = dataprovider.UpdateAdmin(&admin, "", "")
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
@ -6370,7 +6365,7 @@ func TestMFAInvalidSecret(t *testing.T) {
|
||||||
func TestWebUserTOTP(t *testing.T) {
|
func TestWebUserTOTP(t *testing.T) {
|
||||||
u := getTestUser()
|
u := getTestUser()
|
||||||
// TOTPConfig will be ignored on add
|
// TOTPConfig will be ignored on add
|
||||||
u.Filters.TOTPConfig = sdk.TOTPConfig{
|
u.Filters.TOTPConfig = dataprovider.UserTOTPConfig{
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
ConfigName: "",
|
ConfigName: "",
|
||||||
Secret: kms.NewEmptySecret(),
|
Secret: kms.NewEmptySecret(),
|
||||||
|
@ -6430,7 +6425,7 @@ func TestWebUserTOTP(t *testing.T) {
|
||||||
checkResponseCode(t, http.StatusBadRequest, rr)
|
checkResponseCode(t, http.StatusBadRequest, rr)
|
||||||
assert.Contains(t, rr.Body.String(), "this passcode was already used")
|
assert.Contains(t, rr.Body.String(), "this passcode was already used")
|
||||||
|
|
||||||
userTOTPConfig := sdk.TOTPConfig{
|
userTOTPConfig := dataprovider.UserTOTPConfig{
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
ConfigName: totpGenResp.ConfigName,
|
ConfigName: totpGenResp.ConfigName,
|
||||||
Secret: kms.NewPlainSecret(totpGenResp.Secret),
|
Secret: kms.NewPlainSecret(totpGenResp.Secret),
|
||||||
|
@ -6453,11 +6448,11 @@ func TestWebUserTOTP(t *testing.T) {
|
||||||
assert.Empty(t, totpCfg.Secret.GetKey())
|
assert.Empty(t, totpCfg.Secret.GetKey())
|
||||||
assert.Empty(t, totpCfg.Secret.GetAdditionalData())
|
assert.Empty(t, totpCfg.Secret.GetAdditionalData())
|
||||||
assert.NotEmpty(t, secretPayload)
|
assert.NotEmpty(t, secretPayload)
|
||||||
assert.Equal(t, kms.SecretStatusSecretBox, totpCfg.Secret.GetStatus())
|
assert.Equal(t, sdkkms.SecretStatusSecretBox, totpCfg.Secret.GetStatus())
|
||||||
assert.Len(t, totpCfg.Protocols, 1)
|
assert.Len(t, totpCfg.Protocols, 1)
|
||||||
assert.Contains(t, totpCfg.Protocols, common.ProtocolSSH)
|
assert.Contains(t, totpCfg.Protocols, common.ProtocolSSH)
|
||||||
// update protocols only
|
// update protocols only
|
||||||
userTOTPConfig = sdk.TOTPConfig{
|
userTOTPConfig = dataprovider.UserTOTPConfig{
|
||||||
Protocols: []string{common.ProtocolSSH, common.ProtocolFTP},
|
Protocols: []string{common.ProtocolSSH, common.ProtocolFTP},
|
||||||
Secret: kms.NewEmptySecret(),
|
Secret: kms.NewEmptySecret(),
|
||||||
}
|
}
|
||||||
|
@ -6470,7 +6465,7 @@ func TestWebUserTOTP(t *testing.T) {
|
||||||
checkResponseCode(t, http.StatusOK, rr)
|
checkResponseCode(t, http.StatusOK, rr)
|
||||||
|
|
||||||
// update the user, TOTP should not be affected
|
// update the user, TOTP should not be affected
|
||||||
user.Filters.TOTPConfig = sdk.TOTPConfig{
|
user.Filters.TOTPConfig = dataprovider.UserTOTPConfig{
|
||||||
Enabled: false,
|
Enabled: false,
|
||||||
Secret: kms.NewEmptySecret(),
|
Secret: kms.NewEmptySecret(),
|
||||||
}
|
}
|
||||||
|
@ -6484,7 +6479,7 @@ func TestWebUserTOTP(t *testing.T) {
|
||||||
assert.Empty(t, user.Filters.TOTPConfig.Secret.GetKey())
|
assert.Empty(t, user.Filters.TOTPConfig.Secret.GetKey())
|
||||||
assert.Empty(t, user.Filters.TOTPConfig.Secret.GetAdditionalData())
|
assert.Empty(t, user.Filters.TOTPConfig.Secret.GetAdditionalData())
|
||||||
assert.Equal(t, secretPayload, user.Filters.TOTPConfig.Secret.GetPayload())
|
assert.Equal(t, secretPayload, user.Filters.TOTPConfig.Secret.GetPayload())
|
||||||
assert.Equal(t, kms.SecretStatusSecretBox, user.Filters.TOTPConfig.Secret.GetStatus())
|
assert.Equal(t, sdkkms.SecretStatusSecretBox, user.Filters.TOTPConfig.Secret.GetStatus())
|
||||||
assert.Len(t, user.Filters.TOTPConfig.Protocols, 2)
|
assert.Len(t, user.Filters.TOTPConfig.Protocols, 2)
|
||||||
assert.Contains(t, user.Filters.TOTPConfig.Protocols, common.ProtocolSSH)
|
assert.Contains(t, user.Filters.TOTPConfig.Protocols, common.ProtocolSSH)
|
||||||
assert.Contains(t, user.Filters.TOTPConfig.Protocols, common.ProtocolFTP)
|
assert.Contains(t, user.Filters.TOTPConfig.Protocols, common.ProtocolFTP)
|
||||||
|
@ -8520,21 +8515,21 @@ func TestSFTPLoopError(t *testing.T) {
|
||||||
user1.FsConfig = vfs.Filesystem{
|
user1.FsConfig = vfs.Filesystem{
|
||||||
Provider: sdk.SFTPFilesystemProvider,
|
Provider: sdk.SFTPFilesystemProvider,
|
||||||
SFTPConfig: vfs.SFTPFsConfig{
|
SFTPConfig: vfs.SFTPFsConfig{
|
||||||
SFTPFsConfig: sdk.SFTPFsConfig{
|
BaseSFTPFsConfig: sdk.BaseSFTPFsConfig{
|
||||||
Endpoint: sftpServerAddr,
|
Endpoint: sftpServerAddr,
|
||||||
Username: user2.Username,
|
Username: user2.Username,
|
||||||
Password: kms.NewPlainSecret(defaultPassword),
|
|
||||||
},
|
},
|
||||||
|
Password: kms.NewPlainSecret(defaultPassword),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
user2.FsConfig.Provider = sdk.SFTPFilesystemProvider
|
user2.FsConfig.Provider = sdk.SFTPFilesystemProvider
|
||||||
user2.FsConfig.SFTPConfig = vfs.SFTPFsConfig{
|
user2.FsConfig.SFTPConfig = vfs.SFTPFsConfig{
|
||||||
SFTPFsConfig: sdk.SFTPFsConfig{
|
BaseSFTPFsConfig: sdk.BaseSFTPFsConfig{
|
||||||
Endpoint: sftpServerAddr,
|
Endpoint: sftpServerAddr,
|
||||||
Username: user1.Username,
|
Username: user1.Username,
|
||||||
Password: kms.NewPlainSecret(defaultPassword),
|
|
||||||
},
|
},
|
||||||
|
Password: kms.NewPlainSecret(defaultPassword),
|
||||||
}
|
}
|
||||||
|
|
||||||
user1, resp, err := httpdtest.AddUser(user1, http.StatusCreated)
|
user1, resp, err := httpdtest.AddUser(user1, http.StatusCreated)
|
||||||
|
@ -12644,7 +12639,7 @@ func TestWebAdminBasicMock(t *testing.T) {
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
altToken, err := getJWTWebTokenFromTestServer(altAdminUsername, altAdminPassword)
|
altToken, err := getJWTWebTokenFromTestServer(altAdminUsername, altAdminPassword)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
adminTOTPConfig := dataprovider.TOTPConfig{
|
adminTOTPConfig := dataprovider.AdminTOTPConfig{
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
ConfigName: configName,
|
ConfigName: configName,
|
||||||
Secret: kms.NewPlainSecret(secret),
|
Secret: kms.NewPlainSecret(secret),
|
||||||
|
@ -12672,7 +12667,7 @@ func TestWebAdminBasicMock(t *testing.T) {
|
||||||
secretPayload := admin.Filters.TOTPConfig.Secret.GetPayload()
|
secretPayload := admin.Filters.TOTPConfig.Secret.GetPayload()
|
||||||
assert.NotEmpty(t, secretPayload)
|
assert.NotEmpty(t, secretPayload)
|
||||||
|
|
||||||
adminTOTPConfig = dataprovider.TOTPConfig{
|
adminTOTPConfig = dataprovider.AdminTOTPConfig{
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
ConfigName: configName,
|
ConfigName: configName,
|
||||||
Secret: kms.NewEmptySecret(),
|
Secret: kms.NewEmptySecret(),
|
||||||
|
@ -12691,7 +12686,7 @@ func TestWebAdminBasicMock(t *testing.T) {
|
||||||
assert.True(t, admin.Filters.TOTPConfig.Enabled)
|
assert.True(t, admin.Filters.TOTPConfig.Enabled)
|
||||||
assert.Equal(t, secretPayload, admin.Filters.TOTPConfig.Secret.GetPayload())
|
assert.Equal(t, secretPayload, admin.Filters.TOTPConfig.Secret.GetPayload())
|
||||||
|
|
||||||
adminTOTPConfig = dataprovider.TOTPConfig{
|
adminTOTPConfig = dataprovider.AdminTOTPConfig{
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
ConfigName: configName,
|
ConfigName: configName,
|
||||||
Secret: nil,
|
Secret: nil,
|
||||||
|
@ -13374,7 +13369,7 @@ func TestWebUserUpdateMock(t *testing.T) {
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
userToken, err := getJWTWebClientTokenFromTestServer(defaultUsername, defaultPassword)
|
userToken, err := getJWTWebClientTokenFromTestServer(defaultUsername, defaultPassword)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
userTOTPConfig := sdk.TOTPConfig{
|
userTOTPConfig := dataprovider.UserTOTPConfig{
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
ConfigName: configName,
|
ConfigName: configName,
|
||||||
Secret: kms.NewPlainSecret(secret),
|
Secret: kms.NewPlainSecret(secret),
|
||||||
|
@ -14131,7 +14126,7 @@ func TestWebUserS3Mock(t *testing.T) {
|
||||||
assert.Equal(t, updateUser.FsConfig.S3Config.DownloadConcurrency, user.FsConfig.S3Config.DownloadConcurrency)
|
assert.Equal(t, updateUser.FsConfig.S3Config.DownloadConcurrency, user.FsConfig.S3Config.DownloadConcurrency)
|
||||||
assert.True(t, updateUser.FsConfig.S3Config.ForcePathStyle)
|
assert.True(t, updateUser.FsConfig.S3Config.ForcePathStyle)
|
||||||
assert.Equal(t, 2, len(updateUser.Filters.FilePatterns))
|
assert.Equal(t, 2, len(updateUser.Filters.FilePatterns))
|
||||||
assert.Equal(t, kms.SecretStatusSecretBox, updateUser.FsConfig.S3Config.AccessSecret.GetStatus())
|
assert.Equal(t, sdkkms.SecretStatusSecretBox, updateUser.FsConfig.S3Config.AccessSecret.GetStatus())
|
||||||
assert.NotEmpty(t, updateUser.FsConfig.S3Config.AccessSecret.GetPayload())
|
assert.NotEmpty(t, updateUser.FsConfig.S3Config.AccessSecret.GetPayload())
|
||||||
assert.Empty(t, updateUser.FsConfig.S3Config.AccessSecret.GetKey())
|
assert.Empty(t, updateUser.FsConfig.S3Config.AccessSecret.GetKey())
|
||||||
assert.Empty(t, updateUser.FsConfig.S3Config.AccessSecret.GetAdditionalData())
|
assert.Empty(t, updateUser.FsConfig.S3Config.AccessSecret.GetAdditionalData())
|
||||||
|
@ -14157,7 +14152,7 @@ func TestWebUserS3Mock(t *testing.T) {
|
||||||
var lastUpdatedUser dataprovider.User
|
var lastUpdatedUser dataprovider.User
|
||||||
err = render.DecodeJSON(rr.Body, &lastUpdatedUser)
|
err = render.DecodeJSON(rr.Body, &lastUpdatedUser)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, kms.SecretStatusSecretBox, lastUpdatedUser.FsConfig.S3Config.AccessSecret.GetStatus())
|
assert.Equal(t, sdkkms.SecretStatusSecretBox, lastUpdatedUser.FsConfig.S3Config.AccessSecret.GetStatus())
|
||||||
assert.Equal(t, updateUser.FsConfig.S3Config.AccessSecret.GetPayload(), lastUpdatedUser.FsConfig.S3Config.AccessSecret.GetPayload())
|
assert.Equal(t, updateUser.FsConfig.S3Config.AccessSecret.GetPayload(), lastUpdatedUser.FsConfig.S3Config.AccessSecret.GetPayload())
|
||||||
assert.Empty(t, lastUpdatedUser.FsConfig.S3Config.AccessSecret.GetKey())
|
assert.Empty(t, lastUpdatedUser.FsConfig.S3Config.AccessSecret.GetKey())
|
||||||
assert.Empty(t, lastUpdatedUser.FsConfig.S3Config.AccessSecret.GetAdditionalData())
|
assert.Empty(t, lastUpdatedUser.FsConfig.S3Config.AccessSecret.GetAdditionalData())
|
||||||
|
@ -14392,7 +14387,7 @@ func TestWebUserAzureBlobMock(t *testing.T) {
|
||||||
assert.Equal(t, updateUser.FsConfig.AzBlobConfig.UploadPartSize, user.FsConfig.AzBlobConfig.UploadPartSize)
|
assert.Equal(t, updateUser.FsConfig.AzBlobConfig.UploadPartSize, user.FsConfig.AzBlobConfig.UploadPartSize)
|
||||||
assert.Equal(t, updateUser.FsConfig.AzBlobConfig.UploadConcurrency, user.FsConfig.AzBlobConfig.UploadConcurrency)
|
assert.Equal(t, updateUser.FsConfig.AzBlobConfig.UploadConcurrency, user.FsConfig.AzBlobConfig.UploadConcurrency)
|
||||||
assert.Equal(t, 2, len(updateUser.Filters.FilePatterns))
|
assert.Equal(t, 2, len(updateUser.Filters.FilePatterns))
|
||||||
assert.Equal(t, kms.SecretStatusSecretBox, updateUser.FsConfig.AzBlobConfig.AccountKey.GetStatus())
|
assert.Equal(t, sdkkms.SecretStatusSecretBox, updateUser.FsConfig.AzBlobConfig.AccountKey.GetStatus())
|
||||||
assert.NotEmpty(t, updateUser.FsConfig.AzBlobConfig.AccountKey.GetPayload())
|
assert.NotEmpty(t, updateUser.FsConfig.AzBlobConfig.AccountKey.GetPayload())
|
||||||
assert.Empty(t, updateUser.FsConfig.AzBlobConfig.AccountKey.GetKey())
|
assert.Empty(t, updateUser.FsConfig.AzBlobConfig.AccountKey.GetKey())
|
||||||
assert.Empty(t, updateUser.FsConfig.AzBlobConfig.AccountKey.GetAdditionalData())
|
assert.Empty(t, updateUser.FsConfig.AzBlobConfig.AccountKey.GetAdditionalData())
|
||||||
|
@ -14411,7 +14406,7 @@ func TestWebUserAzureBlobMock(t *testing.T) {
|
||||||
var lastUpdatedUser dataprovider.User
|
var lastUpdatedUser dataprovider.User
|
||||||
err = render.DecodeJSON(rr.Body, &lastUpdatedUser)
|
err = render.DecodeJSON(rr.Body, &lastUpdatedUser)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, kms.SecretStatusSecretBox, lastUpdatedUser.FsConfig.AzBlobConfig.AccountKey.GetStatus())
|
assert.Equal(t, sdkkms.SecretStatusSecretBox, lastUpdatedUser.FsConfig.AzBlobConfig.AccountKey.GetStatus())
|
||||||
assert.Equal(t, updateUser.FsConfig.AzBlobConfig.AccountKey.GetPayload(), lastUpdatedUser.FsConfig.AzBlobConfig.AccountKey.GetPayload())
|
assert.Equal(t, updateUser.FsConfig.AzBlobConfig.AccountKey.GetPayload(), lastUpdatedUser.FsConfig.AzBlobConfig.AccountKey.GetPayload())
|
||||||
assert.Empty(t, lastUpdatedUser.FsConfig.AzBlobConfig.AccountKey.GetKey())
|
assert.Empty(t, lastUpdatedUser.FsConfig.AzBlobConfig.AccountKey.GetKey())
|
||||||
assert.Empty(t, lastUpdatedUser.FsConfig.AzBlobConfig.AccountKey.GetAdditionalData())
|
assert.Empty(t, lastUpdatedUser.FsConfig.AzBlobConfig.AccountKey.GetAdditionalData())
|
||||||
|
@ -14434,7 +14429,7 @@ func TestWebUserAzureBlobMock(t *testing.T) {
|
||||||
updateUser = dataprovider.User{}
|
updateUser = dataprovider.User{}
|
||||||
err = render.DecodeJSON(rr.Body, &updateUser)
|
err = render.DecodeJSON(rr.Body, &updateUser)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, kms.SecretStatusSecretBox, updateUser.FsConfig.AzBlobConfig.SASURL.GetStatus())
|
assert.Equal(t, sdkkms.SecretStatusSecretBox, updateUser.FsConfig.AzBlobConfig.SASURL.GetStatus())
|
||||||
assert.NotEmpty(t, updateUser.FsConfig.AzBlobConfig.SASURL.GetPayload())
|
assert.NotEmpty(t, updateUser.FsConfig.AzBlobConfig.SASURL.GetPayload())
|
||||||
assert.Empty(t, updateUser.FsConfig.AzBlobConfig.SASURL.GetKey())
|
assert.Empty(t, updateUser.FsConfig.AzBlobConfig.SASURL.GetKey())
|
||||||
assert.Empty(t, updateUser.FsConfig.AzBlobConfig.SASURL.GetAdditionalData())
|
assert.Empty(t, updateUser.FsConfig.AzBlobConfig.SASURL.GetAdditionalData())
|
||||||
|
@ -14453,7 +14448,7 @@ func TestWebUserAzureBlobMock(t *testing.T) {
|
||||||
lastUpdatedUser = dataprovider.User{}
|
lastUpdatedUser = dataprovider.User{}
|
||||||
err = render.DecodeJSON(rr.Body, &lastUpdatedUser)
|
err = render.DecodeJSON(rr.Body, &lastUpdatedUser)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, kms.SecretStatusSecretBox, lastUpdatedUser.FsConfig.AzBlobConfig.SASURL.GetStatus())
|
assert.Equal(t, sdkkms.SecretStatusSecretBox, lastUpdatedUser.FsConfig.AzBlobConfig.SASURL.GetStatus())
|
||||||
assert.Equal(t, updateUser.FsConfig.AzBlobConfig.SASURL.GetPayload(), lastUpdatedUser.FsConfig.AzBlobConfig.SASURL.GetPayload())
|
assert.Equal(t, updateUser.FsConfig.AzBlobConfig.SASURL.GetPayload(), lastUpdatedUser.FsConfig.AzBlobConfig.SASURL.GetPayload())
|
||||||
assert.Empty(t, lastUpdatedUser.FsConfig.AzBlobConfig.SASURL.GetKey())
|
assert.Empty(t, lastUpdatedUser.FsConfig.AzBlobConfig.SASURL.GetKey())
|
||||||
assert.Empty(t, lastUpdatedUser.FsConfig.AzBlobConfig.SASURL.GetAdditionalData())
|
assert.Empty(t, lastUpdatedUser.FsConfig.AzBlobConfig.SASURL.GetAdditionalData())
|
||||||
|
@ -14530,7 +14525,7 @@ func TestWebUserCryptMock(t *testing.T) {
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, int64(1577836800000), updateUser.ExpirationDate)
|
assert.Equal(t, int64(1577836800000), updateUser.ExpirationDate)
|
||||||
assert.Equal(t, 2, len(updateUser.Filters.FilePatterns))
|
assert.Equal(t, 2, len(updateUser.Filters.FilePatterns))
|
||||||
assert.Equal(t, kms.SecretStatusSecretBox, updateUser.FsConfig.CryptConfig.Passphrase.GetStatus())
|
assert.Equal(t, sdkkms.SecretStatusSecretBox, updateUser.FsConfig.CryptConfig.Passphrase.GetStatus())
|
||||||
assert.NotEmpty(t, updateUser.FsConfig.CryptConfig.Passphrase.GetPayload())
|
assert.NotEmpty(t, updateUser.FsConfig.CryptConfig.Passphrase.GetPayload())
|
||||||
assert.Empty(t, updateUser.FsConfig.CryptConfig.Passphrase.GetKey())
|
assert.Empty(t, updateUser.FsConfig.CryptConfig.Passphrase.GetKey())
|
||||||
assert.Empty(t, updateUser.FsConfig.CryptConfig.Passphrase.GetAdditionalData())
|
assert.Empty(t, updateUser.FsConfig.CryptConfig.Passphrase.GetAdditionalData())
|
||||||
|
@ -14549,7 +14544,7 @@ func TestWebUserCryptMock(t *testing.T) {
|
||||||
var lastUpdatedUser dataprovider.User
|
var lastUpdatedUser dataprovider.User
|
||||||
err = render.DecodeJSON(rr.Body, &lastUpdatedUser)
|
err = render.DecodeJSON(rr.Body, &lastUpdatedUser)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, kms.SecretStatusSecretBox, lastUpdatedUser.FsConfig.CryptConfig.Passphrase.GetStatus())
|
assert.Equal(t, sdkkms.SecretStatusSecretBox, lastUpdatedUser.FsConfig.CryptConfig.Passphrase.GetStatus())
|
||||||
assert.Equal(t, updateUser.FsConfig.CryptConfig.Passphrase.GetPayload(), lastUpdatedUser.FsConfig.CryptConfig.Passphrase.GetPayload())
|
assert.Equal(t, updateUser.FsConfig.CryptConfig.Passphrase.GetPayload(), lastUpdatedUser.FsConfig.CryptConfig.Passphrase.GetPayload())
|
||||||
assert.Empty(t, lastUpdatedUser.FsConfig.CryptConfig.Passphrase.GetKey())
|
assert.Empty(t, lastUpdatedUser.FsConfig.CryptConfig.Passphrase.GetKey())
|
||||||
assert.Empty(t, lastUpdatedUser.FsConfig.CryptConfig.Passphrase.GetAdditionalData())
|
assert.Empty(t, lastUpdatedUser.FsConfig.CryptConfig.Passphrase.GetAdditionalData())
|
||||||
|
@ -14639,11 +14634,11 @@ func TestWebUserSFTPFsMock(t *testing.T) {
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, int64(1577836800000), updateUser.ExpirationDate)
|
assert.Equal(t, int64(1577836800000), updateUser.ExpirationDate)
|
||||||
assert.Equal(t, 2, len(updateUser.Filters.FilePatterns))
|
assert.Equal(t, 2, len(updateUser.Filters.FilePatterns))
|
||||||
assert.Equal(t, kms.SecretStatusSecretBox, updateUser.FsConfig.SFTPConfig.Password.GetStatus())
|
assert.Equal(t, sdkkms.SecretStatusSecretBox, updateUser.FsConfig.SFTPConfig.Password.GetStatus())
|
||||||
assert.NotEmpty(t, updateUser.FsConfig.SFTPConfig.Password.GetPayload())
|
assert.NotEmpty(t, updateUser.FsConfig.SFTPConfig.Password.GetPayload())
|
||||||
assert.Empty(t, updateUser.FsConfig.SFTPConfig.Password.GetKey())
|
assert.Empty(t, updateUser.FsConfig.SFTPConfig.Password.GetKey())
|
||||||
assert.Empty(t, updateUser.FsConfig.SFTPConfig.Password.GetAdditionalData())
|
assert.Empty(t, updateUser.FsConfig.SFTPConfig.Password.GetAdditionalData())
|
||||||
assert.Equal(t, kms.SecretStatusSecretBox, updateUser.FsConfig.SFTPConfig.PrivateKey.GetStatus())
|
assert.Equal(t, sdkkms.SecretStatusSecretBox, updateUser.FsConfig.SFTPConfig.PrivateKey.GetStatus())
|
||||||
assert.NotEmpty(t, updateUser.FsConfig.SFTPConfig.PrivateKey.GetPayload())
|
assert.NotEmpty(t, updateUser.FsConfig.SFTPConfig.PrivateKey.GetPayload())
|
||||||
assert.Empty(t, updateUser.FsConfig.SFTPConfig.PrivateKey.GetKey())
|
assert.Empty(t, updateUser.FsConfig.SFTPConfig.PrivateKey.GetKey())
|
||||||
assert.Empty(t, updateUser.FsConfig.SFTPConfig.PrivateKey.GetAdditionalData())
|
assert.Empty(t, updateUser.FsConfig.SFTPConfig.PrivateKey.GetAdditionalData())
|
||||||
|
@ -14670,11 +14665,11 @@ func TestWebUserSFTPFsMock(t *testing.T) {
|
||||||
var lastUpdatedUser dataprovider.User
|
var lastUpdatedUser dataprovider.User
|
||||||
err = render.DecodeJSON(rr.Body, &lastUpdatedUser)
|
err = render.DecodeJSON(rr.Body, &lastUpdatedUser)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, kms.SecretStatusSecretBox, lastUpdatedUser.FsConfig.SFTPConfig.Password.GetStatus())
|
assert.Equal(t, sdkkms.SecretStatusSecretBox, lastUpdatedUser.FsConfig.SFTPConfig.Password.GetStatus())
|
||||||
assert.Equal(t, updateUser.FsConfig.SFTPConfig.Password.GetPayload(), lastUpdatedUser.FsConfig.SFTPConfig.Password.GetPayload())
|
assert.Equal(t, updateUser.FsConfig.SFTPConfig.Password.GetPayload(), lastUpdatedUser.FsConfig.SFTPConfig.Password.GetPayload())
|
||||||
assert.Empty(t, lastUpdatedUser.FsConfig.SFTPConfig.Password.GetKey())
|
assert.Empty(t, lastUpdatedUser.FsConfig.SFTPConfig.Password.GetKey())
|
||||||
assert.Empty(t, lastUpdatedUser.FsConfig.SFTPConfig.Password.GetAdditionalData())
|
assert.Empty(t, lastUpdatedUser.FsConfig.SFTPConfig.Password.GetAdditionalData())
|
||||||
assert.Equal(t, kms.SecretStatusSecretBox, lastUpdatedUser.FsConfig.SFTPConfig.PrivateKey.GetStatus())
|
assert.Equal(t, sdkkms.SecretStatusSecretBox, lastUpdatedUser.FsConfig.SFTPConfig.PrivateKey.GetStatus())
|
||||||
assert.Equal(t, updateUser.FsConfig.SFTPConfig.PrivateKey.GetPayload(), lastUpdatedUser.FsConfig.SFTPConfig.PrivateKey.GetPayload())
|
assert.Equal(t, updateUser.FsConfig.SFTPConfig.PrivateKey.GetPayload(), lastUpdatedUser.FsConfig.SFTPConfig.PrivateKey.GetPayload())
|
||||||
assert.Empty(t, lastUpdatedUser.FsConfig.SFTPConfig.PrivateKey.GetKey())
|
assert.Empty(t, lastUpdatedUser.FsConfig.SFTPConfig.PrivateKey.GetKey())
|
||||||
assert.Empty(t, lastUpdatedUser.FsConfig.SFTPConfig.PrivateKey.GetAdditionalData())
|
assert.Empty(t, lastUpdatedUser.FsConfig.SFTPConfig.PrivateKey.GetAdditionalData())
|
||||||
|
|
|
@ -33,9 +33,9 @@ import (
|
||||||
|
|
||||||
"github.com/drakkan/sftpgo/v2/common"
|
"github.com/drakkan/sftpgo/v2/common"
|
||||||
"github.com/drakkan/sftpgo/v2/dataprovider"
|
"github.com/drakkan/sftpgo/v2/dataprovider"
|
||||||
|
"github.com/drakkan/sftpgo/v2/kms"
|
||||||
"github.com/drakkan/sftpgo/v2/plugin"
|
"github.com/drakkan/sftpgo/v2/plugin"
|
||||||
"github.com/drakkan/sftpgo/v2/sdk"
|
"github.com/drakkan/sftpgo/v2/sdk"
|
||||||
"github.com/drakkan/sftpgo/v2/sdk/kms"
|
|
||||||
"github.com/drakkan/sftpgo/v2/util"
|
"github.com/drakkan/sftpgo/v2/util"
|
||||||
"github.com/drakkan/sftpgo/v2/vfs"
|
"github.com/drakkan/sftpgo/v2/vfs"
|
||||||
)
|
)
|
||||||
|
@ -1773,10 +1773,10 @@ func TestConnection(t *testing.T) {
|
||||||
FsConfig: vfs.Filesystem{
|
FsConfig: vfs.Filesystem{
|
||||||
Provider: sdk.GCSFilesystemProvider,
|
Provider: sdk.GCSFilesystemProvider,
|
||||||
GCSConfig: vfs.GCSFsConfig{
|
GCSConfig: vfs.GCSFsConfig{
|
||||||
GCSFsConfig: sdk.GCSFsConfig{
|
BaseGCSFsConfig: sdk.BaseGCSFsConfig{
|
||||||
Bucket: "test_bucket_name",
|
Bucket: "test_bucket_name",
|
||||||
Credentials: kms.NewPlainSecret("invalid JSON payload"),
|
|
||||||
},
|
},
|
||||||
|
Credentials: kms.NewPlainSecret("invalid JSON payload"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -1815,12 +1815,12 @@ func TestGetFileWriterErrors(t *testing.T) {
|
||||||
|
|
||||||
user.FsConfig.Provider = sdk.S3FilesystemProvider
|
user.FsConfig.Provider = sdk.S3FilesystemProvider
|
||||||
user.FsConfig.S3Config = vfs.S3FsConfig{
|
user.FsConfig.S3Config = vfs.S3FsConfig{
|
||||||
S3FsConfig: sdk.S3FsConfig{
|
BaseS3FsConfig: sdk.BaseS3FsConfig{
|
||||||
Bucket: "b",
|
Bucket: "b",
|
||||||
Region: "us-west-1",
|
Region: "us-west-1",
|
||||||
AccessKey: "key",
|
AccessKey: "key",
|
||||||
AccessSecret: kms.NewPlainSecret("secret"),
|
|
||||||
},
|
},
|
||||||
|
AccessSecret: kms.NewPlainSecret("secret"),
|
||||||
}
|
}
|
||||||
connection = &Connection{
|
connection = &Connection{
|
||||||
BaseConnection: common.NewBaseConnection(xid.New().String(), common.ProtocolHTTP, "", "", user),
|
BaseConnection: common.NewBaseConnection(xid.New().String(), common.ProtocolHTTP, "", "", user),
|
||||||
|
|
|
@ -16,9 +16,10 @@ import (
|
||||||
|
|
||||||
"github.com/drakkan/sftpgo/v2/common"
|
"github.com/drakkan/sftpgo/v2/common"
|
||||||
"github.com/drakkan/sftpgo/v2/dataprovider"
|
"github.com/drakkan/sftpgo/v2/dataprovider"
|
||||||
|
"github.com/drakkan/sftpgo/v2/kms"
|
||||||
"github.com/drakkan/sftpgo/v2/mfa"
|
"github.com/drakkan/sftpgo/v2/mfa"
|
||||||
"github.com/drakkan/sftpgo/v2/sdk"
|
"github.com/drakkan/sftpgo/v2/sdk"
|
||||||
"github.com/drakkan/sftpgo/v2/sdk/kms"
|
sdkkms "github.com/drakkan/sftpgo/v2/sdk/kms"
|
||||||
"github.com/drakkan/sftpgo/v2/smtp"
|
"github.com/drakkan/sftpgo/v2/smtp"
|
||||||
"github.com/drakkan/sftpgo/v2/util"
|
"github.com/drakkan/sftpgo/v2/util"
|
||||||
"github.com/drakkan/sftpgo/v2/version"
|
"github.com/drakkan/sftpgo/v2/version"
|
||||||
|
@ -179,7 +180,7 @@ type changePasswordPage struct {
|
||||||
type mfaPage struct {
|
type mfaPage struct {
|
||||||
basePage
|
basePage
|
||||||
TOTPConfigs []string
|
TOTPConfigs []string
|
||||||
TOTPConfig dataprovider.TOTPConfig
|
TOTPConfig dataprovider.AdminTOTPConfig
|
||||||
GenerateTOTPURL string
|
GenerateTOTPURL string
|
||||||
ValidateTOTPURL string
|
ValidateTOTPURL string
|
||||||
SaveTOTPURL string
|
SaveTOTPURL string
|
||||||
|
@ -821,8 +822,8 @@ func getFilePatternsFromPostField(r *http.Request) []sdk.PatternsFilter {
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
func getFiltersFromUserPostFields(r *http.Request) (sdk.UserFilters, error) {
|
func getFiltersFromUserPostFields(r *http.Request) (sdk.BaseUserFilters, error) {
|
||||||
var filters sdk.UserFilters
|
var filters sdk.BaseUserFilters
|
||||||
bwLimits, err := getBandwidthLimitsFromPostFields(r)
|
bwLimits, err := getBandwidthLimitsFromPostFields(r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return filters, err
|
return filters, err
|
||||||
|
@ -853,7 +854,7 @@ func getFiltersFromUserPostFields(r *http.Request) (sdk.UserFilters, error) {
|
||||||
func getSecretFromFormField(r *http.Request, field string) *kms.Secret {
|
func getSecretFromFormField(r *http.Request, field string) *kms.Secret {
|
||||||
secret := kms.NewPlainSecret(r.Form.Get(field))
|
secret := kms.NewPlainSecret(r.Form.Get(field))
|
||||||
if strings.TrimSpace(secret.GetPayload()) == redactedSecret {
|
if strings.TrimSpace(secret.GetPayload()) == redactedSecret {
|
||||||
secret.SetStatus(kms.SecretStatusRedacted)
|
secret.SetStatus(sdkkms.SecretStatusRedacted)
|
||||||
}
|
}
|
||||||
if strings.TrimSpace(secret.GetPayload()) == "" {
|
if strings.TrimSpace(secret.GetPayload()) == "" {
|
||||||
secret.SetStatus("")
|
secret.SetStatus("")
|
||||||
|
@ -1204,10 +1205,12 @@ func getUserFromPostFields(r *http.Request) (dataprovider.User, error) {
|
||||||
DownloadBandwidth: bandwidthDL,
|
DownloadBandwidth: bandwidthDL,
|
||||||
Status: status,
|
Status: status,
|
||||||
ExpirationDate: expirationDateMillis,
|
ExpirationDate: expirationDateMillis,
|
||||||
Filters: filters,
|
|
||||||
AdditionalInfo: r.Form.Get("additional_info"),
|
AdditionalInfo: r.Form.Get("additional_info"),
|
||||||
Description: r.Form.Get("description"),
|
Description: r.Form.Get("description"),
|
||||||
},
|
},
|
||||||
|
Filters: dataprovider.UserFilters{
|
||||||
|
BaseUserFilters: filters,
|
||||||
|
},
|
||||||
VirtualFolders: getVirtualFoldersFromPostFields(r),
|
VirtualFolders: getVirtualFoldersFromPostFields(r),
|
||||||
FsConfig: fsConfig,
|
FsConfig: fsConfig,
|
||||||
}
|
}
|
||||||
|
|
|
@ -158,7 +158,7 @@ type changeClientPasswordPage struct {
|
||||||
type clientMFAPage struct {
|
type clientMFAPage struct {
|
||||||
baseClientPage
|
baseClientPage
|
||||||
TOTPConfigs []string
|
TOTPConfigs []string
|
||||||
TOTPConfig sdk.TOTPConfig
|
TOTPConfig dataprovider.UserTOTPConfig
|
||||||
GenerateTOTPURL string
|
GenerateTOTPURL string
|
||||||
ValidateTOTPURL string
|
ValidateTOTPURL string
|
||||||
SaveTOTPURL string
|
SaveTOTPURL string
|
||||||
|
|
|
@ -20,7 +20,7 @@ import (
|
||||||
"github.com/drakkan/sftpgo/v2/dataprovider"
|
"github.com/drakkan/sftpgo/v2/dataprovider"
|
||||||
"github.com/drakkan/sftpgo/v2/httpclient"
|
"github.com/drakkan/sftpgo/v2/httpclient"
|
||||||
"github.com/drakkan/sftpgo/v2/httpd"
|
"github.com/drakkan/sftpgo/v2/httpd"
|
||||||
"github.com/drakkan/sftpgo/v2/sdk/kms"
|
"github.com/drakkan/sftpgo/v2/kms"
|
||||||
"github.com/drakkan/sftpgo/v2/util"
|
"github.com/drakkan/sftpgo/v2/util"
|
||||||
"github.com/drakkan/sftpgo/v2/version"
|
"github.com/drakkan/sftpgo/v2/version"
|
||||||
"github.com/drakkan/sftpgo/v2/vfs"
|
"github.com/drakkan/sftpgo/v2/vfs"
|
||||||
|
|
|
@ -1,17 +1,21 @@
|
||||||
package kms
|
package kms
|
||||||
|
|
||||||
|
import (
|
||||||
|
sdkkms "github.com/drakkan/sftpgo/v2/sdk/kms"
|
||||||
|
)
|
||||||
|
|
||||||
// BaseSecret defines the base struct shared among all the secret providers
|
// BaseSecret defines the base struct shared among all the secret providers
|
||||||
type BaseSecret struct {
|
type BaseSecret struct {
|
||||||
Status SecretStatus `json:"status,omitempty"`
|
Status sdkkms.SecretStatus `json:"status,omitempty"`
|
||||||
Payload string `json:"payload,omitempty"`
|
Payload string `json:"payload,omitempty"`
|
||||||
Key string `json:"key,omitempty"`
|
Key string `json:"key,omitempty"`
|
||||||
AdditionalData string `json:"additional_data,omitempty"`
|
AdditionalData string `json:"additional_data,omitempty"`
|
||||||
// 1 means encrypted using a master key
|
// 1 means encrypted using a master key
|
||||||
Mode int `json:"mode,omitempty"`
|
Mode int `json:"mode,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetStatus returns the secret's status
|
// GetStatus returns the secret's status
|
||||||
func (s *BaseSecret) GetStatus() SecretStatus {
|
func (s *BaseSecret) GetStatus() sdkkms.SecretStatus {
|
||||||
return s.Status
|
return s.Status
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,7 +50,7 @@ func (s *BaseSecret) SetAdditionalData(value string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetStatus sets the secret's status
|
// SetStatus sets the secret's status
|
||||||
func (s *BaseSecret) SetStatus(value SecretStatus) {
|
func (s *BaseSecret) SetStatus(value sdkkms.SecretStatus) {
|
||||||
s.Status = value
|
s.Status = value
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,8 @@ import (
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"errors"
|
"errors"
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
|
sdkkms "github.com/drakkan/sftpgo/v2/sdk/kms"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -19,7 +21,7 @@ type builtinSecret struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
RegisterSecretProvider(SchemeBuiltin, SecretStatusAES256GCM, newBuiltinSecret)
|
RegisterSecretProvider(sdkkms.SchemeBuiltin, sdkkms.SecretStatusAES256GCM, newBuiltinSecret)
|
||||||
}
|
}
|
||||||
|
|
||||||
func newBuiltinSecret(base BaseSecret, url, masterKey string) SecretProvider {
|
func newBuiltinSecret(base BaseSecret, url, masterKey string) SecretProvider {
|
||||||
|
@ -33,7 +35,7 @@ func (s *builtinSecret) Name() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *builtinSecret) IsEncrypted() bool {
|
func (s *builtinSecret) IsEncrypted() bool {
|
||||||
return s.Status == SecretStatusAES256GCM
|
return s.Status == sdkkms.SecretStatusAES256GCM
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *builtinSecret) deriveKey(key []byte) []byte {
|
func (s *builtinSecret) deriveKey(key []byte) []byte {
|
||||||
|
@ -52,7 +54,7 @@ func (s *builtinSecret) Encrypt() error {
|
||||||
return ErrInvalidSecret
|
return ErrInvalidSecret
|
||||||
}
|
}
|
||||||
switch s.Status {
|
switch s.Status {
|
||||||
case SecretStatusPlain:
|
case sdkkms.SecretStatusPlain:
|
||||||
key := make([]byte, 32)
|
key := make([]byte, 32)
|
||||||
if _, err := io.ReadFull(rand.Reader, key); err != nil {
|
if _, err := io.ReadFull(rand.Reader, key); err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -76,7 +78,7 @@ func (s *builtinSecret) Encrypt() error {
|
||||||
ciphertext := gcm.Seal(nonce, nonce, []byte(s.Payload), aad)
|
ciphertext := gcm.Seal(nonce, nonce, []byte(s.Payload), aad)
|
||||||
s.Key = hex.EncodeToString(key)
|
s.Key = hex.EncodeToString(key)
|
||||||
s.Payload = hex.EncodeToString(ciphertext)
|
s.Payload = hex.EncodeToString(ciphertext)
|
||||||
s.Status = SecretStatusAES256GCM
|
s.Status = sdkkms.SecretStatusAES256GCM
|
||||||
return nil
|
return nil
|
||||||
default:
|
default:
|
||||||
return ErrWrongSecretStatus
|
return ErrWrongSecretStatus
|
||||||
|
@ -85,7 +87,7 @@ func (s *builtinSecret) Encrypt() error {
|
||||||
|
|
||||||
func (s *builtinSecret) Decrypt() error {
|
func (s *builtinSecret) Decrypt() error {
|
||||||
switch s.Status {
|
switch s.Status {
|
||||||
case SecretStatusAES256GCM:
|
case sdkkms.SecretStatusAES256GCM:
|
||||||
encrypted, err := hex.DecodeString(s.Payload)
|
encrypted, err := hex.DecodeString(s.Payload)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -115,7 +117,7 @@ func (s *builtinSecret) Decrypt() error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
s.Status = SecretStatusPlain
|
s.Status = sdkkms.SecretStatusPlain
|
||||||
s.Payload = string(plaintext)
|
s.Payload = string(plaintext)
|
||||||
s.Key = ""
|
s.Key = ""
|
||||||
s.AdditionalData = ""
|
s.AdditionalData = ""
|
417
kms/kms.go
Normal file
417
kms/kms.go
Normal file
|
@ -0,0 +1,417 @@
|
||||||
|
// Package kms provides Key Management Services support
|
||||||
|
package kms
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"github.com/drakkan/sftpgo/v2/logger"
|
||||||
|
sdkkms "github.com/drakkan/sftpgo/v2/sdk/kms"
|
||||||
|
)
|
||||||
|
|
||||||
|
// SecretProvider defines the interface for a KMS secrets provider
|
||||||
|
type SecretProvider interface {
|
||||||
|
Name() string
|
||||||
|
Encrypt() error
|
||||||
|
Decrypt() error
|
||||||
|
IsEncrypted() bool
|
||||||
|
GetStatus() sdkkms.SecretStatus
|
||||||
|
GetPayload() string
|
||||||
|
GetKey() string
|
||||||
|
GetAdditionalData() string
|
||||||
|
GetMode() int
|
||||||
|
SetKey(string)
|
||||||
|
SetAdditionalData(string)
|
||||||
|
SetStatus(sdkkms.SecretStatus)
|
||||||
|
Clone() SecretProvider
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
logSender = "kms"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Configuration defines the KMS configuration
|
||||||
|
type Configuration struct {
|
||||||
|
Secrets Secrets `json:"secrets" mapstructure:"secrets"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Secrets define the KMS configuration for encryption/decryption
|
||||||
|
type Secrets struct {
|
||||||
|
URL string `json:"url" mapstructure:"url"`
|
||||||
|
MasterKeyPath string `json:"master_key_path" mapstructure:"master_key_path"`
|
||||||
|
MasterKeyString string `json:"master_key" mapstructure:"master_key"`
|
||||||
|
masterKey string
|
||||||
|
}
|
||||||
|
|
||||||
|
type registeredSecretProvider struct {
|
||||||
|
encryptedStatus sdkkms.SecretStatus
|
||||||
|
newFn func(base BaseSecret, url, masterKey string) SecretProvider
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
// ErrWrongSecretStatus defines the error to return if the secret status is not appropriate
|
||||||
|
// for the request operation
|
||||||
|
ErrWrongSecretStatus = errors.New("wrong secret status")
|
||||||
|
// ErrInvalidSecret defines the error to return if a secret is not valid
|
||||||
|
ErrInvalidSecret = errors.New("invalid secret")
|
||||||
|
validSecretStatuses = []string{sdkkms.SecretStatusPlain, sdkkms.SecretStatusAES256GCM, sdkkms.SecretStatusSecretBox,
|
||||||
|
sdkkms.SecretStatusVaultTransit, sdkkms.SecretStatusAWS, sdkkms.SecretStatusGCP, sdkkms.SecretStatusRedacted}
|
||||||
|
config Configuration
|
||||||
|
secretProviders = make(map[string]registeredSecretProvider)
|
||||||
|
)
|
||||||
|
|
||||||
|
// RegisterSecretProvider register a new secret provider
|
||||||
|
func RegisterSecretProvider(scheme string, encryptedStatus sdkkms.SecretStatus,
|
||||||
|
fn func(base BaseSecret, url, masterKey string) SecretProvider,
|
||||||
|
) {
|
||||||
|
secretProviders[scheme] = registeredSecretProvider{
|
||||||
|
encryptedStatus: encryptedStatus,
|
||||||
|
newFn: fn,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewSecret builds a new Secret using the provided arguments
|
||||||
|
func NewSecret(status sdkkms.SecretStatus, payload, key, data string) *Secret {
|
||||||
|
return config.newSecret(status, payload, key, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewEmptySecret returns an empty secret
|
||||||
|
func NewEmptySecret() *Secret {
|
||||||
|
return NewSecret("", "", "", "")
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewPlainSecret stores the give payload in a plain text secret
|
||||||
|
func NewPlainSecret(payload string) *Secret {
|
||||||
|
return NewSecret(sdkkms.SecretStatusPlain, payload, "", "")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize configures the KMS support
|
||||||
|
func (c *Configuration) Initialize() error {
|
||||||
|
if c.Secrets.MasterKeyString != "" {
|
||||||
|
c.Secrets.masterKey = c.Secrets.MasterKeyString
|
||||||
|
}
|
||||||
|
if c.Secrets.masterKey == "" && c.Secrets.MasterKeyPath != "" {
|
||||||
|
mKey, err := os.ReadFile(c.Secrets.MasterKeyPath)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
c.Secrets.masterKey = strings.TrimSpace(string(mKey))
|
||||||
|
}
|
||||||
|
config = *c
|
||||||
|
if config.Secrets.URL == "" {
|
||||||
|
config.Secrets.URL = sdkkms.SchemeLocal + "://"
|
||||||
|
}
|
||||||
|
for k, v := range secretProviders {
|
||||||
|
logger.Info(logSender, "", "secret provider registered for scheme: %#v, encrypted status: %#v",
|
||||||
|
k, v.encryptedStatus)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Configuration) newSecret(status sdkkms.SecretStatus, payload, key, data string) *Secret {
|
||||||
|
base := BaseSecret{
|
||||||
|
Status: status,
|
||||||
|
Key: key,
|
||||||
|
Payload: payload,
|
||||||
|
AdditionalData: data,
|
||||||
|
}
|
||||||
|
return &Secret{
|
||||||
|
provider: c.getSecretProvider(base),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Configuration) getSecretProvider(base BaseSecret) SecretProvider {
|
||||||
|
for k, v := range secretProviders {
|
||||||
|
if strings.HasPrefix(c.Secrets.URL, k) {
|
||||||
|
return v.newFn(base, c.Secrets.URL, c.Secrets.masterKey)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
logger.Warn(logSender, "", "no secret provider registered for URL %v, fallback to local provider", c.Secrets.URL)
|
||||||
|
return NewLocalSecret(base, c.Secrets.URL, c.Secrets.masterKey)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Secret defines the struct used to store confidential data
|
||||||
|
type Secret struct {
|
||||||
|
sync.RWMutex
|
||||||
|
provider SecretProvider
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarshalJSON return the JSON encoding of the Secret object
|
||||||
|
func (s *Secret) MarshalJSON() ([]byte, error) {
|
||||||
|
s.RLock()
|
||||||
|
defer s.RUnlock()
|
||||||
|
|
||||||
|
return json.Marshal(&BaseSecret{
|
||||||
|
Status: s.provider.GetStatus(),
|
||||||
|
Payload: s.provider.GetPayload(),
|
||||||
|
Key: s.provider.GetKey(),
|
||||||
|
AdditionalData: s.provider.GetAdditionalData(),
|
||||||
|
Mode: s.provider.GetMode(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalJSON parses the JSON-encoded data and stores the result
|
||||||
|
// in the Secret object
|
||||||
|
func (s *Secret) UnmarshalJSON(data []byte) error {
|
||||||
|
s.Lock()
|
||||||
|
defer s.Unlock()
|
||||||
|
|
||||||
|
baseSecret := BaseSecret{}
|
||||||
|
err := json.Unmarshal(data, &baseSecret)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if baseSecret.isEmpty() {
|
||||||
|
s.provider = config.getSecretProvider(baseSecret)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if baseSecret.Status == sdkkms.SecretStatusPlain || baseSecret.Status == sdkkms.SecretStatusRedacted {
|
||||||
|
s.provider = config.getSecretProvider(baseSecret)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, v := range secretProviders {
|
||||||
|
if v.encryptedStatus == baseSecret.Status {
|
||||||
|
s.provider = v.newFn(baseSecret, config.Secrets.URL, config.Secrets.masterKey)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
logger.Error(logSender, "", "no provider registered for status %#v", baseSecret.Status)
|
||||||
|
return ErrInvalidSecret
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsEqual returns true if all the secrets fields are equal
|
||||||
|
func (s *Secret) IsEqual(other *Secret) bool {
|
||||||
|
if s.GetStatus() != other.GetStatus() {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if s.GetPayload() != other.GetPayload() {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if s.GetKey() != other.GetKey() {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if s.GetAdditionalData() != other.GetAdditionalData() {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if s.GetMode() != other.GetMode() {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clone returns a copy of the secret object
|
||||||
|
func (s *Secret) Clone() *Secret {
|
||||||
|
s.RLock()
|
||||||
|
defer s.RUnlock()
|
||||||
|
|
||||||
|
return &Secret{
|
||||||
|
provider: s.provider.Clone(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsEncrypted returns true if the secret is encrypted
|
||||||
|
// This isn't a pointer receiver because we don't want to pass
|
||||||
|
// a pointer to html template
|
||||||
|
func (s *Secret) IsEncrypted() bool {
|
||||||
|
s.RLock()
|
||||||
|
defer s.RUnlock()
|
||||||
|
|
||||||
|
return s.provider.IsEncrypted()
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsPlain returns true if the secret is in plain text
|
||||||
|
func (s *Secret) IsPlain() bool {
|
||||||
|
s.RLock()
|
||||||
|
defer s.RUnlock()
|
||||||
|
|
||||||
|
return s.provider.GetStatus() == sdkkms.SecretStatusPlain
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsNotPlainAndNotEmpty returns true if the secret is not plain and not empty.
|
||||||
|
// This is an utility method, we update the secret for an existing user
|
||||||
|
// if it is empty or plain
|
||||||
|
func (s *Secret) IsNotPlainAndNotEmpty() bool {
|
||||||
|
s.RLock()
|
||||||
|
defer s.RUnlock()
|
||||||
|
|
||||||
|
return !s.IsPlain() && !s.IsEmpty()
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsRedacted returns true if the secret is redacted
|
||||||
|
func (s *Secret) IsRedacted() bool {
|
||||||
|
s.RLock()
|
||||||
|
defer s.RUnlock()
|
||||||
|
|
||||||
|
return s.provider.GetStatus() == sdkkms.SecretStatusRedacted
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetPayload returns the secret payload
|
||||||
|
func (s *Secret) GetPayload() string {
|
||||||
|
s.RLock()
|
||||||
|
defer s.RUnlock()
|
||||||
|
|
||||||
|
return s.provider.GetPayload()
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetAdditionalData returns the secret additional data
|
||||||
|
func (s *Secret) GetAdditionalData() string {
|
||||||
|
s.RLock()
|
||||||
|
defer s.RUnlock()
|
||||||
|
|
||||||
|
return s.provider.GetAdditionalData()
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetStatus returns the secret status
|
||||||
|
func (s *Secret) GetStatus() sdkkms.SecretStatus {
|
||||||
|
s.RLock()
|
||||||
|
defer s.RUnlock()
|
||||||
|
|
||||||
|
return s.provider.GetStatus()
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetKey returns the secret key
|
||||||
|
func (s *Secret) GetKey() string {
|
||||||
|
s.RLock()
|
||||||
|
defer s.RUnlock()
|
||||||
|
|
||||||
|
return s.provider.GetKey()
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetMode returns the secret mode
|
||||||
|
func (s *Secret) GetMode() int {
|
||||||
|
s.RLock()
|
||||||
|
defer s.RUnlock()
|
||||||
|
|
||||||
|
return s.provider.GetMode()
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetAdditionalData sets the given additional data
|
||||||
|
func (s *Secret) SetAdditionalData(value string) {
|
||||||
|
s.Lock()
|
||||||
|
defer s.Unlock()
|
||||||
|
|
||||||
|
s.provider.SetAdditionalData(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetStatus sets the status for this secret
|
||||||
|
func (s *Secret) SetStatus(value sdkkms.SecretStatus) {
|
||||||
|
s.Lock()
|
||||||
|
defer s.Unlock()
|
||||||
|
|
||||||
|
s.provider.SetStatus(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetKey sets the key for this secret
|
||||||
|
func (s *Secret) SetKey(value string) {
|
||||||
|
s.Lock()
|
||||||
|
defer s.Unlock()
|
||||||
|
|
||||||
|
s.provider.SetKey(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsEmpty returns true if all fields are empty
|
||||||
|
func (s *Secret) IsEmpty() bool {
|
||||||
|
s.RLock()
|
||||||
|
defer s.RUnlock()
|
||||||
|
|
||||||
|
if s.provider.GetStatus() != "" {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if s.provider.GetPayload() != "" {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if s.provider.GetKey() != "" {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if s.provider.GetAdditionalData() != "" {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsValid returns true if the secret is not empty and valid
|
||||||
|
func (s *Secret) IsValid() bool {
|
||||||
|
s.RLock()
|
||||||
|
defer s.RUnlock()
|
||||||
|
|
||||||
|
if !s.IsValidInput() {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
switch s.provider.GetStatus() {
|
||||||
|
case sdkkms.SecretStatusAES256GCM, sdkkms.SecretStatusSecretBox:
|
||||||
|
if len(s.provider.GetKey()) != 64 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
case sdkkms.SecretStatusAWS, sdkkms.SecretStatusGCP, sdkkms.SecretStatusVaultTransit:
|
||||||
|
key := s.provider.GetKey()
|
||||||
|
if key != "" && len(key) != 64 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsValidInput returns true if the secret is a valid user input
|
||||||
|
func (s *Secret) IsValidInput() bool {
|
||||||
|
s.RLock()
|
||||||
|
defer s.RUnlock()
|
||||||
|
|
||||||
|
if !isSecretStatusValid(s.provider.GetStatus()) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if s.provider.GetPayload() == "" {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hide hides info to decrypt data
|
||||||
|
func (s *Secret) Hide() {
|
||||||
|
s.Lock()
|
||||||
|
defer s.Unlock()
|
||||||
|
|
||||||
|
s.provider.SetKey("")
|
||||||
|
s.provider.SetAdditionalData("")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Encrypt encrypts a plain text Secret object
|
||||||
|
func (s *Secret) Encrypt() error {
|
||||||
|
s.Lock()
|
||||||
|
defer s.Unlock()
|
||||||
|
|
||||||
|
return s.provider.Encrypt()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decrypt decrypts a Secret object
|
||||||
|
func (s *Secret) Decrypt() error {
|
||||||
|
s.Lock()
|
||||||
|
defer s.Unlock()
|
||||||
|
|
||||||
|
return s.provider.Decrypt()
|
||||||
|
}
|
||||||
|
|
||||||
|
// TryDecrypt decrypts a Secret object if encrypted.
|
||||||
|
// It returns a nil error if the object is not encrypted
|
||||||
|
func (s *Secret) TryDecrypt() error {
|
||||||
|
s.Lock()
|
||||||
|
defer s.Unlock()
|
||||||
|
|
||||||
|
if s.provider.IsEncrypted() {
|
||||||
|
return s.provider.Decrypt()
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func isSecretStatusValid(status string) bool {
|
||||||
|
for idx := range validSecretStatuses {
|
||||||
|
if validSecretStatuses[idx] == status {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
|
@ -9,10 +9,12 @@ import (
|
||||||
|
|
||||||
"gocloud.dev/secrets/localsecrets"
|
"gocloud.dev/secrets/localsecrets"
|
||||||
"golang.org/x/crypto/hkdf"
|
"golang.org/x/crypto/hkdf"
|
||||||
|
|
||||||
|
sdkkms "github.com/drakkan/sftpgo/v2/sdk/kms"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
RegisterSecretProvider(SchemeLocal, SecretStatusSecretBox, NewLocalSecret)
|
RegisterSecretProvider(sdkkms.SchemeLocal, sdkkms.SecretStatusSecretBox, NewLocalSecret)
|
||||||
}
|
}
|
||||||
|
|
||||||
type localSecret struct {
|
type localSecret struct {
|
||||||
|
@ -33,11 +35,11 @@ func (s *localSecret) Name() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *localSecret) IsEncrypted() bool {
|
func (s *localSecret) IsEncrypted() bool {
|
||||||
return s.Status == SecretStatusSecretBox
|
return s.Status == sdkkms.SecretStatusSecretBox
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *localSecret) Encrypt() error {
|
func (s *localSecret) Encrypt() error {
|
||||||
if s.Status != SecretStatusPlain {
|
if s.Status != sdkkms.SecretStatusPlain {
|
||||||
return ErrWrongSecretStatus
|
return ErrWrongSecretStatus
|
||||||
}
|
}
|
||||||
if s.Payload == "" {
|
if s.Payload == "" {
|
||||||
|
@ -60,7 +62,7 @@ func (s *localSecret) Encrypt() error {
|
||||||
}
|
}
|
||||||
s.Key = hex.EncodeToString(secretKey[:])
|
s.Key = hex.EncodeToString(secretKey[:])
|
||||||
s.Payload = base64.StdEncoding.EncodeToString(ciphertext)
|
s.Payload = base64.StdEncoding.EncodeToString(ciphertext)
|
||||||
s.Status = SecretStatusSecretBox
|
s.Status = sdkkms.SecretStatusSecretBox
|
||||||
s.Mode = s.getEncryptionMode()
|
s.Mode = s.getEncryptionMode()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -88,7 +90,7 @@ func (s *localSecret) Decrypt() error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
s.Status = SecretStatusPlain
|
s.Status = sdkkms.SecretStatusPlain
|
||||||
s.Payload = string(plaintext)
|
s.Payload = string(plaintext)
|
||||||
s.Key = ""
|
s.Key = ""
|
||||||
s.AdditionalData = ""
|
s.AdditionalData = ""
|
|
@ -18,8 +18,6 @@ import (
|
||||||
ftpserverlog "github.com/fclairamb/go-log"
|
ftpserverlog "github.com/fclairamb/go-log"
|
||||||
"github.com/rs/zerolog"
|
"github.com/rs/zerolog"
|
||||||
lumberjack "gopkg.in/natefinch/lumberjack.v2"
|
lumberjack "gopkg.in/natefinch/lumberjack.v2"
|
||||||
|
|
||||||
sdklogger "github.com/drakkan/sftpgo/v2/sdk/logger"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -43,22 +41,6 @@ var (
|
||||||
rollingLogger *lumberjack.Logger
|
rollingLogger *lumberjack.Logger
|
||||||
)
|
)
|
||||||
|
|
||||||
type logWrapper struct{}
|
|
||||||
|
|
||||||
// Log logs at the specified level for the specified sender
|
|
||||||
func (l *logWrapper) Log(level int, sender, format string, v ...interface{}) {
|
|
||||||
switch level {
|
|
||||||
case 1:
|
|
||||||
Log(LevelInfo, sender, "", format, v...)
|
|
||||||
case 2:
|
|
||||||
Log(LevelWarn, sender, "", format, v...)
|
|
||||||
case 3:
|
|
||||||
Log(LevelError, sender, "", format, v...)
|
|
||||||
default:
|
|
||||||
Log(LevelDebug, sender, "", format, v...)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// StdLoggerWrapper is a wrapper for standard logger compatibility
|
// StdLoggerWrapper is a wrapper for standard logger compatibility
|
||||||
type StdLoggerWrapper struct {
|
type StdLoggerWrapper struct {
|
||||||
Sender string
|
Sender string
|
||||||
|
@ -194,7 +176,6 @@ func InitLogger(logFilePath string, logMaxSize int, logMaxBackups int, logMaxAge
|
||||||
consoleLogger = zerolog.Nop()
|
consoleLogger = zerolog.Nop()
|
||||||
}
|
}
|
||||||
logger = logger.Level(level)
|
logger = logger.Level(level)
|
||||||
sdklogger.SetLogger(&logWrapper{})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// InitStdErrLogger configures the logger to write to stderr
|
// InitStdErrLogger configures the logger to write to stderr
|
||||||
|
@ -203,7 +184,6 @@ func InitStdErrLogger(level zerolog.Level) {
|
||||||
output: os.Stderr,
|
output: os.Stderr,
|
||||||
}).Level(level)
|
}).Level(level)
|
||||||
consoleLogger = zerolog.Nop()
|
consoleLogger = zerolog.Nop()
|
||||||
sdklogger.SetLogger(&logWrapper{})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// DisableLogger disable the main logger.
|
// DisableLogger disable the main logger.
|
||||||
|
@ -211,7 +191,6 @@ func InitStdErrLogger(level zerolog.Level) {
|
||||||
func DisableLogger() {
|
func DisableLogger() {
|
||||||
logger = zerolog.Nop()
|
logger = zerolog.Nop()
|
||||||
rollingLogger = nil
|
rollingLogger = nil
|
||||||
sdklogger.DisableLogger()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// EnableConsoleLogger enables the console logger
|
// EnableConsoleLogger enables the console logger
|
||||||
|
|
|
@ -9,16 +9,17 @@ import (
|
||||||
"github.com/hashicorp/go-hclog"
|
"github.com/hashicorp/go-hclog"
|
||||||
"github.com/hashicorp/go-plugin"
|
"github.com/hashicorp/go-plugin"
|
||||||
|
|
||||||
|
"github.com/drakkan/sftpgo/v2/kms"
|
||||||
"github.com/drakkan/sftpgo/v2/logger"
|
"github.com/drakkan/sftpgo/v2/logger"
|
||||||
"github.com/drakkan/sftpgo/v2/sdk/kms"
|
sdkkms "github.com/drakkan/sftpgo/v2/sdk/kms"
|
||||||
kmsplugin "github.com/drakkan/sftpgo/v2/sdk/plugin/kms"
|
kmsplugin "github.com/drakkan/sftpgo/v2/sdk/plugin/kms"
|
||||||
"github.com/drakkan/sftpgo/v2/util"
|
"github.com/drakkan/sftpgo/v2/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
validKMSSchemes = []string{kms.SchemeAWS, kms.SchemeGCP, kms.SchemeVaultTransit, kms.SchemeAzureKeyVault}
|
validKMSSchemes = []string{sdkkms.SchemeAWS, sdkkms.SchemeGCP, sdkkms.SchemeVaultTransit, sdkkms.SchemeAzureKeyVault}
|
||||||
validKMSEncryptedStatuses = []string{kms.SecretStatusVaultTransit, kms.SecretStatusAWS, kms.SecretStatusGCP,
|
validKMSEncryptedStatuses = []string{sdkkms.SecretStatusVaultTransit, sdkkms.SecretStatusAWS, sdkkms.SecretStatusGCP,
|
||||||
kms.SecretStatusAzureKeyVault}
|
sdkkms.SecretStatusAzureKeyVault}
|
||||||
)
|
)
|
||||||
|
|
||||||
// KMSConfig defines configuration parameters for kms plugins
|
// KMSConfig defines configuration parameters for kms plugins
|
||||||
|
@ -133,7 +134,7 @@ func (s *kmsPluginSecretProvider) IsEncrypted() bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *kmsPluginSecretProvider) Encrypt() error {
|
func (s *kmsPluginSecretProvider) Encrypt() error {
|
||||||
if s.Status != kms.SecretStatusPlain {
|
if s.Status != sdkkms.SecretStatusPlain {
|
||||||
return kms.ErrWrongSecretStatus
|
return kms.ErrWrongSecretStatus
|
||||||
}
|
}
|
||||||
if s.Payload == "" {
|
if s.Payload == "" {
|
||||||
|
@ -160,7 +161,7 @@ func (s *kmsPluginSecretProvider) Decrypt() error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
s.Status = kms.SecretStatusPlain
|
s.Status = sdkkms.SecretStatusPlain
|
||||||
s.Payload = payload
|
s.Payload = payload
|
||||||
s.Key = ""
|
s.Key = ""
|
||||||
s.AdditionalData = ""
|
s.AdditionalData = ""
|
||||||
|
|
|
@ -11,8 +11,8 @@ import (
|
||||||
|
|
||||||
"github.com/hashicorp/go-hclog"
|
"github.com/hashicorp/go-hclog"
|
||||||
|
|
||||||
|
"github.com/drakkan/sftpgo/v2/kms"
|
||||||
"github.com/drakkan/sftpgo/v2/logger"
|
"github.com/drakkan/sftpgo/v2/logger"
|
||||||
"github.com/drakkan/sftpgo/v2/sdk/kms"
|
|
||||||
"github.com/drakkan/sftpgo/v2/sdk/plugin/auth"
|
"github.com/drakkan/sftpgo/v2/sdk/plugin/auth"
|
||||||
"github.com/drakkan/sftpgo/v2/sdk/plugin/eventsearcher"
|
"github.com/drakkan/sftpgo/v2/sdk/plugin/eventsearcher"
|
||||||
kmsplugin "github.com/drakkan/sftpgo/v2/sdk/plugin/kms"
|
kmsplugin "github.com/drakkan/sftpgo/v2/sdk/plugin/kms"
|
||||||
|
@ -135,7 +135,7 @@ func Initialize(configs []Config, logVerbose bool) error {
|
||||||
kmsID++
|
kmsID++
|
||||||
kms.RegisterSecretProvider(config.KMSOptions.Scheme, config.KMSOptions.EncryptedStatus,
|
kms.RegisterSecretProvider(config.KMSOptions.Scheme, config.KMSOptions.EncryptedStatus,
|
||||||
Handler.Configs[idx].newKMSPluginSecretProvider)
|
Handler.Configs[idx].newKMSPluginSecretProvider)
|
||||||
logger.Debug(logSender, "", "registered secret provider for scheme: %v, encrypted status: %v",
|
logger.Info(logSender, "", "registered secret provider for scheme: %v, encrypted status: %v",
|
||||||
config.KMSOptions.Scheme, config.KMSOptions.EncryptedStatus)
|
config.KMSOptions.Scheme, config.KMSOptions.EncryptedStatus)
|
||||||
case auth.PluginName:
|
case auth.PluginName:
|
||||||
plugin, err := newAuthPlugin(config)
|
plugin, err := newAuthPlugin(config)
|
||||||
|
|
|
@ -84,8 +84,8 @@ func ListProviders() []FilesystemProvider {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// S3FsConfig defines the configuration for S3 based filesystem
|
// BaseS3FsConfig defines the base configuration for S3 based filesystems
|
||||||
type S3FsConfig struct {
|
type BaseS3FsConfig struct {
|
||||||
Bucket string `json:"bucket,omitempty"`
|
Bucket string `json:"bucket,omitempty"`
|
||||||
// KeyPrefix is similar to a chroot directory for local filesystem.
|
// KeyPrefix is similar to a chroot directory for local filesystem.
|
||||||
// If specified then the SFTP user will only see objects that starts
|
// If specified then the SFTP user will only see objects that starts
|
||||||
|
@ -93,12 +93,11 @@ type S3FsConfig struct {
|
||||||
// folder. The prefix, if not empty, must not start with "/" and must
|
// folder. The prefix, if not empty, must not start with "/" and must
|
||||||
// end with "/".
|
// end with "/".
|
||||||
// If empty the whole bucket contents will be available
|
// If empty the whole bucket contents will be available
|
||||||
KeyPrefix string `json:"key_prefix,omitempty"`
|
KeyPrefix string `json:"key_prefix,omitempty"`
|
||||||
Region string `json:"region,omitempty"`
|
Region string `json:"region,omitempty"`
|
||||||
AccessKey string `json:"access_key,omitempty"`
|
AccessKey string `json:"access_key,omitempty"`
|
||||||
AccessSecret *kms.Secret `json:"access_secret,omitempty"`
|
Endpoint string `json:"endpoint,omitempty"`
|
||||||
Endpoint string `json:"endpoint,omitempty"`
|
StorageClass string `json:"storage_class,omitempty"`
|
||||||
StorageClass string `json:"storage_class,omitempty"`
|
|
||||||
// The canned ACL to apply to uploaded objects. Leave empty to use the default ACL.
|
// The canned ACL to apply to uploaded objects. Leave empty to use the default ACL.
|
||||||
// For more information and available ACLs, see here:
|
// For more information and available ACLs, see here:
|
||||||
// https://docs.aws.amazon.com/AmazonS3/latest/userguide/acl-overview.html#canned-acl
|
// https://docs.aws.amazon.com/AmazonS3/latest/userguide/acl-overview.html#canned-acl
|
||||||
|
@ -129,8 +128,14 @@ type S3FsConfig struct {
|
||||||
ForcePathStyle bool `json:"force_path_style,omitempty"`
|
ForcePathStyle bool `json:"force_path_style,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// GCSFsConfig defines the configuration for Google Cloud Storage based filesystem
|
// S3FsConfig defines the base configuration for S3 based filesystems
|
||||||
type GCSFsConfig struct {
|
type S3FsConfig struct {
|
||||||
|
BaseS3FsConfig
|
||||||
|
AccessSecret kms.BaseSecret `json:"access_secret,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// BaseGCSFsConfig defines the base configuration for Google Cloud Storage based filesystems
|
||||||
|
type BaseGCSFsConfig struct {
|
||||||
Bucket string `json:"bucket,omitempty"`
|
Bucket string `json:"bucket,omitempty"`
|
||||||
// KeyPrefix is similar to a chroot directory for local filesystem.
|
// KeyPrefix is similar to a chroot directory for local filesystem.
|
||||||
// If specified then the SFTP user will only see objects that starts
|
// If specified then the SFTP user will only see objects that starts
|
||||||
|
@ -138,9 +143,8 @@ type GCSFsConfig struct {
|
||||||
// folder. The prefix, if not empty, must not start with "/" and must
|
// folder. The prefix, if not empty, must not start with "/" and must
|
||||||
// end with "/".
|
// end with "/".
|
||||||
// If empty the whole bucket contents will be available
|
// If empty the whole bucket contents will be available
|
||||||
KeyPrefix string `json:"key_prefix,omitempty"`
|
KeyPrefix string `json:"key_prefix,omitempty"`
|
||||||
CredentialFile string `json:"-"`
|
CredentialFile string `json:"-"`
|
||||||
Credentials *kms.Secret `json:"credentials,omitempty"`
|
|
||||||
// 0 explicit, 1 automatic
|
// 0 explicit, 1 automatic
|
||||||
AutomaticCredentials int `json:"automatic_credentials,omitempty"`
|
AutomaticCredentials int `json:"automatic_credentials,omitempty"`
|
||||||
StorageClass string `json:"storage_class,omitempty"`
|
StorageClass string `json:"storage_class,omitempty"`
|
||||||
|
@ -150,20 +154,21 @@ type GCSFsConfig struct {
|
||||||
ACL string `json:"acl,omitempty"`
|
ACL string `json:"acl,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// AzBlobFsConfig defines the configuration for Azure Blob Storage based filesystem
|
// GCSFsConfig defines the configuration for Google Cloud Storage based filesystems
|
||||||
type AzBlobFsConfig struct {
|
type GCSFsConfig struct {
|
||||||
|
BaseGCSFsConfig
|
||||||
|
Credentials kms.BaseSecret `json:"credentials,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// BaseAzBlobFsConfig defines the base configuration for Azure Blob Storage based filesystem
|
||||||
|
type BaseAzBlobFsConfig struct {
|
||||||
Container string `json:"container,omitempty"`
|
Container string `json:"container,omitempty"`
|
||||||
// Storage Account Name, leave blank to use SAS URL
|
// Storage Account Name, leave blank to use SAS URL
|
||||||
AccountName string `json:"account_name,omitempty"`
|
AccountName string `json:"account_name,omitempty"`
|
||||||
// Storage Account Key leave blank to use SAS URL.
|
|
||||||
// The access key is stored encrypted based on the kms configuration
|
|
||||||
AccountKey *kms.Secret `json:"account_key,omitempty"`
|
|
||||||
// Optional endpoint. Default is "blob.core.windows.net".
|
// Optional endpoint. Default is "blob.core.windows.net".
|
||||||
// If you use the emulator the endpoint must include the protocol,
|
// If you use the emulator the endpoint must include the protocol,
|
||||||
// for example "http://127.0.0.1:10000"
|
// for example "http://127.0.0.1:10000"
|
||||||
Endpoint string `json:"endpoint,omitempty"`
|
Endpoint string `json:"endpoint,omitempty"`
|
||||||
// Shared access signature URL, leave blank if using account/key
|
|
||||||
SASURL *kms.Secret `json:"sas_url,omitempty"`
|
|
||||||
// KeyPrefix is similar to a chroot directory for local filesystem.
|
// KeyPrefix is similar to a chroot directory for local filesystem.
|
||||||
// If specified then the SFTPGo user will only see objects that starts
|
// If specified then the SFTPGo user will only see objects that starts
|
||||||
// with this prefix and so you can restrict access to a specific
|
// with this prefix and so you can restrict access to a specific
|
||||||
|
@ -187,18 +192,26 @@ type AzBlobFsConfig struct {
|
||||||
AccessTier string `json:"access_tier,omitempty"`
|
AccessTier string `json:"access_tier,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// CryptFsConfig defines the configuration to store local files as encrypted
|
// AzBlobFsConfig defines the configuration for Azure Blob Storage based filesystem
|
||||||
type CryptFsConfig struct {
|
type AzBlobFsConfig struct {
|
||||||
Passphrase *kms.Secret `json:"passphrase,omitempty"`
|
BaseAzBlobFsConfig
|
||||||
|
// Storage Account Key leave blank to use SAS URL.
|
||||||
|
// The access key is stored encrypted based on the kms configuration
|
||||||
|
AccountKey kms.BaseSecret `json:"account_key,omitempty"`
|
||||||
|
// Shared access signature URL, leave blank if using account/key
|
||||||
|
SASURL kms.BaseSecret `json:"sas_url,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// SFTPFsConfig defines the configuration for SFTP based filesystem
|
// CryptFsConfig defines the configuration to store local files as encrypted
|
||||||
type SFTPFsConfig struct {
|
type CryptFsConfig struct {
|
||||||
Endpoint string `json:"endpoint,omitempty"`
|
Passphrase kms.BaseSecret `json:"passphrase,omitempty"`
|
||||||
Username string `json:"username,omitempty"`
|
}
|
||||||
Password *kms.Secret `json:"password,omitempty"`
|
|
||||||
PrivateKey *kms.Secret `json:"private_key,omitempty"`
|
// BaseSFTPFsConfig defines the base configuration for SFTP based filesystem
|
||||||
Fingerprints []string `json:"fingerprints,omitempty"`
|
type BaseSFTPFsConfig struct {
|
||||||
|
Endpoint string `json:"endpoint,omitempty"`
|
||||||
|
Username string `json:"username,omitempty"`
|
||||||
|
Fingerprints []string `json:"fingerprints,omitempty"`
|
||||||
// Prefix is the path prefix to strip from SFTP resource paths.
|
// Prefix is the path prefix to strip from SFTP resource paths.
|
||||||
Prefix string `json:"prefix,omitempty"`
|
Prefix string `json:"prefix,omitempty"`
|
||||||
// Concurrent reads are safe to use and disabling them will degrade performance.
|
// Concurrent reads are safe to use and disabling them will degrade performance.
|
||||||
|
@ -213,6 +226,13 @@ type SFTPFsConfig struct {
|
||||||
BufferSize int64 `json:"buffer_size,omitempty"`
|
BufferSize int64 `json:"buffer_size,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SFTPFsConfig defines the configuration for SFTP based filesystem
|
||||||
|
type SFTPFsConfig struct {
|
||||||
|
BaseSFTPFsConfig
|
||||||
|
Password kms.BaseSecret `json:"password,omitempty"`
|
||||||
|
PrivateKey kms.BaseSecret `json:"private_key,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
// Filesystem defines filesystem details
|
// Filesystem defines filesystem details
|
||||||
type Filesystem struct {
|
type Filesystem struct {
|
||||||
Provider FilesystemProvider `json:"provider"`
|
Provider FilesystemProvider `json:"provider"`
|
||||||
|
|
419
sdk/kms/kms.go
419
sdk/kms/kms.go
|
@ -1,37 +1,6 @@
|
||||||
// Package kms provides Key Management Services support
|
// Package kms provides Key Management Services support
|
||||||
package kms
|
package kms
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"errors"
|
|
||||||
"os"
|
|
||||||
"strings"
|
|
||||||
"sync"
|
|
||||||
|
|
||||||
"github.com/drakkan/sftpgo/v2/sdk/logger"
|
|
||||||
)
|
|
||||||
|
|
||||||
// SecretProvider defines the interface for a KMS secrets provider
|
|
||||||
type SecretProvider interface {
|
|
||||||
Name() string
|
|
||||||
Encrypt() error
|
|
||||||
Decrypt() error
|
|
||||||
IsEncrypted() bool
|
|
||||||
GetStatus() SecretStatus
|
|
||||||
GetPayload() string
|
|
||||||
GetKey() string
|
|
||||||
GetAdditionalData() string
|
|
||||||
GetMode() int
|
|
||||||
SetKey(string)
|
|
||||||
SetAdditionalData(string)
|
|
||||||
SetStatus(SecretStatus)
|
|
||||||
Clone() SecretProvider
|
|
||||||
}
|
|
||||||
|
|
||||||
const (
|
|
||||||
logSender = "kms"
|
|
||||||
)
|
|
||||||
|
|
||||||
// SecretStatus defines the statuses of a Secret object
|
// SecretStatus defines the statuses of a Secret object
|
||||||
type SecretStatus = string
|
type SecretStatus = string
|
||||||
|
|
||||||
|
@ -70,384 +39,12 @@ const (
|
||||||
SchemeAzureKeyVault Scheme = "azurekeyvault"
|
SchemeAzureKeyVault Scheme = "azurekeyvault"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Configuration defines the KMS configuration
|
// BaseSecret defines the base struct shared among all the secret providers
|
||||||
type Configuration struct {
|
type BaseSecret struct {
|
||||||
Secrets Secrets `json:"secrets" mapstructure:"secrets"`
|
Status SecretStatus `json:"status,omitempty"`
|
||||||
}
|
Payload string `json:"payload,omitempty"`
|
||||||
|
Key string `json:"key,omitempty"`
|
||||||
// Secrets define the KMS configuration for encryption/decryption
|
AdditionalData string `json:"additional_data,omitempty"`
|
||||||
type Secrets struct {
|
// 1 means encrypted using a master key
|
||||||
URL string `json:"url" mapstructure:"url"`
|
Mode int `json:"mode,omitempty"`
|
||||||
MasterKeyPath string `json:"master_key_path" mapstructure:"master_key_path"`
|
|
||||||
MasterKeyString string `json:"master_key" mapstructure:"master_key"`
|
|
||||||
masterKey string
|
|
||||||
}
|
|
||||||
|
|
||||||
type registeredSecretProvider struct {
|
|
||||||
encryptedStatus SecretStatus
|
|
||||||
newFn func(base BaseSecret, url, masterKey string) SecretProvider
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
// ErrWrongSecretStatus defines the error to return if the secret status is not appropriate
|
|
||||||
// for the request operation
|
|
||||||
ErrWrongSecretStatus = errors.New("wrong secret status")
|
|
||||||
// ErrInvalidSecret defines the error to return if a secret is not valid
|
|
||||||
ErrInvalidSecret = errors.New("invalid secret")
|
|
||||||
validSecretStatuses = []string{SecretStatusPlain, SecretStatusAES256GCM, SecretStatusSecretBox,
|
|
||||||
SecretStatusVaultTransit, SecretStatusAWS, SecretStatusGCP, SecretStatusRedacted}
|
|
||||||
config Configuration
|
|
||||||
secretProviders = make(map[string]registeredSecretProvider)
|
|
||||||
)
|
|
||||||
|
|
||||||
// RegisterSecretProvider register a new secret provider
|
|
||||||
func RegisterSecretProvider(scheme string, encryptedStatus SecretStatus, fn func(base BaseSecret, url, masterKey string) SecretProvider) {
|
|
||||||
secretProviders[scheme] = registeredSecretProvider{
|
|
||||||
encryptedStatus: encryptedStatus,
|
|
||||||
newFn: fn,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewSecret builds a new Secret using the provided arguments
|
|
||||||
func NewSecret(status SecretStatus, payload, key, data string) *Secret {
|
|
||||||
return config.newSecret(status, payload, key, data)
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewEmptySecret returns an empty secret
|
|
||||||
func NewEmptySecret() *Secret {
|
|
||||||
return NewSecret("", "", "", "")
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewPlainSecret stores the give payload in a plain text secret
|
|
||||||
func NewPlainSecret(payload string) *Secret {
|
|
||||||
return NewSecret(SecretStatusPlain, payload, "", "")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Initialize configures the KMS support
|
|
||||||
func (c *Configuration) Initialize() error {
|
|
||||||
if c.Secrets.MasterKeyString != "" {
|
|
||||||
c.Secrets.masterKey = c.Secrets.MasterKeyString
|
|
||||||
}
|
|
||||||
if c.Secrets.masterKey == "" && c.Secrets.MasterKeyPath != "" {
|
|
||||||
mKey, err := os.ReadFile(c.Secrets.MasterKeyPath)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
c.Secrets.masterKey = strings.TrimSpace(string(mKey))
|
|
||||||
}
|
|
||||||
config = *c
|
|
||||||
if config.Secrets.URL == "" {
|
|
||||||
config.Secrets.URL = SchemeLocal + "://"
|
|
||||||
}
|
|
||||||
for k, v := range secretProviders {
|
|
||||||
logger.Info(logSender, "secret provider registered for scheme: %#v, encrypted status: %#v",
|
|
||||||
k, v.encryptedStatus)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Configuration) newSecret(status SecretStatus, payload, key, data string) *Secret {
|
|
||||||
base := BaseSecret{
|
|
||||||
Status: status,
|
|
||||||
Key: key,
|
|
||||||
Payload: payload,
|
|
||||||
AdditionalData: data,
|
|
||||||
}
|
|
||||||
return &Secret{
|
|
||||||
provider: c.getSecretProvider(base),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Configuration) getSecretProvider(base BaseSecret) SecretProvider {
|
|
||||||
for k, v := range secretProviders {
|
|
||||||
if strings.HasPrefix(c.Secrets.URL, k) {
|
|
||||||
return v.newFn(base, c.Secrets.URL, c.Secrets.masterKey)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// we assume that SchemeLocal is always registered
|
|
||||||
logger.Warn(logSender, "no secret provider registered for URL %v, fallback to local provider", c.Secrets.URL)
|
|
||||||
return NewLocalSecret(base, c.Secrets.URL, c.Secrets.masterKey)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Secret defines the struct used to store confidential data
|
|
||||||
type Secret struct {
|
|
||||||
sync.RWMutex
|
|
||||||
provider SecretProvider
|
|
||||||
}
|
|
||||||
|
|
||||||
// MarshalJSON return the JSON encoding of the Secret object
|
|
||||||
func (s *Secret) MarshalJSON() ([]byte, error) {
|
|
||||||
s.RLock()
|
|
||||||
defer s.RUnlock()
|
|
||||||
|
|
||||||
return json.Marshal(&BaseSecret{
|
|
||||||
Status: s.provider.GetStatus(),
|
|
||||||
Payload: s.provider.GetPayload(),
|
|
||||||
Key: s.provider.GetKey(),
|
|
||||||
AdditionalData: s.provider.GetAdditionalData(),
|
|
||||||
Mode: s.provider.GetMode(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// UnmarshalJSON parses the JSON-encoded data and stores the result
|
|
||||||
// in the Secret object
|
|
||||||
func (s *Secret) UnmarshalJSON(data []byte) error {
|
|
||||||
s.Lock()
|
|
||||||
defer s.Unlock()
|
|
||||||
|
|
||||||
baseSecret := BaseSecret{}
|
|
||||||
err := json.Unmarshal(data, &baseSecret)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if baseSecret.isEmpty() {
|
|
||||||
s.provider = config.getSecretProvider(baseSecret)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if baseSecret.Status == SecretStatusPlain || baseSecret.Status == SecretStatusRedacted {
|
|
||||||
s.provider = config.getSecretProvider(baseSecret)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, v := range secretProviders {
|
|
||||||
if v.encryptedStatus == baseSecret.Status {
|
|
||||||
s.provider = v.newFn(baseSecret, config.Secrets.URL, config.Secrets.masterKey)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
logger.Error(logSender, "no provider registered for status %#v", baseSecret.Status)
|
|
||||||
return ErrInvalidSecret
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsEqual returns true if all the secrets fields are equal
|
|
||||||
func (s *Secret) IsEqual(other *Secret) bool {
|
|
||||||
if s.GetStatus() != other.GetStatus() {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if s.GetPayload() != other.GetPayload() {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if s.GetKey() != other.GetKey() {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if s.GetAdditionalData() != other.GetAdditionalData() {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if s.GetMode() != other.GetMode() {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clone returns a copy of the secret object
|
|
||||||
func (s *Secret) Clone() *Secret {
|
|
||||||
s.RLock()
|
|
||||||
defer s.RUnlock()
|
|
||||||
|
|
||||||
return &Secret{
|
|
||||||
provider: s.provider.Clone(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsEncrypted returns true if the secret is encrypted
|
|
||||||
// This isn't a pointer receiver because we don't want to pass
|
|
||||||
// a pointer to html template
|
|
||||||
func (s *Secret) IsEncrypted() bool {
|
|
||||||
s.RLock()
|
|
||||||
defer s.RUnlock()
|
|
||||||
|
|
||||||
return s.provider.IsEncrypted()
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsPlain returns true if the secret is in plain text
|
|
||||||
func (s *Secret) IsPlain() bool {
|
|
||||||
s.RLock()
|
|
||||||
defer s.RUnlock()
|
|
||||||
|
|
||||||
return s.provider.GetStatus() == SecretStatusPlain
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsNotPlainAndNotEmpty returns true if the secret is not plain and not empty.
|
|
||||||
// This is an utility method, we update the secret for an existing user
|
|
||||||
// if it is empty or plain
|
|
||||||
func (s *Secret) IsNotPlainAndNotEmpty() bool {
|
|
||||||
s.RLock()
|
|
||||||
defer s.RUnlock()
|
|
||||||
|
|
||||||
return !s.IsPlain() && !s.IsEmpty()
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsRedacted returns true if the secret is redacted
|
|
||||||
func (s *Secret) IsRedacted() bool {
|
|
||||||
s.RLock()
|
|
||||||
defer s.RUnlock()
|
|
||||||
|
|
||||||
return s.provider.GetStatus() == SecretStatusRedacted
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetPayload returns the secret payload
|
|
||||||
func (s *Secret) GetPayload() string {
|
|
||||||
s.RLock()
|
|
||||||
defer s.RUnlock()
|
|
||||||
|
|
||||||
return s.provider.GetPayload()
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetAdditionalData returns the secret additional data
|
|
||||||
func (s *Secret) GetAdditionalData() string {
|
|
||||||
s.RLock()
|
|
||||||
defer s.RUnlock()
|
|
||||||
|
|
||||||
return s.provider.GetAdditionalData()
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetStatus returns the secret status
|
|
||||||
func (s *Secret) GetStatus() SecretStatus {
|
|
||||||
s.RLock()
|
|
||||||
defer s.RUnlock()
|
|
||||||
|
|
||||||
return s.provider.GetStatus()
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetKey returns the secret key
|
|
||||||
func (s *Secret) GetKey() string {
|
|
||||||
s.RLock()
|
|
||||||
defer s.RUnlock()
|
|
||||||
|
|
||||||
return s.provider.GetKey()
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetMode returns the secret mode
|
|
||||||
func (s *Secret) GetMode() int {
|
|
||||||
s.RLock()
|
|
||||||
defer s.RUnlock()
|
|
||||||
|
|
||||||
return s.provider.GetMode()
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetAdditionalData sets the given additional data
|
|
||||||
func (s *Secret) SetAdditionalData(value string) {
|
|
||||||
s.Lock()
|
|
||||||
defer s.Unlock()
|
|
||||||
|
|
||||||
s.provider.SetAdditionalData(value)
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetStatus sets the status for this secret
|
|
||||||
func (s *Secret) SetStatus(value SecretStatus) {
|
|
||||||
s.Lock()
|
|
||||||
defer s.Unlock()
|
|
||||||
|
|
||||||
s.provider.SetStatus(value)
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetKey sets the key for this secret
|
|
||||||
func (s *Secret) SetKey(value string) {
|
|
||||||
s.Lock()
|
|
||||||
defer s.Unlock()
|
|
||||||
|
|
||||||
s.provider.SetKey(value)
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsEmpty returns true if all fields are empty
|
|
||||||
func (s *Secret) IsEmpty() bool {
|
|
||||||
s.RLock()
|
|
||||||
defer s.RUnlock()
|
|
||||||
|
|
||||||
if s.provider.GetStatus() != "" {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if s.provider.GetPayload() != "" {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if s.provider.GetKey() != "" {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if s.provider.GetAdditionalData() != "" {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsValid returns true if the secret is not empty and valid
|
|
||||||
func (s *Secret) IsValid() bool {
|
|
||||||
s.RLock()
|
|
||||||
defer s.RUnlock()
|
|
||||||
|
|
||||||
if !s.IsValidInput() {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
switch s.provider.GetStatus() {
|
|
||||||
case SecretStatusAES256GCM, SecretStatusSecretBox:
|
|
||||||
if len(s.provider.GetKey()) != 64 {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
case SecretStatusAWS, SecretStatusGCP, SecretStatusVaultTransit:
|
|
||||||
key := s.provider.GetKey()
|
|
||||||
if key != "" && len(key) != 64 {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsValidInput returns true if the secret is a valid user input
|
|
||||||
func (s *Secret) IsValidInput() bool {
|
|
||||||
s.RLock()
|
|
||||||
defer s.RUnlock()
|
|
||||||
|
|
||||||
if !isSecretStatusValid(s.provider.GetStatus()) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if s.provider.GetPayload() == "" {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// Hide hides info to decrypt data
|
|
||||||
func (s *Secret) Hide() {
|
|
||||||
s.Lock()
|
|
||||||
defer s.Unlock()
|
|
||||||
|
|
||||||
s.provider.SetKey("")
|
|
||||||
s.provider.SetAdditionalData("")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Encrypt encrypts a plain text Secret object
|
|
||||||
func (s *Secret) Encrypt() error {
|
|
||||||
s.Lock()
|
|
||||||
defer s.Unlock()
|
|
||||||
|
|
||||||
return s.provider.Encrypt()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Decrypt decrypts a Secret object
|
|
||||||
func (s *Secret) Decrypt() error {
|
|
||||||
s.Lock()
|
|
||||||
defer s.Unlock()
|
|
||||||
|
|
||||||
return s.provider.Decrypt()
|
|
||||||
}
|
|
||||||
|
|
||||||
// TryDecrypt decrypts a Secret object if encrypted.
|
|
||||||
// It returns a nil error if the object is not encrypted
|
|
||||||
func (s *Secret) TryDecrypt() error {
|
|
||||||
s.Lock()
|
|
||||||
defer s.Unlock()
|
|
||||||
|
|
||||||
if s.provider.IsEncrypted() {
|
|
||||||
return s.provider.Decrypt()
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func isSecretStatusValid(status string) bool {
|
|
||||||
for idx := range validSecretStatuses {
|
|
||||||
if validSecretStatuses[idx] == status {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,57 +0,0 @@
|
||||||
// Package logger provides logging capabilities.
|
|
||||||
package logger
|
|
||||||
|
|
||||||
const (
|
|
||||||
levelDebug = iota
|
|
||||||
levelInfo
|
|
||||||
levelWarn
|
|
||||||
levelError
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
logger Logger
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
DisableLogger()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Logger interface
|
|
||||||
type Logger interface {
|
|
||||||
// Log logs at the specified level for the specified sender
|
|
||||||
Log(level int, sender, format string, v ...interface{})
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetLogger sets the specified logger
|
|
||||||
func SetLogger(l Logger) {
|
|
||||||
logger = l
|
|
||||||
}
|
|
||||||
|
|
||||||
// DisableLogger disables logging
|
|
||||||
func DisableLogger() {
|
|
||||||
logger = &noLogger{}
|
|
||||||
}
|
|
||||||
|
|
||||||
type noLogger struct{}
|
|
||||||
|
|
||||||
func (*noLogger) Log(level int, sender, format string, v ...interface{}) {}
|
|
||||||
|
|
||||||
// Debug logs at debug level for the specified sender
|
|
||||||
func Debug(sender, format string, v ...interface{}) {
|
|
||||||
logger.Log(levelDebug, sender, format, v...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Info logs at info level for the specified sender
|
|
||||||
func Info(sender, format string, v ...interface{}) {
|
|
||||||
logger.Log(levelInfo, sender, format, v...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Warn logs at warn level for the specified sender
|
|
||||||
func Warn(sender, format string, v ...interface{}) {
|
|
||||||
logger.Log(levelWarn, sender, format, v...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Error logs at error level for the specified sender
|
|
||||||
func Error(sender, format string, v ...interface{}) {
|
|
||||||
logger.Log(levelError, sender, format, v...)
|
|
||||||
}
|
|
35
sdk/user.go
35
sdk/user.go
|
@ -100,15 +100,15 @@ type HooksFilter struct {
|
||||||
|
|
||||||
// RecoveryCode defines a 2FA recovery code
|
// RecoveryCode defines a 2FA recovery code
|
||||||
type RecoveryCode struct {
|
type RecoveryCode struct {
|
||||||
Secret *kms.Secret `json:"secret"`
|
Secret kms.BaseSecret `json:"secret"`
|
||||||
Used bool `json:"used,omitempty"`
|
Used bool `json:"used,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// TOTPConfig defines the time-based one time password configuration
|
// TOTPConfig defines the time-based one time password configuration
|
||||||
type TOTPConfig struct {
|
type TOTPConfig struct {
|
||||||
Enabled bool `json:"enabled,omitempty"`
|
Enabled bool `json:"enabled,omitempty"`
|
||||||
ConfigName string `json:"config_name,omitempty"`
|
ConfigName string `json:"config_name,omitempty"`
|
||||||
Secret *kms.Secret `json:"secret,omitempty"`
|
Secret kms.BaseSecret `json:"secret,omitempty"`
|
||||||
// TOTP will be required for the specified protocols.
|
// TOTP will be required for the specified protocols.
|
||||||
// SSH protocol (SFTP/SCP/SSH commands) will ask for the TOTP passcode if the client uses keyboard interactive
|
// SSH protocol (SFTP/SCP/SSH commands) will ask for the TOTP passcode if the client uses keyboard interactive
|
||||||
// authentication.
|
// authentication.
|
||||||
|
@ -136,9 +136,8 @@ func (l *BandwidthLimit) GetSourcesAsString() string {
|
||||||
return strings.Join(l.Sources, ",")
|
return strings.Join(l.Sources, ",")
|
||||||
}
|
}
|
||||||
|
|
||||||
// UserFilters defines additional restrictions for a user
|
// BaseUserFilters defines additional restrictions for a user
|
||||||
// TODO: rename to UserOptions in v3
|
type BaseUserFilters struct {
|
||||||
type UserFilters struct {
|
|
||||||
// only clients connecting from these IP/Mask are allowed.
|
// only clients connecting from these IP/Mask are allowed.
|
||||||
// IP/Mask must be in CIDR notation as defined in RFC 4632 and RFC 4291
|
// IP/Mask must be in CIDR notation as defined in RFC 4632 and RFC 4291
|
||||||
// for example "192.0.2.0/24" or "2001:db8::/32"
|
// for example "192.0.2.0/24" or "2001:db8::/32"
|
||||||
|
@ -175,17 +174,23 @@ type UserFilters struct {
|
||||||
WebClient []string `json:"web_client,omitempty"`
|
WebClient []string `json:"web_client,omitempty"`
|
||||||
// API key auth allows to impersonate this user with an API key
|
// API key auth allows to impersonate this user with an API key
|
||||||
AllowAPIKeyAuth bool `json:"allow_api_key_auth,omitempty"`
|
AllowAPIKeyAuth bool `json:"allow_api_key_auth,omitempty"`
|
||||||
|
// UserType is an hint for authentication plugins.
|
||||||
|
// It is ignored when using SFTPGo internal authentication
|
||||||
|
UserType string `json:"user_type,omitempty"`
|
||||||
|
// Per-source bandwidth limits
|
||||||
|
BandwidthLimits []BandwidthLimit `json:"bandwidth_limits,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// UserFilters defines additional restrictions for a user
|
||||||
|
// TODO: rename to UserOptions in v3
|
||||||
|
type UserFilters struct {
|
||||||
|
BaseUserFilters
|
||||||
// Time-based one time passwords configuration
|
// Time-based one time passwords configuration
|
||||||
TOTPConfig TOTPConfig `json:"totp_config,omitempty"`
|
TOTPConfig TOTPConfig `json:"totp_config,omitempty"`
|
||||||
// Recovery codes to use if the user loses access to their second factor auth device.
|
// Recovery codes to use if the user loses access to their second factor auth device.
|
||||||
// Each code can only be used once, you should use these codes to login and disable or
|
// Each code can only be used once, you should use these codes to login and disable or
|
||||||
// reset 2FA for your account
|
// reset 2FA for your account
|
||||||
RecoveryCodes []RecoveryCode `json:"recovery_codes,omitempty"`
|
RecoveryCodes []RecoveryCode `json:"recovery_codes,omitempty"`
|
||||||
// UserType is an hint for authentication plugins.
|
|
||||||
// It is ignored when using SFTPGo internal authentication
|
|
||||||
UserType string `json:"user_type,omitempty"`
|
|
||||||
// Per-source bandwidth limits
|
|
||||||
BandwidthLimits []BandwidthLimit `json:"bandwidth_limits,omitempty"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// BaseUser defines the shared user fields
|
// BaseUser defines the shared user fields
|
||||||
|
@ -239,8 +244,6 @@ type BaseUser struct {
|
||||||
CreatedAt int64 `json:"created_at"`
|
CreatedAt int64 `json:"created_at"`
|
||||||
// last update time as unix timestamp in milliseconds
|
// last update time as unix timestamp in milliseconds
|
||||||
UpdatedAt int64 `json:"updated_at"`
|
UpdatedAt int64 `json:"updated_at"`
|
||||||
// Additional restrictions
|
|
||||||
Filters UserFilters `json:"filters"`
|
|
||||||
// optional description, for example full name
|
// optional description, for example full name
|
||||||
Description string `json:"description,omitempty"`
|
Description string `json:"description,omitempty"`
|
||||||
// free form text field for external systems
|
// free form text field for external systems
|
||||||
|
@ -250,6 +253,8 @@ type BaseUser struct {
|
||||||
// User defines a SFTPGo user
|
// User defines a SFTPGo user
|
||||||
type User struct {
|
type User struct {
|
||||||
BaseUser
|
BaseUser
|
||||||
|
// Additional restrictions
|
||||||
|
Filters UserFilters `json:"filters"`
|
||||||
// Mapping between virtual paths and virtual folders
|
// Mapping between virtual paths and virtual folders
|
||||||
VirtualFolders []VirtualFolder `json:"virtual_folders,omitempty"`
|
VirtualFolders []VirtualFolder `json:"virtual_folders,omitempty"`
|
||||||
// Filesystem configuration details
|
// Filesystem configuration details
|
||||||
|
|
|
@ -17,9 +17,9 @@ import (
|
||||||
"github.com/drakkan/sftpgo/v2/config"
|
"github.com/drakkan/sftpgo/v2/config"
|
||||||
"github.com/drakkan/sftpgo/v2/dataprovider"
|
"github.com/drakkan/sftpgo/v2/dataprovider"
|
||||||
"github.com/drakkan/sftpgo/v2/ftpd"
|
"github.com/drakkan/sftpgo/v2/ftpd"
|
||||||
|
"github.com/drakkan/sftpgo/v2/kms"
|
||||||
"github.com/drakkan/sftpgo/v2/logger"
|
"github.com/drakkan/sftpgo/v2/logger"
|
||||||
"github.com/drakkan/sftpgo/v2/sdk"
|
"github.com/drakkan/sftpgo/v2/sdk"
|
||||||
"github.com/drakkan/sftpgo/v2/sdk/kms"
|
|
||||||
"github.com/drakkan/sftpgo/v2/sftpd"
|
"github.com/drakkan/sftpgo/v2/sftpd"
|
||||||
"github.com/drakkan/sftpgo/v2/util"
|
"github.com/drakkan/sftpgo/v2/util"
|
||||||
"github.com/drakkan/sftpgo/v2/version"
|
"github.com/drakkan/sftpgo/v2/version"
|
||||||
|
|
|
@ -15,8 +15,8 @@ import (
|
||||||
|
|
||||||
"github.com/drakkan/sftpgo/v2/dataprovider"
|
"github.com/drakkan/sftpgo/v2/dataprovider"
|
||||||
"github.com/drakkan/sftpgo/v2/httpdtest"
|
"github.com/drakkan/sftpgo/v2/httpdtest"
|
||||||
|
"github.com/drakkan/sftpgo/v2/kms"
|
||||||
"github.com/drakkan/sftpgo/v2/sdk"
|
"github.com/drakkan/sftpgo/v2/sdk"
|
||||||
"github.com/drakkan/sftpgo/v2/sdk/kms"
|
|
||||||
"github.com/drakkan/sftpgo/v2/vfs"
|
"github.com/drakkan/sftpgo/v2/vfs"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -20,8 +20,8 @@ import (
|
||||||
|
|
||||||
"github.com/drakkan/sftpgo/v2/common"
|
"github.com/drakkan/sftpgo/v2/common"
|
||||||
"github.com/drakkan/sftpgo/v2/dataprovider"
|
"github.com/drakkan/sftpgo/v2/dataprovider"
|
||||||
|
"github.com/drakkan/sftpgo/v2/kms"
|
||||||
"github.com/drakkan/sftpgo/v2/sdk"
|
"github.com/drakkan/sftpgo/v2/sdk"
|
||||||
"github.com/drakkan/sftpgo/v2/sdk/kms"
|
|
||||||
"github.com/drakkan/sftpgo/v2/util"
|
"github.com/drakkan/sftpgo/v2/util"
|
||||||
"github.com/drakkan/sftpgo/v2/vfs"
|
"github.com/drakkan/sftpgo/v2/vfs"
|
||||||
)
|
)
|
||||||
|
@ -667,7 +667,7 @@ func TestSSHCommandsRemoteFs(t *testing.T) {
|
||||||
user.FsConfig = vfs.Filesystem{
|
user.FsConfig = vfs.Filesystem{
|
||||||
Provider: sdk.S3FilesystemProvider,
|
Provider: sdk.S3FilesystemProvider,
|
||||||
S3Config: vfs.S3FsConfig{
|
S3Config: vfs.S3FsConfig{
|
||||||
S3FsConfig: sdk.S3FsConfig{
|
BaseS3FsConfig: sdk.BaseS3FsConfig{
|
||||||
Bucket: "s3bucket",
|
Bucket: "s3bucket",
|
||||||
Endpoint: "endpoint",
|
Endpoint: "endpoint",
|
||||||
Region: "eu-west-1",
|
Region: "eu-west-1",
|
||||||
|
@ -1753,9 +1753,7 @@ func TestTransferFailingReader(t *testing.T) {
|
||||||
FsConfig: vfs.Filesystem{
|
FsConfig: vfs.Filesystem{
|
||||||
Provider: sdk.CryptedFilesystemProvider,
|
Provider: sdk.CryptedFilesystemProvider,
|
||||||
CryptConfig: vfs.CryptFsConfig{
|
CryptConfig: vfs.CryptFsConfig{
|
||||||
CryptFsConfig: sdk.CryptFsConfig{
|
Passphrase: kms.NewPlainSecret("crypt secret"),
|
||||||
Passphrase: kms.NewPlainSecret("crypt secret"),
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,10 +42,11 @@ import (
|
||||||
"github.com/drakkan/sftpgo/v2/config"
|
"github.com/drakkan/sftpgo/v2/config"
|
||||||
"github.com/drakkan/sftpgo/v2/dataprovider"
|
"github.com/drakkan/sftpgo/v2/dataprovider"
|
||||||
"github.com/drakkan/sftpgo/v2/httpdtest"
|
"github.com/drakkan/sftpgo/v2/httpdtest"
|
||||||
|
"github.com/drakkan/sftpgo/v2/kms"
|
||||||
"github.com/drakkan/sftpgo/v2/logger"
|
"github.com/drakkan/sftpgo/v2/logger"
|
||||||
"github.com/drakkan/sftpgo/v2/mfa"
|
"github.com/drakkan/sftpgo/v2/mfa"
|
||||||
"github.com/drakkan/sftpgo/v2/sdk"
|
"github.com/drakkan/sftpgo/v2/sdk"
|
||||||
"github.com/drakkan/sftpgo/v2/sdk/kms"
|
sdkkms "github.com/drakkan/sftpgo/v2/sdk/kms"
|
||||||
"github.com/drakkan/sftpgo/v2/sftpd"
|
"github.com/drakkan/sftpgo/v2/sftpd"
|
||||||
"github.com/drakkan/sftpgo/v2/util"
|
"github.com/drakkan/sftpgo/v2/util"
|
||||||
"github.com/drakkan/sftpgo/v2/vfs"
|
"github.com/drakkan/sftpgo/v2/vfs"
|
||||||
|
@ -1999,7 +2000,7 @@ func TestLoginWithDatabaseCredentials(t *testing.T) {
|
||||||
|
|
||||||
user, _, err := httpdtest.AddUser(u, http.StatusCreated)
|
user, _, err := httpdtest.AddUser(u, http.StatusCreated)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, kms.SecretStatusSecretBox, user.FsConfig.GCSConfig.Credentials.GetStatus())
|
assert.Equal(t, sdkkms.SecretStatusSecretBox, user.FsConfig.GCSConfig.Credentials.GetStatus())
|
||||||
assert.NotEmpty(t, user.FsConfig.GCSConfig.Credentials.GetPayload())
|
assert.NotEmpty(t, user.FsConfig.GCSConfig.Credentials.GetPayload())
|
||||||
assert.Empty(t, user.FsConfig.GCSConfig.Credentials.GetAdditionalData())
|
assert.Empty(t, user.FsConfig.GCSConfig.Credentials.GetAdditionalData())
|
||||||
assert.Empty(t, user.FsConfig.GCSConfig.Credentials.GetKey())
|
assert.Empty(t, user.FsConfig.GCSConfig.Credentials.GetKey())
|
||||||
|
@ -2283,7 +2284,7 @@ func TestInteractiveLoginWithPasscode(t *testing.T) {
|
||||||
configName, _, secret, _, err := mfa.GenerateTOTPSecret(mfa.GetAvailableTOTPConfigNames()[0], user.Username)
|
configName, _, secret, _, err := mfa.GenerateTOTPSecret(mfa.GetAvailableTOTPConfigNames()[0], user.Username)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
user.Password = defaultPassword
|
user.Password = defaultPassword
|
||||||
user.Filters.TOTPConfig = sdk.TOTPConfig{
|
user.Filters.TOTPConfig = dataprovider.UserTOTPConfig{
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
ConfigName: configName,
|
ConfigName: configName,
|
||||||
Secret: kms.NewPlainSecret(secret),
|
Secret: kms.NewPlainSecret(secret),
|
||||||
|
@ -2332,7 +2333,7 @@ func TestInteractiveLoginWithPasscode(t *testing.T) {
|
||||||
configName, _, secret, _, err = mfa.GenerateTOTPSecret(mfa.GetAvailableTOTPConfigNames()[0], user.Username)
|
configName, _, secret, _, err = mfa.GenerateTOTPSecret(mfa.GetAvailableTOTPConfigNames()[0], user.Username)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
user.Password = defaultPassword
|
user.Password = defaultPassword
|
||||||
user.Filters.TOTPConfig = sdk.TOTPConfig{
|
user.Filters.TOTPConfig = dataprovider.UserTOTPConfig{
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
ConfigName: configName,
|
ConfigName: configName,
|
||||||
Secret: kms.NewPlainSecret(secret),
|
Secret: kms.NewPlainSecret(secret),
|
||||||
|
@ -2521,14 +2522,14 @@ func TestPreLoginHookPreserveMFAConfig(t *testing.T) {
|
||||||
configName, _, secret, _, err := mfa.GenerateTOTPSecret(mfa.GetAvailableTOTPConfigNames()[0], user.Username)
|
configName, _, secret, _, err := mfa.GenerateTOTPSecret(mfa.GetAvailableTOTPConfigNames()[0], user.Username)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
user.Password = defaultPassword
|
user.Password = defaultPassword
|
||||||
user.Filters.TOTPConfig = sdk.TOTPConfig{
|
user.Filters.TOTPConfig = dataprovider.UserTOTPConfig{
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
ConfigName: configName,
|
ConfigName: configName,
|
||||||
Secret: kms.NewPlainSecret(secret),
|
Secret: kms.NewPlainSecret(secret),
|
||||||
Protocols: []string{common.ProtocolSSH},
|
Protocols: []string{common.ProtocolSSH},
|
||||||
}
|
}
|
||||||
for i := 0; i < 12; i++ {
|
for i := 0; i < 12; i++ {
|
||||||
user.Filters.RecoveryCodes = append(user.Filters.RecoveryCodes, sdk.RecoveryCode{
|
user.Filters.RecoveryCodes = append(user.Filters.RecoveryCodes, dataprovider.RecoveryCode{
|
||||||
Secret: kms.NewPlainSecret(fmt.Sprintf("RC-%v", strings.ToUpper(util.GenerateUniqueID()))),
|
Secret: kms.NewPlainSecret(fmt.Sprintf("RC-%v", strings.ToUpper(util.GenerateUniqueID()))),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -2548,7 +2549,7 @@ func TestPreLoginHookPreserveMFAConfig(t *testing.T) {
|
||||||
assert.True(t, user.Filters.TOTPConfig.Enabled)
|
assert.True(t, user.Filters.TOTPConfig.Enabled)
|
||||||
assert.Equal(t, configName, user.Filters.TOTPConfig.ConfigName)
|
assert.Equal(t, configName, user.Filters.TOTPConfig.ConfigName)
|
||||||
assert.Equal(t, []string{common.ProtocolSSH}, user.Filters.TOTPConfig.Protocols)
|
assert.Equal(t, []string{common.ProtocolSSH}, user.Filters.TOTPConfig.Protocols)
|
||||||
assert.Equal(t, kms.SecretStatusSecretBox, user.Filters.TOTPConfig.Secret.GetStatus())
|
assert.Equal(t, sdkkms.SecretStatusSecretBox, user.Filters.TOTPConfig.Secret.GetStatus())
|
||||||
|
|
||||||
err = os.WriteFile(extAuthPath, getExitCodeScriptContent(0), os.ModePerm)
|
err = os.WriteFile(extAuthPath, getExitCodeScriptContent(0), os.ModePerm)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
@ -2566,7 +2567,7 @@ func TestPreLoginHookPreserveMFAConfig(t *testing.T) {
|
||||||
assert.True(t, user.Filters.TOTPConfig.Enabled)
|
assert.True(t, user.Filters.TOTPConfig.Enabled)
|
||||||
assert.Equal(t, configName, user.Filters.TOTPConfig.ConfigName)
|
assert.Equal(t, configName, user.Filters.TOTPConfig.ConfigName)
|
||||||
assert.Equal(t, []string{common.ProtocolSSH}, user.Filters.TOTPConfig.Protocols)
|
assert.Equal(t, []string{common.ProtocolSSH}, user.Filters.TOTPConfig.Protocols)
|
||||||
assert.Equal(t, kms.SecretStatusSecretBox, user.Filters.TOTPConfig.Secret.GetStatus())
|
assert.Equal(t, sdkkms.SecretStatusSecretBox, user.Filters.TOTPConfig.Secret.GetStatus())
|
||||||
|
|
||||||
_, err = httpdtest.RemoveUser(user, http.StatusOK)
|
_, err = httpdtest.RemoveUser(user, http.StatusOK)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
@ -3463,14 +3464,14 @@ func TestExternalAuthPreserveMFAConfig(t *testing.T) {
|
||||||
configName, _, secret, _, err := mfa.GenerateTOTPSecret(mfa.GetAvailableTOTPConfigNames()[0], user.Username)
|
configName, _, secret, _, err := mfa.GenerateTOTPSecret(mfa.GetAvailableTOTPConfigNames()[0], user.Username)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
user.Password = defaultPassword
|
user.Password = defaultPassword
|
||||||
user.Filters.TOTPConfig = sdk.TOTPConfig{
|
user.Filters.TOTPConfig = dataprovider.UserTOTPConfig{
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
ConfigName: configName,
|
ConfigName: configName,
|
||||||
Secret: kms.NewPlainSecret(secret),
|
Secret: kms.NewPlainSecret(secret),
|
||||||
Protocols: []string{common.ProtocolSSH},
|
Protocols: []string{common.ProtocolSSH},
|
||||||
}
|
}
|
||||||
for i := 0; i < 12; i++ {
|
for i := 0; i < 12; i++ {
|
||||||
user.Filters.RecoveryCodes = append(user.Filters.RecoveryCodes, sdk.RecoveryCode{
|
user.Filters.RecoveryCodes = append(user.Filters.RecoveryCodes, dataprovider.RecoveryCode{
|
||||||
Secret: kms.NewPlainSecret(fmt.Sprintf("RC-%v", strings.ToUpper(util.GenerateUniqueID()))),
|
Secret: kms.NewPlainSecret(fmt.Sprintf("RC-%v", strings.ToUpper(util.GenerateUniqueID()))),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -3490,7 +3491,7 @@ func TestExternalAuthPreserveMFAConfig(t *testing.T) {
|
||||||
assert.True(t, user.Filters.TOTPConfig.Enabled)
|
assert.True(t, user.Filters.TOTPConfig.Enabled)
|
||||||
assert.Equal(t, configName, user.Filters.TOTPConfig.ConfigName)
|
assert.Equal(t, configName, user.Filters.TOTPConfig.ConfigName)
|
||||||
assert.Equal(t, []string{common.ProtocolSSH}, user.Filters.TOTPConfig.Protocols)
|
assert.Equal(t, []string{common.ProtocolSSH}, user.Filters.TOTPConfig.Protocols)
|
||||||
assert.Equal(t, kms.SecretStatusSecretBox, user.Filters.TOTPConfig.Secret.GetStatus())
|
assert.Equal(t, sdkkms.SecretStatusSecretBox, user.Filters.TOTPConfig.Secret.GetStatus())
|
||||||
|
|
||||||
err = os.WriteFile(extAuthPath, getExtAuthScriptContent(u, false, true, ""), os.ModePerm)
|
err = os.WriteFile(extAuthPath, getExtAuthScriptContent(u, false, true, ""), os.ModePerm)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
@ -3508,7 +3509,7 @@ func TestExternalAuthPreserveMFAConfig(t *testing.T) {
|
||||||
assert.True(t, user.Filters.TOTPConfig.Enabled)
|
assert.True(t, user.Filters.TOTPConfig.Enabled)
|
||||||
assert.Equal(t, configName, user.Filters.TOTPConfig.ConfigName)
|
assert.Equal(t, configName, user.Filters.TOTPConfig.ConfigName)
|
||||||
assert.Equal(t, []string{common.ProtocolSSH}, user.Filters.TOTPConfig.Protocols)
|
assert.Equal(t, []string{common.ProtocolSSH}, user.Filters.TOTPConfig.Protocols)
|
||||||
assert.Equal(t, kms.SecretStatusSecretBox, user.Filters.TOTPConfig.Secret.GetStatus())
|
assert.Equal(t, sdkkms.SecretStatusSecretBox, user.Filters.TOTPConfig.Secret.GetStatus())
|
||||||
|
|
||||||
_, err = httpdtest.RemoveUser(user, http.StatusOK)
|
_, err = httpdtest.RemoveUser(user, http.StatusOK)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
@ -4428,18 +4429,18 @@ func TestSFTPLoopSimple(t *testing.T) {
|
||||||
user1.FsConfig.Provider = sdk.SFTPFilesystemProvider
|
user1.FsConfig.Provider = sdk.SFTPFilesystemProvider
|
||||||
user2.FsConfig.Provider = sdk.SFTPFilesystemProvider
|
user2.FsConfig.Provider = sdk.SFTPFilesystemProvider
|
||||||
user1.FsConfig.SFTPConfig = vfs.SFTPFsConfig{
|
user1.FsConfig.SFTPConfig = vfs.SFTPFsConfig{
|
||||||
SFTPFsConfig: sdk.SFTPFsConfig{
|
BaseSFTPFsConfig: sdk.BaseSFTPFsConfig{
|
||||||
Endpoint: sftpServerAddr,
|
Endpoint: sftpServerAddr,
|
||||||
Username: user2.Username,
|
Username: user2.Username,
|
||||||
Password: kms.NewPlainSecret(defaultPassword),
|
|
||||||
},
|
},
|
||||||
|
Password: kms.NewPlainSecret(defaultPassword),
|
||||||
}
|
}
|
||||||
user2.FsConfig.SFTPConfig = vfs.SFTPFsConfig{
|
user2.FsConfig.SFTPConfig = vfs.SFTPFsConfig{
|
||||||
SFTPFsConfig: sdk.SFTPFsConfig{
|
BaseSFTPFsConfig: sdk.BaseSFTPFsConfig{
|
||||||
Endpoint: sftpServerAddr,
|
Endpoint: sftpServerAddr,
|
||||||
Username: user1.Username,
|
Username: user1.Username,
|
||||||
Password: kms.NewPlainSecret(defaultPassword),
|
|
||||||
},
|
},
|
||||||
|
Password: kms.NewPlainSecret(defaultPassword),
|
||||||
}
|
}
|
||||||
user1, resp, err := httpdtest.AddUser(user1, http.StatusCreated)
|
user1, resp, err := httpdtest.AddUser(user1, http.StatusCreated)
|
||||||
assert.NoError(t, err, string(resp))
|
assert.NoError(t, err, string(resp))
|
||||||
|
@ -4487,11 +4488,11 @@ func TestSFTPLoopVirtualFolders(t *testing.T) {
|
||||||
FsConfig: vfs.Filesystem{
|
FsConfig: vfs.Filesystem{
|
||||||
Provider: sdk.SFTPFilesystemProvider,
|
Provider: sdk.SFTPFilesystemProvider,
|
||||||
SFTPConfig: vfs.SFTPFsConfig{
|
SFTPConfig: vfs.SFTPFsConfig{
|
||||||
SFTPFsConfig: sdk.SFTPFsConfig{
|
BaseSFTPFsConfig: sdk.BaseSFTPFsConfig{
|
||||||
Endpoint: sftpServerAddr,
|
Endpoint: sftpServerAddr,
|
||||||
Username: user2.Username,
|
Username: user2.Username,
|
||||||
Password: kms.NewPlainSecret(defaultPassword),
|
|
||||||
},
|
},
|
||||||
|
Password: kms.NewPlainSecret(defaultPassword),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -4500,19 +4501,19 @@ func TestSFTPLoopVirtualFolders(t *testing.T) {
|
||||||
|
|
||||||
user2.FsConfig.Provider = sdk.SFTPFilesystemProvider
|
user2.FsConfig.Provider = sdk.SFTPFilesystemProvider
|
||||||
user2.FsConfig.SFTPConfig = vfs.SFTPFsConfig{
|
user2.FsConfig.SFTPConfig = vfs.SFTPFsConfig{
|
||||||
SFTPFsConfig: sdk.SFTPFsConfig{
|
BaseSFTPFsConfig: sdk.BaseSFTPFsConfig{
|
||||||
Endpoint: sftpServerAddr,
|
Endpoint: sftpServerAddr,
|
||||||
Username: user1.Username,
|
Username: user1.Username,
|
||||||
Password: kms.NewPlainSecret(defaultPassword),
|
|
||||||
},
|
},
|
||||||
|
Password: kms.NewPlainSecret(defaultPassword),
|
||||||
}
|
}
|
||||||
user3.FsConfig.Provider = sdk.SFTPFilesystemProvider
|
user3.FsConfig.Provider = sdk.SFTPFilesystemProvider
|
||||||
user3.FsConfig.SFTPConfig = vfs.SFTPFsConfig{
|
user3.FsConfig.SFTPConfig = vfs.SFTPFsConfig{
|
||||||
SFTPFsConfig: sdk.SFTPFsConfig{
|
BaseSFTPFsConfig: sdk.BaseSFTPFsConfig{
|
||||||
Endpoint: sftpServerAddr,
|
Endpoint: sftpServerAddr,
|
||||||
Username: user1.Username,
|
Username: user1.Username,
|
||||||
Password: kms.NewPlainSecret(defaultPassword),
|
|
||||||
},
|
},
|
||||||
|
Password: kms.NewPlainSecret(defaultPassword),
|
||||||
}
|
}
|
||||||
|
|
||||||
user1, resp, err := httpdtest.AddUser(user1, http.StatusCreated)
|
user1, resp, err := httpdtest.AddUser(user1, http.StatusCreated)
|
||||||
|
@ -4546,11 +4547,11 @@ func TestSFTPLoopVirtualFolders(t *testing.T) {
|
||||||
FsConfig: vfs.Filesystem{
|
FsConfig: vfs.Filesystem{
|
||||||
Provider: sdk.SFTPFilesystemProvider,
|
Provider: sdk.SFTPFilesystemProvider,
|
||||||
SFTPConfig: vfs.SFTPFsConfig{
|
SFTPConfig: vfs.SFTPFsConfig{
|
||||||
SFTPFsConfig: sdk.SFTPFsConfig{
|
BaseSFTPFsConfig: sdk.BaseSFTPFsConfig{
|
||||||
Endpoint: sftpServerAddr,
|
Endpoint: sftpServerAddr,
|
||||||
Username: user3.Username,
|
Username: user3.Username,
|
||||||
Password: kms.NewPlainSecret(defaultPassword),
|
|
||||||
},
|
},
|
||||||
|
Password: kms.NewPlainSecret(defaultPassword),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -4602,9 +4603,7 @@ func TestNestedVirtualFolders(t *testing.T) {
|
||||||
FsConfig: vfs.Filesystem{
|
FsConfig: vfs.Filesystem{
|
||||||
Provider: sdk.CryptedFilesystemProvider,
|
Provider: sdk.CryptedFilesystemProvider,
|
||||||
CryptConfig: vfs.CryptFsConfig{
|
CryptConfig: vfs.CryptFsConfig{
|
||||||
CryptFsConfig: sdk.CryptFsConfig{
|
Passphrase: kms.NewPlainSecret(defaultPassword),
|
||||||
Passphrase: kms.NewPlainSecret(defaultPassword),
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
MappedPath: mappedPathCrypt,
|
MappedPath: mappedPathCrypt,
|
||||||
|
@ -7222,24 +7221,24 @@ func TestRelativePaths(t *testing.T) {
|
||||||
filesystems := []vfs.Fs{vfs.NewOsFs("", user.GetHomeDir(), "")}
|
filesystems := []vfs.Fs{vfs.NewOsFs("", user.GetHomeDir(), "")}
|
||||||
keyPrefix := strings.TrimPrefix(user.GetHomeDir(), "/") + "/"
|
keyPrefix := strings.TrimPrefix(user.GetHomeDir(), "/") + "/"
|
||||||
s3config := vfs.S3FsConfig{
|
s3config := vfs.S3FsConfig{
|
||||||
S3FsConfig: sdk.S3FsConfig{
|
BaseS3FsConfig: sdk.BaseS3FsConfig{
|
||||||
KeyPrefix: keyPrefix,
|
KeyPrefix: keyPrefix,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
s3fs, _ := vfs.NewS3Fs("", user.GetHomeDir(), "", s3config)
|
s3fs, _ := vfs.NewS3Fs("", user.GetHomeDir(), "", s3config)
|
||||||
gcsConfig := vfs.GCSFsConfig{
|
gcsConfig := vfs.GCSFsConfig{
|
||||||
GCSFsConfig: sdk.GCSFsConfig{
|
BaseGCSFsConfig: sdk.BaseGCSFsConfig{
|
||||||
KeyPrefix: keyPrefix,
|
KeyPrefix: keyPrefix,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
gcsfs, _ := vfs.NewGCSFs("", user.GetHomeDir(), "", gcsConfig)
|
gcsfs, _ := vfs.NewGCSFs("", user.GetHomeDir(), "", gcsConfig)
|
||||||
sftpconfig := vfs.SFTPFsConfig{
|
sftpconfig := vfs.SFTPFsConfig{
|
||||||
SFTPFsConfig: sdk.SFTPFsConfig{
|
BaseSFTPFsConfig: sdk.BaseSFTPFsConfig{
|
||||||
Endpoint: sftpServerAddr,
|
Endpoint: sftpServerAddr,
|
||||||
Username: defaultUsername,
|
Username: defaultUsername,
|
||||||
Password: kms.NewPlainSecret(defaultPassword),
|
|
||||||
Prefix: keyPrefix,
|
Prefix: keyPrefix,
|
||||||
},
|
},
|
||||||
|
Password: kms.NewPlainSecret(defaultPassword),
|
||||||
}
|
}
|
||||||
sftpfs, _ := vfs.NewSFTPFs("", "", os.TempDir(), []string{user.Username}, sftpconfig)
|
sftpfs, _ := vfs.NewSFTPFs("", "", os.TempDir(), []string{user.Username}, sftpconfig)
|
||||||
if runtime.GOOS != osWindows {
|
if runtime.GOOS != osWindows {
|
||||||
|
@ -7287,7 +7286,7 @@ func TestResolvePaths(t *testing.T) {
|
||||||
filesystems := []vfs.Fs{vfs.NewOsFs("", user.GetHomeDir(), "")}
|
filesystems := []vfs.Fs{vfs.NewOsFs("", user.GetHomeDir(), "")}
|
||||||
keyPrefix := strings.TrimPrefix(user.GetHomeDir(), "/") + "/"
|
keyPrefix := strings.TrimPrefix(user.GetHomeDir(), "/") + "/"
|
||||||
s3config := vfs.S3FsConfig{
|
s3config := vfs.S3FsConfig{
|
||||||
S3FsConfig: sdk.S3FsConfig{
|
BaseS3FsConfig: sdk.BaseS3FsConfig{
|
||||||
KeyPrefix: keyPrefix,
|
KeyPrefix: keyPrefix,
|
||||||
Bucket: "bucket",
|
Bucket: "bucket",
|
||||||
Region: "us-east-1",
|
Region: "us-east-1",
|
||||||
|
@ -7298,7 +7297,7 @@ func TestResolvePaths(t *testing.T) {
|
||||||
s3fs, err := vfs.NewS3Fs("", user.GetHomeDir(), "", s3config)
|
s3fs, err := vfs.NewS3Fs("", user.GetHomeDir(), "", s3config)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
gcsConfig := vfs.GCSFsConfig{
|
gcsConfig := vfs.GCSFsConfig{
|
||||||
GCSFsConfig: sdk.GCSFsConfig{
|
BaseGCSFsConfig: sdk.BaseGCSFsConfig{
|
||||||
KeyPrefix: keyPrefix,
|
KeyPrefix: keyPrefix,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -7401,8 +7400,10 @@ func TestFilterFilePatterns(t *testing.T) {
|
||||||
AllowedPatterns: []string{"*.jpg", "*.png"},
|
AllowedPatterns: []string{"*.jpg", "*.png"},
|
||||||
DeniedPatterns: []string{"*.pdf"},
|
DeniedPatterns: []string{"*.pdf"},
|
||||||
}
|
}
|
||||||
filters := sdk.UserFilters{
|
filters := dataprovider.UserFilters{
|
||||||
FilePatterns: []sdk.PatternsFilter{pattern},
|
BaseUserFilters: sdk.BaseUserFilters{
|
||||||
|
FilePatterns: []sdk.PatternsFilter{pattern},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
user.Filters = filters
|
user.Filters = filters
|
||||||
assert.True(t, user.IsFileAllowed("/test/test.jPg"))
|
assert.True(t, user.IsFileAllowed("/test/test.jPg"))
|
||||||
|
@ -8482,9 +8483,7 @@ func TestSSHRemoveCryptFs(t *testing.T) {
|
||||||
FsConfig: vfs.Filesystem{
|
FsConfig: vfs.Filesystem{
|
||||||
Provider: sdk.CryptedFilesystemProvider,
|
Provider: sdk.CryptedFilesystemProvider,
|
||||||
CryptConfig: vfs.CryptFsConfig{
|
CryptConfig: vfs.CryptFsConfig{
|
||||||
CryptFsConfig: sdk.CryptFsConfig{
|
Passphrase: kms.NewPlainSecret(defaultPassword),
|
||||||
Passphrase: kms.NewPlainSecret(defaultPassword),
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -9070,11 +9069,11 @@ func TestSCPNestedFolders(t *testing.T) {
|
||||||
FsConfig: vfs.Filesystem{
|
FsConfig: vfs.Filesystem{
|
||||||
Provider: sdk.SFTPFilesystemProvider,
|
Provider: sdk.SFTPFilesystemProvider,
|
||||||
SFTPConfig: vfs.SFTPFsConfig{
|
SFTPConfig: vfs.SFTPFsConfig{
|
||||||
SFTPFsConfig: sdk.SFTPFsConfig{
|
BaseSFTPFsConfig: sdk.BaseSFTPFsConfig{
|
||||||
Endpoint: sftpServerAddr,
|
Endpoint: sftpServerAddr,
|
||||||
Username: baseUser.Username,
|
Username: baseUser.Username,
|
||||||
Password: kms.NewPlainSecret(defaultPassword),
|
|
||||||
},
|
},
|
||||||
|
Password: kms.NewPlainSecret(defaultPassword),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -9089,9 +9088,7 @@ func TestSCPNestedFolders(t *testing.T) {
|
||||||
FsConfig: vfs.Filesystem{
|
FsConfig: vfs.Filesystem{
|
||||||
Provider: sdk.CryptedFilesystemProvider,
|
Provider: sdk.CryptedFilesystemProvider,
|
||||||
CryptConfig: vfs.CryptFsConfig{
|
CryptConfig: vfs.CryptFsConfig{
|
||||||
CryptFsConfig: sdk.CryptFsConfig{
|
Passphrase: kms.NewPlainSecret(defaultPassword),
|
||||||
Passphrase: kms.NewPlainSecret(defaultPassword),
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
MappedPath: mappedPathCrypt,
|
MappedPath: mappedPathCrypt,
|
||||||
|
|
|
@ -3,8 +3,8 @@ package vfs
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/drakkan/sftpgo/v2/kms"
|
||||||
"github.com/drakkan/sftpgo/v2/sdk"
|
"github.com/drakkan/sftpgo/v2/sdk"
|
||||||
"github.com/drakkan/sftpgo/v2/sdk/kms"
|
|
||||||
"github.com/drakkan/sftpgo/v2/util"
|
"github.com/drakkan/sftpgo/v2/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -228,11 +228,10 @@ func (f *Filesystem) GetACopy() Filesystem {
|
||||||
fs := Filesystem{
|
fs := Filesystem{
|
||||||
Provider: f.Provider,
|
Provider: f.Provider,
|
||||||
S3Config: S3FsConfig{
|
S3Config: S3FsConfig{
|
||||||
S3FsConfig: sdk.S3FsConfig{
|
BaseS3FsConfig: sdk.BaseS3FsConfig{
|
||||||
Bucket: f.S3Config.Bucket,
|
Bucket: f.S3Config.Bucket,
|
||||||
Region: f.S3Config.Region,
|
Region: f.S3Config.Region,
|
||||||
AccessKey: f.S3Config.AccessKey,
|
AccessKey: f.S3Config.AccessKey,
|
||||||
AccessSecret: f.S3Config.AccessSecret.Clone(),
|
|
||||||
Endpoint: f.S3Config.Endpoint,
|
Endpoint: f.S3Config.Endpoint,
|
||||||
StorageClass: f.S3Config.StorageClass,
|
StorageClass: f.S3Config.StorageClass,
|
||||||
ACL: f.S3Config.ACL,
|
ACL: f.S3Config.ACL,
|
||||||
|
@ -244,47 +243,46 @@ func (f *Filesystem) GetACopy() Filesystem {
|
||||||
DownloadPartMaxTime: f.S3Config.DownloadPartMaxTime,
|
DownloadPartMaxTime: f.S3Config.DownloadPartMaxTime,
|
||||||
ForcePathStyle: f.S3Config.ForcePathStyle,
|
ForcePathStyle: f.S3Config.ForcePathStyle,
|
||||||
},
|
},
|
||||||
|
AccessSecret: f.S3Config.AccessSecret.Clone(),
|
||||||
},
|
},
|
||||||
GCSConfig: GCSFsConfig{
|
GCSConfig: GCSFsConfig{
|
||||||
GCSFsConfig: sdk.GCSFsConfig{
|
BaseGCSFsConfig: sdk.BaseGCSFsConfig{
|
||||||
Bucket: f.GCSConfig.Bucket,
|
Bucket: f.GCSConfig.Bucket,
|
||||||
CredentialFile: f.GCSConfig.CredentialFile,
|
CredentialFile: f.GCSConfig.CredentialFile,
|
||||||
Credentials: f.GCSConfig.Credentials.Clone(),
|
|
||||||
AutomaticCredentials: f.GCSConfig.AutomaticCredentials,
|
AutomaticCredentials: f.GCSConfig.AutomaticCredentials,
|
||||||
StorageClass: f.GCSConfig.StorageClass,
|
StorageClass: f.GCSConfig.StorageClass,
|
||||||
ACL: f.GCSConfig.ACL,
|
ACL: f.GCSConfig.ACL,
|
||||||
KeyPrefix: f.GCSConfig.KeyPrefix,
|
KeyPrefix: f.GCSConfig.KeyPrefix,
|
||||||
},
|
},
|
||||||
|
Credentials: f.GCSConfig.Credentials.Clone(),
|
||||||
},
|
},
|
||||||
AzBlobConfig: AzBlobFsConfig{
|
AzBlobConfig: AzBlobFsConfig{
|
||||||
AzBlobFsConfig: sdk.AzBlobFsConfig{
|
BaseAzBlobFsConfig: sdk.BaseAzBlobFsConfig{
|
||||||
Container: f.AzBlobConfig.Container,
|
Container: f.AzBlobConfig.Container,
|
||||||
AccountName: f.AzBlobConfig.AccountName,
|
AccountName: f.AzBlobConfig.AccountName,
|
||||||
AccountKey: f.AzBlobConfig.AccountKey.Clone(),
|
|
||||||
Endpoint: f.AzBlobConfig.Endpoint,
|
Endpoint: f.AzBlobConfig.Endpoint,
|
||||||
SASURL: f.AzBlobConfig.SASURL.Clone(),
|
|
||||||
KeyPrefix: f.AzBlobConfig.KeyPrefix,
|
KeyPrefix: f.AzBlobConfig.KeyPrefix,
|
||||||
UploadPartSize: f.AzBlobConfig.UploadPartSize,
|
UploadPartSize: f.AzBlobConfig.UploadPartSize,
|
||||||
UploadConcurrency: f.AzBlobConfig.UploadConcurrency,
|
UploadConcurrency: f.AzBlobConfig.UploadConcurrency,
|
||||||
UseEmulator: f.AzBlobConfig.UseEmulator,
|
UseEmulator: f.AzBlobConfig.UseEmulator,
|
||||||
AccessTier: f.AzBlobConfig.AccessTier,
|
AccessTier: f.AzBlobConfig.AccessTier,
|
||||||
},
|
},
|
||||||
|
AccountKey: f.AzBlobConfig.AccountKey.Clone(),
|
||||||
|
SASURL: f.AzBlobConfig.SASURL.Clone(),
|
||||||
},
|
},
|
||||||
CryptConfig: CryptFsConfig{
|
CryptConfig: CryptFsConfig{
|
||||||
CryptFsConfig: sdk.CryptFsConfig{
|
Passphrase: f.CryptConfig.Passphrase.Clone(),
|
||||||
Passphrase: f.CryptConfig.Passphrase.Clone(),
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
SFTPConfig: SFTPFsConfig{
|
SFTPConfig: SFTPFsConfig{
|
||||||
SFTPFsConfig: sdk.SFTPFsConfig{
|
BaseSFTPFsConfig: sdk.BaseSFTPFsConfig{
|
||||||
Endpoint: f.SFTPConfig.Endpoint,
|
Endpoint: f.SFTPConfig.Endpoint,
|
||||||
Username: f.SFTPConfig.Username,
|
Username: f.SFTPConfig.Username,
|
||||||
Password: f.SFTPConfig.Password.Clone(),
|
|
||||||
PrivateKey: f.SFTPConfig.PrivateKey.Clone(),
|
|
||||||
Prefix: f.SFTPConfig.Prefix,
|
Prefix: f.SFTPConfig.Prefix,
|
||||||
DisableCouncurrentReads: f.SFTPConfig.DisableCouncurrentReads,
|
DisableCouncurrentReads: f.SFTPConfig.DisableCouncurrentReads,
|
||||||
BufferSize: f.SFTPConfig.BufferSize,
|
BufferSize: f.SFTPConfig.BufferSize,
|
||||||
},
|
},
|
||||||
|
Password: f.SFTPConfig.Password.Clone(),
|
||||||
|
PrivateKey: f.SFTPConfig.PrivateKey.Clone(),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
if len(f.SFTPConfig.Fingerprints) > 0 {
|
if len(f.SFTPConfig.Fingerprints) > 0 {
|
||||||
|
|
|
@ -23,10 +23,10 @@ import (
|
||||||
"google.golang.org/api/iterator"
|
"google.golang.org/api/iterator"
|
||||||
"google.golang.org/api/option"
|
"google.golang.org/api/option"
|
||||||
|
|
||||||
|
"github.com/drakkan/sftpgo/v2/kms"
|
||||||
"github.com/drakkan/sftpgo/v2/logger"
|
"github.com/drakkan/sftpgo/v2/logger"
|
||||||
"github.com/drakkan/sftpgo/v2/metric"
|
"github.com/drakkan/sftpgo/v2/metric"
|
||||||
"github.com/drakkan/sftpgo/v2/plugin"
|
"github.com/drakkan/sftpgo/v2/plugin"
|
||||||
"github.com/drakkan/sftpgo/v2/sdk/kms"
|
|
||||||
"github.com/drakkan/sftpgo/v2/util"
|
"github.com/drakkan/sftpgo/v2/util"
|
||||||
"github.com/drakkan/sftpgo/v2/version"
|
"github.com/drakkan/sftpgo/v2/version"
|
||||||
)
|
)
|
||||||
|
|
|
@ -19,9 +19,9 @@ import (
|
||||||
"github.com/rs/xid"
|
"github.com/rs/xid"
|
||||||
"golang.org/x/crypto/ssh"
|
"golang.org/x/crypto/ssh"
|
||||||
|
|
||||||
|
"github.com/drakkan/sftpgo/v2/kms"
|
||||||
"github.com/drakkan/sftpgo/v2/logger"
|
"github.com/drakkan/sftpgo/v2/logger"
|
||||||
"github.com/drakkan/sftpgo/v2/sdk"
|
"github.com/drakkan/sftpgo/v2/sdk"
|
||||||
"github.com/drakkan/sftpgo/v2/sdk/kms"
|
|
||||||
"github.com/drakkan/sftpgo/v2/util"
|
"github.com/drakkan/sftpgo/v2/util"
|
||||||
"github.com/drakkan/sftpgo/v2/version"
|
"github.com/drakkan/sftpgo/v2/version"
|
||||||
)
|
)
|
||||||
|
@ -36,8 +36,10 @@ var ErrSFTPLoop = errors.New("SFTP loop or nested local SFTP folders detected")
|
||||||
|
|
||||||
// SFTPFsConfig defines the configuration for SFTP based filesystem
|
// SFTPFsConfig defines the configuration for SFTP based filesystem
|
||||||
type SFTPFsConfig struct {
|
type SFTPFsConfig struct {
|
||||||
sdk.SFTPFsConfig
|
sdk.BaseSFTPFsConfig
|
||||||
forbiddenSelfUsernames []string `json:"-"`
|
Password *kms.Secret `json:"password,omitempty"`
|
||||||
|
PrivateKey *kms.Secret `json:"private_key,omitempty"`
|
||||||
|
forbiddenSelfUsernames []string `json:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// HideConfidentialData hides confidential data
|
// HideConfidentialData hides confidential data
|
||||||
|
|
17
vfs/vfs.go
17
vfs/vfs.go
|
@ -16,10 +16,10 @@ import (
|
||||||
"github.com/eikenb/pipeat"
|
"github.com/eikenb/pipeat"
|
||||||
"github.com/pkg/sftp"
|
"github.com/pkg/sftp"
|
||||||
|
|
||||||
|
"github.com/drakkan/sftpgo/v2/kms"
|
||||||
"github.com/drakkan/sftpgo/v2/logger"
|
"github.com/drakkan/sftpgo/v2/logger"
|
||||||
"github.com/drakkan/sftpgo/v2/plugin"
|
"github.com/drakkan/sftpgo/v2/plugin"
|
||||||
"github.com/drakkan/sftpgo/v2/sdk"
|
"github.com/drakkan/sftpgo/v2/sdk"
|
||||||
"github.com/drakkan/sftpgo/v2/sdk/kms"
|
|
||||||
"github.com/drakkan/sftpgo/v2/sdk/plugin/metadata"
|
"github.com/drakkan/sftpgo/v2/sdk/plugin/metadata"
|
||||||
"github.com/drakkan/sftpgo/v2/util"
|
"github.com/drakkan/sftpgo/v2/util"
|
||||||
)
|
)
|
||||||
|
@ -150,7 +150,8 @@ func (q *QuotaCheckResult) GetRemainingFiles() int {
|
||||||
|
|
||||||
// S3FsConfig defines the configuration for S3 based filesystem
|
// S3FsConfig defines the configuration for S3 based filesystem
|
||||||
type S3FsConfig struct {
|
type S3FsConfig struct {
|
||||||
sdk.S3FsConfig
|
sdk.BaseS3FsConfig
|
||||||
|
AccessSecret *kms.Secret `json:"access_secret,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// HideConfidentialData hides confidential data
|
// HideConfidentialData hides confidential data
|
||||||
|
@ -287,7 +288,8 @@ func (c *S3FsConfig) Validate() error {
|
||||||
|
|
||||||
// GCSFsConfig defines the configuration for Google Cloud Storage based filesystem
|
// GCSFsConfig defines the configuration for Google Cloud Storage based filesystem
|
||||||
type GCSFsConfig struct {
|
type GCSFsConfig struct {
|
||||||
sdk.GCSFsConfig
|
sdk.BaseGCSFsConfig
|
||||||
|
Credentials *kms.Secret `json:"credentials,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// HideConfidentialData hides confidential data
|
// HideConfidentialData hides confidential data
|
||||||
|
@ -358,7 +360,12 @@ func (c *GCSFsConfig) Validate(credentialsFilePath string) error {
|
||||||
|
|
||||||
// AzBlobFsConfig defines the configuration for Azure Blob Storage based filesystem
|
// AzBlobFsConfig defines the configuration for Azure Blob Storage based filesystem
|
||||||
type AzBlobFsConfig struct {
|
type AzBlobFsConfig struct {
|
||||||
sdk.AzBlobFsConfig
|
sdk.BaseAzBlobFsConfig
|
||||||
|
// Storage Account Key leave blank to use SAS URL.
|
||||||
|
// The access key is stored encrypted based on the kms configuration
|
||||||
|
AccountKey *kms.Secret `json:"account_key,omitempty"`
|
||||||
|
// Shared access signature URL, leave blank if using account/key
|
||||||
|
SASURL *kms.Secret `json:"sas_url,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// HideConfidentialData hides confidential data
|
// HideConfidentialData hides confidential data
|
||||||
|
@ -489,7 +496,7 @@ func (c *AzBlobFsConfig) Validate() error {
|
||||||
|
|
||||||
// CryptFsConfig defines the configuration to store local files as encrypted
|
// CryptFsConfig defines the configuration to store local files as encrypted
|
||||||
type CryptFsConfig struct {
|
type CryptFsConfig struct {
|
||||||
sdk.CryptFsConfig
|
Passphrase *kms.Secret `json:"passphrase,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// HideConfidentialData hides confidential data
|
// HideConfidentialData hides confidential data
|
||||||
|
|
|
@ -22,8 +22,8 @@ import (
|
||||||
|
|
||||||
"github.com/drakkan/sftpgo/v2/common"
|
"github.com/drakkan/sftpgo/v2/common"
|
||||||
"github.com/drakkan/sftpgo/v2/dataprovider"
|
"github.com/drakkan/sftpgo/v2/dataprovider"
|
||||||
|
"github.com/drakkan/sftpgo/v2/kms"
|
||||||
"github.com/drakkan/sftpgo/v2/sdk"
|
"github.com/drakkan/sftpgo/v2/sdk"
|
||||||
"github.com/drakkan/sftpgo/v2/sdk/kms"
|
|
||||||
"github.com/drakkan/sftpgo/v2/util"
|
"github.com/drakkan/sftpgo/v2/util"
|
||||||
"github.com/drakkan/sftpgo/v2/vfs"
|
"github.com/drakkan/sftpgo/v2/vfs"
|
||||||
)
|
)
|
||||||
|
|
|
@ -31,9 +31,10 @@ import (
|
||||||
"github.com/drakkan/sftpgo/v2/dataprovider"
|
"github.com/drakkan/sftpgo/v2/dataprovider"
|
||||||
"github.com/drakkan/sftpgo/v2/httpclient"
|
"github.com/drakkan/sftpgo/v2/httpclient"
|
||||||
"github.com/drakkan/sftpgo/v2/httpdtest"
|
"github.com/drakkan/sftpgo/v2/httpdtest"
|
||||||
|
"github.com/drakkan/sftpgo/v2/kms"
|
||||||
"github.com/drakkan/sftpgo/v2/logger"
|
"github.com/drakkan/sftpgo/v2/logger"
|
||||||
"github.com/drakkan/sftpgo/v2/sdk"
|
"github.com/drakkan/sftpgo/v2/sdk"
|
||||||
"github.com/drakkan/sftpgo/v2/sdk/kms"
|
sdkkms "github.com/drakkan/sftpgo/v2/sdk/kms"
|
||||||
"github.com/drakkan/sftpgo/v2/sftpd"
|
"github.com/drakkan/sftpgo/v2/sftpd"
|
||||||
"github.com/drakkan/sftpgo/v2/vfs"
|
"github.com/drakkan/sftpgo/v2/vfs"
|
||||||
"github.com/drakkan/sftpgo/v2/webdavd"
|
"github.com/drakkan/sftpgo/v2/webdavd"
|
||||||
|
@ -1621,7 +1622,7 @@ func TestLoginWithDatabaseCredentials(t *testing.T) {
|
||||||
|
|
||||||
user, _, err := httpdtest.AddUser(u, http.StatusCreated)
|
user, _, err := httpdtest.AddUser(u, http.StatusCreated)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, kms.SecretStatusSecretBox, user.FsConfig.GCSConfig.Credentials.GetStatus())
|
assert.Equal(t, sdkkms.SecretStatusSecretBox, user.FsConfig.GCSConfig.Credentials.GetStatus())
|
||||||
assert.NotEmpty(t, user.FsConfig.GCSConfig.Credentials.GetPayload())
|
assert.NotEmpty(t, user.FsConfig.GCSConfig.Credentials.GetPayload())
|
||||||
assert.Empty(t, user.FsConfig.GCSConfig.Credentials.GetAdditionalData())
|
assert.Empty(t, user.FsConfig.GCSConfig.Credentials.GetAdditionalData())
|
||||||
assert.Empty(t, user.FsConfig.GCSConfig.Credentials.GetKey())
|
assert.Empty(t, user.FsConfig.GCSConfig.Credentials.GetKey())
|
||||||
|
@ -2443,11 +2444,11 @@ func TestSFTPLoopVirtualFolders(t *testing.T) {
|
||||||
FsConfig: vfs.Filesystem{
|
FsConfig: vfs.Filesystem{
|
||||||
Provider: sdk.SFTPFilesystemProvider,
|
Provider: sdk.SFTPFilesystemProvider,
|
||||||
SFTPConfig: vfs.SFTPFsConfig{
|
SFTPConfig: vfs.SFTPFsConfig{
|
||||||
SFTPFsConfig: sdk.SFTPFsConfig{
|
BaseSFTPFsConfig: sdk.BaseSFTPFsConfig{
|
||||||
Endpoint: sftpServerAddr,
|
Endpoint: sftpServerAddr,
|
||||||
Username: user2.Username,
|
Username: user2.Username,
|
||||||
Password: kms.NewPlainSecret(defaultPassword),
|
|
||||||
},
|
},
|
||||||
|
Password: kms.NewPlainSecret(defaultPassword),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -2455,11 +2456,11 @@ func TestSFTPLoopVirtualFolders(t *testing.T) {
|
||||||
})
|
})
|
||||||
user2.FsConfig.Provider = sdk.SFTPFilesystemProvider
|
user2.FsConfig.Provider = sdk.SFTPFilesystemProvider
|
||||||
user2.FsConfig.SFTPConfig = vfs.SFTPFsConfig{
|
user2.FsConfig.SFTPConfig = vfs.SFTPFsConfig{
|
||||||
SFTPFsConfig: sdk.SFTPFsConfig{
|
BaseSFTPFsConfig: sdk.BaseSFTPFsConfig{
|
||||||
Endpoint: sftpServerAddr,
|
Endpoint: sftpServerAddr,
|
||||||
Username: user1.Username,
|
Username: user1.Username,
|
||||||
Password: kms.NewPlainSecret(defaultPassword),
|
|
||||||
},
|
},
|
||||||
|
Password: kms.NewPlainSecret(defaultPassword),
|
||||||
}
|
}
|
||||||
|
|
||||||
user1, resp, err := httpdtest.AddUser(user1, http.StatusCreated)
|
user1, resp, err := httpdtest.AddUser(user1, http.StatusCreated)
|
||||||
|
@ -2506,9 +2507,7 @@ func TestNestedVirtualFolders(t *testing.T) {
|
||||||
FsConfig: vfs.Filesystem{
|
FsConfig: vfs.Filesystem{
|
||||||
Provider: sdk.CryptedFilesystemProvider,
|
Provider: sdk.CryptedFilesystemProvider,
|
||||||
CryptConfig: vfs.CryptFsConfig{
|
CryptConfig: vfs.CryptFsConfig{
|
||||||
CryptFsConfig: sdk.CryptFsConfig{
|
Passphrase: kms.NewPlainSecret(defaultPassword),
|
||||||
Passphrase: kms.NewPlainSecret(defaultPassword),
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
MappedPath: mappedPathCrypt,
|
MappedPath: mappedPathCrypt,
|
||||||
|
|
Loading…
Reference in a new issue