Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add README and documentation #5

Merged
merged 19 commits into from Sep 19, 2020
19 changes: 19 additions & 0 deletions .circleci/config.yml
Expand Up @@ -16,6 +16,21 @@ jobs:
command: |
make lint

- run:
name: Ensure generated docs are up-to-date
command: |
make generated-docs
git diff --exit-code HEAD

test:
executor: custom
steps:
- checkout
- run:
name: Run unit tests
command: |
make test

workflows:
version: 2
build:
Expand All @@ -24,3 +39,7 @@ workflows:
filters:
tags:
only: /.*/
- test:
filters:
tags:
only: /.*/
1 change: 1 addition & 0 deletions .golangci.yml
Expand Up @@ -54,6 +54,7 @@ linters-settings:
- unnecessaryDefer
- importShadow
- emptyStringTest
- hugeParam
nolintlint:
allow-leading-space: false # require machine-readable nolint directives (i.e. with no leading space)
allow-unused: false # report any unused nolint directives
Expand Down
27 changes: 23 additions & 4 deletions Makefile
Expand Up @@ -60,14 +60,33 @@ staticcheck: $(STATICCHECK_BIN)
.PHONY: lint
lint: golangci-lint staticcheck

#############
## Compile ##
#############
####################
## Code generation #
####################

.PHONY: generated-docs
generated-docs: build
./bin/kube-linter templates list --format markdown > docs/generated/templates.md
./bin/kube-linter checks list --format markdown > docs/generated/checks.md

.PHONY: packr
packr: $(PACKR_BIN)
packr

#############
## Compile ##
#############


.PHONY: build
build: packr
go build -o kube-linter ./cmd/kubelinter
go build -o ./bin/kube-linter ./cmd/kube-linter

##########
## Test ##
##########

.PHONY: test
test: packr
go test ./...

32 changes: 32 additions & 0 deletions README.md
@@ -1 +1,33 @@
# kube-linter

kube-linter is a static analysis tool that checks Kubernetes YAML files to ensure the applications represented in them
adhere to best practices.

In detail, `kube-linter` is a binary that takes in paths to YAML files, and runs a list of checks
against them. If any lint errors are found, they are printed to standard error, and `kube-linter` returns a non-zero
exit code.

The list of checks that is run is configurable. `kube-linter` comes with several built-in checks, only some of which
are enabled by default. Users can also create custom checks.

## Install

If you have `go` installed, you can run `go get golang.stackrox.io/kube-linter/cmd/kube-linter`.

Alternatively, `kube-linter` binaries can be downloaded from [the Releases page](https://github.com/stackrox/kube-linter/releases).
Download the `kube-linter` binary, and add it to your PATH.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMHO a readme in an open source repository should always include custom build instructions and contributing guidelines (or references to these)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added instructions for building from source. Contributing guidelines, will do in a follow-up -- we still need to iron those out.


You can also build `kube-linter` from source by cloning the repo, and running `make build`. This will compile a `kube-linter`
binary into the `bin` folder inside the repo.

Note that you will need to have the `go` command installed for this to work.
To install the Go command, follow the instructions [here](https://golang.org/doc/install).

## Usage

See the [documentation](./docs) for details on how to get started.

# WARNING: Breaking changes possible

kube-linter is currently in a very early stage of development. There may be breaking changes to the command usage, flags
and config file formats.
2 changes: 2 additions & 0 deletions bin/.gitignore
@@ -0,0 +1,2 @@
*
!.gitignore
File renamed without changes.
19 changes: 19 additions & 0 deletions config.yaml.example
@@ -0,0 +1,19 @@
# customChecks defines custom checks.
customChecks:
- name: "required-label-app"
template: "required-label"
params:
key: "app"
checks:
# if doNotAutoAddDefaults is true, default checks are not automatically added.
# Otherwise, they are.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove, this is pretty obvious based on the previous line

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, I think doNotAutoAddDefaults is backwards, should be autoAddDefaults that defaults to true

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's also just a bit too verbose

doNotAutoAddDefaults: false

# include explicitly adds checks, by name. You can reference any of the built-in checks.
# Note that customChecks defined above are included automatically.
include:
- "required-label-owner"
# exclude explicitly excludes checks, by name. exclude has the highest priority: if a check is
# in exclude, then it is not considered, even if it is in include as well.
exclude:
- "privileged"
38 changes: 38 additions & 0 deletions docs/README.md
@@ -0,0 +1,38 @@

# Documentation

Welcome to the `kube-linter` documentation. Read on for more detailed information about using and configuring the tool.

## Exploring the CLI

You can run `kube-linter --help` to see a list of supported commands and flags. For each subcommand, you can
run `kube-linter <subcommand> --help` to see detailed help text and flags for it.

## Running the linter

To lint directories or files, simply run `./kube-linter lint files_or_dirs ...`. If a directory is passed, all files
with `.yaml` or `.yml` extensions are parsed, and Kubernetes objects are loaded from them. If a file is passed,
it is parsed irrespective of extension.

Users can pass a config file using the `--config` flag to control which checks are executed, and to configure custom checks.
An example config file is provided [here](../config.yaml.example).

## Built-in checks

`kube-linter` comes with a list of built-in checks, which you can find [here](generated/checks.md). Only some
built-in checks are enabled by default -- others must be explicitly enabled in the config.

## Custom checks

### Check Templates

In `kube-linter`, checks are concrete realizations of check templates. A check template describes a class of check -- it
contains logic (written in Go code) that would execute the check, and lays out (zero or more) parameters that it takes.

The list of supported check templates, along with their metadata, can be found [here](generated/templates.md).

### Custom checks

All checks in `kube-linter` are defined by referencing a check template, passing parameters to it, and adding additional
check specific metadata (like check name and description). Users can configure custom checks the same way built-in checks
are configured, and add them to the config file. The built-in checks are specified [here](../internal/builtinchecks).
7 changes: 7 additions & 0 deletions docs/generated/checks.md
@@ -0,0 +1,7 @@
The following table enumerates built-in checks:

| Name | Enabled by default | Description | Template | Parameters |
| ---- | ------------------ | ----------- | -------- | ---------- |
| env-var-secret | No | Alert on objects using a secret in an environment variable | env-var |- `name`: `.*secret.*` <br />|
| privileged-container | Yes | Alert on deployments with containers running in privileged mode | privileged | none |
| required-label-owner | No | Alert on objects without the 'owner' label | required-label |- `key`: `owner` <br />|
7 changes: 7 additions & 0 deletions docs/generated/templates.md
@@ -0,0 +1,7 @@
The following table enumerates supported check templates:

| Name | Description | Supported Objects | Parameters |
| ---- | ----------- | ----------------- | ---------- |
| env-var | Flag environment variables that match the provided patterns | DeploymentLike |- `name` (required): A regex for the env var name <br />- `value`: A regex for the env var value <br />|
| privileged | Flag privileged containers | DeploymentLike | none |
| required-label | Flag objects not carrying at least one label matching the provided patterns | Any |- `key` (required): A regex for the key of the required label <br />- `value`: A regex for the value of the required label <br />|
2 changes: 2 additions & 0 deletions go.mod
Expand Up @@ -3,13 +3,15 @@ module golang.stackrox.io/kube-linter
go 1.14

require (
github.com/Masterminds/sprig/v3 v3.1.0
github.com/fatih/color v1.9.0
github.com/ghodss/yaml v1.0.0
github.com/gobuffalo/packr v1.30.1
github.com/golangci/golangci-lint v1.30.0
github.com/pkg/errors v0.9.1
github.com/spf13/cobra v1.0.0
github.com/stretchr/objx v0.2.0 // indirect
github.com/stretchr/testify v1.6.1
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 // indirect
honnef.co/go/tools v0.0.1-2020.1.5
Expand Down
18 changes: 18 additions & 0 deletions go.sum
Expand Up @@ -28,8 +28,14 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/Djarvur/go-err113 v0.0.0-20200511133814-5174e21577d5 h1:XTrzB+F8+SpRmbhAH8HLxhiiG6nYNwaBZjrFps1oWEk=
github.com/Djarvur/go-err113 v0.0.0-20200511133814-5174e21577d5/go.mod h1:4UJr5HIiMZrwgkSPdsjy2uOQExX/WEILpIrO9UPGuXs=
github.com/Masterminds/goutils v1.1.0 h1:zukEsf/1JZwCMgHiK3GZftabmxiCw4apj3a28RPBiVg=
github.com/Masterminds/goutils v1.1.0/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU=
github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww=
github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y=
github.com/Masterminds/semver/v3 v3.1.0 h1:Y2lUDsFKVRSYGojLJ1yLxSXdMmMYTYls0rCvoqmMUQk=
github.com/Masterminds/semver/v3 v3.1.0/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs=
github.com/Masterminds/sprig/v3 v3.1.0 h1:j7GpgZ7PdFqNsmncycTHsLmVPf5/3wJtlgW9TNDYD9Y=
github.com/Masterminds/sprig/v3 v3.1.0/go.mod h1:ONGMf7UfYGAbMXCZmQLy8x3lCDIPrEZE/rU8pmrbihA=
github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
github.com/OpenPeeDeeP/depguard v1.0.1 h1:VlW4R6jmBIv3/u1JNlawEvJMM4J+dPORPaZasQee8Us=
Expand Down Expand Up @@ -220,6 +226,7 @@ github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OI
github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY=
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
Expand Down Expand Up @@ -259,8 +266,12 @@ github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0m
github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I=
github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/huandu/xstrings v1.3.1 h1:4jgBlKK6tLKFvO8u5pmYjG91cqytmDCDvGh7ECVFfFs=
github.com/huandu/xstrings v1.3.1/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
github.com/imdario/mergo v0.3.8 h1:CGgOkSJeqMRmt0D9XLWExdT4m4F1vd3FV3VPt+0VxkQ=
github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/jingyugao/rowserrcheck v0.0.0-20191204022205-72ab7603b68a h1:GmsqmapfzSJkm28dhRoHz2tLRbJmqhU86IPgBtN3mmk=
Expand Down Expand Up @@ -325,6 +336,8 @@ github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpe
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
github.com/mitchellh/copystructure v1.0.0 h1:Laisrj+bAB6b/yJwB5Bt3ITZhGJdqmxquMKeZ+mmkFQ=
github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw=
github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
Expand All @@ -335,6 +348,8 @@ github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0Qu
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/reflectwalk v1.0.0 h1:9D+8oIskB4VJBN5SFlmc27fSlIBZaov1Wpk/IfikLNY=
github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
Expand Down Expand Up @@ -440,6 +455,8 @@ github.com/spf13/afero v1.2.2 h1:5jhuqJyZCZf2JRofRvN/nIFgIWNzPa3/Vz8mYylgbWc=
github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
github.com/spf13/cast v1.3.0 h1:oget//CVOEoFewqQxwr0Ej5yjygnqGkvggSE/gB35Q8=
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/spf13/cast v1.3.1 h1:nFm6S0SMdyzrzcmThSipiEubIDy8WEXKNZ0UOgiRpng=
github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=
github.com/spf13/cobra v1.0.0 h1:6m/oheQuQ13N9ks4hubMG6BnvwOeaJrqSPLahSnczz8=
github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE=
Expand Down Expand Up @@ -509,6 +526,7 @@ golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8U
golang.org/x/crypto v0.0.0-20190621222207-cc06ce4a13d4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200414173820-0848c9571904/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
Expand Down
25 changes: 19 additions & 6 deletions internal/builtinchecks/built_in_checks.go
Expand Up @@ -14,18 +14,31 @@ var (

// LoadInto loads built-in checks into the registry.
func LoadInto(registry checkregistry.CheckRegistry) error {
checks, err := List()
if err != nil {
return err
}
for _, chk := range checks {
if err := registry.Register(&chk); err != nil {
return errors.Wrapf(err, "registering default check %s", chk.Name)
}
}
return nil
}

// List lists built-in checks.
func List() ([]check.Check, error) {
var out []check.Check
for _, fileName := range box.List() {
contents, err := box.Find(fileName)
if err != nil {
return errors.Wrapf(err, "loading default check from %s", fileName)
return nil, errors.Wrapf(err, "loading default check from %s", fileName)
}
var chk check.Check
if err := yaml.Unmarshal(contents, &chk); err != nil {
return errors.Wrapf(err, "unmarshaling default check from %s", fileName)
}
if err := registry.Register(&chk); err != nil {
return errors.Wrapf(err, "registering default check from %s", fileName)
return nil, errors.Wrapf(err, "unmarshaling default check from %s", fileName)
}
out = append(out, chk)
}
return nil
return out, nil
}
1 change: 1 addition & 0 deletions internal/check/template.go
Expand Up @@ -25,6 +25,7 @@ type ObjectKindsDesc struct {
// A Template is a template for a check.
type Template struct {
Name string
Description string
SupportedObjectKinds ObjectKindsDesc
Parameters []ParameterDesc
Instantiate func(params map[string]string) (Func, error)
Expand Down