blob: 5a8bf44defe8c14ee6e235b212aa3c55be6df8e6 [file] [log] [blame]
demx8as6a93cb372021-06-06 16:05:58 +02001#!/usr/bin/env python
demx8as6cd178822023-07-01 13:44:31 +00002#############################################################################
3# Copyright 2023 highstreet technologies GmbH
demx8as6a93cb372021-06-06 16:05:58 +02004#
5# Licensed under the Apache License, Version 2.0 (the 'License');
6# you may not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8#
9# http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an 'AS IS' BASIS,
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
16#
17
18# importing the sys, json, requests library
19import os
Martin Skorupski990de722023-02-03 12:30:55 +010020import pathlib
demx8as6a93cb372021-06-06 16:05:58 +020021import sys
22import json
demx8as6f81ad302022-09-15 14:19:17 +020023import time
demx8as6a93cb372021-06-06 16:05:58 +020024import getpass
demx8as6f81ad302022-09-15 14:19:17 +020025import requests
demx8as6b5ec0302023-07-06 14:09:11 +000026import re
demx8as6f81ad302022-09-15 14:19:17 +020027import warnings
28from jproperties import Properties
29from typing import List
30warnings.filterwarnings('ignore', message='Unverified HTTPS request')
demx8as6a93cb372021-06-06 16:05:58 +020031# global configurations
demx8as6a93cb372021-06-06 16:05:58 +020032
demx8as6f81ad302022-09-15 14:19:17 +020033
34def get_environment_variable(name):
35 configs = Properties()
demx8as6cd178822023-07-01 13:44:31 +000036 path = pathlib.Path(os.path.dirname(os.path.abspath(__file__)))
Martin Skorupski990de722023-02-03 12:30:55 +010037 env_file = str(path.parent.absolute()) + '/.env'
demx8as6f81ad302022-09-15 14:19:17 +020038 with open(env_file, "rb") as read_prop:
39 configs.load(read_prop)
demx8as6b5ec0302023-07-06 14:09:11 +000040 value = configs.get(name).data
41
42 regex = r"\$\{([^\}]+)\}"
43 matches = re.finditer(regex, value)
44 while True:
45 match = next(matches, None)
46 if match is None:
47 break
48 inner = get_environment_variable(match.group(1))
49 value = value.replace("${" + match.group(1) + "}", inner )
50 return value
demx8as6f81ad302022-09-15 14:19:17 +020051
52
53def load_arguments(args: List[str]) -> tuple:
54 realm_file = os.path.dirname(os.path.abspath(
55 __file__)) + '/o-ran-sc-realm.json'
56 auth_file = os.path.dirname(os.path.abspath(
57 __file__)) + '/authentication.json'
58 ready_timeout = 180
59 args.pop(0)
60 while len(args) > 0:
61 arg = args.pop(0)
62 if arg == '--auth' and len(args) > 0:
63 auth_file = args.pop(0)
64 print('overwriting auth file: {}'.format(auth_file))
65 elif arg == '--realm' and len(args) > 0:
66 realm_file = args.pop(0)
67 print('overwriting realm file: {}'.format(realm_file))
68 elif arg == '--timeout' and len(args) > 0:
69 ready_timeout = int(args.pop(0))
70 print('waiting for ready {} seconds'.format(ready_timeout))
71
72 return (realm_file, auth_file, ready_timeout)
73
74
75def isReady(timeoutSeconds=180):
demx8as6cd178822023-07-01 13:44:31 +000076 url = getBaseUrl()
demx8as6b5ec0302023-07-06 14:09:11 +000077 print(f'url={url}')
demx8as6f81ad302022-09-15 14:19:17 +020078 while timeoutSeconds > 0:
79 try:
80 response = requests.get(url, verify=False, headers={})
81 except:
demx8as6cd178822023-07-01 13:44:31 +000082 response = None
demx8as6f81ad302022-09-15 14:19:17 +020083 if response is not None and response.status_code == 200:
84 return True
85 time.sleep(1)
86 timeoutSeconds -= 1
87 return False
88
89
90def getBaseUrl():
91 return get_environment_variable("IDENTITY_PROVIDER_URL")
92
93# Request a token for further communication
demx8as6cd178822023-07-01 13:44:31 +000094
95
demx8as6a93cb372021-06-06 16:05:58 +020096def getToken():
demx8as6f81ad302022-09-15 14:19:17 +020097 url = base + '/realms/master/protocol/openid-connect/token'
demx8as6a93cb372021-06-06 16:05:58 +020098 headers = {
99 'content-type': 'application/x-www-form-urlencoded',
100 'accept': 'application/json'
101 }
102 body = {
demx8as6f81ad302022-09-15 14:19:17 +0200103 'client_id': 'admin-cli',
104 'grant_type': 'password',
105 'username': username,
106 'password': password
demx8as6a93cb372021-06-06 16:05:58 +0200107 }
108 try:
demx8as6f81ad302022-09-15 14:19:17 +0200109 response = requests.post(url, verify=False, auth=(
110 username, password), data=body, headers=headers)
demx8as6a93cb372021-06-06 16:05:58 +0200111 except requests.exceptions.Timeout:
demx8as6f81ad302022-09-15 14:19:17 +0200112 sys.exit('HTTP request failed, please check you internet connection.')
demx8as6a93cb372021-06-06 16:05:58 +0200113 except requests.exceptions.TooManyRedirects:
demx8as6f81ad302022-09-15 14:19:17 +0200114 sys.exit('HTTP request failed, please check your proxy settings.')
demx8as6a93cb372021-06-06 16:05:58 +0200115 except requests.exceptions.RequestException as e:
demx8as6f81ad302022-09-15 14:19:17 +0200116 # catastrophic error. bail.
117 raise SystemExit(e)
demx8as6a93cb372021-06-06 16:05:58 +0200118
119 if response.status_code >= 200 and response.status_code < 300:
demx8as6f81ad302022-09-15 14:19:17 +0200120 print('Got token!')
121 return response.json()['access_token']
demx8as6a93cb372021-06-06 16:05:58 +0200122 else:
demx8as6f81ad302022-09-15 14:19:17 +0200123 sys.exit('Getting token failed.')
demx8as6a93cb372021-06-06 16:05:58 +0200124
125# create the default realm from file
demx8as6a93cb372021-06-06 16:05:58 +0200126
demx8as6f81ad302022-09-15 14:19:17 +0200127
128def createRealm(token, realm):
129 url = base + '/admin/realms'
130 auth = 'bearer ' + token
131 headers = {
132 'content-type': 'application/json',
133 'accept': 'application/json',
134 'authorization': auth
135 }
136 try:
137 response = requests.post(
138 url, verify=False, json=realm, headers=headers)
139 except requests.exceptions.Timeout:
140 sys.exit('HTTP request failed, please check you internet connection.')
141 except requests.exceptions.TooManyRedirects:
142 sys.exit('HTTP request failed, please check your proxy settings.')
143 except requests.exceptions.RequestException as e:
144 # catastrophic error. bail.
145 raise SystemExit(e)
146
147 return response.status_code >= 200 and response.status_code < 300
demx8as6a93cb372021-06-06 16:05:58 +0200148
149# Check if default realm exists
demx8as6a93cb372021-06-06 16:05:58 +0200150
demx8as6f81ad302022-09-15 14:19:17 +0200151
152def checkRealmExists(token, realmId):
153 url = base + '/admin/realms/' + realmId
154 auth = 'bearer ' + token
155 headers = {
156 'accept': 'application/json',
157 'authorization': auth
158 }
159 try:
160 response = requests.get(url, verify=False, headers=headers)
161 except requests.exceptions.Timeout:
162 sys.exit('HTTP request failed, please check you internet connection.')
163 except requests.exceptions.TooManyRedirects:
164 sys.exit('HTTP request failed, please check your proxy settings.')
165 except requests.exceptions.RequestException as e:
166 # catastrophic error. bail.
167 raise SystemExit(e)
168
169 if response.status_code >= 200 and response.status_code < 300:
170 return realmId == response.json()['id']
171 else:
172 # sys.exit('Getting realm failed.')
173 return False
demx8as6a93cb372021-06-06 16:05:58 +0200174
175# create a user in default realm
demx8as6a93cb372021-06-06 16:05:58 +0200176
demx8as6f81ad302022-09-15 14:19:17 +0200177
178def createUser(token, realmConfig, user):
179 realmId = realmConfig['id']
180 url = base + '/admin/realms/' + realmId + '/users'
181 auth = 'bearer ' + token
182 headers = {
183 'accept': 'application/json',
184 'authorization': auth
185 }
186 try:
187 response = requests.post(url, verify=False, json=user, headers=headers)
188 except requests.exceptions.Timeout:
189 sys.exit('HTTP request failed, please check you internet connection.')
190 except requests.exceptions.TooManyRedirects:
191 sys.exit('HTTP request failed, please check your proxy settings.')
192 except requests.exceptions.RequestException as e:
193 # catastrophic error. bail.
194 raise SystemExit(e)
195
196 if response.status_code >= 200 and response.status_code < 300:
197 print('User', user['username'], 'created!')
198 else:
199 print('User creation', user['username'], 'failed!\n', response.text)
demx8as6a93cb372021-06-06 16:05:58 +0200200
201# creates User accounts in realm based a file
demx8as6f81ad302022-09-15 14:19:17 +0200202
203
204def createUsers(token, realmConfig, authConfig):
205 for user in authConfig['users']:
206 createUser(token, realmConfig, user)
207
208 # create a user based on system user
209 systemUser = {
210 "firstName": getpass.getuser(),
211 "lastName": "",
212 "email": getpass.getuser() + "@sdnr.onap.org",
213 "enabled": "true",
214 "username": getpass.getuser(),
215 "credentials": [
216 {
217 "type": "password",
218 "value": password,
Martin Skorupskia6355d12023-04-08 11:52:18 +0200219 "temporary": True
demx8as6f81ad302022-09-15 14:19:17 +0200220 }
demx8as6cd178822023-07-01 13:44:31 +0000221 ],
222 "requiredActions": [
223 "UPDATE_PASSWORD"
224 ]
demx8as6f81ad302022-09-15 14:19:17 +0200225 }
226 createUser(token, realmConfig, systemUser)
demx8as6a93cb372021-06-06 16:05:58 +0200227
228# Grants a role to a user
demx8as6a93cb372021-06-06 16:05:58 +0200229
demx8as6f81ad302022-09-15 14:19:17 +0200230
231def addUserRole(user: dict, role: dict, options: dict):
232 url = options['url'] + '/' + user['id'] + '/role-mappings/realm'
233 try:
234 response = requests.post(url, verify=False, json=[
demx8as6cd178822023-07-01 13:44:31 +0000235 {'id': role['id'], 'name':role['name']}],
236 headers=options['headers'])
demx8as6f81ad302022-09-15 14:19:17 +0200237 except requests.exceptions.Timeout:
238 sys.exit('HTTP request failed, please check you internet connection.')
239 except requests.exceptions.TooManyRedirects:
240 sys.exit('HTTP request failed, please check your proxy settings.')
241 except requests.exceptions.RequestException as e:
242 # catastrophic error. bail.
243 raise SystemExit(e)
244
245 if response.status_code >= 200 and response.status_code < 300:
246 print('User role', user['username'], role['name'], 'created!')
247 else:
248 print('Creation of user role',
249 user['username'], role['name'], 'failed!\n', response.text)
demx8as6a93cb372021-06-06 16:05:58 +0200250
251# searches for the role of a given user
demx8as6f81ad302022-09-15 14:19:17 +0200252
demx8as6cd178822023-07-01 13:44:31 +0000253
demx8as6f81ad302022-09-15 14:19:17 +0200254def findRole(username: str, authConfig: dict, realmConfig: dict) -> dict:
255 roleName = 'administration'
256 for grant in authConfig['grants']:
257 if grant['username'] == username:
258 roleName = grant['role']
259 for role in realmConfig['roles']['realm']:
260 if role['name'] == roleName:
261 return role
262 return None
demx8as6a93cb372021-06-06 16:05:58 +0200263
264# adds roles to users
demx8as6a93cb372021-06-06 16:05:58 +0200265
demx8as6f81ad302022-09-15 14:19:17 +0200266
267def addUserRoles(token, realmConfig, authConfig):
268 realmId = realmConfig['id']
269 url = base + '/admin/realms/' + realmId + '/users'
270 auth = 'bearer ' + token
271 headers = {
272 'content-type': 'application/json',
273 'accept': 'application/json',
274 'authorization': auth
demx8as6a93cb372021-06-06 16:05:58 +0200275 }
demx8as6f81ad302022-09-15 14:19:17 +0200276 try:
277 response = requests.get(url, verify=False, headers=headers)
278 except requests.exceptions.Timeout:
279 sys.exit('HTTP request failed, please check you internet connection.')
280 except requests.exceptions.TooManyRedirects:
281 sys.exit('HTTP request failed, please check your proxy settings.')
282 except requests.exceptions.RequestException as e:
283 # catastrophic error. bail.
284 raise SystemExit(e)
285
286 if response.status_code >= 200 and response.status_code < 300:
287 users = response.json()
288 options = {
289 "url": url,
290 "auth": auth,
291 "headers": headers
292 }
293 for user in users:
294 role = findRole(user['username'], authConfig, realmConfig)
295 addUserRole(user, role, options)
296 else:
297 sys.exit('Getting users failed.')
demx8as6a93cb372021-06-06 16:05:58 +0200298
299# main
demx8as6f81ad302022-09-15 14:19:17 +0200300
301
302(realmFile, authFile, readyTimeout) = load_arguments(sys.argv)
303username = get_environment_variable('ADMIN_USERNAME')
304password = get_environment_variable('ADMIN_PASSWORD')
305base = getBaseUrl()
306isReady(readyTimeout)
demx8as6a93cb372021-06-06 16:05:58 +0200307token = getToken()
308if token:
demx8as6f81ad302022-09-15 14:19:17 +0200309 with open(realmFile) as file:
310 realmConfig = json.load(file)
311 if not checkRealmExists(token, realmConfig['id']):
312 createRealm(token, realmConfig)
demx8as6a93cb372021-06-06 16:05:58 +0200313
demx8as6f81ad302022-09-15 14:19:17 +0200314 with open(authFile) as authConfig:
315 authConfig = json.load(authConfig)
316 createUsers(token, realmConfig, authConfig)
317 addUserRoles(token, realmConfig, authConfig)
318 exit(0)
319exit(1)