Audit logs
Overview
The Audit logs page gives you a centralized record of user and system activity across the platform. Use it to monitor activity, investigate issues, and support security and compliance. Audit logs show who did what, when, and how.
To open the page, go to SGOrchestrator > Organization settings > Audit logs.

Audit logs page
Retention time
StackGuardian keeps logs for 30 days only. It permanently deletes logs older than 30 days, and you can't recover them.
Access and permissions
- Admins have full access to Audit logs. They can view, filter, and export logs, and they can configure webhooks.
- Other users don't have access by default. If an admin grants access, they can view, filter, and export logs, but they can't create or configure webhooks.
Audit logs table
StackGuardian automatically records all user, admin, and system activity. Each log entry has these columns:
- Created by: Who performed the action (email).
- Timestamp: When the action occurred, in the format
YYYY-MM-DD hh:mm:ss UTC+01:00. - Event: The type of request, such as
POST,PATCH, orDELETE, or a platform event such asSG_SIGN_IN. - Action: What was done, such as Update a Resource or Login.
- Resource: The URL of the affected resource, or the event name for events without a resource.
- Outcome: Whether StackGuardian allowed or denied the action. The value is Allowed or Denied.
Use the search box to find a log by exact resource, for example /api/v1/orgs/name/wfgrps/name. Select Manage columns to choose which columns appear, and select the refresh icon to reload the table.
From the table, you can:
- Select a name in Created by to open the details of a log entry.
- Select a resource to open its endpoint in a new tab, when a link is available.
- Open the ⋮ menu on a row to export that entry as JSON or CSV.
- Select one or more rows to export them together.
Log entry details
The details dialog has three tabs:
- Meta: The context of the action.
- Created by: Who performed the action (email).
- Timestamp: When the action occurred, as relative time and as an exact date and time.
- Event: The type of request, such as
POST,PATCH, orDELETE. - IP address: The origin of the request.
- Action: What was done.
- Resource: The affected resource. Select the copy icon to copy its URL.
- Outcome: Allowed or Denied.
- Request payloads: The body of the request, as JSON.
- Response payloads: The body of the response, as JSON.
Select Copy on a payload tab to copy the JSON.

Audit logs details
Filters and search
Use the filter panel to narrow the table:
- Date and time range: Relative or absolute. The maximum range is 10 days.
- Event type:
POST,PATCH, orDELETE. - User: Any user that appears in the Audit logs.
- Outcome: Allowed or Denied.
Select the date and time range before you apply other filters.
To search, enter an exact resource in the search box.
Export
You can export log entries as a JSON file or a CSV file:
- One entry: Open the ⋮ menu on the row and select Export as JSON or Export as CSV.
- Several entries: Select the checkboxes of the rows. An export bar appears with Export as JSON and Export as CSV. Select × to clear the selection.
Webhook
Admins can create a webhook to stream logs in real time to external SIEM systems or other monitoring tools. When StackGuardian generates a new log entry, it sends the entry to your endpoint right away as a POST request.
Configuration
-
Webhook: Turn the toggle on to send all audit log events to your endpoint. Turn it off to stop sending events.
-
Endpoint (required): The URL where you want to receive the audit log payloads. For example,
https://yourserver.com/webhooks/github. -
Secret (optional): StackGuardian signs each outgoing webhook request with an HMAC SHA-256 signature, using this secret value as the key. The signature lets you verify that the request came from StackGuardian and that nobody changed the payload in transit. StackGuardian sends the signature in the
X-Sg-Signature-256header. For example:X-Sg-Signature-256: sha256=<signature>.infoThe secret is optional but recommended. To learn how to validate the signature, see Validate webhook deliveries.
-
Headers (optional): Turn the toggle on to add HTTP headers that customize the metadata of the webhook request. You can add up to 10 keys. For each header, enter:
- Key: The name of the header.
- Value: The value of the header.
Each header row also has a Use client secret checkbox. Select Add new header to add another row.
Create a webhook
- Select Create webhook.
- Enter the Endpoint.
- Optional: Select a Secret.
- Optional: Turn on Headers and add your headers.
- Select Create.

Create webhook
Webhook payload examples
When StackGuardian sends a request to your endpoint, the request body contains details about the event. The following samples show what to expect.
Example: user sign-in (SG_SIGN_IN)
{
"timestamp": 1757410496427,
"message": {
"id": "b831d3a7-e450-4acc-b524-78c8c17768a2",
"date_created": "2025-09-09T09:34:56",
"action": "SG_SIGN_IN",
"actor": {
"type": "user",
"user": {
"principalEmail": "user@stackguardian.io"
}
},
"effect": "Deny",
"sourceIp": "2106:9140:11:e7e:8c35:afe9:d781:aefb",
"timestamp": 1757410496427,
"user_name": "0067e754-6701-4072-9530-da736f5b1fde",
"user_pool_id": "region",
"company": null,
"new_device_used": false
}
}
Example: deny action
{
"timestamp": 1757411994648,
"message": {
"id": "b831d3a7-e450-4acc-b524-78c8c17768a3",
"date_created": "2025-09-09T09:59:54",
"action": "PATCH/api/v1/orgs/demo-org/wfgrps/policy-resolution-test/wfs/failing-aws-s3-demo-website-5swa/",
"actor": {
"type": "user",
"user": {
"principalEmail": "user@stackguardian.io"
}
},
"effect": "DENY",
"sourceIp": "158.1140.117.0",
"timestamp": 1757411994
}
}
Example: delete action
{
"timestamp": 1757412835493,
"message": {
"id": "b831d3a7-e450-4acc-b524-78c8c17768a4",
"date_created": "2025-09-09T10:13:55",
"action": "DELETE/api/v1/orgs/demo-org/wfgrps/workflow-delete-test/wfs/terraform-aws-vpc-stripped-new-cot6/",
"actor": {
"type": "user",
"user": {
"principalEmail": "user@stackguardian.io"
}
},
"effect": "Allow",
"sourceIp": "60.243.160.178",
"timestamp": 1757412835,
"request_body": {},
"request_method": "DELETE",
"query_params": {},
"response": "Workflow terraform-aws-vpc-stripped-new-cot6 deleted"
}
}
Example: POST action
{
"timestamp": 1757412855196,
"message": {
"id": "b831d3a7-e450-4acc-b524-78c8c17768a5",
"date_created": "2025-09-09T10:14:15",
"action": "POST/api/v1/orgs/demo-org/wfgrps/workflow-delete-test/wfs/terraform-aws-vpc-stripped-new-d7kw/wfruns/",
"actor": {
"type": "user",
"user": {
"principalEmail": "user@stackguardian.io"
}
},
"effect": "Allow",
"sourceIp": "60.243.160.178",
"timestamp": 1757412855,
"request_body": {
"TerraformAction": {
"action": "destroy"
},
"EnableChaining": true
},
"request_method": "POST",
"query_params": {},
"response": {
"OrgId": "/orgs/demo-org",
"SubResourceId": "/wfgrps/workflow-delete-test/wfs/terraform-aws-vpc-stripped-new-d7kw/wfruns/ov9wr8nru04v",
"CreatedAt": 1757412854960,
"Comments": {
"1757412854960": {
"comment": "Workflow Run initiated",
"createdBy": "user@stackguardian.io"
}
},
"Statuses": {
"pre_0_step": [
{
"name": "QUEUED",
"createdAt": 1757412854960
}
]
},
"LatestStatusKey": "pre_0_step",
"ContextTags": {}
}
}
}
Example: PATCH action
{
"timestamp": 1757411989818,
"message": {
"id": "4e35d725-6e0b-4d58-a5e3-d72e48a393c2",
"date_created": "2025-09-09T09:59:49",
"action": "PATCH/api/v1/orgs/demo-org/roles/patch-wf-bugfix/",
"actor": {
"type": "user",
"user": {
"principalEmail": "user@stackguardian.io"
}
},
"effect": "Allow",
"sourceIp": "158.140.167.0",
"timestamp": 1757411989,
"request_body": {
"AllowedPermissions": {
"PATCH/api/v1/orgs/demo-org/wfgrps/<wfGrp>/stacks/<stack>/wfs/<wf>/": {
"name": "UpdateStackWorkflow",
"paths": {
"<wfGrp>": [".*", ".*/.*"],
"<stack>": [".*", ".*"],
"<wf>": [".*", ".*"]
}
}
}
}
}
}
Change or turn off a webhook
The button stays Create webhook after you set up a webhook. To change the settings, select Create webhook to open the webhook dialog and update the fields. To stop StackGuardian from sending events, turn off the Webhook toggle.
Validate webhook deliveries
When you configure a webhook with a secret, every delivery to your endpoint includes a signature header:
X-Sg-Signature-256: sha256=<HMAC>
This signature lets you verify that:
- The request came from StackGuardian, not an attacker.
- Nobody changed the payload in transit.
Validate the signature before you process any incoming webhook data. This prevents wasted processing on spoofed requests and protects against man-in-the-middle attacks.
1. Configure your webhook secret
- Create a secret in Secrets vault to store your secret token.
- Go to Organization settings > Audit logs and open the webhook settings.
- In Secret, select the secret you created and save your changes.
2. How StackGuardian signs requests
- StackGuardian takes the raw audit log webhook payload.
- It computes an HMAC-SHA256 digest, using your secret token as the key.
- It sends the digest in the
X-Sg-Signature-256header in this format:
X-Sg-Signature-256: sha256=<computed_digest>
3. How to validate the signature
On your server:
- Read the raw request body exactly as you receive it, before you parse the JSON.
- Compute the HMAC-SHA256 of that body, using the same webhook secret you configured in StackGuardian.
- Format the result as:
sha256=<your_computed_digest>
- Compare your computed digest to the value in the
X-Sg-Signature-256header. Always use a constant-time comparison function to avoid timing attacks. - If they match, the request is authentic. If they don't match, reject the request.
4. Example (Python)
import hashlib
import hmac
def verify_signature(secret: str, body: bytes, signature_header: str) -> bool:
"""
Verify the StackGuardian webhook signature.
:param secret: The webhook secret token
:param body: The raw request body (bytes)
:param signature_header: The value of the X-Sg-Signature-256 header
:return: True if the signature is valid, False otherwise
"""
# Compute expected signature
expected_hmac = hmac.new(secret.encode(), body, hashlib.sha256).hexdigest()
expected_signature = f"sha256={expected_hmac}"
# Ensure both are bytes for constant-time comparison
try:
return hmac.compare_digest(expected_signature.encode(), signature_header.encode())
except Exception:
return False
5. Security best practices
- Validate signatures before you process the payload.
- Never log your webhook secret or include it in error messages.
- Compare against the raw request body, not a parsed or reformatted version.
- If you configured a secret but the
X-Sg-Signature-256header is missing or invalid, reject the request immediately. Someone might have tampered with it.
With these checks in place, your webhook listener processes only requests that come from StackGuardian.