github.com/juju/juju@v0.0.0-20240327075706-a90865de2538/core/secrets/secret_test.go (about) 1 // Copyright 2021 Canonical Ltd. 2 // Licensed under the LGPLv3, see LICENCE file for details. 3 4 package secrets_test 5 6 import ( 7 "fmt" 8 "time" 9 10 jc "github.com/juju/testing/checkers" 11 "github.com/rs/xid" 12 gc "gopkg.in/check.v1" 13 14 "github.com/juju/juju/core/secrets" 15 ) 16 17 type SecretURISuite struct{} 18 19 var _ = gc.Suite(&SecretURISuite{}) 20 21 const ( 22 secretID = "9m4e2mr0ui3e8a215n4g" 23 secretSource = "deadbeef-1bad-500d-9000-4b1d0d06f00d" 24 secretURI = "secret:9m4e2mr0ui3e8a215n4g" 25 remoteSecretURI = "secret://deadbeef-1bad-500d-9000-4b1d0d06f00d/9m4e2mr0ui3e8a215n4g" 26 remoteSecretID = "deadbeef-1bad-500d-9000-4b1d0d06f00d/9m4e2mr0ui3e8a215n4g" 27 ) 28 29 func (s *SecretURISuite) TestParseURI(c *gc.C) { 30 for _, t := range []struct { 31 in string 32 str string 33 expected *secrets.URI 34 err string 35 }{ 36 { 37 in: "http:nope", 38 err: `secret URI scheme "http" not valid`, 39 }, { 40 in: "secret:a/b/c", 41 err: `secret URI "secret:a/b/c" not valid`, 42 }, { 43 in: "secret:a.b.", 44 err: `secret URI "secret:a.b." not valid`, 45 }, { 46 in: "secret:a.b#", 47 err: `secret URI "secret:a.b#" not valid`, 48 }, { 49 in: secretURI, 50 expected: &secrets.URI{ 51 ID: secretID, 52 }, 53 }, { 54 in: secretID, 55 str: secretURI, 56 expected: &secrets.URI{ 57 ID: secretID, 58 }, 59 }, { 60 in: remoteSecretURI, 61 str: remoteSecretURI, 62 expected: &secrets.URI{ 63 ID: secretID, 64 SourceUUID: secretSource, 65 }, 66 }, { 67 in: remoteSecretID, 68 str: remoteSecretURI, 69 expected: &secrets.URI{ 70 ID: secretID, 71 SourceUUID: secretSource, 72 }, 73 }, 74 } { 75 result, err := secrets.ParseURI(t.in) 76 if t.err != "" || result == nil { 77 c.Check(err, gc.ErrorMatches, t.err) 78 } else { 79 c.Check(result, jc.DeepEquals, t.expected) 80 if t.str != "" { 81 c.Check(result.String(), gc.Equals, t.str) 82 } else { 83 c.Check(result.String(), gc.Equals, t.in) 84 } 85 } 86 } 87 } 88 89 func (s *SecretURISuite) TestString(c *gc.C) { 90 expected := &secrets.URI{ 91 ID: secretID, 92 } 93 str := expected.String() 94 c.Assert(str, gc.Equals, secretURI) 95 uri, err := secrets.ParseURI(str) 96 c.Assert(err, jc.ErrorIsNil) 97 c.Assert(uri, jc.DeepEquals, expected) 98 } 99 100 func (s *SecretURISuite) TestStringWithSource(c *gc.C) { 101 expected := &secrets.URI{ 102 SourceUUID: secretSource, 103 ID: secretID, 104 } 105 str := expected.String() 106 c.Assert(str, gc.Equals, fmt.Sprintf("secret://%s/%s", secretSource, secretID)) 107 uri, err := secrets.ParseURI(str) 108 c.Assert(err, jc.ErrorIsNil) 109 c.Assert(uri, jc.DeepEquals, expected) 110 } 111 112 func (s *SecretURISuite) TestName(c *gc.C) { 113 uri := &secrets.URI{ID: secretID} 114 name := uri.Name(666) 115 c.Assert(name, gc.Equals, `9m4e2mr0ui3e8a215n4g-666`) 116 } 117 118 func (s *SecretURISuite) TestNew(c *gc.C) { 119 URI := secrets.NewURI() 120 _, err := xid.FromString(URI.ID) 121 c.Assert(err, jc.ErrorIsNil) 122 } 123 124 func (s *SecretURISuite) TestWithSource(c *gc.C) { 125 uri := &secrets.URI{ID: secretID} 126 uri = uri.WithSource(secretSource) 127 c.Assert(uri.SourceUUID, gc.Equals, secretSource) 128 c.Assert(uri.ID, gc.Equals, secretID) 129 } 130 131 func (s *SecretURISuite) TestIsLocal(c *gc.C) { 132 URI := secrets.NewURI() 133 c.Assert(URI.IsLocal("other-uuid"), jc.IsTrue) 134 URI2 := URI.WithSource("some-uuid") 135 c.Assert(URI2.IsLocal("some-uuid"), jc.IsTrue) 136 c.Assert(URI2.IsLocal("other-uuid"), jc.IsFalse) 137 } 138 139 type SecretSuite struct{} 140 141 var _ = gc.Suite(&SecretSuite{}) 142 143 func ptr[T any](v T) *T { 144 return &v 145 } 146 147 func (s *SecretSuite) TestValidateConfig(c *gc.C) { 148 cfg := secrets.SecretConfig{ 149 RotatePolicy: ptr(secrets.RotateDaily), 150 } 151 err := cfg.Validate() 152 c.Assert(err, gc.ErrorMatches, "cannot specify a secret rotate policy without a next rotate time") 153 154 cfg = secrets.SecretConfig{ 155 NextRotateTime: ptr(time.Now()), 156 } 157 err = cfg.Validate() 158 c.Assert(err, gc.ErrorMatches, "cannot specify a secret rotate time without a rotate policy") 159 }