Box
Bring your Box enterprise into the JupiterOne graph to see who owns your content, how it is shared, and who outside the company can reach it. The integration ingests the enterprise account, managed users and groups, the folders and files in every managed user's tree, and the collaborations that grant users and groups access to them. Each collaboration records its role, status, expiration and whether the collaborator is external to the enterprise. Folders and files record their shared-link access level, so you can find content shared through public links. Use it to find files and folders that anyone with the link can open, list external collaborators and the content they can reach, see which user owns each item, and alert when content is newly made public or shared outside the company. The integration reads metadata only. File contents, shared-link URLs, group memberships and Box event activity such as downloads are never retrieved.
- Installation
- Authorization
- Data Model
- Types
Installation
This integration connects to Box through the Box Platform API (https://api.box.com/2.0). It ingests your enterprise account, managed users, groups, folders, files, and the collaborations that share folders and files with users and groups. It is built for data protection use cases: who owns which content, which content has a public shared link, and which collaborators are outside your enterprise. The integration is managed by JupiterOne and runs in the JupiterOne cloud, so no collector is needed.
Prerequisites
- A Box enterprise account.
- Access to the Box Developer Console to create a Platform App, and a Box Admin or Co-Admin to authorize that app for the enterprise.
- Access to JupiterOne with permission to configure integrations.
Configuration in Box
The integration authenticates as a Box Platform App that uses Server Authentication with Client Credentials Grant (CCG). It requests a token at https://api.box.com/oauth2/token with box_subject_type=enterprise and your Enterprise ID as box_subject_id. The token belongs to the app's Service Account. Every API call is read-only.
The Service Account's own folder tree holds only content that has been shared with it. To read the rest of the enterprise, the integration lists your managed users and reads each user's folder tree on their behalf with the As-User header. The app must be set up for this. Otherwise only content shared with the Service Account is ingested.
Create the app
- Sign in to Box and open the Developer Console.
- Select New App, choose Server as the app type, and leave Client Credentials Grant selected as the authentication method.
- Name the app and select Create.
Configure the app
On the app's Configuration tab:
-
Set App Access Level to App + Enterprise Access. With the default, App Access Only, the app can reach only its Service Account and App Users, not your managed users or their content.
-
Under Application Scopes, select only the scopes below. The integration never writes, so you can clear any write scope.
Scope Used for Read all files and folders stored in Box ( root_readonly)Listing folder contents and the collaborations on folders and files. Manage users ( manage_managed_users)Listing enterprise users ( GET /users), which the folder walk and the collaboration data sources also need, and making calls as those users.Manage groups ( manage_groups)Listing groups ( GET /groups) for the Box Groups data source. -
In the Additional Configuration section, enable Make API calls using the as-user header. Some versions of the console label this section Advanced Features.
-
Save the changes.
You do not need Generate User Access Tokens. The integration authenticates only as the Service Account.
Authorize the app
A Box Admin or Co-Admin must authorize the app before it can be used:
- Copy the app's Client ID from its Configuration tab.
- In the Box Admin Console, open Platform, then the Platform Apps tab, and add the app by its Client ID. An Admin or Co-Admin can also authorize it directly from the app's Configuration tab in the Developer Console.
When the app is authorized, Box creates its Service Account.
Re-authorize the app after every change. Changes to the access level, scopes or the As-User setting take effect only after the app is re-authorized. To do that, open Platform > Platform Apps in the Admin Console, select ... on the app's row, and choose Reauthorize. Until then, the integration keeps the old permissions. For example, if As-User calls are not yet allowed, only content shared with the Service Account is ingested.
Collect the values for JupiterOne
- Client ID and Client Secret, from the app's Configuration tab. Box shows the client secret only when your account has multi-factor authentication turned on.
- Enterprise ID. In the Admin Console it is under Account & Billing > Account Information. In the Developer Console, select your account icon in the top right and choose Copy Enterprise ID.
Configuration in JupiterOne
To install the Box integration in JupiterOne, navigate to the Integrations tab in JupiterOne and select Box. Click New Instance to begin configuring your integration.
Creating an instance requires the following:
-
The Account Name used to identify the Box account in JupiterOne. Ingested entities will have this value stored in
tag.AccountNamewhen theAccountNametoggle is enabled. -
Description to assist in identifying the integration instance, if desired.
-
Polling Interval that you feel is sufficient for your monitoring needs. You may leave this as
DISABLEDand manually execute the integration. -
The Authentication fields below.
Authentication fields
| Field | Required | Description |
|---|---|---|
| Client ID | Yes | The Client ID of the Box app created above. |
| Client Secret | Yes | The Client Secret of the Box app. |
| Enterprise ID | Yes | The ID of the Box enterprise the app is authorized for. It is used to request the Service Account token and to identify the box_account entity. |
When you save the instance, JupiterOne checks that all three fields are set, requests an access token, and calls GET /users/me. This check confirms that the credentials work. It does not confirm the scopes or the As-User setting. Those problems show up in the first run.
Filters
Both filters are optional.
| Field | Default | Description |
|---|---|---|
| Ingest files | No default | Turn on to ingest files. When it is turned off, the Box Files data source ingests nothing and no file collaborations are ingested, but folders and folder collaborations still are. Turn it off on very large tenants to ingest only folders and their collaborations. |
| Maximum folder depth | Empty (the full tree) | A whole number that limits how deep each user's folder tree is read, counted from that user's root (All Files). 1 reads only the folders and files directly in the root, 2 also reads the contents of those top-level folders, and so on. 0 behaves like 1. A value that is not a non-negative whole number is ignored, and the full tree is read. The limit applies to both folders and files. |
Click Create once all values are provided to finalize the integration.
Narrowing a filter later removes entities from JupiterOne. When you lower Maximum folder depth or turn off Ingest files, folders and files that are no longer read on the next run are deleted from the graph, along with their collaborations.
Data Sources
Each data source can be enabled or disabled on its own. All data sources are disabled by default, so enable the ones you want to ingest. The box_account and box_service entities are always created. That step has no data source and always runs. It calls GET /users/me to read the enterprise name.
| Data Source | Description | Entities Created |
|---|---|---|
| Box Users | Users in the enterprise, with their login (email), active status, job title, language, time zone, and created and updated dates. | box_user |
| Box Groups | Groups in the enterprise, with their group type and description. | box_group |
| Box Folders | Folders in the Service Account's tree and in every managed user's tree, with their shared-link access level and status. | box_folder |
| Box Files | Files found the same way as folders, with their size, SHA-1 hash, extension, shared-link access level, status, and whether they are owned outside the enterprise. | box_file |
| Box Collaborations | Collaborations on the ingested folders and files, with the role, status, expiration date, invite email, and whether the collaborator is external. Requires Box Folders, Box Files, or both. | box_collaboration |
To ingest everything the integration supports, enable all five data sources.
Box Collaborations needs Box Folders or Box Files. Folder collaborations are read only when Box Folders is enabled, and file collaborations only when Box Files is enabled. With neither enabled, Box Collaborations does not run at all. Ownership (OWNS) and collaborator (ASSIGNED) relationships also need Box Users and, for groups, Box Groups. Enable those data sources if you want to know who owns content and who it is shared with.
Relationships are built only when every data source they need is enabled:
| Relationship | Requires |
|---|---|
box_account PROVIDES box_service | Always created |
box_account HAS box_user | Box Users |
box_account HAS box_group | Box Groups |
box_user OWNS box_folder | Box Users and Box Folders |
box_user OWNS box_file | Box Users and Box Files |
box_folder CONTAINS box_folder (parent folder to subfolder) | Box Folders |
box_folder CONTAINS box_file | Box Folders and Box Files |
box_folder ALLOWS box_collaboration | Box Folders and Box Collaborations |
box_file ALLOWS box_collaboration | Box Files and Box Collaborations |
box_collaboration ASSIGNED box_user | Box Users and Box Collaborations, plus Box Folders or Box Files for collaborations on that item type |
box_collaboration ASSIGNED box_group | Box Groups and Box Collaborations, plus Box Folders or Box Files for collaborations on that item type |
Notes on relationships:
- Each user's root folder (All Files, folder ID
0) is not ingested, so top-level folders and files have no parentCONTAINSrelationship. OWNSis created only when the owner is an ingestedbox_user. Items owned by users outside the enterprise have no owner relationship.ASSIGNEDis created only when the collaborating user or group was ingested. An external collaborator has abox_collaborationentity, withisExternal = trueand the collaborator's login inaccessibleByLogin, but noASSIGNEDrelationship.
How folders and files are read
Box has no endpoint that lists all of an enterprise's content, so the integration walks the folder tree one folder at a time with GET /folders/{id}/items, up to 1,000 items per page:
- It lists the enterprise users with
GET /users. If that call fails, the data source fails, because a walk of the Service Account alone would look complete while missing most content. - It walks the Service Account's tree, then each user's tree as that user (
As-User). - A folder that several users can see, such as a shared folder, is read once, by the first user who reaches it. Each folder and file becomes one entity, however many users can see it.
- A user whose tree cannot be read (Box answers
400,403or404) is skipped and logged. If the first 25 users are all denied before any succeeds, the run fails with an error that points at the App + Enterprise Access and As-User settings. - A folder that was deleted or unshared during the walk (
403or404) is skipped.
Content that only a skipped user can reach is not ingested on that run. Web links (bookmarks) are listed by Box but are not ingested.
Box Collaborations makes one request per ingested folder or file that Box reports as having collaborations. Items Box reports as having none are skipped without a request. The request is made as the item's owner when the owner is an enterprise user, otherwise as the user whose tree the item was found in. isExternal is true when the collaborating user's login, or the invite email, is not the login of an enterprise user. It is empty for group collaborations and when the user list cannot be read.
Example queries
Files and folders that anyone with the link can open:
FIND (box_file | box_folder) WITH isPublic = true
Folders shared with collaborators outside the enterprise, with the role each one was given:
FIND box_folder AS f
THAT ALLOWS box_collaboration WITH isExternal = true AS c
RETURN f.displayName, c.accessibleByLogin, c.inviteEmail, c.role, c.collaborationStatus
Public files and the users who own them:
FIND box_user AS u
THAT OWNS box_file WITH isPublic = true AS f
RETURN u.email, f.displayName, f.sharedLinkAccess
What the integration does not collect
- File contents, file versions, comments, tasks, and metadata or classification labels.
- Shared-link URLs and download URLs. Only the access level (
open,companyorcollaborators) is stored, assharedLinkAccess,isPublicandisSharedLinkConfigured. Shared-link password settings are not collected. - Group memberships. Users and groups are ingested, but which users belong to which group is not.
- User phone numbers and addresses.
- Web links (bookmarks) and each user's All Files root folder.
- Box events and activity, such as downloads, previews, moves and logins.
Request volume and rate limits
Box allows about 1,000 API requests per minute per user. All steps of a run share one API client that sends at most 15 requests per second. When Box answers 429 Too Many Requests, the integration waits for the time in the Retry-After header before retrying. Access tokens last 60 minutes and are renewed during the run.
Request volume grows with the size of your content:
- Box Folders and Box Files each walk the whole tree on their own, one request per folder for each page of up to 1,000 items. With both enabled, the tree is walked twice.
- Box Collaborations adds one request per folder or file that has collaborations.
On a large enterprise, a full run can take a long time. Use Maximum folder depth, or turn off Ingest files, to reduce it.
GET /groups cannot page past an offset of 10,000. On an enterprise with more than about 11,000 groups, the remaining groups are not ingested and a warning is logged.
Next steps
Now that your integration instance has been configured, it will begin running on the polling interval you provided, populating data within JupiterOne. Continue on to our Instance management guide to learn more about working with and editing integration instances.
Additional resources
- Client Credentials Grant: Service Account and user subjects, token lifetime
- Set up an app with Client Credentials Grant: creating the app, access level, scopes and the client secret
- Platform app approval: authorizing and re-authorizing the app in the Admin Console
- Scopes
- As-User header
- Security and application access: App Access Only and App + Enterprise Access
- Locating common values: finding the Enterprise ID
- Rate limits
- List items in folder
- List enterprise users
- List groups for enterprise
OAuth Scopes
OAuth scopes that must be granted to the application or service principal.
Show OAuth Scopes (3)
manage_groupsmanage_managed_usersroot_readonly
Endpoints
API endpoints that the integration makes requests to.
Show Endpoints (6)
https://api.box.com/2.0/files/{fileId}/collaborationshttps://api.box.com/2.0/folders/{folderId}/collaborationshttps://api.box.com/2.0/folders/{folderId}/itemshttps://api.box.com/2.0/groupshttps://api.box.com/2.0/usershttps://api.box.com/2.0/users/me
Documentation Links
Links to provider documentation relevant to setup and configuration.
Show Documentation Links (8)
- https://developer.box.com/guides/authentication/client-credentials/
- https://developer.box.com/guides/authentication/jwt/as-user/
- https://developer.box.com/reference/get-files-id-collaborations/
- https://developer.box.com/reference/get-folders-id-collaborations/
- https://developer.box.com/reference/get-folders-id-items/
- https://developer.box.com/reference/get-groups/
- https://developer.box.com/reference/get-users-me/
- https://developer.box.com/reference/get-users/
Per-Step Breakdown
Detailed authorization requirements for each ingestion step.
Show all steps (2)
| Step | OAuth Scopes | Endpoints |
|---|---|---|
| Fetch File Collaborations | root_readonly, manage_managed_users | https://api.box.com/2.0/files/{fileId}/collaborations, https://api.box.com/2.0/users |
| Fetch Folder Collaborations | root_readonly, manage_managed_users | https://api.box.com/2.0/folders/{folderId}/collaborations, https://api.box.com/2.0/users |
Entities
The following entities are created:
| Resources | Entity _type | Entity _class |
|---|---|---|
| Account | box_account | Account |
| Collaboration | box_collaboration | AccessRole |
| File | box_file | DataObject |
| Folder | box_folder | DataStore |
| Group | box_group | UserGroup |
| Service | box_service | Service |
| User | box_user | User |
Relationships
The following relationships are created:
Source Entity _type | Relationship _class | Target Entity _type |
|---|---|---|
box_account | PROVIDES | box_service |
box_account | HAS | box_user |
box_account | HAS | box_group |
box_collaboration | ASSIGNED | box_user |
box_collaboration | ASSIGNED | box_group |
box_file | ALLOWS | box_collaboration |
box_folder | ALLOWS | box_collaboration |
box_folder | CONTAINS | box_folder |
box_folder | CONTAINS | box_file |
box_user | OWNS | box_folder |
box_user | OWNS | box_file |
Box Account
box_account inherits from Account
| Property | Type | Description | Specifications |
|---|---|---|---|
enterpriseId * | string | The Box Enterprise ID this account represents. |
Box Collaboration
box_collaboration inherits from AccessRole
| Property | Type | Description | Specifications |
|---|---|---|---|
accessibleByLogin | string | null | The login (email) of the collaborating user, used to compute isExternal. | |
accessibleByType | string | null | The type of the collaborator ("user" or "group"). | |
collaborationStatus | string | null | The collaboration status: "accepted", "pending" or "rejected". | |
expiresOn | number | null | When the collaboration expires, in milliseconds since epoch. | |
inviteEmail | string | null | The email the collaboration was invited to, when the collaborator is not yet a Box user. | |
isAccessOnly | boolean | null | Whether the collaboration grants access-only (not visible in the collaborator's items list). | |
isExternal | boolean | null | Computed when collaborations are fetched: true when the collaborating user's login (or invite email) is not an enterprise user login from GET /users; null when the collaborator is a group or absent, or the user list could not be read (unknown). | |
itemType | string | null | The type of the collaborated item ("file" or "folder"). | |
role | string | null | The access level granted, e.g. "editor", "viewer" or "co-owner". |
Box File
box_file inherits from DataObject
| Property | Type | Description | Specifications |
|---|---|---|---|
extension | string | null | The file extension. | |
isExternallyOwned | boolean | null | Whether the file is owned by a user outside the enterprise. | |
isPublic | boolean | null | Computed: true when shared_link.access is "open"; null when the file has no shared link (unknown, not false). | |
isSharedLinkConfigured | boolean | null | Computed: true when the file has a shared link configured. The link URL itself is a secret and is not ingested. | |
itemStatus | string | null | The file status, e.g. "active", "trashed" or "deleted". | |
sha1 | string | null | The SHA-1 hash of the file. | |
sharedLinkAccess | string | null | The shared-link access level ("open", "company" or "collaborators"); null when the file has no shared link. | |
sizeInBytes | number | null | The file size in bytes. |
Box Folder
box_folder inherits from DataStore
| Property | Type | Description | Specifications |
|---|---|---|---|
isPublic | boolean | null | Computed: true when shared_link.access is "open"; null when the folder has no shared link (unknown, not false). | |
isSharedLinkConfigured | boolean | null | Computed: true when the folder has a shared link configured. The link URL itself is a secret and is not ingested. | |
itemStatus | string | null | The folder status, e.g. "active", "trashed" or "deleted". | |
sharedLinkAccess | string | null | The shared-link access level ("open", "company" or "collaborators"); null when the folder has no shared link. |
Box Group
box_group inherits from UserGroup
| Property | Type | Description | Specifications |
|---|---|---|---|
groupType | string | null | The group type, e.g. "managed_group" or "all_users_group". |
Box Service
box_service inherits from Service
Box User
box_user inherits from User
| Property | Type | Description | Specifications |
|---|---|---|---|
jobTitle | string | null | The user's job title. | |
language | string | null | The user's configured language. | |
timezone | string | null | The user's configured timezone. |