Abhishek kumar
Abhishek kumar

Reputation: 103

Cloudformation unable to create resource policy for apigateway

The resource policy is working fine when i directly pass it to the console. Below is resource policy example :-

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": "*",
            "Action": "execute-api:Invoke",
            "Resource": "arn:aws:execute-api:us-west-2:339159142535:ooxmwl6q4e/*",
            "Condition": {
                "IpAddress": {
                    "aws:SourceIp": [
                        ""14.98.8.190/32""
                    ]
                }
            }
        }
    ]
}

Now how to create a cloudformation template for this to get created and get attached to the apigateway

I tried to create a policy but as per new policy "Principal" is depricated.

I created a role also but no help. Below is role snippet :-

{
    "AWSTemplateFormatVersion": "2010-09-09",
    "Resources": {
        "Apifirewall": {
            "Type": "AWS::IAM::Role",
            "Properties": {
                "AssumeRolePolicyDocument": {
                    "Version": "2012-10-17",
                    "Statement": [
                        {
                            "Effect": "Allow",
                            "Principal": {
                                "Service": [
                                    "apigateway.amazonaws.com"
                                ]
                            },
                            "Action": [
                                "sts:AssumeRole"
                            ]
                        }
                    ]
                },
                "Policies": [
                    {
                        "PolicyName": "Apifirewall",
                        "PolicyDocument": {
                            "Version": "2012-10-17",
                            "Statement": [
                                {
                                    "Effect": "Allow",
                                    "Action": "*",
                                    "Resource": [
                                        "arn:aws:execute-api:us-west-2:339159142535:ooxmwl6q4e/*"
                                    ],
                                    "Condition": {
                                        "IpAddress": {
                                            "aws:SourceIp": [
                                                "14.98.8.190/32"
                                            ]
                                        }
                                    }
                                }
                            ]
                        }
                    }
                ]
            }
        }
    },
    "Outputs": {
        "Apifirewall": {
            "Value": {
                "Fn::GetAtt": [
                    "Apifirewall",
                    "Arn"
                ]
            }
        }
    }
}

Upvotes: 5

Views: 11320

Answers (4)

Colm Bhandal
Colm Bhandal

Reputation: 3841

Too long for a comment. This is the transformed YAML from this answer, which a commenter pointed out can be done in CloudFormation Designer:

AWSTemplateFormatVersion: 2010-09-09
Parameters:
  AppEnv:
    Type: String
    Description: 'Application environment, for this deployment'
  DeployTag:
    Type: String
    Description: 'Distinct deployment tag ex: BLUE, GREEN'
Resources:
  LambdaExecutionRole:
    Type: 'AWS::IAM::Role'
    Properties:
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - lambda.amazonaws.com
            Action:
              - 'sts:AssumeRole'
      ManagedPolicyArns:
        - 'arn:aws:iam::aws:policy/AWSLambdaFullAccess'
  RecommenderLambda:
    Type: 'AWS::Lambda::Function'
    Properties:
      Handler: recommender_field_validation_lambda.lambda_handler
      FunctionName: recommenderlambda2
      Role: !GetAtt 
        - LambdaExecutionRole
        - Arn
      Environment:
        Variables:
          S3_BUCKET: belcorp.recommender.test
          REGION_NAME: us-west-2
          TOPIC_ARN: !ImportValue RecommenderTopicARN
          TABLE_NAME: !ImportValue recommederrequestinfo
      Code:
        S3Bucket: belcorp.recommender.lambdas
        S3Key: recommender_field_validation_lambda.zip
      Runtime: python3.6
      Timeout: 25
  LambdaPermission:
    DependsOn: RecommenderLambda
    Type: 'AWS::Lambda::Permission'
    Properties:
      Action: 'lambda:invokeFunction'
      FunctionName: recommenderlambda2
      Principal: apigateway.amazonaws.com
      SourceArn: !Join 
        - ''
        - - 'arn:aws:execute-api:'
          - !Ref 'AWS::Region'
          - ':'
          - !Ref 'AWS::AccountId'
          - ':'
          - !Ref RecommenderApi
          - /*
  RecommenderApi:
    Type: 'AWS::ApiGateway::RestApi'
    Properties:
      EndpointConfiguration:
        Types:
          - EDGE
      Description: RecommenderAPI
      Name: !Sub 'RecommenderApi-${AppEnv}-${DeployTag}'
      Policy:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal: '*'
            Action: 'execute-api:Invoke'
            Resource: !Sub 'arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:*/*'
            Condition:
              IpAddress:
                'aws:SourceIp':
                  - 14.98.8.190/32
  ApiGatewayAccount:
    Type: 'AWS::ApiGateway::Account'
    Properties:
      CloudWatchRoleArn: !ImportValue cloudwatchRole
  ApiDeployment:
    Type: 'AWS::ApiGateway::Deployment'
    DependsOn:
      - OfferPostMethod
      - OrderPostMethod
    Properties:
      RestApiId: !Ref RecommenderApi
      StageName: dev
  ProcessInput:
    Type: 'AWS::ApiGateway::Resource'
    Properties:
      RestApiId: !Ref RecommenderApi
      ParentId: !GetAtt 
        - RecommenderApi
        - RootResourceId
      PathPart: process-input
  OfferLevel:
    Type: 'AWS::ApiGateway::Resource'
    Properties:
      RestApiId: !Ref RecommenderApi
      ParentId: !Ref ProcessInput
      PathPart: offer-level
  OrderLevel:
    Type: 'AWS::ApiGateway::Resource'
    Properties:
      RestApiId: !Ref RecommenderApi
      ParentId: !Ref ProcessInput
      PathPart: order-level
  OfferPostMethod:
    DependsOn: RecommenderLambda
    Type: 'AWS::ApiGateway::Method'
    Properties:
      RestApiId: !Ref RecommenderApi
      ResourceId: !Ref OfferLevel
      HttpMethod: POST
      AuthorizationType: NONE
      Integration:
        Type: AWS_PROXY
        IntegrationHttpMethod: POST
        Uri: !Join 
          - ''
          - - 'arn:aws:apigateway:'
            - !Ref 'AWS::Region'
            - ':lambda:path/2015-03-31/functions/'
            - !GetAtt 
              - RecommenderLambda
              - Arn
            - /invocations
        IntegrationResponses:
          - StatusCode: 200
            ResponseTemplates:
              application/json: $input.json('$.body')
  OrderPostMethod:
    DependsOn: RecommenderLambda
    Type: 'AWS::ApiGateway::Method'
    Properties:
      RestApiId: !Ref RecommenderApi
      ResourceId: !Ref OrderLevel
      HttpMethod: POST
      AuthorizationType: NONE
      Integration:
        Type: AWS_PROXY
        IntegrationHttpMethod: POST
        Uri: !Join 
          - ''
          - - 'arn:aws:apigateway:'
            - !Ref 'AWS::Region'
            - ':lambda:path/2015-03-31/functions/'
            - !GetAtt 
              - RecommenderLambda
              - Arn
            - /invocations
        IntegrationResponses:
          - StatusCode: 200
            ResponseTemplates:
              application/json: $input.json('$.body')
Outputs:
  RootUrl:
    Description: Root URL of the API gateway
    Value: !Join 
      - ''
      - - 'https://'
        - !Ref RecommenderApi
        - .execute-api.
        - !Ref 'AWS::Region'
        - .amazonaws.com
  OfferUrl:
    Description: Root URL of the API gateway
    Value: !Join 
      - ''
      - - 'https://'
        - !Ref RecommenderApi
        - .execute-api.
        - !Ref 'AWS::Region'
        - .amazonaws.com
        - /dev/process-input/offer-level
  OrderUrl:
    Description: Root URL of the API gateway
    Value: !Join 
      - ''
      - - 'https://'
        - !Ref RecommenderApi
        - .execute-api.
        - !Ref 'AWS::Region'
        - .amazonaws.com
        - /dev/process-input/order-level

Upvotes: 2

Marcin
Marcin

Reputation: 238747

If you are using YAML for CloudFormation, the Policy can be in YAML. There is no need to use JSON for it. For example:

  Parameters:
    ApiAllowedIps:
      Type: CommaDelimitedList

  RestApi:
    Type: AWS::ApiGateway::RestApi
    Properties:
      ...
      Policy: 
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Action: '*'
            Principal: '*'
            Resource: '*'
            Condition:
              IpAddress:
                aws:SourceIp: !Ref ApiAllowedIps  

Upvotes: 0

Abhishek kumar
Abhishek kumar

Reputation: 103

Below is the entire CFT for api deployment with lambda integration

{
    "AWSTemplateFormatVersion": "2010-09-09",
    "Parameters": {
        "AppEnv": {
            "Type": "String",
            "Description": "Application environment, for this deployment"
        },
        "DeployTag": {
            "Type": "String",
            "Description": "Distinct deployment tag ex: BLUE, GREEN"
        }
    },
    "Resources": {
        "LambdaExecutionRole": {
            "Type": "AWS::IAM::Role",
            "Properties": {
                "AssumeRolePolicyDocument": {
                    "Version": "2012-10-17",
                    "Statement": [
                        {
                            "Effect": "Allow",
                            "Principal": {
                                "Service": [
                                    "lambda.amazonaws.com"
                                ]
                            },
                            "Action": [
                                "sts:AssumeRole"
                            ]
                        }
                    ]
                },
                "ManagedPolicyArns": [
                    "arn:aws:iam::aws:policy/AWSLambdaFullAccess"
                ]
            }
        },
        "RecommenderLambda": {
            "Type": "AWS::Lambda::Function",
            "Properties": {
                "Handler": "recommender_field_validation_lambda.lambda_handler",
                "FunctionName": "recommenderlambda2",
                "Role": {
                    "Fn::GetAtt": [
                        "LambdaExecutionRole",
                        "Arn"
                    ]
                },
                "Environment": {
                    "Variables": {
                        "S3_BUCKET": "belcorp.recommender.test",
                        "REGION_NAME": "us-west-2",
                        "TOPIC_ARN": {
                            "Fn::ImportValue": "RecommenderTopicARN"
                        },
                        "TABLE_NAME": {
                            "Fn::ImportValue": "recommederrequestinfo"
                        }
                    }
                },
                "Code": {
                    "S3Bucket": "belcorp.recommender.lambdas",
                    "S3Key": "recommender_field_validation_lambda.zip"
                },
                "Runtime": "python3.6",
                "Timeout": 25
            }
        },
        "LambdaPermission": {
            "DependsOn": "RecommenderLambda",
            "Type": "AWS::Lambda::Permission",
            "Properties": {
                "Action": "lambda:invokeFunction",
                "FunctionName": "recommenderlambda2",
                "Principal": "apigateway.amazonaws.com",
                "SourceArn": {
                    "Fn::Join": [
                        "",
                        [
                            "arn:aws:execute-api:",
                            {
                                "Ref": "AWS::Region"
                            },
                            ":",
                            {
                                "Ref": "AWS::AccountId"
                            },
                            ":",
                            {
                                "Ref": "RecommenderApi"
                            },
                            "/*"
                        ]
                    ]
                }
            }
        },
        "RecommenderApi": {
            "Type": "AWS::ApiGateway::RestApi",
            "Properties": {
                "EndpointConfiguration": {
                    "Types": [
                        "EDGE"
                    ]
                },
                "Description": "RecommenderAPI",
                "Name": {
                    "Fn::Sub": "RecommenderApi-${AppEnv}-${DeployTag}"
                },
                "Policy": {
                    "Version": "2012-10-17",
                    "Statement": [
                        {
                            "Effect": "Allow",
                            "Principal": "*",
                            "Action": "execute-api:Invoke",
                            "Resource": {
                                "Fn::Sub": "arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:*/*"
                            },
                            "Condition": {
                                "IpAddress": {
                                    "aws:SourceIp": [
                                        "14.98.8.190/32"
                                    ]
                                }
                            }
                        }
                    ]
                }
            }
        },
        "ApiGatewayAccount": {
            "Type": "AWS::ApiGateway::Account",
            "Properties": {
                "CloudWatchRoleArn": {
                    "Fn::ImportValue": "cloudwatchRole"
                }
            }
        },
        "ApiDeployment": {
            "Type": "AWS::ApiGateway::Deployment",
            "DependsOn": [
                "OfferPostMethod",
                "OrderPostMethod"
            ],
            "Properties": {
                "RestApiId": {
                    "Ref": "RecommenderApi"
                },
                "StageName": "dev"
            }
        },
        "ProcessInput": {
            "Type": "AWS::ApiGateway::Resource",
            "Properties": {
                "RestApiId": {
                    "Ref": "RecommenderApi"
                },
                "ParentId": {
                    "Fn::GetAtt": [
                        "RecommenderApi",
                        "RootResourceId"
                    ]
                },
                "PathPart": "process-input"
            }
        },
        "OfferLevel": {
            "Type": "AWS::ApiGateway::Resource",
            "Properties": {
                "RestApiId": {
                    "Ref": "RecommenderApi"
                },
                "ParentId": {
                    "Ref": "ProcessInput"
                },
                "PathPart": "offer-level"
            }
        },
        "OrderLevel": {
            "Type": "AWS::ApiGateway::Resource",
            "Properties": {
                "RestApiId": {
                    "Ref": "RecommenderApi"
                },
                "ParentId": {
                    "Ref": "ProcessInput"
                },
                "PathPart": "order-level"
            }
        },
        "OfferPostMethod": {
            "DependsOn": "RecommenderLambda",
            "Type": "AWS::ApiGateway::Method",
            "Properties": {
                "RestApiId": {
                    "Ref": "RecommenderApi"
                },
                "ResourceId": {
                    "Ref": "OfferLevel"
                },
                "HttpMethod": "POST",
                "AuthorizationType": "NONE",
                "Integration": {
                    "Type": "AWS_PROXY",
                    "IntegrationHttpMethod": "POST",
                    "Uri": {
                        "Fn::Join": [
                            "",
                            [
                                "arn:aws:apigateway:",
                                {
                                    "Ref": "AWS::Region"
                                },
                                ":lambda:path/2015-03-31/functions/",
                                {
                                    "Fn::GetAtt": [
                                        "RecommenderLambda",
                                        "Arn"
                                    ]
                                },
                                "/invocations"
                            ]
                        ]
                    },
                    "IntegrationResponses": [
                        {
                            "StatusCode": 200,
                            "ResponseTemplates": {
                                "application/json": "$input.json('$.body')"
                            }
                        }
                    ]
                }
            }
        },
        "OrderPostMethod": {
            "DependsOn": "RecommenderLambda",
            "Type": "AWS::ApiGateway::Method",
            "Properties": {
                "RestApiId": {
                    "Ref": "RecommenderApi"
                },
                "ResourceId": {
                    "Ref": "OrderLevel"
                },
                "HttpMethod": "POST",
                "AuthorizationType": "NONE",
                "Integration": {
                    "Type": "AWS_PROXY",
                    "IntegrationHttpMethod": "POST",
                    "Uri": {
                        "Fn::Join": [
                            "",
                            [
                                "arn:aws:apigateway:",
                                {
                                    "Ref": "AWS::Region"
                                },
                                ":lambda:path/2015-03-31/functions/",
                                {
                                    "Fn::GetAtt": [
                                        "RecommenderLambda",
                                        "Arn"
                                    ]
                                },
                                "/invocations"
                            ]
                        ]
                    },
                    "IntegrationResponses": [
                        {
                            "StatusCode": 200,
                            "ResponseTemplates": {
                                "application/json": "$input.json('$.body')"
                            }
                        }
                    ]
                }
            }
        }
    },
    "Outputs": {
        "RootUrl": {
            "Description": "Root URL of the API gateway",
            "Value": {
                "Fn::Join": [
                    "",
                    [
                        "https://",
                        {
                            "Ref": "RecommenderApi"
                        },
                        ".execute-api.",
                        {
                            "Ref": "AWS::Region"
                        },
                        ".amazonaws.com"
                    ]
                ]
            }
        },
        "OfferUrl": {
            "Description": "Root URL of the API gateway",
            "Value": {
                "Fn::Join": [
                    "",
                    [
                        "https://",
                        {
                            "Ref": "RecommenderApi"
                        },
                        ".execute-api.",
                        {
                            "Ref": "AWS::Region"
                        },
                        ".amazonaws.com",
                        "/dev/process-input/offer-level"
                    ]
                ]
            }
        },
        "OrderUrl": {
            "Description": "Root URL of the API gateway",
            "Value": {
                "Fn::Join": [
                    "",
                    [
                        "https://",
                        {
                            "Ref": "RecommenderApi"
                        },
                        ".execute-api.",
                        {
                            "Ref": "AWS::Region"
                        },
                        ".amazonaws.com",
                        "/dev/process-input/order-level"
                    ]
                ]
            }
        }
    }
}

Upvotes: 5

Steve HOUEL
Steve HOUEL

Reputation: 197

APIGateway resource policy is not binding to IAM Policy, it's different kind of resource.

So to implement it on your RestApi your should use the Policy parameter on AWS::ApiGateway::RestApi resource on

{
  "Type" : "AWS::ApiGateway::RestApi",
  "Properties" : {  
    "ApiKeySourceType" : String,
    "BinaryMediaTypes" : [ String, ... ],
    "Body" : JSON object,
    "BodyS3Location" : S3Location,
    "CloneFrom" : String,
    "Description" : String,      
    "EndpointConfiguration" : EndpointConfiguration,
    "FailOnWarnings" : Boolean,
    "MinimumCompressionSize" : Integer,
    "Name" : String,
    "Parameters" : { String:String, ... },
    "Policy" : JSON object
  }
}

Upvotes: 5

Related Questions