s3uploader.go 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  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/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. sess, err = session.NewSession(cfg)
  66. if err != nil {
  67. return "", err
  68. }
  69. svc := s3.New(sess, cfg)
  70. params := &s3.PutObjectInput{
  71. Bucket: aws.String(u.bucket),
  72. Key: aws.String(key),
  73. ACL: aws.String(u.acl),
  74. Body: file,
  75. ContentType: aws.String("image/png"),
  76. }
  77. _, err = svc.PutObject(params)
  78. if err != nil {
  79. return "", err
  80. }
  81. return image_url, nil
  82. }
  83. func remoteCredProvider(sess *session.Session) credentials.Provider {
  84. ecsCredURI := os.Getenv("AWS_CONTAINER_CREDENTIALS_RELATIVE_URI")
  85. if len(ecsCredURI) > 0 {
  86. return ecsCredProvider(sess, ecsCredURI)
  87. }
  88. return ec2RoleProvider(sess)
  89. }
  90. func ecsCredProvider(sess *session.Session, uri string) credentials.Provider {
  91. const host = `169.254.170.2`
  92. d := defaults.Get()
  93. return endpointcreds.NewProviderClient(
  94. *d.Config,
  95. d.Handlers,
  96. fmt.Sprintf("http://%s%s", host, uri),
  97. func(p *endpointcreds.Provider) { p.ExpiryWindow = 5 * time.Minute })
  98. }
  99. func ec2RoleProvider(sess *session.Session) credentials.Provider {
  100. return &ec2rolecreds.EC2RoleProvider{Client: ec2metadata.New(sess), ExpiryWindow: 5 * time.Minute}
  101. }