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

Commit 26fa30c

Browse files
Merge kubeconfig files using "kubectl config view" (#51)
* 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.
1 parent bf3bffa commit 26fa30c

File tree

4 files changed

+77
-25
lines changed

4 files changed

+77
-25
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,8 @@ The version of this resource corresponds to the version of kubectl. We recommend
3535

3636
### cluster configs
3737

38-
- `server`: *Optional.* The address and port of the API server. Requires `token`.
39-
- `token`: *Optional.* Bearer token for authentication to the API server. Requires `server`.
38+
- `server`: *Optional.* The address and port of the API server.
39+
- `token`: *Optional.* Bearer token for authentication to the API server.
4040
- `namespace`: *Optional.* The namespace scope. Defaults to `default`. If set along with `kubeconfig`, `namespace` will override the namespace in the current-context
4141
- `certificate_authority`: *Optional.* A certificate file for the certificate authority.
4242
```yaml

assets/common.sh

Lines changed: 38 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,13 @@ setup_kubectl() {
1111
local payload
1212
payload=$1
1313

14+
# the entry name for auth of kubeconfig
15+
local -r AUTH_NAME=auth
16+
# the entry name for cluster of kubeconfig
17+
local -r CLUSTER_NAME=cluster
18+
# the entry name for context of kubeconfig
19+
local -r CONTEXT_NAME=kubernetes-resource
20+
1421
KUBECONFIG="$(mktemp "$TMPDIR/kubernetes-resource-kubeconfig.XXXXXX")"
1522
export KUBECONFIG
1623

@@ -34,9 +41,6 @@ setup_kubectl() {
3441
# Optional. The address and port of the API server. Requires token.
3542
local server
3643
server="$(jq -r '.source.server // ""' < "$payload")"
37-
# Optional. Bearer token for authentication to the API server. Requires server.
38-
local token
39-
token="$(jq -r '.source.token // ""' < "$payload")"
4044
# Optional. A certificate file for the certificate authority.
4145
local certificate_authority
4246
certificate_authority="$(jq -r '.source.certificate_authority // ""' < "$payload")"
@@ -45,23 +49,6 @@ setup_kubectl() {
4549
local insecure_skip_tls_verify
4650
insecure_skip_tls_verify="$(jq -r '.source.insecure_skip_tls_verify // ""' < "$payload")"
4751

48-
if [[ -z "$server" || -z "$token" ]]; then
49-
echoerr 'You must specify "server" and "token", if not specify "kubeconfig".'
50-
exit 1
51-
fi
52-
53-
local -r AUTH_NAME=auth
54-
local -r CLUSTER_NAME=cluster
55-
local -r CONTEXT_NAME=kubernetes-resource
56-
57-
# Build options for kubectl config set-credentials
58-
# Avoid to expose the token string by using placeholder
59-
local set_credentials_opts
60-
set_credentials_opts=("--token=**********")
61-
exe kubectl config set-credentials "$AUTH_NAME" "${set_credentials_opts[@]}"
62-
# placeholder is replaced with actual token string
63-
sed -i -e "s/[*]\\{10\\}/$token/" "$KUBECONFIG"
64-
6552
# Build options for kubectl config set-cluster
6653
local set_cluster_opts
6754
set_cluster_opts=("--server=$server")
@@ -76,7 +63,7 @@ setup_kubectl() {
7663
fi
7764
exe kubectl config set-cluster "$CLUSTER_NAME" "${set_cluster_opts[@]}"
7865

79-
exe kubectl config set-context "$CONTEXT_NAME" --user="$AUTH_NAME" --cluster="$CLUSTER_NAME"
66+
exe kubectl config set-context "$CONTEXT_NAME" --cluster="$CLUSTER_NAME"
8067

8168
exe kubectl config use-context "$CONTEXT_NAME"
8269

@@ -90,14 +77,26 @@ setup_kubectl() {
9077
echoerr 'You must specify aws_eks_cluster_name when using aws_iam_authenticator.'
9178
exit 1
9279
fi
93-
echo " exec:
80+
local kubeconfig_file_aws
81+
kubeconfig_file_aws="$(mktemp "$TMPDIR/kubernetes-resource-kubeconfig-aws.XXXXXX")"
82+
cat <<EOF > "$kubeconfig_file_aws"
83+
users:
84+
- name: ${AUTH_NAME}
85+
user:
86+
exec:
9487
apiVersion: client.authentication.k8s.io/v1alpha1
9588
args:
9689
- token
9790
- -i
9891
- ${aws_eks_cluster_name}
9992
command: aws-iam-authenticator
100-
env: null" >> "$KUBECONFIG"
93+
env: null
94+
EOF
95+
# Merge two kubeconfig files
96+
local tmpfile
97+
tmpfile="$(mktemp)"
98+
KUBECONFIG="$KUBECONFIG:$kubeconfig_file_aws" kubectl config view --flatten > "$tmpfile"
99+
cat "$tmpfile" > "$KUBECONFIG"
101100
fi
102101
fi
103102

@@ -111,6 +110,22 @@ setup_kubectl() {
111110
if [[ -n "$namespace" ]]; then
112111
exe kubectl config set-context "$(kubectl config current-context)" --namespace="$namespace"
113112
fi
113+
114+
# if providing a token we set a user and override context to support both kubeconfig and generated config
115+
local token
116+
token="$(jq -r '.source.token // ""' < "$payload")"
117+
if [[ -n "$token" ]]; then
118+
# Build options for kubectl config set-credentials
119+
# Avoid to expose the token string by using placeholder
120+
local set_credentials_opts
121+
set_credentials_opts=("--token=**********")
122+
exe kubectl config set-credentials "$AUTH_NAME" "${set_credentials_opts[@]}"
123+
# placeholder is replaced with actual token string
124+
sed -i -e "s/[*]\\{10\\}/$token/" "$KUBECONFIG"
125+
126+
# override user of context to one with token
127+
exe kubectl config set-context "$(kubectl config current-context)" --user="$AUTH_NAME"
128+
fi
114129

115130
# Optional. The name of the kubeconfig context to use.
116131
local context

test/helper.bash

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,3 +39,11 @@ assert_match() {
3939
return 1
4040
fi
4141
}
42+
43+
assert_not_match() {
44+
if [[ "$2" =~ $1 ]]; then
45+
echo "expected: $1"
46+
echo "actual: $2"
47+
return 1
48+
fi
49+
}

test/suite.bats

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,17 @@ setup() {
1212
kubectl config view --flatten --minify > "$kubeconfig_file"
1313
# Change the current-context to $namespace
1414
kubectl --kubeconfig "$kubeconfig_file" config set-context ${current_context} --namespace "$namespace"
15+
# Create a kubeconfig json without users (no token)
16+
kubeconfig_file_no_token="$(mktemp)"
17+
kubectl config view --flatten --minify -o json | jq -r 'del(.contexts[0].context.user,.users)' > "$kubeconfig_file_no_token"
18+
# create rolebinding for full namespace access to default service account in namespace to avoid forbidden errors with token
19+
kubectl create -n $namespace rolebinding --clusterrole=cluster-admin --serviceaccount=$namespace:default testaccount
20+
# get default service account
21+
serviceaccount=$(kubectl get -n $namespace serviceaccount default -o json | jq -r '.secrets[0].name')
22+
# Extract server from service account for testing
23+
server="$(kubectl get -n $namespace secret "$serviceaccount" -o json | jq -r '.data["server"]' | base64 -d)"
24+
# Extract token from service account for testing
25+
token="$(kubectl get -n $namespace secret "$serviceaccount" -o json | jq -r '.data["token"]' | base64 -d)"
1526
}
1627

1728
teardown() {
@@ -21,6 +32,14 @@ teardown() {
2132
rm "$kubeconfig_file"
2233
}
2334

35+
@test "with outputs.use_aws_iam_authenticator" {
36+
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"}}' \
37+
--arg server "$server" \
38+
--arg token "$token" \
39+
--arg kubectl "get po nginx")"
40+
assert_not_match 'did not find expected key' "$output"
41+
}
42+
2443
@test "with source.kubeconfig" {
2544
run assets/out <<< "$(jq -n '{"source": {"kubeconfig": $kubeconfig}, "params": {"kubectl": $kubectl}}' \
2645
--arg kubeconfig "$(cat "$kubeconfig_file")" \
@@ -57,6 +76,16 @@ teardown() {
5776
assert_failure
5877
}
5978

79+
@test "with no credentials in outputs.kubeconfig_file and source.token" {
80+
run assets/out <<< "$(jq -n '{"source": {"token": $token}, "params": {"kubectl": $kubectl, "kubeconfig_file": $kubeconfig_file, "namespace": $namespace}}' \
81+
--arg token "$token" \
82+
--arg kubeconfig_file "$kubeconfig_file_no_token" \
83+
--arg kubectl "get ns $namespace -o name" \
84+
--arg namespace "$namespace")"
85+
assert_match "namespace/$namespace" "$output"
86+
assert_success
87+
}
88+
6089
@test "command substitution in outputs.kubectl" {
6190
run kubectl --kubeconfig "$kubeconfig_file" run nginx --image=nginx
6291
assert_success

0 commit comments

Comments
 (0)