@@ -71,28 +71,13 @@ func (a *awsFetcher) fetchS3Buckets(ctx context.Context) ([]*accessgraphv1alpha.
71
71
}
72
72
}
73
73
74
- region := awsutil .GetKnownRegions ()[0 ]
75
- if len (a .Regions ) > 0 {
76
- region = a .Regions [0 ]
77
- }
78
-
79
- s3Client , err := a .CloudClients .GetAWSS3Client (
80
- ctx ,
81
- region ,
82
- a .getAWSOptions ()... ,
83
- )
84
- if err != nil {
85
- return nil , trace .Wrap (err )
86
- }
87
- rsp , err := s3Client .ListBucketsWithContext (
88
- ctx ,
89
- & s3.ListBucketsInput {},
90
- )
74
+ buckets , getBucketRegion , err := a .listS3Buckets (ctx )
91
75
if err != nil {
92
76
return existing .S3Buckets , trace .Wrap (err )
93
77
}
94
78
95
- for _ , bucket := range rsp .Buckets {
79
+ // Iterate over the buckets and fetch their inline and attached policies.
80
+ for _ , bucket := range buckets {
96
81
bucket := bucket
97
82
eG .Go (func () error {
98
83
var failedReqs failedRequests
@@ -101,54 +86,24 @@ func (a *awsFetcher) fetchS3Buckets(ctx context.Context) ([]*accessgraphv1alpha.
101
86
return b .Name == aws .ToString (bucket .Name ) && b .AccountId == a .AccountID
102
87
},
103
88
)
104
- policy , err := s3Client .GetBucketPolicyWithContext (ctx , & s3.GetBucketPolicyInput {
105
- Bucket : bucket .Name ,
106
- })
89
+ bucketRegion , err := getBucketRegion (bucket .Name )
107
90
if err != nil {
108
91
errs = append (errs ,
109
- trace .Wrap (err , "failed to fetch bucket %q inline policy" , aws . ToString ( bucket . Name ) ),
92
+ trace .Wrap (err ),
110
93
)
111
94
failedReqs .policyFailed = true
112
- }
113
-
114
- policyStatus , err := s3Client .GetBucketPolicyStatusWithContext (ctx , & s3.GetBucketPolicyStatusInput {
115
- Bucket : bucket .Name ,
116
- })
117
- if err != nil {
118
- errs = append (errs ,
119
- trace .Wrap (err , "failed to fetch bucket %q policy status" , aws .ToString (bucket .Name )),
120
- )
121
95
failedReqs .failedPolicyStatus = true
122
- }
123
-
124
- acls , err := s3Client .GetBucketAclWithContext (ctx , & s3.GetBucketAclInput {
125
- Bucket : bucket .Name ,
126
- })
127
- if err != nil {
128
- errs = append (errs ,
129
- trace .Wrap (err , "failed to fetch bucket %q acls policies" , aws .ToString (bucket .Name )),
130
- )
131
96
failedReqs .failedAcls = true
132
- }
133
-
134
- tagsOutput , err := s3Client .GetBucketTaggingWithContext (ctx , & s3.GetBucketTaggingInput {
135
- Bucket : bucket .Name ,
136
- })
137
- var awsErr awserr.Error
138
- const noSuchTagSet = "NoSuchTagSet" // error code when there are no tags or the bucket does not support them
139
- if errors .As (err , & awsErr ) && awsErr .Code () == noSuchTagSet {
140
- // If there are no tags, set the error to nil.
141
- err = nil
142
- }
143
- if err != nil {
144
- errs = append (errs ,
145
- trace .Wrap (err , "failed to fetch bucket %q tags" , aws .ToString (bucket .Name )),
146
- )
147
97
failedReqs .failedTags = true
98
+ newBucket := awsS3Bucket (aws .ToString (bucket .Name ), nil , nil , nil , nil , a .AccountID )
99
+ collect (mergeS3Protos (existingBucket , newBucket , failedReqs ), trace .NewAggregate (errs ... ))
100
+ return nil
148
101
}
149
102
150
- newBucket := awsS3Bucket (aws .ToString (bucket .Name ), policy , policyStatus , acls , tagsOutput , a .AccountID )
151
- collect (mergeS3Protos (existingBucket , newBucket , failedReqs ), trace .NewAggregate (errs ... ))
103
+ details , failedReqs , errsL := a .getS3BucketDetails (ctx , bucket , bucketRegion )
104
+
105
+ newBucket := awsS3Bucket (aws .ToString (bucket .Name ), details .policy , details .policyStatus , details .acls , details .tags , a .AccountID )
106
+ collect (mergeS3Protos (existingBucket , newBucket , failedReqs ), trace .NewAggregate (append (errs , errsL ... )... ))
152
107
return nil
153
108
})
154
109
}
@@ -212,6 +167,7 @@ type failedRequests struct {
212
167
failedPolicyStatus bool
213
168
failedAcls bool
214
169
failedTags bool
170
+ headFailed bool
215
171
}
216
172
217
173
func mergeS3Protos (existing , new * accessgraphv1alpha.AWSS3BucketV1 , failedReqs failedRequests ) * accessgraphv1alpha.AWSS3BucketV1 {
@@ -237,3 +193,124 @@ func mergeS3Protos(existing, new *accessgraphv1alpha.AWSS3BucketV1, failedReqs f
237
193
238
194
return clone
239
195
}
196
+
197
+ type s3Details struct {
198
+ policy * s3.GetBucketPolicyOutput
199
+ policyStatus * s3.GetBucketPolicyStatusOutput
200
+ acls * s3.GetBucketAclOutput
201
+ tags * s3.GetBucketTaggingOutput
202
+ }
203
+
204
+ func (a * awsFetcher ) getS3BucketDetails (ctx context.Context , bucket * s3.Bucket , bucketRegion string ) (s3Details , failedRequests , []error ) {
205
+ var failedReqs failedRequests
206
+ var errs []error
207
+ var details s3Details
208
+
209
+ s3Client , err := a .CloudClients .GetAWSS3Client (
210
+ ctx ,
211
+ bucketRegion ,
212
+ a .getAWSOptions ()... ,
213
+ )
214
+ if err != nil {
215
+ errs = append (errs ,
216
+ trace .Wrap (err , "failed to create s3 client for bucket %q" , aws .ToString (bucket .Name )),
217
+ )
218
+ return s3Details {},
219
+ failedRequests {
220
+ headFailed : true ,
221
+ policyFailed : true ,
222
+ failedPolicyStatus : true ,
223
+ failedAcls : true ,
224
+ failedTags : true ,
225
+ }, errs
226
+ }
227
+
228
+ details .policy , err = s3Client .GetBucketPolicyWithContext (ctx , & s3.GetBucketPolicyInput {
229
+ Bucket : bucket .Name ,
230
+ })
231
+ if err != nil && ! isS3BucketPolicyNotFound (err ) {
232
+ errs = append (errs ,
233
+ trace .Wrap (err , "failed to fetch bucket %q inline policy" , aws .ToString (bucket .Name )),
234
+ )
235
+ failedReqs .policyFailed = true
236
+ }
237
+
238
+ details .policyStatus , err = s3Client .GetBucketPolicyStatusWithContext (ctx , & s3.GetBucketPolicyStatusInput {
239
+ Bucket : bucket .Name ,
240
+ })
241
+ if err != nil && ! isS3BucketPolicyNotFound (err ) {
242
+ errs = append (errs ,
243
+ trace .Wrap (err , "failed to fetch bucket %q policy status" , aws .ToString (bucket .Name )),
244
+ )
245
+ failedReqs .failedPolicyStatus = true
246
+ }
247
+
248
+ details .acls , err = s3Client .GetBucketAclWithContext (ctx , & s3.GetBucketAclInput {
249
+ Bucket : bucket .Name ,
250
+ })
251
+ if err != nil {
252
+ errs = append (errs ,
253
+ trace .Wrap (err , "failed to fetch bucket %q acls policies" , aws .ToString (bucket .Name )),
254
+ )
255
+ failedReqs .failedAcls = true
256
+ }
257
+
258
+ details .tags , err = s3Client .GetBucketTaggingWithContext (ctx , & s3.GetBucketTaggingInput {
259
+ Bucket : bucket .Name ,
260
+ })
261
+ if err != nil && ! isS3BucketNoTagSet (err ) {
262
+ errs = append (errs ,
263
+ trace .Wrap (err , "failed to fetch bucket %q tags" , aws .ToString (bucket .Name )),
264
+ )
265
+ failedReqs .failedTags = true
266
+ }
267
+
268
+ return details , failedReqs , errs
269
+ }
270
+
271
+ func isS3BucketPolicyNotFound (err error ) bool {
272
+ var awsErr awserr.Error
273
+ return errors .As (err , & awsErr ) && awsErr .Code () == "NoSuchBucketPolicy"
274
+ }
275
+
276
+ func isS3BucketNoTagSet (err error ) bool {
277
+ var awsErr awserr.Error
278
+ return errors .As (err , & awsErr ) && awsErr .Code () == "NoSuchTagSet"
279
+ }
280
+
281
+ func (a * awsFetcher ) listS3Buckets (ctx context.Context ) ([]* s3.Bucket , func (* string ) (string , error ), error ) {
282
+ region := awsutil .GetKnownRegions ()[0 ]
283
+ if len (a .Regions ) > 0 {
284
+ region = a .Regions [0 ]
285
+ }
286
+
287
+ // use any region to list buckets
288
+ s3Client , err := a .CloudClients .GetAWSS3Client (
289
+ ctx ,
290
+ region ,
291
+ a .getAWSOptions ()... ,
292
+ )
293
+ if err != nil {
294
+ return nil , nil , trace .Wrap (err )
295
+ }
296
+ rsp , err := s3Client .ListBucketsWithContext (ctx , & s3.ListBucketsInput {})
297
+ if err != nil {
298
+ return nil , nil , trace .Wrap (err )
299
+ }
300
+ return rsp .Buckets ,
301
+ func (bucket * string ) (string , error ) {
302
+ rsp , err := s3Client .GetBucketLocationWithContext (
303
+ ctx ,
304
+ & s3.GetBucketLocationInput {
305
+ Bucket : bucket ,
306
+ },
307
+ )
308
+ if err != nil {
309
+ return "" , trace .Wrap (err , "failed to fetch bucket %q region" , aws .ToString (bucket ))
310
+ }
311
+ if rsp .LocationConstraint == nil {
312
+ return "us-east-1" , nil
313
+ }
314
+ return aws .ToString (rsp .LocationConstraint ), nil
315
+ }, nil
316
+ }
0 commit comments