From 3f0e41f988151beefeb1d52afa2e04a5a1c9c8e7 Mon Sep 17 00:00:00 2001 From: Nicklas Frahm Date: Thu, 20 Oct 2022 09:42:26 +0200 Subject: [PATCH 1/2] feat(cli): allow rotating the passphrase non-interactively Signed-off-by: Nicklas Frahm --- ...low-rotating-the-passphrase-non-interactively.yaml | 4 ++++ pkg/secrets/passphrase/manager.go | 11 ++++++++--- pkg/secrets/passphrase/manager_test.go | 3 +-- 3 files changed, 13 insertions(+), 5 deletions(-) create mode 100644 changelog/pending/20221020--cli--allow-rotating-the-passphrase-non-interactively.yaml diff --git a/changelog/pending/20221020--cli--allow-rotating-the-passphrase-non-interactively.yaml b/changelog/pending/20221020--cli--allow-rotating-the-passphrase-non-interactively.yaml new file mode 100644 index 000000000000..ced324469562 --- /dev/null +++ b/changelog/pending/20221020--cli--allow-rotating-the-passphrase-non-interactively.yaml @@ -0,0 +1,4 @@ +changes: +- type: feat + scope: cli + description: Allow rotating the passphrase non-interactively diff --git a/pkg/secrets/passphrase/manager.go b/pkg/secrets/passphrase/manager.go index ab764de8251f..5a3e3d0813d6 100644 --- a/pkg/secrets/passphrase/manager.go +++ b/pkg/secrets/passphrase/manager.go @@ -22,7 +22,7 @@ import ( "encoding/json" "errors" "fmt" - "io/ioutil" + "io" "os" "path/filepath" "strings" @@ -225,7 +225,12 @@ func PromptForNewPassphrase(rotate bool) (string, secrets.Manager, error) { firstMessage = "Enter your new passphrase to protect config/secrets" if !isInteractive() { - return "", nil, fmt.Errorf("passphrase rotation requires an interactive terminal") + text, err := io.ReadAll(os.Stdin) + if err != nil { + return "", nil, err + } + phrase = strings.TrimSpace(string(text)) + break } } // Here, the stack does not have an EncryptionSalt, so we will get a passphrase and create one @@ -286,7 +291,7 @@ func readPassphrase(prompt string, useEnv bool) (phrase string, interactive bool if err != nil { return "", false, fmt.Errorf("unable to construct a path the PULUMI_CONFIG_PASSPHRASE_FILE: %w", err) } - phraseDetails, err := ioutil.ReadFile(phraseFilePath) + phraseDetails, err := os.ReadFile(phraseFilePath) if err != nil { return "", false, fmt.Errorf("unable to read PULUMI_CONFIG_PASSPHRASE_FILE: %w", err) } diff --git a/pkg/secrets/passphrase/manager_test.go b/pkg/secrets/passphrase/manager_test.go index 49625e179774..6f8030cd5fdc 100644 --- a/pkg/secrets/passphrase/manager_test.go +++ b/pkg/secrets/passphrase/manager_test.go @@ -1,7 +1,6 @@ package passphrase import ( - "io/ioutil" "os" "strings" "testing" @@ -102,7 +101,7 @@ func TestPassphraseManagerCorrectPassfileReturnsSecretsManager(t *testing.T) { resetEnv := resetPassphraseTestEnvVars() defer resetEnv() - tmpFile, err := ioutil.TempFile("", "pulumi-secret-test") + tmpFile, err := os.CreateTemp("", "pulumi-secret-test") assert.NoError(t, err) defer os.Remove(tmpFile.Name()) _, err = tmpFile.WriteString("password") From 3a06c7a58177cd2cb0e0776080ce2bfadc6420a8 Mon Sep 17 00:00:00 2001 From: Nicklas Frahm Date: Fri, 21 Oct 2022 11:31:54 +0200 Subject: [PATCH 2/2] feat(cli): use scanner to read os.Stdin --- pkg/secrets/passphrase/manager.go | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/pkg/secrets/passphrase/manager.go b/pkg/secrets/passphrase/manager.go index 5a3e3d0813d6..9d492e204356 100644 --- a/pkg/secrets/passphrase/manager.go +++ b/pkg/secrets/passphrase/manager.go @@ -16,13 +16,13 @@ package passphrase import ( + "bufio" "context" cryptorand "crypto/rand" "encoding/base64" "encoding/json" "errors" "fmt" - "io" "os" "path/filepath" "strings" @@ -225,11 +225,9 @@ func PromptForNewPassphrase(rotate bool) (string, secrets.Manager, error) { firstMessage = "Enter your new passphrase to protect config/secrets" if !isInteractive() { - text, err := io.ReadAll(os.Stdin) - if err != nil { - return "", nil, err - } - phrase = strings.TrimSpace(string(text)) + scanner := bufio.NewScanner(os.Stdin) + scanner.Scan() + phrase = strings.TrimSpace(scanner.Text()) break } }