Skip to content

Commit 0b9d8d9

Browse files
committed
fix: Adding a lot more nil checking
1 parent 1c12f36 commit 0b9d8d9

1 file changed

Lines changed: 80 additions & 13 deletions

File tree

internal/remotestate/backend/s3/client.go

Lines changed: 80 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,11 @@ func NewClient(ctx context.Context, l log.Logger, config *ExtendedRemoteStateCon
107107
// CreateS3BucketIfNecessary prompts the user to create the given bucket if it doesn't already exist and if the user
108108
// confirms, creates the bucket and enables versioning for it.
109109
func (client *Client) CreateS3BucketIfNecessary(ctx context.Context, l log.Logger, bucketName string, opts *options.TerragruntOptions) error {
110-
cfg := &client.RemoteStateConfigS3
110+
if client.ExtendedRemoteStateConfigS3 == nil {
111+
return errors.Errorf("client configuration is nil - cannot create S3 bucket if necessary")
112+
}
113+
114+
cfg := &client.ExtendedRemoteStateConfigS3.RemoteStateConfigS3
111115

112116
if exists, err := client.DoesS3BucketExistWithLogging(ctx, l, cfg.Bucket); err != nil || exists {
113117
return err
@@ -252,9 +256,13 @@ func (client *Client) UpdateS3BucketIfNecessary(ctx context.Context, l log.Logge
252256

253257
// configureAccessLogBucket - configure access log bucket.
254258
func (client *Client) configureAccessLogBucket(ctx context.Context, l log.Logger, opts *options.TerragruntOptions) error {
255-
cfg := &client.RemoteStateConfigS3
259+
if client.ExtendedRemoteStateConfigS3 == nil {
260+
return errors.Errorf("client configuration is nil - cannot configure access log bucket")
261+
}
256262

257-
l.Debugf("Enabling bucket-wide Access Logging on AWS S3 bucket %s - using as TargetBucket %s", client.RemoteStateConfigS3.Bucket, client.AccessLoggingBucketName)
263+
cfg := &client.ExtendedRemoteStateConfigS3.RemoteStateConfigS3
264+
265+
l.Debugf("Enabling bucket-wide Access Logging on AWS S3 bucket %s - using as TargetBucket %s", cfg.Bucket, client.AccessLoggingBucketName)
258266

259267
if err := client.CreateLogsS3BucketIfNecessary(ctx, l, client.AccessLoggingBucketName, opts); err != nil {
260268
l.Errorf("Could not create logs bucket %s for AWS S3 bucket %s\n%s", client.AccessLoggingBucketName, cfg.Bucket, err.Error())
@@ -435,7 +443,11 @@ func (client *Client) CheckIfVersioningEnabled(ctx context.Context, l log.Logger
435443

436444
// CreateS3BucketWithVersioningSSEncryptionAndAccessLogging creates the given S3 bucket and enable versioning for it.
437445
func (client *Client) CreateS3BucketWithVersioningSSEncryptionAndAccessLogging(ctx context.Context, l log.Logger, opts *options.TerragruntOptions) error {
438-
cfg := &client.RemoteStateConfigS3
446+
if client.ExtendedRemoteStateConfigS3 == nil {
447+
return errors.Errorf("client configuration is nil - cannot create S3 bucket")
448+
}
449+
450+
cfg := &client.ExtendedRemoteStateConfigS3.RemoteStateConfigS3
439451

440452
l.Debugf("Create S3 bucket %s with versioning, SSE encryption, and access logging.", cfg.Bucket)
441453

@@ -565,7 +577,11 @@ func (client *Client) TagS3BucketAccessLogging(ctx context.Context, l log.Logger
565577

566578
// TagS3Bucket tags the S3 bucket with the tags specified in the config.
567579
func (client *Client) TagS3Bucket(ctx context.Context, l log.Logger) error {
568-
cfg := &client.RemoteStateConfigS3
580+
if client.ExtendedRemoteStateConfigS3 == nil {
581+
return errors.Errorf("client configuration is nil - cannot tag S3 bucket")
582+
}
583+
584+
cfg := &client.ExtendedRemoteStateConfigS3.RemoteStateConfigS3
569585

570586
if len(client.S3BucketTags) == 0 {
571587
l.Debugf("No tags to apply to S3 bucket %s", cfg.Bucket)
@@ -612,7 +628,11 @@ func convertTags(tags map[string]string) []types.Tag {
612628
// AWS is eventually consistent, so after creating an S3 bucket, this method can be used to wait until the information
613629
// about that S3 bucket has propagated everywhere.
614630
func (client *Client) WaitUntilS3BucketExists(ctx context.Context, l log.Logger) error {
615-
cfg := &client.RemoteStateConfigS3
631+
if client.ExtendedRemoteStateConfigS3 == nil {
632+
return errors.Errorf("client configuration is nil - cannot wait for S3 bucket")
633+
}
634+
635+
cfg := &client.ExtendedRemoteStateConfigS3.RemoteStateConfigS3
616636

617637
l.Debugf("Waiting for bucket %s to be created", cfg.Bucket)
618638

@@ -634,6 +654,10 @@ func (client *Client) WaitUntilS3BucketExists(ctx context.Context, l log.Logger)
634654

635655
// CreateS3Bucket creates the S3 bucket specified in the given config.
636656
func (client *Client) CreateS3Bucket(ctx context.Context, l log.Logger, bucket string) error {
657+
if client.s3Client == nil {
658+
return errors.Errorf("S3 client is nil - cannot create S3 bucket %s", bucket)
659+
}
660+
637661
l.Debugf("Creating S3 bucket %s", bucket)
638662

639663
input := &s3.CreateBucketInput{
@@ -684,18 +708,42 @@ func isBucketErrorRetriable(err error) bool {
684708

685709
// EnableRootAccesstoS3Bucket adds a policy to allow root access to the bucket.
686710
func (client *Client) EnableRootAccesstoS3Bucket(ctx context.Context, l log.Logger) error {
687-
bucket := client.RemoteStateConfigS3.Bucket
711+
if client.ExtendedRemoteStateConfigS3 == nil {
712+
return errors.Errorf("client configuration is nil - cannot enable root access to S3 bucket")
713+
}
714+
715+
if client.s3Client == nil {
716+
return errors.Errorf("S3 client is nil - cannot enable root access to S3 bucket")
717+
}
718+
719+
// Access bucket name safely through defensive checking
720+
config := client.ExtendedRemoteStateConfigS3
721+
bucket := config.RemoteStateConfigS3.Bucket
722+
if bucket == "" {
723+
return errors.Errorf("S3 bucket name is empty - cannot enable root access to S3 bucket")
724+
}
725+
688726
l.Debugf("Enabling root access to S3 bucket %s", bucket)
689727

728+
if client.awsConfig.Region == "" {
729+
return errors.Errorf("AWS config region is empty - cannot enable root access to S3 bucket %s", bucket)
730+
}
731+
690732
accountID, err := awshelper.GetAWSAccountID(ctx, client.awsConfig)
691733
if err != nil {
692734
return errors.Errorf("error getting AWS account ID %s for bucket %s: %w", accountID, bucket, err)
693735
}
736+
if accountID == "" {
737+
return errors.Errorf("AWS account ID is empty - cannot enable root access to S3 bucket %s", bucket)
738+
}
694739

695740
partition, err := awshelper.GetAWSPartition(ctx, client.awsConfig)
696741
if err != nil {
697742
return errors.Errorf("error getting AWS partition %s for bucket %s: %w", partition, bucket, err)
698743
}
744+
if partition == "" {
745+
return errors.Errorf("AWS partition is empty - cannot enable root access to S3 bucket %s", bucket)
746+
}
699747

700748
var policyInBucket awshelper.Policy
701749

@@ -708,7 +756,7 @@ func (client *Client) EnableRootAccesstoS3Bucket(ctx context.Context, l log.Logg
708756
l.Debugf("Policy not exists for bucket %s", bucket)
709757
}
710758

711-
if policyOutput.Policy != nil {
759+
if policyOutput != nil && policyOutput.Policy != nil {
712760
l.Debugf("Policy already exists for bucket %s", bucket)
713761

714762
policyInBucket, err = awshelper.UnmarshalPolicy(*policyOutput.Policy)
@@ -717,10 +765,13 @@ func (client *Client) EnableRootAccesstoS3Bucket(ctx context.Context, l log.Logg
717765
}
718766
}
719767

720-
for _, statement := range policyInBucket.Statement {
721-
if statement.Sid == SidRootPolicy {
722-
l.Debugf("Policy for RootAccess already exists for bucket %s", bucket)
723-
return nil
768+
// Safely iterate over statements only if they exist
769+
if policyInBucket.Statement != nil {
770+
for _, statement := range policyInBucket.Statement {
771+
if statement.Sid == SidRootPolicy {
772+
l.Debugf("Policy for RootAccess already exists for bucket %s", bucket)
773+
return nil
774+
}
724775
}
725776
}
726777

@@ -854,6 +905,10 @@ func (client *Client) EnablePublicAccessBlockingForS3Bucket(ctx context.Context,
854905
}
855906

856907
func (client *Client) EnableAccessLoggingForS3BucketWide(ctx context.Context, l log.Logger) error {
908+
if client.ExtendedRemoteStateConfigS3 == nil {
909+
return errors.Errorf("client configuration is nil - cannot enable access logging for S3 bucket")
910+
}
911+
857912
cfg := client.ExtendedRemoteStateConfigS3
858913
bucket := cfg.RemoteStateConfigS3.Bucket
859914
logsBucket := cfg.AccessLoggingBucketName
@@ -1091,7 +1146,7 @@ func (client *Client) DeleteS3BucketObjects(ctx context.Context, l log.Logger, b
10911146
// DeleteS3Bucket deletes the S3 bucket specified in the given config.
10921147
func (client *Client) DeleteS3Bucket(ctx context.Context, l log.Logger, bucketName string) error {
10931148
var (
1094-
cfg = &client.RemoteStateConfigS3
1149+
cfg = &client.ExtendedRemoteStateConfigS3.RemoteStateConfigS3
10951150
key = cfg.Key
10961151
bucketInput = &s3.DeleteBucketInput{Bucket: aws.String(bucketName)}
10971152
)
@@ -1183,6 +1238,12 @@ func (client *Client) DoesS3ObjectExist(ctx context.Context, bucketName, key str
11831238
}
11841239

11851240
func (client *Client) DoesS3ObjectExistWithLogging(ctx context.Context, l log.Logger, bucketName, key string) (bool, error) {
1241+
if client.s3Client == nil {
1242+
return false, errors.Errorf("S3 client is nil - cannot check if S3 bucket %s exists", bucketName)
1243+
}
1244+
1245+
l.Debugf("Checking if bucket %s exists", bucketName)
1246+
11861247
if exists, err := client.DoesS3ObjectExist(ctx, bucketName, key); err != nil || exists {
11871248
return exists, err
11881249
}
@@ -1711,6 +1772,12 @@ func (client *Client) DoesS3BucketExist(ctx context.Context, bucketName string)
17111772

17121773
// DoesS3BucketExistWithLogging checks if the S3 bucket exists and logs if not.
17131774
func (client *Client) DoesS3BucketExistWithLogging(ctx context.Context, l log.Logger, bucketName string) (bool, error) {
1775+
if client.s3Client == nil {
1776+
return false, errors.Errorf("S3 client is nil - cannot check if S3 bucket %s exists", bucketName)
1777+
}
1778+
1779+
l.Debugf("Checking if bucket %s exists", bucketName)
1780+
17141781
exists, err := client.DoesS3BucketExist(ctx, bucketName)
17151782
if err != nil || !exists {
17161783
l.Debugf("Remote state S3 bucket %s does not exist or you don't have permissions to access it.", bucketName)

0 commit comments

Comments
 (0)