Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions github_actions/.github/workflows/1password.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
name: Ingest 1Password Events into Chronicle

on:
workflow_dispatch:

jobs:
ingest:
runs-on: ubuntu-latest

steps:
- name: Checkout repo
uses: actions/checkout@v3

- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.10'

- name: Install dependencies
run: |
pip install -r chronicle-scripts/1password-chronicle-ingestor/requirements.txt

- name: Write Chronicle service account key to file
shell: bash
run: |
echo "${{ secrets.CHRONICLE_CREDENTIALS_JSON }}" | base64 --decode > chronicle_sa.json

- name: Run 1Password ingestion script
env:
PYTHONPATH: chronicle-scripts
CHRONICLE_CUSTOMER_ID: ${{ secrets.CHRONICLE_CUSTOMER_ID }}
CHRONICLE_REGION: ${{ secrets.CHRONICLE_REGION }}
GOOGLE_APPLICATION_CREDENTIALS: chronicle_sa.json
CHRONICLE_SERVICE_ACCOUNT: chronicle_sa.json
CHRONICLE_NAMESPACE: ${{ secrets.CHRONICLE_NAMESPACE }}
ONEPASSWORD_TOKEN: ${{ secrets.ONEPASSWORD_TOKEN }}
EVENTS_API_URL: https://events.1password.com/api/v2/auditevents
run: |
python chronicle-scripts/1password-chronicle-ingestor/main.py --creds-file chronicle_sa.json
40 changes: 40 additions & 0 deletions github_actions/.github/workflows/entra.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
name: Ingest Microsoft Entra Non-Interactive Sign-ins into Chronicle

on:
workflow_dispatch: # Manual trigger only

jobs:
ingest:
runs-on: ubuntu-latest

steps:
- name: Checkout repo
uses: actions/checkout@v3

- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.10'

- name: Install dependencies
run: |
pip install -r chronicle-scripts/entra-noninteractive-chronicle-ingestor/requirements.txt

- name: Write Chronicle service account key to file
shell: bash
run: |
echo "${{ secrets.CHRONICLE_CREDENTIALS_JSON }}" | base64 --decode > chronicle_sa.json

- name: Run Entra non-interactive ingestion script
env:
PYTHONPATH: chronicle-scripts
CHRONICLE_CUSTOMER_ID: ${{ secrets.CHRONICLE_CUSTOMER_ID }}
CHRONICLE_REGION: ${{ secrets.CHRONICLE_REGION }}
GOOGLE_APPLICATION_CREDENTIALS: chronicle_sa.json
CHRONICLE_SERVICE_ACCOUNT: chronicle_sa.json
CHRONICLE_NAMESPACE: ${{ secrets.CHRONICLE_NAMESPACE }}
GRAPH_CLIENT_ID: ${{ secrets.GRAPH_CLIENT_ID }}
GRAPH_CLIENT_SECRET: ${{ secrets.GRAPH_CLIENT_SECRET }}
GRAPH_TENANT_ID: ${{ secrets.GRAPH_TENANT_ID }}
run: |
python chronicle-scripts/entra-noninteractive-chronicle-ingestor/main.py --creds-file chronicle_sa.json
39 changes: 39 additions & 0 deletions github_actions/.github/workflows/github.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
name: Ingest GitHub Audit Logs into Chronicle

on:
workflow_dispatch:

jobs:
ingest:
runs-on: ubuntu-latest

steps:
- name: Checkout repo
uses: actions/checkout@v3

- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.10'

- name: Install dependencies
run: |
pip install -r chronicle-scripts/github-chronicle-ingestor/requirements.txt

- name: Write Chronicle service account key to file
run: |
echo "${{ secrets.CHRONICLE_CREDENTIALS_JSON }}" | base64 --decode > chronicle_sa.json

- name: Run GitHub ingestion script
env:
PYTHONPATH: chronicle-scripts
GOOGLE_APPLICATION_CREDENTIALS: chronicle_sa.json
CHRONICLE_CUSTOMER_ID: ${{ secrets.CHRONICLE_CUSTOMER_ID }}
CHRONICLE_REGION: ${{ secrets.CHRONICLE_REGION }}
CHRONICLE_NAMESPACE: ${{ secrets.CHRONICLE_NAMESPACE }}
CHRONICLE_SERVICE_ACCOUNT: chronicle_sa.json
GITHUB_AUDIT_TOKEN: ${{ secrets.GITHUB_AUDIT_TOKEN }}
GITHUB_AUDIT_URL: ${{ secrets.GITHUB_AUDIT_URL }}
run: |
python chronicle-scripts/github-chronicle-ingestor/main.py --creds-file chronicle_sa.json

43 changes: 43 additions & 0 deletions github_actions/.github/workflows/snowflake.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
name: Ingest Snowflake Audit Logs into Chronicle

on:
workflow_dispatch:

jobs:
ingest:
runs-on: ubuntu-latest

steps:
- name: Checkout repo
uses: actions/checkout@v3

- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.10'

- name: Install dependencies
run: |
pip install -r chronicle-scripts/snowflake-chronicle-ingestor/requirements.txt

- name: Write Chronicle service account key to file
shell: bash
run: |
echo "${{ secrets.CHRONICLE_CREDENTIALS_JSON }}" | base64 --decode > chronicle_sa.json

- name: Run Snowflake ingestion script
env:
PYTHONPATH: chronicle-scripts
CHRONICLE_CUSTOMER_ID: ${{ secrets.CHRONICLE_CUSTOMER_ID }}
CHRONICLE_REGION: ${{ secrets.CHRONICLE_REGION }}
CHRONICLE_NAMESPACE: ${{ secrets.CHRONICLE_NAMESPACE }}
GOOGLE_APPLICATION_CREDENTIALS: chronicle_sa.json
CHRONICLE_SERVICE_ACCOUNT: chronicle_sa.json
SNOWFLAKE_USER: ${{ secrets.SNOWFLAKE_USER }}
SNOWFLAKE_PASSWORD: ${{ secrets.SNOWFLAKE_PASSWORD }}
SNOWFLAKE_ACCOUNT: ${{ secrets.SNOWFLAKE_ACCOUNT }}
SNOWFLAKE_WAREHOUSE: ${{ secrets.SNOWFLAKE_WAREHOUSE }}
SNOWFLAKE_ROLE: ${{ secrets.SNOWFLAKE_ROLE }}
run: |
python chronicle-scripts/snowflake-chronicle-ingestor/main.py --creds-file chronicle_sa.json

40 changes: 40 additions & 0 deletions github_actions/.github/workflows/thinkst-audit.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
name: Ingest Thinkst Canary Audit Logs into Chronicle

on:
workflow_dispatch:

jobs:
ingest:
runs-on: ubuntu-latest

steps:
- name: Checkout repo
uses: actions/checkout@v3

- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.10'

- name: Install dependencies
run: |
pip install -r chronicle-scripts/thinkst-canary-chronicle-ingestor/requirements.txt

- name: Write Chronicle service account key to file
shell: bash
run: |
echo "${{ secrets.CHRONICLE_CREDENTIALS_JSON }}" | base64 --decode > chronicle_sa.json

- name: Run Thinkst Canary ingestion script
env:
PYTHONPATH: chronicle-scripts
CHRONICLE_CUSTOMER_ID: ${{ secrets.CHRONICLE_CUSTOMER_ID }}
CHRONICLE_REGION: ${{ secrets.CHRONICLE_REGION }}
GOOGLE_APPLICATION_CREDENTIALS: chronicle_sa.json
CHRONICLE_SERVICE_ACCOUNT: chronicle_sa.json
CHRONICLE_NAMESPACE: ${{ secrets.CHRONICLE_NAMESPACE }}
CANARY_CONSOLE_ID: ${{ secrets.CANARY_CONSOLE_ID }}
CANARY_AUTH_TOKEN: ${{ secrets.CANARY_AUTH_TOKEN }}
run: |
python chronicle-scripts/thinkst-canary-chronicle-ingestor/main.py --creds-file chronicle_sa.json

66 changes: 66 additions & 0 deletions github_actions/1password-chronicle-ingestor/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
# 1Password Events Ingestor for Chronicle

This module ingests security-related events from the **1Password Events API** into **Google Chronicle** using the Unstructured Ingestion API.

---

## πŸ” What It Does

- Authenticates to the 1Password Events API using a bearer token
- Fetches audit events since the last run
- Normalizes and forwards logs to Chronicle
- Supports execution via GitHub Actions or locally

---

## πŸ›  Requirements

- Python 3.7+
- GitHub Actions enabled
- GitHub Secrets:
- `ONEPASSWORD_TOKEN`
- `EVENTS_API_URL` (defaults to `https://events.1password.com/api/v2/auditevents`)
- `CHRONICLE_CUSTOMER_ID`
- `CHRONICLE_REGION`
- `CHRONICLE_NAMESPACE` (optional)
- `CHRONICLE_CREDENTIALS_JSON` (base64-encoded service account JSON)

---

## βš™ GitHub Actions Workflow

Location: `.github/workflows/1password.yml`

This workflow:
- Runs **manually only**
- Installs dependencies
- Writes Chronicle service credentials
- Executes the 1Password ingestion script

---

## πŸ§ͺ Running Locally

```bash
export ONEPASSWORD_TOKEN=...
export EVENTS_API_URL=https://events.1password.com/api/v2/auditevents
export CHRONICLE_CUSTOMER_ID=...
export CHRONICLE_REGION=...
export GOOGLE_APPLICATION_CREDENTIALS=/path/to/chronicle_sa.json

python main.py --creds-file /path/to/chronicle_sa.json
```

---

## πŸ“„ Notes

- The `EVENTS_API_URL` must be accessible and your token scoped appropriately
- Script defaults to collecting events from the last 5 minutes or since the last successful run
- Designed for organizations needing audit coverage from 1Password

---

## 🀝 Contributions

Contributions are welcome via pull request or issue!
37 changes: 37 additions & 0 deletions github_actions/1password-chronicle-ingestor/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import os
import requests
from datetime import datetime, timezone
from common import ingest, env_constants, utils

CHRONICLE_LOG_TYPE = "ONEPASSWORD"
EVENTS_API_URL = os.getenv("EVENTS_API_URL")
ONEPASSWORD_TOKEN = os.getenv("ONEPASSWORD_TOKEN")

def fetch_events(start_time: datetime):
headers = {
"Authorization": f"Bearer {ONEPASSWORD_TOKEN}",
"Content-Type": "application/json"
}

iso_since = start_time.replace(tzinfo=timezone.utc).isoformat(timespec="seconds")
body = {
"limit": 1000,
"since": iso_since
}

print(f"[INFO] Fetching 1Password events since {iso_since} from {EVENTS_API_URL}")
response = requests.post(EVENTS_API_URL, headers=headers, json=body)
response.raise_for_status()

data = response.json()
print(f"[INFO] Retrieved {len(data.get('items', []))} events from 1Password.")
return data.get("items", [])

def main():
last_run_time = utils.get_last_run_at()
logs = fetch_events(last_run_time)
ingest.ingest(logs, CHRONICLE_LOG_TYPE)
print("[INFO] Ingestion completed.")

if __name__ == "__main__":
main()
2 changes: 2 additions & 0 deletions github_actions/1password-chronicle-ingestor/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
requests
google-auth>=2.0.0
76 changes: 76 additions & 0 deletions github_actions/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
# πŸ›‘ Chronicle Ingestion Scripts

This repository contains custom ingestion connectors designed to forward third-party security logs into [Google Chronicle](https://cloud.google.com/chronicle).

Each connector is a lightweight, self-contained Python script that authenticates to a third-party API or platform, collects relevant logs, and pushes them into Chronicle using the **Unstructured Ingestion API**.

---

## πŸ“Œ Why This Exists

While Chronicle provides powerful detection capabilities, it does **not offer native integrations** for many widely used security tools and services. This repository was created to:

- Enable ingestion of log sources not supported by default in Chronicle
- Provide a **cost-effective alternative** to GCP Cloud Functions or Cloud Run for those seeking to reduce infrastructure spend
- Standardize and automate ingestion workflows using open-source tooling and GitHub Actions

---

## βœ… Key Features

- Python-based, modular connectors
- GitHub Actions support for **manual** and **scheduled (cron)** runs
- Secure credential injection via GitHub Secrets

---

## πŸ”— Supported Integrations

| Integration | Log Type | Description |
|--------------------|------------------|-------------------------------------------------------------------------|
| Microsoft Entra ID | `AZURE_AD` | Captures non-interactive sign-in events via Microsoft Graph API (Beta) |
| 1Password | `ONEPASSWORD` | Pulls audit events using 1Password Events API |
| GitHub | `GITHUB` | Collects GitHub org audit logs using the REST API |
| Snowflake | `SNOWFLAKE` | Gathers usage logs from ACCOUNT_USAGE views in Snowflake |
| Thinkst Canary | `THINKST_CANARY` | Ingests audit trail logs from the Canary console |

---

## 🧱 Folder Structure

```
chronicle-scripts/
β”œβ”€β”€ 1password-chronicle-ingestor/ # 1Password Events API ingestion
β”œβ”€β”€ entra-noninteractive-chronicle-ingestor/ # Microsoft Entra non-interactive sign-ins
β”œβ”€β”€ github-chronicle-ingestor/ # GitHub audit log ingestion
β”œβ”€β”€ snowflake-chronicle-ingestor/ # Snowflake ACCOUNT_USAGE logs
β”œβ”€β”€ thinkst-canary-chronicle-ingestor/ # Thinkst Canary audit trail ingestion
```

---

## 🧠 Configuration Notes

- All secrets (API tokens, credentials, org URLs) are securely managed via **GitHub Actions Secrets**
- Each `main.py` script handles:
- Authentication to source platform
- API communication and log retrieval
- Pushing logs to Chronicle via the Unstructured Ingestion API

---

## πŸ•’ Scheduling & Execution

Each connector includes a GitHub Actions workflow that can:

- Be triggered **manually**
- Run on a **cron schedule** (e.g., every 15 or 30 minutes)

This model gives users flexibility while avoiding the costs associated with always-on cloud infrastructure.

---

## πŸ‘₯ Contributions

We welcome community contributions! To propose an enhancement or new connector, please open an issue or submit a pull request.

Loading