You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@airavata.apache.org by ma...@apache.org on 2019/10/11 20:42:23 UTC

[airavata-custos] 16/24: first draft of the python SDK containing methods related to keycloak authentication and admin operations

This is an automated email from the ASF dual-hosted git repository.

machristie pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/airavata-custos.git

commit dc05791a48196135115478083fff208251c0af82
Author: Aarushi <aa...@gmail.com>
AuthorDate: Fri Sep 13 13:24:48 2019 -0400

    first draft of the python SDK containing methods related to keycloak authentication and admin operations
---
 clients/python/README.md                           |    7 +
 .../airavata_custos/admin/iam_admin_client.py      |  111 +
 .../python/airavata_custos/security/__init__.py    |    0
 .../security/authorization_token.py                |   36 +
 .../airavata_custos/security/client_credentials.py |   55 +
 .../security/keycloak_connectors.py                |   78 +
 .../airavata_custos/security/model/__init__.py     |    0
 .../airavata_custos/security/model/ttypes.py       |   97 +
 clients/python/airavata_custos/settings.py         |   31 +
 clients/python/airavata_custos/utils.py            |   16 +
 clients/python/custos/__init__.py                  |    0
 clients/python/custos/commons/__init__.py          |    0
 clients/python/custos/commons/model/__init__.py    |    0
 .../custos/commons/model/security/__init__.py      |    1 +
 .../custos/commons/model/security/constants.py     |   14 +
 .../python/custos/commons/model/security/ttypes.py |  104 +
 clients/python/custos/profile/__init__.py          |    0
 clients/python/custos/profile/iam/__init__.py      |    0
 .../python/custos/profile/iam/admin/__init__.py    |    0
 .../custos/profile/iam/admin/services/__init__.py  |    0
 .../iam/admin/services/cpi/IamAdminServices-remote |  222 ++
 .../iam/admin/services/cpi/IamAdminServices.py     | 3863 ++++++++++++++++++++
 .../profile/iam/admin/services/cpi/__init__.py     |    1 +
 .../profile/iam/admin/services/cpi/constants.py    |   16 +
 .../iam/admin/services/cpi/error/__init__.py       |    1 +
 .../iam/admin/services/cpi/error/constants.py      |   14 +
 .../profile/iam/admin/services/cpi/error/ttypes.py |   85 +
 .../profile/iam/admin/services/cpi/ttypes.py       |   23 +
 .../python/custos/profile/model/User/__init__.py   |    1 +
 .../python/custos/profile/model/User/constants.py  |   16 +
 clients/python/custos/profile/model/User/ttypes.py |  788 ++++
 clients/python/custos/profile/model/__init__.py    |    0
 .../python/custos/profile/model/tenant/__init__.py |    1 +
 .../custos/profile/model/tenant/constants.py       |   14 +
 .../python/custos/profile/model/tenant/ttypes.py   |  604 +++
 .../custos/profile/model/workspace/__init__.py     |    1 +
 .../custos/profile/model/workspace/constants.py    |   14 +
 .../custos/profile/model/workspace/ttypes.py       |  345 ++
 clients/python/requirements_dev.txt                |    5 +
 39 files changed, 6564 insertions(+)

diff --git a/clients/python/README.md b/clients/python/README.md
index 5c4de03..46690eb 100644
--- a/clients/python/README.md
+++ b/clients/python/README.md
@@ -1 +1,8 @@
 # Airavata Custos Python SDK
+
+####Create a virtual environment
+
+####Activate the virtual environment
+
+####Install dependencies
+pip install -r requirements_dev.txt
\ No newline at end of file
diff --git a/clients/python/airavata_custos/admin/iam_admin_client.py b/clients/python/airavata_custos/admin/iam_admin_client.py
new file mode 100644
index 0000000..6f83b58
--- /dev/null
+++ b/clients/python/airavata_custos/admin/iam_admin_client.py
@@ -0,0 +1,111 @@
+import logging
+from airavata_custos.utils import iamadmin_client_pool
+
+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)
+
+
+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_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 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(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 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
+    """
+    return iamadmin_client_pool.isUserExist(authz_token, username)
+
+
+def get_user(authz_token, username):
+    """
+
+    :param authz_token:
+    :param username:
+    :return:
+    """
+    return iamadmin_client_pool.getUser(authz_token, username)
+
+
+def get_users(authz_token, offset, limit, search=None):
+    """
+
+    :param authz_token:
+    :param offset:
+    :param limit:
+    :param search:
+    :return:
+    """
+    return iamadmin_client_pool.getUsers(authz_token, offset, limit, search)
+
+
+def reset_user_password(authz_token, username, new_password):
+    """
+
+    :param authz_token:
+    :param username:
+    :param new_password:
+    :return:
+    """
+    return iamadmin_client_pool.resetUserPassword(
+        authz_token, username, new_password)
+
+def set_up_tenant(authz_token, gateway, tenantAdminPasswordCredentials):
+    pass
diff --git a/clients/python/airavata_custos/security/__init__.py b/clients/python/airavata_custos/security/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/clients/python/airavata_custos/security/authorization_token.py b/clients/python/airavata_custos/security/authorization_token.py
new file mode 100644
index 0000000..cbe4fe2
--- /dev/null
+++ b/clients/python/airavata_custos/security/authorization_token.py
@@ -0,0 +1,36 @@
+#
+# 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 airavata_custos.security.model.ttypes import AuthzToken
+
+
+def create_authorization_token(client_credentials, tenant_id, username=None):
+    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,
+        # This is a service account, so leaving out userName for now
+        claimsMap={'gatewayID': tenant_id, 'userName': username})
diff --git a/clients/python/airavata_custos/security/client_credentials.py b/clients/python/airavata_custos/security/client_credentials.py
new file mode 100644
index 0000000..432dc51
--- /dev/null
+++ b/clients/python/airavata_custos/security/client_credentials.py
@@ -0,0 +1,55 @@
+#
+# 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.
+#
+
+
+class ClientCredentials(object):
+    """
+
+    Attributes:
+        client_id:  Client ID, which you get from tenant registration with Keycloak
+        client_secret: Client Secret, which you get from tenant registration with Keycloak
+        username:  Username of the tenant user that needs to be authenticated
+        password:  Password of the tenant user that needs to be authenticated
+        authorization_code_url: URL of the authorization server’s authorization endpoint
+        state:
+        redirect_uri: Redirect URI you registered as callback
+        refresh_token:
+        verify_ssl: Flag to indicate ssl verification is required
+
+    """
+    client_id = None
+    client_secret = None
+    verify_ssl = None
+    authorization_code_url = None
+    state = None
+    redirect_uri = None
+    username = None
+    password = None
+    refresh_token = None
+
+    def __init__(self, client_id, client_secret, verify_ssl=False, authorization_code_url=None, state=None, redirect_uri=None, username=None, password=None, refresh_token=None):
+        self.client_id = client_id
+        self.client_secret = client_secret
+        self.verify_ssl = verify_ssl
+        self.authorization_code_url = authorization_code_url
+        self.state = state
+        self.redirect_uri = redirect_uri
+        self.username = username
+        self.password = password
+        self.refresh_token = refresh_token
+
+
diff --git a/clients/python/airavata_custos/security/keycloak_connectors.py b/clients/python/airavata_custos/security/keycloak_connectors.py
new file mode 100644
index 0000000..054c787
--- /dev/null
+++ b/clients/python/airavata_custos/security/keycloak_connectors.py
@@ -0,0 +1,78 @@
+#
+# 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 oauthlib.oauth2 import LegacyApplicationClient
+from requests_oauthlib import OAuth2Session
+import requests
+from airavata_custos import settings
+
+
+class KeycloakBackend(object):
+    def authenticate(self, client_credentials):
+        """This method authenticates a client with keycloak
+
+        Parameters:
+        client_credentials (client_credentials): This object has client credentials which needs to be authenticated
+
+        Returns:
+        String:token
+        String:userInfo
+       """
+        try:
+            if client_credentials.username and client_credentials.password:
+                token, userinfo = self._get_token_and_userinfo_password_flow(client_credentials)
+            elif client_credentials.refresh_token:
+                token = self._get_token_from_refresh_token(client_credentials)
+            elif client_credentials.red:
+                token, userinfo = self._get_token_and_userinfo_redirect_flow(client_credentials)
+
+            return token, userinfo
+        except Exception as e:
+            return None
+
+    def _get_token_and_userinfo_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,
+                                           username=client_credentials.username,
+                                           password=client_credentials.password,
+                                           client_id=client_credentials.client_id,
+                                           client_secret=client_credentials.client_secret,
+                                           verify=client_credentials.verify_ssl)
+        userinfo = oauth2_session.get(settings.KEYCLOAK_USERINFO_URL).json()
+        return token, userinfo
+
+    def _get_token_and_userinfo_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,
+                                           client_secret=client_credentials.client_secret,
+                                           authorization_response=client_credentials.authorization_code_url,
+                                           verify=client_credentials.verify_ssl)
+        userinfo = oauth2_session.get(settings.KEYCLOAK_USERINFO_URL).json()
+        return token, userinfo
+
+    def _get_token_from_refresh_token(self, client_credentials):
+
+        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,
+                                             refresh_token=client_credentials.refresh_token,
+                                             auth=auth,
+                                             verify=client_credentials.verify_ssl)
+        return token
\ No newline at end of file
diff --git a/clients/python/airavata_custos/security/model/__init__.py b/clients/python/airavata_custos/security/model/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/clients/python/airavata_custos/security/model/ttypes.py b/clients/python/airavata_custos/security/model/ttypes.py
new file mode 100644
index 0000000..596f6ed
--- /dev/null
+++ b/clients/python/airavata_custos/security/model/ttypes.py
@@ -0,0 +1,97 @@
+#
+# Autogenerated by Thrift Compiler (0.10.0)
+#
+# DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
+#
+#  options string: py
+#
+
+from thrift.Thrift import TType, TMessageType, TFrozenDict, TException, TApplicationException
+from thrift.protocol.TProtocol import TProtocolException
+import sys
+
+from thrift.transport import TTransport
+
+
+class AuthzToken(object):
+    """
+    Attributes:
+     - accessToken
+     - claimsMap
+    """
+
+    thrift_spec = (
+        None,  # 0
+        (1, TType.STRING, 'accessToken', 'UTF8', None, ),  # 1
+        (2, TType.MAP, 'claimsMap', (TType.STRING, 'UTF8', TType.STRING, 'UTF8', False), None, ),  # 2
+    )
+
+    def __init__(self, accessToken=None, claimsMap=None,):
+        self.accessToken = accessToken
+        self.claimsMap = claimsMap
+
+    def read(self, iprot):
+        if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None:
+            iprot._fast_decode(self, iprot, (self.__class__, self.thrift_spec))
+            return
+        iprot.readStructBegin()
+        while True:
+            (fname, ftype, fid) = iprot.readFieldBegin()
+            if ftype == TType.STOP:
+                break
+            if fid == 1:
+                if ftype == TType.STRING:
+                    self.accessToken = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
+                else:
+                    iprot.skip(ftype)
+            elif fid == 2:
+                if ftype == TType.MAP:
+                    self.claimsMap = {}
+                    (_ktype1, _vtype2, _size0) = iprot.readMapBegin()
+                    for _i4 in range(_size0):
+                        _key5 = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
+                        _val6 = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
+                        self.claimsMap[_key5] = _val6
+                    iprot.readMapEnd()
+                else:
+                    iprot.skip(ftype)
+            else:
+                iprot.skip(ftype)
+            iprot.readFieldEnd()
+        iprot.readStructEnd()
+
+    def write(self, oprot):
+        if oprot._fast_encode is not None and self.thrift_spec is not None:
+            oprot.trans.write(oprot._fast_encode(self, (self.__class__, self.thrift_spec)))
+            return
+        oprot.writeStructBegin('AuthzToken')
+        if self.accessToken is not None:
+            oprot.writeFieldBegin('accessToken', TType.STRING, 1)
+            oprot.writeString(self.accessToken.encode('utf-8') if sys.version_info[0] == 2 else self.accessToken)
+            oprot.writeFieldEnd()
+        if self.claimsMap is not None:
+            oprot.writeFieldBegin('claimsMap', TType.MAP, 2)
+            oprot.writeMapBegin(TType.STRING, TType.STRING, len(self.claimsMap))
+            for kiter7, viter8 in self.claimsMap.items():
+                oprot.writeString(kiter7.encode('utf-8') if sys.version_info[0] == 2 else kiter7)
+                oprot.writeString(viter8.encode('utf-8') if sys.version_info[0] == 2 else viter8)
+            oprot.writeMapEnd()
+            oprot.writeFieldEnd()
+        oprot.writeFieldStop()
+        oprot.writeStructEnd()
+
+    def validate(self):
+        if self.accessToken is None:
+            raise TProtocolException(message='Required field accessToken is unset!')
+        return
+
+    def __repr__(self):
+        L = ['%s=%r' % (key, value)
+             for key, value in self.__dict__.items()]
+        return '%s(%s)' % (self.__class__.__name__, ', '.join(L))
+
+    def __eq__(self, other):
+        return isinstance(other, self.__class__) and self.__dict__ == other.__dict__
+
+    def __ne__(self, other):
+        return not (self == other)
diff --git a/clients/python/airavata_custos/settings.py b/clients/python/airavata_custos/settings.py
new file mode 100644
index 0000000..c36909e
--- /dev/null
+++ b/clients/python/airavata_custos/settings.py
@@ -0,0 +1,31 @@
+#
+# 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.
+#
+
+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'
+
+# 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 = ''
+PROFILE_SERVICE_PORT = ''
+PROFILE_SERVICE_SECURE = False
\ No newline at end of file
diff --git a/clients/python/airavata_custos/utils.py b/clients/python/airavata_custos/utils.py
new file mode 100644
index 0000000..afad780
--- /dev/null
+++ b/clients/python/airavata_custos/utils.py
@@ -0,0 +1,16 @@
+import thrift_connector.connection_pool as connection_pool
+from airavata_custos import settings
+from custos.service.profile.iam.admin.services.cpi import IamAdminServices, constants
+
+iamadmin_client_pool = connection_pool.ClientPool(
+    IamAdminServices,
+    settings.PROFILE_SERVICE_HOST,
+    settings.PROFILE_SERVICE_PORT,
+    connection_class=IAMAdminServiceThriftClient,
+    keepalive=settings.THRIFT_CLIENT_POOL_KEEPALIVE
+)
+
+class IAMAdminServiceThriftClient(MultiplexThriftClientMixin,
+                                  CustomThriftClient):
+    service_name = constants.IAM_ADMIN_SERVICES_CPI_NAME
+    secure = settings.PROFILE_SERVICE_SECURE
\ No newline at end of file
diff --git a/clients/python/custos/__init__.py b/clients/python/custos/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/clients/python/custos/commons/__init__.py b/clients/python/custos/commons/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/clients/python/custos/commons/model/__init__.py b/clients/python/custos/commons/model/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/clients/python/custos/commons/model/security/__init__.py b/clients/python/custos/commons/model/security/__init__.py
new file mode 100644
index 0000000..adefd8e
--- /dev/null
+++ b/clients/python/custos/commons/model/security/__init__.py
@@ -0,0 +1 @@
+__all__ = ['ttypes', 'constants']
diff --git a/clients/python/custos/commons/model/security/constants.py b/clients/python/custos/commons/model/security/constants.py
new file mode 100644
index 0000000..c59352d
--- /dev/null
+++ b/clients/python/custos/commons/model/security/constants.py
@@ -0,0 +1,14 @@
+#
+# Autogenerated by Thrift Compiler (0.12.0)
+#
+# DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
+#
+#  options string: py
+#
+
+from thrift.Thrift import TType, TMessageType, TFrozenDict, TException, TApplicationException
+from thrift.protocol.TProtocol import TProtocolException
+from thrift.TRecursive import fix_spec
+
+import sys
+from .ttypes import *
diff --git a/clients/python/custos/commons/model/security/ttypes.py b/clients/python/custos/commons/model/security/ttypes.py
new file mode 100644
index 0000000..fe22b60
--- /dev/null
+++ b/clients/python/custos/commons/model/security/ttypes.py
@@ -0,0 +1,104 @@
+#
+# Autogenerated by Thrift Compiler (0.12.0)
+#
+# DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
+#
+#  options string: py
+#
+
+from thrift.Thrift import TType, TMessageType, TFrozenDict, TException, TApplicationException
+from thrift.protocol.TProtocol import TProtocolException
+from thrift.TRecursive import fix_spec
+
+import sys
+
+from thrift.transport import TTransport
+all_structs = []
+
+
+class AuthzToken(object):
+    """
+    Attributes:
+     - accessToken
+     - claimsMap
+
+    """
+
+
+    def __init__(self, accessToken=None, claimsMap=None,):
+        self.accessToken = accessToken
+        self.claimsMap = claimsMap
+
+    def read(self, iprot):
+        if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None:
+            iprot._fast_decode(self, iprot, [self.__class__, self.thrift_spec])
+            return
+        iprot.readStructBegin()
+        while True:
+            (fname, ftype, fid) = iprot.readFieldBegin()
+            if ftype == TType.STOP:
+                break
+            if fid == 1:
+                if ftype == TType.STRING:
+                    self.accessToken = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
+                else:
+                    iprot.skip(ftype)
+            elif fid == 2:
+                if ftype == TType.MAP:
+                    self.claimsMap = {}
+                    (_ktype1, _vtype2, _size0) = iprot.readMapBegin()
+                    for _i4 in range(_size0):
+                        _key5 = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
+                        _val6 = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
+                        self.claimsMap[_key5] = _val6
+                    iprot.readMapEnd()
+                else:
+                    iprot.skip(ftype)
+            else:
+                iprot.skip(ftype)
+            iprot.readFieldEnd()
+        iprot.readStructEnd()
+
+    def write(self, oprot):
+        if oprot._fast_encode is not None and self.thrift_spec is not None:
+            oprot.trans.write(oprot._fast_encode(self, [self.__class__, self.thrift_spec]))
+            return
+        oprot.writeStructBegin('AuthzToken')
+        if self.accessToken is not None:
+            oprot.writeFieldBegin('accessToken', TType.STRING, 1)
+            oprot.writeString(self.accessToken.encode('utf-8') if sys.version_info[0] == 2 else self.accessToken)
+            oprot.writeFieldEnd()
+        if self.claimsMap is not None:
+            oprot.writeFieldBegin('claimsMap', TType.MAP, 2)
+            oprot.writeMapBegin(TType.STRING, TType.STRING, len(self.claimsMap))
+            for kiter7, viter8 in self.claimsMap.items():
+                oprot.writeString(kiter7.encode('utf-8') if sys.version_info[0] == 2 else kiter7)
+                oprot.writeString(viter8.encode('utf-8') if sys.version_info[0] == 2 else viter8)
+            oprot.writeMapEnd()
+            oprot.writeFieldEnd()
+        oprot.writeFieldStop()
+        oprot.writeStructEnd()
+
+    def validate(self):
+        if self.accessToken is None:
+            raise TProtocolException(message='Required field accessToken is unset!')
+        return
+
+    def __repr__(self):
+        L = ['%s=%r' % (key, value)
+             for key, value in self.__dict__.items()]
+        return '%s(%s)' % (self.__class__.__name__, ', '.join(L))
+
+    def __eq__(self, other):
+        return isinstance(other, self.__class__) and self.__dict__ == other.__dict__
+
+    def __ne__(self, other):
+        return not (self == other)
+all_structs.append(AuthzToken)
+AuthzToken.thrift_spec = (
+    None,  # 0
+    (1, TType.STRING, 'accessToken', 'UTF8', None, ),  # 1
+    (2, TType.MAP, 'claimsMap', (TType.STRING, 'UTF8', TType.STRING, 'UTF8', False), None, ),  # 2
+)
+fix_spec(all_structs)
+del all_structs
diff --git a/clients/python/custos/profile/__init__.py b/clients/python/custos/profile/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/clients/python/custos/profile/iam/__init__.py b/clients/python/custos/profile/iam/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/clients/python/custos/profile/iam/admin/__init__.py b/clients/python/custos/profile/iam/admin/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/clients/python/custos/profile/iam/admin/services/__init__.py b/clients/python/custos/profile/iam/admin/services/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/clients/python/custos/profile/iam/admin/services/cpi/IamAdminServices-remote b/clients/python/custos/profile/iam/admin/services/cpi/IamAdminServices-remote
new file mode 100644
index 0000000..bb6e133
--- /dev/null
+++ b/clients/python/custos/profile/iam/admin/services/cpi/IamAdminServices-remote
@@ -0,0 +1,222 @@
+#!/usr/bin/env python
+#
+# Autogenerated by Thrift Compiler (0.12.0)
+#
+# DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
+#
+#  options string: py
+#
+
+import sys
+import pprint
+if sys.version_info[0] > 2:
+    from urllib.parse import urlparse
+else:
+    from urlparse import urlparse
+from thrift.transport import TTransport, TSocket, TSSLSocket, THttpClient
+from thrift.protocol.TBinaryProtocol import TBinaryProtocol
+
+from custos.profile.iam.admin.services.cpi import IamAdminServices
+from custos.profile.iam.admin.services.cpi.ttypes import *
+
+if len(sys.argv) <= 1 or sys.argv[1] == '--help':
+    print('')
+    print('Usage: ' + sys.argv[0] + ' [-h host[:port]] [-u url] [-f[ramed]] [-s[sl]] [-novalidate] [-ca_certs certs] [-keyfile keyfile] [-certfile certfile] function [arg1 [arg2...]]')
+    print('')
+    print('Functions:')
+    print('  string getAPIVersion()')
+    print('  Gateway setUpGateway(AuthzToken authzToken, Gateway gateway, PasswordCredential tenantAdminPasswordCredential)')
+    print('  bool isUsernameAvailable(AuthzToken authzToken, string username)')
+    print('  bool registerUser(AuthzToken authzToken, string username, string emailAddress, string firstName, string lastName, string newPassword)')
+    print('  bool deleteUser(AuthzToken authzToken, string username)')
+    print('  UserProfile enableUser(AuthzToken authzToken, string username)')
+    print('  bool isUserEnabled(AuthzToken authzToken, string username)')
+    print('  bool isUserExist(AuthzToken authzToken, string username)')
+    print('  UserProfile getUser(AuthzToken authzToken, string username)')
+    print('   getUsers(AuthzToken authzToken, i32 offset, i32 limit, string search)')
+    print('  bool resetUserPassword(AuthzToken authzToken, string username, string newPassword)')
+    print('   findUsers(AuthzToken authzToken, string email, string userId)')
+    print('  void updateUserProfile(AuthzToken authzToken, UserProfile userDetails)')
+    print('  bool addRoleToUser(AuthzToken authzToken, string username, string roleName, PasswordCredential tenantAdminPasswordCredential)')
+    print('  bool removeRoleFromUser(AuthzToken authzToken, string username, string roleName, PasswordCredential tenantAdminPasswordCredential)')
+    print('   getUsersWithRole(AuthzToken authzToken, string roleName, PasswordCredential tenantAdminPasswordCredential)')
+    print('')
+    sys.exit(0)
+
+pp = pprint.PrettyPrinter(indent=2)
+host = 'localhost'
+port = 9090
+uri = ''
+framed = False
+ssl = False
+validate = True
+ca_certs = None
+keyfile = None
+certfile = None
+http = False
+argi = 1
+
+if sys.argv[argi] == '-h':
+    parts = sys.argv[argi + 1].split(':')
+    host = parts[0]
+    if len(parts) > 1:
+        port = int(parts[1])
+    argi += 2
+
+if sys.argv[argi] == '-u':
+    url = urlparse(sys.argv[argi + 1])
+    parts = url[1].split(':')
+    host = parts[0]
+    if len(parts) > 1:
+        port = int(parts[1])
+    else:
+        port = 80
+    uri = url[2]
+    if url[4]:
+        uri += '?%s' % url[4]
+    http = True
+    argi += 2
+
+if sys.argv[argi] == '-f' or sys.argv[argi] == '-framed':
+    framed = True
+    argi += 1
+
+if sys.argv[argi] == '-s' or sys.argv[argi] == '-ssl':
+    ssl = True
+    argi += 1
+
+if sys.argv[argi] == '-novalidate':
+    validate = False
+    argi += 1
+
+if sys.argv[argi] == '-ca_certs':
+    ca_certs = sys.argv[argi+1]
+    argi += 2
+
+if sys.argv[argi] == '-keyfile':
+    keyfile = sys.argv[argi+1]
+    argi += 2
+
+if sys.argv[argi] == '-certfile':
+    certfile = sys.argv[argi+1]
+    argi += 2
+
+cmd = sys.argv[argi]
+args = sys.argv[argi + 1:]
+
+if http:
+    transport = THttpClient.THttpClient(host, port, uri)
+else:
+    if ssl:
+        socket = TSSLSocket.TSSLSocket(host, port, validate=validate, ca_certs=ca_certs, keyfile=keyfile, certfile=certfile)
+    else:
+        socket = TSocket.TSocket(host, port)
+    if framed:
+        transport = TTransport.TFramedTransport(socket)
+    else:
+        transport = TTransport.TBufferedTransport(socket)
+protocol = TBinaryProtocol(transport)
+client = IamAdminServices.Client(protocol)
+transport.open()
+
+if cmd == 'getAPIVersion':
+    if len(args) != 0:
+        print('getAPIVersion requires 0 args')
+        sys.exit(1)
+    pp.pprint(client.getAPIVersion())
+
+elif cmd == 'setUpGateway':
+    if len(args) != 3:
+        print('setUpGateway requires 3 args')
+        sys.exit(1)
+    pp.pprint(client.setUpGateway(eval(args[0]), eval(args[1]), eval(args[2]),))
+
+elif cmd == 'isUsernameAvailable':
+    if len(args) != 2:
+        print('isUsernameAvailable requires 2 args')
+        sys.exit(1)
+    pp.pprint(client.isUsernameAvailable(eval(args[0]), args[1],))
+
+elif cmd == 'registerUser':
+    if len(args) != 6:
+        print('registerUser requires 6 args')
+        sys.exit(1)
+    pp.pprint(client.registerUser(eval(args[0]), args[1], args[2], args[3], args[4], args[5],))
+
+elif cmd == 'deleteUser':
+    if len(args) != 2:
+        print('deleteUser requires 2 args')
+        sys.exit(1)
+    pp.pprint(client.deleteUser(eval(args[0]), args[1],))
+
+elif cmd == 'enableUser':
+    if len(args) != 2:
+        print('enableUser requires 2 args')
+        sys.exit(1)
+    pp.pprint(client.enableUser(eval(args[0]), args[1],))
+
+elif cmd == 'isUserEnabled':
+    if len(args) != 2:
+        print('isUserEnabled requires 2 args')
+        sys.exit(1)
+    pp.pprint(client.isUserEnabled(eval(args[0]), args[1],))
+
+elif cmd == 'isUserExist':
+    if len(args) != 2:
+        print('isUserExist requires 2 args')
+        sys.exit(1)
+    pp.pprint(client.isUserExist(eval(args[0]), args[1],))
+
+elif cmd == 'getUser':
+    if len(args) != 2:
+        print('getUser requires 2 args')
+        sys.exit(1)
+    pp.pprint(client.getUser(eval(args[0]), args[1],))
+
+elif cmd == 'getUsers':
+    if len(args) != 4:
+        print('getUsers requires 4 args')
+        sys.exit(1)
+    pp.pprint(client.getUsers(eval(args[0]), eval(args[1]), eval(args[2]), args[3],))
+
+elif cmd == 'resetUserPassword':
+    if len(args) != 3:
+        print('resetUserPassword requires 3 args')
+        sys.exit(1)
+    pp.pprint(client.resetUserPassword(eval(args[0]), args[1], args[2],))
+
+elif cmd == 'findUsers':
+    if len(args) != 3:
+        print('findUsers requires 3 args')
+        sys.exit(1)
+    pp.pprint(client.findUsers(eval(args[0]), args[1], args[2],))
+
+elif cmd == 'updateUserProfile':
+    if len(args) != 2:
+        print('updateUserProfile requires 2 args')
+        sys.exit(1)
+    pp.pprint(client.updateUserProfile(eval(args[0]), eval(args[1]),))
+
+elif cmd == 'addRoleToUser':
+    if len(args) != 4:
+        print('addRoleToUser requires 4 args')
+        sys.exit(1)
+    pp.pprint(client.addRoleToUser(eval(args[0]), args[1], args[2], eval(args[3]),))
+
+elif cmd == 'removeRoleFromUser':
+    if len(args) != 4:
+        print('removeRoleFromUser requires 4 args')
+        sys.exit(1)
+    pp.pprint(client.removeRoleFromUser(eval(args[0]), args[1], args[2], eval(args[3]),))
+
+elif cmd == 'getUsersWithRole':
+    if len(args) != 3:
+        print('getUsersWithRole requires 3 args')
+        sys.exit(1)
+    pp.pprint(client.getUsersWithRole(eval(args[0]), args[1], eval(args[2]),))
+
+else:
+    print('Unrecognized method %s' % cmd)
+    sys.exit(1)
+
+transport.close()
diff --git a/clients/python/custos/profile/iam/admin/services/cpi/IamAdminServices.py b/clients/python/custos/profile/iam/admin/services/cpi/IamAdminServices.py
new file mode 100644
index 0000000..ffd3247
--- /dev/null
+++ b/clients/python/custos/profile/iam/admin/services/cpi/IamAdminServices.py
@@ -0,0 +1,3863 @@
+#
+# Autogenerated by Thrift Compiler (0.12.0)
+#
+# DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
+#
+#  options string: py
+#
+
+from thrift.Thrift import TType, TMessageType, TFrozenDict, TException, TApplicationException
+from thrift.protocol.TProtocol import TProtocolException
+from thrift.TRecursive import fix_spec
+
+import sys
+import logging
+from .ttypes import *
+from thrift.Thrift import TProcessor
+from thrift.transport import TTransport
+all_structs = []
+
+
+class Iface(object):
+    def getAPIVersion(self):
+        pass
+
+    def setUpGateway(self, authzToken, gateway, tenantAdminPasswordCredential):
+        """
+        Parameters:
+         - authzToken
+         - gateway
+         - tenantAdminPasswordCredential
+
+        """
+        pass
+
+    def isUsernameAvailable(self, authzToken, username):
+        """
+        Parameters:
+         - authzToken
+         - username
+
+        """
+        pass
+
+    def registerUser(self, authzToken, username, emailAddress, firstName, lastName, newPassword):
+        """
+        Parameters:
+         - authzToken
+         - username
+         - emailAddress
+         - firstName
+         - lastName
+         - newPassword
+
+        """
+        pass
+
+    def deleteUser(self, authzToken, username):
+        """
+        Parameters:
+         - authzToken
+         - username
+
+        """
+        pass
+
+    def enableUser(self, authzToken, username):
+        """
+        Parameters:
+         - authzToken
+         - username
+
+        """
+        pass
+
+    def isUserEnabled(self, authzToken, username):
+        """
+        Parameters:
+         - authzToken
+         - username
+
+        """
+        pass
+
+    def isUserExist(self, authzToken, username):
+        """
+        Parameters:
+         - authzToken
+         - username
+
+        """
+        pass
+
+    def getUser(self, authzToken, username):
+        """
+        Parameters:
+         - authzToken
+         - username
+
+        """
+        pass
+
+    def getUsers(self, authzToken, offset, limit, search):
+        """
+        Parameters:
+         - authzToken
+         - offset
+         - limit
+         - search
+
+        """
+        pass
+
+    def resetUserPassword(self, authzToken, username, newPassword):
+        """
+        Parameters:
+         - authzToken
+         - username
+         - newPassword
+
+        """
+        pass
+
+    def findUsers(self, authzToken, email, userId):
+        """
+        Parameters:
+         - authzToken
+         - email
+         - userId
+
+        """
+        pass
+
+    def updateUserProfile(self, authzToken, userDetails):
+        """
+        Parameters:
+         - authzToken
+         - userDetails
+
+        """
+        pass
+
+    def addRoleToUser(self, authzToken, username, roleName, tenantAdminPasswordCredential):
+        """
+        Parameters:
+         - authzToken
+         - username
+         - roleName
+         - tenantAdminPasswordCredential
+
+        """
+        pass
+
+    def removeRoleFromUser(self, authzToken, username, roleName, tenantAdminPasswordCredential):
+        """
+        Parameters:
+         - authzToken
+         - username
+         - roleName
+         - tenantAdminPasswordCredential
+
+        """
+        pass
+
+    def getUsersWithRole(self, authzToken, roleName, tenantAdminPasswordCredential):
+        """
+        Parameters:
+         - authzToken
+         - roleName
+         - tenantAdminPasswordCredential
+
+        """
+        pass
+
+
+class Client(Iface):
+    def __init__(self, iprot, oprot=None):
+        self._iprot = self._oprot = iprot
+        if oprot is not None:
+            self._oprot = oprot
+        self._seqid = 0
+
+    def getAPIVersion(self):
+        self.send_getAPIVersion()
+        return self.recv_getAPIVersion()
+
+    def send_getAPIVersion(self):
+        self._oprot.writeMessageBegin('getAPIVersion', TMessageType.CALL, self._seqid)
+        args = getAPIVersion_args()
+        args.write(self._oprot)
+        self._oprot.writeMessageEnd()
+        self._oprot.trans.flush()
+
+    def recv_getAPIVersion(self):
+        iprot = self._iprot
+        (fname, mtype, rseqid) = iprot.readMessageBegin()
+        if mtype == TMessageType.EXCEPTION:
+            x = TApplicationException()
+            x.read(iprot)
+            iprot.readMessageEnd()
+            raise x
+        result = getAPIVersion_result()
+        result.read(iprot)
+        iprot.readMessageEnd()
+        if result.success is not None:
+            return result.success
+        if result.Idse is not None:
+            raise result.Idse
+        raise TApplicationException(TApplicationException.MISSING_RESULT, "getAPIVersion failed: unknown result")
+
+    def setUpGateway(self, authzToken, gateway, tenantAdminPasswordCredential):
+        """
+        Parameters:
+         - authzToken
+         - gateway
+         - tenantAdminPasswordCredential
+
+        """
+        self.send_setUpGateway(authzToken, gateway, tenantAdminPasswordCredential)
+        return self.recv_setUpGateway()
+
+    def send_setUpGateway(self, authzToken, gateway, tenantAdminPasswordCredential):
+        self._oprot.writeMessageBegin('setUpGateway', TMessageType.CALL, self._seqid)
+        args = setUpGateway_args()
+        args.authzToken = authzToken
+        args.gateway = gateway
+        args.tenantAdminPasswordCredential = tenantAdminPasswordCredential
+        args.write(self._oprot)
+        self._oprot.writeMessageEnd()
+        self._oprot.trans.flush()
+
+    def recv_setUpGateway(self):
+        iprot = self._iprot
+        (fname, mtype, rseqid) = iprot.readMessageBegin()
+        if mtype == TMessageType.EXCEPTION:
+            x = TApplicationException()
+            x.read(iprot)
+            iprot.readMessageEnd()
+            raise x
+        result = setUpGateway_result()
+        result.read(iprot)
+        iprot.readMessageEnd()
+        if result.success is not None:
+            return result.success
+        if result.Idse is not None:
+            raise result.Idse
+        raise TApplicationException(TApplicationException.MISSING_RESULT, "setUpGateway failed: unknown result")
+
+    def isUsernameAvailable(self, authzToken, username):
+        """
+        Parameters:
+         - authzToken
+         - username
+
+        """
+        self.send_isUsernameAvailable(authzToken, username)
+        return self.recv_isUsernameAvailable()
+
+    def send_isUsernameAvailable(self, authzToken, username):
+        self._oprot.writeMessageBegin('isUsernameAvailable', TMessageType.CALL, self._seqid)
+        args = isUsernameAvailable_args()
+        args.authzToken = authzToken
+        args.username = username
+        args.write(self._oprot)
+        self._oprot.writeMessageEnd()
+        self._oprot.trans.flush()
+
+    def recv_isUsernameAvailable(self):
+        iprot = self._iprot
+        (fname, mtype, rseqid) = iprot.readMessageBegin()
+        if mtype == TMessageType.EXCEPTION:
+            x = TApplicationException()
+            x.read(iprot)
+            iprot.readMessageEnd()
+            raise x
+        result = isUsernameAvailable_result()
+        result.read(iprot)
+        iprot.readMessageEnd()
+        if result.success is not None:
+            return result.success
+        if result.Idse is not None:
+            raise result.Idse
+        raise TApplicationException(TApplicationException.MISSING_RESULT, "isUsernameAvailable failed: unknown result")
+
+    def registerUser(self, authzToken, username, emailAddress, firstName, lastName, newPassword):
+        """
+        Parameters:
+         - authzToken
+         - username
+         - emailAddress
+         - firstName
+         - lastName
+         - newPassword
+
+        """
+        self.send_registerUser(authzToken, username, emailAddress, firstName, lastName, newPassword)
+        return self.recv_registerUser()
+
+    def send_registerUser(self, authzToken, username, emailAddress, firstName, lastName, newPassword):
+        self._oprot.writeMessageBegin('registerUser', TMessageType.CALL, self._seqid)
+        args = registerUser_args()
+        args.authzToken = authzToken
+        args.username = username
+        args.emailAddress = emailAddress
+        args.firstName = firstName
+        args.lastName = lastName
+        args.newPassword = newPassword
+        args.write(self._oprot)
+        self._oprot.writeMessageEnd()
+        self._oprot.trans.flush()
+
+    def recv_registerUser(self):
+        iprot = self._iprot
+        (fname, mtype, rseqid) = iprot.readMessageBegin()
+        if mtype == TMessageType.EXCEPTION:
+            x = TApplicationException()
+            x.read(iprot)
+            iprot.readMessageEnd()
+            raise x
+        result = registerUser_result()
+        result.read(iprot)
+        iprot.readMessageEnd()
+        if result.success is not None:
+            return result.success
+        if result.Idse is not None:
+            raise result.Idse
+        raise TApplicationException(TApplicationException.MISSING_RESULT, "registerUser failed: unknown result")
+
+    def deleteUser(self, authzToken, username):
+        """
+        Parameters:
+         - authzToken
+         - username
+
+        """
+        self.send_deleteUser(authzToken, username)
+        return self.recv_deleteUser()
+
+    def send_deleteUser(self, authzToken, username):
+        self._oprot.writeMessageBegin('deleteUser', TMessageType.CALL, self._seqid)
+        args = deleteUser_args()
+        args.authzToken = authzToken
+        args.username = username
+        args.write(self._oprot)
+        self._oprot.writeMessageEnd()
+        self._oprot.trans.flush()
+
+    def recv_deleteUser(self):
+        iprot = self._iprot
+        (fname, mtype, rseqid) = iprot.readMessageBegin()
+        if mtype == TMessageType.EXCEPTION:
+            x = TApplicationException()
+            x.read(iprot)
+            iprot.readMessageEnd()
+            raise x
+        result = deleteUser_result()
+        result.read(iprot)
+        iprot.readMessageEnd()
+        if result.success is not None:
+            return result.success
+        if result.Idse is not None:
+            raise result.Idse
+        raise TApplicationException(TApplicationException.MISSING_RESULT, "deleteUser failed: unknown result")
+
+    def enableUser(self, authzToken, username):
+        """
+        Parameters:
+         - authzToken
+         - username
+
+        """
+        self.send_enableUser(authzToken, username)
+        return self.recv_enableUser()
+
+    def send_enableUser(self, authzToken, username):
+        self._oprot.writeMessageBegin('enableUser', TMessageType.CALL, self._seqid)
+        args = enableUser_args()
+        args.authzToken = authzToken
+        args.username = username
+        args.write(self._oprot)
+        self._oprot.writeMessageEnd()
+        self._oprot.trans.flush()
+
+    def recv_enableUser(self):
+        iprot = self._iprot
+        (fname, mtype, rseqid) = iprot.readMessageBegin()
+        if mtype == TMessageType.EXCEPTION:
+            x = TApplicationException()
+            x.read(iprot)
+            iprot.readMessageEnd()
+            raise x
+        result = enableUser_result()
+        result.read(iprot)
+        iprot.readMessageEnd()
+        if result.success is not None:
+            return result.success
+        if result.Idse is not None:
+            raise result.Idse
+        raise TApplicationException(TApplicationException.MISSING_RESULT, "enableUser failed: unknown result")
+
+    def isUserEnabled(self, authzToken, username):
+        """
+        Parameters:
+         - authzToken
+         - username
+
+        """
+        self.send_isUserEnabled(authzToken, username)
+        return self.recv_isUserEnabled()
+
+    def send_isUserEnabled(self, authzToken, username):
+        self._oprot.writeMessageBegin('isUserEnabled', TMessageType.CALL, self._seqid)
+        args = isUserEnabled_args()
+        args.authzToken = authzToken
+        args.username = username
+        args.write(self._oprot)
+        self._oprot.writeMessageEnd()
+        self._oprot.trans.flush()
+
+    def recv_isUserEnabled(self):
+        iprot = self._iprot
+        (fname, mtype, rseqid) = iprot.readMessageBegin()
+        if mtype == TMessageType.EXCEPTION:
+            x = TApplicationException()
+            x.read(iprot)
+            iprot.readMessageEnd()
+            raise x
+        result = isUserEnabled_result()
+        result.read(iprot)
+        iprot.readMessageEnd()
+        if result.success is not None:
+            return result.success
+        if result.Idse is not None:
+            raise result.Idse
+        raise TApplicationException(TApplicationException.MISSING_RESULT, "isUserEnabled failed: unknown result")
+
+    def isUserExist(self, authzToken, username):
+        """
+        Parameters:
+         - authzToken
+         - username
+
+        """
+        self.send_isUserExist(authzToken, username)
+        return self.recv_isUserExist()
+
+    def send_isUserExist(self, authzToken, username):
+        self._oprot.writeMessageBegin('isUserExist', TMessageType.CALL, self._seqid)
+        args = isUserExist_args()
+        args.authzToken = authzToken
+        args.username = username
+        args.write(self._oprot)
+        self._oprot.writeMessageEnd()
+        self._oprot.trans.flush()
+
+    def recv_isUserExist(self):
+        iprot = self._iprot
+        (fname, mtype, rseqid) = iprot.readMessageBegin()
+        if mtype == TMessageType.EXCEPTION:
+            x = TApplicationException()
+            x.read(iprot)
+            iprot.readMessageEnd()
+            raise x
+        result = isUserExist_result()
+        result.read(iprot)
+        iprot.readMessageEnd()
+        if result.success is not None:
+            return result.success
+        if result.Idse is not None:
+            raise result.Idse
+        raise TApplicationException(TApplicationException.MISSING_RESULT, "isUserExist failed: unknown result")
+
+    def getUser(self, authzToken, username):
+        """
+        Parameters:
+         - authzToken
+         - username
+
+        """
+        self.send_getUser(authzToken, username)
+        return self.recv_getUser()
+
+    def send_getUser(self, authzToken, username):
+        self._oprot.writeMessageBegin('getUser', TMessageType.CALL, self._seqid)
+        args = getUser_args()
+        args.authzToken = authzToken
+        args.username = username
+        args.write(self._oprot)
+        self._oprot.writeMessageEnd()
+        self._oprot.trans.flush()
+
+    def recv_getUser(self):
+        iprot = self._iprot
+        (fname, mtype, rseqid) = iprot.readMessageBegin()
+        if mtype == TMessageType.EXCEPTION:
+            x = TApplicationException()
+            x.read(iprot)
+            iprot.readMessageEnd()
+            raise x
+        result = getUser_result()
+        result.read(iprot)
+        iprot.readMessageEnd()
+        if result.success is not None:
+            return result.success
+        if result.Idse is not None:
+            raise result.Idse
+        raise TApplicationException(TApplicationException.MISSING_RESULT, "getUser failed: unknown result")
+
+    def getUsers(self, authzToken, offset, limit, search):
+        """
+        Parameters:
+         - authzToken
+         - offset
+         - limit
+         - search
+
+        """
+        self.send_getUsers(authzToken, offset, limit, search)
+        return self.recv_getUsers()
+
+    def send_getUsers(self, authzToken, offset, limit, search):
+        self._oprot.writeMessageBegin('getUsers', TMessageType.CALL, self._seqid)
+        args = getUsers_args()
+        args.authzToken = authzToken
+        args.offset = offset
+        args.limit = limit
+        args.search = search
+        args.write(self._oprot)
+        self._oprot.writeMessageEnd()
+        self._oprot.trans.flush()
+
+    def recv_getUsers(self):
+        iprot = self._iprot
+        (fname, mtype, rseqid) = iprot.readMessageBegin()
+        if mtype == TMessageType.EXCEPTION:
+            x = TApplicationException()
+            x.read(iprot)
+            iprot.readMessageEnd()
+            raise x
+        result = getUsers_result()
+        result.read(iprot)
+        iprot.readMessageEnd()
+        if result.success is not None:
+            return result.success
+        if result.Idse is not None:
+            raise result.Idse
+        raise TApplicationException(TApplicationException.MISSING_RESULT, "getUsers failed: unknown result")
+
+    def resetUserPassword(self, authzToken, username, newPassword):
+        """
+        Parameters:
+         - authzToken
+         - username
+         - newPassword
+
+        """
+        self.send_resetUserPassword(authzToken, username, newPassword)
+        return self.recv_resetUserPassword()
+
+    def send_resetUserPassword(self, authzToken, username, newPassword):
+        self._oprot.writeMessageBegin('resetUserPassword', TMessageType.CALL, self._seqid)
+        args = resetUserPassword_args()
+        args.authzToken = authzToken
+        args.username = username
+        args.newPassword = newPassword
+        args.write(self._oprot)
+        self._oprot.writeMessageEnd()
+        self._oprot.trans.flush()
+
+    def recv_resetUserPassword(self):
+        iprot = self._iprot
+        (fname, mtype, rseqid) = iprot.readMessageBegin()
+        if mtype == TMessageType.EXCEPTION:
+            x = TApplicationException()
+            x.read(iprot)
+            iprot.readMessageEnd()
+            raise x
+        result = resetUserPassword_result()
+        result.read(iprot)
+        iprot.readMessageEnd()
+        if result.success is not None:
+            return result.success
+        if result.Idse is not None:
+            raise result.Idse
+        raise TApplicationException(TApplicationException.MISSING_RESULT, "resetUserPassword failed: unknown result")
+
+    def findUsers(self, authzToken, email, userId):
+        """
+        Parameters:
+         - authzToken
+         - email
+         - userId
+
+        """
+        self.send_findUsers(authzToken, email, userId)
+        return self.recv_findUsers()
+
+    def send_findUsers(self, authzToken, email, userId):
+        self._oprot.writeMessageBegin('findUsers', TMessageType.CALL, self._seqid)
+        args = findUsers_args()
+        args.authzToken = authzToken
+        args.email = email
+        args.userId = userId
+        args.write(self._oprot)
+        self._oprot.writeMessageEnd()
+        self._oprot.trans.flush()
+
+    def recv_findUsers(self):
+        iprot = self._iprot
+        (fname, mtype, rseqid) = iprot.readMessageBegin()
+        if mtype == TMessageType.EXCEPTION:
+            x = TApplicationException()
+            x.read(iprot)
+            iprot.readMessageEnd()
+            raise x
+        result = findUsers_result()
+        result.read(iprot)
+        iprot.readMessageEnd()
+        if result.success is not None:
+            return result.success
+        if result.Idse is not None:
+            raise result.Idse
+        raise TApplicationException(TApplicationException.MISSING_RESULT, "findUsers failed: unknown result")
+
+    def updateUserProfile(self, authzToken, userDetails):
+        """
+        Parameters:
+         - authzToken
+         - userDetails
+
+        """
+        self.send_updateUserProfile(authzToken, userDetails)
+        self.recv_updateUserProfile()
+
+    def send_updateUserProfile(self, authzToken, userDetails):
+        self._oprot.writeMessageBegin('updateUserProfile', TMessageType.CALL, self._seqid)
+        args = updateUserProfile_args()
+        args.authzToken = authzToken
+        args.userDetails = userDetails
+        args.write(self._oprot)
+        self._oprot.writeMessageEnd()
+        self._oprot.trans.flush()
+
+    def recv_updateUserProfile(self):
+        iprot = self._iprot
+        (fname, mtype, rseqid) = iprot.readMessageBegin()
+        if mtype == TMessageType.EXCEPTION:
+            x = TApplicationException()
+            x.read(iprot)
+            iprot.readMessageEnd()
+            raise x
+        result = updateUserProfile_result()
+        result.read(iprot)
+        iprot.readMessageEnd()
+        if result.Idse is not None:
+            raise result.Idse
+        return
+
+    def addRoleToUser(self, authzToken, username, roleName, tenantAdminPasswordCredential):
+        """
+        Parameters:
+         - authzToken
+         - username
+         - roleName
+         - tenantAdminPasswordCredential
+
+        """
+        self.send_addRoleToUser(authzToken, username, roleName, tenantAdminPasswordCredential)
+        return self.recv_addRoleToUser()
+
+    def send_addRoleToUser(self, authzToken, username, roleName, tenantAdminPasswordCredential):
+        self._oprot.writeMessageBegin('addRoleToUser', TMessageType.CALL, self._seqid)
+        args = addRoleToUser_args()
+        args.authzToken = authzToken
+        args.username = username
+        args.roleName = roleName
+        args.tenantAdminPasswordCredential = tenantAdminPasswordCredential
+        args.write(self._oprot)
+        self._oprot.writeMessageEnd()
+        self._oprot.trans.flush()
+
+    def recv_addRoleToUser(self):
+        iprot = self._iprot
+        (fname, mtype, rseqid) = iprot.readMessageBegin()
+        if mtype == TMessageType.EXCEPTION:
+            x = TApplicationException()
+            x.read(iprot)
+            iprot.readMessageEnd()
+            raise x
+        result = addRoleToUser_result()
+        result.read(iprot)
+        iprot.readMessageEnd()
+        if result.success is not None:
+            return result.success
+        if result.Idse is not None:
+            raise result.Idse
+        raise TApplicationException(TApplicationException.MISSING_RESULT, "addRoleToUser failed: unknown result")
+
+    def removeRoleFromUser(self, authzToken, username, roleName, tenantAdminPasswordCredential):
+        """
+        Parameters:
+         - authzToken
+         - username
+         - roleName
+         - tenantAdminPasswordCredential
+
+        """
+        self.send_removeRoleFromUser(authzToken, username, roleName, tenantAdminPasswordCredential)
+        return self.recv_removeRoleFromUser()
+
+    def send_removeRoleFromUser(self, authzToken, username, roleName, tenantAdminPasswordCredential):
+        self._oprot.writeMessageBegin('removeRoleFromUser', TMessageType.CALL, self._seqid)
+        args = removeRoleFromUser_args()
+        args.authzToken = authzToken
+        args.username = username
+        args.roleName = roleName
+        args.tenantAdminPasswordCredential = tenantAdminPasswordCredential
+        args.write(self._oprot)
+        self._oprot.writeMessageEnd()
+        self._oprot.trans.flush()
+
+    def recv_removeRoleFromUser(self):
+        iprot = self._iprot
+        (fname, mtype, rseqid) = iprot.readMessageBegin()
+        if mtype == TMessageType.EXCEPTION:
+            x = TApplicationException()
+            x.read(iprot)
+            iprot.readMessageEnd()
+            raise x
+        result = removeRoleFromUser_result()
+        result.read(iprot)
+        iprot.readMessageEnd()
+        if result.success is not None:
+            return result.success
+        if result.Idse is not None:
+            raise result.Idse
+        raise TApplicationException(TApplicationException.MISSING_RESULT, "removeRoleFromUser failed: unknown result")
+
+    def getUsersWithRole(self, authzToken, roleName, tenantAdminPasswordCredential):
+        """
+        Parameters:
+         - authzToken
+         - roleName
+         - tenantAdminPasswordCredential
+
+        """
+        self.send_getUsersWithRole(authzToken, roleName, tenantAdminPasswordCredential)
+        return self.recv_getUsersWithRole()
+
+    def send_getUsersWithRole(self, authzToken, roleName, tenantAdminPasswordCredential):
+        self._oprot.writeMessageBegin('getUsersWithRole', TMessageType.CALL, self._seqid)
+        args = getUsersWithRole_args()
+        args.authzToken = authzToken
+        args.roleName = roleName
+        args.tenantAdminPasswordCredential = tenantAdminPasswordCredential
+        args.write(self._oprot)
+        self._oprot.writeMessageEnd()
+        self._oprot.trans.flush()
+
+    def recv_getUsersWithRole(self):
+        iprot = self._iprot
+        (fname, mtype, rseqid) = iprot.readMessageBegin()
+        if mtype == TMessageType.EXCEPTION:
+            x = TApplicationException()
+            x.read(iprot)
+            iprot.readMessageEnd()
+            raise x
+        result = getUsersWithRole_result()
+        result.read(iprot)
+        iprot.readMessageEnd()
+        if result.success is not None:
+            return result.success
+        if result.Idse is not None:
+            raise result.Idse
+        raise TApplicationException(TApplicationException.MISSING_RESULT, "getUsersWithRole failed: unknown result")
+
+
+class Processor(Iface, TProcessor):
+    def __init__(self, handler):
+        self._handler = handler
+        self._processMap = {}
+        self._processMap["getAPIVersion"] = Processor.process_getAPIVersion
+        self._processMap["setUpGateway"] = Processor.process_setUpGateway
+        self._processMap["isUsernameAvailable"] = Processor.process_isUsernameAvailable
+        self._processMap["registerUser"] = Processor.process_registerUser
+        self._processMap["deleteUser"] = Processor.process_deleteUser
+        self._processMap["enableUser"] = Processor.process_enableUser
+        self._processMap["isUserEnabled"] = Processor.process_isUserEnabled
+        self._processMap["isUserExist"] = Processor.process_isUserExist
+        self._processMap["getUser"] = Processor.process_getUser
+        self._processMap["getUsers"] = Processor.process_getUsers
+        self._processMap["resetUserPassword"] = Processor.process_resetUserPassword
+        self._processMap["findUsers"] = Processor.process_findUsers
+        self._processMap["updateUserProfile"] = Processor.process_updateUserProfile
+        self._processMap["addRoleToUser"] = Processor.process_addRoleToUser
+        self._processMap["removeRoleFromUser"] = Processor.process_removeRoleFromUser
+        self._processMap["getUsersWithRole"] = Processor.process_getUsersWithRole
+
+    def process(self, iprot, oprot):
+        (name, type, seqid) = iprot.readMessageBegin()
+        if name not in self._processMap:
+            iprot.skip(TType.STRUCT)
+            iprot.readMessageEnd()
+            x = TApplicationException(TApplicationException.UNKNOWN_METHOD, 'Unknown function %s' % (name))
+            oprot.writeMessageBegin(name, TMessageType.EXCEPTION, seqid)
+            x.write(oprot)
+            oprot.writeMessageEnd()
+            oprot.trans.flush()
+            return
+        else:
+            self._processMap[name](self, seqid, iprot, oprot)
+        return True
+
+    def process_getAPIVersion(self, seqid, iprot, oprot):
+        args = getAPIVersion_args()
+        args.read(iprot)
+        iprot.readMessageEnd()
+        result = getAPIVersion_result()
+        try:
+            result.success = self._handler.getAPIVersion()
+            msg_type = TMessageType.REPLY
+        except TTransport.TTransportException:
+            raise
+        except custos.profile.iam.admin.services.cpi.error.ttypes.IamAdminServicesException as Idse:
+            msg_type = TMessageType.REPLY
+            result.Idse = Idse
+        except TApplicationException as ex:
+            logging.exception('TApplication exception in handler')
+            msg_type = TMessageType.EXCEPTION
+            result = ex
+        except Exception:
+            logging.exception('Unexpected exception in handler')
+            msg_type = TMessageType.EXCEPTION
+            result = TApplicationException(TApplicationException.INTERNAL_ERROR, 'Internal error')
+        oprot.writeMessageBegin("getAPIVersion", msg_type, seqid)
+        result.write(oprot)
+        oprot.writeMessageEnd()
+        oprot.trans.flush()
+
+    def process_setUpGateway(self, seqid, iprot, oprot):
+        args = setUpGateway_args()
+        args.read(iprot)
+        iprot.readMessageEnd()
+        result = setUpGateway_result()
+        try:
+            result.success = self._handler.setUpGateway(args.authzToken, args.gateway, args.tenantAdminPasswordCredential)
+            msg_type = TMessageType.REPLY
+        except TTransport.TTransportException:
+            raise
+        except custos.profile.iam.admin.services.cpi.error.ttypes.IamAdminServicesException as Idse:
+            msg_type = TMessageType.REPLY
+            result.Idse = Idse
+        except TApplicationException as ex:
+            logging.exception('TApplication exception in handler')
+            msg_type = TMessageType.EXCEPTION
+            result = ex
+        except Exception:
+            logging.exception('Unexpected exception in handler')
+            msg_type = TMessageType.EXCEPTION
+            result = TApplicationException(TApplicationException.INTERNAL_ERROR, 'Internal error')
+        oprot.writeMessageBegin("setUpGateway", msg_type, seqid)
+        result.write(oprot)
+        oprot.writeMessageEnd()
+        oprot.trans.flush()
+
+    def process_isUsernameAvailable(self, seqid, iprot, oprot):
+        args = isUsernameAvailable_args()
+        args.read(iprot)
+        iprot.readMessageEnd()
+        result = isUsernameAvailable_result()
+        try:
+            result.success = self._handler.isUsernameAvailable(args.authzToken, args.username)
+            msg_type = TMessageType.REPLY
+        except TTransport.TTransportException:
+            raise
+        except custos.profile.iam.admin.services.cpi.error.ttypes.IamAdminServicesException as Idse:
+            msg_type = TMessageType.REPLY
+            result.Idse = Idse
+        except TApplicationException as ex:
+            logging.exception('TApplication exception in handler')
+            msg_type = TMessageType.EXCEPTION
+            result = ex
+        except Exception:
+            logging.exception('Unexpected exception in handler')
+            msg_type = TMessageType.EXCEPTION
+            result = TApplicationException(TApplicationException.INTERNAL_ERROR, 'Internal error')
+        oprot.writeMessageBegin("isUsernameAvailable", msg_type, seqid)
+        result.write(oprot)
+        oprot.writeMessageEnd()
+        oprot.trans.flush()
+
+    def process_registerUser(self, seqid, iprot, oprot):
+        args = registerUser_args()
+        args.read(iprot)
+        iprot.readMessageEnd()
+        result = registerUser_result()
+        try:
+            result.success = self._handler.registerUser(args.authzToken, args.username, args.emailAddress, args.firstName, args.lastName, args.newPassword)
+            msg_type = TMessageType.REPLY
+        except TTransport.TTransportException:
+            raise
+        except custos.profile.iam.admin.services.cpi.error.ttypes.IamAdminServicesException as Idse:
+            msg_type = TMessageType.REPLY
+            result.Idse = Idse
+        except TApplicationException as ex:
+            logging.exception('TApplication exception in handler')
+            msg_type = TMessageType.EXCEPTION
+            result = ex
+        except Exception:
+            logging.exception('Unexpected exception in handler')
+            msg_type = TMessageType.EXCEPTION
+            result = TApplicationException(TApplicationException.INTERNAL_ERROR, 'Internal error')
+        oprot.writeMessageBegin("registerUser", msg_type, seqid)
+        result.write(oprot)
+        oprot.writeMessageEnd()
+        oprot.trans.flush()
+
+    def process_deleteUser(self, seqid, iprot, oprot):
+        args = deleteUser_args()
+        args.read(iprot)
+        iprot.readMessageEnd()
+        result = deleteUser_result()
+        try:
+            result.success = self._handler.deleteUser(args.authzToken, args.username)
+            msg_type = TMessageType.REPLY
+        except TTransport.TTransportException:
+            raise
+        except custos.profile.iam.admin.services.cpi.error.ttypes.IamAdminServicesException as Idse:
+            msg_type = TMessageType.REPLY
+            result.Idse = Idse
+        except TApplicationException as ex:
+            logging.exception('TApplication exception in handler')
+            msg_type = TMessageType.EXCEPTION
+            result = ex
+        except Exception:
+            logging.exception('Unexpected exception in handler')
+            msg_type = TMessageType.EXCEPTION
+            result = TApplicationException(TApplicationException.INTERNAL_ERROR, 'Internal error')
+        oprot.writeMessageBegin("deleteUser", msg_type, seqid)
+        result.write(oprot)
+        oprot.writeMessageEnd()
+        oprot.trans.flush()
+
+    def process_enableUser(self, seqid, iprot, oprot):
+        args = enableUser_args()
+        args.read(iprot)
+        iprot.readMessageEnd()
+        result = enableUser_result()
+        try:
+            result.success = self._handler.enableUser(args.authzToken, args.username)
+            msg_type = TMessageType.REPLY
+        except TTransport.TTransportException:
+            raise
+        except custos.profile.iam.admin.services.cpi.error.ttypes.IamAdminServicesException as Idse:
+            msg_type = TMessageType.REPLY
+            result.Idse = Idse
+        except TApplicationException as ex:
+            logging.exception('TApplication exception in handler')
+            msg_type = TMessageType.EXCEPTION
+            result = ex
+        except Exception:
+            logging.exception('Unexpected exception in handler')
+            msg_type = TMessageType.EXCEPTION
+            result = TApplicationException(TApplicationException.INTERNAL_ERROR, 'Internal error')
+        oprot.writeMessageBegin("enableUser", msg_type, seqid)
+        result.write(oprot)
+        oprot.writeMessageEnd()
+        oprot.trans.flush()
+
+    def process_isUserEnabled(self, seqid, iprot, oprot):
+        args = isUserEnabled_args()
+        args.read(iprot)
+        iprot.readMessageEnd()
+        result = isUserEnabled_result()
+        try:
+            result.success = self._handler.isUserEnabled(args.authzToken, args.username)
+            msg_type = TMessageType.REPLY
+        except TTransport.TTransportException:
+            raise
+        except custos.profile.iam.admin.services.cpi.error.ttypes.IamAdminServicesException as Idse:
+            msg_type = TMessageType.REPLY
+            result.Idse = Idse
+        except TApplicationException as ex:
+            logging.exception('TApplication exception in handler')
+            msg_type = TMessageType.EXCEPTION
+            result = ex
+        except Exception:
+            logging.exception('Unexpected exception in handler')
+            msg_type = TMessageType.EXCEPTION
+            result = TApplicationException(TApplicationException.INTERNAL_ERROR, 'Internal error')
+        oprot.writeMessageBegin("isUserEnabled", msg_type, seqid)
+        result.write(oprot)
+        oprot.writeMessageEnd()
+        oprot.trans.flush()
+
+    def process_isUserExist(self, seqid, iprot, oprot):
+        args = isUserExist_args()
+        args.read(iprot)
+        iprot.readMessageEnd()
+        result = isUserExist_result()
+        try:
+            result.success = self._handler.isUserExist(args.authzToken, args.username)
+            msg_type = TMessageType.REPLY
+        except TTransport.TTransportException:
+            raise
+        except custos.profile.iam.admin.services.cpi.error.ttypes.IamAdminServicesException as Idse:
+            msg_type = TMessageType.REPLY
+            result.Idse = Idse
+        except TApplicationException as ex:
+            logging.exception('TApplication exception in handler')
+            msg_type = TMessageType.EXCEPTION
+            result = ex
+        except Exception:
+            logging.exception('Unexpected exception in handler')
+            msg_type = TMessageType.EXCEPTION
+            result = TApplicationException(TApplicationException.INTERNAL_ERROR, 'Internal error')
+        oprot.writeMessageBegin("isUserExist", msg_type, seqid)
+        result.write(oprot)
+        oprot.writeMessageEnd()
+        oprot.trans.flush()
+
+    def process_getUser(self, seqid, iprot, oprot):
+        args = getUser_args()
+        args.read(iprot)
+        iprot.readMessageEnd()
+        result = getUser_result()
+        try:
+            result.success = self._handler.getUser(args.authzToken, args.username)
+            msg_type = TMessageType.REPLY
+        except TTransport.TTransportException:
+            raise
+        except custos.profile.iam.admin.services.cpi.error.ttypes.IamAdminServicesException as Idse:
+            msg_type = TMessageType.REPLY
+            result.Idse = Idse
+        except TApplicationException as ex:
+            logging.exception('TApplication exception in handler')
+            msg_type = TMessageType.EXCEPTION
+            result = ex
+        except Exception:
+            logging.exception('Unexpected exception in handler')
+            msg_type = TMessageType.EXCEPTION
+            result = TApplicationException(TApplicationException.INTERNAL_ERROR, 'Internal error')
+        oprot.writeMessageBegin("getUser", msg_type, seqid)
+        result.write(oprot)
+        oprot.writeMessageEnd()
+        oprot.trans.flush()
+
+    def process_getUsers(self, seqid, iprot, oprot):
+        args = getUsers_args()
+        args.read(iprot)
+        iprot.readMessageEnd()
+        result = getUsers_result()
+        try:
+            result.success = self._handler.getUsers(args.authzToken, args.offset, args.limit, args.search)
+            msg_type = TMessageType.REPLY
+        except TTransport.TTransportException:
+            raise
+        except custos.profile.iam.admin.services.cpi.error.ttypes.IamAdminServicesException as Idse:
+            msg_type = TMessageType.REPLY
+            result.Idse = Idse
+        except TApplicationException as ex:
+            logging.exception('TApplication exception in handler')
+            msg_type = TMessageType.EXCEPTION
+            result = ex
+        except Exception:
+            logging.exception('Unexpected exception in handler')
+            msg_type = TMessageType.EXCEPTION
+            result = TApplicationException(TApplicationException.INTERNAL_ERROR, 'Internal error')
+        oprot.writeMessageBegin("getUsers", msg_type, seqid)
+        result.write(oprot)
+        oprot.writeMessageEnd()
+        oprot.trans.flush()
+
+    def process_resetUserPassword(self, seqid, iprot, oprot):
+        args = resetUserPassword_args()
+        args.read(iprot)
+        iprot.readMessageEnd()
+        result = resetUserPassword_result()
+        try:
+            result.success = self._handler.resetUserPassword(args.authzToken, args.username, args.newPassword)
+            msg_type = TMessageType.REPLY
+        except TTransport.TTransportException:
+            raise
+        except custos.profile.iam.admin.services.cpi.error.ttypes.IamAdminServicesException as Idse:
+            msg_type = TMessageType.REPLY
+            result.Idse = Idse
+        except TApplicationException as ex:
+            logging.exception('TApplication exception in handler')
+            msg_type = TMessageType.EXCEPTION
+            result = ex
+        except Exception:
+            logging.exception('Unexpected exception in handler')
+            msg_type = TMessageType.EXCEPTION
+            result = TApplicationException(TApplicationException.INTERNAL_ERROR, 'Internal error')
+        oprot.writeMessageBegin("resetUserPassword", msg_type, seqid)
+        result.write(oprot)
+        oprot.writeMessageEnd()
+        oprot.trans.flush()
+
+    def process_findUsers(self, seqid, iprot, oprot):
+        args = findUsers_args()
+        args.read(iprot)
+        iprot.readMessageEnd()
+        result = findUsers_result()
+        try:
+            result.success = self._handler.findUsers(args.authzToken, args.email, args.userId)
+            msg_type = TMessageType.REPLY
+        except TTransport.TTransportException:
+            raise
+        except custos.profile.iam.admin.services.cpi.error.ttypes.IamAdminServicesException as Idse:
+            msg_type = TMessageType.REPLY
+            result.Idse = Idse
+        except TApplicationException as ex:
+            logging.exception('TApplication exception in handler')
+            msg_type = TMessageType.EXCEPTION
+            result = ex
+        except Exception:
+            logging.exception('Unexpected exception in handler')
+            msg_type = TMessageType.EXCEPTION
+            result = TApplicationException(TApplicationException.INTERNAL_ERROR, 'Internal error')
+        oprot.writeMessageBegin("findUsers", msg_type, seqid)
+        result.write(oprot)
+        oprot.writeMessageEnd()
+        oprot.trans.flush()
+
+    def process_updateUserProfile(self, seqid, iprot, oprot):
+        args = updateUserProfile_args()
+        args.read(iprot)
+        iprot.readMessageEnd()
+        result = updateUserProfile_result()
+        try:
+            self._handler.updateUserProfile(args.authzToken, args.userDetails)
+            msg_type = TMessageType.REPLY
+        except TTransport.TTransportException:
+            raise
+        except custos.profile.iam.admin.services.cpi.error.ttypes.IamAdminServicesException as Idse:
+            msg_type = TMessageType.REPLY
+            result.Idse = Idse
+        except TApplicationException as ex:
+            logging.exception('TApplication exception in handler')
+            msg_type = TMessageType.EXCEPTION
+            result = ex
+        except Exception:
+            logging.exception('Unexpected exception in handler')
+            msg_type = TMessageType.EXCEPTION
+            result = TApplicationException(TApplicationException.INTERNAL_ERROR, 'Internal error')
+        oprot.writeMessageBegin("updateUserProfile", msg_type, seqid)
+        result.write(oprot)
+        oprot.writeMessageEnd()
+        oprot.trans.flush()
+
+    def process_addRoleToUser(self, seqid, iprot, oprot):
+        args = addRoleToUser_args()
+        args.read(iprot)
+        iprot.readMessageEnd()
+        result = addRoleToUser_result()
+        try:
+            result.success = self._handler.addRoleToUser(args.authzToken, args.username, args.roleName, args.tenantAdminPasswordCredential)
+            msg_type = TMessageType.REPLY
+        except TTransport.TTransportException:
+            raise
+        except custos.profile.iam.admin.services.cpi.error.ttypes.IamAdminServicesException as Idse:
+            msg_type = TMessageType.REPLY
+            result.Idse = Idse
+        except TApplicationException as ex:
+            logging.exception('TApplication exception in handler')
+            msg_type = TMessageType.EXCEPTION
+            result = ex
+        except Exception:
+            logging.exception('Unexpected exception in handler')
+            msg_type = TMessageType.EXCEPTION
+            result = TApplicationException(TApplicationException.INTERNAL_ERROR, 'Internal error')
+        oprot.writeMessageBegin("addRoleToUser", msg_type, seqid)
+        result.write(oprot)
+        oprot.writeMessageEnd()
+        oprot.trans.flush()
+
+    def process_removeRoleFromUser(self, seqid, iprot, oprot):
+        args = removeRoleFromUser_args()
+        args.read(iprot)
+        iprot.readMessageEnd()
+        result = removeRoleFromUser_result()
+        try:
+            result.success = self._handler.removeRoleFromUser(args.authzToken, args.username, args.roleName, args.tenantAdminPasswordCredential)
+            msg_type = TMessageType.REPLY
+        except TTransport.TTransportException:
+            raise
+        except custos.profile.iam.admin.services.cpi.error.ttypes.IamAdminServicesException as Idse:
+            msg_type = TMessageType.REPLY
+            result.Idse = Idse
+        except TApplicationException as ex:
+            logging.exception('TApplication exception in handler')
+            msg_type = TMessageType.EXCEPTION
+            result = ex
+        except Exception:
+            logging.exception('Unexpected exception in handler')
+            msg_type = TMessageType.EXCEPTION
+            result = TApplicationException(TApplicationException.INTERNAL_ERROR, 'Internal error')
+        oprot.writeMessageBegin("removeRoleFromUser", msg_type, seqid)
+        result.write(oprot)
+        oprot.writeMessageEnd()
+        oprot.trans.flush()
+
+    def process_getUsersWithRole(self, seqid, iprot, oprot):
+        args = getUsersWithRole_args()
+        args.read(iprot)
+        iprot.readMessageEnd()
+        result = getUsersWithRole_result()
+        try:
+            result.success = self._handler.getUsersWithRole(args.authzToken, args.roleName, args.tenantAdminPasswordCredential)
+            msg_type = TMessageType.REPLY
+        except TTransport.TTransportException:
+            raise
+        except custos.profile.iam.admin.services.cpi.error.ttypes.IamAdminServicesException as Idse:
+            msg_type = TMessageType.REPLY
+            result.Idse = Idse
+        except TApplicationException as ex:
+            logging.exception('TApplication exception in handler')
+            msg_type = TMessageType.EXCEPTION
+            result = ex
+        except Exception:
+            logging.exception('Unexpected exception in handler')
+            msg_type = TMessageType.EXCEPTION
+            result = TApplicationException(TApplicationException.INTERNAL_ERROR, 'Internal error')
+        oprot.writeMessageBegin("getUsersWithRole", msg_type, seqid)
+        result.write(oprot)
+        oprot.writeMessageEnd()
+        oprot.trans.flush()
+
+# HELPER FUNCTIONS AND STRUCTURES
+
+
+class getAPIVersion_args(object):
+
+
+    def read(self, iprot):
+        if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None:
+            iprot._fast_decode(self, iprot, [self.__class__, self.thrift_spec])
+            return
+        iprot.readStructBegin()
+        while True:
+            (fname, ftype, fid) = iprot.readFieldBegin()
+            if ftype == TType.STOP:
+                break
+            else:
+                iprot.skip(ftype)
+            iprot.readFieldEnd()
+        iprot.readStructEnd()
+
+    def write(self, oprot):
+        if oprot._fast_encode is not None and self.thrift_spec is not None:
+            oprot.trans.write(oprot._fast_encode(self, [self.__class__, self.thrift_spec]))
+            return
+        oprot.writeStructBegin('getAPIVersion_args')
+        oprot.writeFieldStop()
+        oprot.writeStructEnd()
+
+    def validate(self):
+        return
+
+    def __repr__(self):
+        L = ['%s=%r' % (key, value)
+             for key, value in self.__dict__.items()]
+        return '%s(%s)' % (self.__class__.__name__, ', '.join(L))
+
+    def __eq__(self, other):
+        return isinstance(other, self.__class__) and self.__dict__ == other.__dict__
+
+    def __ne__(self, other):
+        return not (self == other)
+all_structs.append(getAPIVersion_args)
+getAPIVersion_args.thrift_spec = (
+)
+
+
+class getAPIVersion_result(object):
+    """
+    Attributes:
+     - success
+     - Idse
+
+    """
+
+
+    def __init__(self, success=None, Idse=None,):
+        self.success = success
+        self.Idse = Idse
+
+    def read(self, iprot):
+        if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None:
+            iprot._fast_decode(self, iprot, [self.__class__, self.thrift_spec])
+            return
+        iprot.readStructBegin()
+        while True:
+            (fname, ftype, fid) = iprot.readFieldBegin()
+            if ftype == TType.STOP:
+                break
+            if fid == 0:
+                if ftype == TType.STRING:
+                    self.success = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
+                else:
+                    iprot.skip(ftype)
+            elif fid == 1:
+                if ftype == TType.STRUCT:
+                    self.Idse = custos.profile.iam.admin.services.cpi.error.ttypes.IamAdminServicesException()
+                    self.Idse.read(iprot)
+                else:
+                    iprot.skip(ftype)
+            else:
+                iprot.skip(ftype)
+            iprot.readFieldEnd()
+        iprot.readStructEnd()
+
+    def write(self, oprot):
+        if oprot._fast_encode is not None and self.thrift_spec is not None:
+            oprot.trans.write(oprot._fast_encode(self, [self.__class__, self.thrift_spec]))
+            return
+        oprot.writeStructBegin('getAPIVersion_result')
+        if self.success is not None:
+            oprot.writeFieldBegin('success', TType.STRING, 0)
+            oprot.writeString(self.success.encode('utf-8') if sys.version_info[0] == 2 else self.success)
+            oprot.writeFieldEnd()
+        if self.Idse is not None:
+            oprot.writeFieldBegin('Idse', TType.STRUCT, 1)
+            self.Idse.write(oprot)
+            oprot.writeFieldEnd()
+        oprot.writeFieldStop()
+        oprot.writeStructEnd()
+
+    def validate(self):
+        return
+
+    def __repr__(self):
+        L = ['%s=%r' % (key, value)
+             for key, value in self.__dict__.items()]
+        return '%s(%s)' % (self.__class__.__name__, ', '.join(L))
+
+    def __eq__(self, other):
+        return isinstance(other, self.__class__) and self.__dict__ == other.__dict__
+
+    def __ne__(self, other):
+        return not (self == other)
+all_structs.append(getAPIVersion_result)
+getAPIVersion_result.thrift_spec = (
+    (0, TType.STRING, 'success', 'UTF8', None, ),  # 0
+    (1, TType.STRUCT, 'Idse', [custos.profile.iam.admin.services.cpi.error.ttypes.IamAdminServicesException, None], None, ),  # 1
+)
+
+
+class setUpGateway_args(object):
+    """
+    Attributes:
+     - authzToken
+     - gateway
+     - tenantAdminPasswordCredential
+
+    """
+
+
+    def __init__(self, authzToken=None, gateway=None, tenantAdminPasswordCredential=None,):
+        self.authzToken = authzToken
+        self.gateway = gateway
+        self.tenantAdminPasswordCredential = tenantAdminPasswordCredential
+
+    def read(self, iprot):
+        if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None:
+            iprot._fast_decode(self, iprot, [self.__class__, self.thrift_spec])
+            return
+        iprot.readStructBegin()
+        while True:
+            (fname, ftype, fid) = iprot.readFieldBegin()
+            if ftype == TType.STOP:
+                break
+            if fid == 1:
+                if ftype == TType.STRUCT:
+                    self.authzToken = custos.commons.model.security.ttypes.AuthzToken()
+                    self.authzToken.read(iprot)
+                else:
+                    iprot.skip(ftype)
+            elif fid == 2:
+                if ftype == TType.STRUCT:
+                    self.gateway = custos.profile.model.workspace.ttypes.Gateway()
+                    self.gateway.read(iprot)
+                else:
+                    iprot.skip(ftype)
+            elif fid == 3:
+                if ftype == TType.STRUCT:
+                    self.tenantAdminPasswordCredential = custos.profile.model.tenant.ttypes.PasswordCredential()
+                    self.tenantAdminPasswordCredential.read(iprot)
+                else:
+                    iprot.skip(ftype)
+            else:
+                iprot.skip(ftype)
+            iprot.readFieldEnd()
+        iprot.readStructEnd()
+
+    def write(self, oprot):
+        if oprot._fast_encode is not None and self.thrift_spec is not None:
+            oprot.trans.write(oprot._fast_encode(self, [self.__class__, self.thrift_spec]))
+            return
+        oprot.writeStructBegin('setUpGateway_args')
+        if self.authzToken is not None:
+            oprot.writeFieldBegin('authzToken', TType.STRUCT, 1)
+            self.authzToken.write(oprot)
+            oprot.writeFieldEnd()
+        if self.gateway is not None:
+            oprot.writeFieldBegin('gateway', TType.STRUCT, 2)
+            self.gateway.write(oprot)
+            oprot.writeFieldEnd()
+        if self.tenantAdminPasswordCredential is not None:
+            oprot.writeFieldBegin('tenantAdminPasswordCredential', TType.STRUCT, 3)
+            self.tenantAdminPasswordCredential.write(oprot)
+            oprot.writeFieldEnd()
+        oprot.writeFieldStop()
+        oprot.writeStructEnd()
+
+    def validate(self):
+        if self.authzToken is None:
+            raise TProtocolException(message='Required field authzToken is unset!')
+        if self.gateway is None:
+            raise TProtocolException(message='Required field gateway is unset!')
+        if self.tenantAdminPasswordCredential is None:
+            raise TProtocolException(message='Required field tenantAdminPasswordCredential is unset!')
+        return
+
+    def __repr__(self):
+        L = ['%s=%r' % (key, value)
+             for key, value in self.__dict__.items()]
+        return '%s(%s)' % (self.__class__.__name__, ', '.join(L))
+
+    def __eq__(self, other):
+        return isinstance(other, self.__class__) and self.__dict__ == other.__dict__
+
+    def __ne__(self, other):
+        return not (self == other)
+all_structs.append(setUpGateway_args)
+setUpGateway_args.thrift_spec = (
+    None,  # 0
+    (1, TType.STRUCT, 'authzToken', [custos.commons.model.security.ttypes.AuthzToken, None], None, ),  # 1
+    (2, TType.STRUCT, 'gateway', [custos.profile.model.workspace.ttypes.Gateway, None], None, ),  # 2
+    (3, TType.STRUCT, 'tenantAdminPasswordCredential', [custos.profile.model.tenant.ttypes.PasswordCredential, None], None, ),  # 3
+)
+
+
+class setUpGateway_result(object):
+    """
+    Attributes:
+     - success
+     - Idse
+
+    """
+
+
+    def __init__(self, success=None, Idse=None,):
+        self.success = success
+        self.Idse = Idse
+
+    def read(self, iprot):
+        if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None:
+            iprot._fast_decode(self, iprot, [self.__class__, self.thrift_spec])
+            return
+        iprot.readStructBegin()
+        while True:
+            (fname, ftype, fid) = iprot.readFieldBegin()
+            if ftype == TType.STOP:
+                break
+            if fid == 0:
+                if ftype == TType.STRUCT:
+                    self.success = custos.profile.model.workspace.ttypes.Gateway()
+                    self.success.read(iprot)
+                else:
+                    iprot.skip(ftype)
+            elif fid == 1:
+                if ftype == TType.STRUCT:
+                    self.Idse = custos.profile.iam.admin.services.cpi.error.ttypes.IamAdminServicesException()
+                    self.Idse.read(iprot)
+                else:
+                    iprot.skip(ftype)
+            else:
+                iprot.skip(ftype)
+            iprot.readFieldEnd()
+        iprot.readStructEnd()
+
+    def write(self, oprot):
+        if oprot._fast_encode is not None and self.thrift_spec is not None:
+            oprot.trans.write(oprot._fast_encode(self, [self.__class__, self.thrift_spec]))
+            return
+        oprot.writeStructBegin('setUpGateway_result')
+        if self.success is not None:
+            oprot.writeFieldBegin('success', TType.STRUCT, 0)
+            self.success.write(oprot)
+            oprot.writeFieldEnd()
+        if self.Idse is not None:
+            oprot.writeFieldBegin('Idse', TType.STRUCT, 1)
+            self.Idse.write(oprot)
+            oprot.writeFieldEnd()
+        oprot.writeFieldStop()
+        oprot.writeStructEnd()
+
+    def validate(self):
+        return
+
+    def __repr__(self):
+        L = ['%s=%r' % (key, value)
+             for key, value in self.__dict__.items()]
+        return '%s(%s)' % (self.__class__.__name__, ', '.join(L))
+
+    def __eq__(self, other):
+        return isinstance(other, self.__class__) and self.__dict__ == other.__dict__
+
+    def __ne__(self, other):
+        return not (self == other)
+all_structs.append(setUpGateway_result)
+setUpGateway_result.thrift_spec = (
+    (0, TType.STRUCT, 'success', [custos.profile.model.workspace.ttypes.Gateway, None], None, ),  # 0
+    (1, TType.STRUCT, 'Idse', [custos.profile.iam.admin.services.cpi.error.ttypes.IamAdminServicesException, None], None, ),  # 1
+)
+
+
+class isUsernameAvailable_args(object):
+    """
+    Attributes:
+     - authzToken
+     - username
+
+    """
+
+
+    def __init__(self, authzToken=None, username=None,):
+        self.authzToken = authzToken
+        self.username = username
+
+    def read(self, iprot):
+        if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None:
+            iprot._fast_decode(self, iprot, [self.__class__, self.thrift_spec])
+            return
+        iprot.readStructBegin()
+        while True:
+            (fname, ftype, fid) = iprot.readFieldBegin()
+            if ftype == TType.STOP:
+                break
+            if fid == 1:
+                if ftype == TType.STRUCT:
+                    self.authzToken = custos.commons.model.security.ttypes.AuthzToken()
+                    self.authzToken.read(iprot)
+                else:
+                    iprot.skip(ftype)
+            elif fid == 2:
+                if ftype == TType.STRING:
+                    self.username = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
+                else:
+                    iprot.skip(ftype)
+            else:
+                iprot.skip(ftype)
+            iprot.readFieldEnd()
+        iprot.readStructEnd()
+
+    def write(self, oprot):
+        if oprot._fast_encode is not None and self.thrift_spec is not None:
+            oprot.trans.write(oprot._fast_encode(self, [self.__class__, self.thrift_spec]))
+            return
+        oprot.writeStructBegin('isUsernameAvailable_args')
+        if self.authzToken is not None:
+            oprot.writeFieldBegin('authzToken', TType.STRUCT, 1)
+            self.authzToken.write(oprot)
+            oprot.writeFieldEnd()
+        if self.username is not None:
+            oprot.writeFieldBegin('username', TType.STRING, 2)
+            oprot.writeString(self.username.encode('utf-8') if sys.version_info[0] == 2 else self.username)
+            oprot.writeFieldEnd()
+        oprot.writeFieldStop()
+        oprot.writeStructEnd()
+
+    def validate(self):
+        if self.authzToken is None:
+            raise TProtocolException(message='Required field authzToken is unset!')
+        if self.username is None:
+            raise TProtocolException(message='Required field username is unset!')
+        return
+
+    def __repr__(self):
+        L = ['%s=%r' % (key, value)
+             for key, value in self.__dict__.items()]
+        return '%s(%s)' % (self.__class__.__name__, ', '.join(L))
+
+    def __eq__(self, other):
+        return isinstance(other, self.__class__) and self.__dict__ == other.__dict__
+
+    def __ne__(self, other):
+        return not (self == other)
+all_structs.append(isUsernameAvailable_args)
+isUsernameAvailable_args.thrift_spec = (
+    None,  # 0
+    (1, TType.STRUCT, 'authzToken', [custos.commons.model.security.ttypes.AuthzToken, None], None, ),  # 1
+    (2, TType.STRING, 'username', 'UTF8', None, ),  # 2
+)
+
+
+class isUsernameAvailable_result(object):
+    """
+    Attributes:
+     - success
+     - Idse
+
+    """
+
+
+    def __init__(self, success=None, Idse=None,):
+        self.success = success
+        self.Idse = Idse
+
+    def read(self, iprot):
+        if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None:
+            iprot._fast_decode(self, iprot, [self.__class__, self.thrift_spec])
+            return
+        iprot.readStructBegin()
+        while True:
+            (fname, ftype, fid) = iprot.readFieldBegin()
+            if ftype == TType.STOP:
+                break
+            if fid == 0:
+                if ftype == TType.BOOL:
+                    self.success = iprot.readBool()
+                else:
+                    iprot.skip(ftype)
+            elif fid == 1:
+                if ftype == TType.STRUCT:
+                    self.Idse = custos.profile.iam.admin.services.cpi.error.ttypes.IamAdminServicesException()
+                    self.Idse.read(iprot)
+                else:
+                    iprot.skip(ftype)
+            else:
+                iprot.skip(ftype)
+            iprot.readFieldEnd()
+        iprot.readStructEnd()
+
+    def write(self, oprot):
+        if oprot._fast_encode is not None and self.thrift_spec is not None:
+            oprot.trans.write(oprot._fast_encode(self, [self.__class__, self.thrift_spec]))
+            return
+        oprot.writeStructBegin('isUsernameAvailable_result')
+        if self.success is not None:
+            oprot.writeFieldBegin('success', TType.BOOL, 0)
+            oprot.writeBool(self.success)
+            oprot.writeFieldEnd()
+        if self.Idse is not None:
+            oprot.writeFieldBegin('Idse', TType.STRUCT, 1)
+            self.Idse.write(oprot)
+            oprot.writeFieldEnd()
+        oprot.writeFieldStop()
+        oprot.writeStructEnd()
+
+    def validate(self):
+        return
+
+    def __repr__(self):
+        L = ['%s=%r' % (key, value)
+             for key, value in self.__dict__.items()]
+        return '%s(%s)' % (self.__class__.__name__, ', '.join(L))
+
+    def __eq__(self, other):
+        return isinstance(other, self.__class__) and self.__dict__ == other.__dict__
+
+    def __ne__(self, other):
+        return not (self == other)
+all_structs.append(isUsernameAvailable_result)
+isUsernameAvailable_result.thrift_spec = (
+    (0, TType.BOOL, 'success', None, None, ),  # 0
+    (1, TType.STRUCT, 'Idse', [custos.profile.iam.admin.services.cpi.error.ttypes.IamAdminServicesException, None], None, ),  # 1
+)
+
+
+class registerUser_args(object):
+    """
+    Attributes:
+     - authzToken
+     - username
+     - emailAddress
+     - firstName
+     - lastName
+     - newPassword
+
+    """
+
+
+    def __init__(self, authzToken=None, username=None, emailAddress=None, firstName=None, lastName=None, newPassword=None,):
+        self.authzToken = authzToken
+        self.username = username
+        self.emailAddress = emailAddress
+        self.firstName = firstName
+        self.lastName = lastName
+        self.newPassword = newPassword
+
+    def read(self, iprot):
+        if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None:
+            iprot._fast_decode(self, iprot, [self.__class__, self.thrift_spec])
+            return
+        iprot.readStructBegin()
+        while True:
+            (fname, ftype, fid) = iprot.readFieldBegin()
+            if ftype == TType.STOP:
+                break
+            if fid == 1:
+                if ftype == TType.STRUCT:
+                    self.authzToken = custos.commons.model.security.ttypes.AuthzToken()
+                    self.authzToken.read(iprot)
+                else:
+                    iprot.skip(ftype)
+            elif fid == 2:
+                if ftype == TType.STRING:
+                    self.username = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
+                else:
+                    iprot.skip(ftype)
+            elif fid == 3:
+                if ftype == TType.STRING:
+                    self.emailAddress = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
+                else:
+                    iprot.skip(ftype)
+            elif fid == 4:
+                if ftype == TType.STRING:
+                    self.firstName = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
+                else:
+                    iprot.skip(ftype)
+            elif fid == 5:
+                if ftype == TType.STRING:
+                    self.lastName = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
+                else:
+                    iprot.skip(ftype)
+            elif fid == 6:
+                if ftype == TType.STRING:
+                    self.newPassword = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
+                else:
+                    iprot.skip(ftype)
+            else:
+                iprot.skip(ftype)
+            iprot.readFieldEnd()
+        iprot.readStructEnd()
+
+    def write(self, oprot):
+        if oprot._fast_encode is not None and self.thrift_spec is not None:
+            oprot.trans.write(oprot._fast_encode(self, [self.__class__, self.thrift_spec]))
+            return
+        oprot.writeStructBegin('registerUser_args')
+        if self.authzToken is not None:
+            oprot.writeFieldBegin('authzToken', TType.STRUCT, 1)
+            self.authzToken.write(oprot)
+            oprot.writeFieldEnd()
+        if self.username is not None:
+            oprot.writeFieldBegin('username', TType.STRING, 2)
+            oprot.writeString(self.username.encode('utf-8') if sys.version_info[0] == 2 else self.username)
+            oprot.writeFieldEnd()
+        if self.emailAddress is not None:
+            oprot.writeFieldBegin('emailAddress', TType.STRING, 3)
+            oprot.writeString(self.emailAddress.encode('utf-8') if sys.version_info[0] == 2 else self.emailAddress)
+            oprot.writeFieldEnd()
+        if self.firstName is not None:
+            oprot.writeFieldBegin('firstName', TType.STRING, 4)
+            oprot.writeString(self.firstName.encode('utf-8') if sys.version_info[0] == 2 else self.firstName)
+            oprot.writeFieldEnd()
+        if self.lastName is not None:
+            oprot.writeFieldBegin('lastName', TType.STRING, 5)
+            oprot.writeString(self.lastName.encode('utf-8') if sys.version_info[0] == 2 else self.lastName)
+            oprot.writeFieldEnd()
+        if self.newPassword is not None:
+            oprot.writeFieldBegin('newPassword', TType.STRING, 6)
+            oprot.writeString(self.newPassword.encode('utf-8') if sys.version_info[0] == 2 else self.newPassword)
+            oprot.writeFieldEnd()
+        oprot.writeFieldStop()
+        oprot.writeStructEnd()
+
+    def validate(self):
+        if self.authzToken is None:
+            raise TProtocolException(message='Required field authzToken is unset!')
+        if self.username is None:
+            raise TProtocolException(message='Required field username is unset!')
+        if self.emailAddress is None:
+            raise TProtocolException(message='Required field emailAddress is unset!')
+        if self.firstName is None:
+            raise TProtocolException(message='Required field firstName is unset!')
+        if self.lastName is None:
+            raise TProtocolException(message='Required field lastName is unset!')
+        if self.newPassword is None:
+            raise TProtocolException(message='Required field newPassword is unset!')
+        return
+
+    def __repr__(self):
+        L = ['%s=%r' % (key, value)
+             for key, value in self.__dict__.items()]
+        return '%s(%s)' % (self.__class__.__name__, ', '.join(L))
+
+    def __eq__(self, other):
+        return isinstance(other, self.__class__) and self.__dict__ == other.__dict__
+
+    def __ne__(self, other):
+        return not (self == other)
+all_structs.append(registerUser_args)
+registerUser_args.thrift_spec = (
+    None,  # 0
+    (1, TType.STRUCT, 'authzToken', [custos.commons.model.security.ttypes.AuthzToken, None], None, ),  # 1
+    (2, TType.STRING, 'username', 'UTF8', None, ),  # 2
+    (3, TType.STRING, 'emailAddress', 'UTF8', None, ),  # 3
+    (4, TType.STRING, 'firstName', 'UTF8', None, ),  # 4
+    (5, TType.STRING, 'lastName', 'UTF8', None, ),  # 5
+    (6, TType.STRING, 'newPassword', 'UTF8', None, ),  # 6
+)
+
+
+class registerUser_result(object):
+    """
+    Attributes:
+     - success
+     - Idse
+
+    """
+
+
+    def __init__(self, success=None, Idse=None,):
+        self.success = success
+        self.Idse = Idse
+
+    def read(self, iprot):
+        if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None:
+            iprot._fast_decode(self, iprot, [self.__class__, self.thrift_spec])
+            return
+        iprot.readStructBegin()
+        while True:
+            (fname, ftype, fid) = iprot.readFieldBegin()
+            if ftype == TType.STOP:
+                break
+            if fid == 0:
+                if ftype == TType.BOOL:
+                    self.success = iprot.readBool()
+                else:
+                    iprot.skip(ftype)
+            elif fid == 1:
+                if ftype == TType.STRUCT:
+                    self.Idse = custos.profile.iam.admin.services.cpi.error.ttypes.IamAdminServicesException()
+                    self.Idse.read(iprot)
+                else:
+                    iprot.skip(ftype)
+            else:
+                iprot.skip(ftype)
+            iprot.readFieldEnd()
+        iprot.readStructEnd()
+
+    def write(self, oprot):
+        if oprot._fast_encode is not None and self.thrift_spec is not None:
+            oprot.trans.write(oprot._fast_encode(self, [self.__class__, self.thrift_spec]))
+            return
+        oprot.writeStructBegin('registerUser_result')
+        if self.success is not None:
+            oprot.writeFieldBegin('success', TType.BOOL, 0)
+            oprot.writeBool(self.success)
+            oprot.writeFieldEnd()
+        if self.Idse is not None:
+            oprot.writeFieldBegin('Idse', TType.STRUCT, 1)
+            self.Idse.write(oprot)
+            oprot.writeFieldEnd()
+        oprot.writeFieldStop()
+        oprot.writeStructEnd()
+
+    def validate(self):
+        return
+
+    def __repr__(self):
+        L = ['%s=%r' % (key, value)
+             for key, value in self.__dict__.items()]
+        return '%s(%s)' % (self.__class__.__name__, ', '.join(L))
+
+    def __eq__(self, other):
+        return isinstance(other, self.__class__) and self.__dict__ == other.__dict__
+
+    def __ne__(self, other):
+        return not (self == other)
+all_structs.append(registerUser_result)
+registerUser_result.thrift_spec = (
+    (0, TType.BOOL, 'success', None, None, ),  # 0
+    (1, TType.STRUCT, 'Idse', [custos.profile.iam.admin.services.cpi.error.ttypes.IamAdminServicesException, None], None, ),  # 1
+)
+
+
+class deleteUser_args(object):
+    """
+    Attributes:
+     - authzToken
+     - username
+
+    """
+
+
+    def __init__(self, authzToken=None, username=None,):
+        self.authzToken = authzToken
+        self.username = username
+
+    def read(self, iprot):
+        if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None:
+            iprot._fast_decode(self, iprot, [self.__class__, self.thrift_spec])
+            return
+        iprot.readStructBegin()
+        while True:
+            (fname, ftype, fid) = iprot.readFieldBegin()
+            if ftype == TType.STOP:
+                break
+            if fid == 1:
+                if ftype == TType.STRUCT:
+                    self.authzToken = custos.commons.model.security.ttypes.AuthzToken()
+                    self.authzToken.read(iprot)
+                else:
+                    iprot.skip(ftype)
+            elif fid == 2:
+                if ftype == TType.STRING:
+                    self.username = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
+                else:
+                    iprot.skip(ftype)
+            else:
+                iprot.skip(ftype)
+            iprot.readFieldEnd()
+        iprot.readStructEnd()
+
+    def write(self, oprot):
+        if oprot._fast_encode is not None and self.thrift_spec is not None:
+            oprot.trans.write(oprot._fast_encode(self, [self.__class__, self.thrift_spec]))
+            return
+        oprot.writeStructBegin('deleteUser_args')
+        if self.authzToken is not None:
+            oprot.writeFieldBegin('authzToken', TType.STRUCT, 1)
+            self.authzToken.write(oprot)
+            oprot.writeFieldEnd()
+        if self.username is not None:
+            oprot.writeFieldBegin('username', TType.STRING, 2)
+            oprot.writeString(self.username.encode('utf-8') if sys.version_info[0] == 2 else self.username)
+            oprot.writeFieldEnd()
+        oprot.writeFieldStop()
+        oprot.writeStructEnd()
+
+    def validate(self):
+        if self.authzToken is None:
+            raise TProtocolException(message='Required field authzToken is unset!')
+        if self.username is None:
+            raise TProtocolException(message='Required field username is unset!')
+        return
+
+    def __repr__(self):
+        L = ['%s=%r' % (key, value)
+             for key, value in self.__dict__.items()]
+        return '%s(%s)' % (self.__class__.__name__, ', '.join(L))
+
+    def __eq__(self, other):
+        return isinstance(other, self.__class__) and self.__dict__ == other.__dict__
+
+    def __ne__(self, other):
+        return not (self == other)
+all_structs.append(deleteUser_args)
+deleteUser_args.thrift_spec = (
+    None,  # 0
+    (1, TType.STRUCT, 'authzToken', [custos.commons.model.security.ttypes.AuthzToken, None], None, ),  # 1
+    (2, TType.STRING, 'username', 'UTF8', None, ),  # 2
+)
+
+
+class deleteUser_result(object):
+    """
+    Attributes:
+     - success
+     - Idse
+
+    """
+
+
+    def __init__(self, success=None, Idse=None,):
+        self.success = success
+        self.Idse = Idse
+
+    def read(self, iprot):
+        if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None:
+            iprot._fast_decode(self, iprot, [self.__class__, self.thrift_spec])
+            return
+        iprot.readStructBegin()
+        while True:
+            (fname, ftype, fid) = iprot.readFieldBegin()
+            if ftype == TType.STOP:
+                break
+            if fid == 0:
+                if ftype == TType.BOOL:
+                    self.success = iprot.readBool()
+                else:
+                    iprot.skip(ftype)
+            elif fid == 1:
+                if ftype == TType.STRUCT:
+                    self.Idse = custos.profile.iam.admin.services.cpi.error.ttypes.IamAdminServicesException()
+                    self.Idse.read(iprot)
+                else:
+                    iprot.skip(ftype)
+            else:
+                iprot.skip(ftype)
+            iprot.readFieldEnd()
+        iprot.readStructEnd()
+
+    def write(self, oprot):
+        if oprot._fast_encode is not None and self.thrift_spec is not None:
+            oprot.trans.write(oprot._fast_encode(self, [self.__class__, self.thrift_spec]))
+            return
+        oprot.writeStructBegin('deleteUser_result')
+        if self.success is not None:
+            oprot.writeFieldBegin('success', TType.BOOL, 0)
+            oprot.writeBool(self.success)
+            oprot.writeFieldEnd()
+        if self.Idse is not None:
+            oprot.writeFieldBegin('Idse', TType.STRUCT, 1)
+            self.Idse.write(oprot)
+            oprot.writeFieldEnd()
+        oprot.writeFieldStop()
+        oprot.writeStructEnd()
+
+    def validate(self):
+        return
+
+    def __repr__(self):
+        L = ['%s=%r' % (key, value)
+             for key, value in self.__dict__.items()]
+        return '%s(%s)' % (self.__class__.__name__, ', '.join(L))
+
+    def __eq__(self, other):
+        return isinstance(other, self.__class__) and self.__dict__ == other.__dict__
+
+    def __ne__(self, other):
+        return not (self == other)
+all_structs.append(deleteUser_result)
+deleteUser_result.thrift_spec = (
+    (0, TType.BOOL, 'success', None, None, ),  # 0
+    (1, TType.STRUCT, 'Idse', [custos.profile.iam.admin.services.cpi.error.ttypes.IamAdminServicesException, None], None, ),  # 1
+)
+
+
+class enableUser_args(object):
+    """
+    Attributes:
+     - authzToken
+     - username
+
+    """
+
+
+    def __init__(self, authzToken=None, username=None,):
+        self.authzToken = authzToken
+        self.username = username
+
+    def read(self, iprot):
+        if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None:
+            iprot._fast_decode(self, iprot, [self.__class__, self.thrift_spec])
+            return
+        iprot.readStructBegin()
+        while True:
+            (fname, ftype, fid) = iprot.readFieldBegin()
+            if ftype == TType.STOP:
+                break
+            if fid == 1:
+                if ftype == TType.STRUCT:
+                    self.authzToken = custos.commons.model.security.ttypes.AuthzToken()
+                    self.authzToken.read(iprot)
+                else:
+                    iprot.skip(ftype)
+            elif fid == 2:
+                if ftype == TType.STRING:
+                    self.username = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
+                else:
+                    iprot.skip(ftype)
+            else:
+                iprot.skip(ftype)
+            iprot.readFieldEnd()
+        iprot.readStructEnd()
+
+    def write(self, oprot):
+        if oprot._fast_encode is not None and self.thrift_spec is not None:
+            oprot.trans.write(oprot._fast_encode(self, [self.__class__, self.thrift_spec]))
+            return
+        oprot.writeStructBegin('enableUser_args')
+        if self.authzToken is not None:
+            oprot.writeFieldBegin('authzToken', TType.STRUCT, 1)
+            self.authzToken.write(oprot)
+            oprot.writeFieldEnd()
+        if self.username is not None:
+            oprot.writeFieldBegin('username', TType.STRING, 2)
+            oprot.writeString(self.username.encode('utf-8') if sys.version_info[0] == 2 else self.username)
+            oprot.writeFieldEnd()
+        oprot.writeFieldStop()
+        oprot.writeStructEnd()
+
+    def validate(self):
+        if self.authzToken is None:
+            raise TProtocolException(message='Required field authzToken is unset!')
+        if self.username is None:
+            raise TProtocolException(message='Required field username is unset!')
+        return
+
+    def __repr__(self):
+        L = ['%s=%r' % (key, value)
+             for key, value in self.__dict__.items()]
+        return '%s(%s)' % (self.__class__.__name__, ', '.join(L))
+
+    def __eq__(self, other):
+        return isinstance(other, self.__class__) and self.__dict__ == other.__dict__
+
+    def __ne__(self, other):
+        return not (self == other)
+all_structs.append(enableUser_args)
+enableUser_args.thrift_spec = (
+    None,  # 0
+    (1, TType.STRUCT, 'authzToken', [custos.commons.model.security.ttypes.AuthzToken, None], None, ),  # 1
+    (2, TType.STRING, 'username', 'UTF8', None, ),  # 2
+)
+
+
+class enableUser_result(object):
+    """
+    Attributes:
+     - success
+     - Idse
+
+    """
+
+
+    def __init__(self, success=None, Idse=None,):
+        self.success = success
+        self.Idse = Idse
+
+    def read(self, iprot):
+        if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None:
+            iprot._fast_decode(self, iprot, [self.__class__, self.thrift_spec])
+            return
+        iprot.readStructBegin()
+        while True:
+            (fname, ftype, fid) = iprot.readFieldBegin()
+            if ftype == TType.STOP:
+                break
+            if fid == 0:
+                if ftype == TType.STRUCT:
+                    self.success = custos.profile.model.User.ttypes.UserProfile()
+                    self.success.read(iprot)
+                else:
+                    iprot.skip(ftype)
+            elif fid == 1:
+                if ftype == TType.STRUCT:
+                    self.Idse = custos.profile.iam.admin.services.cpi.error.ttypes.IamAdminServicesException()
+                    self.Idse.read(iprot)
+                else:
+                    iprot.skip(ftype)
+            else:
+                iprot.skip(ftype)
+            iprot.readFieldEnd()
+        iprot.readStructEnd()
+
+    def write(self, oprot):
+        if oprot._fast_encode is not None and self.thrift_spec is not None:
+            oprot.trans.write(oprot._fast_encode(self, [self.__class__, self.thrift_spec]))
+            return
+        oprot.writeStructBegin('enableUser_result')
+        if self.success is not None:
+            oprot.writeFieldBegin('success', TType.STRUCT, 0)
+            self.success.write(oprot)
+            oprot.writeFieldEnd()
+        if self.Idse is not None:
+            oprot.writeFieldBegin('Idse', TType.STRUCT, 1)
+            self.Idse.write(oprot)
+            oprot.writeFieldEnd()
+        oprot.writeFieldStop()
+        oprot.writeStructEnd()
+
+    def validate(self):
+        return
+
+    def __repr__(self):
+        L = ['%s=%r' % (key, value)
+             for key, value in self.__dict__.items()]
+        return '%s(%s)' % (self.__class__.__name__, ', '.join(L))
+
+    def __eq__(self, other):
+        return isinstance(other, self.__class__) and self.__dict__ == other.__dict__
+
+    def __ne__(self, other):
+        return not (self == other)
+all_structs.append(enableUser_result)
+enableUser_result.thrift_spec = (
+    (0, TType.STRUCT, 'success', [custos.profile.model.User.ttypes.UserProfile, None], None, ),  # 0
+    (1, TType.STRUCT, 'Idse', [custos.profile.iam.admin.services.cpi.error.ttypes.IamAdminServicesException, None], None, ),  # 1
+)
+
+
+class isUserEnabled_args(object):
+    """
+    Attributes:
+     - authzToken
+     - username
+
+    """
+
+
+    def __init__(self, authzToken=None, username=None,):
+        self.authzToken = authzToken
+        self.username = username
+
+    def read(self, iprot):
+        if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None:
+            iprot._fast_decode(self, iprot, [self.__class__, self.thrift_spec])
+            return
+        iprot.readStructBegin()
+        while True:
+            (fname, ftype, fid) = iprot.readFieldBegin()
+            if ftype == TType.STOP:
+                break
+            if fid == 1:
+                if ftype == TType.STRUCT:
+                    self.authzToken = custos.commons.model.security.ttypes.AuthzToken()
+                    self.authzToken.read(iprot)
+                else:
+                    iprot.skip(ftype)
+            elif fid == 2:
+                if ftype == TType.STRING:
+                    self.username = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
+                else:
+                    iprot.skip(ftype)
+            else:
+                iprot.skip(ftype)
+            iprot.readFieldEnd()
+        iprot.readStructEnd()
+
+    def write(self, oprot):
+        if oprot._fast_encode is not None and self.thrift_spec is not None:
+            oprot.trans.write(oprot._fast_encode(self, [self.__class__, self.thrift_spec]))
+            return
+        oprot.writeStructBegin('isUserEnabled_args')
+        if self.authzToken is not None:
+            oprot.writeFieldBegin('authzToken', TType.STRUCT, 1)
+            self.authzToken.write(oprot)
+            oprot.writeFieldEnd()
+        if self.username is not None:
+            oprot.writeFieldBegin('username', TType.STRING, 2)
+            oprot.writeString(self.username.encode('utf-8') if sys.version_info[0] == 2 else self.username)
+            oprot.writeFieldEnd()
+        oprot.writeFieldStop()
+        oprot.writeStructEnd()
+
+    def validate(self):
+        if self.authzToken is None:
+            raise TProtocolException(message='Required field authzToken is unset!')
+        if self.username is None:
+            raise TProtocolException(message='Required field username is unset!')
+        return
+
+    def __repr__(self):
+        L = ['%s=%r' % (key, value)
+             for key, value in self.__dict__.items()]
+        return '%s(%s)' % (self.__class__.__name__, ', '.join(L))
+
+    def __eq__(self, other):
+        return isinstance(other, self.__class__) and self.__dict__ == other.__dict__
+
+    def __ne__(self, other):
+        return not (self == other)
+all_structs.append(isUserEnabled_args)
+isUserEnabled_args.thrift_spec = (
+    None,  # 0
+    (1, TType.STRUCT, 'authzToken', [custos.commons.model.security.ttypes.AuthzToken, None], None, ),  # 1
+    (2, TType.STRING, 'username', 'UTF8', None, ),  # 2
+)
+
+
+class isUserEnabled_result(object):
+    """
+    Attributes:
+     - success
+     - Idse
+
+    """
+
+
+    def __init__(self, success=None, Idse=None,):
+        self.success = success
+        self.Idse = Idse
+
+    def read(self, iprot):
+        if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None:
+            iprot._fast_decode(self, iprot, [self.__class__, self.thrift_spec])
+            return
+        iprot.readStructBegin()
+        while True:
+            (fname, ftype, fid) = iprot.readFieldBegin()
+            if ftype == TType.STOP:
+                break
+            if fid == 0:
+                if ftype == TType.BOOL:
+                    self.success = iprot.readBool()
+                else:
+                    iprot.skip(ftype)
+            elif fid == 1:
+                if ftype == TType.STRUCT:
+                    self.Idse = custos.profile.iam.admin.services.cpi.error.ttypes.IamAdminServicesException()
+                    self.Idse.read(iprot)
+                else:
+                    iprot.skip(ftype)
+            else:
+                iprot.skip(ftype)
+            iprot.readFieldEnd()
+        iprot.readStructEnd()
+
+    def write(self, oprot):
+        if oprot._fast_encode is not None and self.thrift_spec is not None:
+            oprot.trans.write(oprot._fast_encode(self, [self.__class__, self.thrift_spec]))
+            return
+        oprot.writeStructBegin('isUserEnabled_result')
+        if self.success is not None:
+            oprot.writeFieldBegin('success', TType.BOOL, 0)
+            oprot.writeBool(self.success)
+            oprot.writeFieldEnd()
+        if self.Idse is not None:
+            oprot.writeFieldBegin('Idse', TType.STRUCT, 1)
+            self.Idse.write(oprot)
+            oprot.writeFieldEnd()
+        oprot.writeFieldStop()
+        oprot.writeStructEnd()
+
+    def validate(self):
+        return
+
+    def __repr__(self):
+        L = ['%s=%r' % (key, value)
+             for key, value in self.__dict__.items()]
+        return '%s(%s)' % (self.__class__.__name__, ', '.join(L))
+
+    def __eq__(self, other):
+        return isinstance(other, self.__class__) and self.__dict__ == other.__dict__
+
+    def __ne__(self, other):
+        return not (self == other)
+all_structs.append(isUserEnabled_result)
+isUserEnabled_result.thrift_spec = (
+    (0, TType.BOOL, 'success', None, None, ),  # 0
+    (1, TType.STRUCT, 'Idse', [custos.profile.iam.admin.services.cpi.error.ttypes.IamAdminServicesException, None], None, ),  # 1
+)
+
+
+class isUserExist_args(object):
+    """
+    Attributes:
+     - authzToken
+     - username
+
+    """
+
+
+    def __init__(self, authzToken=None, username=None,):
+        self.authzToken = authzToken
+        self.username = username
+
+    def read(self, iprot):
+        if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None:
+            iprot._fast_decode(self, iprot, [self.__class__, self.thrift_spec])
+            return
+        iprot.readStructBegin()
+        while True:
+            (fname, ftype, fid) = iprot.readFieldBegin()
+            if ftype == TType.STOP:
+                break
+            if fid == 1:
+                if ftype == TType.STRUCT:
+                    self.authzToken = custos.commons.model.security.ttypes.AuthzToken()
+                    self.authzToken.read(iprot)
+                else:
+                    iprot.skip(ftype)
+            elif fid == 2:
+                if ftype == TType.STRING:
+                    self.username = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
+                else:
+                    iprot.skip(ftype)
+            else:
+                iprot.skip(ftype)
+            iprot.readFieldEnd()
+        iprot.readStructEnd()
+
+    def write(self, oprot):
+        if oprot._fast_encode is not None and self.thrift_spec is not None:
+            oprot.trans.write(oprot._fast_encode(self, [self.__class__, self.thrift_spec]))
+            return
+        oprot.writeStructBegin('isUserExist_args')
+        if self.authzToken is not None:
+            oprot.writeFieldBegin('authzToken', TType.STRUCT, 1)
+            self.authzToken.write(oprot)
+            oprot.writeFieldEnd()
+        if self.username is not None:
+            oprot.writeFieldBegin('username', TType.STRING, 2)
+            oprot.writeString(self.username.encode('utf-8') if sys.version_info[0] == 2 else self.username)
+            oprot.writeFieldEnd()
+        oprot.writeFieldStop()
+        oprot.writeStructEnd()
+
+    def validate(self):
+        if self.authzToken is None:
+            raise TProtocolException(message='Required field authzToken is unset!')
+        if self.username is None:
+            raise TProtocolException(message='Required field username is unset!')
+        return
+
+    def __repr__(self):
+        L = ['%s=%r' % (key, value)
+             for key, value in self.__dict__.items()]
+        return '%s(%s)' % (self.__class__.__name__, ', '.join(L))
+
+    def __eq__(self, other):
+        return isinstance(other, self.__class__) and self.__dict__ == other.__dict__
+
+    def __ne__(self, other):
+        return not (self == other)
+all_structs.append(isUserExist_args)
+isUserExist_args.thrift_spec = (
+    None,  # 0
+    (1, TType.STRUCT, 'authzToken', [custos.commons.model.security.ttypes.AuthzToken, None], None, ),  # 1
+    (2, TType.STRING, 'username', 'UTF8', None, ),  # 2
+)
+
+
+class isUserExist_result(object):
+    """
+    Attributes:
+     - success
+     - Idse
+
+    """
+
+
+    def __init__(self, success=None, Idse=None,):
+        self.success = success
+        self.Idse = Idse
+
+    def read(self, iprot):
+        if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None:
+            iprot._fast_decode(self, iprot, [self.__class__, self.thrift_spec])
+            return
+        iprot.readStructBegin()
+        while True:
+            (fname, ftype, fid) = iprot.readFieldBegin()
+            if ftype == TType.STOP:
+                break
+            if fid == 0:
+                if ftype == TType.BOOL:
+                    self.success = iprot.readBool()
+                else:
+                    iprot.skip(ftype)
+            elif fid == 1:
+                if ftype == TType.STRUCT:
+                    self.Idse = custos.profile.iam.admin.services.cpi.error.ttypes.IamAdminServicesException()
+                    self.Idse.read(iprot)
+                else:
+                    iprot.skip(ftype)
+            else:
+                iprot.skip(ftype)
+            iprot.readFieldEnd()
+        iprot.readStructEnd()
+
+    def write(self, oprot):
+        if oprot._fast_encode is not None and self.thrift_spec is not None:
+            oprot.trans.write(oprot._fast_encode(self, [self.__class__, self.thrift_spec]))
+            return
+        oprot.writeStructBegin('isUserExist_result')
+        if self.success is not None:
+            oprot.writeFieldBegin('success', TType.BOOL, 0)
+            oprot.writeBool(self.success)
+            oprot.writeFieldEnd()
+        if self.Idse is not None:
+            oprot.writeFieldBegin('Idse', TType.STRUCT, 1)
+            self.Idse.write(oprot)
+            oprot.writeFieldEnd()
+        oprot.writeFieldStop()
+        oprot.writeStructEnd()
+
+    def validate(self):
+        return
+
+    def __repr__(self):
+        L = ['%s=%r' % (key, value)
+             for key, value in self.__dict__.items()]
+        return '%s(%s)' % (self.__class__.__name__, ', '.join(L))
+
+    def __eq__(self, other):
+        return isinstance(other, self.__class__) and self.__dict__ == other.__dict__
+
+    def __ne__(self, other):
+        return not (self == other)
+all_structs.append(isUserExist_result)
+isUserExist_result.thrift_spec = (
+    (0, TType.BOOL, 'success', None, None, ),  # 0
+    (1, TType.STRUCT, 'Idse', [custos.profile.iam.admin.services.cpi.error.ttypes.IamAdminServicesException, None], None, ),  # 1
+)
+
+
+class getUser_args(object):
+    """
+    Attributes:
+     - authzToken
+     - username
+
+    """
+
+
+    def __init__(self, authzToken=None, username=None,):
+        self.authzToken = authzToken
+        self.username = username
+
+    def read(self, iprot):
+        if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None:
+            iprot._fast_decode(self, iprot, [self.__class__, self.thrift_spec])
+            return
+        iprot.readStructBegin()
+        while True:
+            (fname, ftype, fid) = iprot.readFieldBegin()
+            if ftype == TType.STOP:
+                break
+            if fid == 1:
+                if ftype == TType.STRUCT:
+                    self.authzToken = custos.commons.model.security.ttypes.AuthzToken()
+                    self.authzToken.read(iprot)
+                else:
+                    iprot.skip(ftype)
+            elif fid == 2:
+                if ftype == TType.STRING:
+                    self.username = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
+                else:
+                    iprot.skip(ftype)
+            else:
+                iprot.skip(ftype)
+            iprot.readFieldEnd()
+        iprot.readStructEnd()
+
+    def write(self, oprot):
+        if oprot._fast_encode is not None and self.thrift_spec is not None:
+            oprot.trans.write(oprot._fast_encode(self, [self.__class__, self.thrift_spec]))
+            return
+        oprot.writeStructBegin('getUser_args')
+        if self.authzToken is not None:
+            oprot.writeFieldBegin('authzToken', TType.STRUCT, 1)
+            self.authzToken.write(oprot)
+            oprot.writeFieldEnd()
+        if self.username is not None:
+            oprot.writeFieldBegin('username', TType.STRING, 2)
+            oprot.writeString(self.username.encode('utf-8') if sys.version_info[0] == 2 else self.username)
+            oprot.writeFieldEnd()
+        oprot.writeFieldStop()
+        oprot.writeStructEnd()
+
+    def validate(self):
+        if self.authzToken is None:
+            raise TProtocolException(message='Required field authzToken is unset!')
+        if self.username is None:
+            raise TProtocolException(message='Required field username is unset!')
+        return
+
+    def __repr__(self):
+        L = ['%s=%r' % (key, value)
+             for key, value in self.__dict__.items()]
+        return '%s(%s)' % (self.__class__.__name__, ', '.join(L))
+
+    def __eq__(self, other):
+        return isinstance(other, self.__class__) and self.__dict__ == other.__dict__
+
+    def __ne__(self, other):
+        return not (self == other)
+all_structs.append(getUser_args)
+getUser_args.thrift_spec = (
+    None,  # 0
+    (1, TType.STRUCT, 'authzToken', [custos.commons.model.security.ttypes.AuthzToken, None], None, ),  # 1
+    (2, TType.STRING, 'username', 'UTF8', None, ),  # 2
+)
+
+
+class getUser_result(object):
+    """
+    Attributes:
+     - success
+     - Idse
+
+    """
+
+
+    def __init__(self, success=None, Idse=None,):
+        self.success = success
+        self.Idse = Idse
+
+    def read(self, iprot):
+        if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None:
+            iprot._fast_decode(self, iprot, [self.__class__, self.thrift_spec])
+            return
+        iprot.readStructBegin()
+        while True:
+            (fname, ftype, fid) = iprot.readFieldBegin()
+            if ftype == TType.STOP:
+                break
+            if fid == 0:
+                if ftype == TType.STRUCT:
+                    self.success = custos.profile.model.User.ttypes.UserProfile()
+                    self.success.read(iprot)
+                else:
+                    iprot.skip(ftype)
+            elif fid == 1:
+                if ftype == TType.STRUCT:
+                    self.Idse = custos.profile.iam.admin.services.cpi.error.ttypes.IamAdminServicesException()
+                    self.Idse.read(iprot)
+                else:
+                    iprot.skip(ftype)
+            else:
+                iprot.skip(ftype)
+            iprot.readFieldEnd()
+        iprot.readStructEnd()
+
+    def write(self, oprot):
+        if oprot._fast_encode is not None and self.thrift_spec is not None:
+            oprot.trans.write(oprot._fast_encode(self, [self.__class__, self.thrift_spec]))
+            return
+        oprot.writeStructBegin('getUser_result')
+        if self.success is not None:
+            oprot.writeFieldBegin('success', TType.STRUCT, 0)
+            self.success.write(oprot)
+            oprot.writeFieldEnd()
+        if self.Idse is not None:
+            oprot.writeFieldBegin('Idse', TType.STRUCT, 1)
+            self.Idse.write(oprot)
+            oprot.writeFieldEnd()
+        oprot.writeFieldStop()
+        oprot.writeStructEnd()
+
+    def validate(self):
+        return
+
+    def __repr__(self):
+        L = ['%s=%r' % (key, value)
+             for key, value in self.__dict__.items()]
+        return '%s(%s)' % (self.__class__.__name__, ', '.join(L))
+
+    def __eq__(self, other):
+        return isinstance(other, self.__class__) and self.__dict__ == other.__dict__
+
+    def __ne__(self, other):
+        return not (self == other)
+all_structs.append(getUser_result)
+getUser_result.thrift_spec = (
+    (0, TType.STRUCT, 'success', [custos.profile.model.User.ttypes.UserProfile, None], None, ),  # 0
+    (1, TType.STRUCT, 'Idse', [custos.profile.iam.admin.services.cpi.error.ttypes.IamAdminServicesException, None], None, ),  # 1
+)
+
+
+class getUsers_args(object):
+    """
+    Attributes:
+     - authzToken
+     - offset
+     - limit
+     - search
+
+    """
+
+
+    def __init__(self, authzToken=None, offset=None, limit=None, search=None,):
+        self.authzToken = authzToken
+        self.offset = offset
+        self.limit = limit
+        self.search = search
+
+    def read(self, iprot):
+        if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None:
+            iprot._fast_decode(self, iprot, [self.__class__, self.thrift_spec])
+            return
+        iprot.readStructBegin()
+        while True:
+            (fname, ftype, fid) = iprot.readFieldBegin()
+            if ftype == TType.STOP:
+                break
+            if fid == 1:
+                if ftype == TType.STRUCT:
+                    self.authzToken = custos.commons.model.security.ttypes.AuthzToken()
+                    self.authzToken.read(iprot)
+                else:
+                    iprot.skip(ftype)
+            elif fid == 2:
+                if ftype == TType.I32:
+                    self.offset = iprot.readI32()
+                else:
+                    iprot.skip(ftype)
+            elif fid == 3:
+                if ftype == TType.I32:
+                    self.limit = iprot.readI32()
+                else:
+                    iprot.skip(ftype)
+            elif fid == 4:
+                if ftype == TType.STRING:
+                    self.search = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
+                else:
+                    iprot.skip(ftype)
+            else:
+                iprot.skip(ftype)
+            iprot.readFieldEnd()
+        iprot.readStructEnd()
+
+    def write(self, oprot):
+        if oprot._fast_encode is not None and self.thrift_spec is not None:
+            oprot.trans.write(oprot._fast_encode(self, [self.__class__, self.thrift_spec]))
+            return
+        oprot.writeStructBegin('getUsers_args')
+        if self.authzToken is not None:
+            oprot.writeFieldBegin('authzToken', TType.STRUCT, 1)
+            self.authzToken.write(oprot)
+            oprot.writeFieldEnd()
+        if self.offset is not None:
+            oprot.writeFieldBegin('offset', TType.I32, 2)
+            oprot.writeI32(self.offset)
+            oprot.writeFieldEnd()
+        if self.limit is not None:
+            oprot.writeFieldBegin('limit', TType.I32, 3)
+            oprot.writeI32(self.limit)
+            oprot.writeFieldEnd()
+        if self.search is not None:
+            oprot.writeFieldBegin('search', TType.STRING, 4)
+            oprot.writeString(self.search.encode('utf-8') if sys.version_info[0] == 2 else self.search)
+            oprot.writeFieldEnd()
+        oprot.writeFieldStop()
+        oprot.writeStructEnd()
+
+    def validate(self):
+        if self.authzToken is None:
+            raise TProtocolException(message='Required field authzToken is unset!')
+        if self.offset is None:
+            raise TProtocolException(message='Required field offset is unset!')
+        if self.limit is None:
+            raise TProtocolException(message='Required field limit is unset!')
+        return
+
+    def __repr__(self):
+        L = ['%s=%r' % (key, value)
+             for key, value in self.__dict__.items()]
+        return '%s(%s)' % (self.__class__.__name__, ', '.join(L))
+
+    def __eq__(self, other):
+        return isinstance(other, self.__class__) and self.__dict__ == other.__dict__
+
+    def __ne__(self, other):
+        return not (self == other)
+all_structs.append(getUsers_args)
+getUsers_args.thrift_spec = (
+    None,  # 0
+    (1, TType.STRUCT, 'authzToken', [custos.commons.model.security.ttypes.AuthzToken, None], None, ),  # 1
+    (2, TType.I32, 'offset', None, None, ),  # 2
+    (3, TType.I32, 'limit', None, None, ),  # 3
+    (4, TType.STRING, 'search', 'UTF8', None, ),  # 4
+)
+
+
+class getUsers_result(object):
+    """
+    Attributes:
+     - success
+     - Idse
+
+    """
+
+
+    def __init__(self, success=None, Idse=None,):
+        self.success = success
+        self.Idse = Idse
+
+    def read(self, iprot):
+        if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None:
+            iprot._fast_decode(self, iprot, [self.__class__, self.thrift_spec])
+            return
+        iprot.readStructBegin()
+        while True:
+            (fname, ftype, fid) = iprot.readFieldBegin()
+            if ftype == TType.STOP:
+                break
+            if fid == 0:
+                if ftype == TType.LIST:
+                    self.success = []
+                    (_etype3, _size0) = iprot.readListBegin()
+                    for _i4 in range(_size0):
+                        _elem5 = custos.profile.model.User.ttypes.UserProfile()
+                        _elem5.read(iprot)
+                        self.success.append(_elem5)
+                    iprot.readListEnd()
+                else:
+                    iprot.skip(ftype)
+            elif fid == 1:
+                if ftype == TType.STRUCT:
+                    self.Idse = custos.profile.iam.admin.services.cpi.error.ttypes.IamAdminServicesException()
+                    self.Idse.read(iprot)
+                else:
+                    iprot.skip(ftype)
+            else:
+                iprot.skip(ftype)
+            iprot.readFieldEnd()
+        iprot.readStructEnd()
+
+    def write(self, oprot):
+        if oprot._fast_encode is not None and self.thrift_spec is not None:
+            oprot.trans.write(oprot._fast_encode(self, [self.__class__, self.thrift_spec]))
+            return
+        oprot.writeStructBegin('getUsers_result')
+        if self.success is not None:
+            oprot.writeFieldBegin('success', TType.LIST, 0)
+            oprot.writeListBegin(TType.STRUCT, len(self.success))
+            for iter6 in self.success:
+                iter6.write(oprot)
+            oprot.writeListEnd()
+            oprot.writeFieldEnd()
+        if self.Idse is not None:
+            oprot.writeFieldBegin('Idse', TType.STRUCT, 1)
+            self.Idse.write(oprot)
+            oprot.writeFieldEnd()
+        oprot.writeFieldStop()
+        oprot.writeStructEnd()
+
+    def validate(self):
+        return
+
+    def __repr__(self):
+        L = ['%s=%r' % (key, value)
+             for key, value in self.__dict__.items()]
+        return '%s(%s)' % (self.__class__.__name__, ', '.join(L))
+
+    def __eq__(self, other):
+        return isinstance(other, self.__class__) and self.__dict__ == other.__dict__
+
+    def __ne__(self, other):
+        return not (self == other)
+all_structs.append(getUsers_result)
+getUsers_result.thrift_spec = (
+    (0, TType.LIST, 'success', (TType.STRUCT, [custos.profile.model.User.ttypes.UserProfile, None], False), None, ),  # 0
+    (1, TType.STRUCT, 'Idse', [custos.profile.iam.admin.services.cpi.error.ttypes.IamAdminServicesException, None], None, ),  # 1
+)
+
+
+class resetUserPassword_args(object):
+    """
+    Attributes:
+     - authzToken
+     - username
+     - newPassword
+
+    """
+
+
+    def __init__(self, authzToken=None, username=None, newPassword=None,):
+        self.authzToken = authzToken
+        self.username = username
+        self.newPassword = newPassword
+
+    def read(self, iprot):
+        if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None:
+            iprot._fast_decode(self, iprot, [self.__class__, self.thrift_spec])
+            return
+        iprot.readStructBegin()
+        while True:
+            (fname, ftype, fid) = iprot.readFieldBegin()
+            if ftype == TType.STOP:
+                break
+            if fid == 1:
+                if ftype == TType.STRUCT:
+                    self.authzToken = custos.commons.model.security.ttypes.AuthzToken()
+                    self.authzToken.read(iprot)
+                else:
+                    iprot.skip(ftype)
+            elif fid == 2:
+                if ftype == TType.STRING:
+                    self.username = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
+                else:
+                    iprot.skip(ftype)
+            elif fid == 3:
+                if ftype == TType.STRING:
+                    self.newPassword = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
+                else:
+                    iprot.skip(ftype)
+            else:
+                iprot.skip(ftype)
+            iprot.readFieldEnd()
+        iprot.readStructEnd()
+
+    def write(self, oprot):
+        if oprot._fast_encode is not None and self.thrift_spec is not None:
+            oprot.trans.write(oprot._fast_encode(self, [self.__class__, self.thrift_spec]))
+            return
+        oprot.writeStructBegin('resetUserPassword_args')
+        if self.authzToken is not None:
+            oprot.writeFieldBegin('authzToken', TType.STRUCT, 1)
+            self.authzToken.write(oprot)
+            oprot.writeFieldEnd()
+        if self.username is not None:
+            oprot.writeFieldBegin('username', TType.STRING, 2)
+            oprot.writeString(self.username.encode('utf-8') if sys.version_info[0] == 2 else self.username)
+            oprot.writeFieldEnd()
+        if self.newPassword is not None:
+            oprot.writeFieldBegin('newPassword', TType.STRING, 3)
+            oprot.writeString(self.newPassword.encode('utf-8') if sys.version_info[0] == 2 else self.newPassword)
+            oprot.writeFieldEnd()
+        oprot.writeFieldStop()
+        oprot.writeStructEnd()
+
+    def validate(self):
+        if self.authzToken is None:
+            raise TProtocolException(message='Required field authzToken is unset!')
+        if self.username is None:
+            raise TProtocolException(message='Required field username is unset!')
+        if self.newPassword is None:
+            raise TProtocolException(message='Required field newPassword is unset!')
+        return
+
+    def __repr__(self):
+        L = ['%s=%r' % (key, value)
+             for key, value in self.__dict__.items()]
+        return '%s(%s)' % (self.__class__.__name__, ', '.join(L))
+
+    def __eq__(self, other):
+        return isinstance(other, self.__class__) and self.__dict__ == other.__dict__
+
+    def __ne__(self, other):
+        return not (self == other)
+all_structs.append(resetUserPassword_args)
+resetUserPassword_args.thrift_spec = (
+    None,  # 0
+    (1, TType.STRUCT, 'authzToken', [custos.commons.model.security.ttypes.AuthzToken, None], None, ),  # 1
+    (2, TType.STRING, 'username', 'UTF8', None, ),  # 2
+    (3, TType.STRING, 'newPassword', 'UTF8', None, ),  # 3
+)
+
+
+class resetUserPassword_result(object):
+    """
+    Attributes:
+     - success
+     - Idse
+
+    """
+
+
+    def __init__(self, success=None, Idse=None,):
+        self.success = success
+        self.Idse = Idse
+
+    def read(self, iprot):
+        if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None:
+            iprot._fast_decode(self, iprot, [self.__class__, self.thrift_spec])
+            return
+        iprot.readStructBegin()
+        while True:
+            (fname, ftype, fid) = iprot.readFieldBegin()
+            if ftype == TType.STOP:
+                break
+            if fid == 0:
+                if ftype == TType.BOOL:
+                    self.success = iprot.readBool()
+                else:
+                    iprot.skip(ftype)
+            elif fid == 1:
+                if ftype == TType.STRUCT:
+                    self.Idse = custos.profile.iam.admin.services.cpi.error.ttypes.IamAdminServicesException()
+                    self.Idse.read(iprot)
+                else:
+                    iprot.skip(ftype)
+            else:
+                iprot.skip(ftype)
+            iprot.readFieldEnd()
+        iprot.readStructEnd()
+
+    def write(self, oprot):
+        if oprot._fast_encode is not None and self.thrift_spec is not None:
+            oprot.trans.write(oprot._fast_encode(self, [self.__class__, self.thrift_spec]))
+            return
+        oprot.writeStructBegin('resetUserPassword_result')
+        if self.success is not None:
+            oprot.writeFieldBegin('success', TType.BOOL, 0)
+            oprot.writeBool(self.success)
+            oprot.writeFieldEnd()
+        if self.Idse is not None:
+            oprot.writeFieldBegin('Idse', TType.STRUCT, 1)
+            self.Idse.write(oprot)
+            oprot.writeFieldEnd()
+        oprot.writeFieldStop()
+        oprot.writeStructEnd()
+
+    def validate(self):
+        return
+
+    def __repr__(self):
+        L = ['%s=%r' % (key, value)
+             for key, value in self.__dict__.items()]
+        return '%s(%s)' % (self.__class__.__name__, ', '.join(L))
+
+    def __eq__(self, other):
+        return isinstance(other, self.__class__) and self.__dict__ == other.__dict__
+
+    def __ne__(self, other):
+        return not (self == other)
+all_structs.append(resetUserPassword_result)
+resetUserPassword_result.thrift_spec = (
+    (0, TType.BOOL, 'success', None, None, ),  # 0
+    (1, TType.STRUCT, 'Idse', [custos.profile.iam.admin.services.cpi.error.ttypes.IamAdminServicesException, None], None, ),  # 1
+)
+
+
+class findUsers_args(object):
+    """
+    Attributes:
+     - authzToken
+     - email
+     - userId
+
+    """
+
+
+    def __init__(self, authzToken=None, email=None, userId=None,):
+        self.authzToken = authzToken
+        self.email = email
+        self.userId = userId
+
+    def read(self, iprot):
+        if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None:
+            iprot._fast_decode(self, iprot, [self.__class__, self.thrift_spec])
+            return
+        iprot.readStructBegin()
+        while True:
+            (fname, ftype, fid) = iprot.readFieldBegin()
+            if ftype == TType.STOP:
+                break
+            if fid == 1:
+                if ftype == TType.STRUCT:
+                    self.authzToken = custos.commons.model.security.ttypes.AuthzToken()
+                    self.authzToken.read(iprot)
+                else:
+                    iprot.skip(ftype)
+            elif fid == 2:
+                if ftype == TType.STRING:
+                    self.email = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
+                else:
+                    iprot.skip(ftype)
+            elif fid == 3:
+                if ftype == TType.STRING:
+                    self.userId = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
+                else:
+                    iprot.skip(ftype)
+            else:
+                iprot.skip(ftype)
+            iprot.readFieldEnd()
+        iprot.readStructEnd()
+
+    def write(self, oprot):
+        if oprot._fast_encode is not None and self.thrift_spec is not None:
+            oprot.trans.write(oprot._fast_encode(self, [self.__class__, self.thrift_spec]))
+            return
+        oprot.writeStructBegin('findUsers_args')
+        if self.authzToken is not None:
+            oprot.writeFieldBegin('authzToken', TType.STRUCT, 1)
+            self.authzToken.write(oprot)
+            oprot.writeFieldEnd()
+        if self.email is not None:
+            oprot.writeFieldBegin('email', TType.STRING, 2)
+            oprot.writeString(self.email.encode('utf-8') if sys.version_info[0] == 2 else self.email)
+            oprot.writeFieldEnd()
+        if self.userId is not None:
+            oprot.writeFieldBegin('userId', TType.STRING, 3)
+            oprot.writeString(self.userId.encode('utf-8') if sys.version_info[0] == 2 else self.userId)
+            oprot.writeFieldEnd()
+        oprot.writeFieldStop()
+        oprot.writeStructEnd()
+
+    def validate(self):
+        if self.authzToken is None:
+            raise TProtocolException(message='Required field authzToken is unset!')
+        if self.email is None:
+            raise TProtocolException(message='Required field email is unset!')
+        if self.userId is None:
+            raise TProtocolException(message='Required field userId is unset!')
+        return
+
+    def __repr__(self):
+        L = ['%s=%r' % (key, value)
+             for key, value in self.__dict__.items()]
+        return '%s(%s)' % (self.__class__.__name__, ', '.join(L))
+
+    def __eq__(self, other):
+        return isinstance(other, self.__class__) and self.__dict__ == other.__dict__
+
+    def __ne__(self, other):
+        return not (self == other)
+all_structs.append(findUsers_args)
+findUsers_args.thrift_spec = (
+    None,  # 0
+    (1, TType.STRUCT, 'authzToken', [custos.commons.model.security.ttypes.AuthzToken, None], None, ),  # 1
+    (2, TType.STRING, 'email', 'UTF8', None, ),  # 2
+    (3, TType.STRING, 'userId', 'UTF8', None, ),  # 3
+)
+
+
+class findUsers_result(object):
+    """
+    Attributes:
+     - success
+     - Idse
+
+    """
+
+
+    def __init__(self, success=None, Idse=None,):
+        self.success = success
+        self.Idse = Idse
+
+    def read(self, iprot):
+        if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None:
+            iprot._fast_decode(self, iprot, [self.__class__, self.thrift_spec])
+            return
+        iprot.readStructBegin()
+        while True:
+            (fname, ftype, fid) = iprot.readFieldBegin()
+            if ftype == TType.STOP:
+                break
+            if fid == 0:
+                if ftype == TType.LIST:
+                    self.success = []
+                    (_etype10, _size7) = iprot.readListBegin()
+                    for _i11 in range(_size7):
+                        _elem12 = custos.profile.model.User.ttypes.UserProfile()
+                        _elem12.read(iprot)
+                        self.success.append(_elem12)
+                    iprot.readListEnd()
+                else:
+                    iprot.skip(ftype)
+            elif fid == 1:
+                if ftype == TType.STRUCT:
+                    self.Idse = custos.profile.iam.admin.services.cpi.error.ttypes.IamAdminServicesException()
+                    self.Idse.read(iprot)
+                else:
+                    iprot.skip(ftype)
+            else:
+                iprot.skip(ftype)
+            iprot.readFieldEnd()
+        iprot.readStructEnd()
+
+    def write(self, oprot):
+        if oprot._fast_encode is not None and self.thrift_spec is not None:
+            oprot.trans.write(oprot._fast_encode(self, [self.__class__, self.thrift_spec]))
+            return
+        oprot.writeStructBegin('findUsers_result')
+        if self.success is not None:
+            oprot.writeFieldBegin('success', TType.LIST, 0)
+            oprot.writeListBegin(TType.STRUCT, len(self.success))
+            for iter13 in self.success:
+                iter13.write(oprot)
+            oprot.writeListEnd()
+            oprot.writeFieldEnd()
+        if self.Idse is not None:
+            oprot.writeFieldBegin('Idse', TType.STRUCT, 1)
+            self.Idse.write(oprot)
+            oprot.writeFieldEnd()
+        oprot.writeFieldStop()
+        oprot.writeStructEnd()
+
+    def validate(self):
+        return
+
+    def __repr__(self):
+        L = ['%s=%r' % (key, value)
+             for key, value in self.__dict__.items()]
+        return '%s(%s)' % (self.__class__.__name__, ', '.join(L))
+
+    def __eq__(self, other):
+        return isinstance(other, self.__class__) and self.__dict__ == other.__dict__
+
+    def __ne__(self, other):
+        return not (self == other)
+all_structs.append(findUsers_result)
+findUsers_result.thrift_spec = (
+    (0, TType.LIST, 'success', (TType.STRUCT, [custos.profile.model.User.ttypes.UserProfile, None], False), None, ),  # 0
+    (1, TType.STRUCT, 'Idse', [custos.profile.iam.admin.services.cpi.error.ttypes.IamAdminServicesException, None], None, ),  # 1
+)
+
+
+class updateUserProfile_args(object):
+    """
+    Attributes:
+     - authzToken
+     - userDetails
+
+    """
+
+
+    def __init__(self, authzToken=None, userDetails=None,):
+        self.authzToken = authzToken
+        self.userDetails = userDetails
+
+    def read(self, iprot):
+        if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None:
+            iprot._fast_decode(self, iprot, [self.__class__, self.thrift_spec])
+            return
+        iprot.readStructBegin()
+        while True:
+            (fname, ftype, fid) = iprot.readFieldBegin()
+            if ftype == TType.STOP:
+                break
+            if fid == 1:
+                if ftype == TType.STRUCT:
+                    self.authzToken = custos.commons.model.security.ttypes.AuthzToken()
+                    self.authzToken.read(iprot)
+                else:
+                    iprot.skip(ftype)
+            elif fid == 2:
+                if ftype == TType.STRUCT:
+                    self.userDetails = custos.profile.model.User.ttypes.UserProfile()
+                    self.userDetails.read(iprot)
+                else:
+                    iprot.skip(ftype)
+            else:
+                iprot.skip(ftype)
+            iprot.readFieldEnd()
+        iprot.readStructEnd()
+
+    def write(self, oprot):
+        if oprot._fast_encode is not None and self.thrift_spec is not None:
+            oprot.trans.write(oprot._fast_encode(self, [self.__class__, self.thrift_spec]))
+            return
+        oprot.writeStructBegin('updateUserProfile_args')
+        if self.authzToken is not None:
+            oprot.writeFieldBegin('authzToken', TType.STRUCT, 1)
+            self.authzToken.write(oprot)
+            oprot.writeFieldEnd()
+        if self.userDetails is not None:
+            oprot.writeFieldBegin('userDetails', TType.STRUCT, 2)
+            self.userDetails.write(oprot)
+            oprot.writeFieldEnd()
+        oprot.writeFieldStop()
+        oprot.writeStructEnd()
+
+    def validate(self):
+        if self.authzToken is None:
+            raise TProtocolException(message='Required field authzToken is unset!')
+        if self.userDetails is None:
+            raise TProtocolException(message='Required field userDetails is unset!')
+        return
+
+    def __repr__(self):
+        L = ['%s=%r' % (key, value)
+             for key, value in self.__dict__.items()]
+        return '%s(%s)' % (self.__class__.__name__, ', '.join(L))
+
+    def __eq__(self, other):
+        return isinstance(other, self.__class__) and self.__dict__ == other.__dict__
+
+    def __ne__(self, other):
+        return not (self == other)
+all_structs.append(updateUserProfile_args)
+updateUserProfile_args.thrift_spec = (
+    None,  # 0
+    (1, TType.STRUCT, 'authzToken', [custos.commons.model.security.ttypes.AuthzToken, None], None, ),  # 1
+    (2, TType.STRUCT, 'userDetails', [custos.profile.model.User.ttypes.UserProfile, None], None, ),  # 2
+)
+
+
+class updateUserProfile_result(object):
+    """
+    Attributes:
+     - Idse
+
+    """
+
+
+    def __init__(self, Idse=None,):
+        self.Idse = Idse
+
+    def read(self, iprot):
+        if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None:
+            iprot._fast_decode(self, iprot, [self.__class__, self.thrift_spec])
+            return
+        iprot.readStructBegin()
+        while True:
+            (fname, ftype, fid) = iprot.readFieldBegin()
+            if ftype == TType.STOP:
+                break
+            if fid == 1:
+                if ftype == TType.STRUCT:
+                    self.Idse = custos.profile.iam.admin.services.cpi.error.ttypes.IamAdminServicesException()
+                    self.Idse.read(iprot)
+                else:
+                    iprot.skip(ftype)
+            else:
+                iprot.skip(ftype)
+            iprot.readFieldEnd()
+        iprot.readStructEnd()
+
+    def write(self, oprot):
+        if oprot._fast_encode is not None and self.thrift_spec is not None:
+            oprot.trans.write(oprot._fast_encode(self, [self.__class__, self.thrift_spec]))
+            return
+        oprot.writeStructBegin('updateUserProfile_result')
+        if self.Idse is not None:
+            oprot.writeFieldBegin('Idse', TType.STRUCT, 1)
+            self.Idse.write(oprot)
+            oprot.writeFieldEnd()
+        oprot.writeFieldStop()
+        oprot.writeStructEnd()
+
+    def validate(self):
+        return
+
+    def __repr__(self):
+        L = ['%s=%r' % (key, value)
+             for key, value in self.__dict__.items()]
+        return '%s(%s)' % (self.__class__.__name__, ', '.join(L))
+
+    def __eq__(self, other):
+        return isinstance(other, self.__class__) and self.__dict__ == other.__dict__
+
+    def __ne__(self, other):
+        return not (self == other)
+all_structs.append(updateUserProfile_result)
+updateUserProfile_result.thrift_spec = (
+    None,  # 0
+    (1, TType.STRUCT, 'Idse', [custos.profile.iam.admin.services.cpi.error.ttypes.IamAdminServicesException, None], None, ),  # 1
+)
+
+
+class addRoleToUser_args(object):
+    """
+    Attributes:
+     - authzToken
+     - username
+     - roleName
+     - tenantAdminPasswordCredential
+
+    """
+
+
+    def __init__(self, authzToken=None, username=None, roleName=None, tenantAdminPasswordCredential=None,):
+        self.authzToken = authzToken
+        self.username = username
+        self.roleName = roleName
+        self.tenantAdminPasswordCredential = tenantAdminPasswordCredential
+
+    def read(self, iprot):
+        if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None:
+            iprot._fast_decode(self, iprot, [self.__class__, self.thrift_spec])
+            return
+        iprot.readStructBegin()
+        while True:
+            (fname, ftype, fid) = iprot.readFieldBegin()
+            if ftype == TType.STOP:
+                break
+            if fid == 1:
+                if ftype == TType.STRUCT:
+                    self.authzToken = custos.commons.model.security.ttypes.AuthzToken()
+                    self.authzToken.read(iprot)
+                else:
+                    iprot.skip(ftype)
+            elif fid == 2:
+                if ftype == TType.STRING:
+                    self.username = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
+                else:
+                    iprot.skip(ftype)
+            elif fid == 3:
+                if ftype == TType.STRING:
+                    self.roleName = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
+                else:
+                    iprot.skip(ftype)
+            elif fid == 4:
+                if ftype == TType.STRUCT:
+                    self.tenantAdminPasswordCredential = custos.profile.model.tenant.ttypes.PasswordCredential()
+                    self.tenantAdminPasswordCredential.read(iprot)
+                else:
+                    iprot.skip(ftype)
+            else:
+                iprot.skip(ftype)
+            iprot.readFieldEnd()
+        iprot.readStructEnd()
+
+    def write(self, oprot):
+        if oprot._fast_encode is not None and self.thrift_spec is not None:
+            oprot.trans.write(oprot._fast_encode(self, [self.__class__, self.thrift_spec]))
+            return
+        oprot.writeStructBegin('addRoleToUser_args')
+        if self.authzToken is not None:
+            oprot.writeFieldBegin('authzToken', TType.STRUCT, 1)
+            self.authzToken.write(oprot)
+            oprot.writeFieldEnd()
+        if self.username is not None:
+            oprot.writeFieldBegin('username', TType.STRING, 2)
+            oprot.writeString(self.username.encode('utf-8') if sys.version_info[0] == 2 else self.username)
+            oprot.writeFieldEnd()
+        if self.roleName is not None:
+            oprot.writeFieldBegin('roleName', TType.STRING, 3)
+            oprot.writeString(self.roleName.encode('utf-8') if sys.version_info[0] == 2 else self.roleName)
+            oprot.writeFieldEnd()
+        if self.tenantAdminPasswordCredential is not None:
+            oprot.writeFieldBegin('tenantAdminPasswordCredential', TType.STRUCT, 4)
+            self.tenantAdminPasswordCredential.write(oprot)
+            oprot.writeFieldEnd()
+        oprot.writeFieldStop()
+        oprot.writeStructEnd()
+
+    def validate(self):
+        if self.authzToken is None:
+            raise TProtocolException(message='Required field authzToken is unset!')
+        if self.username is None:
+            raise TProtocolException(message='Required field username is unset!')
+        if self.roleName is None:
+            raise TProtocolException(message='Required field roleName is unset!')
+        if self.tenantAdminPasswordCredential is None:
+            raise TProtocolException(message='Required field tenantAdminPasswordCredential is unset!')
+        return
+
+    def __repr__(self):
+        L = ['%s=%r' % (key, value)
+             for key, value in self.__dict__.items()]
+        return '%s(%s)' % (self.__class__.__name__, ', '.join(L))
+
+    def __eq__(self, other):
+        return isinstance(other, self.__class__) and self.__dict__ == other.__dict__
+
+    def __ne__(self, other):
+        return not (self == other)
+all_structs.append(addRoleToUser_args)
+addRoleToUser_args.thrift_spec = (
+    None,  # 0
+    (1, TType.STRUCT, 'authzToken', [custos.commons.model.security.ttypes.AuthzToken, None], None, ),  # 1
+    (2, TType.STRING, 'username', 'UTF8', None, ),  # 2
+    (3, TType.STRING, 'roleName', 'UTF8', None, ),  # 3
+    (4, TType.STRUCT, 'tenantAdminPasswordCredential', [custos.profile.model.tenant.ttypes.PasswordCredential, None], None, ),  # 4
+)
+
+
+class addRoleToUser_result(object):
+    """
+    Attributes:
+     - success
+     - Idse
+
+    """
+
+
+    def __init__(self, success=None, Idse=None,):
+        self.success = success
+        self.Idse = Idse
+
+    def read(self, iprot):
+        if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None:
+            iprot._fast_decode(self, iprot, [self.__class__, self.thrift_spec])
+            return
+        iprot.readStructBegin()
+        while True:
+            (fname, ftype, fid) = iprot.readFieldBegin()
+            if ftype == TType.STOP:
+                break
+            if fid == 0:
+                if ftype == TType.BOOL:
+                    self.success = iprot.readBool()
+                else:
+                    iprot.skip(ftype)
+            elif fid == 1:
+                if ftype == TType.STRUCT:
+                    self.Idse = custos.profile.iam.admin.services.cpi.error.ttypes.IamAdminServicesException()
+                    self.Idse.read(iprot)
+                else:
+                    iprot.skip(ftype)
+            else:
+                iprot.skip(ftype)
+            iprot.readFieldEnd()
+        iprot.readStructEnd()
+
+    def write(self, oprot):
+        if oprot._fast_encode is not None and self.thrift_spec is not None:
+            oprot.trans.write(oprot._fast_encode(self, [self.__class__, self.thrift_spec]))
+            return
+        oprot.writeStructBegin('addRoleToUser_result')
+        if self.success is not None:
+            oprot.writeFieldBegin('success', TType.BOOL, 0)
+            oprot.writeBool(self.success)
+            oprot.writeFieldEnd()
+        if self.Idse is not None:
+            oprot.writeFieldBegin('Idse', TType.STRUCT, 1)
+            self.Idse.write(oprot)
+            oprot.writeFieldEnd()
+        oprot.writeFieldStop()
+        oprot.writeStructEnd()
+
+    def validate(self):
+        return
+
+    def __repr__(self):
+        L = ['%s=%r' % (key, value)
+             for key, value in self.__dict__.items()]
+        return '%s(%s)' % (self.__class__.__name__, ', '.join(L))
+
+    def __eq__(self, other):
+        return isinstance(other, self.__class__) and self.__dict__ == other.__dict__
+
+    def __ne__(self, other):
+        return not (self == other)
+all_structs.append(addRoleToUser_result)
+addRoleToUser_result.thrift_spec = (
+    (0, TType.BOOL, 'success', None, None, ),  # 0
+    (1, TType.STRUCT, 'Idse', [custos.profile.iam.admin.services.cpi.error.ttypes.IamAdminServicesException, None], None, ),  # 1
+)
+
+
+class removeRoleFromUser_args(object):
+    """
+    Attributes:
+     - authzToken
+     - username
+     - roleName
+     - tenantAdminPasswordCredential
+
+    """
+
+
+    def __init__(self, authzToken=None, username=None, roleName=None, tenantAdminPasswordCredential=None,):
+        self.authzToken = authzToken
+        self.username = username
+        self.roleName = roleName
+        self.tenantAdminPasswordCredential = tenantAdminPasswordCredential
+
+    def read(self, iprot):
+        if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None:
+            iprot._fast_decode(self, iprot, [self.__class__, self.thrift_spec])
+            return
+        iprot.readStructBegin()
+        while True:
+            (fname, ftype, fid) = iprot.readFieldBegin()
+            if ftype == TType.STOP:
+                break
+            if fid == 1:
+                if ftype == TType.STRUCT:
+                    self.authzToken = custos.commons.model.security.ttypes.AuthzToken()
+                    self.authzToken.read(iprot)
+                else:
+                    iprot.skip(ftype)
+            elif fid == 2:
+                if ftype == TType.STRING:
+                    self.username = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
+                else:
+                    iprot.skip(ftype)
+            elif fid == 3:
+                if ftype == TType.STRING:
+                    self.roleName = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
+                else:
+                    iprot.skip(ftype)
+            elif fid == 4:
+                if ftype == TType.STRUCT:
+                    self.tenantAdminPasswordCredential = custos.profile.model.tenant.ttypes.PasswordCredential()
+                    self.tenantAdminPasswordCredential.read(iprot)
+                else:
+                    iprot.skip(ftype)
+            else:
+                iprot.skip(ftype)
+            iprot.readFieldEnd()
+        iprot.readStructEnd()
+
+    def write(self, oprot):
+        if oprot._fast_encode is not None and self.thrift_spec is not None:
+            oprot.trans.write(oprot._fast_encode(self, [self.__class__, self.thrift_spec]))
+            return
+        oprot.writeStructBegin('removeRoleFromUser_args')
+        if self.authzToken is not None:
+            oprot.writeFieldBegin('authzToken', TType.STRUCT, 1)
+            self.authzToken.write(oprot)
+            oprot.writeFieldEnd()
+        if self.username is not None:
+            oprot.writeFieldBegin('username', TType.STRING, 2)
+            oprot.writeString(self.username.encode('utf-8') if sys.version_info[0] == 2 else self.username)
+            oprot.writeFieldEnd()
+        if self.roleName is not None:
+            oprot.writeFieldBegin('roleName', TType.STRING, 3)
+            oprot.writeString(self.roleName.encode('utf-8') if sys.version_info[0] == 2 else self.roleName)
+            oprot.writeFieldEnd()
+        if self.tenantAdminPasswordCredential is not None:
+            oprot.writeFieldBegin('tenantAdminPasswordCredential', TType.STRUCT, 4)
+            self.tenantAdminPasswordCredential.write(oprot)
+            oprot.writeFieldEnd()
+        oprot.writeFieldStop()
+        oprot.writeStructEnd()
+
+    def validate(self):
+        if self.authzToken is None:
+            raise TProtocolException(message='Required field authzToken is unset!')
+        if self.username is None:
+            raise TProtocolException(message='Required field username is unset!')
+        if self.roleName is None:
+            raise TProtocolException(message='Required field roleName is unset!')
+        if self.tenantAdminPasswordCredential is None:
+            raise TProtocolException(message='Required field tenantAdminPasswordCredential is unset!')
+        return
+
+    def __repr__(self):
+        L = ['%s=%r' % (key, value)
+             for key, value in self.__dict__.items()]
+        return '%s(%s)' % (self.__class__.__name__, ', '.join(L))
+
+    def __eq__(self, other):
+        return isinstance(other, self.__class__) and self.__dict__ == other.__dict__
+
+    def __ne__(self, other):
+        return not (self == other)
+all_structs.append(removeRoleFromUser_args)
+removeRoleFromUser_args.thrift_spec = (
+    None,  # 0
+    (1, TType.STRUCT, 'authzToken', [custos.commons.model.security.ttypes.AuthzToken, None], None, ),  # 1
+    (2, TType.STRING, 'username', 'UTF8', None, ),  # 2
+    (3, TType.STRING, 'roleName', 'UTF8', None, ),  # 3
+    (4, TType.STRUCT, 'tenantAdminPasswordCredential', [custos.profile.model.tenant.ttypes.PasswordCredential, None], None, ),  # 4
+)
+
+
+class removeRoleFromUser_result(object):
+    """
+    Attributes:
+     - success
+     - Idse
+
+    """
+
+
+    def __init__(self, success=None, Idse=None,):
+        self.success = success
+        self.Idse = Idse
+
+    def read(self, iprot):
+        if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None:
+            iprot._fast_decode(self, iprot, [self.__class__, self.thrift_spec])
+            return
+        iprot.readStructBegin()
+        while True:
+            (fname, ftype, fid) = iprot.readFieldBegin()
+            if ftype == TType.STOP:
+                break
+            if fid == 0:
+                if ftype == TType.BOOL:
+                    self.success = iprot.readBool()
+                else:
+                    iprot.skip(ftype)
+            elif fid == 1:
+                if ftype == TType.STRUCT:
+                    self.Idse = custos.profile.iam.admin.services.cpi.error.ttypes.IamAdminServicesException()
+                    self.Idse.read(iprot)
+                else:
+                    iprot.skip(ftype)
+            else:
+                iprot.skip(ftype)
+            iprot.readFieldEnd()
+        iprot.readStructEnd()
+
+    def write(self, oprot):
+        if oprot._fast_encode is not None and self.thrift_spec is not None:
+            oprot.trans.write(oprot._fast_encode(self, [self.__class__, self.thrift_spec]))
+            return
+        oprot.writeStructBegin('removeRoleFromUser_result')
+        if self.success is not None:
+            oprot.writeFieldBegin('success', TType.BOOL, 0)
+            oprot.writeBool(self.success)
+            oprot.writeFieldEnd()
+        if self.Idse is not None:
+            oprot.writeFieldBegin('Idse', TType.STRUCT, 1)
+            self.Idse.write(oprot)
+            oprot.writeFieldEnd()
+        oprot.writeFieldStop()
+        oprot.writeStructEnd()
+
+    def validate(self):
+        return
+
+    def __repr__(self):
+        L = ['%s=%r' % (key, value)
+             for key, value in self.__dict__.items()]
+        return '%s(%s)' % (self.__class__.__name__, ', '.join(L))
+
+    def __eq__(self, other):
+        return isinstance(other, self.__class__) and self.__dict__ == other.__dict__
+
+    def __ne__(self, other):
+        return not (self == other)
+all_structs.append(removeRoleFromUser_result)
+removeRoleFromUser_result.thrift_spec = (
+    (0, TType.BOOL, 'success', None, None, ),  # 0
+    (1, TType.STRUCT, 'Idse', [custos.profile.iam.admin.services.cpi.error.ttypes.IamAdminServicesException, None], None, ),  # 1
+)
+
+
+class getUsersWithRole_args(object):
+    """
+    Attributes:
+     - authzToken
+     - roleName
+     - tenantAdminPasswordCredential
+
+    """
+
+
+    def __init__(self, authzToken=None, roleName=None, tenantAdminPasswordCredential=None,):
+        self.authzToken = authzToken
+        self.roleName = roleName
+        self.tenantAdminPasswordCredential = tenantAdminPasswordCredential
+
+    def read(self, iprot):
+        if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None:
+            iprot._fast_decode(self, iprot, [self.__class__, self.thrift_spec])
+            return
+        iprot.readStructBegin()
+        while True:
+            (fname, ftype, fid) = iprot.readFieldBegin()
+            if ftype == TType.STOP:
+                break
+            if fid == 1:
+                if ftype == TType.STRUCT:
+                    self.authzToken = custos.commons.model.security.ttypes.AuthzToken()
+                    self.authzToken.read(iprot)
+                else:
+                    iprot.skip(ftype)
+            elif fid == 2:
+                if ftype == TType.STRING:
+                    self.roleName = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
+                else:
+                    iprot.skip(ftype)
+            elif fid == 3:
+                if ftype == TType.STRUCT:
+                    self.tenantAdminPasswordCredential = custos.profile.model.tenant.ttypes.PasswordCredential()
+                    self.tenantAdminPasswordCredential.read(iprot)
+                else:
+                    iprot.skip(ftype)
+            else:
+                iprot.skip(ftype)
+            iprot.readFieldEnd()
+        iprot.readStructEnd()
+
+    def write(self, oprot):
+        if oprot._fast_encode is not None and self.thrift_spec is not None:
+            oprot.trans.write(oprot._fast_encode(self, [self.__class__, self.thrift_spec]))
+            return
+        oprot.writeStructBegin('getUsersWithRole_args')
+        if self.authzToken is not None:
+            oprot.writeFieldBegin('authzToken', TType.STRUCT, 1)
+            self.authzToken.write(oprot)
+            oprot.writeFieldEnd()
+        if self.roleName is not None:
+            oprot.writeFieldBegin('roleName', TType.STRING, 2)
+            oprot.writeString(self.roleName.encode('utf-8') if sys.version_info[0] == 2 else self.roleName)
+            oprot.writeFieldEnd()
+        if self.tenantAdminPasswordCredential is not None:
+            oprot.writeFieldBegin('tenantAdminPasswordCredential', TType.STRUCT, 3)
+            self.tenantAdminPasswordCredential.write(oprot)
+            oprot.writeFieldEnd()
+        oprot.writeFieldStop()
+        oprot.writeStructEnd()
+
+    def validate(self):
+        if self.authzToken is None:
+            raise TProtocolException(message='Required field authzToken is unset!')
+        if self.roleName is None:
+            raise TProtocolException(message='Required field roleName is unset!')
+        if self.tenantAdminPasswordCredential is None:
+            raise TProtocolException(message='Required field tenantAdminPasswordCredential is unset!')
+        return
+
+    def __repr__(self):
+        L = ['%s=%r' % (key, value)
+             for key, value in self.__dict__.items()]
+        return '%s(%s)' % (self.__class__.__name__, ', '.join(L))
+
+    def __eq__(self, other):
+        return isinstance(other, self.__class__) and self.__dict__ == other.__dict__
+
+    def __ne__(self, other):
+        return not (self == other)
+all_structs.append(getUsersWithRole_args)
+getUsersWithRole_args.thrift_spec = (
+    None,  # 0
+    (1, TType.STRUCT, 'authzToken', [custos.commons.model.security.ttypes.AuthzToken, None], None, ),  # 1
+    (2, TType.STRING, 'roleName', 'UTF8', None, ),  # 2
+    (3, TType.STRUCT, 'tenantAdminPasswordCredential', [custos.profile.model.tenant.ttypes.PasswordCredential, None], None, ),  # 3
+)
+
+
+class getUsersWithRole_result(object):
+    """
+    Attributes:
+     - success
+     - Idse
+
+    """
+
+
+    def __init__(self, success=None, Idse=None,):
+        self.success = success
+        self.Idse = Idse
+
+    def read(self, iprot):
+        if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None:
+            iprot._fast_decode(self, iprot, [self.__class__, self.thrift_spec])
+            return
+        iprot.readStructBegin()
+        while True:
+            (fname, ftype, fid) = iprot.readFieldBegin()
+            if ftype == TType.STOP:
+                break
+            if fid == 0:
+                if ftype == TType.LIST:
+                    self.success = []
+                    (_etype17, _size14) = iprot.readListBegin()
+                    for _i18 in range(_size14):
+                        _elem19 = custos.profile.model.User.ttypes.UserProfile()
+                        _elem19.read(iprot)
+                        self.success.append(_elem19)
+                    iprot.readListEnd()
+                else:
+                    iprot.skip(ftype)
+            elif fid == 1:
+                if ftype == TType.STRUCT:
+                    self.Idse = custos.profile.iam.admin.services.cpi.error.ttypes.IamAdminServicesException()
+                    self.Idse.read(iprot)
+                else:
+                    iprot.skip(ftype)
+            else:
+                iprot.skip(ftype)
+            iprot.readFieldEnd()
+        iprot.readStructEnd()
+
+    def write(self, oprot):
+        if oprot._fast_encode is not None and self.thrift_spec is not None:
+            oprot.trans.write(oprot._fast_encode(self, [self.__class__, self.thrift_spec]))
+            return
+        oprot.writeStructBegin('getUsersWithRole_result')
+        if self.success is not None:
+            oprot.writeFieldBegin('success', TType.LIST, 0)
+            oprot.writeListBegin(TType.STRUCT, len(self.success))
+            for iter20 in self.success:
+                iter20.write(oprot)
+            oprot.writeListEnd()
+            oprot.writeFieldEnd()
+        if self.Idse is not None:
+            oprot.writeFieldBegin('Idse', TType.STRUCT, 1)
+            self.Idse.write(oprot)
+            oprot.writeFieldEnd()
+        oprot.writeFieldStop()
+        oprot.writeStructEnd()
+
+    def validate(self):
+        return
+
+    def __repr__(self):
+        L = ['%s=%r' % (key, value)
+             for key, value in self.__dict__.items()]
+        return '%s(%s)' % (self.__class__.__name__, ', '.join(L))
+
+    def __eq__(self, other):
+        return isinstance(other, self.__class__) and self.__dict__ == other.__dict__
+
+    def __ne__(self, other):
+        return not (self == other)
+all_structs.append(getUsersWithRole_result)
+getUsersWithRole_result.thrift_spec = (
+    (0, TType.LIST, 'success', (TType.STRUCT, [custos.profile.model.User.ttypes.UserProfile, None], False), None, ),  # 0
+    (1, TType.STRUCT, 'Idse', [custos.profile.iam.admin.services.cpi.error.ttypes.IamAdminServicesException, None], None, ),  # 1
+)
+fix_spec(all_structs)
+del all_structs
+
diff --git a/clients/python/custos/profile/iam/admin/services/cpi/__init__.py b/clients/python/custos/profile/iam/admin/services/cpi/__init__.py
new file mode 100644
index 0000000..58a44a7
--- /dev/null
+++ b/clients/python/custos/profile/iam/admin/services/cpi/__init__.py
@@ -0,0 +1 @@
+__all__ = ['ttypes', 'constants', 'IamAdminServices']
diff --git a/clients/python/custos/profile/iam/admin/services/cpi/constants.py b/clients/python/custos/profile/iam/admin/services/cpi/constants.py
new file mode 100644
index 0000000..31ef52e
--- /dev/null
+++ b/clients/python/custos/profile/iam/admin/services/cpi/constants.py
@@ -0,0 +1,16 @@
+#
+# Autogenerated by Thrift Compiler (0.12.0)
+#
+# DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
+#
+#  options string: py
+#
+
+from thrift.Thrift import TType, TMessageType, TFrozenDict, TException, TApplicationException
+from thrift.protocol.TProtocol import TProtocolException
+from thrift.TRecursive import fix_spec
+
+import sys
+from .ttypes import *
+IAM_ADMIN_SERVICES_CPI_VERSION = "0.17"
+IAM_ADMIN_SERVICES_CPI_NAME = "IamAdminServices"
diff --git a/clients/python/custos/profile/iam/admin/services/cpi/error/__init__.py b/clients/python/custos/profile/iam/admin/services/cpi/error/__init__.py
new file mode 100644
index 0000000..adefd8e
--- /dev/null
+++ b/clients/python/custos/profile/iam/admin/services/cpi/error/__init__.py
@@ -0,0 +1 @@
+__all__ = ['ttypes', 'constants']
diff --git a/clients/python/custos/profile/iam/admin/services/cpi/error/constants.py b/clients/python/custos/profile/iam/admin/services/cpi/error/constants.py
new file mode 100644
index 0000000..c59352d
--- /dev/null
+++ b/clients/python/custos/profile/iam/admin/services/cpi/error/constants.py
@@ -0,0 +1,14 @@
+#
+# Autogenerated by Thrift Compiler (0.12.0)
+#
+# DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
+#
+#  options string: py
+#
+
+from thrift.Thrift import TType, TMessageType, TFrozenDict, TException, TApplicationException
+from thrift.protocol.TProtocol import TProtocolException
+from thrift.TRecursive import fix_spec
+
+import sys
+from .ttypes import *
diff --git a/clients/python/custos/profile/iam/admin/services/cpi/error/ttypes.py b/clients/python/custos/profile/iam/admin/services/cpi/error/ttypes.py
new file mode 100644
index 0000000..441af21
--- /dev/null
+++ b/clients/python/custos/profile/iam/admin/services/cpi/error/ttypes.py
@@ -0,0 +1,85 @@
+#
+# Autogenerated by Thrift Compiler (0.12.0)
+#
+# DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
+#
+#  options string: py
+#
+
+from thrift.Thrift import TType, TMessageType, TFrozenDict, TException, TApplicationException
+from thrift.protocol.TProtocol import TProtocolException
+from thrift.TRecursive import fix_spec
+
+import sys
+
+from thrift.transport import TTransport
+all_structs = []
+
+
+class IamAdminServicesException(TException):
+    """
+    Attributes:
+     - message
+
+    """
+
+
+    def __init__(self, message=None,):
+        self.message = message
+
+    def read(self, iprot):
+        if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None:
+            iprot._fast_decode(self, iprot, [self.__class__, self.thrift_spec])
+            return
+        iprot.readStructBegin()
+        while True:
+            (fname, ftype, fid) = iprot.readFieldBegin()
+            if ftype == TType.STOP:
+                break
+            if fid == 1:
+                if ftype == TType.STRING:
+                    self.message = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
+                else:
+                    iprot.skip(ftype)
+            else:
+                iprot.skip(ftype)
+            iprot.readFieldEnd()
+        iprot.readStructEnd()
+
+    def write(self, oprot):
+        if oprot._fast_encode is not None and self.thrift_spec is not None:
+            oprot.trans.write(oprot._fast_encode(self, [self.__class__, self.thrift_spec]))
+            return
+        oprot.writeStructBegin('IamAdminServicesException')
+        if self.message is not None:
+            oprot.writeFieldBegin('message', TType.STRING, 1)
+            oprot.writeString(self.message.encode('utf-8') if sys.version_info[0] == 2 else self.message)
+            oprot.writeFieldEnd()
+        oprot.writeFieldStop()
+        oprot.writeStructEnd()
+
+    def validate(self):
+        if self.message is None:
+            raise TProtocolException(message='Required field message is unset!')
+        return
+
+    def __str__(self):
+        return repr(self)
+
+    def __repr__(self):
+        L = ['%s=%r' % (key, value)
+             for key, value in self.__dict__.items()]
+        return '%s(%s)' % (self.__class__.__name__, ', '.join(L))
+
+    def __eq__(self, other):
+        return isinstance(other, self.__class__) and self.__dict__ == other.__dict__
+
+    def __ne__(self, other):
+        return not (self == other)
+all_structs.append(IamAdminServicesException)
+IamAdminServicesException.thrift_spec = (
+    None,  # 0
+    (1, TType.STRING, 'message', 'UTF8', None, ),  # 1
+)
+fix_spec(all_structs)
+del all_structs
diff --git a/clients/python/custos/profile/iam/admin/services/cpi/ttypes.py b/clients/python/custos/profile/iam/admin/services/cpi/ttypes.py
new file mode 100644
index 0000000..5fb60ee
--- /dev/null
+++ b/clients/python/custos/profile/iam/admin/services/cpi/ttypes.py
@@ -0,0 +1,23 @@
+#
+# Autogenerated by Thrift Compiler (0.12.0)
+#
+# DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
+#
+#  options string: py
+#
+
+from thrift.Thrift import TType, TMessageType, TFrozenDict, TException, TApplicationException
+from thrift.protocol.TProtocol import TProtocolException
+from thrift.TRecursive import fix_spec
+
+import sys
+import custos.commons.model.security.ttypes
+import custos.profile.model.workspace.ttypes
+import custos.profile.model.User.ttypes
+import custos.profile.model.tenant.ttypes
+import custos.profile.iam.admin.services.cpi.error.ttypes
+
+from thrift.transport import TTransport
+all_structs = []
+fix_spec(all_structs)
+del all_structs
diff --git a/clients/python/custos/profile/model/User/__init__.py b/clients/python/custos/profile/model/User/__init__.py
new file mode 100644
index 0000000..adefd8e
--- /dev/null
+++ b/clients/python/custos/profile/model/User/__init__.py
@@ -0,0 +1 @@
+__all__ = ['ttypes', 'constants']
diff --git a/clients/python/custos/profile/model/User/constants.py b/clients/python/custos/profile/model/User/constants.py
new file mode 100644
index 0000000..5cf48c3
--- /dev/null
+++ b/clients/python/custos/profile/model/User/constants.py
@@ -0,0 +1,16 @@
+#
+# Autogenerated by Thrift Compiler (0.12.0)
+#
+# DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
+#
+#  options string: py
+#
+
+from thrift.Thrift import TType, TMessageType, TFrozenDict, TException, TApplicationException
+from thrift.protocol.TProtocol import TProtocolException
+from thrift.TRecursive import fix_spec
+
+import sys
+from .ttypes import *
+USER_PROFILE_VERSION = "1.0"
+DEFAULT_ID = "DO_NOT_SET_AT_CLIENTS"
diff --git a/clients/python/custos/profile/model/User/ttypes.py b/clients/python/custos/profile/model/User/ttypes.py
new file mode 100644
index 0000000..85a1b2b
--- /dev/null
+++ b/clients/python/custos/profile/model/User/ttypes.py
@@ -0,0 +1,788 @@
+#
+# Autogenerated by Thrift Compiler (0.12.0)
+#
+# DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
+#
+#  options string: py
+#
+
+from thrift.Thrift import TType, TMessageType, TFrozenDict, TException, TApplicationException
+from thrift.protocol.TProtocol import TProtocolException
+from thrift.TRecursive import fix_spec
+
+import sys
+
+from thrift.transport import TTransport
+all_structs = []
+
+
+class Status(object):
+    ACTIVE = 0
+    CONFIRMED = 1
+    APPROVED = 2
+    DELETED = 3
+    DUPLICATE = 4
+    GRACE_PERIOD = 5
+    INVITED = 6
+    DENIED = 7
+    PENDING = 8
+    PENDING_APPROVAL = 9
+    PENDING_CONFIRMATION = 10
+    SUSPENDED = 11
+    DECLINED = 12
+    EXPIRED = 13
+
+    _VALUES_TO_NAMES = {
+        0: "ACTIVE",
+        1: "CONFIRMED",
+        2: "APPROVED",
+        3: "DELETED",
+        4: "DUPLICATE",
+        5: "GRACE_PERIOD",
+        6: "INVITED",
+        7: "DENIED",
+        8: "PENDING",
+        9: "PENDING_APPROVAL",
+        10: "PENDING_CONFIRMATION",
+        11: "SUSPENDED",
+        12: "DECLINED",
+        13: "EXPIRED",
+    }
+
+    _NAMES_TO_VALUES = {
+        "ACTIVE": 0,
+        "CONFIRMED": 1,
+        "APPROVED": 2,
+        "DELETED": 3,
+        "DUPLICATE": 4,
+        "GRACE_PERIOD": 5,
+        "INVITED": 6,
+        "DENIED": 7,
+        "PENDING": 8,
+        "PENDING_APPROVAL": 9,
+        "PENDING_CONFIRMATION": 10,
+        "SUSPENDED": 11,
+        "DECLINED": 12,
+        "EXPIRED": 13,
+    }
+
+
+class USCitizenship(object):
+    """
+    U.S. Citizen (see: http://en.wikipedia.org/wiki/ISO_3166-1_alpha-2)
+
+
+    """
+    US_CITIZEN = 0
+    US_PERMANENT_RESIDENT = 1
+    OTHER_NON_US_CITIZEN = 2
+
+    _VALUES_TO_NAMES = {
+        0: "US_CITIZEN",
+        1: "US_PERMANENT_RESIDENT",
+        2: "OTHER_NON_US_CITIZEN",
+    }
+
+    _NAMES_TO_VALUES = {
+        "US_CITIZEN": 0,
+        "US_PERMANENT_RESIDENT": 1,
+        "OTHER_NON_US_CITIZEN": 2,
+    }
+
+
+class ethnicity(object):
+    """
+    Hispanic or Latino - a person of Mexican, Puerto Rican, Cuban, South or
+     Central American, or other Spanish culture or origin, regardless of race.
+
+
+    """
+    HISPANIC_LATINO = 0
+    NOT_HISPANIC_LATINO = 1
+
+    _VALUES_TO_NAMES = {
+        0: "HISPANIC_LATINO",
+        1: "NOT_HISPANIC_LATINO",
+    }
+
+    _NAMES_TO_VALUES = {
+        "HISPANIC_LATINO": 0,
+        "NOT_HISPANIC_LATINO": 1,
+    }
+
+
+class race(object):
+    """
+    * Asian - a person having origins in any of the original peoples of the Far East,
+    *      Southeast Asia, or the Indian subcontinent including, for example, Cambodia,
+     *      China, India, Japan, Korea, Malaysia, Pakistan, the Philippine Islands,
+     *      Thailand, and Vietnam.
+    * American Indian or Alaskan Native - a person having origins in any of the original
+     *     peoples of North and South America (including Central America), and who maintains
+      *     tribal affiliation or community attachment.
+    * Black or African American - a person having origins in any of the black racial groups
+    *      of Africa.
+    * Native Hawaiian or Pacific Islander - a person having origins in any of the original
+    *      peoples of Hawaii, Guan, Samoa, or other Pacific Islands.
+    * White - a person having origins in any of the original peoples of Europe, the Middle East, or North Africa.
+    *
+
+    """
+    ASIAN = 0
+    AMERICAN_INDIAN_OR_ALASKAN_NATIVE = 1
+    BLACK_OR_AFRICAN_AMERICAN = 2
+    NATIVE_HAWAIIAN_OR_PACIFIC_ISLANDER = 3
+    WHITE = 4
+
+    _VALUES_TO_NAMES = {
+        0: "ASIAN",
+        1: "AMERICAN_INDIAN_OR_ALASKAN_NATIVE",
+        2: "BLACK_OR_AFRICAN_AMERICAN",
+        3: "NATIVE_HAWAIIAN_OR_PACIFIC_ISLANDER",
+        4: "WHITE",
+    }
+
+    _NAMES_TO_VALUES = {
+        "ASIAN": 0,
+        "AMERICAN_INDIAN_OR_ALASKAN_NATIVE": 1,
+        "BLACK_OR_AFRICAN_AMERICAN": 2,
+        "NATIVE_HAWAIIAN_OR_PACIFIC_ISLANDER": 3,
+        "WHITE": 4,
+    }
+
+
+class disability(object):
+    HEARING_IMAPAIRED = 0
+    VISUAL_IMPAIRED = 1
+    MOBILITY_OR_ORTHOPEDIC_IMPAIRMENT = 2
+    OTHER_IMPAIRMENT = 3
+
+    _VALUES_TO_NAMES = {
+        0: "HEARING_IMAPAIRED",
+        1: "VISUAL_IMPAIRED",
+        2: "MOBILITY_OR_ORTHOPEDIC_IMPAIRMENT",
+        3: "OTHER_IMPAIRMENT",
+    }
+
+    _NAMES_TO_VALUES = {
+        "HEARING_IMAPAIRED": 0,
+        "VISUAL_IMPAIRED": 1,
+        "MOBILITY_OR_ORTHOPEDIC_IMPAIRMENT": 2,
+        "OTHER_IMPAIRMENT": 3,
+    }
+
+
+class NSFDemographics(object):
+    """
+    A structure holding the NSF Demographic information.
+
+
+
+    Attributes:
+     - custosInternalUserId
+     - gender
+     - usCitizenship
+     - ethnicities
+     - races
+     - disabilities
+
+    """
+
+
+    def __init__(self, custosInternalUserId="DO_NOT_SET_AT_CLIENTS", gender=None, usCitizenship=None, ethnicities=None, races=None, disabilities=None,):
+        self.custosInternalUserId = custosInternalUserId
+        self.gender = gender
+        self.usCitizenship = usCitizenship
+        self.ethnicities = ethnicities
+        self.races = races
+        self.disabilities = disabilities
+
+    def read(self, iprot):
+        if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None:
+            iprot._fast_decode(self, iprot, [self.__class__, self.thrift_spec])
+            return
+        iprot.readStructBegin()
+        while True:
+            (fname, ftype, fid) = iprot.readFieldBegin()
+            if ftype == TType.STOP:
+                break
+            if fid == 1:
+                if ftype == TType.STRING:
+                    self.custosInternalUserId = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
+                else:
+                    iprot.skip(ftype)
+            elif fid == 2:
+                if ftype == TType.STRING:
+                    self.gender = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
+                else:
+                    iprot.skip(ftype)
+            elif fid == 3:
+                if ftype == TType.I32:
+                    self.usCitizenship = iprot.readI32()
+                else:
+                    iprot.skip(ftype)
+            elif fid == 4:
+                if ftype == TType.LIST:
+                    self.ethnicities = []
+                    (_etype3, _size0) = iprot.readListBegin()
+                    for _i4 in range(_size0):
+                        _elem5 = iprot.readI32()
+                        self.ethnicities.append(_elem5)
+                    iprot.readListEnd()
+                else:
+                    iprot.skip(ftype)
+            elif fid == 5:
+                if ftype == TType.LIST:
+                    self.races = []
+                    (_etype9, _size6) = iprot.readListBegin()
+                    for _i10 in range(_size6):
+                        _elem11 = iprot.readI32()
+                        self.races.append(_elem11)
+                    iprot.readListEnd()
+                else:
+                    iprot.skip(ftype)
+            elif fid == 6:
+                if ftype == TType.LIST:
+                    self.disabilities = []
+                    (_etype15, _size12) = iprot.readListBegin()
+                    for _i16 in range(_size12):
+                        _elem17 = iprot.readI32()
+                        self.disabilities.append(_elem17)
+                    iprot.readListEnd()
+                else:
+                    iprot.skip(ftype)
+            else:
+                iprot.skip(ftype)
+            iprot.readFieldEnd()
+        iprot.readStructEnd()
+
+    def write(self, oprot):
+        if oprot._fast_encode is not None and self.thrift_spec is not None:
+            oprot.trans.write(oprot._fast_encode(self, [self.__class__, self.thrift_spec]))
+            return
+        oprot.writeStructBegin('NSFDemographics')
+        if self.custosInternalUserId is not None:
+            oprot.writeFieldBegin('custosInternalUserId', TType.STRING, 1)
+            oprot.writeString(self.custosInternalUserId.encode('utf-8') if sys.version_info[0] == 2 else self.custosInternalUserId)
+            oprot.writeFieldEnd()
+        if self.gender is not None:
+            oprot.writeFieldBegin('gender', TType.STRING, 2)
+            oprot.writeString(self.gender.encode('utf-8') if sys.version_info[0] == 2 else self.gender)
+            oprot.writeFieldEnd()
+        if self.usCitizenship is not None:
+            oprot.writeFieldBegin('usCitizenship', TType.I32, 3)
+            oprot.writeI32(self.usCitizenship)
+            oprot.writeFieldEnd()
+        if self.ethnicities is not None:
+            oprot.writeFieldBegin('ethnicities', TType.LIST, 4)
+            oprot.writeListBegin(TType.I32, len(self.ethnicities))
+            for iter18 in self.ethnicities:
+                oprot.writeI32(iter18)
+            oprot.writeListEnd()
+            oprot.writeFieldEnd()
+        if self.races is not None:
+            oprot.writeFieldBegin('races', TType.LIST, 5)
+            oprot.writeListBegin(TType.I32, len(self.races))
+            for iter19 in self.races:
+                oprot.writeI32(iter19)
+            oprot.writeListEnd()
+            oprot.writeFieldEnd()
+        if self.disabilities is not None:
+            oprot.writeFieldBegin('disabilities', TType.LIST, 6)
+            oprot.writeListBegin(TType.I32, len(self.disabilities))
+            for iter20 in self.disabilities:
+                oprot.writeI32(iter20)
+            oprot.writeListEnd()
+            oprot.writeFieldEnd()
+        oprot.writeFieldStop()
+        oprot.writeStructEnd()
+
+    def validate(self):
+        if self.custosInternalUserId is None:
+            raise TProtocolException(message='Required field custosInternalUserId is unset!')
+        return
+
+    def __repr__(self):
+        L = ['%s=%r' % (key, value)
+             for key, value in self.__dict__.items()]
+        return '%s(%s)' % (self.__class__.__name__, ', '.join(L))
+
+    def __eq__(self, other):
+        return isinstance(other, self.__class__) and self.__dict__ == other.__dict__
+
+    def __ne__(self, other):
+        return not (self == other)
+
+
+class UserProfile(object):
+    """
+    * A structure holding the user profile and its child models.
+    *
+    * Notes:
+    *  The model does not include passwords as it is assumed an external identity provider is used to authenticate user.
+    *  References:
+    *     NSF Demographic Information - http://www.nsf.gov/pubs/2000/00form1225/00form1225.doc
+    *     LDAP Schema - https://tools.ietf.org/html/rfc4519
+    *     SCIM 2.0 - https://tools.ietf.org/html/rfc7643
+    *
+    * userModelVersion:
+    *  Version number of profile
+    *
+    * custosInternalUserId:
+    *  internal to custos, not intended to be used outside of the custos platform or possibly by gateways
+    *  (that is, never shown to users), never reassigned, REQUIRED
+    *
+    * userId:
+    *  Externally assertable unique identifier. SAML (primarly in higher education, academic) tends to keep
+    *   user name less opaque. OpenID Connect maintains them to be opaque.
+    *
+    * firstName, middleName, lastName:
+    *  First and Last names as assertede by the user
+    *
+    * namePrefix, nameSuffix:
+    *  prefix and suffix to the users name as asserted by the user
+    *
+    * emails:
+    *   Email identifier are Verified, REQUIRED and MULTIVALUED
+    *
+    * userName:
+    *  Name-based identifiers can be multivalues. To keep it simple, custos will make it a string.
+    *   In the future these can be enumerated as:
+        *   Official name (as asserted possibly by some external identity provider)
+        *   Prefered name (as asserted or suggested by user directly)
+        *   Components:
+        *      givenName
+        *      surname (familyName)
+        *      displayName (often asserted by user to handle things like middle names, suffix, prefix, and the like)
+    *
+    * orcidId: ORCID ID - http://orcid.org/about/what-is-orcid)
+    *
+    * phones: Telephone MULTIVALUED
+    *
+    * country: Country of Residance
+    *
+    * nationality Countries of citizenship
+    *
+    * comments:
+    *   Free-form information (treated as opaque by custos and simply passed to resource).
+    *
+    * labeledURI:
+      * Google Scholar, Web of Science, ACS, e.t.c
+    *
+    * timeZone:
+    *  User’s preferred timezone - IANA Timezone Databases - http://www.iana.org/time-zones.
+    *
+
+    Attributes:
+     - userModelVersion
+     - custosInternalUserId
+     - userId
+     - gatewayId
+     - emails
+     - firstName
+     - lastName
+     - middleName
+     - namePrefix
+     - nameSuffix
+     - orcidId
+     - phones
+     - country
+     - nationality
+     - homeOrganization
+     - orginationAffiliation
+     - creationTime
+     - lastAccessTime
+     - validUntil
+     - State
+     - comments
+     - labeledURI
+     - gpgKey
+     - timeZone
+     - nsfDemographics
+
+    """
+
+
+    def __init__(self, userModelVersion="1.0", custosInternalUserId="DO_NOT_SET_AT_CLIENTS", userId=None, gatewayId=None, emails=None, firstName=None, lastName=None, middleName=None, namePrefix=None, nameSuffix=None, orcidId=None, phones=None, country=None, nationality=None, homeOrganization=None, orginationAffiliation=None, creationTime=None, lastAccessTime=None, validUntil=None, State=None, comments=None, labeledURI=None, gpgKey=None, timeZone=None, nsfDemographics=None,):
+        self.userModelVersion = userModelVersion
+        self.custosInternalUserId = custosInternalUserId
+        self.userId = userId
+        self.gatewayId = gatewayId
+        self.emails = emails
+        self.firstName = firstName
+        self.lastName = lastName
+        self.middleName = middleName
+        self.namePrefix = namePrefix
+        self.nameSuffix = nameSuffix
+        self.orcidId = orcidId
+        self.phones = phones
+        self.country = country
+        self.nationality = nationality
+        self.homeOrganization = homeOrganization
+        self.orginationAffiliation = orginationAffiliation
+        self.creationTime = creationTime
+        self.lastAccessTime = lastAccessTime
+        self.validUntil = validUntil
+        self.State = State
+        self.comments = comments
+        self.labeledURI = labeledURI
+        self.gpgKey = gpgKey
+        self.timeZone = timeZone
+        self.nsfDemographics = nsfDemographics
+
+    def read(self, iprot):
+        if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None:
+            iprot._fast_decode(self, iprot, [self.__class__, self.thrift_spec])
+            return
+        iprot.readStructBegin()
+        while True:
+            (fname, ftype, fid) = iprot.readFieldBegin()
+            if ftype == TType.STOP:
+                break
+            if fid == 1:
+                if ftype == TType.STRING:
+                    self.userModelVersion = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
+                else:
+                    iprot.skip(ftype)
+            elif fid == 2:
+                if ftype == TType.STRING:
+                    self.custosInternalUserId = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
+                else:
+                    iprot.skip(ftype)
+            elif fid == 3:
+                if ftype == TType.STRING:
+                    self.userId = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
+                else:
+                    iprot.skip(ftype)
+            elif fid == 4:
+                if ftype == TType.STRING:
+                    self.gatewayId = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
+                else:
+                    iprot.skip(ftype)
+            elif fid == 5:
+                if ftype == TType.LIST:
+                    self.emails = []
+                    (_etype24, _size21) = iprot.readListBegin()
+                    for _i25 in range(_size21):
+                        _elem26 = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
+                        self.emails.append(_elem26)
+                    iprot.readListEnd()
+                else:
+                    iprot.skip(ftype)
+            elif fid == 6:
+                if ftype == TType.STRING:
+                    self.firstName = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
+                else:
+                    iprot.skip(ftype)
+            elif fid == 7:
+                if ftype == TType.STRING:
+                    self.lastName = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
+                else:
+                    iprot.skip(ftype)
+            elif fid == 8:
+                if ftype == TType.STRING:
+                    self.middleName = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
+                else:
+                    iprot.skip(ftype)
+            elif fid == 9:
+                if ftype == TType.STRING:
+                    self.namePrefix = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
+                else:
+                    iprot.skip(ftype)
+            elif fid == 10:
+                if ftype == TType.STRING:
+                    self.nameSuffix = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
+                else:
+                    iprot.skip(ftype)
+            elif fid == 11:
+                if ftype == TType.STRING:
+                    self.orcidId = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
+                else:
+                    iprot.skip(ftype)
+            elif fid == 12:
+                if ftype == TType.LIST:
+                    self.phones = []
+                    (_etype30, _size27) = iprot.readListBegin()
+                    for _i31 in range(_size27):
+                        _elem32 = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
+                        self.phones.append(_elem32)
+                    iprot.readListEnd()
+                else:
+                    iprot.skip(ftype)
+            elif fid == 13:
+                if ftype == TType.STRING:
+                    self.country = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
+                else:
+                    iprot.skip(ftype)
+            elif fid == 14:
+                if ftype == TType.LIST:
+                    self.nationality = []
+                    (_etype36, _size33) = iprot.readListBegin()
+                    for _i37 in range(_size33):
+                        _elem38 = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
+                        self.nationality.append(_elem38)
+                    iprot.readListEnd()
+                else:
+                    iprot.skip(ftype)
+            elif fid == 15:
+                if ftype == TType.STRING:
+                    self.homeOrganization = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
+                else:
+                    iprot.skip(ftype)
+            elif fid == 16:
+                if ftype == TType.STRING:
+                    self.orginationAffiliation = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
+                else:
+                    iprot.skip(ftype)
+            elif fid == 17:
+                if ftype == TType.I64:
+                    self.creationTime = iprot.readI64()
+                else:
+                    iprot.skip(ftype)
+            elif fid == 18:
+                if ftype == TType.I64:
+                    self.lastAccessTime = iprot.readI64()
+                else:
+                    iprot.skip(ftype)
+            elif fid == 19:
+                if ftype == TType.I64:
+                    self.validUntil = iprot.readI64()
+                else:
+                    iprot.skip(ftype)
+            elif fid == 20:
+                if ftype == TType.I32:
+                    self.State = iprot.readI32()
+                else:
+                    iprot.skip(ftype)
+            elif fid == 21:
+                if ftype == TType.STRING:
+                    self.comments = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
+                else:
+                    iprot.skip(ftype)
+            elif fid == 22:
+                if ftype == TType.LIST:
+                    self.labeledURI = []
+                    (_etype42, _size39) = iprot.readListBegin()
+                    for _i43 in range(_size39):
+                        _elem44 = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
+                        self.labeledURI.append(_elem44)
+                    iprot.readListEnd()
+                else:
+                    iprot.skip(ftype)
+            elif fid == 23:
+                if ftype == TType.STRING:
+                    self.gpgKey = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
+                else:
+                    iprot.skip(ftype)
+            elif fid == 24:
+                if ftype == TType.STRING:
+                    self.timeZone = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
+                else:
+                    iprot.skip(ftype)
+            elif fid == 25:
+                if ftype == TType.STRUCT:
+                    self.nsfDemographics = NSFDemographics()
+                    self.nsfDemographics.read(iprot)
+                else:
+                    iprot.skip(ftype)
+            else:
+                iprot.skip(ftype)
+            iprot.readFieldEnd()
+        iprot.readStructEnd()
+
+    def write(self, oprot):
+        if oprot._fast_encode is not None and self.thrift_spec is not None:
+            oprot.trans.write(oprot._fast_encode(self, [self.__class__, self.thrift_spec]))
+            return
+        oprot.writeStructBegin('UserProfile')
+        if self.userModelVersion is not None:
+            oprot.writeFieldBegin('userModelVersion', TType.STRING, 1)
+            oprot.writeString(self.userModelVersion.encode('utf-8') if sys.version_info[0] == 2 else self.userModelVersion)
+            oprot.writeFieldEnd()
+        if self.custosInternalUserId is not None:
+            oprot.writeFieldBegin('custosInternalUserId', TType.STRING, 2)
+            oprot.writeString(self.custosInternalUserId.encode('utf-8') if sys.version_info[0] == 2 else self.custosInternalUserId)
+            oprot.writeFieldEnd()
+        if self.userId is not None:
+            oprot.writeFieldBegin('userId', TType.STRING, 3)
+            oprot.writeString(self.userId.encode('utf-8') if sys.version_info[0] == 2 else self.userId)
+            oprot.writeFieldEnd()
+        if self.gatewayId is not None:
+            oprot.writeFieldBegin('gatewayId', TType.STRING, 4)
+            oprot.writeString(self.gatewayId.encode('utf-8') if sys.version_info[0] == 2 else self.gatewayId)
+            oprot.writeFieldEnd()
+        if self.emails is not None:
+            oprot.writeFieldBegin('emails', TType.LIST, 5)
+            oprot.writeListBegin(TType.STRING, len(self.emails))
+            for iter45 in self.emails:
+                oprot.writeString(iter45.encode('utf-8') if sys.version_info[0] == 2 else iter45)
+            oprot.writeListEnd()
+            oprot.writeFieldEnd()
+        if self.firstName is not None:
+            oprot.writeFieldBegin('firstName', TType.STRING, 6)
+            oprot.writeString(self.firstName.encode('utf-8') if sys.version_info[0] == 2 else self.firstName)
+            oprot.writeFieldEnd()
+        if self.lastName is not None:
+            oprot.writeFieldBegin('lastName', TType.STRING, 7)
+            oprot.writeString(self.lastName.encode('utf-8') if sys.version_info[0] == 2 else self.lastName)
+            oprot.writeFieldEnd()
+        if self.middleName is not None:
+            oprot.writeFieldBegin('middleName', TType.STRING, 8)
+            oprot.writeString(self.middleName.encode('utf-8') if sys.version_info[0] == 2 else self.middleName)
+            oprot.writeFieldEnd()
+        if self.namePrefix is not None:
+            oprot.writeFieldBegin('namePrefix', TType.STRING, 9)
+            oprot.writeString(self.namePrefix.encode('utf-8') if sys.version_info[0] == 2 else self.namePrefix)
+            oprot.writeFieldEnd()
+        if self.nameSuffix is not None:
+            oprot.writeFieldBegin('nameSuffix', TType.STRING, 10)
+            oprot.writeString(self.nameSuffix.encode('utf-8') if sys.version_info[0] == 2 else self.nameSuffix)
+            oprot.writeFieldEnd()
+        if self.orcidId is not None:
+            oprot.writeFieldBegin('orcidId', TType.STRING, 11)
+            oprot.writeString(self.orcidId.encode('utf-8') if sys.version_info[0] == 2 else self.orcidId)
+            oprot.writeFieldEnd()
+        if self.phones is not None:
+            oprot.writeFieldBegin('phones', TType.LIST, 12)
+            oprot.writeListBegin(TType.STRING, len(self.phones))
+            for iter46 in self.phones:
+                oprot.writeString(iter46.encode('utf-8') if sys.version_info[0] == 2 else iter46)
+            oprot.writeListEnd()
+            oprot.writeFieldEnd()
+        if self.country is not None:
+            oprot.writeFieldBegin('country', TType.STRING, 13)
+            oprot.writeString(self.country.encode('utf-8') if sys.version_info[0] == 2 else self.country)
+            oprot.writeFieldEnd()
+        if self.nationality is not None:
+            oprot.writeFieldBegin('nationality', TType.LIST, 14)
+            oprot.writeListBegin(TType.STRING, len(self.nationality))
+            for iter47 in self.nationality:
+                oprot.writeString(iter47.encode('utf-8') if sys.version_info[0] == 2 else iter47)
+            oprot.writeListEnd()
+            oprot.writeFieldEnd()
+        if self.homeOrganization is not None:
+            oprot.writeFieldBegin('homeOrganization', TType.STRING, 15)
+            oprot.writeString(self.homeOrganization.encode('utf-8') if sys.version_info[0] == 2 else self.homeOrganization)
+            oprot.writeFieldEnd()
+        if self.orginationAffiliation is not None:
+            oprot.writeFieldBegin('orginationAffiliation', TType.STRING, 16)
+            oprot.writeString(self.orginationAffiliation.encode('utf-8') if sys.version_info[0] == 2 else self.orginationAffiliation)
+            oprot.writeFieldEnd()
+        if self.creationTime is not None:
+            oprot.writeFieldBegin('creationTime', TType.I64, 17)
+            oprot.writeI64(self.creationTime)
+            oprot.writeFieldEnd()
+        if self.lastAccessTime is not None:
+            oprot.writeFieldBegin('lastAccessTime', TType.I64, 18)
+            oprot.writeI64(self.lastAccessTime)
+            oprot.writeFieldEnd()
+        if self.validUntil is not None:
+            oprot.writeFieldBegin('validUntil', TType.I64, 19)
+            oprot.writeI64(self.validUntil)
+            oprot.writeFieldEnd()
+        if self.State is not None:
+            oprot.writeFieldBegin('State', TType.I32, 20)
+            oprot.writeI32(self.State)
+            oprot.writeFieldEnd()
+        if self.comments is not None:
+            oprot.writeFieldBegin('comments', TType.STRING, 21)
+            oprot.writeString(self.comments.encode('utf-8') if sys.version_info[0] == 2 else self.comments)
+            oprot.writeFieldEnd()
+        if self.labeledURI is not None:
+            oprot.writeFieldBegin('labeledURI', TType.LIST, 22)
+            oprot.writeListBegin(TType.STRING, len(self.labeledURI))
+            for iter48 in self.labeledURI:
+                oprot.writeString(iter48.encode('utf-8') if sys.version_info[0] == 2 else iter48)
+            oprot.writeListEnd()
+            oprot.writeFieldEnd()
+        if self.gpgKey is not None:
+            oprot.writeFieldBegin('gpgKey', TType.STRING, 23)
+            oprot.writeString(self.gpgKey.encode('utf-8') if sys.version_info[0] == 2 else self.gpgKey)
+            oprot.writeFieldEnd()
+        if self.timeZone is not None:
+            oprot.writeFieldBegin('timeZone', TType.STRING, 24)
+            oprot.writeString(self.timeZone.encode('utf-8') if sys.version_info[0] == 2 else self.timeZone)
+            oprot.writeFieldEnd()
+        if self.nsfDemographics is not None:
+            oprot.writeFieldBegin('nsfDemographics', TType.STRUCT, 25)
+            self.nsfDemographics.write(oprot)
+            oprot.writeFieldEnd()
+        oprot.writeFieldStop()
+        oprot.writeStructEnd()
+
+    def validate(self):
+        if self.userModelVersion is None:
+            raise TProtocolException(message='Required field userModelVersion is unset!')
+        if self.custosInternalUserId is None:
+            raise TProtocolException(message='Required field custosInternalUserId is unset!')
+        if self.userId is None:
+            raise TProtocolException(message='Required field userId is unset!')
+        if self.gatewayId is None:
+            raise TProtocolException(message='Required field gatewayId is unset!')
+        if self.emails is None:
+            raise TProtocolException(message='Required field emails is unset!')
+        if self.firstName is None:
+            raise TProtocolException(message='Required field firstName is unset!')
+        if self.lastName is None:
+            raise TProtocolException(message='Required field lastName is unset!')
+        if self.creationTime is None:
+            raise TProtocolException(message='Required field creationTime is unset!')
+        if self.lastAccessTime is None:
+            raise TProtocolException(message='Required field lastAccessTime is unset!')
+        if self.validUntil is None:
+            raise TProtocolException(message='Required field validUntil is unset!')
+        if self.State is None:
+            raise TProtocolException(message='Required field State is unset!')
+        return
+
+    def __repr__(self):
+        L = ['%s=%r' % (key, value)
+             for key, value in self.__dict__.items()]
+        return '%s(%s)' % (self.__class__.__name__, ', '.join(L))
+
+    def __eq__(self, other):
+        return isinstance(other, self.__class__) and self.__dict__ == other.__dict__
+
+    def __ne__(self, other):
+        return not (self == other)
+all_structs.append(NSFDemographics)
+NSFDemographics.thrift_spec = (
+    None,  # 0
+    (1, TType.STRING, 'custosInternalUserId', 'UTF8', "DO_NOT_SET_AT_CLIENTS", ),  # 1
+    (2, TType.STRING, 'gender', 'UTF8', None, ),  # 2
+    (3, TType.I32, 'usCitizenship', None, None, ),  # 3
+    (4, TType.LIST, 'ethnicities', (TType.I32, None, False), None, ),  # 4
+    (5, TType.LIST, 'races', (TType.I32, None, False), None, ),  # 5
+    (6, TType.LIST, 'disabilities', (TType.I32, None, False), None, ),  # 6
+)
+all_structs.append(UserProfile)
+UserProfile.thrift_spec = (
+    None,  # 0
+    (1, TType.STRING, 'userModelVersion', 'UTF8', "1.0", ),  # 1
+    (2, TType.STRING, 'custosInternalUserId', 'UTF8', "DO_NOT_SET_AT_CLIENTS", ),  # 2
+    (3, TType.STRING, 'userId', 'UTF8', None, ),  # 3
+    (4, TType.STRING, 'gatewayId', 'UTF8', None, ),  # 4
+    (5, TType.LIST, 'emails', (TType.STRING, 'UTF8', False), None, ),  # 5
+    (6, TType.STRING, 'firstName', 'UTF8', None, ),  # 6
+    (7, TType.STRING, 'lastName', 'UTF8', None, ),  # 7
+    (8, TType.STRING, 'middleName', 'UTF8', None, ),  # 8
+    (9, TType.STRING, 'namePrefix', 'UTF8', None, ),  # 9
+    (10, TType.STRING, 'nameSuffix', 'UTF8', None, ),  # 10
+    (11, TType.STRING, 'orcidId', 'UTF8', None, ),  # 11
+    (12, TType.LIST, 'phones', (TType.STRING, 'UTF8', False), None, ),  # 12
+    (13, TType.STRING, 'country', 'UTF8', None, ),  # 13
+    (14, TType.LIST, 'nationality', (TType.STRING, 'UTF8', False), None, ),  # 14
+    (15, TType.STRING, 'homeOrganization', 'UTF8', None, ),  # 15
+    (16, TType.STRING, 'orginationAffiliation', 'UTF8', None, ),  # 16
+    (17, TType.I64, 'creationTime', None, None, ),  # 17
+    (18, TType.I64, 'lastAccessTime', None, None, ),  # 18
+    (19, TType.I64, 'validUntil', None, None, ),  # 19
+    (20, TType.I32, 'State', None, None, ),  # 20
+    (21, TType.STRING, 'comments', 'UTF8', None, ),  # 21
+    (22, TType.LIST, 'labeledURI', (TType.STRING, 'UTF8', False), None, ),  # 22
+    (23, TType.STRING, 'gpgKey', 'UTF8', None, ),  # 23
+    (24, TType.STRING, 'timeZone', 'UTF8', None, ),  # 24
+    (25, TType.STRUCT, 'nsfDemographics', [NSFDemographics, None], None, ),  # 25
+)
+fix_spec(all_structs)
+del all_structs
diff --git a/clients/python/custos/profile/model/__init__.py b/clients/python/custos/profile/model/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/clients/python/custos/profile/model/tenant/__init__.py b/clients/python/custos/profile/model/tenant/__init__.py
new file mode 100644
index 0000000..adefd8e
--- /dev/null
+++ b/clients/python/custos/profile/model/tenant/__init__.py
@@ -0,0 +1 @@
+__all__ = ['ttypes', 'constants']
diff --git a/clients/python/custos/profile/model/tenant/constants.py b/clients/python/custos/profile/model/tenant/constants.py
new file mode 100644
index 0000000..c59352d
--- /dev/null
+++ b/clients/python/custos/profile/model/tenant/constants.py
@@ -0,0 +1,14 @@
+#
+# Autogenerated by Thrift Compiler (0.12.0)
+#
+# DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
+#
+#  options string: py
+#
+
+from thrift.Thrift import TType, TMessageType, TFrozenDict, TException, TApplicationException
+from thrift.protocol.TProtocol import TProtocolException
+from thrift.TRecursive import fix_spec
+
+import sys
+from .ttypes import *
diff --git a/clients/python/custos/profile/model/tenant/ttypes.py b/clients/python/custos/profile/model/tenant/ttypes.py
new file mode 100644
index 0000000..f216058
--- /dev/null
+++ b/clients/python/custos/profile/model/tenant/ttypes.py
@@ -0,0 +1,604 @@
+#
+# Autogenerated by Thrift Compiler (0.12.0)
+#
+# DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
+#
+#  options string: py
+#
+
+from thrift.Thrift import TType, TMessageType, TFrozenDict, TException, TApplicationException
+from thrift.protocol.TProtocol import TProtocolException
+from thrift.TRecursive import fix_spec
+
+import sys
+
+from thrift.transport import TTransport
+all_structs = []
+
+
+class TenantApprovalStatus(object):
+    REQUESTED = 0
+    APPROVED = 1
+    ACTIVE = 2
+    DEACTIVATED = 3
+    CANCELLED = 4
+    DENIED = 5
+    CREATED = 6
+    DEPLOYED = 7
+
+    _VALUES_TO_NAMES = {
+        0: "REQUESTED",
+        1: "APPROVED",
+        2: "ACTIVE",
+        3: "DEACTIVATED",
+        4: "CANCELLED",
+        5: "DENIED",
+        6: "CREATED",
+        7: "DEPLOYED",
+    }
+
+    _NAMES_TO_VALUES = {
+        "REQUESTED": 0,
+        "APPROVED": 1,
+        "ACTIVE": 2,
+        "DEACTIVATED": 3,
+        "CANCELLED": 4,
+        "DENIED": 5,
+        "CREATED": 6,
+        "DEPLOYED": 7,
+    }
+
+
+class TenantPreferences(object):
+    """
+    Attributes:
+     - tenantAdminFirstName
+     - tenantAdminLastName
+     - tenantAdminEmail
+
+    """
+
+
+    def __init__(self, tenantAdminFirstName=None, tenantAdminLastName=None, tenantAdminEmail=None,):
+        self.tenantAdminFirstName = tenantAdminFirstName
+        self.tenantAdminLastName = tenantAdminLastName
+        self.tenantAdminEmail = tenantAdminEmail
+
+    def read(self, iprot):
+        if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None:
+            iprot._fast_decode(self, iprot, [self.__class__, self.thrift_spec])
+            return
+        iprot.readStructBegin()
+        while True:
+            (fname, ftype, fid) = iprot.readFieldBegin()
+            if ftype == TType.STOP:
+                break
+            if fid == 10:
+                if ftype == TType.STRING:
+                    self.tenantAdminFirstName = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
+                else:
+                    iprot.skip(ftype)
+            elif fid == 11:
+                if ftype == TType.STRING:
+                    self.tenantAdminLastName = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
+                else:
+                    iprot.skip(ftype)
+            elif fid == 12:
+                if ftype == TType.STRING:
+                    self.tenantAdminEmail = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
+                else:
+                    iprot.skip(ftype)
+            else:
+                iprot.skip(ftype)
+            iprot.readFieldEnd()
+        iprot.readStructEnd()
+
+    def write(self, oprot):
+        if oprot._fast_encode is not None and self.thrift_spec is not None:
+            oprot.trans.write(oprot._fast_encode(self, [self.__class__, self.thrift_spec]))
+            return
+        oprot.writeStructBegin('TenantPreferences')
+        if self.tenantAdminFirstName is not None:
+            oprot.writeFieldBegin('tenantAdminFirstName', TType.STRING, 10)
+            oprot.writeString(self.tenantAdminFirstName.encode('utf-8') if sys.version_info[0] == 2 else self.tenantAdminFirstName)
+            oprot.writeFieldEnd()
+        if self.tenantAdminLastName is not None:
+            oprot.writeFieldBegin('tenantAdminLastName', TType.STRING, 11)
+            oprot.writeString(self.tenantAdminLastName.encode('utf-8') if sys.version_info[0] == 2 else self.tenantAdminLastName)
+            oprot.writeFieldEnd()
+        if self.tenantAdminEmail is not None:
+            oprot.writeFieldBegin('tenantAdminEmail', TType.STRING, 12)
+            oprot.writeString(self.tenantAdminEmail.encode('utf-8') if sys.version_info[0] == 2 else self.tenantAdminEmail)
+            oprot.writeFieldEnd()
+        oprot.writeFieldStop()
+        oprot.writeStructEnd()
+
+    def validate(self):
+        return
+
+    def __repr__(self):
+        L = ['%s=%r' % (key, value)
+             for key, value in self.__dict__.items()]
+        return '%s(%s)' % (self.__class__.__name__, ', '.join(L))
+
+    def __eq__(self, other):
+        return isinstance(other, self.__class__) and self.__dict__ == other.__dict__
+
+    def __ne__(self, other):
+        return not (self == other)
+
+
+class TenantConfig(object):
+    """
+    Attributes:
+     - oauthClientId
+     - oauthClientSecret
+     - identityServerUserName
+     - identityServerPasswordToken
+
+    """
+
+
+    def __init__(self, oauthClientId=None, oauthClientSecret=None, identityServerUserName=None, identityServerPasswordToken=None,):
+        self.oauthClientId = oauthClientId
+        self.oauthClientSecret = oauthClientSecret
+        self.identityServerUserName = identityServerUserName
+        self.identityServerPasswordToken = identityServerPasswordToken
+
+    def read(self, iprot):
+        if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None:
+            iprot._fast_decode(self, iprot, [self.__class__, self.thrift_spec])
+            return
+        iprot.readStructBegin()
+        while True:
+            (fname, ftype, fid) = iprot.readFieldBegin()
+            if ftype == TType.STOP:
+                break
+            if fid == 16:
+                if ftype == TType.STRING:
+                    self.oauthClientId = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
+                else:
+                    iprot.skip(ftype)
+            elif fid == 17:
+                if ftype == TType.STRING:
+                    self.oauthClientSecret = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
+                else:
+                    iprot.skip(ftype)
+            elif fid == 13:
+                if ftype == TType.STRING:
+                    self.identityServerUserName = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
+                else:
+                    iprot.skip(ftype)
+            elif fid == 14:
+                if ftype == TType.STRING:
+                    self.identityServerPasswordToken = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
+                else:
+                    iprot.skip(ftype)
+            else:
+                iprot.skip(ftype)
+            iprot.readFieldEnd()
+        iprot.readStructEnd()
+
+    def write(self, oprot):
+        if oprot._fast_encode is not None and self.thrift_spec is not None:
+            oprot.trans.write(oprot._fast_encode(self, [self.__class__, self.thrift_spec]))
+            return
+        oprot.writeStructBegin('TenantConfig')
+        if self.identityServerUserName is not None:
+            oprot.writeFieldBegin('identityServerUserName', TType.STRING, 13)
+            oprot.writeString(self.identityServerUserName.encode('utf-8') if sys.version_info[0] == 2 else self.identityServerUserName)
+            oprot.writeFieldEnd()
+        if self.identityServerPasswordToken is not None:
+            oprot.writeFieldBegin('identityServerPasswordToken', TType.STRING, 14)
+            oprot.writeString(self.identityServerPasswordToken.encode('utf-8') if sys.version_info[0] == 2 else self.identityServerPasswordToken)
+            oprot.writeFieldEnd()
+        if self.oauthClientId is not None:
+            oprot.writeFieldBegin('oauthClientId', TType.STRING, 16)
+            oprot.writeString(self.oauthClientId.encode('utf-8') if sys.version_info[0] == 2 else self.oauthClientId)
+            oprot.writeFieldEnd()
+        if self.oauthClientSecret is not None:
+            oprot.writeFieldBegin('oauthClientSecret', TType.STRING, 17)
+            oprot.writeString(self.oauthClientSecret.encode('utf-8') if sys.version_info[0] == 2 else self.oauthClientSecret)
+            oprot.writeFieldEnd()
+        oprot.writeFieldStop()
+        oprot.writeStructEnd()
+
+    def validate(self):
+        return
+
+    def __repr__(self):
+        L = ['%s=%r' % (key, value)
+             for key, value in self.__dict__.items()]
+        return '%s(%s)' % (self.__class__.__name__, ', '.join(L))
+
+    def __eq__(self, other):
+        return isinstance(other, self.__class__) and self.__dict__ == other.__dict__
+
+    def __ne__(self, other):
+        return not (self == other)
+
+
+class Tenant(object):
+    """
+    Attributes:
+     - tenantId
+     - tenantApprovalStatus
+     - tenantName
+     - domain
+     - emailAddress
+     - tenantAcronym
+     - tenantURL
+     - tenantPublicAbstract
+     - reviewProposalDescription
+     - declinedReason
+     - requestCreationTime
+     - requesterUsername
+
+    """
+
+
+    def __init__(self, tenantId=None, tenantApprovalStatus=None, tenantName=None, domain=None, emailAddress=None, tenantAcronym=None, tenantURL=None, tenantPublicAbstract=None, reviewProposalDescription=None, declinedReason=None, requestCreationTime=None, requesterUsername=None,):
+        self.tenantId = tenantId
+        self.tenantApprovalStatus = tenantApprovalStatus
+        self.tenantName = tenantName
+        self.domain = domain
+        self.emailAddress = emailAddress
+        self.tenantAcronym = tenantAcronym
+        self.tenantURL = tenantURL
+        self.tenantPublicAbstract = tenantPublicAbstract
+        self.reviewProposalDescription = reviewProposalDescription
+        self.declinedReason = declinedReason
+        self.requestCreationTime = requestCreationTime
+        self.requesterUsername = requesterUsername
+
+    def read(self, iprot):
+        if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None:
+            iprot._fast_decode(self, iprot, [self.__class__, self.thrift_spec])
+            return
+        iprot.readStructBegin()
+        while True:
+            (fname, ftype, fid) = iprot.readFieldBegin()
+            if ftype == TType.STOP:
+                break
+            if fid == 1:
+                if ftype == TType.STRING:
+                    self.tenantId = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
+                else:
+                    iprot.skip(ftype)
+            elif fid == 2:
+                if ftype == TType.I32:
+                    self.tenantApprovalStatus = iprot.readI32()
+                else:
+                    iprot.skip(ftype)
+            elif fid == 3:
+                if ftype == TType.STRING:
+                    self.tenantName = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
+                else:
+                    iprot.skip(ftype)
+            elif fid == 4:
+                if ftype == TType.STRING:
+                    self.domain = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
+                else:
+                    iprot.skip(ftype)
+            elif fid == 5:
+                if ftype == TType.STRING:
+                    self.emailAddress = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
+                else:
+                    iprot.skip(ftype)
+            elif fid == 6:
+                if ftype == TType.STRING:
+                    self.tenantAcronym = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
+                else:
+                    iprot.skip(ftype)
+            elif fid == 7:
+                if ftype == TType.STRING:
+                    self.tenantURL = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
+                else:
+                    iprot.skip(ftype)
+            elif fid == 8:
+                if ftype == TType.STRING:
+                    self.tenantPublicAbstract = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
+                else:
+                    iprot.skip(ftype)
+            elif fid == 9:
+                if ftype == TType.STRING:
+                    self.reviewProposalDescription = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
+                else:
+                    iprot.skip(ftype)
+            elif fid == 15:
+                if ftype == TType.STRING:
+                    self.declinedReason = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
+                else:
+                    iprot.skip(ftype)
+            elif fid == 18:
+                if ftype == TType.I64:
+                    self.requestCreationTime = iprot.readI64()
+                else:
+                    iprot.skip(ftype)
+            elif fid == 19:
+                if ftype == TType.STRING:
+                    self.requesterUsername = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
+                else:
+                    iprot.skip(ftype)
+            else:
+                iprot.skip(ftype)
+            iprot.readFieldEnd()
+        iprot.readStructEnd()
+
+    def write(self, oprot):
+        if oprot._fast_encode is not None and self.thrift_spec is not None:
+            oprot.trans.write(oprot._fast_encode(self, [self.__class__, self.thrift_spec]))
+            return
+        oprot.writeStructBegin('Tenant')
+        if self.tenantId is not None:
+            oprot.writeFieldBegin('tenantId', TType.STRING, 1)
+            oprot.writeString(self.tenantId.encode('utf-8') if sys.version_info[0] == 2 else self.tenantId)
+            oprot.writeFieldEnd()
+        if self.tenantApprovalStatus is not None:
+            oprot.writeFieldBegin('tenantApprovalStatus', TType.I32, 2)
+            oprot.writeI32(self.tenantApprovalStatus)
+            oprot.writeFieldEnd()
+        if self.tenantName is not None:
+            oprot.writeFieldBegin('tenantName', TType.STRING, 3)
+            oprot.writeString(self.tenantName.encode('utf-8') if sys.version_info[0] == 2 else self.tenantName)
+            oprot.writeFieldEnd()
+        if self.domain is not None:
+            oprot.writeFieldBegin('domain', TType.STRING, 4)
+            oprot.writeString(self.domain.encode('utf-8') if sys.version_info[0] == 2 else self.domain)
+            oprot.writeFieldEnd()
+        if self.emailAddress is not None:
+            oprot.writeFieldBegin('emailAddress', TType.STRING, 5)
+            oprot.writeString(self.emailAddress.encode('utf-8') if sys.version_info[0] == 2 else self.emailAddress)
+            oprot.writeFieldEnd()
+        if self.tenantAcronym is not None:
+            oprot.writeFieldBegin('tenantAcronym', TType.STRING, 6)
+            oprot.writeString(self.tenantAcronym.encode('utf-8') if sys.version_info[0] == 2 else self.tenantAcronym)
+            oprot.writeFieldEnd()
+        if self.tenantURL is not None:
+            oprot.writeFieldBegin('tenantURL', TType.STRING, 7)
+            oprot.writeString(self.tenantURL.encode('utf-8') if sys.version_info[0] == 2 else self.tenantURL)
+            oprot.writeFieldEnd()
+        if self.tenantPublicAbstract is not None:
+            oprot.writeFieldBegin('tenantPublicAbstract', TType.STRING, 8)
+            oprot.writeString(self.tenantPublicAbstract.encode('utf-8') if sys.version_info[0] == 2 else self.tenantPublicAbstract)
+            oprot.writeFieldEnd()
+        if self.reviewProposalDescription is not None:
+            oprot.writeFieldBegin('reviewProposalDescription', TType.STRING, 9)
+            oprot.writeString(self.reviewProposalDescription.encode('utf-8') if sys.version_info[0] == 2 else self.reviewProposalDescription)
+            oprot.writeFieldEnd()
+        if self.declinedReason is not None:
+            oprot.writeFieldBegin('declinedReason', TType.STRING, 15)
+            oprot.writeString(self.declinedReason.encode('utf-8') if sys.version_info[0] == 2 else self.declinedReason)
+            oprot.writeFieldEnd()
+        if self.requestCreationTime is not None:
+            oprot.writeFieldBegin('requestCreationTime', TType.I64, 18)
+            oprot.writeI64(self.requestCreationTime)
+            oprot.writeFieldEnd()
+        if self.requesterUsername is not None:
+            oprot.writeFieldBegin('requesterUsername', TType.STRING, 19)
+            oprot.writeString(self.requesterUsername.encode('utf-8') if sys.version_info[0] == 2 else self.requesterUsername)
+            oprot.writeFieldEnd()
+        oprot.writeFieldStop()
+        oprot.writeStructEnd()
+
+    def validate(self):
+        if self.tenantId is None:
+            raise TProtocolException(message='Required field tenantId is unset!')
+        if self.tenantApprovalStatus is None:
+            raise TProtocolException(message='Required field tenantApprovalStatus is unset!')
+        return
+
+    def __repr__(self):
+        L = ['%s=%r' % (key, value)
+             for key, value in self.__dict__.items()]
+        return '%s(%s)' % (self.__class__.__name__, ', '.join(L))
+
+    def __eq__(self, other):
+        return isinstance(other, self.__class__) and self.__dict__ == other.__dict__
+
+    def __ne__(self, other):
+        return not (self == other)
+
+
+class PasswordCredential(object):
+    """
+    Attributes:
+     - gatewayId
+     - portalUserName
+     - loginUserName
+     - password
+     - description
+     - persistedTime
+     - token
+
+    """
+
+
+    def __init__(self, gatewayId=None, portalUserName=None, loginUserName=None, password=None, description=None, persistedTime=None, token=None,):
+        self.gatewayId = gatewayId
+        self.portalUserName = portalUserName
+        self.loginUserName = loginUserName
+        self.password = password
+        self.description = description
+        self.persistedTime = persistedTime
+        self.token = token
+
+    def read(self, iprot):
+        if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None:
+            iprot._fast_decode(self, iprot, [self.__class__, self.thrift_spec])
+            return
+        iprot.readStructBegin()
+        while True:
+            (fname, ftype, fid) = iprot.readFieldBegin()
+            if ftype == TType.STOP:
+                break
+            if fid == 1:
+                if ftype == TType.STRING:
+                    self.gatewayId = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
+                else:
+                    iprot.skip(ftype)
+            elif fid == 2:
+                if ftype == TType.STRING:
+                    self.portalUserName = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
+                else:
+                    iprot.skip(ftype)
+            elif fid == 3:
+                if ftype == TType.STRING:
+                    self.loginUserName = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
+                else:
+                    iprot.skip(ftype)
+            elif fid == 4:
+                if ftype == TType.STRING:
+                    self.password = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
+                else:
+                    iprot.skip(ftype)
+            elif fid == 5:
+                if ftype == TType.STRING:
+                    self.description = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
+                else:
+                    iprot.skip(ftype)
+            elif fid == 6:
+                if ftype == TType.I64:
+                    self.persistedTime = iprot.readI64()
+                else:
+                    iprot.skip(ftype)
+            elif fid == 7:
+                if ftype == TType.STRING:
+                    self.token = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
+                else:
+                    iprot.skip(ftype)
+            else:
+                iprot.skip(ftype)
+            iprot.readFieldEnd()
+        iprot.readStructEnd()
+
+    def write(self, oprot):
+        if oprot._fast_encode is not None and self.thrift_spec is not None:
+            oprot.trans.write(oprot._fast_encode(self, [self.__class__, self.thrift_spec]))
+            return
+        oprot.writeStructBegin('PasswordCredential')
+        if self.gatewayId is not None:
+            oprot.writeFieldBegin('gatewayId', TType.STRING, 1)
+            oprot.writeString(self.gatewayId.encode('utf-8') if sys.version_info[0] == 2 else self.gatewayId)
+            oprot.writeFieldEnd()
+        if self.portalUserName is not None:
+            oprot.writeFieldBegin('portalUserName', TType.STRING, 2)
+            oprot.writeString(self.portalUserName.encode('utf-8') if sys.version_info[0] == 2 else self.portalUserName)
+            oprot.writeFieldEnd()
+        if self.loginUserName is not None:
+            oprot.writeFieldBegin('loginUserName', TType.STRING, 3)
+            oprot.writeString(self.loginUserName.encode('utf-8') if sys.version_info[0] == 2 else self.loginUserName)
+            oprot.writeFieldEnd()
+        if self.password is not None:
+            oprot.writeFieldBegin('password', TType.STRING, 4)
+            oprot.writeString(self.password.encode('utf-8') if sys.version_info[0] == 2 else self.password)
+            oprot.writeFieldEnd()
+        if self.description is not None:
+            oprot.writeFieldBegin('description', TType.STRING, 5)
+            oprot.writeString(self.description.encode('utf-8') if sys.version_info[0] == 2 else self.description)
+            oprot.writeFieldEnd()
+        if self.persistedTime is not None:
+            oprot.writeFieldBegin('persistedTime', TType.I64, 6)
+            oprot.writeI64(self.persistedTime)
+            oprot.writeFieldEnd()
+        if self.token is not None:
+            oprot.writeFieldBegin('token', TType.STRING, 7)
+            oprot.writeString(self.token.encode('utf-8') if sys.version_info[0] == 2 else self.token)
+            oprot.writeFieldEnd()
+        oprot.writeFieldStop()
+        oprot.writeStructEnd()
+
+    def validate(self):
+        if self.gatewayId is None:
+            raise TProtocolException(message='Required field gatewayId is unset!')
+        if self.portalUserName is None:
+            raise TProtocolException(message='Required field portalUserName is unset!')
+        if self.loginUserName is None:
+            raise TProtocolException(message='Required field loginUserName is unset!')
+        if self.password is None:
+            raise TProtocolException(message='Required field password is unset!')
+        return
+
+    def __repr__(self):
+        L = ['%s=%r' % (key, value)
+             for key, value in self.__dict__.items()]
+        return '%s(%s)' % (self.__class__.__name__, ', '.join(L))
+
+    def __eq__(self, other):
+        return isinstance(other, self.__class__) and self.__dict__ == other.__dict__
+
+    def __ne__(self, other):
+        return not (self == other)
+all_structs.append(TenantPreferences)
+TenantPreferences.thrift_spec = (
+    None,  # 0
+    None,  # 1
+    None,  # 2
+    None,  # 3
+    None,  # 4
+    None,  # 5
+    None,  # 6
+    None,  # 7
+    None,  # 8
+    None,  # 9
+    (10, TType.STRING, 'tenantAdminFirstName', 'UTF8', None, ),  # 10
+    (11, TType.STRING, 'tenantAdminLastName', 'UTF8', None, ),  # 11
+    (12, TType.STRING, 'tenantAdminEmail', 'UTF8', None, ),  # 12
+)
+all_structs.append(TenantConfig)
+TenantConfig.thrift_spec = (
+    None,  # 0
+    None,  # 1
+    None,  # 2
+    None,  # 3
+    None,  # 4
+    None,  # 5
+    None,  # 6
+    None,  # 7
+    None,  # 8
+    None,  # 9
+    None,  # 10
+    None,  # 11
+    None,  # 12
+    (13, TType.STRING, 'identityServerUserName', 'UTF8', None, ),  # 13
+    (14, TType.STRING, 'identityServerPasswordToken', 'UTF8', None, ),  # 14
+    None,  # 15
+    (16, TType.STRING, 'oauthClientId', 'UTF8', None, ),  # 16
+    (17, TType.STRING, 'oauthClientSecret', 'UTF8', None, ),  # 17
+)
+all_structs.append(Tenant)
+Tenant.thrift_spec = (
+    None,  # 0
+    (1, TType.STRING, 'tenantId', 'UTF8', None, ),  # 1
+    (2, TType.I32, 'tenantApprovalStatus', None, None, ),  # 2
+    (3, TType.STRING, 'tenantName', 'UTF8', None, ),  # 3
+    (4, TType.STRING, 'domain', 'UTF8', None, ),  # 4
+    (5, TType.STRING, 'emailAddress', 'UTF8', None, ),  # 5
+    (6, TType.STRING, 'tenantAcronym', 'UTF8', None, ),  # 6
+    (7, TType.STRING, 'tenantURL', 'UTF8', None, ),  # 7
+    (8, TType.STRING, 'tenantPublicAbstract', 'UTF8', None, ),  # 8
+    (9, TType.STRING, 'reviewProposalDescription', 'UTF8', None, ),  # 9
+    None,  # 10
+    None,  # 11
+    None,  # 12
+    None,  # 13
+    None,  # 14
+    (15, TType.STRING, 'declinedReason', 'UTF8', None, ),  # 15
+    None,  # 16
+    None,  # 17
+    (18, TType.I64, 'requestCreationTime', None, None, ),  # 18
+    (19, TType.STRING, 'requesterUsername', 'UTF8', None, ),  # 19
+)
+all_structs.append(PasswordCredential)
+PasswordCredential.thrift_spec = (
+    None,  # 0
+    (1, TType.STRING, 'gatewayId', 'UTF8', None, ),  # 1
+    (2, TType.STRING, 'portalUserName', 'UTF8', None, ),  # 2
+    (3, TType.STRING, 'loginUserName', 'UTF8', None, ),  # 3
+    (4, TType.STRING, 'password', 'UTF8', None, ),  # 4
+    (5, TType.STRING, 'description', 'UTF8', None, ),  # 5
+    (6, TType.I64, 'persistedTime', None, None, ),  # 6
+    (7, TType.STRING, 'token', 'UTF8', None, ),  # 7
+)
+fix_spec(all_structs)
+del all_structs
diff --git a/clients/python/custos/profile/model/workspace/__init__.py b/clients/python/custos/profile/model/workspace/__init__.py
new file mode 100644
index 0000000..adefd8e
--- /dev/null
+++ b/clients/python/custos/profile/model/workspace/__init__.py
@@ -0,0 +1 @@
+__all__ = ['ttypes', 'constants']
diff --git a/clients/python/custos/profile/model/workspace/constants.py b/clients/python/custos/profile/model/workspace/constants.py
new file mode 100644
index 0000000..c59352d
--- /dev/null
+++ b/clients/python/custos/profile/model/workspace/constants.py
@@ -0,0 +1,14 @@
+#
+# Autogenerated by Thrift Compiler (0.12.0)
+#
+# DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
+#
+#  options string: py
+#
+
+from thrift.Thrift import TType, TMessageType, TFrozenDict, TException, TApplicationException
+from thrift.protocol.TProtocol import TProtocolException
+from thrift.TRecursive import fix_spec
+
+import sys
+from .ttypes import *
diff --git a/clients/python/custos/profile/model/workspace/ttypes.py b/clients/python/custos/profile/model/workspace/ttypes.py
new file mode 100644
index 0000000..1600229
--- /dev/null
+++ b/clients/python/custos/profile/model/workspace/ttypes.py
@@ -0,0 +1,345 @@
+#
+# Autogenerated by Thrift Compiler (0.12.0)
+#
+# DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
+#
+#  options string: py
+#
+
+from thrift.Thrift import TType, TMessageType, TFrozenDict, TException, TApplicationException
+from thrift.protocol.TProtocol import TProtocolException
+from thrift.TRecursive import fix_spec
+
+import sys
+
+from thrift.transport import TTransport
+all_structs = []
+
+
+class GatewayApprovalStatus(object):
+    REQUESTED = 0
+    APPROVED = 1
+    ACTIVE = 2
+    DEACTIVATED = 3
+    CANCELLED = 4
+    DENIED = 5
+    CREATED = 6
+    DEPLOYED = 7
+
+    _VALUES_TO_NAMES = {
+        0: "REQUESTED",
+        1: "APPROVED",
+        2: "ACTIVE",
+        3: "DEACTIVATED",
+        4: "CANCELLED",
+        5: "DENIED",
+        6: "CREATED",
+        7: "DEPLOYED",
+    }
+
+    _NAMES_TO_VALUES = {
+        "REQUESTED": 0,
+        "APPROVED": 1,
+        "ACTIVE": 2,
+        "DEACTIVATED": 3,
+        "CANCELLED": 4,
+        "DENIED": 5,
+        "CREATED": 6,
+        "DEPLOYED": 7,
+    }
+
+
+class Gateway(object):
+    """
+    Attributes:
+     - custosInternalGatewayId
+     - gatewayId
+     - gatewayApprovalStatus
+     - gatewayName
+     - domain
+     - emailAddress
+     - gatewayAcronym
+     - gatewayURL
+     - gatewayPublicAbstract
+     - reviewProposalDescription
+     - gatewayAdminFirstName
+     - gatewayAdminLastName
+     - gatewayAdminEmail
+     - identityServerUserName
+     - identityServerPasswordToken
+     - declinedReason
+     - oauthClientId
+     - oauthClientSecret
+     - requestCreationTime
+     - requesterUsername
+
+    """
+
+
+    def __init__(self, custosInternalGatewayId=None, gatewayId=None, gatewayApprovalStatus=None, gatewayName=None, domain=None, emailAddress=None, gatewayAcronym=None, gatewayURL=None, gatewayPublicAbstract=None, reviewProposalDescription=None, gatewayAdminFirstName=None, gatewayAdminLastName=None, gatewayAdminEmail=None, identityServerUserName=None, identityServerPasswordToken=None, declinedReason=None, oauthClientId=None, oauthClientSecret=None, requestCreationTime=None, requesterUsern [...]
+        self.custosInternalGatewayId = custosInternalGatewayId
+        self.gatewayId = gatewayId
+        self.gatewayApprovalStatus = gatewayApprovalStatus
+        self.gatewayName = gatewayName
+        self.domain = domain
+        self.emailAddress = emailAddress
+        self.gatewayAcronym = gatewayAcronym
+        self.gatewayURL = gatewayURL
+        self.gatewayPublicAbstract = gatewayPublicAbstract
+        self.reviewProposalDescription = reviewProposalDescription
+        self.gatewayAdminFirstName = gatewayAdminFirstName
+        self.gatewayAdminLastName = gatewayAdminLastName
+        self.gatewayAdminEmail = gatewayAdminEmail
+        self.identityServerUserName = identityServerUserName
+        self.identityServerPasswordToken = identityServerPasswordToken
+        self.declinedReason = declinedReason
+        self.oauthClientId = oauthClientId
+        self.oauthClientSecret = oauthClientSecret
+        self.requestCreationTime = requestCreationTime
+        self.requesterUsername = requesterUsername
+
+    def read(self, iprot):
+        if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None:
+            iprot._fast_decode(self, iprot, [self.__class__, self.thrift_spec])
+            return
+        iprot.readStructBegin()
+        while True:
+            (fname, ftype, fid) = iprot.readFieldBegin()
+            if ftype == TType.STOP:
+                break
+            if fid == 1:
+                if ftype == TType.STRING:
+                    self.custosInternalGatewayId = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
+                else:
+                    iprot.skip(ftype)
+            elif fid == 2:
+                if ftype == TType.STRING:
+                    self.gatewayId = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
+                else:
+                    iprot.skip(ftype)
+            elif fid == 3:
+                if ftype == TType.I32:
+                    self.gatewayApprovalStatus = iprot.readI32()
+                else:
+                    iprot.skip(ftype)
+            elif fid == 4:
+                if ftype == TType.STRING:
+                    self.gatewayName = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
+                else:
+                    iprot.skip(ftype)
+            elif fid == 5:
+                if ftype == TType.STRING:
+                    self.domain = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
+                else:
+                    iprot.skip(ftype)
+            elif fid == 6:
+                if ftype == TType.STRING:
+                    self.emailAddress = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
+                else:
+                    iprot.skip(ftype)
+            elif fid == 7:
+                if ftype == TType.STRING:
+                    self.gatewayAcronym = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
+                else:
+                    iprot.skip(ftype)
+            elif fid == 8:
+                if ftype == TType.STRING:
+                    self.gatewayURL = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
+                else:
+                    iprot.skip(ftype)
+            elif fid == 9:
+                if ftype == TType.STRING:
+                    self.gatewayPublicAbstract = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
+                else:
+                    iprot.skip(ftype)
+            elif fid == 10:
+                if ftype == TType.STRING:
+                    self.reviewProposalDescription = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
+                else:
+                    iprot.skip(ftype)
+            elif fid == 11:
+                if ftype == TType.STRING:
+                    self.gatewayAdminFirstName = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
+                else:
+                    iprot.skip(ftype)
+            elif fid == 12:
+                if ftype == TType.STRING:
+                    self.gatewayAdminLastName = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
+                else:
+                    iprot.skip(ftype)
+            elif fid == 13:
+                if ftype == TType.STRING:
+                    self.gatewayAdminEmail = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
+                else:
+                    iprot.skip(ftype)
+            elif fid == 14:
+                if ftype == TType.STRING:
+                    self.identityServerUserName = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
+                else:
+                    iprot.skip(ftype)
+            elif fid == 15:
+                if ftype == TType.STRING:
+                    self.identityServerPasswordToken = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
+                else:
+                    iprot.skip(ftype)
+            elif fid == 16:
+                if ftype == TType.STRING:
+                    self.declinedReason = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
+                else:
+                    iprot.skip(ftype)
+            elif fid == 17:
+                if ftype == TType.STRING:
+                    self.oauthClientId = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
+                else:
+                    iprot.skip(ftype)
+            elif fid == 18:
+                if ftype == TType.STRING:
+                    self.oauthClientSecret = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
+                else:
+                    iprot.skip(ftype)
+            elif fid == 19:
+                if ftype == TType.I64:
+                    self.requestCreationTime = iprot.readI64()
+                else:
+                    iprot.skip(ftype)
+            elif fid == 20:
+                if ftype == TType.STRING:
+                    self.requesterUsername = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
+                else:
+                    iprot.skip(ftype)
+            else:
+                iprot.skip(ftype)
+            iprot.readFieldEnd()
+        iprot.readStructEnd()
+
+    def write(self, oprot):
+        if oprot._fast_encode is not None and self.thrift_spec is not None:
+            oprot.trans.write(oprot._fast_encode(self, [self.__class__, self.thrift_spec]))
+            return
+        oprot.writeStructBegin('Gateway')
+        if self.custosInternalGatewayId is not None:
+            oprot.writeFieldBegin('custosInternalGatewayId', TType.STRING, 1)
+            oprot.writeString(self.custosInternalGatewayId.encode('utf-8') if sys.version_info[0] == 2 else self.custosInternalGatewayId)
+            oprot.writeFieldEnd()
+        if self.gatewayId is not None:
+            oprot.writeFieldBegin('gatewayId', TType.STRING, 2)
+            oprot.writeString(self.gatewayId.encode('utf-8') if sys.version_info[0] == 2 else self.gatewayId)
+            oprot.writeFieldEnd()
+        if self.gatewayApprovalStatus is not None:
+            oprot.writeFieldBegin('gatewayApprovalStatus', TType.I32, 3)
+            oprot.writeI32(self.gatewayApprovalStatus)
+            oprot.writeFieldEnd()
+        if self.gatewayName is not None:
+            oprot.writeFieldBegin('gatewayName', TType.STRING, 4)
+            oprot.writeString(self.gatewayName.encode('utf-8') if sys.version_info[0] == 2 else self.gatewayName)
+            oprot.writeFieldEnd()
+        if self.domain is not None:
+            oprot.writeFieldBegin('domain', TType.STRING, 5)
+            oprot.writeString(self.domain.encode('utf-8') if sys.version_info[0] == 2 else self.domain)
+            oprot.writeFieldEnd()
+        if self.emailAddress is not None:
+            oprot.writeFieldBegin('emailAddress', TType.STRING, 6)
+            oprot.writeString(self.emailAddress.encode('utf-8') if sys.version_info[0] == 2 else self.emailAddress)
+            oprot.writeFieldEnd()
+        if self.gatewayAcronym is not None:
+            oprot.writeFieldBegin('gatewayAcronym', TType.STRING, 7)
+            oprot.writeString(self.gatewayAcronym.encode('utf-8') if sys.version_info[0] == 2 else self.gatewayAcronym)
+            oprot.writeFieldEnd()
+        if self.gatewayURL is not None:
+            oprot.writeFieldBegin('gatewayURL', TType.STRING, 8)
+            oprot.writeString(self.gatewayURL.encode('utf-8') if sys.version_info[0] == 2 else self.gatewayURL)
+            oprot.writeFieldEnd()
+        if self.gatewayPublicAbstract is not None:
+            oprot.writeFieldBegin('gatewayPublicAbstract', TType.STRING, 9)
+            oprot.writeString(self.gatewayPublicAbstract.encode('utf-8') if sys.version_info[0] == 2 else self.gatewayPublicAbstract)
+            oprot.writeFieldEnd()
+        if self.reviewProposalDescription is not None:
+            oprot.writeFieldBegin('reviewProposalDescription', TType.STRING, 10)
+            oprot.writeString(self.reviewProposalDescription.encode('utf-8') if sys.version_info[0] == 2 else self.reviewProposalDescription)
+            oprot.writeFieldEnd()
+        if self.gatewayAdminFirstName is not None:
+            oprot.writeFieldBegin('gatewayAdminFirstName', TType.STRING, 11)
+            oprot.writeString(self.gatewayAdminFirstName.encode('utf-8') if sys.version_info[0] == 2 else self.gatewayAdminFirstName)
+            oprot.writeFieldEnd()
+        if self.gatewayAdminLastName is not None:
+            oprot.writeFieldBegin('gatewayAdminLastName', TType.STRING, 12)
+            oprot.writeString(self.gatewayAdminLastName.encode('utf-8') if sys.version_info[0] == 2 else self.gatewayAdminLastName)
+            oprot.writeFieldEnd()
+        if self.gatewayAdminEmail is not None:
+            oprot.writeFieldBegin('gatewayAdminEmail', TType.STRING, 13)
+            oprot.writeString(self.gatewayAdminEmail.encode('utf-8') if sys.version_info[0] == 2 else self.gatewayAdminEmail)
+            oprot.writeFieldEnd()
+        if self.identityServerUserName is not None:
+            oprot.writeFieldBegin('identityServerUserName', TType.STRING, 14)
+            oprot.writeString(self.identityServerUserName.encode('utf-8') if sys.version_info[0] == 2 else self.identityServerUserName)
+            oprot.writeFieldEnd()
+        if self.identityServerPasswordToken is not None:
+            oprot.writeFieldBegin('identityServerPasswordToken', TType.STRING, 15)
+            oprot.writeString(self.identityServerPasswordToken.encode('utf-8') if sys.version_info[0] == 2 else self.identityServerPasswordToken)
+            oprot.writeFieldEnd()
+        if self.declinedReason is not None:
+            oprot.writeFieldBegin('declinedReason', TType.STRING, 16)
+            oprot.writeString(self.declinedReason.encode('utf-8') if sys.version_info[0] == 2 else self.declinedReason)
+            oprot.writeFieldEnd()
+        if self.oauthClientId is not None:
+            oprot.writeFieldBegin('oauthClientId', TType.STRING, 17)
+            oprot.writeString(self.oauthClientId.encode('utf-8') if sys.version_info[0] == 2 else self.oauthClientId)
+            oprot.writeFieldEnd()
+        if self.oauthClientSecret is not None:
+            oprot.writeFieldBegin('oauthClientSecret', TType.STRING, 18)
+            oprot.writeString(self.oauthClientSecret.encode('utf-8') if sys.version_info[0] == 2 else self.oauthClientSecret)
+            oprot.writeFieldEnd()
+        if self.requestCreationTime is not None:
+            oprot.writeFieldBegin('requestCreationTime', TType.I64, 19)
+            oprot.writeI64(self.requestCreationTime)
+            oprot.writeFieldEnd()
+        if self.requesterUsername is not None:
+            oprot.writeFieldBegin('requesterUsername', TType.STRING, 20)
+            oprot.writeString(self.requesterUsername.encode('utf-8') if sys.version_info[0] == 2 else self.requesterUsername)
+            oprot.writeFieldEnd()
+        oprot.writeFieldStop()
+        oprot.writeStructEnd()
+
+    def validate(self):
+        if self.gatewayId is None:
+            raise TProtocolException(message='Required field gatewayId is unset!')
+        if self.gatewayApprovalStatus is None:
+            raise TProtocolException(message='Required field gatewayApprovalStatus is unset!')
+        return
+
+    def __repr__(self):
+        L = ['%s=%r' % (key, value)
+             for key, value in self.__dict__.items()]
+        return '%s(%s)' % (self.__class__.__name__, ', '.join(L))
+
+    def __eq__(self, other):
+        return isinstance(other, self.__class__) and self.__dict__ == other.__dict__
+
+    def __ne__(self, other):
+        return not (self == other)
+all_structs.append(Gateway)
+Gateway.thrift_spec = (
+    None,  # 0
+    (1, TType.STRING, 'custosInternalGatewayId', 'UTF8', None, ),  # 1
+    (2, TType.STRING, 'gatewayId', 'UTF8', None, ),  # 2
+    (3, TType.I32, 'gatewayApprovalStatus', None, None, ),  # 3
+    (4, TType.STRING, 'gatewayName', 'UTF8', None, ),  # 4
+    (5, TType.STRING, 'domain', 'UTF8', None, ),  # 5
+    (6, TType.STRING, 'emailAddress', 'UTF8', None, ),  # 6
+    (7, TType.STRING, 'gatewayAcronym', 'UTF8', None, ),  # 7
+    (8, TType.STRING, 'gatewayURL', 'UTF8', None, ),  # 8
+    (9, TType.STRING, 'gatewayPublicAbstract', 'UTF8', None, ),  # 9
+    (10, TType.STRING, 'reviewProposalDescription', 'UTF8', None, ),  # 10
+    (11, TType.STRING, 'gatewayAdminFirstName', 'UTF8', None, ),  # 11
+    (12, TType.STRING, 'gatewayAdminLastName', 'UTF8', None, ),  # 12
+    (13, TType.STRING, 'gatewayAdminEmail', 'UTF8', None, ),  # 13
+    (14, TType.STRING, 'identityServerUserName', 'UTF8', None, ),  # 14
+    (15, TType.STRING, 'identityServerPasswordToken', 'UTF8', None, ),  # 15
+    (16, TType.STRING, 'declinedReason', 'UTF8', None, ),  # 16
+    (17, TType.STRING, 'oauthClientId', 'UTF8', None, ),  # 17
+    (18, TType.STRING, 'oauthClientSecret', 'UTF8', None, ),  # 18
+    (19, TType.I64, 'requestCreationTime', None, None, ),  # 19
+    (20, TType.STRING, 'requesterUsername', 'UTF8', None, ),  # 20
+)
+fix_spec(all_structs)
+del all_structs
diff --git a/clients/python/requirements_dev.txt b/clients/python/requirements_dev.txt
index a1d25f4..353a50e 100644
--- a/clients/python/requirements_dev.txt
+++ b/clients/python/requirements_dev.txt
@@ -11,3 +11,8 @@ pyflakes==2.1.1
 pytest==4.3.0
 pytest-runner==4.4
 six==1.12.0
+oauthlib==3.1.0
+requests_oauthlib==1.2.0
+requests==2.22.0
+thrift_connector==0.24
+thrift==0.11.0
\ No newline at end of file