Guides / kosa8 Cloud / Security Center
Security Center
The Security Center is one page in the kosa8 Cloud dashboard (Access → Security Center
at app.kosa8.com), the same thing in the CLI (kosa8 cloud security, agents,
freeze, siem, evidence) and a Cloud Security panel in the
desktop app's Account view. It reads your organization's own settings, API keys and
audit log. It does not certify anything: the checklist is a self-check
for you to act on, and the evidence file is your own record for your own review or your auditor's.
Posture checklist
Each check passes, fails, or does not apply, and names the dashboard page that changes it. The score is
the number that pass out of the number that apply, for example 7 / 12. There is no letter grade.
| Check | Passes when |
|---|---|
| Single sign-on is connected | An OIDC connection is set up (Team & SSO). |
| Dashboard sign-in requires SSO | “Require SSO for the dashboard” is on. |
| An email domain is verified | At least one SSO domain is verified by its DNS TXT record. |
| A named person is an owner | At least one member has the owner role, so the org is not run only from a shared admin key. |
| Few people hold owner or admin | Owners plus admins are at most half the members, or at most two. Does not apply with no members. |
| At most 2 live admin keys | No more than two unrevoked, unexpired API keys have the admin scope. |
| No key older than 90 days | Every live key was made (or rotated) in the last 90 days. |
| No key unused for 30 days | Every live key was used, or made, in the last 30 days. |
| Non-admin keys have an end date | Every live key without admin has an expiry. |
| A monthly spending cap is set | Settings has a spending cap. |
| The audit log's hash chain verifies | GET /v1/audit/verify finds no edited, removed or reordered event. |
| The audit log left kosa8 in the last 30 days | An NDJSON export or an evidence export in the last 30 days, or a working SIEM destination. |
| The audit log streams to a SIEM | At least one SIEM destination whose last delivery succeeded. |
Not checked, and said so on the page: kosa8 Cloud has no built-in multi-factor sign-in (require SSO and use your identity provider's MFA), and no org-wide egress policy setting yet.
curl -s https://api.kosa8.com/v1/security/posture -H "Authorization: Bearer $KOSA8_API_KEY"
# {"score":{"passed":7,"total":12},"frozen":false,"items":[{"id":"sso_connected","area":"Identity",
# "title":"Single sign-on is connected","ok":false,"detail":"…","fix":{"tab":"team","label":"Set up SSO"}},…]}
Reading it needs the owner or admin role, or a key with audit:read.
Agent inventory
Every API key (an agent's, a CI job's or a person's) and every member, with its scopes or role, its
state (active, suspended, expired, revoked), when it was last
used, and the sandboxes and functions it made. Who made what comes from the audit log's successful
sandbox.create, sandbox.fork and function.deploy events; anything made before
the audit log, or by a key revoked more than 30 days ago, is listed as unattributed. Revoke ends a key at once
through the usual DELETE /v1/api-keys/{id}.
$ kosa8 cloud agents $ kosa8 cloud agents --revoke key_…
Kill switch: freeze the organization
An owner or admin can freeze the organization, for example when a key may have leaked or an agent is
doing something it should not. You type the organization's name to confirm (the CLI asks for it unless you
pass --yes). A freeze:
- refuses new sandboxes, commands, wakes, forks, file writes, function calls and deploys, new keys and
key rotation, with
423and{"error":"org_frozen"}, scheduled and web-endpoint function calls included; - puts every running sandbox to sleep through the normal sleep path (state kept, nothing deleted). A host that does not answer is retried by the minute tick until it does;
- with
suspend_keys, suspends every live API key except the one making the call. A suspended key answers401 key_suspended. Members' dashboard sessions keep working, so someone can always unfreeze.
While frozen, reads and incident response still work: revoking keys, adding, demoting or removing members, changing SSO and settings, deleting or sleeping sandboxes, deleting functions and webhooks, and the Security Center itself. Function invocations already running when the freeze lands are not cut short.
Unfreezing restores the keys the freeze suspended, unless you ask it not to. Sandboxes stay asleep until
woken; their next command wakes them. Both actions are in the audit log as security.freeze and
security.unfreeze, with the reason, how many keys were suspended or restored and how many
sandboxes were put to sleep; every refused call is recorded too.
curl -s -X POST https://api.kosa8.com/v1/security/freeze -H "Authorization: Bearer $KOSA8_API_KEY" \
-H 'Content-Type: application/json' -d '{"confirm":"Acme Inc","reason":"key in a public repo","suspend_keys":true}'
curl -s -X POST https://api.kosa8.com/v1/security/unfreeze -H "Authorization: Bearer $KOSA8_API_KEY" \
-H 'Content-Type: application/json' -d '{"confirm":"Acme Inc"}' # "restore_keys":false keeps them suspended
$ kosa8 cloud freeze --reason "key in a public repo" --suspend-keys $ kosa8 cloud unfreeze
SIEM streaming
Every audit event, in order, to up to five destinations per organization. The minute tick sends the
events after each destination's cursor, up to 100 per request and 500 per minute, and moves the cursor only when
the destination answers 2xx. A failure is retried after 1, 5 and 15 minutes, then hourly, and the
stream resumes where it stopped: no event is skipped. Redirects are not followed, and URLs must be public
https. Owners and admins manage destinations.
| Kind | Request |
|---|---|
webhook | POST of {"org_id","destination_id","events":[…]} with
Kosa8-Signature: t=<unix s>,v1=<hex HMAC-SHA256(secret, "<t>.<body>")>, as the
event webhooks sign. The whsec_… secret is shown once. |
splunk_hec | Your HEC URL with Authorization: Splunk <token>; one
{"time","host","source","sourcetype","index"?,"event"} object per line. sourcetype defaults
to ocsf:api_activity. |
datadog | https://http-intake.logs.<site>/api/v2/logs with
DD-API-KEY; a JSON array of {"ddsource":"kosa8","service":"kosa8-cloud","message","ocsf"}.
Sites: datadoghq.com, us3, us5, datadoghq.eu, ap1, ap2, ddog-gov.com. |
Tokens and API keys are stored encrypted and never returned by the API. Each event is OCSF API Activity
(class_uid 6003, category_uid 6): activity_id from the action's verb (1 create,
2 read, 3 update, 4 delete, 99 other), status_id 2 with status_code for a refused call,
time, actor.user (a member, an API key or the system), api.operation (the
audit action, e.g. sandbox.exec), resources, and metadata.uid
org:seq. kosa8 Cloud does not record client IP addresses, so src_endpoint carries only the
channel (key, session, sso, system). The original event, its
detail and its chain hashes are in unmapped.
curl -s -X POST https://api.kosa8.com/v1/security/siem -H "Authorization: Bearer $KOSA8_API_KEY" \
-H 'Content-Type: application/json' \
-d '{"kind":"splunk_hec","url":"https://splunk.example.com:8088/services/collector/event","token":"…","index":"security"}'
# start: "beginning" (default, sends the whole log first) or "now"
curl -s -X POST https://api.kosa8.com/v1/security/siem/siem_…/test -H "Authorization: Bearer $KOSA8_API_KEY"
$ KOSA8_SIEM_TOKEN=… kosa8 cloud siem add --kind datadog --site datadoghq.eu $ kosa8 cloud siem ls $ kosa8 cloud siem test siem_…
Evidence export
Download evidence (or kosa8 cloud evidence export, or
GET /v1/security/evidence?since=&until=) saves one JSON file: the posture checklist, the audit
chain's verification, and the audit events in the range (default the last 90 days, at most 20,000 events,
with truncated set past that).
{"content":{"format":"kosa8.evidence.v1","statement":"…","org":{…},"range":{…},"posture":{…},
"audit":{"chain":{"ok":true,…},"count":412,"truncated":false,"events":[…]}},"sha256":"9f2c…"}
sha256 is the SHA-256 of content as served: canonical JSON, object keys sorted and no
spaces, the same form the audit chain hashes. The CLI checks it before saving. To check it yourself:
python3 -c 'import json,hashlib,sys; f=json.load(open(sys.argv[1]));
c=json.dumps(f["content"],sort_keys=True,separators=(",",":"),ensure_ascii=False);
print(hashlib.sha256(c.encode()).hexdigest()==f["sha256"])' kosa8-evidence-….json
Each export is recorded in the audit log as security.evidence_export, with its hash. The file is
generated by kosa8 Cloud from your organization's own data; it is not a certification, an attestation or an
audit opinion.
API
| Route | Scope |
|---|---|
GET /v1/security/posture | audit:read |
GET /v1/security/inventory | audit:read |
GET /v1/security/evidence | audit:read |
GET /v1/security/freeze | any key of the org |
POST /v1/security/freeze, /unfreeze | admin (owners and admins) |
GET, POST /v1/security/siem, DELETE /v1/security/siem/{id}, POST …/{id}/test | admin |