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
42 changes: 41 additions & 1 deletion core/connectors/runtime/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -136,8 +136,10 @@ Connector runtime has an optional HTTP API that can be enabled by setting the `e
```toml
[http] # Optional HTTP API configuration
enabled = true
# Loopback on purpose: the configuration endpoints return plugin credentials in
# plaintext. Set api_key in the same edit if you move this off loopback.
address = "127.0.0.1:8081"
api_key = "" # Optional API key for authentication to be passed as `api-key` header
api_key = "" # Optional API key for authentication to be passed as `api-key` header; empty disables authentication

[http.cors] # Optional CORS configuration for HTTP API
enabled = false
Expand All @@ -158,6 +160,40 @@ cert_file = "core/certs/iggy_cert.pem"
key_file = "core/certs/iggy_key.pem"
```

> [!IMPORTANT]
> **Treat this API as privileged. It reads and it writes.**
>
> The configuration endpoints return plugin configuration exactly as stored,
> credentials included - a database connection string, an S3 secret key, a
> webhook signing secret. There is no redaction layer anywhere in the runtime.
>
> The exposure is not limited to disclosure. Publishing a configuration with
> `POST /{sinks,sources}/{key}/configs` and then calling `POST .../restart` is
> enough to repoint a connector at a destination of the caller's choosing,
> because `restart` re-reads the stored configuration and starts the connector
> from it. The runtime then forwards your topic data using its own Iggy
> credentials, and the stored plugin `path` is `dlopen`ed on the next start.
> `PUT .../configs/active` and `DELETE .../configs` sit behind the same key.
>
> `api_key` is empty by default, which means authentication is **off** by
> default. Only `/` and `/health` are exempt once it is set, so everything above
> sits behind that one empty string, and the loopback default `address` is what
> confines it to local processes.
>
> Three ways that containment goes away:
>
> - **Moving `address` off loopback.** Set `api_key` in the same edit. The
> runtime warns at startup when the address resolves beyond loopback with no
> key configured, but nothing prevents it.
> - **Enabling `[http.cors]`.** It ships `allowed_origins = ["*"]`, which becomes
> `AllowOrigin::any()`, and the CORS layer wraps *outside* authentication. A
> browser is a local process, so with CORS enabled and no key, any page the
> operator visits can read the configuration endpoints cross-origin. Setting
> `api_key` closes it, since an attacker's page cannot supply the header.
> - **Leaving `http.tls.enabled = false`.** It ships disabled, so the `api-key`
> header and the responses carrying your credentials both travel in cleartext.
> Enable TLS alongside `api_key` whenever this API leaves loopback.

Currently, it does expose the following endpoints:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

list is missing every mutating route: POST /sinks/{key}/restart, POST /sources/{key}/restart, and DELETE on both configs routes. restart appears nowhere in this file, and the DELETE lines at 127-128 belong to the config provider section. pre-existing, but a GET/POST/PUT-only list right under the new notice is what makes the read-only framing look right.


- `GET /`: welcome message.
Expand All @@ -168,19 +204,23 @@ Currently, it does expose the following endpoints:
- `GET /sinks/{key}`: sink details.
- `GET /sinks/{key}/configs`: list of configuration versions for the sink.
- `POST /sinks/{key}/configs`: add a new configuration version for the sink.
- `DELETE /sinks/{key}/configs`: delete configuration versions for the sink.
- `GET /sinks/{key}/configs/{version}`: configuration details for a specific version.
- `GET /sinks/{key}/configs/active`: active configuration details.
- `PUT /sinks/{key}/configs/active`: activate a specific configuration version for the sink.
- `GET /sinks/{key}/configs/plugin`: sink plugin config, including the optional `format` query parameter to specify the config format.
- `POST /sinks/{key}/restart`: stop the sink and start it again from its stored active configuration.
- `GET /sinks/{key}/transforms`: sink transforms to be applied to the fields.
- `GET /sources`: list of sources.
- `GET /sources/{key}`: source details.
- `GET /sources/{key}/configs`: list of configuration versions for the source.
- `POST /sources/{key}/configs`: add a new configuration version for the source.
- `DELETE /sources/{key}/configs`: delete configuration versions for the source.
- `GET /sources/{key}/configs/{version}`: configuration details for a specific version.
- `GET /sources/{key}/configs/active`: active configuration details.
- `PUT /sources/{key}/configs/active`: activate a specific configuration version for the source.
- `GET /sources/{key}/configs/plugin`: source plugin config, including the optional `format` query parameter to specify the config format.
- `POST /sources/{key}/restart`: stop the source and start it again from its stored active configuration.
- `GET /sources/{key}/transforms`: source transforms to be applied to the fields.

## Telemetry
Expand Down
4 changes: 3 additions & 1 deletion core/connectors/runtime/config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,10 @@

[http] # Optional HTTP API configuration
enabled = true
# Loopback on purpose: the configuration endpoints return plugin credentials in
# plaintext. Set api_key in the same edit if you move this off loopback.
address = "127.0.0.1:8081"
api_key = "" # Optional API key for authentication to be passed as `api-key` header
api_key = "" # Optional API key for authentication to be passed as `api-key` header; empty disables authentication

[http.cors] # Optional CORS configuration for HTTP API
enabled = false
Expand Down
5 changes: 4 additions & 1 deletion core/connectors/runtime/example_config/config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,11 @@

[http] # Optional HTTP API configuration
enabled = true
# Loopback on purpose: the configuration endpoints return plugin credentials in
# plaintext and also accept writes. Set api_key in the same edit if you move
# this off loopback, and http.tls unless cleartext is acceptable.
address = "127.0.0.1:8081"
api_key = "" # Optional API key for authentication to be passed as `api-key` header
api_key = "" # Optional API key for authentication to be passed as `api-key` header; empty disables authentication

[http.cors] # Optional CORS configuration for HTTP API
enabled = false
Expand Down
Loading
Loading