added the functionality to load server configuration from ini file
diff --git a/clients/python/airavata_custos/admin/iam_admin_client.py b/clients/python/airavata_custos/admin/iam_admin_client.py
index ee9c11b..f72df76 100644
--- a/clients/python/airavata_custos/admin/iam_admin_client.py
+++ b/clients/python/airavata_custos/admin/iam_admin_client.py
@@ -16,123 +16,135 @@
#
import logging
-from airavata_custos.utils import iamadmin_client_pool
+import configparser
+from airavata_custos import utils
+from airavata_custos.settings import ProfileSettings
logger = logging.getLogger(__name__)
-def is_username_available(authz_token, username):
- """
- This method validates if the username is available or not
- :param authz_token: Object of AuthzToken class containing access token, username, gatewayId of the active user
- :param username: The username whose availability needs to be verified
- :return: boolean
- """
- return iamadmin_client_pool.isUsernameAvailable(authz_token, username)
+class IAMAdminClient(object):
+ def __init__(self, configuration_file_location):
+ """
+ constructor for IAMAdminClient class
+ :param configuration_file_location: takes the location of the ini file containing server configuration
+ """
+ self.profile_settings = ProfileSettings()
+ self._load_settings(configuration_file_location)
+ self.iamadmin_client_pool = utils.initialize_iamadmin_client_pool(self.profile_settings.PROFILE_SERVICE_HOST,
+ self.profile_settings.PROFILE_SERVICE_PORT)
-def register_user(authz_token, username, email_address, first_name, last_name, password):
- """
- This method registers the user with the keycloak instance returns true if successful, false if the registration fails
- :param authz_token: Object of AuthzToken class containing access token, username, gatewayId of the active user
- :param username: The username of the user that needs to be registered
- :param email_address: The email address of the user that needs to be registered
- :param first_name: The first name of the user that needs to be registered
- :param last_name: The last name of the user that needs to be registered
- :param password: The password of the user that needs to be registered
- :return: boolean
- """
- return iamadmin_client_pool.registerUser(
- authz_token,
- username,
- email_address,
- first_name,
- last_name,
- password)
+ def is_username_available(self, authz_token, username):
+ """
+ This method validates if the username is available or not
+ :param authz_token: Object of AuthzToken class containing access token, username, gatewayId of the active user
+ :param username: The username whose availability needs to be verified
+ :return: boolean
+ """
+ return self.iamadmin_client_pool.isUsernameAvailable(authz_token, username)
+ def register_user(self, authz_token, username, email_address, first_name, last_name, password):
+ """
+ This method registers the user with the keycloak instance returns true if successful, false if the registration fails
+ :param authz_token: Object of AuthzToken class containing access token, username, gatewayId of the active user
+ :param username: The username of the user that needs to be registered
+ :param email_address: The email address of the user that needs to be registered
+ :param first_name: The first name of the user that needs to be registered
+ :param last_name: The last name of the user that needs to be registered
+ :param password: The password of the user that needs to be registered
+ :return: boolean
+ """
+ return self.iamadmin_client_pool.registerUser(
+ authz_token,
+ username,
+ email_address,
+ first_name,
+ last_name,
+ password)
-def is_user_enabled(authz_token, username):
- """
- Checks the user is enabled/disabled in keycloak. Only the enabled user can login
- :param authz_token: Object of AuthzToken class containing access token, username, gatewayId of the active user
- :param username: The username of the user
- :return: boolean
- """
- return iamadmin_client_pool.isUserEnabled(authz_token, username)
+ def is_user_enabled(self, authz_token, username):
+ """
+ Checks the user is enabled/disabled in keycloak. Only the enabled user can login
+ :param authz_token: Object of AuthzToken class containing access token, username, gatewayId of the active user
+ :param username: The username of the user
+ :return: boolean
+ """
+ return self.iamadmin_client_pool.isUserEnabled(authz_token, username)
+ def enable_user(self, authz_token, username):
+ """
+ The method to enable a disabled user
+ :param authz_token: Object of AuthzToken class containing access token, username, gatewayId of the active user
+ :param username: The username of the user
+ :return: Object of UserProfile class, containing user details
+ """
+ return self.iamadmin_client_pool.enableUser(authz_token, username)
-def enable_user(authz_token, username):
- """
- The method to enable a disabled user
- :param authz_token: Object of AuthzToken class containing access token, username, gatewayId of the active user
- :param username: The username of the user
- :return: Object of UserProfile class, containing user details
- """
- return iamadmin_client_pool.enableUser(authz_token, username)
+ def delete_user(self, authz_token, username):
+ """
+ This method deleted the user from keycloak. Returns true if delete is successful
+ :param authz_token: Object of AuthzToken class containing access token, username, gatewayId of the active user
+ :param username: The username of the user
+ :return: boolean
+ """
+ return self.iamadmin_client_pool.deleteUser(authz_token, username)
+ def is_user_exist(self, authz_token, username):
+ """
+ This method checks if the user exists in keycloak. Returns true if the user exists otherwise returns false
+ :param authz_token: Object of AuthzToken class containing access token, username, gatewayId of the active user
+ :param username: The username of the user
+ :return: boolean
+ """
+ try:
+ return self.iamadmin_client_pool.isUserExist(authz_token, username)
+ except Exception:
+ return None
-def delete_user(authz_token, username):
- """
- This method deleted the user from keycloak. Returns true if delete is successful
- :param authz_token: Object of AuthzToken class containing access token, username, gatewayId of the active user
- :param username: The username of the user
- :return: boolean
- """
- return iamadmin_client_pool.deleteUser(authz_token, username)
+ def get_user(self, authz_token, username):
+ """
+ :param authz_token: Object of AuthzToken class containing access token, username, gatewayId of the active user
+ :param username: username of the user
+ :return: object of class UserProfile
+ """
+ try:
+ return self.iamadmin_client_pool.getUser(authz_token, username)
+ except Exception:
+ return None
-def is_user_exist(authz_token, username):
- """
- This method checks if the user exists in keycloak. Returns true if the user exists otherwise returns false
- :param authz_token: Object of AuthzToken class containing access token, username, gatewayId of the active user
- :param username: The username of the user
- :return: boolean
- """
- try:
- return iamadmin_client_pool.isUserExist(authz_token, username)
- except Exception:
- return None
+ def get_users(self, authz_token, offset=0, limit=-1, search=None):
+ """
+ :param authz_token: Object of AuthzToken class containing access token, username, gatewayId of the active user
+ :param offset: start index
+ :param limit: end index
+ :param search: search criteria for filtering users
+ :return: list of UserProfile class objects
+ """
+ try:
+ return self.iamadmin_client_pool.getUsers(authz_token, offset, limit, search)
+ except Exception:
+ return None
-def get_user(authz_token, username):
- """
+ def reset_user_password(self, authz_token, username, new_password):
+ """
- :param authz_token: Object of AuthzToken class containing access token, username, gatewayId of the active user
- :param username: username of the user
- :return: object of class UserProfile
- """
- try:
- return iamadmin_client_pool.getUser(authz_token, username)
- except Exception:
- return None
+ :param authz_token: Object of AuthzToken class containing access token, username, gatewayId of the active user
+ :param username: username of the user
+ :param new_password: new password for the user
+ :return:
+ """
+ try:
+ return self.iamadmin_client_pool.resetUserPassword(
+ authz_token, username, new_password)
+ except Exception:
+ return None
-
-def get_users(authz_token, offset=0, limit=-1, search=None):
- """
-
- :param authz_token: Object of AuthzToken class containing access token, username, gatewayId of the active user
- :param offset: start index
- :param limit: end index
- :param search: search criteria for filtering users
- :return: list of UserProfile class objects
- """
- try:
- return iamadmin_client_pool.getUsers(authz_token, offset, limit, search)
- except Exception:
- return None
-
-
-def reset_user_password(authz_token, username, new_password):
- """
-
- :param authz_token: Object of AuthzToken class containing access token, username, gatewayId of the active user
- :param username: username of the user
- :param new_password: new password for the user
- :return:
- """
- try:
- return iamadmin_client_pool.resetUserPassword(
- authz_token, username, new_password)
- except Exception:
- return None
-
+ def _load_settings(self, configuration_file_location):
+ config = configparser.ConfigParser()
+ config.read(configuration_file_location)
+ settings = config['ProfileServerSettings']
+ self.profile_settings.PROFILE_SERVICE_HOST = settings['PROFILE_SERVICE_HOST']
+ self.profile_settings.PROFILE_SERVICE_PORT = settings['PROFILE_SERVICE_PORT']
diff --git a/clients/python/airavata_custos/sample_settings.ini b/clients/python/airavata_custos/sample_settings.ini
new file mode 100644
index 0000000..c9a1e1c
--- /dev/null
+++ b/clients/python/airavata_custos/sample_settings.ini
@@ -0,0 +1,10 @@
+[IAMSeverSettings]
+KEYCLOAK_AUTHORIZE_URL = https://localhost:8443/auth/realms/default/protocol/openid-connect/auth
+KEYCLOAK_TOKEN_URL = https://localhost:8443/auth/realms/default/protocol/openid-connect/token
+KEYCLOAK_USERINFO_URL = https://localhost:8443/auth/realms/default/protocol/openid-connect/userinfo
+KEYCLOAK_LOGOUT_URL = https://localhost:8443/auth/realms/default/protocol/openid-connect/logout
+VERIFY_SSL = no
+
+[ProfileServerSettings]
+PROFILE_SERVICE_HOST = '0.0.0.0'
+PROFILE_SERVICE_PORT = '8081'
\ No newline at end of file
diff --git a/clients/python/airavata_custos/security/custos_authorization_token.py b/clients/python/airavata_custos/security/custos_authorization_token.py
deleted file mode 100644
index dd4b531..0000000
--- a/clients/python/airavata_custos/security/custos_authorization_token.py
+++ /dev/null
@@ -1,43 +0,0 @@
-#
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements. See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-from airavata_custos import settings
-from oauthlib.oauth2 import BackendApplicationClient
-from requests_oauthlib import OAuth2Session
-from custos.commons.model.security.ttypes import AuthzToken
-
-
-def get_authorization_token(client_credentials, tenant_id, username=None):
- """
- This method created a authorization token for the user or a service account
- In case of a service account username will be null
- :param client_credentials: object of class client_credentials
- :param tenant_id: gateway id of the client
- :param username: username of the user for which authorization token is being created
- :return: AuthzToken
- """
- client = BackendApplicationClient(client_id=client_credentials.client_id)
- oauth = OAuth2Session(client=client)
- token = oauth.fetch_token(
- token_url=settings.token_url,
- client_id=client_credentials.client_id,
- client_secret=client_credentials.client_secret,
- verify=client_credentials.verify_ssl)
-
- access_token = token.get('access_token')
- return AuthzToken(
- accessToken=access_token,
- claimsMap={'gatewayID': tenant_id, 'userName': username})
diff --git a/clients/python/airavata_custos/security/keycloak_connectors.py b/clients/python/airavata_custos/security/keycloak_connectors.py
index d31e5a8..05816c2 100644
--- a/clients/python/airavata_custos/security/keycloak_connectors.py
+++ b/clients/python/airavata_custos/security/keycloak_connectors.py
@@ -16,13 +16,24 @@
#
import time
from oauthlib.oauth2 import LegacyApplicationClient
-from requests_oauthlib import OAuth2Session
import requests
-from airavata_custos import settings
+import configparser
+from airavata_custos.settings import IAMSettings
+from oauthlib.oauth2 import BackendApplicationClient
+from requests_oauthlib import OAuth2Session
+from custos.commons.model.security.ttypes import AuthzToken
class KeycloakBackend(object):
+ def __init__(self, configuration_file_location):
+ """
+ constructor for KeycloakBackend class
+ :param configuration_file_location: takes the location of the ini file containing server configuration
+ """
+ self.keycloak_settings = IAMSettings()
+ self._load_settings(configuration_file_location)
+
def authenticate_user(self, user_credentials):
"""
Method to authenticate a gateway user with keycloak
@@ -60,42 +71,61 @@
except Exception as e:
return None
- @classmethod
- def _get_token_and_user_info_password_flow(cls, client_credentials):
+ def _get_token_and_user_info_password_flow(self, client_credentials):
oauth2_session = OAuth2Session(client=LegacyApplicationClient(client_id=client_credentials.client_id))
- token = oauth2_session.fetch_token(token_url=settings.KEYCLOAK_TOKEN_URL,
+ token = oauth2_session.fetch_token(token_url=self.keycloak_settings.KEYCLOAK_TOKEN_URL,
username=client_credentials.username,
password=client_credentials.password,
client_id=client_credentials.client_id,
client_secret=client_credentials.client_secret,
- verify=settings.VERIFY_SSL)
- user_info = oauth2_session.get(settings.KEYCLOAK_USERINFO_URL).json()
- return cls._process_token(token), cls._process_userinfo(user_info)
+ verify=self.keycloak_settings.VERIFY_SSL)
+ user_info = oauth2_session.get(self.keycloak_settings.KEYCLOAK_USERINFO_URL).json()
+ return self._process_token(token), self._process_userinfo(user_info)
- @classmethod
- def _get_token_and_user_info_redirect_flow(cls, client_credentials):
+ def _get_token_and_user_info_redirect_flow(self, client_credentials):
oauth2_session = OAuth2Session(client_credentials.client_id,
scope='openid',
redirect_uri=client_credentials.redirect_uri,
state=client_credentials.state)
- token = oauth2_session.fetch_token(settings.KEYCLOAK_TOKEN_URL,
+ token = oauth2_session.fetch_token(self.keycloak_settings.KEYCLOAK_TOKEN_URL,
client_secret=client_credentials.client_secret,
authorization_response=client_credentials.authorization_code_url,
- verify=settings.VERIFY_SSL)
- user_info = oauth2_session.get(settings.KEYCLOAK_USERINFO_URL).json()
- return cls._process_token(token), cls._process_userinfo(user_info)
+ verify=self.keycloak_settings.VERIFY_SSL)
+ user_info = oauth2_session.get(self.keycloak_settings.KEYCLOAK_USERINFO_URL).json()
+ return self._process_token(token), self._process_userinfo(user_info)
- @classmethod
- def _get_token_from_refresh_token(cls, client_credentials, refresh_token):
+ def _get_token_from_refresh_token(self, client_credentials, refresh_token):
oauth2_session = OAuth2Session(client_credentials.client_id, scope='openid')
auth = requests.auth.HTTPBasicAuth(client_credentials.client_id, client_credentials.client_secret)
- token = oauth2_session.refresh_token(token_url=settings.KEYCLOAK_TOKEN_URL,
+ token = oauth2_session.refresh_token(token_url=self.keycloak_settings.KEYCLOAK_TOKEN_URL,
refresh_token=refresh_token,
auth=auth,
- verify=settings.VERIFY_SSL)
- return cls._process_token(token)
+ verify=self.keycloak_settings.VERIFY_SSL)
+ return self._process_token(token)
+
+ def get_authorization_token(self, client_credentials, tenant_id, username=None):
+ """
+ This method created a authorization token for the user or a service account
+ In case of a service account username will be null
+ :param client_credentials: object of class client_credentials
+ :param tenant_id: gateway id of the client
+ :param username: username of the user for which authorization token is being created
+ :return: AuthzToken
+ """
+ client = BackendApplicationClient(client_id=client_credentials.client_id)
+ oauth = OAuth2Session(client=client)
+ token = oauth.fetch_token(
+ token_url=self.keycloak_settings.token_url,
+ client_id=client_credentials.client_id,
+ client_secret=client_credentials.client_secret,
+ verify=client_credentials.verify_ssl)
+
+ access_token = token.get('access_token')
+ return AuthzToken(
+ accessToken=access_token,
+ claimsMap={'gatewayID': tenant_id, 'userName': username})
@classmethod
def _process_token(cls, token):
@@ -116,6 +146,16 @@
last_name = userinfo['family_name']
return UserInfo(username, email, first_name, last_name)
+ def _load_settings(self, configuration_file_location):
+ config = configparser.ConfigParser()
+ config.read(configuration_file_location)
+ settings = config['IAMSeverSettings']
+ self.keycloak_settings.KEYCLOAK_AUTHORIZE_URL = settings['KEYCLOAK_AUTHORIZE_URL']
+ self.keycloak_settings.KEYCLOAK_LOGOUT_URL = settings['KEYCLOAK_LOGOUT_URL']
+ self.keycloak_settings.KEYCLOAK_TOKEN_URL = settings['KEYCLOAK_TOKEN_URL']
+ self.keycloak_settings.KEYCLOAK_USERINFO_URL = settings['KEYCLOAK_USERINFO_URL']
+ self.keycloak_settings.VERIFY_SSL = settings.getboolean('VERIFY_SSL')
+
class Token(object):
diff --git a/clients/python/airavata_custos/settings.py b/clients/python/airavata_custos/settings.py
index 89a05ef..dc4d101 100644
--- a/clients/python/airavata_custos/settings.py
+++ b/clients/python/airavata_custos/settings.py
@@ -15,19 +15,25 @@
# limitations under the License.
#
-KEYCLOAK_AUTHORIZE_URL = 'https://localhost:8443/auth/realms/default/protocol/openid-connect/auth'
-KEYCLOAK_TOKEN_URL = 'https://localhost:8443/auth/realms/default/protocol/openid-connect/token'
-KEYCLOAK_USERINFO_URL = 'https://localhost:8443/auth/realms/default/protocol/openid-connect/userinfo'
-KEYCLOAK_LOGOUT_URL = 'https://localhost:8443/auth/realms/default/protocol/openid-connect/logout'
+
+class ProfileSettings(object):
+ # Profile Service Configuration
+
+ def __init__(self):
+ self.PROFILE_SERVICE_HOST = '0.0.0.0'
+ self.PROFILE_SERVICE_PORT = '8081'
+
+
+class IAMSettings(object):
+
+ def __init__(self):
+ self.KEYCLOAK_AUTHORIZE_URL = 'https://localhost:8443/auth/realms/default/protocol/openid-connect/auth'
+ self.KEYCLOAK_TOKEN_URL = 'https://localhost:8443/auth/realms/default/protocol/openid-connect/token'
+ self.KEYCLOAK_USERINFO_URL = 'https://localhost:8443/auth/realms/default/protocol/openid-connect/userinfo'
+ self.KEYCLOAK_LOGOUT_URL = 'https://localhost:8443/auth/realms/default/protocol/openid-connect/logout'
+ self.VERIFY_SSL = False
# Seconds each connection in the pool is able to stay alive. If open connection
# has lived longer than this period, it will be closed.
# (https://github.com/Thriftpy/thrift_connector)
-THRIFT_CLIENT_POOL_KEEPALIVE = 5
-
-# Profile Service Configuration
-PROFILE_SERVICE_HOST = '0.0.0.0'
-PROFILE_SERVICE_PORT = '8081'
-PROFILE_SERVICE_SECURE = False
-
-VERIFY_SSL = False
+THRIFT_CLIENT_POOL_KEEPALIVE = 5
\ No newline at end of file
diff --git a/clients/python/airavata_custos/utils.py b/clients/python/airavata_custos/utils.py
index 17fdf59..e025077 100644
--- a/clients/python/airavata_custos/utils.py
+++ b/clients/python/airavata_custos/utils.py
@@ -21,8 +21,8 @@
from thrift.protocol.TMultiplexedProtocol import TMultiplexedProtocol
from thrift.transport import TSocket, TSSLSocket, TTransport
-from airavata_custos import settings
from custos.profile.iam.admin.services.cpi import IamAdminServices, constants
+from airavata_custos import settings
log = logging.getLogger(__name__)
@@ -63,14 +63,16 @@
class IAMAdminServiceThriftClient(MultiplexThriftClientMixin,
CustomThriftClient):
service_name = constants.IAM_ADMIN_SERVICES_CPI_NAME
- secure = settings.PROFILE_SERVICE_SECURE
+ secure = True
-iamadmin_client_pool = connection_pool.ClientPool(
- IamAdminServices,
- settings.PROFILE_SERVICE_HOST,
- settings.PROFILE_SERVICE_PORT,
- connection_class=IAMAdminServiceThriftClient,
- keepalive=settings.THRIFT_CLIENT_POOL_KEEPALIVE
-)
+def initialize_iamadmin_client_pool(host, port):
+ iamadmin_client_pool = connection_pool.ClientPool(
+ IamAdminServices,
+ host,
+ port,
+ connection_class=IAMAdminServiceThriftClient,
+ keepalive=settings.THRIFT_CLIENT_POOL_KEEPALIVE
+ )
+ return iamadmin_client_pool
diff --git a/clients/python/requirements_dev.txt b/clients/python/requirements_dev.txt
index 353a50e..e0209cb 100644
--- a/clients/python/requirements_dev.txt
+++ b/clients/python/requirements_dev.txt
@@ -15,4 +15,5 @@
requests_oauthlib==1.2.0
requests==2.22.0
thrift_connector==0.24
-thrift==0.11.0
\ No newline at end of file
+thrift==0.11.0
+configparser==4.0.2