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  }