aim-web2.1.0rc9
This commit is contained in:
@@ -0,0 +1,153 @@
|
||||
# AIM public service API
|
||||
|
||||
**Core 3.3.0rc8; API/wire/event 1.0, stable additive 1.x; Ansible Core 2.19.11.**
|
||||
Supported Python imports: `aim.services.v1` only. `aimctl` is a separate-process JSONL
|
||||
interface in the AIM Python environment. No HTTP service, privilege broker or add-on
|
||||
runtime is introduced. Core keeps its built-in terminal independently usable.
|
||||
|
||||
## Authorization and discovery
|
||||
|
||||
Protected calls check active primary/supplementary membership in configured
|
||||
`required_group` plus normal local access. capabilities is unguarded non-sensitive
|
||||
metadata. Caller-provided actor/user fields cannot authorize a request and are not
|
||||
accepted. `--config` is a trusted operator path, never user input to a privileged wrapper.
|
||||
|
||||
| Operation | Python | Wire fields in addition to api_version/operation |
|
||||
|---|---|---|
|
||||
| capabilities | capabilities() | none |
|
||||
| list_customers | list_customers() | none |
|
||||
| list_hosts | list_hosts(customer) | customer |
|
||||
| inventory_hierarchy | inventory_hierarchy(customer) | customer |
|
||||
| list_playbooks | list_playbooks(customer) | customer |
|
||||
| prepare | prepare(request) | request |
|
||||
| readiness | readiness(request) | request |
|
||||
| staging_check | staging_check() | none |
|
||||
| execute | execute(request, expected_revision=..., credentials=..., event_sink=..., cancel=...) | request, expected_revision; secrets on separate FD |
|
||||
|
||||
Catalog metadata includes typed inputs and `result` (null or a resolved declaration
|
||||
including data_schema). prepare returns normalized request, revision, credential
|
||||
requirements/reasons, warnings, revision coverage and result_contract. Discovery and
|
||||
prepare do not contact hosts or acquire secrets. readiness performs bounded local runtime
|
||||
and staging checks; it does not prove remote authentication. staging_check is a bounded
|
||||
local filesystem probe that may create missing private staging directories and deletes
|
||||
its own test file, not operator contents. It invokes no Ansible or remote commands.
|
||||
|
||||
## RunRequest
|
||||
|
||||
```json
|
||||
{"customer":"CUSTOMER","playbook":"debug_detect_host_roles","hosts":["HOST"],"overrides":{},"check":false,"key_mode":"none","become_password":false,"timeout_seconds":3600,"progress_mode":"summary"}
|
||||
```
|
||||
|
||||
customer, playbook and hosts are required. Host count 1-1000; explicit unique inventory
|
||||
names only, never arbitrary group/limit patterns. Core revalidates membership/platforms
|
||||
and declared typed options. Omit options to inherit; 64 KiB maximum JSON overrides.
|
||||
Secret-reference inputs are variable references, not passwords. Customer/host/catalog
|
||||
code is trusted executable controller input, not an untrusted-tenant sandbox.
|
||||
|
||||
key_mode none preserves native inventory handling without importing the caller's agent.
|
||||
customer loads only the canonical customer key into an owned agent: Linux target scope,
|
||||
0600 key owned by execution UID, ssh-agent/ssh-add required. It never exports the key.
|
||||
become_password true permits a default escalation password for a compatible catalog
|
||||
scope; it does not independently turn on escalation. check uses native check mode, not
|
||||
a guarantee of no effects for every plugin. timeout_seconds 10-86400 bounds the launched
|
||||
playbook; preflight stages have their own deadlines. progress_mode summary/detail is
|
||||
negotiated and part of the revision. Operation reports need no new request field.
|
||||
|
||||
## Lifecycle and revisions
|
||||
|
||||
Show prepared scope/options/key mode, result_contract and warnings before approval.
|
||||
Check readiness in the real worker sandbox, obtain a slot, then fresh credentials.
|
||||
execute re-prepares and checks revision before consuming secrets and before launch.
|
||||
Known source/config/key bytes and metadata are hashed with limits, not a complete atomic
|
||||
snapshot of dynamic includes, collections, external assets or arbitrary lookups. Stable
|
||||
customer locks cover cooperating writers, not direct shell edits. Quiesce source updates.
|
||||
|
||||
`customer_vault_present` is conservative: a Vault can be needed by inventory credentials
|
||||
even when catalog require_vault is false. Other reason codes include catalog_requires_vault,
|
||||
catalog_requests_connection_password, request_requires_become_password and
|
||||
encrypted_customer_key_selected. This is not exhaustive templated variable analysis.
|
||||
|
||||
## Private credentials
|
||||
|
||||
Accepted keys only: vault_password, connection_password, become_password,
|
||||
ssh_key_passphrase. Literal single-line UTF-8 <=8192 bytes per value; no CR/LF/NUL;
|
||||
nonempty Vault/connection/become passwords. No trimming, hashing or recursive templating.
|
||||
Unencrypted keys need no passphrase. If selected encrypted key has no supplied phrase,
|
||||
Core can read the literal vault_linux_ssh_key_passphrase after Vault unlock.
|
||||
|
||||
Python: use OneRunCredentials(values, ttl_seconds=120) and close in finally; TTL 1-300
|
||||
seconds before consume. Custom providers implement bounded single-run consume(run_id).
|
||||
Never prompt unattended or reuse a provider across jobs. Native executable password
|
||||
sources use private same-UID sockets; helper files hold no secret material. No password
|
||||
in argv/environment/request JSON/events. Native processes necessarily hold it in memory;
|
||||
cleanup is not a memory-erasure guarantee. Supplied passwords are native defaults, not
|
||||
forced Custom overrides or proof of password-only authentication.
|
||||
|
||||
Machine: one newline-terminated JSON object on stdin <=128 KiB within ten seconds.
|
||||
Use `aimctl request --credentials-fd N` for execute, inheriting a private pipe/socket FD
|
||||
>=3 with one EOF-terminated JSON object <=64 KiB. Close writer after sending. Ordinary
|
||||
files/terminal/stdin/out/err FDs are rejected. Read deadline is five seconds when consumed.
|
||||
Send request/secrets concurrently with event consumption; avoid filling a pipe before
|
||||
starting the receiver. Pass FD using subprocess pass_fds, never shell text with passwords.
|
||||
Cross-UID launcher transport is outside the Core-supported profile.
|
||||
|
||||
```bash
|
||||
aimctl capabilities
|
||||
printf '%s\n' '{"api_version":"1.0","operation":"list_customers"}' | aimctl request
|
||||
printf '%s\n' '{"api_version":"1.0","operation":"prepare","request":{"customer":"CUSTOMER","playbook":"debug_detect_host_roles","hosts":["HOST"]}}' | aimctl request
|
||||
```
|
||||
|
||||
## Events and final results
|
||||
|
||||
Each event has event_version, run_id, increasing sequence, UTC timestamp and kind.
|
||||
Summary kinds stage/progress/stats/result stay. Detail adds negotiated play/task/host
|
||||
metadata; see DETAILED_PROGRESS.md. Wire events are `{"type":"event","event":{...}}`.
|
||||
Final response is `{"type":"response","api_version":"1.0","ok":true,"result":{...}}`
|
||||
or ok:false with result/error. A final result event and final response are one job,
|
||||
not two. Missing final response is unknown outcome, not success. Stdout is JSONL only.
|
||||
|
||||
RunResult fields: api_version, run_id, status (succeeded/failed/cancelled), stage,
|
||||
nullable exit_code, remote_work_may_have_started, nullable error, aggregate task counts,
|
||||
target_summary, targets, and operation_result (null when not declared). Target accounting
|
||||
is in TARGET_OUTCOMES.md. Purposeful report availability, schemas, limits and errors are
|
||||
in OPERATION_RESULTS.md. Native failures are preserved. A required report validation
|
||||
failure after native exit 0 yields status failed/stage result_validation/exit_code 0;
|
||||
native target stats remain unchanged. Never infer application data from ok/skipped counts.
|
||||
|
||||
Error fields: code, fixed message, stage, retryable, required_credentials. Handle unknown
|
||||
codes safely, not by parsing message text. Pre-run ServiceError can occur without a
|
||||
RunResult. No fake report or target success is synthesized for a rejected request.
|
||||
|
||||
| Error family | Action |
|
||||
|---|---|
|
||||
| access_denied / execution_disabled | Correct operator authorization/enablement, not bypass |
|
||||
| invalid_request / invalid_target / invalid_options / unknown_playbook | Correct request, re-prepare |
|
||||
| source_invalid / playbook_unavailable / source_symlink_unsupported | Repair trusted source |
|
||||
| resource_busy / review_stale | Wait or re-review; retain no stale secrets |
|
||||
| runtime_missing / runtime_version_unsupported / collections_missing | Repair approved native runtime |
|
||||
| controller_staging_* | Repair scoped worker staging inside sandbox; no password loop |
|
||||
| runtime_credential_defaults_unsupported | Resolve unsupported global Vault sources explicitly |
|
||||
| credential_required / credentials_expired / invalid_credential_channel | Fresh bounded provider/channel |
|
||||
| vault_unlock_failed / key_load_failed | Correct secret/access/format before launch |
|
||||
| syntax_check_failed | Authorized native diagnostics, no raw fallback |
|
||||
| host_unreachable / playbook_failed | Inspect outcomes; no automatic replay |
|
||||
| operation_result_* | Inspect report availability; remote work may be finished; never replay automatically |
|
||||
| invalid_event_stream / event_bridge_* / event_limit | Incomplete stream is not success |
|
||||
| timeout / cancelled / event_sink_failed / internal_error | Explicit recovery decision, preserve remote-work flag |
|
||||
|
||||
Cancel with threading.Event in Python or SIGINT/SIGTERM to aimctl. Core stops owned
|
||||
process groups/agents, not completed remote changes or asynchronous external work.
|
||||
Use a bounded nonblocking event sink; slow browsers must not stall execution.
|
||||
|
||||
## Runtime and detailed contracts
|
||||
|
||||
The configured ansible-playbook plus sibling Vault/Galaxy must report canonical 2.19.11
|
||||
and consistent native Python/module identity. Collections, roles, local staging, remote
|
||||
Python/PowerShell, HOME/known-hosts and service restrictions need actual acceptance.
|
||||
The service selects root_dir/ansible.cfg or its fallback; it does not inherit arbitrary
|
||||
shell environment/credential/debug settings. Supported collection search path is explicit.
|
||||
No auto-install, recursive ownership repair, remote_tmp override or service-unit edit.
|
||||
|
||||
See EXECUTOR_STAGING.md (both applicable homes), INVENTORY_HIERARCHY.md, TARGET_OUTCOMES.md,
|
||||
DETAILED_PROGRESS.md and OPERATION_RESULTS.md. ADDON_SUPPORT.md lists deliberate exclusions.
|
||||
VALIDATION.md records present evidence; SANITY.md is the only current acceptance checklist.
|
||||
Reference in New Issue
Block a user