keychain: always ensure the default key is generated
Signed-off-by: Andrea Luzzardi <aluzzardi@gmail.com>
This commit is contained in:
parent
a4e31949a3
commit
687c0e33a4
@ -12,6 +12,7 @@ import (
|
|||||||
"go.dagger.io/dagger/cmd/dagger/cmd/input"
|
"go.dagger.io/dagger/cmd/dagger/cmd/input"
|
||||||
"go.dagger.io/dagger/cmd/dagger/cmd/output"
|
"go.dagger.io/dagger/cmd/dagger/cmd/output"
|
||||||
"go.dagger.io/dagger/cmd/dagger/logger"
|
"go.dagger.io/dagger/cmd/dagger/logger"
|
||||||
|
"go.dagger.io/dagger/keychain"
|
||||||
)
|
)
|
||||||
|
|
||||||
var rootCmd = &cobra.Command{
|
var rootCmd = &cobra.Command{
|
||||||
@ -25,8 +26,16 @@ func init() {
|
|||||||
rootCmd.PersistentFlags().StringP("environment", "e", "", "Select an environment")
|
rootCmd.PersistentFlags().StringP("environment", "e", "", "Select an environment")
|
||||||
rootCmd.PersistentFlags().StringP("workspace", "w", "", "Specify a workspace (defaults to current git repository)")
|
rootCmd.PersistentFlags().StringP("workspace", "w", "", "Specify a workspace (defaults to current git repository)")
|
||||||
|
|
||||||
rootCmd.PersistentPreRun = func(*cobra.Command, []string) {
|
rootCmd.PersistentPreRun = func(cmd *cobra.Command, _ []string) {
|
||||||
|
lg := logger.New()
|
||||||
|
ctx := lg.WithContext(cmd.Context())
|
||||||
|
|
||||||
go checkVersion()
|
go checkVersion()
|
||||||
|
|
||||||
|
err := keychain.EnsureDefaultKey(ctx)
|
||||||
|
if err != nil {
|
||||||
|
lg.Fatal().Err(err).Msg("failed to generate default key")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
rootCmd.PersistentPostRun = func(*cobra.Command, []string) {
|
rootCmd.PersistentPostRun = func(*cobra.Command, []string) {
|
||||||
warnVersion()
|
warnVersion()
|
||||||
|
@ -14,43 +14,65 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func Path() (string, error) {
|
func Path() (string, error) {
|
||||||
keysFile, err := homedir.Expand("~/.config/dagger/keys.txt")
|
return homedir.Expand("~/.config/dagger/keys.txt")
|
||||||
|
}
|
||||||
|
|
||||||
|
func EnsureDefaultKey(ctx context.Context) error {
|
||||||
|
keysFile, err := Path()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// if the keys file doesn't exist, attempt a migration
|
// If the keys file already exists, there's nothing to do.
|
||||||
if _, err := os.Stat(keysFile); errors.Is(err, os.ErrNotExist) {
|
_, err = os.Stat(keysFile)
|
||||||
migrateKeys(keysFile)
|
if err == nil {
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return keysFile, nil
|
// If we got a different error than not existent, abort
|
||||||
|
if !errors.Is(err, os.ErrNotExist) {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Attempt a migration from the old keys file
|
||||||
|
migrated, err := migrateKeys(ctx, keysFile)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we migrated a previous identity, stop here.
|
||||||
|
if migrated {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise, generate a new key
|
||||||
|
log.Ctx(ctx).Debug().Msg("generating default key pair")
|
||||||
|
_, err = Generate(ctx)
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// migrateKeys attempts a migration from `~/.dagger/keys.txt` to `~/.config/dagger/keys.txt`
|
// migrateKeys attempts a migration from `~/.dagger/keys.txt` to `~/.config/dagger/keys.txt`
|
||||||
func migrateKeys(keysFile string) error {
|
func migrateKeys(ctx context.Context, keysFile string) (bool, error) {
|
||||||
oldKeysFile, err := homedir.Expand("~/.dagger/keys.txt")
|
oldKeysFile, err := homedir.Expand("~/.dagger/keys.txt")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err := os.Stat(oldKeysFile); err != nil {
|
if _, err := os.Stat(oldKeysFile); err != nil {
|
||||||
return err
|
return false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := os.MkdirAll(filepath.Dir(keysFile), 0700); err != nil {
|
if err := os.MkdirAll(filepath.Dir(keysFile), 0700); err != nil {
|
||||||
return err
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return os.Rename(oldKeysFile, keysFile)
|
log.Ctx(ctx).Info().Msg("migrating keychain")
|
||||||
|
return true, os.Rename(oldKeysFile, keysFile)
|
||||||
}
|
}
|
||||||
|
|
||||||
func Default(ctx context.Context) (string, error) {
|
func Default(ctx context.Context) (string, error) {
|
||||||
keys, err := List(ctx)
|
keys, err := List(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, os.ErrNotExist) {
|
|
||||||
return Generate(ctx)
|
|
||||||
}
|
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
if len(keys) == 0 {
|
if len(keys) == 0 {
|
||||||
@ -85,7 +107,7 @@ func Generate(ctx context.Context) (string, error) {
|
|||||||
|
|
||||||
pubkey := k.Recipient().String()
|
pubkey := k.Recipient().String()
|
||||||
|
|
||||||
log.Ctx(ctx).Debug().Str("publicKey", pubkey).Msg("generating keypair")
|
log.Ctx(ctx).Debug().Str("publicKey", pubkey).Msg("keypair generated")
|
||||||
|
|
||||||
return pubkey, nil
|
return pubkey, nil
|
||||||
}
|
}
|
||||||
@ -98,7 +120,7 @@ func List(ctx context.Context) ([]*age.X25519Identity, error) {
|
|||||||
|
|
||||||
f, err := os.Open(keysFile)
|
f, err := os.Open(keysFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to open keys file file %q: %w", keysFile, err)
|
return nil, fmt.Errorf("failed to open keys file %q: %w", keysFile, err)
|
||||||
}
|
}
|
||||||
ids, err := age.ParseIdentities(f)
|
ids, err := age.ParseIdentities(f)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -107,7 +129,7 @@ func List(ctx context.Context) ([]*age.X25519Identity, error) {
|
|||||||
|
|
||||||
keys := make([]*age.X25519Identity, 0, len(ids))
|
keys := make([]*age.X25519Identity, 0, len(ids))
|
||||||
for _, id := range ids {
|
for _, id := range ids {
|
||||||
key, ok := ids[0].(*age.X25519Identity)
|
key, ok := id.(*age.X25519Identity)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("internal error: unexpected identity type: %T", id)
|
return nil, fmt.Errorf("internal error: unexpected identity type: %T", id)
|
||||||
}
|
}
|
||||||
|
@ -8,12 +8,15 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
"go.dagger.io/dagger/keychain"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestWorkspace(t *testing.T) {
|
func TestWorkspace(t *testing.T) {
|
||||||
ctx := context.TODO()
|
ctx := context.TODO()
|
||||||
|
|
||||||
|
keychain.EnsureDefaultKey(ctx)
|
||||||
|
|
||||||
root, err := os.MkdirTemp(os.TempDir(), "dagger-*")
|
root, err := os.MkdirTemp(os.TempDir(), "dagger-*")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
@ -60,6 +63,8 @@ func TestWorkspace(t *testing.T) {
|
|||||||
func TestEncryption(t *testing.T) {
|
func TestEncryption(t *testing.T) {
|
||||||
ctx := context.TODO()
|
ctx := context.TODO()
|
||||||
|
|
||||||
|
keychain.EnsureDefaultKey(ctx)
|
||||||
|
|
||||||
readManifest := func(st *State) *State {
|
readManifest := func(st *State) *State {
|
||||||
data, err := os.ReadFile(path.Join(st.Path, manifestFile))
|
data, err := os.ReadFile(path.Join(st.Path, manifestFile))
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
Reference in New Issue
Block a user