Update to Control Plane
Snapshot Oct 30, 2026 · 00:05 UTC · version 1.2.0
Collection source: downloaded plugin package.
Instructions updated for setup-cloud-access
Skill instructions — Now says: `grant_cloud_access`, `create_identity`, and `update_identity` are core. **One call once the cloud account exists:** `mcp__cpln__grant_cloud_access`...
Observed in instructions or declared skills. Runtime behavior has not been tested.
Up to 10 plugins free · no card required.
All fields and original values.
Skill instructions
Oct 28, 2026 · 18:05 UTC
`grant_cloud_access` is core. **One call once the cloud account exists:** `mcp__cpln__grant_cloud_access` (`workload`, `provider`, `cloudAccount`, and the provider block from step 3) ensures the workload's identity, attaches the cloud ac...
Oct 30, 2026 · 00:05 UTC
`grant_cloud_access`, `create_identity`, and `update_identity` are core. **One call once the cloud account exists:** `mcp__cpln__grant_cloud_access` (`workload`, `provider`, `cloudAccount`, and the provider block from step 3) ensures the...
Compare saved observations
Download comparison JSONSKILL.md text changes
− removed · + added
--- before +++ after @@ -5,13 +5,13 @@ # Cloud Access Setup (Universal Cloud Identity) -> **Tool availability:** `create_cloud_account`, `update_cloud_account`, and `how_to_create_cloud_account` need `?toolsets=full`; `grant_cloud_access` is core. +> **Tool availability:** `create_cloud_account`, `update_cloud_account`, and `how_to_create_cloud_account` need `?toolsets=full`; `grant_cloud_access`, `create_identity`, and `update_identity` are core. A workload reads cloud resources with **no embedded keys**: a GVC-scoped **identity** carries a per-provider cloud-access block that federates with the provider's IAM, and Control Plane vends short-lived credentials at runtime. Cloud SDKs (boto3, google-cloud, @azure/sdk) pick them up automatically — no SDK config. ## The chain -**One call once the cloud account exists:** `mcp__cpln__grant_cloud_access` (`workload`, `provider`, `cloudAccount`, and the provider block from step 3) ensures the workload's identity, attaches the cloud account to it, and waits for `status.<provider>.usable`. Steps 3 and 4 below are what it does, for hand-built setups. +**One call once the cloud account exists:** `mcp__cpln__grant_cloud_access` (`workload`, `provider`, `cloudAccount`, and the provider block from step 3) ensures the workload's identity, attaches the cloud account to it, and waits for `status.<provider>.usable` (none comes for a reused `roleName` or `serviceAccount`). Steps 3 and 4 below are what it does, for hand-built setups. | Step | What must be true | Without it | |---|---|---| @@ -68,13 +68,13 @@ policyRefs: ["aws::AmazonS3ReadOnlyAccess", "MyCustomPolicy"] ``` -CLI fallback (MCP unavailable / CI-CD): `cpln identity get NAME --gvc GVC -o yaml-slim > id.yaml`, add the block under `spec`, `cpln apply -f id.yaml`. Confirm the exact shape with `get_resource_schema` (kind `identity`) before authoring YAML by hand. +CLI fallback (MCP unavailable / CI-CD): `cpln identity get NAME --gvc GVC -o yaml-slim > id.yaml`, add the block under `spec`, `cpln apply -f id.yaml`. Confirm the exact shape with `get_resource` (kind `identity`, `schema: true`) before authoring YAML by hand. ## Step 4 — Link to the workload and verify `update_workload` sets `spec.identityLink = //identity/NAME` (CLI: `cpln workload update NAME --set spec.identityLink=//identity/NAME`). -Read the identity back with `get_resource` (kind `identity`): `status.<provider>.usable` must be `true`; if `false`, read `status.<provider>.lastError`. Cloud CLIs are usually absent from production containers, so a missing `aws`/`gcloud`/`az` does **not** mean access is broken — the SDK path still works. +Read the identity back with `get_resource` (kind `identity`): `status.<provider>.usable` must be `true`; if `false`, read `status.<provider>.lastError`. Control Plane writes none for a reused `roleName` or `serviceAccount`: the workload's own cloud calls are the check there. Cloud CLIs are usually absent from production containers, so a missing `aws`/`gcloud`/`az` does **not** mean access is broken: the SDK path still works. ## Private-network resources @@ -86,6 +86,6 @@ - **Skipping the how-to** — the org-specific account/external IDs and SA email are required and can't be guessed. - **Full ARN in AWS `policyRefs`** — use the policy name with an optional `aws::` prefix, no colons. - **Both `policyRefs` + `roleName` (AWS) or `bindings` + `serviceAccount` (GCP)** — exactly one. -- **Not checking `status.<provider>.usable`** — verify `true` before linking to the workload. +- **Not checking `status.<provider>.usable`**: verify `true` before linking to the workload (it is never set for a reused `roleName` or `serviceAccount`). - **Confusing cloud access with secret access** — cloud access is the identity's `aws`/`gcp`/`azure`/`ngs` block; secret access is a `reveal` policy on a `cpln://secret/` reference (see **setup-secret**). - **Sharing an identity across GVCs** — recreate it per GVC.
Full technical diff · 1 changed fields
changed /skill_md_contents
"---\nname: setup-cloud-access\ndescription: Credential-free cloud access (Universal Cloud Identity) for a Control Plane workload. Use when a workload needs AWS, GCP, Azure, or NATS NGS resources without embedded keys, or asks to register a cloud account.\n---\n\n# Cloud Access Setup (Universal Cloud Identity)\n\n> **Tool availability:** `create_cloud_account`, `update_cloud_account`, and `how_to_create_cloud_account` need `?toolsets=full`; `grant_cloud_access` is core.\n\nA workload reads cloud resources with **no embedded keys**: a GVC-scoped **identity** carries a per-provider cloud-access block that federates with the provider's IAM, and Control Plane vends short-lived credentials at runtime. Cloud SDKs (boto3, google-cloud, @azure/sdk) pick them up automatically — no SDK config.\n\n## The chain\n\n**One call once the cloud account exists:** `mcp__cpln__grant_cloud_access` (`workload`, `provider`, `cloudAccount`, and the provider block from step 3) ensures the workload's identity, attaches the cloud account to it, and waits for `status.<provider>.usable`. Steps 3 and 4 below are what it does, for hand-built setups.\n\n| Step | What must be true | Without it |\n|---|---|---|\n| **1. Cloud account** | a `cloud_account` (org-wide) maps to the provider, registered after the cloud-side IAM setup | identity can't federate |\n| **2. Identity cloud block** | the identity carries an `aws`/`gcp`/`azure`/`ngs` block linking that cloud account | no credentials vended |\n| **3. Workload link** | the identity is attached to the workload (`spec.identityLink`) | workload has no identity |\n\nOrder is strict: the cloud account must exist **before** the identity's cloud block references it.\n\n## Key constraints\n\n- **Identities are GVC-scoped** — one per workload, shareable within a GVC, never across GVCs. Same access in another GVC = recreate the identity there.\n- **One cloud account per provider per identity** — one AWS + one GCP + one Azure + one NGS is fine; two AWS on one identity is not.\n- **Cloud accounts are org-scoped** — always pass `org`.\n- **Provider is immutable** — to switch providers, delete and recreate the cloud account.\n\n## Step 1 — Cloud-side IAM setup\n\nEach provider needs IAM configured **on the provider side first** so Control Plane can assume a role / impersonate a service account. Run the per-provider how-to to get the org-specific values (Control Plane's AWS account ID + external ID, the GCP service-account email, the Azure Function-App connector steps) — **never guess these**:\n\n- `how_to_create_cloud_account` with `provider: aws` (`cloudAccountName`, `awsAccountId`, `roleArn`) — trust policy, account ID, external ID, the IAM permissions for the `cpln-connector` policy. Create an IAM role with that trust policy + connector policy + `ReadOnlyAccess`; note the **role ARN**.\n- `how_to_create_cloud_account` with `provider: gcp` (`projectId`) — add the shown service account as an IAM principal with **Viewer, Project IAM Admin, Service Account Admin, Service Account Token Creator** (plus the service Admin role, e.g. `roles/storage.admin`, for each resource type identities will use); note the **project ID**.\n- `how_to_create_cloud_account` with `provider: azure` (`subscriptionId`, `resourceGroupName`, `storageAccountName`, `locationName`, `functionAppName`) — create a Function App, deploy the connector, make it subscription **Owner**, capture the Function URL + `iam-broker` code into an `azure-connector` secret.\n- `how_to_create_cloud_account` with `provider: ngs` (`secretName`) — create a `nats-account` secret holding your NATS account credentials.\n\nCLI fallback: `cpln cloudaccount create-<provider> --how --org ORG`.\n\n## Step 2 — Register the cloud account\n\n`create_cloud_account` (`provider` = `aws`/`gcp`/`azure`/`ngs`), passing the value the provider needs:\n\n| Provider | Required field |\n|---|---|\n| aws | `roleArn` (the role ARN from step 1) |\n| gcp | `projectId` |\n| azure | `secretLink` to an existing `azure-connector` secret (created by the user) |\n| ngs | `secretLink` to an existing `nats-account` secret (created by the user) |\n\n`status.usable` stays `false` until the cloud-side IAM exists. `update_cloud_account` edits the data block / tags (provider stays immutable). CLI fallback: `cpln cloudaccount create-aws|create-gcp|create-azure|create-ngs`.\n\n## Step 3 — Identity with a cloud-access block\n\n`create_identity` (or `update_identity` on an existing one) accepts the per-provider block directly — pass `aws`, `gcp`, `azure`, or `ngs`. On update each block **replaces wholesale**; `removeCloudIdentities: [\"aws\"]` detaches one. Every block needs `cloudAccountLink: //cloudaccount/NAME`. The pattern per provider:\n\n- **aws** — Control Plane creates a new IAM role with `policyRefs` (managed = `aws::AmazonS3ReadOnlyAccess`, custom = bare name; chars `a-zA-Z0-9/+=,.@_-` only — **never full ARNs**), **xor** `roleName` to reuse a role. Optional `trustPolicy` (only alongside `policyRefs`).\n- **gcp** — creates a service account with `bindings` (`resource` + `roles` like `roles/storage.objectViewer`; omit `resource` = project), **xor** `serviceAccount` to reuse one. Optional `scopes`.\n- **azure** — creates a managed identity with `roleAssignments` (`scope` + `roles`; omit `scope` = subscription).\n- **ngs** — scoped NATS creds: `pub`/`sub` `allow`/`deny` subjects (`*` single, `>` multi-level), `resp.max`/`resp.ttl`, and `subs`/`data`/`payload` limits (`-1` = no limit).\n\n```yaml\nspec:\n aws:\n cloudAccountLink: //cloudaccount/my-aws\n policyRefs: [\"aws::AmazonS3ReadOnlyAccess\", \"MyCustomPolicy\"]\n```\n\nCLI fallback (MCP unavailable / CI-CD): `cpln identity get NAME --gvc GVC -o yaml-slim > id.yaml`, add the block under `spec`, `cpln apply -f id.yaml`. Confirm the exact shape with `get_resource_schema` (kind `identity`) before authoring YAML by hand.\n\n## Step 4 — Link to the workload and verify\n\n`update_workload` sets `spec.identityLink = //identity/NAME` (CLI: `cpln workload update NAME --set spec.identityLink=//identity/NAME`).\n\nRead the identity back with `get_resource` (kind `identity`): `status.<provider>.usable` must be `true`; if `false`, read `status.<provider>.lastError`. Cloud CLIs are usually absent from production containers, so a missing `aws`/`gcloud`/`az` does **not** mean access is broken — the SDK path still works.\n\n## Private-network resources\n\nReaching a private VPC / on-prem endpoint is a different mechanism on the **same identity**: a `networkResources` (agent/wormhole) or `nativeNetworkResources` (AWS PrivateLink / GCP PSC) array, not a cloud-access block. For the agent deployment walkthrough use **setup-agent**; for the comparison, producer-side setup, and the resource schema use **native-networking**.\n\n## Common mistakes\n\n- **Cloud block before the cloud account** — register the account first; the link won't resolve otherwise.\n- **Skipping the how-to** — the org-specific account/external IDs and SA email are required and can't be guessed.\n- **Full ARN in AWS `policyRefs`** — use the policy name with an optional `aws::` prefix, no colons.\n- **Both `policyRefs` + `roleName` (AWS) or `bindings` + `serviceAccount` (GCP)** — exactly one.\n- **Not checking `status.<provider>.usable`** — verify `true` before linking to the workload.\n- **Confusing cloud access with secret access** — cloud access is the identity's `aws`/`gcp`/`azure`/`ngs` block; secret access is a `reveal` policy on a `cpln://secret/` reference (see **setup-secret**).\n- **Sharing an identity across GVCs** — recreate it per GVC.\n"
"---\nname: setup-cloud-access\ndescription: Credential-free cloud access (Universal Cloud Identity) for a Control Plane workload. Use when a workload needs AWS, GCP, Azure, or NATS NGS resources without embedded keys, or asks to register a cloud account.\n---\n\n# Cloud Access Setup (Universal Cloud Identity)\n\n> **Tool availability:** `create_cloud_account`, `update_cloud_account`, and `how_to_create_cloud_account` need `?toolsets=full`; `grant_cloud_access`, `create_identity`, and `update_identity` are core.\n\nA workload reads cloud resources with **no embedded keys**: a GVC-scoped **identity** carries a per-provider cloud-access block that federates with the provider's IAM, and Control Plane vends short-lived credentials at runtime. Cloud SDKs (boto3, google-cloud, @azure/sdk) pick them up automatically — no SDK config.\n\n## The chain\n\n**One call once the cloud account exists:** `mcp__cpln__grant_cloud_access` (`workload`, `provider`, `cloudAccount`, and the provider block from step 3) ensures the workload's identity, attaches the cloud account to it, and waits for `status.<provider>.usable` (none comes for a reused `roleName` or `serviceAccount`). Steps 3 and 4 below are what it does, for hand-built setups.\n\n| Step | What must be true | Without it |\n|---|---|---|\n| **1. Cloud account** | a `cloud_account` (org-wide) maps to the provider, registered after the cloud-side IAM setup | identity can't federate |\n| **2. Identity cloud block** | the identity carries an `aws`/`gcp`/`azure`/`ngs` block linking that cloud account | no credentials vended |\n| **3. Workload link** | the identity is attached to the workload (`spec.identityLink`) | workload has no identity |\n\nOrder is strict: the cloud account must exist **before** the identity's cloud block references it.\n\n## Key constraints\n\n- **Identities are GVC-scoped** — one per workload, shareable within a GVC, never across GVCs. Same access in another GVC = recreate the identity there.\n- **One cloud account per provider per identity** — one AWS + one GCP + one Azure + one NGS is fine; two AWS on one identity is not.\n- **Cloud accounts are org-scoped** — always pass `org`.\n- **Provider is immutable** — to switch providers, delete and recreate the cloud account.\n\n## Step 1 — Cloud-side IAM setup\n\nEach provider needs IAM configured **on the provider side first** so Control Plane can assume a role / impersonate a service account. Run the per-provider how-to to get the org-specific values (Control Plane's AWS account ID + external ID, the GCP service-account email, the Azure Function-App connector steps) — **never guess these**:\n\n- `how_to_create_cloud_account` with `provider: aws` (`cloudAccountName`, `awsAccountId`, `roleArn`) — trust policy, account ID, external ID, the IAM permissions for the `cpln-connector` policy. Create an IAM role with that trust policy + connector policy + `ReadOnlyAccess`; note the **role ARN**.\n- `how_to_create_cloud_account` with `provider: gcp` (`projectId`) — add the shown service account as an IAM principal with **Viewer, Project IAM Admin, Service Account Admin, Service Account Token Creator** (plus the service Admin role, e.g. `roles/storage.admin`, for each resource type identities will use); note the **project ID**.\n- `how_to_create_cloud_account` with `provider: azure` (`subscriptionId`, `resourceGroupName`, `storageAccountName`, `locationName`, `functionAppName`) — create a Function App, deploy the connector, make it subscription **Owner**, capture the Function URL + `iam-broker` code into an `azure-connector` secret.\n- `how_to_create_cloud_account` with `provider: ngs` (`secretName`) — create a `nats-account` secret holding your NATS account credentials.\n\nCLI fallback: `cpln cloudaccount create-<provider> --how --org ORG`.\n\n## Step 2 — Register the cloud account\n\n`create_cloud_account` (`provider` = `aws`/`gcp`/`azure`/`ngs`), passing the value the provider needs:\n\n| Provider | Required field |\n|---|---|\n| aws | `roleArn` (the role ARN from step 1) |\n| gcp | `projectId` |\n| azure | `secretLink` to an existing `azure-connector` secret (created by the user) |\n| ngs | `secretLink` to an existing `nats-account` secret (created by the user) |\n\n`status.usable` stays `false` until the cloud-side IAM exists. `update_cloud_account` edits the data block / tags (provider stays immutable). CLI fallback: `cpln cloudaccount create-aws|create-gcp|create-azure|create-ngs`.\n\n## Step 3 — Identity with a cloud-access block\n\n`create_identity` (or `update_identity` on an existing one) accepts the per-provider block directly — pass `aws`, `gcp`, `azure`, or `ngs`. On update each block **replaces wholesale**; `removeCloudIdentities: [\"aws\"]` detaches one. Every block needs `cloudAccountLink: //cloudaccount/NAME`. The pattern per provider:\n\n- **aws** — Control Plane creates a new IAM role with `policyRefs` (managed = `aws::AmazonS3ReadOnlyAccess`, custom = bare name; chars `a-zA-Z0-9/+=,.@_-` only — **never full ARNs**), **xor** `roleName` to reuse a role. Optional `trustPolicy` (only alongside `policyRefs`).\n- **gcp** — creates a service account with `bindings` (`resource` + `roles` like `roles/storage.objectViewer`; omit `resource` = project), **xor** `serviceAccount` to reuse one. Optional `scopes`.\n- **azure** — creates a managed identity with `roleAssignments` (`scope` + `roles`; omit `scope` = subscription).\n- **ngs** — scoped NATS creds: `pub`/`sub` `allow`/`deny` subjects (`*` single, `>` multi-level), `resp.max`/`resp.ttl`, and `subs`/`data`/`payload` limits (`-1` = no limit).\n\n```yaml\nspec:\n aws:\n cloudAccountLink: //cloudaccount/my-aws\n policyRefs: [\"aws::AmazonS3ReadOnlyAccess\", \"MyCustomPolicy\"]\n```\n\nCLI fallback (MCP unavailable / CI-CD): `cpln identity get NAME --gvc GVC -o yaml-slim > id.yaml`, add the block under `spec`, `cpln apply -f id.yaml`. Confirm the exact shape with `get_resource` (kind `identity`, `schema: true`) before authoring YAML by hand.\n\n## Step 4 — Link to the workload and verify\n\n`update_workload` sets `spec.identityLink = //identity/NAME` (CLI: `cpln workload update NAME --set spec.identityLink=//identity/NAME`).\n\nRead the identity back with `get_resource` (kind `identity`): `status.<provider>.usable` must be `true`; if `false`, read `status.<provider>.lastError`. Control Plane writes none for a reused `roleName` or `serviceAccount`: the workload's own cloud calls are the check there. Cloud CLIs are usually absent from production containers, so a missing `aws`/`gcloud`/`az` does **not** mean access is broken: the SDK path still works.\n\n## Private-network resources\n\nReaching a private VPC / on-prem endpoint is a different mechanism on the **same identity**: a `networkResources` (agent/wormhole) or `nativeNetworkResources` (AWS PrivateLink / GCP PSC) array, not a cloud-access block. For the agent deployment walkthrough use **setup-agent**; for the comparison, producer-side setup, and the resource schema use **native-networking**.\n\n## Common mistakes\n\n- **Cloud block before the cloud account** — register the account first; the link won't resolve otherwise.\n- **Skipping the how-to** — the org-specific account/external IDs and SA email are required and can't be guessed.\n- **Full ARN in AWS `policyRefs`** — use the policy name with an optional `aws::` prefix, no colons.\n- **Both `policyRefs` + `roleName` (AWS) or `bindings` + `serviceAccount` (GCP)** — exactly one.\n- **Not checking `status.<provider>.usable`**: verify `true` before linking to the workload (it is never set for a reused `roleName` or `serviceAccount`).\n- **Confusing cloud access with secret access** — cloud access is the identity's `aws`/`gcp`/`azure`/`ngs` block; secret access is a `reveal` policy on a `cpln://secret/` reference (see **setup-secret**).\n- **Sharing an identity across GVCs** — recreate it per GVC.\n"
Full snapshot data
{
"description": "Credential-free cloud access (Universal Cloud Identity) for a Control Plane workload. Use when a workload needs AWS, GCP, Azure, or NATS NGS resources without embedded keys, or asks to register a cloud account.",
"included_files": [],
"name": "setup-cloud-access",
"skill_md_contents": "---\nname: setup-cloud-access\ndescription: Credential-free cloud access (Universal Cloud Identity) for a Control Plane workload. Use when a workload needs AWS, GCP, Azure, or NATS NGS resources without embedded keys, or asks to register a cloud account.\n---\n\n# Cloud Access Setup (Universal Cloud Identity)\n\n> **Tool availability:** `create_cloud_account`, `update_cloud_account`, and `how_to_create_cloud_account` need `?toolsets=full`; `grant_cloud_access`, `create_identity`, and `update_identity` are core.\n\nA workload reads cloud resources with **no embedded keys**: a GVC-scoped **identity** carries a per-provider cloud-access block that federates with the provider's IAM, and Control Plane vends short-lived credentials at runtime. Cloud SDKs (boto3, google-cloud, @azure/sdk) pick them up automatically — no SDK config.\n\n## The chain\n\n**One call once the cloud account exists:** `mcp__cpln__grant_cloud_access` (`workload`, `provider`, `cloudAccount`, and the provider block from step 3) ensures the workload's identity, attaches the cloud account to it, and waits for `status.<provider>.usable` (none comes for a reused `roleName` or `serviceAccount`). Steps 3 and 4 below are what it does, for hand-built setups.\n\n| Step | What must be true | Without it |\n|---|---|---|\n| **1. Cloud account** | a `cloud_account` (org-wide) maps to the provider, registered after the cloud-side IAM setup | identity can't federate |\n| **2. Identity cloud block** | the identity carries an `aws`/`gcp`/`azure`/`ngs` block linking that cloud account | no credentials vended |\n| **3. Workload link** | the identity is attached to the workload (`spec.identityLink`) | workload has no identity |\n\nOrder is strict: the cloud account must exist **before** the identity's cloud block references it.\n\n## Key constraints\n\n- **Identities are GVC-scoped** — one per workload, shareable within a GVC, never across GVCs. Same access in another GVC = recreate the identity there.\n- **One cloud account per provider per identity** — one AWS + one GCP + one Azure + one NGS is fine; two AWS on one identity is not.\n- **Cloud accounts are org-scoped** — always pass `org`.\n- **Provider is immutable** — to switch providers, delete and recreate the cloud account.\n\n## Step 1 — Cloud-side IAM setup\n\nEach provider needs IAM configured **on the provider side first** so Control Plane can assume a role / impersonate a service account. Run the per-provider how-to to get the org-specific values (Control Plane's AWS account ID + external ID, the GCP service-account email, the Azure Function-App connector steps) — **never guess these**:\n\n- `how_to_create_cloud_account` with `provider: aws` (`cloudAccountName`, `awsAccountId`, `roleArn`) — trust policy, account ID, external ID, the IAM permissions for the `cpln-connector` policy. Create an IAM role with that trust policy + connector policy + `ReadOnlyAccess`; note the **role ARN**.\n- `how_to_create_cloud_account` with `provider: gcp` (`projectId`) — add the shown service account as an IAM principal with **Viewer, Project IAM Admin, Service Account Admin, Service Account Token Creator** (plus the service Admin role, e.g. `roles/storage.admin`, for each resource type identities will use); note the **project ID**.\n- `how_to_create_cloud_account` with `provider: azure` (`subscriptionId`, `resourceGroupName`, `storageAccountName`, `locationName`, `functionAppName`) — create a Function App, deploy the connector, make it subscription **Owner**, capture the Function URL + `iam-broker` code into an `azure-connector` secret.\n- `how_to_create_cloud_account` with `provider: ngs` (`secretName`) — create a `nats-account` secret holding your NATS account credentials.\n\nCLI fallback: `cpln cloudaccount create-<provider> --how --org ORG`.\n\n## Step 2 — Register the cloud account\n\n`create_cloud_account` (`provider` = `aws`/`gcp`/`azure`/`ngs`), passing the value the provider needs:\n\n| Provider | Required field |\n|---|---|\n| aws | `roleArn` (the role ARN from step 1) |\n| gcp | `projectId` |\n| azure | `secretLink` to an existing `azure-connector` secret (created by the user) |\n| ngs | `secretLink` to an existing `nats-account` secret (created by the user) |\n\n`status.usable` stays `false` until the cloud-side IAM exists. `update_cloud_account` edits the data block / tags (provider stays immutable). CLI fallback: `cpln cloudaccount create-aws|create-gcp|create-azure|create-ngs`.\n\n## Step 3 — Identity with a cloud-access block\n\n`create_identity` (or `update_identity` on an existing one) accepts the per-provider block directly — pass `aws`, `gcp`, `azure`, or `ngs`. On update each block **replaces wholesale**; `removeCloudIdentities: [\"aws\"]` detaches one. Every block needs `cloudAccountLink: //cloudaccount/NAME`. The pattern per provider:\n\n- **aws** — Control Plane creates a new IAM role with `policyRefs` (managed = `aws::AmazonS3ReadOnlyAccess`, custom = bare name; chars `a-zA-Z0-9/+=,.@_-` only — **never full ARNs**), **xor** `roleName` to reuse a role. Optional `trustPolicy` (only alongside `policyRefs`).\n- **gcp** — creates a service account with `bindings` (`resource` + `roles` like `roles/storage.objectViewer`; omit `resource` = project), **xor** `serviceAccount` to reuse one. Optional `scopes`.\n- **azure** — creates a managed identity with `roleAssignments` (`scope` + `roles`; omit `scope` = subscription).\n- **ngs** — scoped NATS creds: `pub`/`sub` `allow`/`deny` subjects (`*` single, `>` multi-level), `resp.max`/`resp.ttl`, and `subs`/`data`/`payload` limits (`-1` = no limit).\n\n```yaml\nspec:\n aws:\n cloudAccountLink: //cloudaccount/my-aws\n policyRefs: [\"aws::AmazonS3ReadOnlyAccess\", \"MyCustomPolicy\"]\n```\n\nCLI fallback (MCP unavailable / CI-CD): `cpln identity get NAME --gvc GVC -o yaml-slim > id.yaml`, add the block under `spec`, `cpln apply -f id.yaml`. Confirm the exact shape with `get_resource` (kind `identity`, `schema: true`) before authoring YAML by hand.\n\n## Step 4 — Link to the workload and verify\n\n`update_workload` sets `spec.identityLink = //identity/NAME` (CLI: `cpln workload update NAME --set spec.identityLink=//identity/NAME`).\n\nRead the identity back with `get_resource` (kind `identity`): `status.<provider>.usable` must be `true`; if `false`, read `status.<provider>.lastError`. Control Plane writes none for a reused `roleName` or `serviceAccount`: the workload's own cloud calls are the check there. Cloud CLIs are usually absent from production containers, so a missing `aws`/`gcloud`/`az` does **not** mean access is broken: the SDK path still works.\n\n## Private-network resources\n\nReaching a private VPC / on-prem endpoint is a different mechanism on the **same identity**: a `networkResources` (agent/wormhole) or `nativeNetworkResources` (AWS PrivateLink / GCP PSC) array, not a cloud-access block. For the agent deployment walkthrough use **setup-agent**; for the comparison, producer-side setup, and the resource schema use **native-networking**.\n\n## Common mistakes\n\n- **Cloud block before the cloud account** — register the account first; the link won't resolve otherwise.\n- **Skipping the how-to** — the org-specific account/external IDs and SA email are required and can't be guessed.\n- **Full ARN in AWS `policyRefs`** — use the policy name with an optional `aws::` prefix, no colons.\n- **Both `policyRefs` + `roleName` (AWS) or `bindings` + `serviceAccount` (GCP)** — exactly one.\n- **Not checking `status.<provider>.usable`**: verify `true` before linking to the workload (it is never set for a reused `roleName` or `serviceAccount`).\n- **Confusing cloud access with secret access** — cloud access is the identity's `aws`/`gcp`/`azure`/`ngs` block; secret access is a `reveal` policy on a `cpln://secret/` reference (see **setup-secret**).\n- **Sharing an identity across GVCs** — recreate it per GVC.\n"
}SHA-256 of public snapshot: 607ec519c7229fc16ba2384520a73ef5a44edfc7182d532be79dffb67587b726