Open rockey5520 opened 3 years ago
Hey, I think you're encountering this issue because you're missing the ApiId
property on HttpApiEvent
, not because of an issue with the SAM CLI. I haven't tried your stack myself because the meaningful indentation has been stripped from your YAML
(*I made an edit to make yaml formatted.)
Assuming I understand correctly, what you are trying to do here is quite similar to one of our example "HttpApi with configuration settings" and you can find it here: https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-resource-httpapi.html, let me paste it at the end of this comment. Both are trying to "define a AWS::Serverless::HttpApi and use it in a function."
You can try to replace
...
HttpApiEvent:
Type: HttpApi
Properties:
TimeoutInMillis: 20000
PayloadFormatVersion: '2.0'
Auth:
Authorizer: MyOauth2Authorizer
...
with this
...
HttpApiEvent:
Type: HttpApi
Properties:
ApiId: !Ref Api
TimeoutInMillis: 20000
PayloadFormatVersion: '2.0'
ApiId
ApiId
Identifier of an AWS::Serverless::HttpApi resource defined in this template. If not defined, a default AWS::Serverless::HttpApi resource is created called ServerlessHttpApi using a generated OpenApi document containing a union of all paths and methods defined by Api events defined in this template that do not specify an ApiId. This cannot reference an AWS::Serverless::HttpApi resource defined in another template. Type: String Required: No AWS CloudFormation compatibility: This property is unique to AWS SAM and doesn't have an AWS CloudFormation equivalent. https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-property-function-httpapi.html
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Parameters:
StageName:
Type: String
Default: Prod
Resources:
HttpApiFunction:
Type: AWS::Serverless::Function
Properties:
InlineCode: |
def handler(event, context):
import json
return {
"statusCode": 200,
"body": json.dumps(event),
}
Handler: index.handler
Runtime: python3.7
Events:
ExplicitApi: # warning: creates a public endpoint
Type: HttpApi
Properties:
ApiId: !Ref HttpApi
Method: GET
Path: /path
TimeoutInMillis: 15000
PayloadFormatVersion: "2.0"
RouteSettings:
ThrottlingBurstLimit: 600
HttpApi:
Type: AWS::Serverless::HttpApi
Properties:
StageName: !Ref StageName
Tags:
Tag: Value
AccessLogSettings:
DestinationArn: !GetAtt AccessLogs.Arn
Format: $context.requestId
DefaultRouteSettings:
ThrottlingBurstLimit: 200
RouteSettings:
"GET /path":
ThrottlingBurstLimit: 500 # overridden in HttpApi Event
StageVariables:
StageVar: Value
FailOnWarnings: True
AccessLogs:
Type: AWS::Logs::LogGroup
Outputs:
HttpApiUrl:
Description: URL of your API endpoint
Value:
Fn::Sub: 'https://${HttpApi}.execute-api.${AWS::Region}.${AWS::URLSuffix}/${StageName}/'
HttpApiId:
Description: Api id of HttpApi
Value:
Ref: HttpApi
Hi @aahung ,
I found changing the template to the below structure worked. Is this the right way to construct it?
https://gist.github.com/rockey5520/a654124bb6b891ce329470f1c0d63474
Hi @aahung ,
I found changing the template to the below structure worked. Is this the right way to construct it?
https://gist.github.com/rockey5520/a654124bb6b891ce329470f1c0d63474
+ Add APIStage AWS::ApiGatewayV2::Stage
+ Add API AWS::ApiGatewayV2::Api
+ Add ServerlessHttpApiApiGatewayDefaultStage AWS::ApiGatewayV2::Stage
+ Add ServerlessHttpApi AWS::ApiGatewayV2::Api
+ Add XFunctionHttpApiEventPermission AWS::Lambda::Permission
+ Add XFunctionRole AWS::IAM::Role
+ Add XFunction AWS::Lambda::Function
Your template creates two APIs, I don't think it is what you want.
Would you mind trying to write your template based on the example I sent you? Like this:
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Parameters:
StageName:
Type: String
Default: Prod
Resources:
HttpApiFunction:
Type: AWS::Serverless::Function
Properties:
InlineCode: |
def handler(event, context):
import json
return {
"statusCode": 200,
"body": json.dumps(event),
}
Handler: index.handler
Runtime: python3.7
Events:
ExplicitApi: # warning: creates a public endpoint
Type: HttpApi
Properties:
ApiId: !Ref HttpApi
Method: GET
Path: /path
TimeoutInMillis: 15000
PayloadFormatVersion: "2.0"
RouteSettings:
ThrottlingBurstLimit: 600
HttpApi:
Type: AWS::Serverless::HttpApi
Properties:
StageName: !Ref StageName
Tags:
Tag: Value
AccessLogSettings:
DestinationArn: !GetAtt AccessLogs.Arn
Format: $context.requestId
DefaultRouteSettings:
ThrottlingBurstLimit: 200
RouteSettings:
"GET /path":
ThrottlingBurstLimit: 500 # overridden in HttpApi Event
StageVariables:
StageVar: Value
FailOnWarnings: True
+ Auth:
+ Authorizers:
+ MyOauthAuthorizer:
+ IdentitySource: $request.header.Authorization
+ JwtConfiguration:
+ audience:
+ - https://awsgateway
+ issuer: "https://xxx.xx.com/"
+ DefaultAuthorizer: MyOauthAuthorizer
AccessLogs:
Type: AWS::Logs::LogGroup
Outputs:
HttpApiUrl:
Description: URL of your API endpoint
Value:
Fn::Sub: 'https://${HttpApi}.execute-api.${AWS::Region}.${AWS::URLSuffix}/${StageName}/'
HttpApiId:
Description: Api id of HttpApi
Value:
Ref: HttpApi
Hi @aahung
I tried with the structure given above. But I need to make a small change where my API Gateway needs to accept any HTTP methods and pass the request to lambda and replaced the above structure PATH to be as / and removed METHOD. By doing so I am getting error as
CREATE_FAILED AWS::ApiGatewayV2::Api HttpApi Warnings found during import: Parse
issue: attribute paths. Resource $default
should start with / (Service:
AmazonApiGatewayV2; Status Code: 400; Error
Code: BadRequestException; Request ID:
a60fsasa9a83-a9433g34gh6d-43c7-b1b0-4aa65ab65836; Proxy:
null) (Service: null; Status Code: 404; Error
Code: BadRequestException; Request ID: null;
Proxy: null)
ROLLBACK_IN_PROGRESS AWS::CloudFormation::Stack finapi The following resource(s) failed to create:
[HttpApi]. Rollback requested by user.
Can you post your updated template here?
Sure @aahung ,
I am trying to get HttpAPI on gateway with $default route which can accept ANY HTTP method
Template.yaml I tried using is : https://gist.github.com/rockey5520/8d9ae3828075149b40a31c6acad68476
Sorry for the delay @rockey5520. Support for $default
route was added at a later date as part of a quick create for HttpApi. SAM do not have support for this yet. When you declare Path
as $default
SAM puts it in Path body which based on OpenAPI specification need to start with a /
, that is why you are seeing that error.
I am marking this issue as a feature request and will update after discussing in team.
Please let me know if you have any questions.
Thanks Tarun
Thank @c2tarun for answering. One question i have is,
via SAM template is it possible to create a method OPTIONS to the httpapi gateway which does not need to integrate with lambda but it does need to exist for my case?
Reason : Use case I have is to build an httpapi integrated to one lambda via /{path+}(GET, POST, PATCH, DELETE) and direct all calls to lambda and I have accomplished this with SAM, and works well when I invoke the endpoint via curl/postman but facing CORS issue when calling the same endpoint via frontend due to the reason there is no OPTIONS method defined on httpapi.
I was able to overcome this situation by setting OPTIONS on httpapi via console but it would nice to have that in template.
Hope my question makes sense or let me know I will try to rephrase.
The same was accomplished via restapi following https://docs.aws.amazon.com/apigateway/latest/developerguide/how-to-cors.html but I am looking for the same in httpapi
I have the same issue with Sam local and HttpApi auth... it works fine when deployed but the Auth is not used locally... Any ideas ?
As for auth support in sam local
, it is not yet supported in AWS SAM CLI. Please refer to the issue https://github.com/aws/aws-sam-cli/issues/137
Thank @c2tarun for answering. One question i have is,
via SAM template is it possible to create a method OPTIONS to the httpapi gateway which does not need to integrate with lambda but it does need to exist for my case?
Reason : Use case I have is to build an httpapi integrated to one lambda via /{path+}(GET, POST, PATCH, DELETE) and direct all calls to lambda and I have accomplished this with SAM, and works well when I invoke the endpoint via curl/postman but facing CORS issue when calling the same endpoint via frontend due to the reason there is no OPTIONS method defined on httpapi.
I was able to overcome this situation by setting OPTIONS on httpapi via console but it would nice to have that in template.
Hope my question makes sense or let me know I will try to rephrase.
The same was accomplished via restapi following https://docs.aws.amazon.com/apigateway/latest/developerguide/how-to-cors.html but I am looking for the same in httpapi
HttpApi
has CorsConfiguration
to enable CORS (in my experience, with this property set, there is still no OPTIONS defined in httpapi but CORS works). https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-resource-httpapi.html#sam-httpapi-corsconfiguration
Hey guys,
The same issue is driving me crazy for the last 2 days, I hope someone here can help me.
Here is the error I can see in my Lambda function:
I indeed can't see the route in the API Gateway console.
Here is my template:
AWSTemplateFormatVersion: "2010-09-09"
Transform: AWS::Serverless-2016-10-31
Description: Cognito to API Gateway HTTP API (JWT)
Parameters:
Environment:
Description: Environment to deploy to.
Type: String
AllowedValues:
- dev
- prd
Globals:
Function:
Runtime: python3.9
MemorySize: 128
Timeout: 5
Description: "aws:states:opt-in"
ReservedConcurrentExecutions: 5
Resources:
HttpApi:
Type: AWS::Serverless::HttpApi
Properties:
StageName: !Ref Environment
CorsConfiguration:
AllowMethods:
- "*"
AllowOrigins:
- Fn::ImportValue: !Sub backend-${Environment}-client-domain
Auth:
Authorizers:
BasicAuthorizer:
AuthorizationScopes:
- email
IdentitySource: "$request.header.Authorization"
JwtConfiguration:
issuer:
- Fn::ImportValue: !Sub backend-${Environment}-issuer
audience:
- Fn::ImportValue: !Sub backend-${Environment}-user-pool-client-id
DataPointsCreateRole:
Type: AWS::IAM::Role
Properties:
RoleName: backend-data-points-create-role
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Principal:
Service: lambda.amazonaws.com
Action:
- sts:AssumeRole
ManagedPolicyArns:
- arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
DataPointsCreateFunction:
Type: AWS::Serverless::Function
Properties:
FunctionName: !Sub backend-${Environment}-data-points-create-function
Role: !GetAtt DataPointsCreateRole.Arn
CodeUri: ./../c-crop-backend/data_points/create
Handler: handler.handler
Events:
RootGet:
Type: HttpApi
Properties:
Auth:
Authorizer: BasicAuthorizer
Path: /simple
Method: get
ApiId: !Ref HttpApi
What am I doing wrong?
I'm deploying it with SAM CLI.
Thanks,
Thomas
Hey @tbenhamou
I can give you template structure that worked for me, if you like to adjust yours and see if it helps
https://gist.github.com/rockey5520/82a32603ea096621be524f2816da98c2
Hope it works
Hey @rockey5520 ,
Thanks for assisting me! Your template helped me for some other stuff but I found my issue just a few minutes ago!!! The issuer field within the HttpApi resources should be a string and not a list of string. The deployment didn't failed on that. How did I find out? I tried to deploy a separated Authorizer and there the deployment did fail on the bad format of the value supplied!
BTW, The field issuer
and audience
should be in lowercase within the AWS::Serverless::HttpApi
resource but if it's an AWS::ApiGatewayV2::Authorizer
, it should be Issuer
and Audience
...
Thank you!
This is a request on the SAM Spec not CLI. Moving to the correct repo (to make it easier to track) and updated the title to reflect the request.
Just FYI for anyone getting here with sam cli -v 1.9
Properties issuer and audience are case insensitive and can be used either lowercase as in OpenAPI or uppercase Issuer and Audience as in AWS::ApiGatewayV2::Authorizer.
For my issue with Authorizer not showing up, I had to update SAM CLI as well as change Audience to a list as in...
Auth:
Authorizers:
TestAuth:
IdentitySource: $request.header.Authorization
JwtConfiguration:
Issuer: https://cognito-idp.us-east-1.amazonaws.com/.....
Audience:
- 355.......
DefaultAuthorizer: TestAuth
Description:
Unable to set OAuth2 authorizer on API method [x-amazon-apigateway-any-method] for path [$default]
Steps to reproduce:
Below is template.Yaml file used and when run sam deploy gives errror as
Waiting for changeset to be created.. "Error: Failed to create changeset for the stack: finapi, ex: Waiter ChangeSetCreateComplete failed: Waiter encountered a terminal failure state Status: FAILED. Reason: Transform AWS::Serverless-2016-10-31 failed with: Invalid Serverless Application Specification document. Number of errors found: 1. Resource with id [XXX] is invalid. Event with id [HttpApiEvent] is invalid. Unable to set Authorizer [MyOauth2Authorizer] on API method [x-amazon-apigateway-any-method] for path [$default] because the related API does not define any Authorizers."
Observed result:
Waiting for changeset to be created.. Error: Failed to create changeset for the stack: finapi, ex: Waiter ChangeSetCreateComplete failed: Waiter encountered a terminal failure state Status: FAILED. Reason: Transform AWS::Serverless-2016-10-31 failed with: Invalid Serverless Application Specification document. Number of errors found: 1. Resource with id [FinApiFunction] is invalid. Event with id [HttpApiEvent] is invalid. Unable to set Authorizer [MyOauth2Authorizer] on API method [x-amazon-apigateway-any-method] for path [$default] because the related API does not define any Authorizers.
Expected result:
function with API method [x-amazon-apigateway-any-method] for path [$default] is created on API gateway with OAuth 2.0/JWT authorizer configured
Additional environment details (Ex: Windows, Mac, Amazon Linux etc)
sam --version
: 1.15.0Add --debug flag to command you are running