A common operational challenge when integrating Orca Security into a broader DevOps or SecOps workflow is alert fatigue, particularly with informational or context-specific alerts that become stale after a certain period. Manually reviewing and closing these alerts is a poor use of engineering resources. In this thread, I'll outline a methodical, API-driven approach to automatically close stale alerts using AWS Lambda, treating the Orca API as a component within a middleware architecture.
The core logic hinges on the Orca API's `POST /api/alerts/{alert_id}/dismiss` endpoint. The automation workflow is straightforward:
1. Periodically (e.g., daily via CloudWatch Events) trigger a Lambda function.
2. The function queries the Orca API for alerts matching specific criteria (e.g., `category: 'Informational'`, `state: 'open'`, `created_before: 30 days`).
3. It iterates through the results, programmatically dismissing each alert with a consistent note.
Here is a foundational Python example for the Lambda function. It assumes you have stored your Orca API credentials in AWS Secrets Manager.
```python
import json
import requests
import os
from datetime import datetime, timedelta
import boto3
from botocore.exceptions import ClientError
def get_secret():
secret_name = "OrcaAPICredentials"
region_name = "us-east-1"
session = boto3.session.Session()
client = session.client(service_name='secretsmanager', region_name=region_name)
try:
get_secret_value_response = client.get_secret_value(SecretId=secret_name)
except ClientError as e:
raise e
return json.loads(get_secret_value_response['SecretString'])
def lambda_handler(event, context):
# Fetch API credentials
secrets = get_secret()
ORCA_API_TOKEN = secrets['ORCA_API_TOKEN']
ORCA_API_HOST = secrets['ORCA_API_HOST'] # e.g., 'api.orcasecurity.io'
headers = {
'Authorization': f'Token {ORCA_API_TOKEN}',
'Content-Type': 'application/json'
}
# Calculate timestamp for alerts created more than 30 days ago
time_threshold = (datetime.now() - timedelta(days=30)).isoformat() + 'Z'
# Build query to fetch stale, open informational alerts
query_params = {
'state': 'open',
'category': 'Informational', # Refine this filter as needed
'created_before': time_threshold,
'limit': 100
}
try:
list_alerts_url = f"https://{ORCA_API_HOST}/api/alerts"
response = requests.get(list_alerts_url, headers=headers, params=query_params)
response.raise_for_status()
alerts = response.json().get('data', [])
dismissed_count = 0
for alert in alerts:
alert_id = alert.get('id')
dismiss_payload = {
'operation': 'dismiss',
'comment': f'Auto-dismissed by stale alert Lambda on {datetime.now().date().isoformat()}. Alert older than 30 days.'
}
dismiss_url = f"https://{ORCA_API_HOST}/api/alerts/{alert_id}/dismiss"
dismiss_response = requests.post(dismiss_url, headers=headers, json=dismiss_payload)
if dismiss_response.status_code == 200:
dismissed_count += 1
return {
'statusCode': 200,
'body': json.dumps(f'Successfully processed {len(alerts)} alerts. Dismissed {dismissed_count}.')
}
except requests.exceptions.RequestException as e:
print(f'Error communicating with Orca API: {e}')
return {
'statusCode': 500,
'body': json.dumps('Failed to process alerts.')
}
```
**Key Integration Considerations & Pitfalls:**
* **Idempotency & Rate Limiting:** The Orca API has rate limits. Implement exponential backoff and retry logic for robust error handling, especially when dealing with large volumes of alerts.
* **Alert Criteria Refinement:** The example uses `category: 'Informational'`. You must tailor the query parameters (`severity`, `type`, `asset_group`) to match your specific definition of "stale" to avoid dismissing critical alerts.
* **Audit Trail:** The dismissal comment is crucial for auditability. Consider logging the dismissed alert IDs to an S3 bucket or a SIEM for future reference.
* **Security:** Never hardcode API tokens. Use a secure service like AWS Secrets Manager, as shown, or AWS Systems Manager Parameter Store.
* **Orca API Evolution:** This uses a stable endpoint, but always monitor Orca's API changelog. Building a small abstraction layer around the API calls can mitigate future breaking changes.
This pattern can be extended into a more complex workflow using Step Functions for error handling or by triggering the Lambda from an SQS queue populated by a separate alert polling service. The principle remains: treat security tooling as an integrable component within your automation fabric.
- Mike
- Mike