Рубрики
Uncategorized

Openapi с террафом на шлюзе AWS API

TL; DR Вы просто хотите выкопать исходный код, посмотрите здесь на GitHub. Readme.md contai … Помечено с AWS, DEVOPS, безвероведно, тестированием.

Openapi (7 части серии)

Вы просто хотите выкопать исходный код, посмотрите здесь Гадость . Readme.md содержит инструкции о том, как запустить его. Посмотреть Это Раздел для краткого решения решения.

Если вы заинтересованы в том, как я развернул это решение с террафом, иди сюда.

Если вы заинтересованы в аспектах тестирования, идите сюда.

Спасибо за чтение и до следующей недели!

  • TL; доктор
  • Тема разрыва
  • Openapi с террафом на шлюзе AWS API
    • Краткое введение в базу кода
  • Что такое спецификация Openapi?
    • Как создать конечную точку отдыха API?
    • Как насчет CORS?
    • Спецификация схемы компонентов
    • Как мы заботимся о защищенных конечных точках?
  • Как развернуть конечные точки Openapi с террафом для AWS?
    • Модуль шлюза API
    • Интеграция услуг
    • AWS Lambda обработчик функции
  • Как настроить контрактное тестирование с Openapi?
  • Что дальше?
  • дальнейшее чтение

На прошлой неделе мы обсудили почему Openapi и его поддержка инструментов. Сегодня я продемонстрирую и отвечу следующие темы;

  • Что такое спецификация Openapi? . Наш единственный источник правды.
  • Как развернуть конечные точки Openapi с террафом для AWS?
  • Как настроить контрактное тестирование с Openapi?

Основные принципы здесь;

  • Автоматизация ; Мы хотим максимально кодифицировать, любое ручное взаимодействие означает, что мы вводим возможные ошибки из-за несоответствия.
  • Один источник правды ; Меньшее количество документов, которые нам нужно поддерживать, тем выше вероятность информации является Текущий и последовательный Отказ

Краткое введение в базу кода

Если вам нравится следовать с кодом, пожалуйста, посмотрите здесь на Github. Readme.md содержит инструкцию о том, как запустить ее.

Структура выглядит следующим образом:

  • ./env/dev Где среда специфичная Террафом код проживает. Это для среды развития. Точно так же вы бы дублируете эти файлы для Тест и Производство Отказ

    • Таким образом, вы можете хранить файлы состояния в своих собственных учетных записях AWS, специфичные для окружающей среды, и вы можете создавать различные конфигурации для каждой среды (например, в файле dev.tfvars ).
  • ./modules Содержит все базовые модули террафора, которые состоят в ./Сервисы папка
  • ./node содержит;

    • Все AWS Lambda Handler/Lib Node12 в ./узел/src.
    • Узел программы командной строки в ./node/cmd Отказ
    • JSON Schema файл, сгенерированный из спецификации Openapi в ./узел/схема
  • ./services Содержит файлы Terraform, которые указывают на службы, это решение состоит с использованием базовых облачных услуг AWS в ./modules. .

    • Документ Openapi находится в ./services/api и это базовый документ для AWS API Gateway и файл схемы JSON обсуждался ранее.
  • ./gulpfile.js Содержит код для создания артефактов ZIP-файла из ./node/src Кодовая база и развертывает, что с террафом.

Давайте направимся в него с структурой документа Openapi, прежде чем объяснить отдельные детали более подробно. Или пропустить к следующему подразделе.

Документы Openapi по крайней мере будут иметь эти основные части (верхняя иерархия);

  • openapi указывает на версию,
  • Информация описывает общую информацию о владельце и лицензионных соглашениях (TOS),
  • Серверы , где подключиться к
  • Пути , доступные конечные точки,
  • Компоненты конкретные модели (схема JSON), которые применяются к конечным точкам и определениям безопасности.
  • Теги Используется для создания читабельной структуры человека (вы можете группировать конечные точки вместе с тем же тегом) из документа с описаниями.
  • Есть концепция Расширения (например x- Пользовательские параметры) В спецификации мы увидим примеры этого в ближайшее время, что позволяет всем предотвращать официальный документ Openapi, не нарушая проверку документа. Больше на этом здесь Отказ

Теперь, когда у нас есть общий смысл планировки документов, давайте посмотрим, как мы создаем Пути (конечные точки).

Как создать конечную точку отдыха API?

Давайте рассмотрим следующую конечную точку; Сообщение/идентичность/аутентификация

paths:
  /identity/authenticate:
    post:
      operationId: identityAuthenticate
      description: Authenticate user (either login, or continue session)
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Authenticate'
      x-amazon-apigateway-integration:
        uri: "arn:aws:apigateway:${region}:lambda:path/2015-03-31/functions/${lambda_identity_arn}/invocations"
        passthroughBehavior: "when_no_match"
        httpMethod: "POST"
        timeoutInMillis: ${lambda_identity_timeout}
        type: "aws_proxy"
      responses:
        200:
          $ref: '#/components/responses/lambda'
        500:
          $ref: '#/components/responses/500APIError'
      tags:
        - Identity

Здесь много, чтобы распаковать здесь, давайте начнем с вершины:

  • Эксидация используется для дифференцировки между операциями API. Это имя должно быть уникальным для этого документа. В этой базе кода он используется для обнаружения aws lambda, какая работа выполняется. Больше на этом, когда я объясню пользовательские AWS X- параметр.
  • Запросю Указывает, какие Пост Объект, который он ожидает, и если это требуется.

    • $ ref Относится к схеме JSON дальше по этому документу. Это ключевое слово позволяет ссылаться на другие части спецификации без дублирования одного и того же контента.
  • X-Amazon-Appistway-Integration Это пользовательский параметр AWS, который используется для определения интеграции с, в данном случае AWS Lambda.

    • Этот параметр необходим для каждой операции.
    • Он указывает, что AWS Lambda функционирует, она интегрирована с помощью $ {lambda_identity_arn} Параметр, который устанавливается сценарием Terraform.
    • Он указывает максимальную тайм-аут интеграции с $ {lambda_identey_timeout} параметр.

Позвольте сказать, что мы хотим выполнить эту API из другого домена, как мы это делаем?

Как насчет CORS?

Это типичная неприятность с REST API, как запрашивать запросы по пересечению происхождения на работу.

С помощью Gateway API operapi и AWS это относительно просто, есть 2 шага:

  • Во-первых, добавьте Варианты к путям конечной точки, которые вы хотите выполнить перекрестный домен:
    options:
      responses:
        200:
          $ref: '#/components/responses/cors'
        500:
          $ref: '#/components/responses/cors'
      x-amazon-apigateway-integration:
        responses:
          default:
            statusCode: "200"
            responseParameters:
              method.response.header.Access-Control-Max-Age: "'7200'"
              method.response.header.Access-Control-Allow-Methods: "'OPTIONS,HEAD,GET,POST,PUT,PATCH,DELETE'"
              method.response.header.Access-Control-Allow-Headers: "'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token'"
              method.response.header.Access-Control-Allow-Origin: "'*'"
        passthroughBehavior: "when_no_match"
        timeoutInMillis: 29000
        requestTemplates:
          application/json: "{ \"statusCode\": 200 }"
        type: "mock"
  • Во-вторых, в коде обработчика AWS Lambda нам нужно убедиться, что ответ содержит следующий заголовок
{
  isBase64Encoded: false,
  statusCode: 200,
  headers: {
    'Access-Control-Allow-Origin': '*'
  },
  body: JSON.stringify(message)
}

Теперь мы должны быть в состоянии создать конечную точку, которое является исполняемым поперечным происхождением. Как валидация и спецификация ввода и вывода работа?

Спецификация схемы компонентов

Компонент Раздел спецификации — это все о данных, что происходит и что выходит.

У нас есть 3 варианта, чтобы указать;

  • Параметры : Они используются в Получить Запросы, например, они отображаются в качестве параметров запроса в URL-адресе, например /user/2
  parameters:
    userID:
      description: User identifier
      in: query
      name: userID
      schema:
        type: string
      required: true
  • схемы : Используется в Пост Запросы, например, и часто ссылаются в ответ API. Требуется , Тип и узор Все определения могут быть использованы для подтверждения ввода и вывода API.

    • Больше на это позже, когда мы освещаем проверку схемы JSON
  schemas:
    Register:
      title: Register
      type: object
      description: Registration form
      required:
        - email
        - password
        - username
        - firstName
        - lastName
      properties:
        email:
          type: string
          example: "user@business.com"
          pattern: "^[_A-Za-z0-9-\\+]+(\\.[_A-Za-z0-9-]+)*@[A-Za-z0-9-]+(\\.[A-Za-z0-9]+)*(\\.[A-Za-z]{2,})$"
        password:
          type: string
          example: "123$SFF22l"
        username:
          type: string
          example: "testUsername"
        firstName:
          type: string
          example: "Rolf"
        lastName:
          type: string
          example: "Streefkerk"
  • Ответы : Ниже вы можете увидеть ссылку на схему, или если мы хотим, мы можем, чтобы, мы могли определить схему JSON здесь, как в схемы .
  responses:
    user:
      description: User
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/User'

Как мы заботимся о защищенных конечных точках?

Все, что мы видели до сих пор, доступ к общественности в целом, как мы защищаем конечную точку аутентификацией?

В этом примере я использовал AWS Cognito Как служба аутентификации, и она действительно хорошо интегрируется с Gateway API.

Укажите следующие данные:

  • Имя Определение безопасности, например Пример-когнитустерпулуухорозеризатор
  • Тип auth это cognito_user_pools.
  • Авторизатор является фактическим экземпляром AWS Cognito, идентифицированным своим уникальным ARN (имена ресурсов Amazon), которые поставляются Terraform в развертывании времени.
securitySchemes:
  example-CognitoUserPoolAuthorizer:
    type: "apiKey"
    name: "Authorization"
    in: "header"
    x-amazon-apigateway-authtype: "cognito_user_pools"
    x-amazon-apigateway-authorizer:
      providerARNs:
      - "${cognito_user_pool_arn}"
      type: "cognito_user_pools"

Теперь, чтобы включить защищенную конечную точку, вам придется добавить безопасность параметр следующим образом;

/user:
  get:
    operationId: getUser
    description: get User details by ID
    parameters:
      - $ref: '#/components/parameters/userID'
    security:
    - example-CognitoUserPoolAuthorizer: []
    ...

Если вы новичок в Terraform, пожалуйста, оставайтесь настроенными для более подробного террафора как Отказ

Кратко мы обсудили планировку каталога во введении. Хорошая структура имеет решающее значение с террафом, чтобы обеспечить максимально возможное дублирование кода, и правильная информация хранится в нужных местах.

Моя предпочтительная структура это:

  • env код и состояние, которое специфично для окружающей среды, который мы развернули.

    • Мы не хотим смешивать в состоянии изготовления в экскуревенстве в разработке.
    • Мы определенно не хотим совершать государство в Git. Используйте зашифрованное общее хранение, такое как AWS S3.
  • модули Чтобы повторно использовать код, создавать модули для каждого из основных используемых услуг и предпочтительно версии, которые такие, как разные проекты могут запускать разные версии и обновлять независимо. Для этой демонстрации они просто включены в одно и то же репо.
  • Услуги Здесь инфраструктура состоит с модули И мы храним файл определения Openapi здесь как часть нашего решения.

Модуль шлюза API

Чтобы построить интеграцию OpenAPI, нам нужно прокормить документ в AWS_API_GATEWAY_REST_API ресурс. Это сделано в Aspitay Модуль следующим образом (выдержка):

data "template_file" "_" {
  template = var.api_template

  vars = var.api_template_vars
}

resource "aws_api_gateway_rest_api" "_" {
  name           = "${local.resource_name_prefix}-${var.api_name}"
  api_key_source = "HEADER"

  body = data.template_file._.rendered
}

Когда этот модуль вызывается в ./env/dev/main.tf Файл террафора. Нам нужно указать переменные шаблона, которые мы уже видели в документе Openapi (например, $ {cognito_user_pool_arn} )

module "apigateway" {
  source            = "../../modules/apigateway"
  resource_tag_name = var.resource_tag_name
  namespace         = var.namespace
  region            = var.region

  api_name                   = local.api_name
  api_throttling_rate_limit  = var.api_throttling_rate_limit
  api_throttling_burst_limit = var.api_throttling_burst_limit
  api_template               = file("../../services/api/${local.api_name}.yml")
  api_template_vars = {
    region = var.region

    cognito_user_pool_arn = module.cognito.cognito_user_pool_arn

    lambda_identity_arn     = module.identity.lambda_arn
    lambda_identity_timeout = var.lambda_identity_api_timeout

    lambda_user_arn     = module.user.lambda_arn
    lambda_user_timeout = var.lambda_user_api_timeout
  }

  lambda_zip_name = local.lambda_zip_name
  dist_file_path  = local.dist_file_path
}

Интеграция услуг

Вы заметите, что есть упоминание о module.identity.lambda_arn. и module.user.lambda_arn. . Это два сервиса, которые были интегрированы с идентичности и конечными точками пользователя.

Когда Получить/пользователь называется, aws lambda определяется в модуле модуль.уз будет выполнено.

Кроме того, любой доступ к функции лямбда требует AWS Service Ase Cognito, ему понадобятся соответствующие разрешения для установки. Они определены в своих собственных файлах JSON. Например. Для службы пользователей они расположены в ./services/user/polyies/lambda.json.

AWS Lambda обработчик функции

Теперь, когда сторона террафора была установлена, она все еще требуется исполняемый код. Обработчики AWS Lambda входные точки в нашем узлевом коде. Они выглядят так; (см. ./node/src/handlers )

const middy = require('middy')
const { httpErrorHandler, httpSecurityHeaders } = require('middy/middlewares')
const { ErrorResponse } = require('../../lib/response')
const standards = require('../../lib/standards')
const getUser = require('./operations/getUser')

const handler = middy(async (event, context) => {
  const params = standards.getParams(event)
  const operation = standards.getOperationName(event)

  switch (operation) {
    case 'getUser': {
      return getUser.handler(params, operation)
    }

    default: {
      console.error('Unsupported operationName: ' + operation)
      return new ErrorResponse('Unsupported operationName: ' + operation)
    }
  }
}).use(httpErrorHandler()).use(httpSecurityHeaders())

module.exports = { handler }

Именно здесь мы можем использовать схему JSON, чтобы подтвердить наш входные данные конечной точки покоя.

Исходный файл IS (RE), созданный, запустив этот скрипт узла:

NPM Run Convert Это возьмет файл operapi YML и преобразовать его в файл совместимого файла json Schema V4.

В свою очередь это используется ./node/src/lib/jsonschema И инициализирован в обработчике функции следующим образом:

const JsonSchema = require('../../../lib/jsonSchema') // our library
const schema = require('../../../schema/example.json') // our JSON Schema
const input = new JsonSchema(schema['/identity/register'].post.body) //the Path in that JSON Schema we want to validate against

const results = input.validateInput(params) // validate the input

if (results.valid) {
  return new SuccessResponse('Success, user with email address: ' + params.email + ' registered successfully')
}

У нас есть работающая спецификация Openapi, мы развернули решение с террафом. Теперь мы также можем генерировать основу нашего контрактного тестового люкса с Почтальон Отказ

Вот как это сделать:

  • Открыть почтальон, перейдите на вкладку APIS на левой части приложения, нажмите + Новый API Отказ
  • Добавить схему> Импорт файла Перейдите к \ openapi-tf-пример \ services \ api \ example.yml Отказ
  • Замените в импортируемый документ (серверы: — URL: http://example.com/ ), с выходом URL-адреса в командной строке, когда развертывание примера REST API закончила, он называется api_url. .

    • Рекомендуется, создайте доменное имя и ссылку, которое на ваш API отдыха и автоматически заполняется в файл Openapi YML с террафом.
  • Нажмите на Создать коллекцию Дайте ему имя (например Пример ) А затем добавьте в Контрактный тест Отказ
  • Когда вы перейдите к своим коллекциям (левая сторона) Вы должны увидеть это перечисленные там.
  • Перейти к себе Пример Коллекция и открыть Идентификация> Регистрация> Регистрация отдельных личностей , нажмите Отправить
  • Вы должны увидеть сообщения об ошибках, находящихся в нижней панели;
    • например «Сообщение»: «Должна соответствовать шаблону \» ^ ^ _ a-za-z0-9 — \ +] + (\. [_ a-za-z0-9 -] +) @ [A-ZA-Z0-9 -] + (\. [A-ZA-Z0-9] +) (\. [A-ZA-Z] {2,}) $ \ «»
  • Если вы получите сообщение, которое подтверждает, что API работает правильно, и вы можете разработать ваши контрактные тесты с документацией под вкладкой Тест в API вкладка.

Вы можете использовать это в качестве основы для создания тестовых случаев. Смотри на Это Статья, например, которая подробно обсуждается, как вы можете создавать тестовые случаи и запустить их от Postman CLI с Ньюман Отказ

В этой статье мы охватили много земли, дайте мне знать в комментариях, если это было полезно и что вы хотели бы видеть больше.

Любые вопросы и идеи. Стрелять!

Спасибо за чтение и до следующей недели!

Openapi (7 части серии)

Оригинал: «https://dev.to/rolfstreefkerk/openapi-with-terraform-on-aws-api-gateway-17je»