-
Notifications
You must be signed in to change notification settings - Fork 9
/
Copy path_functions_keycloak.sh
236 lines (218 loc) · 10.2 KB
/
_functions_keycloak.sh
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
#!/bin/bash -eu
# Don't load it several times
set +u
${_FUNCTIONS_KEYCLOAK_LOADED:-false} && return
set -u
# if the script was started from the base directory, then the
# expansion returns a period
if test "${SCRIPT_DIR}" == "."; then
SCRIPT_DIR="$PWD"
# if the script was not called with an absolute path, then we need to add the
# current working directory to the relative path of the script
elif test "${SCRIPT_DIR:0:1}" != "/"; then
SCRIPT_DIR="$PWD/${SCRIPT_DIR}"
fi
do_get_keycloak_settings() {
if [ "${DEPLOYMENT_KEYCLOAK_ENABLED}" == "false" ]; then
return;
fi
env_var DEPLOYMENT_KEYCLOAK_CONTAINER_NAME "${INSTANCE_KEY}_Keycloak"
}
#
# Drops all Keycloak data used by the instance.
#
do_drop_keycloak_data() {
echo_info "Dropping Keycloak data ..."
if [ "${DEPLOYMENT_KEYCLOAK_ENABLED}" == "true" ]; then
echo_info "Drops Keycloak container ${DEPLOYMENT_KEYCLOAK_CONTAINER_NAME} ..."
delete_docker_container ${DEPLOYMENT_KEYCLOAK_CONTAINER_NAME}
delete_docker_volume ${DEPLOYMENT_KEYCLOAK_CONTAINER_NAME}
echo_info "Done."
echo_info "Keycloak data dropped"
else
echo_info "Skip Drops Keycloak container ..."
fi
}
do_create_keycloak() {
if [ "${DEPLOYMENT_KEYCLOAK_ENABLED}" == "true" ]; then
echo_info "Creation of the Keycloak Docker volume ${DEPLOYMENT_KEYCLOAK_CONTAINER_NAME} ..."
create_docker_volume ${DEPLOYMENT_KEYCLOAK_CONTAINER_NAME}
fi
}
do_stop_keycloak() {
echo_info "Stopping Keycloak ..."
if [ "${DEPLOYMENT_KEYCLOAK_ENABLED}" == "false" ]; then
echo_info "Keycloak wasn't specified, skiping its server container shutdown"
return
fi
ensure_docker_container_stopped ${DEPLOYMENT_KEYCLOAK_CONTAINER_NAME}
echo_info "Keycloak container ${DEPLOYMENT_KEYCLOAK_CONTAINER_NAME} stopped."
}
do_start_keycloak() {
echo_info "Starting Keycloak..."
if [ "${DEPLOYMENT_KEYCLOAK_ENABLED}" == "false" ]; then
echo_info "Keycloak not specified, skiping its server container startup"
return
fi
echo_info "Starting Keycloak container ${DEPLOYMENT_KEYCLOAK_CONTAINER_NAME} based on image ${DEPLOYMENT_KEYCLOAK_IMAGE}:${DEPLOYMENT_KEYCLOAK_IMAGE_VERSION}"
# Ensure there is no container with the same name
delete_docker_container ${DEPLOYMENT_KEYCLOAK_CONTAINER_NAME}
env_var DEP_URL "$(echo ${DEPLOYMENT_URL} | sed -e 's/\(.*\)/\L\1/')"
if [ "${DEPLOYMENT_KEYCLOAK_MODE:-SAML}" = "SAML" ]; then
evaluate_file_content ${ETC_DIR}/keycloak/client_saml2_def.json.template ${DEPLOYMENT_DIR}/client_def.json
else
evaluate_file_content ${ETC_DIR}/keycloak/client_openid_def.json.template ${DEPLOYMENT_DIR}/client_def.json
fi
local _startArgs=""
if ${DEPLOYMENT_APACHE_HTTPSONLY_ENABLED:-false}; then
_startArgs="--proxy-headers=xforwarded --hostname-strict=false"
fi
${DOCKER_CMD} run \
-d \
-e KC_BOOTSTRAP_ADMIN_USERNAME=bootstrap_admin \
-e KC_BOOTSTRAP_ADMIN_PASSWORD=b00tstrap_p@ssw0rd \
-e PROXY_ADDRESS_FORWARDING=${DEPLOYMENT_APACHE_HTTPSONLY_ENABLED:-false} \
-e KC_HTTP_RELATIVE_PATH=/auth \
-p "${DEPLOYMENT_KEYCLOAK_HTTP_PORT}:8080" \
-v ${DEPLOYMENT_KEYCLOAK_CONTAINER_NAME}:/opt/keycloak/data \
--health-cmd="timeout 2 /bin/bash -c '</dev/tcp/localhost/8080' || exit 1" \
--health-interval=30s \
--health-timeout=30s \
--health-retries=3 \
--name ${DEPLOYMENT_KEYCLOAK_CONTAINER_NAME} ${DEPLOYMENT_KEYCLOAK_IMAGE}:${DEPLOYMENT_KEYCLOAK_IMAGE_VERSION} start-dev ${_startArgs}
echo_info "${DEPLOYMENT_KEYCLOAK_CONTAINER_NAME} container started"
check_keycloak_availability
do_provision_keycloak_permanent_admin
do_provision_keycloak_clients
}
check_keycloak_availability() {
echo_info "Waiting for Keycloak availability on port ${DEPLOYMENT_KEYCLOAK_HTTP_PORT}"
local count=0
local try=600
local wait_time=1
local RET=-1
while [ $count -lt $try -a $RET -ne 0 ]; do
count=$(( $count + 1 ))
set +e
curl -s -q --max-time ${wait_time} http://localhost:${DEPLOYMENT_KEYCLOAK_HTTP_PORT} > /dev/null
RET=$?
if [ $RET -ne 0 ]; then
[ $(( ${count} % 10 )) -eq 0 ] && echo_info "Keycloak not yet available (${count} / ${try})..."
echo -n "."
sleep $wait_time
fi
set -e
done
if [ $count -eq $try ]; then
echo_error "Keycloak ${DEPLOYMENT_KEYCLOAK_CONTAINER_NAME} not available after $(( ${count} * ${wait_time}))s"
exit 1
fi
echo_info "Keycloak ${DEPLOYMENT_KEYCLOAK_CONTAINER_NAME} up and available"
}
# Restore dataset
do_restore_keycloak_dataset() {
do_drop_keycloak_data
do_create_keycloak
local _keycloakData="${DEPLOYMENT_DIR}/${DEPLOYMENT_DATA_DIR}/_restore/keycloak"
if [ ! -d ${_keycloakData} ]; then
echo_warn "Keycloak data (${_keycloakData}) don't exist."
return 0
fi
local mount_point=$(${DOCKER_CMD} volume inspect --format '{{ .Mountpoint }}' ${DEPLOYMENT_KEYCLOAK_CONTAINER_NAME})
sudo mv -v ${_keycloakData}/* ${mount_point}/ >/dev/null
sudo chown 1000:1000 -R ${mount_point}
rm -rf ${_keycloakData}
}
# Dump dataset
do_dump_keycloak_dataset() {
local _keycloakData="$1/keycloak"
mkdir -p ${_keycloakData}
local mount_point=$(${DOCKER_CMD} volume inspect --format '{{ .Mountpoint }}' ${DEPLOYMENT_KEYCLOAK_CONTAINER_NAME})
sudo chown 1000:1000 -R ${mount_point}
sudo cp -fTr "${mount_point}/" ${_keycloakData}/ || touch ${_keycloakData}/__nofile
}
# Provision Keycloak permanent admin user
do_provision_keycloak_permanent_admin() {
local KEYCLOAK_URL="http://localhost:${DEPLOYMENT_KEYCLOAK_HTTP_PORT}/auth"
local KC_TOKEN=$(curl -s -X POST \
-d "client_id=admin-cli" \
-d "username=bootstrap_admin" \
-d "password=b00tstrap_p@ssw0rd" \
-d "grant_type=password" \
"$KEYCLOAK_URL/realms/master/protocol/openid-connect/token" | jq -r '.access_token')
echo_info "Checking if user root already exists..."
local rootUserId=$(curl -s -X GET \
-H "Authorization: Bearer $KC_TOKEN" \
"$KEYCLOAK_URL/admin/realms/master/users?username=root" | jq -r '.[0].id')
if [ "$rootUserId" != "null" ] && [ -n "$rootUserId" ]; then
echo_info "User root already exists with ID: ${rootUserId}. Skipping creation."
else
echo_info "Creating a new admin user: root..."
local creationResp=$(curl -s -o /dev/null -w "%{http_code}" -X POST \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $KC_TOKEN" \
-d '{"username": "root", "enabled": true, "firstName": "Root", "lastName": "Root", "email": "[email protected]"}' \
"$KEYCLOAK_URL/admin/realms/master/users")
if [ "$creationResp" -ne 201 ]; then
echo_error "Failed to create user. HTTP status code: $creationResp"
exit 1
fi
echo_info "User created successfully."
rootUserId=$(curl -s -X GET \
-H "Authorization: Bearer $KC_TOKEN" \
"$KEYCLOAK_URL/admin/realms/master/users?username=root" | jq -r '.[0].id')
local setPassResp=$(curl -s -o /dev/null -w "%{http_code}" -X PUT \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $KC_TOKEN" \
-d '{ "type": "password", "value": "password", "temporary": false }' \
"$KEYCLOAK_URL/admin/realms/master/users/${rootUserId}/reset-password")
if [ "$setPassResp" -ne 204 ]; then
echo_error "Failed to set password. HTTP status code: $setPassResp"
exit 1
fi
echo_info "User root Password set successfully."
echo_info "Assigning admin role to root..."
local adminRoleId=$(curl -s -X GET \
-H "Authorization: Bearer $KC_TOKEN" \
"$KEYCLOAK_URL/admin/realms/master/roles" | jq -r --arg ROLE_NAME "admin" '.[] | select(.name == $ROLE_NAME) | .id')
if [ -z "$adminRoleId" ]; then
echo "Realm admin role $adminRoleId not found."
exit 1
fi
# Assign the realm role to the user
local roleAssignmentResp=$(curl -s -o /dev/null -w "%{http_code}" -X POST \
-H "Authorization: Bearer $KC_TOKEN" \
-H "Content-Type: application/json" \
-d '[{"id": "'"$adminRoleId"'", "name": "admin"}]' \
"$KEYCLOAK_URL/admin/realms/master/users/${rootUserId}/role-mappings/realm")
if [ "$roleAssignmentResp" -ne 204 ]; then
echo_error "Failed to assign admin role. HTTP status code: $roleAssignmentResp"
exit 1
fi
echo_info "Admin role assigned to user root successfully."
fi
}
# Provision Keycloak clients
do_provision_keycloak_clients() {
local token=$(curl -X POST "http://localhost:${DEPLOYMENT_KEYCLOAK_HTTP_PORT}/auth/realms/master/protocol/openid-connect/token" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "username=root" \
-d "password=password" \
-d 'grant_type=password' \
-d 'client_id=admin-cli' | jq -r '.access_token')
local keycloakRootUserId=$(curl -fssL "http://localhost:${DEPLOYMENT_KEYCLOAK_HTTP_PORT}/auth/admin/realms/master/users" -H 'Content-Type: application/json' -H "Authorization: Bearer $token" | jq -r '.[]| select(.username == "root") | .id')
local keycloakCreatedTimestamp=$(curl -fssL "http://localhost:${DEPLOYMENT_KEYCLOAK_HTTP_PORT}/auth/admin/realms/master/users" -H 'Content-Type: application/json' -H "Authorization: Bearer $token" | jq -r '.[]| select(.username == "root") | .createdTimestamp')
curl -s -X PUT --output /dev/null "http://localhost:${DEPLOYMENT_KEYCLOAK_HTTP_PORT}/auth/admin/realms/master/users/${keycloakRootUserId}" \
-H 'Content-type: application/json' \
-H "Authorization: Bearer ${token}" \
-d "{\"id\":\"${keycloakRootUserId}\",\"createdTimestamp\":${keycloakCreatedTimestamp},\"username\":\"root\",\"enabled\":true,\"totp\":false,\"emailVerified\":false,\"disableableCredentialTypes\":[],\"requiredActions\":[],\"notBefore\":0,\"access\":{\"manageGroupMembership\":true,\"view\":true,\"mapRoles\":true,\"impersonate\":true,\"manage\":true},\"attributes\":{},\"email\":\"[email protected]\",\"firstName\":\"Root\",\"lastName\":\"Root\"}" \
&& echo_info "Keycloak root user updated"
curl -s -X POST --output /dev/null "http://localhost:${DEPLOYMENT_KEYCLOAK_HTTP_PORT}/auth/admin/realms/master/clients" \
-H 'Content-type: application/json' \
-H "Authorization: Bearer ${token}" \
-d "@${DEPLOYMENT_DIR}/client_def.json" && echo_info "Keycloak client added"
}
# #############################################################################
# Env var to not load it several times
_FUNCTIONS_KEYCLOAK_LOADED=true
echo_debug "_function_keycloak.sh Loaded"