Esempio n. 1
0
class Keycloakconnector:
    keycloak_openid = None

    def __init__(self, serverurl, realm, clientid, secret):
        self.keycloak_openid = KeycloakOpenID(server_url=serverurl,
                                              client_id=clientid,
                                              realm_name=realm,
                                              client_secret_key=secret,
                                              verify=True)
        config_well_know = self.keycloak_openid.well_know()
        # print(config_well_know)

    def getToken(self, appID, api):
        token = self.keycloak_openid.token(username="",
                                           password="",
                                           grant_type=["client_credentials"])
        token = token['access_token']
        print("Access token = ")
        print(token)
        return token

    # Get JWT public key.
    def getJWTPublickey(self):
        cert = self.keycloak_openid.certs()
        if cert is None:
            return ""
        x5c = cert.get('keys')[0]['x5c'][0]
        x5c = '-----BEGIN CERTIFICATE-----\n' + x5c + '\n-----END CERTIFICATE-----'
        x509 = OpenSSL.crypto.load_certificate(FILETYPE_PEM, x5c)
        pubkey = x509.get_pubkey()
        pubkey = OpenSSL.crypto.dump_publickey(FILETYPE_PEM,
                                               pubkey).decode("utf-8")
        return pubkey
Esempio n. 2
0
def manager_login(url, username, password):
    realm = 'master'
    if username == 'smartcity':
        realm = 'smartcity'
    keycloak_openid = KeycloakOpenID(
        server_url=f'https://{url}/auth/',
        client_id="admin-cli",
        realm_name=realm,
        client_secret_key="secret",
    )
    if password:
        response = keycloak_openid.token(username, password)
    else:
        password = config.get_password(url, username)
        response = keycloak_openid.token(username, password)
    config.store_token(url, username, password, response['refresh_token'])
def get_common_services_access_token(config):
    # Configure Keycloak client
    keycloak_openid = KeycloakOpenID(server_url=config.COMM_SERV_AUTH_URL,
                                     client_id=config.COMM_SERV_CLIENT_ID,
                                     realm_name=config.COMM_SERV_REALM,
                                     client_secret_key=config.COMM_SERV_CLIENT_SECRET)
    # Get Token
    token = keycloak_openid.token('', '', 'client_credentials')
    return token['access_token']
Esempio n. 4
0
def interactive_login(realm_label):
    """Logs in interactively."""
    env, config = utils.get_selected_deployment_config()
    if config is not None and URL_KEY in config:
        nxs.config.set_environment(config[URL_KEY])
    else:
        utils.error(
            "You must first select a profile using the 'profiles' command")

    issuer = ''
    if realm_label:
        try:
            response = nxs.realms.fetch(realm_label)
            issuer = response['_issuer']
        except nxs.HTTPError as e:
            print(e.response.json())
            utils.error(str(e))
    else:
        realm = utils.get_default_realm()
        if realm is None:
            realm = _select_realm()
            issuer = realm['_issuer']
            label = realm['_label']
            print("Saving realm '%s' in your profile" % realm['_label'])
            utils.set_default_realm(label, issuer)
        else:
            issuer = realm['_issuer']
            print(
                "Using default realm '%s' set in your profile. Use --realm to override."
                % realm['_label'])

    default_client_id = utils.get_default_client_id()
    client_id = input("Please enter the client ID [%s]: " % default_client_id)
    if not client_id:
        client_id = default_client_id
    utils.set_default_client_id(client_id)

    detected_user = getpass.getuser()
    username = input("Username [%s]: " % detected_user)
    if not username:
        username = detected_user
    password = getpass.getpass()
    try:
        url, name = issuer.split("realms/")
        keycloak_openid = KeycloakOpenID(server_url=url,
                                         client_id=client_id,
                                         realm_name=name,
                                         verify=True)
        response = keycloak_openid.token(username, password)
        token = response['access_token']
        _set_token(token)
        utils.success(
            "Authentication successful. Use 'view-token' to show your credentials."
        )
    except KeycloakError as e:
        utils.error("Authentication failed: %s" % e)
Esempio n. 5
0
def get_kc_token():
    keycloak_openid = KeycloakOpenID(
        server_url        = config.gpap_token_auth['server_url'],
        client_id         = config.gpap_token_auth['client_id'],
        realm_name        = config.gpap_token_auth['realm_name'],
        client_secret_key = config.gpap_token_auth['client_secret_key'],
        verify            = False
    )
    token = keycloak_openid.token(config.gpap_token_required[1], config.gpap_token_required[2])
    return token
def get_keycloak_token(configs):
    """Retrieves Keycloak bearer token"""
    keycloak_openid = KeycloakOpenID(
        server_url=configs['url'], 
        client_id=configs['client_id'],
        realm_name=configs['realm_name'],
        client_secret_key=None,
        verify=configs['secure'])

    return keycloak_openid.token(configs['username'], configs['password'])
Esempio n. 7
0
def get_token(auth_url: str, auth_client_id: str, auth_realm: str):
    username = args.username
    password = args.password
    from keycloak import KeycloakOpenID

    keycloak_openid = KeycloakOpenID(server_url=auth_url,
                                     client_id=auth_client_id,
                                     realm_name=auth_realm)

    # Get Token
    token = keycloak_openid.token(username, password)
    return token, keycloak_openid
Esempio n. 8
0
    def authenticate(cls, username=None, password=None):
        """
        Return 2tuple, representing authorized user or (None,None) on fail

        First tuple element is String ID representing a distingushed
         name for external users, e.g.:
        "[email protected],ou=People,o=warehouse-external"
        
        Second tuple element is Dict, representing a decoded ODIC access
         token

        >>> b = KeycloakBackend()
        >>> b.authenticate()
        (None, None)
        >>> # Check username
        >>> b.authenticate("*****@*****.**", "anything")
        (None, None)
        >>> # Check bogus username
        >>> b.authenticate("Test", "anything")
        (None, None)
        """
        user_identifier = None
        decoded_token = None
        if username is not None:
            u = None #auth may have failed: prepare to return None

            # setup OIDC client
            conf = config_loader.get_api_config()
            auth_url = conf['external.keycloak.url']
            dw_client_id = conf['external.keycloak.warehouse_client_id']
            auth_client = KeycloakOpenID(server_url=auth_url
                ,client_id=dw_client_id, realm_name="master"
                ,client_secret_key="value-doesnt-matter"
                ,verify=False)

            try:
                # login
                encoded_token = auth_client.token(username, password)
                # get server public key
                iss_url = auth_url+'realms/master'
                json_iss = requests.get(iss_url, verify=False).json()
                pub_key = add_pem_headfoot(json_iss['public_key'])
                # decode server response
                decode_opts = {"verify_signature":True, "verify_aud": True, "exp": True}
                decoded_token = auth_client.decode_token(
                     encoded_token['access_token']
                    ,key=pub_key, options=decode_opts)
                user_dn = oidc_token_to_ldap_style_name(decoded_token)
                #login is valid
                user_identifier = user_dn #return
            except KeycloakAuthenticationError:
                pass #login is invalid
        return user_identifier, decoded_token
def get_token(envs):
    username = args.username
    password = args.password
    from keycloak import KeycloakOpenID

    print(f"Auth Url:      {envs['auth']['url']}")
    print(f"Auth ClientId:      {envs['auth']['clientId']}")
    print(f"Auth Realm:      {envs['auth']['realm']}")

    keycloak_openid = KeycloakOpenID(server_url=envs['auth']['url'],
                                     client_id=envs['auth']['clientId'],
                                     realm_name=envs['auth']['realm'])

    # Get Token
    token = keycloak_openid.token(username, password)
    return token, keycloak_openid
Esempio n. 10
0
def keycloak_handler(keycloak_config):
    """
    Keycloak token is required for many API calls
    """
    # Configure client
    keycloak_openid = KeycloakOpenID(
        server_url=keycloak_config['url'],
        client_id=get_envar(keycloak_config['client_id']),
        realm_name=keycloak_config['realm'],
        client_secret_key=get_envar(keycloak_config['client_secret']))

    # Get Token
    token = keycloak_openid.token(get_envar(keycloak_config['user']),
                                  get_envar(keycloak_config['password']))
    token = token['access_token']
    return {'Authorization': f'Bearer {token}'}
Esempio n. 11
0
def login():
	# Configure client
	keycloak_openid = KeycloakOpenID(server_url="http://10.255.230.159:8181/auth/",
	                    client_id="calls-gateway",
	                    realm_name="ambulance-example",
	                    client_secret_key="supersecret")

	# Get WellKnow
	# config_well_know = keycloak_openid.well_know()

	# Get Token
	token = keycloak_openid.token("user1", "user1")
	# token = keycloak_openid.token("user", "password", totp="012345")

	# Get Userinfo
	# userinfo = keycloak_openid.userinfo(token['access_token'])
	return token
Esempio n. 12
0
    def is_valid_token(self):

        credentials = self.__parse_token();
        username = credentials[1]
        pwd = credentials[2]

        keycloak = KeyCloak(server_url="https://auth.s2s-omxware.us-south.containers.appdomain.cloud/auth/",
                                client_id="omx-zeppelin",
                                realm_name="omxware",
                                client_secret_key="c05b7553-cf21-4f0c-ab81-a38aca3ba172",
                                verify=False)

        if self.__env != 'public':
            keycloak = KeyCloak(server_url="https://omx-auth.sl.cloud9.ibm.com/auth/",
                                client_id="omx-zeppelin",
                                realm_name="omxware",
                                client_secret_key="1320e78d-025d-48eb-ad3e-451281786932",
                                verify=False)

        try:
            # Get Token
            token = keycloak.token(username, pwd)
            self.__userinfo = keycloak.userinfo(token['access_token'])

            self.__keycloak_token = token['access_token']

            return True

        except KeycloakAuthenticationError as auth_error:
            # Exception object looks like this
            # keycloak.exceptions.KeycloakAuthenticationError:
            # 401: b'{"error":"invalid_grant","error_description":"Invalid user credentials"}'

            error_msg = ''

            if auth_error['error_description'] != None:
                error_msg = auth_error['error_description']

            if error_msg.strip() != None:
                print(error_msg)
            else:
                print(auth_error['error_description'])

            return False
Esempio n. 13
0
    from io import StringIO

print(" ")
print("=================")
print("=== SSO LOGIN ===")
print("=================")
print(" ")

keycloak_openid = KeycloakOpenID(
    server_url="https://service.wienerstadtwerke.at/auth/",
    client_id="client-smp-public",
    realm_name="wienernetze",
    client_secret_key=uuid.uuid1())

try:
    token = keycloak_openid.token(USERNAME, PASSWORD)
except:
    try:
        print('[' + str(sys.exc_info()[1]).split(":")[0] + '] ' +
              requests.status_codes._codes[int(
                  str(sys.exc_info()[1]).split(":")[0])][0])
    except:
        print("Network ERROR")
    print(" ")
    sys.exit()

userinfo = keycloak_openid.userinfo(token['access_token'])
print('[200] ' + str(userinfo))

print(" ")
print("===============")
Esempio n. 14
0
class NDMWS:
    ''' Main class to talk to NDM Web Services.

        NDM public web services are at endpoints:
        - /api/mprc: MAVProxy Remote Console services (add, remove, list and update data)
        - /api/rmp: Reactive Mission Planner services (send or retrieve subplan, get GPS pos)

        In order to use these service, an authentication bearer is required that should be
        sent along with the request to any service. The NDMWS library helps with this
        authentication and provides several shortcuts to common sequences of service
        requests.

        A tipical use of the library could be:
        1. Connect to Keycloak (retrieve the authentication bearer)
        2. Create a custom subplan
        3. Send the subplan to the RMP

        Other tipical (shorter) use could be:
        1. Connect to Keycloak (retrieve the authentication bearer)
        2. Trigger a predefined alarm (with its mapped subplan)

        In this last case, the alarm is only a label identifying a predefined mapping
        that we want to call use. This requires an association between the alarm and a
        subplan that should be defined in the configuration file in advance. The alarm
        is then sent to the vMPA and the mapped subplan is sent to the vDFC for execution.
    '''
    def __init__(self,
                 dfcaddr=None,
                 droneid=None,
                 mpaaddr=None,
                 inifile='ndmws.ini',
                 debug=False):
        ''' Creates an instance of the helper to call NDM Web Services.

            This is the first object to instantiate and the one to start WS interaction.
            You can specify `dfcaddr`, `mpaaddr` and a `droneid` or you can leave it blank.
            In this case, you an alternativelly inform the `inifile` name or leave the
            defaults. Debug is `False` by default, so you'll have to set `debug=True` to
            see config variables, i.e.
        '''
        global DEBUG
        DEBUG = debug
        config.read(inifile)
        if dfcaddr == None:
            _('Using config: %s' % inifile)
            self.dfcaddr = config.get('dfc', 'hostport')
        else:
            self.dfcaddr = dfcaddr
        if mpaaddr == None:
            self.mpaaddr = config.get('mpa', 'hostport')
            _('Using mpaaddr: %s' % self.mpaaddr)
        else:
            self.mpaaddr = mpaaddr
        if droneid == None:
            self.droneid = config.get('dfc', 'droneid')
            _('Using droneid: %s' % self.droneid)
        else:
            self.droneid = droneid
        self.logger = logging.getLogger(__name__)
        # create console handler with a higher log level
        ch = logging.StreamHandler()
        ch.setLevel(logging.INFO)
        # create formatter and add it to the handlers
        formatter = logging.Formatter(
            "%(asctime)s.%(msecs)03d[%(levelname)-8s]:%(created).3f %(message)s",
            datefmt="%Y-%m-%d %H:%M:%S")
        ch.setFormatter(formatter)
        # add the handlers to logger
        if (self.logger.hasHandlers()):
            self.logger.handlers.clear()
        self.logger.addHandler(ch)
        self.logger.propagate = False

        self.authenticate()

        self.last_t_subplan = 0

        # self.relay_bcp_client = RelayClient(
        #     password=PASSWORD,
        #     keyfile=KEYFILE,
        #     identity=IDENTITY,  # can be set afterwards by calling `client.set_identity(identity)`
        #     tx_relay_address=TX_RELAY_ADDRESS,
        #     meta_identity_manager_address=META_IDENTITY_MANAGER_ADDRESS,
        #     entity_data_manager_address=ENTITY_DATA_MANAGER_ADDRESS,
        #     relay_server_address=RELAY_ENDPOINT,)

        # self.vmme_producer = None
        # self.initialized_vmme = False

    def authenticate(self, hostport=None, username=None, password=None):
        ''' Authentication with Keycloak is required before any API interaction.

            Realm is hardcoded to 'ndmws' and client 'ndmws-client', so no other
            configuration is required. Note that the communication is always
            encrypted so no plain text is on the wire, but you should protect your
            configuration file from unathorized access (i.e. don't ever commit your
            ndmws.ini file in your repo).
        '''
        if hostport == None or username == None or password == None:
            hostport = config.get('auth', 'hostport')
            _('Using auth hostport: %s' % hostport)
            username = config.get('auth', 'username')
            _('Using auth username: %s' % username)
            password = config.get('auth', 'password')
            _('Using auth password: %s' % password)
            _('Using auth url: %s' % (AUTHURL % hostport))
        self.kc = KeycloakOpenID(server_url=AUTHURL % hostport,
                                 client_id='ndmws-client',
                                 realm_name='ndmws')
        self.token = self.kc.token(username, password)
        self.logger.info(self.token)

    def userinfo(self):
        ''' Get keycloak user info from the identity server.

            This is only required if you want to be sure that the user you are
            authenticating with is the one allowed to interact with the
            web services, also no estrictly neccessary.
        '''
        return self.kc.userinfo(self.token['access_token'])

    def getpos(self, ts, th):
        ''' Get the GPS position of the flying drone when time = `ts`.

            While the drone (in config) is flying, every instant can be resolved
            to a known GPS position. This method retrieves the GPS position from
            the done `traces` before the drone lands. The opposite is not true,
            since the drone might (and usually does) pass twice or more to the
            same GPS position.
        '''
        auth = self.token['access_token']
        trace_url = TRACEURL % (self.dfcaddr, self.droneid, ts, th)
        r = get(trace_url, headers={'Authorization': 'Bearer %s' % auth})
        self.logger.info("RESPONSE GETPOS: {}".format(r.text))
        if r.status_code == 200:
            j = loads(r.text)
            return {'time': j['time'], 'pos': j['pos']}
        else:
            return {'code': r.status_code, 'msg': r.json()['msg']}

    def sendplan(self, data):
        ''' Send a subplan to the vDFC for a subplan change.

            With this method you can arbitrarily send a hand-made subplan (JSON)
            or a plan constructed using the `Subplan` fluent language builder.
            The plan will be executed only if the drone is not currently executing
            a subplan. If the drone is yet executing a subplan, an 409 error will be
            issued, but you can catch and ignore it as you wish, since no exception
            is raised at this moment.
        '''
        auth = self.token['access_token']
        r = put(SUBPLANURL % (self.dfcaddr, self.droneid),
                json=loads(data) if type(data) == str else data,
                headers={'Authorization': 'Bearer %s' % auth})
        self.logger.info('SUBPLAN RESPONSE: {}'.format(r.text))
        if r.status_code == 200:
            return r.text
        else:
            return {'code': r.status_code, 'msg': r.json()['msg']}

    def sendalarm(self, src, obj, ts):
        ''' Send an alarm to the vMPA for notification.

            Use this method to send a notification to the vMPA party.
            This notification could be sent in parallel to a subplan change (i.e.
            senplan) in the vDFC, so that both parties are notified of
            the alarm at the same time or sent by itself when an uploaded video
            is being processed. The 'src' param should be self.droneid if the
            video source comes from a drone live video or the label id (user
            supplied when a video is uploaded. 'object' identification and actual
            time 'ts' should also be passed as a way to enrich the alert message.
        '''
        auth = self.token['access_token']
        r = put(ALARMURL % (self.mpaaddr, src, obj, ts),
                headers={'Authorization': 'Bearer %s' % auth})
        self.logger.info("Response ALARM:{}".format(r.text))
        if r.status_code == 200:
            return r.text
        else:
            return {'code': r.status_code, 'msg': r.json()['msg']}

    def triggeralarm(self,
                     alarm,
                     t,
                     subplan_time_space=60,
                     send_subplan=False,
                     threshold=GPS_POS_THRESHOLD):
        ''' Trigger an alarm and send a predefined subplan to the RMP (Reactive Mission Planner).

            Predefined subplans could be configured in the configuration file easily
            following this structure:

            [alarmmap]
            ALARM = SP_SUBPLAN_NAME

            By adding a mapping between an alarm name and a suplan name, the library knows
            which subplan should be loaded when an alarm is triggered.

            [ALARM]
            reason = reason_text
            object = object_text

            A new section should be added for every new alarm, specifying two keys, `reason`
            and `object` that will be substituted into every subplan mapped to this alarm.

            [subplans]
            SP_SUBPLAN_NAME = { subplan: [ ... ] }

            A new key should be added to the `subplans` section to write the JSON corresponding
            to the subplan. Of course, the subplan object can (and should) include substitution
            variables that need to be escaped (use a double `%`) to avoid early template subtitution.

            Allowed template variables are as follows:
            - clientid
            - reason
            - obj
            - lat
            - lon
            - alt
        '''
        try:
            resp = self.getpos(t, threshold)
            if 'code' in resp:
                # self.logger.info('Exception of drone not flying')
                raise Exception('%d: %s' % (resp['code'], resp['msg']))
            else:
                _('Event: %s' % alarm)
                sp = config.get('alarmmap', alarm)
                _('Subplan name: %s' % sp)
                if sp == None:
                    raise Exception('ERROR: alarm `%s` has no mapped subplan' %
                                    alarm)
                subplan = config.get('subplans', sp)
                _('Subplan: %s' % subplan)
                reason = config.get(alarm, 'reason')
                obj = config.get(alarm, 'object')
                _('Sending alert of object %s at time %d' % (obj, t))
                self.sendalarm(self.droneid, obj, t)
                if t > (self.last_t_subplan +
                        subplan_time_space * 1000) and send_subplan:
                    clientid = config.get('client', 'clientid')
                    params = resp['pos']
                    params.update({
                        'clientid': clientid,
                        'reason': reason,
                        'obj': obj
                    })
                    _('Subplan params: %s' % params.__str__())
                    self.logger.info(('Subplan params: %s' % params.__str__()))
                    subplan = subplan % params
                    _('Sending subplan: %s' % subplan)
                    # vBCP client
                    # params["ts"] = t
                    # self.send_bcp_data(params)
                    # vMME client
                    # self.send_mme_data(params)
                    # self.last_t_subplan = t
                    self.logger.info("sending subplan")
                    return self.sendplan(subplan)
                else:
                    # if (int((t-self.last_t_subplan)*0.001)) % 10 == 0:
                    # self.logger.info('No subplans allowed. Last one sent {}(s) ago'.format(int((t-self.last_t_subplan)*0.001)))
                    return {'code': 200, 'msg': 'No subplans allowed'}
        except Exception:
            pass

    def send_bcp_data(self, data):
        payload = dumps(data)
        # Relay the payload as a signed message to the  Relay Server. The message will be forwarded to the vMCM.
        self.logger.info(
            'Relaying signed payload to the server: {}'.format(payload))
        # status = self.relay_bcp_client.relay_signed_message(payload)
        # self.logger.info('Got status code : {}'.format(status))
        tx_hash = self.relay_bcp_client.register_mpa_data(payload)
        self.logger.info('Got transaction hash : {}'.format(tx_hash))
        self.logger.info("data has been sent to vBCP")

    # def init_mme(self, data):
    #     device_data = self.generate_mme_data(data)
    #     send_init_msg_influx(device_data)

    def generate_mme_data(self, data):
        topic = generate_mqtt_topics()
        device_data = {
            "device_id": "DEVICE_ID_VMPA",
            "device_name": "DEVICE_NAME_VMPA",
            "device_ip": self.droneid,
            "lat": data['lat'],
            "lon": data['lon'],
            "prev_mme": "none",
            "sender": "device",
            "device_topic": topic,
            # data["topic"] if "topic" in data.keys() else data["reason"],
            "entity_type": "drone"
        }
        return device_data

    def send_mme_data(self, data):
        db_path = "vmme_client/device.db"
        device_data = self.generate_mme_data(data)
        self.write_mme_data(db_path, device_data)
        self.logger.info("Data has been sent to vMME")

    def write_mme_data(self, db_path, device_data):
        self.logger.info("On write_mme_data")
        self.logger.info(self.initialized_vmme)
        if self.initialized_vmme == False:
            self.logger.info("TO INITIALIZE VMME")
            initialize_vmme(db_path, device_data)
            #             send_init_msg_influx(device_data)
            #             FIRST_BROKER = select(db_path, device_data["device_id"])
            # #             if DEMO:
            # #                 try:
            # #                     base = BaseClient(password=password,
            # #                                       keyfile="vmme_client/keyfile.json")
            # #                     base.create_keyfile()
            # #                     vmme_wallet_addr = base._fetch_signer_address()
            # #                     identity_hash_response = create_identity(vmme_wallet_addr)
            # #                     identity_hash = identity_hash_response.json()
            # #                     valid_identity(identity_hash["tx_hash"].strip(), vmme_wallet_addr, device_data["entity_type"])
            # #                     self.logger.info("The device registration to the vAAA was successful: \n")
            # #                 except Exception as e:
            # #                     self.logger.info(e)
            #             insert_ip(db_path, FIRST_BROKER)
            #             insert_device_data(db_path, device_data)
            self.vmme_producer = Producer()
            self.initialized_vmme = True
            self.logger.info("Initialized vMME")
        if self.vmme_producer:
            self.vmme_producer.operate(device_data["device_id"])
        self.logger.info("Out of write mme data")
Esempio n. 15
0
def auto_test(data_frame,
              sso,
              api,
              website,
              user,
              password,
              prefix,
              logger,
              db_var,
              dashboards,
              add_cookies,
              custom_headers,
              headers,
              var_type='default',
              keycloak=False):
    """
    Key function to start and poll metrics on selected instance via API

    :param (str) var_type: variables use from "logs" or "default"
    :param (pandas.core.frame.DataFrame) data_frame: existing metrics from prod
    :param (str) sso: url to sso
    :param (str) api: url to api
    :param (str) website: DNS
    :param user: username
    :param password: password
    :param (str) prefix: prefix like 'prod' or 'qa'
    :param logger: logger
    :param db_var: db for getting variables
    :param (str) dashboards: collection with dashboard
    :param (bool) add_cookies: if True then add '_currentUser' and 'roles' cookies
    :param (bool) custom_headers: if True then add custom headers
    :param (dict) headers: dictionary with custom headers
    :param (bool) keycloak: if keycloak authorization is active
    :return:
    """
    if keycloak:
        keycloak_openid = KeycloakOpenID(
            server_url=config.server_url,
            client_id=config.client_id,
            realm_name=config.realm_name,
            client_secret_key=config.client_secret_key)
        token = keycloak_openid.token(user.split('@')[0], password)
        headers = {
            'Authorization': 'Bearer {}'.format(str(token['access_token']))
        }
        session = requests.Session()
        session.headers.update(headers)
    else:
        session = run_sso_session(sso, user, password, logger, add_cookies,
                                  custom_headers, headers)
    result = pd.DataFrame()
    for i in range(0, data_frame.shape[0]):
        dashboard_id = data_frame.loc[i, 'dashboard_id']
        metric_id = data_frame.loc[i, 'metric_id']

        aggregation = collect_parameters(i, dashboard_id, metric_id, logger,
                                         user, db_var, dashboards, var_type)

        # формирование тела запроса метрики
        body = {
            "__content": {
                "type": "metricData",
                "parameters": {
                    "dashboardId": "{}".format(dashboard_id),
                    "metricId": "{}".format(metric_id),
                    "variables": aggregation['variables']
                }
            }
        }

        # отправка запроса
        try:
            start_job = session.post(api + 'startJob',
                                     json=body,
                                     timeout=(12, 20))
        except requests.exceptions.Timeout:
            start_job = 'start_job_timeout'
            logger.info('{} at metric {}'.format(start_job, metric_id))
            result = write_results(result, i, dashboard_id, metric_id,
                                   str(start_job), 0, 400, website, prefix)
            sleep(120)
            break
        logger.info("metric {} run with code {} by {}".format(
            metric_id, int(start_job.status_code), user))
        if int(start_job.status_code) in [403, 500]:
            logger.info("metric {} failed with code {}".format(
                metric_id, int(start_job.status_code)))
            result = write_results(result, i, dashboard_id, metric_id,
                                   str(start_job.text), 0,
                                   int(start_job.status_code), website, prefix)
        elif int(start_job.status_code) in [404, 502]:
            logger.info("metric {} failed with code {}".format(
                metric_id, int(start_job.status_code)))
            result = write_results(result, i, dashboard_id, metric_id,
                                   str(start_job.text), 0,
                                   int(start_job.status_code), website, prefix)
            sleep(120)
        else:
            try:
                job = start_job.json()['id']
            except json.decoder.JSONDecodeError:
                try:
                    logger.info("metric {} failed with code {}".format(
                        metric_id, int(start_job.status_code)))
                except ValueError:
                    logger.info("metric {} failed with code {}".format(
                        metric_id, start_job.text))
                break

            # Получение ответа на запрос
            sleeper = time()
            poll_job = 'poll_job_timeout'
            while time() - sleeper <= 121:
                try:
                    poll_job = session.get(api + 'pollJob/' + job,
                                           timeout=(12, 20))
                    logger.info("metric {} polled with code {}".format(
                        metric_id, int(poll_job.status_code)))
                except requests.exceptions.ReadTimeout or requests.exceptions.ConnectionError:
                    logger.info('{} at metric {}'.format(poll_job, metric_id))
                    sleep(120)
                    break
                if int(poll_job.status_code) != 204:
                    logger.info(
                        "metric {} polled with code {} in {} sec".format(
                            metric_id, int(poll_job.status_code),
                            int(time() - sleeper)))
                    break
                sleep(1)
            if poll_job == 'poll_job_timeout':
                text = poll_job
                status_code = 204
            else:
                text = read_poll_job(poll_job)
                status_code = int(poll_job.status_code)
            result = write_results(result, i, dashboard_id, metric_id, text,
                                   int(time() - sleeper), status_code, website,
                                   prefix)
    return result
Esempio n. 16
0
from keycloak import KeycloakOpenID

# Configure client
keycloak_openid = KeycloakOpenID(server_url="http://localhost:7501/auth/",
                    client_id="oidc-native-app-client",
                    realm_name="realm0")

# Get WellKnow
config_well_know = keycloak_openid.well_know()

# Get Token
token = keycloak_openid.token("user0", "password0")
print (token['access_token'])

# Get Userinfo
userinfo = keycloak_openid.userinfo(token['access_token'])

print(userinfo)

# Refresh token
token = keycloak_openid.refresh_token(token['refresh_token'])

# Logout
keycloak_openid.logout(token['refresh_token'])
Esempio n. 17
0
LHCR1_CLIENT_ID = "testviewer"
LHCR1_CLIENT_SECRET = "85ac8b3e-df3c-4e4f-be65-ca5e5b68d3dc"

LHCR2_SERVER_URL = "http://192.168.0.36:8082/auth/"
LHCR2_REALM_NAME = "lhcr2"
LHCR2_CLIENT_ID = "lhcr1_testviewer"
LHCR2_CLIENT_SECRET = "91568b49-bb6d-4197-90f7-132e9db5fe16"

#Get a token from lhcr1
lhcr1oidc = KeycloakOpenID(server_url=LHCR1_SERVER_URL,
                           client_id=LHCR1_CLIENT_ID,
                           realm_name=LHCR1_REALM_NAME,
                           client_secret_key=LHCR1_CLIENT_SECRET,
                           verify=True)

lhcr1token = lhcr1oidc.token("user1", "user1")

print(lhcr1token)

#Exchange it for a token from lhcr2
lhcr2oidc = KeycloakOpenID(server_url=LHCR2_SERVER_URL,
                           client_id=LHCR2_CLIENT_ID,
                           realm_name=LHCR2_REALM_NAME,
                           client_secret_key=LHCR2_CLIENT_SECRET,
                           verify=True)

lhcr2token = exchange_token(lhcr2oidc, lhcr1token['access_token'], "lhcr1oidc")
print(lhcr2token)
"""
curl -X POST \
    -d "client_id=starting-client" \
Esempio n. 18
0
#!/usr/bin/env python3
from keycloak import KeycloakOpenID

keycloak_openid = KeycloakOpenID(
    server_url='http://localhost:8080/auth/',
    client_id='romi-dashboard',
    realm_name='master'
)

token = keycloak_openid.token('admin', 'admin')
user_id = keycloak_openid.userinfo(token['access_token'])['sub']
user_name = keycloak_openid.userinfo(token['access_token'])['preferred_username']
print(f'user ID: {user_id}')
print(f'user name: {user_name}')

#import requests
# todo: stuff the token into the request headers
#headers = {'foo': 'bar'}
#r = requests.get('http://localhost:5000', headers=headers)
#print(r.text)
Esempio n. 19
0
    ]
)

# jwt_admin_id = '8ea63bb3-32b7-4619-acbd-cc6ab267d6a4'
jwt_admin_id = '18bd82e0-cfd6-434f-807c-443e6b81f18c'
# jwt_user_id = '1295b697-e8d6-4125-b6f4-98992ea3f0c6'
jwt_user_id = 'c44e7443-d62b-41c0-85c9-7a56a1b8c60e'


headers = {
    'Content-type': 'application/json'
}

if IS_GUARD_ENABLED:
    keycloak_openid = KeycloakOpenID(server_url=KEYCLOAK_URL, client_id=CLIENT_ID, realm_name=REALM_NAME)
    response = keycloak_openid.token(ADMIN_USERNAME, ADMIN_PASSWORD)
    auth_token = response['access_token']
    headers['Authorization'] = f'Bearer {auth_token}'


def create_user(user):
    response = requests.post(url=f'{NEW_USER_URL}', json=user, headers=headers)
    logging.info(f'New user was added. id: {response.json()["id"]}')
    return response.json()['id']


def create_sub_location(loc_id, sub_location):
    response = requests.post(url=f'{NEW_SUB_LOCATION_URL}/{loc_id}', json=sub_location, headers=headers)
    logging.info(f'New sub locations was added. id: {response.json()["id"]}')
    return response.json()['id']
user = '******'
password = '******'
realm_name = 'demo'

client_id = 'demo_client'
client_secret = 'df0eb620-53af-4c62-ae41-71941cbfa1a4'

# interact with the software in various ways
keycloak_openid = KeycloakOpenID(server_url=server_url,
                                 realm_name=realm_name,
                                 client_id=client_id,
                                 client_secret_key=client_secret)
print("OPENID:")
print(keycloak_openid)

config_well_know = keycloak_openid.well_know()
print("WELL KNOW:")
print(config_well_know)

token = keycloak_openid.token(user, password)
print("TOKEN:")
print(token)

user_info = keycloak_openid.userinfo(token['access_token'])
print("USER INFO:")
print(user_info)

certs = keycloak_openid.certs()
print("CERTS:")
print(certs)
Esempio n. 21
0
class AuthProvider:
    def __init__(self, app=None):
        if app is not None:
            self.init_app(app)

    def init_app(self, app):
        self.provider = app.config['THROAT_CONFIG'].auth.provider
        if self.provider == 'KEYCLOAK':
            cfg = app.config['THROAT_CONFIG'].auth.keycloak
            self.keycloak_admin = KeycloakAdmin(server_url=cfg.server,
                                                realm_name=cfg.user_realm,
                                                user_realm_name=cfg.admin_realm,
                                                client_id=cfg.admin_client,
                                                client_secret_key=cfg.admin_secret,
                                                verify=True,
                                                auto_refresh_token=['get', 'put', 'post', 'delete'])

            self.keycloak_openid = KeycloakOpenID(server_url=cfg.server,
                                                  client_id=cfg.auth_client,
                                                  client_secret_key=cfg.auth_secret,
                                                  realm_name=cfg.user_realm,
                                                  verify=True)

    def get_user_by_email(self, email):
        try:
            return User.get(fn.Lower(User.email) == email.lower())
        except User.DoesNotExist:
            try:
                um = UserMetadata.get((UserMetadata.key == 'pending_email') &
                                      (fn.Lower(UserMetadata.value) == email.lower()))
                return User.get(User.uid == um.uid)
            except UserMetadata.DoesNotExist:
                pass
        if self.provider == 'KEYCLOAK':
            users = self.keycloak_admin.get_users({"email": email})
            for userdict in users:
                try:
                    return User.get(User.name == userdict['username'])
                except User.DoesNotExist:
                    return None
        return None

    def create_user(self, name, password, email, status=UserStatus.OK,
                    verified_email=False):
        auth_source = getattr(UserAuthSource, self.provider)

        if self.provider == 'LOCAL':
            uid = str(uuid.uuid4())
            crypto = UserCrypto.BCRYPT
            password = bcrypt.hashpw(password.encode('utf-8'), bcrypt.gensalt())
        else:
            uid = self.keycloak_admin.create_user({'email': email,
                                                   'username': name,
                                                   'enabled': True,
                                                   'emailVerified': verified_email,
                                                   'credentials': [{'value': password,
                                                                    'type': 'password'}]})
            password = ''
            crypto = UserCrypto.REMOTE
        user = User.create(uid=uid, name=name, crypto=crypto, password=password,
                           status=status, email=email, joindate=datetime.utcnow())
        self.set_user_auth_source(user, auth_source)
        self._set_email_verified(user, verified_email)
        return user

    def get_user_auth_source(self, user):
        try:
            umd = UserMetadata.get((UserMetadata.uid == user.uid) &
                                   (UserMetadata.key == "auth_source"))
            return UserAuthSource(int(umd.value))
        except UserMetadata.DoesNotExist:
            return UserAuthSource.LOCAL

    def set_user_auth_source(self, user, value):
        value = str(int(value))
        try:
            umd = UserMetadata.get((UserMetadata.uid == user.uid) &
                                   (UserMetadata.key == "auth_source"))
            umd.value = value
            umd.save()
        except UserMetadata.DoesNotExist:
            UserMetadata.create(uid=user.uid, key="auth_source", value=value)

    def get_user_remote_uid(self, user):
        try:
            umd = UserMetadata.get((UserMetadata.uid == user.uid) &
                                   (UserMetadata.key == "remote_uid"))
            return umd.value
        except UserMetadata.DoesNotExist:
            return user.uid

    def set_user_remote_uid(self, user, remote_uid):
        try:
            umd = UserMetadata.get((UserMetadata.uid == user.uid) &
                                   (UserMetadata.key == "remote_uid"))
            umd.value = remote_uid
            umd.save()
        except UserMetadata.DoesNotExist:
            UserMetadata.create(uid=user.uid, key="remote_uid", value=remote_uid)
        pass

    def change_password(self, user, old_password, new_password):
        if self.validate_password(user, old_password):
            auth_source = self.get_user_auth_source(user)
            if self.provider == 'LOCAL' and auth_source == UserAuthSource.LOCAL:
                user.crypto = UserCrypto.BCRYPT
                user.password = bcrypt.hashpw(new_password.encode('utf-8'),
                                              bcrypt.gensalt())
                user.save()
            elif self.provider == 'KEYCLOAK' and auth_source == UserAuthSource.KEYCLOAK:
                self.keycloak_admin.update_user(user_id=self.get_user_remote_uid(user),
                                                payload={'credentials':
                                                         [{'value': new_password,
                                                           'type': 'password'}]})
            else:
                raise AuthError
            # Invalidate other existing login sessions.
            User.update(resets=User.resets + 1).where(User.uid == user.uid).execute()
            theuser = misc.load_user(user.uid)
            login_user(theuser, remember=session.get("remember_me", False))

    def reset_password(self, user, new_password):
        auth_source = self.get_user_auth_source(user)
        if self.provider == 'LOCAL':
            if auth_source == UserAuthSource.LOCAL:
                user.crypto = UserCrypto.BCRYPT
                user.password = bcrypt.hashpw(new_password.encode('utf-8'), bcrypt.gensalt())
            else:
                raise AuthError
        elif self.provider == 'KEYCLOAK':
            if auth_source == UserAuthSource.LOCAL:
                kuid = self.keycloak_admin.create_user({'email': user.email,
                                                        'username': user.name,
                                                        'enabled': True,
                                                        'emailVerified': self.is_email_verified(user),
                                                        'credentials': [{'value': new_password,
                                                                         'type': 'password'}]})
                self.set_user_remote_uid(user, kuid)
                self.set_user_auth_source(user, UserAuthSource.KEYCLOAK)
                user.crypto = UserCrypto.REMOTE
                user.password = ''
            elif auth_source == UserAuthSource.KEYCLOAK:
                self.keycloak_admin.update_user(user_id=self.get_user_remote_uid(user),
                                                payload={'credentials':
                                                         [{'value': new_password,
                                                           'type': 'password'}]})
            else:
                raise AuthError
        user.save()
        User.update(resets=User.resets + 1).where(User.uid == user.uid).execute()

    def get_pending_email(self, user):
        try:
            umd = UserMetadata.get((UserMetadata.uid == user.uid) &
                                   (UserMetadata.key == "pending_email"))
            return umd.value
        except UserMetadata.DoesNotExist:
            return None

    def clear_pending_email(self, user):
        try:
            umd = UserMetadata.get((UserMetadata.uid == user.uid) &
                                   (UserMetadata.key == "pending_email"))
            umd.delete_instance()
        except UserMetadata.DoesNotExist:
            return None

    def set_pending_email(self, user, email):
        try:
            umd = UserMetadata.get((UserMetadata.uid == user.uid) &
                                   (UserMetadata.key == "pending_email"))
            umd.value = email
            umd.save()
        except UserMetadata.DoesNotExist:
            UserMetadata.create(uid=user.uid, key="pending_email", value=email)

    def confirm_pending_email(self, user, email):
        umd = None
        try:
            umd = UserMetadata.get((UserMetadata.uid == user.uid) &
                                   (UserMetadata.key == "pending_email"))
        except UserMetadata.DoesNotExist:
            pass
        auth_source = self.get_user_auth_source(user)
        if self.provider == 'LOCAL':
            if auth_source != UserAuthSource.LOCAL:
                raise AuthError
        elif self.provider == 'KEYCLOAK':
            if auth_source == UserAuthSource.KEYCLOAK:
                self.keycloak_admin.update_user(user_id=self.get_user_remote_uid(user),
                                                payload={'email': email,
                                                         'emailVerified': True})
            else:
                raise AuthError

        if umd is not None:
            umd.delete_instance()
        user.email = email
        user.save()
        self._set_email_verified(user)

    def is_email_verified(self, user):
        try:
            umd = UserMetadata.get((UserMetadata.uid == user.uid) &
                                   (UserMetadata.key == "email_verified"))
            return umd.value == '1'
        except UserMetadata.DoesNotExist:
            return False

    def set_email_verified(self, user, value=True):
        """Set both the UserMetadata and remote (if any) email_verified flags."""
        auth_source = self.get_user_auth_source(user)
        if self.provider == 'LOCAL':
            if auth_source != UserAuthSource.LOCAL:
                raise AuthError
        elif self.provider == 'KEYCLOAK':
            if auth_source == UserAuthSource.KEYCLOAK:
                self.keycloak_admin.update_user(user_id=self.get_user_remote_uid(user),
                                                payload={'email': user.email,
                                                         'emailVerified': value})
            else:
                raise AuthError
        self._set_email_verified(user, value)

    def _set_email_verified(self, user, value=True):
        """Set the UserMetadata email_verified flag. """
        value = '1' if value else '0'
        try:
            umd = UserMetadata.get((UserMetadata.uid == user.uid) &
                                   (UserMetadata.key == "email_verified"))
            umd.value = value
            umd.save()
        except UserMetadata.DoesNotExist:
            UserMetadata.create(uid=user.uid, key="email_verified", value=value)

    def validate_password(self, user, password):
        if user.crypto == UserCrypto.BCRYPT:
            thash = bcrypt.hashpw(password.encode('utf-8'), user.password.encode('utf-8'))
            if thash == user.password.encode('utf-8'):
                if self.provider == 'KEYCLOAK':
                    kuid = self.keycloak_admin.create_user({'email': user.email,
                                                            'username': user.name,
                                                            'enabled': True,
                                                            'emailVerified': self.is_email_verified(user),
                                                            'credentials': [{'value': password,
                                                                             'type': 'password'}]})
                    self.set_user_remote_uid(user, kuid)
                    self.set_user_auth_source(user, UserAuthSource.KEYCLOAK)
                    user.crypto = UserCrypto.REMOTE
                    user.password = ''
                    user.save()
                return True
        elif (user.crypto == UserCrypto.REMOTE and
              self.get_user_auth_source(user) == UserAuthSource.KEYCLOAK and
              self.provider == 'KEYCLOAK'):
            try:
                # TODO do something with the token
                self.keycloak_openid.token(username=user.name,
                                           password=password)
                return True
            except KeycloakError as err:
                return False
        return False

    def change_user_status(self, user, new_status):
        if new_status == 10:
            payload = {'email': '',
                       'emailVerified': False,
                       'enabled': False}
            user.email = ''
            user.email_verified = False
            self.clear_pending_email(user)
        elif user.status != 10 and new_status == 5:
            if user.email and self.is_email_verified(user):
                domain = user.email.split('@')[1]
                logger.info('Banned %s; confirmed email on %s',
                            user.name, domain)

            payload = {'enabled': False}
        elif user.status != 10 and new_status == 0:
            payload = {'enabled': True}
        else:
            raise RuntimeError("Invalid user status")

        if (new_status == 0 and email_validation_is_required() and
                not self.is_email_verified(user)):
            new_status = 1

        if user.crypto == UserCrypto.REMOTE:
            if (self.get_user_auth_source(user) == UserAuthSource.KEYCLOAK and
                    self.provider == 'KEYCLOAK'):
                self.keycloak_admin.update_user(user_id=self.get_user_remote_uid(user),
                                                payload=payload)

        user.status = new_status
        user.save()
        User.update(resets=User.resets + 1).where(User.uid == user.uid).execute()

    def actually_delete_user(self, user):
        # Used by automatic tests to clean up test realm on server.
        # You should probably be using change_user_status.
        if user.crypto == UserCrypto.REMOTE:
            self.keycloak_admin.delete_user(self.get_user_remote_uid(user))
Esempio n. 22
0
class AuthProvider:
    def __init__(self, app=None):
        if app is not None:
            self.init_app(app)

    def init_app(self, app):
        self.provider = app.config["THROAT_CONFIG"].auth.provider
        if self.provider == "KEYCLOAK":
            cfg = app.config["THROAT_CONFIG"].auth.keycloak
            self.keycloak_admin = KeycloakAdmin(
                server_url=cfg.server,
                realm_name=cfg.user_realm,
                user_realm_name=cfg.admin_realm,
                client_id=cfg.admin_client,
                client_secret_key=cfg.admin_secret,
                verify=True,
                auto_refresh_token=["get", "put", "post", "delete"],
            )

            self.keycloak_openid = KeycloakOpenID(
                server_url=cfg.server,
                client_id=cfg.auth_client,
                client_secret_key=cfg.auth_secret,
                realm_name=cfg.user_realm,
                verify=True,
            )

    def get_user_by_email(self, email):
        try:
            return User.get(fn.Lower(User.email) == email.lower())
        except User.DoesNotExist:
            try:
                um = UserMetadata.get(
                    (UserMetadata.key == "pending_email")
                    & (fn.Lower(UserMetadata.value) == email.lower()))
                return User.get(User.uid == um.uid)
            except UserMetadata.DoesNotExist:
                pass
        if self.provider == "KEYCLOAK":
            users = self.keycloak_admin.get_users({"email": email})
            for userdict in users:
                try:
                    return User.get(User.name == userdict["username"])
                except User.DoesNotExist:
                    return None
        return None

    def create_user(self,
                    name,
                    password,
                    email,
                    status=UserStatus.OK,
                    verified_email=False):
        auth_source = getattr(UserAuthSource, self.provider)

        if self.provider == "LOCAL":
            uid = str(uuid.uuid4())
            crypto = UserCrypto.BCRYPT
            password = bcrypt.hashpw(password.encode("utf-8"),
                                     bcrypt.gensalt())
        else:
            uid = self.keycloak_admin.create_user({
                "email":
                email,
                "username":
                name,
                "enabled":
                True,
                "emailVerified":
                verified_email,
                "credentials": [{
                    "value": password,
                    "type": "password"
                }],
            })
            password = ""
            crypto = UserCrypto.REMOTE
        user = User.create(
            uid=uid,
            name=name,
            crypto=crypto,
            password=password,
            status=status,
            email=email,
            joindate=datetime.utcnow(),
        )
        self.set_user_auth_source(user, auth_source)
        self._set_email_verified(user, verified_email)
        return user

    @staticmethod
    def get_user_auth_source(user):
        try:
            umd = UserMetadata.get((UserMetadata.uid == user.uid)
                                   & (UserMetadata.key == "auth_source"))
            return UserAuthSource(int(umd.value))
        except UserMetadata.DoesNotExist:
            return UserAuthSource.LOCAL

    @staticmethod
    def set_user_auth_source(user, value):
        value = str(int(value))
        try:
            umd = UserMetadata.get((UserMetadata.uid == user.uid)
                                   & (UserMetadata.key == "auth_source"))
            umd.value = value
            umd.save()
        except UserMetadata.DoesNotExist:
            UserMetadata.create(uid=user.uid, key="auth_source", value=value)

    @staticmethod
    def get_user_remote_uid(user):
        try:
            umd = UserMetadata.get((UserMetadata.uid == user.uid)
                                   & (UserMetadata.key == "remote_uid"))
            return umd.value
        except UserMetadata.DoesNotExist:
            return user.uid

    @staticmethod
    def set_user_remote_uid(user, remote_uid):
        try:
            umd = UserMetadata.get((UserMetadata.uid == user.uid)
                                   & (UserMetadata.key == "remote_uid"))
            umd.value = remote_uid
            umd.save()
        except UserMetadata.DoesNotExist:
            UserMetadata.create(uid=user.uid,
                                key="remote_uid",
                                value=remote_uid)
        pass

    def change_password(self, user, old_password, new_password):
        if self.validate_password(user, old_password):
            auth_source = self.get_user_auth_source(user)
            if self.provider == "LOCAL" and auth_source == UserAuthSource.LOCAL:
                user.crypto = UserCrypto.BCRYPT
                user.password = bcrypt.hashpw(new_password.encode("utf-8"),
                                              bcrypt.gensalt())
                user.save()
            elif self.provider == "KEYCLOAK" and auth_source == UserAuthSource.KEYCLOAK:
                self.keycloak_admin.update_user(
                    user_id=self.get_user_remote_uid(user),
                    payload={
                        "credentials": [{
                            "value": new_password,
                            "type": "password"
                        }]
                    },
                )
            else:
                raise AuthError
            # Invalidate other existing login sessions.
            User.update(resets=User.resets +
                        1).where(User.uid == user.uid).execute()
            theuser = misc.load_user(user.uid)
            login_user(theuser, remember=session.get("remember_me", False))

    def reset_password(self, user, new_password):
        auth_source = self.get_user_auth_source(user)
        if self.provider == "LOCAL":
            if auth_source == UserAuthSource.LOCAL:
                user.crypto = UserCrypto.BCRYPT
                user.password = bcrypt.hashpw(new_password.encode("utf-8"),
                                              bcrypt.gensalt())
            else:
                raise AuthError
        elif self.provider == "KEYCLOAK":
            if auth_source == UserAuthSource.LOCAL:
                kuid = self.keycloak_admin.create_user({
                    "email":
                    user.email,
                    "username":
                    user.name,
                    "enabled":
                    True,
                    "emailVerified":
                    self.is_email_verified(user),
                    "credentials": [{
                        "value": new_password,
                        "type": "password"
                    }],
                })
                self.set_user_remote_uid(user, kuid)
                self.set_user_auth_source(user, UserAuthSource.KEYCLOAK)
                user.crypto = UserCrypto.REMOTE
                user.password = ""
            elif auth_source == UserAuthSource.KEYCLOAK:
                self.keycloak_admin.update_user(
                    user_id=self.get_user_remote_uid(user),
                    payload={
                        "credentials": [{
                            "value": new_password,
                            "type": "password"
                        }]
                    },
                )
            else:
                raise AuthError
        user.save()
        User.update(resets=User.resets +
                    1).where(User.uid == user.uid).execute()

    def change_unconfirmed_user_email(self, user, new_email):
        """Use this to change the email before the user confirms it.  To
        change the email of a user with a confirmed email address, use
        the pending email change functions below.
        """
        user.email = new_email
        if self.provider == "KEYCLOAK":
            self.keycloak_admin.update_user(
                user_id=self.get_user_remote_uid(user),
                payload={
                    "email": new_email,
                    "emailVerified": False
                },
            )
        user.save()
        User.update(resets=User.resets +
                    1).where(User.uid == user.uid).execute()

    @staticmethod
    def get_pending_email(user):
        try:
            umd = UserMetadata.get((UserMetadata.uid == user.uid)
                                   & (UserMetadata.key == "pending_email"))
            return umd.value
        except UserMetadata.DoesNotExist:
            return None

    @staticmethod
    def clear_pending_email(user):
        try:
            umd = UserMetadata.get((UserMetadata.uid == user.uid)
                                   & (UserMetadata.key == "pending_email"))
            umd.delete_instance()
        except UserMetadata.DoesNotExist:
            return None

    @staticmethod
    def set_pending_email(user, email):
        try:
            umd = UserMetadata.get((UserMetadata.uid == user.uid)
                                   & (UserMetadata.key == "pending_email"))
            umd.value = email
            umd.save()
        except UserMetadata.DoesNotExist:
            UserMetadata.create(uid=user.uid, key="pending_email", value=email)

    def confirm_pending_email(self, user, email):
        umd = None
        try:
            umd = UserMetadata.get((UserMetadata.uid == user.uid)
                                   & (UserMetadata.key == "pending_email"))
        except UserMetadata.DoesNotExist:
            pass
        auth_source = self.get_user_auth_source(user)
        if self.provider == "LOCAL":
            if auth_source != UserAuthSource.LOCAL:
                raise AuthError
        elif self.provider == "KEYCLOAK":
            if auth_source == UserAuthSource.KEYCLOAK:
                self.keycloak_admin.update_user(
                    user_id=self.get_user_remote_uid(user),
                    payload={
                        "email": email,
                        "emailVerified": True
                    },
                )
            else:
                raise AuthError

        if umd is not None:
            umd.delete_instance()
        user.email = email
        user.save()
        self._set_email_verified(user)

    @staticmethod
    def is_email_verified(user):
        try:
            umd = UserMetadata.get((UserMetadata.uid == user.uid)
                                   & (UserMetadata.key == "email_verified"))
            return umd.value == "1"
        except UserMetadata.DoesNotExist:
            return False

    def set_email_verified(self, user, value=True):
        """Set both the UserMetadata and remote (if any) email_verified flags."""
        auth_source = self.get_user_auth_source(user)
        if self.provider == "LOCAL":
            if auth_source != UserAuthSource.LOCAL:
                raise AuthError
        elif self.provider == "KEYCLOAK":
            if auth_source == UserAuthSource.KEYCLOAK:
                self.keycloak_admin.update_user(
                    user_id=self.get_user_remote_uid(user),
                    payload={
                        "email": user.email,
                        "emailVerified": value
                    },
                )
            else:
                raise AuthError
        self._set_email_verified(user, value)

    @staticmethod
    def _set_email_verified(user, value=True):
        """Set the UserMetadata email_verified flag."""
        value = "1" if value else "0"
        try:
            umd = UserMetadata.get((UserMetadata.uid == user.uid)
                                   & (UserMetadata.key == "email_verified"))
            umd.value = value
            umd.save()
        except UserMetadata.DoesNotExist:
            UserMetadata.create(uid=user.uid,
                                key="email_verified",
                                value=value)

    def validate_password(self, user, password):
        if user.crypto == UserCrypto.BCRYPT:
            thash = bcrypt.hashpw(password.encode("utf-8"),
                                  user.password.encode("utf-8"))
            if thash == user.password.encode("utf-8"):
                if self.provider == "KEYCLOAK":
                    kuid = self.keycloak_admin.create_user({
                        "email":
                        user.email,
                        "username":
                        user.name,
                        "enabled":
                        True,
                        "emailVerified":
                        self.is_email_verified(user),
                        "credentials": [{
                            "value": password,
                            "type": "password"
                        }],
                    })
                    self.set_user_remote_uid(user, kuid)
                    self.set_user_auth_source(user, UserAuthSource.KEYCLOAK)
                    user.crypto = UserCrypto.REMOTE
                    user.password = ""
                    user.save()
                return True
        elif (user.crypto == UserCrypto.REMOTE
              and self.get_user_auth_source(user) == UserAuthSource.KEYCLOAK
              and self.provider == "KEYCLOAK"):
            try:
                # TODO do something with the token
                self.keycloak_openid.token(username=user.name,
                                           password=password)
                return True
            except KeycloakError:
                return False
        return False

    def change_user_status(self, user, new_status):
        if new_status == 10:
            payload = {"email": "", "emailVerified": False, "enabled": False}
            user.email = ""
            user.email_verified = False
            self.clear_pending_email(user)
        elif user.status != 10 and new_status == 5:
            if user.email and self.is_email_verified(user):
                domain = user.email.split("@")[1]
                logger.info("Banned %s; confirmed email on %s", user.name,
                            domain)

            payload = {"enabled": False}
        elif user.status != 10 and new_status == 0:
            payload = {"enabled": True}
        else:
            raise RuntimeError("Invalid user status")

        if (new_status == 0 and email_validation_is_required()
                and not self.is_email_verified(user)):
            new_status = 1

        if user.crypto == UserCrypto.REMOTE:
            if (self.get_user_auth_source(user) == UserAuthSource.KEYCLOAK
                    and self.provider == "KEYCLOAK"):
                self.keycloak_admin.update_user(
                    user_id=self.get_user_remote_uid(user), payload=payload)

        user.status = new_status
        user.save()
        User.update(resets=User.resets +
                    1).where(User.uid == user.uid).execute()

    def actually_delete_user(self, user):
        # Used by automatic tests to clean up test realm on server.
        # You should probably be using change_user_status.
        if user.crypto == UserCrypto.REMOTE:
            self.keycloak_admin.delete_user(self.get_user_remote_uid(user))
Esempio n. 23
0
class AuthProvider:
    def __init__(self, app=None):
        if app is not None:
            self.init_app(app)

    def init_app(self, app):
        self.provider = app.config['THROAT_CONFIG'].auth.provider
        if self.provider == 'KEYCLOAK':
            cfg = app.config['THROAT_CONFIG'].auth.keycloak
            self.keycloak_admin = KeycloakAdmin(
                server_url=cfg.server,
                realm_name=cfg.user_realm,
                user_realm_name=cfg.admin_realm,
                client_id=cfg.admin_client,
                client_secret_key=cfg.admin_secret,
                verify=True,
                auto_refresh_token=['get', 'put', 'post', 'delete'])

            self.keycloak_openid = KeycloakOpenID(
                server_url=cfg.server,
                client_id=cfg.auth_client,
                client_secret_key=cfg.auth_secret,
                realm_name=cfg.user_realm,
                verify=True)

    def get_user_by_email(self, email):
        # TODO when there are pending change emails, check those too.
        try:
            return User.get(User.email == email)
        except User.DoesNotExist:
            try:
                um = UserMetadata.get((UserMetadata.key == 'pending_email')
                                      & (UserMetadata.value == email))
                return User.get(User.uid == um.uid)
            except UserMetadata.DoesNotExist:
                pass
        if self.provider == 'KEYCLOAK':
            users = self.keycloak_admin.get_users({"email": email})
            for userdict in users:
                try:
                    return User.get(User.name == userdict['username'])
                except User.DoesNotExist:
                    return None
        return None

    def create_user(self, name, password, email, verified_email=False):
        auth_source = getattr(UserAuthSource, self.provider)

        if self.provider == 'LOCAL':
            uid = str(uuid.uuid4())
            crypto = UserCrypto.BCRYPT
            password = bcrypt.hashpw(password.encode('utf-8'),
                                     bcrypt.gensalt())
        else:
            uid = self.keycloak_admin.create_user({
                'email':
                email,
                'username':
                name,
                'enabled':
                True,
                'emailVerified':
                verified_email,
                'credentials': [{
                    'value': password,
                    'type': 'password'
                }]
            })
            # email = ''  # Store emails in local db, or not?
            password = ''
            crypto = UserCrypto.REMOTE
        user = User.create(uid=uid,
                           name=name,
                           crypto=crypto,
                           password=password,
                           email=email,
                           joindate=datetime.utcnow())
        self.set_user_auth_source(user, auth_source)
        self.set_email_verified(user, verified_email)
        return user

    def get_user_auth_source(self, user):
        try:
            umd = UserMetadata.get((UserMetadata.uid == user.uid)
                                   & (UserMetadata.key == "auth_source"))
            return UserAuthSource(int(umd.value))
        except UserMetadata.DoesNotExist:
            return UserAuthSource.LOCAL

    def set_user_auth_source(self, user, value):
        value = str(int(value))
        try:
            umd = UserMetadata.get((UserMetadata.uid == user.uid)
                                   & (UserMetadata.key == "auth_source"))
            umd.value = value
            umd.save()
        except UserMetadata.DoesNotExist:
            UserMetadata.create(uid=user.uid, key="auth_source", value=value)

    def change_password(self, user, old_password, new_password):
        if not self.validate_password(user, old_password):
            return False
        if self.provider == 'LOCAL':
            user.crypto = UserCrypto.BCRYPT
            user.password = bcrypt.hashpw(new_password.encode('utf-8'),
                                          bcrypt.gensalt())
        elif self.provider == 'KEYCLOAK':
            # validate_password promotes LOCAL users to KEYCLOAK ones.
            self.keycloak_admin.update_user(user_id=user.uid,
                                            payload={
                                                'credentials': [{
                                                    'value':
                                                    new_password,
                                                    'type':
                                                    'password'
                                                }]
                                            })
        # Invalidate other existing login sessions.
        user.resets += 1
        user.save()
        theuser = misc.load_user(user.uid)
        login_user(theuser, remember=session.get("remember_me", False))

    def reset_password(self, user, new_password):
        if self.provider == 'LOCAL':
            user.crypto = UserCrypto.BCRYPT
            user.password = bcrypt.hashpw(new_password.encode('utf-8'),
                                          bcrypt.gensalt())
            self.set_user_auth_source(user, UserAuthSource.LOCAL)
        elif self.provider == 'KEYCLOAK':
            if self.get_user_auth_source(user) == UserAuthSource.LOCAL:
                self.keycloak_admin.create_user({
                    'id':
                    user.uid,
                    'email':
                    user.email,
                    'username':
                    user.name,
                    'enabled':
                    True,
                    'emailVerified':
                    self.is_email_verified(user),
                    'credentials': [{
                        'value': new_password,
                        'type': 'password'
                    }]
                })
                self.set_user_auth_source(user, UserAuthSource.KEYCLOAK)
                user.crypto = UserCrypto.REMOTE
                user.password = ''
            else:
                self.keycloak_admin.update_user(user_id=user.uid,
                                                payload={
                                                    'credentials': [{
                                                        'value':
                                                        new_password,
                                                        'type':
                                                        'password'
                                                    }]
                                                })
        user.resets += 1
        user.save()

    def get_pending_email(self, user):
        try:
            umd = UserMetadata.get((UserMetadata.uid == user.uid)
                                   & (UserMetadata.key == "pending_email"))
            return umd.value
        except UserMetadata.DoesNotExist:
            return None

    def clear_pending_email(self, user):
        try:
            umd = UserMetadata.get((UserMetadata.uid == user.uid)
                                   & (UserMetadata.key == "pending_email"))
            umd.delete_instance()
        except UserMetadata.DoesNotExist:
            return None

    def set_pending_email(self, user, email):
        try:
            umd = UserMetadata.get((UserMetadata.uid == user.uid)
                                   & (UserMetadata.key == "pending_email"))
            umd.value = email
            umd.save()
        except UserMetadata.DoesNotExist:
            UserMetadata.create(uid=user.uid, key="pending_email", value=email)

    def confirm_pending_email(self, user, email):
        try:
            umd = UserMetadata.get((UserMetadata.uid == user.uid)
                                   & (UserMetadata.key == "pending_email"))
            umd.delete_instance()
        except UserMetadata.DoesNotExist:
            pass
        if self.get_user_auth_source(user) == UserAuthSource.KEYCLOAK:
            self.keycloak_admin.update_user(user_id=user.uid,
                                            payload={'email': email})
        user.email = email
        user.save()
        self.set_email_verified(user)

    def is_email_verified(self, user):
        try:
            umd = UserMetadata.get((UserMetadata.uid == user.uid)
                                   & (UserMetadata.key == "email_verified"))
            return bool(umd.value)
        except UserMetadata.DoesNotExist:
            return False

    def set_email_verified(self, user, value=True):
        if self.get_user_auth_source(user) == UserAuthSource.KEYCLOAK:
            self.keycloak_admin.update_user(user_id=user.uid,
                                            payload={'emailVerified': value})
        value = '1' if value else '0'
        try:
            umd = UserMetadata.get((UserMetadata.uid == user.uid)
                                   & (UserMetadata.key == "email_verified"))
            umd.value = value
            umd.save()
        except UserMetadata.DoesNotExist:
            UserMetadata.create(uid=user.uid,
                                key="email_verified",
                                value=value)

    def validate_password(self, user, password):
        if user.crypto == UserCrypto.BCRYPT:
            thash = bcrypt.hashpw(password.encode('utf-8'),
                                  user.password.encode('utf-8'))
            if thash == user.password.encode('utf-8'):
                if self.provider == 'KEYCLOAK':
                    self.keycloak_admin.create_user({
                        'id':
                        user.uid,
                        'email':
                        user.email,
                        'username':
                        user.name,
                        'enabled':
                        True,
                        'emailVerified':
                        self.is_email_verified(user),
                        'credentials': [{
                            'value': password,
                            'type': 'password'
                        }]
                    })
                    self.set_user_auth_source(user, UserAuthSource.KEYCLOAK)
                    user.crypto = UserCrypto.REMOTE
                    user.password = ''
                    user.save()
                return True
        elif (user.crypto == UserCrypto.REMOTE
              and self.get_user_auth_source(user) == UserAuthSource.KEYCLOAK
              and self.provider == 'KEYCLOAK'):
            try:
                # TODO do something with the token
                self.keycloak_openid.token(username=user.name,
                                           password=password)
                return True
            except KeycloakError as err:
                return False
        return False

    def change_user_status(self, user, new_status):
        if new_status == 10:
            payload = {'email': '', 'emailVerified': False, 'enabled': False}
            user.email = ''
            user.email_verified = False
        elif user.status != 10 and new_status == 5:
            payload = {'enabled': False}
        elif user.status != 10 and new_status == 0:
            payload = {'enabled': True}
        else:
            raise RuntimeError("Invalid user status")

        if user.crypto == UserCrypto.REMOTE:
            if (self.get_user_auth_source(user) == UserAuthSource.KEYCLOAK
                    and self.provider == 'KEYCLOAK'):
                self.keycloak_admin.update_user(user_id=user.uid,
                                                payload=payload)

        user.status = new_status
        user.resets += 1  # Make them log in again.
        user.save()

    def actually_delete_user(self, user):
        # Used by automatic tests to clean up test realm on server.
        # You should probably be using mark_user_deleted.
        if user.crypto == UserCrypto.REMOTE:
            self.keycloak_admin.delete_user(user.uid)
Esempio n. 24
0
class KeycloakUserManagement(UserManagement):
    def __init__(self, ex, parameters=None):
        from keycloak import KeycloakOpenID

        if parameters is None:
            parameters = {}
        self.ex = ex
        self.server_url = parameters["server_url"]
        self.client_id = parameters["client_id"]
        self.realm_name = parameters["realm_name"]
        self.client_secret_key = parameters["client_secret_key"]

        self.keycloak_manager = KeycloakOpenID(
            server_url=self.server_url,
            client_id=self.client_id,
            realm_name=self.realm_name,
            client_secret_key=self.client_secret_key)

        UserManagement.__init__(self, ex)

    def do_login(self, user, password):
        """
        Logs in a user and returns a session id

        Parameters
        ------------
        user
            Username
        password
            Password

        Returns
        ------------
        session_id
            Session ID
        """
        try:
            token = self.keycloak_manager.token(user, password)
            return token['access_token']
        except:
            # traceback.print_exc()
            pass
        return None

    def check_session_validity(self, session_id):
        """
        Checks the validity of a session

        Parameters
        ------------
        session_id
            Session ID

        Returns
        ------------
        boolean
            Boolean value
        """
        validity = False
        try:
            if not (str(session_id) == "null"):
                userinfo = self.keycloak_manager.userinfo(session_id)
                if type(userinfo["preferred_username"]) is str:
                    if userinfo["preferred_username"]:
                        validity = True
        except:
            # traceback.print_exc()
            pass
        return validity

    def get_user_from_session(self, session_id):
        """
        Gets the user from the session

        Parameters
        ------------
        session_id
            Session ID

        Returns
        ------------
        user
            User ID
        """
        user = None
        try:
            if not (str(session_id) == "null"):
                userinfo = self.keycloak_manager.userinfo(session_id)
                if type(userinfo["preferred_username"]) is str:
                    if userinfo["preferred_username"]:
                        user = userinfo["preferred_username"]
        except:
            # traceback.print_exc()
            pass
        return user

    def clean_expired_sessions(self):
        """
        Cleans the expired sessions in IAM
        """
        pass

    def get_all_sessions(self):
        """
        Gets all sessions from the users database

        Returns
        -----------
        sessions
            List of sessions
        """

        return None

    def get_all_users(self):
        """
        Possibly get all the users from the users database

        Returns
        -------------
        users
            List of users
        """

        return []
Esempio n. 25
0
from keycloak import KeycloakOpenID
import pprint

keycloak_openid = KeycloakOpenID(server_url="https://localhost:8181/auth/",
    client_id="example_client",
    realm_name="example_realm",
    client_secret_key="0f0f6195-41bb-4077-bd30-469964328ba0",
    verify=False)

config_well_know = keycloak_openid.well_know()

token = keycloak_openid.token("example_client", "0f0f6195-41bb-4077-bd30-469964328ba0", grant_type="client_credentials")

pprint.pprint(token)

Esempio n. 26
0
        config_well_know = keycloak_openid.well_know()

    except KeycloakError, e:
        pam_syslog(
            syslog.LOG_NOTICE, pamh, "auth",
            "unable to authenticate for %s: %d %s" %
            (user, e.response_code, e.error_message))
        return pamh.PAM_AUTHINFO_UNAVAIL

    if pamh.authtok is None:
        passmsg = pamh.Message(pamh.PAM_PROMPT_ECHO_OFF, "Password: "******"auth",
            "authentication failure for %s: %d %s" %
            (user, e.response_code, e.error_message))

        if e.response_code == 401:
            return pamh.PAM_AUTH_ERR
Esempio n. 27
0
    def check_password(self, user_id, password):
        """ Attempt to authenticate a user against an Keycloak Server
            and register an account if none exists.

            Returns:
                True if authentication against Keycloak was successful
        """
        if not password:
            defer.returnValue(False)

        localpart = user_id.split(":", 1)[0][1:]
        logger.info("! %s", localpart)

        keycloak_openid = KeycloakOpenID(server_url=self.url,
                                         client_id=self.client_id,
                                         realm_name=self.realm_name,
                                         client_secret_key=self.secret_key)
        logger.debug("Attempting Keycloak connection with %s", self.url)

        try:
            token = yield keycloak_openid.token(localpart, password)
        except KeycloakAuthenticationError as e:
            logger.info("Failed login attempt %s error: %s", localpart, e)
            defer.returnValue(False)

        logger.info("User %s authenticated", user_id)
        options = {"verify_signature": True, "verify_aud": True, "exp": True}

        key = self.public_key
        if self.algorithm == 'RS256':
            key = '-----BEGIN PUBLIC KEY-----\n' + key + '\n-----END PUBLIC KEY-----'

        token_info = keycloak_openid.decode_token(token['access_token'],
                                                  key=key,
                                                  algorithms=[self.algorithm],
                                                  options=options)

        if not (yield self.account_handler.check_user_exists(user_id)):
            logger.info("User %s does not exist yet, creating...", user_id)
            if localpart != localpart.lower() and self.regLower:
                logger.info(
                    'User %s was cannot be created due to username lowercase policy',
                    localpart)
                defer.returnValue(False)
            user_id, access_token = (yield self.account_handler.register(
                localpart=localpart))
            registration = True
            logger.info(
                "Registration based on REST data was successful for %s",
                user_id)
        else:
            logger.info("User %s already exists, registration skipped",
                        user_id)

        if bool(self.profile_attrs):
            logger.info("profile attrs")
            store = yield self.account_handler.hs.get_profile_handler().store
            profile = {}
            for key, alias in self.profile_attrs.items():
                if alias in token_info:
                    profile[key] = token_info[alias]

            display_name = profile.pop('display_name', None)
            if display_name:
                logger.info(
                    "Setting display name to '%s' based on profile data",
                    display_name)
                yield store.set_profile_displayname(localpart, display_name)
            logger.info("end profile attrs")

            # TODO 3pids
        else:
            logger.info("No profile data")

        def _save_keycloak_token(txn):
            template = """
INSERT INTO keycloak_provider_tokens
(user_id, refresh_tokens)
VALUES
('{0}', ARRAY['{1}'])
ON CONFLICT (user_id) DO
UPDATE SET
refresh_tokens = array_append(keycloak_provider_tokens.refresh_tokens, '{1}')
"""
            sql = template.format(user_id, token['refresh_token'])
            txn.execute(sql)

        self.account_handler.run_db_interaction("save_keycloak_token",
                                                _save_keycloak_token)
        logger.info("insert end")
        defer.returnValue(True)
Esempio n. 28
0
class Keycloakconnector:
    keycloak_openid = None

    def __init__(self, serverurl, realm, clientid, secret):
        self.keycloak_openid = KeycloakOpenID(server_url=serverurl,
                                              client_id=clientid,
                                              realm_name=realm,
                                              client_secret_key=secret,
                                              verify=True)
        config_well_know = self.keycloak_openid.well_know()
        self.serverurl = serverurl
        self.realm = realm
        # print(config_well_know)

    def getToken(self, appID, api):
        token = self.keycloak_openid.token(username="",
                                           password="",
                                           grant_type=["client_credentials"])
        token = token['access_token']
        print("Access token = ")
        print(token)
        return token

    # Get JWT public key.
    def getJWTPublickey(self):
        cert = self.keycloak_openid.certs()
        if cert is None:
            return ""
        x5c = cert.get('keys')[0]['x5c'][0]
        x5c = '-----BEGIN CERTIFICATE-----\n' + x5c + '\n-----END CERTIFICATE-----'
        x509 = OpenSSL.crypto.load_certificate(FILETYPE_PEM, x5c)
        pubkey = x509.get_pubkey()
        pubkey = OpenSSL.crypto.dump_publickey(FILETYPE_PEM,
                                               pubkey).decode("utf-8")
        return pubkey

    def getClientRoles(self, clientid, daa_token):
        api_call_headers = {
            'Authorization': 'Bearer ' + daa_token,
            'cache-control': "no-cache",
            "Content-Type": "application/json",
            "charset": "utf-8"
        }

        roles = ""

        try:
            # get keycloak client representation (needed to get the value of id_of_client parameter)
            client_url = self.serverurl + "admin/realms/" + self.realm + "/clients?clientId=" + clientid
            client_rep = get(client_url, headers=api_call_headers)
            client_json = json.loads(client_rep.text)
            id_of_client = client_json[0]["id"]
            print(id_of_client)

            # get client roles
            roles_url = self.serverurl + "admin/realms/" + self.realm + "/clients/" + id_of_client + "/roles"
            roles_rep = get(roles_url, headers=api_call_headers)
            keycloak_roles = json.loads(roles_rep.text)

            if "can_id_read" in keycloak_roles[0]:
                can_id_read_array = keycloak_roles[0]["description"].split(",")
                can_id_write_array = keycloak_roles[1]["description"].split(
                    ",")
            else:
                can_id_read_array = keycloak_roles[1]["description"].split(",")
                can_id_write_array = keycloak_roles[0]["description"].split(
                    ",")

            roles = json.loads('{"can_id_read": "", "can_id_write" : ""}')
            roles["can_id_read"] = can_id_read_array
            roles["can_id_write"] = can_id_write_array

        except JSONDecodeError as error:
            print(
                "Json decoding error occurred. Input is not in json format or does not contain the required fields"
            )
            raise SyntaxError
        except Exception as exp:
            print("An exception occurred while retrieving client roles {}".
                  format(exp))

        return roles
Esempio n. 29
0
class KeycloakClient:
    """Wrapper for Keycloak OpenID and admin clients."""
    def __init__(self, server, resource, realm, secret, admin_user,
                 admin_pass):
        self.openid = KeycloakOpenID(
            server_url=server,
            client_id=resource,
            realm_name=realm,
            client_secret_key=secret,
        )
        self.admin = _KeycloakAdmin(
            server_url=server,
            client_id=resource,
            realm_name=realm,
            client_secret_key=secret,
            username=admin_user,
            password=admin_pass,
            auto_refresh_token=['get', 'put', 'post', 'delete'],
        )

    def login(self, username, password):
        return self.openid.token(username, password, totp=None)

    def token_refresh(self, refresh_token):
        return self.openid.refresh_token(refresh_token)

    def token_info(self, token):
        return self.openid.introspect(token)

    def user_list(self, query=None):
        return self.admin.get_users(query)

    def user_get(self, user_id):
        return self.admin.get_user(user_id)

    def user_create(self, data):
        data = data.copy()
        data.setdefault('enabled', True)

        if 'password' in data:
            data['credentials'] = [
                {
                    'type': 'password',
                    'value': data['password']
                },
            ]
            del data['password']

        return self.admin.create_user(data)

    def user_update(self, user_id, data):
        data = data.copy()

        if 'password' in data:
            data['credentials'] = [
                {
                    'type': 'password',
                    'value': data['password']
                },
            ]
            del data['password']

        self.admin.update_user(user_id, data)

    def user_delete(self, user_id):
        self.admin.delete_user(user_id)

    def user_group_list(self, user_id):
        """Get list of groups user belongs to."""
        return self.admin.get_user_groups(user_id)

    def user_role_list(self, user_id):
        """
        Get set of all user roles (**role names**), directly assigned and also
        inherited from a group.
        """
        roles = set()

        # directly assigned roles
        roles = {
            i['name']
            for i in self.admin.get_realm_roles_of_user(user_id)
        }

        # iherited roles from group
        for group in self.user_group_list(user_id):
            roles |= {
                i['name']
                for i in self.admin.get_group_realm_roles(group['id'])
            }

        return roles

    def user_check_group(self, user_id, group_id):
        """Check if user belongs to the given group."""
        return self.user_check_group_any(user_id, [group_id])

    def user_check_group_any(self, user_id, group_id_list):
        """Check if user belongs to any of the given groups."""
        return any(group['id'] in group_id_list
                   for group in self.user_group_list(user_id))

    def user_check_role(self, user_id, role_name):
        """Check if user has role."""
        return role_name in self.user_role_list(user_id)

    def group_list(self):
        return self.admin.get_groups()

    def group_get(self, group_id):
        return self.admin.get_group(group_id)

    def group_create(self, data):
        # `create_group` always returns b''
        self.admin.create_group(data)

        for group in self.group_list():
            if group['name'] == data['name']:
                return group['id']

    def group_update(self, group_id, data):
        self.admin.update_group(group_id, data)

    def group_delete(self, group_id):
        self.admin.delete_group(group_id)

    def group_user_list(self, group_id):
        """Get list of users in group."""
        return self.admin.get_group_members(group_id)

    def group_user_add(self, user_id, group_id):
        """Add user to group."""
        self.admin.group_user_add(user_id, group_id)

    def group_user_remove(self, user_id, group_id):
        """Remove user from group."""
        self.admin.group_user_remove(user_id, group_id)

    def group_role_list(self, group_id):
        return self.admin.get_group_realm_roles(group_id)

    def group_role_add(self, role_name, group_id):
        """Add role to group. **Role NAME, not ID.**"""
        role = self.role_get(role_name)
        self.admin.assign_group_realm_roles(group_id, [role])

    def group_role_remove(self, role_name, group_id):
        """Remove role from group. **Role NAME, not ID.**"""
        role = self.role_get(role_name)
        self.admin.delete_group_realm_roles(group_id, [role])

    def role_list(self):
        return self.admin.get_realm_roles()

    def role_get(self, role_name):
        """Get role by name. **NAME, not ID.**"""
        return self.admin.get_realm_role(role_name)

    def role_create(self, data):
        # `create_role` always returns b''
        self.admin.create_realm_role(data)

        for role in self.role_list():
            if role['name'] == data['name']:
                return role['name']

    def role_update(self, role_id, data):
        self.admin.update_realm_role(role_id, data)

    def role_delete(self, role_id):
        self.admin.delete_realm_role(role_id)
Esempio n. 30
0
from keycloak import KeycloakOpenID

# Configure client
keycloak_openid = KeycloakOpenID(server_url="http://localhost:8080/auth/",
                    client_id="example_client",
                    realm_name="example_realm",
                    client_secret_key="secret")

# Get WellKnow
config_well_know = keycloak_openid.well_know()

# Get Token
token = keycloak_openid.token("user", "password")
token = keycloak_openid.token("user", "password", totp="012345")

# Get Userinfo
userinfo = keycloak_openid.userinfo(token['access_token'])

# Refresh token
token = keycloak_openid.refresh_token(token['refresh_token'])

# Logout
keycloak_openid.logout(token['refresh_token'])

# Get Certs
certs = keycloak_openid.certs()

# Get RPT (Entitlement)
token = keycloak_openid.token("user", "password")
rpt = keycloak_openid.entitlement(token['access_token'], "resource_id")