github.com/aavshr/aws-sdk-go@v1.41.3/service/s3/s3crypto/decryption_client_test.go (about)

     1  package s3crypto_test
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/base64"
     6  	"encoding/hex"
     7  	"fmt"
     8  	"io/ioutil"
     9  	"net/http"
    10  	"net/http/httptest"
    11  	"strings"
    12  	"testing"
    13  
    14  	"github.com/aavshr/aws-sdk-go/aws"
    15  	"github.com/aavshr/aws-sdk-go/aws/awserr"
    16  	"github.com/aavshr/aws-sdk-go/aws/request"
    17  	"github.com/aavshr/aws-sdk-go/awstesting"
    18  	"github.com/aavshr/aws-sdk-go/awstesting/unit"
    19  	"github.com/aavshr/aws-sdk-go/service/s3"
    20  	"github.com/aavshr/aws-sdk-go/service/s3/s3crypto"
    21  )
    22  
    23  func TestGetObjectGCM(t *testing.T) {
    24  	key, _ := hex.DecodeString("31bdadd96698c204aa9ce1448ea94ae1fb4a9a0b3c9d773b51bb1822666b8f22")
    25  	keyB64 := base64.StdEncoding.EncodeToString(key)
    26  	// This is our KMS response
    27  	ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    28  		fmt.Fprintln(w, fmt.Sprintf("%s%s%s", `{"KeyId":"test-key-id","Plaintext":"`, keyB64, `"}`))
    29  	}))
    30  	defer ts.Close()
    31  
    32  	sess := unit.Session.Copy(&aws.Config{
    33  		MaxRetries:       aws.Int(0),
    34  		Endpoint:         aws.String(ts.URL),
    35  		DisableSSL:       aws.Bool(true),
    36  		S3ForcePathStyle: aws.Bool(true),
    37  		Region:           aws.String("us-west-2"),
    38  	})
    39  
    40  	c := s3crypto.NewDecryptionClient(sess)
    41  	if c == nil {
    42  		t.Error("expected non-nil value")
    43  	}
    44  	input := &s3.GetObjectInput{
    45  		Key:    aws.String("test"),
    46  		Bucket: aws.String("test"),
    47  	}
    48  	req, out := c.GetObjectRequest(input)
    49  	req.Handlers.Send.Clear()
    50  	req.Handlers.Send.PushBack(func(r *request.Request) {
    51  		iv, err := hex.DecodeString("0d18e06c7c725ac9e362e1ce")
    52  		if err != nil {
    53  			t.Errorf("expected no error, but received %v", err)
    54  		}
    55  
    56  		b, err := hex.DecodeString("fa4362189661d163fcd6a56d8bf0405ad636ac1bbedd5cc3ee727dc2ab4a9489")
    57  		if err != nil {
    58  			t.Errorf("expected no error, but received %v", err)
    59  		}
    60  
    61  		r.HTTPResponse = &http.Response{
    62  			StatusCode: 200,
    63  			Header: http.Header{
    64  				http.CanonicalHeaderKey("x-amz-meta-x-amz-key-v2"):   []string{"SpFRES0JyU8BLZSKo51SrwILK4lhtZsWiMNjgO4WmoK+joMwZPG7Hw=="},
    65  				http.CanonicalHeaderKey("x-amz-meta-x-amz-iv"):       []string{base64.URLEncoding.EncodeToString(iv)},
    66  				http.CanonicalHeaderKey("x-amz-meta-x-amz-matdesc"):  []string{`{"kms_cmk_id":"arn:aws:kms:us-east-1:172259396726:key/a22a4b30-79f4-4b3d-bab4-a26d327a231b"}`},
    67  				http.CanonicalHeaderKey("x-amz-meta-x-amz-wrap-alg"): []string{s3crypto.KMSWrap},
    68  				http.CanonicalHeaderKey("x-amz-meta-x-amz-cek-alg"):  []string{s3crypto.AESGCMNoPadding},
    69  				http.CanonicalHeaderKey("x-amz-meta-x-amz-tag-len"):  []string{"128"},
    70  			},
    71  			Body: ioutil.NopCloser(bytes.NewBuffer(b)),
    72  		}
    73  	})
    74  	err := req.Send()
    75  	if err != nil {
    76  		t.Errorf("expected no error, but received %v", err)
    77  	}
    78  	b, err := ioutil.ReadAll(out.Body)
    79  	if err != nil {
    80  		t.Errorf("expected no error, but received %v", err)
    81  	}
    82  	expected, err := hex.DecodeString("2db5168e932556f8089a0622981d017d")
    83  	if err != nil {
    84  		t.Errorf("expected no error, but received %v", err)
    85  	}
    86  
    87  	if !bytes.Equal(expected, b) {
    88  		t.Error("expected bytes to be equivalent")
    89  	}
    90  }
    91  
    92  func TestGetObjectCBC(t *testing.T) {
    93  	key, _ := hex.DecodeString("898be9cc5004ed0fa6e117c9a3099d31")
    94  	keyB64 := base64.StdEncoding.EncodeToString(key)
    95  	// This is our KMS response
    96  	ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    97  		fmt.Fprintln(w, fmt.Sprintf("%s%s%s", `{"KeyId":"test-key-id","Plaintext":"`, keyB64, `"}`))
    98  	}))
    99  	defer ts.Close()
   100  
   101  	sess := unit.Session.Copy(&aws.Config{
   102  		MaxRetries:       aws.Int(0),
   103  		Endpoint:         aws.String(ts.URL),
   104  		DisableSSL:       aws.Bool(true),
   105  		S3ForcePathStyle: aws.Bool(true),
   106  		Region:           aws.String("us-west-2"),
   107  	})
   108  
   109  	c := s3crypto.NewDecryptionClient(sess)
   110  	if c == nil {
   111  		t.Error("expected non-nil value")
   112  	}
   113  	input := &s3.GetObjectInput{
   114  		Key:    aws.String("test"),
   115  		Bucket: aws.String("test"),
   116  	}
   117  	req, out := c.GetObjectRequest(input)
   118  	req.Handlers.Send.Clear()
   119  	req.Handlers.Send.PushBack(func(r *request.Request) {
   120  		iv, err := hex.DecodeString("9dea7621945988f96491083849b068df")
   121  		if err != nil {
   122  			t.Errorf("expected no error, but received %v", err)
   123  		}
   124  		b, err := hex.DecodeString("e232cd6ef50047801ee681ec30f61d53cfd6b0bca02fd03c1b234baa10ea82ac9dab8b960926433a19ce6dea08677e34")
   125  		if err != nil {
   126  			t.Errorf("expected no error, but received %v", err)
   127  		}
   128  
   129  		r.HTTPResponse = &http.Response{
   130  			StatusCode: 200,
   131  			Header: http.Header{
   132  				http.CanonicalHeaderKey("x-amz-meta-x-amz-key-v2"):   []string{"SpFRES0JyU8BLZSKo51SrwILK4lhtZsWiMNjgO4WmoK+joMwZPG7Hw=="},
   133  				http.CanonicalHeaderKey("x-amz-meta-x-amz-iv"):       []string{base64.URLEncoding.EncodeToString(iv)},
   134  				http.CanonicalHeaderKey("x-amz-meta-x-amz-matdesc"):  []string{`{"kms_cmk_id":"arn:aws:kms:us-east-1:172259396726:key/a22a4b30-79f4-4b3d-bab4-a26d327a231b"}`},
   135  				http.CanonicalHeaderKey("x-amz-meta-x-amz-wrap-alg"): []string{s3crypto.KMSWrap},
   136  				http.CanonicalHeaderKey("x-amz-meta-x-amz-cek-alg"):  []string{strings.Join([]string{s3crypto.AESCBC, s3crypto.AESCBCPadder.Name()}, "/")},
   137  			},
   138  			Body: ioutil.NopCloser(bytes.NewBuffer(b)),
   139  		}
   140  	})
   141  	err := req.Send()
   142  	if err != nil {
   143  		t.Errorf("expected no error, but received %v", err)
   144  	}
   145  	b, err := ioutil.ReadAll(out.Body)
   146  	if err != nil {
   147  		t.Errorf("expected no error, but received %v", err)
   148  	}
   149  	expected, err := hex.DecodeString("0397f4f6820b1f9386f14403be5ac16e50213bd473b4874b9bcbf5f318ee686b1d")
   150  	if err != nil {
   151  		t.Errorf("expected no error, but received %v", err)
   152  	}
   153  
   154  	if !bytes.Equal(expected, b) {
   155  		t.Error("expected bytes to be equivalent")
   156  	}
   157  }
   158  
   159  func TestGetObjectCBC2(t *testing.T) {
   160  	key, _ := hex.DecodeString("8d70e92489c4e6cfb12261b4d17f4b85826da687fc8742fcf9f87fadb5b4cb89")
   161  	keyB64 := base64.StdEncoding.EncodeToString(key)
   162  	// This is our KMS response
   163  	ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   164  		fmt.Fprintln(w, fmt.Sprintf("%s%s%s", `{"KeyId":"test-key-id","Plaintext":"`, keyB64, `"}`))
   165  	}))
   166  	defer ts.Close()
   167  
   168  	sess := unit.Session.Copy(&aws.Config{
   169  		MaxRetries:       aws.Int(0),
   170  		Endpoint:         aws.String(ts.URL),
   171  		DisableSSL:       aws.Bool(true),
   172  		S3ForcePathStyle: aws.Bool(true),
   173  		Region:           aws.String("us-west-2"),
   174  	})
   175  
   176  	c := s3crypto.NewDecryptionClient(sess)
   177  	if c == nil {
   178  		t.Error("expected non-nil value")
   179  	}
   180  	input := &s3.GetObjectInput{
   181  		Key:    aws.String("test"),
   182  		Bucket: aws.String("test"),
   183  	}
   184  	req, out := c.GetObjectRequest(input)
   185  	req.Handlers.Send.Clear()
   186  	req.Handlers.Send.PushBack(func(r *request.Request) {
   187  		b, err := hex.DecodeString("fd0c71ecb7ed16a9bf42ea5f75501d416df608f190890c3b4d8897f24744cd7f9ea4a0b212e60634302450e1c5378f047ff753ccefe365d411c36339bf22e301fae4c3a6226719a4b93dc74c1af79d0296659b5d56c0892315f2c7cc30190220db1eaafae3920d6d9c65d0aa366499afc17af493454e141c6e0fbdeb6a990cb4")
   188  		if err != nil {
   189  			t.Errorf("expected no error, but received %v", err)
   190  		}
   191  
   192  		r.HTTPResponse = &http.Response{
   193  			StatusCode: 200,
   194  			Header: http.Header{
   195  				http.CanonicalHeaderKey("x-amz-meta-x-amz-key-v2"):   []string{"AQEDAHikdGvcj7Gil5VqAR/JWvvPp3ue26+t2vhWy4lL2hg4mAAAAH4wfAYJKoZIhvcNAQcGoG8wbQIBADBoBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDCcy43wCR0bSsnzTrAIBEIA7WdD2jxC3tCrK6TOdiEfbIN64m+UN7Velz4y0LRra5jn2U1CDClacwIpiBYuDp5ymPKO+ZqUGE0WEf20="},
   196  				http.CanonicalHeaderKey("x-amz-meta-x-amz-iv"):       []string{"EMMWJY8ZLcK/9FOj3iCpng=="},
   197  				http.CanonicalHeaderKey("x-amz-meta-x-amz-matdesc"):  []string{`{"kms_cmk_id":"arn:aws:kms:us-east-1:172259396726:key/a22a4b30-79f4-4b3d-bab4-a26d327a231b"}`},
   198  				http.CanonicalHeaderKey("x-amz-meta-x-amz-wrap-alg"): []string{s3crypto.KMSWrap},
   199  				http.CanonicalHeaderKey("x-amz-meta-x-amz-cek-alg"):  []string{strings.Join([]string{s3crypto.AESCBC, s3crypto.AESCBCPadder.Name()}, "/")},
   200  			},
   201  			Body: ioutil.NopCloser(bytes.NewBuffer(b)),
   202  		}
   203  	})
   204  	err := req.Send()
   205  	if err != nil {
   206  		t.Errorf("expected no error, but received %v", err)
   207  	}
   208  	b, err := ioutil.ReadAll(out.Body)
   209  	if err != nil {
   210  		t.Errorf("expected no error, but received %v", err)
   211  	}
   212  	expected, err := hex.DecodeString("a6ccd3482f5ce25c9ddeb69437cd0acbc0bdda2ef8696d90781de2b35704543529871b2032e68ef1c5baed1769aba8d420d1aca181341b49b8b3587a6580cdf1d809c68f06735f7735c16691f4b70c967d68fc08195b81ad71bcc4df452fd0a5799c1e1234f92f1cd929fc072167ccf9f2ac85b93170932b32")
   213  	if err != nil {
   214  		t.Errorf("expected no error, but received %v", err)
   215  	}
   216  
   217  	if !bytes.Equal(expected, b) {
   218  		t.Error("expected bytes to be equivalent")
   219  	}
   220  }
   221  
   222  func TestGetObjectWithContext(t *testing.T) {
   223  	c := s3crypto.NewDecryptionClient(unit.Session)
   224  
   225  	ctx := &awstesting.FakeContext{DoneCh: make(chan struct{})}
   226  	ctx.Error = fmt.Errorf("context canceled")
   227  	close(ctx.DoneCh)
   228  
   229  	input := s3.GetObjectInput{
   230  		Key:    aws.String("test"),
   231  		Bucket: aws.String("test"),
   232  	}
   233  	_, err := c.GetObjectWithContext(ctx, &input)
   234  	if err == nil {
   235  		t.Fatalf("expected error, did not get one")
   236  	}
   237  	aerr := err.(awserr.Error)
   238  	if e, a := request.CanceledErrorCode, aerr.Code(); e != a {
   239  		t.Errorf("expected error code %q, got %q", e, a)
   240  	}
   241  	if e, a := "canceled", aerr.Message(); !strings.Contains(a, e) {
   242  		t.Errorf("expected error message to contain %q, but did not %q", e, a)
   243  	}
   244  }
   245  
   246  func TestDecryptionClient_GetObject_V2Artifact(t *testing.T) {
   247  	ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   248  		fmt.Fprintln(w, fmt.Sprintf("%s%s%s", `{"KeyId":"test-key-id","Plaintext":"`, "hJUv7S6K2cHF64boS9ixHX0TZAjBZLT4ZpEO4XxkGnY=", `"}`))
   249  	}))
   250  	defer ts.Close()
   251  
   252  	c := s3crypto.NewDecryptionClient(unit.Session.Copy(&aws.Config{Endpoint: &ts.URL}))
   253  
   254  	input := &s3.GetObjectInput{
   255  		Bucket: aws.String("test"),
   256  		Key:    aws.String("test"),
   257  	}
   258  
   259  	req, out := c.GetObjectRequest(input)
   260  	req.Handlers.Send.Clear()
   261  	req.Handlers.Send.PushBack(func(r *request.Request) {
   262  		b, err := hex.DecodeString("6b134eb7a353131de92faff64f594b2794e3544e31776cca26fe3bbeeffc68742d1007234f11c6670522602326868e29f37e9d2678f1614ec1a2418009b9772100929aadbed9a21a")
   263  		if err != nil {
   264  			t.Errorf("expected no error, but received %v", err)
   265  		}
   266  
   267  		r.HTTPResponse = &http.Response{
   268  			StatusCode: 200,
   269  			Header: http.Header{
   270  				http.CanonicalHeaderKey("x-amz-meta-x-amz-key-v2"):   []string{"PsuclPnlo2O0MQoov6kL1TBlaZG6oyNwWuAqmAgq7g8b9ZeeORi3VTMg624FU9jx"},
   271  				http.CanonicalHeaderKey("x-amz-meta-x-amz-iv"):       []string{"dqqlq2dRVSQ5hFRb"},
   272  				http.CanonicalHeaderKey("x-amz-meta-x-amz-matdesc"):  []string{`{"aws:x-amz-cek-alg": "AES/GCM/NoPadding"}`},
   273  				http.CanonicalHeaderKey("x-amz-meta-x-amz-wrap-alg"): []string{s3crypto.KMSContextWrap},
   274  				http.CanonicalHeaderKey("x-amz-meta-x-amz-cek-alg"):  []string{"AES/GCM/NoPadding"},
   275  			},
   276  			Body: ioutil.NopCloser(bytes.NewBuffer(b)),
   277  		}
   278  	})
   279  	err := req.Send()
   280  	if err != nil {
   281  		t.Fatalf("expected no error, got %v", err)
   282  	}
   283  
   284  	actual, err := ioutil.ReadAll(out.Body)
   285  	if err != nil {
   286  		t.Fatalf("expected no error, got %v", err)
   287  	}
   288  
   289  	expected, err := hex.DecodeString("af150d7156bf5b3f5c461e5c6ac820acc5a33aab7085d920666c250ff251209d5a4029b3bd78250fab6e11aed52fae948d407056a9519b68")
   290  	if err != nil {
   291  		t.Fatalf("expected no error, got %v", err)
   292  	}
   293  
   294  	if bytes.Compare(expected, actual) != 0 {
   295  		t.Fatalf("expected content to match but it did not")
   296  	}
   297  }