1package s3crypto 2 3import ( 4 "github.com/aws/aws-sdk-go/aws" 5 "github.com/aws/aws-sdk-go/aws/client" 6 "github.com/aws/aws-sdk-go/aws/request" 7 "github.com/aws/aws-sdk-go/service/s3" 8 "github.com/aws/aws-sdk-go/service/s3/s3iface" 9) 10 11// DecryptionClientV2 is an S3 crypto client. The decryption client 12// will handle all get object requests from Amazon S3. 13// Supported key wrapping algorithms: 14// * AWS KMS 15// * AWS KMS + Context 16// 17// Supported content ciphers: 18// * AES/GCM 19// * AES/CBC 20type DecryptionClientV2 struct { 21 options DecryptionClientOptions 22} 23 24// DecryptionClientOptions is the configuration options for DecryptionClientV2. 25type DecryptionClientOptions struct { 26 S3Client s3iface.S3API 27 // LoadStrategy is used to load the metadata either from the metadata of the object 28 // or from a separate file in s3. 29 // 30 // Defaults to our default load strategy. 31 LoadStrategy LoadStrategy 32 33 CryptoRegistry *CryptoRegistry 34} 35 36// NewDecryptionClientV2 instantiates a new DecryptionClientV2. The NewDecryptionClientV2 must be configured with the 37// desired key wrapping and content encryption algorithms that are required to be read by the client. These algorithms 38// are registered by providing the client a CryptoRegistry that has been constructed with the desired configuration. 39// NewDecryptionClientV2 will return an error if no key wrapping or content encryption algorithms have been provided. 40// 41// Example: 42// sess := session.Must(session.NewSession()) 43// cr := s3crypto.NewCryptoRegistry() 44// if err := s3crypto.RegisterKMSContextWrapWithAnyCMK(cr, kms.New(sess)); err != nil { 45// panic(err) // handle error 46// } 47// if err := s3crypto.RegisterAESGCMContentCipher(cr); err != nil { 48// panic(err) // handle error 49// } 50// svc, err := s3crypto.NewDecryptionClientV2(sess, cr, func(o *s3crypto.DecryptionClientOptions) { 51// // Custom client options here 52// }) 53// if err != nil { 54// panic(err) // handle error 55// } 56func NewDecryptionClientV2( 57 prov client.ConfigProvider, cryptoRegistry *CryptoRegistry, 58 options ...func(clientOptions *DecryptionClientOptions), 59) (*DecryptionClientV2, error) { 60 s3client := s3.New(prov) 61 62 s3client.Handlers.Build.PushBack(func(r *request.Request) { 63 request.AddToUserAgent(r, "S3CryptoV2") 64 }) 65 66 clientOptions := &DecryptionClientOptions{ 67 S3Client: s3client, 68 LoadStrategy: defaultV2LoadStrategy{ 69 client: s3client, 70 }, 71 CryptoRegistry: cryptoRegistry, 72 } 73 for _, option := range options { 74 option(clientOptions) 75 } 76 77 if err := cryptoRegistry.valid(); err != nil { 78 return nil, err 79 } 80 81 return &DecryptionClientV2{options: *clientOptions}, nil 82} 83 84// GetObjectRequest will make a request to s3 and retrieve the object. In this process 85// decryption will be done. The SDK only supports V2 reads of KMS and GCM. 86// 87// Example: 88// req, out := svc.GetObjectRequest(&s3.GetObjectInput { 89// Key: aws.String("testKey"), 90// Bucket: aws.String("testBucket"), 91// }) 92// err := req.Send() 93func (c *DecryptionClientV2) GetObjectRequest(input *s3.GetObjectInput) (*request.Request, *s3.GetObjectOutput) { 94 return getObjectRequest(c.options, input) 95} 96 97// GetObject is a wrapper for GetObjectRequest 98func (c *DecryptionClientV2) GetObject(input *s3.GetObjectInput) (*s3.GetObjectOutput, error) { 99 req, out := getObjectRequest(c.options, input) 100 return out, req.Send() 101} 102 103// GetObjectWithContext is a wrapper for GetObjectRequest with the additional 104// context, and request options support. 105// 106// GetObjectWithContext is the same as GetObject with the additional support for 107// Context input parameters. The Context must not be nil. A nil Context will 108// cause a panic. Use the Context to add deadlining, timeouts, etc. In the future 109// this may create sub-contexts for individual underlying requests. 110func (c *DecryptionClientV2) GetObjectWithContext(ctx aws.Context, input *s3.GetObjectInput, opts ...request.Option) (*s3.GetObjectOutput, error) { 111 req, out := getObjectRequest(c.options, input) 112 req.SetContext(ctx) 113 req.ApplyOptions(opts...) 114 return out, req.Send() 115} 116