github.com/cornelk/go-cloud@v0.17.1/secrets/drivertest/drivertest.go (about) 1 // Copyright 2018 The Go Cloud Development Kit Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // https://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 // Package drivertest provides a conformance test for implementations of 16 // the secrets driver. 17 package drivertest // import "github.com/cornelk/go-cloud/secrets/drivertest" 18 19 import ( 20 "bytes" 21 "context" 22 "errors" 23 "testing" 24 25 "github.com/cornelk/go-cloud/secrets" 26 "github.com/cornelk/go-cloud/secrets/driver" 27 "github.com/google/go-cmp/cmp" 28 ) 29 30 // Harness descibes the functionality test harnesses must provide to run 31 // conformance tests. 32 type Harness interface { 33 // MakeDriver returns a pair of driver.Keeper, each backed by a different key. 34 MakeDriver(ctx context.Context) (driver.Keeper, driver.Keeper, error) 35 36 // Close is called when the test is complete. 37 Close() 38 } 39 40 // HarnessMaker describes functions that construct a harness for running tests. 41 // It is called exactly once per test. 42 type HarnessMaker func(ctx context.Context, t *testing.T) (Harness, error) 43 44 // AsTest represents a test of As functionality. 45 // The conformance test: 46 // 1. Tries to decrypt malformed message, and calls ErrorCheck with the error. 47 type AsTest interface { 48 // Name returns a descriptive name for the test. 49 Name() string 50 // ErrorCheck is called to allow verification of Keeper.ErrorAs. 51 ErrorCheck(k *secrets.Keeper, err error) error 52 } 53 54 type verifyAsFailsOnNil struct{} 55 56 func (v verifyAsFailsOnNil) Name() string { 57 return "verify As returns false when passed nil" 58 } 59 60 func (v verifyAsFailsOnNil) ErrorCheck(k *secrets.Keeper, err error) (ret error) { 61 defer func() { 62 if recover() == nil { 63 ret = errors.New("want ErrorAs to panic when passed nil") 64 } 65 }() 66 k.ErrorAs(err, nil) 67 return nil 68 } 69 70 // RunConformanceTests runs conformance tests for driver implementations of secret management. 71 func RunConformanceTests(t *testing.T, newHarness HarnessMaker, asTests []AsTest) { 72 t.Run("TestEncryptDecrypt", func(t *testing.T) { 73 testEncryptDecrypt(t, newHarness) 74 }) 75 t.Run("TestMultipleEncryptionsNotEqual", func(t *testing.T) { 76 testMultipleEncryptionsNotEqual(t, newHarness) 77 }) 78 t.Run("TestMultipleKeys", func(t *testing.T) { 79 testMultipleKeys(t, newHarness) 80 }) 81 t.Run("TestDecryptMalformedError", func(t *testing.T) { 82 testDecryptMalformedError(t, newHarness) 83 }) 84 asTests = append(asTests, verifyAsFailsOnNil{}) 85 t.Run("TestAs", func(t *testing.T) { 86 for _, tc := range asTests { 87 if tc.Name() == "" { 88 t.Fatal("AsTest.Name is required") 89 } 90 t.Run(tc.Name(), func(t *testing.T) { 91 testAs(t, newHarness, tc) 92 }) 93 } 94 }) 95 } 96 97 // testEncryptDecrypt tests the functionality of encryption and decryption 98 func testEncryptDecrypt(t *testing.T, newHarness HarnessMaker) { 99 ctx := context.Background() 100 harness, err := newHarness(ctx, t) 101 if err != nil { 102 t.Fatal(err) 103 } 104 defer harness.Close() 105 106 drv, _, err := harness.MakeDriver(ctx) 107 if err != nil { 108 t.Fatal(err) 109 } 110 keeper := secrets.NewKeeper(drv) 111 defer keeper.Close() 112 113 msg := []byte("I'm a secret message!") 114 encryptedMsg, err := keeper.Encrypt(ctx, msg) 115 if err != nil { 116 t.Fatal(err) 117 } 118 if cmp.Equal(msg, encryptedMsg) { 119 t.Errorf("Got encrypted message %v, want it to differ from original message %v", string(msg), string(encryptedMsg)) 120 } 121 decryptedMsg, err := keeper.Decrypt(ctx, encryptedMsg) 122 if err != nil { 123 t.Fatal(err) 124 } 125 if !cmp.Equal(msg, decryptedMsg) { 126 t.Errorf("Got decrypted message %v, want it to match original message %v", string(msg), string(decryptedMsg)) 127 } 128 129 } 130 131 // testMultipleEncryptionsNotEqual tests that encrypting a plaintext multiple 132 // times with the same key works, and that the encrypted bytes are different. 133 func testMultipleEncryptionsNotEqual(t *testing.T, newHarness HarnessMaker) { 134 ctx := context.Background() 135 harness, err := newHarness(ctx, t) 136 if err != nil { 137 t.Fatal(err) 138 } 139 defer harness.Close() 140 141 drv, _, err := harness.MakeDriver(ctx) 142 if err != nil { 143 t.Fatal(err) 144 } 145 keeper := secrets.NewKeeper(drv) 146 defer keeper.Close() 147 148 msg := []byte("I'm a secret message!") 149 encryptedMsg1, err := keeper.Encrypt(ctx, msg) 150 if err != nil { 151 t.Fatal(err) 152 } 153 encryptedMsg2, err := keeper.Encrypt(ctx, msg) 154 if err != nil { 155 t.Fatal(err) 156 } 157 if cmp.Equal(encryptedMsg1, encryptedMsg2) { 158 t.Errorf("Got same encrypted messages from multiple encryptions %v, want them to be different", string(encryptedMsg1)) 159 } 160 decryptedMsg, err := keeper.Decrypt(ctx, encryptedMsg1) 161 if err != nil { 162 t.Fatal(err) 163 } 164 if !bytes.Equal(decryptedMsg, msg) { 165 t.Errorf("got decrypted %q want %q", string(decryptedMsg), string(msg)) 166 } 167 decryptedMsg, err = keeper.Decrypt(ctx, encryptedMsg2) 168 if err != nil { 169 t.Fatal(err) 170 } 171 if !bytes.Equal(decryptedMsg, msg) { 172 t.Errorf("got decrypted %q want %q", string(decryptedMsg), string(msg)) 173 } 174 } 175 176 // testMultipleKeys tests that encrypting the same text with different 177 // keys works, and that the encrypted bytes are different. 178 func testMultipleKeys(t *testing.T, newHarness HarnessMaker) { 179 ctx := context.Background() 180 harness, err := newHarness(ctx, t) 181 if err != nil { 182 t.Fatal(err) 183 } 184 defer harness.Close() 185 186 drv1, drv2, err := harness.MakeDriver(ctx) 187 if err != nil { 188 t.Fatal(err) 189 } 190 keeper1 := secrets.NewKeeper(drv1) 191 defer keeper1.Close() 192 keeper2 := secrets.NewKeeper(drv2) 193 defer keeper2.Close() 194 195 msg := []byte("I'm a secret message!") 196 encryptedMsg1, err := keeper1.Encrypt(ctx, msg) 197 if err != nil { 198 t.Fatal(err) 199 } 200 encryptedMsg2, err := keeper2.Encrypt(ctx, msg) 201 if err != nil { 202 t.Fatal(err) 203 } 204 if cmp.Equal(encryptedMsg1, encryptedMsg2) { 205 t.Errorf("Got same encrypted messages from multiple encryptions %v, want them to be different", string(encryptedMsg1)) 206 } 207 208 // We cannot assert that decrypting encryptedMsg1 with keeper2 fails, 209 // or that decrypting encryptedMsg2 with keeper1 fails, as Decrypt is allowed 210 // to decrypt using a different key than the one given to Keeper. 211 212 decryptedMsg, err := keeper1.Decrypt(ctx, encryptedMsg1) 213 if err != nil { 214 t.Fatal(err) 215 } 216 if !bytes.Equal(decryptedMsg, msg) { 217 t.Errorf("got decrypted %q want %q", string(decryptedMsg), string(msg)) 218 } 219 220 decryptedMsg, err = keeper2.Decrypt(ctx, encryptedMsg2) 221 if err != nil { 222 t.Fatal(err) 223 } 224 if !bytes.Equal(decryptedMsg, msg) { 225 t.Errorf("got decrypted %q want %q", string(decryptedMsg), string(msg)) 226 } 227 } 228 229 // testDecryptMalformedError tests decryption returns an error when the 230 // ciphertext is malformed. 231 func testDecryptMalformedError(t *testing.T, newHarness HarnessMaker) { 232 ctx := context.Background() 233 harness, err := newHarness(ctx, t) 234 if err != nil { 235 t.Fatal(err) 236 } 237 defer harness.Close() 238 239 drv, _, err := harness.MakeDriver(ctx) 240 if err != nil { 241 t.Fatal(err) 242 } 243 keeper := secrets.NewKeeper(drv) 244 defer keeper.Close() 245 246 msg := []byte("I'm a secret message!") 247 encryptedMsg, err := keeper.Encrypt(ctx, msg) 248 if err != nil { 249 t.Fatal(err) 250 } 251 copyEncryptedMsg := func() []byte { 252 return append([]byte{}, encryptedMsg...) 253 } 254 255 l := len(encryptedMsg) 256 for _, tc := range []struct { 257 name string 258 malformed []byte 259 }{ 260 { 261 name: "wrong first byte", 262 malformed: append([]byte{encryptedMsg[0] + 1}, encryptedMsg[1:]...), 263 }, 264 { 265 name: "missing second byte", 266 malformed: append(copyEncryptedMsg()[:1], encryptedMsg[2:]...), 267 }, 268 { 269 name: "wrong last byte", 270 malformed: append(copyEncryptedMsg()[:l-2], encryptedMsg[l-1]-1), 271 }, 272 { 273 name: "one more byte", 274 malformed: append(encryptedMsg, 4), 275 }, 276 } { 277 t.Run(tc.name, func(t *testing.T) { 278 if _, err := keeper.Decrypt(ctx, []byte(tc.malformed)); err == nil { 279 t.Error("Got nil, want decrypt error") 280 } 281 }) 282 } 283 } 284 285 func testAs(t *testing.T, newHarness HarnessMaker, tc AsTest) { 286 ctx := context.Background() 287 harness, err := newHarness(ctx, t) 288 if err != nil { 289 t.Fatal(err) 290 } 291 defer harness.Close() 292 293 drv, _, err := harness.MakeDriver(ctx) 294 if err != nil { 295 t.Fatal(err) 296 } 297 keeper := secrets.NewKeeper(drv) 298 defer keeper.Close() 299 300 _, gotErr := keeper.Decrypt(ctx, []byte("malformed cipher message")) 301 if gotErr == nil { 302 t.Error("Got nil, want decrypt error") 303 } 304 if err := tc.ErrorCheck(keeper, gotErr); err != nil { 305 t.Error(err) 306 } 307 }