github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/worker/uniter/runner/jujuc/secret-set_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/testing"
    14  	jc "github.com/juju/testing/checkers"
    15  	gc "gopkg.in/check.v1"
    16  
    17  	coresecrets "github.com/juju/juju/core/secrets"
    18  	"github.com/juju/juju/worker/uniter/runner/jujuc"
    19  )
    20  
    21  type SecretUpdateSuite struct {
    22  	ContextSuite
    23  }
    24  
    25  var _ = gc.Suite(&SecretUpdateSuite{})
    26  
    27  func (s *SecretUpdateSuite) TestUpdateSecretInvalidArgs(c *gc.C) {
    28  	hctx, _ := s.ContextSuite.NewHookContext()
    29  
    30  	for _, t := range []struct {
    31  		args []string
    32  		err  string
    33  	}{
    34  		{
    35  			args: []string{},
    36  			err:  "ERROR missing secret URI",
    37  		}, {
    38  			args: []string{"foo"},
    39  			err:  `ERROR secret URI "foo" not valid`,
    40  		}, {
    41  			args: []string{"secret:9m4e2mr0ui3e8a215n4g", "s3cret"},
    42  			err:  `ERROR key value "s3cret" not valid`,
    43  		}, {
    44  			args: []string{"secret:9m4e2mr0ui3e8a215n4g", "foo=bar", "--rotate", "foo"},
    45  			err:  `ERROR rotate policy "foo" not valid`,
    46  		}, {
    47  			args: []string{"secret:9m4e2mr0ui3e8a215n4g", "foo=bar", "--expire", "-1h"},
    48  			err:  `ERROR negative expire duration "-1h" not valid`,
    49  		}, {
    50  			args: []string{"secret:9m4e2mr0ui3e8a215n4g", "foo=bar", "--expire", "2022-01-01"},
    51  			err:  `ERROR expire time or duration "2022-01-01" not valid`,
    52  		},
    53  	} {
    54  		com, err := jujuc.NewCommand(hctx, "secret-set")
    55  		c.Assert(err, jc.ErrorIsNil)
    56  		ctx := cmdtesting.Context(c)
    57  		code := cmd.Main(jujuc.NewJujucCommandWrappedForTest(com), ctx, t.args)
    58  
    59  		c.Assert(code, gc.Equals, 2)
    60  		c.Assert(bufferString(ctx.Stderr), gc.Equals, t.err+"\n")
    61  	}
    62  }
    63  
    64  func (s *SecretUpdateSuite) TestUpdateSecret(c *gc.C) {
    65  	hctx, _ := s.ContextSuite.NewHookContext()
    66  
    67  	expectedExpiry := time.Now().Add(time.Hour)
    68  	com, err := jujuc.NewCommand(hctx, "secret-set")
    69  	c.Assert(err, jc.ErrorIsNil)
    70  	ctx := cmdtesting.Context(c)
    71  	code := cmd.Main(jujuc.NewJujucCommandWrappedForTest(com), ctx, []string{
    72  		"secret:9m4e2mr0ui3e8a215n4g", "data=secret",
    73  		"--rotate", "daily", "--expire", "1h",
    74  		"--description", "sssshhhh",
    75  		"--label", "foobar",
    76  	})
    77  
    78  	c.Assert(code, gc.Equals, 0)
    79  	val := coresecrets.NewSecretValue(map[string]string{"data": "c2VjcmV0"})
    80  	expectedArgs := &jujuc.SecretUpdateArgs{
    81  		Value:        val,
    82  		RotatePolicy: ptr(coresecrets.RotateDaily),
    83  		Description:  ptr("sssshhhh"),
    84  		Label:        ptr("foobar"),
    85  	}
    86  	s.Stub.CheckCallNames(c, "UpdateSecret")
    87  	call := s.Stub.Calls()[0]
    88  	c.Assert(call.Args, gc.HasLen, 2)
    89  	c.Assert(call.Args[0], gc.Equals, "secret:9m4e2mr0ui3e8a215n4g")
    90  	args, ok := call.Args[1].(*jujuc.SecretUpdateArgs)
    91  	c.Assert(ok, jc.IsTrue)
    92  	c.Assert(args.ExpireTime, gc.NotNil)
    93  	c.Assert(args.ExpireTime.After(expectedExpiry), jc.IsTrue)
    94  	args.ExpireTime = nil
    95  	c.Assert(args, jc.DeepEquals, expectedArgs)
    96  }
    97  
    98  func (s *SecretUpdateSuite) TestUpdateSecretBase64(c *gc.C) {
    99  	hctx, _ := s.ContextSuite.NewHookContext()
   100  
   101  	com, err := jujuc.NewCommand(hctx, "secret-set")
   102  	c.Assert(err, jc.ErrorIsNil)
   103  	ctx := cmdtesting.Context(c)
   104  	code := cmd.Main(jujuc.NewJujucCommandWrappedForTest(com), ctx, []string{"secret:9m4e2mr0ui3e8a215n4g", "token#base64=key="})
   105  
   106  	c.Assert(code, gc.Equals, 0)
   107  	val := coresecrets.NewSecretValue(map[string]string{"token": "key="})
   108  	args := &jujuc.SecretUpdateArgs{
   109  		Value: val,
   110  	}
   111  	s.Stub.CheckCalls(c, []testing.StubCall{{FuncName: "UpdateSecret", Args: []interface{}{"secret:9m4e2mr0ui3e8a215n4g", args}}})
   112  }
   113  
   114  func (s *SecretUpdateSuite) TestUpdateSecretRotateInterval(c *gc.C) {
   115  	hctx, _ := s.ContextSuite.NewHookContext()
   116  
   117  	com, err := jujuc.NewCommand(hctx, "secret-set")
   118  	c.Assert(err, jc.ErrorIsNil)
   119  	ctx := cmdtesting.Context(c)
   120  	code := cmd.Main(jujuc.NewJujucCommandWrappedForTest(com), ctx, []string{"--rotate", "daily", "secret:9m4e2mr0ui3e8a215n4g"})
   121  
   122  	c.Assert(code, gc.Equals, 0)
   123  	args := &jujuc.SecretUpdateArgs{
   124  		Value:        coresecrets.NewSecretValue(nil),
   125  		RotatePolicy: ptr(coresecrets.RotateDaily),
   126  	}
   127  	s.Stub.CheckCalls(c, []testing.StubCall{{FuncName: "UpdateSecret", Args: []interface{}{"secret:9m4e2mr0ui3e8a215n4g", args}}})
   128  }
   129  
   130  func (s *SecretUpdateSuite) TestUpdateSecretFromFile(c *gc.C) {
   131  	data := `
   132      key: |-
   133        secret
   134      another-key: !!binary |
   135        R0lGODlhDAAMAIQAAP//9/X17unp5WZmZgAAAOfn515eXvPz7Y6OjuDg4J+fn5
   136        OTk6enp56enmlpaWNjY6Ojo4SEhP/++f/++f/++f/++f/++f/++f/++f/++f/+
   137        +f/++f/++f/++f/++f/++SH+Dk1hZGUgd2l0aCBHSU1QACwAAAAADAAMAAAFLC
   138        AgjoEwnuNAFOhpEMTRiggcz4BNJHrv/zCFcLiwMWYNG84BwwEeECcgggoBADs=`
   139  
   140  	dir := c.MkDir()
   141  	fileName := filepath.Join(dir, "secret.yaml")
   142  	err := os.WriteFile(fileName, []byte(data), os.FileMode(0644))
   143  	c.Assert(err, jc.ErrorIsNil)
   144  
   145  	hctx, _ := s.ContextSuite.NewHookContext()
   146  	com, err := jujuc.NewCommand(hctx, "secret-set")
   147  	c.Assert(err, jc.ErrorIsNil)
   148  	ctx := cmdtesting.Context(c)
   149  	code := cmd.Main(jujuc.NewJujucCommandWrappedForTest(com), ctx, []string{"secret:9m4e2mr0ui3e8a215n4g", "token#base64=key=", "--file", fileName})
   150  
   151  	c.Assert(code, gc.Equals, 0)
   152  	val := coresecrets.NewSecretValue(map[string]string{
   153  		"token":       "key=",
   154  		"key":         "c2VjcmV0",
   155  		"another-key": `R0lGODlhDAAMAIQAAP//9/X17unp5WZmZgAAAOfn515eXvPz7Y6OjuDg4J+fn5OTk6enp56enmlpaWNjY6Ojo4SEhP/++f/++f/++f/++f/++f/++f/++f/++f/++f/++f/++f/++f/++f/++SH+Dk1hZGUgd2l0aCBHSU1QACwAAAAADAAMAAAFLCAgjoEwnuNAFOhpEMTRiggcz4BNJHrv/zCFcLiwMWYNG84BwwEeECcgggoBADs=`,
   156  	})
   157  	args := &jujuc.SecretUpdateArgs{
   158  		Value: val,
   159  	}
   160  	s.Stub.CheckCalls(c, []testing.StubCall{{FuncName: "UpdateSecret", Args: []interface{}{"secret:9m4e2mr0ui3e8a215n4g", args}}})
   161  }