| name | datalens-yc-rls-resolve |
| description | Use this skill when a DataLens user on datalens.ru (Yandex Cloud) needs to resolve user, email, service-account, or Cloud Organization group names into RLSv2 subject IDs, fill the `rls2` field, or migrate a legacy `rls` configuration. |
| license | Apache-2.0 |
| metadata | {"domain":"datalens"} |
DataLens RLS resolve
Overview
For cloud DataLens on Yandex Cloud (datalens.ru). RLSv2 (the rls2 field) stores subjects by
id, whereas the legacy RLS (the rls text config) let you use names. This skill
resolves names → ids via the yc CLI (Cloud Organization Manager) and can emit a complete
rls2 config.
Users → cloud subject id (subject_claims.sub); groups → org group id.
subject_name is display-only; subject_id is what enforcement uses. Unresolved subjects
in convert output become notfound with a !FAILED_ name prefix. In resolve output,
resolved subject objects stay under resolved and unresolved input names are listed separately
under unresolved.
⚠️ Access required. To resolve Yandex Cloud subjects you must hold at least the
organization-manager.viewer role on the target organization. Without it, the
yc organization-manager user list / group list calls fail with a PermissionDenied
error and nothing resolves. If you hit that, ask an organization admin to grant you
organization-manager.viewer (or a higher Organization Manager role) on that org —
do not work around it.
When to use
- Filling
rls2 for a dataset and you only have logins / emails / group names.
- Migrating an existing dataset from the legacy
rls text config to rls2.
Two modes
| Mode | Input | Output |
|---|
resolve | subject names (logins, emails, group names) | rls2 subject objects + unresolved list |
convert | the legacy rls config — JSON {field_guid: "<text>"} (one or many fields), or a single field's raw RLS text | the full exact rls2 config {field_guid: [rules]} |
Subject input format
| Subject | Input form |
|---|
| user | login or email as-is |
| group | @group:<group name> |
| service account | @sa:<service-account id> |
| all rows | * |
| source-level user id | userid |
Normalize explicit group names and service-account IDs before invoking the tool. If the user says
"group Analysts", pass @group:Analysts. If the user supplies service-account ID aje123, pass
@sa:aje123; do not look it up as a user or ask for the same ID again.
How users are matched. The tool lists Cloud Organization members and matches your input,
case-insensitively, against each member's preferred_username (login) and email; the id it
returns is subject_claims.sub — exactly what the backend stores. A full email is the most
reliable key. A bare login (ivan) is treated as ivan@yandex.ru (a legacy compatibility
mapping), so it resolves only for yandex.ru accounts — in a federated organization pass the
full email or the name comes back unresolved. A name that matches more than one subject is left
unresolved rather than guessed. Large orgs are handled: the tool raises yc's default 1000-row
--limit so members past the first page are not silently dropped.
Convert input — the legacy rls config
convert takes the dataset's legacy rls field: a JSON object mapping each field guid to
that field's RLS text — the text you edit in a field's Row-level security settings. It
accepts the whole config (every field) or a single field; {"<one_guid>": "<text>"} is
equally valid, and the output is keyed by the same guids.
Each field's text uses the legacy grammar (one rule per line):
'Moscow': alice@example.com, @group:Analysts
'Tver': alice@example.com
*: bob@example.com
userid: userid
'value': subjects — one quoted value per line; those subjects see rows where the field equals
value (double '' inside to escape a literal quote).
*: subjects — those subjects see all rows.
userid: userid — filter rows by the field equalling the viewer's own id.
When the user pastes just one field's text (the common case — copied from the field's RLS
settings), convert it directly: pass the raw text (stdin or --input) and convert emits the
rules under a <field_guid> placeholder to substitute later. The guid is optional — it never
affects the resolved subjects, only the output key — so if you do have it, wrap the text yourself
as {"<field_guid>": "<text>"} to key the output correctly.
Prerequisites
- Python 3.9+ (standard library only — no
pip install).
- The
yc CLI installed and authenticated (IAM-token session — OAuth Yandex ID is
deprecated for YC). Auth is handled below, by you.
- At least the
organization-manager.viewer role on the target organization (see the
⚠️ warning above) — required to list users/groups.
Authenticate yc — YOU run these checks; never expose the token
Check the session with the bundled wrapper — it runs the token call for you with output
discarded and a timeout, and prints only a status word (never the token):
python3 scripts/rls_tool.py auth-check
authenticated → continue.
not_authenticated / not_installed → re-authenticate or install (below).
timeout → the check is blocked — often an interactive hardware-key touch, or a sandbox
withholding network. Re-authenticate interactively with yc init (below), where you can
respond to the prompt.
Prefer the wrapper so a live token is never exposed. Backstop — never run these yourself:
yc iam create-token without redirecting output, or yc config list / yc config get token —
they print the OAuth token / SA key into the transcript. Never print, echo, log, or store any
token or key. (yc config profile list, which shows only profile names, is fine.)
Re-authenticate — drive it, don't hand the user a to-do list
If step 2 failed, re-auth yourself. Do not use a plain OAuth token: OAuth Yandex ID
tokens are not supported for IAM exchange (error OAuth token … is not supported for IAM token exchange). Use one of these instead:
- Federated SSO (default).
yc init --federation-id <FEDERATION_ID> authenticates via
the org federation in the browser — not subject to the OAuth deprecation. If you don't
already know the federation id, ask the user for it (YC console → Organization →
Federations, or their cloud admin). Run yc init --federation-id <FEDERATION_ID> in an
interactive terminal. If the current agent cannot complete the browser interaction, ask the
user to run that one command locally, then continue automatically.
- Service-account key. If the user has an SA key file:
yc config set service-account-key <path> (a path, not a secret).
Then re-check with python3 scripts/rls_tool.py auth-check and proceed. Do not stop and dump
a list of manual steps — drive the flow, and only hand off the single interactive browser step.
Organization id — YOU fetch it
Run yc organization-manager organization list --format json.
- Exactly one org → use its
id.
- Several → ask the user which one.
Run the resolver — YOU run it, then present the result
Do not tell the user to "then run the resolver". You invoke the tool via Bash yourself
and show them the output.
python3 scripts/rls_tool.py resolve --org-id <ORG_ID> alice@example.com "@group:Analysts" bob
python3 scripts/rls_tool.py convert --org-id <ORG_ID> --input old_rls.json
printf "%s\n" "'Moscow': alice@example.com" "*: bob@example.com" | python3 scripts/rls_tool.py convert --org-id <ORG_ID>
Names may be comma / newline / semicolon separated (not space — cloud group names can
contain spaces). Prefix groups with @group: and service accounts with @sa:. If the tool
prints an auth error (the yc session lapsed mid-run),
re-authenticate as above and retry — automatically, without asking the user to intervene.
Output shape
convert prints exactly what the backend stores:
{
"<field_guid>": [
{"subject": {"subject_id": "aje1234...", "subject_name": "alice@example.com", "subject_type": "user"},
"allowed_value": "Philadelphia", "pattern_type": "value"}
]
}
Subject id details and the yc calls are in references/id-formats.md.
Common mistakes
- Leaking the token. Never run
yc config list / yc config get token or an unredirected
yc iam create-token. Check auth only via python3 scripts/rls_tool.py auth-check.
- Handing work to the user. Drive
yc init and run the resolver yourself; don't tell
the user to do it.
- Sending both
rls and rls2. The backend rejects a dataset with both set — send
only rls2.
- Cross-installation ids. Yandex Cloud ids (cloud subject id / org group id) are not valid on
other DataLens installations.
- Unresolved subjects. In
convert, they are emitted as notfound (never dropped) and
summarized; fix the name and re-run rather than shipping a !FAILED_ entry. In resolve,
they are listed under unresolved.
Verify the transform
python3 tests/test_rls_tool.py runs offline logic tests (parser, normalization,
resolution assembly) whose expected rls2 values mirror the backend.