Updated installation and components
[nonrtric/plt/ranpm.git] / install / scripts / populate_keycloak.sh
1 #!/bin/bash
2
3 #  ============LICENSE_START===============================================
4 #  Copyright (C) 2023 Nordix Foundation. All rights reserved.
5 #  ========================================================================
6 #  Licensed under the Apache License, Version 2.0 (the "License");
7 #  you may not use this file except in compliance with the License.
8 #  You may obtain a copy of the License at
9 #
10 #       http://www.apache.org/licenses/LICENSE-2.0
11 #
12 #  Unless required by applicable law or agreed to in writing, software
13 #  distributed under the License is distributed on an "AS IS" BASIS,
14 #  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 #  See the License for the specific language governing permissions and
16 #  limitations under the License.
17 #  ============LICENSE_END=================================================
18 #
19
20 # Script intended to be sourced by other script to add functions to the keycloak rest API
21
22 echo "Cluster ip: $KUBERNETESHOST"
23
24 KC_URL=http://keycloak.nonrtric:8080
25 echo "Keycloak url: "$KC_URL
26
27 KC_PROXY_PORT=$(kubectl get svc -n nonrtric keycloak-proxy --output jsonpath='{.spec.ports[?(@.name=="http")].nodePort}')
28 echo "Nodeport to keycloak proxy: "$KC_PROXY_PORT
29
30 __get_admin_token() {
31     echo "Get admin token"
32     ADMIN_TOKEN=""
33     while [ "${#ADMIN_TOKEN}" -lt 20 ]; do
34         ADMIN_TOKEN=$(curl --proxy $KUBERNETESHOST:$KC_PROXY_PORT -s -X POST --max-time 2     "$KC_URL/realms/master/protocol/openid-connect/token"     -H "Content-Type: application/x-www-form-urlencoded"     -d "username=admin" -d "password=admin" -d 'grant_type=password' -d "client_id=admin-cli"  |  jq -r '.access_token')
35         if [ "${#ADMIN_TOKEN}" -lt 20 ]; then
36             echo "Could not get admin token, retrying..."
37             echo "Retrieved token: $ADMIN_TOKEN"
38         fi
39     done
40     echo "Admin token: ${ADMIN_TOKEN:0:10}..."
41     echo $ADMIN_TOKEN > .admin_token
42     __ADM_TOKEN_TS=$SECONDS
43 }
44
45 __check_admin_token() {
46     __diff=$(($SECONDS-$__ADM_TOKEN_TS))
47     if [ $__diff -gt 15 ]; then
48         __get_admin_token
49     fi
50 }
51
52 __get_admin_token
53
54 indent1() { sed 's/^/ /'; }
55 indent2() { sed 's/^/  /'; }
56
57 decode_token() {
58     echo "Decoding access_token"
59     echo $1 | jq -R 'split(".") | .[0,1] | @base64d | fromjson'
60 }
61
62 decode_jwt() {
63     echo "Decoding jwt"
64     echo $1 | jq -r .access_token | jq -R 'split(".") | .[0,1] | @base64d | fromjson'
65 }
66
67 list_realms() {
68     echo "Listing all realms"
69     __check_admin_token
70     curl --proxy $KUBERNETESHOST:$KC_PROXY_PORT -s \
71         -X GET \
72         -H "Authorization: Bearer ${ADMIN_TOKEN}" \
73         "$KC_URL/admin/realms" | jq -r '.[].id' | indent2
74 }
75 delete_realms() {
76     echo "$@"
77     for realm in "$@"; do
78         echo "Attempt to delete realm: $realm"
79         __check_admin_token
80         curl --proxy $KUBERNETESHOST:$KC_PROXY_PORT -s \
81         -X DELETE \
82         -H "Authorization: Bearer ${ADMIN_TOKEN}" \
83         "$KC_URL/admin/realms/$realm" | indent1
84         if [ $? -ne 0 ]; then
85             echo "Command failed"
86             exit 1
87         fi
88         echo " OK"
89     done
90 }
91
92 create_realms() {
93     echo "Creating realms: $@"
94     while [ $# -gt 0 ]; do
95         echo " Attempt to create realm: $1"
96         __check_admin_token
97 cat > .jsonfile1 <<- "EOF"
98 {
99 "realm":"$__realm_name",
100 "enabled":true
101 }
102 EOF
103         export __realm_name=$1
104         envsubst < .jsonfile1 > .jsonfile2
105         curl --proxy $KUBERNETESHOST:$KC_PROXY_PORT -s \
106         -X POST \
107         -H "Authorization: Bearer ${ADMIN_TOKEN}" \
108         -H "Content-Type: application/json" \
109         -d @".jsonfile2" \
110         "$KC_URL/admin/realms" | indent2
111         if [ $? -ne 0 ]; then
112             echo "Command failed"
113             exit 1
114         fi
115         echo "  OK"
116         shift
117     done
118 }
119
120 create_clients() {
121     __realm=$1
122     shift
123     echo "Attempt to create clients $@ for realm: $__realm"
124
125 cat > .jsonfile1 <<- "EOF"
126 {
127    "clientId":"$__client_name",
128    "publicClient": false,
129    "serviceAccountsEnabled": true,
130    "rootUrl":"https://example.com/example/",
131    "adminUrl":"https://example.com/example/"
132 }
133 EOF
134     while [ $# -gt 0 ]; do
135         echo " Creating client: $1"
136         __check_admin_token
137         export __client_name=$1
138         envsubst < .jsonfile1 > .jsonfile2
139         curl --proxy $KUBERNETESHOST:$KC_PROXY_PORT -s \
140         -X POST \
141         -H "Authorization: Bearer ${ADMIN_TOKEN}" \
142         -H "Content-Type: application/json" \
143         -d @".jsonfile2" \
144         "$KC_URL/admin/realms/$__realm/clients" | indent1
145         if [ $? -ne 0 ]; then
146             echo "Command failed"
147             exit 1
148         fi
149         echo " OK"
150         shift
151     done
152 }
153
154 __get_client_id() {
155     __client_data=$(curl --proxy $KUBERNETESHOST:$KC_PROXY_PORT -s \
156         -X GET \
157         -H "Authorization: Bearer ${ADMIN_TOKEN}" \
158         "$KC_URL/admin/realms/$1/clients?clientId=$2")
159     if [ $? -ne 0 ]; then
160         return 1
161     fi
162     __client_id=$(echo $__client_data |  jq -r '.[0].id')
163     echo $__client_id
164     return 0
165 }
166
167 generate_client_secrets() {
168     __realm=$1
169     shift
170     echo "Attempt to generate secret for clients $@ in realm $__realm"
171     while [ $# -gt 0 ]; do
172         __check_admin_token
173         __client_id=$(__get_client_id $__realm $1)
174         if [ $? -ne 0 ]; then
175             echo "Command failed"
176             exit 1
177         fi
178         echo " Client id for client $1 in realm $__realm: "$__client_id | indent1
179         echo "  Creating secret"
180         __client_secret=$(curl --proxy $KUBERNETESHOST:$KC_PROXY_PORT -s \
181                 -X POST \
182                 -H "Authorization: Bearer ${ADMIN_TOKEN}" \
183                 "$KC_URL/admin/realms/$__realm/clients/$__client_id/client-secret")
184         if [ $? -ne 0 ]; then
185             echo "Command failed"
186             exit 1
187         fi
188         __client_secret=$(curl --proxy $KUBERNETESHOST:$KC_PROXY_PORT -s \
189                 -X GET \
190                 -H "Authorization: Bearer ${ADMIN_TOKEN}" \
191                 "$KC_URL/admin/realms/$__realm/clients/$__client_id/client-secret")
192         if [ $? -ne 0 ]; then
193             echo "Command failed"
194             exit 1
195         fi
196         __client_secret=$(echo $__client_secret | jq -r .value)
197         echo "  Client secret for client $1 in realm $__realm: "$__client_secret | indent1
198         echo $__client_secret > ".sec_$__realm""_$1"
199         echo "   OK"
200         shift
201     done
202 }
203
204 create_client_roles() {
205     # <realm-name> <client-name> [<role-name>]+
206     __check_admin_token
207     __client_id=$(__get_client_id $1 $2)
208     if [ $? -ne 0 ]; then
209         echo "Command failed"
210         exit 1
211     fi
212     __realm=$1
213     shift; shift;
214     while [ $# -gt 0 ]; do
215
216 cat > .jsonfile1 <<- "EOF"
217 {
218    "name":"$__role"
219 }
220 EOF
221         export __role=$1
222         envsubst < .jsonfile1 > .jsonfile2
223         curl --proxy $KUBERNETESHOST:$KC_PROXY_PORT -s \
224         -X POST \
225         -H "Authorization: Bearer ${ADMIN_TOKEN}" \
226         -H "Content-Type: application/json" \
227         -d @".jsonfile2" \
228         "$KC_URL/admin/realms/$__realm/clients/$__client_id/roles" | indent1
229         if [ $? -ne 0 ]; then
230             echo "Command failed"
231             exit 1
232         fi
233         shift
234     done
235 }
236
237 __get_service_account_id() {
238     # <realm-name> <client-id>
239     __service_account_data=$(curl --proxy $KUBERNETESHOST:$KC_PROXY_PORT -s \
240         -X GET \
241         -H "Authorization: Bearer ${ADMIN_TOKEN}" \
242         "$KC_URL/admin/realms/$1/clients/$2/service-account-user")
243     if [ $? -ne 0 ]; then
244         return 1
245     fi
246     __service_account_id=$(echo $__service_account_data |  jq -r '.id')
247     echo $__service_account_id
248     return 0
249 }
250
251 #     curl --proxy $KUBERNETESHOST:$KC_PROXY_PORT -s \
252 #     -X GET \
253 #     -H "Authorization: Bearer ${ADMIN_TOKEN}" \
254 #     "$KC_URL/admin/realms/$__realm/users/$__service_account_id/role-mappings/clients/$__client_id/available"
255 __get_client_available_role_id() {
256     # <realm-name> <service-account-id> <client-id> <client-role-name>
257     __client_role_data=$(curl --proxy $KUBERNETESHOST:$KC_PROXY_PORT -s \
258         -X GET \
259         -H "Authorization: Bearer ${ADMIN_TOKEN}" \
260         "$KC_URL/admin/realms/$1/users/$2/role-mappings/clients/$3/available")
261     if [ $? -ne 0 ]; then
262         return 1
263     fi
264     #__client_role_id=$(echo $__client_role_data |  jq -r '.id')
265     __client_role_id=$(echo $__client_role_data | jq  -r '.[] | select(.name=="'$4'") | .id ')
266     echo $__client_role_id
267     return 0
268 }
269
270 __get_client_mapped_role_id() {
271     # <realm-name> <service-account-id> <client-id> <client-role-name>
272     __client_role_data=$(curl --proxy $KUBERNETESHOST:$KC_PROXY_PORT -s \
273         -X GET \
274         -H "Authorization: Bearer ${ADMIN_TOKEN}" \
275         "$KC_URL/admin/realms/$1/users/$2/role-mappings/clients/$3")
276     if [ $? -ne 0 ]; then
277         return 1
278     fi
279     #__client_role_id=$(echo $__client_role_data |  jq -r '.id')
280     __client_role_id=$(echo $__client_role_data | jq  -r '.[] | select(.name=="'$4'") | .id ')
281     echo $__client_role_id
282     return 0
283 }
284
285 add_client_roles_mapping()  {
286     # <realm-name> <client-name> [<role-name>]+
287     echo "Attempt to add roles ${@:3} to client $2 in realm $1"
288     __check_admin_token
289     __realm=$1
290     __client=$2
291     __client_id=$(__get_client_id $__realm $__client)
292     if [ $? -ne 0 ]; then
293         echo "Command failed"
294         exit 1
295     fi
296     echo " Client id for client $__client in realm $__realm: "$__client_id | indent1
297     __service_account_id=$(__get_service_account_id $__realm $__client_id)
298     if [ $? -ne 0 ]; then
299         echo "Command failed"
300         exit 1
301     fi
302     echo " Service account id for client $__client in realm $__realm: "$__service_account_id | indent1
303     shift; shift
304     __cntr=0
305     __all_roles=$@
306     while [ $# -gt 0 ]; do
307         if [ $__cntr -eq 0 ]; then
308             echo "[" > .jsonfile2
309         fi
310         __client_role_id=$(__get_client_available_role_id $__realm $__service_account_id $__client_id $1)
311         if [ $? -ne 0 ]; then
312             echo "Command failed"
313             exit 1
314         fi
315         #echo "CLIENT ROLE ID $1 "$__client_role_id
316         #echo " Role id for role $1 and client $__client in realm $__realm: "$__client_role_id | indent1
317         __role='{"name":"'$1'","id":"'$__client_role_id'","composite": false,"clientRole": true}'
318         if [ $__cntr -gt 0 ]; then
319             echo "," >> .jsonfile2
320         fi
321         echo $__role >> .jsonfile2
322         let __cntr=__cntr+1
323         shift
324     done
325     echo "]" >> .jsonfile2
326     echo "  Adding roles $__all_roles to client $__client in realm $__realm"
327
328     curl --proxy $KUBERNETESHOST:$KC_PROXY_PORT -s \
329     -X POST \
330     -H "Authorization: Bearer ${ADMIN_TOKEN}" \
331     -H "Content-Type: application/json" \
332     -d @".jsonfile2" \
333     "$KC_URL/admin/realms/$__realm/users/$__service_account_id/role-mappings/clients/$__client_id" | indent2
334     if [ $? -ne 0 ]; then
335         echo "Command failed"
336         exit 1
337     fi
338     echo "  OK"
339 }
340
341
342
343 remove_client_roles_mapping()  {
344     # <realm-name> <client-name> [<role-name>]+
345     echo "Attempt to removed roles ${@:3} from client $2 in realm $1"
346     __check_admin_token
347     __realm=$1
348     __client=$2
349     __client_id=$(__get_client_id $__realm $__client)
350     if [ $? -ne 0 ]; then
351         echo "Command failed"
352         exit 1
353     fi
354     echo " Client id for client $__client in realm $__realm: "$__client_id | indent1
355     __service_account_id=$(__get_service_account_id $__realm $__client_id)
356     if [ $? -ne 0 ]; then
357         echo "Command failed"
358         exit 1
359     fi
360     echo " Service account id for client $__client in realm $__realm: "$__service_account_id | indent1
361     shift; shift
362     __cntr=0
363     __all_roles=$@
364     while [ $# -gt 0 ]; do
365         if [ $__cntr -eq 0 ]; then
366             echo "[" > .jsonfile2
367         fi
368         __client_role_id=$(__get_client_mapped_role_id $__realm $__service_account_id $__client_id $1)
369         if [ $? -ne 0 ]; then
370             echo "Command failed"
371             exit 1
372         fi
373         #echo "CLIENT ROLE ID $1 "$__client_role_id
374         #echo " Role id for role $1 and client $__client in realm $__realm: "$__client_role_id | indent1
375         __role='{"name":"'$1'","id":"'$__client_role_id'","composite": false,"clientRole": true}'
376         if [ $__cntr -gt 0 ]; then
377             echo "," >> .jsonfile2
378         fi
379         echo $__role >> .jsonfile2
380         let __cntr=__cntr+1
381         shift
382     done
383     echo "]" >> .jsonfile2
384     echo "  Removing roles $__all_roles from client $__client in realm $__realm"
385
386     curl --proxy $KUBERNETESHOST:$KC_PROXY_PORT -s \
387     -X DELETE \
388     -H "Authorization: Bearer ${ADMIN_TOKEN}" \
389     -H "Content-Type: application/json" \
390     -d @".jsonfile2" \
391     "$KC_URL/admin/realms/$__realm/users/$__service_account_id/role-mappings/clients/$__client_id" | indent2
392     if [ $? -ne 0 ]; then
393         echo "Command failed"
394         exit 1
395     fi
396     echo "  OK"
397 }
398
399 add_client_hardcoded-claim-mapper() {
400 # <realm-name> <client-name> <mapper-name> <claim-name> <claim-value>
401     __check_admin_token
402     __realm=$1
403     __client=$2
404     export __mapper_name=$3
405     export __claim_name=$4
406     export __claim_value=$5
407
408     __client_id=$(__get_client_id $__realm $__client)
409     if [ $? -ne 0 ]; then
410         echo " Fatal error when getting client id, response: "$?
411         exit 1
412     fi
413     cat > .jsonfile1 <<- "EOF"
414 {
415     "name": "$__mapper_name",
416     "protocol": "openid-connect",
417     "protocolMapper": "oidc-hardcoded-claim-mapper",
418     "consentRequired": false,
419     "config": {
420       "claim.value": "$__claim_value",
421       "userinfo.token.claim": "true",
422       "id.token.claim": "true",
423       "access.token.claim": "true",
424       "claim.name": "$__claim_name",
425       "access.tokenResponse.claim": "false"
426     }
427 }
428 EOF
429     envsubst < .jsonfile1 > .jsonfile2
430     curl --proxy $KUBERNETESHOST:$KC_PROXY_PORT -s \
431     -X POST \
432     -H "Authorization: Bearer ${ADMIN_TOKEN}" \
433     -H "Content-Type: application/json" \
434     -d @".jsonfile2" \
435     "$KC_URL/admin/realms/nonrtric-realm/clients/"$__client_id"/protocol-mappers/models" | indent2
436     if [ $? -ne 0 ]; then
437         echo "Command failed"
438         exit 1
439     fi
440     set +x
441     cat .jsonfile2
442     echo "  OK"
443 }
444
445 # Get a client token
446 # args: <realm-name> <client-name>
447 get_client_token() {
448     __check_admin_token
449     __realm=$1
450     __client=$2
451     __client_id=$(__get_client_id $__realm $__client)
452     if [ $? -ne 0 ]; then
453         echo " Fatal error when getting client id, response: "$?
454         exit 1
455     fi
456     #echo " Client id for client $__client in realm $__realm: "$__client_id | indent1
457
458     __client_secret=$(curl --proxy $KUBERNETESHOST:$KC_PROXY_PORT -s -f \
459             -X GET \
460             -H "Authorization: Bearer ${ADMIN_TOKEN}" \
461             "$KC_URL/admin/realms/$__realm/clients/$__client_id/client-secret")
462     if [ $? -ne 0 ]; then
463         echo " Fatal error when getting client secret, response: "$?
464         exit 1
465     fi
466
467     __client_secret=$(echo $__client_secret | jq -r .value)
468
469         __TMP_TOKEN=$(curl --proxy $KUBERNETESHOST:$KC_PROXY_PORT -f -s -X POST $KC_URL/realms/$__realm/protocol/openid-connect/token   \
470                   -H Content-Type:application/x-www-form-urlencoded \
471                   -d client_id="$__client" -d client_secret="$__client_secret" -d grant_type=client_credentials)
472         if [ $? -ne 0 ]; then
473                 echo " Fatal error when getting client token, response: "$?
474                 exit 1
475         fi
476
477         echo $__TMP_TOKEN| jq -r .access_token
478         return 0
479 }