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

     1  //go:build go1.7
     2  // +build go1.7
     3  
     4  package s3crypto
     5  
     6  import (
     7  	"bytes"
     8  	"encoding/hex"
     9  	"fmt"
    10  	"io"
    11  	"io/ioutil"
    12  	"net/http"
    13  	"net/http/httptest"
    14  	"reflect"
    15  	"strings"
    16  	"testing"
    17  
    18  	"github.com/aavshr/aws-sdk-go/aws"
    19  	"github.com/aavshr/aws-sdk-go/aws/request"
    20  	"github.com/aavshr/aws-sdk-go/aws/session"
    21  	"github.com/aavshr/aws-sdk-go/awstesting/unit"
    22  	"github.com/aavshr/aws-sdk-go/service/kms"
    23  	"github.com/aavshr/aws-sdk-go/service/s3"
    24  )
    25  
    26  func sessionWithLogCheck(message string) (*session.Session, *bool) {
    27  	gotWarning := false
    28  
    29  	u := unit.Session.Copy(&aws.Config{Logger: aws.LoggerFunc(func(i ...interface{}) {
    30  		if len(i) == 0 {
    31  			return
    32  		}
    33  		s, ok := i[0].(string)
    34  		if !ok {
    35  			return
    36  		}
    37  		if s == message {
    38  			gotWarning = true
    39  		}
    40  	})})
    41  
    42  	return u, &gotWarning
    43  }
    44  
    45  func TestNewEncryptionClientV2(t *testing.T) {
    46  	tUnit, gotWarning := sessionWithLogCheck(customTypeWarningMessage)
    47  
    48  	mcb := AESGCMContentCipherBuilderV2(NewKMSContextKeyGenerator(nil, "id", nil))
    49  	v2, err := NewEncryptionClientV2(tUnit, mcb)
    50  	if err != nil {
    51  		t.Fatalf("expected no error, got %v", err)
    52  	}
    53  	if v2 == nil {
    54  		t.Fatal("expected client to not be nil")
    55  	}
    56  
    57  	if *gotWarning {
    58  		t.Errorf("expected no warning for aws provided custom cipher builder")
    59  	}
    60  
    61  	if !reflect.DeepEqual(mcb, v2.options.ContentCipherBuilder) {
    62  		t.Errorf("content cipher builder did not match provided value")
    63  	}
    64  
    65  	_, ok := v2.options.SaveStrategy.(HeaderV2SaveStrategy)
    66  	if !ok {
    67  		t.Errorf("expected default save strategy to be s3 header strategy")
    68  	}
    69  
    70  	if v2.options.S3Client == nil {
    71  		t.Errorf("expected s3 client not be nil")
    72  	}
    73  
    74  	if e, a := DefaultMinFileSize, v2.options.MinFileSize; int64(e) != a {
    75  		t.Errorf("expected %v, got %v", e, a)
    76  	}
    77  
    78  	if e, a := "", v2.options.TempFolderPath; e != a {
    79  		t.Errorf("expected %v, got %v", e, a)
    80  	}
    81  }
    82  
    83  func TestNewEncryptionClientV2_NonDefaults(t *testing.T) {
    84  	tUnit, gotWarning := sessionWithLogCheck(customTypeWarningMessage)
    85  
    86  	s3Client := s3.New(tUnit)
    87  
    88  	mcb := mockCipherBuilderV2{}
    89  	v2, err := NewEncryptionClientV2(tUnit, nil, func(clientOptions *EncryptionClientOptions) {
    90  		clientOptions.S3Client = s3Client
    91  		clientOptions.ContentCipherBuilder = mcb
    92  		clientOptions.TempFolderPath = "/mock/path"
    93  		clientOptions.MinFileSize = 42
    94  		clientOptions.SaveStrategy = S3SaveStrategy{}
    95  	})
    96  	if err != nil {
    97  		t.Fatalf("expected no error, got %v", err)
    98  	}
    99  	if v2 == nil {
   100  		t.Fatal("expected client to not be nil")
   101  	}
   102  
   103  	if !*gotWarning {
   104  		t.Errorf("expected warning for custom provided content cipher builder")
   105  	}
   106  
   107  	if !reflect.DeepEqual(mcb, v2.options.ContentCipherBuilder) {
   108  		t.Errorf("content cipher builder did not match provided value")
   109  	}
   110  
   111  	_, ok := v2.options.SaveStrategy.(S3SaveStrategy)
   112  	if !ok {
   113  		t.Errorf("expected default save strategy to be s3 header strategy")
   114  	}
   115  
   116  	if v2.options.S3Client != s3Client {
   117  		t.Errorf("expected s3 client not be nil")
   118  	}
   119  
   120  	if e, a := 42, v2.options.MinFileSize; int64(e) != a {
   121  		t.Errorf("expected %v, got %v", e, a)
   122  	}
   123  
   124  	if e, a := "/mock/path", v2.options.TempFolderPath; e != a {
   125  		t.Errorf("expected %v, got %v", e, a)
   126  	}
   127  }
   128  
   129  // cdgWithStaticTestIV is a test structure that wraps a CipherDataGeneratorWithCEKAlg and stubs in a static IV
   130  // so that encryption tests can be guaranteed to be consistent.
   131  type cdgWithStaticTestIV struct {
   132  	IV []byte
   133  	CipherDataGeneratorWithCEKAlg
   134  }
   135  
   136  // isAWSFixture will avoid the warning log message when doing tests that need to mock the IV
   137  func (k cdgWithStaticTestIV) isAWSFixture() bool {
   138  	return true
   139  }
   140  
   141  func (k cdgWithStaticTestIV) GenerateCipherDataWithCEKAlg(ctx aws.Context, keySize, ivSize int, cekAlg string) (CipherData, error) {
   142  	cipherData, err := k.CipherDataGeneratorWithCEKAlg.GenerateCipherDataWithCEKAlg(ctx, keySize, ivSize, cekAlg)
   143  	if err == nil {
   144  		cipherData.IV = k.IV
   145  	}
   146  	return cipherData, err
   147  }
   148  
   149  func TestEncryptionClientV2_PutObject_KMSCONTEXT_AESGCM(t *testing.T) {
   150  	ts := httptest.NewServer(http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) {
   151  		fmt.Fprintln(writer, `{"CiphertextBlob":"8gSzlk7giyfFbLPUVgoVjvQebI1827jp8lDkO+n2chsiSoegx1sjm8NdPk0Bl70I","KeyId":"test-key-id","Plaintext":"lP6AbIQTmptyb/+WQq+ubDw+w7na0T1LGSByZGuaono="}`)
   152  	}))
   153  
   154  	sess := unit.Session.Copy()
   155  	kmsClient := kms.New(sess.Copy(&aws.Config{Endpoint: &ts.URL}))
   156  
   157  	var md MaterialDescription
   158  	iv, _ := hex.DecodeString("ae325acae2bfd5b9c3d0b813")
   159  	kmsWithStaticIV := cdgWithStaticTestIV{
   160  		IV:                            iv,
   161  		CipherDataGeneratorWithCEKAlg: NewKMSContextKeyGenerator(kmsClient, "test-key-id", md),
   162  	}
   163  	contentCipherBuilderV2 := AESGCMContentCipherBuilderV2(kmsWithStaticIV)
   164  	client, err := NewEncryptionClientV2(sess, contentCipherBuilderV2)
   165  	if err != nil {
   166  		t.Fatalf("expected no error, got %v", err)
   167  	}
   168  
   169  	req, _ := client.PutObjectRequest(&s3.PutObjectInput{
   170  		Bucket: aws.String("test-bucket"),
   171  		Key:    aws.String("test-key"),
   172  		Body: func() io.ReadSeeker {
   173  			content, _ := hex.DecodeString("8f2c59c6dbfcacf356f3da40788cbde67ca38161a4702cbcf757af663e1c24a600001b2f500417dbf5a050f57db6737422b2ed6a44c75e0d")
   174  			return bytes.NewReader(content)
   175  		}(),
   176  	})
   177  
   178  	req.Handlers.Send.Clear()
   179  	req.Handlers.Send.PushFront(func(r *request.Request) {
   180  		all, err := ioutil.ReadAll(r.Body)
   181  		if err != nil {
   182  			t.Fatalf("expected no error, got %v", err)
   183  		}
   184  
   185  		expected, _ := hex.DecodeString("4cd8e95a1c9b8b19640e02838b02c8c09e66250703a602956695afbc23cbb8647d51645955ab63b89733d0766f9a264adb88571b1d467b734ff72eb73d31de9a83670d59688c54ea")
   186  
   187  		if !bytes.Equal(all, expected) {
   188  			t.Error("encrypted bytes did not match expected")
   189  		}
   190  
   191  		req.HTTPResponse = &http.Response{
   192  			Status:     http.StatusText(200),
   193  			StatusCode: http.StatusOK,
   194  			Body:       aws.ReadSeekCloser(bytes.NewReader([]byte{})),
   195  		}
   196  	})
   197  	err = req.Send()
   198  	if err != nil {
   199  		t.Errorf("expected no error, got %v", err)
   200  	}
   201  }
   202  
   203  func TestNewEncryptionClientV2_FailsOnIncompatibleFixtures(t *testing.T) {
   204  	sess := unit.Session.Copy()
   205  	_, err := NewEncryptionClientV2(sess, AESGCMContentCipherBuilder(NewKMSKeyGenerator(kms.New(sess), "cmkId")))
   206  	if err == nil {
   207  		t.Fatal("expected to fail, but got nil")
   208  	}
   209  	if !strings.Contains(err.Error(), "attempted to use deprecated or incompatible cipher builder") {
   210  		t.Errorf("expected to get error for using dperecated cipher builder")
   211  	}
   212  }