1
0
mirror of https://github.com/imgproxy/imgproxy.git synced 2025-09-16 09:36:18 +02:00

Migrate from aws-sdk-go to aws-sdk-go-v2

This commit is contained in:
DarthSim
2024-03-07 22:25:18 +03:00
parent 8f95063e16
commit aa1b7b6973
6 changed files with 316 additions and 174 deletions

View File

@@ -1,15 +1,17 @@
package loadenv
import (
"context"
"fmt"
"os"
"strings"
"time"
"github.com/DarthSim/godotenv"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/secretsmanager"
"github.com/aws/aws-sdk-go/service/ssm"
"github.com/aws/aws-sdk-go-v2/aws"
awsConfig "github.com/aws/aws-sdk-go-v2/config"
"github.com/aws/aws-sdk-go-v2/service/secretsmanager"
"github.com/aws/aws-sdk-go-v2/service/ssm"
)
func loadAWSSecret() error {
@@ -22,18 +24,20 @@ func loadAWSSecret() error {
return nil
}
sess, err := session.NewSession()
conf, err := awsConfig.LoadDefaultConfig(context.Background())
if err != nil {
return fmt.Errorf("Can't create AWS Secrets Manager session: %s", err)
return fmt.Errorf("can't load AWS Secrets Manager config: %s", err)
}
conf := aws.NewConfig()
if len(secretRegion) != 0 {
conf.Region = aws.String(secretRegion)
conf.Region = secretRegion
}
svc := secretsmanager.New(sess, conf)
if len(conf.Region) == 0 {
conf.Region = "us-west-1"
}
client := secretsmanager.NewFromConfig(conf)
input := secretsmanager.GetSecretValueInput{SecretId: aws.String(secretID)}
if len(secretVersionID) > 0 {
@@ -42,7 +46,10 @@ func loadAWSSecret() error {
input.VersionStage = aws.String(secretVersionStage)
}
output, err := svc.GetSecretValue(&input)
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
output, err := client.GetSecretValue(ctx, &input)
if err != nil {
return fmt.Errorf("Can't retrieve config from AWS Secrets Manager: %s", err)
}
@@ -73,18 +80,23 @@ func loadAWSSystemManagerParams() error {
return nil
}
sess, err := session.NewSession()
conf, err := awsConfig.LoadDefaultConfig(context.Background())
if err != nil {
return fmt.Errorf("Can't create AWS SSM session: %s", err)
return fmt.Errorf("can't load AWS SSM config: %s", err)
}
conf := aws.NewConfig()
if len(paramsRegion) != 0 {
conf.Region = aws.String(paramsRegion)
conf.Region = paramsRegion
}
svc := ssm.New(sess, conf)
if len(conf.Region) == 0 {
conf.Region = "us-west-1"
}
client := ssm.NewFromConfig(conf)
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
var nextToken *string
@@ -95,13 +107,13 @@ func loadAWSSystemManagerParams() error {
NextToken: nextToken,
}
output, err := svc.GetParametersByPath(&input)
output, err := client.GetParametersByPath(ctx, &input)
if err != nil {
return fmt.Errorf("Can't retrieve parameters from AWS SSM: %s", err)
}
for _, p := range output.Parameters {
if p == nil || p.Name == nil || p.Value == nil {
if p.Name == nil || p.Value == nil {
continue
}

30
go.mod
View File

@@ -13,14 +13,24 @@ require (
github.com/DarthSim/godotenv v1.3.1
github.com/DataDog/datadog-go/v5 v5.5.0
github.com/airbrake/gobrake/v5 v5.6.1
github.com/aws/aws-sdk-go v1.50.23
github.com/aws/amazon-s3-encryption-client-go/v3 v3.0.0
github.com/aws/aws-sdk-go-v2 v1.25.2
github.com/aws/aws-sdk-go-v2/config v1.27.6
github.com/aws/aws-sdk-go-v2/credentials v1.17.6
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.16.8
github.com/aws/aws-sdk-go-v2/service/cloudwatch v1.36.1
github.com/aws/aws-sdk-go-v2/service/kms v1.29.1
github.com/aws/aws-sdk-go-v2/service/s3 v1.51.3
github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.28.1
github.com/aws/aws-sdk-go-v2/service/ssm v1.49.1
github.com/aws/aws-sdk-go-v2/service/sts v1.28.3
github.com/benesch/cgosymbolizer v0.0.0-20190515212042-bec6fe6e597b
github.com/bugsnag/bugsnag-go/v2 v2.2.1
github.com/felixge/httpsnoop v1.0.4
github.com/fsouza/fake-gcs-server v1.42.2
github.com/getsentry/sentry-go v0.27.0
github.com/honeybadger-io/honeybadger-go v0.6.0
github.com/johannesboyne/gofakes3 v0.0.0-20221128113635-c2f5cc6b5294
github.com/johannesboyne/gofakes3 v0.0.0-20240217095638-c55a48f17be6
github.com/matoous/go-nanoid/v2 v2.0.0
github.com/ncw/swift/v2 v2.0.2
github.com/newrelic/go-agent/v3 v3.30.0
@@ -72,6 +82,20 @@ require (
github.com/DataDog/go-tuf v1.0.4-0.5.2-debug // indirect
github.com/DataDog/sketches-go v1.4.4 // indirect
github.com/Microsoft/go-winio v0.6.1 // indirect
github.com/aws/aws-sdk-go v1.50.10 // indirect
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.1 // indirect
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.15.2 // indirect
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.2 // indirect
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.2 // indirect
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0 // indirect
github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.2 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.1 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.3.4 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.4 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.17.2 // indirect
github.com/aws/aws-sdk-go-v2/service/sso v1.20.1 // indirect
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.23.1 // indirect
github.com/aws/smithy-go v1.20.1 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/brunoscheufler/aws-ecs-metadata-go v0.0.0-20221221133751-67e37ae746cd // indirect
github.com/bugsnag/panicwrap v1.3.4 // indirect
@@ -167,5 +191,3 @@ require (
sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect
sigs.k8s.io/yaml v1.4.0 // indirect
)
replace github.com/johannesboyne/gofakes3 => github.com/DarthSim/gofakes3 v0.0.0-20230502153341-3fc66d2bc272

79
go.sum
View File

@@ -30,8 +30,6 @@ github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2/go.mod h1:wP83
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/DarthSim/godotenv v1.3.1 h1:NMWdswlRx2M9uPY4Ux8p/Q/rDs7A97OG89fECiQ/Tz0=
github.com/DarthSim/godotenv v1.3.1/go.mod h1:B3ySe1HYTUFFR6+TPyHyxPWjUdh48il0Blebg9p1cCc=
github.com/DarthSim/gofakes3 v0.0.0-20230502153341-3fc66d2bc272 h1:Gj21neabaU3DEwwVPG6/Vn0GSuDQ1n2m2z1qV33SCI0=
github.com/DarthSim/gofakes3 v0.0.0-20230502153341-3fc66d2bc272/go.mod h1:Cnosl0cRZIfKjTMuH49sQog2LeNsU5Hf4WnPIDWIDV0=
github.com/DataDog/appsec-internal-go v1.4.2 h1:rLOp0mSzJ7L7Nn3jAdWbgvs+1HK25H0DN4XYVDJu72s=
github.com/DataDog/appsec-internal-go v1.4.2/go.mod h1:pEp8gjfNLtEOmz+iZqC8bXhu0h4k7NUsW/qiQb34k1U=
github.com/DataDog/datadog-agent/pkg/obfuscate v0.51.0 h1:GztQU5i304cIkHadEDV77lqmW6CaJ36G0XMoXgZcPgA=
@@ -55,9 +53,57 @@ github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migc
github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM=
github.com/airbrake/gobrake/v5 v5.6.1 h1:sCDq6EuHO4dFytpXcZ2tNLoJZevaigFiNMusF098CEI=
github.com/airbrake/gobrake/v5 v5.6.1/go.mod h1:hyuUJaj7We4nB8Evy9n6LOkxRwxSxMW2IIgOMQcz79E=
github.com/aws/aws-sdk-go v1.33.0/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0=
github.com/aws/aws-sdk-go v1.50.23 h1:BB99ohyCmq6O7m5RvjN2yqTt57snL8OhDvfxEvM6ihs=
github.com/aws/aws-sdk-go v1.50.23/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
github.com/aws/amazon-s3-encryption-client-go/v3 v3.0.0 h1:p7M5gUM4YpkTAzHjn1TzukYg8jzW5MqE5ea1tUs82pw=
github.com/aws/amazon-s3-encryption-client-go/v3 v3.0.0/go.mod h1:olnwkBTbWjaJCaGOHohvJu98q40GiJZuDHLXj751mII=
github.com/aws/aws-sdk-go v1.44.256/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.50.10 h1:H3NQvqRUKG+9oysCKTIyylpkqfPA7MiBtzTnu/cIGqE=
github.com/aws/aws-sdk-go v1.50.10/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
github.com/aws/aws-sdk-go-v2 v1.25.2 h1:/uiG1avJRgLGiQM9X3qJM8+Qa6KRGK5rRPuXE0HUM+w=
github.com/aws/aws-sdk-go-v2 v1.25.2/go.mod h1:Evoc5AsmtveRt1komDwIsjHFyrP5tDuF1D1U+6z6pNo=
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.1 h1:gTK2uhtAPtFcdRRJilZPx8uJLL2J85xK11nKtWL0wfU=
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.1/go.mod h1:sxpLb+nZk7tIfCWChfd+h4QwHNUR57d8hA1cleTkjJo=
github.com/aws/aws-sdk-go-v2/config v1.27.6 h1:WmoH1aPrxwcqAZTTnETjKr+fuvqzKd4hRrKxQUiuKP4=
github.com/aws/aws-sdk-go-v2/config v1.27.6/go.mod h1:W9RZFF2pL+OhnUSZsQS/eDMWD8v+R+yWgjj3nSlrXVU=
github.com/aws/aws-sdk-go-v2/credentials v1.17.6 h1:akhj/nSC6SEx3OmiYGG/7mAyXMem9ZNVVf+DXkikcTk=
github.com/aws/aws-sdk-go-v2/credentials v1.17.6/go.mod h1:chJZuJ7TkW4kiMwmldOJOEueBoSkUb4ynZS1d9dhygo=
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.15.2 h1:AK0J8iYBFeUk2Ax7O8YpLtFsfhdOByh2QIkHmigpRYk=
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.15.2/go.mod h1:iRlGzMix0SExQEviAyptRWRGdYNo3+ufW/lCzvKVTUc=
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.16.8 h1:fjsaZ2EUoOaosuYMLbQAVJsPIAOV4Xn52AQmk5JbhAs=
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.16.8/go.mod h1:WPJcs0Mze3WntafH9Df2NdJ1oSQkEQVL6piZxoS0ecY=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.2 h1:bNo4LagzUKbjdxE0tIcR9pMzLR2U/Tgie1Hq1HQ3iH8=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.2/go.mod h1:wRQv0nN6v9wDXuWThpovGQjqF1HFdcgWjporw14lS8k=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.2 h1:EtOU5jsPdIQNP+6Q2C5e3d65NKT1PeCiQk+9OdzO12Q=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.2/go.mod h1:tyF5sKccmDz0Bv4NrstEr+/9YkSPJHrcO7UsUKf7pWM=
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0 h1:hT8rVHwugYE2lEfdFE0QWVo81lF7jMrYJVDWI+f+VxU=
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0/go.mod h1:8tu/lYfQfFe6IGnaOdrpVgEL2IrrDOf6/m9RQum4NkY=
github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.2 h1:en92G0Z7xlksoOylkUhuBSfJgijC7rHVLRdnIlHEs0E=
github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.2/go.mod h1:HgtQ/wN5G+8QSlK62lbOtNwQ3wTSByJ4wH2rCkPt+AE=
github.com/aws/aws-sdk-go-v2/service/cloudwatch v1.36.1 h1:mQySuI87thHtcbZvEDjwUROGWikU6fqgpHklCBXpJU4=
github.com/aws/aws-sdk-go-v2/service/cloudwatch v1.36.1/go.mod h1:Z1ThUUTuCO9PArtiQsTmBGBv+38NGj+795Zl0n1jgiM=
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.1 h1:EyBZibRTVAs6ECHZOw5/wlylS9OcTzwyjeQMudmREjE=
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.1/go.mod h1:JKpmtYhhPs7D97NL/ltqz7yCkERFW5dOlHyVl66ZYF8=
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.3.4 h1:J3Q6N2sTChfYLZSTey3Qeo7n3JSm6RTJDcKev+7Sbus=
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.3.4/go.mod h1:ZopsdDMVg1H03X7BdzpGaufOkuz27RjtKDzioP2U0Hg=
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.4 h1:jRiWxyuVO8PlkN72wDMVn/haVH4SDCBkUt0Lf/dxd7s=
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.4/go.mod h1:Ru7vg1iQ7cR4i7SZ/JTLYN9kaXtbL69UdgG0OQWQxW0=
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.17.2 h1:1oY1AVEisRI4HNuFoLdRUB0hC63ylDAN6Me3MrfclEg=
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.17.2/go.mod h1:KZ03VgvZwSjkT7fOetQ/wF3MZUvYFirlI1H5NklUNsY=
github.com/aws/aws-sdk-go-v2/service/kms v1.29.1 h1:OdjJjUWFlMZLAMl54ASxIpZdGEesY4BH3/c0HAPSFdI=
github.com/aws/aws-sdk-go-v2/service/kms v1.29.1/go.mod h1:Cbx2uxEX0bAB7SlSY+ys05ZBkEb8IbmuAOcGVmDfJFs=
github.com/aws/aws-sdk-go-v2/service/s3 v1.51.3 h1:7cR4xxS480TI0R6Bd75g9Npdw89VriquvQPlMNmuds4=
github.com/aws/aws-sdk-go-v2/service/s3 v1.51.3/go.mod h1:zb72GZ2MvfCX5ynVJ+Mc/NCx7hncbsko4NZm5E+p6J4=
github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.28.1 h1:DtKw4TxZT3VrzYupXQJPBqT9ImyobZZE+JIQPPAVxqs=
github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.28.1/go.mod h1:bit9G2ORpSjUTr4PA4usvbBfbOyvMj0LbE1dXF14Sug=
github.com/aws/aws-sdk-go-v2/service/ssm v1.49.1 h1:MeYuN4Ld4FWVJb9ZiOJkon7/foj0Zm2GTDorSaInHj4=
github.com/aws/aws-sdk-go-v2/service/ssm v1.49.1/go.mod h1:TM0pqkfTRMVtsMlPnOivUmrZSIANsLbq9FTm4oJPcPQ=
github.com/aws/aws-sdk-go-v2/service/sso v1.20.1 h1:utEGkfdQ4L6YW/ietH7111ZYglLJvS+sLriHJ1NBJEQ=
github.com/aws/aws-sdk-go-v2/service/sso v1.20.1/go.mod h1:RsYqzYr2F2oPDdpy+PdhephuZxTfjHQe7SOBcZGoAU8=
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.23.1 h1:9/GylMS45hGGFCcMrUZDVayQE1jYSIN6da9jo7RAYIw=
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.23.1/go.mod h1:YjAPFn4kGFqKC54VsHs5fn5B6d+PCY2tziEa3U/GB5Y=
github.com/aws/aws-sdk-go-v2/service/sts v1.28.3 h1:TkiFkSVX990ryWIMBCT4kPqZEgThQe1xPU/AQXavtvU=
github.com/aws/aws-sdk-go-v2/service/sts v1.28.3/go.mod h1:xYNauIUqSuvzlPVb3VB5no/n48YGhmlInD3Uh0Co8Zc=
github.com/aws/smithy-go v1.20.1 h1:4SZlSlMr36UEqC7XOyRVb27XMeZubNcBNN+9IgEPIQw=
github.com/aws/smithy-go v1.20.1/go.mod h1:krry+ya/rV9RDcV/Q16kpu6ypI4K2czasz0NC3qS14E=
github.com/benesch/cgosymbolizer v0.0.0-20190515212042-bec6fe6e597b h1:5JgaFtHFRnOPReItxvhMDXbvuBkjSWE+9glJyF466yw=
github.com/benesch/cgosymbolizer v0.0.0-20190515212042-bec6fe6e597b/go.mod h1:eMD2XUcPsHYbakFEocKrWZp47G0MRJYoC60qFblGjpA=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
@@ -127,7 +173,6 @@ github.com/go-openapi/jsonreference v0.20.4 h1:bKlDxQxQJgwpUSgOENiMPzCTBVuc7vTdX
github.com/go-openapi/jsonreference v0.20.4/go.mod h1:5pZJyJP2MnYCpoeoMAql78cCHauHj0V9Lhc506VOpw4=
github.com/go-openapi/swag v0.22.9 h1:XX2DssF+mQKM2DHsbgZK74y/zj4mo9I99+89xUmuZCE=
github.com/go-openapi/swag v0.22.9/go.mod h1:3/OXnFfnMAwBD099SwYRk7GD3xOrr1iL7d/XNLXVVwE=
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
@@ -200,11 +245,12 @@ github.com/honeybadger-io/honeybadger-go v0.6.0 h1:RHOml6S0+3w0vWGTM8zOfWTGsfHBv
github.com/honeybadger-io/honeybadger-go v0.6.0/go.mod h1:YaVKI0eSWUwNOzWa4xr5INoBTWGGz6trlcA3a9gzZ6I=
github.com/ianlancetaylor/cgosymbolizer v0.0.0-20231130194700-cfcb2fd150eb h1:asfjGoPvNgSPvgbBiwFqMUOgWgid8xlQGCGHfgM/PAs=
github.com/ianlancetaylor/cgosymbolizer v0.0.0-20231130194700-cfcb2fd150eb/go.mod h1:DvXTE/K/RtHehxU8/GtDs4vFtfw64jJ3PaCnFri8CRg=
github.com/jmespath/go-jmespath v0.3.0/go.mod h1:9QtRXoHjLGCJ5IBSaohpXITPlowMeeYCZ7fLUTSywik=
github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg=
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8=
github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
github.com/johannesboyne/gofakes3 v0.0.0-20240217095638-c55a48f17be6 h1:W8heH5NR7dfdB4FehSFI+DxjCbVKe9fPkPqKzCPJwnM=
github.com/johannesboyne/gofakes3 v0.0.0-20240217095638-c55a48f17be6/go.mod h1:AxgWC4DDX54O2WDoQO1Ceabtn6IbktjU/7bigor+66g=
github.com/jonboulle/clockwork v0.4.0 h1:p4Cf1aMWXnXAUh8lVfewRBx1zaTSYKrKMF2g3ST4RZ4=
github.com/jonboulle/clockwork v0.4.0/go.mod h1:xgRqUGwRcjKCO1vbZUEtSLrqKoPSsUpK7fnezOII0kc=
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
@@ -286,7 +332,6 @@ github.com/ryszard/goskiplist v0.0.0-20150312221310-2dfbae5fcf46 h1:GHRpF1pTW19a
github.com/ryszard/goskiplist v0.0.0-20150312221310-2dfbae5fcf46/go.mod h1:uAQ5PCi+MFsC7HjREoAz1BU+Mq60+05gifQSsHSDG/8=
github.com/secure-systems-lab/go-securesystemslib v0.8.0 h1:mr5An6X45Kb2nddcFlbmfHkLguCE9laoZCUzEEpIZXA=
github.com/secure-systems-lab/go-securesystemslib v0.8.0/go.mod h1:UH2VZVuJfCYR8WgMlCU1uFsOUU+KeyrTWcSS73NBOzU=
github.com/shabbyrobe/gocovmerge v0.0.0-20180507124511-f6ea450bfb63/go.mod h1:n+VKSARF5y/tS9XFSP7vWDfS+GUC5vs/YT7M5XDTUEM=
github.com/shabbyrobe/gocovmerge v0.0.0-20190829150210-3e036491d500 h1:WnNuhiq+FOY3jNj6JXFT+eLN3CQ/oPIsDPRanvwsmbI=
github.com/shabbyrobe/gocovmerge v0.0.0-20190829150210-3e036491d500/go.mod h1:+njLrG5wSeoG4Ds61rFgEzKvenR2UHbjMoDHsczxly0=
github.com/shirou/gopsutil v3.21.11+incompatible h1:+1+c1VGhc88SSonWP6foOcLhvnKlUeu/erjjvaPEYiI=
@@ -405,6 +450,8 @@ golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.15.0 h1:SernR4v+D55NyBH2QiEQrlBAnj1ECL6AGrA5+dPaMY8=
golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -413,13 +460,15 @@ golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73r
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4=
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
@@ -432,6 +481,7 @@ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ=
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -452,16 +502,24 @@ golang.org/x/sys v0.0.0-20220627191245-f75cf1eec38b/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y=
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY=
golang.org/x/term v0.17.0 h1:mkTF7LCd6WGJNL3K1Ad7kwxNfYAW6a8a8QqtMblp/4U=
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
@@ -469,7 +527,6 @@ golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
golang.org/x/tools v0.0.0-20190308174544-00c44ba9c14f/go.mod h1:25r3+/G6/xytQM8iWZKq3Hn0kr0rgFKPUNVEL/dr3z4=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190829051458-42f498d34c4d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
@@ -478,6 +535,8 @@ golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roY
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/tools v0.8.0/go.mod h1:JxBZ99ISMI5ViVkT1tr6tdNmXeTrcpVSD3vZ1RsRdN4=
golang.org/x/tools v0.18.0 h1:k8NLag8AGHnn+PHbl7g43CtqZAwG60vZkLqgyZgIHgQ=
golang.org/x/tools v0.18.0/go.mod h1:GL7B4CwcLLeo59yx/9UWWuNOW1n3VZ4f5axWfML7Lcg=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=

View File

@@ -3,22 +3,25 @@ package cloudwatch
import (
"context"
"fmt"
"slices"
"sync"
"time"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/cloudwatch"
"github.com/aws/aws-sdk-go-v2/aws"
awsConfig "github.com/aws/aws-sdk-go-v2/config"
"github.com/aws/aws-sdk-go-v2/service/cloudwatch"
cloudwatchTypes "github.com/aws/aws-sdk-go-v2/service/cloudwatch/types"
"github.com/sirupsen/logrus"
"github.com/imgproxy/imgproxy/v3/config"
"github.com/imgproxy/imgproxy/v3/imath"
"github.com/imgproxy/imgproxy/v3/metrics/stats"
"github.com/sirupsen/logrus"
)
type GaugeFunc func() float64
type gauge struct {
unit string
unit cloudwatchTypes.StandardUnit
f GaugeFunc
}
@@ -30,7 +33,7 @@ type bufferStats struct {
var (
enabled bool
client *cloudwatch.CloudWatch
client *cloudwatch.Client
gauges = make(map[string]gauge)
gaugesMutex sync.RWMutex
@@ -49,22 +52,20 @@ func Init() error {
return nil
}
conf := aws.NewConfig()
if len(config.CloudWatchRegion) > 0 {
conf = conf.WithRegion(config.CloudWatchRegion)
}
sess, err := session.NewSession()
conf, err := awsConfig.LoadDefaultConfig(context.Background())
if err != nil {
return fmt.Errorf("Can't create CloudWatch session: %s", err)
return fmt.Errorf("can't load CloudWatch config: %s", err)
}
if sess.Config.Region == nil || len(*sess.Config.Region) == 0 {
sess.Config.Region = aws.String("us-west-1")
if len(config.CloudWatchRegion) != 0 {
conf.Region = config.CloudWatchRegion
}
client = cloudwatch.New(sess, conf)
if len(conf.Region) == 0 {
conf.Region = "us-west-1"
}
client = cloudwatch.NewFromConfig(conf)
collectorCtx, collectorCtxCancel = context.WithCancel(context.Background())
@@ -89,7 +90,13 @@ func AddGaugeFunc(name, unit string, f GaugeFunc) {
gaugesMutex.Lock()
defer gaugesMutex.Unlock()
gauges[name] = gauge{unit: unit, f: f}
standardUnit := cloudwatchTypes.StandardUnit(unit)
if !slices.Contains(cloudwatchTypes.StandardUnitNone.Values(), standardUnit) {
panic(fmt.Errorf("Unknown CloudWatch unit: %s", unit))
}
gauges[name] = gauge{unit: standardUnit, f: f}
}
func ObserveBufferSize(t string, size int) {
@@ -135,18 +142,18 @@ func runMetricsCollector() {
tick := time.NewTicker(10 * time.Second)
defer tick.Stop()
dimension := &cloudwatch.Dimension{
dimension := cloudwatchTypes.Dimension{
Name: aws.String("ServiceName"),
Value: aws.String(config.CloudWatchServiceName),
}
bufferDimensions := make(map[string]*cloudwatch.Dimension)
bufferDimension := func(t string) *cloudwatch.Dimension {
bufferDimensions := make(map[string]cloudwatchTypes.Dimension)
bufferDimension := func(t string) cloudwatchTypes.Dimension {
if d, ok := bufferDimensions[t]; ok {
return d
}
d := &cloudwatch.Dimension{
d := cloudwatchTypes.Dimension{
Name: aws.String("BufferType"),
Value: aws.String(t),
}
@@ -160,17 +167,17 @@ func runMetricsCollector() {
select {
case <-tick.C:
metricsCount := len(gauges) + len(bufferDefaultSizes) + len(bufferMaxSizes) + len(bufferSizeStats) + 3
metrics := make([]*cloudwatch.MetricDatum, 0, metricsCount)
metrics := make([]cloudwatchTypes.MetricDatum, 0, metricsCount)
func() {
gaugesMutex.RLock()
defer gaugesMutex.RUnlock()
for name, g := range gauges {
metrics = append(metrics, &cloudwatch.MetricDatum{
Dimensions: []*cloudwatch.Dimension{dimension},
metrics = append(metrics, cloudwatchTypes.MetricDatum{
Dimensions: []cloudwatchTypes.Dimension{dimension},
MetricName: aws.String(name),
Unit: aws.String(g.unit),
Unit: g.unit,
Value: aws.Float64(g.f()),
})
}
@@ -181,29 +188,29 @@ func runMetricsCollector() {
defer bufferStatsMutex.Unlock()
for t, size := range bufferDefaultSizes {
metrics = append(metrics, &cloudwatch.MetricDatum{
Dimensions: []*cloudwatch.Dimension{dimension, bufferDimension(t)},
metrics = append(metrics, cloudwatchTypes.MetricDatum{
Dimensions: []cloudwatchTypes.Dimension{dimension, bufferDimension(t)},
MetricName: aws.String("BufferDefaultSize"),
Unit: aws.String("Bytes"),
Unit: cloudwatchTypes.StandardUnitBytes,
Value: aws.Float64(float64(size)),
})
}
for t, size := range bufferMaxSizes {
metrics = append(metrics, &cloudwatch.MetricDatum{
Dimensions: []*cloudwatch.Dimension{dimension, bufferDimension(t)},
metrics = append(metrics, cloudwatchTypes.MetricDatum{
Dimensions: []cloudwatchTypes.Dimension{dimension, bufferDimension(t)},
MetricName: aws.String("BufferMaximumSize"),
Unit: aws.String("Bytes"),
Unit: cloudwatchTypes.StandardUnitBytes,
Value: aws.Float64(float64(size)),
})
}
for t, stats := range bufferSizeStats {
metrics = append(metrics, &cloudwatch.MetricDatum{
Dimensions: []*cloudwatch.Dimension{dimension, bufferDimension(t)},
metrics = append(metrics, cloudwatchTypes.MetricDatum{
Dimensions: []cloudwatchTypes.Dimension{dimension, bufferDimension(t)},
MetricName: aws.String("BufferSize"),
Unit: aws.String("Bytes"),
StatisticValues: &cloudwatch.StatisticSet{
Unit: cloudwatchTypes.StandardUnitBytes,
StatisticValues: &cloudwatchTypes.StatisticSet{
SampleCount: aws.Float64(float64(stats.count)),
Sum: aws.Float64(float64(stats.sum)),
Minimum: aws.Float64(float64(stats.min)),
@@ -213,45 +220,51 @@ func runMetricsCollector() {
}
}()
metrics = append(metrics, &cloudwatch.MetricDatum{
Dimensions: []*cloudwatch.Dimension{dimension},
metrics = append(metrics, cloudwatchTypes.MetricDatum{
Dimensions: []cloudwatchTypes.Dimension{dimension},
MetricName: aws.String("RequestsInProgress"),
Unit: aws.String("Count"),
Unit: cloudwatchTypes.StandardUnitCount,
Value: aws.Float64(stats.RequestsInProgress()),
})
metrics = append(metrics, &cloudwatch.MetricDatum{
Dimensions: []*cloudwatch.Dimension{dimension},
metrics = append(metrics, cloudwatchTypes.MetricDatum{
Dimensions: []cloudwatchTypes.Dimension{dimension},
MetricName: aws.String("ImagesInProgress"),
Unit: aws.String("Count"),
Unit: cloudwatchTypes.StandardUnitCount,
Value: aws.Float64(stats.ImagesInProgress()),
})
metrics = append(metrics, &cloudwatch.MetricDatum{
Dimensions: []*cloudwatch.Dimension{dimension},
metrics = append(metrics, cloudwatchTypes.MetricDatum{
Dimensions: []cloudwatchTypes.Dimension{dimension},
MetricName: aws.String("ConcurrencyUtilization"),
Unit: aws.String("Percent"),
Unit: cloudwatchTypes.StandardUnitPercent,
Value: aws.Float64(
stats.RequestsInProgress() / float64(config.Workers) * 100.0,
),
})
metrics = append(metrics, &cloudwatch.MetricDatum{
Dimensions: []*cloudwatch.Dimension{dimension},
metrics = append(metrics, cloudwatchTypes.MetricDatum{
Dimensions: []cloudwatchTypes.Dimension{dimension},
MetricName: aws.String("WorkersUtilization"),
Unit: aws.String("Percent"),
Unit: cloudwatchTypes.StandardUnitPercent,
Value: aws.Float64(
stats.RequestsInProgress() / float64(config.Workers) * 100.0,
),
})
_, err := client.PutMetricData(&cloudwatch.PutMetricDataInput{
input := cloudwatch.PutMetricDataInput{
Namespace: aws.String(config.CloudWatchNamespace),
MetricData: metrics,
})
if err != nil {
logrus.Warnf("Can't send CloudWatch metrics: %s", err)
}
func() {
ctx, cancel := context.WithTimeout(collectorCtx, 30*time.Second)
defer cancel()
if _, err := client.PutMetricData(ctx, &input); err != nil {
logrus.Warnf("Can't send CloudWatch metrics: %s", err)
}
}()
case <-collectorCtx.Done():
return
}

View File

@@ -2,6 +2,7 @@ package s3
import (
"context"
"errors"
"fmt"
"io"
"net/http"
@@ -10,29 +11,32 @@ import (
"sync"
"time"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/aws/credentials/stscreds"
"github.com/aws/aws-sdk-go/aws/request"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/kms"
"github.com/aws/aws-sdk-go/service/s3"
"github.com/aws/aws-sdk-go/service/s3/s3crypto"
"github.com/aws/aws-sdk-go/service/s3/s3manager"
s3Crypto "github.com/aws/amazon-s3-encryption-client-go/v3/client"
s3CryptoMaterials "github.com/aws/amazon-s3-encryption-client-go/v3/materials"
"github.com/aws/aws-sdk-go-v2/aws"
awsHttp "github.com/aws/aws-sdk-go-v2/aws/transport/http"
awsConfig "github.com/aws/aws-sdk-go-v2/config"
"github.com/aws/aws-sdk-go-v2/credentials/stscreds"
s3Manager "github.com/aws/aws-sdk-go-v2/feature/s3/manager"
"github.com/aws/aws-sdk-go-v2/service/kms"
"github.com/aws/aws-sdk-go-v2/service/s3"
"github.com/aws/aws-sdk-go-v2/service/sts"
"github.com/imgproxy/imgproxy/v3/config"
defaultTransport "github.com/imgproxy/imgproxy/v3/transport"
)
type s3Client interface {
GetObjectRequest(input *s3.GetObjectInput) (req *request.Request, output *s3.GetObjectOutput)
GetObject(ctx context.Context, input *s3.GetObjectInput, opts ...func(*s3.Options)) (*s3.GetObjectOutput, error)
HeadBucket(ctx context.Context, input *s3.HeadBucketInput, optFns ...func(*s3.Options)) (*s3.HeadBucketOutput, error)
}
// transport implements RoundTripper for the 's3' protocol.
type transport struct {
session *session.Session
clientOptions []func(*s3.Options)
defaultClient s3Client
defaultConfig *aws.Config
defaultConfig aws.Config
clientsByRegion map[string]s3Client
clientsByBucket map[string]s3Client
@@ -41,7 +45,10 @@ type transport struct {
}
func New() (http.RoundTripper, error) {
conf := aws.NewConfig()
conf, err := awsConfig.LoadDefaultConfig(context.Background())
if err != nil {
return nil, fmt.Errorf("can't load AWS S3 config: %s", err)
}
trans, err := defaultTransport.New(false)
if err != nil {
@@ -50,40 +57,38 @@ func New() (http.RoundTripper, error) {
conf.HTTPClient = &http.Client{Transport: trans}
if len(config.S3Endpoint) != 0 {
conf.Endpoint = aws.String(config.S3Endpoint)
conf.S3ForcePathStyle = aws.Bool(true)
}
sess, err := session.NewSession()
if err != nil {
return nil, fmt.Errorf("can't create S3 session: %s", err)
}
if len(config.S3Region) != 0 {
sess.Config.Region = aws.String(config.S3Region)
conf.Region = config.S3Region
}
if sess.Config.Region == nil || len(*sess.Config.Region) == 0 {
sess.Config.Region = aws.String("us-west-1")
if len(conf.Region) == 0 {
conf.Region = "us-west-1"
}
if len(config.S3AssumeRoleArn) != 0 {
conf.Credentials = stscreds.NewCredentials(sess, config.S3AssumeRoleArn)
creds := stscreds.NewAssumeRoleProvider(sts.NewFromConfig(conf), config.S3AssumeRoleArn)
conf.Credentials = creds
}
client, err := createClient(sess, conf)
clientOptions := []func(*s3.Options){}
if len(config.S3Endpoint) != 0 {
clientOptions = append(clientOptions, func(o *s3.Options) {
o.BaseEndpoint = aws.String(config.S3Endpoint)
o.UsePathStyle = true
})
}
client, err := createClient(conf, clientOptions)
if err != nil {
return nil, fmt.Errorf("can't create S3 client: %s", err)
}
clientRegion := *sess.Config.Region
return &transport{
session: sess,
clientOptions: clientOptions,
defaultClient: client,
defaultConfig: conf,
clientsByRegion: map[string]s3Client{clientRegion: client},
clientsByRegion: map[string]s3Client{conf.Region: client},
clientsByBucket: make(map[string]s3Client),
}, nil
}
@@ -91,13 +96,15 @@ func New() (http.RoundTripper, error) {
func (t *transport) RoundTrip(req *http.Request) (*http.Response, error) {
input := &s3.GetObjectInput{
Bucket: aws.String(req.URL.Host),
Key: aws.String(req.URL.Path),
Key: aws.String(strings.TrimPrefix(req.URL.Path, "/")),
}
if len(req.URL.RawQuery) > 0 {
input.VersionId = aws.String(req.URL.RawQuery)
}
statusCode := http.StatusOK
if r := req.Header.Get("Range"); len(r) != 0 {
input.Range = aws.String(r)
} else {
@@ -121,30 +128,71 @@ func (t *transport) RoundTrip(req *http.Request) (*http.Response, error) {
return handleError(req, err)
}
s3req, objectOutput := client.GetObjectRequest(input)
s3req.SetContext(req.Context())
if err := s3req.Send(); err != nil {
if s3req.HTTPResponse != nil && s3req.HTTPResponse.Body != nil {
s3req.HTTPResponse.Body.Close()
output, err := client.GetObject(req.Context(), input)
if err != nil {
if output != nil && output.Body != nil {
output.Body.Close()
}
return handleError(req, err)
}
if config.S3DecryptionClientEnabled {
s3req.HTTPResponse.Body = objectOutput.Body
contentLength := int64(-1)
if output.ContentLength != nil {
contentLength = *output.ContentLength
}
if unencryptedContentLength := s3req.HTTPResponse.Header.Get("X-Amz-Meta-X-Amz-Unencrypted-Content-Length"); len(unencryptedContentLength) != 0 {
contentLength, err := strconv.ParseInt(unencryptedContentLength, 10, 64)
if config.S3DecryptionClientEnabled {
if unencryptedContentLength := output.Metadata["X-Amz-Meta-X-Amz-Unencrypted-Content-Length"]; len(unencryptedContentLength) != 0 {
cl, err := strconv.ParseInt(unencryptedContentLength, 10, 64)
if err != nil {
handleError(req, err)
}
s3req.HTTPResponse.ContentLength = contentLength
contentLength = cl
}
}
return s3req.HTTPResponse, nil
header := make(http.Header)
if contentLength > 0 {
header.Set("Content-Length", strconv.FormatInt(contentLength, 10))
}
if output.ContentType != nil {
header.Set("Content-Type", *output.ContentType)
}
if output.ContentEncoding != nil {
header.Set("Content-Encoding", *output.ContentEncoding)
}
if output.CacheControl != nil {
header.Set("Cache-Control", *output.CacheControl)
}
if output.Expires != nil {
header.Set("Expires", output.Expires.Format(http.TimeFormat))
}
if output.ETag != nil {
header.Set("ETag", *output.ETag)
}
if output.LastModified != nil {
header.Set("Last-Modified", output.LastModified.Format(http.TimeFormat))
}
if output.AcceptRanges != nil {
header.Set("Accept-Ranges", *output.AcceptRanges)
}
if output.ContentRange != nil {
header.Set("Content-Range", *output.ContentRange)
statusCode = http.StatusPartialContent
}
return &http.Response{
StatusCode: statusCode,
Proto: "HTTP/1.0",
ProtoMajor: 1,
ProtoMinor: 0,
Header: header,
ContentLength: contentLength,
Body: output.Body,
Close: true,
Request: req,
}, nil
}
func (t *transport) getClient(ctx context.Context, bucket string) (s3Client, error) {
@@ -172,9 +220,13 @@ func (t *transport) getClient(ctx context.Context, bucket string) (s3Client, err
return client, nil
}
region, err := s3manager.GetBucketRegion(ctx, t.session, bucket, *t.session.Config.Region)
region, err := s3Manager.GetBucketRegion(ctx, t.defaultClient, bucket)
if err != nil {
return nil, err
return nil, fmt.Errorf("can't get bucket region: %s", err)
}
if len(region) == 0 {
region = t.defaultConfig.Region
}
if client = t.clientsByRegion[region]; client != nil {
@@ -183,9 +235,9 @@ func (t *transport) getClient(ctx context.Context, bucket string) (s3Client, err
}
conf := t.defaultConfig.Copy()
conf.Region = aws.String(region)
conf.Region = region
client, err = createClient(t.session, conf)
client, err = createClient(conf, t.clientOptions)
if err != nil {
return nil, fmt.Errorf("can't create regional S3 client: %s", err)
}
@@ -196,53 +248,38 @@ func (t *transport) getClient(ctx context.Context, bucket string) (s3Client, err
return client, nil
}
func createClient(sess *session.Session, conf *aws.Config) (s3Client, error) {
if config.S3DecryptionClientEnabled {
// `s3crypto.NewDecryptionClientV2` doesn't accept additional configs, so we
// need to copy the session with an additional config
sess = sess.Copy(conf)
func createClient(conf aws.Config, opts []func(*s3.Options)) (s3Client, error) {
client := s3.NewFromConfig(conf, opts...)
cryptoRegistry, err := createCryptoRegistry(sess)
if config.S3DecryptionClientEnabled {
kmsClient := kms.NewFromConfig(conf)
keyring := s3CryptoMaterials.NewKmsDecryptOnlyAnyKeyKeyring(kmsClient)
cmm, err := s3CryptoMaterials.NewCryptographicMaterialsManager(keyring)
if err != nil {
return nil, err
}
return s3crypto.NewDecryptionClientV2(sess, cryptoRegistry)
return s3Crypto.New(client, cmm)
} else {
return s3.New(sess, conf), nil
return client, nil
}
}
func createCryptoRegistry(sess *session.Session) (*s3crypto.CryptoRegistry, error) {
kmsClient := kms.New(sess)
cr := s3crypto.NewCryptoRegistry()
if err := s3crypto.RegisterKMSContextWrapWithAnyCMK(cr, kmsClient); err != nil {
return nil, err
}
if err := s3crypto.RegisterAESGCMContentCipher(cr); err != nil {
return nil, err
}
return cr, nil
}
func handleError(req *http.Request, err error) (*http.Response, error) {
if s3err, ok := err.(awserr.Error); ok && s3err.Code() == request.CanceledErrorCode {
if e := s3err.OrigErr(); e != nil {
return nil, e
}
}
s3err, ok := err.(awserr.RequestFailure)
if !ok || s3err.StatusCode() < 100 || s3err.StatusCode() == 301 {
var rerr *awsHttp.ResponseError
if !errors.As(err, &rerr) {
return nil, err
}
body := strings.NewReader(s3err.Message())
if rerr.Response == nil || rerr.Response.StatusCode < 100 || rerr.Response.StatusCode == 301 {
return nil, err
}
body := strings.NewReader(err.Error())
return &http.Response{
StatusCode: s3err.StatusCode(),
StatusCode: rerr.Response.StatusCode,
Proto: "HTTP/1.0",
ProtoMajor: 1,
ProtoMinor: 0,

View File

@@ -9,8 +9,8 @@ import (
"testing"
"time"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/s3"
"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/service/s3"
"github.com/johannesboyne/gofakes3"
"github.com/johannesboyne/gofakes3/backend/s3mem"
"github.com/stretchr/testify/require"
@@ -50,18 +50,18 @@ func (s *S3TestSuite) SetupSuite() {
svc, err := s.transport.(*transport).getClient(context.Background(), "test")
require.Nil(s.T(), err)
require.NotNil(s.T(), svc)
require.IsType(s.T(), &s3.S3{}, svc)
require.IsType(s.T(), &s3.Client{}, svc)
client := svc.(*s3.S3)
client := svc.(*s3.Client)
_, err = client.PutObject(&s3.PutObjectInput{
_, err = client.PutObject(context.Background(), &s3.PutObjectInput{
Body: bytes.NewReader(make([]byte, 32)),
Bucket: aws.String("test"),
Key: aws.String("foo/test.png"),
})
require.Nil(s.T(), err)
obj, err := client.GetObject(&s3.GetObjectInput{
obj, err := client.GetObject(context.Background(), &s3.GetObjectInput{
Bucket: aws.String("test"),
Key: aws.String("foo/test.png"),
})
@@ -128,7 +128,7 @@ func (s *S3TestSuite) TestRoundTripWithLastModifiedDisabledReturns200() {
}
func (s *S3TestSuite) TestRoundTripWithLastModifiedEnabled() {
config.ETagEnabled = true
config.LastModifiedEnabled = true
request, _ := http.NewRequest("GET", "s3://test/foo/test.png", nil)
response, err := s.transport.RoundTrip(request)
@@ -137,7 +137,6 @@ func (s *S3TestSuite) TestRoundTripWithLastModifiedEnabled() {
require.Equal(s.T(), s.lastModified.Format(http.TimeFormat), response.Header.Get("Last-Modified"))
}
// gofakes3 doesn't support If-Modified-Since (yet?)
func (s *S3TestSuite) TestRoundTripWithIfModifiedSinceReturns304() {
config.LastModifiedEnabled = true