Harden and add gosec linter

Remediate:
G104: Errors unhandled.
G109: Potential Integer overflow made by strconv.Atoi result conversion to int16/32
G112: Potential Slowloris Attack because ReadHeaderTimeout is not configured in the http.Server
G304: Potential file inclusion via variable
G601: Implicit memory aliasing in for loop.

Signed-off-by: Manuel Rüger <manuel@rueg.eu>
This commit is contained in:
Manuel Rüger
2022-10-17 00:48:44 +02:00
parent d4fdcda6f5
commit 6b7027ff41
11 changed files with 70 additions and 22 deletions

View File

@@ -8,6 +8,7 @@ linters:
- gocyclo - gocyclo
- gofmt - gofmt
- goimports - goimports
- gosec
- gosimple - gosimple
- govet - govet
- ineffassign - ineffassign
@@ -28,3 +29,7 @@ issues:
- path: _test\.go - path: _test\.go
linters: linters:
- promlinter - promlinter
# TODO(mrueg) Improve error handling
- text: "G104:"
linters:
- gosec

View File

@@ -212,7 +212,8 @@ func jobMetricFamilies(allowAnnotationsList, allowLabelsList []string) []generat
} }
} }
for _, condition := range j.Status.Conditions { for _, c := range j.Status.Conditions {
condition := c
if condition.Type == v1batch.JobFailed { if condition.Type == v1batch.JobFailed {
reasonKnown := false reasonKnown := false
for _, reason := range jobFailureReasons { for _, reason := range jobFailureReasons {

View File

@@ -33,9 +33,9 @@ import (
var ( var (
descSecretAnnotationsName = "kube_secret_annotations" descSecretAnnotationsName = "kube_secret_annotations"
descSecretAnnotationsHelp = "Kubernetes annotations converted to Prometheus labels." descSecretAnnotationsHelp = "Kubernetes annotations converted to Prometheus labels." //nolint:gosec
descSecretLabelsName = "kube_secret_labels" descSecretLabelsName = "kube_secret_labels"
descSecretLabelsHelp = "Kubernetes labels converted to Prometheus labels." descSecretLabelsHelp = "Kubernetes labels converted to Prometheus labels." //nolint:gosec
descSecretLabelsDefaultLabels = []string{"namespace", "secret"} descSecretLabelsDefaultLabels = []string{"namespace", "secret"}
) )

View File

@@ -20,6 +20,7 @@ import (
"context" "context"
"fmt" "fmt"
"os" "os"
"path/filepath"
"strings" "strings"
"github.com/prometheus/common/version" "github.com/prometheus/common/version"
@@ -74,7 +75,7 @@ func resolveCustomResourceConfig(opts *options.Options) (customresourcestate.Con
return yaml.NewDecoder(strings.NewReader(s)), true return yaml.NewDecoder(strings.NewReader(s)), true
} }
if file := opts.CustomResourceConfigFile; file != "" { if file := opts.CustomResourceConfigFile; file != "" {
f, err := os.Open(file) f, err := os.Open(filepath.Clean(file))
if err != nil { if err != nil {
klog.ErrorS(err, "Custom Resource State Metrics file could not be opened") klog.ErrorS(err, "Custom Resource State Metrics file could not be opened")
klog.FlushAndExit(klog.ExitFlushTimeout, 1) klog.FlushAndExit(klog.ExitFlushTimeout, 1)

View File

@@ -178,11 +178,17 @@ func RunKubeStateMetrics(ctx context.Context, opts *options.Options, factories .
telemetryMux := buildTelemetryServer(ksmMetricsRegistry) telemetryMux := buildTelemetryServer(ksmMetricsRegistry)
telemetryListenAddress := net.JoinHostPort(opts.TelemetryHost, strconv.Itoa(opts.TelemetryPort)) telemetryListenAddress := net.JoinHostPort(opts.TelemetryHost, strconv.Itoa(opts.TelemetryPort))
telemetryServer := http.Server{Handler: telemetryMux, Addr: telemetryListenAddress} telemetryServer := http.Server{
Handler: telemetryMux,
Addr: telemetryListenAddress,
ReadHeaderTimeout: 5 * time.Second}
metricsMux := buildMetricsServer(m, durationVec) metricsMux := buildMetricsServer(m, durationVec)
metricsServerListenAddress := net.JoinHostPort(opts.Host, strconv.Itoa(opts.Port)) metricsServerListenAddress := net.JoinHostPort(opts.Host, strconv.Itoa(opts.Port))
metricsServer := http.Server{Handler: metricsMux, Addr: metricsServerListenAddress} metricsServer := http.Server{
Handler: metricsMux,
Addr: metricsServerListenAddress,
ReadHeaderTimeout: 5 * time.Second}
// Run Telemetry server // Run Telemetry server
{ {

View File

@@ -73,7 +73,10 @@ func BenchmarkKubeStateMetrics(b *testing.B) {
builder := store.NewBuilder() builder := store.NewBuilder()
builder.WithMetrics(reg) builder.WithMetrics(reg)
builder.WithEnabledResources(options.DefaultResources.AsSlice()) err := builder.WithEnabledResources(options.DefaultResources.AsSlice())
if err != nil {
b.Fatal(err)
}
builder.WithKubeClient(kubeClient) builder.WithKubeClient(kubeClient)
builder.WithSharding(0, 1) builder.WithSharding(0, 1)
builder.WithContext(ctx) builder.WithContext(ctx)
@@ -118,7 +121,10 @@ func BenchmarkKubeStateMetrics(b *testing.B) {
b.StopTimer() b.StopTimer()
buf := bytes.Buffer{} buf := bytes.Buffer{}
buf.ReadFrom(resp.Body) _, err := buf.ReadFrom(resp.Body)
if err != nil {
b.Fatal(err)
}
accumulatedContentLength += buf.Len() accumulatedContentLength += buf.Len()
b.StartTimer() b.StartTimer()
} }
@@ -144,7 +150,10 @@ func TestFullScrapeCycle(t *testing.T) {
reg := prometheus.NewRegistry() reg := prometheus.NewRegistry()
builder := store.NewBuilder() builder := store.NewBuilder()
builder.WithMetrics(reg) builder.WithMetrics(reg)
builder.WithEnabledResources(options.DefaultResources.AsSlice()) err = builder.WithEnabledResources(options.DefaultResources.AsSlice())
if err != nil {
t.Fatal(err)
}
builder.WithKubeClient(kubeClient) builder.WithKubeClient(kubeClient)
builder.WithNamespaces(options.DefaultNamespaces, "") builder.WithNamespaces(options.DefaultNamespaces, "")
builder.WithGenerateStoresFunc(builder.DefaultGenerateStoresFunc()) builder.WithGenerateStoresFunc(builder.DefaultGenerateStoresFunc())
@@ -428,7 +437,10 @@ func TestShardingEquivalenceScrapeCycle(t *testing.T) {
reg := prometheus.NewRegistry() reg := prometheus.NewRegistry()
unshardedBuilder := store.NewBuilder() unshardedBuilder := store.NewBuilder()
unshardedBuilder.WithMetrics(reg) unshardedBuilder.WithMetrics(reg)
unshardedBuilder.WithEnabledResources(options.DefaultResources.AsSlice()) err = unshardedBuilder.WithEnabledResources(options.DefaultResources.AsSlice())
if err != nil {
t.Fatal(err)
}
unshardedBuilder.WithKubeClient(kubeClient) unshardedBuilder.WithKubeClient(kubeClient)
unshardedBuilder.WithNamespaces(options.DefaultNamespaces, "") unshardedBuilder.WithNamespaces(options.DefaultNamespaces, "")
unshardedBuilder.WithFamilyGeneratorFilter(l) unshardedBuilder.WithFamilyGeneratorFilter(l)
@@ -441,7 +453,10 @@ func TestShardingEquivalenceScrapeCycle(t *testing.T) {
regShard1 := prometheus.NewRegistry() regShard1 := prometheus.NewRegistry()
shardedBuilder1 := store.NewBuilder() shardedBuilder1 := store.NewBuilder()
shardedBuilder1.WithMetrics(regShard1) shardedBuilder1.WithMetrics(regShard1)
shardedBuilder1.WithEnabledResources(options.DefaultResources.AsSlice()) err = shardedBuilder1.WithEnabledResources(options.DefaultResources.AsSlice())
if err != nil {
t.Fatal(err)
}
shardedBuilder1.WithKubeClient(kubeClient) shardedBuilder1.WithKubeClient(kubeClient)
shardedBuilder1.WithNamespaces(options.DefaultNamespaces, "") shardedBuilder1.WithNamespaces(options.DefaultNamespaces, "")
shardedBuilder1.WithFamilyGeneratorFilter(l) shardedBuilder1.WithFamilyGeneratorFilter(l)
@@ -454,7 +469,10 @@ func TestShardingEquivalenceScrapeCycle(t *testing.T) {
regShard2 := prometheus.NewRegistry() regShard2 := prometheus.NewRegistry()
shardedBuilder2 := store.NewBuilder() shardedBuilder2 := store.NewBuilder()
shardedBuilder2.WithMetrics(regShard2) shardedBuilder2.WithMetrics(regShard2)
shardedBuilder2.WithEnabledResources(options.DefaultResources.AsSlice()) err = shardedBuilder2.WithEnabledResources(options.DefaultResources.AsSlice())
if err != nil {
t.Fatal(err)
}
shardedBuilder2.WithKubeClient(kubeClient) shardedBuilder2.WithKubeClient(kubeClient)
shardedBuilder2.WithNamespaces(options.DefaultNamespaces, "") shardedBuilder2.WithNamespaces(options.DefaultNamespaces, "")
shardedBuilder2.WithFamilyGeneratorFilter(l) shardedBuilder2.WithFamilyGeneratorFilter(l)
@@ -591,7 +609,11 @@ func TestCustomResourceExtension(t *testing.T) {
builder := store.NewBuilder() builder := store.NewBuilder()
builder.WithCustomResourceStoreFactories(factories...) builder.WithCustomResourceStoreFactories(factories...)
builder.WithMetrics(reg) builder.WithMetrics(reg)
builder.WithEnabledResources(resources) err := builder.WithEnabledResources(resources)
if err != nil {
t.Fatal(err)
}
builder.WithKubeClient(kubeClient) builder.WithKubeClient(kubeClient)
builder.WithCustomResourceClients(customResourceClients) builder.WithCustomResourceClients(customResourceClients)
builder.WithNamespaces(options.DefaultNamespaces, "") builder.WithNamespaces(options.DefaultNamespaces, "")

View File

@@ -40,9 +40,12 @@ var (
func TestBuilderWithCustomStore(t *testing.T) { func TestBuilderWithCustomStore(t *testing.T) {
b := builder.NewBuilder() b := builder.NewBuilder()
b.WithFamilyGeneratorFilter(generator.NewCompositeFamilyGeneratorFilter()) b.WithFamilyGeneratorFilter(generator.NewCompositeFamilyGeneratorFilter())
b.WithEnabledResources([]string{"pods"}) err := b.WithEnabledResources([]string{"pods"})
b.WithGenerateStoresFunc(customStore) if err != nil {
t.Fatal(err)
}
b.WithGenerateStoresFunc(customStore)
var fStores []*fakeStore var fStores []*fakeStore
for _, stores := range b.BuildStores() { for _, stores := range b.BuildStores() {
for _, store := range stores { for _, store := range stores {

View File

@@ -76,7 +76,8 @@ func TestWriteAllWithSingleStore(t *testing.T) {
}, },
}, },
} }
for _, svc := range svcs { for _, s := range svcs {
svc := s
if err := store.Add(&svc); err != nil { if err := store.Add(&svc); err != nil {
t.Fatal(err) t.Fatal(err)
} }
@@ -160,7 +161,8 @@ func TestWriteAllWithMultipleStores(t *testing.T) {
}, },
}, },
} }
for _, svc := range svcs1 { for _, s := range svcs1 {
svc := s
if err := s1.Add(&svc); err != nil { if err := s1.Add(&svc); err != nil {
t.Fatal(err) t.Fatal(err)
} }
@@ -183,7 +185,8 @@ func TestWriteAllWithMultipleStores(t *testing.T) {
}, },
} }
s2 := metricsstore.NewMetricsStore([]string{"Info 1 about services", "Info 2 about services"}, genFunc) s2 := metricsstore.NewMetricsStore([]string{"Info 1 about services", "Info 2 about services"}, genFunc)
for _, svc := range svcs2 { for _, s := range svcs2 {
svc := s
if err := s2.Add(&svc); err != nil { if err := s2.Add(&svc); err != nil {
t.Fatal(err) t.Fatal(err)
} }

View File

@@ -205,7 +205,10 @@ func (m *MetricsHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
// In case we gzipped the response, we have to close the writer. // In case we gzipped the response, we have to close the writer.
if closer, ok := writer.(io.Closer); ok { if closer, ok := writer.(io.Closer); ok {
closer.Close() err := closer.Close()
if err != nil {
klog.ErrorS(err, "Failed to close the writer")
}
} }
} }
@@ -226,7 +229,7 @@ func shardingSettingsFromStatefulSet(ss *appsv1.StatefulSet, podName string) (no
func detectNominalFromPod(statefulSetName, podName string) (int32, error) { func detectNominalFromPod(statefulSetName, podName string) (int32, error) {
nominalString := strings.TrimPrefix(podName, statefulSetName+"-") nominalString := strings.TrimPrefix(podName, statefulSetName+"-")
nominal, err := strconv.Atoi(nominalString) nominal, err := strconv.ParseInt(nominalString, 10, 32)
if err != nil { if err != nil {
return 0, fmt.Errorf("failed to detect shard index for Pod %s of StatefulSet %s, parsed %s: %w", podName, statefulSetName, nominalString, err) return 0, fmt.Errorf("failed to detect shard index for Pod %s of StatefulSet %s, parsed %s: %w", podName, statefulSetName, nominalString, err)
} }

View File

@@ -79,7 +79,10 @@ func (o *Options) AddFlags() {
klogFlags := flag.NewFlagSet("klog", flag.ExitOnError) klogFlags := flag.NewFlagSet("klog", flag.ExitOnError)
klog.InitFlags(klogFlags) klog.InitFlags(klogFlags)
o.flags.AddGoFlagSet(klogFlags) o.flags.AddGoFlagSet(klogFlags)
o.flags.Lookup("logtostderr").Value.Set("true") err := o.flags.Lookup("logtostderr").Value.Set("true")
if err != nil {
klog.Error(err)
}
o.flags.Lookup("logtostderr").DefValue = "true" o.flags.Lookup("logtostderr").DefValue = "true"
o.flags.Lookup("logtostderr").NoOptDefVal = "true" o.flags.Lookup("logtostderr").NoOptDefVal = "true"

View File

@@ -24,6 +24,7 @@ import (
"log" "log"
"os" "os"
"path" "path"
"path/filepath"
"regexp" "regexp"
"sort" "sort"
"strings" "strings"
@@ -165,7 +166,7 @@ func getLabelsDocumentation() (map[string][]string, error) {
} }
filePath := path.Join(docPath, file.Name()) filePath := path.Join(docPath, file.Name())
f, err := os.Open(filePath) f, err := os.Open(filepath.Clean(filePath))
if err != nil { if err != nil {
return nil, fmt.Errorf("cannot read file %s: %w", filePath, err) return nil, fmt.Errorf("cannot read file %s: %w", filePath, err)
} }