feat: read masterkey from file or env (#3389)

* feat: read masterkey from file

* add read from env
This commit is contained in:
Livio Amstutz 2022-04-04 10:10:57 +02:00 committed by GitHub
parent 5112aae177
commit 7d6a10015a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 152 additions and 7 deletions

View File

@ -17,8 +17,7 @@ import (
)
const (
flagMasterKey = "masterkey"
flagKeyFile = "file"
flagKeyFile = "file"
)
type Config struct {
@ -30,7 +29,7 @@ func New() *cobra.Command {
Use: "keys",
Short: "manage encryption keys",
}
cmd.PersistentFlags().String(flagMasterKey, "", "masterkey for en/decryption keys")
AddMasterKeyFlag(cmd)
cmd.AddCommand(newKey())
return cmd
}
@ -67,7 +66,10 @@ new -f keys.yaml key2=anotherkey`,
if err := viper.Unmarshal(config); err != nil {
return err
}
masterKey, _ := cmd.Flags().GetString(flagMasterKey)
masterKey, err := MasterKey(cmd)
if err != nil {
return err
}
storage, err := keyStorage(config.Database, masterKey)
if err != nil {
return err
@ -113,7 +115,7 @@ func keysFromYAML(file io.Reader) ([]*crypto.Key, error) {
return keys, nil
}
func openFile(fileName string) (*os.File, error) {
func openFile(fileName string) (io.Reader, error) {
file, err := os.Open(fileName)
if err != nil {
return nil, caos_errs.ThrowInternalf(err, "KEY-asGr2", "failed to open file: %s", fileName)

View File

@ -0,0 +1,64 @@
package key
import (
"errors"
"io/ioutil"
"os"
"github.com/spf13/cobra"
)
const (
flagMasterKey = "masterkeyFile"
flagMasterKeyShort = "m"
flagMasterKeyArg = "masterkey"
flagMasterKeyEnv = "masterkeyFromEnv"
envMasterKey = "ZITADEL_MASTERKEY"
)
var (
ErrNotSingleFlag = errors.New("masterkey must either be provided by file path, value or environment variable")
)
func AddMasterKeyFlag(cmd *cobra.Command) {
cmd.PersistentFlags().StringP(flagMasterKey, flagMasterKeyShort, "", "path to the masterkey for en/decryption keys")
cmd.PersistentFlags().String(flagMasterKeyArg, "", "masterkey as argument for en/decryption keys")
cmd.PersistentFlags().Bool(flagMasterKeyEnv, false, "read masterkey for en/decryption keys from environment variable (ZITADEL_MASTERKEY)")
}
func MasterKey(cmd *cobra.Command) (string, error) {
masterKeyFile, _ := cmd.Flags().GetString(flagMasterKey)
masterKeyFromArg, _ := cmd.Flags().GetString(flagMasterKeyArg)
masterKeyFromEnv, _ := cmd.Flags().GetBool(flagMasterKeyEnv)
if err := checkSingleFlag(masterKeyFile, masterKeyFromArg, masterKeyFromEnv); err != nil {
return "", err
}
if masterKeyFromArg != "" {
return masterKeyFromArg, nil
}
if masterKeyFromEnv {
return os.Getenv(envMasterKey), nil
}
data, err := ioutil.ReadFile(masterKeyFile)
if err != nil {
return "", err
}
return string(data), nil
}
func checkSingleFlag(masterKeyFile, masterKeyFromArg string, masterKeyFromEnv bool) error {
var flags int
if masterKeyFile != "" {
flags++
}
if masterKeyFromArg != "" {
flags++
}
if masterKeyFromEnv {
flags++
}
if flags != 1 {
return ErrNotSingleFlag
}
return nil
}

View File

@ -0,0 +1,72 @@
package key
import (
"fmt"
"testing"
"github.com/stretchr/testify/assert"
)
func Test_checkSingleFlag(t *testing.T) {
type args struct {
masterKeyFile string
masterKeyFromArg string
masterKeyFromEnv bool
}
tests := []struct {
name string
args args
wantErr assert.ErrorAssertionFunc
}{
{
"no values, error",
args{
masterKeyFile: "",
masterKeyFromArg: "",
masterKeyFromEnv: false,
},
assert.Error,
},
{
"multiple values, error",
args{
masterKeyFile: "file",
masterKeyFromArg: "masterkey",
masterKeyFromEnv: true,
},
assert.Error,
},
{
"only file, ok",
args{
masterKeyFile: "file",
masterKeyFromArg: "",
masterKeyFromEnv: false,
},
assert.NoError,
},
{
"only argument, ok",
args{
masterKeyFile: "",
masterKeyFromArg: "masterkey",
masterKeyFromEnv: false,
},
assert.NoError,
},
{
"only env, ok",
args{
masterKeyFile: "",
masterKeyFromArg: "",
masterKeyFromEnv: true,
},
assert.NoError,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
tt.wantErr(t, checkSingleFlag(tt.args.masterKeyFile, tt.args.masterKeyFromArg, tt.args.masterKeyFromEnv), fmt.Sprintf("checkSingleFlag(%v, %v)", tt.args.masterKeyFile, tt.args.masterKeyFromArg))
})
}
}

View File

@ -3,6 +3,8 @@ package start
import (
"github.com/spf13/cobra"
"github.com/spf13/viper"
"github.com/caos/zitadel/cmd/admin/key"
)
func startFlags(cmd *cobra.Command) {
@ -11,7 +13,7 @@ func startFlags(cmd *cobra.Command) {
bindStringFlag(cmd, "externalPort", "port ZITADEL will be exposed on")
bindBoolFlag(cmd, "externalSecure", "if ZITADEL will be served on HTTPS")
cmd.PersistentFlags().String(flagMasterKey, "", "masterkey for en/decryption keys")
key.AddMasterKeyFlag(cmd)
}

View File

@ -19,6 +19,8 @@ import (
"golang.org/x/net/http2"
"golang.org/x/net/http2/h2c"
"github.com/caos/zitadel/cmd/admin/key"
admin_es "github.com/caos/zitadel/internal/admin/repository/eventsourcing"
"github.com/caos/zitadel/internal/api"
"github.com/caos/zitadel/internal/api/assets"
@ -59,7 +61,10 @@ Requirements:
- cockroachdb`,
RunE: func(cmd *cobra.Command, args []string) error {
config := MustNewConfig(viper.GetViper())
masterKey, _ := cmd.Flags().GetString(flagMasterKey)
masterKey, err := key.MasterKey(cmd)
if err != nil {
return err
}
return startZitadel(config, masterKey)
},