github.com/aavshr/aws-sdk-go@v1.41.3/service/s3/s3crypto/kms_context_key_handler_test.go (about) 1 package s3crypto 2 3 import ( 4 "bytes" 5 "encoding/base64" 6 "encoding/hex" 7 "encoding/json" 8 "fmt" 9 "io/ioutil" 10 "net/http" 11 "net/http/httptest" 12 "reflect" 13 "strings" 14 "testing" 15 16 "github.com/aavshr/aws-sdk-go/aws" 17 "github.com/aavshr/aws-sdk-go/awstesting/unit" 18 "github.com/aavshr/aws-sdk-go/service/kms" 19 ) 20 21 func TestKmsContextKeyHandler_GenerateCipherDataWithCEKAlg(t *testing.T) { 22 ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 23 bodyBytes, err := ioutil.ReadAll(r.Body) 24 if err != nil { 25 w.WriteHeader(500) 26 return 27 } 28 var body map[string]interface{} 29 err = json.Unmarshal(bodyBytes, &body) 30 if err != nil { 31 w.WriteHeader(500) 32 return 33 } 34 35 md, ok := body["EncryptionContext"].(map[string]interface{}) 36 if !ok { 37 w.WriteHeader(500) 38 return 39 } 40 41 exEncContext := map[string]interface{}{ 42 "aws:" + cekAlgorithmHeader: "cekAlgValue", 43 } 44 45 if e, a := exEncContext, md; !reflect.DeepEqual(e, a) { 46 w.WriteHeader(500) 47 t.Errorf("expected %v, got %v", e, a) 48 return 49 } 50 51 fmt.Fprintln(w, `{"CiphertextBlob":"AQEDAHhqBCCY1MSimw8gOGcUma79cn4ANvTtQyv9iuBdbcEF1QAAAH4wfAYJKoZIhvcNAQcGoG8wbQIBADBoBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDJ6IcN5E4wVbk38MNAIBEIA7oF1E3lS7FY9DkoxPc/UmJsEwHzL82zMqoLwXIvi8LQHr8If4Lv6zKqY8u0+JRgSVoqCvZDx3p8Cn6nM=","KeyId":"arn:aws:kms:us-west-2:042062605278:key/c80a5cdb-8d09-4f9f-89ee-df01b2e3870a","Plaintext":"6tmyz9JLBE2yIuU7iXpArqpDVle172WSmxjcO6GNT7E="}`) 52 })) 53 defer ts.Close() 54 55 sess := unit.Session.Copy(&aws.Config{ 56 MaxRetries: aws.Int(0), 57 Endpoint: aws.String(ts.URL), 58 DisableSSL: aws.Bool(true), 59 S3ForcePathStyle: aws.Bool(true), 60 Region: aws.String("us-west-2"), 61 }) 62 63 svc := kms.New(sess) 64 handler := NewKMSContextKeyGenerator(svc, "testid", nil) 65 66 keySize := 32 67 ivSize := 16 68 69 cd, err := handler.GenerateCipherDataWithCEKAlg(aws.BackgroundContext(), keySize, ivSize, "cekAlgValue") 70 if err != nil { 71 t.Errorf("expected no error, but received %v", err) 72 } 73 if keySize != len(cd.Key) { 74 t.Errorf("expected %d, but received %d", keySize, len(cd.Key)) 75 } 76 if ivSize != len(cd.IV) { 77 t.Errorf("expected %d, but received %d", ivSize, len(cd.IV)) 78 } 79 } 80 81 func TestKmsContextKeyHandler_GenerateCipherDataWithCEKAlg_ReservedKeyConflict(t *testing.T) { 82 svc := kms.New(unit.Session.Copy()) 83 handler := NewKMSContextKeyGenerator(svc, "testid", MaterialDescription{ 84 "aws:x-amz-cek-alg": aws.String("something unexpected"), 85 }) 86 87 _, err := handler.GenerateCipherDataWithCEKAlg(aws.BackgroundContext(), 32, 16, "cekAlgValue") 88 if err == nil { 89 t.Errorf("expected error, but none") 90 } else if !strings.Contains(err.Error(), "conflict in reserved KMS Encryption Context key aws:x-amz-cek-alg") { 91 t.Errorf("expected reserved key error, got %v", err) 92 } 93 } 94 95 func TestKmsContextKeyHandler_DecryptKey(t *testing.T) { 96 key, _ := hex.DecodeString("31bdadd96698c204aa9ce1448ea94ae1fb4a9a0b3c9d773b51bb1822666b8f22") 97 keyB64 := base64.URLEncoding.EncodeToString(key) 98 ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 99 bodyBytes, err := ioutil.ReadAll(r.Body) 100 if err != nil { 101 t.Errorf("expected no error, got %v", err) 102 w.WriteHeader(500) 103 return 104 } 105 106 var body map[string]interface{} 107 err = json.Unmarshal(bodyBytes, &body) 108 if err != nil { 109 w.WriteHeader(500) 110 return 111 } 112 113 if _, ok := body["KeyId"]; ok { 114 t.Errorf("expected CMK to not be sent") 115 } 116 117 md, ok := body["EncryptionContext"].(map[string]interface{}) 118 if !ok { 119 w.WriteHeader(500) 120 return 121 } 122 123 exEncContext := map[string]interface{}{ 124 "aws:" + cekAlgorithmHeader: "AES/GCM/NoPadding", 125 } 126 127 if e, a := exEncContext, md; !reflect.DeepEqual(e, a) { 128 w.WriteHeader(500) 129 t.Errorf("expected %v, got %v", e, a) 130 return 131 } 132 133 fmt.Fprintln(w, fmt.Sprintf("%s%s%s", `{"KeyId":"test-key-id","Plaintext":"`, keyB64, `"}`)) 134 })) 135 defer ts.Close() 136 137 sess := unit.Session.Copy(&aws.Config{ 138 MaxRetries: aws.Int(0), 139 Endpoint: aws.String(ts.URL), 140 DisableSSL: aws.Bool(true), 141 S3ForcePathStyle: aws.Bool(true), 142 Region: aws.String("us-west-2"), 143 }) 144 handler, err := newKMSContextWrapEntryWithAnyCMK(kms.New(sess))(Envelope{WrapAlg: KMSContextWrap, CEKAlg: "AES/GCM/NoPadding", MatDesc: `{"aws:x-amz-cek-alg": "AES/GCM/NoPadding"}`}) 145 if err != nil { 146 t.Fatalf("expected no error, but received %v", err) 147 } 148 149 plaintextKey, err := handler.DecryptKey([]byte{1, 2, 3, 4}) 150 if err != nil { 151 t.Errorf("expected no error, but received %v", err) 152 } 153 154 if !bytes.Equal(key, plaintextKey) { 155 t.Errorf("expected %v, but received %v", key, plaintextKey) 156 } 157 } 158 159 func TestKmsContextKeyHandler_decryptHandler_MismatchCEK(t *testing.T) { 160 _, err := newKMSContextWrapEntryWithAnyCMK(kms.New(unit.Session.Copy()))(Envelope{WrapAlg: KMSContextWrap, CEKAlg: "MismatchCEKValue", MatDesc: `{"aws:x-amz-cek-alg": "AES/GCM/NoPadding"}`}) 161 if err == nil { 162 t.Fatal("expected error, but got none") 163 } 164 165 if e, a := "algorithm used at encryption time does not match the algorithm stored", err.Error(); !strings.Contains(a, e) { 166 t.Errorf("expected error to contain %v, got %v", e, a) 167 } 168 } 169 170 func TestKmsContextKeyHandler_decryptHandler_MissingContextKey(t *testing.T) { 171 _, err := newKMSContextWrapEntryWithAnyCMK(kms.New(unit.Session.Copy()))(Envelope{WrapAlg: KMSContextWrap, CEKAlg: "AES/GCM/NoPadding", MatDesc: `{}`}) 172 if err == nil { 173 t.Fatal("expected error, but got none") 174 } 175 176 if e, a := "missing from encryption context", err.Error(); !strings.Contains(a, e) { 177 t.Errorf("expected error to contain %v, got %v", e, a) 178 } 179 } 180 181 func TestKmsContextKeyHandler_decryptHandler_MismatchWrap(t *testing.T) { 182 _, err := newKMSContextWrapEntryWithAnyCMK(kms.New(unit.Session.Copy()))(Envelope{WrapAlg: KMSWrap, CEKAlg: "AES/GCM/NoPadding", MatDesc: `{}`}) 183 if err == nil { 184 t.Fatal("expected error, but got none") 185 } 186 187 if e, a := "x-amz-cek-alg value `kms` did not match the expected algorithm `kms+context` for this handler", err.Error(); !strings.Contains(a, e) { 188 t.Errorf("expected error to contain %v, got %v", e, a) 189 } 190 } 191 192 func TestKmsContextKeyHandler_DecryptKey_WithCMK(t *testing.T) { 193 key, _ := hex.DecodeString("31bdadd96698c204aa9ce1448ea94ae1fb4a9a0b3c9d773b51bb1822666b8f22") 194 keyB64 := base64.URLEncoding.EncodeToString(key) 195 ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 196 body, err := ioutil.ReadAll(r.Body) 197 if err != nil { 198 t.Errorf("expected no error, got %v", err) 199 w.WriteHeader(500) 200 return 201 } 202 203 if !bytes.Contains(body, []byte(`"KeyId":"thisKey"`)) { 204 t.Errorf("expected CMK to be sent") 205 } 206 207 fmt.Fprintln(w, fmt.Sprintf("%s%s%s", `{"KeyId":"thisKey","Plaintext":"`, keyB64, `"}`)) 208 })) 209 defer ts.Close() 210 211 sess := unit.Session.Copy(&aws.Config{ 212 MaxRetries: aws.Int(0), 213 Endpoint: aws.String(ts.URL), 214 DisableSSL: aws.Bool(true), 215 S3ForcePathStyle: aws.Bool(true), 216 Region: aws.String("us-west-2"), 217 }) 218 handler, err := newKMSContextWrapEntryWithCMK(kms.New(sess), "thisKey")(Envelope{WrapAlg: KMSContextWrap, CEKAlg: "AES/GCM/NoPadding", MatDesc: `{"aws:x-amz-cek-alg": "AES/GCM/NoPadding"}`}) 219 if err != nil { 220 t.Errorf("expected no error, but received %v", err) 221 } 222 223 _, err = handler.DecryptKey([]byte{1, 2, 3, 4}) 224 if err != nil { 225 t.Errorf("expected no error, but received %v", err) 226 } 227 } 228 229 func TestRegisterKMSContextWrapWithAnyCMK(t *testing.T) { 230 kmsClient := kms.New(unit.Session.Copy()) 231 232 cr := NewCryptoRegistry() 233 if err := RegisterKMSContextWrapWithAnyCMK(cr, kmsClient); err != nil { 234 t.Errorf("expected no error, got %v", err) 235 } 236 237 if wrap, ok := cr.GetWrap(KMSContextWrap); !ok { 238 t.Errorf("expected wrapped to be present") 239 } else if wrap == nil { 240 t.Errorf("expected wrap to not be nil") 241 } 242 243 if err := RegisterKMSContextWrapWithCMK(cr, kmsClient, "test-key-id"); err == nil { 244 t.Error("expected error, got none") 245 } 246 } 247 248 func TestRegisterKMSContextWrapWithCMK(t *testing.T) { 249 kmsClient := kms.New(unit.Session.Copy()) 250 251 cr := NewCryptoRegistry() 252 if err := RegisterKMSContextWrapWithCMK(cr, kmsClient, "cmkId"); err != nil { 253 t.Errorf("expected no error, got %v", err) 254 } 255 256 if wrap, ok := cr.GetWrap(KMSContextWrap); !ok { 257 t.Errorf("expected wrapped to be present") 258 } else if wrap == nil { 259 t.Errorf("expected wrap to not be nil") 260 } 261 262 if err := RegisterKMSContextWrapWithAnyCMK(cr, kmsClient); err == nil { 263 t.Error("expected error, got none") 264 } 265 }