From e92ff6e0138046a50f33ccba8b07cfc1c0616538 Mon Sep 17 00:00:00 2001 From: p4u1 Date: Mon, 25 Aug 2025 12:52:52 +0200 Subject: [PATCH] feat(secrets): Inserting secret data from stdin This can be usefull for scripting and gives a lot of flexibility --- cli/app/secret.go | 47 +++++++++++++++++++++++++------ tests/integration/app_secret.bats | 17 +++++++++++ 2 files changed, 56 insertions(+), 8 deletions(-) diff --git a/cli/app/secret.go b/cli/app/secret.go index 550714b2..d1ef0b29 100644 --- a/cli/app/secret.go +++ b/cli/app/secret.go @@ -3,6 +3,7 @@ package app import ( "context" "fmt" + "io" "os" "strconv" "strings" @@ -28,7 +29,8 @@ var AppSecretGenerateCommand = &cobra.Command{ ValidArgsFunction: func( cmd *cobra.Command, args []string, - toComplete string) ([]string, cobra.ShellCompDirective) { + toComplete string, + ) ([]string, cobra.ShellCompDirective) { switch l := len(args); l { case 0: return autocomplete.AppNameComplete() @@ -155,12 +157,16 @@ environment. Typically, you can let Abra generate them for you on app creation abra app secret insert 1312.net my_secret v1 mySuperSecret # insert secret as file - abra app secret insert 1312.net my_secret v1 secret.txt -f`), - Args: cobra.MinimumNArgs(4), + abra app secret insert 1312.net my_secret v1 secret.txt -f + + # insert secret from stdin + echo "mmySuperSecret" | abra app secret insert 1312.net my_secret v1`), + Args: cobra.MinimumNArgs(3), ValidArgsFunction: func( cmd *cobra.Command, args []string, - toComplete string) ([]string, cobra.ShellCompDirective) { + toComplete string, + ) ([]string, cobra.ShellCompDirective) { switch l := len(args); l { case 0: return autocomplete.AppNameComplete() @@ -188,7 +194,30 @@ environment. Typically, you can let Abra generate them for you on app creation name := args[1] version := args[2] - data := args[3] + var data string + if len(args) == 4 { + data = args[3] + } else if len(args) == 3 { + if insertFromFile { + log.Fatal("can not insert from file and read from stdin") + } + + fi, err := os.Stdin.Stat() + if err != nil { + log.Fatal(err) + } + if fi.Mode()&os.ModeNamedPipe == 0 { + log.Fatal("need to provide secret data or stdin stream") + } + + log.Debug("reading secret data from stdin") + bytes, err := io.ReadAll(os.Stdin) + if err != nil { + log.Fatalf("reading data from stdin: %s", err) + } + + data = string(bytes) + } composeFiles, err := app.Recipe.GetComposeFiles(app.Env) if err != nil { @@ -210,7 +239,7 @@ environment. Typically, you can let Abra generate them for you on app creation log.Fatal(i18n.G("no secret %s available for recipe %s?", name, app.Recipe.Name)) } - if insertFromFile { + if insertFromFile && len(args) == 4 { raw, err := os.ReadFile(data) if err != nil { log.Fatal(i18n.G("reading secret from file: %s", err)) @@ -269,7 +298,8 @@ match those configured in the recipe beforehand.`), ValidArgsFunction: func( cmd *cobra.Command, args []string, - toComplete string) ([]string, cobra.ShellCompDirective) { + toComplete string, + ) ([]string, cobra.ShellCompDirective) { switch l := len(args); l { case 0: return autocomplete.AppNameComplete() @@ -376,7 +406,8 @@ var AppSecretLsCommand = &cobra.Command{ ValidArgsFunction: func( cmd *cobra.Command, args []string, - toComplete string) ([]string, cobra.ShellCompDirective) { + toComplete string, + ) ([]string, cobra.ShellCompDirective) { return autocomplete.AppNameComplete() }, Run: func(cmd *cobra.Command, args []string) { diff --git a/tests/integration/app_secret.bats b/tests/integration/app_secret.bats index 11151c9a..a009c33c 100644 --- a/tests/integration/app_secret.bats +++ b/tests/integration/app_secret.bats @@ -208,6 +208,9 @@ teardown(){ run $ABRA app secret insert "$TEST_APP_DOMAIN" bar baz assert_failure + + run bash -c "echo foo | $ABRA app secret insert $TEST_APP_DOMAIN bar baz -f" + assert_failure } @test "insert: cannot insert unknown secret" { @@ -248,6 +251,20 @@ teardown(){ assert_output --partial 'true' } +@test "insert: create secret from stdin" { + run $ABRA app secret ls "$TEST_APP_DOMAIN" + assert_success + assert_output --partial 'false' + + run bash -c "echo foo | $ABRA app secret insert $TEST_APP_DOMAIN test_pass_one v1" + assert_success + assert_output --partial 'successfully stored on server' + + run $ABRA app secret ls "$TEST_APP_DOMAIN" + assert_success + assert_output --partial 'true' +} + @test "rm: validate arguments" { run $ABRA app secret rm assert_failure