Socket
Socket
Sign inDemoInstall

@alma-cdk/openapix

Package Overview
Dependencies
61
Maintainers
1
Versions
46
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

    @alma-cdk/openapix

Combine the power of AWS CDK & OpenAPI YAML Schema Definitions


Version published
Maintainers
1
Created

Readme

Source


Alma CDK OpenApiX

npm i -D @alma-cdk/openapix

Generate AWS Api Gateway REST APIs via OpenAPI (a.k.a. Swagger) Schema Definitions by consuming "clean" OpenAPI schemas and inject x-amazon-apigateway- extensions with type-safety.



diagram


Work in Progress

experimental

🚧  Do not use for production critial stuff! This construct is still very much work in progress and breaking changes may occur. 🚧


Getting Started

  1. First, let's create some integration points:

    const fn = new lambda.Function(this, "fn", {
      handler: "index.handler",
      runtime: lambda.Runtime.NODEJS_14_X,
      code: lambda.Code.fromInline('export function handler() { return { statusCode: 200, body: JSON.stringify("hello")} }'),
    });
    
    const pkName = 'item';
    const table = new dynamodb.Table(this, 'table', {
      partitionKey: {
        type: dynamodb.AttributeType.STRING,
        name: pkName,
      }
    });
    
    const role = new iam.Role(this, "role", {
      assumedBy: new iam.ServicePrincipal('apigateway.amazonaws.com'),
    });
    
    table.grantReadData(role);
    
  2. Next, let's inject the integrations into an existing OpenAPI schema:

    import * as openapix from '@alma-cdk/openapix';
    
    new openapix.OpenApi(this, 'MyApi', {
      upload: false, // by default add as inline Body, set to true to use as BodyS3Location
      source: './schema.yaml',
      paths: {
    
        // Mock Integration
        '/mock': {
          get: new openapix.MockIntegration(this),
        },
    
        // AWS Lambda integration
        '/message': {
          post: new openapix.LambdaIntegration(this, fn),
        },
    
        // HTTP Proxy integration
        '/ext': {
          any: new openapix.HttpIntegration(this, "https://example.com"),
        },
    
        // Direct integration to AWS Service
        '/item': {
          get: new openapix.AwsIntegration(this, {
            service: 'dynamodb',
            action: 'GetItem',
            options: {
              credentialsRole: role,
              requestTemplates: {
                'application/json': JSON.stringify({
                  "TableName": table.tableName,
                  "Key": {
                    [pkName]: {
                      "S": "$input.params('item')"
                    }
                  }
                }),
              },
            },
          }),
        },
    
      },
    })
    

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

new openapix.OpenApi(this, 'MyApi', {
  source: './schema.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: {
    '/message': {
      // Set a method-specific validator by assigning validator into props
      post: new openapix.LambdaIntegration(this, fn, { validator: 'params-only' }),
    },
  },
})

Authorizers

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.0
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.OpenApi(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.0
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.OpenApi(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.OpenApi(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

Using openapix.CorsIntegration creates a Mock integration which responds with correct response headers:

new openapix.OpenApi(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.OpenApi(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.OpenApi(this, 'MyApi', {
  source: './schema.yaml',

  paths: {/*...*/},

  restApiProps: {
    endpointConfiguration: {
      types: [ apigateway.EndpointType.EDGE ],
    },
  },
});

Keywords

FAQs

Last updated on 20 May 2022

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.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc