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