1package s3crypto_test
2
3import (
4	"bytes"
5	"encoding/json"
6	"io/ioutil"
7	"net/http"
8	"reflect"
9	"testing"
10
11	"github.com/aws/aws-sdk-go/aws"
12	"github.com/aws/aws-sdk-go/aws/request"
13	"github.com/aws/aws-sdk-go/awstesting/unit"
14	"github.com/aws/aws-sdk-go/service/s3"
15	"github.com/aws/aws-sdk-go/service/s3/s3crypto"
16)
17
18func TestHeaderV2SaveStrategy(t *testing.T) {
19	cases := []struct {
20		env      s3crypto.Envelope
21		expected map[string]*string
22	}{
23		{
24			s3crypto.Envelope{
25				CipherKey:             "Foo",
26				IV:                    "Bar",
27				MatDesc:               "{}",
28				WrapAlg:               s3crypto.KMSWrap,
29				CEKAlg:                s3crypto.AESGCMNoPadding,
30				TagLen:                "128",
31				UnencryptedMD5:        "hello",
32				UnencryptedContentLen: "0",
33			},
34			map[string]*string{
35				"X-Amz-Key-V2":                     aws.String("Foo"),
36				"X-Amz-Iv":                         aws.String("Bar"),
37				"X-Amz-Matdesc":                    aws.String("{}"),
38				"X-Amz-Wrap-Alg":                   aws.String(s3crypto.KMSWrap),
39				"X-Amz-Cek-Alg":                    aws.String(s3crypto.AESGCMNoPadding),
40				"X-Amz-Tag-Len":                    aws.String("128"),
41				"X-Amz-Unencrypted-Content-Length": aws.String("0"),
42			},
43		},
44		{
45			s3crypto.Envelope{
46				CipherKey:             "Foo",
47				IV:                    "Bar",
48				MatDesc:               "{}",
49				WrapAlg:               s3crypto.KMSWrap,
50				CEKAlg:                s3crypto.AESGCMNoPadding,
51				UnencryptedMD5:        "hello",
52				UnencryptedContentLen: "0",
53			},
54			map[string]*string{
55				"X-Amz-Key-V2":                     aws.String("Foo"),
56				"X-Amz-Iv":                         aws.String("Bar"),
57				"X-Amz-Matdesc":                    aws.String("{}"),
58				"X-Amz-Wrap-Alg":                   aws.String(s3crypto.KMSWrap),
59				"X-Amz-Cek-Alg":                    aws.String(s3crypto.AESGCMNoPadding),
60				"X-Amz-Unencrypted-Content-Length": aws.String("0"),
61			},
62		},
63	}
64
65	for _, c := range cases {
66		params := &s3.PutObjectInput{}
67		req := &request.Request{
68			Params: params,
69		}
70		strat := s3crypto.HeaderV2SaveStrategy{}
71		err := strat.Save(c.env, req)
72		if err != nil {
73			t.Errorf("expected no error, but received %v", err)
74		}
75
76		if !reflect.DeepEqual(c.expected, params.Metadata) {
77			t.Errorf("expected %v, but received %v", c.expected, params.Metadata)
78		}
79	}
80}
81
82func TestS3SaveStrategy(t *testing.T) {
83	cases := []struct {
84		env      s3crypto.Envelope
85		expected s3crypto.Envelope
86	}{
87		{
88			s3crypto.Envelope{
89				CipherKey:             "Foo",
90				IV:                    "Bar",
91				MatDesc:               "{}",
92				WrapAlg:               s3crypto.KMSWrap,
93				CEKAlg:                s3crypto.AESGCMNoPadding,
94				TagLen:                "128",
95				UnencryptedMD5:        "hello",
96				UnencryptedContentLen: "0",
97			},
98			s3crypto.Envelope{
99				CipherKey:             "Foo",
100				IV:                    "Bar",
101				MatDesc:               "{}",
102				WrapAlg:               s3crypto.KMSWrap,
103				CEKAlg:                s3crypto.AESGCMNoPadding,
104				TagLen:                "128",
105				UnencryptedContentLen: "0",
106			},
107		},
108		{
109			s3crypto.Envelope{
110				CipherKey:             "Foo",
111				IV:                    "Bar",
112				MatDesc:               "{}",
113				WrapAlg:               s3crypto.KMSWrap,
114				CEKAlg:                s3crypto.AESGCMNoPadding,
115				UnencryptedMD5:        "hello",
116				UnencryptedContentLen: "0",
117			},
118			s3crypto.Envelope{
119				CipherKey:             "Foo",
120				IV:                    "Bar",
121				MatDesc:               "{}",
122				WrapAlg:               s3crypto.KMSWrap,
123				CEKAlg:                s3crypto.AESGCMNoPadding,
124				UnencryptedContentLen: "0",
125			},
126		},
127	}
128
129	for _, c := range cases {
130		params := &s3.PutObjectInput{
131			Bucket: aws.String("fooBucket"),
132			Key:    aws.String("barKey"),
133		}
134		req := &request.Request{
135			Params: params,
136		}
137
138		client := s3.New(unit.Session)
139
140		client.Handlers.Send.Clear()
141		client.Handlers.Unmarshal.Clear()
142		client.Handlers.UnmarshalMeta.Clear()
143		client.Handlers.UnmarshalError.Clear()
144		client.Handlers.Send.PushBack(func(r *request.Request) {
145			bodyBytes, err := ioutil.ReadAll(r.Body)
146			if err != nil {
147				r.HTTPResponse = &http.Response{
148					StatusCode: 500,
149					Body:       ioutil.NopCloser(bytes.NewReader([]byte(err.Error()))),
150				}
151				return
152			}
153
154			var actual s3crypto.Envelope
155			err = json.Unmarshal(bodyBytes, &actual)
156			if err != nil {
157				r.HTTPResponse = &http.Response{
158					StatusCode: 500,
159					Body:       ioutil.NopCloser(bytes.NewReader([]byte(err.Error()))),
160				}
161				return
162			}
163
164			if e, a := c.expected, actual; !reflect.DeepEqual(e, a) {
165				t.Errorf("expected %v, got %v", e, a)
166			}
167
168			r.HTTPResponse = &http.Response{
169				StatusCode: 200,
170				Body:       ioutil.NopCloser(bytes.NewReader([]byte(""))),
171			}
172		})
173
174		strat := s3crypto.S3SaveStrategy{Client: client}
175		err := strat.Save(c.env, req)
176		if err != nil {
177			t.Errorf("expected no error, but received %v", err)
178		}
179	}
180}
181