Skip to content

Commit b8b58f3

Browse files
raethlodanpoletaevTC-MO
authored
feat: Public Actor Permissions (#2053)
This PR adds docs for a new platfrom feature: Actor permissions. --------- Co-authored-by: Daniil Poletaev <[email protected]> Co-authored-by: Michał Olender <[email protected]>
1 parent 7260d29 commit b8b58f3

File tree

12 files changed

+389
-1
lines changed

12 files changed

+389
-1
lines changed

apify-api/openapi/paths/actors/acts@{actorId}@runs.yaml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,21 @@ post:
275275
schema:
276276
type: string
277277
example: dGhpcyBpcyBqdXN0IGV4YW1wbGUK...
278+
- name: forcePermissionLevel
279+
in: query
280+
description: |
281+
Overrides the Actor's permission level for this specific run. Use to test restricted permissions
282+
before deploying changes to your Actor or to temporarily elevate or restrict access. If you don't specify this
283+
parameter, the Actor uses its configured default permission level. For more information on permissions, see the
284+
[documentation](https://docs.apify.com/platform/actors/development/permissions).
285+
style: form
286+
explode: true
287+
schema:
288+
type: string
289+
enum:
290+
- LIMITED_PERMISSIONS
291+
- FULL_PERMISSIONS
292+
example: LIMITED_PERMISSIONS
278293
requestBody:
279294
description: ''
280295
content:

sources/platform/actors/development/actor_definition/input_schema/specification.md

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -872,7 +872,8 @@ Example of multiple datasets input:
872872
"title": "Datasets",
873873
"type": "array",
874874
"description": "Select multiple datasets",
875-
"resourceType": "dataset"
875+
"resourceType": "dataset",
876+
"resourcePermissions": ["READ"]
876877
}
877878
```
878879

@@ -887,6 +888,7 @@ Rendered input:
887888
| `type` | `string` | Yes | Specifies the type of input - `string` for single value. |
888889
| `editor` | One of <ul><li>`resourcePicker`</li><li>`textfield`</li><li>`hidden`</li></ul> | No | Visual editor used for <br/>the input field. Defaults to `resourcePicker`. |
889890
| `resourceType` | One of <ul><li>`dataset`</li><li>`keyValueStore`</li><li>`requestQueue`</li></ul> | Yes | Type of Apify Platform resource |
891+
| `resourcePermissions` | Array of strings; allowed values: <ul><li>`READ`</li><li>`WRITE`</li></ul> | Yes | Permissions requested for the referenced resource. Use [\"READ\"] for read-only access, or [\"READ\", \"WRITE\"] to allow writes.|
890892
| `pattern` | String | No | Regular expression that will be used to validate the input. If validation fails, the Actor will not run. |
891893
| `minLength` | Integer | No | Minimum length of the string. |
892894
| `maxLength` | Integer | No | Maximum length of the string. |
@@ -898,5 +900,20 @@ Rendered input:
898900
| `type` | `array` | Yes | Specifies the type of input - `array` for multiple values. |
899901
| `editor` | One of <ul><li>`resourcePicker`</li><li>`hidden`</li></ul> | No | Visual editor used for <br/>the input field. Defaults to `resourcePicker`. |
900902
| `resourceType` | One of <ul><li>`dataset`</li><li>`keyValueStore`</li><li>`requestQueue`</li></ul> | Yes | Type of Apify Platform resource |
903+
| `resourcePermissions` | Array of strings; allowed values: <ul><li>`READ`</li><li>`WRITE`</li></ul> | Yes | Permissions requested for the referenced resources. Use [\"READ\"] for read-only access, or [\"READ\", \"WRITE\"] to allow writes. Applies to each selected resource. |
901904
| `minItems` | Integer | No | Minimum number of items the array can contain. |
902905
| `maxItems` | Integer | No | Maximum number of items the array can contain. |
906+
907+
#### Resource permissions
908+
909+
If your Actor runs with limited permissions, it must declare what access it needs to resources supplied via input. The `resourcePermissions` field defines which operations your Actor can perform on user-selected storages. This field is evaluated at run start and expands the Actor's [limited permissions](../../permissions/index.md) scope to access resources sent via input.
910+
911+
- `["READ"]` - The Actor can read from the referenced resources.
912+
- `["READ", "WRITE"]` - The Actor can read from and write to the referenced resources.
913+
914+
:::note Runtime behavior
915+
916+
This setting defines runtime access only and doesn't change field visibility or whether the field is required in the UI. For array fields (`type: array`), the same permissions apply to each selected resource. Your Actor's run will fail with an insufficient-permissions error if it attempts an operation without the required permission, such as writing with read-only access. Users can see the required permissions in the [input field's tooltip](../../../running/permissions.md#recognizing-permission-levels-in-console-and-store).
917+
918+
919+
:::
185 KB
Loading
14.8 KB
Loading
156 KB
Loading
146 KB
Loading
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
---
2+
title: Permissions
3+
description: Learn how to declare and manage permissions for your Actor, what access levels mean, and how to build secure, trusted Actors for Apify users.
4+
sidebar_position: 7.5
5+
slug: /actors/development/permissions
6+
---
7+
8+
**Learn how to declare and manage permissions for your Actor, what permission levels mean, and how to build secure, trusted Actors for Apify users.**
9+
10+
---
11+
12+
Every time a user runs your Actor, it runs under their Apify account. **Actor permissions** define the level of access your Actor needs to run. This gives users transparency and control over what data your Actor can access, building trust in your tools.
13+
14+
Your Actors can request two levels of access:
15+
16+
- **Limited permissions:** Actors with this permission level have restricted access, primarily to their own storages and the data they generate. They cannot access other user data on the Apify platform.
17+
- **Full permissions:** This level grants an Actor access to all of a user's Apify account data.
18+
19+
Most Actors should use limited permissions to request only the specific access they need and reserve full permissions for exceptional cases where the Actor cannot function otherwise.
20+
21+
## How Actor permissions work
22+
23+
When a user runs an Actor, it receives an Apify API token. This token is injected to the Actor's runtime and has a scope of access as requested by the Actor's permission level.
24+
25+
Actors with **Full permissions** receive a token that grants complete access to the user's Apify account via the Apify API.
26+
27+
Actors with **Limited permissions** receive [a restricted scoped token](../../../integrations/programming/api.md#api-tokens-with-limited-permissions). This token only allows the Actor to perform a specific set of actions, which covers the vast majority of common use cases.
28+
29+
A limited-permission Actor can:
30+
31+
- Read and write to its default storages.
32+
- Create any additional storage, and write to that storage.
33+
- Read and write to storages created in previous runs.
34+
- Update the current run's status or abort the run.
35+
- [Metamorph](../programming_interface/metamorph.md) to another Actor with limited permissions.
36+
- Read and write to storages provided via Actor input (for example, when the user provides a dataset that the Actor should write into).
37+
- Read basic user information from the environment (whether the user is paying, their proxy password, or public profile).
38+
- Run any other Actor with limited permissions.
39+
40+
This approach ensures your Actor has everything it needs to function while protecting user data from unnecessary exposure.
41+
42+
:::info Migrating to limited permissions
43+
44+
To learn how to migrate your Actors to run under limited permissions, check out the [Migration guide](./migration_guide.md)
45+
46+
:::
47+
48+
### Configuring Actor permissions level
49+
50+
You can set the permission level for your Actor in the Apify Console under its **Settings** tab. All the existing Actors are configured to use full permissions.
51+
52+
![Actor permissions configuration in Actor settings](./images/actor_settings_permissions.webp)
53+
54+
### End-user experience
55+
56+
Users see a visible permission badge on your Actor's detail page indicating whether it requires **Limited permissions** or **Full permissions**. The experience of running an Actor remains the same for users.
57+
58+
![User experience for users viewing limited permission Actor in console](./images/end_user_ux_limited_permissions.png)
59+
60+
![User experience for users viewing full permission Actor in console](./images/end_user_ux_full_permissions.png)
61+
62+
:::warning Impact on Actor Quality score
63+
64+
When possible, design your Actors to use limited permissions and request only the access they truly need. Actors requiring full permissions may receive a lower [Actor Quality score](../../publishing/quality_score.mdx), which can reduce their ranking in the store.
65+
66+
:::
67+
68+
69+
### Accessing user provided storages
70+
71+
By default, limited-permissions Actors can't access user storages. However, they can access storages that users explicitly provide via the Actor input. To do so, use the input schema to add a storage picker and declare exactly which operations your Actor needs.
72+
73+
- Add a field with `editor: "resourcePicker"`.
74+
- Set `resourceType` to one of `dataset`, `keyValueStore`, or `requestQueue`.
75+
- Specify `resourcePermissions` with the minimal required scope: `"READ"` or `"READ", "WRITE"`.
76+
77+
Actors running under full permissions are assumed to have full (i.e. read/write/manage) access to user storages. In that case the `resourcePermissions` field does not have to be set.
78+
79+
Example input schema field (single resource):
80+
81+
```json
82+
{
83+
"title": "Output dataset",
84+
"type": "string",
85+
"editor": "resourcePicker",
86+
"resourceType": "dataset",
87+
"resourcePermissions": ["READ", "WRITE"]
88+
}
89+
```
90+
91+
Selecting multiple resources:
92+
93+
- Use `type: "array"` to let users choose more than one storage.
94+
- Each selected resource will have the same `resourcePermissions`
95+
96+
```json
97+
{
98+
"title": "Source datasets",
99+
"type": "array",
100+
"editor": "resourcePicker",
101+
"resourceType": "dataset",
102+
"resourcePermissions": ["READ"],
103+
"minItems": 1
104+
}
105+
```
106+
107+
Behavior at run time:
108+
109+
- The user’s selection is injected into the run input, and the run token is expanded to allow only the requested operations on the selected storages.
110+
- If your code attempts an operation not covered by `resourcePermissions` (for example, writing with only `READ`), the platform returns an insufficient-permissions error.
111+
112+
See the full [input schema reference for details.](../actor_definition/input_schema/specification.md).
113+
114+
### Requesting full permissions
115+
116+
Designing your Actors to work under limited permissions is the recommended approach, it helps improve your [Actor Quality score](../../publishing/quality_score.mdx#trustworthiness) and increases user trust and adoption. However, some use cases do legitimately require broader access to user data (e.g., to perform administrative tasks or orchestrate other Actors). If your Actor falls in this category or cannot function with limited permissions for another reason:
117+
118+
- Explain why you need full permissions in your Actor's README. This will help keep user trust and set correct user expectations.
119+
- Set the permission level in the Actor’s **Settings** in Console to **Full permissions**.
120+
- Be aware of the [UX implications](#end-user-experience) and impact on [Actor Quality score](../../publishing/quality_score.mdx) for full-permission Actors.
121+
122+
123+
:::info Need help with Actor permissions?
124+
125+
If you cannot migrate to limited permissions or have a use case that should work under limited permissions but does not, contact support or ask on [the community forum](https://discord.gg/eN73Xdhtqc).
126+
127+
:::
Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
---
2+
title: Migration guide
3+
description: How to migrate your Actor to limited permissions. Common migration paths, code examples, and common issues.
4+
sidebar_position: 9
5+
slug: /actors/development/permissions/migration-guide
6+
---
7+
8+
**Migrate your Actor to limited permissions, review common migration paths, code examples, and solutions to common issues.**
9+
10+
---
11+
12+
This guide explains how to migrate your existing Actors to use [limited permissions](index.md#how-actor-permissions-work). Before you start, make sure your Actor uses the latest [Apify SDK](https://docs.apify.com/sdk).
13+
14+
Recommended minimum SDK versions:
15+
16+
- JavaScript SDK: [[email protected]](https://github.com/apify/apify-sdk-js/releases/tag/apify%403.4.4)
17+
- Python SDK: [v3.0.0](https://github.com/apify/apify-sdk-python/releases/tag/v3.0.0)
18+
19+
Before you start it's helpful to understand [what access restrictions limited permissions impose](index.md#how-actor-permissions-work).
20+
21+
## Test your Actor with limited permissions before migrating
22+
23+
You can override the permission level for a single run using run options under the **Actor Source** tab in Console:
24+
25+
![Forcing Actor permissions for a single run.](./images/actor_run_permission_override.png)
26+
27+
You can do the same using the Apify Client as well:
28+
29+
```ts
30+
await apifyClient.actor(actorId).call(input, {
31+
forcePermissionLevel: ACTOR_PERMISSION_LEVEL.LIMITED_PERMISSIONS,
32+
});
33+
```
34+
35+
Or just using the API:
36+
37+
```tsx
38+
POST https://api.apify.com/v2/acts/<actor_id>/runs?**forcePermissionLevel=LIMITED_PERMISSIONS**
39+
```
40+
41+
42+
## Common migration paths
43+
44+
Most public Actors can migrate to limited permissions with minor adjustments, if any. The general prerequisite is to **update the Actor to use the latest [Apify SDK](https://docs.apify.com/sdk)**. To assess what needs to change in your Actor, review these areas:
45+
46+
- How your Actor uses storages (e.g. named storages and storages provided via input)
47+
- Whether it requests correct resource access for user-provided storages
48+
- Whether it needs to access information about the user (specifically if the user is paying or access their proxy configuration)
49+
50+
Once you have updated and [tested](#test-your-actor-with-limited-permissions-before-migrating) your Actor, you can change the permissions in the Actor settings. The setting takes immediate effect.
51+
52+
Below you can review common migration paths for advanced cases in greater detail.
53+
54+
### The Actor only pushes data to default storages
55+
56+
This is the most common and simplest use case. If your Actor only reads its input and writes results to its default dataset, key-value store, or request queue, _no changes are needed_. Limited permissions fully support this behavior out of the box.
57+
58+
### The Actor calls other Actors
59+
60+
An Actor with limited permissions can only call other Actors that also have limited permissions. If your Actor calls another one, you will need to ensure the target Actor has been migrated first.
61+
62+
### The Actor accesses storages provided by the user
63+
64+
If your Actor reads from or writes to a storage that the user provides via an input field, you must explicitly declare what access you need in the Actor's input schema.
65+
66+
1. Populate `resourceType` property on the field to enable the native resource picker.
67+
1. Populate `resourcePermissions` with permissions you need for the resource.
68+
69+
For example, your Actor allows the user to provide a custom dataset for the Actor results. Your `input_schema.json` might contain something like this:
70+
71+
```json
72+
{
73+
"title": "Output",
74+
"type": "string",
75+
"description": "Select a dataset for the Actor results",
76+
}
77+
```
78+
79+
To support limited permissions, change it to this:
80+
81+
```json
82+
{
83+
"title": "Output",
84+
"type": "string",
85+
"description": "Select a dataset for the Actor results",
86+
"resourceType": "dataset",
87+
"resourcePermissions": ["READ", "WRITE"],
88+
"editor": "textfield", // If you want to preserve the plain "string" input UI, instead of rich resource picker.
89+
}
90+
```
91+
92+
Now when the platform runs your Actor, it’ll automatically add the user-provided storage to the Actor’s scope so that it can access it.
93+
94+
:::info Backward compatibility
95+
96+
Users can provide the resource both via its name and its ID. If you have users with inputs that specify the resource via its name, this change to the input schema will not break it.
97+
98+
:::
99+
100+
### The Actor accesses named storages
101+
102+
Actors sometimes use named storages for caching or persisting state across runs. With limited permissions, an Actor can create a named storage on its first run and will automatically retain access to it in all subsequent runs by the same user.
103+
104+
If your Actor previously relied on accessing a pre-existing named storage, you will need to rename it in your code. This will cause the Actor to recreate the storage under the new system on its next run.
105+
106+
To achieve a smooth migration without disrupting your Actor’s users, you will need to make sure that your Actor can handle the transition. The suggested approach is the following:
107+
108+
1. Adjust the code of the Actor so that it can run with both limited and full permissions.
109+
1. Change the Actor setting to limited permissions.
110+
1. Clean up the migration code.
111+
112+
```ts
113+
const OLD_CACHE_STORE_NAME = 'my-actor-cache';
114+
const NEW_CACHE_STORE_NAME = 'my-actor-cache-updated';
115+
116+
let store;
117+
118+
if (process.env.ACTOR_PERMISSION_LEVEL === 'LIMITED_PERMISSIONS') {
119+
// If the Actor is running with limited permissions and we need to create
120+
// a new store. The platform will remember that the store was created by this Actor
121+
// and will allow access in all follow-up runs.
122+
store = await Actor.openKeyValueStore(NEW_CACHE_STORE_NAME);
123+
} else {
124+
// If the Actor is still running with full permissions and we should use
125+
// the existing store.
126+
store = await Actor.openKeyValueStore(OLD_CACHE_STORE_NAME);
127+
}
128+
```
129+
130+
:::info Re-create cache only under limited permissions.
131+
132+
Create the new storage _only once the Actor runs with limited permissions_. Only that way the access is retained in follow-up runs.
133+
134+
:::
135+
136+
If the contents of the named storage are critical for your Actor to keep functioning for users and it is impossible, costly or highly impractical to migrate, contact support or reach out to us [on the community forum](https://discord.gg/eN73Xdhtqc). We can discuss the available options.
137+
138+
### The Actor needs to know whether the user is paying
139+
140+
Some Actors have different logic for free and paying users. Previously you could retrieve this information by calling the `/users/me` API endpoint. However, Actors running under limited permissions don't have access to that endpoint. To get this information, your Actor should read the `APIFY_USER_IS_PAYING` environment variable, or use the SDK to obtain the value:
141+
142+
```ts
143+
const { userIsPaying } = Actor.getEnv();
144+
```
145+
146+
### The Actor uses Proxy
147+
148+
Similarly, if your Actor uses [Proxy](../../../proxy/index.md) and needs to retrieve the user's proxy password, it should get it from the `APIFY_PROXY_PASSWORD` environment variable instead of calling the `/users/me` endpoint or, preferably, rely on the SDK to handle proxy configuration automatically.

sources/platform/actors/development/programming_interface/environment_variables.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ Here's a table of key system environment variables:
5454
| `APIFY_HEADLESS` | If **1**, web browsers inside the Actor should run in headless mode (no windowing system available). |
5555
| `APIFY_IS_AT_HOME` | Contains **1** if the Actor is running on Apify servers. |
5656
| `ACTOR_MEMORY_MBYTES` | Size of memory allocated for the Actor run, in megabytes. Can be used to optimize memory usage or finetuning of low-level external libraries. |
57+
| `ACTOR_PERMISSION_LEVEL` | [Permission level](../../running/permissions.md) the Actor is run under. This determines what resources in the user’s account the Actor can access. |
5758
| `APIFY_PROXY_PASSWORD` | Password for accessing Apify Proxy services. This password enables the Actor to utilize proxy servers on behalf of the user who initiated the Actor run. |
5859
| `APIFY_PROXY_PORT` | TCP port number to be used for connecting to the Apify Proxy. |
5960
| `APIFY_PROXY_STATUS_URL` | URL for retrieving proxy status information. Appending `?format=json` to this URL returns the data in JSON format for programmatic processing. |

0 commit comments

Comments
 (0)