github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/worker/uniter/runner/jujuc/secret-add_test.go (about) 1 // Copyright 2021 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package jujuc_test 5 6 import ( 7 "os" 8 "path/filepath" 9 "time" 10 11 "github.com/juju/cmd/v3" 12 "github.com/juju/cmd/v3/cmdtesting" 13 "github.com/juju/names/v5" 14 "github.com/juju/testing" 15 jc "github.com/juju/testing/checkers" 16 gc "gopkg.in/check.v1" 17 18 coresecrets "github.com/juju/juju/core/secrets" 19 "github.com/juju/juju/worker/uniter/runner/jujuc" 20 ) 21 22 type SecretAddSuite struct { 23 ContextSuite 24 } 25 26 var _ = gc.Suite(&SecretAddSuite{}) 27 28 func (s *SecretAddSuite) TestAddSecretInvalidArgs(c *gc.C) { 29 hctx, _ := s.ContextSuite.NewHookContext() 30 31 for _, t := range []struct { 32 args []string 33 err string 34 }{ 35 { 36 args: []string{}, 37 err: "ERROR missing secret value or filename", 38 }, { 39 args: []string{"s3cret"}, 40 err: `ERROR key value "s3cret" not valid`, 41 }, { 42 args: []string{"foo=bar", "--rotate", "foo"}, 43 err: `ERROR rotate policy "foo" not valid`, 44 }, { 45 args: []string{"foo=bar", "--owner", "foo"}, 46 err: `ERROR secret owner "foo" not valid`, 47 }, { 48 args: []string{"foo=bar", "--expire", "-1h"}, 49 err: `ERROR negative expire duration "-1h" not valid`, 50 }, { 51 args: []string{"foo=bar", "--expire", "2022-01-01"}, 52 err: `ERROR expire time or duration "2022-01-01" not valid`, 53 }, 54 } { 55 com, err := jujuc.NewCommand(hctx, "secret-add") 56 c.Assert(err, jc.ErrorIsNil) 57 ctx := cmdtesting.Context(c) 58 code := cmd.Main(jujuc.NewJujucCommandWrappedForTest(com), ctx, t.args) 59 60 c.Assert(code, gc.Equals, 2) 61 c.Assert(bufferString(ctx.Stderr), gc.Equals, t.err+"\n") 62 } 63 } 64 65 func ptr[T any](v T) *T { 66 return &v 67 } 68 69 func (s *SecretAddSuite) TestAddSecretExpireDuration(c *gc.C) { 70 hctx, _ := s.ContextSuite.NewHookContext() 71 72 com, err := jujuc.NewCommand(hctx, "secret-add") 73 c.Assert(err, jc.ErrorIsNil) 74 75 expectedExpiry := time.Now().Add(time.Hour) 76 ctx := cmdtesting.Context(c) 77 code := cmd.Main(jujuc.NewJujucCommandWrappedForTest(com), ctx, []string{ 78 "--rotate", "daily", "--expire", "1h", 79 "--description", "sssshhhh", 80 "--label", "foobar", 81 "data=secret", 82 }) 83 84 c.Assert(code, gc.Equals, 0) 85 val := coresecrets.NewSecretValue(map[string]string{"data": "c2VjcmV0"}) 86 expectedArgs := &jujuc.SecretCreateArgs{ 87 SecretUpdateArgs: jujuc.SecretUpdateArgs{ 88 Value: val, 89 RotatePolicy: ptr(coresecrets.RotateDaily), 90 Description: ptr("sssshhhh"), 91 Label: ptr("foobar"), 92 }, 93 OwnerTag: names.NewApplicationTag("u"), 94 } 95 s.Stub.CheckCallNames(c, "UnitName", "CreateSecret") 96 call := s.Stub.Calls()[1] 97 c.Assert(call.Args, gc.HasLen, 1) 98 args, ok := call.Args[0].(*jujuc.SecretCreateArgs) 99 c.Assert(ok, jc.IsTrue) 100 c.Assert(args.ExpireTime, gc.NotNil) 101 c.Assert(args.ExpireTime.After(expectedExpiry), jc.IsTrue) 102 args.ExpireTime = nil 103 c.Assert(args, jc.DeepEquals, expectedArgs) 104 c.Assert(bufferString(ctx.Stdout), gc.Equals, "secret:9m4e2mr0ui3e8a215n4g\n") 105 } 106 107 func (s *SecretAddSuite) TestAddSecretExpireTimestamp(c *gc.C) { 108 hctx, _ := s.ContextSuite.NewHookContext() 109 110 com, err := jujuc.NewCommand(hctx, "secret-add") 111 c.Assert(err, jc.ErrorIsNil) 112 113 ctx := cmdtesting.Context(c) 114 code := cmd.Main(jujuc.NewJujucCommandWrappedForTest(com), ctx, []string{ 115 "--rotate", "daily", "--expire", "2022-03-04T06:06:06", 116 "--description", "sssshhhh", 117 "--label", "foobar", 118 "data=secret", 119 }) 120 121 c.Assert(code, gc.Equals, 0) 122 val := coresecrets.NewSecretValue(map[string]string{"data": "c2VjcmV0"}) 123 expectedExpiry, err := time.Parse("2006-01-02T15:04:05", "2022-03-04T06:06:06") 124 c.Assert(err, jc.ErrorIsNil) 125 args := &jujuc.SecretCreateArgs{ 126 SecretUpdateArgs: jujuc.SecretUpdateArgs{ 127 Value: val, 128 RotatePolicy: ptr(coresecrets.RotateDaily), 129 Description: ptr("sssshhhh"), 130 Label: ptr("foobar"), 131 ExpireTime: ptr(expectedExpiry), 132 }, 133 OwnerTag: names.NewApplicationTag("u"), 134 } 135 s.Stub.CheckCalls(c, []testing.StubCall{{FuncName: "UnitName"}, {FuncName: "CreateSecret", Args: []interface{}{args}}}) 136 c.Assert(bufferString(ctx.Stdout), gc.Equals, "secret:9m4e2mr0ui3e8a215n4g\n") 137 } 138 139 func (s *SecretAddSuite) TestAddSecretBase64(c *gc.C) { 140 hctx, _ := s.ContextSuite.NewHookContext() 141 142 com, err := jujuc.NewCommand(hctx, "secret-add") 143 c.Assert(err, jc.ErrorIsNil) 144 ctx := cmdtesting.Context(c) 145 code := cmd.Main(jujuc.NewJujucCommandWrappedForTest(com), ctx, []string{"token#base64=key=", "--owner", "unit"}) 146 147 c.Assert(code, gc.Equals, 0) 148 val := coresecrets.NewSecretValue(map[string]string{"token": "key="}) 149 args := &jujuc.SecretCreateArgs{ 150 SecretUpdateArgs: jujuc.SecretUpdateArgs{ 151 Value: val, 152 }, 153 OwnerTag: names.NewUnitTag("u/0"), 154 } 155 s.Stub.CheckCalls(c, []testing.StubCall{{FuncName: "UnitName"}, {FuncName: "CreateSecret", Args: []interface{}{args}}}) 156 c.Assert(bufferString(ctx.Stdout), gc.Equals, "secret:9m4e2mr0ui3e8a215n4g\n") 157 } 158 159 func (s *SecretAddSuite) TestAddSecretFromFile(c *gc.C) { 160 data := ` 161 key: |- 162 secret 163 another-key: !!binary | 164 R0lGODlhDAAMAIQAAP//9/X17unp5WZmZgAAAOfn515eXvPz7Y6OjuDg4J+fn5 165 OTk6enp56enmlpaWNjY6Ojo4SEhP/++f/++f/++f/++f/++f/++f/++f/++f/+ 166 +f/++f/++f/++f/++f/++SH+Dk1hZGUgd2l0aCBHSU1QACwAAAAADAAMAAAFLC 167 AgjoEwnuNAFOhpEMTRiggcz4BNJHrv/zCFcLiwMWYNG84BwwEeECcgggoBADs=` 168 169 dir := c.MkDir() 170 fileName := filepath.Join(dir, "secret.yaml") 171 err := os.WriteFile(fileName, []byte(data), os.FileMode(0644)) 172 c.Assert(err, jc.ErrorIsNil) 173 174 hctx, _ := s.ContextSuite.NewHookContext() 175 com, err := jujuc.NewCommand(hctx, "secret-add") 176 c.Assert(err, jc.ErrorIsNil) 177 ctx := cmdtesting.Context(c) 178 code := cmd.Main(jujuc.NewJujucCommandWrappedForTest(com), ctx, []string{"token#base64=key=", "--file", fileName}) 179 180 c.Assert(code, gc.Equals, 0) 181 val := coresecrets.NewSecretValue(map[string]string{ 182 "token": "key=", 183 "key": "c2VjcmV0", 184 "another-key": `R0lGODlhDAAMAIQAAP//9/X17unp5WZmZgAAAOfn515eXvPz7Y6OjuDg4J+fn5OTk6enp56enmlpaWNjY6Ojo4SEhP/++f/++f/++f/++f/++f/++f/++f/++f/++f/++f/++f/++f/++f/++SH+Dk1hZGUgd2l0aCBHSU1QACwAAAAADAAMAAAFLCAgjoEwnuNAFOhpEMTRiggcz4BNJHrv/zCFcLiwMWYNG84BwwEeECcgggoBADs=`, 185 }) 186 args := &jujuc.SecretCreateArgs{ 187 SecretUpdateArgs: jujuc.SecretUpdateArgs{ 188 Value: val, 189 }, 190 OwnerTag: names.NewApplicationTag("u"), 191 } 192 s.Stub.CheckCalls(c, []testing.StubCall{{FuncName: "UnitName"}, {FuncName: "CreateSecret", Args: []interface{}{args}}}) 193 c.Assert(bufferString(ctx.Stdout), gc.Equals, "secret:9m4e2mr0ui3e8a215n4g\n") 194 }