Creating a Kinesis Firehose Stream in Serverless YAML with IamRoleLambdaExecution Role

Is there any way of creating a Kinesis Firehose stream in the serverless.yaml and associated the service’s role with the stream? I am currently attempting to create a Firehose Stream in resources (where myBucket is an existing S3 bucket):

resources:
  Resources:
    myFirehose:
      Type: AWS::KinesisFirehose::DeliveryStream
      Properties:
        DeliveryStreamName: myFirehose
        S3DestinationConfiguration:
          BucketARN:
            Fn::Sub: arn:aws:s3:::myBucket
          BufferingHints:
            IntervalInSeconds: 300
            SizeInMBs: 5 
          CompressionFormat: UNCOMPRESSED
          Prefix: category/
          RoleARN: 
            Fn::GetAtt: [IamRoleLambdaExecution, Arn]

In provider, I added the following iamRoleStatements

provider:
  name: aws
  runtime: python2.7
  stage: ${{opt:stage, env:STAGE, self:custom.defaults.stage}}
  region: ${{opt:region, env:AWS_DEFAULT_REGION, self:custom.defaults.region}}
  memorySize: 256
  # NOTE: by default AWS variables like ${saml:sub} use same format as
  # Serverless variables like ${self:custom.prefix} We use variableSyntax here
  # to change serverless vars to look instead like ${{self:custom.prefix}}
  variableSyntax: '\${{([\s\S]+?)}}'
  iamRoleStatements:
    - Effect: Allow
      Resource:
        Fn::Sub: arn:aws:s3:::*
      Action: 's3:*'
    - Effect: Allow
      Resource:
        Fn::Sub: arn:aws:firehose:${AWS::Region}:${AWS::AccountId}:deliverystream/*
      Action: 'firehose:*'
    - Effect: Allow
      Resource: 
        Fn::Sub: arn:aws:iam::${AWS::AccountId}:role/${{self:service}}-${{self:provider.stage}}-${AWS::Region}-lambdaRole
      Action: 'sts:AssumeRole'
      Condition:
        StringEquals:
          sts:ExternalId: ${AWS::AccountId}

However, when I try to deploy, I get a ‘Firehose is unable to assume role’ error. Am I missing any iamRoleStatements?

Check the output of a sls package command (i.e. the generated template files), and confirm that the role statements are being generated as you expect. You’ve done the right thing by overriding the variableSyntax, but best to be sure (alternatively you can inspect the function role you have already deployed as part of your testing).

I haven’t used Firehose personally (it’s not in ap-southeast-2 yet), but you might need to have a trust relationship with the Firehose service principal? As per these docs. Usually you would create a separate IAM role (in your resources section) for it to use i.e. that would have access to the S3 bucket, etc.

The firehose resource arn is incorrect.
The correct way is as below:

- Effect: Allow
  Action:
    - firehose:*
  Resource: 
    - "*"

I know this is an old thread, but Google leads here so I’m replying for other people.

The reason the role assignment is failing is because it’s trying to assign the default lambda role to the Firehose, and the permissions on that role are not set up for assignment. Serverless Framework does not expose the AssumeRolePolicyDocument on the default role, so you have to create a new role specifically for your Firehose and then assign it.

There might be an easier way to do this, but the example below works.

resources:
  Resources:
    FirehoseRole:
      Type: AWS::IAM::Role
      Properties:
        RoleName: ${self:service}-${self:provider.stage}-FirehoseRole
        AssumeRolePolicyDocument:
          Version: '2012-10-17'
          Statement:
            - Effect: Allow
              Principal:
                Service:
                  - firehose.amazonaws.com
              Action: sts:AssumeRole
        Policies:
          - PolicyName: root
            PolicyDocument:
              Version: '2012-10-17'
              Statement:
                - Effect: Allow
                  Action: s3:*
                  Resource:
                    Fn::Sub: arn:aws:s3:::${self:service}-${self:provider.stage}-data
    MyFirehose:
      Type: AWS::KinesisFirehose::DeliveryStream
      Properties:
        DeliveryStreamName: ${self:service}-${self:provider.stage}-MyFirehose
        S3DestinationConfiguration:
          BucketARN:
            Fn::Sub: arn:aws:s3:::${self:service}-${self:provider.stage}-data
          BufferingHints:
            IntervalInSeconds: 300
            SizeInMBs: 5
          CompressionFormat: UNCOMPRESSED
          RoleARN:
            Fn::GetAtt: [FirehoseRole, Arn]
1 Like