filesystem.go 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303
  1. // Copyright (C) 2019-2022 Nicola Murino
  2. //
  3. // This program is free software: you can redistribute it and/or modify
  4. // it under the terms of the GNU Affero General Public License as published
  5. // by the Free Software Foundation, version 3.
  6. //
  7. // This program is distributed in the hope that it will be useful,
  8. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. // GNU Affero General Public License for more details.
  11. //
  12. // You should have received a copy of the GNU Affero General Public License
  13. // along with this program. If not, see <https://www.gnu.org/licenses/>.
  14. package vfs
  15. import (
  16. "github.com/sftpgo/sdk"
  17. "github.com/drakkan/sftpgo/v2/kms"
  18. )
  19. // Filesystem defines filesystem details
  20. type Filesystem struct {
  21. RedactedSecret string `json:"-"`
  22. Provider sdk.FilesystemProvider `json:"provider"`
  23. S3Config S3FsConfig `json:"s3config,omitempty"`
  24. GCSConfig GCSFsConfig `json:"gcsconfig,omitempty"`
  25. AzBlobConfig AzBlobFsConfig `json:"azblobconfig,omitempty"`
  26. CryptConfig CryptFsConfig `json:"cryptconfig,omitempty"`
  27. SFTPConfig SFTPFsConfig `json:"sftpconfig,omitempty"`
  28. }
  29. // SetEmptySecrets sets the secrets to empty
  30. func (f *Filesystem) SetEmptySecrets() {
  31. f.S3Config.AccessSecret = kms.NewEmptySecret()
  32. f.GCSConfig.Credentials = kms.NewEmptySecret()
  33. f.AzBlobConfig.AccountKey = kms.NewEmptySecret()
  34. f.AzBlobConfig.SASURL = kms.NewEmptySecret()
  35. f.CryptConfig.Passphrase = kms.NewEmptySecret()
  36. f.SFTPConfig.Password = kms.NewEmptySecret()
  37. f.SFTPConfig.PrivateKey = kms.NewEmptySecret()
  38. f.SFTPConfig.KeyPassphrase = kms.NewEmptySecret()
  39. }
  40. // SetEmptySecretsIfNil sets the secrets to empty if nil
  41. func (f *Filesystem) SetEmptySecretsIfNil() {
  42. if f.S3Config.AccessSecret == nil {
  43. f.S3Config.AccessSecret = kms.NewEmptySecret()
  44. }
  45. if f.GCSConfig.Credentials == nil {
  46. f.GCSConfig.Credentials = kms.NewEmptySecret()
  47. }
  48. if f.AzBlobConfig.AccountKey == nil {
  49. f.AzBlobConfig.AccountKey = kms.NewEmptySecret()
  50. }
  51. if f.AzBlobConfig.SASURL == nil {
  52. f.AzBlobConfig.SASURL = kms.NewEmptySecret()
  53. }
  54. if f.CryptConfig.Passphrase == nil {
  55. f.CryptConfig.Passphrase = kms.NewEmptySecret()
  56. }
  57. if f.SFTPConfig.Password == nil {
  58. f.SFTPConfig.Password = kms.NewEmptySecret()
  59. }
  60. if f.SFTPConfig.PrivateKey == nil {
  61. f.SFTPConfig.PrivateKey = kms.NewEmptySecret()
  62. }
  63. if f.SFTPConfig.KeyPassphrase == nil {
  64. f.SFTPConfig.KeyPassphrase = kms.NewEmptySecret()
  65. }
  66. }
  67. // SetNilSecretsIfEmpty set the secrets to nil if empty.
  68. // This is useful before rendering as JSON so the empty fields
  69. // will not be serialized.
  70. func (f *Filesystem) SetNilSecretsIfEmpty() {
  71. if f.S3Config.AccessSecret != nil && f.S3Config.AccessSecret.IsEmpty() {
  72. f.S3Config.AccessSecret = nil
  73. }
  74. if f.GCSConfig.Credentials != nil && f.GCSConfig.Credentials.IsEmpty() {
  75. f.GCSConfig.Credentials = nil
  76. }
  77. if f.AzBlobConfig.AccountKey != nil && f.AzBlobConfig.AccountKey.IsEmpty() {
  78. f.AzBlobConfig.AccountKey = nil
  79. }
  80. if f.AzBlobConfig.SASURL != nil && f.AzBlobConfig.SASURL.IsEmpty() {
  81. f.AzBlobConfig.SASURL = nil
  82. }
  83. if f.CryptConfig.Passphrase != nil && f.CryptConfig.Passphrase.IsEmpty() {
  84. f.CryptConfig.Passphrase = nil
  85. }
  86. f.SFTPConfig.setNilSecretsIfEmpty()
  87. }
  88. // IsEqual returns true if the fs is equal to other
  89. func (f *Filesystem) IsEqual(other *Filesystem) bool {
  90. if f.Provider != other.Provider {
  91. return false
  92. }
  93. switch f.Provider {
  94. case sdk.S3FilesystemProvider:
  95. return f.S3Config.isEqual(&other.S3Config)
  96. case sdk.GCSFilesystemProvider:
  97. return f.GCSConfig.isEqual(&other.GCSConfig)
  98. case sdk.AzureBlobFilesystemProvider:
  99. return f.AzBlobConfig.isEqual(&other.AzBlobConfig)
  100. case sdk.CryptedFilesystemProvider:
  101. return f.CryptConfig.isEqual(&other.CryptConfig)
  102. case sdk.SFTPFilesystemProvider:
  103. return f.SFTPConfig.isEqual(&other.SFTPConfig)
  104. default:
  105. return true
  106. }
  107. }
  108. // Validate verifies the FsConfig matching the configured provider and sets all other
  109. // Filesystem.*Config to their zero value if successful
  110. func (f *Filesystem) Validate(additionalData string) error {
  111. switch f.Provider {
  112. case sdk.S3FilesystemProvider:
  113. if err := f.S3Config.ValidateAndEncryptCredentials(additionalData); err != nil {
  114. return err
  115. }
  116. f.GCSConfig = GCSFsConfig{}
  117. f.AzBlobConfig = AzBlobFsConfig{}
  118. f.CryptConfig = CryptFsConfig{}
  119. f.SFTPConfig = SFTPFsConfig{}
  120. return nil
  121. case sdk.GCSFilesystemProvider:
  122. if err := f.GCSConfig.ValidateAndEncryptCredentials(additionalData); err != nil {
  123. return err
  124. }
  125. f.S3Config = S3FsConfig{}
  126. f.AzBlobConfig = AzBlobFsConfig{}
  127. f.CryptConfig = CryptFsConfig{}
  128. f.SFTPConfig = SFTPFsConfig{}
  129. return nil
  130. case sdk.AzureBlobFilesystemProvider:
  131. if err := f.AzBlobConfig.ValidateAndEncryptCredentials(additionalData); err != nil {
  132. return err
  133. }
  134. f.S3Config = S3FsConfig{}
  135. f.GCSConfig = GCSFsConfig{}
  136. f.CryptConfig = CryptFsConfig{}
  137. f.SFTPConfig = SFTPFsConfig{}
  138. return nil
  139. case sdk.CryptedFilesystemProvider:
  140. if err := f.CryptConfig.ValidateAndEncryptCredentials(additionalData); err != nil {
  141. return err
  142. }
  143. f.S3Config = S3FsConfig{}
  144. f.GCSConfig = GCSFsConfig{}
  145. f.AzBlobConfig = AzBlobFsConfig{}
  146. f.SFTPConfig = SFTPFsConfig{}
  147. return nil
  148. case sdk.SFTPFilesystemProvider:
  149. if err := f.SFTPConfig.ValidateAndEncryptCredentials(additionalData); err != nil {
  150. return err
  151. }
  152. f.S3Config = S3FsConfig{}
  153. f.GCSConfig = GCSFsConfig{}
  154. f.AzBlobConfig = AzBlobFsConfig{}
  155. f.CryptConfig = CryptFsConfig{}
  156. return nil
  157. default:
  158. f.Provider = sdk.LocalFilesystemProvider
  159. f.S3Config = S3FsConfig{}
  160. f.GCSConfig = GCSFsConfig{}
  161. f.AzBlobConfig = AzBlobFsConfig{}
  162. f.CryptConfig = CryptFsConfig{}
  163. f.SFTPConfig = SFTPFsConfig{}
  164. return nil
  165. }
  166. }
  167. // HasRedactedSecret returns true if configured the filesystem configuration has a redacted secret
  168. func (f *Filesystem) HasRedactedSecret() bool {
  169. // TODO move vfs specific code into each *FsConfig struct
  170. switch f.Provider {
  171. case sdk.S3FilesystemProvider:
  172. if f.S3Config.AccessSecret.IsRedacted() {
  173. return true
  174. }
  175. case sdk.GCSFilesystemProvider:
  176. if f.GCSConfig.Credentials.IsRedacted() {
  177. return true
  178. }
  179. case sdk.AzureBlobFilesystemProvider:
  180. if f.AzBlobConfig.AccountKey.IsRedacted() {
  181. return true
  182. }
  183. if f.AzBlobConfig.SASURL.IsRedacted() {
  184. return true
  185. }
  186. case sdk.CryptedFilesystemProvider:
  187. if f.CryptConfig.Passphrase.IsRedacted() {
  188. return true
  189. }
  190. case sdk.SFTPFilesystemProvider:
  191. if f.SFTPConfig.Password.IsRedacted() {
  192. return true
  193. }
  194. if f.SFTPConfig.PrivateKey.IsRedacted() {
  195. return true
  196. }
  197. if f.SFTPConfig.KeyPassphrase.IsRedacted() {
  198. return true
  199. }
  200. }
  201. return false
  202. }
  203. // HideConfidentialData hides filesystem confidential data
  204. func (f *Filesystem) HideConfidentialData() {
  205. switch f.Provider {
  206. case sdk.S3FilesystemProvider:
  207. f.S3Config.HideConfidentialData()
  208. case sdk.GCSFilesystemProvider:
  209. f.GCSConfig.HideConfidentialData()
  210. case sdk.AzureBlobFilesystemProvider:
  211. f.AzBlobConfig.HideConfidentialData()
  212. case sdk.CryptedFilesystemProvider:
  213. f.CryptConfig.HideConfidentialData()
  214. case sdk.SFTPFilesystemProvider:
  215. f.SFTPConfig.HideConfidentialData()
  216. }
  217. }
  218. // GetACopy returns a filesystem copy
  219. func (f *Filesystem) GetACopy() Filesystem {
  220. f.SetEmptySecretsIfNil()
  221. fs := Filesystem{
  222. Provider: f.Provider,
  223. S3Config: S3FsConfig{
  224. BaseS3FsConfig: sdk.BaseS3FsConfig{
  225. Bucket: f.S3Config.Bucket,
  226. Region: f.S3Config.Region,
  227. AccessKey: f.S3Config.AccessKey,
  228. RoleARN: f.S3Config.RoleARN,
  229. Endpoint: f.S3Config.Endpoint,
  230. StorageClass: f.S3Config.StorageClass,
  231. ACL: f.S3Config.ACL,
  232. KeyPrefix: f.S3Config.KeyPrefix,
  233. UploadPartSize: f.S3Config.UploadPartSize,
  234. UploadConcurrency: f.S3Config.UploadConcurrency,
  235. DownloadPartSize: f.S3Config.DownloadPartSize,
  236. DownloadConcurrency: f.S3Config.DownloadConcurrency,
  237. DownloadPartMaxTime: f.S3Config.DownloadPartMaxTime,
  238. UploadPartMaxTime: f.S3Config.UploadPartMaxTime,
  239. ForcePathStyle: f.S3Config.ForcePathStyle,
  240. },
  241. AccessSecret: f.S3Config.AccessSecret.Clone(),
  242. },
  243. GCSConfig: GCSFsConfig{
  244. BaseGCSFsConfig: sdk.BaseGCSFsConfig{
  245. Bucket: f.GCSConfig.Bucket,
  246. AutomaticCredentials: f.GCSConfig.AutomaticCredentials,
  247. StorageClass: f.GCSConfig.StorageClass,
  248. ACL: f.GCSConfig.ACL,
  249. KeyPrefix: f.GCSConfig.KeyPrefix,
  250. },
  251. Credentials: f.GCSConfig.Credentials.Clone(),
  252. },
  253. AzBlobConfig: AzBlobFsConfig{
  254. BaseAzBlobFsConfig: sdk.BaseAzBlobFsConfig{
  255. Container: f.AzBlobConfig.Container,
  256. AccountName: f.AzBlobConfig.AccountName,
  257. Endpoint: f.AzBlobConfig.Endpoint,
  258. KeyPrefix: f.AzBlobConfig.KeyPrefix,
  259. UploadPartSize: f.AzBlobConfig.UploadPartSize,
  260. UploadConcurrency: f.AzBlobConfig.UploadConcurrency,
  261. DownloadPartSize: f.AzBlobConfig.DownloadPartSize,
  262. DownloadConcurrency: f.AzBlobConfig.DownloadConcurrency,
  263. UseEmulator: f.AzBlobConfig.UseEmulator,
  264. AccessTier: f.AzBlobConfig.AccessTier,
  265. },
  266. AccountKey: f.AzBlobConfig.AccountKey.Clone(),
  267. SASURL: f.AzBlobConfig.SASURL.Clone(),
  268. },
  269. CryptConfig: CryptFsConfig{
  270. Passphrase: f.CryptConfig.Passphrase.Clone(),
  271. },
  272. SFTPConfig: SFTPFsConfig{
  273. BaseSFTPFsConfig: sdk.BaseSFTPFsConfig{
  274. Endpoint: f.SFTPConfig.Endpoint,
  275. Username: f.SFTPConfig.Username,
  276. Prefix: f.SFTPConfig.Prefix,
  277. DisableCouncurrentReads: f.SFTPConfig.DisableCouncurrentReads,
  278. BufferSize: f.SFTPConfig.BufferSize,
  279. },
  280. Password: f.SFTPConfig.Password.Clone(),
  281. PrivateKey: f.SFTPConfig.PrivateKey.Clone(),
  282. KeyPassphrase: f.SFTPConfig.KeyPassphrase.Clone(),
  283. },
  284. }
  285. if len(f.SFTPConfig.Fingerprints) > 0 {
  286. fs.SFTPConfig.Fingerprints = make([]string, len(f.SFTPConfig.Fingerprints))
  287. copy(fs.SFTPConfig.Fingerprints, f.SFTPConfig.Fingerprints)
  288. }
  289. return fs
  290. }