s3.go 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  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) ReadFile(infra *models.Infra, name string, shouldDecrypt bool) ([]byte, error) {
  68. output, err := s.client.GetObject(&s3.GetObjectInput{
  69. Bucket: &s.bucket,
  70. Key: aws.String(getKeyFromInfra(infra, name)),
  71. })
  72. if err != nil {
  73. if aerr, ok := err.(awserr.Error); ok {
  74. switch aerr.Code() {
  75. case s3.ErrCodeNoSuchKey:
  76. return nil, storage.FileDoesNotExist
  77. default:
  78. return nil, err
  79. }
  80. }
  81. return nil, err
  82. }
  83. if shouldDecrypt {
  84. var encryptedData bytes.Buffer
  85. _, err = encryptedData.ReadFrom(output.Body)
  86. if err != nil {
  87. return nil, err
  88. }
  89. data, err := encryption.Decrypt(encryptedData.Bytes(), s.encryptionKey)
  90. if err != nil {
  91. return nil, err
  92. }
  93. return data, nil
  94. } else {
  95. return io.ReadAll(output.Body)
  96. }
  97. }
  98. func (s *S3StorageClient) DeleteFile(infra *models.Infra, name string) error {
  99. _, err := s.client.DeleteObject(&s3.DeleteObjectInput{
  100. Bucket: &s.bucket,
  101. Key: aws.String(getKeyFromInfra(infra, name)),
  102. })
  103. if err != nil {
  104. return err
  105. }
  106. return nil
  107. }
  108. func getKeyFromInfra(infra *models.Infra, name string) string {
  109. return fmt.Sprintf("%s/%s", infra.GetUniqueName(), name)
  110. }