|
| 1 | +# Verification Tests |
| 2 | + |
| 3 | +**Table of Contents** |
| 4 | + |
| 5 | +- [Verification Tests](#verification-tests) |
| 6 | + - [Overview](#overview) |
| 7 | + - [Note](#note) |
| 8 | + - [`verify-govet-levee`](#verify-govet-leve) |
| 9 | + |
| 10 | +## Overview |
| 11 | + |
| 12 | +Verification tests for Kubernetes provide a mechanism to verify contributions for adherence to project conventions |
| 13 | +and best practices, and to validate generated build artifacts for soundness. |
| 14 | + |
| 15 | +All blocking verification tests can be executed via `make verify`. |
| 16 | +Individual verification tests also can be found in vestigial shell scripts at `hack/verify-*.sh`. |
| 17 | + |
| 18 | +Most verification tests are self-explanatory. |
| 19 | +`verify-govet`, for instance, performs `go vet` checks, which [defends against common mistakes](https://golang.org/cmd/vet/). |
| 20 | +The verification tests fails when `go vet` produces any findings. |
| 21 | +More complex verification tests are described below. |
| 22 | + |
| 23 | +### Note |
| 24 | + |
| 25 | +This documentation is a work in progress. This listing is incomplete. |
| 26 | + |
| 27 | +### `verify-govet-levee` |
| 28 | + |
| 29 | +Verification in `verify-govet-levee.sh` uses taint propagation analysis |
| 30 | +to defend against accidental logging of credentials. |
| 31 | +Struct fields which may contain credentials should be annotated as such using the `datapolicy` field tag. |
| 32 | +Field tagging was introduced by [KEP-1753](https://github.com/kubernetes/enhancements/issues/1753), and analysis was introduced by [KEP-1993](https://github.com/kubernetes/enhancements/issues/1933). |
| 33 | +Additional credential sources may be identified in analysis configuration (see below). |
| 34 | + |
| 35 | +Taint propagation analysis defends against both direct and indirect logging of credentials. |
| 36 | +Consider the following hypothetical snippet. |
| 37 | + |
| 38 | +```golang |
| 39 | +// kubernetes/cmd/kubelet/app/server.go |
| 40 | + |
| 41 | +// kubeConfigSpec struct holds info required to build a KubeConfig object |
| 42 | +type kubeConfigSpec struct { |
| 43 | + CACert *x509.Certificate |
| 44 | + APIServer string |
| 45 | + ClientName string |
| 46 | + TokenAuth *tokenAuth `datapolicy:"token"` |
| 47 | + ClientCertAuth *clientCertAuth `datapolicy:"security-key"` |
| 48 | +} |
| 49 | + |
| 50 | +func MyDangerousFunction(spec kubeConfigSpec) error { |
| 51 | + if spec.CACert == nil { |
| 52 | + err := fmt.Errorf("kubeConfigSpec missing expected CACert, got %#v", spec) // Dangerous logging! |
| 53 | + klog.Error(err) |
| 54 | + return err |
| 55 | + } |
| 56 | + |
| 57 | + if err := DoSomethingElse(spec); err != nil { |
| 58 | + klog.Error(err) // Dangerous logging! |
| 59 | + } |
| 60 | + |
| 61 | + return nil |
| 62 | +} |
| 63 | +``` |
| 64 | + |
| 65 | +In the above, when `spec.CACert == nil`, we log the `spec`. |
| 66 | +However, we know from the datapolicy field tags that the spec could contain one or more credentials and should not be logged. |
| 67 | +The analysis will detect this and cause the verification test to fail. |
| 68 | +The log call should be adjusted to extract exactly what information is relevant from the `spec`. |
| 69 | + |
| 70 | +The second `klog.Error` call is also problematic. |
| 71 | +The error returned by `DoSomethingElse` could potentially encapsulate the credential passed in by `spec`, and so we must not log it. |
| 72 | +That is, we consider `err` to be "tainted" by the call which has access to the credentials. |
| 73 | +The analysis will detect this as well and call the verification test to fail. |
| 74 | + |
| 75 | +When this analysis causes the verification test to fail, a developer has several options. |
| 76 | +In order of decreasing preference: |
| 77 | +* Reconstruct logging calls such that only non-secret information is passed. |
| 78 | +* Reconstruct a method which caused taint to spread to return indicators which are not logged directly, e.g. return `value, ok` rather than `value, err`. |
| 79 | +* Write a *sanitizer* whose return value is guaranteed to be log-safe. Add this sanitizer to the analysis configuration (see below). |
| 80 | +* Add the method where the log call occurs to the analysis configuration exclude-list. |
| 81 | + |
| 82 | +Analysis configuration can be found at [kubernetes/kubernetes/hack/testdata/levee/levee-config.yaml](https://github.com/kubernetes/kubernetes/blob/master/hack/testdata/levee/levee-config.yaml). |
| 83 | +Contact SIG-Security with any additional questions. |
0 commit comments