Skip to content

Website: Reduce Android Management API usage#49065

Open
eashaw wants to merge 3 commits into
mainfrom
website-reduce-android-api-usage
Open

Website: Reduce Android Management API usage#49065
eashaw wants to merge 3 commits into
mainfrom
website-reduce-android-api-usage

Conversation

@eashaw

@eashaw eashaw commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Related to: #41908

Changes:

  • Updated Android proxy endpoints (create-android-enrollment-token, create-enterprise-webapp, delete-android-device, get-android-device, get-android-devices, get-enterprise-applications, issue-command-on-android-device, modify-android-device, modify-android-policies, and modify-enterprise-app-policy) to send requests to the Android Management API without verifying that an enterprise is still managed by Fleet with the getIsEnterpriseManagedByFleet helper, and to return a enterpriseNotAccessible (notFound) response to Fleet servers if the Android management API returns a 403 response.

Summary by CodeRabbit

  • Bug Fixes
    • Improved Android management flows to handle authorization failures more consistently.
    • Requests now return a clearer “not accessible” response when access to an Android enterprise is denied.
    • Several Android device, app, policy, and enterprise actions now surface this response instead of falling back to generic errors.
    • Streamlined Android enterprise operations by removing an extra pre-check, letting the API response determine the final outcome.

Copilot AI review requested due to automatic review settings July 9, 2026 17:56

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR reduces Android Management API usage in the fleetdm.com Android proxy by removing the per-request “is this enterprise still managed?” check (which triggers ListEnterprises) and instead relying on Android Management API responses to determine access.

Changes:

  • Removed calls to sails.helpers.androidProxy.getIsEnterpriseManagedByFleet(...) from multiple Android proxy controllers.
  • Added a new enterpriseNotAccessible exit and intercept mapping so Android Management API 403 responses return a notFound-typed response to Fleet servers.

Reviewed changes

Copilot reviewed 10 out of 10 changed files in this pull request and generated no comments.

Show a summary per file
File Description
website/api/controllers/android-proxy/create-android-enrollment-token.js Drops enterprise-managed verification call; maps AMAPI 403 to enterpriseNotAccessible.
website/api/controllers/android-proxy/create-enterprise-webapp.js Drops enterprise-managed verification call; maps AMAPI 403 to enterpriseNotAccessible.
website/api/controllers/android-proxy/delete-android-device.js Drops enterprise-managed verification call; maps AMAPI 403 to enterpriseNotAccessible.
website/api/controllers/android-proxy/get-android-device.js Drops enterprise-managed verification call; maps AMAPI 403 to enterpriseNotAccessible.
website/api/controllers/android-proxy/get-android-devices.js Adds enterpriseNotAccessible exit and maps AMAPI 403 accordingly.
website/api/controllers/android-proxy/get-enterprise-applications.js Drops enterprise-managed verification call; maps AMAPI 403 to enterpriseNotAccessible.
website/api/controllers/android-proxy/issue-command-on-android-device.js Drops enterprise-managed verification call; maps AMAPI 403 to enterpriseNotAccessible.
website/api/controllers/android-proxy/modify-android-device.js Drops enterprise-managed verification call; maps AMAPI 403 to enterpriseNotAccessible.
website/api/controllers/android-proxy/modify-android-policies.js Drops enterprise-managed verification call; maps AMAPI 403 to enterpriseNotAccessible.
website/api/controllers/android-proxy/modify-enterprise-app-policy.js Drops enterprise-managed verification call; maps AMAPI 403 to enterpriseNotAccessible.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@coderabbitai

coderabbitai Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Walkthrough

This change updates ten Android proxy controllers (create-android-enrollment-token, create-enterprise-webapp, delete-android-device, get-android-device, get-android-devices, get-enterprise-applications, issue-command-on-android-device, modify-android-device, modify-android-policies, modify-enterprise-app-policy) in the website API. Each controller adds a new enterpriseNotAccessible exit mapped to responseType: 'notFound'. Nine of the ten controllers remove a prior pre-flight check that called sails.helpers.androidProxy.getIsEnterpriseManagedByFleet and threw notFound when the enterprise was unmanaged. Each controller's Google Android Management API call handling adds an HTTP 403 interceptor that returns the new enterpriseNotAccessible payload instead of falling through to generic error handling.

Possibly related PRs

  • fleetdm/fleet#48240: Modifies the same set of android-proxy controllers' error-interception logic, adding a structured exit for transient 5xx errors (managementApiError), paralleling this PR's 403 enterpriseNotAccessible exit additions.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description states the issue and change summary, but it omits the required template sections like testing and checklist details. Rewrite it using the repository template, including the related issue, testing notes, and checklist items, and delete any non-applicable lines.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly reflects the main change: reducing Android Management API usage by removing pre-checks and handling 403s.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch website-reduce-android-api-usage

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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/create-android-enrollment-token.js`:
- Around line 78-80: Update the Android proxy error mapping so deleted
enterprises returning 404 are treated the same as 403 and converted to
enterpriseNotAccessible instead of falling through to a generic 500. In
createAndroidEnrollmentToken’s intercept handler, expand the status interception
to include 404, and apply the same response mapping pattern used by the other
Android proxy controllers in this cohort so enterpriseNotAccessible is returned
consistently.

In `@website/api/controllers/android-proxy/get-enterprise-applications.js`:
- Around line 82-84: The 403 handling in get-enterprise-applications should not
always map to enterpriseNotAccessible; applications.get can fail for scope,
API-enabled, or permission reasons as well. Update the intercept logic in this
controller to inspect the AMAPI error body/reason before deciding whether to
return the enterpriseNotAccessible response, and only use that fallback for the
specific not-authorized case while letting other 403s surface as real
proxy/config errors.
🪄 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: 7ace5379-610f-4283-a101-6dec7e27aa0e

📥 Commits

Reviewing files that changed from the base of the PR and between 4f8677d and def72ba.

📒 Files selected for processing (10)
  • website/api/controllers/android-proxy/create-android-enrollment-token.js
  • website/api/controllers/android-proxy/create-enterprise-webapp.js
  • website/api/controllers/android-proxy/delete-android-device.js
  • website/api/controllers/android-proxy/get-android-device.js
  • website/api/controllers/android-proxy/get-android-devices.js
  • website/api/controllers/android-proxy/get-enterprise-applications.js
  • website/api/controllers/android-proxy/issue-command-on-android-device.js
  • website/api/controllers/android-proxy/modify-android-device.js
  • website/api/controllers/android-proxy/modify-android-policies.js
  • website/api/controllers/android-proxy/modify-enterprise-app-policy.js

Comment on lines +78 to +80
}).intercept({status: 403}, ()=>{
// If the Android management API returns a 403 response, return a enterpriseNotAccessible (notFound) response to the Fleet server.
return {'enterpriseNotAccessible': 'Fleet is not authorized to manage this Android enterprise.'};

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🌐 Web query:

Google Android Management API enterprises.enrollmentTokens.create HTTP status 403 vs 404 when service account not authorized or enterprise deleted

💡 Result:

When interacting with the Google Android Management API, the HTTP 403 and 404 status codes indicate fundamentally different issues [1][2]. HTTP 403 Forbidden A 403 error signifies an authorization or permission problem [2]. It means the request was understood by the server, but the caller (service account) does not have the necessary permissions to perform the requested action, or the project/enterprise configuration restricts access [2][3]. - Common causes: The service account lacks the required IAM role, such as the Android Management User (roles/androidmanagement.user) role, which contains the androidmanagement.enterprises.manage permission [3][4]. It may also occur if the API is not enabled for the project [3]. HTTP 404 Not Found A 404 error signifies that the requested resource does not exist [1]. In the context of the Android Management API, it indicates that the specific object identified in the API path (e.g., the enterprise or enrollment token) could not be located [1][5]. - Common causes: If an enterprise has been deleted, any attempt to access its resources—such as calling enterprises.enrollmentTokens.create for an enterprise ID that no longer exists—will return a 404 error [1][6]. This is because the server can no longer find the parent resource required to fulfill the request [1]. In summary: 403 means you do not have permission to do what you are asking, while 404 means the entity you are trying to act upon is missing or has been deleted [1][2].

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect the target file and nearby status handling.
sed -n '1,220p' website/api/controllers/android-proxy/create-android-enrollment-token.js

echo
echo "---- cohort search ----"
rg -n "getIsEnterpriseManagedByFleet|intercept\\(\\{status: 403\\}|enterpriseNotAccessible" website/api/controllers/android-proxy

Repository: fleetdm/fleet

Length of output: 11625


🌐 Web query:

Android Management API enrollmentTokens.create 403 404 enterprise deleted revoked access documentation

💡 Result:

When encountering 403 or 404 errors with the Android Management API's enterprises.enrollmentTokens.create method, the issues typically stem from authorization, resource state, or invalid parent paths [1][2]. 403 Forbidden Errors A 403 status code indicates an authorization or access denial. Common causes include: - Insufficient Permissions: The service account or credentials used do not have the required IAM roles to manage the specified enterprise [2]. - Deleted or Revoked Enterprise: If the enterprise associated with the request has been deleted or its access has been revoked, the API will reject calls made on its behalf [3]. - Invalid Scope: Ensure the request is authorized with the correct OAuth 2.0 scopes necessary for Android Management API operations. 404 Not Found Errors A 404 status code indicates that the requested resource, typically the parent enterprise, does not exist or is inaccessible [2]. Causes include: - Incorrect Parent Path: The parent parameter must be correctly formatted as enterprises/{enterpriseId} [1][4]. If the {enterpriseId} is mistyped, invalid, or does not exist, the API returns a 404. - Deleted Enterprise: If the enterprise itself was deleted, any attempts to interact with its resources (like creating enrollment tokens) will fail with a 404 [3]. - Resource Lifecycle: Once an enrollment token is explicitly deleted via enterprises.enrollmentTokens.delete, it is invalidated and no longer exists [5][4]. Attempting to access or perform operations on a deleted token will result in a 404 [4]. To troubleshoot, verify that your {enterpriseId} is correct, ensure your service account has proper IAM permissions for that specific enterprise, and confirm that the enterprise has not been deleted or suspended [1][2][4]. You can list active enterprises or tokens to verify their current state using the list methods [3][4].

Citations:


Handle 404 as enterpriseNotAccessible too
Deleted Android enterprises can return 404, so a 403-only intercept still sends that case to the generic error path and surfaces a 500. Map 404 here as well; the same pattern applies to the other Android proxy controllers in this cohort.

🤖 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/create-android-enrollment-token.js`
around lines 78 - 80, Update the Android proxy error mapping so deleted
enterprises returning 404 are treated the same as 403 and converted to
enterpriseNotAccessible instead of falling through to a generic 500. In
createAndroidEnrollmentToken’s intercept handler, expand the status interception
to include 404, and apply the same response mapping pattern used by the other
Android proxy controllers in this cohort so enterpriseNotAccessible is returned
consistently.

Comment on lines +82 to +84
}).intercept({status: 403}, ()=>{
// If the Android management API returns a 403 response, return a enterpriseNotAccessible (notFound) response to the Fleet server.
return {'enterpriseNotAccessible': 'Fleet is not authorized to manage this Android enterprise.'};

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

git ls-files website/api/controllers/android-proxy/get-enterprise-applications.js && sed -n '1,180p' website/api/controllers/android-proxy/get-enterprise-applications.js

Repository: fleetdm/fleet

Length of output: 4616


🏁 Script executed:

rg -n "intercept\\(\\{status: 403\\}|enterpriseNotAccessible|androidmanagement" website/api/controllers website/api/helpers -g '!**/node_modules/**'

Repository: fleetdm/fleet

Length of output: 15669


🌐 Web query:

Android Management API applications.get 403 insufficient scope permission API disabled error reason documentation

💡 Result:

When encountering a 403 error while calling the Android Management API enterprises.applications.get method, the error generally stems from one of two distinct configuration issues [1][2][3]. 1. Insufficient Authentication Scopes The enterprises.applications.get method requires the specific OAuth scope https://www.googleapis.com/auth/androidmanagement [4][5]. If your request uses a different or less privileged scope (such as a generic Google Cloud scope), the API will return a 403 error with a message indicating "insufficient authentication scopes" [1][3]. Ensure your OAuth 2.0 flow or service account configuration includes this exact string [5][1]. 2. API Disabled or Not Configured If the Android Management API is not enabled in the Google Cloud project associated with your credentials, or if the service is disabled, the request will fail [2][3]. The API error message often specifies that the API has not been used in the project before or is disabled [2][3]. You can resolve this by visiting the Google Cloud Console for your project, navigating to the APIs & Services dashboard, and ensuring the "Android Management API" is explicitly enabled [2][3]. Other common causes for 403 errors in the Android Management API include: - Permission Denied: Even with the correct scope and enabled API, your credentials may lack the necessary IAM role (e.g., roles/androidmanagement.user) to manage the specific enterprise resource [6]. - Unauthorized Enterprise Access: The service account or user account must be properly associated with the enterprise [6]. If the caller is not authorized to manage that specific enterprise, you will receive a "Caller is not authorized to manage enterprise" 403 error [6]. To troubleshoot, verify your project's API settings in the Google Cloud Console, confirm your service account has the required androidmanagement IAM roles, and ensure your access token was requested with the correct androidmanagement scope [4][5][6].

Citations:


Don't collapse every AMAPI 403 into enterpriseNotAccessible. applications.get can also return 403 for scope, API-enabled, or permission issues, so this turns real proxy/config failures into a generic 404. Inspect the error reason/body before mapping it here.

🤖 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 82 - 84, The 403 handling in get-enterprise-applications should not always
map to enterpriseNotAccessible; applications.get can fail for scope,
API-enabled, or permission reasons as well. Update the intercept logic in this
controller to inspect the AMAPI error body/reason before deciding whether to
return the enterpriseNotAccessible response, and only use that fallback for the
specific not-authorized case while letting other 403s surface as real
proxy/config errors.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants