示例#1
0
    def resolveStandardUserToken(self, username, password, clientId):
        params = self.resolveStandardUserTokenRequestParameters(clientId)
        redirectUri = urllib.parse.unquote(params['redirectUri'])

        params = self.resolveKeycloakSessionAuthenticationCode(username, password, params)

        code = params.get("code", None)
        if isEmpty(code):
            die("No Keycloak access token session code")

        requestHeaders = {
            "Accepts": "application/json",
            "Content-Type": "application/x-www-form-urlencoded"
        }

        formData = "&".join(
            (
                "grant_type=authorization_code",
                "code=%s" % code,
                "client_id=%s" % clientId,
                "redirect_uri=%s"% redirectUri
            )
        )

        url = self.resolveKeycloakDirectTokenAccessUrl()
        rsp = self.executeHttpRequest(url, "POST", requestHeaders, formData, asJson=True)
        return rsp["body"]
示例#2
0
    def resolveKeycloakRealmAccessUrl(self):
        if self.args is None:
            die("No Keycloak access arguments provided")

        protocol = self.args.get("protocol", "https")
        host = self.args.get("host", None)
        if isEmpty(host):
            die("No Keycloak host specified")

        port = self.args.get("port", -1)
        realm = self.args.get("realm", "unifiedpush-installations")
        if port > 0:
            return "%s://%s:%d/auth/realms/%s" % (protocol, host, port, realm)
        else:
            return "%s://%s/auth/realms/%s" % (protocol, host, realm)
示例#3
0
def parse_site_url(args):
    url = args["site_basic_url"]

    protocol = url.split("://")[0]
    args["protocol"] = protocol

    base_url = url.split("://")[1]
    args["host"] = base_url.split(":")[0]
    if len(base_url.split(":")) > 1:
        args["port"] = base_url.split(":")[1]
    domain = args.get("domain")

    if domain not in base_url:
        die("domain %s is missing from site_basic_url %s" % (domain, url))
    client_id = base_url.split("-%s" % domain)[0]
    args["clientId"] = client_id
示例#4
0
    def resolveKeycloakSessionAuthenticationCode(self, username, password, params):
        url = params['loginUrl']
        if isEmpty(url):
            die("Failed to extract Keycloak login URL value")

        cookies = {}

        sessionId = params.get('AUTH_SESSION_ID', None)
        if isEmpty(sessionId):
            die("No Keycloak session ID cookie present")
        cookies["AUTH_SESSION_ID"] = sessionId

        kcToken = params.get('KC_RESTART', None)
        if isEmpty(kcToken):
            die("No Keycloak restart cookie present")
        cookies["KC_RESTART"] = kcToken

        requestHeaders = {
            "Content-Type": "application/x-www-form-urlencoded",
            "Referer": params["referer"]
        }

        formData = "&".join(("username=%s" % username, "password=%s" % password))

        rsp = self.executeHttpRequest(url, "POST", requestHeaders, formData, cookieJar=cookies, asJson=False)
        redirectHistory = rsp.get("history", None)
        if isEmpty(redirectHistory):
            if "INVALID_USER_PASS" in rsp.get("body", None):
                die("Invalid Username or Password")
            else:
                die("No Keycloak redirection available")

        rdData = redirectHistory[0]
        rdHeaders = rdData.headers
        locHeader = rdHeaders.get("Location", None)
        locItems = urllib.parse.urlparse(locHeader)
        # Response is https://..../#state=...
        queryParams = urllib.parse.parse_qs(locItems.fragment)
        code = queryParams.get("code", None)
        if isinstance(code, list):
            code = code[0]

        return {
            "url": rdData.url,
            "cookies": rsp.get("cookies", None),
            "code": code
        }
示例#5
0
    def run(self, opt_args=None):
        pyVersion = sys.version_info
        if pyVersion.major != 3:
            die("Major Python version must be 3.x: %s" % str(pyVersion))
        if pyVersion.minor < 0:
            die("Minor Python version %s should be at least 3.0+" %
                str(pyVersion))

        signal.signal(signal.SIGINT, self.signal_handler)
        if os.name == 'nt':
            sys.stderr.write("Use Ctrl+Break to stop the script\n")
        else:
            sys.stderr.write("Use Ctrl+C to stop the script\n")

        if opt_args is None:
            args = arguments_parser.ArgumentParser(
                self.report_type).parse_arguments()
        else:
            args = opt_args
            arguments_parser.process_args(args, self.report_type)

        logFactory = LogFactory(args)
        logger = logFactory.getLogger("main")
        token_fetcher = access_token_fetcher.AccessTokenFetcher(logger, args)
        token = token_fetcher.get_access_token()
        if isEmpty(token):
            die("Could not get access token for the username")

        try:
            if self.report_type == ReportType.RESPONSE:
                self.response_report(args, logger, token)
            else:
                self.earnings_report(args, logger, token)
        finally:
            token_fetcher.logout(token)
示例#6
0
    def resolve_user_token(self, username, password):
        self.logger.debug("Retrieving Keycloak access token")

        if isinstance(username, (int, float)):
            username = str(username)
        elif isEmpty(username):
            die("No Keycloak access username provided")

        if isinstance(password, (int, float)):
            password = str(password)
        elif isEmpty(password):
            die("No Keycloak access password provided")

        clientId = self.args.get("clientId", None)

        if isEmpty(clientId):
            die("No Keycloak client identifier provided")

        clientIdFormat = self.args.get("clientIdFormat", "ups-installation-%s")
        effectiveClientId = clientIdFormat % clientId

        mode = self.args.get("mode", "STANDARD")
        mode = mode.upper()
        if mode == "STANDARD":
            rsp = self.resolveStandardUserToken(
                username, password, effectiveClientId)
        elif mode == "DIRECT":
            rsp = self.resolveDirectGrantUserToken(
                username, password, effectiveClientId)
        else:
            die("Unknown Keycloak access token retrieval mode: %s" % mode)

        accessToken = rsp.get("access_token", None)
        self.refresh_token = rsp.get("refresh_token", None)
        if isEmpty(accessToken):
            self.logger.error("No access token in Keycloak response: %s" % str(rsp))
            die("No access token returned from Keycloak")

        self.logger.debug("Retrieved Keycloak access token")
        return accessToken
示例#7
0
    def appendLog(self, level, msg, err=None):
        nowValue = datetime.datetime.now()
        timestamp = nowValue.strftime(self.dateTimeFormat)
        threadName = "unknown"
        thread = threading.current_thread()
        if not thread is None:
            threadName = thread.name

        if msg:
            if '\n' in msg:
                for line in msg.splitlines(False):
                    self.writeLogMessage(
                        level, "%s %s [%s] [%s] %s" %
                        (timestamp, threadName, level.name, self.name, line))
            else:
                self.writeLogMessage(
                    level, "%s %s [%s] [%s] %s" %
                    (timestamp, threadName, level.name, self.name, msg))
        if err:
            self.writeLogMessage(
                level, "%s %s [%s] [%s] %s: %s" %
                (timestamp, threadName, level.name, self.name,
                 err.__class__.__name__, str(err)))

            if self.maxStackTraceDepth > 0:
                # TODO this doesn't quite do the job - by the time it is here, most stack trace data is gone...
                traceValue = traceback.format_exc(self.maxStackTraceDepth)
                lines = traceValue.splitlines()
                for traceLine in lines:
                    self.writeLogMessage(
                        level, "%s %s [%s] %s %s" %
                        (timestamp, threadName, level.name, self.name,
                         traceLine))

            if err.__class__.__name__ == "KeyboardInterrupt":
                die("Killed by Control+C")
示例#8
0
 def signal_handler(self):
     die('Exit due to Control+C')