-
Notifications
You must be signed in to change notification settings - Fork 41
feat(starr): add mTLS client certificate support for all starr apps #556
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
- Add TLSClientCert, TLSClientKey, and TLSCACert fields to StarrConfig - Implement certificate loading and validation in validateApp() - Support custom CA certificates for private certificate authorities - Maintain backward compatibility when mTLS fields are not configured - Add docker volume mount note for certificate directories - Update all example configurations with mTLS options
- Add static error ErrInvalidCA for wrapped error handling (err113) - Extract configureTLS helper function to reduce complexity (funlen) - Move embedded field to top of struct declaration - Align all struct tags in columns (tagalign) - Add nolint comment for unavoidable line length
| app, conf.URL, expandHomedir(conf.TLSCACert), err) | ||
| } | ||
|
|
||
| caCertPool := x509.NewCertPool() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| caCertPool := x509.NewCertPool() | |
| tlsConfig.RootCA = x509.NewCertPool() |
Can you just set this directly here? (I'm not sure if .RootCAs is an interface or not.)
| ValidSSL bool `json:"valid_ssl" toml:"valid_ssl" xml:"valid_ssl" yaml:"valid_ssl"` | ||
| Timeout cnfg.Duration `json:"timeout" toml:"timeout" xml:"timeout" yaml:"timeout"` | ||
| starr.Config | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Extra whitespace you don't need here.
| TLSClientCert string `json:"tls_client_cert" toml:"tls_client_cert" xml:"tls_client_cert" yaml:"tls_client_cert"` //nolint:lll | ||
| TLSClientKey string `json:"tls_client_key" toml:"tls_client_key" xml:"tls_client_key" yaml:"tls_client_key"` | ||
| TLSCACert string `json:"tls_ca_cert" toml:"tls_ca_cert" xml:"tls_ca_cert" yaml:"tls_ca_cert"` | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you consider this instead? You'll have to make a few other changes, but I think this will be a bit cleaner in the end.
| TLSClientCert string `json:"tls_client_cert" toml:"tls_client_cert" xml:"tls_client_cert" yaml:"tls_client_cert"` //nolint:lll | |
| TLSClientKey string `json:"tls_client_key" toml:"tls_client_key" xml:"tls_client_key" yaml:"tls_client_key"` | |
| TLSCACert string `json:"tls_ca_cert" toml:"tls_ca_cert" xml:"tls_ca_cert" yaml:"tls_ca_cert"` | |
| } | |
| TLS *ClientTLS `json:"tls" toml:"tls" xml:"tls" yaml:"tls"` | |
| } | |
| type ClientTLS struct { | |
| Cert string `json:"client_cert" toml:"client_cert" xml:"client_cert" yaml:"client_cert"` | |
| Key string `json:"client_key" toml:"client_key" xml:"client_key" yaml:"client_key"` | |
| CA string `json:"ca_cert" toml:"ca_cert" xml:"ca_cert" yaml:"ca_cert"` | |
| } |
| tlsConfig := &tls.Config{InsecureSkipVerify: !conf.ValidSSL} //nolint:gosec | ||
|
|
||
| // Add mTLS if certificates are configured | ||
| if conf.TLSClientCert != "" && conf.TLSClientKey != "" { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| if conf.TLSClientCert != "" && conf.TLSClientKey != "" { | |
| if conf.TLSClientCert != "" || conf.TLSClientKey != "" { |
I usually do an "or" on these two variables when dealing with SSL. In case a user sets one, they'll get an error. Instead of nothing.
Summary
This PR adds mutual TLS (mTLS) client certificate authentication support to Unpackerr, enabling secure communication with Starr applications (Sonarr, Radarr, Lidarr, Readarr, Whisparr) that are protected behind reverse proxies requiring client certificates.
Testing
Configuration Example
TOML Configuration
Docker Compose
Implementation Details
The implementation modifies the HTTP transport configuration to include TLS client certificates when provided: