blob: 22ef6413e1185864c1429e4b5df51501082c34bf [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
26import warnings
27from jproperties import Properties
28from typing import List
29warnings.filterwarnings('ignore', message='Unverified HTTPS request')
demx8as6a93cb372021-06-06 16:05:58 +020030# global configurations
demx8as6a93cb372021-06-06 16:05:58 +020031
demx8as6f81ad302022-09-15 14:19:17 +020032
33def get_environment_variable(name):
34 configs = Properties()
demx8as6cd178822023-07-01 13:44:31 +000035 path = pathlib.Path(os.path.dirname(os.path.abspath(__file__)))
Martin Skorupski990de722023-02-03 12:30:55 +010036 env_file = str(path.parent.absolute()) + '/.env'
demx8as6f81ad302022-09-15 14:19:17 +020037 with open(env_file, "rb") as read_prop:
38 configs.load(read_prop)
39 return configs.get(name).data
40
41
42def load_arguments(args: List[str]) -> tuple:
43 realm_file = os.path.dirname(os.path.abspath(
44 __file__)) + '/o-ran-sc-realm.json'
45 auth_file = os.path.dirname(os.path.abspath(
46 __file__)) + '/authentication.json'
47 ready_timeout = 180
48 args.pop(0)
49 while len(args) > 0:
50 arg = args.pop(0)
51 if arg == '--auth' and len(args) > 0:
52 auth_file = args.pop(0)
53 print('overwriting auth file: {}'.format(auth_file))
54 elif arg == '--realm' and len(args) > 0:
55 realm_file = args.pop(0)
56 print('overwriting realm file: {}'.format(realm_file))
57 elif arg == '--timeout' and len(args) > 0:
58 ready_timeout = int(args.pop(0))
59 print('waiting for ready {} seconds'.format(ready_timeout))
60
61 return (realm_file, auth_file, ready_timeout)
62
63
64def isReady(timeoutSeconds=180):
demx8as6cd178822023-07-01 13:44:31 +000065 url = getBaseUrl()
demx8as6f81ad302022-09-15 14:19:17 +020066 while timeoutSeconds > 0:
67 try:
68 response = requests.get(url, verify=False, headers={})
69 except:
demx8as6cd178822023-07-01 13:44:31 +000070 response = None
demx8as6f81ad302022-09-15 14:19:17 +020071 if response is not None and response.status_code == 200:
72 return True
73 time.sleep(1)
74 timeoutSeconds -= 1
75 return False
76
77
78def getBaseUrl():
79 return get_environment_variable("IDENTITY_PROVIDER_URL")
80
81# Request a token for further communication
demx8as6cd178822023-07-01 13:44:31 +000082
83
demx8as6a93cb372021-06-06 16:05:58 +020084def getToken():
demx8as6f81ad302022-09-15 14:19:17 +020085 url = base + '/realms/master/protocol/openid-connect/token'
demx8as6a93cb372021-06-06 16:05:58 +020086 headers = {
87 'content-type': 'application/x-www-form-urlencoded',
88 'accept': 'application/json'
89 }
90 body = {
demx8as6f81ad302022-09-15 14:19:17 +020091 'client_id': 'admin-cli',
92 'grant_type': 'password',
93 'username': username,
94 'password': password
demx8as6a93cb372021-06-06 16:05:58 +020095 }
96 try:
demx8as6f81ad302022-09-15 14:19:17 +020097 response = requests.post(url, verify=False, auth=(
98 username, password), data=body, headers=headers)
demx8as6a93cb372021-06-06 16:05:58 +020099 except requests.exceptions.Timeout:
demx8as6f81ad302022-09-15 14:19:17 +0200100 sys.exit('HTTP request failed, please check you internet connection.')
demx8as6a93cb372021-06-06 16:05:58 +0200101 except requests.exceptions.TooManyRedirects:
demx8as6f81ad302022-09-15 14:19:17 +0200102 sys.exit('HTTP request failed, please check your proxy settings.')
demx8as6a93cb372021-06-06 16:05:58 +0200103 except requests.exceptions.RequestException as e:
demx8as6f81ad302022-09-15 14:19:17 +0200104 # catastrophic error. bail.
105 raise SystemExit(e)
demx8as6a93cb372021-06-06 16:05:58 +0200106
107 if response.status_code >= 200 and response.status_code < 300:
demx8as6f81ad302022-09-15 14:19:17 +0200108 print('Got token!')
109 return response.json()['access_token']
demx8as6a93cb372021-06-06 16:05:58 +0200110 else:
demx8as6f81ad302022-09-15 14:19:17 +0200111 sys.exit('Getting token failed.')
demx8as6a93cb372021-06-06 16:05:58 +0200112
113# create the default realm from file
demx8as6a93cb372021-06-06 16:05:58 +0200114
demx8as6f81ad302022-09-15 14:19:17 +0200115
116def createRealm(token, realm):
117 url = base + '/admin/realms'
118 auth = 'bearer ' + token
119 headers = {
120 'content-type': 'application/json',
121 'accept': 'application/json',
122 'authorization': auth
123 }
124 try:
125 response = requests.post(
126 url, verify=False, json=realm, headers=headers)
127 except requests.exceptions.Timeout:
128 sys.exit('HTTP request failed, please check you internet connection.')
129 except requests.exceptions.TooManyRedirects:
130 sys.exit('HTTP request failed, please check your proxy settings.')
131 except requests.exceptions.RequestException as e:
132 # catastrophic error. bail.
133 raise SystemExit(e)
134
135 return response.status_code >= 200 and response.status_code < 300
demx8as6a93cb372021-06-06 16:05:58 +0200136
137# Check if default realm exists
demx8as6a93cb372021-06-06 16:05:58 +0200138
demx8as6f81ad302022-09-15 14:19:17 +0200139
140def checkRealmExists(token, realmId):
141 url = base + '/admin/realms/' + realmId
142 auth = 'bearer ' + token
143 headers = {
144 'accept': 'application/json',
145 'authorization': auth
146 }
147 try:
148 response = requests.get(url, verify=False, headers=headers)
149 except requests.exceptions.Timeout:
150 sys.exit('HTTP request failed, please check you internet connection.')
151 except requests.exceptions.TooManyRedirects:
152 sys.exit('HTTP request failed, please check your proxy settings.')
153 except requests.exceptions.RequestException as e:
154 # catastrophic error. bail.
155 raise SystemExit(e)
156
157 if response.status_code >= 200 and response.status_code < 300:
158 return realmId == response.json()['id']
159 else:
160 # sys.exit('Getting realm failed.')
161 return False
demx8as6a93cb372021-06-06 16:05:58 +0200162
163# create a user in default realm
demx8as6a93cb372021-06-06 16:05:58 +0200164
demx8as6f81ad302022-09-15 14:19:17 +0200165
166def createUser(token, realmConfig, user):
167 realmId = realmConfig['id']
168 url = base + '/admin/realms/' + realmId + '/users'
169 auth = 'bearer ' + token
170 headers = {
171 'accept': 'application/json',
172 'authorization': auth
173 }
174 try:
175 response = requests.post(url, verify=False, json=user, headers=headers)
176 except requests.exceptions.Timeout:
177 sys.exit('HTTP request failed, please check you internet connection.')
178 except requests.exceptions.TooManyRedirects:
179 sys.exit('HTTP request failed, please check your proxy settings.')
180 except requests.exceptions.RequestException as e:
181 # catastrophic error. bail.
182 raise SystemExit(e)
183
184 if response.status_code >= 200 and response.status_code < 300:
185 print('User', user['username'], 'created!')
186 else:
187 print('User creation', user['username'], 'failed!\n', response.text)
demx8as6a93cb372021-06-06 16:05:58 +0200188
189# creates User accounts in realm based a file
demx8as6f81ad302022-09-15 14:19:17 +0200190
191
192def createUsers(token, realmConfig, authConfig):
193 for user in authConfig['users']:
194 createUser(token, realmConfig, user)
195
196 # create a user based on system user
197 systemUser = {
198 "firstName": getpass.getuser(),
199 "lastName": "",
200 "email": getpass.getuser() + "@sdnr.onap.org",
201 "enabled": "true",
202 "username": getpass.getuser(),
203 "credentials": [
204 {
205 "type": "password",
206 "value": password,
Martin Skorupskia6355d12023-04-08 11:52:18 +0200207 "temporary": True
demx8as6f81ad302022-09-15 14:19:17 +0200208 }
demx8as6cd178822023-07-01 13:44:31 +0000209 ],
210 "requiredActions": [
211 "UPDATE_PASSWORD"
212 ]
demx8as6f81ad302022-09-15 14:19:17 +0200213 }
214 createUser(token, realmConfig, systemUser)
demx8as6a93cb372021-06-06 16:05:58 +0200215
216# Grants a role to a user
demx8as6a93cb372021-06-06 16:05:58 +0200217
demx8as6f81ad302022-09-15 14:19:17 +0200218
219def addUserRole(user: dict, role: dict, options: dict):
220 url = options['url'] + '/' + user['id'] + '/role-mappings/realm'
221 try:
222 response = requests.post(url, verify=False, json=[
demx8as6cd178822023-07-01 13:44:31 +0000223 {'id': role['id'], 'name':role['name']}],
224 headers=options['headers'])
demx8as6f81ad302022-09-15 14:19:17 +0200225 except requests.exceptions.Timeout:
226 sys.exit('HTTP request failed, please check you internet connection.')
227 except requests.exceptions.TooManyRedirects:
228 sys.exit('HTTP request failed, please check your proxy settings.')
229 except requests.exceptions.RequestException as e:
230 # catastrophic error. bail.
231 raise SystemExit(e)
232
233 if response.status_code >= 200 and response.status_code < 300:
234 print('User role', user['username'], role['name'], 'created!')
235 else:
236 print('Creation of user role',
237 user['username'], role['name'], 'failed!\n', response.text)
demx8as6a93cb372021-06-06 16:05:58 +0200238
239# searches for the role of a given user
demx8as6f81ad302022-09-15 14:19:17 +0200240
demx8as6cd178822023-07-01 13:44:31 +0000241
demx8as6f81ad302022-09-15 14:19:17 +0200242def findRole(username: str, authConfig: dict, realmConfig: dict) -> dict:
243 roleName = 'administration'
244 for grant in authConfig['grants']:
245 if grant['username'] == username:
246 roleName = grant['role']
247 for role in realmConfig['roles']['realm']:
248 if role['name'] == roleName:
249 return role
250 return None
demx8as6a93cb372021-06-06 16:05:58 +0200251
252# adds roles to users
demx8as6a93cb372021-06-06 16:05:58 +0200253
demx8as6f81ad302022-09-15 14:19:17 +0200254
255def addUserRoles(token, realmConfig, authConfig):
256 realmId = realmConfig['id']
257 url = base + '/admin/realms/' + realmId + '/users'
258 auth = 'bearer ' + token
259 headers = {
260 'content-type': 'application/json',
261 'accept': 'application/json',
262 'authorization': auth
demx8as6a93cb372021-06-06 16:05:58 +0200263 }
demx8as6f81ad302022-09-15 14:19:17 +0200264 try:
265 response = requests.get(url, verify=False, headers=headers)
266 except requests.exceptions.Timeout:
267 sys.exit('HTTP request failed, please check you internet connection.')
268 except requests.exceptions.TooManyRedirects:
269 sys.exit('HTTP request failed, please check your proxy settings.')
270 except requests.exceptions.RequestException as e:
271 # catastrophic error. bail.
272 raise SystemExit(e)
273
274 if response.status_code >= 200 and response.status_code < 300:
275 users = response.json()
276 options = {
277 "url": url,
278 "auth": auth,
279 "headers": headers
280 }
281 for user in users:
282 role = findRole(user['username'], authConfig, realmConfig)
283 addUserRole(user, role, options)
284 else:
285 sys.exit('Getting users failed.')
demx8as6a93cb372021-06-06 16:05:58 +0200286
287# main
demx8as6f81ad302022-09-15 14:19:17 +0200288
289
290(realmFile, authFile, readyTimeout) = load_arguments(sys.argv)
291username = get_environment_variable('ADMIN_USERNAME')
292password = get_environment_variable('ADMIN_PASSWORD')
293base = getBaseUrl()
294isReady(readyTimeout)
demx8as6a93cb372021-06-06 16:05:58 +0200295token = getToken()
296if token:
demx8as6f81ad302022-09-15 14:19:17 +0200297 with open(realmFile) as file:
298 realmConfig = json.load(file)
299 if not checkRealmExists(token, realmConfig['id']):
300 createRealm(token, realmConfig)
demx8as6a93cb372021-06-06 16:05:58 +0200301
demx8as6f81ad302022-09-15 14:19:17 +0200302 with open(authFile) as authConfig:
303 authConfig = json.load(authConfig)
304 createUsers(token, realmConfig, authConfig)
305 addUserRoles(token, realmConfig, authConfig)
306 exit(0)
307exit(1)