Skip to content
This repository has been archived by the owner on Aug 16, 2022. It is now read-only.

Bugfix/s3 bucket errors #131

Merged
merged 3 commits into from
Aug 3, 2021
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
252 changes: 166 additions & 86 deletions resources/s3_buckets.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import (
"encoding/json"
"errors"

"github.com/aws/aws-sdk-go-v2/aws"

"github.com/aws/aws-sdk-go-v2/service/s3"
"github.com/aws/aws-sdk-go-v2/service/s3/types"
smithy "github.com/aws/smithy-go"
Expand Down Expand Up @@ -454,7 +456,6 @@ func resolveS3BucketsAttributes(ctx context.Context, meta schema.ClientMeta, res
}
return err
}
svc := meta.(*client.Client).Services().S3
bucketRegion := "us-east-1"
if output != "" {
// This is a weird corner case by AWS API https://github.com/aws/aws-sdk-net/issues/323#issuecomment-196584538
Expand All @@ -463,105 +464,28 @@ func resolveS3BucketsAttributes(ctx context.Context, meta schema.ClientMeta, res
if err := resource.Set("region", bucketRegion); err != nil {
return err
}

loggingOutput, err := svc.GetBucketLogging(ctx, &s3.GetBucketLoggingInput{Bucket: r.Name}, func(options *s3.Options) {
options.Region = bucketRegion
})
if err != nil {
if err := resolveBucketLogging(ctx, meta, resource, *r.Name, bucketRegion); err != nil {
return err
}
if loggingOutput.LoggingEnabled != nil {
if err := resource.Set("logging_target_bucket", loggingOutput.LoggingEnabled.TargetBucket); err != nil {
return err
}
if err := resource.Set("logging_target_prefix", loggingOutput.LoggingEnabled.TargetPrefix); err != nil {
return err
}
}

policyOutput, err := svc.GetBucketPolicy(ctx, &s3.GetBucketPolicyInput{Bucket: r.Name}, func(options *s3.Options) {
options.Region = bucketRegion
})
if err != nil && !(errors.As(err, &ae) && ae.ErrorCode() == "NoSuchBucketPolicy") {
if err := resolveBucketPolicy(ctx, meta, resource, *r.Name, bucketRegion); err != nil {
return err
}
if policyOutput != nil {
if err := resource.Set("policy", policyOutput.Policy); err != nil {
return err
}
}

versioningOutput, err := svc.GetBucketVersioning(ctx, &s3.GetBucketVersioningInput{Bucket: r.Name}, func(options *s3.Options) {
options.Region = bucketRegion
})
if err != nil {
if err := resolveBucketVersioning(ctx, meta, resource, *r.Name, bucketRegion); err != nil {
return err
}

if err := resource.Set("versioning_status", versioningOutput.Status); err != nil {
return err
}
if err := resource.Set("versioning_mfa_delete", versioningOutput.MFADelete); err != nil {
if err := resolveBucketPublicAccessBlock(ctx, meta, resource, *r.Name, bucketRegion); err != nil {
return err
}

publicAccessOutput, err := svc.GetPublicAccessBlock(ctx, &s3.GetPublicAccessBlockInput{Bucket: r.Name}, func(options *s3.Options) {
options.Region = bucketRegion
})
if err != nil {
// If we received any error other than NoSuchPublicAccessBlockConfiguration, we return and error
if errors.As(err, &ae) && ae.ErrorCode() != "NoSuchPublicAccessBlockConfiguration" {
return err
}
} else {
if err := resource.Set("block_public_acls", publicAccessOutput.PublicAccessBlockConfiguration.BlockPublicAcls); err != nil {
return err
}
if err := resource.Set("block_public_policy", publicAccessOutput.PublicAccessBlockConfiguration.BlockPublicPolicy); err != nil {
return err
}
if err := resource.Set("ignore_public_acls", publicAccessOutput.PublicAccessBlockConfiguration.IgnorePublicAcls); err != nil {
return err
}
if err := resource.Set("restrict_public_buckets", publicAccessOutput.PublicAccessBlockConfiguration.RestrictPublicBuckets); err != nil {
return err
}
}

replicationOutput, err := svc.GetBucketReplication(ctx, &s3.GetBucketReplicationInput{Bucket: r.Name}, func(options *s3.Options) {
options.Region = bucketRegion
})
if err != nil {
// If we received any error other than ReplicationConfigurationNotFoundError, we return and error
if errors.As(err, &ae) && ae.ErrorCode() != "ReplicationConfigurationNotFoundError" {
return err
}
} else {
if replicationOutput.ReplicationConfiguration != nil {
if err := resource.Set("replication_role", replicationOutput.ReplicationConfiguration.Role); err != nil {
return err
}
// We set this here for fetchReplicationRules to get and insert
resource.Item.(*WrappedBucket).ReplicationRules = replicationOutput.ReplicationConfiguration.Rules
}
if err := resolveBucketReplication(ctx, meta, resource, *r.Name, bucketRegion); err != nil {
return err
}

taggingOutput, err := svc.GetBucketTagging(ctx, &s3.GetBucketTaggingInput{Bucket: r.Name}, func(options *s3.Options) {
options.Region = bucketRegion
})
if err != nil {
if !errors.As(err, &ae) || ae.ErrorCode() != "NoSuchTagSet" {
return err
}
}
if taggingOutput != nil {
tags := make(map[string]*string, len(taggingOutput.TagSet))
for _, t := range taggingOutput.TagSet {
tags[*t.Key] = t.Value
}
if err := resource.Set("tags", tags); err != nil {
return err
}
if err := resolveBucketTagging(ctx, meta, resource, *r.Name, bucketRegion); err != nil {
return err
}
return nil
}
Expand Down Expand Up @@ -685,3 +609,159 @@ type WrappedBucket struct {
ReplicationRole *string
ReplicationRules []types.ReplicationRule
}

func resolveBucketLogging(ctx context.Context, meta schema.ClientMeta, resource *schema.Resource, bucketName, bucketRegion string) error {
svc := meta.(*client.Client).Services().S3
loggingOutput, err := svc.GetBucketLogging(ctx, &s3.GetBucketLoggingInput{Bucket: aws.String(bucketName)}, func(options *s3.Options) {
options.Region = bucketRegion
})
if err != nil {
if client.IgnoreAccessDeniedServiceDisabled(err) {
meta.Logger().Warn("received access denied on GetBucketLogging", "bucket", bucketName, "err", err)
return nil
}
return err
}
if loggingOutput.LoggingEnabled == nil {
return nil
}
if err := resource.Set("logging_target_bucket", loggingOutput.LoggingEnabled.TargetBucket); err != nil {
return err
}
if err := resource.Set("logging_target_prefix", loggingOutput.LoggingEnabled.TargetPrefix); err != nil {
return err
}
return nil
}

func resolveBucketPolicy(ctx context.Context, meta schema.ClientMeta, resource *schema.Resource, bucketName, bucketRegion string) error {
svc := meta.(*client.Client).Services().S3
policyOutput, err := svc.GetBucketPolicy(ctx, &s3.GetBucketPolicyInput{Bucket: aws.String(bucketName)}, func(options *s3.Options) {
options.Region = bucketRegion
})
// check if we got an error but its access denied we can continue
if err != nil {
if client.IgnoreAccessDeniedServiceDisabled(err) {
meta.Logger().Warn("received access denied on GetBucketPolicy", "bucket", bucketName, "err", err)
return nil
}
// if we got an error and its not a NoSuchBucketError, return err
var ae smithy.APIError
if errors.As(err, &ae) && ae.ErrorCode() == "NoSuchBucketPolicy" {
return nil
}
return err
}
if policyOutput == nil {
return nil
}
return resource.Set("policy", policyOutput.Policy)
}

func resolveBucketVersioning(ctx context.Context, meta schema.ClientMeta, resource *schema.Resource, bucketName, bucketRegion string) error {
svc := meta.(*client.Client).Services().S3
versioningOutput, err := svc.GetBucketVersioning(ctx, &s3.GetBucketVersioningInput{Bucket: aws.String(bucketName)}, func(options *s3.Options) {
options.Region = bucketRegion
})
if err != nil {
if client.IgnoreAccessDeniedServiceDisabled(err) {
meta.Logger().Warn("received access denied on GetBucketVersioning", "bucket", bucketName, "err", err)
return nil
}
return err
}
if err := resource.Set("versioning_status", versioningOutput.Status); err != nil {
return err
}
if err := resource.Set("versioning_mfa_delete", versioningOutput.MFADelete); err != nil {
return err
}
return nil
}

func resolveBucketPublicAccessBlock(ctx context.Context, meta schema.ClientMeta, resource *schema.Resource, bucketName, bucketRegion string) error {
svc := meta.(*client.Client).Services().S3
publicAccessOutput, err := svc.GetPublicAccessBlock(ctx, &s3.GetPublicAccessBlockInput{Bucket: aws.String(bucketName)}, func(options *s3.Options) {
options.Region = bucketRegion
})
var ae smithy.APIError
if err != nil {
if client.IgnoreAccessDeniedServiceDisabled(err) {
meta.Logger().Warn("received access denied on GetPublicAccessBlock", "bucket", bucketName, "err", err)
return nil
}
// If we received any error other than NoSuchPublicAccessBlockConfiguration, we return and error
if errors.As(err, &ae) && ae.ErrorCode() == "NoSuchPublicAccessBlockConfiguration" {
return nil
}
return err
}
if err := resource.Set("block_public_acls", publicAccessOutput.PublicAccessBlockConfiguration.BlockPublicAcls); err != nil {
return err
}
if err := resource.Set("block_public_policy", publicAccessOutput.PublicAccessBlockConfiguration.BlockPublicPolicy); err != nil {
return err
}
if err := resource.Set("ignore_public_acls", publicAccessOutput.PublicAccessBlockConfiguration.IgnorePublicAcls); err != nil {
return err
}
if err := resource.Set("restrict_public_buckets", publicAccessOutput.PublicAccessBlockConfiguration.RestrictPublicBuckets); err != nil {
return err
}
return nil
}

func resolveBucketReplication(ctx context.Context, meta schema.ClientMeta, resource *schema.Resource, bucketName, bucketRegion string) error {
svc := meta.(*client.Client).Services().S3
replicationOutput, err := svc.GetBucketReplication(ctx, &s3.GetBucketReplicationInput{Bucket: aws.String(bucketName)}, func(options *s3.Options) {
options.Region = bucketRegion
})

if err != nil {
if client.IgnoreAccessDeniedServiceDisabled(err) {
meta.Logger().Warn("received access denied on getBucketReplication", "bucket", bucketName, "err", err)
return nil
}
// If we received any error other than ReplicationConfigurationNotFoundError, we return and error
var ae smithy.APIError
if errors.As(err, &ae) && ae.ErrorCode() == "ReplicationConfigurationNotFoundError" {
return nil
}
return err
}
if replicationOutput.ReplicationConfiguration == nil {
return nil
}
if err := resource.Set("replication_role", replicationOutput.ReplicationConfiguration.Role); err != nil {
return err
}
// We set this here for fetchReplicationRules to get and insert
resource.Item.(*WrappedBucket).ReplicationRules = replicationOutput.ReplicationConfiguration.Rules
return nil
}

func resolveBucketTagging(ctx context.Context, meta schema.ClientMeta, resource *schema.Resource, bucketName, bucketRegion string) error {
svc := meta.(*client.Client).Services().S3
taggingOutput, err := svc.GetBucketTagging(ctx, &s3.GetBucketTaggingInput{Bucket: aws.String(bucketName)}, func(options *s3.Options) {
options.Region = bucketRegion
})
if err != nil {
if client.IgnoreAccessDeniedServiceDisabled(err) {
meta.Logger().Warn("received access denied on getBucketReplication", "bucket", bucketName, "err", err)
return nil
}
var ae smithy.APIError
if errors.As(err, &ae) && ae.ErrorCode() == "NoSuchTagSet" {
return nil
}
return err
}
if taggingOutput == nil {
return nil
}
tags := make(map[string]*string, len(taggingOutput.TagSet))
for _, t := range taggingOutput.TagSet {
tags[*t.Key] = t.Value
}
return resource.Set("tags", tags)
}