Website: use shared Google API auth client in android proxy endpoints.#47810
Website: use shared Google API auth client in android proxy endpoints.#47810eashaw wants to merge 5 commits into
Conversation
There was a problem hiding this comment.
Claude Code Review
This repository is configured for manual code reviews. Comment @claude review to trigger a review and subscribe this PR to future pushes, or @claude review once for a one-time review.
Tip: disable this comment in your organization's Code Review settings.
There was a problem hiding this comment.
Pull request overview
This PR addresses repeated Google API auth client instantiation across the website’s Android Management API proxy endpoints by creating a single shared auth client at Sails lift time and reusing it for all AMAPI/PubSub requests.
Changes:
- Initialize and cache a shared Google API auth client on
sails.googleAuthClientduring server startup. - Update Android proxy controllers/helpers to pass
auth: sails.googleAuthClientintogoogle.androidmanagement()/google.pubsub()instead of recreatingGoogleAuthper request. - Remove per-request
google.options({ auth })usage, avoiding global mutable state per request.
Reviewed changes
Copilot reviewed 16 out of 16 changed files in this pull request and generated 15 comments.
Show a summary per file
| File | Description |
|---|---|
| website/api/hooks/custom/index.js | Creates the shared sails.googleAuthClient once at lift time using service account credentials and scopes. |
| website/api/helpers/android-proxy/get-is-enterprise-managed-by-fleet.js | Uses sails.googleAuthClient when constructing the Android Management API client. |
| website/api/controllers/android-proxy/create-android-enrollment-token.js | Reuses the shared auth client for enrollment token creation. |
| website/api/controllers/android-proxy/create-android-enterprise.js | Reuses the shared auth client for AMAPI + Pub/Sub enterprise provisioning calls. |
| website/api/controllers/android-proxy/create-android-signup-url.js | Reuses the shared auth client for signup URL creation. |
| website/api/controllers/android-proxy/create-enterprise-webapp.js | Reuses the shared auth client for web app creation. |
| website/api/controllers/android-proxy/delete-android-device.js | Reuses the shared auth client for device deletion. |
| website/api/controllers/android-proxy/delete-one-android-enterprise.js | Reuses the shared auth client for enterprise deletion and Pub/Sub cleanup. |
| website/api/controllers/android-proxy/get-android-device.js | Reuses the shared auth client for device retrieval. |
| website/api/controllers/android-proxy/get-android-devices.js | Reuses the shared auth client for device listing. |
| website/api/controllers/android-proxy/get-android-enterprises.js | Reuses the shared auth client for enterprise listing. |
| website/api/controllers/android-proxy/get-enterprise-applications.js | Reuses the shared auth client for enterprise application retrieval. |
| website/api/controllers/android-proxy/issue-command-on-android-device.js | Reuses the shared auth client for issuing device commands. |
| website/api/controllers/android-proxy/modify-android-device.js | Reuses the shared auth client for device patch operations. |
| website/api/controllers/android-proxy/modify-android-policies.js | Reuses the shared auth client for policy patch operations. |
| website/api/controllers/android-proxy/modify-enterprise-app-policy.js | Reuses the shared auth client for policy application modifications. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| // Log into google. | ||
| // Reuse the shared Google API auth client created at server startup (see api/hooks/custom/). | ||
| let { google } = require('googleapis'); | ||
| let androidmanagement = google.androidmanagement('v1'); | ||
| let googleAuth = new google.auth.GoogleAuth({ | ||
| scopes: ['https://www.googleapis.com/auth/androidmanagement'], | ||
| credentials: { | ||
| client_email: sails.config.custom.androidEnterpriseServiceAccountEmailAddress,// eslint-disable-line camelcase | ||
| private_key: sails.config.custom.androidEnterpriseServiceAccountPrivateKey,// eslint-disable-line camelcase | ||
| }, | ||
| }); | ||
| let authClient = await googleAuth.getClient(); | ||
| google.options({auth: authClient}); | ||
| let androidmanagement = google.androidmanagement({version: 'v1', auth: sails.googleAuthClient}); | ||
|
|
| let { google } = require('googleapis'); | ||
| let androidmanagement = google.androidmanagement('v1'); | ||
| let googleAuth = new google.auth.GoogleAuth({ | ||
| scopes: ['https://www.googleapis.com/auth/androidmanagement'], | ||
| credentials: { | ||
| client_email: sails.config.custom.androidEnterpriseServiceAccountEmailAddress,// eslint-disable-line camelcase | ||
| private_key: sails.config.custom.androidEnterpriseServiceAccountPrivateKey,// eslint-disable-line camelcase | ||
| }, | ||
| }); | ||
| // Acquire the google auth client, and bind it to all future calls | ||
| let authClient = await googleAuth.getClient(); | ||
| google.options({auth: authClient}); | ||
| // Reuse the shared Google API auth client created at server startup (see api/hooks/custom/). | ||
| let androidmanagement = google.androidmanagement({version: 'v1', auth: sails.googleAuthClient}); |
| let { google } = require('googleapis'); | ||
| let androidmanagement = google.androidmanagement('v1'); | ||
| let googleAuth = new google.auth.GoogleAuth({ | ||
| scopes: ['https://www.googleapis.com/auth/androidmanagement'], | ||
| credentials: { | ||
| client_email: sails.config.custom.androidEnterpriseServiceAccountEmailAddress,// eslint-disable-line camelcase | ||
| private_key: sails.config.custom.androidEnterpriseServiceAccountPrivateKey,// eslint-disable-line camelcase | ||
| }, | ||
| }); | ||
| // Acquire the google auth client, and bind it to all future calls | ||
| let authClient = await googleAuth.getClient(); | ||
| google.options({auth: authClient}); | ||
| // Reuse the shared Google API auth client created at server startup (see api/hooks/custom/). | ||
| let androidmanagement = google.androidmanagement({version: 'v1', auth: sails.googleAuthClient}); |
| let { google } = require('googleapis'); | ||
| let androidmanagement = google.androidmanagement('v1'); | ||
| let googleAuth = new google.auth.GoogleAuth({ | ||
| scopes: ['https://www.googleapis.com/auth/androidmanagement'], | ||
| credentials: { | ||
| client_email: sails.config.custom.androidEnterpriseServiceAccountEmailAddress,// eslint-disable-line camelcase | ||
| private_key: sails.config.custom.androidEnterpriseServiceAccountPrivateKey,// eslint-disable-line camelcase | ||
| }, | ||
| }); | ||
| // Acquire the google auth client, and bind it to all future calls | ||
| let authClient = await googleAuth.getClient(); | ||
| google.options({ auth: authClient }); | ||
| // Reuse the shared Google API auth client created at server startup (see api/hooks/custom/). | ||
| let androidmanagement = google.androidmanagement({version: 'v1', auth: sails.googleAuthClient}); |
| let { google } = require('googleapis'); | ||
| let androidmanagement = google.androidmanagement('v1'); | ||
| let googleAuth = new google.auth.GoogleAuth({ | ||
| scopes: ['https://www.googleapis.com/auth/androidmanagement'], | ||
| credentials: { | ||
| client_email: sails.config.custom.androidEnterpriseServiceAccountEmailAddress,// eslint-disable-line camelcase | ||
| private_key: sails.config.custom.androidEnterpriseServiceAccountPrivateKey,// eslint-disable-line camelcase | ||
| }, | ||
| }); | ||
| // Acquire the google auth client, and bind it to all future calls | ||
| let authClient = await googleAuth.getClient(); | ||
| google.options({ auth: authClient }); | ||
| // Reuse the shared Google API auth client created at server startup (see api/hooks/custom/). | ||
| let androidmanagement = google.androidmanagement({version: 'v1', auth: sails.googleAuthClient}); |
| let { google } = require('googleapis'); | ||
| let androidmanagement = google.androidmanagement('v1'); | ||
| let googleAuth = new google.auth.GoogleAuth({ | ||
| scopes: ['https://www.googleapis.com/auth/androidmanagement'], | ||
| credentials: { | ||
| client_email: sails.config.custom.androidEnterpriseServiceAccountEmailAddress,// eslint-disable-line camelcase | ||
| private_key: sails.config.custom.androidEnterpriseServiceAccountPrivateKey,// eslint-disable-line camelcase | ||
| }, | ||
| }); | ||
| // Acquire the google auth client, and bind it to all future calls | ||
| let authClient = await googleAuth.getClient(); | ||
| google.options({ auth: authClient }); | ||
| // Reuse the shared Google API auth client created at server startup (see api/hooks/custom/). | ||
| let androidmanagement = google.androidmanagement({version: 'v1', auth: sails.googleAuthClient}); | ||
| // [?]: https://googleapis.dev/nodejs/googleapis/latest/androidmanagement/classes/Resource$Enterprises$Applications.html#get |
| let { google } = require('googleapis'); | ||
| let androidmanagement = google.androidmanagement('v1'); | ||
| let googleAuth = new google.auth.GoogleAuth({ | ||
| scopes: ['https://www.googleapis.com/auth/androidmanagement'], | ||
| credentials: { | ||
| client_email: sails.config.custom.androidEnterpriseServiceAccountEmailAddress,// eslint-disable-line camelcase | ||
| private_key: sails.config.custom.androidEnterpriseServiceAccountPrivateKey,// eslint-disable-line camelcase | ||
| }, | ||
| }); | ||
| // Acquire the google auth client, and bind it to all future calls | ||
| let authClient = await googleAuth.getClient(); | ||
| google.options({ auth: authClient }); | ||
| // Reuse the shared Google API auth client created at server startup (see api/hooks/custom/). | ||
| let androidmanagement = google.androidmanagement({version: 'v1', auth: sails.googleAuthClient}); | ||
| // [?]: https://googleapis.dev/nodejs/googleapis/latest/androidmanagement/classes/Resource$Enterprises$Devices.html#issueCommand |
| let { google } = require('googleapis'); | ||
| let androidmanagement = google.androidmanagement('v1'); | ||
| let googleAuth = new google.auth.GoogleAuth({ | ||
| scopes: ['https://www.googleapis.com/auth/androidmanagement'], | ||
| credentials: { | ||
| client_email: sails.config.custom.androidEnterpriseServiceAccountEmailAddress,// eslint-disable-line camelcase | ||
| private_key: sails.config.custom.androidEnterpriseServiceAccountPrivateKey,// eslint-disable-line camelcase | ||
| }, | ||
| }); | ||
| // Acquire the google auth client, and bind it to all future calls | ||
| let authClient = await googleAuth.getClient(); | ||
| google.options({ auth: authClient }); | ||
| // Reuse the shared Google API auth client created at server startup (see api/hooks/custom/). | ||
| let androidmanagement = google.androidmanagement({version: 'v1', auth: sails.googleAuthClient}); | ||
| // [?]: https://googleapis.dev/nodejs/googleapis/latest/androidmanagement/classes/Resource$Enterprises$Devices.html#patch |
| let { google } = require('googleapis'); | ||
| let androidmanagement = google.androidmanagement('v1'); | ||
| let googleAuth = new google.auth.GoogleAuth({ | ||
| scopes: ['https://www.googleapis.com/auth/androidmanagement'], | ||
| credentials: { | ||
| client_email: sails.config.custom.androidEnterpriseServiceAccountEmailAddress,// eslint-disable-line camelcase | ||
| private_key: sails.config.custom.androidEnterpriseServiceAccountPrivateKey,// eslint-disable-line camelcase | ||
| }, | ||
| }); | ||
| // Acquire the google auth client, and bind it to all future calls | ||
| let authClient = await googleAuth.getClient(); | ||
| google.options({ auth: authClient }); | ||
| // Reuse the shared Google API auth client created at server startup (see api/hooks/custom/). | ||
| let androidmanagement = google.androidmanagement({version: 'v1', auth: sails.googleAuthClient}); | ||
| // [?]: https://googleapis.dev/nodejs/googleapis/latest/androidmanagement/classes/Resource$Enterprises$Policies.html#patch |
| let { google } = require('googleapis'); | ||
| let androidmanagement = google.androidmanagement('v1'); | ||
| let googleAuth = new google.auth.GoogleAuth({ | ||
| scopes: ['https://www.googleapis.com/auth/androidmanagement'], | ||
| credentials: { | ||
| client_email: sails.config.custom.androidEnterpriseServiceAccountEmailAddress,// eslint-disable-line camelcase | ||
| private_key: sails.config.custom.androidEnterpriseServiceAccountPrivateKey,// eslint-disable-line camelcase | ||
| }, | ||
| }); | ||
| // Acquire the google auth client, and bind it to all future calls | ||
| let authClient = await googleAuth.getClient(); | ||
| google.options({ auth: authClient }); | ||
| // Reuse the shared Google API auth client created at server startup (see api/hooks/custom/). | ||
| let androidmanagement = google.androidmanagement({version: 'v1', auth: sails.googleAuthClient}); | ||
|
|
WalkthroughAll 13 Android proxy controllers and one helper previously created a new Possibly related PRs
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 inconclusive)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@website/api/controllers/android-proxy/get-enterprise-applications.js`:
- Around line 68-69: The code at the androidmanagement client instantiation uses
sails.googleAuthClient without verifying it has been properly initialized. Add a
guard check before creating the androidmanagement client to ensure
sails.googleAuthClient is defined and not null. If the shared Google auth client
is missing, throw or return an appropriate error response with a clear message
indicating that Android credentials were not properly configured during startup,
rather than letting the undefined client propagate into the Google API call
where it will produce opaque errors.
In `@website/api/hooks/custom/index.js`:
- Around line 162-164: The catch block for the shared Google API auth client
initialization in the Android Management API setup is only logging a warning
instead of failing fast. Replace the sails.log.warn call with code that throws
an error or exits the process to ensure startup fails deterministically when
this critical client cannot be initialized, rather than allowing the application
to continue and fail later when downstream Android proxy handlers attempt to use
the uninitialized shared client.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: fd21caff-c26a-4874-a3ce-010754689032
📒 Files selected for processing (16)
website/api/controllers/android-proxy/create-android-enrollment-token.jswebsite/api/controllers/android-proxy/create-android-enterprise.jswebsite/api/controllers/android-proxy/create-android-signup-url.jswebsite/api/controllers/android-proxy/create-enterprise-webapp.jswebsite/api/controllers/android-proxy/delete-android-device.jswebsite/api/controllers/android-proxy/delete-one-android-enterprise.jswebsite/api/controllers/android-proxy/get-android-device.jswebsite/api/controllers/android-proxy/get-android-devices.jswebsite/api/controllers/android-proxy/get-android-enterprises.jswebsite/api/controllers/android-proxy/get-enterprise-applications.jswebsite/api/controllers/android-proxy/issue-command-on-android-device.jswebsite/api/controllers/android-proxy/modify-android-device.jswebsite/api/controllers/android-proxy/modify-android-policies.jswebsite/api/controllers/android-proxy/modify-enterprise-app-policy.jswebsite/api/helpers/android-proxy/get-is-enterprise-managed-by-fleet.jswebsite/api/hooks/custom/index.js
| // Reuse the shared Google API auth client created at server startup (see api/hooks/custom/). | ||
| let androidmanagement = google.androidmanagement({version: 'v1', auth: sails.googleAuthClient}); |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Description: Inspect shared Google auth initialization and direct consumers.
rg -n -C3 'sails\.googleAuthClient|androidEnterpriseServiceAccountEmailAddress|androidEnterpriseServiceAccountPrivateKey|getAccessToken\(|catch\s*\(' \
website/api/hooks/custom/index.js \
website/api/controllers/android-proxy \
website/api/helpers/android-proxyRepository: fleetdm/fleet
Length of output: 22147
Guard the shared Google auth client before using it.
The startup hook can leave sails.googleAuthClient unset when Android credentials are not configured or when initialization fails (caught and logged as a warning at line 163 in website/api/hooks/custom/index.js). This endpoint and at least 12 other Android proxy call sites pass it directly into the Google API client without checking, causing runtime failures with opaque error messages. Add a shared fail-fast guard, or fail startup when Android proxy credentials are configured but the shared client cannot be created, so requests fail clearly rather than devolving into ambiguous Google API errors.
🛡️ Example localized guard
let { google } = require('googleapis');
// Reuse the shared Google API auth client created at server startup (see api/hooks/custom/).
+ if (!sails.googleAuthClient) {
+ throw new Error('Google API auth client was not initialized for Android proxy requests.');
+ }
let androidmanagement = google.androidmanagement({version: 'v1', auth: sails.googleAuthClient});🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@website/api/controllers/android-proxy/get-enterprise-applications.js` around
lines 68 - 69, The code at the androidmanagement client instantiation uses
sails.googleAuthClient without verifying it has been properly initialized. Add a
guard check before creating the androidmanagement client to ensure
sails.googleAuthClient is defined and not null. If the shared Google auth client
is missing, throw or return an appropriate error response with a clear message
indicating that Android credentials were not properly configured during startup,
rather than letting the undefined client propagate into the Google API call
where it will produce opaque errors.
| } catch (err) { | ||
| sails.log.warn('p1: Failed to initialize the shared Google API auth client for the Android Management API. Android proxy endpoints will not function until this is resolved. Error: '+err); | ||
| } |
There was a problem hiding this comment.
Fail fast when shared Android proxy auth client initialization fails.
At Line 162, initialization errors are only logged and startup continues, but downstream Android proxy handlers rely on this shared client. This creates partial startup and request-time failures instead of a deterministic lift-time failure.
Proposed fix
- } catch (err) {
- sails.log.warn('p1: Failed to initialize the shared Google API auth client for the Android Management API. Android proxy endpoints will not function until this is resolved. Error: '+err);
- }
+ } catch (err) {
+ sails.log.error('Failed to initialize shared Google API auth client for Android proxy.', err);
+ throw new Error('Android proxy auth initialization failed with configured credentials.');
+ }📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| } catch (err) { | |
| sails.log.warn('p1: Failed to initialize the shared Google API auth client for the Android Management API. Android proxy endpoints will not function until this is resolved. Error: '+err); | |
| } | |
| } catch (err) { | |
| sails.log.error('Failed to initialize shared Google API auth client for Android proxy.', err); | |
| throw new Error('Android proxy auth initialization failed with configured credentials.'); | |
| } |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@website/api/hooks/custom/index.js` around lines 162 - 164, The catch block
for the shared Google API auth client initialization in the Android Management
API setup is only logging a warning instead of failing fast. Replace the
sails.log.warn call with code that throws an error or exits the process to
ensure startup fails deterministically when this critical client cannot be
initialized, rather than allowing the application to continue and fail later
when downstream Android proxy handlers attempt to use the uninitialized shared
client.
Closes: #46496
Changes:
sails.googleAuthClientSummary by CodeRabbit