-
Notifications
You must be signed in to change notification settings - Fork 2.1k
/
encryption_client_v2.go
117 lines (104 loc) · 4.51 KB
/
encryption_client_v2.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
package s3crypto
import (
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/client"
"github.com/aws/aws-sdk-go/aws/request"
"github.com/aws/aws-sdk-go/service/s3"
"github.com/aws/aws-sdk-go/service/s3/s3iface"
)
const customTypeWarningMessage = "WARNING: The S3 Encryption Client is configured to write encrypted objects using types not provided by AWS. Security and compatibility with these types can not be guaranteed."
// EncryptionClientV2 is an S3 crypto client. By default the SDK will use Authentication mode which
// will use KMS for key wrapping and AES GCM for content encryption.
// AES GCM will load all data into memory. However, the rest of the content algorithms
// do not load the entire contents into memory.
type EncryptionClientV2 struct {
options EncryptionClientOptions
}
// EncryptionClientOptions is the configuration options for EncryptionClientV2
type EncryptionClientOptions struct {
S3Client s3iface.S3API
ContentCipherBuilder ContentCipherBuilder
// SaveStrategy will dictate where the envelope is saved.
//
// Defaults to the object's metadata
SaveStrategy SaveStrategy
// TempFolderPath is used to store temp files when calling PutObject.
// Temporary files are needed to compute the X-Amz-Content-Sha256 header.
TempFolderPath string
// MinFileSize is the minimum size for the content to write to a
// temporary file instead of using memory.
MinFileSize int64
}
// NewEncryptionClientV2 instantiates a new S3 crypto client. An error will be returned to the caller if the provided
// contentCipherBuilder has been deprecated or was constructed with a deprecated component.
//
// Example:
//
// cmkID := "arn:aws:kms:region:000000000000:key/00000000-0000-0000-0000-000000000000"
// sess := session.Must(session.NewSession())
// var matdesc s3crypto.MaterialDescription
// handler := s3crypto.NewKMSContextKeyGenerator(kms.New(sess), cmkID, matdesc)
// svc := s3crypto.NewEncryptionClientV2(sess, s3crypto.AESGCMContentCipherBuilderV2(handler))
func NewEncryptionClientV2(prov client.ConfigProvider, contentCipherBuilder ContentCipherBuilder, options ...func(clientOptions *EncryptionClientOptions),
) (
client *EncryptionClientV2, err error,
) {
s3client := s3.New(prov)
s3client.Handlers.Build.PushBack(func(r *request.Request) {
request.AddToUserAgent(r, "S3CryptoV2")
})
clientOptions := &EncryptionClientOptions{
S3Client: s3client,
ContentCipherBuilder: contentCipherBuilder,
SaveStrategy: HeaderV2SaveStrategy{},
MinFileSize: DefaultMinFileSize,
}
for _, option := range options {
option(clientOptions)
}
// Check that the configured client uses a compatible ContentCipherBuilder.
// User provided types will not implement this method
if fixture, ok := contentCipherBuilder.(compatibleEncryptionFixture); ok {
if err := fixture.isEncryptionVersionCompatible(v2ClientVersion); err != nil {
return nil, err
}
}
// Check if the passed in type is an fixture, if not log a warning message to the user
if fixture, ok := contentCipherBuilder.(awsFixture); !ok || !fixture.isAWSFixture() {
if s3client.Config.Logger != nil {
s3client.Config.Logger.Log(customTypeWarningMessage)
}
}
client = &EncryptionClientV2{
*clientOptions,
}
return client, err
}
// PutObjectRequest creates a temp file to encrypt the contents into. It then streams
// that data to S3.
//
// Example:
//
// req, out := svc.PutObjectRequest(&s3.PutObjectInput {
// Key: aws.String("testKey"),
// Bucket: aws.String("testBucket"),
// Body: strings.NewReader("test data"),
// })
// err := req.Send()
func (c *EncryptionClientV2) PutObjectRequest(input *s3.PutObjectInput) (*request.Request, *s3.PutObjectOutput) {
return putObjectRequest(c.options, input)
}
// PutObject is a wrapper for PutObjectRequest
func (c *EncryptionClientV2) PutObject(input *s3.PutObjectInput) (*s3.PutObjectOutput, error) {
return putObject(c.options, input)
}
// PutObjectWithContext is a wrapper for PutObjectRequest with the additional
// context, and request options support.
//
// PutObjectWithContext is the same as PutObject with the additional support for
// Context input parameters. The Context must not be nil. A nil Context will
// cause a panic. Use the Context to add deadlining, timeouts, etc. In the future
// this may create sub-contexts for individual underlying requests.
func (c *EncryptionClientV2) PutObjectWithContext(ctx aws.Context, input *s3.PutObjectInput, opts ...request.Option) (*s3.PutObjectOutput, error) {
return putObjectWithContext(c.options, ctx, input, opts...)
}