Skip to content
Merged
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
11 changes: 8 additions & 3 deletions .claude-plugin/marketplace.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@
"url": "https://github.com/crowdsecurity"
},
"metadata": {
"description": "CrowdSec skills and tooling for Claude Code — operational automation for installing, configuring, and debugging CrowdSec."
"description": "CrowdSec skills and tooling — operational automation for installing, configuring, and debugging CrowdSec, plus a Service API skill for the premium Console cloud API."
},
"plugins": [
{
"name": "crowdsec",
"source": "./",
"description": "Operational skill for installing, configuring, operating, and debugging CrowdSec (cscli, LAPI/CAPI, hub, bouncers, WAF/AppSec) across bare-metal, Docker, and Kubernetes.",
"description": "CrowdSec skills: an operational skill (engine, cscli, hub, bouncers, WAF/AppSec across bare-metal, Docker, Kubernetes) and a Service API skill (premium Console cloud API — blocklists, allowlists, firewall integrations, metrics, decisions).",
"version": "0.2.3",
"author": {
"name": "CrowdSec",
Expand All @@ -30,7 +30,12 @@
"bouncer",
"fail2ban",
"devops",
"sre"
"sre",
"console",
"service-api",
"sapi",
"blocklist",
"integration"
]
}
]
Expand Down
13 changes: 10 additions & 3 deletions .claude-plugin/plugin.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@
"name": "crowdsec",
"version": "0.2.3",
"skills": [
"./skills/crowdsec"
"./skills/crowdsec",
"./skills/crowdsec-service-api"
],
"description": "Operational skill for installing, configuring, operating, and debugging CrowdSec (cscli, LAPI/CAPI, hub, bouncers, WAF/AppSec) across bare-metal, Docker, and Kubernetes.",
"description": "CrowdSec skills: an operational skill (install/configure/operate/debug the engine, cscli, bouncers, WAF across bare-metal/Docker/Kubernetes) and a Service API skill (drive the premium Console cloud API — blocklists, allowlists, firewall integrations, metrics, decisions).",
"author": {
"name": "CrowdSec",
"url": "https://github.com/crowdsecurity"
Expand All @@ -18,6 +19,12 @@
"waf",
"appsec",
"bouncer",
"fail2ban"
"fail2ban",
"console",
"service-api",
"sapi",
"blocklist",
"integration",
"cloud"
]
}
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [0.1.0] - 2026-05-19

### Added
- Initial release of the CrowdSec operational skill for Claude Code.
- Initial release of the CrowdSec operational skill.
- `crowdsec/SKILL.md` covering install, configure, operate, and debug flows for
bare-metal/systemd, Docker, and Kubernetes/Helm.
- Reference docs:
Expand Down
32 changes: 32 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,13 @@ If you are uncertain about any fact, statistic, date, or piece of technical info

## Content structure

The plugin ships **two skills** under `skills/`: `crowdsec` (operational — local
engine/cscli/bouncers/WAF) and `crowdsec-service-api` (the premium Console cloud REST API). Each has
its own router `SKILL.md` and `references/`. The layout below describes the `crowdsec` skill; the
`crowdsec-service-api` layout follows in its own subsection.

### `crowdsec` skill layout

`SKILL.md` is the router — a symptom/intent-indexed table that points into `references/`.
All depth lives in `references/<area>/`, organized by the axis that fits the area:

Expand Down Expand Up @@ -61,6 +68,31 @@ All depth lives in `references/<area>/`, organized by the axis that fits the are
area's organizing axis — update the table above in the *same* change. This section is the
authoritative map of the layout; let it drift and it stops being trustworthy.

### `crowdsec-service-api` skill layout

`SKILL.md` is the router **plus** the "acting on the user's behalf" operating contract (key
resolution, `/info` validation, read-vs-mutate confirm gate). `references/` is organized by **API
resource group** — the axis that fits a REST API — one file each:

| File | Covers |
|---|---|
| `authentication.md` | Key creation, `x-api-key`, key resolution (env → `~/.config/crowdsec/sapi_key`), `/info`, Python SDK pointer. |
| `blocklists.md` | CRUD, add/remove/bulk IPs + expiration, download, subscribers, shares, search. |
| `allowlists.md` | CRUD, items + expiration, subscribers (cross-links the `crowdsec` skill's *local* allowlists). |
| `integrations.md` | Firewall/appliance feeds: create (entity_type/output_format), Basic-auth content pull + pagination, decisions stream, vendor table. |
| `decisions.md` | Org-level decisions + aggregated (short; prefer blocklists). |
| `metrics.md` | `/metrics/remediation` ROI (raw vs computed). |

CTI (the tracker surface — cves/vendors/fingerprints/tags/products/tracker-*) is **deferred to a
future iteration**: it needs a CTI-scoped key (a blocklist/decision key gets `403`). When added,
restore a `cti.md` row here.

Conventions differ from the `crowdsec` skill in two ways: **no platform axis** (the "environment" is
HTTPS, not systemd/docker/k8s — so no per-platform prefixes), and recipes are `curl` the skill runs
on the user's behalf, every mutating one gated behind explicit confirmation. Verification uses
`env: sapi` in the `verified:` block. When you add/rename a resource file here, update this table in
the same change.

## Testing

- **Nothing ships unverified.** Every command and every expected outcome must have been
Expand Down
8 changes: 4 additions & 4 deletions PRIVACY.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
# Privacy Policy

**Plugin:** `crowdsec` (CrowdSec skills for Claude Code)
**Plugin:** `crowdsec` (CrowdSec skills)
**Maintainer:** CrowdSec — <https://github.com/crowdsecurity>
**Last updated:** 2026-06-11

## Summary

This plugin collects no personal data. It is a set of documentation skills and
helper scripts that run **locally** inside Claude Code on your machine. It does not transmit
data CrowdSec or any third party on its own.
helper scripts that run **locally** on your machine. It does not transmit
data to CrowdSec or any third party on its own.

## What the plugin is

Expand All @@ -20,7 +20,7 @@ maintainer never receives any data as a result of you installing or using it.
## Third-party services (acting on the skill's guidance)

The plugin's purpose is to help you operate **your own** CrowdSec deployment.
When you follow its guidance — or run its helper scripts — Claude Code or those
When you follow its guidance — or run its helper scripts — your agent or those
scripts may contact CrowdSec services **using credentials you supply**, for
example:

Expand Down
42 changes: 31 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,28 +2,35 @@

<img src="https://raw.githubusercontent.com/crowdsecurity/crowdsec-docs/main/crowdsec-docs/static/img/crowdsec_logo.png" alt="CrowdSec" width="280">

# CrowdSec skill for Claude Code
# CrowdSec skills

**Install, configure, operate, and debug [CrowdSec](https://doc.crowdsec.net) — straight from your terminal, with Claude doing the heavy lifting.**
**Install, configure, operate, and debug [CrowdSec](https://doc.crowdsec.net) — straight from your terminal, with your coding agent doing the heavy lifting.**

[![Version](https://img.shields.io/badge/version-0.2.3-blue)](.claude-plugin/plugin.json)
[![License: MIT](https://img.shields.io/badge/license-MIT-green)](LICENSE)
[![Claude Code skill](https://img.shields.io/badge/Claude%20Code-skill-8A2BE2)](https://docs.claude.com/en/docs/claude-code/skills)
[![Agent Skills](https://img.shields.io/badge/Agent-Skills-8A2BE2)](https://docs.claude.com/en/docs/claude-code/skills)
[![CrowdSec](https://img.shields.io/badge/CrowdSec-docs-orange)](https://docs.crowdsec.net)

</div>

---

This is an [Agent Skill](https://docs.claude.com/en/docs/claude-code/skills) that turns Claude/Codex/... into a
hands-on CrowdSec operator. Ask it to stand up an engine, wire a bouncer, enable
the WAF, or figure out why nothing's getting blocked — it knows the `cscli`
commands, the config layout, the failure modes, and the safe way through each of
them across **bare-metal/systemd, Docker, OpnSense and Kubernetes/Helm**.
This plugin bundles **two [Agent Skills](https://docs.claude.com/en/docs/claude-code/skills)**:

- **`crowdsec`** — a hands-on CrowdSec operator. Stand up an engine, wire a
bouncer, enable the WAF, or figure out why nothing's getting blocked. It knows
the `cscli` commands, the config layout, the failure modes, and the safe way
through each across **bare-metal/systemd, Docker, OpnSense and Kubernetes/Helm**.
- **`crowdsec-service-api`** — drives the premium **Console Service API** (cloud)
on your behalf with your API key: create and populate blocklists/allowlists,
wire firewall/appliance integrations, pull remediation ROI metrics, and manage
org-level decisions — every state change gated behind an explicit confirmation.


## What it covers

**`crowdsec` (operational):**

| Area | Covered |
|---|---|
| **Install** | bare-metal/systemd · Docker · Kubernetes/Helm · OpnSense · Console enrollment |
Expand All @@ -34,12 +41,22 @@ them across **bare-metal/systemd, Docker, OpnSense and Kubernetes/Helm**.
| **Operate** | health checks & smoke tests · upgrades & rollback · multi-server / remote LAPI / mTLS |
| **Debug** | logs not parsing · no alerts firing · bouncer not blocking · specific errors |

**`crowdsec-service-api` (premium cloud API):**

| Area | Covered |
|---|---|
| **Blocklists** | create · add/remove/bulk IPs (with expiry) · download · share across orgs · subscribe engines/bouncers |
| **Allowlists** | create · items with expiry · subscribe by engine/tag/org |
| **Integrations** | firewall/appliance feeds (Palo Alto, Fortinet, Cisco, F5, Sophos, pfSense/OPNsense…) · paginated Basic-auth content pull |
| **Metrics** | remediation ROI (traffic dropped, bytes/egress saved, attacks prevented) |
| **Decisions** | org-level decisions + aggregated (read/manage) |

## 🚀 Install

The skill loads automatically once installed. Just talk to
Claude about CrowdSec.
your agent about CrowdSec.

**On Claude**
**On Claude Code**

```text
/plugin marketplace add crowdsecurity/crowdsec-skill
Expand Down Expand Up @@ -72,14 +89,17 @@ npx skills add crowdsecurity/crowdsec-skill

## 💬 Example prompts

Once installed, Claude picks the skill up whenever your prompt involves CrowdSec:
Once installed, the agent picks the skill up whenever your prompt involves CrowdSec:

- _"Install CrowdSec on this server and set up the nginx bouncer."_
- _"Deploy CrowdSec in my Kubernetes cluster and enroll it in the Console."_
- _"Enable the WAF / AppSec on my server."_
- _"CrowdSec doesn't detect attacks on my nginx server, why?"_
- _"There's a decision for this IP but it's not being blocked."_
- _"Migrate my fail2ban jails to CrowdSec."_
- _"Create a Console blocklist and push these IPs from my SIEM to it."_ (Service API)
- _"Wire a Palo Alto external dynamic list to my CrowdSec blocklist."_ (Service API)
- _"Show me the remediation ROI metrics for last month."_ (Service API)

## What it does **not** do

Expand Down
125 changes: 125 additions & 0 deletions skills/crowdsec-service-api/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
---
name: crowdsec-service-api
description: Use when the user wants to drive the CrowdSec Console **Service API (SAPI)** — the premium cloud REST API at admin.api.crowdsec.net — to programmatically manage blocklists (add/remove/bulk IPs, share, subscribe engines), allowlists, firewall/appliance integrations (Palo Alto, Fortinet, Cisco, F5, Sophos, pfSense/OPNsense…), remediation ROI metrics, and org-level decisions. Acts on the user's behalf with their API key. This is the cloud/API skill — for the local engine, cscli, and bouncers use the `crowdsec` skill.
verified:
- date: 2026-07-29
version: "1.70.52"
env: sapi
notes: "key resolution + GET /info validation + list recipes against production SAPI"
---

# CrowdSec Service API (SAPI) — cloud blocklist / allowlist / integration automation

SAPI is the **premium** REST API behind the CrowdSec Console. It manages
**cloud-side** objects (private blocklists, allowlists, decisions, firewall integrations)
that then push down to enrolled engines and bouncers. It is **not** the local
engine API — there is no `cscli` here, only HTTPS.

- **Base URL:** `https://admin.api.crowdsec.net/v1`
- **Auth:** `x-api-key: <key>` header on every call. (One exception: the
integration *content* endpoint uses HTTP Basic with credentials minted at
integration creation — see [references/integrations.md](./references/integrations.md).)
- **Interactive API docs:** <https://admin.api.crowdsec.net/v1/docs> · spec
<https://admin.api.crowdsec.net/v1/openapi.json>

## Boundary — this skill vs the `crowdsec` skill

| You want to… | Use |
|---|---|
| Create/manage a **private blocklist** in the cloud, push IPs to it via API | this skill |
| Wire a firewall/appliance (Palo Alto, Fortinet…) to a cloud **integration** | this skill |
| Manage **cloud allowlists**, subscribe engines/tags/orgs to lists | this skill |
| Create/manage **org-level decisions** (targeted or ad-hoc bans, non-IP scopes, per tag/entity) | this skill |
| Pull **remediation ROI metrics** | this skill |
| Install / run / debug the **local engine**, `cscli`, bouncers, WAF | the `crowdsec` skill |
| **Enroll** an engine into the Console (`cscli console enroll`) | the `crowdsec` skill → `references/install/console.md` |
| Configure a **local** allowlist/whitelist on one engine | the `crowdsec` skill → `references/configure/allowlists.md` |

Cloud allowlists/blocklists here only take effect on an engine once that engine
is enrolled **and** subscribed to the list. The enrollment half lives in the
`crowdsec` skill.

## Operating contract

Every call here hits production and can change what subscribed engines enforce.

**1 — Resolve the key.** Never echo it, never write it anywhere but the file
below:
```bash
KEY="${CROWDSEC_SAPI_KEY:-$(cat ~/.config/crowdsec/sapi_key 2>/dev/null)}"
[ -n "$KEY" ] || echo "No key: export CROWDSEC_SAPI_KEY or store it in ~/.config/crowdsec/sapi_key (chmod 0600)"
```

**2 — Validate before acting** — one read call confirms the key and shows *which
tenant* is about to change:
```bash
curl -s -H "x-api-key: $KEY" https://admin.api.crowdsec.net/v1/info
# → {"organization_id":"…","subscription_type":"…","api_key_name":"…"}
```

**3 — Classify read vs mutate.** `GET` / download / `POST …/search` are safe —
run them directly. Every **`POST` / `PATCH` / `DELETE` that changes state**
requires **explicit confirmation first**: present the exact URL and JSON body,
then wait for a yes.

**4 — Extra-danger operations** — spell out the consequence in plain words
*before* the confirm, because subscribed engines **enforce** these lists, so a
change can block or unblock real traffic and is hard to undo:

| Operation | Why it's dangerous |
|---|---|
| `POST …/ips/bulk_overwrite` | Replaces the **entire** blocklist content. |
| `DELETE /blocklists/{id}` · `/allowlists/{id}` · `/integrations/{id}` | Removes the object and everyone's subscription/feed to it. |
| `POST …/ips/delete` | Un-blocks IPs fleet-wide. |
| `POST /decisions` with `target.type: org` | Bans fleet-wide across every enrolled engine in the org. |
| `…/shares` / unshare | Grants/revokes another **organization** access. |
| any `…/subscribers` change | Changes which engines/bouncers enforce the list. |

**5 — Clean up** any object created only to test a recipe. A key that was exposed
anywhere in transit must be rotated.

## Step — Detect the intent

| Cue from user | Go to |
|---|---|
| "test my key", "what org / plan am I on" | [references/authentication.md](./references/authentication.md) |
| "create a blocklist", "push IPs from my SIEM/SOAR", "expire IPs", "share a blocklist with another org", "subscribe my engine to a list" | [references/blocklists.md](./references/blocklists.md) |
| "cloud allowlist via API", "allow my office/CDN across the fleet" | [references/allowlists.md](./references/allowlists.md) |
| "connect Palo Alto / Fortinet / Cisco / F5 / Sophos / pfSense / OPNsense", "firewall integration", "pull IP list in vendor format", "paginate the feed" | [references/integrations.md](./references/integrations.md) |
| "remediation metrics", "how much did CrowdSec save / block", "ROI dashboard" | [references/metrics.md](./references/metrics.md) |
| "org-level decisions via API", "aggregated decisions" | [references/decisions.md](./references/decisions.md) |

## Step — curl cheat sheet

All assume `KEY` is set (see operating contract). `jq` optional for readability.

| Purpose | Command |
|---|---|
| Who am I / validate key | `curl -s -H "x-api-key: $KEY" $B/info` |
| List blocklists | `curl -s -H "x-api-key: $KEY" "$B/blocklists"` |
| List allowlists | `curl -s -H "x-api-key: $KEY" "$B/allowlists"` |
| List integrations | `curl -s -H "x-api-key: $KEY" "$B/integrations"` |
| List / find decisions | `curl -s -H "x-api-key: $KEY" "$B/decisions"` · `…?ips=1.2.3.4` |
| Remediation metrics | `curl -s -H "x-api-key: $KEY" "$B/metrics/remediation?start_date=$FROM&end_date=$TO"` |
| Add IPs to a blocklist *(mutating — confirm)* | `curl -s -H "x-api-key: $KEY" -H 'Content-Type: application/json' -X POST "$B/blocklists/$ID/ips" -d '{"ips":["1.2.3.4"]}'` |
| Create a decision *(mutating — confirm)* | `curl -s -H "x-api-key: $KEY" -H 'Content-Type: application/json' -X POST "$B/decisions" -d '{"duration":"4h","origin":"cscli","scenario":"manual","scope":"Ip","type":"ban","value":"1.2.3.4","target":{"type":"org","value":"<org>"}}'` |

where `B=https://admin.api.crowdsec.net/v1`.

## Hard don'ts

- Don't send a mutating call before the URL + body have been shown and approved
(see operating contract §3–4).
- Don't use `…/ips/bulk_overwrite` when the user means "add a few IPs" — that's
`…/ips`. `bulk_overwrite` wipes the list first.
- Don't print, log, or persist the API key anywhere but
`~/.config/crowdsec/sapi_key`. Resolve it from there or from the env var only.
- Don't assume a cloud allowlist/blocklist is enforced just because the API call
succeeded — the engine must be enrolled and subscribed, and it pulls on a poll
cycle (verify locally via the `crowdsec` skill).

## Docs

Canonical: <https://docs.crowdsec.net/u/console/service_api/getting_started>. Each
`references/` file cites the specific upstream page and the live OpenAPI operation
it derives from.
Loading
Loading