Research
Security News
Malicious npm Packages Inject SSH Backdoors via Typosquatted Libraries
Socket’s threat research team has detected six malicious npm packages typosquatting popular libraries to insert SSH backdoors.
@alma-cdk/openapix
Advanced tools
Combine the power of AWS CDK & OpenAPI YAML Schema Definitions
npm i -D @alma-cdk/openapix
Generate AWS Api Gateway REST APIs via OpenAPI (formely known as “Swagger”) Schema Definitions by consuming "clean" OpenAPI schemas and inject x-amazon-apigateway-
extensions with type-safety.
This construct is still versioned with v0
major version and breaking changes might be introduced if necessary (without a major version bump), though we aim to keep the API as stable as possible (even within v0
development). We aim to publish v1.0.0
soon and after that breaking changes will be introduced via major version bumps.
There are also some incomplete or buggy features, such as CORS and CognitoUserPoolsAuthorizer
.
Install npm i -D @alma-cdk/openapix
Define your API OpenApi Schema Definition in a .yaml
file
without any x-amazon-apigateway-
extensions
Use openapix
constructs in CDK to consume the .yaml
file and then assign API Gateway integrations using CDK
Given the following http-proxy.yaml
OpenApi schema definition, without any AWS API Gateway OpenApi extensions:
openapi: 3.0.3
info:
title: HTTP Proxy
description: Proxies requests to example.com
version: "0.0.1"
paths:
"/":
get:
summary: proxy
description: Proxies example.com
You may then define API Gateway HTTP integration (within your stack):
new openapix.Api(this, 'HttpProxy', {
source: path.join(__dirname, '../schema/http-proxy.yaml'),
paths: {
'/': {
get: new openapix.HttpIntegration(this, 'http://example.com', {
httpMethod: 'get',
}),
},
},
});
See /examples/http-proxy
for full OpenApi definition (with response models) and an example within a CDK application.
Given the following hello-api.yaml
OpenApi schema definition, without any AWS API Gateway OpenApi extensions:
openapi: 3.0.3
info:
title: Hello API
description: Defines an example “Hello World” API
version: "0.0.1"
paths:
"/":
get:
operationId: sayHello
summary: Say Hello
description: Prints out a greeting
parameters:
- name: name
in: query
required: false
schema:
type: string
default: "World"
responses:
"200":
description: Successful response
content:
"application/json":
schema:
$ref: "#/components/schemas/HelloResponse"
components:
schemas:
HelloResponse:
description: Response body
type: object
properties:
message:
type: string
description: Greeting
example: Hello World!
You may then define API Gateway AWS Lambda integration (within your stack):
const greetFn = new NodejsFunction(this, 'greet');
new openapix.Api(this, 'HelloApi', {
source: path.join(__dirname, '../schema/hello-api.yaml'),
paths: {
'/': {
get: new openapix.LambdaIntegration(this, greetFn),
},
},
})
See /examples/hello-api
for full OpenApi definition (with response models) and an example within a CDK application.
Given books-api.yaml
OpenApi schema definition, without any AWS API Gateway OpenApi extensions, You may then define API Gateway AWS service integration such as DynamoDB (within your stack):
new openapix.Api(this, 'BooksApi', {
source: path.join(__dirname, '../schema/books-api.yaml'),
paths: {
'/': {
get: new openapix.AwsIntegration(this, {
service: 'dynamodb',
action: 'Scan',
options: {
credentialsRole: role, // role must have access to DynamoDB table
requestTemplates: {
'application/json': JSON.stringify({
TableName: table.tableName,
}),
},
integrationResponses: [
{
statusCode: '200',
responseTemplates: {
// See /examples/http-proxy/lib/list-books.vtl
'application/json': readFileSync(__dirname+'/list-books.vtl', 'utf-8'),
},
}
],
},
}),
},
'/{isbn}': {
get: new openapix.AwsIntegration(this, {
service: 'dynamodb',
action: 'GetItem',
options: {
credentialsRole: role, // role must have access to DynamoDB table
requestTemplates: {
'application/json': JSON.stringify({
TableName: table.tableName,
Key: {
item: {
"S": "$input.params('isbn')"
}
}
}),
},
integrationResponses: [
{
statusCode: '200',
responseTemplates: {
// See /examples/http-proxy/lib/get-book.vtl
'application/json': readFileSync(__dirname+'/get-book.vtl', 'utf-8'),
},
}
],
},
}),
},
},
});
See /examples/books-api
for full OpenApi definition (with response models) and an example within a CDK application.
Given the following mock-api.yaml
OpenApi schema definition, without any AWS API Gateway OpenApi extensions:
openapi: 3.0.3
info:
title: Hello API
description: Defines an example “Hello World” API
version: "0.0.1"
paths:
"/":
get:
operationId: sayHello
summary: Say Hello
description: Prints out a greeting
parameters:
- name: name
in: query
required: false
schema:
type: string
default: "World"
responses:
"200":
description: Successful response
content:
"application/json":
schema:
$ref: "#/components/schemas/HelloResponse"
components:
schemas:
HelloResponse:
description: Response body
type: object
properties:
message:
type: string
description: Greeting
example: Hello World!
You may then define API Gateway Mock integration (within your stack):
new openapix.Api(this, 'MockApi', {
source: path.join(__dirname, '../schema/mock-api.yaml'),
paths: {
'/': {
get: new openapix.MockIntegration(this, {
requestTemplates: {
"application/json": JSON.stringify({ statusCode: 200 }),
},
passthroughBehavior: apigateway.PassthroughBehavior.NEVER,
requestParameters: {
'integration.request.querystring.name': 'method.request.querystring.name',
},
integrationResponses: [
{
statusCode: '200',
responseTemplates: {
// see /examples/mock-api/lib/greet.vtl
'application/json': readFileSync(__dirname+'/greet.vtl', 'utf-8'),
},
responseParameters: {},
},
],
}),
},
},
});
See /examples/mock-api
for full OpenApi definition (with response models) and an example within a CDK application.
API Gateway REST APIs can perform request parameter and request body validation. You can provide both default validator and integration specific validator (which will override the default for given integration).
See /examples/todo-api
for complete example within a CDK application.
Given todo-api.yaml
OpenApi schema definition you may define the API Gateway validators for your integration in CDK:
new openapix.Api(this, 'MyApi', {
source: path.join(__dirname, '../schema/todo-api.yaml'),
validators: {
'all': {
validateRequestBody: true,
validateRequestParameters: true,
default: true, // set this as the "API level" default validator (there can be only one)
},
'params-only' : {
validateRequestBody: false,
validateRequestParameters: true,
},
},
paths: {
'/todos': {
// this one uses the default 'all' validator
post: new openapix.HttpIntegration(this, baseUrl, { httpMethod: 'post' }),
},
'/todos/{todoId}': {
// this one has validator override and uses 'params-only' validator
get: new openapix.HttpIntegration(this, `${baseUrl}/{todoId}`, {
validator: 'params-only',
options: {
requestParameters: {
'integration.request.path.todoId': 'method.request.path.todoId',
},
},
}),
},
},
})
🚧 Work-in-Progress
There are multiple ways to control & manages access to API Gateway REST APIs such as resource policies, IAM permissions and usage plans with API keys but this section focuses on Cognito User Pools and Lambda authorizers.
In this example we're defining a Congito User Pool based authorizer.
Given the following schema.yaml
OpenApi definition:
openapi: 3.0.3
paths:
/:
get:
security:
- MyAuthorizer: ["test/read"] # add scope
components:
securitySchemes:
MyCognitoAuthorizer:
type: apiKey
name: Authorization
in: header
You can define the Cognito Authorizer in CDK with:
const userPool: cognito.IUserPool;
new openapix.Api(this, 'MyApi', {
source: './schema.yaml',
authorizers: [
new openapix.CognitoUserPoolsAuthorizer(this, 'MyCognitoAuthorizer', {
cognitoUserPools: [userPool],
resultsCacheTtl: Duration.minutes(5),
})
],
})
In this example we're defining a custom Lambda authorizer. The authorizer function code is not relevant for the example but the idea in the example is that an API caller sends some "secret code" in query parameters (?code=example123456
) which then the authorizer function somehow evaluates.
Given the following schema.yaml
OpenApi definition:
openapi: 3.0.3
paths:
/:
get:
security:
- MyAuthorizer: [] # note the empty array
components:
securitySchemes:
MyCustomAuthorizer:
type: apiKey
name: code
in: query
You can define the custom Lambda Authorizer in CDK with:
const authFn: lambda.IFunction;
new openapix.Api(this, 'MyApi', {
source: './schema.yaml',
authorizers: [
new openapix.LambdaAuthorizer(this, 'MyCustomAuthorizer', {
fn: authFn,
identitySource: apigateway.IdentitySource.queryString('code'),
type: 'request',
authType: 'custom',
resultsCacheTtl: Duration.minutes(5),
}),
],
})
You may modify the generated OpenAPI definition (which is used to define API Gateway REST API) by injecting or rejecting values from the source OpenAPI schema definition:
new openapix.Api(this, 'MyApi', {
source: './schema.yaml',
// Add any OpenAPI v3 data.
// Can be useful for passing values from CDK code.
// See https://swagger.io/specification/
injections: {
"info.title": "FancyPantsAPI"
},
// Reject fields by absolute object path from generated definition
rejections: ['info.description'],
// Reject all matching fields from generated definition
rejectionsDeep: ['example', 'examples'],
});
🚧 Work-in-Progress
Using openapix.CorsIntegration
creates a Mock integration which responds with correct response headers:
new openapix.Api(this, 'MyApi', {
source: './schema.yaml',
paths: {
'/foo': {
options: new openapix.CorsIntegration(this, {
// using helper method to define explicit values:
headers: CorsHeaders.from(this, 'Content-Type', 'X-Amz-Date', 'Authorization'),
origins: CorsOrigins.from(this, 'https://www.example.com'),
methods: CorsMethods.from(this, 'options','post','get'),
}),
},
'/bar': {
options: new openapix.CorsIntegration(this, {
// using regular string values:
headers: 'Content-Type,X-Amz-Date,Authorization',
origins: '*',
methods: 'options,get',
}),
},
'/baz': {
options: new openapix.CorsIntegration(this, {
// using helper constant for wildcard values:
headers: CorsHeaders.ANY,
origins: CorsOrigins.ANY,
methods: CorsMethods.ANY,
}),
},
},
});
When specifying multiple origins
the mock integration uses VTL magic to respond with the correct Access-Control-Allow-Origin
header.
If you wish to define same CORS options to every path, you may do so by providing a default cors
value:
new openapix.Api(this, 'MyApi', {
source: './schema.yaml',
defaultCors: new openapix.CorsIntegration(this, {
headers: CorsHeaders.ANY,
origins: CorsOrigins.ANY,
methods: CorsMethods.ANY,
}),
paths: {/*...*/},
});
This will apply the given cors
configuration to every path as options
method. You may still do path specific overrides by adding an options
method to specific paths.
AWS CDK API Gateway constructs default to Edge-optimized API endpoints by using EndpointType.EDGE
as the default.
This construct @alma-cdk/openapix
instead defaults to using Regional API endpoints by setting EndpointType.REGIONAL
as the default value. This is because we believe that in most cases you're better of by configuring your own CloudFront distribution in front the API. If you do that, you might also be interested in @alma-cdk/origin-verify
construct.
You MAY override this default in @alma-cdk/openapix
by providing your preferred endpoint types via restApiProps
:
new openapix.Api(this, 'MyApi', {
source: './schema.yaml',
paths: {/*...*/},
restApiProps: {
endpointConfiguration: {
types: [ apigateway.EndpointType.EDGE ],
},
},
});
FAQs
Combine the power of AWS CDK & OpenAPI YAML Schema Definitions
We found that @alma-cdk/openapix demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Security News
Socket’s threat research team has detected six malicious npm packages typosquatting popular libraries to insert SSH backdoors.
Security News
MITRE's 2024 CWE Top 25 highlights critical software vulnerabilities like XSS, SQL Injection, and CSRF, reflecting shifts due to a refined ranking methodology.
Security News
In this segment of the Risky Business podcast, Feross Aboukhadijeh and Patrick Gray discuss the challenges of tracking malware discovered in open source softare.