Package: netcheck
NetchecksNetchecksis a set of tools for testing network conditions and asserting that they are as expected.There are two main components:Netchecks Operator- Kubernetes Operator that runs network checks and reports results asPolicyReportresources. See theoperator READMEfor more details and the full documentation can be found athttps://docs.netchecks.ioNetcheck CLI and Python Library- Command line tool for running network checks and asserting that they are as expected. Keep reading for the quickstart guide.Netcheck Command Line Toolnetcheckis 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:netcheckhttp--url=https://github.com/status--validation-rule"data.body.contains('GitHub lives!') && data['status-code'] in [200, 201]"InstallationInstall the Python package from PyPi:pip install netcheckThe cli can also be run via Docker:dockerrun-itghcr.io/hardbyte/netchecks:mainIndividual AssertionsBy defaultnetcheckoutputs a JSON result to stdout including response details:$netcheckdns{"spec":{"type":"dns","nameserver":null,"host":"github.com","timeout":30.0},"data":{"canonical_name":"github.com.","expiration":1675825244.2986872,"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","A":["20.248.137.48"],"startTimestamp":"2023-02-08T02:59:44.248174","endTimestamp":"2023-02-08T02:59:44.298773"},"status":"pass"}Pass the-vflag to see log messages.Each check can be configured, e.g. you can specify theserverandhostfor adnscheck, and
tellnetcheckwhether a particular configuration is expected to pass or fail:netcheckdns--server1.1.1.1--hosthardbyte.nz--should-pass{"spec":{"type":"dns","nameserver":"1.1.1.1","host":"hardbyte.nz","timeout":30.0,"pattern":"\ndata['response-code'] == 'NOERROR' &&\nsize(data['A']) >= 1 && \n(timestamp(data['endTimestamp']) - timestamp(data['startTimestamp']) < duration('10s'))\n"},"data":{"canonical_name":"hardbyte.nz.","expiration":1683241225.5542665,"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","A":["209.58.165.79"],"response-code":"NOERROR","startTimestamp":"2023-05-04T22:00:24.491750","endTimestamp":"2023-05-04T22:00:25.554344"},"status":"pass"}Netcheck can handle checks that are expected to fail:$netcheckdns--server=1.1.1.1--host=made.updomain--should-failNote the resulting status will showpassif the check fails as expected, andfailif the check passes unexpectedly!netcheck has built in default validation for each check type. For example, thednscheck will pass if the DNS response code isNOERROR, there is at least oneArecord, and resolver responds in under 10 seconds. Custom validation is also possible, see theCustom Validationsection below.Custom ValidationCustom validation can be added to checks by providing avalidation-ruleoption on the command line, or avalidationkey in the rules of a test spec when configuring via json.For example to override the default validation for thednscheck to check that the A record resolves to a particular IP:netcheckdns--hostgithub.com--validation-rule"data['A'].contains('20.248.137.48')"The validation rule is a CEL expression that is evaluated with thedatareturned by the check andspecobjects in scope. For an introduction to CEL seehttps://github.com/google/cel-spec/blob/master/doc/intro.mdhttp checkshttpchecks are also available:Assert that GitHub's status page includes the text "GitHub lives!" and that the response code is 200:netcheckhttp--url=https://github.com/status--validation-rule"data.body.contains('GitHub lives!') && data['status-code'] in [200, 201]"Provide a header with a request:netcheckhttp--urlhttps://pie.dev/headers--header"X-Header:special"Validate that the response body is valid JSON and includes aheadersobject containing theX-Headerkey with the valuespecial:netcheckhttp--urlhttps://pie.dev/headers\--header"X-Header:special"\--validation-rule"parse_json(data.body).headers['X-Header'] == 'special'"Ensure that a POST request fails:$netcheckhttp--method=post--url=https://s3.ap-southeast-2.amazonaws.com--should-failConfiguration via fileThe main way to runnetcheckis passing in a list of assertions.
A json file can be provided with a list of assertions to be checked:{"assertions":[{"name":"deny-cloudflare-dns","rules":[{"type":"dns","server":"1.1.1.1","host":"github.com"}]}]}And theruncommand can be called:$netcheckrun--configtests/testdata/dns-config.jsonThe output should be valid JSON containing results for each assertion.Multiple assertions with multiple rules can be specified in the config file,
configuration can be provided to each rule such as headers and custom validation:{"assertions":[{"name":"get-with-header","rules":[{"type":"http","url":"https://pie.dev/headers","headers":{"X-Test-Header":"value"}},{"type":"http","url":"https://pie.dev/headers","headers":{"X-Header":"secret"},"validation":"parse_json(data.body).headers['X-Header'] == 'secret'"}]}]}External DataFinally, external context can be referenced to inject data. The following example is a valid config file, if a bit contrived:{"assertions":[{"name":"example-assertion","rules":[{"type":"http","url":"{{customdata.url}}","headers":{"{{customdata.header}}":"{{ b64decode(token) }}"},"validation":"parse_json(data.body).headers['X-Header'] == 'secret'"}]}],"contexts":[{"name":"customdata","type":"inline","data":{"url":"https://pie.dev/headers","header":"X-Header"}},{"name":"token","type":"inline","data":"c2VjcmV0=="},{"name":"selfref","type":"file","path":"example-config.json"}]}In the above example thecustomdataandtokencontexts are injected into the rule.
Thecustomdata.urlis used as the URL for the request,customdata.headeris used as the name of the header.
Thetokenis base64 decoded and used as the value of the header.
Theselfrefcontext is unused but shows how to load data an external JSON file which is used extensively by the
Kubernetes operator to inject data.DevelopmentUpdate version inpyproject.toml, push tomainand create a release on GitHub. Pypi release will be carried
out by GitHub actions.Install dev dependencies with Poetry:poetryinstall--withdevManual ReleaseTo release manually, use Poetry:poetryversionpatch
poetrybuild
poetrypublishTestingPytest is used for testing.poetryrunpytest