{"id":13765148,"url":"https://github.com/hardbyte/netchecks","last_synced_at":"2026-03-09T07:10:06.007Z","repository":{"id":65952151,"uuid":"563647815","full_name":"hardbyte/netchecks","owner":"hardbyte","description":"Tool to validate assumptions about the network","archived":false,"fork":false,"pushed_at":"2025-03-25T03:25:13.000Z","size":5748,"stargazers_count":162,"open_issues_count":16,"forks_count":4,"subscribers_count":7,"default_branch":"main","last_synced_at":"2025-05-10T09:54:00.187Z","etag":null,"topics":["cloud-native","kubernetes-operator","network-monitoring","network-security","security"],"latest_commit_sha":null,"homepage":"https://docs.netchecks.io","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/hardbyte.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":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-11-09T03:06:49.000Z","updated_at":"2025-05-06T13:50:55.000Z","dependencies_parsed_at":"2023-11-20T08:04:14.244Z","dependency_job_id":"81231d06-76d1-4d9d-ad26-71488565666f","html_url":"https://github.com/hardbyte/netchecks","commit_stats":null,"previous_names":[],"tags_count":38,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hardbyte%2Fnetchecks","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hardbyte%2Fnetchecks/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hardbyte%2Fnetchecks/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hardbyte%2Fnetchecks/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/hardbyte","download_url":"https://codeload.github.com/hardbyte/netchecks/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254553959,"owners_count":22090417,"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":["cloud-native","kubernetes-operator","network-monitoring","network-security","security"],"created_at":"2024-08-03T16:00:34.581Z","updated_at":"2026-03-09T07:10:05.902Z","avatar_url":"https://github.com/hardbyte.png","language":"Python","funding_links":[],"categories":["Open Source Projects","Python"],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n\n# Netchecks\n\n\u003c/div\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003cimg alt=\"Netchecks Logo\" src=\"https://raw.githubusercontent.com/hardbyte/netchecks/main/.github/logo.png\" width=\"150\" /\u003e\n\u003c/p\u003e\n\n\u003cdiv align=\"center\"\u003e\n\n![Kubernetes](https://img.shields.io/badge/k8s-%23326ce5.svg?style=flat-square\u0026logo=kubernetes\u0026logoColor=white)\n[![HELM](https://img.shields.io/badge/helm-%23326ce5.svg?style=flat-square\u0026logo=helm\u0026logoColor=white)](https://artifacthub.io/packages/helm/netchecks/netchecks)\n[![ArtifactHub - Netchecks](https://img.shields.io/badge/ArtifactHub-Netchecks-informational?style=flat-square\u0026logo=artifacthub)](https://artifacthub.io/packages/helm/netchecks/netchecks)\n[![GitHub release (with filter)](https://img.shields.io/github/v/release/hardbyte/netchecks?style=flat-square\u0026logo=github)](https://github.com/hardbyte/netchecks/releases/latest)\n[![PyPI](https://img.shields.io/pypi/v/netcheck.svg?style=flat-square\u0026logo=pypi)](https://pypi.org/project/netcheck/)\n![PyPI - Python Version](https://img.shields.io/pypi/pyversions/netcheck?style=flat-square\u0026logo=python)\n[![Coverage Status](https://img.shields.io/coverallsCoverage/github/hardbyte/netchecks?branch=main\u0026style=flat-square\u0026logo=coveralls)](https://coveralls.io/github/hardbyte/netcheck?branch=main)\n[![CI status](https://img.shields.io/github/actions/workflow/status/hardbyte/netchecks/ci.yaml?branch=main\u0026style=flat-square\u0026logo=github)](https://github.com/hardbyte/netchecks/actions?query=branch%3Amain)\n[![Website](https://img.shields.io/website?url=https%3A%2F%2Fdocs.netchecks.io%2F\u0026style=flat-square\u0026label=docs.netchecks.io)](https://docs.netchecks.io/)\n[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg?style=flat-square)](https://github.com/psf/black)\n[![PyPI Downloads](https://static.pepy.tech/badge/netcheck)](https://pypi.org/project/netcheck?style=flat-square)\n[![License](https://img.shields.io/github/license/hardbyte/netchecks?style=flat-square)](/LICENSE)\n\n\u003c/div\u003e\n\n**Netchecks** is a set of tools for testing network conditions and asserting that they are as expected.\n\nThere are two main components:\n- **Netchecks Operator** - Kubernetes Operator that runs network checks and reports results as `PolicyReport` resources. See the [operator README](https://github.com/hardbyte/netchecks/blob/main/operator/README.md) for more details and the full documentation can be found at [https://docs.netchecks.io](https://docs.netchecks.io)\n- **Netcheck CLI and Python Library** - Command line tool for running network checks and asserting that they are as expected. Keep reading for the quickstart guide.\n\n\n# Netcheck Command Line Tool\n\n`netcheck` is a configurable command line application for testing network conditions are as expected. It can be used to validate DNS and HTTP connectivity and can be configured to assert that the results are as expected, for example:\n\n```shell\nnetcheck http --url=https://github.com/status --validation-rule \"data.body.contains('GitHub lives!') \u0026\u0026 data['status-code'] in [200, 201]\"\n```\n\n## Installation\n\nInstall the Python package from PyPi:\n\n```\npip install netcheck\n```\n\nThe cli can also be run via Docker:\n\n```shell\ndocker run -it ghcr.io/hardbyte/netchecks:main\n```\n\n### Individual Assertions\n\nBy default `netcheck` outputs a JSON result to stdout including response details: \n\n```shell\n$ netcheck dns\n```\n\n```json\n{\n  \"spec\": {\n    \"type\": \"dns\",\n    \"nameserver\": null,\n    \"host\": \"github.com\",\n    \"timeout\": 30.0\n  },\n  \"data\": {\n    \"canonical_name\": \"github.com.\",\n    \"expiration\": 1675825244.2986872,\n    \"response\": \"id 6176\\nopcode QUERY\\nrcode NOERROR\\nflags QR RD RA\\nedns 0\\npayload 65494\\n;QUESTION\\ngithub.com. IN A\\n;ANSWER\\ngithub.com. 60 IN A 20.248.137.48\\n;AUTHORITY\\n;ADDITIONAL\",\n    \"A\": [\n      \"20.248.137.48\"\n    ],\n    \"startTimestamp\": \"2023-02-08T02:59:44.248174\",\n    \"endTimestamp\": \"2023-02-08T02:59:44.298773\"\n  },\n  \"status\": \"pass\"\n}\n\n```\n\nPass the `-v` flag to see log messages.\n\nEach check can be configured, e.g. you can specify the `server` and `host` for a `dns` check, and\ntell `netcheck` whether a particular configuration is expected to pass or fail:\n\n\n```shell\nnetcheck dns --server 1.1.1.1 --host hardbyte.nz --should-pass\n```\n\n```json\n{\n  \"spec\": {\n    \"type\": \"dns\",\n    \"nameserver\": \"1.1.1.1\",\n    \"host\": \"hardbyte.nz\",\n    \"timeout\": 30.0,\n    \"pattern\": \"\\ndata['response-code'] == 'NOERROR' \u0026\u0026\\nsize(data['A']) \u003e= 1 \u0026\u0026 \\n(timestamp(data['endTimestamp']) - timestamp(data['startTimestamp']) \u003c duration('10s'))\\n\"\n  },\n  \"data\": {\n    \"canonical_name\": \"hardbyte.nz.\",\n    \"expiration\": 1683241225.5542665,\n    \"response\": \"id 53196\\nopcode QUERY\\nrcode NOERROR\\nflags QR RD RA\\n;QUESTION\\nhardbyte.nz. IN A\\n;ANSWER\\nhardbyte.nz. 3600 IN A 209.58.165.79\\n;AUTHORITY\\n;ADDITIONAL\",\n    \"A\": [\n      \"209.58.165.79\"\n    ],\n    \"response-code\": \"NOERROR\",\n    \"startTimestamp\": \"2023-05-04T22:00:24.491750\",\n    \"endTimestamp\": \"2023-05-04T22:00:25.554344\"\n  },\n  \"status\": \"pass\"\n}\n```\n\nNetcheck can handle checks that are expected to fail:\n```shell\n$ netcheck dns --server=1.1.1.1 --host=made.updomain --should-fail\n```\n\nNote the resulting status will show **pass** if the check fails as expected, and **fail** if the check passes unexpectedly!\n\nnetcheck has built in default validation for each check type. For example, the `dns` check will pass if the DNS response code is `NOERROR`, there is at least one `A` record, and resolver responds in under 10 seconds. Custom validation is also possible, see the [Custom Validation](#custom-validation) section below.\n\n\n## Custom Validation\n\nCustom validation can be added to checks by providing a `validation-rule` option on the command line, or a `validation` key in the rules of a test spec when configuring via json. \n\nFor example to override the default validation for the `dns` check to check that the A record resolves to a particular IP:\n\n```shell\nnetcheck dns --host github.com --validation-rule \"data['A'].contains('20.248.137.48')\"\n```\n\nThe validation rule is a CEL expression that is evaluated with the `data` returned by the check and `spec` objects in scope. For an introduction to CEL see https://github.com/google/cel-spec/blob/master/doc/intro.md\n\n\n\n## http checks\n\n`http` checks are also available:\n\nAssert that GitHub's status page includes the text \"GitHub lives!\" and that the response code is 200:\n\n```shell\nnetcheck http --url=https://github.com/status --validation-rule \"data.body.contains('GitHub lives!') \u0026\u0026 data['status-code'] in [200, 201]\"\n```\n\nProvide a header with a request:\n\n```shell\nnetcheck http --url https://pie.dev/headers --header \"X-Header:special\"\n```\n\nValidate that the response body is valid JSON and includes a `headers` object containing the `X-Header` key with the value `special`:\n\n```shell\nnetcheck http --url https://pie.dev/headers \\\n  --header \"X-Header:special\" \\\n  --validation-rule \"parse_json(data.body).headers['X-Header'] == 'special'\"\n```\n\n\nEnsure that a POST request fails:\n\n```shell\n$ netcheck http --method=post --url=https://s3.ap-southeast-2.amazonaws.com --should-fail\n```\n\n\n## Configuration via file\n\nThe main way to run `netcheck` is passing in a list of assertions. \nA json file can be provided with a list of assertions to be checked:\n\n```json\n{\n  \"assertions\": [\n    {\n      \"name\":  \"deny-cloudflare-dns\", \n      \"rules\": [\n        {\"type\": \"dns\", \"server\":  \"1.1.1.1\", \"host\": \"github.com\"}\n      ]\n    }\n  ]\n}\n```\n\nAnd the `run` command can be called:\n\n\n```shell\n$ netcheck run --config tests/testdata/dns-config.json\n```\n\nThe output should be valid JSON containing results for each assertion.\n\nMultiple assertions with multiple rules can be specified in the config file,\nconfiguration can be provided to each rule such as headers and custom validation:\n\n```json\n{\n  \"assertions\": [\n    {\"name\":  \"get-with-header\", \"rules\": [\n      {\"type\": \"http\", \"url\": \"https://pie.dev/headers\", \"headers\": {\"X-Test-Header\":  \"value\"}},\n      {\"type\": \"http\", \"url\": \"https://pie.dev/headers\", \"headers\": {\"X-Header\": \"secret\"}, \"validation\": \"parse_json(data.body).headers['X-Header'] == 'secret'\" }\n    ]}\n  ]\n}\n```\n\n## External Data\n\nFinally, external context can be referenced to inject data. The following example is a valid config file, if a bit contrived:\n\n```json\n{\n  \"assertions\": [\n    {\n      \"name\": \"example-assertion\",\n      \"rules\": [\n        {\n          \"type\": \"http\",\n          \"url\": \"{{customdata.url}}\",\n          \"headers\": {\"{{customdata.header}}\": \"{{ b64decode(token) }}\"},\n          \"validation\": \"parse_json(data.body).headers['X-Header'] == 'secret'\"\n        }\n      ]\n    }\n  ],\n  \"contexts\": [\n    {\"name\": \"customdata\", \"type\": \"inline\", \"data\": {\"url\": \"https://pie.dev/headers\", \"header\": \"X-Header\"}},\n    {\"name\": \"token\", \"type\": \"inline\", \"data\": \"c2VjcmV0==\"},\n    {\"name\": \"selfref\", \"type\": \"file\", \"path\": \"example-config.json\"}\n  ]\n}\n```\n\nIn the above example the `customdata` and `token` contexts are injected into the rule.\nThe `customdata.url` is used as the URL for the request, `customdata.header` is used as the name of the header.\nThe `token` is base64 decoded and used as the value of the header.\nThe `selfref` context is unused but shows how to load data an external JSON file which is used extensively by the\nKubernetes operator to inject data.\n\n## Development\n\nUpdate version in `pyproject.toml`, push to `main` and create a release on GitHub. Pypi release will be carried\nout by GitHub actions. \n\nInstall dev dependencies with Poetry:\n\n```shell\npoetry install --with dev\n```\n\n### Manual Release \nTo release manually, use Poetry:\n\n```shell\npoetry version patch\npoetry build\npoetry publish\n```\n\n### Testing\n\nPytest is used for testing. \n\n```shell\npoetry run pytest\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhardbyte%2Fnetchecks","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhardbyte%2Fnetchecks","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhardbyte%2Fnetchecks/lists"}