diff --git a/.gitignore b/.gitignore
index 4e258cbced3420643a6aaa401405208c78c0baab..4bfdd88308ed5366ced3f9ecab74fb8e2194fcbb 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,3 +2,5 @@ kube-bench
 *.swp
 vendor
 dist
+.vscode/
+hack/kind.test.yaml
diff --git a/Gopkg.lock b/Gopkg.lock
index f06a5d04148f80b61b68811746039a1fecb02962..4f431e3f8082db5e70abef269daf43bee544368f 100644
--- a/Gopkg.lock
+++ b/Gopkg.lock
@@ -2,23 +2,30 @@
 
 
 [[projects]]
+  digest = "1:938a2672d6ebbb7f7bc63eee3e4b9464c16ffcf77ec8913d3edbf32b4e3984dd"
   name = "github.com/fatih/color"
   packages = ["."]
+  pruneopts = "UT"
   revision = "570b54cabe6b8eb0bc2dfce68d964677d63b5260"
   version = "v1.5.0"
 
 [[projects]]
+  digest = "1:38c783cf85b9454cc02a1a8319239800ed0af6c1c864adf19cea0539e134adad"
   name = "github.com/fsnotify/fsnotify"
   packages = ["."]
+  pruneopts = "UT"
   revision = "4da3e2cfbabc9f751898f250b49f2439785783a1"
 
 [[projects]]
   branch = "master"
+  digest = "1:1ba1d79f2810270045c328ae5d674321db34e3aae468eb4233883b473c5c0467"
   name = "github.com/golang/glog"
   packages = ["."]
+  pruneopts = "UT"
   revision = "23def4e6c14b4da8ac2ed8007337bc5eb5007998"
 
 [[projects]]
+  digest = "1:145eff5207977eb95c3649a27cdc2e467d8a1c104810bc12b6a53745a91d823a"
   name = "github.com/hashicorp/hcl"
   packages = [
     ".",
@@ -29,106 +36,140 @@
     "hcl/token",
     "json/parser",
     "json/scanner",
-    "json/token"
+    "json/token",
   ]
+  pruneopts = "UT"
   revision = "23c074d0eceb2b8a5bfdbb271ab780cde70f05a8"
 
 [[projects]]
+  digest = "1:870d441fe217b8e689d7949fef6e43efbc787e50f200cb1e70dbca9204a1d6be"
   name = "github.com/inconshreveable/mousetrap"
   packages = ["."]
+  pruneopts = "UT"
   revision = "76626ae9c91c4f2a10f34cad8ce83ea42c93bb75"
   version = "v1.0"
 
 [[projects]]
+  digest = "1:510a2b056950ed12b4f3ac704ee1b34fd1920cb5b26f60f98d069de89c60adb7"
   name = "github.com/jinzhu/gorm"
   packages = [
     ".",
-    "dialects/postgres"
+    "dialects/postgres",
   ]
+  pruneopts = "UT"
   revision = "5174cc5c242a728b435ea2be8a2f7f998e15429b"
   version = "v1.0"
 
 [[projects]]
+  digest = "1:2cf1e05311b662e68d938f6655c6c5a44ae0e6b3995e390c75fcd8224afa48df"
   name = "github.com/jinzhu/inflection"
   packages = ["."]
+  pruneopts = "UT"
   revision = "1c35d901db3da928c72a72d8458480cc9ade058f"
 
 [[projects]]
+  digest = "1:38dd5cee5306173bfe78f8c401edec1e08f772551bee95a85617b4e39347e366"
   name = "github.com/lib/pq"
   packages = [
     ".",
     "hstore",
-    "oid"
+    "oid",
   ]
+  pruneopts = "UT"
   revision = "83612a56d3dd153a94a629cd64925371c9adad78"
 
 [[projects]]
+  digest = "1:9cbfcfd1ec741817698b844d17b523f54682a5f7c8683b1ec62b6b6542143240"
   name = "github.com/magiconair/properties"
   packages = ["."]
+  pruneopts = "UT"
   revision = "49d762b9817ba1c2e9d0c69183c2b4a8b8f1d934"
 
 [[projects]]
+  digest = "1:31fcf8f5f8f6cc36ef11182c0a0f63ba464e1a7ad9f0e92a7cf46f38bfc0adfd"
   name = "github.com/mattn/go-colorable"
   packages = ["."]
+  pruneopts = "UT"
   revision = "5411d3eea5978e6cdc258b30de592b60df6aba96"
 
 [[projects]]
+  digest = "1:fa610f9fe6a93f4a75e64c83673dfff9bf1a34bbb21e6102021b6bc7850834a3"
   name = "github.com/mattn/go-isatty"
   packages = ["."]
+  pruneopts = "UT"
   revision = "57fdcb988a5c543893cc61bce354a6e24ab70022"
 
 [[projects]]
+  digest = "1:56a0bd1a1f3809171d1abe0bfd389558be0cd672e858e1f831b88f806aa8764f"
   name = "github.com/mitchellh/mapstructure"
   packages = ["."]
+  pruneopts = "UT"
   revision = "06020f85339e21b2478f756a78e295255ffa4d6a"
 
 [[projects]]
+  digest = "1:128af710970a788bb2348dbcdde6b86fa41f92086297f909d659b6d3affc2902"
   name = "github.com/pelletier/go-toml"
   packages = ["."]
+  pruneopts = "UT"
   revision = "0131db6d737cfbbfb678f8b7d92e55e27ce46224"
 
 [[projects]]
+  digest = "1:1fccaaeae58b2a2f1af4dbf7eee92ff14f222e161d143bfd20082ef664f91216"
   name = "github.com/spf13/afero"
   packages = [
     ".",
-    "mem"
+    "mem",
   ]
+  pruneopts = "UT"
   revision = "57afd63c68602b63ed976de00dd066ccb3c319db"
 
 [[projects]]
+  digest = "1:9b28ee2984c69d78afe2ce52b1650ba91a6381f355ff08c1d0e53d9e66bd62fe"
   name = "github.com/spf13/cast"
   packages = ["."]
+  pruneopts = "UT"
   revision = "acbeb36b902d72a7a4c18e8f3241075e7ab763e4"
   version = "v1.1.0"
 
 [[projects]]
+  digest = "1:7ffc0983035bc7e297da3688d9fe19d60a420e9c38bef23f845c53788ed6a05e"
   name = "github.com/spf13/cobra"
   packages = ["."]
+  pruneopts = "UT"
   revision = "7b2c5ac9fc04fc5efafb60700713d4fa609b777b"
   version = "v0.0.1"
 
 [[projects]]
+  digest = "1:9f28b7e326b8cd1db556678b7ce679cf9bf888647e40922f91d9d40f451f942b"
   name = "github.com/spf13/jwalterweatherman"
   packages = ["."]
+  pruneopts = "UT"
   revision = "12bd96e66386c1960ab0f74ced1362f66f552f7b"
 
 [[projects]]
+  digest = "1:772bf4d1907ccb275aaa532ec6cb0d85fc61bd05648af28551590af3ea4e2d53"
   name = "github.com/spf13/pflag"
   packages = ["."]
+  pruneopts = "UT"
   revision = "4c012f6dcd9546820e378d0bdda4d8fc772cdfea"
 
 [[projects]]
+  digest = "1:f8e1a678a2571e265f4bf91a3e5e32aa6b1474a55cb0ea849750cc177b664d96"
   name = "github.com/spf13/viper"
   packages = ["."]
+  pruneopts = "UT"
   revision = "25b30aa063fc18e48662b86996252eabdcf2f0c7"
   version = "v1.0.0"
 
 [[projects]]
+  digest = "1:c9c0ba9ea00233c41b91e441cfd490f34b129bbfebcb1858979623bd8de07f72"
   name = "golang.org/x/sys"
   packages = ["unix"]
+  pruneopts = "UT"
   revision = "e24f485414aeafb646f6fca458b0bf869c0880a1"
 
 [[projects]]
+  digest = "1:8029e9743749d4be5bc9f7d42ea1659471767860f0cdc34d37c3111bd308a295"
   name = "golang.org/x/text"
   packages = [
     "internal/gen",
@@ -136,18 +177,29 @@
     "internal/ucd",
     "transform",
     "unicode/cldr",
-    "unicode/norm"
+    "unicode/norm",
   ]
+  pruneopts = "UT"
   revision = "e19ae1496984b1c655b8044a65c0300a3c878dd3"
 
 [[projects]]
+  digest = "1:cb130999076da4717267c51235d62b63228c330ad86160255cbe3276de4c9892"
   name = "gopkg.in/yaml.v2"
   packages = ["."]
+  pruneopts = "UT"
   revision = "c95af922eae69f190717a0b7148960af8c55a072"
 
 [solve-meta]
   analyzer-name = "dep"
   analyzer-version = 1
-  inputs-digest = "8d9a1b665b338530deef434f168913ba1184f835aa5bfed3a213a14c613bc17e"
+  input-imports = [
+    "github.com/fatih/color",
+    "github.com/golang/glog",
+    "github.com/jinzhu/gorm",
+    "github.com/jinzhu/gorm/dialects/postgres",
+    "github.com/spf13/cobra",
+    "github.com/spf13/viper",
+    "gopkg.in/yaml.v2",
+  ]
   solver-name = "gps-cdcl"
   solver-version = 1
diff --git a/README.md b/README.md
index 08da0105663da6da53959056d8f8532484980ec4..1bfe745096ce1c59c76f1a0343d670b62a5db7b7 100644
--- a/README.md
+++ b/README.md
@@ -28,45 +28,50 @@ You can choose to
 You can avoid installing kube-bench on the host by running it inside a container using the host PID namespace and mounting the `/etc` and `/var` directories where the configuration and other files are located on the host, so that kube-bench can check their existence and permissions.
 
 ```
-docker run --pid=host -v /etc:/etc:ro -v /var:/var:ro -t aquasec/kube-bench:latest <master|node>
+docker run --pid=host -v /etc:/etc:ro -v /var:/var:ro -t aquasec/kube-bench:latest [master|node]
 ```
 
 You can even use your own configs by mounting them over the default ones in `/opt/kube-bench/cfg/`
 
 ```
-docker run --pid=host -v /etc:/etc:ro -v /var:/var:ro -t -v path/to/my-config.yaml:/opt/kube-bench/cfg/config.yaml aquasec/kube-bench:latest <master|node>
+docker run --pid=host -v /etc:/etc:ro -v /var:/var:ro -t -v path/to/my-config.yaml:/opt/kube-bench/cfg/config.yaml aquasec/kube-bench:latest [master|node]
 ```
 
 > Note: the tests require either the kubelet or kubectl binary in the path in order to know the Kubernetes version. You can pass `-v $(which kubectl):/usr/bin/kubectl` to the above invocations to resolve this.
 
 ### Running in a kubernetes cluster
 
-You can run kube-bench inside a pod, but it will need access to the host's PID namespace in order to check the running processes, as well as access to some directories on the host where config files and other files are stored. 
+You can run kube-bench inside a pod, but it will need access to the host's PID namespace in order to check the running processes, as well as access to some directories on the host where config files and other files are stored.
 
-To run the tests on the master node, the pod needs to be scheduled on that node. This involves setting a nodeSelector and tolerations in the pod spec.
+Master nodes are automatically detected by kube-bench and will run master checks when possible.
+The detection is done by verifying that mandatory components for master are running. (see [config file](#configuration).
 
-The supplied `job-node.yaml` and `job-master.yaml` files can be applied to run the tests as a job. For example:
+The supplied `job.yaml` file can be applied to run the tests as a job. For example:
 
 ```bash
-$ kubectl apply -f job-master.yaml 
-job.batch/kube-bench-master created
+$ kubectl apply -f job.yaml
+job.batch/kube-bench created
 
 $ kubectl get pods
 NAME                      READY   STATUS              RESTARTS   AGE
-kube-bench-master-j76s9   0/1     ContainerCreating   0          3s
+kube-bench-j76s9   0/1     ContainerCreating   0          3s
 
 # Wait for a few seconds for the job to complete
 $ kubectl get pods
 NAME                      READY   STATUS      RESTARTS   AGE
-kube-bench-master-j76s9   0/1     Completed   0          11s
+kube-bench-j76s9   0/1     Completed   0          11s
 
 # The results are held in the pod's logs
-k logs kube-bench-master-j76s9
+k logs kube-bench-j76s9
 [INFO] 1 Master Node Security Configuration
 [INFO] 1.1 API Server
 ...
 ```
 
+You can still force to run specific master or node checks using respectively `job-master.yaml` and `job-node.yaml`.
+
+To run the tests on the master node, the pod needs to be scheduled on that node. This involves setting a nodeSelector and tolerations in the pod spec.
+
 The default labels applied to master nodes has changed since Kubernetes 1.11, so if you are using an older version you may need to modify the nodeSelector and tolerations to run the job on the master node.
 
 ### Installing from a container
@@ -77,7 +82,7 @@ This command copies the kube-bench binary and configuration files to your host f
 docker run --rm -v `pwd`:/host aquasec/kube-bench:latest install
 ```
 
-You can then run `./kube-bench <master|node>`.
+You can then run `./kube-bench [master|node]`.
 
 ### Installing from sources
 
@@ -93,8 +98,8 @@ go build -o kube-bench .
 # See all supported options
 ./kube-bench --help
 
-# Run the all checks on a master node
-./kube-bench master
+# Run the all checks
+./kube-bench
 
 ```
 
@@ -170,3 +175,17 @@ These operations are:
 Going forward we plan to release updates to kube-bench to add support for new releases of the Benchmark, which in turn we can anticipate being made for each new Kubernetes release.
 
 We welcome PRs and issue reports.
+
+# Testing locally with kind
+
+Our makefile contains targets to test your current version of kube-bench inside a [Kind](https://kind.sigs.k8s.io/) cluster. This can be very handy if you don't want to run a real kubernetes cluster for development purpose.
+
+First you'll need to create the cluster using `make kind-test-cluster` this will create a new cluster if it cannot be found on your machine. By default the cluster is named `kube-bench` but you can change the name by using the environment variable `KIND_PROFILE`.
+
+*If kind cannot be found on your system the target will try to install it using `go get`*
+
+Next you'll have to build the kube-bench docker image using `make build-docker`, then we will be able to push the docker image to the cluster using `make kind-push`.
+
+Finally we can use the `make kind-run` target to run the current version of kube-bench in the cluster and follow the logs of pods created. (Ctrl+C to exit)
+
+Everytime you want to test a change, you'll need to rebuild the docker image and push it to cluster before running it again. ( `make build-docker kind-push kind-run` )
\ No newline at end of file
diff --git a/cmd/common.go b/cmd/common.go
index 2cfa3106131afd9946a04001802d65dc49325fd5..b7f7793a318789d09856b07af0b16cc9a40e7040 100644
--- a/cmd/common.go
+++ b/cmd/common.go
@@ -31,32 +31,8 @@ var (
 
 func runChecks(nodetype check.NodeType) {
 	var summary check.Summary
-	var file string
-	var err error
-	var typeConf *viper.Viper
-
-	switch nodetype {
-	case check.MASTER:
-		file = masterFile
-	case check.NODE:
-		file = nodeFile
-	case check.FEDERATED:
-		file = federatedFile
-	}
-
-	runningVersion := ""
-	if kubeVersion == "" {
-		runningVersion, err = getKubeVersion()
-		if err != nil {
-			exitWithError(fmt.Errorf("Version check failed: %s\nAlternatively, you can specify the version with --version", err))
-		}
-	}
-	path, err := getConfigFilePath(kubeVersion, runningVersion, file)
-	if err != nil {
-		exitWithError(fmt.Errorf("can't find %s controls file in %s: %v", nodetype, cfgDir, err))
-	}
 
-	def := filepath.Join(path, file)
+	def := loadConfig(nodetype)
 	in, err := ioutil.ReadFile(def)
 	if err != nil {
 		exitWithError(fmt.Errorf("error opening %s controls file: %v", nodetype, err))
@@ -64,23 +40,15 @@ func runChecks(nodetype check.NodeType) {
 
 	glog.V(1).Info(fmt.Sprintf("Using benchmark file: %s\n", def))
 
-	// Merge kubernetes version specific config if any.
-	viper.SetConfigFile(path + "/config.yaml")
-	err = viper.MergeInConfig()
+	// Get the set of exectuables and config files we care about on this type of node.
+	typeConf := viper.Sub(string(nodetype))
+	binmap, err := getBinaries(typeConf)
+
+	// Checks that the executables we need for the node type are running.
 	if err != nil {
-		if os.IsNotExist(err) {
-			glog.V(2).Info(fmt.Sprintf("No version-specific config.yaml file in %s", path))
-		} else {
-			exitWithError(fmt.Errorf("couldn't read config file %s: %v", path+"/config.yaml", err))
-		}
-	} else {
-		glog.V(1).Info(fmt.Sprintf("Using config file: %s\n", viper.ConfigFileUsed()))
+		exitWithError(err)
 	}
 
-	// Get the set of exectuables and config files we care about on this type of node. This also
-	// checks that the executables we need for the node type are running.
-	typeConf = viper.Sub(string(nodetype))
-	binmap := getBinaries(typeConf)
 	confmap := getConfigFiles(typeConf)
 	svcmap := getServiceFiles(typeConf)
 
@@ -183,3 +151,58 @@ func prettyPrint(r *check.Controls, summary check.Summary) {
 		)
 	}
 }
+
+// loadConfig finds the correct config dir based on the kubernetes version,
+// merges any specific config.yaml file found with the main config
+// and returns the benchmark file to use.
+func loadConfig(nodetype check.NodeType) string {
+	var file string
+	var err error
+
+	switch nodetype {
+	case check.MASTER:
+		file = masterFile
+	case check.NODE:
+		file = nodeFile
+	case check.FEDERATED:
+		file = federatedFile
+	}
+
+	runningVersion := ""
+	if kubeVersion == "" {
+		runningVersion, err = getKubeVersion()
+		if err != nil {
+			exitWithError(fmt.Errorf("Version check failed: %s\nAlternatively, you can specify the version with --version", err))
+		}
+	}
+	path, err := getConfigFilePath(kubeVersion, runningVersion, file)
+	if err != nil {
+		exitWithError(fmt.Errorf("can't find %s controls file in %s: %v", nodetype, cfgDir, err))
+	}
+
+	// Merge kubernetes version specific config if any.
+	viper.SetConfigFile(path + "/config.yaml")
+	err = viper.MergeInConfig()
+	if err != nil {
+		if os.IsNotExist(err) {
+			glog.V(2).Info(fmt.Sprintf("No version-specific config.yaml file in %s", path))
+		} else {
+			exitWithError(fmt.Errorf("couldn't read config file %s: %v", path+"/config.yaml", err))
+		}
+	} else {
+		glog.V(1).Info(fmt.Sprintf("Using config file: %s\n", viper.ConfigFileUsed()))
+	}
+	return filepath.Join(path, file)
+}
+
+// isMaster verify if master components are running on the node.
+func isMaster() bool {
+	_ = loadConfig(check.MASTER)
+	glog.V(2).Info("Checking if the current node is running master components")
+	masterConf := viper.Sub(string(check.MASTER))
+	if _, err := getBinaries(masterConf); err != nil {
+		glog.V(2).Info(err)
+		return false
+	}
+	return true
+}
diff --git a/cmd/root.go b/cmd/root.go
index 5f525a279794c8b5241b2290344c39967e9ac316..eab044dce825189160cb09452be0d6ab428e9d10 100644
--- a/cmd/root.go
+++ b/cmd/root.go
@@ -20,6 +20,7 @@ import (
 	"os"
 
 	"github.com/aquasecurity/kube-bench/check"
+	"github.com/golang/glog"
 	"github.com/spf13/cobra"
 	"github.com/spf13/viper"
 )
@@ -34,8 +35,8 @@ var (
 	pgSQL              bool
 	checkList          string
 	groupList          string
-	masterFile         string
-	nodeFile           string
+	masterFile         = "master.yaml"
+	nodeFile           = "node.yaml"
 	federatedFile      string
 	noResults          bool
 	noSummary          bool
@@ -47,6 +48,14 @@ var RootCmd = &cobra.Command{
 	Use:   os.Args[0],
 	Short: "Run CIS Benchmarks checks against a Kubernetes deployment",
 	Long:  `This tool runs the CIS Kubernetes Benchmark (https://www.cisecurity.org/benchmark/kubernetes/)`,
+	Run: func(cmd *cobra.Command, args []string) {
+		if isMaster() {
+			glog.V(1).Info("== Running master checks ==\n")
+			runChecks(check.MASTER)
+		}
+		glog.V(1).Info("== Running node checks ==\n")
+		runChecks(check.NODE)
+	},
 }
 
 // Execute adds all child commands to the root command sets flags appropriately.
diff --git a/cmd/util.go b/cmd/util.go
index 97cd94a6d314d644a1149de69bee831a2dcd9510..9988cb17cf619698d48e3282ff10a470c4bdc6a3 100644
--- a/cmd/util.go
+++ b/cmd/util.go
@@ -72,8 +72,9 @@ func ps(proc string) string {
 	return string(out)
 }
 
-// getBinaries finds which of the set of candidate executables are running
-func getBinaries(v *viper.Viper) map[string]string {
+// getBinaries finds which of the set of candidate executables are running.
+// It returns an error if one mandatory executable is not running.
+func getBinaries(v *viper.Viper) (map[string]string, error) {
 	binmap := make(map[string]string)
 
 	for _, component := range v.GetStringSlice("components") {
@@ -87,7 +88,7 @@ func getBinaries(v *viper.Viper) map[string]string {
 		if len(bins) > 0 {
 			bin, err := findExecutable(bins)
 			if err != nil && !optional {
-				exitWithError(fmt.Errorf("need %s executable but none of the candidates are running", component))
+				return nil, fmt.Errorf("need %s executable but none of the candidates are running", component)
 			}
 
 			// Default the executable name that we'll substitute to the name of the component
@@ -101,7 +102,7 @@ func getBinaries(v *viper.Viper) map[string]string {
 		}
 	}
 
-	return binmap
+	return binmap, nil
 }
 
 // getConfigFilePath locates the config files we should be using based on either the specified
diff --git a/cmd/util_test.go b/cmd/util_test.go
index cf8cb0d506bd90f6cf95af7010209bb8902a4685..1dea45d863a0fe4811cbb76d9718acd290f090a9 100644
--- a/cmd/util_test.go
+++ b/cmd/util_test.go
@@ -109,38 +109,51 @@ func TestFindExecutable(t *testing.T) {
 
 func TestGetBinaries(t *testing.T) {
 	cases := []struct {
-		config map[string]interface{}
-		psOut  string
-		exp    map[string]string
+		config    map[string]interface{}
+		psOut     string
+		exp       map[string]string
+		expectErr bool
 	}{
 		{
-			config: map[string]interface{}{"components": []string{"apiserver"}, "apiserver": map[string]interface{}{"bins": []string{"apiserver", "kube-apiserver"}}},
-			psOut:  "kube-apiserver",
-			exp:    map[string]string{"apiserver": "kube-apiserver"},
+			config:    map[string]interface{}{"components": []string{"apiserver"}, "apiserver": map[string]interface{}{"bins": []string{"apiserver", "kube-apiserver"}}},
+			psOut:     "kube-apiserver",
+			exp:       map[string]string{"apiserver": "kube-apiserver"},
+			expectErr: false,
 		},
 		{
 			// "thing" is not in the list of components
-			config: map[string]interface{}{"components": []string{"apiserver"}, "apiserver": map[string]interface{}{"bins": []string{"apiserver", "kube-apiserver"}}, "thing": map[string]interface{}{"bins": []string{"something else", "thing"}}},
-			psOut:  "kube-apiserver thing",
-			exp:    map[string]string{"apiserver": "kube-apiserver"},
+			config:    map[string]interface{}{"components": []string{"apiserver"}, "apiserver": map[string]interface{}{"bins": []string{"apiserver", "kube-apiserver"}}, "thing": map[string]interface{}{"bins": []string{"something else", "thing"}}},
+			psOut:     "kube-apiserver thing",
+			exp:       map[string]string{"apiserver": "kube-apiserver"},
+			expectErr: false,
 		},
 		{
 			// "anotherthing" in list of components but doesn't have a defintion
-			config: map[string]interface{}{"components": []string{"apiserver", "anotherthing"}, "apiserver": map[string]interface{}{"bins": []string{"apiserver", "kube-apiserver"}}, "thing": map[string]interface{}{"bins": []string{"something else", "thing"}}},
-			psOut:  "kube-apiserver thing",
-			exp:    map[string]string{"apiserver": "kube-apiserver"},
+			config:    map[string]interface{}{"components": []string{"apiserver", "anotherthing"}, "apiserver": map[string]interface{}{"bins": []string{"apiserver", "kube-apiserver"}}, "thing": map[string]interface{}{"bins": []string{"something else", "thing"}}},
+			psOut:     "kube-apiserver thing",
+			exp:       map[string]string{"apiserver": "kube-apiserver"},
+			expectErr: false,
 		},
 		{
 			// more than one component
-			config: map[string]interface{}{"components": []string{"apiserver", "thing"}, "apiserver": map[string]interface{}{"bins": []string{"apiserver", "kube-apiserver"}}, "thing": map[string]interface{}{"bins": []string{"something else", "thing"}}},
-			psOut:  "kube-apiserver \nthing",
-			exp:    map[string]string{"apiserver": "kube-apiserver", "thing": "thing"},
+			config:    map[string]interface{}{"components": []string{"apiserver", "thing"}, "apiserver": map[string]interface{}{"bins": []string{"apiserver", "kube-apiserver"}}, "thing": map[string]interface{}{"bins": []string{"something else", "thing"}}},
+			psOut:     "kube-apiserver \nthing",
+			exp:       map[string]string{"apiserver": "kube-apiserver", "thing": "thing"},
+			expectErr: false,
 		},
 		{
 			// default binary to component name
-			config: map[string]interface{}{"components": []string{"apiserver", "thing"}, "apiserver": map[string]interface{}{"bins": []string{"apiserver", "kube-apiserver"}}, "thing": map[string]interface{}{"bins": []string{"something else", "thing"}, "optional": true}},
-			psOut:  "kube-apiserver \notherthing some params",
-			exp:    map[string]string{"apiserver": "kube-apiserver", "thing": "thing"},
+			config:    map[string]interface{}{"components": []string{"apiserver", "thing"}, "apiserver": map[string]interface{}{"bins": []string{"apiserver", "kube-apiserver"}}, "thing": map[string]interface{}{"bins": []string{"something else", "thing"}, "optional": true}},
+			psOut:     "kube-apiserver \notherthing some params",
+			exp:       map[string]string{"apiserver": "kube-apiserver", "thing": "thing"},
+			expectErr: false,
+		},
+		{
+			// missing mandatory component
+			config:    map[string]interface{}{"components": []string{"apiserver", "thing"}, "apiserver": map[string]interface{}{"bins": []string{"apiserver", "kube-apiserver"}}, "thing": map[string]interface{}{"bins": []string{"something else", "thing"}, "optional": true}},
+			psOut:     "otherthing some params",
+			exp:       map[string]string{"apiserver": "kube-apiserver", "thing": "thing"},
+			expectErr: true,
 		},
 	}
 
@@ -153,8 +166,12 @@ func TestGetBinaries(t *testing.T) {
 			for k, val := range c.config {
 				v.Set(k, val)
 			}
-			m := getBinaries(v)
-			if !reflect.DeepEqual(m, c.exp) {
+			m, err := getBinaries(v)
+			if c.expectErr {
+				if err == nil {
+					t.Fatal("Got nil Expected error")
+				}
+			} else if !reflect.DeepEqual(m, c.exp) {
 				t.Fatalf("Got %v\nExpected %v", m, c.exp)
 			}
 		})
diff --git a/hack/debug.yaml b/hack/debug.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..e26e447bc1f5d9a8991b7075023d3e6edc1b8b78
--- /dev/null
+++ b/hack/debug.yaml
@@ -0,0 +1,46 @@
+# use this pod with: kubectl run ubuntu -it --pid=host  -- /bin/bash
+# this allows you to debug what is running on the host.
+apiVersion: v1
+kind: Pod
+metadata:
+  name: ubuntu
+spec:
+  hostPID: true
+  containers:
+  - name: ubuntu
+    image: ubuntu
+    command: [ "/bin/bash", "-c", "--" ]
+    args: [ "while true; do sleep 30; done;" ]
+    volumeMounts:
+    - name: var-lib-kubelet
+      mountPath: /var/lib/kubelet
+    - name: etc-systemd
+      mountPath: /etc/systemd
+    - name: etc-kubernetes
+      mountPath: /etc/kubernetes
+      # /usr/bin is mounted to access kubectl / kubelet, for auto-detecting the Kubernetes version. 
+      # You can omit this mount if you specify --version as part of the command.           
+    - name: usr-bin
+      mountPath: /usr/bin
+    - name: kind-bin
+      mountPath: /kind/bin
+    resources:
+      limits:
+        memory: "128Mi"
+        cpu: "500m"
+  volumes:
+  - name: var-lib-kubelet
+    hostPath:
+      path: "/var/lib/kubelet"
+  - name: etc-systemd
+    hostPath:
+      path: "/etc/systemd"
+  - name: etc-kubernetes
+    hostPath:
+      path: "/etc/kubernetes"
+  - name: usr-bin
+    hostPath:
+      path: "/usr/bin"
+  - name: kind-bin
+    hostPath:
+      path: "/kind/bin"
diff --git a/hack/kind.yaml b/hack/kind.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..b58811a0d53d365f19f2b4cce8e9b39388c43bcb
--- /dev/null
+++ b/hack/kind.yaml
@@ -0,0 +1,50 @@
+apiVersion: batch/v1
+kind: Job
+metadata:
+  name: kube-bench
+spec:
+  template:
+    metadata:
+      labels:
+        app: kube-bench
+    spec:
+      hostPID: true
+      containers:
+      - name: kube-bench
+        image: aquasec/kube-bench:${VERSION}
+        command: ["kube-bench"]
+        volumeMounts:
+        - name: var-lib-etcd
+          mountPath: /var/lib/etcd
+        - name: var-lib-kubelet
+          mountPath: /var/lib/kubelet
+        - name: etc-systemd
+          mountPath: /etc/systemd
+        - name: etc-kubernetes
+          mountPath: /etc/kubernetes
+          # /usr/bin is mounted to access kubectl / kubelet, for auto-detecting the Kubernetes version. 
+          # You can omit this mount if you specify --version as part of the command.           
+        - name: usr-bin
+          mountPath: /usr/bin
+        - name: kind-bin
+          mountPath: /kind/bin
+      restartPolicy: Never
+      volumes:
+      - name: var-lib-etcd
+        hostPath:
+          path: "/var/lib/etcd"
+      - name: var-lib-kubelet
+        hostPath:
+          path: "/var/lib/kubelet"
+      - name: etc-systemd
+        hostPath:
+          path: "/etc/systemd"
+      - name: etc-kubernetes
+        hostPath:
+          path: "/etc/kubernetes"
+      - name: usr-bin
+        hostPath:
+          path: "/usr/bin"
+      - name: kind-bin
+        hostPath:
+          path: "/kind/bin"
diff --git a/job.yaml b/job.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..3fae9e1c97d9f95c88d1a8411293cd9907414968
--- /dev/null
+++ b/job.yaml
@@ -0,0 +1,45 @@
+apiVersion: batch/v1
+kind: Job
+metadata:
+  name: kube-bench
+spec:
+  template:
+    metadata:
+      labels:
+        app: kube-bench
+    spec:
+      hostPID: true
+      containers:
+      - name: kube-bench
+        image: aquasec/kube-bench:latest
+        command: ["kube-bench"]
+        volumeMounts:
+        - name: var-lib-etcd
+          mountPath: /var/lib/etcd
+        - name: var-lib-kubelet
+          mountPath: /var/lib/kubelet
+        - name: etc-systemd
+          mountPath: /etc/systemd
+        - name: etc-kubernetes
+          mountPath: /etc/kubernetes
+          # /usr/bin is mounted to access kubectl / kubelet, for auto-detecting the Kubernetes version. 
+          # You can omit this mount if you specify --version as part of the command.           
+        - name: usr-bin
+          mountPath: /usr/bin
+      restartPolicy: Never
+      volumes:
+      - name: var-lib-etcd
+        hostPath:
+          path: "/var/lib/etcd"
+      - name: var-lib-kubelet
+        hostPath:
+          path: "/var/lib/kubelet"
+      - name: etc-systemd
+        hostPath:
+          path: "/etc/systemd"
+      - name: etc-kubernetes
+        hostPath:
+          path: "/etc/kubernetes"
+      - name: usr-bin
+        hostPath:
+          path: "/usr/bin"
diff --git a/makefile b/makefile
index c0a68ddc15652298e8510da74c2b3c17dcb16b6b..2e1bc29cdbde5f23fa10c6a31bea6bd044fefb13 100644
--- a/makefile
+++ b/makefile
@@ -1,7 +1,72 @@
 SOURCES := $(shell find . -name '*.go')
-TARGET_OS := linux
 BINARY := kube-bench
+DOCKER_REGISTRY ?= aquasec
+VERSION ?= $(shell git rev-parse --short=7 HEAD)
+IMAGE_NAME ?= $(DOCKER_REGISTRY)/$(BINARY):$(VERSION)
+TARGET_OS := linux
+BUILD_OS := linux
+uname := $(shell uname -s)
+
+ifneq ($(findstring Microsoft,$(shell uname -r)),)
+	BUILD_OS := windows
+else ifeq ($(uname),Linux)
+	BUILD_OS := linux
+else ifeq ($(uname),Darwin)
+	BUILD_OS := darwin
+endif
+
+# kind cluster name to use
+KIND_PROFILE ?= kube-bench
+KIND_CONTAINER_NAME=$(KIND_PROFILE)-control-plane
+
+build: kube-bench
 
 $(BINARY): $(SOURCES)
 	GOOS=$(TARGET_OS) go build -o $(BINARY) .
 
+# builds the current dev docker version
+build-docker:
+	docker build --build-arg BUILD_DATE=$(shell date -u +"%Y-%m-%dT%H:%M:%SZ") \
+             --build-arg VCS_REF=$(shell git rev-parse --short HEAD) \
+             -t $(IMAGE_NAME) .
+
+tests:
+	go test -race -timeout 30s -cover ./cmd ./check
+
+# creates a kind cluster to be used for development.
+HAS_KIND := $(shell command -v kind;)
+kind-test-cluster:
+ifndef HAS_KIND
+	go get -u sigs.k8s.io/kind
+endif
+	@if [ -z $$(kind get clusters | grep $(KIND_PROFILE)) ]; then\
+		echo "Could not find $(KIND_PROFILE) cluster. Creating...";\
+		kind create cluster --name $(KIND_PROFILE) --image kindest/node:v1.11.3 --wait 5m;\
+	fi
+
+# pushses the current dev version to the kind cluster.
+kind-push:
+	docker save $(IMAGE_NAME) -o kube-bench.tar.gz; \
+	docker cp kube-bench.tar.gz $(KIND_CONTAINER_NAME):/kube-bench.tar.gz; \
+	docker exec $(KIND_CONTAINER_NAME) docker load -i /kube-bench.tar.gz;
+	-rm -f kube-bench.tar.gz
+
+# runs the current version on kind using a job and follow logs
+kind-run: KUBECONFIG = "$(shell kind get kubeconfig-path --name="$(KIND_PROFILE)")"
+kind-run: ensure-stern
+	sed "s/\$${VERSION}/$(VERSION)/" ./hack/kind.yaml > ./hack/kind.test.yaml
+	-KUBECONFIG=$(KUBECONFIG) \
+		kubectl delete job kube-bench 
+	KUBECONFIG=$(KUBECONFIG) \
+		kubectl apply -f ./hack/kind.test.yaml
+	KUBECONFIG=$(KUBECONFIG) \
+		stern -l app=kube-bench --container kube-bench
+
+# ensures that stern is installed
+HAS_STERN := $(shell command -v stern;)
+ensure-stern:
+ifndef HAS_STERN
+	curl -LO https://github.com/wercker/stern/releases/download/1.10.0/stern_$(BUILD_OS)_amd64 && \
+		chmod +rx ./stern_$(BUILD_OS)_amd64 && \
+    	mv ./stern_$(BUILD_OS)_amd64 /usr/local/bin/stern
+endif