Веб — это поистине уникальная платформа для приложений. Приложения, созданные на его основе, мгновенно доступны на любой операционной системе без каких-либо изменений кода или компиляции. Когда пользователь заходит в ваше приложение, у него всегда есть самая актуальная версия. Приложения можно установить и использовать в автономном режиме, они обладают широкими возможностями и легко распространяются по ссылке. Создайте веб-приложение, и оно будет работать везде.
Поскольку веб-пространство по умолчанию стремится к безопасности , его модель безопасности должна быть очень консервативной. Любые новые возможности должны быть безопасны для случайного пользователя, который может столкнуться с ними через URL-адрес. Мы называем эту модель безопасности « безопасностью через веб-пространство» . Хотя она отлично подходит для многих приложений и может быть повышена безопасность с помощью политик безопасности контента и междоменной изоляции , она не работает для всех случаев. Ряд действительно важных и мощных API, таких как Direct Sockets и Controlled Frame , которые необходимы разработчикам, не могут быть достаточно безопасными для «безопасности через веб-пространство».
Для этих приложений в настоящее время нет возможности разработки на веб-платформе. Для других же модель безопасности веб-приложений может быть недостаточно консервативной; они могут не разделять предположение о надежности сервера и предпочитать автономные приложения с дискретными версиями и подписями. Необходима новая модель безопасности с высоким уровнем доверия. Изолированные веб-приложения (IWA) предоставляют изолированную, объединенную, версионированную, подписанную и доверенную модель приложений, построенную на основе существующей веб-платформы, что позволяет разработчикам использовать эту модель.
Спектр доверия в интернете
Безопасность и функциональные возможности в интернете можно рассматривать как спектр.

Веб -приложения, устанавливаемые через браузер ( слева), имеют самую низкую степень доверия к системе пользователя, поскольку они должны быть максимально доступными и, следовательно, имеют наименьший доступ к системе пользователя. Веб-приложения, устанавливаемые через браузер (посередине), пользуются немного большим доверием и могут быть интегрированы в систему пользователя немного глубже. Пользователи, как правило, могут без проблем переключаться между веб-версиями приложений, устанавливаемыми через браузер, и версиями, устанавливаемыми через браузер.
Затем идут высоконадежные изолированные веб-приложения.
Они работают и ощущаются как нативные приложения и могут получить доступ к глубокой системной интеграции и мощным возможностям. Пользователи не могут переключаться между ними и веб-версиями. Если вам нужен такой уровень безопасности или такие возможности, пути назад нет.
При выборе оптимального варианта на этом спектре следует отдавать предпочтение модели безопасности с наименьшим уровнем доверия, например, прогрессивному веб-приложению (PWEP) . Это обеспечит вам наибольший охват, потребует от вас наименьшего количества задач по обеспечению безопасности и будет наиболее гибким вариантом для разработчиков и пользователей.
Безопасность по замыслу
Изолированные веб-приложения обеспечивают модель безопасности с высоким уровнем доверия для веб-приложений. Однако для этого необходимо переосмыслить некоторые предположения, лежащие в основе развития веб-технологий в отношении доверия. Основные компоненты веб-приложений, такие как серверы и DNS, больше не могут считаться надежными. Векторы атак, которые могут казаться более актуальными для нативных приложений, внезапно становятся важными. Таким образом, для доступа к новой модели безопасности с высоким уровнем доверия, предоставляемой изолированными веб-приложениями, веб-приложения необходимо упаковывать, изолировать и защищать.
Упакованный
Страницы и ресурсы для изолированных веб-приложений не могут обслуживаться с работающих серверов или загружаться по сети, как обычные веб-приложения. Вместо этого, чтобы получить доступ к новой модели безопасности с высоким уровнем доверия, веб-приложениям необходимо упаковывать все необходимые для работы ресурсы в подписанный веб-пакет (Signed WebBundle) . Подписанные веб-пакеты берут все ресурсы, необходимые для работы сайта, и упаковывают их вместе в файл .swbn , объединяя их с блоком целостности . Это позволяет безопасно загружать веб-приложение целиком и даже совместно использовать или устанавливать его в автономном режиме.
Однако это создает проблему для проверки подлинности кода сайта: для работы ключей TLS требуется подключение к интернету. Вместо ключей TLS, IWA подписываются ключом, который можно безопасно хранить в автономном режиме. Хорошая новость заключается в том, что, если вы сможете собрать все свои рабочие файлы в папку, вы сможете превратить ее в IWA без особых изменений.
Сгенерировать ключи подписи
Ключи подписи представляют собой пары ключей Ed25519 или ECDSA P-256, при этом закрытый ключ используется для подписи пакета, а открытый ключ — для проверки пакета. Для генерации и шифрования ключа Ed25519 или ECDSA P-256 можно использовать OpenSSL :
# Generate an unencrypted Ed25519 key
openssl genpkey -algorithm Ed25519 -out private_key.pem
# or generate an unencrypted ECDSA P-256 key
openssl ecparam -name prime256v1 -genkey -noout -out private_key.pem
# Encrypt the generated key. This will ask for a passphrase, make sure to use a strong one
openssl pkcs8 -in private_key.pem -topk8 -out encrypted_key.pem
# Delete the unencrypted key
rm private_key.pem
Ключи подписи также выполняют второстепенную функцию. Поскольку домен может быть уязвим для потери контроля, как сервер, его нельзя использовать для идентификации установленного IWA. Вместо этого IWA идентифицируется открытым ключом пакета, который является частью его подписи и связан с закрытым ключом. Это существенное изменение в работе механизма защиты веб-сайтов от взлома, поэтому вместо HTTPS IWA используют новую схему : isolated-app:// .
Объедините ваше приложение в пакет.
Получив ключ подписи, пришло время упаковать ваше веб-приложение. Для этого вы можете использовать официальные пакеты NodeJS для упаковки, а затем подписи ваших IWA ( также доступны инструменты командной строки Go ). Сначала используйте пакет wbn , указав папку, содержащую все файлы вашего IWA (здесь dist), чтобы упаковать их в неподписанный пакет:
npx wbn --dir dist
Это сгенерирует неподписанный веб-пакет из этой директории в out.wbn. После генерации используйте зашифрованный ключ Ed25519 или ECDSA P-256, который вы создали ранее, для подписи с помощью wbn-sign :
npx wbn-sign -i out.wbn -k encrypted_key.pem -o signed.swbn
Это позволит сгенерировать подписанный веб-пакет из неподписанного веб-пакета под названием signed.swbn . После подписания инструмент также выведет идентификатор веб-пакета и его источник в изолированном веб-приложении. Источник в изолированном веб-приложении определяет, как ваше изолированное веб-приложение идентифицируется в браузере.
Web Bundle ID: ggx2sheak3vpmm7vmjqnjwuzx3xwot3vdayrlgnvbkq2mp5lg4daaaic
Isolated Web App Origin: isolated-app://ggx2sheak3vpmm7vmjqnjwuzx3xwot3vdayrlgnvbkq2mp5lg4daaaic/
Если вы используете Webpack , Rollup или инструмент, поддерживающий их плагины (например, Vite ), вы можете использовать один из плагинов сборщика ( Webpack , Rollup ), который оборачивает эти пакеты, вместо того, чтобы вызывать их напрямую. В этом случае в результате сборки будет сгенерирован подписанный пакет.
Протестируйте своё приложение
Вы можете протестировать свой IWA двумя способами: либо запустив сервер разработки через встроенный в Chrome прокси-сервер разработчика IWA, либо установив встроенный IWA. Для этого вам потребуется Chrome или ChromeOS версии 120 или выше, включить флаги IWA и установить приложение через Web App Internals в Chrome.
- Включите флаг
chrome://flags/#enable-isolated-web-app-dev-mode - Проверьте работу вашей внутренней структуры веб-приложений (IWA), перейдя на страницу внутренних компонентов веб-приложений Chrome по адресу
chrome://web-app-internals
На странице «Внутренние компоненты веб-приложения» у вас есть два варианта: Install IWA with Dev Mode Proxy или Install IWA from Signed Web Bundle .
При установке через прокси-сервер в режиме разработчика вы можете установить любой URL-адрес, включая сайты, работающие с локального сервера разработки, в виде IWA (Integrated Web Bundle), без их объединения в пакет, при условии, что они соответствуют другим требованиям для установки IWA. После установки IWA для этого URL-адреса будет добавлен в вашу систему с правильными политиками безопасности и ограничениями, а также доступом к API, доступным только для IWA. Ему будет присвоен случайный идентификатор. В этом режиме также доступны инструменты разработчика Chrome, которые помогут вам отлаживать ваше приложение. При установке из подписанного веб-пакета (Signed Web Bundle) вы загрузите свой подписанный, объединенный IWA, и он установится так, как если бы его скачал конечный пользователь.
На странице «Внутренние настройки веб-приложения» вы также можете принудительно запустить проверку обновлений для любых приложений, установленных через прокси-сервер в режиме разработчика или из подписанного веб-пакета, чтобы протестировать процесс обновления.
Изолированный
Доверие — ключевой фактор для изолированных веб-приложений. Начинается это с того, как они работают. У пользователей разные представления о том, что приложение может и должно делать, в зависимости от того, работает ли оно в браузере или в отдельном окне, и они, как правило, считают, что автономные приложения имеют больший доступ и обладают большими возможностями. Поскольку изолированные веб-приложения могут получить доступ к API с высоким уровнем доверия, они должны работать в отдельном окне, чтобы соответствовать этой модели мышления. Это визуально отделяет их от браузера. Но это выходит за рамки просто визуального разделения.
Изолированные веб-приложения (IWA) работают по отдельному протоколу, отличному от веб-сайтов, работающих в браузере ( isolated-app против http или https ). Это означает, что каждое IWA полностью отделено от веб-сайтов, работающих в браузере, даже если они созданы одной и той же компанией, благодаря политике одного источника . Хранилище IWA также отделено друг от друга. В совокупности это гарантирует, что контент из разных источников не может просачиваться между различными IWA или между IWA и обычным контекстом просмотра пользователя.
Однако ни изоляция, ни объединение и подписание кода сайта не помогут установить доверие, если IWA может загрузить и запустить произвольный код после установки. Чтобы обеспечить это, одновременно позволяя IWA подключаться к другим сайтам для получения контента, IWA применяют строгий набор политик безопасности контента :
- Разрешается запускать только JavaScript из пакета; однако, это позволяет запускать Wasm независимо от его источника. (
script-src) - Позволяет JavaScript получать данные из защищенных доменов, отличных от локального хоста, подключаться к конечным точкам WebSocket и WebTransport , а также к URL-адресам BLOB-объектов и данных (
connect-src). - Защита от атак межсайтового внедрения скриптов (XSS) в DOM путем регулирования способов использования функций манипулирования DOM (
require-trusted-types-for). - Разрешает использование фреймов, изображений, аудио и видео с любого HTTPS-домена (
frame-src,img-src,media-src). - Разрешает использование шрифтов из пакета и BLOB-объектов (
font-src). - Разрешить использование встроенных CSS-стилей или CSS-стилей из пакета (
style-src). - Элементы
<object>,<embed>и<base>использовать нельзя (object-srcиbase-uri). - Разрешает использовать ресурсы из пакета только для других запросов, подпадающих под действие CSP (
default-src).
Content-Security-Policy: script-src 'self' 'wasm-unsafe-eval';
connect-src 'self' https: wss: blob: data:;
require-trusted-types-for 'script';
frame-src 'self' https: blob: data:;
img-src 'self' https: blob: data:;
media-src 'self' https: blob: data:;
font-src 'self' blob: data:;
style-src 'self' 'unsafe-inline';
object-src 'none';
base-uri 'none';
default-src 'self';
Этих CSP недостаточно для полной защиты от потенциально вредоносного кода третьих лиц. IWA также обеспечивают междоменную изоляцию , устанавливая заголовки, которые уменьшают возможность воздействия на них со стороны ресурсов третьих лиц:
- Разрешайте доступ только к ресурсам из пакета или к ресурсам из других источников, явно помеченным как поддерживающие CORS либо с помощью заголовка политики ресурсов из других источников (CORP), либо с помощью атрибута
crossorigin. (Cross-Origin-Embedder-Policy) - Запретить междоменные запросы без CORS (
Cross-Origin-Resource-Policy) - Изолируйте контекст просмотра от документов из разных источников, предотвращая ссылки на window.opener и доступ к глобальным объектам (
Cross-Origin-Opener-Policy). - Предотвратите встраивание сайта во фрейм или iframe (CSP,
frame-ancestors).
Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Embedder-Policy: require-corp
Cross-Origin-Resource-Policy: same-origin
Content-Security-Policy: frame-ancestors 'self'
Даже при наличии этих ограничений существует еще одна потенциальная атака, от которой защищают IWA: атаки с нарушением последовательности. Атака с нарушением последовательности происходит, когда вредоносный контент третьих лиц пытается создать запутанный и потенциально уязвимый пользовательский опыт, переходя на страницу неожиданным способом, например, напрямую на внутреннюю страницу настроек. IWA предотвращают это, запрещая произвольные глубокие ссылки с внешних сайтов и разрешая открывать приложения только через четко определенные точки входа, такие как start_url , обработчик протокола , целевой объект для обмена или обработчик запуска .
В режиме изоляции
Упаковка и изоляция обеспечивают набор гарантий относительно того, что разрешено запускать и откуда это взялось, но динамический характер разрешений в интернете означает, что сами по себе они не могут гарантировать, что веб-приложение использует только необходимые ему возможности. Поскольку разные возможности имеют разные аспекты безопасности, пользователю или администратору следует проверять, какие разрешения может использовать интегрированное веб-приложение, так же, как это можно сделать с другими нативными приложениями, такими как Android и iOS, перед установкой или обновлением приложения.
Для этого изолированные веб-приложения по умолчанию блокируют все запросы на получение разрешений. Разработчики могут затем включить необходимые им разрешения, добавив поле permissions_policy в манифест своего веб-приложения. Это поле содержит пары ключ/значение директив политики разрешений и списков разрешений для каждого разрешения, которое может запросить изолированное веб-приложение или любой дочерний фрейм , например, управляемый фрейм или iframe. Добавление разрешения сюда не предоставляет его автоматически; вместо этого оно делает его доступным для запроса при получении запроса на эту возможность.
Рассмотрим в качестве примера разработку веб-приложения для отслеживания автопарка. Вам может потребоваться, чтобы ваше веб-приложение могло запрашивать местоположение пользователя, а встроенная карта также могла запрашивать местоположение. Кроме того, вы можете захотеть, чтобы любой встроенный сайт мог разворачиваться на весь экран для обеспечения полного погружения пользователя. Для этого вам потребуется настроить следующую политику разрешений в манифесте вашего веб-приложения:
"permissions_policy": {
"geolocation": [ "self", "https://map.example.com" ],
"fullscreen": [ "*" ]
}
Поскольку WebBundles также могут указывать заголовки Permissions Policy , будут разрешены только те разрешения, которые указаны в обоих списках, и только источники, включенные в списки разрешений, будут разрешены в обоих списках.
Именованный и версионированный
Обычные веб-приложения используют доменное имя для идентификации пользователей и могут быть обновлены путем изменения кода, размещенного на этом домене. Однако из-за ограничений безопасности, связанных с изолированными веб-приложениями, идентификация и обновления должны обрабатываться иначе. Как и прогрессивные веб-приложения, изолированные веб-приложения нуждаются в файле Web App Manifest для идентификации пользователей.
манифест веб-приложения
Изолированные веб-приложения используют те же ключевые свойства манифеста , что и PWA, с некоторыми незначительными отличиями. Например, display работает немного иначе: и browser , и minimal-ui принудительно отображаются в режиме minimal-ui , а fullscreen и standalone в режиме standalone (дополнительные параметры display_override работают как положено). Кроме того, следует включить еще два поля: version и update_manifest_url :
-
version: Обязательно для изолированных веб-приложений. Строка, состоящая из одного или нескольких целых чисел, разделенных точкой (.). Ваша версия может быть простой, например,1,2,3и т. д., или сложной, например, SemVer (1.2.3). Номер версии должен соответствовать регулярному выражению^(\d+.?)*\d$. -
update_manifest_url: Необязательное , но рекомендуемое поле, указывающее на HTTPS-адрес (илиlocalhostдля тестирования), где можно получить манифест обновления веб-приложения.
Минимальный манифест веб-приложения для изолированного веб-приложения может выглядеть примерно так:
{
"name": "IWA Kitchen Sink",
"version": "0.1.0",
"update_manifest_url": "https://example.com/updates.json",
"start_url": "/",
"icons": [
{
"src": "/images/icon.png",
"type": "image/png",
"sizes": "512x512",
"purpose": "any"
},
{
"src": "/images/icon-mask.png",
"type": "image/png",
"sizes": "512x512",
"purpose": "maskable"
}
]
}
манифест обновления веб-приложения
Манифест обновления веб-приложения — это JSON-файл, описывающий каждую версию данного веб-приложения. JSON-объект содержит одно обязательное поле — version , представляющее собой список объектов, содержащих version , src и channels :
-
version— номер версии приложения, аналогичный полюversionв манифесте веб-приложения. -
src— URL-адрес HTTPS (илиlocalhostдля тестирования), указывающий на размещенный пакет для данной версии (файл.swbn). Относительные URL-адреса указываются относительно файла манифеста обновления веб-приложения. -
channels— Список строк, идентифицирующих канал обновления, к которому относится данная версия. Специальный каналdefaultиспользуется для описания основного канала, который будет применяться, если не выбран другой канал.
Вы также можете добавить поле channels — объект с идентификаторами ваших каналов, содержащий необязательное свойство name для каждого идентификатора, чтобы указать удобочитаемое имя (включая имя для канала default ). Канал, не содержащий свойства name или не включенный в объект channels , использует свой идентификатор в качестве имени.
Минимальный манифест обновления может выглядеть примерно так:
{
"versions": [
{
"version": "5.2.17",
"src": "https://cdn.example.com/app-package-5.2.17.swbn",
"channels": ["next", "5-lts", "default"]
},
{
"version": "5.3.0",
"src": "v5.3.0/package.swbn",
"channels": ["next", "default"]
},
{
"version": "5.3.1",
"src": "v5.3.1/package.swbn",
"channels": ["next"]
},
],
"channels": {
"default": {
"name": "Stable"
},
"5-lts": {
"name": "5.x Long-term Stable"
}
}
}
В этом примере есть три канала: default , который будет помечен как Stable , 5-lts , который будет помечен как 5.x Long-term Stable , и next , который будет помечен как next . Если пользователь находится на канале 5-lts , он получит версию 5.2.17 , если он находится на канале default он получит версию 5.3.0 , а если он находится на канале next он получит версию 5.3.1 .
Манифесты обновления веб-приложения могут размещаться на любом сервере. Проверка обновлений производится каждые 4-6 часов.
Администратор управляет
На начальном этапе запуска изолированные веб-приложения можно будет установить на Chromebook, управляемые Chrome Enterprise, только администратором через панель администратора .
Для начала перейдите в панель администратора: Устройства > Chrome > Приложения и расширения > Пользователи и браузеры . На этой вкладке вы можете добавлять приложения и расширения из Chrome Web Store, Google Play и веб-браузеров для пользователей вашей организации. Добавление элементов осуществляется путем открытия желтой плавающей кнопки добавления ( + ) в правом нижнем углу экрана и выбора типа добавляемого элемента.
При открытии появится значок квадрата внутри квадрата с надписью « Добавить изолированное веб-приложение» . Щелкнув по нему, вы откроете модальное окно для добавления изолированного веб-приложения в ваше подразделение. Для этого вам потребуется две части информации: идентификатор веб-пакета изолированного веб-приложения (сгенерированный из открытого ключа вашего приложения и отображаемый после того, как приложение будет упаковано и подписано) и URL-адрес манифеста обновления веб-приложения для изолированного веб-приложения. После установки вам будет доступен стандартный набор параметров панели администратора для управления им:
- Политика установки : Как вы хотите установить IWA: принудительно, принудительно установить и закрепить на панели ChromeOS или запретить установку.
- Запуск при входе в систему : Как вы хотите, чтобы IWA запускалась: разрешить пользователю запускать её вручную, принудительно запускать IWA при входе пользователя в систему, но позволять ему её закрыть, или принудительно запускать при входе пользователя в систему и не допускать её закрытия.
После сохранения приложение будет установлено при следующем обновлении политики для Chromebook в этом подразделении. После установки устройство пользователя будет проверять наличие обновлений в веб-интерфейсе обновления приложений каждые 4-6 часов.
Помимо принудительной установки IWA, вы также можете автоматически предоставлять им некоторые разрешения аналогично другим веб-приложениям. Для этого перейдите в «Устройства» > «Chrome» > «Веб-возможности» и нажмите кнопку «Добавить источник» . В Origin / site pattern field вставьте идентификатор веб-пакета IWA (в качестве протокола автоматически будет добавлен isolated-app:// ). После этого вы можете установить уровни доступа к различным API (разрешено/заблокировано/не задано), включая управление окнами, управление локальными шрифтами и API мониторинга экрана . Для API, которые могут потребовать дополнительного согласия администратора для включения, например, обязательного API мониторинга экрана, появится дополнительное диалоговое окно для подтверждения вашего выбора. После завершения сохраните изменения, и ваши пользователи смогут начать использовать ваш IWA!
Работа с расширениями
Хотя изолированные веб-приложения (IWA) не работают с расширениями «из коробки», вы можете подключить к ним принадлежащие вам расширения. Для этого вам потребуется отредактировать файл манифеста расширения. Раздел externally_connectable в манифесте определяет, с какими внешними веб-страницами или другими расширениями Chrome может взаимодействовать ваше расширение. Добавьте источник вашего IWA в поле matches в externally_connectable (обязательно укажите схему isolated-app:// ):
{
"externally_connectable": {
"matches": ["isolated-app://79990854-bc9f-4319-a6f3-47686e54ed29/*"]
}
}
Хотя это позволит вашему расширению работать в изолированном веб-приложении, это не позволит ему внедрять в него контент; вы будете ограничены передачей сообщений между расширением и вашим изолированным веб-приложением.