mirror of
https://github.com/kerberos-io/agent.git
synced 2026-08-23 15:08:32 +00:00
Add RTSPS support and configuration options for secure camera streams
- Updated README.md to include instructions for using RTSPS camera URLs. - Enhanced gortsplib.go to support insecure TLS configuration for self-signed certificates. - Added unit tests for RTSPS TLS configuration in gortsplib_test.go.
This commit is contained in:
16
README.md
16
README.md
@@ -189,6 +189,17 @@ Next to attaching the configuration file, it is also possible to override the co
|
||||
-e AGENT_CAPTURE_CONTINUOUS=true \
|
||||
-d --restart=always kerberos/agent:latest
|
||||
|
||||
### Secure camera streams (RTSPS)
|
||||
|
||||
The Agent accepts `rtsps://` camera URLs. Do not use `srtsp://`; RTSPS is RTSP over TLS. For a Bosch FLEXIDOME micro 3100i, enable **Secure RTSP** under **Network > Network Services** and use port `9554`:
|
||||
|
||||
```bash
|
||||
AGENT_CAPTURE_IPCAMERA_RTSP='rtsps://username:password@camera.example:9554/?inst=1'
|
||||
AGENT_CAPTURE_IPCAMERA_SUB_RTSP='rtsps://username:password@camera.example:9554/?inst=2'
|
||||
```
|
||||
|
||||
Certificate verification is enabled by default. The URL hostname must match the camera certificate. For a private CA or self-signed camera certificate, mount its CA certificate and set `SSL_CERT_FILE` to that PEM file. As a temporary fallback, `AGENT_CAPTURE_IPCAMERA_RTSPS_INSECURE=true` disables certificate verification for camera streams only.
|
||||
|
||||
| Name | Description | Default Value |
|
||||
| --------------------------------------- | ----------------------------------------------------------------------------------------------- | ------------------------------ |
|
||||
| `LOG_LEVEL` | Level for logging, could be "info", "warning", "debug", "error" or "fatal". | "info" |
|
||||
@@ -208,8 +219,9 @@ Next to attaching the configuration file, it is also possible to override the co
|
||||
| `AGENT_TIME` | Enable the timetable for Kerberos Agent | "false" |
|
||||
| `AGENT_TIMETABLE` | A (weekly) time table to specify when to make recordings "start1,end1,start2,end2;start1.. | "" |
|
||||
| `AGENT_REGION_POLYGON` | A single polygon set for motion detection: "x1,y1;x2,y2;x3,y3;... | "" |
|
||||
| `AGENT_CAPTURE_IPCAMERA_RTSP` | Full-HD RTSP endpoint to the camera you're targetting. | "" |
|
||||
| `AGENT_CAPTURE_IPCAMERA_SUB_RTSP` | Sub-stream RTSP endpoint used for livestreaming (WebRTC). | "" |
|
||||
| `AGENT_CAPTURE_IPCAMERA_RTSP` | Full-HD RTSP or RTSPS endpoint for the target camera. | "" |
|
||||
| `AGENT_CAPTURE_IPCAMERA_SUB_RTSP` | RTSP or RTSPS sub-stream endpoint used for livestreaming (WebRTC). | "" |
|
||||
| `AGENT_CAPTURE_IPCAMERA_RTSPS_INSECURE` | Disable RTSPS camera certificate verification; use only when a trusted CA cannot be installed. | "false" |
|
||||
| `AGENT_CAPTURE_IPCAMERA_BASE_WIDTH` | Force a specific width resolution for live view processing. | "" |
|
||||
| `AGENT_CAPTURE_IPCAMERA_BASE_HEIGHT` | Force a specific height resolution for live view processing. | "" |
|
||||
| `AGENT_CAPTURE_IPCAMERA_ONVIF` | Mark as a compliant ONVIF device. | "" |
|
||||
|
||||
@@ -8,9 +8,11 @@ import "C"
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"errors"
|
||||
"fmt"
|
||||
"image"
|
||||
"os"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"sync"
|
||||
@@ -38,6 +40,16 @@ import (
|
||||
|
||||
var tracer = otel.Tracer("github.com/kerberos-io/agent/machinery/src/capture")
|
||||
|
||||
const rtspsInsecureEnv = "AGENT_CAPTURE_IPCAMERA_RTSPS_INSECURE"
|
||||
|
||||
func rtspsTLSConfig() *tls.Config {
|
||||
if os.Getenv(rtspsInsecureEnv) != "true" {
|
||||
return nil
|
||||
}
|
||||
|
||||
return &tls.Config{InsecureSkipVerify: true} // #nosec G402 -- explicit opt-in for cameras with self-signed certificates
|
||||
}
|
||||
|
||||
// Implements the RTSPClient interface.
|
||||
type Golibrtsp struct {
|
||||
RTSPClient
|
||||
@@ -322,6 +334,7 @@ func (g *Golibrtsp) Connect(ctx context.Context, ctxOtel context.Context) (err e
|
||||
g.Client = gortsplib.Client{
|
||||
RequestBackChannels: false,
|
||||
Protocol: &protocol,
|
||||
TLSConfig: rtspsTLSConfig(),
|
||||
// Route gortsplib's packet-loss / decode-error reporting through our
|
||||
// structured logger with stream context (replaces its plain stdout
|
||||
// logging). These hooks are what let us tell whether the camera is
|
||||
@@ -599,6 +612,7 @@ func (g *Golibrtsp) ConnectBackChannel(ctx context.Context, ctxRunAgent context.
|
||||
g.Client = gortsplib.Client{
|
||||
RequestBackChannels: true,
|
||||
Protocol: &protocol,
|
||||
TLSConfig: rtspsTLSConfig(),
|
||||
}
|
||||
// parse URL
|
||||
u, err := base.ParseURL(g.Url)
|
||||
|
||||
22
machinery/src/capture/gortsplib_test.go
Normal file
22
machinery/src/capture/gortsplib_test.go
Normal file
@@ -0,0 +1,22 @@
|
||||
package capture
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestRTSPSTLSConfig(t *testing.T) {
|
||||
t.Run("verifies certificates by default", func(t *testing.T) {
|
||||
t.Setenv(rtspsInsecureEnv, "")
|
||||
|
||||
if got := rtspsTLSConfig(); got != nil {
|
||||
t.Fatalf("rtspsTLSConfig() = %#v, want nil", got)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("allows explicit insecure mode", func(t *testing.T) {
|
||||
t.Setenv(rtspsInsecureEnv, "true")
|
||||
|
||||
got := rtspsTLSConfig()
|
||||
if got == nil || !got.InsecureSkipVerify {
|
||||
t.Fatalf("rtspsTLSConfig() = %#v, want InsecureSkipVerify enabled", got)
|
||||
}
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user