aws-cloudformation / rain

A development workflow tool for working with AWS CloudFormation.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Nil pointer for existing parameter value

pnc opened this issue · comments

Approximate steps to reproduce:

  1. Deploy the following stack, setting a value like arn:aws:iam::xxx:role/phil-axle-ReplicationRole-VwMQmmcofdJ for the single parameter, which works normally.
  2. Attempt to update the stack (I changed the lifecycle duration) using rain:
› ./rain --version
Rain v1.8.3 darwin/arm64
› rain deploy backup-bucket.yml phil-axle-backup
Enter a value for parameter 'SourceRoleArn' "The ARN of the IAM role from the source account that will perform the replication." (existing value: arn:aws:iam::xxx:role/phil-axle-ReplicationRole-VwMQmmcofdJ)

At this point I press enter without entering a value, intending to make it use the current value.

Rain shows some progess information and then exits with this error:

runtime error: invalid memory address or nil pointer dereference

Expected results: Rain uses the existing value (in parens) as the value (common UNIX tool UX, see adduser for example), or deploys the stack with the value blanked out, but either way doesn't crash.

here's the backtrace lldb gives:

› lldb rain deploy backup-bucket.yml phil-axle-backup
(lldb) target create "rain"
Current executable set to '/opt/homebrew/bin/rain' (arm64).
(lldb) settings set -- target.run-args  "deploy" "backup-bucket.yml" "phil-axle-backup"
(lldb) run
Process 86583 launched: '/opt/homebrew/bin/rain' (arm64)
Enter a value for parameter 'SourceRoleArn' "The ARN of the IAM role from the source account that will perform the replication." (existing value: arn:aws:iam::403345046096:role/phil-axle-ReplicationRole-VwMQmmcofdJj): 
Creating change set .· Creating change set .· Creating change set  .˙Creating change set ˙ ·Creating change set ·˙.Process 86583 stopped
* thread #14, stop reason = EXC_BAD_ACCESS (code=1, address=0x0)
    frame #0: 0x00000001007ce324 rain`github.com/aws-cloudformation/rain/internal/aws/cfn.CreateChangeSet + 2308
rain`github.com/aws-cloudformation/rain/internal/aws/cfn.CreateChangeSet:
->  0x1007ce324 <+2308>: ldr    x0, [x3]
    0x1007ce328 <+2312>: ldr    x1, [x3, #0x8]
    0x1007ce32c <+2316>: bl     0x10000dd50               ; runtime.convTstring
    0x1007ce330 <+2320>: adrp   x2, 2978
Target 0: (rain) stopped.

This advice from https://go.dev/doc/gdb also appears to apply to lldb on macos:

As of Go 1.11, debug information is compressed by default. Older versions of gdb, such as the one available by default on MacOS, do not understand the compression. You can generate uncompressed debug information by using go build -ldflags=-compressdwarf=false. (For convenience you can put the -ldflags option in the GOFLAGS environment variable so that you don't have to specify it each time.)

I cloned 2fe3ddc and ran:

phil@Neutrino ~/rain on main› go build -ldflags=-compressdwarf=false ./cmd/rain
› lldb -- ./rain deploy ../infrastructure/backup-bucket.yml phil-axle-backup
(lldb) target create "./rain"
Current executable set to '/Users/phil/rain/rain' (arm64).
(lldb) settings set -- target.run-args  "deploy" "../infrastructure/backup-bucket.yml" "phil-axle-backup"
(lldb) run
Process 89594 launched: '/Users/phil/rain/rain' (arm64)
Enter a value for parameter 'SourceRoleArn' "The ARN of the IAM role from the source account that will perform the replication." (existing value: arn:aws:iam::403345046096:role/phil-axle-ReplicationRole-VwMQmmcofdJj): 
Creating change set ˙ ·Creating change set ˙ ·Creating change set ·˙.Process 89594 stopped
* thread #11, stop reason = EXC_BAD_ACCESS (code=1, address=0x0)
    frame #0: 0x00000001007ce1b4 rain`github.com/aws-cloudformation/rain/internal/aws/cfn.CreateChangeSet at cfn.go:472
   469 			config.Debugf("About to create changeset with body:\n%s", templateBody)
   470 			for _, param := range params {
   471 				config.Debugf("Parameter Key: %s, Value: %s",
-> 472 					*param.ParameterKey, *param.ParameterValue)
   473 			}
   474 		}
   475 	
Target 0: (rain) stopped.

Template:

AWSTemplateFormatVersion: '2010-09-09'
Description: description

Parameters:
  SourceRoleArn:
    Description: The ARN of the IAM role from the source account that will perform the replication.
    Type: String
  ObjectLockMode:
    Description: |
      Set this to `GOVERNANCE` initially to allow overriding the object lock in case something goes wrong.

      Once you set this to `COMPLIANCE`, the S3 object lock mode is changed to compliance mode and
      locked objects will be retained for their full duration. This cannot be overridden or changed
      by anyone, including AWS, so make sure the retention isn't something undesirable like 7 years.

      See https://docs.aws.amazon.com/AmazonS3/latest/userguide/object-lock.html#object-lock-retention-modes
    Type: String
    Default: GOVERNANCE
    AllowedValues:
      - GOVERNANCE
      - COMPLIANCE

Resources:
  Bucket:
    Type: 'AWS::S3::Bucket'
    DeletionPolicy: Retain
    Properties:
      AccessControl: Private
      # Versioning is best practice, and also required for replication to work
      VersioningConfiguration:
        Status: Enabled
      ObjectLockEnabled: true
      ObjectLockConfiguration:
        ObjectLockEnabled: "Enabled"
        Rule:
          DefaultRetention:
            # Governance mode can be overridden by authorized users, compliance mode cannot
            Mode: !Ref ObjectLockMode
            Days: 7
      LifecycleConfiguration:
        Rules:
          # Delete markers will be replicated from the source bucket, but in case of malicious
          # or accidental deletes, we want to keep the original objects for a period of time
          # so they can be manually restored.
          - Id: Keep deleted versions for 14 days and delete tombstones
            NoncurrentVersionExpirationInDays: 14
            ExpiredObjectDeleteMarker: true
            AbortIncompleteMultipartUpload:
                DaysAfterInitiation: 7
            Status: Enabled
      OwnershipControls:
        Rules:
          - ObjectOwnership: BucketOwnerEnforced

  ReplicaBucketPolicy:
    Type: 'AWS::S3::BucketPolicy'
    Properties:
      Bucket: !Ref Bucket
      PolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Sid: 'AllowReplicationFromSourceBucket'
            Effect: 'Allow'
            Principal:
              AWS: !Ref SourceRoleArn
            Action:
              - s3:ReplicateObject
              - s3:ReplicateDelete
              - s3:ReplicateTags
              - s3:List*
              - s3:PutBucketVersioning
              - s3:GetBucketVersioning
            Resource:
              - !Sub '${Bucket.Arn}'
              - !Sub '${Bucket.Arn}/*'

For others, I'm able to work around the crash by providing the same value (arn:aws:iam::xxx:role/phil-axle-ReplicationRole-VwMQmmcofdJ) for the parameter rather than pressing Enter.

I can reproduce this with a simple test case. Will work on a fix today.