Что такое сервисный аккаунт и зачем он нужен в 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)
- Откройте Google Cloud Console.
Создание нового проекта GCP или выбор существующего
- Если у вас еще нет проекта GCP, создайте новый. Дайте ему понятное имя, например, «Apps Script Service Account Project».
- Если проект уже есть, выберите его.
Создание сервисного аккаунта в GCP
- В меню навигации GCP выберите IAM & Admin -> Service Accounts.
- Нажмите CREATE SERVICE ACCOUNT.
- Введите имя сервисного аккаунта, например, «apps-script-service-account».
- При необходимости добавьте описание.
- Нажмите CREATE AND CONTINUE.
Предоставление сервисному аккаунту необходимых разрешений (ролей) для доступа к Google Workspace (Drive, Sheets и т.д.)
- На странице Grant this service account access to project назначьте необходимые роли. Например, для доступа к Google Sheets потребуется роль Storage Object Viewer (для доступа к ресурсам) и, возможно, Editor (для изменения данных). Для доступа к Google Drive потребуется роль Drive API. Важно! Предоставляйте сервисному аккаунту только минимально необходимые права. Избегайте роли Owner, если в ней нет крайней необходимости.
- Нажмите CONTINUE.
- На странице Grant users access to this service account можно добавить пользователей, которые будут иметь право управлять этим сервисным аккаунтом. Это не обязательно, но может быть полезно в командной работе.
- Нажмите DONE.
Генерация ключа JSON для сервисного аккаунта
- Найдите только что созданный сервисный аккаунт в списке.
- Нажмите на его имя.
- Перейдите на вкладку KEYS.
- Нажмите ADD KEY -> Create new key.
- Выберите JSON в качестве типа ключа.
- Нажмите 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:
- Нажмите Services (значок
+рядом с Services в редакторе скриптов). - Найдите и добавьте сервис 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 или другие инструменты для сбора и анализа логов.