Exemple #1
0
    def resolveOutputFilePath(self):
        filePath = self.args.get("file", None)
        if not isEmpty(filePath):
            filePath = self.resolvePathVariables(filePath)
            if os.path.isabs(filePath):
                print("report exported: {}".format(filePath))
                return filePath

        dirPath = self.args.get("dir", None)
        if not isEmpty(dirPath):
            dirPath = self.resolvePathVariables(dirPath)
        else:
            dirPath = gettempdir()

        if isEmpty(filePath):
            today = datetime.datetime.utcnow()
            filePath = "%s_%s.csv" % (self.file_name_prefix,
                                      today.strftime("%Y%m%d_%H%M"))

        if not os.path.isabs(dirPath):
            dirPath = os.path.abspath(dirPath)

        path = os.path.join(dirPath, filePath)
        print("Report exported to: {}".format(path))
        return path
Exemple #2
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)
Exemple #3
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"]
Exemple #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
        }
Exemple #5
0
 def parse_arguments(self):
     args = self.parser.parse_args()
     args = vars(args)
     for arg in args:
         if isEmpty(arg):
             args.pop(arg, None)
     process_args(args, self.report_type)
     return args
Exemple #6
0
    def resolvePathVariables(self, path):
        """
        Expands ~/xxx and ${XXX} variables
        """
        if isEmpty(path):
            return path

        path = os.path.expanduser(path)
        path = os.path.expandvars(path)
        return path
Exemple #7
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
Exemple #8
0
def manage_earnings_report_start_and_end_dates(args):
    req_start_date = args.get("start_date")
    day_of_week = args.get("first_day_of_week", DEFAULT_FIRST_DAY_OF_WEEK)

    today = datetime.datetime.utcnow().replace(hour=0,
                                               minute=0,
                                               second=0,
                                               microsecond=0)
    if not isEmpty(req_start_date):
        args["start_date"] = shift_date_to_first_day_of_week(
            parse_date(req_start_date), day_of_week)
    else:
        start_date = today - datetime.timedelta(weeks=5 * 12 * 4)
        args["start_date"] = shift_date_to_first_day_of_week(
            start_date, day_of_week)

    req_end_date = args.get("end_date")
    if not isEmpty(req_end_date):
        args["end_date"] = shift_date_to_end_day_of_week(
            parse_date(req_end_date), day_of_week)
    else:
        args["end_date"] = shift_date_to_end_day_of_week(today, day_of_week)

    attribute_start_month = args.get("attribute_start_month")
    if not isEmpty(attribute_start_month):
        args["attribute_start_month"] = shift_date_to_first_day_of_month(
            parse_date(attribute_start_month, "%b-%Y", "MMM-yyyy"))
    else:
        start_date = today - datetime.timedelta(weeks=5 * 12 * 4)
        args["attribute_start_month"] = shift_date_to_first_day_of_month(
            start_date)

    attribute_end_month = args.get("attribute_end_month")
    if not isEmpty(attribute_end_month):
        args["attribute_end_month"] = shift_date_to_end_day_of_month(
            parse_date(attribute_end_month, "%b-%Y", "MMM-yyyy"))
    else:
        args["attribute_end_month"] = shift_date_to_end_day_of_month(today)
Exemple #9
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)
Exemple #10
0
    def downloadReport(self, url, verb, headersMap, reqData):
        if headersMap is None:
            headersMap = {}

        dataBytes = None
        if not isEmpty(reqData):
            dataBytes = bytes(reqData, 'utf-8')
            headersMap["Content-Length"] = str(len(dataBytes))

        try:
            # InsecureRequestWarning: Unverified HTTPS request is being made.
            requests.packages.urllib3.disable_warnings()

            self.logger.debug("url: %s, header:%s, data: %s" %
                              (url, headersMap, dataBytes))
            connTimeout = self.args.get("connectTimeout", 15)
            rspTimeout = self.args.get("responseTimeout", 3000)
            rsp = requests.request(verb,
                                   url,
                                   headers=headersMap,
                                   data=dataBytes,
                                   verify=False,
                                   timeout=(connTimeout, rspTimeout))
            statusCode = rsp.status_code
            if (statusCode < 200) or (statusCode >= 400):
                raise urllib.error.HTTPError(url, statusCode,
                                             "Failed: %d" % statusCode,
                                             rsp.headers, None)

            filePath = self.resolveOutputFilePath()
            text_file = open(filePath, "wb")
            for chunk in rsp.iter_content(chunk_size=1024):
                text_file.write(chunk)

            text_file.close()
        except urllib.error.HTTPError as err:
            self.logger.error("Failed (%d %s) to invoke %s %s" %
                              (err.code, err.msg, verb, url))
            raise err
        except urllib.error.URLError as err:
            self.logger.error("Some unknown error for %s %s: %s" %
                              (verb, url, err.reason))
            raise err
Exemple #11
0
    def executeHttpRequest(self, url, verb, headersMap, reqData, cookieJar=None, asJson=True):
        if headersMap is None:
            headersMap = {}

        dataBytes = None
        if not isEmpty(reqData):
            dataBytes = bytes(reqData, 'utf-8')
            headersMap["Content-Length"] = str(len(dataBytes))

        try:
            # InsecureRequestWarning: Unverified HTTPS request is being made.
            requests.packages.urllib3.disable_warnings()

            self.logger.debug("%s %s" % (verb, url))
            connTimeout = self.args.get("connectTimeout", 15)
            rspTimeout = self.args.get("responseTimeout", 30)
            rsp = requests.request(verb, url, headers=headersMap,
                data=dataBytes, cookies=cookieJar, verify=False, timeout=(connTimeout, rspTimeout))
            statusCode = rsp.status_code
            if asJson and (statusCode >= 200) and (statusCode < 300):
                rspContent = rsp.json()
            else:
                rspContent = rsp.text
            # NOTE: we extract the response context regardless of the status code
            # so we can place a debug breakpoint here and see it
            if (statusCode < 200) or (statusCode >= 400):
                raise urllib.error.HTTPError(url, statusCode, "Reason: %s. URL: %s" % (rsp.reason, url), rsp.headers, None)
            result = {
                "statusCode": statusCode,
                "headers": rsp.headers,
                "cookies": rsp.cookies,
                "history": rsp.history,
                "body": rspContent
            }
            return result
        except urllib.error.HTTPError as err:
            self.logger.error("Failed (%d %s) to invoke %s %s" % (err.code, err.msg, verb, url))
            raise err
        except urllib.error.URLError as err:
            self.logger.error("Some unknown error for %s %s: %s" % (verb, url, err.reason))
            raise err
Exemple #12
0
def manage_response_report_start_and_end_dates(args):
    req_start_date = args.get("start_date")
    req_end_date = args.get("end_date")
    day_of_week = args.get("first_day_of_week", DEFAULT_FIRST_DAY_OF_WEEK)
    weeks_count = args.get("weeks_count", DEFAULT_WEEKS_COUNT)
    if isEmpty(req_end_date) and isEmpty(req_start_date):
        today = datetime.datetime.utcnow().replace(hour=0,
                                                   minute=0,
                                                   second=0,
                                                   microsecond=0)
        end_date = shift_date_to_end_day_of_week(today, day_of_week)
        args["end_date"] = end_date
        args["start_date"] = shift_date_to_first_day_of_week(
            end_date - datetime.timedelta(weeks=weeks_count), day_of_week)
        return

    if not isEmpty(req_end_date) and not isEmpty(req_start_date):
        args["start_date"] = shift_date_to_first_day_of_week(
            parse_date(req_start_date), day_of_week)
        args["end_date"] = shift_date_to_end_day_of_week(
            parse_date(req_end_date), day_of_week)
        return

    if not isEmpty(req_start_date):
        start_date = shift_date_to_first_day_of_week(
            parse_date(req_start_date), day_of_week)
        args["start_date"] = start_date
        args["end_date"] = shift_date_to_end_day_of_week(
            start_date + datetime.timedelta(weeks=weeks_count), day_of_week)
        return

    if not isEmpty(req_end_date):
        end_date = shift_date_to_end_day_of_week(parse_date(req_end_date),
                                                 day_of_week)
        args["end_date"] = end_date
        args["start_date"] = shift_date_to_first_day_of_week(
            end_date - datetime.timedelta(weeks=weeks_count), day_of_week)
Exemple #13
0
 def get_access_token(self) -> str:
     password = self.args.get("password")
     if isEmpty(password):
         password = getpass('Password: ')
     return self.resolve_user_token(self.args["username"], password)