AsterionDocumentation v0.4.1

Protocol and security

How Polaris and Pulsar authenticate every message, and what each side refuses.

All calls go to {POLARIS_URL}/api/pulsar/v1/… over HTTPS only. Plain HTTP needs POLARIS_PULSAR_ALLOW_HTTP=true on Polaris and PULSAR_ALLOW_INSECURE=true on the satellite — lab use only.

Signatures

Both directions are signed with the satellite’s 64-character secret:

Request   X-Pulsar-Id, X-Pulsar-Instance, X-Pulsar-Timestamp (±300 s), X-Pulsar-Nonce (single use)
          X-Pulsar-Signature  = hex(HMAC-SHA256(secret, ts \n nonce \n METHOD \n /api/path \n sha256(body)))
Response  X-Polaris-Timestamp
          X-Polaris-Signature = hex(HMAC-SHA256(secret, "polaris" \n ts \n request-nonce \n status \n sha256(body)))
Websocket {"body": "<json>", "ts", "id",
           "sig": hex(HMAC-SHA256(secret, "polaris-ws" \n event \n ts \n id \n body))}
  • Pulsar → Polaris: signed, timestamped, nonces are single use, the credentials are bound to the first instance that registered.
  • Polaris → Pulsar: the satellite acts only on responses and websocket commands whose signature matches, that are at most 5 minutes old and (websocket) whose id it has not seen before. A man in the middle can neither inject nor replay plans, jobs or console grants.
  • Shared test vectors in both test suites prove both sides compute identical signatures.

Endpoints

EndpointPurpose
POST registerfirst contact binds the instance; returns portal info, intervals, websocket settings, abuse contact
POST heartbeatround-trip times, connectivity, websocket state, queue size, load, active runs, geo
GET syncplans with schedules, options and resolved targets, plus a version hash
POST progresslive parts of a running plan or job
POST resultsbatch of finished runs; answers the accepted run ids
POST jobs/{uuid}/status, jobs/{uuid}/resultimmediate jobs
POST logs, POST tracelog shipping, traceroute to the portal
POST ws/authsignature for the private channel private-pulsar.{uuid}

Websocket events on private-pulsar.{uuid}: job.run, plans.updated, console.update.

What Polaris accepts

Every upload is rebuilt by a strict validator (app/Support/PulsarPayload.php):

  • only plans assigned to that satellite, only targets of that plan or job,
  • nmap hosts only inside the scanned address, network or DNS answers,
  • typed and bounded fields; unknown keys are dropped, control characters stripped,
  • domain checks only on domain targets, host checks never on them.

Rejected results are written to the satellite log.

Defence in depth on the satellite

Targets and options are validated again before they reach nmap, traceroute or ping (pulsar/validate.py): only addresses, networks, ranges and hostnames in strict formats, ports and numbers in their ranges. No value can become a command-line option.