s3.go 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. package s3
  2. import (
  3. "bytes"
  4. "fmt"
  5. "io"
  6. "github.com/aws/aws-sdk-go/aws"
  7. "github.com/aws/aws-sdk-go/aws/awserr"
  8. "github.com/aws/aws-sdk-go/aws/credentials"
  9. "github.com/aws/aws-sdk-go/aws/session"
  10. "github.com/aws/aws-sdk-go/service/s3"
  11. "github.com/porter-dev/porter/internal/encryption"
  12. "github.com/porter-dev/porter/internal/models"
  13. "github.com/porter-dev/porter/provisioner/integrations/storage"
  14. )
  15. type S3StorageClient struct {
  16. client *s3.S3
  17. bucket string
  18. encryptionKey *[32]byte
  19. }
  20. type S3Options struct {
  21. AWSRegion string
  22. AWSAccessKeyID string
  23. AWSSecretKey string
  24. AWSBucketName string
  25. EncryptionKey *[32]byte
  26. }
  27. func NewS3StorageClient(opts *S3Options) (*S3StorageClient, error) {
  28. var sess *session.Session
  29. var err error
  30. awsConf := &aws.Config{
  31. Credentials: credentials.NewStaticCredentials(
  32. opts.AWSAccessKeyID,
  33. opts.AWSSecretKey,
  34. "",
  35. ),
  36. Region: &opts.AWSRegion,
  37. }
  38. sess, err = session.NewSessionWithOptions(session.Options{
  39. SharedConfigState: session.SharedConfigEnable,
  40. Config: *awsConf,
  41. })
  42. if err != nil {
  43. return nil, fmt.Errorf("cannot create AWS session: %v", err)
  44. }
  45. return &S3StorageClient{
  46. bucket: opts.AWSBucketName,
  47. encryptionKey: opts.EncryptionKey,
  48. client: s3.New(sess),
  49. }, nil
  50. }
  51. func (s *S3StorageClient) WriteFile(infra *models.Infra, name string, fileBytes []byte, shouldEncrypt bool) error {
  52. body := fileBytes
  53. var err error
  54. if shouldEncrypt {
  55. body, err = encryption.Encrypt(fileBytes, s.encryptionKey)
  56. if err != nil {
  57. return err
  58. }
  59. }
  60. _, err = s.client.PutObject(&s3.PutObjectInput{
  61. Body: aws.ReadSeekCloser(bytes.NewReader(body)),
  62. Bucket: &s.bucket,
  63. Key: aws.String(getKeyFromInfra(infra, name)),
  64. })
  65. return err
  66. }
  67. func (s *S3StorageClient) WriteFileWithKey(fileBytes []byte, shouldEncrypt bool, key string) error {
  68. body := fileBytes
  69. var err error
  70. if shouldEncrypt {
  71. body, err = encryption.Encrypt(fileBytes, s.encryptionKey)
  72. if err != nil {
  73. return err
  74. }
  75. }
  76. _, err = s.client.PutObject(&s3.PutObjectInput{
  77. Body: aws.ReadSeekCloser(bytes.NewReader(body)),
  78. Bucket: &s.bucket,
  79. Key: aws.String(key),
  80. })
  81. return err
  82. }
  83. func (s *S3StorageClient) ReadFile(infra *models.Infra, name string, shouldDecrypt bool) ([]byte, error) {
  84. output, err := s.client.GetObject(&s3.GetObjectInput{
  85. Bucket: &s.bucket,
  86. Key: aws.String(getKeyFromInfra(infra, name)),
  87. })
  88. if err != nil {
  89. if aerr, ok := err.(awserr.Error); ok {
  90. switch aerr.Code() {
  91. case s3.ErrCodeNoSuchKey:
  92. return nil, storage.FileDoesNotExist
  93. default:
  94. return nil, err
  95. }
  96. }
  97. return nil, err
  98. }
  99. if shouldDecrypt {
  100. var encryptedData bytes.Buffer
  101. _, err = encryptedData.ReadFrom(output.Body)
  102. if err != nil {
  103. return nil, err
  104. }
  105. data, err := encryption.Decrypt(encryptedData.Bytes(), s.encryptionKey)
  106. if err != nil {
  107. return nil, err
  108. }
  109. return data, nil
  110. } else {
  111. return io.ReadAll(output.Body)
  112. }
  113. }
  114. func (s *S3StorageClient) DeleteFile(infra *models.Infra, name string) error {
  115. _, err := s.client.DeleteObject(&s3.DeleteObjectInput{
  116. Bucket: &s.bucket,
  117. Key: aws.String(getKeyFromInfra(infra, name)),
  118. })
  119. if err != nil {
  120. return err
  121. }
  122. return nil
  123. }
  124. func getKeyFromInfra(infra *models.Infra, name string) string {
  125. return fmt.Sprintf("%s/%s", infra.GetUniqueName(), name)
  126. }