{"id":13677219,"url":"https://github.com/internap/fake-switches","last_synced_at":"2026-01-16T12:14:28.892Z","repository":{"id":1993658,"uuid":"41325076","full_name":"internap/fake-switches","owner":"internap","description":"A pluggable switch/router command-line simulator","archived":false,"fork":false,"pushed_at":"2024-06-20T10:39:17.000Z","size":835,"stargazers_count":71,"open_issues_count":13,"forks_count":42,"subscribers_count":16,"default_branch":"master","last_synced_at":"2025-09-25T02:25:14.788Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/internap.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":"2015-08-24T20:19:57.000Z","updated_at":"2025-07-11T15:38:50.000Z","dependencies_parsed_at":"2024-08-02T13:15:34.763Z","dependency_job_id":"8b014311-71ec-44d8-87b7-e8ef770b5bfe","html_url":"https://github.com/internap/fake-switches","commit_stats":{"total_commits":173,"total_committers":26,"mean_commits":6.653846153846154,"dds":0.791907514450867,"last_synced_commit":"954ef1d86e2630274d7df1690601a5c511065d43"},"previous_names":[],"tags_count":68,"template":false,"template_full_name":null,"purl":"pkg:github/internap/fake-switches","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/internap%2Ffake-switches","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/internap%2Ffake-switches/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/internap%2Ffake-switches/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/internap%2Ffake-switches/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/internap","download_url":"https://codeload.github.com/internap/fake-switches/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/internap%2Ffake-switches/sbom","scorecard":{"id":491446,"data":{"date":"2025-08-11","repo":{"name":"github.com/internap/fake-switches","commit":"954ef1d86e2630274d7df1690601a5c511065d43"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3.8,"checks":[{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Code-Review","score":9,"reason":"Found 20/22 approved changesets -- score normalized to 9","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Info: jobLevel 'contents' permission set to 'read': .github/workflows/release.yaml:14","Warn: no topLevel permission defined: .github/workflows/release.yaml:1","Warn: no topLevel permission defined: .github/workflows/unittests.yml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: Apache License 2.0: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Pinned-Dependencies","score":1,"reason":"dependency not pinned by hash detected -- score normalized to 1","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/release.yaml:22: update your workflow using https://app.stepsecurity.io/secureworkflow/internap/fake-switches/release.yaml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/release.yaml:24: update your workflow using https://app.stepsecurity.io/secureworkflow/internap/fake-switches/release.yaml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/release.yaml:39: update your workflow using https://app.stepsecurity.io/secureworkflow/internap/fake-switches/release.yaml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/release.yaml:48: update your workflow using https://app.stepsecurity.io/secureworkflow/internap/fake-switches/release.yaml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/release.yaml:51: update your workflow using https://app.stepsecurity.io/secureworkflow/internap/fake-switches/release.yaml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/unittests.yml:18: update your workflow using https://app.stepsecurity.io/secureworkflow/internap/fake-switches/unittests.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/unittests.yml:20: update your workflow using https://app.stepsecurity.io/secureworkflow/internap/fake-switches/unittests.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/unittests.yml:34: update your workflow using https://app.stepsecurity.io/secureworkflow/internap/fake-switches/unittests.yml/master?enable=pin","Warn: containerImage not pinned by hash: Dockerfile:1: pin your Docker image by updating python:2.7-alpine to python:2.7-alpine@sha256:724d0540eb56ffaa6dd770aa13c3bc7dfc829dec561d87cb36b2f5b9ff8a760a","Warn: pipCommand not pinned by hash: Dockerfile:13","Warn: pipCommand not pinned by hash: Dockerfile:20","Warn: pipCommand not pinned by hash: .github/workflows/release.yaml:29","Warn: pipCommand not pinned by hash: .github/workflows/release.yaml:31","Warn: pipCommand not pinned by hash: .github/workflows/unittests.yml:25","Info:   0 out of   6 GitHub-owned GitHubAction dependencies pinned","Info:   2 out of   4 third-party GitHubAction dependencies pinned","Info:   0 out of   1 containerImage dependencies pinned","Info:   0 out of   5 pipCommand dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Branch-Protection","score":-1,"reason":"internal error: error during branchesHandler.setup: internal error: githubv4.Query: Resource not accessible by integration","details":null,"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 28 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Vulnerabilities","score":0,"reason":"18 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GHSA-55x5-fj6c-h6m8","Warn: Project is vulnerable to: PYSEC-2021-19 / GHSA-jq4v-f5q6-mjqq","Warn: Project is vulnerable to: PYSEC-2020-62 / GHSA-pgww-xf46-h92r","Warn: Project is vulnerable to: PYSEC-2022-230 / GHSA-wrxv-2j5q-m38w","Warn: Project is vulnerable to: PYSEC-2018-12 / GHSA-xp26-p53h-6h2p","Warn: Project is vulnerable to: GHSA-32gv-6cf3-wcmq","Warn: Project is vulnerable to: PYSEC-2020-214 / GHSA-3gqj-cmxr-p4x2","Warn: Project is vulnerable to: PYSEC-2019-129 / GHSA-65rm-h285-5cc5","Warn: Project is vulnerable to: PYSEC-2019-128 / GHSA-6cc5-2vg4-cc7m","Warn: Project is vulnerable to: GHSA-8r99-h8j2-rw64","Warn: Project is vulnerable to: PYSEC-2022-195 / GHSA-c2jg-hw38-jrqq","Warn: Project is vulnerable to: GHSA-c8m8-j448-xjx7","Warn: Project is vulnerable to: PYSEC-2024-75 / GHSA-cf56-g6w6-pqq2","Warn: Project is vulnerable to: PYSEC-2020-259 / GHSA-h96w-mmrf-2h6v","Warn: Project is vulnerable to: PYSEC-2020-260 / GHSA-p5xh-vx83-mxcj","Warn: Project is vulnerable to: PYSEC-2023-224 / GHSA-xc8x-vp79-p3wm","Warn: Project is vulnerable to: PYSEC-2019-212","Warn: Project is vulnerable to: PYSEC-2022-160"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-19T19:16:16.439Z","repository_id":1993658,"created_at":"2025-08-19T19:16:16.439Z","updated_at":"2025-08-19T19:16:16.439Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28478528,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-16T11:59:17.896Z","status":"ssl_error","status_checked_at":"2026-01-16T11:55:55.838Z","response_time":107,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":[],"created_at":"2024-08-02T13:00:39.000Z","updated_at":"2026-01-16T12:14:28.876Z","avatar_url":"https://github.com/internap.png","language":"Python","funding_links":[],"categories":["Python"],"sub_categories":[],"readme":"[![Build Status](https://travis-ci.org/internap/fake-switches.svg?branch=master)](https://travis-ci.org/internap/fake-switches)\n[![PyPI version](https://badge.fury.io/py/fake-switches.svg)](http://badge.fury.io/py/fake-switches)\n\nFake-switches\n=============\n\n![Commandline Demo](demo-cli.gif)\n\nFake-switches is a pluggable switch/router command-line simulator. It is meant\nto help running integrated tests against network equipment without the burden\nof having devices in a lab. This helps testing the communication with the\nequipment along with all of its layers for more robust high level tests.  Since\nit is meant to be used by other systems and not humans, error handling on\nincomplete commands and fail-proofing has been mostly left out and only\nrelevant errors are shown. \n\nThe library can easily be extended to react to some changes in the fake switch\nconfiguration and control an actual set of tools to have an environment\nbehaving like a real one driven by a switch.  For example, you could hook\nyourself to the VLAN creation and use vconfig to create an actual vlan on a\nmachine for some network testing.\n\nThis library is NOT supported by any vendor, it was built by\nreverse-engineering network equipment.\n\n\nActual supported commands\n=========================\n\nCommand support has been added in a as-needed manner for the purpose of what\nwas tested and how.  So see which commands may be used and their supported\nbehavior, please see the tests section for each model.\n\n| Model   | Protocols        | Test location |\n| ------- | ---------------- | ------------- |\n| Cisco   | ssh and telnet   | [tests/cisco/test_cisco_switch_protocol.py](tests/cisco/test_cisco_switch_protocol.py) |             \n| Brocade | ssh              | [tests/brocade/test_brocade_switch_protocol.py](tests/brocade/test_brocade_switch_protocol.py) |\n| Juniper | netconf over ssh | [tests/juniper/juniper_base_protocol_test.py](tests/juniper/juniper_base_protocol_test.py) |\n| Dell    | ssh and telnet   | [tests/dell/](tests/dell/) |\n\nUsing it with Docker\n====================\n\n```shell\n$ docker run -P -d internap/fake-switches\n$ docker ps\nCONTAINER ID        IMAGE                             COMMAND                  CREATED             STATUS              PORTS                     NAMES\n6eec86849561        internap/fake-switches            \"/bin/sh -c 'fake-swi\"   35 seconds ago      Up 13 seconds       0.0.0.0:32776-\u003e22/tcp     boring_thompson\n$ ssh 127.0.0.1 -p 32776 -l root\nroot@127.0.0.1's password:  # root\nmy_switch\u003eenable\nPassword:  # press \u003cRETURN\u003e\nmy_switch#show run\nBuilding configuration...\n\nCurrent configuration : 164 bytes\nversion 12.1\n!\nhostname my_switch\n!\n!\nvlan 1\n!\ninterface FastEthernet0/1\n!\ninterface FastEthernet0/2\n!\ninterface FastEthernet0/3\n!\ninterface FastEthernet0/4\n!\nend\n\nmy_switch#\n\n```\n\nLaunching with custom parameters\n--------------------------------\n\n```shell\n$ docker run -P -d -e SWITCH_MODEL=\"another_model\" internap/fake-switches\n```\n\nSupported parameters\n--------------------\n\n| Name              | Default value     |\n| ----------------- | ----------------- |\n| SWITCH_MODEL \t\t| cisco_generic \t|\n| SWITCH_HOSTNAME \t| switch \t\t\t|\n| SWITCH_USERNAME \t| root \t\t\t\t|\n| SWITCH_PASSWORD \t| root \t\t\t\t|\n| LISTEN_HOST \t\t| 0.0.0.0 \t\t\t|\n| LISTEN_PORT \t\t| 22 \t\t\t\t|\n\n\nBuilding image from source\n--------------------------\n\n```shell\n$ docker build -t fake-switches .\n$ docker run -P -d fake-switches\n```\n\nExtending functionality\n=======================\n\nThe SwitchConfiguration class can be extended and given an object factory with\ncustom classes that can act upon resources changes. For example :\n\n```python\n\nfrom twisted.internet import reactor\nfrom fake_switches.switch_configuration import SwitchConfiguration, Port\nfrom fake_switches.transports.ssh_service import SwitchSshService\nfrom fake_switches.cisco.cisco_core import CiscoSwitchCore\n\nclass MySwitchConfiguration(SwitchConfiguration):\n    def __init__(self, *args, **kwargs):\n        super(MySwitchConfiguration, self).__init__(objects_overrides={\"Port\": MyPort}, *args, **kwargs)\n\n\nclass MyPort(Port):\n    def __init__(self, name):\n        self._access_vlan = None\n\n        super(MyPort, self).__init__(name)\n\n    @property\n    def access_vlan(self):\n        return self._access_vlan\n\n    @access_vlan.setter\n    def access_vlan(self, value):\n        if self._access_vlan != value:\n            self._access_vlan = value\n            print \"This could add vlan to eth0\"\n\n\nif __name__ == '__main__':\n    ssh_service = SwitchSshService(\n        ip=\"127.0.0.1\",\n        ssh_port=11001,\n        switch_core=CiscoSwitchCore(MySwitchConfiguration(\"127.0.0.1\", \"my_switch\", ports=[MyPort(\"FastEthernet0/1\")])))\n    ssh_service.hook_to_reactor(reactor)\n    reactor.run()\n```\n\nThen, if you connect to the switch and do\n\n```\n    ssh root@127.0.0.1 -p 11001\n    password : root\n    \u003e enable\n    password:\n    # configure terminal\n    # vlan 1000\n    # interface FastEthernet0/1\n    # switchport access vlan 1000\n```\n\nYour program should say \"This could add vlan to eth0\" or do anything you would\nwant it to do :)\n\n\nStarting a switch from the command line\n=======================================\n\n```shell\n    pip install fake-switches\n    \n    fake-switches\n\n    # On a different shell, type the following:\n    ssh root@127.0.0.1 -p 22222\n```\n\nCommand line help\n-----------------\n\nThe --help flag is supported.\n\n    fake-switches --help\n    usage: fake-switches [-h] [--model MODEL] [--hostname HOSTNAME]\n                         [--username USERNAME] [--password PASSWORD]\n                         [--listen-host LISTEN_HOST] [--listen-port LISTEN_PORT]\n\n    Fake-switch simulator launcher\n\n    optional arguments:\n      -h, --help            show this help message and exit\n      --model MODEL         Switch model, allowed values are\n                            juniper_qfx_copper_generic, cisco_2960_24TT_L,\n                            dell_generic, dell10g_generic, juniper_generic,\n                            cisco_2960_48TT_L, cisco_generic, brocade_generic\n                            (default: cisco_generic)\n      --hostname HOSTNAME   Switch hostname (default: switch)\n      --username USERNAME   Switch username (default: root)\n      --password PASSWORD   Switch password (default: root)\n      --listen-host LISTEN_HOST\n                            Listen host (default: 0.0.0.0)\n      --listen-port LISTEN_PORT\n                            Listen port (default: 2222)\n\n\nAvailable switch models\n-----------------------\n\nAt time of writing this document, the following models are available:\n \n  * brocade_generic\n  * cisco_generic\n  * cisco_2960_24TT_L\n  * cisco_2960_48TT_L\n  * dell_generic\n  * dell10g_generic\n  * juniper_generic\n  * juniper_qfx_copper_generic\n\nUse the --help flag to find the available models.\n\nThe generic models are mainly for test purposes. They usually have less ports than a proper switch\nmodel but behave the same otherwise. Once a \"core\" is available, more specific models can be very\neasily added. Send your pull requests :)\n\n\nContributing\n============\n\nFeel free raise issues and send some pull request,\nwe'll be happy to look at them!\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Finternap%2Ffake-switches","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Finternap%2Ffake-switches","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Finternap%2Ffake-switches/lists"}