What the caller would be approving
const url = 'https://example.com/api/certs/requests/example';const options = {method: 'GET', headers: {'X-Ssoossh-Key-Secret': '<X-Ssoossh-Key-Secret>'}};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request GET \ --url https://example.com/api/certs/requests/example \ --header 'X-Ssoossh-Key-Secret: <X-Ssoossh-Key-Secret>'The approval page’s data source.
Returns requested and granted separately on purpose: server config is
the outer bound on every option and trims rather than rejects, so a human
has to be able to see what is being dropped before they approve.
This binds the request to the caller. It is the first authenticated touch a request gets, so opening the page claims it; a different user gets 403 here rather than after clicking approve.
Authorizations
Section titled “Authorizations”Parameters
Section titled “Parameters”Path Parameters
Section titled “Path Parameters”The certificate request’s UUID
Responses
Section titled “Responses”Request detail
object
object
ClientPolicy is the administrative policy the requesting machine claimed was in force on it, so the page can say why an option is missing rather than only that it is. Absent when nothing was claimed.
A claim, like every other self-reported field on this response, and advisory by design: it narrows and explains what an approver is offered, and never decides whether a certificate is issued. A client that wants an option simply does not send this.
object
FIPS reports the machine is held to FIPS-approved algorithms. Omitted when policy was silent, which is not the same as false.
ForbiddenExtensions are the extensions the requesting machine’s policy forbids. The client already removed them from what it asked for; this says which rule accounts for the gap.
Options are the certificate options fixed at approval, already narrowed by server config: what a redemption actually grants, not what the client asked for.
object
What the approval granted and why: the principals selected, the options after every narrowing, and the lifetime policy’s own explanation as a JSON document (see service.PolicyExplanation). Approvals only; absent for denials and for decisions predating the columns.
ExpiresAt is when the request stops being approvable, from its own type’s budget. The page counts down to it, which matters most for console requests: their budget is deliberately the shortest, and an approver who cannot see the clock cannot tell a slow OIDC login from a request that has already died.
Options are the certificate options fixed at approval, already narrowed by server config: what a redemption actually grants, not what the client asked for.
object
The console context the request carried: which machine it claims to be, through which PAM service, at which terminal, and what it reported as the remote host.
Every one of them is self-reported by an unauthenticated caller and the UI must render them as claims rather than as facts — they are what lets a human notice “I am at my desk, why is there a console login on rack07”, not what authorizes anything. A non-empty RemoteHost on a console request is worth flagging outright: a real console has no remote host.
Set for PAM and console requests; empty for the others.
Options are the certificate options fixed at approval, already narrowed by server config: what a redemption actually grants, not what the client asked for.
object
The rest of the host context, same trust: who invoked the service (PAM_RUSER), the command line asking, the process identifiers, a stable machine id, the platform, the module and its configured mode, the host’s clock, and the CA fingerprints the host trusts. See apitypes.PAMRequestBody for each. Set for PAM and console requests; the numeric ones are absent rather than zero when the module did not report them.
SelectableExtensions is cert_options.
Distinct from Granted.Extensions, which is what this request would get if approved untouched: for a request that asked for nothing, that is empty while the ceiling may be large. The picker needs the ceiling to know which toggles exist and Granted to know which start on.
TargetAccount is the local account a PAM or console request is
authenticating: who sudo is being run as, or the account typed at
the login: prompt. Empty for every other type. It is
reported by an unauthenticated client and never becomes a principal
(see model.CertificateRequest.Username), so the UI must present it as
what is being attempted rather than as what is being granted. Without
it the approver cannot see which account the sudo is for, since the
principals now describe the approver instead.
Type is what was asked for. Empty when the request row behind the decision is gone: the decisions table is the permanent one by design, so the client must render a row whose type it does not know.
ViewerIP is the address this server sees the approving browser connect from, resolved the same way as SourceIP, so the approval page can set the two side by side. Display only and never a reason to refuse: plenty of people approve from one machine a request their terminal made on another. A difference is something the approver can check, where everything the requester reports about itself is not.
Example
{ "data": { "status": "pending", "type": "user" }}No valid session
object
Data is always null on an error response.
Error is a human-readable message. Branch on the HTTP status rather than this string; it is for humans and logs.
ErrorCode is a machine-readable error classifier. One of the error_code constants from internal/apitypes; use this to decide whether to retry or branch on the failure mode.
Example
{ "error": "certificate request \"9f1c…\" not found", "error_code": "not_found"}Already bound to another user
object
Data is always null on an error response.
Error is a human-readable message. Branch on the HTTP status rather than this string; it is for humans and logs.
ErrorCode is a machine-readable error classifier. One of the error_code constants from internal/apitypes; use this to decide whether to retry or branch on the failure mode.
Example
{ "error": "certificate request \"9f1c…\" not found", "error_code": "not_found"}No such request
object
Data is always null on an error response.
Error is a human-readable message. Branch on the HTTP status rather than this string; it is for humans and logs.
ErrorCode is a machine-readable error classifier. One of the error_code constants from internal/apitypes; use this to decide whether to retry or branch on the failure mode.
Example
{ "error": "certificate request \"9f1c…\" not found", "error_code": "not_found"}