mirror of
https://github.com/zitadel/zitadel.git
synced 2025-08-11 17:27:31 +00:00

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>
132 lines
3.1 KiB
Go
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)
|
|
}
|