Google Apps Script: Как использовать сервисный аккаунт?

Что такое сервисный аккаунт и зачем он нужен в Google Apps Script?

Объяснение понятия сервисного аккаунта

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

Преимущества использования сервисного аккаунта в Apps Script

  • Автоматизация: Сервисные аккаунты идеально подходят для автоматизации задач, которые не требуют вмешательства пользователя, таких как регулярный экспорт данных из Google Sheets в базу данных или автоматическое создание отчетов.
  • Доступ к ресурсам без авторизации пользователя: Сервисный аккаунт позволяет скрипту работать от своего имени, не требуя постоянного подтверждения прав доступа пользователем. Это особенно полезно для скриптов, работающих по расписанию (через триггеры).
  • Работа с несколькими доменами: Сервисный аккаунт может быть настроен для доступа к ресурсам в разных доменах Google Workspace, что полезно для интеграций между компаниями или отделами.

Сравнение сервисного аккаунта с обычным аккаунтом пользователя в контексте Apps Script

| Характеристика | Обычный аккаунт пользователя | Сервисный аккаунт |
| ———————— | ————————— | ————————- |
| Аутентификация | Требуется ввод логина/пароля | Используется ключ JSON |
| Интерактивность | Предназначен для пользователей | Предназначен для приложений |
| Требуется ли согласие пользователя при первом запуске | Да | Нет, если предоставлены права администратором |
| Работа по расписанию | Требует авторизации пользователя | Идеален для этой цели |

Случаи, когда использование сервисного аккаунта предпочтительнее

  • Скрипты, работающие по расписанию (например, ночные бэкапы).
  • Интеграции между различными системами (например, передача данных из Google Sheets в CRM).
  • Массовое создание или изменение объектов Google Workspace (например, создание сотен документов Google Docs на основе шаблона).
  • Скрипты, которым требуется доступ к данным, к которым у пользователя нет прямого доступа (например, доступ к данным аналитики Google Analytics от имени аккаунта компании).

Создание и настройка сервисного аккаунта

Переход в Google Cloud Platform (GCP)

  1. Откройте Google Cloud Console.

Создание нового проекта GCP или выбор существующего

  • Если у вас еще нет проекта GCP, создайте новый. Дайте ему понятное имя, например, «Apps Script Service Account Project».
  • Если проект уже есть, выберите его.

Создание сервисного аккаунта в GCP

  1. В меню навигации GCP выберите IAM & Admin -> Service Accounts.
  2. Нажмите CREATE SERVICE ACCOUNT.
  3. Введите имя сервисного аккаунта, например, «apps-script-service-account».
  4. При необходимости добавьте описание.
  5. Нажмите CREATE AND CONTINUE.

Предоставление сервисному аккаунту необходимых разрешений (ролей) для доступа к Google Workspace (Drive, Sheets и т.д.)

  1. На странице Grant this service account access to project назначьте необходимые роли. Например, для доступа к Google Sheets потребуется роль Storage Object Viewer (для доступа к ресурсам) и, возможно, Editor (для изменения данных). Для доступа к Google Drive потребуется роль Drive API. Важно! Предоставляйте сервисному аккаунту только минимально необходимые права. Избегайте роли Owner, если в ней нет крайней необходимости.
  2. Нажмите CONTINUE.
  3. На странице Grant users access to this service account можно добавить пользователей, которые будут иметь право управлять этим сервисным аккаунтом. Это не обязательно, но может быть полезно в командной работе.
  4. Нажмите DONE.

Генерация ключа JSON для сервисного аккаунта

  1. Найдите только что созданный сервисный аккаунт в списке.
  2. Нажмите на его имя.
  3. Перейдите на вкладку KEYS.
  4. Нажмите ADD KEY -> Create new key.
  5. Выберите JSON в качестве типа ключа.
  6. Нажмите CREATE. Файл с ключом JSON будет автоматически загружен на ваш компьютер. Важно! Этот файл содержит конфиденциальную информацию. Храните его в безопасном месте и не передавайте третьим лицам.

Использование сервисного аккаунта в Google Apps Script

Установка библиотеки Script Properties

Рекомендуется использовать Script Properties для хранения конфиденциальной информации, такой как содержимое ключа JSON. Хранение ключа непосредственно в коде скрипта не безопасно.

Реклама
/**
 * Пример функции для сохранения ключа JSON в Script Properties.
 * @param {string} jsonKey - Ключ JSON в виде строки.
 */
function storeJsonKey(jsonKey: string): void {
  PropertiesService.getScriptProperties().setProperty('SERVICE_ACCOUNT_KEY', jsonKey);
}

/**
 * Пример функции для получения ключа JSON из Script Properties.
 * @returns {string} - Ключ JSON в виде строки.
 */
function getJsonKey(): string {
  return PropertiesService.getScriptProperties().getProperty('SERVICE_ACCOUNT_KEY');
}

Чтение данных ключа JSON в Apps Script

/**
 * Получает данные ключа JSON из Script Properties и преобразует их в объект.
 * @returns {object} - Объект с данными ключа JSON.
 */
function getServiceAccountCredentials(): object {
  const jsonKey: string = getJsonKey();
  if (!jsonKey) {
    throw new Error('JSON key not found in Script Properties.');
  }
  return JSON.parse(jsonKey);
}

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

Для аутентификации необходимо использовать библиотеку google-auth-library. Её можно установить через Apps Script IDE:

  1. Нажмите Services (значок + рядом с Services в редакторе скриптов).
  2. Найдите и добавьте сервис Google Cloud Resource Manager API и включите его.
/**
 * Аутентифицируется с использованием сервисного аккаунта и возвращает экземпляр клиента.
 * @param {string} scopes - Области доступа, необходимые для работы скрипта.
 * @returns {object} - Аутентифицированный клиент.
 */
function authenticate(scopes: string[]): object {
  const credentials = getServiceAccountCredentials();
  const auth = new googleAuth.GoogleAuth({
    credentials: credentials,
    scopes: scopes,
  });

  return auth.getClient();
}

Примеры кода: доступ к Google Sheets, Drive, Calendar и другим сервисам от имени сервисного аккаунта

/**
 * Пример доступа к Google Sheets от имени сервисного аккаунта.
 */
function accessGoogleSheets(): void {
  const scopes: string[] = ['https://www.googleapis.com/auth/spreadsheets'];
  const authClient: any = authenticate(scopes);
  const spreadsheetId: string = 'YOUR_SPREADSHEET_ID'; // Замените на ID вашей таблицы

  const sheets = google.sheets({
    version: 'v4',
    auth: authClient,
  });

  const request = {
    spreadsheetId: spreadsheetId,
    range: 'Sheet1!A1:B2',
    valueInputOption: 'USER_ENTERED',
    resource: {
      values: [
        ['Hello', 'World'],
        ['Apps', 'Script'],
      ],
    },
  };

  sheets.spreadsheets.values.update(request, (err: any, response: any) => {
    if (err) {
      console.log('The API returned an error: ' + err);
      return;
    }
    console.log(response.data);
  });
}

/**
 * Пример доступа к Google Drive от имени сервисного аккаунта.
 */
function accessGoogleDrive(): void {
  const scopes: string[] = ['https://www.googleapis.com/auth/drive'];
  const authClient: any = authenticate(scopes);

  const drive = google.drive({
    version: 'v3',
    auth: authClient,
  });

  drive.files.list({
    pageSize: 10,
    fields: 'nextPageToken, files(id, name)',
  }, (err: any, res: any) => {
    if (err) return console.log('The API returned an error: ' + err);
    const files = res.data.files;
    if (files.length) {
      console.log('Files:');
      files.forEach((file: any) => {
        console.log(`${file.name} (${file.id})`);
      });
    } else {
      console.log('No files found.');
    }
  });
}

Решение проблем и распространенные ошибки

Ошибка ‘The caller does not have permission’

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

Проблемы с аутентификацией и авторизацией

  • Проверьте правильность ключа JSON.
  • Убедитесь, что библиотека google-auth-library установлена и подключена.
  • Убедитесь, что scopes указаны правильно и соответствуют требуемым разрешениям.

Ограничения сервисных аккаунтов и способы их обхода

  • Сервисные аккаунты не могут выполнять действия, требующие участия пользователя (например, подтверждение условий использования сервиса).
  • У сервисных аккаунтов есть лимиты на использование API, аналогичные обычным аккаунтам. При превышении лимитов используйте экспоненциальную задержку (exponential backoff) для повторных попыток.

Вопросы безопасности при хранении и использовании ключа JSON

  • Не храните ключ JSON непосредственно в коде скрипта.
  • Используйте Script Properties или Vault для безопасного хранения ключа.
  • Ограничьте доступ к Script Properties, чтобы только авторизованные пользователи могли изменять ключ JSON.
  • Регулярно ротируйте ключи (создавайте новые и удаляйте старые).

Альтернативные подходы и лучшие практики

Использование Vault для безопасного хранения ключей

Vault – это инструмент для безопасного хранения секретов. Он позволяет хранить ключ JSON в зашифрованном виде и получать его только при необходимости. Интеграция Vault с Apps Script требует использования внешнего API.

Разделение ответственности и принципы минимальных привилегий

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

Мониторинг и логирование действий сервисного аккаунта

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


Добавить комментарий