Skip to content

Commit

Permalink
feat: unify encKey to encryptionSecret and make .env file readonly in… (
Browse files Browse the repository at this point in the history
#5365)

* feat: unify encKey to encryptionSecret and make .env file readonly in codebase

* fix: e2e test and ci-lint
  • Loading branch information
abeizn authored Jun 6, 2023
1 parent f3cfbc1 commit ff51f3b
Show file tree
Hide file tree
Showing 10 changed files with 59 additions and 67 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -36,21 +36,21 @@ type BlueprintEncryption0904 struct {
}

func (script *encryptBlueprint) Up(basicRes context.BasicRes) errors.Error {
encKey := basicRes.GetConfig(plugin.EncodeKeyEnvStr)
if encKey == "" {
return errors.BadInput.New("invalid encKey")
encryptionSecret := basicRes.GetConfig(plugin.EncodeKeyEnvStr)
if encryptionSecret == "" {
return errors.BadInput.New("invalid encryptionSecret")
}
err := migrationhelper.TransformColumns(
basicRes,
script,
"_devlake_blueprints",
[]string{"plan", "settings"},
func(src *BlueprintEncryption0904) (*BlueprintEncryption0904, errors.Error) {
plan, err := plugin.Encrypt(encKey, src.Plan)
plan, err := plugin.Encrypt(encryptionSecret, src.Plan)
if err != nil {
return nil, err
}
settings, err := plugin.Encrypt(encKey, src.Settings)
settings, err := plugin.Encrypt(encryptionSecret, src.Settings)
if err != nil {
return nil, err
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,17 +35,17 @@ type PipelineEncryption0904 struct {
}

func (script *encryptPipeline) Up(basicRes context.BasicRes) errors.Error {
encKey := basicRes.GetConfig(plugin.EncodeKeyEnvStr)
if encKey == "" {
return errors.BadInput.New("invalid encKey")
encryptionSecret := basicRes.GetConfig(plugin.EncodeKeyEnvStr)
if encryptionSecret == "" {
return errors.BadInput.New("invalid encryptionSecret")
}
err := migrationhelper.TransformColumns(
basicRes,
script,
"_devlake_pipelines",
[]string{"plan"},
func(src *PipelineEncryption0904) (*PipelineEncryption0904, errors.Error) {
plan, err := plugin.Encrypt(encKey, src.Plan)
plan, err := plugin.Encrypt(encryptionSecret, src.Plan)
if err != nil {
return nil, err
}
Expand Down
8 changes: 4 additions & 4 deletions backend/core/models/migrationscripts/20221221_encrypt_task.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,17 +42,17 @@ type dstTaskEncryption221221 struct {
}

func (script *encryptTask221221) Up(basicRes context.BasicRes) errors.Error {
encKey := basicRes.GetConfig(plugin.EncodeKeyEnvStr)
if encKey == "" {
return errors.BadInput.New("invalid encKey")
encryptionSecret := basicRes.GetConfig(plugin.EncodeKeyEnvStr)
if encryptionSecret == "" {
return errors.BadInput.New("invalid encryptionSecret")
}
err := migrationhelper.TransformColumns(
basicRes,
script,
"_devlake_tasks",
[]string{"options"},
func(src *srcTaskEncryption221221) (*dstTaskEncryption221221, errors.Error) {
options, err := plugin.Encrypt(encKey, string(src.Options))
options, err := plugin.Encrypt(encryptionSecret, string(src.Options))
if err != nil {
return nil, err
}
Expand Down
24 changes: 12 additions & 12 deletions backend/core/plugin/plugin_utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,28 +29,28 @@ import (
"github.com/apache/incubator-devlake/core/utils"
)

const EncodeKeyEnvStr = "ENCODE_KEY"
const EncodeKeyEnvStr = "ENCRYPTION_SECRET"

// TODO: maybe move encryption/decryption into helper?
// AES + Base64 encryption using ENCODE_KEY in .env as key
func Encrypt(encKey, plainText string) (string, errors.Error) {
// AES + Base64 encryption using ENCRYPTION_SECRET in .env as key
func Encrypt(encryptionSecret, plainText string) (string, errors.Error) {
// add suffix to the data part
inputBytes := append([]byte(plainText), 123, 110, 100, 100, 116, 102, 125)
// perform encryption
output, err := AesEncrypt(inputBytes, []byte(encKey))
output, err := AesEncrypt(inputBytes, []byte(encryptionSecret))
if err != nil {
return plainText, err
}
// Return the result after Base64 processing
return base64.StdEncoding.EncodeToString(output), nil
}

// Base64 + AES decryption using ENCODE_KEY in .env as key
func Decrypt(encKey, encryptedText string) (string, errors.Error) {
// Base64 + AES decryption using ENCRYPTION_SECRET in .env as key
func Decrypt(encryptionSecret, encryptedText string) (string, errors.Error) {
// when encryption key is not set
if encKey == "" {
if encryptionSecret == "" {
// return error message
return encryptedText, errors.Default.New("encKey is required")
return encryptedText, errors.Default.New("encryptionSecret is required")
}

// Decode Base64
Expand All @@ -59,7 +59,7 @@ func Decrypt(encKey, encryptedText string) (string, errors.Error) {
return encryptedText, errors.Convert(err1)
}
// perform AES decryption
output, err2 := AesDecrypt(decodingFromBase64, []byte(encKey))
output, err2 := AesDecrypt(decodingFromBase64, []byte(encryptionSecret))
if err2 != nil {
return encryptedText, err2
}
Expand All @@ -75,7 +75,7 @@ func Decrypt(encKey, encryptedText string) (string, errors.Error) {
return string(output), nil
}
}
return "", errors.Default.New("invalid encKey")
return "", errors.Default.New("invalid encryptionSecret")
}

// PKCS7Padding PKCS7 padding
Expand Down Expand Up @@ -139,7 +139,7 @@ func AesDecrypt(crypted, key []byte) ([]byte, errors.Error) {
return origData, nil
}

// RandomEncKey will return a random string of length 128
func RandomEncKey() (string, errors.Error) {
// RandomEncryptionSecret will return a random string of length 128
func RandomEncryptionSecret() (string, errors.Error) {
return utils.RandLetterBytes(128)
}
10 changes: 5 additions & 5 deletions backend/core/plugin/plugin_utils_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,21 +30,21 @@ func TestEncodeAndDecode(t *testing.T) {
var TestEncode string
var TestDecode string

encKey, _ := RandomEncKey()
encryptionSecret, _ := RandomEncryptionSecret()
// encryption test
TestEncode, err = Encrypt(encKey, TestStr)
TestEncode, err = Encrypt(encryptionSecret, TestStr)
assert.Empty(t, err)

// decrypt test
TestDecode, err = Decrypt(encKey, TestEncode)
TestDecode, err = Decrypt(encryptionSecret, TestEncode)
assert.Empty(t, err)

// Verify decryption result
assert.Equal(t, string(TestDecode), TestStr)
}

func TestEncode(t *testing.T) {
encKey, _ := RandomEncKey()
encryptionSecret, _ := RandomEncryptionSecret()
type args struct {
Input string
}
Expand All @@ -61,7 +61,7 @@ func TestEncode(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := Encrypt(encKey, tt.args.Input)
got, err := Encrypt(encryptionSecret, tt.args.Input)
if (err != nil) != tt.wantErr {
t.Errorf("Encode() error = %v, wantErr %v", err, tt.wantErr)
return
Expand Down
19 changes: 10 additions & 9 deletions backend/helpers/pluginhelper/api/connection_helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,22 +18,23 @@ limitations under the License.
package api

import (
"strconv"

"github.com/apache/incubator-devlake/core/context"
"github.com/apache/incubator-devlake/core/dal"
"github.com/apache/incubator-devlake/core/errors"
"github.com/apache/incubator-devlake/core/log"
"github.com/apache/incubator-devlake/core/models"
plugin "github.com/apache/incubator-devlake/core/plugin"
"github.com/go-playground/validator/v10"
"strconv"
)

// ConnectionApiHelper is used to write the CURD of connection
type ConnectionApiHelper struct {
encKey string
log log.Logger
db dal.Dal
validator *validator.Validate
encryptionSecret string
log log.Logger
db dal.Dal
validator *validator.Validate
}

// NewConnectionHelper creates a ConnectionHelper for connection management
Expand All @@ -45,10 +46,10 @@ func NewConnectionHelper(
vld = validator.New()
}
return &ConnectionApiHelper{
encKey: basicRes.GetConfig(plugin.EncodeKeyEnvStr),
log: basicRes.GetLogger(),
db: basicRes.GetDal(),
validator: vld,
encryptionSecret: basicRes.GetConfig(plugin.EncodeKeyEnvStr),
log: basicRes.GetLogger(),
db: basicRes.GetDal(),
validator: vld,
}
}

Expand Down
10 changes: 5 additions & 5 deletions backend/impls/dalgorm/encdec_serializer.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ var _ schema.SerializerInterface = (*EncDecSerializer)(nil)
// EncDecSerializer is responsible for field encryption/decryption in Application Level
// Ref: https://gorm.io/docs/serializer.html
type EncDecSerializer struct {
encKey string
encryptionSecret string
}

// Scan implements serializer interface
Expand All @@ -52,7 +52,7 @@ func (es *EncDecSerializer) Scan(ctx context.Context, field *schema.Field, dst r
return fmt.Errorf("failed to decrypt value: %#v", dbValue)
}

decrypted, err := plugin.Decrypt(es.encKey, base64str)
decrypted, err := plugin.Decrypt(es.encryptionSecret, base64str)
if err != nil {
return err
}
Expand Down Expand Up @@ -81,10 +81,10 @@ func (es *EncDecSerializer) Value(ctx context.Context, field *schema.Field, dst
default:
return nil, fmt.Errorf("failed to encrypt value: %#v", fieldValue)
}
return plugin.Encrypt(es.encKey, target)
return plugin.Encrypt(es.encryptionSecret, target)
}

// Init the encdec serializer
func Init(encKey string) {
schema.RegisterSerializer("encdec", &EncDecSerializer{encKey: encKey})
func Init(encryptionSecret string) {
schema.RegisterSerializer("encdec", &EncDecSerializer{encryptionSecret: encryptionSecret})
}
17 changes: 3 additions & 14 deletions backend/server/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,27 +19,16 @@ package main

import (
"github.com/apache/incubator-devlake/core/config"
"github.com/apache/incubator-devlake/core/errors"
"github.com/apache/incubator-devlake/core/plugin"
_ "github.com/apache/incubator-devlake/core/version"
"github.com/apache/incubator-devlake/server/api"
)

func main() {
v := config.GetConfig()
encKey := v.GetString(plugin.EncodeKeyEnvStr)
if encKey == "" {
var err errors.Error
// Randomly generate a bunch of encryption keys and set them to config
encKey, err = plugin.RandomEncKey()
if err != nil {
panic(err)
}
v.Set(plugin.EncodeKeyEnvStr, encKey)
err = config.WriteConfig(v)
if err != nil {
panic(err)
}
encryptionSecret := v.GetString(plugin.EncodeKeyEnvStr)
if encryptionSecret == "" {
panic("ENCRYPTION_SECRET must be set in .env file")
}
api.CreateApiService()
}
18 changes: 10 additions & 8 deletions backend/test/helper/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,6 @@ import (
"encoding/json"
goerror "errors"
"fmt"
"github.com/apache/incubator-devlake/core/dal"
dora "github.com/apache/incubator-devlake/plugins/dora/impl"
org "github.com/apache/incubator-devlake/plugins/org/impl"
remotePlugin "github.com/apache/incubator-devlake/server/services/remote/plugin"
"io"
"math"
"net/http"
Expand All @@ -36,6 +32,11 @@ import (
"testing"
"time"

"github.com/apache/incubator-devlake/core/dal"
dora "github.com/apache/incubator-devlake/plugins/dora/impl"
org "github.com/apache/incubator-devlake/plugins/org/impl"
remotePlugin "github.com/apache/incubator-devlake/server/services/remote/plugin"

"github.com/apache/incubator-devlake/core/config"
corectx "github.com/apache/incubator-devlake/core/context"
"github.com/apache/incubator-devlake/core/errors"
Expand Down Expand Up @@ -215,15 +216,16 @@ func (d *DevlakeClient) RunPlugin(ctx context.Context, pluginName string, plugin

func (d *DevlakeClient) configureEncryption() {
v := config.GetConfig()
encKey := v.GetString(plugin.EncodeKeyEnvStr)
if encKey == "" {
encryptionSecret := v.GetString(plugin.EncodeKeyEnvStr)
// only test environment should have this set
if encryptionSecret == "" {
var err errors.Error
// Randomly generate a bunch of encryption keys and set them to config
encKey, err = plugin.RandomEncKey()
encryptionSecret, err = plugin.RandomEncryptionSecret()
if err != nil {
panic(err)
}
v.Set(plugin.EncodeKeyEnvStr, encKey)
v.Set(plugin.EncodeKeyEnvStr, encryptionSecret)
err = config.WriteConfig(v)
if err != nil {
panic(err)
Expand Down
2 changes: 1 addition & 1 deletion env.example
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ DISABLED_REMOTE_PLUGINS=
##########################
# Sensitive information encryption key
##########################
ENCODE_KEY=
ENCRYPTION_SECRET=

##########################
# Set if skip verify and connect with out trusted certificate when use https
Expand Down

0 comments on commit ff51f3b

Please sign in to comment.