Repository: Shopify/kubeaudit
Pull request #427 (2022-05-23 02:48:17)

✨ Add the --context option
##### Description

As for `kubectl` command line tool, the option `-c/--context` is added to specify a context. The `-c` flag is therefore no longer used to specify. the kubeconfig path.

##### Type of change

- [x] New feature :sparkles:
- [x] This change requires a documentation update :book:
- [x] Breaking changes :warning:
##### How Has This Been Tested?

<!-- Please describe the tests that you ran to verify your changes. Provide instructions so we can reproduce. Please also list any relevant details for your test configuration -->

- [x] Added unit test in `kubeaudit_test.go` to test invalid context name
- [x] Instead of specify a context with the  `kubectl cluster-info --context <CONTEXT>` command I ran a `kubeaudit limits`  with the `--context <CLUSTER>` flag.
- [x] The help information is updated. 
  ```
  $ ./kubeaudit --help                                        
  Kubeaudit audits Kubernetes clusters for common security controls.
  
  ...
  
  Flags:
    -c, --context string       The name of the kubeconfig context to use
    -e, --exitcode int         Exit code to use if there are results with severity of "error". Conventionally, 0 is used for success and all non-zero codes for an error. (default 2)
    -p, --format string        The output format to use (one of "pretty", "logrus", "json") (default "pretty")
    -h, --help                 help for kubeaudit
    -g, --includegenerated     Include generated resources in scan  (eg. pods generated by deployments).
        --kubeconfig string    Path to local Kubernetes config file. Only used in local mode (default is $HOME/.kube/config)
    -f, --manifest string      Path to the yaml configuration to audit. Only used in manifest mode.
    -m, --minseverity string   Set the lowest severity level to report (one of "error", "warning", "info") (default "info")
    -n, --namespace string     Only audit resources in the specified namespace. Not currently supported in manifest mode.
  ```

##### Checklist:

- [ ] I have :tophat: my changes (A 🎩 specifically includes pulling down changes, setting them up, and manually testing the changed features and potential side effects to make sure nothing is broken)
- [ ] I have performed a self-review of my own code
- [ ] I have made corresponding changes to the documentation
- [ ] I have added tests that prove my fix is effective or that my feature works
- [ ] New and existing unit tests pass locally with my changes
- [ ] The test coverage did not decrease
- [ ] I have signed the appropriate [Contributor License Agreement](https://cla.shopify.com/)


jerr: 👆 rebased on the `main` branch to fix tests in CI (with KinD 1.20 nodes) 
jerr: 👆 rebased on the `main` branch to use the dynamic client

Patch:
diff --git a/README.md b/README.md
index caeef4c..5333af8 100644
--- a/README.md
+++ b/README.md
@@ -156,9 +156,9 @@ kubeaudit all
 
 ### Local Mode
 
-Kubeaudit will try to connect to a cluster using the local kubeconfig file (`$HOME/.kube/config`). A different kubeconfig location can be specified using the `-c/--kubeconfig` flag.
+Kubeaudit will try to connect to a cluster using the local kubeconfig file (`$HOME/.kube/config`). A different kubeconfig location can be specified using the `--kubeconfig` flag. To specify a context of the kubeconfig, use the `-c/--context` flag.
 ```
-kubeaudit all -c "/path/to/config"
+kubeaudit all --kubeconfig "/path/to/config" --context my_cluster
 ```
 
 For more information on kubernetes config files, see https://kubernetes.io/docs/concepts/configuration/organize-cluster-access-kubeconfig/
@@ -212,7 +212,8 @@ Auditors can also be run individually.
 | Short | Long               | Description                                                                                                                                            |
 | :---- | :----------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------- |
 |       | --format           | The output format to use (one of "pretty", "logrus", "json") (default is "pretty")                                                                     |
-| -c    | --kubeconfig       | Path to local Kubernetes config file. Only used in local mode (default is `$HOME/.kube/config`)                                                        |
+|       | --kubeconfig       | Path to local Kubernetes config file. Only used in local mode (default is `$HOME/.kube/config`)                                                        |
+| -c    | --context          | The name of the kubeconfig context to use                                                                                                              |
 | -f    | --manifest         | Path to the yaml configuration to audit. Only used in manifest mode. You may use `-` to read from stdin.                                               |
 | -n    | --namespace        | Only audit resources in the specified namespace. Not currently supported in manifest mode.                                                             |
 | -g    | --includegenerated | Include generated resources in scan  (such as Pods generated by deployments). If you would like kubeaudit to produce results for generated resources (for example if you have custom resources or want to catch orphaned resources where the owner resource no longer exists) you can use this flag. |
@@ -263,7 +264,7 @@ auditors:
 
 For more details about each auditor, including a description of the auditor-specific configuration in the config, see the [Auditor Docs](#auditors).
 
-**Note**: The kubeaudit config is not the same as the kubeconfig file specified with the `-c/--kubeconfig` flag, which refers to the Kubernetes config file (see [Local Mode](/README.md#local-mode)). Also note that only the `all` and `autofix` commands support using a kubeaudit config. It will not work with other commands.
+**Note**: The kubeaudit config is not the same as the kubeconfig file specified with the `--kubeconfig` flag, which refers to the Kubernetes config file (see [Local Mode](/README.md#local-mode)). Also note that only the `all` and `autofix` commands support using a kubeaudit config. It will not work with other commands.
 
 **Note**: If flags are used in combination with the config file, flags will take precedence.
 
diff --git a/cmd/commands/root.go b/cmd/commands/root.go
index 99e3e10..80927dc 100644
--- a/cmd/commands/root.go
+++ b/cmd/commands/root.go
@@ -19,6 +19,7 @@ var rootConfig rootFlags
 type rootFlags struct {
 	format           string
 	kubeConfig       string
+	context          string
 	manifest         string
 	namespace        string
 	minSeverity      string
@@ -47,7 +48,8 @@ func Execute() {
 }
 
 func init() {
-	RootCmd.PersistentFlags().StringVarP(&rootConfig.kubeConfig, "kubeconfig", "c", "", "Path to local Kubernetes config file. Only used in local mode (default is $HOME/.kube/config)")
+	RootCmd.PersistentFlags().StringVarP(&rootConfig.kubeConfig, "kubeconfig", "", "", "Path to local Kubernetes config file. Only used in local mode (default is $HOME/.kube/config)")
+	RootCmd.PersistentFlags().StringVarP(&rootConfig.context, "context", "c", "", "The name of the kubeconfig context to use")
 	RootCmd.PersistentFlags().StringVarP(&rootConfig.minSeverity, "minseverity", "m", "info", "Set the lowest severity level to report (one of \"error\", \"warning\", \"info\")")
 	RootCmd.PersistentFlags().StringVarP(&rootConfig.format, "format", "p", "pretty", "The output format to use (one of \"pretty\", \"logrus\", \"json\")")
 	RootCmd.PersistentFlags().StringVarP(&rootConfig.namespace, "namespace", "n", apiv1.NamespaceAll, "Only audit resources in the specified namespace. Not currently supported in manifest mode.")
@@ -118,7 +120,7 @@ func getReport(auditors ...kubeaudit.Auditable) *kubeaudit.Report {
 		return report
 	}
 
-	report, err := auditor.AuditLocal(rootConfig.kubeConfig, kubeaudit.AuditOptions{Namespace: rootConfig.namespace, IncludeGenerated: rootConfig.includeGenerated})
+	report, err := auditor.AuditLocal(rootConfig.kubeConfig, rootConfig.context, kubeaudit.AuditOptions{Namespace: rootConfig.namespace, IncludeGenerated: rootConfig.includeGenerated})
 	if err != nil {
 		log.WithError(err).Fatal("Error auditing cluster in local mode")
 	}
diff --git a/go.mod b/go.mod
index bcbb789..de632e5 100644
--- a/go.mod
+++ b/go.mod
@@ -3,12 +3,12 @@ module github.com/Shopify/kubeaudit
 require (
 	github.com/jetstack/cert-manager v1.6.1
 	github.com/sirupsen/logrus v1.8.1
-	github.com/spf13/cobra v1.4.0
-	github.com/stretchr/testify v1.7.2
+	github.com/spf13/cobra v1.5.0
+	github.com/stretchr/testify v1.7.5
 	gopkg.in/yaml.v3 v3.0.1
-	k8s.io/api v0.24.1
-	k8s.io/apimachinery v0.24.1
-	k8s.io/client-go v0.24.1
+	k8s.io/api v0.24.2
+	k8s.io/apimachinery v0.24.2
+	k8s.io/client-go v0.24.2
 )
 
 require (
@@ -45,7 +45,7 @@ require (
 	github.com/pkg/errors v0.9.1 // indirect
 	github.com/pmezard/go-difflib v1.0.0 // indirect
 	github.com/spf13/pflag v1.0.5 // indirect
-	github.com/stretchr/objx v0.2.0 // indirect
+	github.com/stretchr/objx v0.4.0 // indirect
 	golang.org/x/crypto v0.0.0-20220214200702-86341886e292 // indirect
 	golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd // indirect
 	golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 // indirect
diff --git a/go.sum b/go.sum
index d223d8d..cdcdc47 100644
--- a/go.sum
+++ b/go.sum
@@ -322,6 +322,7 @@ github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwc
 github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
 github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
 github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
+github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
 github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
 github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
 github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
@@ -998,8 +999,8 @@ github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHN
 github.com/spf13/cobra v1.1.1/go.mod h1:WnodtKOvamDL/PwE2M4iKs8aMDBZ5Q5klgD3qfVJQMI=
 github.com/spf13/cobra v1.1.3/go.mod h1:pGADOWyqRD/YMrPZigI/zbliZ2wVD/23d+is3pSWzOo=
 github.com/spf13/cobra v1.2.1/go.mod h1:ExllRjgxM/piMAM+3tAZvg8fsklGAf3tPfi+i8t68Nk=
-github.com/spf13/cobra v1.4.0 h1:y+wJpx64xcgO1V+RcnwW0LEHxTKRi2ZDPSBjWnrg88Q=
-github.com/spf13/cobra v1.4.0/go.mod h1:Wo4iy3BUC+X2Fybo0PDqwJIv3dNRiZLHQymsfxlB84g=
+github.com/spf13/cobra v1.5.0 h1:X+jTBEBqF0bHN+9cSMgmfuvv2VHJ9ezmFNf9Y/XstYU=
+github.com/spf13/cobra v1.5.0/go.mod h1:dWXEIy2H428czQCjInthrTRUg7yKbok+2Qi/yBIJoUM=
 github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
 github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo=
 github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
@@ -1017,8 +1018,9 @@ github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag
 github.com/stretchr/objx v0.0.0-20180129172003-8a3f7159479f/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
 github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
 github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
-github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48=
 github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
+github.com/stretchr/objx v0.4.0 h1:M2gUjqZET1qApGOWNSnZ49BAIMX4F/1plDv3+l31EJ4=
+github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
 github.com/stretchr/testify v0.0.0-20180303142811-b89eecf5ca5d/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
 github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
 github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
@@ -1026,8 +1028,9 @@ github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81P
 github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
 github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
 github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
-github.com/stretchr/testify v1.7.2 h1:4jaiDzPyXQvSd7D0EjG45355tLlV3VOECpq10pLC+8s=
-github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals=
+github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.7.5 h1:s5PTfem8p8EbKQOctVV53k6jCJt3UX4IEJzwh+C324Q=
+github.com/stretchr/testify v1.7.5/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
 github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
 github.com/syndtr/gocapability v0.0.0-20170704070218-db04d3cc01c8/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
 github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
@@ -1728,8 +1731,8 @@ k8s.io/api v0.22.0/go.mod h1:0AoXXqst47OI/L0oGKq9DG61dvGRPXs7X4/B7KyjBCU=
 k8s.io/api v0.22.1/go.mod h1:bh13rkTp3F1XEaLGykbyRD2QaTTzPm0e/BMd8ptFONY=
 k8s.io/api v0.22.2/go.mod h1:y3ydYpLJAaDI+BbSe2xmGcqxiWHmWjkEeIbiwHvnPR8=
 k8s.io/api v0.23.5/go.mod h1:Na4XuKng8PXJ2JsploYYrivXrINeTaycCGcYgF91Xm8=
-k8s.io/api v0.24.1 h1:BjCMRDcyEYz03joa3K1+rbshwh1Ay6oB53+iUx2H8UY=
-k8s.io/api v0.24.1/go.mod h1:JhoOvNiLXKTPQ60zh2g0ewpA+bnEYf5q44Flhquh4vQ=
+k8s.io/api v0.24.2 h1:g518dPU/L7VRLxWfcadQn2OnsiGWVOadTLpdnqgY2OI=
+k8s.io/api v0.24.2/go.mod h1:AHqbSkTm6YrQ0ObxjO3Pmp/ubFF/KuM7jU+3khoBsOg=
 k8s.io/apiextensions-apiserver v0.18.0/go.mod h1:18Cwn1Xws4xnWQNC00FLq1E350b9lUF+aOdIWDOZxgo=
 k8s.io/apiextensions-apiserver v0.20.1/go.mod h1:ntnrZV+6a3dB504qwC5PN/Yg9PBiDNt1EVqbW2kORVk=
 k8s.io/apiextensions-apiserver v0.20.2/go.mod h1:F6TXp389Xntt+LUq3vw6HFOLttPa0V8821ogLGwb6Zs=
@@ -1747,8 +1750,8 @@ k8s.io/apimachinery v0.22.0/go.mod h1:O3oNtNadZdeOMxHFVxOreoznohCpy0z6mocxbZr7oJ
 k8s.io/apimachinery v0.22.1/go.mod h1:O3oNtNadZdeOMxHFVxOreoznohCpy0z6mocxbZr7oJ0=
 k8s.io/apimachinery v0.22.2/go.mod h1:O3oNtNadZdeOMxHFVxOreoznohCpy0z6mocxbZr7oJ0=
 k8s.io/apimachinery v0.23.5/go.mod h1:BEuFMMBaIbcOqVIJqNZJXGFTP4W6AycEpb5+m/97hrM=
-k8s.io/apimachinery v0.24.1 h1:ShD4aDxTQKN5zNf8K1RQ2u98ELLdIW7jEnlO9uAMX/I=
-k8s.io/apimachinery v0.24.1/go.mod h1:82Bi4sCzVBdpYjyI4jY6aHX+YCUchUIrZrXKedjd2UM=
+k8s.io/apimachinery v0.24.2 h1:5QlH9SL2C8KMcrNJPor+LbXVTaZRReml7svPEh4OKDM=
+k8s.io/apimachinery v0.24.2/go.mod h1:82Bi4sCzVBdpYjyI4jY6aHX+YCUchUIrZrXKedjd2UM=
 k8s.io/apiserver v0.18.0/go.mod h1:3S2O6FeBBd6XTo0njUrLxiqk8GNy6wWOftjhJcXYnjw=
 k8s.io/apiserver v0.20.1/go.mod h1:ro5QHeQkgMS7ZGpvf4tSMx6bBOgPfE+f52KwvXfScaU=
 k8s.io/apiserver v0.20.2/go.mod h1:2nKd93WyMhZx4Hp3RfgH2K5PhwyTrprrkWYnI7id7jA=
@@ -1769,8 +1772,8 @@ k8s.io/client-go v0.22.0/go.mod h1:GUjIuXR5PiEv/RVK5OODUsm6eZk7wtSWZSaSJbpFdGg=
 k8s.io/client-go v0.22.1/go.mod h1:BquC5A4UOo4qVDUtoc04/+Nxp1MeHcVc1HJm1KmG8kk=
 k8s.io/client-go v0.22.2/go.mod h1:sAlhrkVDf50ZHx6z4K0S40wISNTarf1r800F+RlCF6U=
 k8s.io/client-go v0.23.5/go.mod h1:flkeinTO1CirYgzMPRWxUCnV0G4Fbu2vLhYCObnt/r4=
-k8s.io/client-go v0.24.1 h1:w1hNdI9PFrzu3OlovVeTnf4oHDt+FJLd9Ndluvnb42E=
-k8s.io/client-go v0.24.1/go.mod h1:f1kIDqcEYmwXS/vTbbhopMUbhKp2JhOeVTfxgaCIlF8=
+k8s.io/client-go v0.24.2 h1:CoXFSf8if+bLEbinDqN9ePIDGzcLtqhfd6jpfnwGOFA=
+k8s.io/client-go v0.24.2/go.mod h1:zg4Xaoo+umDsfCWr4fCnmLEtQXyCNXCvJuSsglNcV30=
 k8s.io/code-generator v0.18.0/go.mod h1:+UHX5rSbxmR8kzS+FAv7um6dtYrZokQvjHpDSYRVkTc=
 k8s.io/code-generator v0.20.1/go.mod h1:UsqdF+VX4PU2g46NC2JRs4gc+IfrctnwHb76RNbWHJg=
 k8s.io/code-generator v0.20.2/go.mod h1:UsqdF+VX4PU2g46NC2JRs4gc+IfrctnwHb76RNbWHJg=
diff --git a/internal/k8sinternal/client.go b/internal/k8sinternal/client.go
index 1123fbf..d5c8314 100644
--- a/internal/k8sinternal/client.go
+++ b/internal/k8sinternal/client.go
@@ -45,14 +45,14 @@ func (kc k8sClient) InClusterConfig() (*rest.Config, error) {
 }
 
 // NewKubeClientLocal creates a new kube client for local mode
-func NewKubeClientLocal(configPath string) (KubeClient, error) {
+func NewKubeClientLocal(configPath string, context string) (KubeClient, error) {
 	var kubeconfig *rest.Config
 	var err error
 
 	if configPath == "" {
 		kubeconfig, err = clientcmd.NewNonInteractiveDeferredLoadingClientConfig(
 			clientcmd.NewDefaultClientConfigLoadingRules(),
-			&clientcmd.ConfigOverrides{ClusterInfo: clientcmdapi.Cluster{Server: ""}},
+			&clientcmd.ConfigOverrides{CurrentContext: context, ClusterInfo: clientcmdapi.Cluster{Server: ""}},
 		).ClientConfig()
 	} else {
 		if _, err = os.Stat(configPath); err != nil {
diff --git a/kubeaudit.go b/kubeaudit.go
index d1e7e17..aea3852 100644
--- a/kubeaudit.go
+++ b/kubeaudit.go
@@ -185,8 +185,8 @@ func (a *Kubeaudit) AuditCluster(options AuditOptions) (*Report, error) {
 }
 
 // AuditLocal audits the Kubernetes resources found in the provided Kubernetes config file
-func (a *Kubeaudit) AuditLocal(configpath string, options AuditOptions) (*Report, error) {
-	client, err := k8sinternal.NewKubeClientLocal(configpath)
+func (a *Kubeaudit) AuditLocal(configpath string, context string, options AuditOptions) (*Report, error) {
+	client, err := k8sinternal.NewKubeClientLocal(configpath, context)
 	if err == k8sinternal.ErrNoReadableKubeConfig {
 		return nil, fmt.Errorf("failed to open kubeconfig file %s", configpath)
 	} else if err != nil {


Test patch:
diff --git a/example_test.go b/example_test.go
index 79410d9..41c51e0 100644
--- a/example_test.go
+++ b/example_test.go
@@ -78,7 +78,7 @@ func Example_auditLocal() {
 	}
 
 	// Run the audit in local mode
-	report, err := auditor.AuditLocal("", kubeaudit.AuditOptions{})
+	report, err := auditor.AuditLocal("", "", kubeaudit.AuditOptions{})
 	if err != nil {
 		log.Fatal(err)
 	}
@@ -204,7 +204,7 @@ func Example_printOptions() {
 		log.Fatal(err)
 	}
 
-	report, err := auditor.AuditLocal("", kubeaudit.AuditOptions{})
+	report, err := auditor.AuditLocal("", "", kubeaudit.AuditOptions{})
 	if err != nil {
 		log.Fatal(err)
 	}
diff --git a/internal/k8sinternal/client_test.go b/internal/k8sinternal/client_test.go
index 2f33321..97a4f93 100644
--- a/internal/k8sinternal/client_test.go
+++ b/internal/k8sinternal/client_test.go
@@ -37,10 +37,10 @@ func (kc *MockK8sClient) InClusterConfig() (*rest.Config, error) {
 func TestKubeClientConfigLocal(t *testing.T) {
 	assert := assert.New(t)
 
-	_, err := k8sinternal.NewKubeClientLocal("/notarealfile")
+	_, err := k8sinternal.NewKubeClientLocal("/notarealfile", "")
 	assert.Equal(k8sinternal.ErrNoReadableKubeConfig, err)
 
-	_, err = k8sinternal.NewKubeClientLocal("client.go")
+	_, err = k8sinternal.NewKubeClientLocal("client.go", "")
 	assert.NotEqual(k8sinternal.ErrNoReadableKubeConfig, err)
 	assert.NotNil(err)
 }
@@ -144,7 +144,7 @@ func TestIncludeGenerated(t *testing.T) {
 	test.CreateNamespace(t, namespace)
 	test.ApplyManifest(t, "./fixtures/include-generated.yml", namespace)
 
-	client, err := k8sinternal.NewKubeClientLocal("")
+	client, err := k8sinternal.NewKubeClientLocal("", "")
 	require.NoError(t, err)
 
 	// Test IncludeGenerated = false
diff --git a/internal/test/test.go b/internal/test/test.go
index 60d7aae..06995ca 100644
--- a/internal/test/test.go
+++ b/internal/test/test.go
@@ -111,7 +111,7 @@ func GetReport(t *testing.T, fixtureDir, fixture string, auditables []kubeaudit.
 		defer DeleteNamespace(t, namespace)
 		CreateNamespace(t, namespace)
 		ApplyManifest(t, fixture, namespace)
-		report, err = auditor.AuditLocal("", k8sinternal.ClientOptions{Namespace: namespace})
+		report, err = auditor.AuditLocal("", "", k8sinternal.ClientOptions{Namespace: namespace})
 	}
 
 	require.NoError(err)
diff --git a/kubeaudit_test.go b/kubeaudit_test.go
index 27a9430..1370707 100644
--- a/kubeaudit_test.go
+++ b/kubeaudit_test.go
@@ -41,10 +41,13 @@ func TestAuditLocal(t *testing.T) {
 	auditor, err := kubeaudit.New(allAuditors)
 	require.NoError(err)
 
-	_, err = auditor.AuditLocal("", k8sinternal.ClientOptions{})
+	_, err = auditor.AuditLocal("", "", k8sinternal.ClientOptions{})
 	require.NoError(err)
 
-	_, err = auditor.AuditLocal("invalid_path", k8sinternal.ClientOptions{})
+	_, err = auditor.AuditLocal("invalid_path", "", k8sinternal.ClientOptions{})
+	require.NotNil(err)
+
+	_, err = auditor.AuditLocal("", "invalid_context", k8sinternal.ClientOptions{})
 	require.NotNil(err)
 }