Skip to content

Commit

Permalink
Add additional tags for x509 Input Plugin (influxdata#6686)
Browse files Browse the repository at this point in the history
  • Loading branch information
lawliet89 authored and Mathieu Lecarme committed Apr 17, 2020
1 parent 1323c73 commit 359c4f6
Show file tree
Hide file tree
Showing 3 changed files with 91 additions and 15 deletions.
6 changes: 6 additions & 0 deletions plugins/inputs/x509_cert/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,12 @@ file or network connection.
- province
- locality
- verification
- serial_number
- signature_algorithm
- public_key_algorithm
- issuer_common_name
- issuer_serial_number
- san
- fields:
- verification_code (int)
- verification_error (string)
Expand Down
44 changes: 29 additions & 15 deletions plugins/inputs/x509_cert/x509_cert.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import (
"bytes"
"crypto/tls"
"crypto/x509"
"crypto/x509/pkix"
"encoding/pem"
"fmt"
"io/ioutil"
Expand Down Expand Up @@ -136,28 +135,43 @@ func getFields(cert *x509.Certificate, now time.Time) map[string]interface{} {
return fields
}

func getTags(subject pkix.Name, location string) map[string]string {
func getTags(cert *x509.Certificate, location string) map[string]string {
tags := map[string]string{
"source": location,
"common_name": subject.CommonName,
"source": location,
"common_name": cert.Subject.CommonName,
"serial_number": cert.SerialNumber.Text(16),
"signature_algorithm": cert.SignatureAlgorithm.String(),
"public_key_algorithm": cert.PublicKeyAlgorithm.String(),
}

if len(subject.Organization) > 0 {
tags["organization"] = subject.Organization[0]
if len(cert.Subject.Organization) > 0 {
tags["organization"] = cert.Subject.Organization[0]
}
if len(subject.OrganizationalUnit) > 0 {
tags["organizational_unit"] = subject.OrganizationalUnit[0]
if len(cert.Subject.OrganizationalUnit) > 0 {
tags["organizational_unit"] = cert.Subject.OrganizationalUnit[0]
}
if len(subject.Country) > 0 {
tags["country"] = subject.Country[0]
if len(cert.Subject.Country) > 0 {
tags["country"] = cert.Subject.Country[0]
}
if len(subject.Province) > 0 {
tags["province"] = subject.Province[0]
if len(cert.Subject.Province) > 0 {
tags["province"] = cert.Subject.Province[0]
}
if len(subject.Locality) > 0 {
tags["locality"] = subject.Locality[0]
if len(cert.Subject.Locality) > 0 {
tags["locality"] = cert.Subject.Locality[0]
}

tags["issuer_common_name"] = cert.Issuer.CommonName
tags["issuer_serial_number"] = cert.Issuer.SerialNumber

san := append(cert.DNSNames, cert.EmailAddresses...)
for _, ip := range cert.IPAddresses {
san = append(san, ip.String())
}
for _, uri := range cert.URIs {
san = append(san, uri.String())
}
tags["san"] = strings.Join(san, ",")

return tags
}

Expand All @@ -179,7 +193,7 @@ func (c *X509Cert) Gather(acc telegraf.Accumulator) error {

for i, cert := range certs {
fields := getFields(cert, now)
tags := getTags(cert.Subject, location)
tags := getTags(cert, location)

// The first certificate is the leaf/end-entity certificate which needs DNS
// name validation against the URL hostname.
Expand Down
56 changes: 56 additions & 0 deletions plugins/inputs/x509_cert/x509_cert_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"encoding/base64"
"fmt"
"io/ioutil"
"math/big"
"os"
"testing"
"time"
Expand Down Expand Up @@ -195,6 +196,61 @@ func TestGatherLocal(t *testing.T) {
}
}

func TestTags(t *testing.T) {
cert := fmt.Sprintf("%s\n%s", pki.ReadServerCert(), pki.ReadCACert())

f, err := ioutil.TempFile("", "x509_cert")
if err != nil {
t.Fatal(err)
}

_, err = f.Write([]byte(cert))
if err != nil {
t.Fatal(err)
}

err = f.Close()
if err != nil {
t.Fatal(err)
}

defer os.Remove(f.Name())

sc := X509Cert{
Sources: []string{f.Name()},
}
sc.Init()

acc := testutil.Accumulator{}
err = sc.Gather(&acc)
require.NoError(t, err)

assert.True(t, acc.HasMeasurement("x509_cert"))

assert.True(t, acc.HasTag("x509_cert", "common_name"))
assert.Equal(t, "server.localdomain", acc.TagValue("x509_cert", "common_name"))

assert.True(t, acc.HasTag("x509_cert", "signature_algorithm"))
assert.Equal(t, "SHA256-RSA", acc.TagValue("x509_cert", "signature_algorithm"))

assert.True(t, acc.HasTag("x509_cert", "public_key_algorithm"))
assert.Equal(t, "RSA", acc.TagValue("x509_cert", "public_key_algorithm"))

assert.True(t, acc.HasTag("x509_cert", "issuer_common_name"))
assert.Equal(t, "Telegraf Test CA", acc.TagValue("x509_cert", "issuer_common_name"))

assert.True(t, acc.HasTag("x509_cert", "san"))
assert.Equal(t, "localhost,127.0.0.1", acc.TagValue("x509_cert", "san"))

assert.True(t, acc.HasTag("x509_cert", "serial_number"))
serialNumber := new(big.Int)
_, validSerialNumber := serialNumber.SetString(acc.TagValue("x509_cert", "serial_number"), 16)
if !validSerialNumber {
t.Errorf("Expected a valid Hex serial number but got %s", acc.TagValue("x509_cert", "serial_number"))
}
assert.Equal(t, big.NewInt(1), serialNumber)
}

func TestGatherChain(t *testing.T) {
cert := fmt.Sprintf("%s\n%s", pki.ReadServerCert(), pki.ReadCACert())

Expand Down

0 comments on commit 359c4f6

Please sign in to comment.