From 7d9aedf9ed3fc58ad9fe124609bef4c76f4d4194 Mon Sep 17 00:00:00 2001 From: natsuki-hoshino Date: Wed, 24 Jul 2024 07:56:47 +0000 Subject: [PATCH 1/2] Add metrics for revocation data provided by Certificate Revocation Lists --- README.md | 6 ++ prober/https_test.go | 8 +++ prober/metrics.go | 130 +++++++++++++++++++++++++++++++++++++++++ prober/metrics_test.go | 64 ++++++++++++++++++++ prober/tcp_test.go | 122 ++++++++++++++++++++++++++++++++++++++ prober/tls.go | 4 ++ test/tcp.go | 13 +++++ test/test.go | 35 ++++++++++- 8 files changed, 381 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index da58d588..370cd347 100644 --- a/README.md +++ b/README.md @@ -73,6 +73,12 @@ Flags: | ssl_ocsp_response_status | The status in the OCSP response. 0=Good 1=Revoked 2=Unknown | | tcp, https | | ssl_ocsp_response_stapled | Does the connection state contain a stapled OCSP response? Boolean. | | tcp, https | | ssl_ocsp_response_this_update | The thisUpdate value in the OCSP response. Expressed as a Unix Epoch Time | | tcp, https | +| ssl_crl_status | The status of the CRL check 0=Good 1=Revoked 2=Unknown | | tcp, https | +| ssl_crl_revoke_reason | The reason code for revocation in the CRL as specified in RFC 5280 Section 5.3.1 | | tcp, https | +| ssl_crl_revoked_at | The revocationTime value in the CRL, expressed as a Unix Epoch Time | | tcp, https | +| ssl_crl_number | The value of the X.509 v2 cRLNumber extension in the CRL | | tcp, https | +| ssl_crl_this_update | The thisUpdate value in the CRL, expressed as a Unix Epoch Time | | tcp, https | +| ssl_crl_next_update | The nextUpdate value in the CRL, expressed as a Unix Epoch Time | | tcp, https | | ssl_probe_success | Was the probe successful? Boolean. | | all | | ssl_prober | The prober used by the exporter to connect to the target. Boolean. | prober | all | | ssl_tls_version_info | The TLS version used. Always 1. | version | tcp, https | diff --git a/prober/https_test.go b/prober/https_test.go index 28bcaf26..c7796b4e 100644 --- a/prober/https_test.go +++ b/prober/https_test.go @@ -55,6 +55,7 @@ func TestProbeHTTPS(t *testing.T) { } checkCertificateMetrics(cert, registry, t) checkOCSPMetrics([]byte{}, registry, t) + checkCRLMetrics([]byte{}, registry, t) checkTLSVersionMetrics("TLS 1.3", registry, t) } @@ -164,6 +165,7 @@ func TestProbeHTTPSNoScheme(t *testing.T) { } checkCertificateMetrics(cert, registry, t) checkOCSPMetrics([]byte{}, registry, t) + checkCRLMetrics([]byte{}, registry, t) checkTLSVersionMetrics("TLS 1.3", registry, t) } @@ -207,6 +209,7 @@ func TestProbeHTTPSServerName(t *testing.T) { } checkCertificateMetrics(cert, registry, t) checkOCSPMetrics([]byte{}, registry, t) + checkCRLMetrics([]byte{}, registry, t) checkTLSVersionMetrics("TLS 1.3", registry, t) } @@ -285,6 +288,7 @@ func TestProbeHTTPSClientAuth(t *testing.T) { } checkCertificateMetrics(cert, registry, t) checkOCSPMetrics([]byte{}, registry, t) + checkCRLMetrics([]byte{}, registry, t) checkTLSVersionMetrics("TLS 1.3", registry, t) } @@ -422,6 +426,7 @@ func TestProbeHTTPSExpiredInsecure(t *testing.T) { } checkCertificateMetrics(cert, registry, t) checkOCSPMetrics([]byte{}, registry, t) + checkCRLMetrics([]byte{}, registry, t) checkTLSVersionMetrics("TLS 1.3", registry, t) } @@ -486,6 +491,7 @@ func TestProbeHTTPSProxy(t *testing.T) { } checkCertificateMetrics(cert, registry, t) checkOCSPMetrics([]byte{}, registry, t) + checkCRLMetrics([]byte{}, registry, t) checkTLSVersionMetrics("TLS 1.3", registry, t) } @@ -532,6 +538,7 @@ func TestProbeHTTPSOCSP(t *testing.T) { checkCertificateMetrics(cert, registry, t) checkOCSPMetrics(resp, registry, t) + checkCRLMetrics([]byte{}, registry, t) checkTLSVersionMetrics("TLS 1.3", registry, t) } @@ -613,6 +620,7 @@ func TestProbeHTTPSVerifiedChains(t *testing.T) { checkCertificateMetrics(serverCert, registry, t) checkOCSPMetrics([]byte{}, registry, t) + checkCRLMetrics([]byte{}, registry, t) checkVerifiedChainMetrics(verifiedChains, registry, t) checkTLSVersionMetrics("TLS 1.3", registry, t) } diff --git a/prober/metrics.go b/prober/metrics.go index bb0fc382..627b1109 100644 --- a/prober/metrics.go +++ b/prober/metrics.go @@ -6,6 +6,8 @@ import ( "encoding/base64" "fmt" "io/ioutil" + "math/big" + "net/http" "sort" "strconv" "strings" @@ -231,6 +233,90 @@ func collectOCSPMetrics(ocspResponse []byte, registry *prometheus.Registry) erro return nil } +func collectCRLMetrics(verifiedChains [][]*x509.Certificate, registry *prometheus.Registry) error { + var ( + crlStatus = prometheus.NewGauge( + prometheus.GaugeOpts{ + Name: prometheus.BuildFQName(namespace, "", "crl_status"), + Help: "The status of the CRL check 0=Good 1=Revoked 2=Unknown", + }, + ) + crlRevokeReason = prometheus.NewGauge( + prometheus.GaugeOpts{ + Name: prometheus.BuildFQName(namespace, "", "crl_revoke_reason"), + Help: "The reason code for revocation in the CRL as specified in RFC 5280 Section 5.3.1", + }, + ) + crlRevokedAt = prometheus.NewGauge( + prometheus.GaugeOpts{ + Name: prometheus.BuildFQName(namespace, "", "crl_revoked_at"), + Help: "The revocationTime value in the CRL, expressed as a Unix Epoch Time", + }, + ) + crlNumber = prometheus.NewGauge( + prometheus.GaugeOpts{ + Name: prometheus.BuildFQName(namespace, "", "crl_number"), + Help: "The value of the X.509 v2 cRLNumber extension in the CRL", + }, + ) + crlThisUpdate = prometheus.NewGauge( + prometheus.GaugeOpts{ + Name: prometheus.BuildFQName(namespace, "", "crl_this_update"), + Help: "The thisUpdate value in the CRL, expressed as a Unix Epoch Time", + }, + ) + crlNextUpdate = prometheus.NewGauge( + prometheus.GaugeOpts{ + Name: prometheus.BuildFQName(namespace, "", "crl_next_update"), + Help: "The nextUpdate value in the CRL, expressed as a Unix Epoch Time", + }, + ) + ) + registry.MustRegister( + crlStatus, + crlRevokeReason, + crlRevokedAt, + crlNumber, + crlThisUpdate, + crlNextUpdate, + ) + + if len(verifiedChains) == 0 { + crlStatus.Set(2) + return nil + } + issuerIndex := 1 + if len(verifiedChains[0]) < 2 { + issuerIndex = 0 + } + + cert := verifiedChains[0][0] + issuer := verifiedChains[0][issuerIndex] + + crl, err := fetchCRL(cert, issuer) + if err != nil { + crlStatus.Set(2) + return err + } + if crl == nil { + crlStatus.Set(2) + return nil + } + num, _ := new(big.Float).SetInt(crl.Number).Float64() + crlNumber.Set(num) + crlThisUpdate.Set(float64(crl.ThisUpdate.Unix())) + crlNextUpdate.Set(float64(crl.NextUpdate.Unix())) + for _, revokedCert := range crl.RevokedCertificateEntries { + if revokedCert.SerialNumber.Cmp(cert.SerialNumber) == 0 { + crlStatus.Set(1) + crlRevokeReason.Set(float64(revokedCert.ReasonCode)) + crlRevokedAt.Set(float64(revokedCert.RevocationTime.Unix())) + break + } + } + return nil +} + func collectFileMetrics(logger log.Logger, files []string, registry *prometheus.Registry) error { var ( totalCerts []*x509.Certificate @@ -480,3 +566,47 @@ func organizationalUnits(cert *x509.Certificate) string { return "" } + +func fetchCRLDistributionPointFromCert(cert *x509.Certificate) string { + for _, url := range cert.CRLDistributionPoints { + if strings.HasPrefix(url, "http://") || strings.HasPrefix(url, "https://") { + return url + } + } + return "" +} + +func fetchCRL(cert, issuer *x509.Certificate) (*x509.RevocationList, error) { + crlURL := fetchCRLDistributionPointFromCert(cert) + // the leaf certificate may not always contain a CRL distribution point, but its issuer should + if crlURL == "" { + crlURL = fetchCRLDistributionPointFromCert(issuer) + } + if crlURL == "" { + // CA/B Forum Ballot SC-063 v4 requires a CRL distribution point, but that only applies for publicly trusted CAs + return nil, nil + } + + resp, err := http.Get(crlURL) + if err != nil { + return nil, err + } + defer resp.Body.Close() + + data, err := ioutil.ReadAll(resp.Body) + if err != nil { + return nil, err + } + + crl, err := x509.ParseRevocationList(data) + if err != nil { + return nil, err + } + if err := crl.CheckSignatureFrom(issuer); err != nil { + return nil, err + } + if crl.NextUpdate.Before(time.Now()) { + return nil, fmt.Errorf("CRL has expired") + } + return crl, nil +} diff --git a/prober/metrics_test.go b/prober/metrics_test.go index 843a4339..d4341e38 100644 --- a/prober/metrics_test.go +++ b/prober/metrics_test.go @@ -195,6 +195,70 @@ func checkOCSPMetrics(resp []byte, registry *prometheus.Registry, t *testing.T) checkRegistryResults(expectedResults, mfs, t) } +func checkCRLMetrics(crlRaw []byte, registry *prometheus.Registry, t *testing.T) { + var ( + status float64 + reason float64 + revokedAt float64 + number float64 + thisUpdate float64 + nextUpdate float64 + ) + mfs, err := registry.Gather() + if err != nil { + t.Fatal(err) + } + if len(crlRaw) == 0 { + expectedResults := []*registryResult{ + { + Name: "ssl_crl_status", + Value: 2, + }, + } + checkRegistryResults(expectedResults, mfs, t) + return + } + crl, err := x509.ParseRevocationList(crlRaw) + if err != nil { + t.Fatal(err) + } + number = float64(crl.Number.Int64()) + thisUpdate = float64(crl.ThisUpdate.Unix()) + nextUpdate = float64(crl.NextUpdate.Unix()) + if len(crl.RevokedCertificateEntries) > 0 { + status = 1 + reason = float64(crl.RevokedCertificateEntries[0].ReasonCode) + revokedAt = float64(crl.RevokedCertificateEntries[0].RevocationTime.Unix()) + } + expectedResults := []*registryResult{ + { + Name: "ssl_crl_status", + Value: status, + }, + { + Name: "ssl_crl_revoke_reason", + Value: reason, + }, + { + Name: "ssl_crl_revoked_at", + Value: revokedAt, + }, + { + Name: "ssl_crl_number", + Value: number, + }, + { + Name: "ssl_crl_this_update", + Value: thisUpdate, + }, + { + Name: "ssl_crl_next_update", + Value: nextUpdate, + }, + } + checkRegistryResults(expectedResults, mfs, t) +} + func checkTLSVersionMetrics(version string, registry *prometheus.Registry, t *testing.T) { mfs, err := registry.Gather() if err != nil { diff --git a/prober/tcp_test.go b/prober/tcp_test.go index 50774c70..e60395c4 100644 --- a/prober/tcp_test.go +++ b/prober/tcp_test.go @@ -9,6 +9,8 @@ import ( "crypto/x509" "math/big" "net" + "net/http" + "net/http/httptest" "testing" "time" @@ -52,6 +54,7 @@ func TestProbeTCP(t *testing.T) { } checkCertificateMetrics(cert, registry, t) checkOCSPMetrics([]byte{}, registry, t) + checkCRLMetrics([]byte{}, registry, t) checkTLSVersionMetrics("TLS 1.3", registry, t) } @@ -123,6 +126,7 @@ func TestProbeTCPServerName(t *testing.T) { } checkCertificateMetrics(cert, registry, t) checkOCSPMetrics([]byte{}, registry, t) + checkCRLMetrics([]byte{}, registry, t) checkTLSVersionMetrics("TLS 1.3", registry, t) } @@ -204,6 +208,7 @@ func TestProbeTCPExpiredInsecure(t *testing.T) { } checkCertificateMetrics(cert, registry, t) checkOCSPMetrics([]byte{}, registry, t) + checkCRLMetrics([]byte{}, registry, t) checkTLSVersionMetrics("TLS 1.3", registry, t) } @@ -243,6 +248,7 @@ func TestProbeTCPStartTLSSMTP(t *testing.T) { } checkCertificateMetrics(cert, registry, t) checkOCSPMetrics([]byte{}, registry, t) + checkCRLMetrics([]byte{}, registry, t) checkTLSVersionMetrics("TLS 1.3", registry, t) } @@ -283,6 +289,7 @@ func TestProbeTCPStartTLSSMTPWithDashInResponse(t *testing.T) { } checkCertificateMetrics(cert, registry, t) checkOCSPMetrics([]byte{}, registry, t) + checkCRLMetrics([]byte{}, registry, t) checkTLSVersionMetrics("TLS 1.3", registry, t) } @@ -322,6 +329,7 @@ func TestProbeTCPStartTLSFTP(t *testing.T) { } checkCertificateMetrics(cert, registry, t) checkOCSPMetrics([]byte{}, registry, t) + checkCRLMetrics([]byte{}, registry, t) checkTLSVersionMetrics("TLS 1.3", registry, t) } @@ -361,6 +369,7 @@ func TestProbeTCPStartTLSIMAP(t *testing.T) { } checkCertificateMetrics(cert, registry, t) checkOCSPMetrics([]byte{}, registry, t) + checkCRLMetrics([]byte{}, registry, t) checkTLSVersionMetrics("TLS 1.3", registry, t) } @@ -400,6 +409,7 @@ func TestProbeTCPStartTLSPOP3(t *testing.T) { } checkCertificateMetrics(cert, registry, t) checkOCSPMetrics([]byte{}, registry, t) + checkCRLMetrics([]byte{}, registry, t) checkTLSVersionMetrics("TLS 1.3", registry, t) } @@ -439,6 +449,7 @@ func TestProbeTCPStartTLSPostgreSQL(t *testing.T) { } checkCertificateMetrics(cert, registry, t) checkOCSPMetrics([]byte{}, registry, t) + checkCRLMetrics([]byte{}, registry, t) checkTLSVersionMetrics("TLS 1.3", registry, t) } @@ -515,6 +526,7 @@ func TestProbeTCPOCSP(t *testing.T) { checkCertificateMetrics(cert, registry, t) checkOCSPMetrics(resp, registry, t) + checkCRLMetrics([]byte{}, registry, t) checkTLSVersionMetrics("TLS 1.3", registry, t) } @@ -596,6 +608,116 @@ func TestProbeTCPVerifiedChains(t *testing.T) { checkCertificateMetrics(serverCert, registry, t) checkOCSPMetrics([]byte{}, registry, t) + checkCRLMetrics([]byte{}, registry, t) checkVerifiedChainMetrics(verifiedChains, registry, t) checkTLSVersionMetrics("TLS 1.3", registry, t) } + +func TestProbeTCPCRL(t *testing.T) { + var crlFile []byte + + crlServer := httptest.NewUnstartedServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { + w.Write(crlFile) + })) + + crlServer.Start() + defer crlServer.Close() + + server, certPEM, keyPEM, caFile, teardown, err := test.SetupTCPServerWithCRLDP(crlServer.URL) + if err != nil { + t.Fatal(err) + } + defer teardown() + + cert, err := newCertificate(certPEM) + if err != nil { + t.Fatal(err) + } + key, err := newKey(keyPEM) + if err != nil { + t.Fatal(err) + } + crlFile, err = test.GenerateCRL(nil, cert, key, time.Now().AddDate(0, 0, 1)) + if err != nil { + t.Fatal(err) + } + + server.StartTLS() + defer server.Close() + + module := config.Module{ + TLSConfig: config.TLSConfig{ + CAFile: caFile, + InsecureSkipVerify: false, + }, + } + + registry := prometheus.NewRegistry() + + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + + if err := ProbeTCP(ctx, newTestLogger(), server.Listener.Addr().String(), module, registry); err != nil { + t.Fatalf("error: %s", err) + } + + checkCertificateMetrics(cert, registry, t) + checkOCSPMetrics([]byte{}, registry, t) + checkCRLMetrics(crlFile, registry, t) + checkTLSVersionMetrics("TLS 1.3", registry, t) +} + +func TestProbeTCPCRL_Revoked(t *testing.T) { + var crlFile []byte + + crlServer := httptest.NewUnstartedServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { + w.Write(crlFile) + })) + + crlServer.Start() + defer crlServer.Close() + + server, certPEM, keyPEM, caFile, teardown, err := test.SetupTCPServerWithCRLDP(crlServer.URL) + if err != nil { + t.Fatal(err) + } + defer teardown() + + cert, err := newCertificate(certPEM) + if err != nil { + t.Fatal(err) + } + key, err := newKey(keyPEM) + if err != nil { + t.Fatal(err) + } + entry := test.GenerateRevocationListEntry(cert.SerialNumber, 5) + crlFile, err = test.GenerateCRL(entry, cert, key, time.Now().AddDate(0, 0, 1)) + if err != nil { + t.Fatal(err) + } + + server.StartTLS() + defer server.Close() + + module := config.Module{ + TLSConfig: config.TLSConfig{ + CAFile: caFile, + InsecureSkipVerify: false, + }, + } + + registry := prometheus.NewRegistry() + + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + + if err := ProbeTCP(ctx, newTestLogger(), server.Listener.Addr().String(), module, registry); err != nil { + t.Fatalf("error: %s", err) + } + + checkCertificateMetrics(cert, registry, t) + checkOCSPMetrics([]byte{}, registry, t) + checkCRLMetrics(crlFile, registry, t) + checkTLSVersionMetrics("TLS 1.3", registry, t) +} diff --git a/prober/tls.go b/prober/tls.go index cca4053e..90bb1845 100644 --- a/prober/tls.go +++ b/prober/tls.go @@ -30,6 +30,10 @@ func newTLSConfig(target string, registry *prometheus.Registry, cfg *config.TLSC return collectConnectionStateMetrics(state, registry) } + tlsConfig.VerifyPeerCertificate = func(_ [][]byte, verifiedChains [][]*x509.Certificate) error { + return collectCRLMetrics(verifiedChains, registry) + } + return tlsConfig, nil } diff --git a/test/tcp.go b/test/tcp.go index f57afe80..2707ba34 100644 --- a/test/tcp.go +++ b/test/tcp.go @@ -288,6 +288,19 @@ func SetupTCPServer() (*TCPServer, []byte, []byte, string, func(), error) { return server, testcertPEM, testkeyPEM, caFile, teardown, nil } +// SetupTCPServerWithCRLDP sets up a server for testing with a generated cert and key pair +// and a CRL distribution point +func SetupTCPServerWithCRLDP(crlURL string) (*TCPServer, []byte, []byte, string, func(), error) { + testcertPEM, testkeyPEM := GenerateTestCertificateWithCRLDP(time.Now().AddDate(0, 0, 1), crlURL) + + server, caFile, teardown, err := SetupTCPServerWithCertAndKey(testcertPEM, testcertPEM, testkeyPEM) + if err != nil { + return nil, testcertPEM, testkeyPEM, caFile, teardown, err + } + + return server, testcertPEM, testkeyPEM, caFile, teardown, nil +} + // SetupTCPServerWithCertAndKey sets up a server with the provided certs and key func SetupTCPServerWithCertAndKey(caPEM, certPEM, keyPEM []byte) (*TCPServer, string, func(), error) { var teardown func() diff --git a/test/test.go b/test/test.go index a05ca1b5..bdb940a4 100644 --- a/test/test.go +++ b/test/test.go @@ -1,6 +1,7 @@ package test import ( + "crypto" "crypto/rand" "crypto/rsa" "crypto/x509" @@ -15,6 +16,11 @@ import ( // GenerateTestCertificate generates a test certificate with the given expiry date func GenerateTestCertificate(expiry time.Time) ([]byte, []byte) { + return GenerateTestCertificateWithCRLDP(expiry, "") +} + +// GenerateTestCertificateWithCRLDP generates a test certificate which contains a CRL distribution point +func GenerateTestCertificateWithCRLDP(expiry time.Time, crlURL string) ([]byte, []byte) { privateKey, err := rsa.GenerateKey(rand.Reader, 2048) if err != nil { panic(fmt.Sprintf("Error creating rsa key: %s", err)) @@ -23,6 +29,9 @@ func GenerateTestCertificate(expiry time.Time) ([]byte, []byte) { cert := GenerateCertificateTemplate(expiry) cert.IsCA = true + if crlURL != "" { + cert.CRLDistributionPoints = []string{crlURL} + } _, pemCert := GenerateSelfSignedCertificateWithPrivateKey(cert, privateKey) @@ -76,7 +85,7 @@ func GenerateCertificateTemplate(expiry time.Time) *x509.Certificate { NotBefore: time.Now(), NotAfter: expiry, ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth}, - KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign, + KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign | x509.KeyUsageCRLSign, IPAddresses: []net.IP{net.ParseIP("127.0.0.1"), net.ParseIP("::1")}, Subject: pkix.Name{ CommonName: "example.ribbybibby.me", @@ -88,6 +97,30 @@ func GenerateCertificateTemplate(expiry time.Time) *x509.Certificate { } } +func GenerateRevocationListEntry(serial *big.Int, reason int) *x509.RevocationListEntry { + return &x509.RevocationListEntry{ + SerialNumber: serial, + RevocationTime: time.Now(), + ReasonCode: reason, + } +} + +// GenerateCRL generates a Certificate Revocation List +func GenerateCRL(entry *x509.RevocationListEntry, issuer *x509.Certificate, key crypto.Signer, expiry time.Time) ([]byte, error) { + template := &x509.RevocationList{ + SignatureAlgorithm: issuer.SignatureAlgorithm, + Issuer: issuer.Subject, + ThisUpdate: time.Now(), + NextUpdate: expiry, + RevokedCertificateEntries: []x509.RevocationListEntry{}, + Number: big.NewInt(1), + } + if entry != nil { + template.RevokedCertificateEntries = append(template.RevokedCertificateEntries, *entry) + } + return x509.CreateRevocationList(rand.Reader, template, issuer, key) +} + // WriteFile writes some content to a temporary file func WriteFile(filename string, contents []byte) (string, error) { tmpFile, err := ioutil.TempFile("", filename) From 4dae54fde757b628730008f8e006959d33434013 Mon Sep 17 00:00:00 2001 From: natsuki-hoshino Date: Wed, 24 Jul 2024 08:02:31 +0000 Subject: [PATCH 2/2] Address ioutil deprecation in touched files --- prober/metrics.go | 11 ++++++----- test/test.go | 4 ++-- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/prober/metrics.go b/prober/metrics.go index 627b1109..7fe8fbbd 100644 --- a/prober/metrics.go +++ b/prober/metrics.go @@ -5,9 +5,10 @@ import ( "crypto/x509" "encoding/base64" "fmt" - "io/ioutil" + "io" "math/big" "net/http" + "os" "sort" "strconv" "strings" @@ -338,7 +339,7 @@ func collectFileMetrics(logger log.Logger, files []string, registry *prometheus. registry.MustRegister(fileNotAfter, fileNotBefore) for _, f := range files { - data, err := ioutil.ReadFile(f) + data, err := os.ReadFile(f) if err != nil { level.Debug(logger).Log("msg", fmt.Sprintf("Error reading file %s: %s", f, err)) continue @@ -449,7 +450,7 @@ func collectKubeconfigMetrics(logger log.Logger, kubeconfig KubeConfig, registry return err } } else if c.Cluster.CertificateAuthority != "" { - data, err = ioutil.ReadFile(c.Cluster.CertificateAuthority) + data, err = os.ReadFile(c.Cluster.CertificateAuthority) if err != nil { level.Debug(logger).Log("msg", fmt.Sprintf("Error reading file %s: %s", c.Cluster.CertificateAuthority, err)) return err @@ -485,7 +486,7 @@ func collectKubeconfigMetrics(logger log.Logger, kubeconfig KubeConfig, registry return err } } else if u.User.ClientCertificate != "" { - data, err = ioutil.ReadFile(u.User.ClientCertificate) + data, err = os.ReadFile(u.User.ClientCertificate) if err != nil { level.Debug(logger).Log("msg", fmt.Sprintf("Error reading file %s: %s", u.User.ClientCertificate, err)) return err @@ -593,7 +594,7 @@ func fetchCRL(cert, issuer *x509.Certificate) (*x509.RevocationList, error) { } defer resp.Body.Close() - data, err := ioutil.ReadAll(resp.Body) + data, err := io.ReadAll(resp.Body) if err != nil { return nil, err } diff --git a/test/test.go b/test/test.go index bdb940a4..e8cf03d9 100644 --- a/test/test.go +++ b/test/test.go @@ -8,9 +8,9 @@ import ( "crypto/x509/pkix" "encoding/pem" "fmt" - "io/ioutil" "math/big" "net" + "os" "time" ) @@ -123,7 +123,7 @@ func GenerateCRL(entry *x509.RevocationListEntry, issuer *x509.Certificate, key // WriteFile writes some content to a temporary file func WriteFile(filename string, contents []byte) (string, error) { - tmpFile, err := ioutil.TempFile("", filename) + tmpFile, err := os.CreateTemp("", filename) if err != nil { return tmpFile.Name(), err }