AWS SAM app API multiple method declarations - yaml

I created AWS sam application. It has a REST API customers. Presently I'm able to add only one http method type either GET or POST.
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: ""
Globals:
Function:
Timeout: 59
Resources:
HealthFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: src/
Handler: index.handler
Runtime: nodejs14.x
Architectures:
- x86_64
Events:
Health:
Type: Api
Properties:
Path: /health
Method: get
Customers:
Type: Api
Properties:
Path: /customers
Method: get
Outputs:
HealthApi:
Description: "API Gateway endpoint URL for Prod for Health function"
Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/health"
CustomersApi:
Description: "API Gateway endpoint URL for Prod for Health function"
Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/customers"
How can I declare customers API http methods both GET and POST?

You can define multiple events for the same path.
CustomersGetEvent:
Type: Api
Properties:
Path: /customers
Method: GET
CustomersPostEvent:
Type: Api
Properties:
Path: /customers
Method: POST
As an alternative you can also use Method: ANY.

Related

How to use Keycloak JWT for authentication in Micronaut GraphQL

I'm trying to use Micronaut GraphQL using keycloak JWT. I was able to get things working with Basic Auth, trying to move over to bearer token instead, and I'm missing something, as I always get a 401 Unauthorized, but I'm not seeing any useful error messages in the log, even with the logging set to TRACE
Using Micronaut 3.0.0.
My application.yml looks like this:
micronaut:
application:
name: myapp
server:
cors:
enabled: true
port: 8080
security:
authentication: bearer
intercept-url-map:
- pattern: /graphiql
access:
- isAnonymous()
- pattern: /graphql
access:
- isAuthenticated()
endpoints:
login:
enabled: false
token:
jwt:
enabled: true
signatures:
jwks:
keycloak:
url: http://xx.xx.xx.xx:8090/auth/realms/myrealm/protocol/openid-connect/certs
oauth2.clients.keycloak:
grant-type: password
client-id: myapp-backend
client-secret: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
authorization:
url: http://xx.xx.xx.xx:8090/auth/realms/myrealm/protocol/openid-connect/auth
custom:
keycloak:
url: http://xx.xx.xx.xx:8090
graphql:
enabled: true
path: /graphql
graphiql:
enabled: true
path: /graphiql
here is what I'm posting to test:
curl --location --request POST 'localhost:8080/graphql' \
--header 'Authorization: Bearer {exceptionally long jwt token}' \
--header 'Content-Type: application/json' \
--data-raw '{"query":"query test { scenarios { id } }","operationName":"test"}'
I'm not sure what else would be useful to provide. Any thoughts?
I don't know much about Micronaut but isn't this missing an openid configuration like this:
micronaut:
security:
oauth2.clients.keycloak.openid:
issuer: http://xx.xx.xx.xx:8090/auth/realms/myrealm
After more searching and stepping through in the debugger, I was able to finally determine that I had mistyped my realm name.
However, for posterity, here is the minimal configuration that I needed to run:
micronaut:
application:
name: myapplication
server:
cors:
enabled: true
port: 8080
security:
enabled: true
authentication: bearer
intercept-url-map:
- pattern: /graphiql
access:
- isAnonymous()
- pattern: /graphql
access:
- isAuthenticated()
endpoints:
login:
enabled: false
token:
jwt:
enabled: true
signatures:
jwks:
keycloak:
url: http://xx.xx.xx.xx:8090/auth/realms/MyRealm/protocol/openid-connect/certs
oauth2.clients.keycloak:
grant-type: password
client-id: myapp-backend
client-secret: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
authorization:
url: http://xx.xx.xx.xx:8090/auth/realms/MyRealm/protocol/openid-connect/auth
custom:
keycloak:
url: http://xx.xx.xx.xx:8090/auth/realms/MyRealm
graphql:
enabled: true
graphiql.enabled: true
graphql-ws.enabled: true

IntegrationResponse SAM Template

Questions:
IntegrationResponse to Sam template ? Is it possible without OpenApi?
Way to add headers to GatewayResponses in SAM template?
What im trying to achive:
Define gateway responses and integration responses inside a SAM
CloudFront template.
What i checked so far:
SAM github link
SAM issue
I was checking SAM github but for me it wasnt clear how to do it based on the above link.
Also i didnt found any answer on stackoverflow which would explain why the headers are bad in my gatewayresponse snippet
Every Help is appreciated
Some examples:
Globals:
Api:
GatewayResponses:
MISSING_AUTHENTICATION_TOKEN:
ResponseParameters:
# gatewayresponse.header.Cache-Control: "no-cache"
ResponseTemplates:
"application/json" : '{"errors": [{errorKey: "error Value"}]}'
StatusCode: '404'
#defaultResponse: true
Expected function level integrationResponse:
Function:
Type: AWS::Serverless::Function
Properties:
Handler: Function.handler
Timeout: 20
CodeUri: "src/Function"
Role: .......
Events:
FunctionGet:
Type: Api
Properties:
Path: /Function
Method: get
IntegrationResponse:
SOME_ERROR_CODE
ResponseTemplates
integrationresponse.header
So long story short half of my question is stupid. in proxy integration API GW is by defult returning the response from server to client no need further declaration in SAM template.
As for the headers the following way is the correct:
Globals:
Api:
GatewayResponses:
MISSING_AUTHENTICATION_TOKEN:
ResponseParameters:
Headers:
Access-Control-Allow-Origin: "'*'"
Access-Control-Allow-Headers: "'*'"
Cache-Control: "'no-cache'"
Content-Type: "'application/json'"
ResponseTemplates:
"application/json" : '{"errors": [{errorKey: "error Value"}]}'
StatusCode: '404'
#defaultResponse: true

go-swagger do not validates Body in POST request

Swagger ignoring required fields in body of POST request.
Steps to reproduce:
Describe swaggerfile
swagger: "2.0"
info:
title: Sample API
description: API description in Markdown.
version: 1.0.0
host: api.example.com
schemes:
- http
paths:
/users:
post:
operationId: UserCreate
parameters:
- name: body
in: body
required: true
schema:
allOf:
- $ref: "#/definitions/ID"
- $ref: "#/definitions/User_object"
- type: object
required: # HERE! IT IS NOT WORKING
- ID
- genderCode
- birthDate
- code
produces:
- application/json
consumes:
- application/json
responses:
200:
description: "OK"
definitions:
ID:
title: ID
properties:
GUID:
type: string
description: "ID"
format: uuid
User_object:
title: User_object
properties:
genderCode:
type: string
birthDate:
type: string
format: date
code:
type: string
Generate api
swagger generate server -f swaggerfile.yaml -t api
Describe single handler:
api.UserCreateHandler = operations.UserCreateHandlerFunc(func(params operations.UserCreateParams) middleware.Responder {
return middleware.NotImplemented("MUST NOT BE PRINTED")
})
Make a request to generated api:
curl -X POST -H "Content-Type: application/json" -d '{"foo":"bar"}' localhost:{{host}}/users
Expected result:
400 Bad Request
Given result:
501 MUST NOT BE PRINTED
My personal workaround is
api.UserCreateHandler = operations.UserCreateHandlerFunc(func(params operations.UserCreateParams) middleware.Responder {
if params.Body.UserObject == (models.UserObject{}) {
return //... your BAD REQUEST type
}
return middleware.NotImplemented("MUST NOT BE PRINTED")
})

Custom api gateway websocket endpoint using serverless

I’m trying to custom my api gateway websocket endpoint via serverless because I need to initialize it for cloudfront which is deployed before websocket.
The initialize code is below:
ApiGatewayWebsocketApi:
Type: AWS::ApiGatewayV2::Api
Properties:
Name: ${self:provider.stage}-${self:provider.variant}-WebsocketApi
ProtocolType: WEBSOCKET
RouteSelectionExpression: "$request.body.action"
Description: "WebSocket API for ${self:provider.variant}"
And I exported it as an output:
ApiGatewayWebsocketApiId:
Value:
Ref: ApiGatewayWebsocketApi
Export:
Name: ${self:custom.configFile.appCode}-${self:provider.stage}-${self:provider.variant}-ApiGatewayWebsocketApiId
Then ApiGatewayWebsocketApiId will represent an endpoint string like b6hnpuyzq6
And I can get it in websocket serverless.yml:
WebSocketApiId:
Fn::ImportValue: ${self:custom.configFile.appCode}-${self:provider.stage}-${self:provider.variant}-ApiGatewayWebsocketApiId
But here is the problem:
how can I import it to my function such as connectionHandler so that this websocket can use the endpoint imported above:
connectionHandler:
name: ${self:provider.stage}-${self:provider.variant}-${self:custom.configFile.appCode}-ws-connection
handler: WebsocketTestHandler
events:
- websocket:
route: $connect
- websocket:
route: $disconnect
Perhaps you can try to pass WebSocketApiId parameter value trough WEB_SOCKET_API_ID environment variable available in the handler, like this:
connectionHandler:
name: ${self:provider.stage}-${self:provider.variant}-${self:custom.configFile.appCode}-ws-connection
handler: WebsocketTestHandler
environment:
WEB_SOCKET_API_ID:
Ref: WebSocketApiId
events:
- websocket:
route: $connect
- websocket:
route: $disconnect

How to access API Gateway's pathParameters in step function using Serverless framework?

How to pass the pathParameter user_id to the first function in a Step Function?
PS: I'm using API Gateway to invoke the step function.
stepFunctions:
stateMachines:
hellostepfunc:
name: HelloStep
events:
- http:
path: users/list/{user_id}
method: GET
cors: true
authorizer: aws_iam
You can try something like below, hope it helps.
serverless.yml
events:
— http:
path: users/list/{user_id}
method: get
cors: true
request:
parameters:
paths:
user_id: true

Resources