User Guide
Injecting External Data
Use data from ConfigMaps and Secrets in your Network Assertions.
When an assertion referencing a ConfigMap or Secret is evaluated, the data is mounted into the Pod carrying out the assertion at the time the test runs. Should the Secret or ConfigMap be updated, subsequent probes will pick up the latest data at that point.
This data is made available to the probe in the form of a context. The context data can then be referenced within a CEL template.
{{ <context-name>.<key-name> }}
Contexts from ConfigMaps
A ConfigMap in Kubernetes is commonly used to store configuration data for applications. Each ConfigMap is namespaced and stores key-value pairs.
Say you have a ConfigMap
in the target namespace which contains an API_TOKEN
that you want to use in your assertions.
apiVersion: v1
kind: ConfigMap
metadata:
name: some-config-map
data:
API_TOKEN: "some-data-from-a-configmap"
Create one or more named contexts in your assertion to load the data from the ConfigMap. The name of the context can be anything you like except for data
and spec
which are already used by Netchecks.
Then reference the data in your custom validation patterns, or anywhere in your assertion rules using the {{ }}
template syntax.
In this example somecontext will load the data from the some-config-map ConfigMap and inject it into a header in the HTTP request:
apiVersion: netchecks.io/v1
kind: NetworkAssertion
metadata:
name: http-with-external-data
annotations:
description: Assert probe can access configmap data
spec:
# Include the full context and headers in the PolicyReport for easier debugging
disableRedaction: true
# All rules in the NetworkAssertion share the same context
context:
# A unique name for each context object
- name: somecontext
configMap:
name: some-config-map
rules:
- name: pie-dev-headers-and-validation
type: http
url: https://pie.dev/headers
headers:
"X-Netcheck-Header": "{{ somecontext.API_TOKEN }}"
expected: pass
validate:
message: Http request with header to pie.dev service should reply with header value
pattern: "parse_json(data.body).headers['X-Netcheck-Header'] == somecontext.API_TOKEN"
The templated variable {{ somecontext.API_TOKEN }}
will be substituted with the value some-data-from-a-configmap
before the test is executed.
Contexts from Secrets
A Secret in Kubernetes is an object that contains sensitive data such as passwords, tokens, or other potentially sensitive configuration data.
Let's repeat the same example with an API_TOKEN
this time stored - more appropriately - as a secret:
apiVersion: v1
kind: Secret
metadata:
name: some-secret
data:
API_TOKEN: a3E0Z2lodnN6emduMXAwcg==
The NetworkAssertion doesn't change much, note the context now refers to a secret
:
apiVersion: netchecks.io/v1
kind: NetworkAssertion
metadata:
name: http-with-external-secret-data
annotations:
description: Assert probe can access secret data
spec:
context:
- name: somecontext
secret:
name: some-secret
# [Optionally] Limit which keys from the Secret (or ConfigMap)
# get created as files.
# items:
# - key: API_TOKEN
# path: API_TOKEN
rules:
- name: pie-dev-headers-and-validation
type: http
url: https://pie.dev/headers
headers:
"X-Netcheck-Header": "{{ somecontext.API_TOKEN }}"
expected: pass
validate:
message: Http request with header to pie.dev service should reply with header value
pattern: "parse_json(data.body).headers['X-Netcheck-Header'] == somecontext.API_TOKEN"
Template Evaluation
The {{ }}
syntax is used to evaluate CEL templates before the assertion is carried out.
The validate.pattern
is the exception, always evaluated as a CEL expression after the assertion has run.
Handling JSON and YAML data
Often a config map contains JSON or YAML data. The parse_json
and parse_yaml
functions can be used to extract data from these formats.
apiVersion: v1
kind: ConfigMap
metadata:
name: a-config-map
data:
yaml_data: |
toplevel:
nestedkey: "yaml-data"
array:
- "value"
- "value2"
apiVersion: netchecks.io/v1
kind: NetworkAssertion
metadata:
name: example-with-yaml-format
spec:
context:
- name: somecontext
configMap:
name: a-config-map
rules:
- name: yaml-parsing-test
type: http
url: https://pie.dev/headers
headers:
"X-Netcheck-Header": "{{ parse_yaml(somecontext.yaml_data).toplevel.nestedkey }}"
expected: pass
validate:
message: Http request with header to pie.dev service should reply with header value
pattern: parse_json(data.body).headers['X-Netcheck-Header'] == "yaml-data"
- name: yaml-array-parsing-test
type: http
url: https://pie.dev/headers
headers:
"X-Netcheck-Header": "{{ parse_yaml(somecontext.yaml_data).array[0] }}"
expected: pass
validate:
message: Http request with header to pie.dev service should reply with header value
pattern: parse_json(data.body).headers['X-Netcheck-Header'] == "value"
Reusable Variables
Data to be used in multiple rules can be declared as an inline context, and can reference already defined contexts using the {{ }}
template syntax.
This can be useful to pre-process external data in one place that might be reused in multiple NetworkAssertion rules.
For example:
apiVersion: netchecks.io/v1
kind: NetworkAssertion
metadata:
name: http-with-inline-data
annotations:
description: Assert probe can access configmap data
spec:
context:
- name: originalcontext
inline:
key: "inline-value"
- name: derivedcontext
inline:
key: "{{ originalcontext.key }}"
rules:
- name: pie-dev-headers-and-validation
type: http
url: https://pie.dev/headers
headers:
"X-Netcheck-Header": "{{ derivedcontext.key }}"
expected: pass
validate:
message: Http request with header to pie.dev service should reply with header value
pattern: "parse_json(data.body).headers['X-Netcheck-Header'] == derivedcontext.key"
Redaction
By default, contexts are not included in the PolicyReport. This is to because they often include sensitive information such as passwords or tokens. You can disable this redaction for debugging purposes by setting disableRedaction: true
in the spec
section of the NetworkAssertion.
Note that limiting which keys are projected from the Secret or ConfigMap is also a good way to limit the amount of sensitive data that is exposed to the Pod carrying out the test.
apiVersion: netchecks.io/v1
kind: NetworkAssertion
metadata:
name: redaction-disabled
spec:
disableRedaction: true
context:
- name: somecontext
secret:
name: some-secret
# [Optionally] Limit which keys from the Secret or ConfigMap
# get created as files
items:
- key: API_TOKEN
path: API_TOKEN
rules:
- name: pie-dev-headers-and-validation
type: http
url: https://pie.dev/headers
headers:
"X-Netcheck-Header": "{{ somecontext.API_TOKEN }}"
expected: pass
validate:
message: Http request with header to pie.dev service should reply with header value
pattern: "parse_json(data.body).headers['X-Netcheck-Header'] == somecontext.API_TOKEN"
Override Service Account for a
Netchecks probes run using the default
service account in the target namespace. In some environments you will need to create ServiceAccounts for your probes and grant permissions to the service account using RBAC. Many custom overrides for the generated Job/CronJob can be achieved using the Network Assertion template
:
apiVersion: v1
kind: ServiceAccount
metadata:
name: netcheck-test-probe-account
labels:
app.kubernetes.io/instance: netchecks
---
apiVersion: netchecks.io/v1
kind: NetworkAssertion
metadata:
name: custom-service-account
annotations:
description: Probe with custom service account
spec:
template:
spec:
serviceAccountName: netcheck-test-probe-account
rules: []