{"id":16793587,"url":"https://github.com/joergschultzelutter/robotframework-remoterunner-ssl","last_synced_at":"2026-05-20T06:09:58.315Z","repository":{"id":139330697,"uuid":"516470336","full_name":"joergschultzelutter/robotframework-remoterunner-ssl","owner":"joergschultzelutter","description":"Port of the original 'robotframework-remoterunner' repository to a multithreaded XMLRPC Robot server with additional bugfixes and support for auto-installation of PyPi packages on the remote server","archived":false,"fork":false,"pushed_at":"2024-05-19T10:00:22.000Z","size":117,"stargazers_count":1,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-01-23T12:15:02.880Z","etag":null,"topics":["python3","robotframework","robotframework-remote","robotframework-testing","secure-communication"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/joergschultzelutter.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-07-21T17:52:01.000Z","updated_at":"2024-05-19T09:58:55.000Z","dependencies_parsed_at":null,"dependency_job_id":"5a54ea5a-9228-4f22-9b8d-31d50ddaaeee","html_url":"https://github.com/joergschultzelutter/robotframework-remoterunner-ssl","commit_stats":null,"previous_names":[],"tags_count":7,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/joergschultzelutter%2Frobotframework-remoterunner-ssl","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/joergschultzelutter%2Frobotframework-remoterunner-ssl/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/joergschultzelutter%2Frobotframework-remoterunner-ssl/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/joergschultzelutter%2Frobotframework-remoterunner-ssl/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/joergschultzelutter","download_url":"https://codeload.github.com/joergschultzelutter/robotframework-remoterunner-ssl/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243960636,"owners_count":20375107,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["python3","robotframework","robotframework-remote","robotframework-testing","secure-communication"],"created_at":"2024-10-13T08:49:42.445Z","updated_at":"2026-05-20T06:09:58.288Z","avatar_url":"https://github.com/joergschultzelutter.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# robotframework-remoterunner-ssl\n\n[![License: GPL v3](https://img.shields.io/badge/License-GPLv3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0) [![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black) [![CodeQL](https://github.com/joergschultzelutter/robotframework-remoterunner-mt/actions/workflows/codeql.yml/badge.svg)](https://github.com/joergschultzelutter/robotframework-remoterunner-mt/actions/workflows/codeql.yml)\n\nThis is a Python3 port of [chrisBrookes93](https://github.com/chrisBrookes93)'s [robotframework-remoterunner](https://github.com/chrisBrookes93/robotframework-remoterunner) to  [Etopian](https://github.com/etopian/)'s [https XMLRPC server](https://github.com/etopian/python3-xmlrpc-ssl-basic-auth), providing a multithreaded XMLRPC SSL server with BasicAuth support and automated remote server PyPi package installation to Robot Framework users.\n\n## Installation\n\n- Clone repository\n- ```pip install -r requirements.txt```\n- Generate the certificates\n- start ```server.py```\n- run ```client.py```. Ideally, you want to run a connection test first (```--test-connection``` option)\n\n## Repository contents\n\nThe ```src``` directory from this repo contains two core Python files:\n\n- ```server.py``` - The (remote) server that receives and executes the Robot Framework run\n- ```client.py``` - The client that connects to the server process and invokes the execution the Robot Framework run on that remote machine\n\n### client.py\n\n```text\nusage: client.py [-h] \n                 [--test-connection]\n                 [--host ROBOT_HOST]\n                 [--port ROBOT_PORT]\n                 [--user ROBOT_USER]\n                 [--pass ROBOT_PASS]\n                 [--log-level {NONE,TRACE,WARN,INFO,DEBUG}] \n                 [--suite ROBOT_SUITE [ROBOT_SUITE ...]]\n                 [--test ROBOT_TEST [ROBOT_TEST ...]] \n                 [--include ROBOT_INCLUDE [ROBOT_INCLUDE ...]]\n                 [--exclude ROBOT_EXCLUDE [ROBOT_EXCLUDE ...]] \n                 [--extension ROBOT_EXTENSION [ROBOT_EXTENSION ...]]\n                 [--output-dir ROBOT_OUTPUT_DIR] \n                 [--input-dir ROBOT_INPUT_DIR [ROBOT_INPUT_DIR ...]]\n                 [--output-file ROBOT_OUTPUT_FILE] \n                 [--log-file ROBOT_LOG_FILE]\n                 [--report-file ROBOT_REPORT_FILE]\n                 [--client-enforces-server-package-upgrade]\n                 [--debug]\n\noptions:\n  -h, --help            show this help message and exit\n  --test-connection     Enable this option to check if both client and server\n                        are properly configured. \n                        Returns a simple 'ok' string to the client if it was \n                        able to establish a secure connection to the remote \n                        XMLRPC server and supplied user/pass credentials\n                        were ok\n  --host ROBOT_HOST     IP or Hostname of the server to execute the\n                        robot run on. \n                        Default value = localhost\n  --port ROBOT_PORT     Port number of the server to execute the robot run on.\n                        Default value = 8111\n  --user ROBOT_USER     Server user name. \n                        Default value = admin\n  --pass ROBOT_PASS     Server user passwort.\n                        Default value = admin\n  --log-level {NONE,TRACE,WARN,INFO,DEBUG}\n                        Threshold level for logging. \n                        Available levels: TRACE, DEBUG, INFO,\n                        WARN, NONE (no logging). \n                        Examples: --log-level DEBUG\n  --suite ROBOT_SUITE [ROBOT_SUITE ...]\n                        Select test suites to run by name. When this option\n                        is used with --test, --include or --exclude, only test\n                        cases in matching suites and also matching other \n                        filtering criteria are selected. Name can be a\n                        simple pattern similarly as with --test and it\n                        can contain parent name separated with a dot. \n                        You can specify this parameter multiple times,\n                        if necessary.\n  --test ROBOT_TEST [ROBOT_TEST ...]\n                        Select test cases to run by name or long name. Name\n                        is case insensitive and it can also be a simple pattern\n                        where `*` matches anything and `?` matches any char.\n                        You can specify this parameter multiple times, if \n                        necessary.\n  --include ROBOT_INCLUDE [ROBOT_INCLUDE ...]\n                        Select test cases to run by tag. Similarly as name\n                        with --test, tag is case and space insensitive and\n                        it is possible to use patterns with `*` and `?` as \n                        wildcards. Tags and patterns can also be combined\n                        together with `AND`, `OR`, and `NOT` operators. \n                        Examples: --include foo, --include bar*, --include fooANDbar*\n  --exclude ROBOT_EXCLUDE [ROBOT_EXCLUDE ...]\n                        Select test cases not to run by tag. These tests are\n                        not run even if included with --include. \n                        Tags are matched using the rules explained with --include.\n  --extension ROBOT_EXTENSION [ROBOT_EXTENSION ...]\n                        Parse only files with this extension when executing a\n                        directory. Has no effect when running individual files\n                        or when using resource files. You can specify this\n                        parameter multiple times, if necessary. Specify the \n                        value without leading '.'. \n                        Example: `--extension robot`. \n                        Default extensions: robot, text, txt, resource\n  --output-dir ROBOT_OUTPUT_DIR\n                        Output directory which will host your output files. If\n                        a nonexisting dictionary is specified, it will be\n                        created for you. \n                        Default value: current directory\n  --input-dir ROBOT_INPUT_DIR [ROBOT_INPUT_DIR ...]\n                        Input directory (containing your robot tests). You can\n                        specify this parameter multiple times, if necessary. \n                        Default value: current directory\n  --output-file ROBOT_OUTPUT_FILE\n                        Robot Framework output file name.\n                        Default value: remote_output.xml\n  --log-file ROBOT_LOG_FILE\n                        Robot Framework log file name.\n                        Default value: remote_log.html\n  --report-file ROBOT_REPORT_FILE\n                        Robot Framework report file name.\n                        Default value: remote_report.html\n  --client-enforces-server-package-upgrade\n                        If your Robot Framework suite depends on external pip\n                        packages, enabling this switch results in always \n                        upgrading these packages on the remote XMLRPC server\n                        even if they are already installed. This is the \n                        equivalent to the server's \n                        'upgrade-server-packages=ALWAYS' option \n                        which allows you to control a forced update through \n                        the client. Note that the server can\n                        still disable upgrades completely by setting its \n                        'upgrade-server-packages' option to 'NEVER'\n  --debug               Run in debug mode. This will enable debug logging and\n                        does not cleanup the workspace directory\n                        on the remote machine after test execution\n```\n\nIf no parameters are specified, the ```client.py``` script will connect to a server on ```localhost``` port ```8111``` while serving all robot files from the current directory\n\n### server.py\n\n```text\nusage: server.py [-h]\n                 [--host ROBOT_HOST]\n                 [--port ROBOT_PORT]\n                 [--user ROBOT_USER] \n                 [--pass ROBOT_PASS]\n                 [--keyfile ROBOT_KEYFILE]\n                 [--certfile ROBOT_CERTFILE] \n                 [--log-level {TRACE,NONE,DEBUG,INFO,WARN}]\n                 [--upgrade-server-packages {NEVER,ALWAYS,OUTDATED}]\n                 [--debug]\n\noptions:\n  -h, --help            show this help message and exit\n  --host ROBOT_HOST     Address to bind to.\n                        Default is 'localhost'\n  --port ROBOT_PORT     Port to listen on. \n                        Default is 8111\n  --user ROBOT_USER     User name for BasicAuth authentification. \n                        Default value is 'admin'\n  --pass ROBOT_PASS     password for BasicAuth authentification.\n                        Default value is 'admin'\n  --keyfile ROBOT_KEYFILE\n                        SSL private key for secure communication. \n                        Default value is 'privkey.pem'\n  --certfile ROBOT_CERTFILE\n                        SSL certfile for secure communication.\n                        Default value is 'cacert.pem'\n  --log-level {TRACE,NONE,DEBUG,INFO,WARN}\n                        Robot Framework log level. \n                        Valid values = TRACE, DEBUG, INFO, WARN, NONE.\n                        Default value = WARN\n  --upgrade-server-packages {NEVER,ALWAYS,OUTDATED}\n                        If your Robot Framework suite depends on external\n                        pip packages, upgrade these packages on the remote\n                        XMLRPC server if they are outdated or not installed. \n                        Note that you are still required to specify the version \n                        decorator information in the Robot Framework code - \n                        see program documentation.\n                        Options: \n                        NEVER (default) = never upgrade or install pip \n                        packages on the server even if the client process\n                        requests it\n                        OUTDATED = only update if installed version differs\n                        from user-specified or latest PyPi version,\n                        ALWAYS = always update the packages on the server \n                        (this is equivalent to the client setting \n                        --client-enforces-server-package-upgrade but \n                        delegates the upgrade request to the server\n  --debug               Enables debug logging and will not delete the \n                        temporary directory after a robot run\n```\n\n## In scope\n\nSupports all features that are supported by Chris' [robotframework-remoterunner](https://github.com/chrisBrookes93/robotframework-remoterunner) repository. Additional features and bug fixes:\n\n- multithreaded https connection with both certificate and BasicAuth support\n- fixed error with Library / Resource statements and trailing comments\n- support for automated pip package installation on a remote server, including a distinction between forced updates and updates for outdated packages (details: see separate chapter)\n\n## Out of scope\n\n- Support for Python version 2\n- When using the server's pip version comparison (```--upgrade-server-packages=OUTDATED```), a version comparison range such as ```mypackage\u003e=1.2.3,\u003c=4.5.6``` is not supported and the program will fail\n- If you enable either the ```Client```'s or the ```Server```'s various pip package upgrade option, is is expected that the ```Server``` has access to the Internet. The is no magic wand or network proxy code that will establish this connection for you.\n\n## Connection Test\n\nFor a simple connection test between ```Client``` and ```Server```, install programs, environment variables and certificates (see following chapters). Run the server. Then run the client with the ```--test-connection``` option:\n\n```bash\n(venv) [20:52:52 - jsl@gowron - ~/git/robotframework-remoterunner-ssl/src]$ python client.py --test-connection\n2022-08-04 20:53:06,690 client -INFO- Connecting to: localhost:8111\n2022-08-04 20:53:06,762 client -INFO- OK\n```\nIf a SSL connection could be established and there was no mismatch in user/passwords, you should receive a plain 'OK' string from the ```Server```.\n\n## Library and Resource references for external files\n\nChris's original code already supported external references for:\n\n- external resource files\n- external python files\n\nExamples:\n\n```robotframework\n*** Settings ***\n\nResource        robot_resource.resource\nLibrary         python_file.py\n\n```\nRobot Framework standard libraries were also detected and obviously never got read from disk. However, PyPi/pip packages which were not installed on the server did not get detected. This topic is addressed in the next chapter.\n\n## Support for auto-installation of PyPi packages on the remote server\n\n### Introduction\n\nIf your Robot Framework suite depends on PyPi package libraries which are currently _not_ installed on the remote XMLRPC server, the previous lookup process would fail.\n\n```robotframework\nLibrary         Uninstalled_PyPi_Library\n```\n\nIn order to support this use case, both ```Server```/```Client``` processes use a decorator-like reference. Let's extend the previous example with that decorator:\n\n```robotframework\n*** Settings ***\n\nResource        robot_resource.resource\nLibrary         python_file.py\nLibrary         AppriseLibrary # @pip:robotframework-apprise\t\n```\n\nTo summarize: in order to enable PyPi package installation process via pip, you need to do the following:\n\n1. Specify your ```Library``` reference as usual\n\n```robotframework\nLibrary         AppriseLibrary\t\n```\n2. Add a trailing comment with a decorator to that line. Specify the name of the package as listed on PyPi.\n\n```robotframework\nLibrary         AppriseLibrary \t# @pip:robotframework-apprise\t\n```\nSyntax: ```@pip:\u003cPyPi-Package-Name\u003e[pypi version]``` \n\nStandard pip versioning is supported; just extend the decorator setting:\n\n```robotframework\nLibrary         AppriseLibrary # @pip:robotframework-apprise==0.1.0\t\n```\n\nLeading / trailing comments etc are ignored by the decorator parser, meaning that a decorator setting like the following would still be successful:\n\n```robotframework\nLibrary         AppriseLibrary               ##### Hello @pip:robotframework-aprslib==0.1.0 World\t\n```\n\n### Tell me more about what happens under the hood\n\n- Client process examines Robot code suites / tests\n- All ```Library``` references which do __not__ refer to external files (e.g. local Python files) and are __not__ part of the Robot Framework standard libraries will be cached by the ```Client``` and later on sent to the ```Server``` (similar to the file-based dependencies)\n- ```Server``` lookup process will only start if ```--upgrade-server-packages``` option is NOT set to ```NEVER```. The ```NEVER``` value setting disables __all__ package updates - even if they get requested by the client. \n- If that option is either set to ```OUTDATED``` or ```ALWAYS```, the ```Server``` process has a look at the pip package reference directory from the ```Client``` and checks if packages need to be installed:\n    - The ```Server``` temporarily unsets both ```SSL_CERT_FILE``` and ```REQUESTS_CA_BUNDLE``` environment variables as otherwise, the Pip installation and lookup process would fail.\n    - Each entry in the ```Client```'s pip directory will be checked against the list of PyPi packages that are installed on the server's Python environment.\n    - If the package is detected as 'installed', the ```Server``` process will not reinstall the package. Exceptions:\n        - Option ```--upgrade-server-packages``` was set to ```ALWAYS``` OR\n        - Option ```--upgrade-server-packages``` was set to ```OUTDATED``` AND a pip version mismatch was detected\n    - __Note that any use of these pip upgrade options might cause unintended side effects in case you run more than one test in parallel and re-install PyPi dependencies while running tasks at the same time which are dependent on these packages.__ \n    - The ```Server``` now processes any PyPi packages deemed for installation.\n    - The ```Server``` restores both ```SSL_CERT_FILE``` and ```REQUESTS_CA_BUNDLE``` environment variables to their original values\n- Finally, the Robot Framework Suite(s) are executed as usual\n\n## Certificate generation\n\n- Run the [genpubkey.sh](https://github.com/joergschultzelutter/robotframework-remoterunner-mt/blob/master/src/genpubkey.sh) script.\n- For testing on localhost, you can keep all defaults as is. Exception: set the ```FQDN``` setting to value ```localhost``` for both certificates\n- In case you use self-signed certificates for testing on ```localhost```, remember that you may be required set the following environment variables for __both__ ```Server``` _and_ ```Client``` sessions:\n\n```bash\n    export SSL_CERT_FILE=/path/to/your/cacert.pem\n    export REQUESTS_CA_BUNDLE=/path/to/your/cacert.pem\n```\n\nIn order to allow OpenSSL to trust your recently hatched self-signed certificate, you may need to apply a few more OS-specific steps. Details: see post on [StackOverflow](https://stackoverflow.com/questions/17437100/how-to-avoid-the-tlsv1-alert-unknown-ca-error-in-libmproxy)\n\n#### Windows\n\nSee [https://docs.microsoft.com/en-US/troubleshoot/windows-server/identity/export-root-certification-authority-certificate](https://docs.microsoft.com/en-US/troubleshoot/windows-server/identity/export-root-certification-authority-certificate)\n\n#### Linux\n\n##### Install\n\n```bash\nsudo mkdir /etc/share/certificates/extra \u0026\u0026 cp cacert.crt /user/share/certficates/extra/cacert.crt\nsudo dpkg-reconfigure ca-certificates\n```\n\n##### Uninstall\n\n```bash\nsudo rm -r /etc/share/certificates/extra\nsudo dpkg-reconfigure ca-certificates\n```\n\n### MacOS\n\n##### Install\n```bash\nsudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain cacert.pem\n```\n\n##### Uninstall\n```bash\nsudo security remove-trusted-cert -d cacert.pem\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjoergschultzelutter%2Frobotframework-remoterunner-ssl","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjoergschultzelutter%2Frobotframework-remoterunner-ssl","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjoergschultzelutter%2Frobotframework-remoterunner-ssl/lists"}