diff --git a/plugin/skills/aca-sandboxes/SKILL.md b/plugin/skills/aca-sandboxes/SKILL.md index 7a63ef0..ed686ce 100644 --- a/plugin/skills/aca-sandboxes/SKILL.md +++ b/plugin/skills/aca-sandboxes/SKILL.md @@ -33,7 +33,7 @@ folder. > ⚠️ **There is no `aca sandbox-group` (hyphenated) command group.** > Every group-level verb is `aca sandboxgroup …` (no hyphen): > `aca sandboxgroup create / get / list / delete / role create / -> identity assign / secret upsert / disk list / volume create / snapshot …`. +> identity assign / secret set / disk list / volume create / snapshot …`. > The hyphenated `--sandbox-group ` is the *flag* you pass to > top-level commands to select the default group — it is not a verb. > If you see `aca sandbox-group …` in a snippet (including for MCP @@ -50,7 +50,7 @@ intent. |---|---| | **Install the `aca` CLI** (any OS) | (1) The curl/iwr one-liner from [references/install.md](references/install.md) — use the `https://aka.ms/aca-cli-install` (Linux/macOS) and `https://aka.ms/aca-cli-install-ps` (Windows) short URLs. (2) `aca --version` + **auth-aware sign-in** (`az account show -o none 2>$null; if ($LASTEXITCODE -ne 0) { az login }`, then `aca auth login` to acquire an `aca` token — never call `az login` or `aca auth login` unconditionally; gate both on a status check) + `aca doctor`. The CLI surface for auth is **`aca auth login`** (the top-level `aca` binary does not have a bare `login` subcommand). (3) The explicit sentence: **"this same install path is also used inside sandboxes and containers for agent-driven self-installs."** | | **Bootstrap a sandbox group (one-time setup)** | The 4-step flow: **check auth first** (`az account show -o none 2>$null; if ($LASTEXITCODE -ne 0) { az login }`, then `aca auth login` if `aca` is not yet authenticated — *never* call `az login` or `aca auth login` unconditionally) → `aca sandboxgroup create --name --location --set-config` → `aca sandboxgroup role create --role "Container Apps SandboxGroup Data Owner" --principal-id $(az ad signed-in-user show --query id -o tsv)` → `aca doctor`. **`--set-config` is required** so subsequent `aca sandbox …` commands don't need `--group` on every call. Treat green `aca doctor` as the gate before doing anything else. **Heads-up:** `aca sandboxgroup create` already grants the Data Owner role to the calling principal, so the explicit `role create` is only needed when granting access to *additional* principals (use `--skip-role-check` on `create` if you want to defer). | -| **Create a sandbox (imperative)** | Minimum: `aca sandbox create --disk ubuntu`. Common knobs: `--cpu 2000m`, `--memory 4096Mi`, `--env "K=V"`, `--labels "name=dev,role=worker"`. Capture the printed ID into `SANDBOX_ID=$(aca sandbox create --disk ubuntu -o json \| jq -r .id)` for reuse. For config that should live in source control, use the manifest flow (see the row below) instead. | +| **Create a sandbox (imperative)** | Minimum: `aca sandbox create --disk ubuntu`. Common knobs: `--cpu 2000m`, `--memory 4096Mi`, `--env "K=V"`, `--label name=dev --label role=worker` (repeatable; **not** `--labels`). Capture the printed ID into `SANDBOX_ID=$(aca sandbox create --disk ubuntu -o json \| jq -r .id)` for reuse. For config that should live in source control, use the manifest flow (see the row below) instead. | | **Apply / deploy a sandbox manifest** | The full 3-command flow: `aca sandbox init` → `aca sandbox validate --file sandbox.yaml` → `aca sandbox apply --file sandbox.yaml`. Always `--file` (no `-f` short flag). State that **the manifest pattern is the recommended path for CI/CD and reproducibility**, in contrast to imperative `aca sandbox create`. If no manifest is present, run `aca sandbox init` — don't ask for a path. | | **Scaffold / generate a sandbox manifest** | Run (or show) `aca sandbox init` to scaffold a starter `sandbox.yaml`. Mention the commonly edited fields (`disk`, `resources`, `lifecycle.autoSuspendPolicy`, `egressPolicy`, plus `ports`, `env`, `labels` as needed). Mention `aca sandbox schema` as the way to dump the JSON Schema for editor autocomplete. | | **Run a command or open a shell in a sandbox** | Two distinct verbs: `aca sandbox exec --id "$SANDBOX_ID" -c ""` for one-shot commands (returns stdout/stderr); `aca sandbox shell --id "$SANDBOX_ID"` for an interactive PTY. **Anti-cue:** `ssh` does not work — there is no SSH daemon inside the sandbox. `aca sandbox exec` / `shell` is the only path. | @@ -59,7 +59,7 @@ intent. | **Expose a port — public preview (anonymous)** | The two-step shape: `URL=$(aca sandbox port add --id "$SANDBOX_ID" --port

--anonymous -o json \| jq -r .url)`, then hit `$URL`. **State explicitly** that anonymous = anyone with the URL can reach it (public preview only). Remove with `aca sandbox port remove --id "$SANDBOX_ID" --port

`. For per-user gating use the Entra row below. | | **Expose a port with Entra auth (per-user gating)** | `aca sandbox port add --id "$SANDBOX_ID" --port

--auth entra --allow-principal `. Fetch the principal's object id with `az ad signed-in-user show --query id -o tsv` (or `az ad user show --id --query id -o tsv` for someone else). Pass `--allow-principal` once per principal you want to admit. **Anti-cue:** there is **no `--email` flag** — that's a stale shape; the supported gating is `--auth entra` + `--allow-principal `. | | **Mount a shared volume** | Two-step: (1) at the group: `aca sandboxgroup volume create --name --type AzureBlob` (multi-attach, shared) or `--type DataDisk` (single-attach, high-perf block). (2) at the sandbox: `aca sandbox mount --id "$SANDBOX_ID" --volume --path /mnt/`. State that **the volume lives at the group level**; sandboxes attach it at runtime. | -| **Lock down network egress (deny-default + allow-list)** | The canonical form: `aca sandbox egress set --id "$SANDBOX_ID" --default Deny --host-allow "*.github.com" --traffic-inspection Full`. Multiple `--host-allow ""` flags accumulate. Inspect current policy with `aca sandbox egress show --id "$SANDBOX_ID"`. For production agent code, **always recommend `--default Deny`** with an explicit `--host-allow` list. **Anti-cue:** do not invent flags for individual IPs or block-lists — the only supported shape is `--default Deny|Allow` plus repeated `--host-allow`. | +| **Lock down network egress (deny-default + allow-list)** | The canonical form: `aca sandbox egress set --id "$SANDBOX_ID" --default Deny --rule "*.github.com:Allow" --traffic-inspection Full`. Multiple `--rule ":Allow"` flags accumulate. Inspect current policy with `aca sandbox egress show --id "$SANDBOX_ID"`. For production agent code, **always recommend `--default Deny`** with an explicit `--rule` allow-list. **Anti-cue:** do not invent flags for individual IPs or block-lists, and **not** `--host-allow` — the only supported shape is `--default Deny|Allow` plus repeated `--rule ":Allow|Deny"`. | | **List / use a disk image** | The canonical "what disks are available?" verb is **`aca sandboxgroup disk list-public`** (NOT `aca disks list`, which does not exist). Common presets include `ubuntu`, `debian`, `alpine`, `python`, `node`, `dotnet`, and `playwright`. To bake your own from an OCI image: `aca sandboxgroup disk create --image docker.io/library/alpine:3.19 --name `, then `aca sandbox create --disk-id `. **Flag distinction:** `--disk` takes the public preset name; `--disk-id` takes the resource ID of a private/committed disk. | | **Suspend, resume, or set auto-suspend** | Manual: `aca sandbox stop --id "$SANDBOX_ID"` suspends (preserves memory + disk); `aca sandbox resume --id "$SANDBOX_ID"` does sub-second restore. Idle policy: `aca sandbox lifecycle set --id "$SANDBOX_ID" --auto-suspend ` (default 300s = 5 min). State that **suspended sandboxes incur storage cost only, no compute** — this is the primary cost lever. | | **Snapshot / commit a sandbox** | Per-sandbox: `aca sandbox snapshot --id "$SANDBOX_ID" --name `, then boot replicas with `aca sandbox create --snapshot `. Group-level CRUD: `aca sandboxgroup snapshot list / get / delete --selector "name="`. **Strongly recommend snapshotting BEFORE `aca sandbox delete`** to preserve state. Always use `--name `, **never `--image`** (that is the wrong flag and will be rejected). Disk-only baking is `aca sandbox commit --id "$SANDBOX_ID" --name `. | @@ -136,17 +136,17 @@ options. | # | Capability | What it does | `aca` CLI | |----|---------------------------|------------------------------------------------------------------------------|-----------| | 00 | **Sandbox groups** | Provision, list/get, assign Data Owner role, tear down. | `aca sandboxgroup create / list / get / role create / delete` | -| 01 | **Sandboxes** | Create, list, get, delete; cpu/memory/labels/env; parallel. | `aca sandbox create / list / get / delete` (+ `--cpu --memory --labels --env`) | +| 01 | **Sandboxes** | Create, list, get, delete; cpu/memory/labels/env; parallel. | `aca sandbox create / list / get / delete` (+ `--cpu --memory --label --env`) | | 02 | **Snapshots** | Freeze a running sandbox; boot new ones from that point. | `aca sandbox snapshot --id --name X` · `aca sandbox create --snapshot X` | | 03 | **Disks** | Public disks, build from container image, commit a running sandbox. | `aca sandboxgroup disk list-public / create --image` · `aca sandbox commit --id --name X` · `aca sandbox create --disk ` (or `--disk-id ` for private/committed disks) | | 04 | **Volumes** | `AzureBlob` (shared) or `DataDisk` (block); mount at create or post-create. | `aca sandboxgroup volume create --type AzureBlob` · `aca sandbox mount --volume X --path /mnt/x` | | 05 | **Lifecycle** | Stop/resume; auto-suspend after idle; auto-delete after TTL. | `aca sandbox stop / resume` · `aca sandbox lifecycle set --auto-suspend 60` | | 06 | **Ports** | Expose an HTTP port; anonymous or Entra-gated (`--auth entra --allow-principal`); revoke. | `aca sandbox port add --port 8080 [--anonymous \| --auth entra --allow-principal ]` · `port list / remove` | | 07 | **Files** | write / read / list / stat / mkdir / delete inside the sandbox. | `aca sandbox fs write --file ./local` · `fs cat / ls` · `fs cp ` (positional, `sbx-id:/path` syntax) | -| 08 | **Egress** | Deny-default outbound + host allow-list; audit decisions; YAML transforms. | `aca sandbox egress set --default Deny --host-allow "*.host.com"` · `egress show / decisions / apply` | -| 09 | **Secrets** | Group-scoped key/value, fetched at runtime from inside the sandbox. | `aca sandboxgroup secret upsert --name X --values "K=V"` · `secret list / delete` | +| 08 | **Egress** | Deny-default outbound + host allow-list; audit decisions; YAML transforms. | `aca sandbox egress set --default Deny --rule "*.host.com:Allow"` · `egress show / decisions / apply` | +| 09 | **Secrets** | Group-scoped key/value, fetched at runtime from inside the sandbox. | `aca sandboxgroup secret set --name X --key K --value V` · `secret list / show / remove / delete` | | 10 | **Managed identity** | System- or User-assigned MI on the group; grant RBAC for cross-group orchestration. | `aca sandboxgroup identity assign --system-assigned` (or `--user-assigned `) · `identity show / remove` | -| 11 | **Labels & selectors** | `--labels k=v` at create time; AND-filter on list. Fleet management pattern. | `aca sandbox create --labels role=worker,tenant=t42` · `aca sandbox list -l role=worker` | +| 11 | **Labels & selectors** | `--label k=v` at create time (repeatable); AND-filter on list. Fleet management pattern. | `aca sandbox create --label role=worker --label tenant=t42` · `aca sandbox list -l role=worker` | | 12 | **Interactive shell** | Real PTY into a running sandbox. | `aca sandbox shell --id ` | | 13 | **YAML spec / `apply`** | Declarative infra-as-code: `init`, `validate`, `apply`, `schema`. | `aca sandbox init > sandbox.yaml` · `validate` · `apply --file sandbox.yaml` | | 14 | **`aca doctor`** | Diagnose subscription / RG / group / region / role. | `aca doctor` | diff --git a/plugin/skills/aca-sandboxes/references/scenarios.md b/plugin/skills/aca-sandboxes/references/scenarios.md index fcdd8d6..9e5b750 100644 --- a/plugin/skills/aca-sandboxes/references/scenarios.md +++ b/plugin/skills/aca-sandboxes/references/scenarios.md @@ -44,8 +44,8 @@ can only reach the endpoints you allow. SBX=$(aca sandbox create --disk ubuntu --label task=copilot-run -o json | jq -r .id) aca sandbox egress set --id $SBX \ --default Deny \ - --host-allow "api.githubcopilot.com" \ - --host-allow "*.githubusercontent.com" + --rule "api.githubcopilot.com:Allow" \ + --rule "*.githubusercontent.com:Allow" aca sandbox exec --id $SBX -c "curl -fsSL https://github.com/cli/cli/releases/.../gh.tar.gz | tar -xz && ./gh ..." ```