Giter Site home page Giter Site logo

alma-cdk / openapix Goto Github PK

View Code? Open in Web Editor NEW
88.0 7.0 5.0 1.15 MB

Combine the power of AWS CDK & OpenAPI YAML Schema Definitions

Home Page: https://constructs.dev/packages/@alma-cdk/openapix/

JavaScript 1.04% TypeScript 98.96%
aws api-gateway aws-cdk cdk openapi rest-api swagger aws-cdk-construct

openapix's Introduction



Alma CDK OpenApiX

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.



diagram


🚧   Project Stability

experimental

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.


Getting Started

  1. Install npm i -D @alma-cdk/openapix

  2. Define your API OpenApi Schema Definition in a .yaml file
    without any x-amazon-apigateway- extensions

  3. Use openapix constructs in CDK to consume the .yaml file and then assign API Gateway integrations using CDK


HTTP Integration

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.


Lambda Integration

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.


AWS Service Integration

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.


Mock Integration

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.


Validators

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',
          },
        },
      }),
    },
  },
})

Authorizers

🚧 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.


Cognito 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),
    })
  ],
})

Lambda Authorizers

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),
    }),
  ],


})

Inject/Reject

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'],
});

CORS

🚧 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.

Default CORS

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.


API Gateway EndpointType

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 ],
    },
  },
});

openapix's People

Contributors

aripalo avatar bkovacki avatar dependabot[bot] avatar hutchy2570 avatar joni3k avatar mpiltz avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

openapix's Issues

Allow for support of multiple sources

Given I have multiple APIs and API paths I would like to load multiple yaml files and have openapix merge them. For example

const api = new openapix.Api(this, 'Hello-API', {
      restApiProps:{ 
        restApiName: 'Hello API',
        description: 'An API for saying hello',
        defaultCorsPreflightOptions:{
          allowOrigins:Cors.ALL_ORIGINS,
          allowHeaders:Cors.DEFAULT_HEADERS,
          allowMethods:Cors.ALL_METHODS
        }
      },
      source: "This only supports one very large yaml of APIs",
      paths: {
        '/hello': {
          get: new openapix.LambdaIntegration(this, getHelloAllHandler),
          post: new openapix.LambdaIntegration(this, postHelloHandler),
        },
        '/goodbye': {
          get: new openapix.LambdaIntegration(this, getGoodbyeAllHandler),
          post: new openapix.LambdaIntegration(this, postGoodbyeHandler),
        },
      },
      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,
        },
      },
    })

In the case above I would like to define a source for each of the APIs so that I can maintain individual API yamls instead of one huge yaml that all of my developers have to maintain. This would support the use of lambdas and cutting up the application APIs to allow multiple developers to work in parallel without conflicts. One way this could be done is by adding "source" at the path level.

defaultCors is written to root of the document and set with key xAmazonApigatwayIntegration

When defining defaultCors, the output is written to the root of the document, rather than under paths which means the CORS configuration is not applied when the API is deployed. Additionally the integration key is output as xAmazonApigatwayIntegration.

Here is the generated document from the hello-api example when defaultCors is set:

{
  "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"
                }
              }
            }
          }
        },
        "x-amazon-apigateway-integration": {
          "httpMethod": "POST",
          "responses": {},
          "type": "AWS_PROXY",
          "uri": "arn:${Token[AWS.Partition.6]}:apigateway:${Token[AWS.Region.7]}:lambda:path/2015-03-31/functions/${Token[TOKEN.215]}/invocations"
        }
      }
    }
  },
  "components": {
    "schemas": {
      "HelloResponse": {
        "description": "Response body",
        "type": "object",
        "properties": {
          "message": {
            "type": "string",
            "description": "Greeting",
            "example": "Hello World!"
          }
        }
      }
    }
  },
  "/": {
    "options": {
      "xAmazonApigatwayIntegration": {
        "httpMethod": "POST",
        "responses": {
          "default": {
            "statusCode": "204",
            "responseParameters": {
              "method.response.header.Access-Control-Allow-Methods": "*",
              "method.response.header.Access-Control-Allow-Headers": "*"
            },
            "responseTemplates": {
              "application/json": "$input.json(\"$\")\n#set($domains = [__DOMAINS__])\n#set($origin = $input.params(\"origin\"))\n#if($domains.size()==0)\n#set($context.responseOverride.header.Access-Control-Allow-Origin=\"*\")\n#elseif($domains.contains($origin))\n#set($context.responseOverride.header.Access-Control-Allow-Origin=\"$origin\")\n#end"
            }
          }
        },
        "type": "MOCK"
      },
      "type": "CORS"
    }
  }
}

This is the stack from the sample:

import { Stack, StackProps } from "aws-cdk-lib";
import { Construct } from "constructs";
import { NodejsFunction } from "aws-cdk-lib/aws-lambda-nodejs";
import * as openapix from "@alma-cdk/openapix";
import {
  CorsHeaders,
  CorsMethods,
  CorsOrigins,
} from "@alma-cdk/openapix/lib/corsvalue";
import * as path from "path";

export class HelloApiStack extends Stack {
  constructor(scope: Construct, id: string, props?: StackProps) {
    super(scope, id, props);

    const greetFn = new NodejsFunction(this, "greet");

    const api = new openapix.Api(this, "HelloApi", {
      source: path.join(__dirname, "../schema/hello-api.yaml"),
      defaultCors: new openapix.CorsIntegration(this, {
        headers: CorsHeaders.ANY,
        origins: CorsOrigins.ANY,
        methods: CorsMethods.ANY,
      }),
      paths: {
        "/": {
          get: new openapix.LambdaIntegration(this, greetFn),
        },
      },
    });

    console.log(JSON.stringify(api.document, null, 2));
  }
}

Lambda PrincipalWithConditions error when using CDK 2.30.0

Hi,

Firstly thanks for building this library, having an openapi driven API Gateway has always been a bit rough when using Cloudformation/SAM/CDK and openapix seems to be a great idea to make this a much nicer situation!

I've been evaluating using openapix and have come across an issue with Lambda backed apis when using CDK 2.30.0 (released 3 days ago as of writing). When I use the hello-api example and upgrade the aws-cdk and aws-cdk-lib dependencies to 2.30.0 I receive the following error during synth.

PrincipalWithConditions had unsupported conditions for Lambda permission statement: [{"operator":"0","key":"ArnLike"}]. Supported operator/condition pairs: [{"operator":"ArnLike","key":"aws:SourceArn"},{"operator":"StringEquals","key":"aws:SourceAccount"},{"operator":"StringEquals","key":"aws:PrincipalOrgID"}]

It works fine with 2.29.1.

I can see in the changelog for CDK that there's been some changes around Lambda and API Gateway permissions, so I can only assume these have caused an incompatibility with openapix.

Edit:

I somehow missed this issue when looking in the CDK repo, looks like a regression on CDK's side. aws/aws-cdk#20974

Top level descriptors on path

Hi,

How would you handle the following JSON file, specifically the servers, description and x-param fields. These are at the same level as "get", so I tried to mock them.

<snip>
 "paths": {
    "/v1/Services/{Service}": {
      "get": {
        "description": "",
        "parameters": [
          {
            "name": "Service",
            "description": "some description.",
            "required": true
          },
        ],
      },
     "servers": [
        {
          "url": "https://some.server.com"
        }
      ],
      "description": "TODO: Resource-level docs",
      "x-param": {
        "defaultOutputProperties": [
          "identity",
          "address"
        ],
        "pathType": "instance",
        "parent": "/Services"
      },
 
  <snip>

Specifically the part I am struggling with is how to handle the servers, description and x-param fields. The get is fine. I tried this, but no luck

new openapix.Api(this, 'Notify_v1_Api', {
      source: path.join(__dirname, '../schema/twilio_notify_v1.json'),
      paths: { 
        "/v1/Services/{Sid}": {
          get: new openapix.LambdaIntegration(this, fetchService ),
          servers: new openapix.MockIntegration(),
          description: new openapix.MockIntegration(),
          ['x-param']: new openapix.MockIntegration(),

        },
      },
}

5:21:23 pm | CREATE_FAILED | AWS::ApiGateway::RestApi | v1ApiBE24E58A
Errors found during import:
Unable to create model for 'binding_enum_binding_type': Model name must be alphanumeric: binding_enum_binding_type
Unable to create model for 'credential_enum_push_service': Model name must be alphanumeric: credential_enum_push_service
Unable to create model for 'notification_enum_priority': Model name must be alphanumeric: notification_enum_priority
Unable to create model for 'notify.v1.service': Model name must be alphanumeric: notify.v1.service
Unable to create model for 'notify.v1.service.binding': Model name must be alphanumeric: notify.v1.service.binding
Unable to create resource at path '/v1/Services/{Sid}': A sibling ({ServiceSid}) of this resource already has a variable path part -- only one is allowed
Additionally, these warnings were found:
Parse issue: attribute paths.'/v1/Services/{Sid}'.description is not of type string
Unsupported security definition type 'http' for 'accountSid_authToken'. Ignoring.
Unable to insert model 'v1.credential' due to an unsatisfied schema reference.
Unable to insert model 'v1.service.notification' due to an unsatisfied schema reference.

Cannot define x-amazon-apigateway-endpoint-configuration using openapix directly

Hi,

I would like to be able to disable the default execution endpoint of an API Gateway when using a custom domain. I tried setting disableExecuteApiEndpoint: true on the restApiProps but it appears that the SpecRestApi construct ignores this and instead expects it to be configured via the top level x-amazon-apigateway-endpoint-configuration openapi extension.

I have managed to workaround this at the moment by loading the yaml, adding the config, then manually creating the openapix schema:

  const schema = <openapix.SchemaProps>(
    yaml.load(
      fs.readFileSync(path.join(__dirname, "../schema/api.yaml"), "utf-8")
    )
  );

  // eslint-disable-next-line @typescript-eslint/ban-ts-comment
  // @ts-ignore
  schema["x-amazon-apigateway-endpoint-configuration"] = {
    disableExecuteApiEndpoint: true,
  };

  const openapixSchema = new openapix.Schema(schema);

  new openapix.Api(this, "MyApi", {
      source: openapixSchema,
      ...
    });

I suspect this may also be an issue when trying to configure a resource policy using x-amazon-apigateway-policy since this is also a top level extension, but I've yet to try defining this.

I'm happy to help with contributing this feature, I'm just not sure whether you'd prefer an openapix specific input property for this, or to piggyback on the restApiProps.disableExecuteApiEndpoint property. Unfortunately the SpecRestApi construct doesn't specifically say which props it ignores in favour of extensions, it just has a general statement about this being the case for some properties.

Resources defined outside of OpenApi spec disappears from API Gateway

What im trying to do

const api = new openapix.Api(this, 'ExampleApi', {
  source: path.join(__dirname, '../example-schema.yaml'),
  paths: {
    '/add': {
      get: new openapix.LambdaIntegration(this, addFn),
    },
  },
});

api.root
      .addResource("_hiddenResource")
      .addMethod("GET", new LambdaIntegration(hiddenFn));

The issue

Running cdk deploy on first time everything is ok and i can see the resources defined outside of OpenApi spec in API Gateway. Running cdk deploy on second time and thereafter these resources disappear from API Gateway although the resources are still in place in CloudFormation template.

Paths not properly implemented in python module.

I am trying to use openapix to build an AWS API Gateway API from a source OpenAPI 3 file. I passing in my paths as a dict object (since I couldnt find out how using the Paths class) and when I try cdk synth I get TypeError: Paths.__init__() got an unexpected keyword argument [redacted]. So I traced the error:

  1.     # If paths argument is a dict pass its key-value pairs as keyword arguments to Paths constructor
         if isinstance(paths, dict):
             paths = Paths(**paths)
    
2. ```
    # the constructor (__init__) accepts no arguments
 class Paths:
    def __init__(self) -> None:
        '''(experimental) Paths with methods containing integrations.

        :stability: experimental
        '''
        self._values: typing.Dict[str, typing.Any] = {}
  1. Code fails

Any hopes that this might be fixed in the near future? I am planning on using this library more heavily in the near future if I can make it work with my small-scale project.

Fix issues with defaultCors

Currently defining defaultCors does not produce valid OpenApi schema for ApiGW.
Also when defining defultCors method validators throw error because underlying schema has been modified.

OPTIONS method with CorsIntegration returns HTTP 500 "Internal server error"

Calling an OPTIONS method defined with CorsIntegration returns error with status code 500.

Response body:

{
  "message": "Internal server error"
}

API Gateway Logs:

Execution log for request 8eae9904-378d-4377-bff1-97a2cd11f8f7
Mon Nov 28 19:52:17 UTC 2022 : Starting execution for request: 8eae9904-378d-4377-bff1-97a2cd11f8f7
Mon Nov 28 19:52:17 UTC 2022 : HTTP Method: OPTIONS, Resource Path: /test
Mon Nov 28 19:52:17 UTC 2022 : Method request path: {}
Mon Nov 28 19:52:17 UTC 2022 : Method request query string: {}
Mon Nov 28 19:52:17 UTC 2022 : Method request headers: {content-type= application/json}
Mon Nov 28 19:52:17 UTC 2022 : Method request body before transformations: 
Mon Nov 28 19:52:17 UTC 2022 : Execution failed due to configuration error: Unable to parse statusCode. It should be an integer that is defined in the request template.
Mon Nov 28 19:52:17 UTC 2022 : Method completed with status: 500

Example code:

new openapix.Api(this, "TestAPI", {
  source: testApiSource,
  paths: {
    "/test": 
      post: new openapix.LambdaIntegration(this, testFunction),
      options: new CorsIntegration(this, {
        headers: "'Content-Type,X-Amz-Date,Authorization'",
        origins: "*",
        methods: "'POST, OPTIONS'",
      }),
    },
  },
});

Additional Language Support

The plan is to support at least following CDK languages:

  • Python (pip)
  • Java (maven)
  • Go (github)

The additional publish mechanism for additional languages will be implemented once this package is close to v1 release.

Stages

Is there any current way to configure the API GateWay stages and implement lambda function aliases? I have not been able to find anything regarding this in the documentation. And if there is and already existing way for this implementation then i would appreciate someone pointing me to the right direction.

0.0.38 cannot be installed using npm 8

When running npm i on openapix 0.0.38 using npm 8, the following error occurs:

npm ERR! code EOVERRIDE
npm ERR! Override for @types/[email protected] conflicts with direct dependency

This appears to be due to @types/prettier being defined as v2.6.0 in devDependencies and the override for @types/prettier being 2.6.0.

CorsIntegration does not return Access-Control-Allow-Origin="*"

Configuring CorsIntegration on OPTIONS method with options.origins: "*" or options.origins: CorsOrigins.ANY does not return Access-Control-Allow-Origin header in OPTIONS response.

Code example:

new openapix.Api(this, "TestAPI", {
  source: testApiSource,
  paths: {
    "/test": 
      post: new openapix.LambdaIntegration(this, testFunction),
      options: new CorsIntegration(this, {
        headers: "'Content-Type,X-Amz-Date,Authorization'",
        origins: "*",
        methods: "'POST, OPTIONS'",
      }),
    },
  },
});

Method integration validation

If API Gateway is generated from openapi, an integration is required for every method. Currently the error message from AWS is "No integration defined for method (Service: ApiGateway, Status Code: 400, Request ID: xxx), which is not helpful.

For now, at least some kind of validation should happen when generating the integrations. A good-to-have optional feature would be to generate a mock-integration for missing integrations.

Support scopes with Lambda Authorizer

Hi, I managed to set up Lambda Authorizer and it seems to work without Scopes.

But once I add some scope to OpenAPI specification I get this error (Scopes are only valid for COGNITO_USER_POOLS authorization type) once I try to run cdk deploy:

11:34:22 AM | UPDATE_FAILED        | AWS::ApiGateway::RestApi    | HelloApi3F989F66
Errors found during import:
        Unable to put method 'GET' on resource at path '/': Invalid Method authorization type specified. Authorization Scopes are only valid for COGNITO_USER_POOLS authori
zation type (Service: AmazonApiGateway; Status Code: 400; Error Code: BadRequestException; Request ID: 93473e85-6912-442b-bef5-5bf9120dcd83; Proxy: null)


 ❌  OpenapixCdkStack failed: Error: The stack named OpenapixCdkStack failed to deploy: UPDATE_ROLLBACK_COMPLETE: Errors found during import:
        Unable to put method 'GET' on resource at path '/': Invalid Method authorization type specified. Authorization Scopes are only valid for COGNITO_USER_POOLS authorization type (Service: AmazonApiGateway; Status Code: 400; Error Code: BadRequestException; Request ID: 93473e85-6912-442b-bef5-5bf9120dcd83; Proxy: null)
    at FullCloudFormationDeployment.monitorDeployment (/home/test/.nvm/versions/node/v18.0.0/lib/node_modules/aws-cdk/lib/api/deploy-stack.ts:505:13)
    at processTicksAndRejections (node:internal/process/task_queues:95:5)
    at deployStack2 (/home/test/.nvm/versions/node/v18.0.0/lib/node_modules/aws-cdk/lib/cdk-toolkit.ts:241:24)
    at /home/test/.nvm/versions/node/v18.0.0/lib/node_modules/aws-cdk/lib/deploy.ts:39:11
    at run (/home/test/.nvm/versions/node/v18.0.0/lib/node_modules/p-queue/dist/index.js:163:29)

 ❌ Deployment failed: Error: Stack Deployments Failed: Error: The stack named OpenapixCdkStack failed to deploy: UPDATE_ROLLBACK_COMPLETE: Errors found during import:
        Unable to put method 'GET' on resource at path '/': Invalid Method authorization type specified. Authorization Scopes are only valid for COGNITO_USER_POOLS authorization type (Service: AmazonApiGateway; Status Code: 400; Error Code: BadRequestException; Request ID: 93473e85-6912-442b-bef5-5bf9120dcd83; Proxy: null)
    at deployStacks (/home/test/.nvm/versions/node/v18.0.0/lib/node_modules/aws-cdk/lib/deploy.ts:61:11)
    at CdkToolkit.deploy (/home/test/.nvm/versions/node/v18.0.0/lib/node_modules/aws-cdk/lib/cdk-toolkit.ts:315:7)
    at initCommandLine (/home/test/.nvm/versions/node/v18.0.0/lib/node_modules/aws-cdk/lib/cli.ts:358:12)

Stack Deployments Failed: Error: The stack named OpenapixCdkStack failed to deploy: UPDATE_ROLLBACK_COMPLETE: Errors found during import:
        Unable to put method 'GET' on resource at path '/': Invalid Method authorization type specified. Authorization Scopes are only valid for COGNITO_USER_POOLS authorization type (Service: AmazonApiGateway; Status Code: 400; Error Code: BadRequestException; Request ID: 93473e85-6912-442b-bef5-5bf9120dcd83; Proxy: null)

Are there plans to implement scopes for Lambda Authorizers?

Write tests for all scenarios of Definition class

For each scenario, provide:

  1. minimum OpenAPI schema definition
  2. openapix.Definition setup in CDK
  3. expectations

These tests should also work as an example.

Also consider refactoring of Definition class (or rather the processing of Schema object) at that time.

Schema uploading is not working properly

Simply uploading the generated schema to s3 as an Asset and importing it later is not enough, when x-amazon integrations are generated:

  1. CDK generates references to AWS resources as Tokens
  2. The generated references are set to the generated spec-file as Tokens, and exported as is to S3
  3. The Tokens are resolved during deploy normally, but because we import the specfile with those Tokens unresolved the deployment fails

A possible solution could utilize custom resources, or lifecycle hooks

Are API keys still not supported?

Hi, I know that when we want to add an API key to an API Gateway method, we can do so by passing apiKeyRequired: true to addMethod in @aws-cdk/aws-apigateway.

declare const integration: apigateway.LambdaIntegration;

const api = new apigateway.RestApi(this, 'hello-api');

const v1 = api.root.addResource('v1');
const echo = v1.addResource('echo');
const echoMethod = echo.addMethod('GET', integration, { apiKeyRequired: true });

const plan = api.addUsagePlan('UsagePlan', {
  name: 'Easy',
  throttle: {
    rateLimit: 10,
    burstLimit: 2
  }
});

const key = api.addApiKey('ApiKey');
plan.addApiKey(key);

But I couldn't find the same way in this library.
Are API keys still not supported?
It would be wonderful if we could do the following.

new openapix.Api(scope, 'SomeApi', {
  source: 'path/to/yaml',
  paths: {
    '/some': {
       get: new openapix.LambdaIntegration(scope, lambdaFn, {
          apiKeyRequired: true
      }),
    },
  },
....

Here is the sample from the Open API document, however, this was not enough to set the API key.

openapi: 3.0.0
    paths:
      /something:
        get:
          # Operation-specific security:
          security:
            - ApiKeyAuth: []
          responses:
            '200':
              description: OK (successfully authenticated)
# 1) Define the key name and location
components:
  securitySchemes:
    ApiKeyAuth:        # arbitrary name for the security scheme
      type: apiKey
      in: header       # can be "header", "query" or "cookie"
      name: X-API-KEY  # name of the header, query parameter or cookie
# 2) Apply the API key globally to all operations
security:
  - ApiKeyAuth: []     # use the same name as under securitySchemes

Is this project still being developed?

I really like the ideas here. I don't have the capacity to take ownership of it currently so I'd like to know if this is still live since the last commit is pretty old?

Thanks.

Reporting a vulnerability

Hello!

I hope you are doing well!

We are a security research team. Our tool automatically detected a vulnerability in this repository. We want to disclose it responsibly. GitHub has a feature called Private vulnerability reporting, which enables security research to privately disclose a vulnerability. Unfortunately, it is not enabled for this repository.

Can you enable it, so that we can report it?

Thanks in advance!

PS: you can read about how to enable private vulnerability reporting here: https://docs.github.com/en/code-security/security-advisories/repository-security-advisories/configuring-private-vulnerability-reporting-for-a-repository

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.