Search code examples
amazon-web-servicesamazon-s3aws-cloudformationgroup-policyassume-role

Kinesis Firehose Delivery Stream is unable to assume role while using cloudformation


I am writing a cloudformation template that creates a Kinesis Firehose Delivery Stream and sends the data to S3 bucket. The source stream is a Kinesis Steam. It creates the s3 bucket, Policies, and roles but when it tries to create the Kinesis Firehose Delivery Stream, it fails saying unable to assume role

After some research i found that Delivery should not be created using the root account. I tried creating a new user but it still gave me the same error.

# creates the Kinesis Stream
KinesisStream:
  Type: AWS::Kinesis::Stream
  Properties:
    Name: HealthApp        
    RetentionPeriodHours: 24
    ShardCount: 8

# creates the firehose delivery stream   
KinesisFirehoseDeliveryStream:
  Type: AWS::KinesisFirehose::DeliveryStream
  Properties:
    DeliveryStreamName: HealthAppFirehose   
    DeliveryStreamType: KinesisStreamAsSource
    KinesisStreamSourceConfiguration:
    KinesisStreamARN:
      Fn::GetAtt:
      - KinesisStream
      - Arn
    RoleARN:
      Fn::GetAtt:
      - FirehoseDeliveryIAMRole
      - Arn

  S3DestinationConfiguration:
    BucketARN: !GetAtt MyS3Bucket.Arn
    Prefix: cloudformation-test/kinesis-fh
    BufferingHints:
       IntervalInSeconds: 60
       SizeInMBs: 100
    CloudWatchLoggingOptions:
      Enabled: 'false'
    CompressionFormat: UNCOMPRESSED
    RoleARN:
      Fn::GetAtt:
      - FirehoseDeliveryIAMRole
      - Arn
DependsOn:
- FirehoseDeliveryIAMPolicy


FirehoseDeliveryIAMRole:
 Type: AWS::IAM::Role
 Properties:
  AssumeRolePolicyDocument:
    Version: '2012-10-17'
    Statement:

      Effect: Allow
      Principal:
        Service: firehose.amazonaws.com
      Action: sts:AssumeRole
      Condition:
        StringEquals:
          sts:ExternalId: ACCOUNT_NUMBER


FirehoseDeliveryIAMPolicy:
  Type: AWS::IAM::Policy
  Properties:
  PolicyName: HealthAppPolicy

  PolicyDocument:
    Version: '2012-10-17'
    Statement:
    - Effect: Allow
      Action:
      - s3:AbortMultipartUpload
      - s3:GetBucketLocation
      - s3:GetObject
      - s3:ListBucket
      - s3:ListBucketMultipartUploads
      - s3:PutObject
      Resource:
      - arn:aws:s3:::health-app-bucket/cloudformation-test/kinesis-fh*
    - Effect: Allow
      Action:
      - kinesis:DescribeStream
      - kinesis:GetShardIterator
      - kinesis:GetRecords
      Resource:
        Fn::GetAtt:
        - KinesisStream
        - Arn
  Roles:
  - Ref: FirehoseDeliveryIAMRole
DependsOn:
- KinesisStream

Outputs:
  kinesisStreamArn:
    Description: Kinesis Stream ARN
    Value:
      Fn::GetAtt:
       - KinesisStream
       - Arn
  firehoseDeliveryStreamArn:
  Description: Firehose Delivery Stream ARN
  Value:
    Fn::GetAtt:
    - KinesisFirehoseDeliveryStream
    - Arn
firehoseDeliveryRoleArn:
  Description: Firehose Delivery Role ARN
  Value:
    Fn::GetAtt:
    - FirehoseDeliveryIAMRole
    - Arn

I want the delivery stream to succesfully be created. Any help would be appreciated.

Thank you


Solution

  • Two things to check for:

    1. I wonder if ACCOUNT_NUMBER is being set and interpreted properly. You can check this by removing the entire Condition statement as a test. As a test (not for production) remove the following and see if it works
          Condition:
            StringEquals:
              sts:ExternalId: ACCOUNT_NUMBER
    
    1. Does the user you created have access to create IAM policies and roles? You said

      I tried creating a new user but it still gave me the same error

    Again, for testing/debugging only you can give this user the following policy and see if it works

    {
      "Version": "2012-10-17",
      "Statement": {
        "Effect": "Allow",
        "Action": "iam:*",
        "Resource": "*"
      }
    }
    

    If that is the problem this use this to determine the actual polices needed for your IAM User that is executing the CloudFormation