Serverless-application-model: Execution Role is created although an existing Role is specified in the template

Created on 2 Jul 2019  路  14Comments  路  Source: aws/serverless-application-model

Description:

In our dev account we have a single Lambda Role for each project, created by the sys admin. In our SAM template we'd like to specify these project-specific execution roles, created by the admin, so that developers can deploy SAM apps without permissions to create IAM Roles.

We did try to deploy a dummy package configured as above, but stack creation fails with error:

API: iam:CreateRole User: arn:aws:iam::<accountId>:user/<developerAccount> is not authorized to perform: iam:CreateRole on resource: arn:aws:iam::<accountId>:role/<functionName>FunctionRole-VQZEBY7GY1P

Hence, it seems that although we have set Role: arn:aws:iam::<acccountId>:role/<project>-Lambda-Role in our SAM template, CloudFormation is attempting to generate the default Execution Basic Role.

Steps to reproduce the issue:

  1. create an IAM user ("steve") and provide him full access to CloudFormation. Make sure to manually include the (undocumented) permission to transform SAM template to CloudFormation template (arn:aws:cloudformation:<region>:aws:transform/Serverless-2016-10-31)
  1. create a Lambda Role with access to whatever resources (access to CloudWatchLogs should be provided). Let's call this "IssueRole".

  2. Initialize the default SAM app with sam-cli and add Role: <IssueRole arn>

  3. pack and deploy with "steve" credentials

Observed result:

CloudFormation attempts to create the default Lambda Basic Execution Role, and fails because "steve" hasn't been granted permissions to created IAM Roles.

Expected result:

The deployment should succeed because CloudFormation should NOT create the Lambda Basic Execution Role, as a Role has already been provided in the SAM template.

Most helpful comment

@k-hasan-19 there is an error in your template. Role should be nested under Properties.

Resources:
  EAPCompanyCRUDFunction:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: eap-company-crud/
      FunctionName: "eap-company-crud" # was in the wrong place
      Role: "arn:aws:iam::596343339730:role/LambdaS3ReadDynamoDBFull" # was in the wrong place
      Handler: app.lambda_handler
      Runtime: python3.8
      Events:
        CompanyDetails:
          Type: Api 
          Properties:
            Path: /company
            Method: get

All 14 comments

If you have supplied a Role in the SAM template, SAM should not generate an additional role. Does your template have the Role property specified for every Serverless::Function that you're using? Are you using any additional SAM features in that template?

The template we're testing with is just the hello-world template produced by sam init, with our Role specified.

Here it is:

AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: >
  sam-app

  Sample SAM Template for sam-app

# More info about Globals: https://github.com/awslabs/serverless-application-model/blob/master/docs/globals.rst
Globals:
  Function:
    Timeout: 3

Resources:
  ProjectPingFunction:
    Type: AWS::Serverless::Function
    Properties:
      Role: arn:aws:iam::<accountId>:role/<Project>-Lambda-Role
      CodeUri: ping/
      Handler: app.handler
      Runtime: nodejs10.x
      Events:
        HelloWorld:
          Type: Api 
          Properties:
            Path: /ping
            Method: get

Outputs:
  HelloWorldApi:
    Description: "API Gateway endpoint URL for Prod stage for Hello World function"
    Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/hello/"
  ProjectPingFunction:
    Description: "Hello World Lambda Function ARN"
    Value: !GetAtt ProjectPingFunction.Arn

I ran this through SAM and here is the template that is generated. It should use the exact Role that is supplied to the template. It does, however, create a few permissions that are needed to let APIGW call the Lambda function.

{
  "AWSTemplateFormatVersion": "2010-09-09", 
  "Outputs": {
    "HelloWorldApi": {
      "Description": "API Gateway endpoint URL for Prod stage for Hello World function", 
      "Value": {
        "Fn::Sub": "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/hello/"
      }
    }, 
    "ProjectPingFunction": {
      "Description": "Hello World Lambda Function ARN", 
      "Value": {
        "Fn::GetAtt": [
          "ProjectPingFunction", 
          "Arn"
        ]
      }
    }
  }, 
  "Description": "sam-app\nSample SAM Template for sam-app\n", 
  "Resources": {
    "ProjectPingFunctionHelloWorldPermissionTest": {
      "Type": "AWS::Lambda::Permission", 
      "Properties": {
        "Action": "lambda:invokeFunction", 
        "Principal": "apigateway.amazonaws.com", 
        "FunctionName": {
          "Ref": "ProjectPingFunction"
        }, 
        "SourceArn": {
          "Fn::Sub": [
            "arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${__ApiId__}/${__Stage__}/GET/ping", 
            {
              "__Stage__": "*", 
              "__ApiId__": {
                "Ref": "ServerlessRestApi"
              }
            }
          ]
        }
      }
    }, 
    "ProjectPingFunctionHelloWorldPermissionProd": {
      "Type": "AWS::Lambda::Permission", 
      "Properties": {
        "Action": "lambda:invokeFunction", 
        "Principal": "apigateway.amazonaws.com", 
        "FunctionName": {
          "Ref": "ProjectPingFunction"
        }, 
        "SourceArn": {
          "Fn::Sub": [
            "arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${__ApiId__}/${__Stage__}/GET/ping", 
            {
              "__Stage__": "Prod", 
              "__ApiId__": {
                "Ref": "ServerlessRestApi"
              }
            }
          ]
        }
      }
    }, 
    "ServerlessRestApiProdStage": {
      "Type": "AWS::ApiGateway::Stage", 
      "Properties": {
        "DeploymentId": {
          "Ref": "ServerlessRestApiDeployment4ea78aa67e"
        }, 
        "RestApiId": {
          "Ref": "ServerlessRestApi"
        }, 
        "StageName": "Prod"
      }
    }, 
    "ServerlessRestApiDeployment4ea78aa67e": {
      "Type": "AWS::ApiGateway::Deployment", 
      "Properties": {
        "RestApiId": {
          "Ref": "ServerlessRestApi"
        }, 
        "Description": "RestApi deployment id: 4ea78aa67ee6edf1d7bc9f428126a2815346545b", 
        "StageName": "Stage"
      }
    }, 
    "ProjectPingFunction": {
      "Type": "AWS::Lambda::Function", 
      "Properties": {
        "Code": {
          "S3Bucket": "bucket", 
          "S3Key": "key"
        }, 
        "Tags": [
          {
            "Value": "SAM", 
            "Key": "lambda:createdBy"
          }
        ], 
        "Handler": "app.handler", 
        "Role": "arn:aws:iam::<accountId>:role/<Project>-Lambda-Role", 
        "Timeout": 3, 
        "Runtime": "nodejs10.x"
      }
    }, 
    "ServerlessRestApi": {
      "Type": "AWS::ApiGateway::RestApi", 
      "Properties": {
        "Body": {
          "info": {
            "version": "1.0", 
            "title": {
              "Ref": "AWS::StackName"
            }
          }, 
          "paths": {
            "/ping": {
              "get": {
                "x-amazon-apigateway-integration": {
                  "httpMethod": "POST", 
                  "type": "aws_proxy", 
                  "uri": {
                    "Fn::Sub": "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${ProjectPingFunction.Arn}/invocations"
                  }
                }, 
                "responses": {}
              }
            }
          }, 
          "swagger": "2.0"
        }
      }
    }
  }
}

@keetonian thank you in advance for the support.

I'm not saying that it won't use the exact Role we supply to the template, I'm saying that although I supply the template CloudFormation attempts to generate a Role.

Could you please retry with an account which has no iam:CreateRole permissions?

EDIT: or are you saying that the issue is caused by those permissions needed by APIGW?

@39otrebla I will retry with an account without that permission

@keetonian why this is marked as more info needed? Please let me know any further information you need. We cannot use SAM if all our developers need iam:CreateRole permission in order to deploy changes, as only Cloud Administrators can have such privilege.

I just tried using SecretsManagerRDSMySQLRotationSingleUser application CFN template (not as a nested stack) passing Role attribute and it did create lambda function successfully using the custom role (it did not attempt to create a role and I am sure I don't have permission to create a role). I am really looking to use this application as a nested stack (so I don't have to provide the bucket, key etc) but currently, there is no provision to provide a role as a param to the application.

I just ran into this problem too.

Here is my template.yaml:

AWSTemplateFormatVersion: '2010-09-09'
Transform: 'AWS::Serverless-2016-10-31'
Description: A starter AWS Lambda function.
Parameters: 
    IdentityNameParameter: 
      Type: String

Resources:
  helloworldpython3:
    Type: 'AWS::Serverless::Function'
    Properties:
      Role: arn:aws:iam::{account):role/CloudCoreSvcAMISharingLambda
      Handler: lambda_function.lambda_handler
      Runtime: python3.6
      CodeUri: .
      Description: A starter AWS Lambda function.
      MemorySize: 128
      Timeout: 3

and on deploy I get an error is not authorized to perform: iam:CreateRole

@pswenson I ran the SAM translator on your provided template (switching CodeUri: . for a fake s3 url CodeUri: s3://foo/bar and I get this:

{
  "AWSTemplateFormatVersion": "2010-09-09",
  "Resources": {
    "helloworldpython3": {
      "Type": "AWS::Lambda::Function",
      "Properties": {
        "Code": {
          "S3Bucket": "foo",
          "S3Key": "bar"
        },
        "Description": "A starter AWS Lambda function.",
        "Tags": [
          {
            "Value": "SAM",
            "Key": "lambda:createdBy"
          }
        ],
        "MemorySize": 128,
        "Handler": "lambda_function.lambda_handler",
        "Role": "arn:aws:iam::{account}:role/CloudCoreSvcAMISharingLambda",
        "Timeout": 3,
        "Runtime": "python3.6"
      }
    }
  },
  "Parameters": {
    "IdentityNameParameter": {
      "Type": "String"
    }
  },
  "Description": "A starter AWS Lambda function."
}

The SAM translator is not generating a resource of type AWS::IAM::Role, so deploying the above CloudFormation template should not result in a role creation. Are you sure you attempted to deploy the exact template above and got this error? If so, where was the error specifically? Did change set creation fail and this error was the statusReason? Or did change set execution fail and this error was in the stack events? If so, for what resource?

I'm having same problem!! Here is my template:

AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: >
  eap-inneed

Globals:
  Function:
    Timeout: 3
    Environment:
      Variables:
        TABLE_NAME: inneedEap
        AWS_REGION_DYNAMODB: us-west-2


Resources:
  EAPCompanyCRUDFunction:
    Type: AWS::Serverless::Function
    FunctionName: "eap-company-crud"
    Role: "arn:aws:iam::596343339730:role/LambdaS3ReadDynamoDBFull"
    Properties:
      CodeUri: eap-company-crud/
      Handler: app.lambda_handler
      Runtime: python3.8
      Events:
        CompanyDetails:
          Type: Api 
          Properties:
            Path: /company
            Method: get

Outputs:
  # ServerlessRestApi is an implicit API created out of Events key under Serverless::Function
  # Find out more about other implicit resources you can reference within SAM
  # https://github.com/awslabs/serverless-application-model/blob/master/docs/internals/generated_resources.rst#api
  EAPApi:
    Description: "API Gateway endpoint URL for Prod stage for EAP functions"
    Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/company/"

And here is sam deploy --guided output:

image

Why its trying to create a Role for the function where I've already given it a Role Arn??
I'm running SAM CLI, version 0.40.0 on cloud9.

@k-hasan-19 there is an error in your template. Role should be nested under Properties.

Resources:
  EAPCompanyCRUDFunction:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: eap-company-crud/
      FunctionName: "eap-company-crud" # was in the wrong place
      Role: "arn:aws:iam::596343339730:role/LambdaS3ReadDynamoDBFull" # was in the wrong place
      Handler: app.lambda_handler
      Runtime: python3.8
      Events:
        CompanyDetails:
          Type: Api 
          Properties:
            Path: /company
            Method: get

@keetonian Sorry! My mistake. Must be lack of late night coffee!!
Thanks for your quick response.

I was facing exactly the same issue, but I have forgot to run sam build after put role entry nested to Properties. My bad.

Reading through the comments here, adding a Role Property will not produce a role when translated. If you are seeing this and using SAM CLI things to check:

  • Are you using sam build? Did you rebuild the application if you have updated code or the template?
  • When using sam package and sam build, do not provide --template|template-file to ensure the recently built application gets picked up. If you provide --template you are overriding the command to use that template.

Closing this as no issue.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

kwcrook picture kwcrook  路  3Comments

charsleysa picture charsleysa  路  3Comments

polovi picture polovi  路  3Comments

feinstein picture feinstein  路  3Comments

MaxVynohradov picture MaxVynohradov  路  3Comments