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
1,175 changes: 1,119 additions & 56 deletions Cargo.lock

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
[workspace]
resolver = "3"
members = [
"rpc-log-plugin",
"event-plugin",
"metrics-plugin"
]
Expand Down
26 changes: 20 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,16 @@ A growing collection of plugins for [Core Lightning](https://github.com/Elements
Running a Core Lightning node often means connecting it to the rest of your infrastructure: monitoring, event pipelines,
dashboards, alerts, and more. This repository keeps those integrations small, composable, and open source.

Each plugin lives in its own workspace crate and can be built, configured, and run independently. There are two plugins
Each plugin lives in its own workspace crate and can be built, configured, and run independently. There are three plugins
today—and the collection is designed to grow.

## Plugins

| Plugin | What it does | Integrates with |
|--------------------------------------|------------------------------------------------------------------|-----------------|
| [`event-plugin`](./event-plugin) | Publishes CLN events and hook data to a message broker | RabbitMQ |
| [`metrics-plugin`](./metrics-plugin) | Exposes node, funds, liquidity, channel, peer, and event metrics | Prometheus |
| Plugin | What it does | Integrates with |
|--------------------------------------|--------------------------------------------------------------------|----------------------|
| [`event-plugin`](./event-plugin) | Publishes CLN events and hook data to a message broker | RabbitMQ |
| [`metrics-plugin`](./metrics-plugin) | Exposes node, funds, liquidity, channel, peer, and event metrics | Prometheus |
| [`rpc-log-plugin`](./rpc-log-plugin) | Stores selected, sanitized RPC requests as individual JSON objects | Google Cloud Storage |

### Event plugin

Expand All @@ -45,14 +46,26 @@ Use it as the foundation for dashboards, alerts, and day-to-day node monitoring.

[Configuration and metric reference →](./metrics-plugin/README.md)

### RPC log plugin

Keep a durable audit trail of requests made to your node. The plugin observes selected calls through CLN's
`rpc_command` hook, redacts known sensitive fields, and uploads each request as a separate JSON object to Google Cloud
Storage.

It logs `checkrune` by default, making it useful for auditing rune-authorized calls received through the commando
plugin. The method list is configurable, and rune comments in the form `operator#Name` can identify callers without
retaining the rune itself.

[Configuration, security, and bucket setup →](./rpc-log-plugin/README.md)

## Quick start

### Prerequisites

- A working Core Lightning node
- A recent stable Rust toolchain
- Protocol Buffers compiler (`protoc`) to build `event-plugin`
- RabbitMQ for `event-plugin`, or Prometheus for `metrics-plugin`
- RabbitMQ for `event-plugin`, Prometheus for `metrics-plugin`, or a Google Cloud Storage bucket for `rpc-log-plugin`

### Build

Expand All @@ -69,6 +82,7 @@ The executables are created in `target/release/`:
```text
target/release/event-plugin
target/release/metrics-plugin
target/release/rpc-log-plugin
```

You can also build only the plugin you need:
Expand Down
18 changes: 18 additions & 0 deletions rpc-log-plugin/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
[package]
name = "rpc-log-plugin"
version = "0.1.0"
edition = "2024"
license.workspace = true

[dependencies]
cln-plugin = { version = "0.7" }
tokio = { version = "1", features = ["full"] }
anyhow = { version = "1" }
serde = { version = "1", features = ["derive"] }
serde_json = { version = "1" }
cln-rpc = { version = "0.7" }
google-cloud-storage = "1"
google-cloud-auth = { version = "1", default-features = false }
time = { version = "0.3", features = ["formatting"] }
uuid = { version = "1", features = ["v4"] }
base64 = "0.23"
158 changes: 158 additions & 0 deletions rpc-log-plugin/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
# RPC Log Plugin

The `rpc-log-plugin` records Core Lightning RPC requests as JSON objects in Google Cloud Storage.

It is useful when you need a durable audit trail for debugging, operational analysis, or investigating how a node is
being used. The plugin observes selected calls through the `rpc_command` hook, replaces values of known sensitive
fields with `"***"`, and uploads each request as a separate object.

Objects are stored under the following prefix:

```text
rpc/<RFC3339 timestamp>-<UUID>.json
```

The UUID makes every object name unique, so the plugin never needs to overwrite an existing log.

## Security model

The plugin recursively redacts named JSON fields whose keys contain one of the configured sensitive terms, including
`rune`, `hsmsecret`, `preimage`, `payment_secret`, `private_key`, `seed`, and `mnemonic`. Matching is
case-insensitive.

This is a defensive filter, not a complete data-loss-prevention system. In particular, positional RPC parameters do
not contain field names and therefore cannot be identified by the current sanitizer. Unknown plugin RPCs may also use
different names for sensitive values. Review the resulting data before enabling the plugin on a production node.

For least privilege, grant the plugin only the `roles/storage.objectCreator` role on its bucket. This allows it to
create objects but not read, list, delete, or overwrite them. Bucket creation must be performed separately by a
deployment or administrator identity.

## Build

From the repository root:

```bash
cargo build --release --package rpc-log-plugin
```

The executable is created at:

```text
target/release/rpc-log-plugin
```

## Create the bucket

The following commands must be run with an identity that can create buckets and manage bucket IAM policies:

```bash
PROJECT_ID="my-project"
BUCKET="my-cln-rpc-logs"
REGION="europe-west1"
WRITER_SA="cln-log-writer@${PROJECT_ID}.iam.gserviceaccount.com"

gcloud services enable storage.googleapis.com \
--project="${PROJECT_ID}"

gcloud storage buckets create "gs://${BUCKET}" \
--project="${PROJECT_ID}" \
--location="${REGION}" \
--uniform-bucket-level-access

gcloud storage buckets add-iam-policy-binding "gs://${BUCKET}" \
--member="serviceAccount:${WRITER_SA}" \
--role="roles/storage.objectCreator"
```

Bucket names are globally unique. Choose a different value if the requested name is already taken.

The plugin accepts the plain bucket ID through `log-bucket`, for example `my-cln-rpc-logs`. Do not pass `gs://` or the
full `projects/_/buckets/...` resource name; the plugin adds the resource-name prefix internally.

## Authentication

The Google Cloud client uses Application Default Credentials (ADC). No credential path is configured in the plugin.

### GKE

Use Workload Identity Federation for GKE and associate the pod's Kubernetes service account with the Google service
account that received `roles/storage.objectCreator`. The pod then obtains short-lived credentials automatically; do
not mount a downloaded service-account key in the container.

### Local development

Authenticate ADC with the Google Cloud CLI:

```bash
gcloud auth application-default login
```

The authenticated development identity must have permission to create objects in the selected bucket.

## Configure Core Lightning

Add the plugin and bucket ID to `lightningd`'s configuration:

```ini
plugin=/absolute/path/to/target/release/rpc-log-plugin
log-bucket=my-cln-rpc-logs
log-rpc-list=checkrune,commando,pay
```

Alternatively, pass the same options on the command line:

```bash
lightningd \
--plugin=/absolute/path/to/target/release/rpc-log-plugin \
--log-bucket=my-cln-rpc-logs \
--log-rpc-list=checkrune,commando,pay
```

The bucket must already exist when RPC requests are logged. Authentication failures, missing buckets, and upload
errors are returned by the hook, so verify the setup outside production before relying on it.

### Select RPC methods

`log-rpc-list` controls which RPC methods are logged. The default is `checkrune`. Use a comma-separated list to select
more than one method:

```ini
log-rpc-list=checkrune,commando,pay
```

Whitespace around method names is ignored. Method names must otherwise match exactly. Calls to methods not present in
this list continue normally without being uploaded.

## Log format

Each uploaded object contains one JSON document:

```json
{
"method": "pay",
"request_id": 42,
"body": {
"bolt11": "lnbc...",
"payment_secret": "***"
},
"caller": "Name",
"peer_id": "02..."
}
```

The `caller` field contains the value of the first `operator#<name>` comment found in a rune passed through named JSON
parameters. The caller field exists only if the request has rune, the rune can be decoded and has such tag.

Create a rune carrying this comment with:

```bash
lightning-cli createrune -k restrictions='[["operator#Name"]]'
```

When that rune is supplied as a named `rune` parameter, the plugin records `"Name"` in `caller` and redacts the rune
itself from `body`. The comment is descriptive metadata and does not restrict authorization.

The request body may still contain financially or personally sensitive information that is not covered by the danger
field list, such as invoices, labels, descriptions, addresses, routes, and payment hashes. Restrict access to the
bucket and configure retention and deletion policies appropriate for your environment.
Loading
Loading