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 ( const (
flagMasterKey = "masterkey" flagKeyFile = "file"
flagKeyFile = "file"
) )
type Config struct { type Config struct {
@ -30,7 +29,7 @@ func New() *cobra.Command {
Use: "keys", Use: "keys",
Short: "manage encryption keys", Short: "manage encryption keys",
} }
cmd.PersistentFlags().String(flagMasterKey, "", "masterkey for en/decryption keys") AddMasterKeyFlag(cmd)
cmd.AddCommand(newKey()) cmd.AddCommand(newKey())
return cmd return cmd
} }
@ -67,7 +66,10 @@ new -f keys.yaml key2=anotherkey`,
if err := viper.Unmarshal(config); err != nil { if err := viper.Unmarshal(config); err != nil {
return err return err
} }
masterKey, _ := cmd.Flags().GetString(flagMasterKey) masterKey, err := MasterKey(cmd)
if err != nil {
return err
}
storage, err := keyStorage(config.Database, masterKey) storage, err := keyStorage(config.Database, masterKey)
if err != nil { if err != nil {
return err return err
@ -113,7 +115,7 @@ func keysFromYAML(file io.Reader) ([]*crypto.Key, error) {
return keys, nil return keys, nil
} }
func openFile(fileName string) (*os.File, error) { func openFile(fileName string) (io.Reader, error) {
file, err := os.Open(fileName) file, err := os.Open(fileName)
if err != nil { if err != nil {
return nil, caos_errs.ThrowInternalf(err, "KEY-asGr2", "failed to open file: %s", fileName) 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 ( import (
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/spf13/viper" "github.com/spf13/viper"
"github.com/caos/zitadel/cmd/admin/key"
) )
func startFlags(cmd *cobra.Command) { func startFlags(cmd *cobra.Command) {
@ -11,7 +13,7 @@ func startFlags(cmd *cobra.Command) {
bindStringFlag(cmd, "externalPort", "port ZITADEL will be exposed on") bindStringFlag(cmd, "externalPort", "port ZITADEL will be exposed on")
bindBoolFlag(cmd, "externalSecure", "if ZITADEL will be served on HTTPS") 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"
"golang.org/x/net/http2/h2c" "golang.org/x/net/http2/h2c"
"github.com/caos/zitadel/cmd/admin/key"
admin_es "github.com/caos/zitadel/internal/admin/repository/eventsourcing" admin_es "github.com/caos/zitadel/internal/admin/repository/eventsourcing"
"github.com/caos/zitadel/internal/api" "github.com/caos/zitadel/internal/api"
"github.com/caos/zitadel/internal/api/assets" "github.com/caos/zitadel/internal/api/assets"
@ -59,7 +61,10 @@ Requirements:
- cockroachdb`, - cockroachdb`,
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(cmd *cobra.Command, args []string) error {
config := MustNewConfig(viper.GetViper()) config := MustNewConfig(viper.GetViper())
masterKey, _ := cmd.Flags().GetString(flagMasterKey) masterKey, err := key.MasterKey(cmd)
if err != nil {
return err
}
return startZitadel(config, masterKey) return startZitadel(config, masterKey)
}, },