s3uploader.go 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. package imguploader
  2. import (
  3. "context"
  4. "fmt"
  5. "os"
  6. "time"
  7. "github.com/aws/aws-sdk-go/aws"
  8. "github.com/aws/aws-sdk-go/aws/credentials"
  9. "github.com/aws/aws-sdk-go/aws/credentials/ec2rolecreds"
  10. "github.com/aws/aws-sdk-go/aws/credentials/endpointcreds"
  11. "github.com/aws/aws-sdk-go/aws/defaults"
  12. "github.com/aws/aws-sdk-go/aws/ec2metadata"
  13. "github.com/aws/aws-sdk-go/aws/endpoints"
  14. "github.com/aws/aws-sdk-go/aws/session"
  15. "github.com/aws/aws-sdk-go/service/s3"
  16. "github.com/grafana/grafana/pkg/infra/log"
  17. "github.com/grafana/grafana/pkg/util"
  18. )
  19. type S3Uploader struct {
  20. region string
  21. bucket string
  22. path string
  23. acl string
  24. secretKey string
  25. accessKey string
  26. log log.Logger
  27. }
  28. func NewS3Uploader(region, bucket, path, acl, accessKey, secretKey string) *S3Uploader {
  29. return &S3Uploader{
  30. region: region,
  31. bucket: bucket,
  32. path: path,
  33. acl: acl,
  34. accessKey: accessKey,
  35. secretKey: secretKey,
  36. log: log.New("s3uploader"),
  37. }
  38. }
  39. func (u *S3Uploader) Upload(ctx context.Context, imageDiskPath string) (string, error) {
  40. sess, err := session.NewSession()
  41. if err != nil {
  42. return "", err
  43. }
  44. creds := credentials.NewChainCredentials(
  45. []credentials.Provider{
  46. &credentials.StaticProvider{Value: credentials.Value{
  47. AccessKeyID: u.accessKey,
  48. SecretAccessKey: u.secretKey,
  49. }},
  50. &credentials.EnvProvider{},
  51. remoteCredProvider(sess),
  52. })
  53. cfg := &aws.Config{
  54. Region: aws.String(u.region),
  55. Credentials: creds,
  56. }
  57. s3_endpoint, _ := endpoints.DefaultResolver().EndpointFor("s3", u.region)
  58. key := u.path + util.GetRandomString(20) + ".png"
  59. image_url := s3_endpoint.URL + "/" + u.bucket + "/" + key
  60. log.Debug("Uploading image to s3. url = %s", image_url)
  61. file, err := os.Open(imageDiskPath)
  62. if err != nil {
  63. return "", err
  64. }
  65. defer file.Close()
  66. sess, err = session.NewSession(cfg)
  67. if err != nil {
  68. return "", err
  69. }
  70. svc := s3.New(sess, cfg)
  71. params := &s3.PutObjectInput{
  72. Bucket: aws.String(u.bucket),
  73. Key: aws.String(key),
  74. ACL: aws.String(u.acl),
  75. Body: file,
  76. ContentType: aws.String("image/png"),
  77. }
  78. _, err = svc.PutObject(params)
  79. if err != nil {
  80. return "", err
  81. }
  82. return image_url, nil
  83. }
  84. func remoteCredProvider(sess *session.Session) credentials.Provider {
  85. ecsCredURI := os.Getenv("AWS_CONTAINER_CREDENTIALS_RELATIVE_URI")
  86. if len(ecsCredURI) > 0 {
  87. return ecsCredProvider(sess, ecsCredURI)
  88. }
  89. return ec2RoleProvider(sess)
  90. }
  91. func ecsCredProvider(sess *session.Session, uri string) credentials.Provider {
  92. const host = `169.254.170.2`
  93. d := defaults.Get()
  94. return endpointcreds.NewProviderClient(
  95. *d.Config,
  96. d.Handlers,
  97. fmt.Sprintf("http://%s%s", host, uri),
  98. func(p *endpointcreds.Provider) { p.ExpiryWindow = 5 * time.Minute })
  99. }
  100. func ec2RoleProvider(sess *session.Session) credentials.Provider {
  101. return &ec2rolecreds.EC2RoleProvider{Client: ec2metadata.New(sess), ExpiryWindow: 5 * time.Minute}
  102. }