mirror of
https://github.com/getsops/sops.git
synced 2026-02-05 12:45:21 +01:00
Use age/armor for encrypted data key (#819)
* Use age/armor for encrypted data key Currently the encrypted data key is stored as a binary value, and this results in SOPS encrypted DOTENV files having weird binary characters. This changes the encrypt/decrypt methods to use the armor reader writer provided by: filippo.io/age/armor Signed-off-by: Andreas Amstutz <tullo@users.noreply.github.com> * upgrade filippo.io/age to v1.0.0-beta7 Signed-off-by: Andreas Amstutz <tullo@users.noreply.github.com> * add unit test Signed-off-by: Andreas Amstutz <tullo@users.noreply.github.com> Co-authored-by: Andreas Amstutz <tullo@users.noreply.github.com>
This commit is contained in:
@@ -9,6 +9,7 @@ import (
|
||||
"strings"
|
||||
|
||||
"filippo.io/age"
|
||||
"filippo.io/age/armor"
|
||||
"github.com/sirupsen/logrus"
|
||||
"go.mozilla.org/sops/v3/logging"
|
||||
)
|
||||
@@ -46,7 +47,8 @@ func (key *MasterKey) Encrypt(datakey []byte) error {
|
||||
key.parsedRecipient = parsedRecipient
|
||||
}
|
||||
|
||||
w, err := age.Encrypt(buffer, key.parsedRecipient)
|
||||
aw := armor.NewWriter(buffer)
|
||||
w, err := age.Encrypt(aw, key.parsedRecipient)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to open file for encrypting sops data key with age: %w", err)
|
||||
}
|
||||
@@ -61,6 +63,11 @@ func (key *MasterKey) Encrypt(datakey []byte) error {
|
||||
return fmt.Errorf("failed to close file for encrypting sops data key with age: %w", err)
|
||||
}
|
||||
|
||||
if err := aw.Close(); err != nil {
|
||||
log.WithField("recipient", key.parsedRecipient).Error("Encryption failed")
|
||||
return fmt.Errorf("failed to close armored writer: %w", err)
|
||||
}
|
||||
|
||||
key.EncryptedKey = buffer.String()
|
||||
|
||||
log.WithField("recipient", key.parsedRecipient).Info("Encryption succeeded")
|
||||
@@ -115,19 +122,20 @@ func (key *MasterKey) Decrypt() ([]byte, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
buffer := &bytes.Buffer{}
|
||||
reader := bytes.NewReader([]byte(key.EncryptedKey))
|
||||
r, err := age.Decrypt(reader, identities...)
|
||||
src := bytes.NewReader([]byte(key.EncryptedKey))
|
||||
ar := armor.NewReader(src)
|
||||
r, err := age.Decrypt(ar, identities...)
|
||||
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("no age identity found in %q that could decrypt the data", ageKeyFilePath)
|
||||
}
|
||||
|
||||
if _, err := io.Copy(buffer, r); err != nil {
|
||||
return nil, fmt.Errorf("failed to copy decrypted data into bytes.Buffer")
|
||||
var b bytes.Buffer
|
||||
if _, err := io.Copy(&b, r); err != nil {
|
||||
return nil, fmt.Errorf("failed to copy decrypted data into bytes.Buffer: %w", err)
|
||||
}
|
||||
|
||||
return buffer.Bytes(), nil
|
||||
return b.Bytes(), nil
|
||||
}
|
||||
|
||||
// NeedsRotation returns whether the data key needs to be rotated or not.
|
||||
|
||||
@@ -17,7 +17,7 @@ func TestMasterKeysFromRecipientsEmpty(t *testing.T) {
|
||||
|
||||
assert.NoError(err)
|
||||
|
||||
assert.Equal(recipients, make([]*MasterKey,0))
|
||||
assert.Equal(recipients, make([]*MasterKey, 0))
|
||||
}
|
||||
|
||||
func TestAge(t *testing.T) {
|
||||
@@ -41,3 +41,29 @@ func TestAge(t *testing.T) {
|
||||
assert.NoError(err)
|
||||
assert.Equal(dataKey, decryptedKey)
|
||||
}
|
||||
|
||||
func TestAgeDotEnv(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
key, err := MasterKeyFromRecipient("age1yt3tfqlfrwdwx0z0ynwplcr6qxcxfaqycuprpmy89nr83ltx74tqdpszlw")
|
||||
|
||||
assert.NoError(err)
|
||||
assert.Equal("age1yt3tfqlfrwdwx0z0ynwplcr6qxcxfaqycuprpmy89nr83ltx74tqdpszlw", key.ToString())
|
||||
|
||||
dotenv := `IMAGE_PREFIX=repo/service-
|
||||
APPLICATION_KEY=K6pfAWuUVND9Fz5SC7jmA6pfAWuUVND9Fz5SC7jmA
|
||||
KEY_ID=003683d721f2ae683d721f2a1
|
||||
DOMAIN=files.127.0.0.1.nip.io`
|
||||
dataKey := []byte(dotenv)
|
||||
|
||||
err = key.Encrypt(dataKey)
|
||||
assert.NoError(err)
|
||||
|
||||
_, filename, _, _ := runtime.Caller(0)
|
||||
err = os.Setenv("SOPS_AGE_KEY_FILE", path.Join(path.Dir(filename), "keys.txt"))
|
||||
assert.NoError(err)
|
||||
|
||||
decryptedKey, err := key.Decrypt()
|
||||
assert.NoError(err)
|
||||
assert.Equal(dataKey, decryptedKey)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user