From greennode-agentbase
Authors authorization policies for GreenNode AgentBase resources including policy groups, statements, and condition operators. Useful for managing access to Resource Gateway (MCP).
How this skill is triggered — by the user, by Claude, or both
Slash command
/greennode-agentbase:agentbase-policyThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Author authorization policies for GreenNode AgentBase resources. A policy decides whether a given caller (identified by `principal`) is allowed to perform a given `action` on a given `resource`, optionally conditioned on attributes of the caller and the request context.
Author authorization policies for GreenNode AgentBase resources. A policy decides whether a given caller (identified by principal) is allowed to perform a given action on a given resource, optionally conditioned on attributes of the caller and the request context.
The Policy service is resource-type-agnostic by design — resources are written as <type>:<name> and actions are free-form strings. Today the only resource type wired into a runtime enforcement point is gateway (the Resource Gateway, which evaluates MCP JSON-RPC calls such as tools/call), but the model is intended to extend to additional resource types over time.
Parse the user's arguments to determine the operation and optional group/policy ID.
https://agentbase.api.vngcloud.vn/policy/api/v1https://agentbase.api.vngcloud.vn/policy/api/v1/policies/condition-operatorsRead the shared auth setup reference at /agentbase skill's references/auth-setup.md for full IAM credential configuration. In brief: run bash .claude/skills/agentbase/scripts/check_credentials.sh iam to verify credentials are configured, then use TOKEN=$(bash .claude/skills/agentbase/scripts/get_token.sh) to obtain a token. NEVER read .greennode.json or .env directly — always use the helper scripts. On 401: re-run with --force. If check_credentials.sh iam returns MISSING, STOP — you MUST read the "If Credentials Are Not Found" section in /agentbase skill's references/auth-setup.md and follow it exactly. Do NOT skip this or provide your own credential setup instructions.
IMPORTANT: Before constructing any API URL, read /agentbase skill's references/endpoints.md for the domain validation whitelist. Only use domains listed there.
statement JSON (effect / principal / actions / resources / condition), and the target Policy Group, then ask the user to confirm. Do NOT auto-execute. Proceed only when the user responds with an explicit confirmation keyword: yes, confirm, ok, approve, proceed, go ahead, do it, ship it, lgtm, or equivalent affirmative. If the user responds with anything else (parameter changes, questions, corrections), treat it as adjustment input — update the plan and re-present for confirmation. NEVER interpret a non-confirmation response as approval. For destructive operations (delete policy, delete policy group — which cascades and removes all child policies), additionally warn that the action is irreversible.effect, principal, actions, resources, and each condition clause. You may recommend sensible defaults and show the impact of each choice, but never silently pick.deny policy in a group matches a request, the decision is deny. If a user writes a deny rule alongside allow rules in the same group, surface this so they understand the outcome.gateway today, the Resource Gateway always permits the MCP discovery method tools/list. If a user expects to block a "list/discovery"-style action with a policy, check the resource type's behaviour first and say so.--dry-run or preview, show the exact API request (method, URL, headers, payload) and explain the expected outcome WITHOUT executing.operator "is" is not supported; see GET /api/v1/policy/condition-operators — surface that text to the user verbatim instead of paraphrasing.| Concept | Description | Quota |
|---|---|---|
| Policy Group | Top-level container of policies, identified by policyGroupId. The enforcement point (today: the Resource Gateway) evaluates one group per request. | Max 20 per user |
| Policy | Single authorization rule belonging to a group. The rule body lives under the statement field. | Max 10 per group |
statement | The rule body: effect, principal, actions, resources, condition. Sent as the statement field on create/update. | — |
| Effect | allow or deny. Lowercase only. When any matching deny exists in the group, the decision is deny. | — |
| Principal | Caller scope: * (any), jwt:*, iam:*, jwt:<id>, iam:<id>. Only jwt and iam types are recognised. | — |
| Actions | List of actions the rule applies to. ["*"] or specific entries matching target__method (alphanumeric + underscore, with __ as the separator). The Policy service validates the format generically; the meaning of target__method is set by the resource type. For gateway today, target is the MCP server target name on the gateway and method is the tool name in tools/call (e.g. hr__lookup_employee matches tools/call to target hr, tool lookup_employee). Other resource types will define their own action vocabulary. | ≥1 |
| Resources | List of <type>:<name> entries (e.g. gateway:hr-prod), or <type>:*, or the universal *. Wildcard cannot be mixed with specific entries. The only resource type recognised today is gateway. | ≥1 |
| Condition | Map of <operator> → { <key>: <value> }. Multiple operators AND together; multiple keys inside one operator AND together. Omit for unconditional rules. | optional |
Resource-type-specific behaviour. Each resource type can short-circuit certain actions. For
gatewaytoday,tools/listis always allowed regardless of policies. New resource types may have their own bypasses — when in doubt, check the resource type's documentation.
| Operator | Arity | Value type | Example |
|---|---|---|---|
equals | single | string / long / bool | {"equals": {"principal.role": "analyst"}} |
notEquals | single | string / long / bool | {"notEquals": {"principal.status": "suspended"}} |
in | list | string[] | {"in": {"context.ip": ["203.0.113.10", "203.0.113.11"]}} |
like | single | string (glob *) | {"like": {"principal.role": "admin-*"}} |
contains | single | string | {"contains": {"principal.email": "@vng.com.vn"}} |
lessThan | single | long | {"lessThan": {"context.input.qty": 100}} |
lessThanOrEqual | single | long | {"lessThanOrEqual": {"context.input.qty": 100}} |
greaterThan | single | long | {"greaterThan": {"context.input.qty": 0}} |
greaterThanOrEqual | single | long | {"greaterThanOrEqual": {"context.input.qty": 1}} |
Any other operator name is rejected by the API (HTTP 400) with a pointer to the operator catalog. Live source of truth: GET /policy/api/v1/policies/condition-operators.
Each key is <prefix>.<identifier> (single identifier, letters/digits/underscore, not starting with a digit; no nested paths). The API accepts three prefixes at create/update time — context.<name>, context.input.<name>, principal.<name> — but only the specific keys below are populated by the enforcement point today. Any other key in those namespaces is syntactically valid but will never match at decision time, so the rule effectively never fires.
For the gateway resource type, the keys populated today are:
| Key | Source | Notes |
|---|---|---|
context.ip | Client IP of the inbound request. | Always populated. |
context.input.<name> | Subfield <name> of params.arguments in the MCP JSON-RPC body. | Only present for actions that carry a params.arguments object (in practice, tools/call). Referencing a subfield the caller did not send produces a TYPE_MISMATCH deny — not a silent miss. |
principal.<name> | A claim from the caller's JWT. | JWT inbound auth only. When the gateway is fronted by other inbound auth methods (e.g. IAM), there are no JWT claims to match against, so a condition on principal.* will never be satisfied. If a user wants per-IAM-user rules, identify them via the principal: "iam:<id>" header instead. |
principal.id is reserved (caller identity belongs in the policy's principal field, not in a condition) and resource.* keys are not supported.
| Operation | Method | Endpoint |
|---|---|---|
| Create | POST | /policy-groups |
| List | GET | /policy-groups?page=1&page_size=10&name=... |
| Get | GET | /policy-groups/{group_id} |
| Update | PUT | /policy-groups/{group_id} |
| Delete (cascade) | DELETE | /policy-groups/{group_id} |
| Operation | Method | Endpoint |
|---|---|---|
| Create | POST | /policy-groups/{group_id}/policies |
| List | GET | /policy-groups/{group_id}/policies?page=1&page_size=10&name=... |
| Get | GET | /policy-groups/{group_id}/policies/{policy_id} |
| Update | PUT | /policy-groups/{group_id}/policies/{policy_id} |
| Delete | DELETE | /policy-groups/{group_id}/policies/{policy_id} |
| Operation | Method | Endpoint |
|---|---|---|
| List supported operators | GET | /policies/condition-operators (sends Accept-Language: en|vi for localized display names) |
Pagination: Policy service uses 1-indexed pagination with the GreenNode-style response shape (listData, totalItem, totalPage, page, pageSize). Defaults: page=1, page_size=10, max page_size=100.
Read references/policy-statement.md for full statement authoring rules. Read references/policy-ops.md for curl recipes for every endpoint. Read references/examples.md for end-to-end realistic policy examples.
group or policy, plus create | list | get | update | delete) and any name/ID provided./agentbase skill's references/auth-setup.md — do not invent your own.GET /policy-groups) and let the user pick.statement field individually — effect, principal, actions, resources, and each condition clause. Validate locally against the rules in references/policy-statement.md before sending; this surfaces problems faster than a round trip.requests with the same payload shape.| Error | Cause | Fix |
|---|---|---|
operator "X" is not supported | Used an operator outside the supported set. | Use one of the 9 supported operators. GET /policies/condition-operators is the live source of truth. |
unknown operator "X" | Typo or unsupported operator name. | Check the operator catalog. Operator names are case-sensitive camelCase. |
invalid condition key "X" | Key does not match context.<name>, context.input.<name>, or principal.<name> (single identifier, no nested paths). | Use one of the allowed prefixes with a single identifier. |
invalid effect "X": must be 'allow' or 'deny' | Used Allow / Deny / permit / forbid. | Lowercase allow or deny only. |
invalid action entry "X": must be '*' or match targetname__methodname | Used /, space, dash, or other unsupported characters in an action. | Use * or target__method (alphanumeric + underscore, with __ between target and method). |
wildcard resource cannot be mixed with specific entries | Mixed * (or gateway:*) with gateway:foo. | Use either wildcard alone or only specific entries. |
| 401 Unauthorized | Expired or invalid IAM token | Re-obtain token with bash .claude/skills/agentbase/scripts/get_token.sh --force. Confirm GREENNODE_CLIENT_ID / GREENNODE_CLIENT_SECRET are correct. |
| 403 Forbidden | Service account lacks Policy service permissions | Check IAM roles at https://iam.console.vngcloud.vn |
| 404 Not Found on policy | Policy ID does not exist in the given group | Verify with GET /policy-groups/{group_id}/policies |
| 409 Conflict | Group or policy name already exists for this portal user / group | Pick a different name |
| 429 Too Many Requests | Exceeded quota (20 groups/user or 10 policies/group) | Delete unused entries or consolidate |
npx claudepluginhub vngcloud/greennode-agentbase-skills --plugin greennode-agentbaseManages GreenNode AgentBase Resource Gateway (MCP) — a managed proxy for MCP servers with inbound/outbound auth, policy enforcement, and VPC routing. Use for gateway CRUD, target registration, auth configuration, and policy binding.
Authors, edits, and applies Descope FGA schemas using the ReBAC/ABAC DSL. Handles schema creation, modification, dry-run validation, and application via the Descope Management MCP.
Creates ZPA access policy rules with v2 conditions. Walks through requirements gathering, identity attribute lookups, condition payload construction, and rule creation.