Уик: Запоздалое вступление

Это введение в wick, мета-фреймворк приложения, который я начал создавать почти два года назад.

Фон

Два года назад я врезался в стену. Я проработал в программном обеспечении более двадцати лет и семь из них провел, помогая Shape Security вырасти из маленького стартапа до единорога.

Я был готов начать что-то новое. Но я не смог.

Я знал, что меня ждет впереди, и это меня пугало. Мне было невыносимо начинать те же задачи, которые я выполнял сто раз раньше. Новые языки и фреймворки, облака, бессерверные технологии, микросервисы и т. д. не изменили ситуацию. Это была все та же работа с новыми именами. Интегрируйте сюда дюжину API, заставьте там работать вместе сотню случайных библиотек и перепишите ту же логику еще раз.

Работа была несложной. Я не думаю, что нам больше придется этим заниматься.

Большая часть каждого приложения представляет собой программные компоненты, соединяющиеся с другими программными компонентами. Почему у нас не было возможности использовать USB для программного обеспечения? Меняйте местами любые зависимости, где угодно и когда угодно. Если сверхширокоэкранный монитор 4K можно подключить к моему компьютеру через тот же порт, что и моя мышь, мы, несомненно, сможем обеспечить бесперебойную работу программных библиотек.

Если бы мы это сделали, мы могли бы создавать реальные приложения быстрее, одновременно используя больше ресурсов. Мы могли бы автоматически генерировать документацию и даже примеры. Мы могли бы защитить все одинаково, развернуть и протестировать одинаково. Более того, если бы все было асинхронно, мы могли бы масштабироваться от одного процесса до распределенной сети без изменения кода.

Эти идеи не новы. Это многое из того, что можно найти в функциональных языках, реактивных средах и таких идеях, как потоковое программирование. Проблема в том, что они в основном применяются в пределах языка или среды выполнения. Но бизнес не работает в рамках языка или среды выполнения. У команд есть разные варианты использования, разные среды и множество инструментов для интеграции.

Благодаря таким достижениям, как WebAssembly и таким инструментам, как Kubernetes и Docker, казалось, что пришло время перенести эти идеи на новый уровень.

Оказывается, я был не одинок в этой мысли. Мне удалось получить предварительное финансирование и полностью посвятить себя созданию того, что мы сейчас называем фитилем.

Wick — это платформа приложений, существующая вне языка и — благодаря WebAssembly — на разных языках.

В основе Wick лежит определение компонента. Фитильный компонент представляет собой набор операций, каждая из которых принимает и создает произвольное количество потоков.

Компоненты Wick подобны библиотекам на любом языке программирования. Это коллекции функций.

За исключением того, что они начинаются как YAML.

Фитильные компоненты

Определения компонентов написаны в YAML и определяют конфигурацию, тестовые примеры, метаданные пакета, операции, а также входные и выходные данные операции.

Фактическая логика компонента представлена ​​в четырех (текущих) вариантах:

  • WebAssembly: определение компонента Wick определяет операции, которые обрабатывает модуль WebAssembly и которые Wick делегирует функции WASM при вызове.
  • Композит: составные компоненты строят свою логику на основе других компонентов. Они определяют логику в потоке — функциональном конвейере данных — путем соединения операций других компонентов. Думайте об операциях с составными компонентами как о каналах Unix или об использовании map() в массивах или потоках.
  • SQL: компоненты SQL определяют операции как запросы SQL. Уик связывает входные данные с аргументами запроса, и каждая строка выводится в поток. Wick поддерживает MS SQL Server, Postgres и Sqlite «из коробки».
  • HTTP. Компонент HTTP определяет конфигурацию, необходимую для выполнения HTTP-запроса. Вик использует входные данные операции для построения URL-пути, строки запроса и тела, а выходные данные операции — это метаданные и тело ответа (в виде необработанных байтов или JSON).

Лучший способ понять, как все это работает, — это примеры. Создание динамического приложения из набора YAML может показаться бредом.

Быстрое создание нового компонента

Приведенная выше команда создает пример компонента с помощью одной операции echo.

Операция echo по умолчанию имеет один входной поток с соответствующим названием input и выходной поток с именем output. Вот как это выглядит:

kind: wick/component@v1
name: my_component
component:
  kind: wick/component/composite@v1
  operations:
  - name: echo
    inputs:
    - name: input
      type: object # an "any" type
    outputs:
    - name: output
      type: object
    flow:
    - <>.input -> <>.output

Эти файлы конфигурации являются источником истины. Даже компоненты WebAssembly, которые могут определять свои собственные экспорты, не могут работать в фитильном контексте ни с чем, кроме интерфейсов, определенных в определении. Это ограничение позволяет инструментам запрашивать и утверждать компоненты без анализа множества языков или проверки каких-либо внутренних компонентов компонента. Например, такие инструменты, как wick list.

Команда wick list загружает компонент и сообщает его подпись. Конечно, это просто, но сколько языков или фреймворков предоставляют вам такой инструмент?

Все команды wick принимают флаг --json для интеграции с другими инструментами. Определения компонентов также поддерживают описательные поля во многих элементах, поэтому вы можете использовать эти выходные данные для создания документации и примеров, как мы это делаем на нашем сайте документации:

Запуск компонентов из командной строки

Поскольку каждый фитильный компонент использует один и тот же общий API, команда wick invoke может вызывать любую операцию в любом компоненте или любое приложение из командной строки.

Да, вы можете вызвать функцию глубоко внутри приложения прямо из командной строки. Никакой дополнительной настройки или настройки не требуется.

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

Хотите предоставить функциональность другой команде? Уже сделано.

Необходимо проверить данные в другое время и в других условиях? Используйте само приложение в bash-скрипте.

Хотите устранить неполадки, почему часть приложения не работает? Выполните операцию из командной строки и протестируйте ее изолированно.

Раз уж мы заговорили о тестировании…

Тестирование компонентов

Хотя вы можете писать модульные тесты на языке, который вы компилируете в WebAssembly, wick поставляется с собственной средой тестирования, что упрощает добавление тестов.

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

tests:
  - name: basic_tests
    cases:

      - name: basic_equality
        operation: echo
        inputs:
          - name: input
            value: 'Hello, world!'
        outputs:
          - name: output
            value: 'Hello, world!'

      - name: assertions
        operation: echo
        inputs:
          - name: input
            value:
              string_value: Hello! 
              number: 42
        outputs:
          - name: output
            assertions:
              - operator: Contains
                value: { string_value: Hello! }
              - operator: LessThan
                path: number
                value: 100

Wick печатает результаты тестов в формате TAP — Test Anything Protocol. TAP существует уже несколько десятилетий, и большинство инструментов CI/CD поддерживают вывод TAP «из коробки».

Выводим «безопасность по умолчанию» на новый уровень

Я увлечен безопасностью приложений, но пришло время быть честными с самими собой. Мы по-прежнему становимся жертвами уязвимостей, которые прекрасно понимали в 90-х годах. Нам нужно быть более агрессивными.

Уик — это не панацея, но мы потратили сотни часов на разработку решений, которые предоставляют все возможности, необходимые разработчикам, сохраняя при этом меры безопасности и функции, необходимые для автоматической защиты приложений.

Такие функции, как:

  • Явно настроенные ресурсы.
    Разработчики явно определяют базовые URL-адреса, каталоги, файлы, порты и т. д. как часть конфигурации компонента. Уик проверяет и обрабатывает ресурсы еще до того, как компоненты запустятся, не говоря уже о получении доступа.
  • Песочница.
    Wick помещает компоненты в песочницу и предоставляет каждому отдельные разрешения и доступ.
  • Безопасные API по своей конструкции
    Wick делает невозможными такие уязвимости, как внедрение SQL или манипулирование путями.
  • Узкие места
    Передавать конфигурацию в виде переменных ENV — лучшая практика, но предоставление всем зависимостям доступа ко всем переменным ENV может — в лучшем случае — привести к трудновоспроизводимым проблемам и уязвимостям на худший. Вик позволяет только корневому приложению получить доступ к среде. Отсюда конфигурация переходит к компонентам.

Многие из этих проектов уже являются передовыми практиками и рекомендациями. Уик просто считает рекомендуемый способ сделать это единственным способом сделать это.

Безопасный аудит приложений

Команда wick config audit одним махом выводит список всех ресурсов, используемых приложением.

Команды DevOps и безопасности могут независимо проверять и проверять приложение, вообще не запуская и не просматривая исходный код.

Защита приложения на уровне компонента

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

Допустим, вы хотите интегрировать зависимость, которая выполняет запросы с нового URL-адреса или требует доступа к файловой системе. Вам не нужно предоставлять доступ ко всему приложению, а только к тому компоненту, которому он нужен.

wick config audit удобно принимает флаг --lockdown и успешно генерирует (проходящую) конфигурацию блокировки из отчета об аудите.

kind: wick/lockdown@v1
resources:
- kind: wick/resource/tcpport@v1
  address: 0.0.0.0
  port: '8999'
  components: [__local__] # __local__ is the root app context

- kind: wick/resource/url@v1
  allow: https://login.microsoftonline.com/organizations/oauth2/v2.0/token
  components: [oauth]

- kind: wick/resource/url@v1
  allow: http://localhost:5173/
  components: [__local__]

- kind: wick/resource/url@v1
  allow: mssql://account.database.windows.net:1433/database
  components: [reports, users]

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

И многое другое

С wick можно поговорить о многом благодаря таким функциям, как:

  • Распределенные компоненты
  • wick install
  • Wick-триггеры для HTTP-серверов, команд CLI и заданий cron.
  • Как автоматически генерировать артефакты, такие как спецификации OpenAPI.
  • Облачный сервис и реестр Candle
  • Ведение журнала и отслеживание
  • Компоненты для автоматического добавления таких функций, как OAuth, разрешения и платежи.
  • Будущее WebAssembly и компонентной модели.
  • Субстримы!
  • И более!

Мы уже несколько месяцев внедряем приложения Wick в производство. В дорожной карте еще многое предстоит сделать, и я с нетерпением жду того, что будет дальше.

Обязательно ознакомьтесь с wick on github, документацией wick на candle.dev и присоединяйтесь к нашему discord-серверу!

Спасибо!