[otlploggrpc] Resolve mTLS certificate and key signal overrides independently #9139
Description
Observed behavior
With valid PEM files:
OTEL_EXPORTER_OTLP_CLIENT_CERTIFICATE=/path/client.pem
OTEL_EXPORTER_OTLP_LOGS_CLIENT_KEY=/path/client.key
No client TLS configuration is loaded and no diagnostic is generated. Swapping the scopes (Logs certificate, generic key) has the same result.
When a complete generic certificate/key pair exists but only OTEL_EXPORTER_OTLP_LOGS_CLIENT_CERTIFICATE overrides the certificate, the override is ignored and the generic pair is loaded. The probe used a missing Logs-specific certificate path to make the ignored selection unambiguous: the valid generic pair was loaded without any warning about the selected Logs path.
Current paired resolution requires both files to come from the same scope. Public documentation independently describes each Logs-specific override.
Specification and strength
The exporter configuration specification says each option MUST be overridable by a signal-specific option. Client key and certificate are distinct configuration options, so their scope overrides must resolve independently before loading the resulting PEM pair.
Reproduction and acceptance
Temporary TestAuditConfigTLSAndMTLS subtests under -race used valid existing certificate/key fixtures copied into temporary files. They confirmed both mixed-scope pairs are ignored and a single Logs certificate override is ignored when a generic pair exists. The existing complete-scope mTLS integration test passes.
Resolve each of certificate and private key with Logs-specific precedence and generic fallback, then validate/load the selected pair. Do not silently substitute a generic pair for an explicitly selected Logs-specific file. Cover mixed scopes, single overrides, invalid/missing selected files, and complete-pair precedence.
Searches for client certificate/key, certificate precedence, and CLIENT_KEY found no existing matching issue; closed #6661 covered trusted server certificates, not client-file precedence.
Implementation reviewed: 6b3ec1621285c44b321ba65b972f453213461fc6. Specification: 1d77cd02d8a2f4ac7d056b3d771126f807e28cba; wire: 4d394fcbf35e65d932e8dda58c602e7d8d446e56. This finding is from the audit of #9102; no implementation changes were made.
Copy-pastable regression reproduction
In a checkout of the implementation commit above, save the following as exporters/otlp/otlplog/otlploggrpc/audit_compliance_test.go. It uses existing same-package test helpers where indicated. Then run:
make test/exporters/otlp/otlplog/otlploggrpc ARGS='-race -count=1 -run ^TestReproCompliance$' TIMEOUT=120The test asserts the intended behavior and fails on the audited baseline. The separately executed observation probes passed because they asserted the current behavior.
package otlploggrpc
import (
"os"
"path/filepath"
"testing"
)
func TestReproCompliance(t *testing.T) {
dir := t.TempDir()
cert := filepath.Join(dir, "cert.pem")
key := filepath.Join(dir, "key.pem")
// Existing same-package test fixtures; parsing does not verify expiry.
if err:=os.WriteFile(cert, []byte(weakCertificate), 0600); err!=nil {t.Fatal(err)}
if err:=os.WriteFile(key, []byte(weakPrivateKey), 0600); err!=nil {t.Fatal(err)}
t.Setenv("OTEL_EXPORTER_OTLP_CLIENT_CERTIFICATE", cert)
t.Setenv("OTEL_EXPORTER_OTLP_LOGS_CLIENT_CERTIFICATE", "")
t.Setenv("OTEL_EXPORTER_OTLP_CLIENT_KEY", "")
t.Setenv("OTEL_EXPORTER_OTLP_LOGS_CLIENT_KEY", key)
cfg := newConfig(nil)
if cfg.tlsCfg.Value==nil || len(cfg.tlsCfg.Value.Certificates)!=1 {
t.Fatal("mixed-scope certificate/key should resolve one client certificate")
}
}
Activity
fix(exporters/otlp): resolve log exporter mTLS cert and key overrides…
fix(exporters/otlp): resolve log exporter mTLS cert and key overrides…