Skip to content

Commit c28ff3b

Browse files
committed
pxc-useradd added as component
1 parent 5d48e3c commit c28ff3b

File tree

1 file changed

+220
-0
lines changed

1 file changed

+220
-0
lines changed

component/useradd/pxc-useradd

+220
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,220 @@
1+
#!/bin/bash
2+
#
3+
# Copyright © 2020 Portworx
4+
#
5+
# Licensed under the Apache License, Version 2.0 (the "License");
6+
# you may not use this file except in compliance with the License.
7+
# You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing, software
12+
# distributed under the License is distributed on an "AS IS" BASIS,
13+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
# See the License for the specific language governing permissions and
15+
# limitations under the License.
16+
#
17+
18+
# USE ONLY FOR DEVELOPMENT
19+
# Implementation of the blog: https://www.openlogic.com/blog/granting-user-access-your-kubernetes-cluster
20+
21+
function fail() {
22+
echo "$1"
23+
exit 1
24+
}
25+
26+
# run() from BATS testing system
27+
function runorfail() {
28+
local origFlags="$-"
29+
set +eET
30+
local origIFS="$IFS"
31+
echo $@
32+
output="$("$@" 2>&1)"
33+
if [ $? -ne 0 ]; then
34+
fail "Failed to execute ${*}"
35+
fi
36+
IFS=$'\n' lines=($output)
37+
IFS="$origIFS"
38+
set "-$origFlags"
39+
}
40+
41+
# Creats a user in Kubernetes only. Use createUserKubeconfig() instead to create a full
42+
# kubeconfig for the new user.
43+
function createUser() {
44+
local username="$1"
45+
local location="$2"
46+
47+
runorfail openssl req -new -newkey rsa:4096 -nodes \
48+
-keyout ${location}/${username}-k8s.key \
49+
-out ${location}/${username}-k8s.csr \
50+
-subj "/CN=${username}/O=${ORGANIZATION}"
51+
52+
cat <<EOF | kubectl --context=$CONTEXT apply -f -
53+
apiVersion: certificates.k8s.io/v1beta1
54+
kind: CertificateSigningRequest
55+
metadata:
56+
name: ${username}-access
57+
spec:
58+
request: $(cat ${location}/${username}-k8s.csr | base64 | tr -d '\n')
59+
usages:
60+
- client auth
61+
EOF
62+
if [ $? -ne 0 ] ; then
63+
fail "Failed to create certificate signing request in Kubernetes"
64+
fi
65+
66+
runorfail kubectl --context=$CONTEXT certificate approve ${username}-access
67+
kubectl --context=$CONTEXT get csr ${username}-access \
68+
-o jsonpath='{.status.certificate}' | base64 --decode > ${location}/${username}-kubeconfig.crt
69+
if [ $? -ne 0 ] ; then
70+
fail "Failed to get certificate for user"
71+
fi
72+
}
73+
74+
# Creates a new Kubernetes user only able to access their namespace with the
75+
# same name. The kubeconfig for this user must be passed in.
76+
function createUserKubeconfig() {
77+
local user="$1"
78+
local location="$2"
79+
local cafile="$3"
80+
local kubeconfig="${location}/${user}-kubeconfig.conf"
81+
82+
echo ">>> Registering ${user}"
83+
84+
# create certs for user
85+
createUser "$user" "$location"
86+
87+
# Create namespace
88+
if ! kubectl --context=$CONTEXT get namespace ${NAMESPACE} > /dev/null 2>&1 ; then
89+
runorfail kubectl create namespace ${NAMESPACE} --context=$CONTEXT
90+
fi
91+
92+
# Enable user to use their namespace
93+
runorfail kubectl create rolebinding ${user}-admin \
94+
--context=$CONTEXT \
95+
--namespace=${NAMESPACE} \
96+
--clusterrole=admin \
97+
--user=${user}
98+
99+
# Enable token to have API access
100+
runorfail kubectl create rolebinding default-access-rest \
101+
--context=$CONTEXT \
102+
--namespace=${NAMESPACE} \
103+
--clusterrole=admin \
104+
--serviceaccount=${user}:default
105+
106+
echo ">>> Creating ${kubeconfig}"
107+
108+
# Create config for user
109+
kubectl config set-cluster $cluster \
110+
--server=$address \
111+
--certificate-authority=$cafile \
112+
--embed-certs=true \
113+
--kubeconfig=${kubeconfig}
114+
kubectl config set-credentials \
115+
${user} \
116+
--client-certificate=${location}/${user}-kubeconfig.crt \
117+
--client-key=${location}/${user}-k8s.key \
118+
--embed-certs \
119+
--kubeconfig=${kubeconfig}
120+
kubectl --kubeconfig=${kubeconfig} config set-context ${user} \
121+
--cluster=${cluster} \
122+
--user=${user} \
123+
--namespace=${NAMESPACE}
124+
kubectl --kubeconfig=${kubeconfig} config use-context ${user}
125+
126+
echo ""
127+
echo ">>> Kubeconfig ready: ${kubeconfig}"
128+
}
129+
130+
function usage() {
131+
echo "
132+
Creates a new Kubernetes user and creating a new kubeconfig
133+
134+
Usage:
135+
kubectl pxc useradd [flags]
136+
137+
Flags:
138+
-h, --help help for create
139+
--name Name of user
140+
--namespace Specify the new namespace for the user (default: user name)
141+
--organization Name of the organization (default: portworx)
142+
--px-secret Name of secret to contain the Portworx token (default: px-user-token)
143+
--outdir Directory where to place the created files (default: .)
144+
--kubeconfig Specify the kubeconfig to use (optional)
145+
--context Specify the context to use (optional)
146+
"
147+
exit 1
148+
}
149+
150+
parsed=$(getopt -o h -n "kubectl pxc useradd" --long name:,namespace:,help,organization:,px-secret:,outdir:,context:,kubeconfig: -- "$@" )
151+
if [ $? -ne 0 ] ; then
152+
usage
153+
fi
154+
155+
eval set -- "$parsed"
156+
157+
NAME=""
158+
ORGANIZATION="portworx"
159+
PXSECRET="px-user-token"
160+
NAMESPACE=""
161+
CONTEXT=""
162+
OUTDIR="."
163+
164+
while true; do
165+
case "$1" in
166+
--organization) ORGANIZATION="$2"; shift 2 ;;
167+
--namespace) NAMESPACE="$2"; shift 2 ;;
168+
--name) NAME="$2"; shift 2 ;;
169+
--px-secret) PXSECRET="$2"; shift 2 ;;
170+
--outdir) OUTDIR="$2"; shift 2 ;;
171+
--context) CONTEXT="$2"; shift 2;;
172+
--kubeconfig) export KUBECONFIG="$2"; shift 2;;
173+
-h | --help) usage;;
174+
--) shift; break ;;
175+
*) usage; break ;;
176+
esac
177+
done
178+
179+
if [ "$NAME" = "" ] ; then
180+
echo "Must provide a user name"
181+
exit 1
182+
fi
183+
184+
if [ "$NAMESPACE" = "" ] ; then
185+
NAMESPACE="$NAME"
186+
fi
187+
188+
if [ "$CONTEXT" = "" ] ; then
189+
CONTEXT=$(kubectl config view --raw -o jsonpath="{.current-context}")
190+
fi
191+
192+
if [ "$OUTDIR" != "." -a ! -d "$OUTDIR" ] ; then
193+
runorfail mkdir $OUTDIR
194+
fi
195+
196+
# Check that kubectl config works
197+
if ! kubectl --context=$CONTEXT version --short=true > /dev/null 2>&1 ; then
198+
fail "kubectl failed to communicate with Kubernetes. Is the kubeconfig setup correctly?"
199+
fi
200+
201+
# Use the current context cluster address and CA Cert data
202+
cafile=/tmp/cacert.$$
203+
cluster=$(kubectl config view --raw -o jsonpath="{.contexts[?(@.name==\"$CONTEXT\")].context.cluster}")
204+
address=$(kubectl config view --raw -o jsonpath="{.clusters[?(@.name==\"$cluster\")].cluster.server}")
205+
cacert_data=$(kubectl config view --raw -o jsonpath="{.clusters[?(@.name==\"$cluster\")].cluster.certificate-authority-data}")
206+
if [ -z ${cacert_data} ] ; then
207+
fail "No CA cert data found in cluster ${cluster}"
208+
elif [ ! -f ${cacert_data} ] ; then
209+
echo ${cacert_data} | base64 -d > $cafile
210+
delete_cafile=$cafile
211+
else
212+
cafile=$cacert_data
213+
fi
214+
215+
createUserKubeconfig "${NAME}" "${OUTDIR}" "${cafile}"
216+
217+
# Cleanup
218+
if [ -f $delete_cafile ] ; then
219+
rm -f $delete_cafile > /dev/null 2>&1
220+
fi

0 commit comments

Comments
 (0)