Metadata-Version: 2.4
Name: opentip-cli
Version: 0.1.0
Summary: Python library and CLI for the Kaspersky OpenTIP (Threat Intelligence Portal) API
Author: Marc Rivero López
License-Expression: MIT
Project-URL: Homepage, https://github.com/seifreed/OpenTip
Project-URL: Repository, https://github.com/seifreed/OpenTip
Project-URL: Issues, https://github.com/seifreed/OpenTip/issues
Requires-Python: >=3.14
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: requests>=2.32.4
Requires-Dist: types-requests
Requires-Dist: black
Requires-Dist: ruff
Requires-Dist: mypy
Requires-Dist: bandit
Requires-Dist: build
Requires-Dist: pip-audit
Requires-Dist: pytest
Requires-Dist: pytest-cov
Dynamic: license-file

<p align="center">
  <img src="https://img.shields.io/badge/opentip--cli-Threat%20Intelligence-blue?style=for-the-badge" alt="opentip-cli">
</p>

<h1 align="center">opentip-cli</h1>

<p align="center">
  <strong>Python library and CLI for the Kaspersky OpenTIP (Threat Intelligence Portal) API</strong>
</p>

<p align="center">
  <a href="https://pypi.org/project/opentip-cli/"><img src="https://img.shields.io/pypi/v/opentip-cli?style=flat-square&logo=pypi&logoColor=white" alt="PyPI Version"></a>
  <a href="https://pypi.org/project/opentip-cli/"><img src="https://img.shields.io/pypi/pyversions/opentip-cli?style=flat-square&logo=python&logoColor=white" alt="Python Versions"></a>
  <a href="https://github.com/seifreed/OpenTip/blob/main/LICENSE"><img src="https://img.shields.io/badge/license-MIT-green?style=flat-square" alt="License"></a>
  <a href="https://github.com/seifreed/OpenTip/actions"><img src="https://img.shields.io/github/actions/workflow/status/seifreed/OpenTip/ci.yml?style=flat-square&logo=github&label=CI" alt="CI Status"></a>
</p>

<p align="center">
  <a href="https://github.com/seifreed/OpenTip/stargazers"><img src="https://img.shields.io/github/stars/seifreed/OpenTip?style=flat-square" alt="GitHub Stars"></a>
  <a href="https://github.com/seifreed/OpenTip/issues"><img src="https://img.shields.io/github/issues/seifreed/OpenTip?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

**opentip-cli** is a Python library and command-line client for the [Kaspersky OpenTIP API](https://opentip.kaspersky.com/Help/Doc_data/WorkingWithAPI.htm). It covers every public API endpoint: hash, IP, domain, and URL lookups, file submission to the Sandbox, and full analysis report retrieval.

### Endpoints

| Endpoint | Library method | CLI command |
|----------|----------------|-------------|
| `GET /search/hash` | `lookup_hash` | `opentip hash <hash>` |
| `GET /search/ip` | `lookup_ip` | `opentip ip <address>` |
| `GET /search/domain` | `lookup_domain` | `opentip domain <domain>` |
| `GET /search/url` | `lookup_url` | `opentip url <address>` |
| `POST /scan/file` | `scan_file` | `opentip scan <path>` |
| `POST /getresult/file` | `get_file_report` | `opentip report <hash>` |

---

## Installation

### From PyPI (Recommended)

```bash
pip install opentip-cli
```

### From Source

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

---

## API Token

Request a token in the [OpenTIP web interface](https://opentip.kaspersky.com/), then provide it in one of these ways (checked in this order):

1. `--api-key` CLI flag or the `api_key` argument of `OpenTipClient`.
2. `OPENTIP_API_KEY` environment variable.
3. Config file at `~/.config/opentip/config.ini` (override with `--config`):

```ini
[opentip]
api_key = <your token>
```

Security notes:

- Restrict the config file to your user (`chmod 600 ~/.config/opentip/config.ini` on Linux/macOS).
- Prefer the environment variable or the config file over `--api-key`: command-line arguments are visible to other local processes and end up in your shell history.

---

## Quick Start

```bash
# Look up a file hash
opentip hash 275a021bbfb6489e54d471899f7db9d1663fc695ec2fe2a2c4538aabf651fd0f

# Look up an IP address
opentip ip 8.8.8.8

# Submit a file to the Sandbox
opentip scan ./sample.bin

# Choose the output format (default: table)
opentip --format json ip 8.8.8.8
opentip --format toon ip 8.8.8.8
opentip --format sarif hash 275a021bbfb6489e54d471899f7db9d1663fc695ec2fe2a2c4538aabf651fd0f
```

---

## Usage

### Command Line Interface

```bash
opentip hash 275a021bbfb6489e54d471899f7db9d1663fc695ec2fe2a2c4538aabf651fd0f
opentip ip 8.8.8.8
opentip domain example.com
opentip url https://example.com/index.html
opentip scan ./sample.bin --filename sample.bin
opentip report 275a021bbfb6489e54d471899f7db9d1663fc695ec2fe2a2c4538aabf651fd0f
```

By default results are printed as a readable table; use `--format` for machine-readable output. On API errors the command prints the reason to stderr and exits with code 1.

```text
+---------------------------+----------------------+
| Field                     | Value                |
+---------------------------+----------------------+
| Zone                      | Green                |
| IpGeneralInfo.Status      | known                |
| IpGeneralInfo.CountryCode | US                   |
| IpGeneralInfo.FirstSeen   | 2014-06-07T18:51:00Z |
+---------------------------+----------------------+
```

Note: the URL endpoint requires a web address with a path (for example `example.com/index.html`); the API answers `400 Bad Request` for bare hosts — use the `domain` command for those.

### Available Commands

| Command | Description |
|---------|-------------|
| `opentip hash` | Look up an MD5, SHA1, or SHA256 file hash |
| `opentip ip` | Look up an IP address |
| `opentip domain` | Look up a domain |
| `opentip url` | Look up a web address |
| `opentip scan` | Submit a file for Sandbox analysis (`--filename` to override the name) |
| `opentip report` | Get the full analysis report for a previously submitted hash |

### Global Options

| Option | Description |
|--------|-------------|
| `--api-key <token>` | API token (defaults to `OPENTIP_API_KEY` or the config file) |
| `--config <file>` | Path to a config file with `api_key` under an `[opentip]` section |
| `--format <format>` | Output format: `table` (default), `json`, `toon`, or `sarif` |

### Output Formats

| Format | Description |
|--------|-------------|
| `table` | Prettytable-style ASCII table with flattened fields (default) |
| `json` | Pretty-printed JSON, the raw API response |
| `toon` | [TOON (Token-Oriented Object Notation)](https://github.com/toon-format/toon) — compact, token-efficient output for LLM pipelines |
| `sarif` | [SARIF 2.1.0](https://docs.oasis-open.org/sarif/sarif/v2.1.0/) log with the verdict mapped to a result level (`Red` → `error`, `Orange`/`Yellow` → `warning`, `Green`/`Grey` → `note`) and the full API response embedded in the result properties |

---

## Python Library

### Basic Usage

```python
from opentip import OpenTipClient

client = OpenTipClient()  # token from env var or config file
verdict = client.lookup_hash(
    "275a021bbfb6489e54d471899f7db9d1663fc695ec2fe2a2c4538aabf651fd0f"
)
print(verdict["Zone"])
```

### File Submission and Reports

```python
from opentip import OpenTipClient

client = OpenTipClient()
report = client.scan_file("sample.bin")
full_report = client.get_file_report(report["FileGeneralInfo"]["Sha256"])
print(full_report["Status"])
```

### Error Handling

```python
from opentip import MissingApiKeyError, OpenTipClient, OpenTipError

try:
    client = OpenTipClient()
    result = client.lookup_domain("example.com")
except MissingApiKeyError as error:
    print(f"No token configured: {error}")
except OpenTipError as error:
    print(f"API error {error.status_code}: {error}")
```

All methods return the API response as a `dict` and raise `opentip.OpenTipError` (with `status_code`) on failure.

### Output Formatters

```python
from opentip import OpenTipClient, to_json, to_sarif, to_table, to_toon

client = OpenTipClient()
result = client.lookup_ip("8.8.8.8")

print(to_table(result))                   # prettytable-style ASCII table
print(to_json(result))                    # pretty-printed JSON
print(to_toon(result))                    # TOON, token-efficient for LLM prompts
print(to_sarif(result, "ip", "8.8.8.8"))  # SARIF 2.1.0 log
```

---

## Requirements

- Python 3.14+
- All dependencies (runtime and development) live in [requirements.txt](requirements.txt)

---

## Development

```bash
python3.14 -m venv venv
venv/bin/pip install -r requirements.txt
```

Quality and security gates (all must pass with zero findings):

```bash
black --check .
ruff check .
mypy .
bandit -c pyproject.toml -r .
pip-audit
```

Tests run against the real API (no mocks) and require `OPENTIP_API_KEY` to be set. Coverage below 100% fails the run:

```bash
OPENTIP_API_KEY=<your token> venv/bin/pytest
```

---

## 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 MIT license. See [LICENSE](LICENSE).

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

---

<p align="center">
  <sub>Built for practical threat intelligence lookups and security automation</sub>
</p>
