kms: remove support for compat secrets

also document how to activate the deprecated builtin provider
This commit is contained in:
Nicola Murino 2021-12-01 17:53:19 +01:00
parent 4df0ae82ac
commit 6ee51c5cc1
No known key found for this signature in database
GPG key ID: 2F1FB59433D5A8CB
6 changed files with 11 additions and 89 deletions

View file

@ -6,7 +6,7 @@
[![Docker Pulls](https://img.shields.io/docker/pulls/drakkan/sftpgo)](https://hub.docker.com/r/drakkan/sftpgo)
[![Mentioned in Awesome Go](https://awesome.re/mentioned-badge.svg)](https://github.com/avelino/awesome-go)
Fully featured and highly configurable SFTP server with optional HTTP, FTP/S and WebDAV support, written in Go.
Fully featured and highly configurable SFTP server with optional HTTP, FTP/S and WebDAV support.
Several storage backends are supported: local filesystem, encrypted local filesystem, S3 (compatible) Object Storage, Google Cloud Storage, Azure Blob Storage, SFTP.
## Features

View file

@ -19,7 +19,7 @@ We first generate a random key, then the per-object encryption key is derived fr
1. a master key is provided: the encryption key is derived using the HMAC-based Extract-and-Expand Key Derivation Function (HKDF) as defined in [RFC 5869](http://tools.ietf.org/html/rfc5869)
2. no master key is provided: the encryption key is derived as simple hash of the random key. This is the default configuration.
For compatibility with SFTPGo versions 1.2.x and before we also support encryption based on `AES-256-GCM`. The data encrypted with this algorithm will never use the master key to keep backward compatibility.
For compatibility with SFTPGo versions 1.2.x and before we also support encryption based on `AES-256-GCM`. The data encrypted with this algorithm will never use the master key to keep backward compatibility. You can activate it using `builtin://` as `url` but this is not recommended.
### Cloud providers

View file

@ -144,7 +144,7 @@ const (
maxRequestSize = 1048576 // 1MB
maxLoginBodySize = 262144 // 256 KB
httpdMaxEditFileSize = 1048576 // 1 MB
maxMultipartMem = 8388608 // 8MB
maxMultipartMem = 10485760 // 10 MB
osWindows = "windows"
otpHeaderCode = "X-SFTPGO-OTP"
)

View file

@ -2857,14 +2857,6 @@ func TestSecretObject(t *testing.T) {
require.Equal(t, kms.SecretStatusPlain, s.GetStatus())
require.Equal(t, "test data", s.GetPayload())
require.Empty(t, s.GetKey())
oldFormat := "$aes$5b97e3a3324a2f53e2357483383367c0$0ed3132b584742ab217866219da633266782b69b13e50ebc6ddfb7c4fbf2f2a414c6d5f813"
s, err = kms.GetSecretFromCompatString(oldFormat)
require.NoError(t, err)
require.True(t, s.IsValid())
require.Equal(t, kms.SecretStatusPlain, s.GetStatus())
require.Equal(t, "test data", s.GetPayload())
require.Empty(t, s.GetKey())
}
func TestSecretObjectCompatibility(t *testing.T) {
@ -8988,6 +8980,10 @@ func TestShareUncompressed(t *testing.T) {
checkResponseCode(t, http.StatusOK, rr)
assert.Equal(t, "application/octet-stream", rr.Header().Get("Content-Type"))
share, err = dataprovider.ShareExists(objectID, user.Username)
assert.NoError(t, err)
assert.Equal(t, 2, share.UsedTokens)
user.Permissions["/"] = []string{dataprovider.PermListItems, dataprovider.PermUpload}
user, _, err = httpdtest.UpdateUser(user, http.StatusOK, "")
assert.NoError(t, err)
@ -8998,6 +8994,10 @@ func TestShareUncompressed(t *testing.T) {
rr = executeRequest(req)
checkResponseCode(t, http.StatusForbidden, rr)
share, err = dataprovider.ShareExists(objectID, user.Username)
assert.NoError(t, err)
assert.Equal(t, 2, share.UsedTokens)
user.Permissions["/"] = []string{dataprovider.PermAny}
user, _, err = httpdtest.UpdateUser(user, http.StatusOK, "")
assert.NoError(t, err)

View file

@ -125,15 +125,6 @@ func NewPlainSecret(payload string) *Secret {
return NewSecret(SecretStatusPlain, payload, "", "")
}
// GetSecretFromCompatString returns a secret from the previous format
func GetSecretFromCompatString(secret string) (*Secret, error) {
plain, err := util.DecryptData(secret)
if err != nil {
return &Secret{}, errMalformedCiphertext
}
return NewSecret(SecretStatusPlain, plain, "", ""), nil
}
// Initialize configures the KMS support
func (c *Configuration) Initialize() error {
if c.Secrets.MasterKeyString != "" {

View file

@ -3,8 +3,6 @@ package util
import (
"bytes"
"crypto/aes"
"crypto/cipher"
"crypto/ecdsa"
"crypto/ed25519"
"crypto/elliptic"
@ -12,7 +10,6 @@ import (
"crypto/rsa"
"crypto/tls"
"crypto/x509"
"encoding/hex"
"encoding/pem"
"errors"
"fmt"
@ -154,72 +151,6 @@ func NilIfEmpty(s string) *string {
return &s
}
// EncryptData encrypts data using the given key
func EncryptData(data string) (string, error) {
var result string
key := make([]byte, 16)
if _, err := io.ReadFull(rand.Reader, key); err != nil {
return result, err
}
keyHex := hex.EncodeToString(key)
block, err := aes.NewCipher([]byte(keyHex))
if err != nil {
return result, err
}
gcm, err := cipher.NewGCM(block)
if err != nil {
return result, err
}
nonce := make([]byte, gcm.NonceSize())
if _, err = io.ReadFull(rand.Reader, nonce); err != nil {
return result, err
}
ciphertext := gcm.Seal(nonce, nonce, []byte(data), nil)
result = fmt.Sprintf("$aes$%s$%x", keyHex, ciphertext)
return result, err
}
// RemoveDecryptionKey returns encrypted data without the decryption key
func RemoveDecryptionKey(encryptData string) string {
vals := strings.Split(encryptData, "$")
if len(vals) == 4 {
return fmt.Sprintf("$%v$%v", vals[1], vals[3])
}
return encryptData
}
// DecryptData decrypts data encrypted using EncryptData
func DecryptData(data string) (string, error) {
var result string
vals := strings.Split(data, "$")
if len(vals) != 4 {
return "", errors.New("data to decrypt is not in the correct format")
}
key := vals[2]
encrypted, err := hex.DecodeString(vals[3])
if err != nil {
return result, err
}
block, err := aes.NewCipher([]byte(key))
if err != nil {
return result, err
}
gcm, err := cipher.NewGCM(block)
if err != nil {
return result, err
}
nonceSize := gcm.NonceSize()
if len(encrypted) < nonceSize {
return result, errors.New("malformed ciphertext")
}
nonce, ciphertext := encrypted[:nonceSize], encrypted[nonceSize:]
plaintext, err := gcm.Open(nil, nonce, ciphertext, nil)
if err != nil {
return result, err
}
return string(plaintext), nil
}
// GenerateRSAKeys generate rsa private and public keys and write the
// private key to specified file and the public key to the specified
// file adding the .pub suffix