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