Skip to content
This repository has been archived by the owner on Apr 27, 2020. It is now read-only.

Commit

Permalink
Merge kubeconfig files using "kubectl config view" (#51)
Browse files Browse the repository at this point in the history
* Revert "Revert "Use token with kubeconfig set (#46)" (#48)"

This reverts commit 9112a93.

* Merge kubeconfig files using "kubectl config view"

When using `use_aws_iam_authenticator`, the kubeconfig file is broken
due to merging by shell redirection. With this commit, the kubeconfig
file is merged by `kubectl config view` command instead of shell
redirection.
  • Loading branch information
superbrothers authored Oct 30, 2018
1 parent bf3bffa commit 26fa30c
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 25 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ The version of this resource corresponds to the version of kubectl. We recommend

### cluster configs

- `server`: *Optional.* The address and port of the API server. Requires `token`.
- `token`: *Optional.* Bearer token for authentication to the API server. Requires `server`.
- `server`: *Optional.* The address and port of the API server.
- `token`: *Optional.* Bearer token for authentication to the API server.
- `namespace`: *Optional.* The namespace scope. Defaults to `default`. If set along with `kubeconfig`, `namespace` will override the namespace in the current-context
- `certificate_authority`: *Optional.* A certificate file for the certificate authority.
```yaml
Expand Down
61 changes: 38 additions & 23 deletions assets/common.sh
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,13 @@ setup_kubectl() {
local payload
payload=$1

# the entry name for auth of kubeconfig
local -r AUTH_NAME=auth
# the entry name for cluster of kubeconfig
local -r CLUSTER_NAME=cluster
# the entry name for context of kubeconfig
local -r CONTEXT_NAME=kubernetes-resource

KUBECONFIG="$(mktemp "$TMPDIR/kubernetes-resource-kubeconfig.XXXXXX")"
export KUBECONFIG

Expand All @@ -34,9 +41,6 @@ setup_kubectl() {
# Optional. The address and port of the API server. Requires token.
local server
server="$(jq -r '.source.server // ""' < "$payload")"
# Optional. Bearer token for authentication to the API server. Requires server.
local token
token="$(jq -r '.source.token // ""' < "$payload")"
# Optional. A certificate file for the certificate authority.
local certificate_authority
certificate_authority="$(jq -r '.source.certificate_authority // ""' < "$payload")"
Expand All @@ -45,23 +49,6 @@ setup_kubectl() {
local insecure_skip_tls_verify
insecure_skip_tls_verify="$(jq -r '.source.insecure_skip_tls_verify // ""' < "$payload")"

if [[ -z "$server" || -z "$token" ]]; then
echoerr 'You must specify "server" and "token", if not specify "kubeconfig".'
exit 1
fi

local -r AUTH_NAME=auth
local -r CLUSTER_NAME=cluster
local -r CONTEXT_NAME=kubernetes-resource

# Build options for kubectl config set-credentials
# Avoid to expose the token string by using placeholder
local set_credentials_opts
set_credentials_opts=("--token=**********")
exe kubectl config set-credentials "$AUTH_NAME" "${set_credentials_opts[@]}"
# placeholder is replaced with actual token string
sed -i -e "s/[*]\\{10\\}/$token/" "$KUBECONFIG"

# Build options for kubectl config set-cluster
local set_cluster_opts
set_cluster_opts=("--server=$server")
Expand All @@ -76,7 +63,7 @@ setup_kubectl() {
fi
exe kubectl config set-cluster "$CLUSTER_NAME" "${set_cluster_opts[@]}"

exe kubectl config set-context "$CONTEXT_NAME" --user="$AUTH_NAME" --cluster="$CLUSTER_NAME"
exe kubectl config set-context "$CONTEXT_NAME" --cluster="$CLUSTER_NAME"

exe kubectl config use-context "$CONTEXT_NAME"

Expand All @@ -90,14 +77,26 @@ setup_kubectl() {
echoerr 'You must specify aws_eks_cluster_name when using aws_iam_authenticator.'
exit 1
fi
echo " exec:
local kubeconfig_file_aws
kubeconfig_file_aws="$(mktemp "$TMPDIR/kubernetes-resource-kubeconfig-aws.XXXXXX")"
cat <<EOF > "$kubeconfig_file_aws"
users:
- name: ${AUTH_NAME}
user:
exec:
apiVersion: client.authentication.k8s.io/v1alpha1
args:
- token
- -i
- ${aws_eks_cluster_name}
command: aws-iam-authenticator
env: null" >> "$KUBECONFIG"
env: null
EOF
# Merge two kubeconfig files
local tmpfile
tmpfile="$(mktemp)"
KUBECONFIG="$KUBECONFIG:$kubeconfig_file_aws" kubectl config view --flatten > "$tmpfile"
cat "$tmpfile" > "$KUBECONFIG"
fi
fi

Expand All @@ -111,6 +110,22 @@ setup_kubectl() {
if [[ -n "$namespace" ]]; then
exe kubectl config set-context "$(kubectl config current-context)" --namespace="$namespace"
fi

# if providing a token we set a user and override context to support both kubeconfig and generated config
local token
token="$(jq -r '.source.token // ""' < "$payload")"
if [[ -n "$token" ]]; then
# Build options for kubectl config set-credentials
# Avoid to expose the token string by using placeholder
local set_credentials_opts
set_credentials_opts=("--token=**********")
exe kubectl config set-credentials "$AUTH_NAME" "${set_credentials_opts[@]}"
# placeholder is replaced with actual token string
sed -i -e "s/[*]\\{10\\}/$token/" "$KUBECONFIG"

# override user of context to one with token
exe kubectl config set-context "$(kubectl config current-context)" --user="$AUTH_NAME"
fi

# Optional. The name of the kubeconfig context to use.
local context
Expand Down
8 changes: 8 additions & 0 deletions test/helper.bash
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,11 @@ assert_match() {
return 1
fi
}

assert_not_match() {
if [[ "$2" =~ $1 ]]; then
echo "expected: $1"
echo "actual: $2"
return 1
fi
}
29 changes: 29 additions & 0 deletions test/suite.bats
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,17 @@ setup() {
kubectl config view --flatten --minify > "$kubeconfig_file"
# Change the current-context to $namespace
kubectl --kubeconfig "$kubeconfig_file" config set-context ${current_context} --namespace "$namespace"
# Create a kubeconfig json without users (no token)
kubeconfig_file_no_token="$(mktemp)"
kubectl config view --flatten --minify -o json | jq -r 'del(.contexts[0].context.user,.users)' > "$kubeconfig_file_no_token"
# create rolebinding for full namespace access to default service account in namespace to avoid forbidden errors with token
kubectl create -n $namespace rolebinding --clusterrole=cluster-admin --serviceaccount=$namespace:default testaccount
# get default service account
serviceaccount=$(kubectl get -n $namespace serviceaccount default -o json | jq -r '.secrets[0].name')
# Extract server from service account for testing
server="$(kubectl get -n $namespace secret "$serviceaccount" -o json | jq -r '.data["server"]' | base64 -d)"
# Extract token from service account for testing
token="$(kubectl get -n $namespace secret "$serviceaccount" -o json | jq -r '.data["token"]' | base64 -d)"
}

teardown() {
Expand All @@ -21,6 +32,14 @@ teardown() {
rm "$kubeconfig_file"
}

@test "with outputs.use_aws_iam_authenticator" {
run assets/out <<< "$(jq -n '{"source": {"use_aws_iam_authenticator": true, "aws_eks_cluster_name": "eks-cluster01", "server": $server, "token": $token}, "params": {"kubectl": "get po"}}' \
--arg server "$server" \
--arg token "$token" \
--arg kubectl "get po nginx")"
assert_not_match 'did not find expected key' "$output"
}

@test "with source.kubeconfig" {
run assets/out <<< "$(jq -n '{"source": {"kubeconfig": $kubeconfig}, "params": {"kubectl": $kubectl}}' \
--arg kubeconfig "$(cat "$kubeconfig_file")" \
Expand Down Expand Up @@ -57,6 +76,16 @@ teardown() {
assert_failure
}

@test "with no credentials in outputs.kubeconfig_file and source.token" {
run assets/out <<< "$(jq -n '{"source": {"token": $token}, "params": {"kubectl": $kubectl, "kubeconfig_file": $kubeconfig_file, "namespace": $namespace}}' \
--arg token "$token" \
--arg kubeconfig_file "$kubeconfig_file_no_token" \
--arg kubectl "get ns $namespace -o name" \
--arg namespace "$namespace")"
assert_match "namespace/$namespace" "$output"
assert_success
}

@test "command substitution in outputs.kubectl" {
run kubectl --kubeconfig "$kubeconfig_file" run nginx --image=nginx
assert_success
Expand Down

0 comments on commit 26fa30c

Please sign in to comment.