fix(inputs.x509_cert): Add config to left-pad serial number to 128-bits (#16447)

This commit is contained in:
Dane Strandboge 2025-02-04 09:57:13 -06:00 committed by GitHub
parent 1329ae89ee
commit 7f1c5d31aa
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 32 additions and 4 deletions

View File

@ -39,6 +39,9 @@ See the [CONFIGURATION.md][CONFIGURATION.md] for more details.
## Only output the leaf certificates and omit the root ones.
# exclude_root_certs = false
## Pad certificate serial number with zeroes to 128-bits.
# pad_serial_with_zeroes = false
## Optional TLS Config
# tls_ca = "/etc/telegraf/ca.pem"
# tls_cert = "/etc/telegraf/cert.pem"

View File

@ -19,6 +19,9 @@
## Only output the leaf certificates and omit the root ones.
# exclude_root_certs = false
## Pad certificate serial number with zeroes to 128-bits.
# pad_serial_with_zeroes = false
## Optional TLS Config
# tls_ca = "/etc/telegraf/ca.pem"
# tls_cert = "/etc/telegraf/cert.pem"

View File

@ -44,6 +44,7 @@ type X509Cert struct {
Timeout config.Duration `toml:"timeout"`
ServerName string `toml:"server_name"`
ExcludeRootCerts bool `toml:"exclude_root_certs"`
PadSerial bool `toml:"pad_serial_with_zeroes"`
Log telegraf.Logger `toml:"-"`
common_tls.ClientConfig
proxy.TCPProxy
@ -132,7 +133,7 @@ func (c *X509Cert) Gather(acc telegraf.Accumulator) error {
for i, cert := range certs {
fields := getFields(cert, now)
tags := getTags(cert, location.String())
tags := c.getTags(cert, location.String())
// Extract the verification result
err := results[i]
@ -215,7 +216,7 @@ func (c *X509Cert) Gather(acc telegraf.Accumulator) error {
func (c *X509Cert) processCertificate(certificate *x509.Certificate, opts x509.VerifyOptions) error {
chains, err := certificate.Verify(opts)
if err != nil {
c.Log.Debugf("Invalid certificate %v", certificate.SerialNumber.Text(16))
c.Log.Debugf("Invalid certificate %v", c.getSerialNumberString(certificate))
c.Log.Debugf(" cert DNS names: %v", certificate.DNSNames)
c.Log.Debugf(" cert IP addresses: %v", certificate.IPAddresses)
c.Log.Debugf(" cert subject: %v", certificate.Subject)
@ -466,11 +467,11 @@ func getFields(cert *x509.Certificate, now time.Time) map[string]interface{} {
return fields
}
func getTags(cert *x509.Certificate, location string) map[string]string {
func (c *X509Cert) getTags(cert *x509.Certificate, location string) map[string]string {
tags := map[string]string{
"source": location,
"common_name": cert.Subject.CommonName,
"serial_number": cert.SerialNumber.Text(16),
"serial_number": c.getSerialNumberString(cert),
"signature_algorithm": cert.SignatureAlgorithm.String(),
"public_key_algorithm": cert.PublicKeyAlgorithm.String(),
}
@ -524,6 +525,13 @@ func (c *X509Cert) collectCertURLs() []*url.URL {
return urls
}
func (c *X509Cert) getSerialNumberString(cert *x509.Certificate) string {
if c.PadSerial {
return fmt.Sprintf("%016x", cert.SerialNumber)
}
return cert.SerialNumber.Text(16)
}
func init() {
inputs.Add("x509_cert", func() telegraf.Input {
return &X509Cert{

View File

@ -482,6 +482,20 @@ func TestServerName(t *testing.T) {
}
}
func TestCertificateSerialNumberRetainsLeadingZeroes(t *testing.T) {
bi := &big.Int{}
bi.SetString("123456789abcdef", 16)
plugin := &X509Cert{}
certificate := &x509.Certificate{
SerialNumber: bi,
}
require.Equal(t, "123456789abcdef", plugin.getSerialNumberString(certificate))
plugin.PadSerial = true
require.Equal(t, "0123456789abcdef", plugin.getSerialNumberString(certificate))
}
// Bases on code from
// https://medium.com/@shaneutt/create-sign-x509-certificates-in-golang-8ac4ae49f903
func TestClassification(t *testing.T) {