Metadata-Version: 2.4
Name: surinort-ast
Version: 2.0.1
Summary: Production-grade Abstract Syntax Tree parser for IDS rules (Suricata/Snort) with comprehensive validation and serialization support
Project-URL: Homepage, https://github.com/seifreed/surinort-ast
Project-URL: Documentation, https://seifreed.github.io/surinort-ast
Project-URL: Repository, https://github.com/seifreed/surinort-ast
Project-URL: Issues, https://github.com/seifreed/surinort-ast/issues
Project-URL: Changelog, https://github.com/seifreed/surinort-ast/blob/main/CHANGELOG.md
Project-URL: Source, https://github.com/seifreed/surinort-ast
Project-URL: Bug Tracker, https://github.com/seifreed/surinort-ast/issues
Project-URL: Release Notes, https://github.com/seifreed/surinort-ast/releases
Project-URL: Discussions, https://github.com/seifreed/surinort-ast/discussions
Author-email: Marc Rivero López <mriverolopez@gmail.com>
Maintainer-email: Marc Rivero López <mriverolopez@gmail.com>
License: GPL-3.0-or-later
License-File: LICENSE
Keywords: ast,cybersecurity,ids,intrusion-detection,ips,malware-analysis,network-monitoring,network-security,parser,pcap,rule-parser,security,signature-analysis,snort,suricata,threat-detection
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Information Technology
Classifier: Intended Audience :: Science/Research
Classifier: Intended Audience :: System Administrators
Classifier: License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)
Classifier: Natural Language :: English
Classifier: Operating System :: MacOS :: MacOS X
Classifier: Operating System :: Microsoft :: Windows
Classifier: Operating System :: OS Independent
Classifier: Operating System :: POSIX :: Linux
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Programming Language :: Python :: Implementation :: CPython
Classifier: Topic :: Security
Classifier: Topic :: Software Development :: Compilers
Classifier: Topic :: Software Development :: Interpreters
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Topic :: System :: Networking :: Monitoring
Classifier: Typing :: Typed
Requires-Python: >=3.11
Requires-Dist: jsonschema>=4.26.0
Requires-Dist: lark>=1.3.1
Requires-Dist: pydantic>=2.12.5
Requires-Dist: typer>=0.24.1
Provides-Extra: all
Requires-Dist: bandit>=1.9.4; extra == 'all'
Requires-Dist: build>=1.4.2; extra == 'all'
Requires-Dist: hypothesis>=6.151.10; extra == 'all'
Requires-Dist: mkdocs-material>=9.7.6; extra == 'all'
Requires-Dist: msgpack>=1.1.2; extra == 'all'
Requires-Dist: mypy>=1.20.0; extra == 'all'
Requires-Dist: networkx>=3.6.1; extra == 'all'
Requires-Dist: pre-commit>=4.5.1; extra == 'all'
Requires-Dist: protobuf>=7.34.1; extra == 'all'
Requires-Dist: pytest-benchmark>=5.2.3; extra == 'all'
Requires-Dist: pytest-cov>=7.1.0; extra == 'all'
Requires-Dist: pytest>=9.0.2; extra == 'all'
Requires-Dist: python-magic>=0.4.27; extra == 'all'
Requires-Dist: pyyaml>=6.0.3; extra == 'all'
Requires-Dist: rich>=14.3.3; extra == 'all'
Requires-Dist: ruff>=0.15.9; extra == 'all'
Requires-Dist: safety>=3.7.0; extra == 'all'
Requires-Dist: twine>=6.2.0; extra == 'all'
Provides-Extra: analysis
Requires-Dist: networkx>=3.6.1; extra == 'analysis'
Provides-Extra: benchmark
Requires-Dist: pytest-benchmark>=5.2.3; extra == 'benchmark'
Provides-Extra: cli-enhanced
Requires-Dist: rich>=14.3.3; extra == 'cli-enhanced'
Provides-Extra: dev
Requires-Dist: build>=1.4.2; extra == 'dev'
Requires-Dist: hypothesis>=6.151.10; extra == 'dev'
Requires-Dist: mkdocs-material>=9.7.6; extra == 'dev'
Requires-Dist: mypy>=1.20.0; extra == 'dev'
Requires-Dist: pre-commit>=4.5.1; extra == 'dev'
Requires-Dist: pytest-cov>=7.1.0; extra == 'dev'
Requires-Dist: pytest>=9.0.2; extra == 'dev'
Requires-Dist: ruff>=0.15.9; extra == 'dev'
Requires-Dist: twine>=6.2.0; extra == 'dev'
Provides-Extra: formats
Requires-Dist: python-magic>=0.4.27; extra == 'formats'
Requires-Dist: pyyaml>=6.0.3; extra == 'formats'
Provides-Extra: security
Requires-Dist: bandit>=1.9.4; extra == 'security'
Requires-Dist: safety>=3.7.0; extra == 'security'
Provides-Extra: serialization
Requires-Dist: msgpack>=1.1.2; extra == 'serialization'
Requires-Dist: protobuf>=7.34.1; extra == 'serialization'
Description-Content-Type: text/markdown

<p align="center">
  <img src="https://img.shields.io/badge/surinort--ast-IDS%2FIPS%20AST-blue?style=for-the-badge" alt="surinort-ast">
</p>

<h1 align="center">surinort-ast</h1>

<p align="center">
  <strong>Production-grade AST parser and analysis toolkit for Suricata/Snort rules</strong>
</p>

<p align="center">
  <a href="https://pypi.org/project/surinort-ast/"><img src="https://img.shields.io/pypi/v/surinort-ast?style=flat-square&logo=pypi&logoColor=white" alt="PyPI Version"></a>
  <a href="https://pypi.org/project/surinort-ast/"><img src="https://img.shields.io/pypi/pyversions/surinort-ast?style=flat-square&logo=python&logoColor=white" alt="Python Versions"></a>
  <a href="https://github.com/seifreed/surinort-ast/blob/main/LICENSE"><img src="https://img.shields.io/badge/license-GPL--3.0-green?style=flat-square" alt="License"></a>
  <a href="https://github.com/seifreed/surinort-ast/actions"><img src="https://img.shields.io/github/actions/workflow/status/seifreed/surinort-ast/ci.yml?style=flat-square&logo=github&label=CI" alt="CI Status"></a>
  <a href="https://github.com/seifreed/surinort-ast/security/code-scanning"><img src="https://img.shields.io/badge/code%20scanning-SARIF%20enabled-brightgreen?style=flat-square" alt="SARIF"></a>
</p>

<p align="center">
  <a href="https://github.com/seifreed/surinort-ast/stargazers"><img src="https://img.shields.io/github/stars/seifreed/surinort-ast?style=flat-square" alt="GitHub Stars"></a>
  <a href="https://github.com/seifreed/surinort-ast/issues"><img src="https://img.shields.io/github/issues/seifreed/surinort-ast?style=flat-square" alt="GitHub Issues"></a>
  <a href="https://buymeacoffee.com/seifreed"><img src="https://img.shields.io/badge/Buy%20Me%20a%20Coffee-support-yellow?style=flat-square&logo=buy-me-a-coffee&logoColor=white" alt="Buy Me a Coffee"></a>
</p>

---

## Overview

**surinort-ast** is a Python toolkit to parse, validate, serialize, and analyze IDS/IPS rules from Suricata, Snort2, and Snort3. It provides a typed AST, CLI workflows, and machine-readable outputs including JSON and SARIF 2.1.0.

### Key Features

| Feature | Description |
|---------|-------------|
| **Typed AST** | Full Pydantic-backed AST for headers, options, and metadata |
| **Multi-dialect** | Suricata, Snort2, and Snort3 support |
| **Validation** | Syntax/semantic diagnostics with severity levels |
| **Serialization** | JSON and protobuf support |
| **SARIF 2.1.0** | Parse/validate/analysis findings export for Code Scanning |
| **CLI + Library** | Use as command-line tool or Python package |
| **Coverage/Optimization Analysis** | Built-in analyzers for coverage and optimization insights |
| **Streaming Mode** | Memory-efficient parsing for large rule sets |

### Supported Outputs

```text
AST Data        JSON, protobuf
Diagnostics     Human-readable tables, SARIF 2.1.0
Analysis        Text reports, SARIF 2.1.0 findings
CI Integration  SARIF artifact + GitHub Code Scanning upload
```

---

## Installation

### From PyPI (Recommended)

```bash
pip install surinort-ast
```

### From Source

```bash
git clone https://github.com/seifreed/surinort-ast.git
cd surinort-ast
python3 -m venv venv
source venv/bin/activate  # Windows: venv\Scripts\activate
pip install -e .
```

### Optional Extras

```bash
pip install "surinort-ast[all]"
pip install "surinort-ast[serialization]"
pip install "surinort-ast[analysis]"
pip install "surinort-ast[cli-enhanced]"
```

---

## Quick Start

```bash
# Parse rule file
surinort parse rules/local.rules

# Validate with strict mode
surinort validate rules/local.rules --strict

# Export parse findings to SARIF
surinort parse rules/local.rules --format sarif -o parse-results.sarif
```

---

## Usage

### Command Line Interface

```bash
# Parse to JSON
surinort parse rules/local.rules --json -o rules.json

# Validate and export SARIF
surinort validate rules/local.rules --format sarif -o validate-results.sarif

# Stats and coverage findings in SARIF
surinort stats rules/local.rules --format sarif -o stats-results.sarif
```

### Available Options (Main Commands)

| Command | Description |
|--------|-------------|
| `surinort parse` | Parse rules (`text`, `json`, `sarif`) |
| `surinort validate` | Validate rules with optional strict mode and SARIF output |
| `surinort stats` | Rule statistics and optional SARIF coverage findings |
| `surinort fmt` | Canonical formatting for rule files |
| `surinort to-json` | Convert rules to JSON |
| `surinort from-json` | Convert JSON back to rule text |
| `surinort schema` | Print AST JSON schema |

### SARIF Flags

| Option | Description |
|--------|-------------|
| `--format sarif` | Print SARIF content as command output |
| `--sarif-out <file>` | Write SARIF report while keeping default output mode |
| `-o, --output <file>` | Write primary output to file |

---

## Python Library

### Basic Usage

```python
from surinort_ast import parse_rule, validate_rule, to_json

rule = parse_rule('alert tcp any any -> any 80 (msg:"HTTP"; sid:1;)')
diags = validate_rule(rule)
print(to_json(rule))

for diag in diags:
    print(diag.level, diag.code, diag.message)
```

### SARIF API Usage

```python
from surinort_ast import (
    diagnostics_to_sarif,
    parse_file,
    validate_rule,
)

rules = parse_file("rules/local.rules")
diagnostics = []
for rule in rules:
    diagnostics.extend(validate_rule(rule))

sarif = diagnostics_to_sarif(diagnostics, default_file_path="rules/local.rules")
with open("results.sarif", "w", encoding="utf-8") as f:
    f.write(sarif)
```

### Additional SARIF Helpers

```python
from surinort_ast import (
    coverage_report_to_sarif,
    optimization_results_to_sarif,
    to_sarif,
)
```

---

## CI and GitHub Code Scanning (SARIF)

The project CI now supports SARIF generation and upload:

1. Generate `results.sarif` from real validation diagnostics.
2. Upload SARIF as workflow artifact.
3. Upload SARIF to GitHub Code Scanning.

Minimal workflow example:

```yaml
- name: Generate SARIF report
  run: |
    python - <<'PY'
    from pathlib import Path
    from surinort_ast import diagnostics_to_sarif, parse_file, validate_rule

    fixture_path = Path("tests/fixtures/simple_rules.txt")
    rules = parse_file(fixture_path)
    diagnostics = []
    for rule in rules:
        diagnostics.extend(validate_rule(rule))

    Path("results.sarif").write_text(
        diagnostics_to_sarif(diagnostics, default_file_path=str(fixture_path)),
        encoding="utf-8",
    )
    PY

- name: Upload SARIF to GitHub Code Scanning
  uses: github/codeql-action/upload-sarif@v3
  with:
    sarif_file: results.sarif
```

---

## Requirements

- Python 3.11+
- See [pyproject.toml](pyproject.toml) for dependencies and extras

---

## Contributing

Contributions are welcome.

1. Fork the repository
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
3. Commit your changes (`git commit -m 'Add amazing feature'`)
4. Push to the branch (`git push origin feature/amazing-feature`)
5. Open a Pull Request

---

## Support the Project

If this project is useful in your workflows, you can support development:

<a href="https://buymeacoffee.com/seifreed" target="_blank">
  <img src="https://cdn.buymeacoffee.com/buttons/v2/default-yellow.png" alt="Buy Me A Coffee" height="50">
</a>

---

## License

This project is licensed under the GPL-3.0-or-later license. See [LICENSE](LICENSE).

**Attribution**
- Author: **Marc Rivero López** | [@seifreed](https://github.com/seifreed)
- Repository: [github.com/seifreed/surinort-ast](https://github.com/seifreed/surinort-ast)

---

<p align="center">
  <sub>Built for practical IDS/IPS rule engineering and security automation</sub>
</p>
