docs/documentation/platform/pki/code-signing/approvals.mdx
A Signer with an approval policy makes signing a two-party operation: someone asks, someone else says yes, and the request becomes an active access window with limits on how much and how long. This page covers everything that happens inside a Signer's Approvals tab.
Concretely, approvals govern three things:
flowchart LR
A[Operator clicks
Request to sign] --> B[Step 1 approvers notified]
B -->|Required approvals reached| C[Step 2 approvers notified]
C -->|Required approvals reached| D[Access issued]
D --> E[Operator signs]
B -.->|Step 1 rejected| X[Rejected]
C -.->|Step 2 rejected| X
Each step runs in order. Once the last step's required approvals are reached, Infisical issues an active access record bounded by the policy's per-approval limits. The Operator can then sign through the PKCS#11 module or the Sign API.
Administrators can also pre-approve signing directly when the approval flow isn't a fit, for example during an incident response where waiting on approvers would block recovery.
Open the Signer's Approvals tab and click the pencil icon on the Approval Policy panel. The editor is a 2-step sheet.
<Steps> <Step title="Approvers"> Define one or more approval steps. To turn the policy off entirely, delete every step. The Signer reverts to direct signing.For each step:
| Field | Description |
|-------|-------------|
| **Step name** | Optional label like *Security Team Review* or *Manager Sign-off*. Visible to approvers in their queue. |
| **Approvers** | Eligible users **or groups** for this step. They must already be members of the Signer (any role). Group approvers let anyone in the group approve. Auditors can be members but cannot be approvers. |
| **Required approvals** | The number of **distinct** approvers that must approve before the step is complete. |
Add more steps to run multiple sign-offs in sequence. For example: *Step 1 Team Lead Review* (1 approval), then *Step 2 Security* (2 approvals).
**Required-approval validation:**
- A step must have at least one approver.
- **Required approvals** must be ≥ 1.
| Field | Description |
|-------|-------------|
| **Signatures per approval** | How many signing operations one approval is good for. Leave empty for unlimited. Set to **1** for "approve once per artifact". |
| **Signing window** | The longest an access record can stay valid, counted from approval. Options: No limit, 1h, 8h, 24h, 7d, 30d. |
You can combine both. For example: `maxSignings=10` with `signing window=1h` issues access good for at most 10 sign calls within one hour of approval, whichever comes first.
[Scoping](#scoping-an-approval) is not configured here. Whoever opens a request or pre-approval chooses, per request, which signing parameters to lock it to.
Press Save policy. The new policy applies to new requests; existing active access keeps its original terms until it expires or is revoked.
By default an approval means "this member may sign N times before it expires". Expanding Scope this request on a request or pre-approval lets you narrow that to a specific signing situation. Every parameter is optional, and the ones you fill in are the only ones that get restricted.
| Parameter | What it locks the approval to |
|---|---|
| Command | The exact signing command that must be issued, compared character for character apart from whitespace. |
| Signing Application | The signing tool's executable filename, exactly as it appears on the machine. Signing clients report os.Executable, so this is signtool.exe on Windows and pkcs11-tool on Linux, extension included. |
| Signing Application Checksum | The SHA-256 checksum of the signing tool binary, so a modified or different tool no longer matches. |
| Hostname | The machine the sign calls come from. |
| OS Username | The operating system account running the signing tool. |
| IP Address | The address sign calls have to arrive from, for example a build agent's egress address. Infisical reads the address off the sign call itself, the same way audit logs record it, so the caller cannot present a different one. |
| Data Hash | The SHA-256 digest of the payload submitted for signing, which pins the approval to one artifact. Signing tools submit a digest of the file rather than the file itself, so this is not the same value as sha256sum yourfile. The PKCS#11 module and the Windows KSP fill it in for you. |
Pinning an approval to a Data Hash is the tightest option: the approver signs off on one file rather than on a window of time, and no other payload can be signed under it.
The PKCS#11 module and the Windows KSP fill this in for you. When signing is denied, the request they open is already scoped to the artifact of the denied attempt, along with the command and machine it came from, so you approve it in Infisical and re-run the same command.
<Tip> For release pipelines, pair a data hash scope with a signature count of **1**. The approval then covers exactly one signature over exactly one file. </Tip> <Note> Filling in a digest by hand is fiddly, because a sign call carries a digest rather than the file, so the value to declare is the hash of the bytes the call submits and not `sha256sum yourfile`. If you are calling the API directly, see the [Sign API reference](/api-reference/endpoints/code-signing/signers/sign). </Note>A request's scope is fixed once it is open. Nobody edits it during review, including the approvers: an approval means the parameters shown on the request, so if they are wrong the request is rejected and a new one is opened with the parameters you want.
For a pipeline that signs a different artifact on every run, do not fight this per request. Tell the signing client which parameters to leave out in the first place, with approval.exclude_scope_fields in the PKCS#11 module or the Windows KSP. Excluding data_hash is the common case: a timestamped signature changes the digest between runs even for the same file, so pinning it would mean a fresh approval for every build. Exclude one parameter at a time. Each one you drop widens what the approval covers, and because an approval belongs to the identity rather than to a machine, dropping all of them grants that identity any signature it asks for until the window or count runs out.
Every approved request becomes an active access record. On the Approvals tab it's a row in the Requests table with its own status, expiry, and signature counter.
| Status | Meaning |
|---|---|
| Pending | Approval workflow is in progress. Waiting on the current step's approvers. |
| Active | All steps approved, access issued, still within window and signatures remaining. |
| Expired | Window has passed, or the signature count was exhausted. |
| Revoked | An Administrator revoked the access (or the requester cancelled the request). |
| Rejected | An approver rejected one of the steps. |
There are two ways someone gets active access on a Signer: Administrators pre-approve signing directly for someone else, or members open a request to sign that runs through the approval policy.
<Tabs> <Tab title="Pre-approve signing"> An Administrator gives a specific member access up-front. **No approval workflow runs.** The access is created **Active** immediately and the recipient can sign right away.<Steps>
<Step title="Click Pre-approve signing">
From the Signer's **Approvals** tab, click **Pre-approve signing**.
</Step>
<Step title="Pick the recipient">
Select the user or machine identity that should receive access. The list includes every Signer member except Auditors (including users reachable via a group).
</Step>
<Step title="Set the access terms">
| Field | Description |
|-------|-------------|
| **Justification** | Short note recorded on the access record for audit. Required. |
| **Signatures allowed** | How many sign operations the access permits. Capped at the policy's **Signatures per approval**. Leave empty to fall back to the policy ceiling. |
| **How long the approval lasts** | How long the access stays usable, counted from the moment the access is granted. Capped at the policy's **Signing window**. |
| **Scope this request** | Optional. Expand it to [scope](#scoping-an-approval) the access to a specific command, signing tool, checksum, machine, OS account, IP address, or data hash. Useful for pre-approving a known build agent: set its address and the access only works from there. |
<Note>
Per-access values cannot exceed the policy ceilings. Requesting `maxSignings=10` against a policy that allows 3 returns a 400 with a clear message. Omitting a field that the policy caps simply clamps to the ceiling, never silently unlimited.
</Note>
</Step>
<Step title="Issue the access">
Press **Pre-approve**. The recipient can sign immediately.
</Step>
</Steps>
Typical use: pre-approving a CI machine identity for "10 signings within the next hour" right before a release pipeline runs.
<Steps>
<Step title="Click Request to sign">
From the Signer's **Approvals** tab, click **Request to sign**. (Hidden if the Signer has no policy, if you don't have sign permission, or if you already have active access.)
</Step>
<Step title="Justify the request">
Provide a short reason: *"Signing release v2.4.0"*, *"Hotfix for #4823"*. The justification appears to approvers and is recorded on the eventual access record.
</Step>
<Step title="Specify what you need">
| Field | Description |
|-------|-------------|
| **Signatures requested** | How many sign operations you need. Capped at the policy's **Signatures per approval**. Leave empty to fall back to the policy ceiling. |
| **How long the approval lasts** | How long you need the access for, counted from the moment approvals complete. Capped at the policy's **Signing window**. Waiting for an approver does not eat into it. |
| **Scope this request** | Optional. Expand it to [scope](#scoping-an-approval) your access to the command, signing tool, checksum, machine, OS account, IP address, or data hash you will sign with. Approvers see whatever you declare, and the access only covers matching sign calls. |
<Note>
Submitting a request with the same scope as one you already have pending returns the pending request instead of opening a duplicate. Signing clients that auto-request access can safely retry without flooding approvers.
</Note>
<Note>
Per-access values cannot exceed the policy ceilings. Requesting `maxSignings=10` against a policy that allows 3 returns a 400 with a clear message. Omitting a field that the policy caps simply clamps to the ceiling, never silently unlimited.
</Note>
</Step>
<Step title="Submit">
Press **Submit**. The first step's approvers are notified in-app and by email. Each step advances when its required approvals are reached. When the last step completes, the access record is automatically created with the terms you requested (clamped to policy caps).
</Step>
</Steps>
Typical use: a developer requesting access to sign a release, with the release manager (or a group) approving before the access goes Active.
If you're an eligible approver for the current step of a pending request, an Approve or Reject action is visible on the request row.
<Steps> <Step title="Open the request"> Click the row on the Signer's **Approvals** tab. Full details: requester, recipient, justification, requested signings, requested duration, and which step is currently pending. </Step> <Step title="Review"> Verify who's asking, for how many signings, for how long, and why. If the requester scoped the request, the detail page lists every parameter the access will be limited to, so you can see exactly which signing situation you are approving. </Step> <Step title="Decide"> - **Approve** counts toward the current step's required approvals. When the last step's count is reached, the access record is created. - **Reject** terminates the workflow. No access is created. The requester can submit a new request. </Step> </Steps> <Note> You can never approve your own signing request, even if you are listed as an approver for the current step. This is always enforced and cannot be disabled. (Pre-approving signing for yourself is allowed. It is an administrator action, not an approval of your own request.) </Note>Administrators can revoke an active access record (or cancel a pending request) at any time. Hover the row on the Approvals tab; an X icon appears. Confirm in the dialog and:
In-flight sign calls already in progress complete normally; revocation is checked at request entry, not mid-operation. The row stays visible in Revoked status so the audit trail is preserved.