---
title: Audit Log Export | Keycard
description: Export Keycard audit logs to your S3 bucket in OCSF format
---

Audit Log Export allows you to automatically export Keycard audit logs to your own AWS S3 bucket in OCSF (Open Cybersecurity Schema Framework) format. This enables integration with security information and event management (SIEM) tools, data warehouses, and custom analytics platforms.

## Data Format

### OCSF Schema

Audit logs are exported in [OCSF v1.7.0](https://schema.ocsf.io/1.7.0/) format, an industry-standard schema for security events. Events include authentication, authorization, API operations, and secret management activities.

### File Format

Files are delivered as **Parquet** files with the following characteristics:

- **Compression**: Snappy compression
- **Partitioning**: Files are organized by date
- **Naming**: `YYYY-MM-DD-HH-MM-SS-{uuid}.parquet`
- **Delivery SLA**: Events are delivered within one hour of occurrence

### S3 Key Structure

Files will be written to your bucket with this structure:

```
s3://your-bucket/[prefix/]YYYY-MM-DD-HH-MM-SS-{uuid}.parquet
```

Example:

```
s3://acme-keycard-audit-logs/keycard/audit_logs/2026-02-05-14-30-00-1b2e4543-cf21-49c2-9459-bdada803c24b.parquet
```

## Prerequisites

Before configuring audit log export, you’ll need:

- An AWS S3 bucket in your AWS account
- An IAM role with permissions for Keycard to write to your bucket

## Setup

Note

**First step:** Contact Keycard support to request audit log export and provide them with your configuration details (see final step).

The **Keycard AWS Organization Path** for production is: `o-c7hznpvsin/r-6n6x/ou-6n6x-bcvsfrlg/ou-6n6x-oox2udyt/*`

You’ll need to generate an **External ID** - a secret credential for the IAM trust policy. Generate a random UUID or use:

Terminal window

```
uuidgen
```

Keep this External ID secure - you’ll use it in your IAM trust policy and provide it to Keycard support.

1. **Create an S3 bucket**

   Create an S3 bucket in your AWS account where audit logs will be delivered:

   Terminal window

   ```
   aws s3api create-bucket \
     --bucket $BUCKET_NAME \
     --region us-east-1
   ```

   Note

   Choose a bucket name that follows your organization’s naming conventions. We recommend including “keycard” and “audit” in the name for clarity.

2. **Enable bucket encryption**

   Enable default encryption at rest for all objects:

   Terminal window

   ```
   aws s3api put-bucket-encryption \
     --bucket $BUCKET_NAME \
     --server-side-encryption-configuration '{
       "Rules": [{
         "ApplyServerSideEncryptionByDefault": {
           "SSEAlgorithm": "AES256"
         },
         "BucketKeyEnabled": true
       }]
     }'
   ```

   Note

   For enhanced security, you can use AWS KMS encryption instead of AES256. See the KMS encryption step below for details.

3. **Block public access**

   Enable S3 Block Public Access to prevent accidental public exposure:

   Terminal window

   ```
   aws s3api put-public-access-block \
     --bucket $BUCKET_NAME \
     --public-access-block-configuration \
       "BlockPublicAcls=true,IgnorePublicAcls=true,BlockPublicPolicy=true,RestrictPublicBuckets=true"
   ```

4. **Enable bucket versioning**

   Enable versioning to protect audit logs from accidental deletion or modification:

   Terminal window

   ```
   aws s3api put-bucket-versioning \
     --bucket $BUCKET_NAME \
     --versioning-configuration Status=Enabled
   ```

5. **Create IAM trust policy**

   Create a file named `trust-policy.json`:

   ```
   {
     "Version": "2012-10-17",
     "Statement": [
       {
         "Effect": "Allow",
         "Principal": {
           "AWS": "*"
         },
         "Action": "sts:AssumeRole",
         "Condition": {
           "StringEquals": {
             "sts:ExternalId": "$EXTERNAL_ID"
           },
           "ForAnyValue:StringLike": {
             "aws:PrincipalOrgPaths": "o-c7hznpvsin/r-6n6x/ou-6n6x-bcvsfrlg/ou-6n6x-oox2udyt/*"
           }
         }
       }
     ]
   }
   ```

   Caution

   Replace `$EXTERNAL_ID` with the External ID you generated. The External ID is a secret credential that prevents the confused deputy problem. Keep it secure.

6. **Create the IAM role**

   Terminal window

   ```
   aws iam create-role \
     --role-name KeycardAuditLogWriter \
     --assume-role-policy-document file://trust-policy.json
   ```

7. **Attach S3 permissions**

   Create a file named `permissions-policy.json`:

   ```
   {
     "Version": "2012-10-17",
     "Statement": [
       {
         "Sid": "ListBucketForPrefix",
         "Effect": "Allow",
         "Action": ["s3:ListBucket"],
         "Resource": "arn:aws:s3:::$BUCKET_NAME"
       },
       {
         "Sid": "ReadWriteWithTLS",
         "Effect": "Allow",
         "Action": ["s3:PutObject", "s3:AbortMultipartUpload"],
         "Resource": "arn:aws:s3:::$BUCKET_NAME/*",
         "Condition": {
           "Bool": {
             "aws:SecureTransport": "true"
           }
         }
       }
     ]
   }
   ```

   Replace `$BUCKET_NAME` with your actual bucket name.

   Attach the policy:

   Terminal window

   ```
   aws iam put-role-policy \
     --role-name KeycardAuditLogWriter \
     --policy-name S3WriteAccess \
     --policy-document file://permissions-policy.json
   ```

   Save the role ARN - you’ll need it for configuration:

   Terminal window

   ```
   aws iam get-role \
     --role-name KeycardAuditLogWriter \
     --query 'Role.Arn' \
     --output text
   ```

8. **(Optional) Upgrade to KMS encryption**

   For enhanced security with customer-managed keys, you can upgrade from AES256 to KMS encryption.

   Caution

   If you enable KMS encryption, you must update both the IAM role permissions and the KMS key policy. Missing IAM role KMS permissions will prevent Keycard from writing audit logs and you from reading exported files.

   First, update your bucket encryption configuration to use KMS:

   Terminal window

   ```
   aws s3api put-bucket-encryption \
     --bucket $BUCKET_NAME \
     --server-side-encryption-configuration '{
       "Rules": [{
         "ApplyServerSideEncryptionByDefault": {
           "SSEAlgorithm": "aws:kms",
           "KMSMasterKeyID": "arn:aws:kms:us-east-1:$AWS_ACCOUNT_ID:key/$KMS_ID"
         },
         "BucketKeyEnabled": true
       }]
     }'
   ```

   Next, update the IAM role policy to grant KMS permissions. Create a file named `kms-permissions-policy.json`:

   ```
   {
     "Version": "2012-10-17",
     "Statement": [
       {
         "Sid": "ListBucketForPrefix",
         "Effect": "Allow",
         "Action": ["s3:ListBucket"],
         "Resource": "arn:aws:s3:::$BUCKET_NAME"
       },
       {
         "Sid": "ReadWriteWithTLS",
         "Effect": "Allow",
         "Action": ["s3:PutObject", "s3:AbortMultipartUpload"],
         "Resource": "arn:aws:s3:::$BUCKET_NAME/*",
         "Condition": {
           "Bool": {
             "aws:SecureTransport": "true"
           }
         }
       },
       {
         "Sid": "AllowKMSEncryption",
         "Effect": "Allow",
         "Action": ["kms:Decrypt", "kms:GenerateDataKey"],
         "Resource": "arn:aws:kms:us-east-1:$AWS_ACCOUNT_ID:key/$KMS_ID"
       }
     ]
   }
   ```

   Replace:

   - `$BUCKET_NAME` with your bucket name (appears in 2 places)
   - `$AWS_ACCOUNT_ID` with your AWS account ID
   - `$KMS_ID` with your KMS key ID

   Update the IAM role policy:

   Terminal window

   ```
   aws iam put-role-policy \
     --role-name KeycardAuditLogWriter \
     --policy-name S3WriteAccess \
     --policy-document file://kms-permissions-policy.json
   ```

   Then grant the IAM role access to your KMS key by adding this statement to your KMS key policy:

   ```
   {
     "Sid": "AllowKeycardToEncrypt",
     "Effect": "Allow",
     "Principal": {
       "AWS": "arn:aws:iam::$AWS_ACCOUNT_ID:role/KeycardAuditLogWriter"
     },
     "Action": ["kms:Decrypt", "kms:GenerateDataKey"],
     "Resource": "*"
   }
   ```

   Update your KMS key policy:

   Terminal window

   ```
   # Get current policy
   aws kms get-key-policy \
     --key-id $KMS_ID \
     --policy-name default \
     --output text > current-key-policy.json


   # Edit current-key-policy.json to add the AllowKeycardToEncrypt statement above to the "Statement" array


   # Update the key policy
   aws kms put-key-policy \
     --key-id $KMS_ID \
     --policy-name default \
     --policy file://current-key-policy.json
   ```

   Replace `$AWS_ACCOUNT_ID` and `$KMS_ID` with your actual AWS account ID and KMS key ID.

9. **Provide configuration to Keycard support**

   Provide Keycard support with your configuration details:

   - **S3 Bucket Name**
   - **S3 Bucket Region**
   - **IAM Role ARN**
   - **External ID** - The External ID you generated and used in your IAM trust policy
   - **S3 Key Prefix** (optional): A prefix for organizing files, e.g., `keycard/audit_logs/`
   - **KMS Key ARN** (optional): Only if you upgraded to KMS encryption

   Keycard support will configure the export and notify you when it’s active.

## Verifying Export

1. **Check S3 bucket**

   Confirm that Parquet files are being created in your bucket:

   Terminal window

   ```
   aws s3 ls s3://$BUCKET_NAME/keycard/audit_logs/
   ```

   Tip

   Files should appear within one hour of activity in Keycard. File names follow the pattern: `YYYY-MM-DD-HH-MM-SS-{uuid}.parquet`

2. **Validate file contents**

   Download and inspect a sample file:

   Terminal window

   ```
   # Install parquet-tools
   pip install parquet-tools


   # View file schema and sample data
   parquet-tools show s3://your-bucket/prefix/file.parquet
   ```

## Troubleshooting

No files appearing in S3 bucket

- Verify the IAM role trust policy includes the correct External ID provided by Keycard support
- Confirm the IAM role has `s3:PutObject` permission on your bucket
- Check with Keycard support that export is enabled for your organization

Access denied errors

- Verify the IAM role has `s3:PutObject` and `s3:ListBucket` permissions
- Ensure the External ID in the trust policy matches the value provided by Keycard support
- If you upgraded to KMS encryption, confirm the KMS key policy grants access to the IAM role
- Check that Block Public Access settings aren’t preventing the write operation

Files not readable by downstream systems

- Confirm your system supports Parquet file format
- Check that your system has appropriate AWS credentials to read from your S3 bucket
- Verify file permissions and encryption settings are compatible with your system

---

## Security Responsibility

Keycard delivers your audit logs to your S3 bucket using encrypted connections and authenticated access. It is your sole responsibility to ensure your S3 bucket is secure, this includes but is not limited to:

- Maintaining appropriate S3 bucket policies and access controls
- Managing encryption keys (if using KMS)
- Controlling who can read audit logs from your bucket
- Implementing lifecycle policies and retention requirements
- Meeting your organization’s security and compliance standards

Keycard’s obligations are set out in your Master Services Agreement and Service Level Agreement. Once successful delivery of logs to your S3 bucket has been completed Keycard responsibility for the safekeeping of the data ends. All subsequent storage, access control, and data handling is your responsibility.

---

Note

Need help? Contact Keycard support.
