Files
zitadel/cmd/key/key.go
Fabienne Bühler 07ce3b6905 chore!: Introduce ZITADEL v3 (#9645)
This PR summarizes multiple changes specifically only available with
ZITADEL v3:

- feat: Web Keys management
(https://github.com/zitadel/zitadel/pull/9526)
- fix(cmd): ensure proper working of mirror
(https://github.com/zitadel/zitadel/pull/9509)
- feat(Authz): system user support for permission check v2
(https://github.com/zitadel/zitadel/pull/9640)
- chore(license): change from Apache to AGPL
(https://github.com/zitadel/zitadel/pull/9597)
- feat(console): list v2 sessions
(https://github.com/zitadel/zitadel/pull/9539)
- fix(console): add loginV2 feature flag
(https://github.com/zitadel/zitadel/pull/9682)
- fix(feature flags): allow reading "own" flags
(https://github.com/zitadel/zitadel/pull/9649)
- feat(console): add Actions V2 UI
(https://github.com/zitadel/zitadel/pull/9591)

BREAKING CHANGE
- feat(webkey): migrate to v2beta API
(https://github.com/zitadel/zitadel/pull/9445)
- chore!: remove CockroachDB Support
(https://github.com/zitadel/zitadel/pull/9444)
- feat(actions): migrate to v2beta API
(https://github.com/zitadel/zitadel/pull/9489)

---------

Co-authored-by: Livio Spring <livio.a@gmail.com>
Co-authored-by: Stefan Benz <46600784+stebenz@users.noreply.github.com>
Co-authored-by: Silvan <27845747+adlerhurst@users.noreply.github.com>
Co-authored-by: Ramon <mail@conblem.me>
Co-authored-by: Elio Bischof <elio@zitadel.com>
Co-authored-by: Kenta Yamaguchi <56732734+KEY60228@users.noreply.github.com>
Co-authored-by: Harsha Reddy <harsha.reddy@klaviyo.com>
Co-authored-by: Livio Spring <livio@zitadel.com>
Co-authored-by: Max Peintner <max@caos.ch>
Co-authored-by: Iraq <66622793+kkrime@users.noreply.github.com>
Co-authored-by: Florian Forster <florian@zitadel.com>
Co-authored-by: Tim Möhlmann <tim+github@zitadel.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Max Peintner <peintnerm@gmail.com>
2025-04-02 16:53:06 +02:00

132 lines
3.1 KiB
Go

package key
import (
"io"
"os"
"strings"
"github.com/spf13/cobra"
"github.com/spf13/viper"
"sigs.k8s.io/yaml"
"github.com/zitadel/zitadel/internal/crypto"
cryptoDB "github.com/zitadel/zitadel/internal/crypto/database"
"github.com/zitadel/zitadel/internal/database"
"github.com/zitadel/zitadel/internal/zerrors"
)
const (
flagKeyFile = "file"
)
type Config struct {
Database database.Config
}
func New() *cobra.Command {
cmd := &cobra.Command{
Use: "keys",
Short: "manage encryption keys",
}
AddMasterKeyFlag(cmd)
cmd.AddCommand(newKey())
return cmd
}
func newKey() *cobra.Command {
cmd := &cobra.Command{
Use: "new [keyID=key]... [-f file]",
Short: "create new encryption key(s)",
Long: `create new encryption key(s) (encrypted by the provided master key)
provide key(s) by YAML file and/or by argument
Requirements:
- postgreSQL`,
Example: `new -f keys.yaml
new key1=somekey key2=anotherkey
new -f keys.yaml key2=anotherkey`,
RunE: func(cmd *cobra.Command, args []string) error {
keys, err := keysFromArgs(args)
if err != nil {
return err
}
filePath, _ := cmd.Flags().GetString(flagKeyFile)
if filePath != "" {
file, err := openFile(filePath)
if err != nil {
return err
}
yamlKeys, err := keysFromYAML(file)
if err != nil {
return err
}
keys = append(keys, yamlKeys...)
}
config := new(Config)
if err := viper.Unmarshal(config); err != nil {
return err
}
masterKey, err := MasterKey(cmd)
if err != nil {
return err
}
storage, err := keyStorage(config.Database, masterKey)
if err != nil {
return err
}
return storage.CreateKeys(cmd.Context(), keys...)
},
}
cmd.PersistentFlags().StringP(flagKeyFile, "f", "", "path to keys file")
return cmd
}
func keysFromArgs(args []string) ([]*crypto.Key, error) {
keys := make([]*crypto.Key, len(args))
for i, arg := range args {
key := strings.Split(arg, "=")
if len(key) != 2 {
return nil, zerrors.ThrowInternal(nil, "KEY-JKd82", "argument is not in the valid format [keyID=key]")
}
keys[i] = &crypto.Key{
ID: key[0],
Value: key[1],
}
}
return keys, nil
}
func keysFromYAML(file io.Reader) ([]*crypto.Key, error) {
data, err := io.ReadAll(file)
if err != nil {
return nil, zerrors.ThrowInternal(err, "KEY-ajGFr", "unable to extract keys from file")
}
keysYAML := make(map[string]string)
if err = yaml.Unmarshal(data, &keysYAML); err != nil {
return nil, zerrors.ThrowInternal(err, "KEY-sd34K", "unable to extract keys from file")
}
keys := make([]*crypto.Key, 0, len(keysYAML))
for id, key := range keysYAML {
keys = append(keys, &crypto.Key{
ID: id,
Value: key,
})
}
return keys, nil
}
func openFile(fileName string) (io.Reader, error) {
file, err := os.Open(fileName)
if err != nil {
return nil, zerrors.ThrowInternalf(err, "KEY-asGr2", "failed to open file: %s", fileName)
}
return file, nil
}
func keyStorage(config database.Config, masterKey string) (crypto.KeyStorage, error) {
db, err := database.Connect(config, false)
if err != nil {
return nil, err
}
return cryptoDB.NewKeyStorage(db, masterKey)
}