Skip to content

Commit bdb2a13

Browse files
authored
fix(object): getting a 403 when reading bucket should not exit the provider (#2302)
* feat(object): 403 when reading bucket should not exit the provider * feat(object): gofumpt * doc(object): review comments
1 parent caecfcc commit bdb2a13

File tree

2 files changed

+82
-25
lines changed

2 files changed

+82
-25
lines changed

scaleway/helpers_object.go

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,10 @@ import (
1818
"github.com/aws/aws-sdk-go/aws/session"
1919
"github.com/aws/aws-sdk-go/service/s3"
2020
awspolicy "github.com/hashicorp/awspolicyequivalence"
21+
"github.com/hashicorp/go-cty/cty"
2122
"github.com/hashicorp/go-multierror"
2223
"github.com/hashicorp/terraform-plugin-log/tflog"
24+
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
2325
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/logging"
2426
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
2527
"github.com/scaleway/scaleway-sdk-go/scw"
@@ -590,3 +592,48 @@ func normalizeOwnerID(id *string) *string {
590592

591593
return &tab[0]
592594
}
595+
596+
func addReadBucketErrorDiagnostic(diags *diag.Diagnostics, err error, resource string, awsResourceNotFoundCode string) (bucketFound bool, resourceFound bool) {
597+
switch {
598+
case isS3Err(err, s3.ErrCodeNoSuchBucket, ""):
599+
*diags = append(*diags, diag.Diagnostic{
600+
Severity: diag.Warning,
601+
Summary: "Bucket not found",
602+
Detail: "Got 404 error while reading bucket, removing from state",
603+
})
604+
return false, false
605+
606+
case isS3Err(err, awsResourceNotFoundCode, ""):
607+
return true, false
608+
609+
case isS3Err(err, ErrCodeAccessDenied, ""):
610+
d := diag.Diagnostic{
611+
Severity: diag.Warning,
612+
Summary: fmt.Sprintf("Cannot read bucket %s: Forbidden", resource),
613+
Detail: fmt.Sprintf("Got 403 error while reading bucket %s, please check your IAM permissions and your bucket policy", resource),
614+
}
615+
616+
attributes := map[string]string{
617+
"acl": "acl",
618+
"object lock configuration": "object_lock_enabled",
619+
"objects": "",
620+
"tags": "tags",
621+
"CORS configuration": "cors_rule",
622+
"versioning": "versioning",
623+
"lifecycle configuration": "lifecycle_rule",
624+
}
625+
if attributeName, ok := attributes[resource]; ok {
626+
d.AttributePath = cty.GetAttrPath(attributeName)
627+
}
628+
629+
*diags = append(*diags, d)
630+
return true, true
631+
632+
default:
633+
*diags = append(*diags, diag.Diagnostic{
634+
Severity: diag.Error,
635+
Summary: fmt.Errorf("couldn't read bucket %s: %w", resource, err).Error(),
636+
})
637+
return true, true
638+
}
639+
}

scaleway/resource_object_bucket.go

Lines changed: 35 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,7 @@ import (
66
"log"
77

88
"github.com/aws/aws-sdk-go/aws"
9-
"github.com/aws/aws-sdk-go/aws/awserr"
109
"github.com/aws/aws-sdk-go/service/s3"
11-
"github.com/hashicorp/aws-sdk-go-base/tfawserr"
1210
"github.com/hashicorp/terraform-plugin-log/tflog"
1311
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
1412
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
@@ -452,14 +450,18 @@ func resourceScalewayObjectBucketRead(ctx context.Context, d *schema.ResourceDat
452450
return diag.FromErr(err)
453451
}
454452

453+
var diags diag.Diagnostics
454+
455455
_ = d.Set("name", bucketName)
456456
_ = d.Set("region", region)
457457

458458
acl, err := s3Client.GetBucketAclWithContext(ctx, &s3.GetBucketAclInput{
459459
Bucket: aws.String(bucketName),
460460
})
461461
if err != nil {
462-
return diag.FromErr(fmt.Errorf("couldn't read bucket acl: %s", err))
462+
if bucketFound, _ := addReadBucketErrorDiagnostic(&diags, err, "acl", ""); !bucketFound {
463+
return diags
464+
}
463465
}
464466
_ = d.Set("project_id", normalizeOwnerID(acl.Owner.ID))
465467

@@ -468,15 +470,13 @@ func resourceScalewayObjectBucketRead(ctx context.Context, d *schema.ResourceDat
468470
Bucket: aws.String(bucketName),
469471
})
470472
if err != nil {
471-
switch {
472-
case isS3Err(err, ErrCodeObjectLockConfigurationNotFoundError, ""):
473-
_ = d.Set("object_lock_enabled", false)
474-
case isS3Err(err, s3.ErrCodeNoSuchBucket, ""):
475-
tflog.Error(ctx, fmt.Sprintf("Bucket %q was not found - removing from state!", bucketName))
473+
bucketFound, objectLockFound := addReadBucketErrorDiagnostic(&diags, err, "object lock configuration", ErrCodeObjectLockConfigurationNotFoundError)
474+
if !bucketFound {
476475
d.SetId("")
477-
return nil
478-
default:
479-
return diag.FromErr(fmt.Errorf("couldn't read bucket: %s", err))
476+
return diags
477+
}
478+
if !objectLockFound {
479+
_ = d.Set("object_lock_enabled", false)
480480
}
481481
} else if objectLockConfiguration.ObjectLockConfiguration != nil {
482482
_ = d.Set("object_lock_enabled", true)
@@ -495,12 +495,10 @@ func resourceScalewayObjectBucketRead(ctx context.Context, d *schema.ResourceDat
495495
Bucket: scw.StringPtr(bucketName),
496496
})
497497
if err != nil {
498-
if s3err, ok := err.(awserr.Error); ok && s3err.Code() == s3.ErrCodeNoSuchBucket {
499-
tflog.Error(ctx, fmt.Sprintf("Bucket %q was not found - removing from state!", bucketName))
498+
if bucketFound, _ := addReadBucketErrorDiagnostic(&diags, err, "objects", ""); !bucketFound {
500499
d.SetId("")
501-
return nil
500+
return diags
502501
}
503-
return diag.FromErr(fmt.Errorf("couldn't read bucket: %s", err))
504502
}
505503

506504
var tagsSet []*s3.Tag
@@ -509,8 +507,9 @@ func resourceScalewayObjectBucketRead(ctx context.Context, d *schema.ResourceDat
509507
Bucket: scw.StringPtr(bucketName),
510508
})
511509
if err != nil {
512-
if s3err, ok := err.(awserr.Error); !ok || s3err.Code() != ErrCodeNoSuchTagSet {
513-
return diag.FromErr(fmt.Errorf("couldn't read tags from bucket: %s", err))
510+
if bucketFound, _ := addReadBucketErrorDiagnostic(&diags, err, "tags", ErrCodeNoSuchTagSet); !bucketFound {
511+
d.SetId("")
512+
return diags
514513
}
515514
} else {
516515
tagsSet = tagsResponse.TagSet
@@ -525,9 +524,11 @@ func resourceScalewayObjectBucketRead(ctx context.Context, d *schema.ResourceDat
525524
corsResponse, err := s3Client.GetBucketCorsWithContext(ctx, &s3.GetBucketCorsInput{
526525
Bucket: scw.StringPtr(bucketName),
527526
})
528-
529-
if err != nil && !isS3Err(err, ErrCodeNoSuchCORSConfiguration, "") {
530-
return diag.FromErr(fmt.Errorf("error getting S3 Bucket CORS configuration: %s", err))
527+
if err != nil {
528+
if bucketFound, _ := addReadBucketErrorDiagnostic(&diags, err, "CORS configuration", ErrCodeNoSuchCORSConfiguration); !bucketFound {
529+
d.SetId("")
530+
return diags
531+
}
531532
}
532533

533534
_ = d.Set("cors_rule", flattenBucketCORS(corsResponse))
@@ -537,16 +538,22 @@ func resourceScalewayObjectBucketRead(ctx context.Context, d *schema.ResourceDat
537538
Bucket: scw.StringPtr(bucketName),
538539
})
539540
if err != nil {
540-
return diag.FromErr(err)
541+
if bucketFound, _ := addReadBucketErrorDiagnostic(&diags, err, "versioning", ""); !bucketFound {
542+
d.SetId("")
543+
return diags
544+
}
541545
}
542546
_ = d.Set("versioning", flattenObjectBucketVersioning(versioningResponse))
543547

544548
// Read the lifecycle configuration
545549
lifecycle, err := s3Client.GetBucketLifecycleConfigurationWithContext(ctx, &s3.GetBucketLifecycleConfigurationInput{
546550
Bucket: scw.StringPtr(bucketName),
547551
})
548-
if err != nil && !tfawserr.ErrMessageContains(err, ErrCodeNoSuchLifecycleConfiguration, "") {
549-
return diag.FromErr(err)
552+
if err != nil {
553+
if bucketFound, _ := addReadBucketErrorDiagnostic(&diags, err, "lifecycle configuration", ErrCodeNoSuchLifecycleConfiguration); !bucketFound {
554+
d.SetId("")
555+
return diags
556+
}
550557
}
551558

552559
lifecycleRules := make([]map[string]interface{}, 0)
@@ -632,10 +639,13 @@ func resourceScalewayObjectBucketRead(ctx context.Context, d *schema.ResourceDat
632639
}
633640
}
634641
if err := d.Set("lifecycle_rule", lifecycleRules); err != nil {
635-
return diag.FromErr(fmt.Errorf("error setting lifecycle_rule: %s", err))
642+
return append(diags, diag.Diagnostic{
643+
Severity: diag.Error,
644+
Summary: fmt.Sprintf("error setting lifecycle_rule: %s", err),
645+
})
636646
}
637647

638-
return nil
648+
return diags
639649
}
640650

641651
func resourceScalewayObjectBucketDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {

0 commit comments

Comments
 (0)