-
Notifications
You must be signed in to change notification settings - Fork 0
/
oc-context
executable file
·284 lines (227 loc) · 8.13 KB
/
oc-context
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
#!/bin/bash
set -eo pipefail
shopt -s nullglob
CFG="$HOME/.config/oc-context"
EDITOR=${EDITOR-vi}
function banner() {
cat <<'EOF'
___ ___ _ _ __ _ _ _
/ _ \ _ __ ___ _ _ / __| |_ (_)/ _| |_ __ ___ _ _| |_ _____ _| |_
| (_) | '_ \/ -_) ' \\__ \ ' \| | _| _| / _/ _ \ ' \ _/ -_) \ / _|
\___/| .__/\___|_||_|___/_||_|_|_| \__| \__\___/_||_\__\___/_\_\\__|
|_|
EOF
}
function usage() {
cat <<'EOF'
usage: oc-context <cmd>|<context>
--------------------------------------------
help show usage information
list list all availabe contexts
create <context> create a new context
import <context> import current context
edit <context> edit config
delete <context> deletes a context
[use] <context> use a context
create-cert create user certificate
EOF
exit 0
}
function read_var() {
cat "$1" | grep -e "^\\(export *\\)\\?$2=" | sed 's/[^=]*=\(.*\)/\1/' || echo "not set"
}
function list() {
( echo -e "NAME|CONSOLE|VERSION|USER"
for p in $CFG/*; do
OC_NAME=$(basename $p)
OC_CONSOLE=$(read_var "$p/env" OC_CONSOLE)
OC_VERSION=$(read_var "$p/env" OC_VERSION)
OC_USER=$(read_var "$p/env" OC_USER)
echo -e "$OC_NAME|$OC_CONSOLE|$OC_VERSION|$OC_USER"
done
) | column -t -s '|'
}
function select_context() {
[[ ! "$OC_NAME" == "" ]] && echo "Already in an OpenShift context. Please leave context first." && exit 1
OC_NAME=""
for p in $CFG/*; do
c=$(basename $p)
if [[ "$c" =~ .*$1.* ]]; then
if [[ ! "$OC_NAME" == "" ]]; then
echo "$1 has multiple matches. ($OC_NAME and $c)"
exit 1
fi
OC_NAME="$c"
#exact match
if [[ "$c" == "$1" ]]; then
break
fi
fi
done
if [[ "$OC_NAME" == "" ]]; then
echo "$1 not found."
exit 1
fi
source "$CFG/$OC_NAME/env"
clear
banner
echo ""
env | grep -e "^OC_" | sort | column -t -s =
echo ""
}
function create_cert() {
if [ "$OC_NAME" == "" ]; then
echo "OC_NAME not set. Please enter an OpenShift context first."
exit 1
fi
if ! oc auth can-i create csr &> /dev/null ; then
echo "Not able to create CSRs. Please login to the cluster first."
exit 1
fi
if [ "$OC_USER" == "" ]; then
OC_USER=$(oc whoami)
fi
openssl genrsa -out $CFG/$OC_NAME/$OC_USER.key 2048
openssl req -new -key $CFG/$OC_NAME/$OC_USER.key -out $CFG/$OC_NAME/$OC_USER.csr -subj "/CN=$OC_USER"
cat <<EOF | oc create -f -
apiVersion: certificates.k8s.io/v1beta1
kind: CertificateSigningRequest
metadata:
name: $OC_USER
spec:
groups:
- system:authenticated
request: $(cat "$CFG/$OC_NAME/$OC_USER.csr" | base64 | tr -d '\n')
usages:
- digital signature
- key encipherment
- client auth
EOF
oc adm certificate approve $OC_USER
sleep 3
oc get csr $OC_USER -o jsonpath='{.status.certificate}' | base64 -d > $CFG/$OC_NAME/$OC_USER.crt
oc delete csr $OC_USER
MASTER_URL=$(oc whoami --show-server)
oc adm create-kubeconfig --client-certificate $CFG/$OC_NAME/$OC_USER.crt --client-key $CFG/$OC_NAME/$OC_USER.key --certificate-authority $CFG/$OC_NAME/$OC_USER.crt --master=$MASTER_URL --kubeconfig $CFG/$OC_NAME/.kubeconfig
sed '/certificate-authority-data/d' -i $CFG/$OC_NAME/.kubeconfig
}
function use_context() {
select_context "$1"
OC_PATH=$(oc-select path "$OC_VERSION")
export PATH=$OC_PATH:$PATH
export KUBECONFIG=$CFG/$OC_NAME/.kubeconfig
export OC_NAME=$OC_NAME
export OC_CONTEXT_INFO="OpenShift $OC_NAME "
export OC_USER=$OC_USER
export OC_VERSION=$OC_VERSION
if [[ "$OC_USE_CLIENT_CERTIFICATE" == "true" ]]; then
CERTFILE=$CFG/$OC_NAME/$OC_USER.crt
if openssl x509 -in "$CERTFILE" -checkend 0 > /dev/null ; then
if ! openssl x509 -in "$CERTFILE" -checkend 604800 > /dev/null ; then
echo "Certificate will expire in less than 7 days. Creating new certificate."
create_cert "$1"
fi
else
echo "Certificate is expired. Fallback to next method."
fi
fi
if ! oc whoami &>/dev/null; then
password=$(eval $OC_PW_FUNCTION) &&
oc login "$OC_URL" --username=$OC_USER --password=$password || true
fi
if oc whoami &>/dev/null; then
oc project || true
fi
exec $SHELL
}
function edit_context() {
OC_NAME=$1
[[ "$OC_NAME" == "" ]] && usage
[[ ! -e "$CFG/$OC_NAME/env" ]] && echo "Context $OC_NAME doesn't exists" && exit 1
$EDITOR "$CFG/$OC_NAME/env"
}
function create_context() {
OC_NAME=$1
[[ "$OC_NAME" == "" ]] && usage
[[ -e "$CFG/$OC_NAME/env" ]] && echo "Context $OC_NAME already exists" && exit 1
mkdir -p "$CFG/$OC_NAME"
cat <<EOF > "$CFG/$OC_NAME/env"
export OC_VERSION=4.3
export OC_URL=api.openshift-sandbox.catalysts.digital:6443
export OC_USER=username
#OC_PW_FUNCTION="echo mypassword"
#OC_PW_FUNCTION="systemd-ask-password password:"
#OC_PW_FUNCTION="pass openshift/sandbox/username"
export OC_TOKEN_URL=https://oauth-openshift.apps.openshift-sandbox.catalysts.digital/oauth/token/request
# create user certificate first with 'oc-context create-cert'
export OC_USE_CLIENT_CERTIFICATE=false
# export all variables you want to have in your context
export OC_CONSOLE=https://console.apps.openshift-sandbox.catalysts.digital
export OC_REGISTRY=default-route-openshift-image-registry.apps.openshift-sandbox.catalysts.digital
EOF
edit_context "$OC_NAME"
}
function discover_version() {
VERSION=$(oc version | grep "Kubernetes Version" | sed 's/Kubernetes Version: v1\.\([^.]*\).*/3.\1/')
case $VERSION in
3.13) echo "4.1";;
3.14) echo "4.2";;
3.16) echo "4.3";;
3.17) echo "4.4";;
*) echo "$VERSION";;
esac
}
function discover_token_url() {
oc login -u invalid_user -p invalid_password | grep "You must obtain" | sed 's/You must obtain an API token by visiting //'
}
function discover_registry() {
IS=$(oc get is -o custom-columns=n:metadata.name --no-headers -n openshift | head -n1 || true)
[[ ! -z "$IS" ]] && oc get is $IS -n openshift -ojson | jq -r '.status.publicDockerImageRepository' | cut -f1 -d"/" || true
}
function import_context() {
OC_NAME=$1
[[ "$OC_NAME" == "" ]] && usage
oc whoami &> /dev/null || (echo "You must be logged in to a server!" && exit 1)
[[ -e "$CFG/$OC_NAME/env" ]] && echo "Context $OC_NAME already exists" && exit 1
mkdir -p "$CFG/$OC_NAME"
OC_URL=$(oc whoami --show-server)
OC_USER=$(oc whoami)
cat <<EOF > "$CFG/$OC_NAME/env"
export OC_VERSION=$(discover_version)
export OC_URL=$OC_URL
export OC_USER=$OC_USER
#OC_PW_FUNCTION="echo my_insecure_password"
#OC_PW_FUNCTION="systemd-ask-password password:"
#OC_PW_FUNCTION="pass openshift/sandbox/username"
export OC_TOKEN_URL=$(discover_token_url)
# create user certificate first with 'oc-context create-cert'
export OC_USE_CLIENT_CERTIFICATE=false
# export all variables you want to have in your context
export OC_CONSOLE=$(oc whoami --show-server)
export OC_REGISTRY=$(discover_registry)
EOF
if oc whoami -t &> /dev/null ; then
#initialize kubeconfig with current token
oc login --kubeconfig="$CFG/$OC_NAME/.kubeconfig" --server=$OC_URL --token=$(oc whoami -t) &> /dev/null
fi
edit_context "$OC_NAME"
}
function delete_context() {
OC_NAME=$1
[[ "$OC_NAME" == "" ]] && usage
[[ ! -e "$CFG/$OC_NAME/env" ]] && echo "Context $OC_NAME doesn't exists" && exit 1
read -p "Do you really want to delete openshift context $OC_NAME? (y/N) "
([[ "$REPLY" == "y" ]] || [[ "$REPLY" == "Y" ]]) && rm -fr "$CFG/$OC_NAME" && echo "Context $OC_NAME deleted!"
}
[[ "$1" == "" ]] && usage
case "$1" in
list) list;;
help) usage;;
create) create_context "$2";;
import) import_context "$2";;
edit) edit_context "${2-$OC_NAME}";;
delete) delete_context "$2";;
use) use_context "$2";;
create-cert) create_cert;;
*) use_context "$1";;
esac