33package downloader
44
55import (
6- "bufio "
6+ "context "
77 "errors"
88 "os"
99 "strings"
1010
11- "github.com/aws/aws-sdk-go/aws"
12- "github.com/aws/aws-sdk-go/aws/awserr "
13- "github.com/aws/aws-sdk-go/aws /credentials"
14- "github.com/aws/aws-sdk-go/aws/session "
15- "github.com/aws/aws-sdk-go/service/s3"
16- "github.com/aws/aws-sdk-go/service/s3/s3manager "
11+ "github.com/aws/aws-sdk-go-v2 /aws"
12+ "github.com/aws/aws-sdk-go-v2/config "
13+ "github.com/aws/aws-sdk-go-v2 /credentials"
14+ "github.com/aws/aws-sdk-go-v2/feature/s3/manager "
15+ "github.com/aws/aws-sdk-go-v2 /service/s3"
16+ "github.com/aws/smithy-go "
1717)
1818
19- // Downloader tracks the region and Session and only recreates the Session
19+ // Downloader tracks the region and AWS config and only recreates the config
2020// if the region has changed
2121type Downloader struct {
2222 region string
23- sess * session.Session
23+ cfg aws.Config
24+ ctx context.Context
2425}
2526
26- func New () * Downloader {
27- d := & Downloader {}
28- return d
29- }
30-
31- // getValue parses a string and returns the value assigned to a key
32- func (d * Downloader ) getValue (line string ) string {
33- splitLine := strings .Split (line , " = " )
34- return (splitLine [len (splitLine )- 1 ])
35- }
36-
37- // credentialsFromFile loads AWS credentials from a non-standard path
38- func (d * Downloader ) credentialsFromFile (fileName string ) (string , string , string , error ) {
39- var accessKey , secretKey , token string
40-
41- file , err := os .Open (fileName )
42- if err != nil {
43- return "" , "" , "" , err
44- }
45- defer file .Close ()
46-
47- scanner := bufio .NewScanner (file )
48- for scanner .Scan () {
49- switch {
50- case strings .Contains (scanner .Text (), "aws_access_key_id" ):
51- accessKey = d .getValue (scanner .Text ())
52- case strings .Contains (scanner .Text (), "aws_secret_access_key" ):
53- secretKey = d .getValue (scanner .Text ())
54- case strings .Contains (scanner .Text (), "aws_session_token" ):
55- token = d .getValue (scanner .Text ())
56- }
27+ func New (ctx context.Context ) * Downloader {
28+ d := & Downloader {
29+ ctx : ctx ,
5730 }
58- if err := scanner .Err (); err != nil {
59- return "" , "" , "" , err
60- }
61-
62- return accessKey , secretKey , token , nil
31+ return d
6332}
6433
65- // loadCredentials sets up a Session using credentials found in /etc/apt/s3creds
66- // or using the default configuration supported by AWS if /etc/apt/s3creds does
67- // not exist
68- func (d * Downloader ) loadCredentials (region string ) (* session.Session , error ) {
69- var config aws.Config
70- var sess * session.Session
71-
72- if _ , err := os .Stat ("/etc/apt/s3creds" ); err == nil {
73- accessKey , secretKey , token , err := d .credentialsFromFile ("/etc/apt/s3creds" )
74- if err != nil {
75- return nil , err
76- }
77- config = aws.Config {
78- Region : aws .String (region ),
79- Credentials : credentials .NewStaticCredentials (accessKey , secretKey , token ),
80- }
81- } else if os .IsNotExist (err ) {
82- config = aws.Config {Region : aws .String (region )}
34+ // loadCredentials sets up an AWS Config using credentials from environment variables
35+ // (OIDC_KEY_ID, OIDC_ACCESS_KEY, OIDC_SESSION_TOKEN), or falling back to the default
36+ // AWS credential chain (which includes AWS_PROFILE, ~/.aws/config, IAM roles, etc.)
37+ func (d * Downloader ) loadCredentials (region string ) (aws.Config , error ) {
38+ // Check OIDC environment variables
39+ oidcKeyID := os .Getenv ("OIDC_KEY_ID" )
40+ oidcAccessKey := os .Getenv ("OIDC_ACCESS_KEY" )
41+ oidcSessionToken := os .Getenv ("OIDC_SESSION_TOKEN" )
42+
43+ if oidcKeyID != "" && oidcAccessKey != "" {
44+ // Use static credentials from OIDC environment variables
45+ cfg , err := config .LoadDefaultConfig (d .ctx ,
46+ config .WithRegion (region ),
47+ config .WithCredentialsProvider (credentials .NewStaticCredentialsProvider (
48+ oidcKeyID ,
49+ oidcAccessKey ,
50+ oidcSessionToken ,
51+ )),
52+ )
53+ return cfg , err
8354 }
84- sess , err := session .NewSession (& config )
8555
86- return sess , err
56+ // Use default AWS credential chain (supports AWS_PROFILE, IAM roles, etc.)
57+ cfg , err := config .LoadDefaultConfig (d .ctx , config .WithRegion (region ))
58+ return cfg , err
8759}
8860
8961// parseUri takes an S3 URI s3://<bucket>.s3-<region>.amazonaws.com/key/file
@@ -113,22 +85,24 @@ func (d *Downloader) GetFileAttributes(s3Uri string) (string, int64, error) {
11385
11486 if d .region != region {
11587 d .region = region
116- d .sess , err = d .loadCredentials (region )
88+ d .cfg , err = d .loadCredentials (region )
11789 if err != nil {
11890 return "" , - 1 , err
11991 }
12092 }
12193
122- svc := s3 .New (d .sess )
94+ client := s3 .NewFromConfig (d .cfg )
12395
124- result , err := svc .GetObject (& s3.GetObjectInput {
96+ result , err := client .GetObject (d . ctx , & s3.GetObjectInput {
12597 Bucket : aws .String (bucket ),
12698 Key : aws .String (key ),
12799 })
128100 if err != nil {
129- if aerr , ok := err .(awserr.Error ); ok {
130- return "" , - 1 , errors .New (strings .Join (strings .Split (aerr .Error (), "\n " ), " " ))
101+ var ae smithy.APIError
102+ if errors .As (err , & ae ) {
103+ return "" , - 1 , errors .New (strings .Join (strings .Split (ae .Error (), "\n " ), " " ))
131104 }
105+ return "" , - 1 , err
132106 }
133107
134108 return result .LastModified .Format ("2006-01-02T15:04:05+00:00" ), * result .ContentLength , nil
@@ -145,19 +119,22 @@ func (d *Downloader) DownloadFile(s3Uri string, path string) (string, error) {
145119
146120 if d .region != region {
147121 d .region = region
148- d .sess , err = d .loadCredentials (region )
122+ d .cfg , err = d .loadCredentials (region )
149123 if err != nil {
150124 return "" , err
151125 }
152126 }
153- downloader := s3manager .NewDownloader (d .sess )
127+
128+ client := s3 .NewFromConfig (d .cfg )
129+ downloader := manager .NewDownloader (client )
154130
155131 f , err := os .Create (filename )
156132 if err != nil {
157133 return "" , err
158134 }
135+ defer f .Close ()
159136
160- if _ , err := downloader .Download (f , & s3.GetObjectInput {
137+ if _ , err := downloader .Download (d . ctx , f , & s3.GetObjectInput {
161138 Bucket : aws .String (bucket ),
162139 Key : aws .String (key ),
163140 }); err != nil {
0 commit comments