kms.go 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417
  1. // Package kms provides Key Management Services support
  2. package kms
  3. import (
  4. "encoding/json"
  5. "errors"
  6. "os"
  7. "strings"
  8. "sync"
  9. "github.com/drakkan/sftpgo/v2/logger"
  10. sdkkms "github.com/drakkan/sftpgo/v2/sdk/kms"
  11. )
  12. // SecretProvider defines the interface for a KMS secrets provider
  13. type SecretProvider interface {
  14. Name() string
  15. Encrypt() error
  16. Decrypt() error
  17. IsEncrypted() bool
  18. GetStatus() sdkkms.SecretStatus
  19. GetPayload() string
  20. GetKey() string
  21. GetAdditionalData() string
  22. GetMode() int
  23. SetKey(string)
  24. SetAdditionalData(string)
  25. SetStatus(sdkkms.SecretStatus)
  26. Clone() SecretProvider
  27. }
  28. const (
  29. logSender = "kms"
  30. )
  31. // Configuration defines the KMS configuration
  32. type Configuration struct {
  33. Secrets Secrets `json:"secrets" mapstructure:"secrets"`
  34. }
  35. // Secrets define the KMS configuration for encryption/decryption
  36. type Secrets struct {
  37. URL string `json:"url" mapstructure:"url"`
  38. MasterKeyPath string `json:"master_key_path" mapstructure:"master_key_path"`
  39. MasterKeyString string `json:"master_key" mapstructure:"master_key"`
  40. masterKey string
  41. }
  42. type registeredSecretProvider struct {
  43. encryptedStatus sdkkms.SecretStatus
  44. newFn func(base BaseSecret, url, masterKey string) SecretProvider
  45. }
  46. var (
  47. // ErrWrongSecretStatus defines the error to return if the secret status is not appropriate
  48. // for the request operation
  49. ErrWrongSecretStatus = errors.New("wrong secret status")
  50. // ErrInvalidSecret defines the error to return if a secret is not valid
  51. ErrInvalidSecret = errors.New("invalid secret")
  52. validSecretStatuses = []string{sdkkms.SecretStatusPlain, sdkkms.SecretStatusAES256GCM, sdkkms.SecretStatusSecretBox,
  53. sdkkms.SecretStatusVaultTransit, sdkkms.SecretStatusAWS, sdkkms.SecretStatusGCP, sdkkms.SecretStatusRedacted}
  54. config Configuration
  55. secretProviders = make(map[string]registeredSecretProvider)
  56. )
  57. // RegisterSecretProvider register a new secret provider
  58. func RegisterSecretProvider(scheme string, encryptedStatus sdkkms.SecretStatus,
  59. fn func(base BaseSecret, url, masterKey string) SecretProvider,
  60. ) {
  61. secretProviders[scheme] = registeredSecretProvider{
  62. encryptedStatus: encryptedStatus,
  63. newFn: fn,
  64. }
  65. }
  66. // NewSecret builds a new Secret using the provided arguments
  67. func NewSecret(status sdkkms.SecretStatus, payload, key, data string) *Secret {
  68. return config.newSecret(status, payload, key, data)
  69. }
  70. // NewEmptySecret returns an empty secret
  71. func NewEmptySecret() *Secret {
  72. return NewSecret("", "", "", "")
  73. }
  74. // NewPlainSecret stores the give payload in a plain text secret
  75. func NewPlainSecret(payload string) *Secret {
  76. return NewSecret(sdkkms.SecretStatusPlain, payload, "", "")
  77. }
  78. // Initialize configures the KMS support
  79. func (c *Configuration) Initialize() error {
  80. if c.Secrets.MasterKeyString != "" {
  81. c.Secrets.masterKey = c.Secrets.MasterKeyString
  82. }
  83. if c.Secrets.masterKey == "" && c.Secrets.MasterKeyPath != "" {
  84. mKey, err := os.ReadFile(c.Secrets.MasterKeyPath)
  85. if err != nil {
  86. return err
  87. }
  88. c.Secrets.masterKey = strings.TrimSpace(string(mKey))
  89. }
  90. config = *c
  91. if config.Secrets.URL == "" {
  92. config.Secrets.URL = sdkkms.SchemeLocal + "://"
  93. }
  94. for k, v := range secretProviders {
  95. logger.Info(logSender, "", "secret provider registered for scheme: %#v, encrypted status: %#v",
  96. k, v.encryptedStatus)
  97. }
  98. return nil
  99. }
  100. func (c *Configuration) newSecret(status sdkkms.SecretStatus, payload, key, data string) *Secret {
  101. base := BaseSecret{
  102. Status: status,
  103. Key: key,
  104. Payload: payload,
  105. AdditionalData: data,
  106. }
  107. return &Secret{
  108. provider: c.getSecretProvider(base),
  109. }
  110. }
  111. func (c *Configuration) getSecretProvider(base BaseSecret) SecretProvider {
  112. for k, v := range secretProviders {
  113. if strings.HasPrefix(c.Secrets.URL, k) {
  114. return v.newFn(base, c.Secrets.URL, c.Secrets.masterKey)
  115. }
  116. }
  117. logger.Warn(logSender, "", "no secret provider registered for URL %v, fallback to local provider", c.Secrets.URL)
  118. return NewLocalSecret(base, c.Secrets.URL, c.Secrets.masterKey)
  119. }
  120. // Secret defines the struct used to store confidential data
  121. type Secret struct {
  122. sync.RWMutex
  123. provider SecretProvider
  124. }
  125. // MarshalJSON return the JSON encoding of the Secret object
  126. func (s *Secret) MarshalJSON() ([]byte, error) {
  127. s.RLock()
  128. defer s.RUnlock()
  129. return json.Marshal(&BaseSecret{
  130. Status: s.provider.GetStatus(),
  131. Payload: s.provider.GetPayload(),
  132. Key: s.provider.GetKey(),
  133. AdditionalData: s.provider.GetAdditionalData(),
  134. Mode: s.provider.GetMode(),
  135. })
  136. }
  137. // UnmarshalJSON parses the JSON-encoded data and stores the result
  138. // in the Secret object
  139. func (s *Secret) UnmarshalJSON(data []byte) error {
  140. s.Lock()
  141. defer s.Unlock()
  142. baseSecret := BaseSecret{}
  143. err := json.Unmarshal(data, &baseSecret)
  144. if err != nil {
  145. return err
  146. }
  147. if baseSecret.isEmpty() {
  148. s.provider = config.getSecretProvider(baseSecret)
  149. return nil
  150. }
  151. if baseSecret.Status == sdkkms.SecretStatusPlain || baseSecret.Status == sdkkms.SecretStatusRedacted {
  152. s.provider = config.getSecretProvider(baseSecret)
  153. return nil
  154. }
  155. for _, v := range secretProviders {
  156. if v.encryptedStatus == baseSecret.Status {
  157. s.provider = v.newFn(baseSecret, config.Secrets.URL, config.Secrets.masterKey)
  158. return nil
  159. }
  160. }
  161. logger.Error(logSender, "", "no provider registered for status %#v", baseSecret.Status)
  162. return ErrInvalidSecret
  163. }
  164. // IsEqual returns true if all the secrets fields are equal
  165. func (s *Secret) IsEqual(other *Secret) bool {
  166. if s.GetStatus() != other.GetStatus() {
  167. return false
  168. }
  169. if s.GetPayload() != other.GetPayload() {
  170. return false
  171. }
  172. if s.GetKey() != other.GetKey() {
  173. return false
  174. }
  175. if s.GetAdditionalData() != other.GetAdditionalData() {
  176. return false
  177. }
  178. if s.GetMode() != other.GetMode() {
  179. return false
  180. }
  181. return true
  182. }
  183. // Clone returns a copy of the secret object
  184. func (s *Secret) Clone() *Secret {
  185. s.RLock()
  186. defer s.RUnlock()
  187. return &Secret{
  188. provider: s.provider.Clone(),
  189. }
  190. }
  191. // IsEncrypted returns true if the secret is encrypted
  192. // This isn't a pointer receiver because we don't want to pass
  193. // a pointer to html template
  194. func (s *Secret) IsEncrypted() bool {
  195. s.RLock()
  196. defer s.RUnlock()
  197. return s.provider.IsEncrypted()
  198. }
  199. // IsPlain returns true if the secret is in plain text
  200. func (s *Secret) IsPlain() bool {
  201. s.RLock()
  202. defer s.RUnlock()
  203. return s.provider.GetStatus() == sdkkms.SecretStatusPlain
  204. }
  205. // IsNotPlainAndNotEmpty returns true if the secret is not plain and not empty.
  206. // This is an utility method, we update the secret for an existing user
  207. // if it is empty or plain
  208. func (s *Secret) IsNotPlainAndNotEmpty() bool {
  209. s.RLock()
  210. defer s.RUnlock()
  211. return !s.IsPlain() && !s.IsEmpty()
  212. }
  213. // IsRedacted returns true if the secret is redacted
  214. func (s *Secret) IsRedacted() bool {
  215. s.RLock()
  216. defer s.RUnlock()
  217. return s.provider.GetStatus() == sdkkms.SecretStatusRedacted
  218. }
  219. // GetPayload returns the secret payload
  220. func (s *Secret) GetPayload() string {
  221. s.RLock()
  222. defer s.RUnlock()
  223. return s.provider.GetPayload()
  224. }
  225. // GetAdditionalData returns the secret additional data
  226. func (s *Secret) GetAdditionalData() string {
  227. s.RLock()
  228. defer s.RUnlock()
  229. return s.provider.GetAdditionalData()
  230. }
  231. // GetStatus returns the secret status
  232. func (s *Secret) GetStatus() sdkkms.SecretStatus {
  233. s.RLock()
  234. defer s.RUnlock()
  235. return s.provider.GetStatus()
  236. }
  237. // GetKey returns the secret key
  238. func (s *Secret) GetKey() string {
  239. s.RLock()
  240. defer s.RUnlock()
  241. return s.provider.GetKey()
  242. }
  243. // GetMode returns the secret mode
  244. func (s *Secret) GetMode() int {
  245. s.RLock()
  246. defer s.RUnlock()
  247. return s.provider.GetMode()
  248. }
  249. // SetAdditionalData sets the given additional data
  250. func (s *Secret) SetAdditionalData(value string) {
  251. s.Lock()
  252. defer s.Unlock()
  253. s.provider.SetAdditionalData(value)
  254. }
  255. // SetStatus sets the status for this secret
  256. func (s *Secret) SetStatus(value sdkkms.SecretStatus) {
  257. s.Lock()
  258. defer s.Unlock()
  259. s.provider.SetStatus(value)
  260. }
  261. // SetKey sets the key for this secret
  262. func (s *Secret) SetKey(value string) {
  263. s.Lock()
  264. defer s.Unlock()
  265. s.provider.SetKey(value)
  266. }
  267. // IsEmpty returns true if all fields are empty
  268. func (s *Secret) IsEmpty() bool {
  269. s.RLock()
  270. defer s.RUnlock()
  271. if s.provider.GetStatus() != "" {
  272. return false
  273. }
  274. if s.provider.GetPayload() != "" {
  275. return false
  276. }
  277. if s.provider.GetKey() != "" {
  278. return false
  279. }
  280. if s.provider.GetAdditionalData() != "" {
  281. return false
  282. }
  283. return true
  284. }
  285. // IsValid returns true if the secret is not empty and valid
  286. func (s *Secret) IsValid() bool {
  287. s.RLock()
  288. defer s.RUnlock()
  289. if !s.IsValidInput() {
  290. return false
  291. }
  292. switch s.provider.GetStatus() {
  293. case sdkkms.SecretStatusAES256GCM, sdkkms.SecretStatusSecretBox:
  294. if len(s.provider.GetKey()) != 64 {
  295. return false
  296. }
  297. case sdkkms.SecretStatusAWS, sdkkms.SecretStatusGCP, sdkkms.SecretStatusVaultTransit:
  298. key := s.provider.GetKey()
  299. if key != "" && len(key) != 64 {
  300. return false
  301. }
  302. }
  303. return true
  304. }
  305. // IsValidInput returns true if the secret is a valid user input
  306. func (s *Secret) IsValidInput() bool {
  307. s.RLock()
  308. defer s.RUnlock()
  309. if !isSecretStatusValid(s.provider.GetStatus()) {
  310. return false
  311. }
  312. if s.provider.GetPayload() == "" {
  313. return false
  314. }
  315. return true
  316. }
  317. // Hide hides info to decrypt data
  318. func (s *Secret) Hide() {
  319. s.Lock()
  320. defer s.Unlock()
  321. s.provider.SetKey("")
  322. s.provider.SetAdditionalData("")
  323. }
  324. // Encrypt encrypts a plain text Secret object
  325. func (s *Secret) Encrypt() error {
  326. s.Lock()
  327. defer s.Unlock()
  328. return s.provider.Encrypt()
  329. }
  330. // Decrypt decrypts a Secret object
  331. func (s *Secret) Decrypt() error {
  332. s.Lock()
  333. defer s.Unlock()
  334. return s.provider.Decrypt()
  335. }
  336. // TryDecrypt decrypts a Secret object if encrypted.
  337. // It returns a nil error if the object is not encrypted
  338. func (s *Secret) TryDecrypt() error {
  339. s.Lock()
  340. defer s.Unlock()
  341. if s.provider.IsEncrypted() {
  342. return s.provider.Decrypt()
  343. }
  344. return nil
  345. }
  346. func isSecretStatusValid(status string) bool {
  347. for idx := range validSecretStatuses {
  348. if validSecretStatuses[idx] == status {
  349. return true
  350. }
  351. }
  352. return false
  353. }