API keys rotation

Назначение и необходимость ротации ключей

Mapbox GL JS использует токены доступа (Access Tokens) для авторизации запросов к сервисам платформы Mapbox. Каждый запрос на загрузку стилей, тайлов, геокодирование, маршрутизацию и другие сервисы проходит через механизм проверки токена.

Ротация API-ключей (API Keys Rotation) представляет собой процесс регулярной замены используемых токенов новыми. Такая практика относится к базовым мерам обеспечения безопасности современных веб-приложений.

Основные причины внедрения ротации:

  • снижение риска компрометации токенов;
  • ограничение последствий утечки ключа;
  • соблюдение корпоративных требований безопасности;
  • управление жизненным циклом учетных данных;
  • разделение доступа между различными окружениями;
  • упрощение отзыва скомпрометированных токенов.

Даже если токен является публичным и используется на стороне клиента, его компрометация способна привести к:

  • несанкционированному использованию квоты;
  • увеличению расходов;
  • превышению лимитов запросов;
  • нарушениям политики безопасности организации.

Типы токенов Mapbox

В экосистеме Mapbox используются два основных типа токенов.

Public Token

Публичный токен предназначен для клиентских приложений:

pk.eyJ1IjoiZXhhbXBsZSIsImEiOiJja2FiYzEyMzQ1In0.xxxxxxxxxxxxxxxxx

Особенности:

  • безопасен для размещения в браузере;
  • используется в большинстве проектов на Mapbox GL JS;
  • поддерживает настройку ограничений доступа;
  • может быть привязан к определенным URL-адресам.

Secret Token

Секретный токен используется исключительно на серверной стороне:

sk.eyJ1IjoiZXhhbXBsZSIsImEiOiJja2FiYzEyMzQ1In0.xxxxxxxxxxxxxxxxx

Особенности:

  • никогда не должен попадать в браузер;
  • предоставляет расширенные права;
  • применяется для административных операций;
  • требует строгого контроля доступа.

Ротация особенно важна для секретных токенов, однако публичные токены также рекомендуется регулярно обновлять.


Архитектура хранения токенов

Неправильный подход

Жесткое встраивание токена непосредственно в код:

mapboxgl.accessToken =
    'pk.eyJ1IjoiZXhhbXBsZSIsImEiOiJja2FiYzEyMzQ1In0.xxxxxxxxx';

Недостатки:

  • сложность обновления;
  • необходимость повторной сборки приложения;
  • риск использования устаревшего токена;
  • невозможность централизованного управления.

Более гибкий подход через конфигурацию

const config = {
    mapboxToken: window.APP_CONFIG.MAPBOX_TOKEN
};

mapboxgl.accessToken = config.mapboxToken;

Преимущества:

  • централизованное управление;
  • независимость от исходного кода;
  • возможность динамического обновления.

Использование переменных окружения

При работе с современными сборщиками:

mapboxgl.accessToken = process.env.MAPBOX_ACCESS_TOKEN;

или:

mapboxgl.accessToken =
    import.meta.env.VITE_MAPBOX_ACCESS_TOKEN;

Подобная архитектура значительно упрощает процедуру ротации.


Жизненный цикл токена

Грамотно организованная ротация основывается на контролируемом жизненном цикле ключей.

Типичная схема:

Создание токена
        ↓
Развертывание
        ↓
Эксплуатация
        ↓
Мониторинг
        ↓
Создание нового токена
        ↓
Переключение клиентов
        ↓
Удаление старого токена

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


Стратегия Zero Downtime Rotation

Наиболее безопасной считается стратегия ротации без простоя.

Последовательность действий:

  1. Создается новый токен.
  2. Новый токен распространяется по окружениям.
  3. Проверяется работоспособность.
  4. Выполняется переключение клиентов.
  5. Старый токен остается активным некоторое время.
  6. После завершения миграции старый токен удаляется.

Схематично процесс выглядит следующим образом:

Старый токен: [=======================]

Новый токен:             [=======================]

Период перекрытия:       [======]

Перекрытие гарантирует отсутствие отказов во время обновления.


Динамическая загрузка токена

Получение токена с сервера

Вместо хранения ключа внутри приложения возможно получение его через API.

async function getMapboxToken() {
    const response = await fetch('/api/mapbox-token');

    const data = await response.json();

    return data.token;
}

Использование:

const token = await getMapboxToken();

mapboxgl.accessToken = token;

Преимущества:

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

Автоматическая ротация через конфигурационный сервис

Во многих корпоративных системах используется отдельный сервис конфигурации.

Пример получения настроек:

async function loadConfiguration() {
    const response = await fetch('/config');

    return response.json();
}

const config = await loadConfiguration();

mapboxgl.accessToken = config.mapbox.token;

После обновления конфигурации новое значение начинает использоваться автоматически.


Проверка актуальности токена

Перед инициализацией карты полезно выполнять валидацию.

async function validateToken(token) {
    try {
        const response = await fetch(
            `https://api.mapbox.com/styles/v1/mapbox/streets-v12?access_token=${token}`
        );

        return response.ok;
    } catch {
        return false;
    }
}

Использование:

const isValid = await validateToken(token);

if (!isValid) {
    throw new Error('Invalid Mapbox token');
}

Такая проверка помогает обнаружить ошибки еще до отображения карты.


Автоматическое переключение на резервный токен

Иногда применяется механизм аварийного переключения.

const primaryToken =
    window.CONFIG.primaryToken;

const backupToken =
    window.CONFIG.backupToken;

Логика выбора:

async function initializeMap() {
    const primaryValid =
        await validateToken(primaryToken);

    const token = primaryValid
        ? primaryToken
        : backupToken;

    mapboxgl.accessToken = token;
}

Подобная схема повышает отказоустойчивость системы.


Использование ограничений токена

Mapbox позволяет задавать ограничения для токенов.

Наиболее распространенные варианты:

  • ограничение по домену;
  • ограничение по API;
  • ограничение по набору разрешений;
  • ограничение по окружению.

Например:

production.example.com
staging.example.com

Для разных окружений рекомендуется создавать отдельные токены.


Разделение токенов по окружениям

Development

MAPBOX_TOKEN_DEV

Staging

MAPBOX_TOKEN_STAGING

Production

MAPBOX_TOKEN_PRODUCTION

Выбор выполняется автоматически:

const tokenMap = {
    development: process.env.MAPBOX_TOKEN_DEV,
    staging: process.env.MAPBOX_TOKEN_STAGING,
    production: process.env.MAPBOX_TOKEN_PRODUCTION
};

mapboxgl.accessToken =
    tokenMap[process.env.NODE_ENV];

Такой подход предотвращает случайное использование производственного токена в тестовых средах.


Реализация плановой ротации

Во многих организациях устанавливаются сроки жизни ключей:

Тип окружения Период
Development 30 дней
Staging 60 дней
Production 90 дней
Критические сервисы 30–60 дней

Конкретные значения зависят от требований безопасности компании.


Мониторинг использования токенов

Эффективная ротация невозможна без наблюдения за активностью.

Контролируются:

  • количество запросов;
  • всплески активности;
  • необычные источники трафика;
  • ошибки авторизации;
  • превышение лимитов.

При обнаружении подозрительной активности может потребоваться внеплановая ротация.


Обработка ошибок авторизации

При работе с Mapbox GL JS следует отслеживать ошибки загрузки ресурсов.

Пример:

map.on('error', (event) => {
    console.error(event.error);
});

Более детальная обработка:

map.on('error', (event) => {
    if (
        event.error &&
        event.error.status === 401
    ) {
        console.error(
            'Mapbox token expired or invalid'
        );
    }
});

Ошибки авторизации часто становятся первым признаком проблем после ротации.


Обновление токена без перезагрузки страницы

В некоторых приложениях требуется замена ключа во время работы.

Пример:

async function refreshToken() {
    const token = await getMapboxToken();

    mapboxgl.accessToken = token;
}

Периодическое обновление:

setInterval(
    refreshToken,
    1000 * 60 * 60
);

В этом случае приложение может получать новый токен без полной перезагрузки.


Централизованный менеджер токенов

Для крупных проектов полезно выделять отдельный класс.

class TokenManager {
    constructor() {
        this.token = null;
    }

    async load() {
        const response =
            await fetch('/api/token');

        const data =
            await response.json();

        this.token = data.token;
    }

    getToken() {
        return this.token;
    }

    async refresh() {
        await this.load();
    }
}

Использование:

const manager =
    new TokenManager();

await manager.load();

mapboxgl.accessToken =
    manager.getToken();

Преимущества:

  • единая точка управления;
  • упрощение тестирования;
  • удобство расширения логики ротации.

Ротация в CI/CD

Автоматизация часто реализуется через конвейеры развертывания.

Типичный процесс:

Pipeline Start
       ↓
Create New Token
       ↓
Store In Secrets
       ↓
Deploy Application
       ↓
Health Check
       ↓
Revoke Old Token
       ↓
Pipeline Finish

Интеграция с CI/CD позволяет исключить ручные операции и уменьшить вероятность ошибок.


Типичные ошибки при ротации

Немедленное удаление старого токена

Неверно:

Создать новый токен
↓
Удалить старый токен
↓
Обновить приложение

Возможны массовые ошибки авторизации.


Один токен для всех окружений

Проблемы:

  • высокий риск компрометации;
  • сложность аудита;
  • невозможность независимой ротации.

Хранение секретных токенов в клиентском коде

Недопустимый пример:

const secretToken =
    'sk.xxxxxxxxxxxxxxxxx';

Секретные токены никогда не должны попадать в браузер.


Отсутствие мониторинга

Без контроля использования невозможно определить:

  • факт компрометации;
  • неиспользуемые токены;
  • ошибки после обновления;
  • несанкционированную активность.

Рекомендуемая схема для production

Архитектура корпоративного уровня обычно выглядит следующим образом:

Mapbox Token
      ↓
Secrets Manager
      ↓
Configuration Service
      ↓
Backend API
      ↓
Mapbox GL JS Client

Ключевые характеристики такой схемы:

  • централизованное хранение;
  • автоматическая ротация;
  • аудит использования;
  • разделение окружений;
  • аварийное переключение;
  • отсутствие простоев при обновлении;
  • минимизация последствий компрометации токенов.

При использовании Mapbox GL JS ротация API-ключей должна рассматриваться как постоянный процесс управления безопасностью, а не как разовая административная операция. Регулярное обновление токенов, контроль их использования и автоматизация жизненного цикла позволяют обеспечить устойчивую работу картографических сервисов даже в крупных распределенных приложениях.