Repository: helm/helm (go)

Issue:
implement `helm --as` | `helm --as-group`
**Feature:**
Ability to install a chart for a different persona to the user calling the Helm CLI or Helm library.

**Use Case:**
A user logs into a portal that provides the ability to install charts.  The user is assigned to a team, which grants the user access to specific resources on the system:  namespaces, repositories, and charts within the repository.  The user is also assigned a role on the specific team which controls what actions the user may perform, such as a viewer or an editor.

On the UI, there is a catalog of charts to which the user has been given access.  The user selects one of the charts, updates the configuration values, and clicks `install`.  The request is sent to a backend processor for installing the chart.  The backend retrieves the user identify from an access token the user was assigned when logging into the portal, and the backend maps the teams to which the user is assigned to a set of groups for the user.

The backend service has been given the right to perform [user impersonation](https://kubernetes.io/docs/reference/access-authn-authz/authentication/#user-impersonation), and includes the user identity and groups in impersonation headers that are sent to Kubernetes.  Kubernetes validates the backend service and since it is able to impersonate users, accepts the user identity and user groups passed in the impersonation headers.

The key is the user does not use the helm library directly but is used instead by the backend service on behalf of the user.

Pull request description:
Implement Impersonation via flags/env
**What this PR does / why we need it**:
This patch implements similar global flags + env to `kubectl --as=user --as-group=admins --as-group=operators` for helm.
The equivalent flags look like `helm --kube-as-user=user --kube-as-group=admins --kube-as-group=operators`.

Fixes #5303

**Special notes for your reviewer**:
The flags were prefixed with `kube-` -- this follows the existing flags and was mentioned in this commment:
> We will probably want to preface the flags with --kube- to match with the current convention (like how kubectl's --context flag matches with Helm's --kube-context flag).
> https://github.com/helm/helm/issues/5304#issuecomment-551306428

I also prepended an extra commit which updates the complete list of global ENV vars for the root CLI help-text.

**If applicable**:
- [*] this PR contains documentation
- [*] this PR contains unit tests
- [*] this PR has been tested for backwards compatibility

Changes:
- Support impersonation via flags similar to kubectl --as="user"
- Document all env vars for CLI help

Patch:
diff --git a/cmd/helm/load_plugins.go b/cmd/helm/load_plugins.go
index a6e0c4eae..e4aac6c0f 100644
--- a/cmd/helm/load_plugins.go
+++ b/cmd/helm/load_plugins.go
@@ -154,7 +154,7 @@ func callPluginExecutable(pluginName string, main string, argv []string, out io.
 func manuallyProcessArgs(args []string) ([]string, []string) {
 	known := []string{}
 	unknown := []string{}
-	kvargs := []string{"--kube-context", "--namespace", "-n", "--kubeconfig", "--kube-apiserver", "--kube-token", "--registry-config", "--repository-cache", "--repository-config"}
+	kvargs := []string{"--kube-context", "--namespace", "-n", "--kubeconfig", "--kube-apiserver", "--kube-token", "--kube-as-user", "--kube-as-group", "--registry-config", "--repository-cache", "--repository-config"}
 	knownArg := func(a string) bool {
 		for _, pre := range kvargs {
 			if strings.HasPrefix(a, pre+"=") {
diff --git a/cmd/helm/root.go b/cmd/helm/root.go
index 904f11a21..82c87bd7d 100644
--- a/cmd/helm/root.go
+++ b/cmd/helm/root.go
@@ -48,11 +48,22 @@ Environment variables:
 | $HELM_CACHE_HOME                   | set an alternative location for storing cached files.                             |
 | $HELM_CONFIG_HOME                  | set an alternative location for storing Helm configuration.                       |
 | $HELM_DATA_HOME                    | set an alternative location for storing Helm data.                                |
+| $HELM_DEBUG                        | indicate whether or not Helm is running in Debug mode                             |
 | $HELM_DRIVER                       | set the backend storage driver. Values are: configmap, secret, memory, postgres   |
 | $HELM_DRIVER_SQL_CONNECTION_STRING | set the connection string the SQL storage driver should use.                      |
 | $HELM_MAX_HISTORY                  | set the maximum number of helm release history.                                   |
+| $HELM_NAMESPACE                    | set the namespace used for the helm operations.                                   |
 | $HELM_NO_PLUGINS                   | disable plugins. Set HELM_NO_PLUGINS=1 to disable plugins.                        |
+| $HELM_PLUGINS                      | set the path to the plugins directory                                             |
+| $HELM_REGISTRY_CONFIG              | set the path to the registry config file.                                         |
+| $HELM_REPOSITORY_CACHE             | set the path to the repository cache directory                                    |
+| $HELM_REPOSITORY_CONFIG            | set the path to the repositories file.                                            |
 | $KUBECONFIG                        | set an alternative Kubernetes configuration file (default "~/.kube/config")       |
+| $HELM_KUBEAPISERVER                | set the Kubernetes API Server Endpoint for authentication                         |
+| $HELM_KUBEASGROUPS                 | set the Username to impersonate for the operation.                                |
+| $HELM_KUBEASUSER                   | set the Groups to use for impoersonation using a comma-separated list.            |
+| $HELM_KUBECONTEXT                  | set the name of the kubeconfig context.                                           |
+| $HELM_KUBETOKEN                    | set the Bearer KubeToken used for authentication.                                 |
 
 Helm stores cache, configuration, and data based on the following configuration order:
 
diff --git a/pkg/cli/environment.go b/pkg/cli/environment.go
index a9994f03d..4f3abc08b 100644
--- a/pkg/cli/environment.go
+++ b/pkg/cli/environment.go
@@ -26,6 +26,7 @@ import (
 	"fmt"
 	"os"
 	"strconv"
+	"strings"
 
 	"github.com/spf13/pflag"
 	"k8s.io/cli-runtime/pkg/genericclioptions"
@@ -47,6 +48,10 @@ type EnvSettings struct {
 	KubeContext string
 	// Bearer KubeToken used for authentication
 	KubeToken string
+	// Username to impersonate for the operation
+	KubeAsUser string
+	// Groups to impersonate for the operation, multiple groups parsed from a comma delimited list
+	KubeAsGroups []string
 	// Kubernetes API Server Endpoint for authentication
 	KubeAPIServer string
 	// Debug indicates whether or not Helm is running in Debug mode.
@@ -69,6 +74,8 @@ func New() *EnvSettings {
 		MaxHistory:       envIntOr("HELM_MAX_HISTORY", defaultMaxHistory),
 		KubeContext:      os.Getenv("HELM_KUBECONTEXT"),
 		KubeToken:        os.Getenv("HELM_KUBETOKEN"),
+		KubeAsUser:       os.Getenv("HELM_KUBEASUSER"),
+		KubeAsGroups:     envCSV("HELM_KUBEASGROUPS"),
 		KubeAPIServer:    os.Getenv("HELM_KUBEAPISERVER"),
 		PluginsDirectory: envOr("HELM_PLUGINS", helmpath.DataPath("plugins")),
 		RegistryConfig:   envOr("HELM_REGISTRY_CONFIG", helmpath.ConfigPath("registry.json")),
@@ -79,11 +86,13 @@ func New() *EnvSettings {
 
 	// bind to kubernetes config flags
 	env.config = &genericclioptions.ConfigFlags{
-		Namespace:   &env.namespace,
-		Context:     &env.KubeContext,
-		BearerToken: &env.KubeToken,
-		APIServer:   &env.KubeAPIServer,
-		KubeConfig:  &env.KubeConfig,
+		Namespace:        &env.namespace,
+		Context:          &env.KubeContext,
+		BearerToken:      &env.KubeToken,
+		APIServer:        &env.KubeAPIServer,
+		KubeConfig:       &env.KubeConfig,
+		Impersonate:      &env.KubeAsUser,
+		ImpersonateGroup: &env.KubeAsGroups,
 	}
 	return env
 }
@@ -94,6 +103,8 @@ func (s *EnvSettings) AddFlags(fs *pflag.FlagSet) {
 	fs.StringVar(&s.KubeConfig, "kubeconfig", "", "path to the kubeconfig file")
 	fs.StringVar(&s.KubeContext, "kube-context", s.KubeContext, "name of the kubeconfig context to use")
 	fs.StringVar(&s.KubeToken, "kube-token", s.KubeToken, "bearer token used for authentication")
+	fs.StringVar(&s.KubeAsUser, "kube-as-user", s.KubeAsUser, "Username to impersonate for the operation")
+	fs.StringArrayVar(&s.KubeAsGroups, "kube-as-group", s.KubeAsGroups, "Group to impersonate for the operation, this flag can be repeated to specify multiple groups.")
 	fs.StringVar(&s.KubeAPIServer, "kube-apiserver", s.KubeAPIServer, "the address and the port for the Kubernetes API server")
 	fs.BoolVar(&s.Debug, "debug", s.Debug, "enable verbose output")
 	fs.StringVar(&s.RegistryConfig, "registry-config", s.RegistryConfig, "path to the registry config file")
@@ -120,6 +131,14 @@ func envIntOr(name string, def int) int {
 	return ret
 }
 
+func envCSV(name string) (ls []string) {
+	trimmed := strings.Trim(os.Getenv(name), ", ")
+	if trimmed != "" {
+		ls = strings.Split(trimmed, ",")
+	}
+	return
+}
+
 func (s *EnvSettings) EnvVars() map[string]string {
 	envvars := map[string]string{
 		"HELM_BIN":               os.Args[0],
@@ -137,6 +156,8 @@ func (s *EnvSettings) EnvVars() map[string]string {
 		// broken, these are populated from helm flags and not kubeconfig.
 		"HELM_KUBECONTEXT":   s.KubeContext,
 		"HELM_KUBETOKEN":     s.KubeToken,
+		"HELM_KUBEASUSER":    s.KubeAsUser,
+		"HELM_KUBEASGROUPS":  strings.Join(s.KubeAsGroups, ","),
 		"HELM_KUBEAPISERVER": s.KubeAPIServer,
 	}
 	if s.KubeConfig != "" {
diff --git a/scripts/get-helm-3 b/scripts/get-helm-3
index 08d0e14ca..f2495e444 100755
--- a/scripts/get-helm-3
+++ b/scripts/get-helm-3
@@ -19,16 +19,8 @@
 
 : ${BINARY_NAME:="helm"}
 : ${USE_SUDO:="true"}
-: ${DEBUG:="false"}
-: ${VERIFY_CHECKSUM:="true"}
-: ${VERIFY_SIGNATURES:="false"}
 : ${HELM_INSTALL_DIR:="/usr/local/bin"}
 
-HAS_CURL="$(type "curl" &> /dev/null && echo true || echo false)"
-HAS_WGET="$(type "wget" &> /dev/null && echo true || echo false)"
-HAS_OPENSSL="$(type "openssl" &> /dev/null && echo true || echo false)"
-HAS_GPG="$(type "gpg" &> /dev/null && echo true || echo false)"
-
 # initArch discovers the architecture for this system.
 initArch() {
   ARCH=$(uname -m)
@@ -66,7 +58,7 @@ runAsRoot() {
 }
 
 # verifySupported checks that the os/arch combination is supported for
-# binary builds, as well whether or not necessary tools are present.
+# binary builds.
 verifySupported() {
   local supported="darwin-amd64\nlinux-386\nlinux-amd64\nlinux-arm\nlinux-arm64\nlinux-ppc64le\nlinux-s390x\nwindows-amd64"
   if ! echo "${supported}" | grep -q "${OS}-${ARCH}"; then
@@ -75,29 +67,10 @@ verifySupported() {
     exit 1
   fi
 
-  if [ "${HAS_CURL}" != "true" ] && [ "${HAS_WGET}" != "true" ]; then
+  if ! type "curl" > /dev/null && ! type "wget" > /dev/null; then
     echo "Either curl or wget is required"
     exit 1
   fi
-
-  if [ "${VERIFY_CHECKSUM}" == "true" ] && [ "${HAS_OPENSSL}" != "true" ]; then
-    echo "In order to verify checksum, openssl must first be installed."
-    echo "Please install openssl or set VERIFY_CHECKSUM=false in your environment."
-    exit 1
-  fi
-
-  if [ "${VERIFY_SIGNATURES}" == "true" ]; then
-    if [ "${HAS_GPG}" != "true" ]; then
-      echo "In order to verify signatures, gpg must first be installed."
-      echo "Please install gpg or set VERIFY_SIGNATURES=false in your environment."
-      exit 1
-    fi
-    if [ "${OS}" != "linux" ]; then
-      echo "Signature verification is currently only supported on Linux."
-      echo "Please set VERIFY_SIGNATURES=false or verify the signatures manually."
-      exit 1
-    fi
-  fi
 }
 
 # checkDesiredVersion checks if the desired version is available.
@@ -105,9 +78,9 @@ checkDesiredVersion() {
   if [ "x$DESIRED_VERSION" == "x" ]; then
     # Get tag from release URL
     local latest_release_url="https://github.com/helm/helm/releases"
-    if [ "${HAS_CURL}" == "true" ]; then
+    if type "curl" > /dev/null; then
       TAG=$(curl -Ls $latest_release_url | grep 'href="/helm/helm/releases/tag/v3.[0-9]*.[0-9]*\"' | grep -v no-underline | head -n 1 | cut -d '"' -f 2 | awk '{n=split($NF,a,"/");print a[n]}' | awk 'a !~ $0{print}; {a=$0}')
-    elif [ "${HAS_WGET}" == "true" ]; then
+    elif type "wget" > /dev/null; then
       TAG=$(wget $latest_release_url -O - 2>&1 | grep 'href="/helm/helm/releases/tag/v3.[0-9]*.[0-9]*\"' | grep -v no-underline | head -n 1 | cut -d '"' -f 2 | awk '{n=split($NF,a,"/");print a[n]}' | awk 'a !~ $0{print}; {a=$0}')
     fi
   else
@@ -142,94 +115,35 @@ downloadFile() {
   HELM_TMP_FILE="$HELM_TMP_ROOT/$HELM_DIST"
   HELM_SUM_FILE="$HELM_TMP_ROOT/$HELM_DIST.sha256"
   echo "Downloading $DOWNLOAD_URL"
-  if [ "${HAS_CURL}" == "true" ]; then
+  if type "curl" > /dev/null; then
     curl -SsL "$CHECKSUM_URL" -o "$HELM_SUM_FILE"
-    curl -SsL "$DOWNLOAD_URL" -o "$HELM_TMP_FILE"
-  elif [ "${HAS_WGET}" == "true" ]; then
+  elif type "wget" > /dev/null; then
     wget -q -O "$HELM_SUM_FILE" "$CHECKSUM_URL"
-    wget -q -O "$HELM_TMP_FILE" "$DOWNLOAD_URL"
   fi
-}
-
-# verifyFile verifies the SHA256 checksum of the binary package
-# and the GPG signatures for both the package and checksum file
-# (depending on settings in environment).
-verifyFile() {
-  if [ "${VERIFY_CHECKSUM}" == "true" ]; then
-    verifyChecksum
-  fi
-  if [ "${VERIFY_SIGNATURES}" == "true" ]; then
-    verifySignatures
+  if type "curl" > /dev/null; then
+    curl -SsL "$DOWNLOAD_URL" -o "$HELM_TMP_FILE"
+  elif type "wget" > /dev/null; then
+    wget -q -O "$HELM_TMP_FILE" "$DOWNLOAD_URL"
   fi
 }
 
-# installFile installs the Helm binary.
+# installFile verifies the SHA256 for the file, then unpacks and
+# installs it.
 installFile() {
   HELM_TMP="$HELM_TMP_ROOT/$BINARY_NAME"
-  mkdir -p "$HELM_TMP"
-  tar xf "$HELM_TMP_FILE" -C "$HELM_TMP"
-  HELM_TMP_BIN="$HELM_TMP/$OS-$ARCH/helm"
-  echo "Preparing to install $BINARY_NAME into ${HELM_INSTALL_DIR}"
-  runAsRoot cp "$HELM_TMP_BIN" "$HELM_INSTALL_DIR/$BINARY_NAME"
-  echo "$BINARY_NAME installed into $HELM_INSTALL_DIR/$BINARY_NAME"
-}
-
-# verifyChecksum verifies the SHA256 checksum of the binary package.
-verifyChecksum() {
-  printf "Verifying checksum... "
   local sum=$(openssl sha1 -sha256 ${HELM_TMP_FILE} | awk '{print $2}')
   local expected_sum=$(cat ${HELM_SUM_FILE})
   if [ "$sum" != "$expected_sum" ]; then
     echo "SHA sum of ${HELM_TMP_FILE} does not match. Aborting."
     exit 1
   fi
-  echo "Done."
-}
 
-# verifySignatures obtains the latest KEYS file from GitHub master branch
-# as well as the signature .asc files from the specific GitHub release,
-# then verifies that the release artifacts were signed by a maintainer's key.
-verifySignatures() {
-  printf "Verifying signatures... "
-  local keys_filename="KEYS"
-  local github_keys_url="https://raw.githubusercontent.com/helm/helm/master/${keys_filename}"
-  if [ "${HAS_CURL}" == "true" ]; then
-    curl -SsL "${github_keys_url}" -o "${HELM_TMP_ROOT}/${keys_filename}"
-  elif [ "${HAS_WGET}" == "true" ]; then
-    wget -q -O "${HELM_TMP_ROOT}/${keys_filename}" "${github_keys_url}"
-  fi
-  local gpg_keyring="${HELM_TMP_ROOT}/keyring.gpg"
-  local gpg_homedir="${HELM_TMP_ROOT}/gnupg"
-  mkdir -p -m 0700 "${gpg_homedir}"
-  local gpg_stderr_device="/dev/null"
-  if [ "${DEBUG}" == "true" ]; then
-    gpg_stderr_device="/dev/stderr"
-  fi
-  gpg --batch --quiet --homedir="${gpg_homedir}" --import "${HELM_TMP_ROOT}/${keys_filename}" 2> "${gpg_stderr_device}"
-  gpg --batch --no-default-keyring --keyring "${gpg_homedir}/pubring.kbx" --export > "${gpg_keyring}"
-  local github_release_url="https://github.com/helm/helm/releases/download/${TAG}"
-  if [ "${HAS_CURL}" == "true" ]; then
-    curl -SsL "${github_release_url}/helm-${TAG}-${OS}-${ARCH}.tar.gz.sha256.asc" -o "${HELM_TMP_ROOT}/helm-${TAG}-${OS}-${ARCH}.tar.gz.sha256.asc"
-    curl -SsL "${github_release_url}/helm-${TAG}-${OS}-${ARCH}.tar.gz.asc" -o "${HELM_TMP_ROOT}/helm-${TAG}-${OS}-${ARCH}.tar.gz.asc"
-  elif [ "${HAS_WGET}" == "true" ]; then
-    wget -q -O "${HELM_TMP_ROOT}/helm-${TAG}-${OS}-${ARCH}.tar.gz.sha256.asc" "${github_release_url}/helm-${TAG}-${OS}-${ARCH}.tar.gz.sha256.asc"
-    wget -q -O "${HELM_TMP_ROOT}/helm-${TAG}-${OS}-${ARCH}.tar.gz.asc" "${github_release_url}/helm-${TAG}-${OS}-${ARCH}.tar.gz.asc"
-  fi
-  local error_text="If you think this might be a potential security issue,"
-  error_text="${error_text}\nplease see here: https://github.com/helm/community/blob/master/SECURITY.md"
-  local num_goodlines_sha=$(gpg --verify --keyring="${gpg_keyring}" --status-fd=1 "${HELM_TMP_ROOT}/helm-${TAG}-${OS}-${ARCH}.tar.gz.sha256.asc" 2> "${gpg_stderr_device}" | grep -c -E '^\[GNUPG:\] (GOODSIG|VALIDSIG)')
-  if [[ ${num_goodlines_sha} -lt 2 ]]; then
-    echo "Unable to verify the signature of helm-${TAG}-${OS}-${ARCH}.tar.gz.sha256!"
-    echo -e "${error_text}"
-    exit 1
-  fi
-  local num_goodlines_tar=$(gpg --verify --keyring="${gpg_keyring}" --status-fd=1 "${HELM_TMP_ROOT}/helm-${TAG}-${OS}-${ARCH}.tar.gz.asc" 2> "${gpg_stderr_device}" | grep -c -E '^\[GNUPG:\] (GOODSIG|VALIDSIG)')
-  if [[ ${num_goodlines_tar} -lt 2 ]]; then
-    echo "Unable to verify the signature of helm-${TAG}-${OS}-${ARCH}.tar.gz!"
-    echo -e "${error_text}"
-    exit 1
-  fi
-  echo "Done."
+  mkdir -p "$HELM_TMP"
+  tar xf "$HELM_TMP_FILE" -C "$HELM_TMP"
+  HELM_TMP_BIN="$HELM_TMP/$OS-$ARCH/helm"
+  echo "Preparing to install $BINARY_NAME into ${HELM_INSTALL_DIR}"
+  runAsRoot cp "$HELM_TMP_BIN" "$HELM_INSTALL_DIR/$BINARY_NAME"
+  echo "$BINARY_NAME installed into $HELM_INSTALL_DIR/$BINARY_NAME"
 }
 
 # fail_trap is executed if an error occurs.
@@ -281,11 +195,6 @@ cleanup() {
 trap "fail_trap" EXIT
 set -e
 
-# Set debug if desired
-if [ "${DEBUG}" == "true" ]; then
-  set -x
-fi
-
 # Parsing input arguments (if any)
 export INPUT_ARGUMENTS="${@}"
 set -u
@@ -320,7 +229,6 @@ verifySupported
 checkDesiredVersion
 if ! checkHelmInstalledVersion; then
   downloadFile
-  verifyFile
   installFile
 fi
 testVersion


Test patch:
diff --git a/cmd/helm/plugin_test.go b/cmd/helm/plugin_test.go
index cf21d8460..0bf867f2a 100644
--- a/cmd/helm/plugin_test.go
+++ b/cmd/helm/plugin_test.go
@@ -37,6 +37,9 @@ func TestManuallyProcessArgs(t *testing.T) {
 		"--kubeconfig", "/home/foo",
 		"--kube-context=test1",
 		"--kube-context", "test1",
+		"--kube-as-user", "pikachu",
+		"--kube-as-group", "teatime",
+		"--kube-as-group", "admins",
 		"-n=test2",
 		"-n", "test2",
 		"--namespace=test2",
@@ -51,6 +54,9 @@ func TestManuallyProcessArgs(t *testing.T) {
 		"--kubeconfig", "/home/foo",
 		"--kube-context=test1",
 		"--kube-context", "test1",
+		"--kube-as-user", "pikachu",
+		"--kube-as-group", "teatime",
+		"--kube-as-group", "admins",
 		"-n=test2",
 		"-n", "test2",
 		"--namespace=test2",
diff --git a/cmd/helm/testdata/output/env-comp.txt b/cmd/helm/testdata/output/env-comp.txt
index c4b46ae6b..3739d8bc1 100644
--- a/cmd/helm/testdata/output/env-comp.txt
+++ b/cmd/helm/testdata/output/env-comp.txt
@@ -4,6 +4,8 @@ HELM_CONFIG_HOME
 HELM_DATA_HOME
 HELM_DEBUG
 HELM_KUBEAPISERVER
+HELM_KUBEASGROUPS
+HELM_KUBEASUSER
 HELM_KUBECONTEXT
 HELM_KUBETOKEN
 HELM_MAX_HISTORY
diff --git a/pkg/cli/environment_test.go b/pkg/cli/environment_test.go
index 3234a133b..ffdbce68b 100644
--- a/pkg/cli/environment_test.go
+++ b/pkg/cli/environment_test.go
@@ -18,6 +18,7 @@ package cli
 
 import (
 	"os"
+	"reflect"
 	"strings"
 	"testing"
 
@@ -36,6 +37,8 @@ func TestEnvSettings(t *testing.T) {
 		ns, kcontext string
 		debug        bool
 		maxhistory   int
+		kAsUser      string
+		kAsGroups    []string
 	}{
 		{
 			name:       "defaults",
@@ -44,25 +47,31 @@ func TestEnvSettings(t *testing.T) {
 		},
 		{
 			name:       "with flags set",
-			args:       "--debug --namespace=myns",
+			args:       "--debug --namespace=myns --kube-as-user=poro --kube-as-group=admins --kube-as-group=teatime --kube-as-group=snackeaters",
 			ns:         "myns",
 			debug:      true,
 			maxhistory: defaultMaxHistory,
+			kAsUser:    "poro",
+			kAsGroups:  []string{"admins", "teatime", "snackeaters"},
 		},
 		{
 			name:       "with envvars set",
-			envvars:    map[string]string{"HELM_DEBUG": "1", "HELM_NAMESPACE": "yourns", "HELM_MAX_HISTORY": "5"},
+			envvars:    map[string]string{"HELM_DEBUG": "1", "HELM_NAMESPACE": "yourns", "HELM_KUBEASUSER": "pikachu", "HELM_KUBEASGROUPS": ",,,operators,snackeaters,partyanimals", "HELM_MAX_HISTORY": "5"},
 			ns:         "yourns",
 			maxhistory: 5,
 			debug:      true,
+			kAsUser:    "pikachu",
+			kAsGroups:  []string{"operators", "snackeaters", "partyanimals"},
 		},
 		{
 			name:       "with flags and envvars set",
-			args:       "--debug --namespace=myns",
-			envvars:    map[string]string{"HELM_DEBUG": "1", "HELM_NAMESPACE": "yourns"},
+			args:       "--debug --namespace=myns --kube-as-user=poro --kube-as-group=admins --kube-as-group=teatime --kube-as-group=snackeaters",
+			envvars:    map[string]string{"HELM_DEBUG": "1", "HELM_NAMESPACE": "yourns", "HELM_KUBEASUSER": "pikachu", "HELM_KUBEASGROUPS": ",,,operators,snackeaters,partyanimals", "HELM_MAX_HISTORY": "5"},
 			ns:         "myns",
 			debug:      true,
-			maxhistory: defaultMaxHistory,
+			maxhistory: 5,
+			kAsUser:    "poro",
+			kAsGroups:  []string{"admins", "teatime", "snackeaters"},
 		},
 	}
 
@@ -92,6 +101,12 @@ func TestEnvSettings(t *testing.T) {
 			if settings.MaxHistory != tt.maxhistory {
 				t.Errorf("expected maxHistory %d, got %d", tt.maxhistory, settings.MaxHistory)
 			}
+			if tt.kAsUser != settings.KubeAsUser {
+				t.Errorf("expected kAsUser %q, got %q", tt.kAsUser, settings.KubeAsUser)
+			}
+			if !reflect.DeepEqual(tt.kAsGroups, settings.KubeAsGroups) {
+				t.Errorf("expected kAsGroups %+v, got %+v", len(tt.kAsGroups), len(settings.KubeAsGroups))
+			}
 		})
 	}
 }