1package s3crypto 2 3import ( 4 "github.com/aws/aws-sdk-go/aws" 5 "github.com/aws/aws-sdk-go/aws/awserr" 6 "github.com/aws/aws-sdk-go/aws/client" 7 "github.com/aws/aws-sdk-go/aws/request" 8 "github.com/aws/aws-sdk-go/service/s3" 9 "github.com/aws/aws-sdk-go/service/s3/s3iface" 10) 11 12// DefaultMinFileSize is used to check whether we want to write to a temp file 13// or store the data in memory. 14const DefaultMinFileSize = 1024 * 512 * 5 15 16// EncryptionClient is an S3 crypto client. By default the SDK will use Authentication mode which 17// will use KMS for key wrapping and AES GCM for content encryption. 18// AES GCM will load all data into memory. However, the rest of the content algorithms 19// do not load the entire contents into memory. 20// 21// deprecated: This feature is in maintenance mode, no new updates will be released. Please see https://docs.aws.amazon.com/general/latest/gr/aws_sdk_cryptography.html for more information. 22type EncryptionClient struct { 23 S3Client s3iface.S3API 24 ContentCipherBuilder ContentCipherBuilder 25 // SaveStrategy will dictate where the envelope is saved. 26 // 27 // Defaults to the object's metadata 28 SaveStrategy SaveStrategy 29 // TempFolderPath is used to store temp files when calling PutObject. 30 // Temporary files are needed to compute the X-Amz-Content-Sha256 header. 31 TempFolderPath string 32 // MinFileSize is the minimum size for the content to write to a 33 // temporary file instead of using memory. 34 MinFileSize int64 35} 36 37func validateV1EncryptionClientConstruction(c *EncryptionClient) error { 38 builder, ok := c.ContentCipherBuilder.(compatibleEncryptionFixture) 39 if !ok { 40 return nil 41 } 42 43 err := builder.isEncryptionVersionCompatible(v1ClientVersion) 44 if err != nil { 45 return awserr.New(clientConstructionErrorCode, "invalid client configuration", err) 46 } 47 return nil 48} 49 50// NewEncryptionClient instantiates a new S3 crypto client 51// 52// Example: 53// cmkID := "arn:aws:kms:region:000000000000:key/00000000-0000-0000-0000-000000000000" 54// sess := session.Must(session.NewSession()) 55// handler := s3crypto.NewKMSKeyGenerator(kms.New(sess), cmkID) 56// svc := s3crypto.NewEncryptionClient(sess, s3crypto.AESGCMContentCipherBuilder(handler)) 57// 58// deprecated: This feature is in maintenance mode, no new updates will be released. Please see https://docs.aws.amazon.com/general/latest/gr/aws_sdk_cryptography.html for more information. 59func NewEncryptionClient(prov client.ConfigProvider, builder ContentCipherBuilder, options ...func(*EncryptionClient)) *EncryptionClient { 60 s3client := s3.New(prov) 61 62 s3client.Handlers.Build.PushBack(func(r *request.Request) { 63 request.AddToUserAgent(r, "S3CryptoV1n") 64 }) 65 66 client := &EncryptionClient{ 67 S3Client: s3client, 68 ContentCipherBuilder: builder, 69 SaveStrategy: HeaderV2SaveStrategy{}, 70 MinFileSize: DefaultMinFileSize, 71 } 72 73 for _, option := range options { 74 option(client) 75 } 76 77 return client 78} 79 80// PutObjectRequest creates a temp file to encrypt the contents into. It then streams 81// that data to S3. 82// 83// Example: 84// svc := s3crypto.NewEncryptionClient(session.Must(session.NewSession()), s3crypto.AESGCMContentCipherBuilder(handler)) 85// req, out := svc.PutObjectRequest(&s3.PutObjectInput { 86// Key: aws.String("testKey"), 87// Bucket: aws.String("testBucket"), 88// Body: strings.NewReader("test data"), 89// }) 90// err := req.Send() 91// 92// deprecated: This feature is in maintenance mode, no new updates will be released. Please see https://docs.aws.amazon.com/general/latest/gr/aws_sdk_cryptography.html for more information. 93func (c *EncryptionClient) PutObjectRequest(input *s3.PutObjectInput) (*request.Request, *s3.PutObjectOutput) { 94 req, out := putObjectRequest(c.getClientOptions(), input) 95 if err := validateV1EncryptionClientConstruction(c); err != nil { 96 errHandler := setReqError(err) 97 req.Error = err 98 req.Handlers.Build.Clear() 99 req.Handlers.Send.Clear() 100 req.Handlers.Validate.PushFront(errHandler) 101 req.Handlers.Build.PushFront(errHandler) 102 req.Handlers.Send.PushFront(errHandler) 103 } 104 return req, out 105} 106 107func setReqError(err error) func(*request.Request) { 108 return func(r *request.Request) { 109 r.Error = err 110 } 111} 112 113// PutObject is a wrapper for PutObjectRequest 114// 115// deprecated: This feature is in maintenance mode, no new updates will be released. Please see https://docs.aws.amazon.com/general/latest/gr/aws_sdk_cryptography.html for more information. 116func (c *EncryptionClient) PutObject(input *s3.PutObjectInput) (*s3.PutObjectOutput, error) { 117 if err := validateV1EncryptionClientConstruction(c); err != nil { 118 return nil, err 119 } 120 return putObject(c.getClientOptions(), input) 121} 122 123// PutObjectWithContext is a wrapper for PutObjectRequest with the additional 124// context, and request options support. 125// 126// PutObjectWithContext is the same as PutObject with the additional support for 127// Context input parameters. The Context must not be nil. A nil Context will 128// cause a panic. Use the Context to add deadlining, timeouts, etc. In the future 129// this may create sub-contexts for individual underlying requests. 130// PutObject is a wrapper for PutObjectRequest 131// 132// deprecated: This feature is in maintenance mode, no new updates will be released. Please see https://docs.aws.amazon.com/general/latest/gr/aws_sdk_cryptography.html for more information. 133func (c *EncryptionClient) PutObjectWithContext(ctx aws.Context, input *s3.PutObjectInput, opts ...request.Option) (*s3.PutObjectOutput, error) { 134 if err := validateV1EncryptionClientConstruction(c); err != nil { 135 return nil, err 136 } 137 return putObjectWithContext(c.getClientOptions(), ctx, input, opts...) 138} 139 140func (c *EncryptionClient) getClientOptions() EncryptionClientOptions { 141 return EncryptionClientOptions{ 142 S3Client: c.S3Client, 143 ContentCipherBuilder: c.ContentCipherBuilder, 144 SaveStrategy: c.SaveStrategy, 145 TempFolderPath: c.TempFolderPath, 146 MinFileSize: c.MinFileSize, 147 } 148} 149