Pod API modify body
Pod API modify body is a Kubernetes pod-level chaos fault that modifies the api request and response body by replacing any portions that match a specified regular expression with a provided value. This is achieved by starting the proxy server and redirecting the traffic through the proxy server.
A transient proxy (also known as helper pod) is brought up for a chaos duration to intercept the requests made from the target application to another service and elsewhere, and inject chaos accordingly. Target application refers to the application pods calling/sending egress traffic to an endpoint.
Use cases
Pod API modify body:
- It can be used for API testing, by replacing specific portions of the request or response body to simulate different scenarios and validate how your application handles different data variations.
- Simulate error conditions and test the error handling capabilities of API by replacing specific patterns in the response body with error messages or custom error codes to test error handling and reporting mechanisms are in place.
- It can be useful for obscuring or redacting personally identifiable information (PII), such as email addresses or phone numbers, before logging or transmitting the data for security and privacy compliance.
Permissions required
Below is a sample Kubernetes role that defines the permissions required to execute the fault.
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: hce
name: pod-api-modify-body
spec:
definition:
scope: Cluster # Supports "Namespaced" mode too
permissions:
- apiGroups: [""]
resources: ["pods"]
verbs: ["create", "delete", "get", "list", "patch", "deletecollection", "update"]
- apiGroups: [""]
resources: ["events"]
verbs: ["create", "get", "list", "patch", "update"]
- apiGroups: [""]
resources: ["pods/log"]
verbs: ["get", "list", "watch"]
- apiGroups: [""]
resources: ["deployments, statefulsets"]
verbs: ["get", "list"]
- apiGroups: [""]
resources: ["replicasets, daemonsets"]
verbs: ["get", "list"]
- apiGroups: [""]
resources: ["chaosEngines", "chaosExperiments", "chaosResults"]
verbs: ["create", "delete", "get", "list", "patch", "update"]
- apiGroups: ["batch"]
resources: ["jobs"]
verbs: ["create", "delete", "get", "list", "deletecollection"]
Prerequisites
- Kubernetes> 1.17
- The application pods should be in the running state before and after injecting chaos.
Mandatory tunables
Tunable | Description | Notes |
---|---|---|
TARGET_CONTAINER | Name of the container subject to API body modification. | None. For more information, go to target specific container |
TARGET_SERVICE_PORT | Port of the target service. | Defaults to port 80. For more information, go to target service port |
NODE_LABEL | Node label used to filter the target node if TARGET_NODE environment variable is not set. | It is mutually exclusive with the TARGET_NODE environment variable. If both are provided, the fault uses TARGET_NODE . For more information, go to node label. |
RESPONSE_BODY | String body to overwrite the HTTP response body. | If no value is provided, response will be an empty body. Defaults to empty body. For more information, go to response body |
Optional tunables
Tunable | Description | Notes |
---|---|---|
PATH_FILTER | API path or route used for the filtering. | Targets all paths if not provided. For more information, go to path filter . |
TRANSACTION_PERCENTAGE | Percentage of the API requests to be affected. | It supports values in range (0,100]. It targets all requests if not provided. For more information, go to transaction percentage . |
HEADERS_FILTERS | Filters for HTTP request headers accept multiple comma-separated headers in the format key1:value1,key2:value2 . | For more information, go to header filters. |
METHODS | The HTTP request method type accepts comma-separated HTTP methods in upper cases, such as "GET,POST". | For more information, go to methods. |
QUERY_PARAMS | HTTP request query parameter filters accept multiple comma-separated query parameters in the format of param1:value1,param2:value2 . | For more information, go to query params. |
SOURCE_HOSTS | Includes comma-separated source host names as filters, indicating the origin of the HTTP request. This is specifically relevant to the "ingress" type. | For more information, go to source hosts. |
SOURCE_IPS | This includes comma-separated source IPs as filters, indicating the origin of the HTTP request. This is specifically relevant to the "ingress" type. | For more information, go to source ips. |
DESTINATION_HOSTS | Comma-separated destination host names are used as filters, indicating the hosts on which you call the API. This specification applies exclusively to the "egress" type. | For more information, go to destination hosts. |
DESTINATION_IPS | Comma-separated destination IPs are used as filters, indicating the hosts on which you call the API. This specification applies exclusively to the "egress" type. | For more information, go to destination hosts. |
PROXY_PORT | Port where the proxy listens for requests. | Default: 20000. For more information, go to proxy port |
LIB_IMAGE | Image used to inject chaos. | Default: harness/chaos-go-runner:main-latest . For more information, go to image used by the helper pod. |
SERVICE_DIRECTION | Direction of the flow of control, ingress or egress | Default: ingress . For more information, go to service direction |
DATA_DIRECTION | API payload type, request or response | Default: both . For more information, go to data direction |
DESTINATION_PORTS | comma-separated list of the destination service or host ports for which egress traffic should be affected | Default: 80,443. For more information, go to destination ports |
HTTPS_ENABLED | facilitate HTTPS support for both incoming and outgoing traffic | Default: false. For more information, go to https |
CA_CERTIFICATES | These CA certificates are used by the proxy server to generate the server certificates for the TLS handshake between the target application and the proxy server. | These CA certificates must also be added to the target application's root certificate. For more information, go to CA certificates. |
SERVER_CERTIFICATES | These server certificates are used by the proxy server for the TLS handshake between the target application and the proxy server. | The corresponding CA certificates should be loaded as root certificates inside the target application. For more information, go to server certificates. |
HTTPS_ROOT_CERT_PATH | Provide the root CA certificate directory path | This setting must be configured if the root CA certificate directory differs from /etc/ssl/certs. Please refer to https://go.dev/src/crypto/x509/root_linux.go to understand the default certificate directory based on various Linux distributions. For more information, go to HTTPS |
HTTPS_ROOT_CERT_FILE_NAME | Provide the root CA certificate file name | This setting must be configured if the root CA certificate file name differs from ca-certificates.crt. Please refer to https://go.dev/src/crypto/x509/root_linux.go to understand the default certificate file names based on various Linux distributions. For more information, go to HTTPS |
NETWORK_INTERFACE | Network interface used for the proxy. | Default: eth0 . For more information, go to network interface |
CONTAINER_RUNTIME | Container runtime interface for the cluster | Default: containerd. Support values: docker, containerd and crio. For more information, go to container runtime |
SOCKET_PATH | Path of the containerd or crio or docker socket file. | Default: /run/containerd/containerd.sock . For more information, go to socket path |
TOTAL_CHAOS_DURATION | Duration of chaos injection (in seconds). | Default: 60 s. For more information, go to duration of the chaos |
TARGET_PODS | Comma-separated list of application pod names subject to pod HTTP modify body. | If not provided, the fault selects target pods randomly based on provided appLabels. For more information, go to target specific pods |
PODS_AFFECTED_PERC | Percentage of total pods to target. Provide numeric values. | Default: 0 (corresponds to 1 replica). For more information, go to pod affected percentage |
RAMP_TIME | Period to wait before and after injecting chaos (in seconds). | For example, 30 s. For more information, go to ramp time |
SEQUENCE | Sequence of chaos execution for multiple target pods. | Default: parallel. Supports serial and parallel. For more information, go to sequence of chaos execution |
Target service port
Port of the target service. Tune it by using the TARGET_SERVICE_PORT
environment variable.
The following YAML snippet illustrates the use of this environment variable:
## provide the port of the targeted service
apiVersion: litmuschaos.io/v1alpha1
kind: ChaosEngine
metadata:
name: engine-nginx
spec:
engineState: "active"
annotationCheck: "false"
appinfo:
appns: "default"
applabel: "app=nginx"
appkind: "deployment"
chaosServiceAccount: litmus-admin
experiments:
- name: pod-api-modify-body
spec:
components:
env:
# provide the port of the targeted service
- name: TARGET_SERVICE_PORT
value: "80"
# provide the body string to overwrite the response body
- name: RESPONSE_BODY
value: "/.+/test"
- name: PATH_FILTER
value: '/status'
Response body
String body that overwrites the API request and response body. Tune it by using the RESPONSE_BODY
environment variable.
The following YAML snippet illustrates the use of this environment variable:
## provide the response body value
apiVersion: litmuschaos.io/v1alpha1
kind: ChaosEngine
metadata:
name: engine-nginx
spec:
engineState: "active"
annotationCheck: "false"
appinfo:
appns: "default"
applabel: "app=nginx"
appkind: "deployment"
chaosServiceAccount: litmus-admin
experiments:
- name: pod-api-modify-body
spec:
components:
env:
# provide the body string to overwrite the response body
- name: RESPONSE_BODY
value: "/.+/test"
- name: PATH_FILTER
value: '/status'
# provide the port of the targeted service
- name: TARGET_SERVICE_PORT
value: "80"
Path Filter
API sub path (or route) to filter the API calls. Tune it by using the PATH_FILTER
environment variable.
The following YAML snippet illustrates the use of this environment variable:
## provide api path filter
apiVersion: litmuschaos.io/v1alpha1
kind: ChaosEngine
metadata:
name: engine-nginx
spec:
engineState: "active"
annotationCheck: "false"
appinfo:
appns: "default"
applabel: "app=nginx"
appkind: "deployment"
chaosServiceAccount: litmus-admin
experiments:
- name: pod-api-modify-body
spec:
components:
env:
# provide the api path filter
- name: PATH_FILTER
value: '/status'
- name: RESPONSE_BODY
value: "/.+/test"
# provide the port of the targeted service
- name: TARGET_SERVICE_PORT
value: "80"
Destination ports
A comma-separated list of the destination service or host ports for which egress
traffic should be affected as a result of chaos testing on the target application. Tune it by using the DESTINATION_PORTS
environment variable.
It is applicable only for the egress SERVICE_DIRECTION
.
The following YAML snippet illustrates the use of this environment variable:
## provide destination ports
apiVersion: litmuschaos.io/v1alpha1
kind: ChaosEngine
metadata:
name: engine-nginx
spec:
engineState: "active"
annotationCheck: "false"
appinfo:
appns: "default"
applabel: "app=nginx"
appkind: "deployment"
chaosServiceAccount: litmus-admin
experiments:
- name: pod-api-modify-body
spec:
components:
env:
# provide destination ports
- name: DESTINATION_PORTS
value: '80,443'
# provide the api path filter
- name: PATH_FILTER
value: '/status'
- name: RESPONSE_BODY
value: "/.+/test"
# provide the port of the targeted service
- name: TARGET_SERVICE_PORT
value: "80"
HTTPS
To enable HTTPS support for both incoming and outgoing traffic between the target and the proxy, set the HTTPS_ENABLED
field to true
. The next step is to configure TLS, for which you can follow one of the ways: Using self-signed certificate or using trusted certificate.
Using Self-Signed Certificates
To establish TLS communication between the target application and the proxy server, you can use one of the following.
-
CA certificates
The certificates provided by CA (or self-signed) to sign or validate the server certificates.
-
ca.key: The private key used to generate CA certificates.
-
ca.crt: The actual CA certificate.
-
Prerequisite: Load the
ca.crt
as the root CA certificate in the target application before experiment creation or execution. -
Fault Configuration: Provide base64-encoded
ca.key
andca.crt
in theCA_CERTIFICATES
environment variable.cat ca.key ca.crt > ca.pem
cat ca.pem | base64 # Add this to the CA_CERTIFICATES environment variable
In this setup, the proxy dynamically generates the server certificates with appropriate domain names during TLS handshake and sign them by the self-signed CA (provided in
CA_CERTIFICATES
environemtn variable) before sending them to the target application server. -
-
Server certificates
The certificates used by the transient proxy server for TLS handshake with the target application.
-
server.key: The private key used to generate the server certificates.
-
server.crt: The actual Server certificate (signed by the CA).
-
Internal Domain: Domain in which the local (organization-managed) services are deployed. Typically, it contains the local upstream or soft microservice dependencies.
-
External Domain: Domain in which the third-party services are deployed (for example, AWS services like DynamoDB or S3). Typically, it comprises the hard dependencies.
-
SAN (Subject Alternative Names): List of domain names provided to the cert-generation command or within the config file (*.cnf) passed as args to the cert-generators while creating the CSR (Certificate Signing Request).
-
Prerequisites: Load the
ca.crt
as the root CA certificate in the target application before experiment creation or execution. Create aserver.crt
with the necessary domain names and sign it using CA certificates. -
Fault Configuration: Provide base64-encoded
server.key
andserver.crt
in theSERVER_CERTIFICATES
environment variable.cat server.key server.crt > server.pem
cat server.pem | base64 # Add this to the SERVER_CERTIFICATES environment variable
In this setup, the proxy sends the server certificates (provided in
SERVER_CERTIFICATES
environment variable) to the target application server as part of the TLS handshake. -
Intermediate Certificates are the chain of certificates that are used to generate the eventual server certificate for security purposes.
Using Trusted Certificates
You can use trusted server certificates for internal or external domains, both of which are described below.
-
For Internal Domains
-
Prerequisites: Generate the server certificates with the internal domain names and sign them using a trusted CA. Since the CA is trusted, there is no need to load the CA certificate in the target application.
-
Fault Configuration: Provide the base64-encoded
server.key
,server.crt
, and any intermediate certificates in theSERVER_CERTIFICATES
environment variable.cat server.key server.crt <intermediate-certificates> > server.pem
cat server.pem | base64 # Add this to the SERVER_CERTIFICATES env
-
-
For External Domains
-
Prerequisites: Generate the server certificates that include both internal and external domain names, and sign them with the trusted CA. Since the CA is trusted, there is no need to load the CA certificates in the target application.
-
Fault Configuration: Provide the base64-encoded
server.key
,server.crt
, and any intermediate certificates in theSERVER_CERTIFICATES
environment variable.cat server.key server.crt <intermediate-certificates> > server.pem
cat server.pem | base64 # Add this to the SERVER_CERTIFICATES env
-
Advanced fault tunables
PROXY_PORT
: Port where the proxy listens for requests and responses.SERVICE_DIRECTION
: Direction of the flow of control, eitheringress
oregress
.DATA_DIRECTION
: API payload type, request, or response. It supportsrequest
,response
, andboth
values.NETWORK_INTERFACE
: Network interface used for the proxy.
The following YAML snippet illustrates the use of this environment variable:
# it injects the api modify body fault
apiVersion: litmuschaos.io/v1alpha1
kind: ChaosEngine
metadata:
name: engine-nginx
spec:
engineState: "active"
annotationCheck: "false"
appinfo:
appns: "default"
applabel: "app=nginx"
appkind: "deployment"
chaosServiceAccount: litmus-admin
experiments:
- name: pod-api-modify-body
spec:
components:
env:
# provide the proxy port
- name: PROXY_PORT
value: '20000'
# provide the connection type
- name: SERVICE_DIRECTION
value: 'ingress'
# provide the payload type
- name: DATA_DIRECTION
value: 'both'
# provide the network interface
- name: NETWORK_INTERFACE
value: 'eth0'
# provide the api path filter
- name: PATH_FILTER
value: '/status'
# provide the port of the targeted service
- name: TARGET_SERVICE_PORT
value: "80"
- name: RESPONSE_BODY
value: "/.+/test"
Advanced filters
HEADERS_FILTERS
: The HTTP request headers filters, that accept multiple comma-separated headers in the format ofkey1:value1,key2:value2
.METHODS
: The HTTP request method type filters, that accept comma-separated HTTP methods in upper case, that is,GET,POST
.QUERY_PARAMS
: The HTTP request query parameters filter, accepts multiple comma-separated query parameters in the format ofparam1:value1,param2:value2
.SOURCE_HOSTS
: Comma-separated source host names filters, indicating the origin of the HTTP request. This is relevant to theingress
type, specified bySERVICE_DIRECTION
environment variable.SOURCE_IPS
: Comma-separated source IPs filters, indicating the origin of the HTTP request. This is specifically relevant to theingress
type, specified bySERVICE_DIRECTION
environment variable.DESTINATION_HOSTS
: Comma-separated destination host names filters, indicating the hosts on which you call the API. This specification applies exclusively to theegress
type, specified bySERVICE_DIRECTION
environment variable.DESTINATION_IPS
: Comma-separated destination IPs filters, indicating the hosts on which you call the API. This specification applies exclusively to theegress
type, specified bySERVICE_DIRECTION
environment variable.TRANSACTION_PERCENTAGE
: The percentage of API requests to be affected, with supported values in the range (0, 100]. If not specified, it targets all requests.
The following YAML snippet illustrates the use of this environment variable:
# it injects the api modify body fault
apiVersion: litmuschaos.io/v1alpha1
kind: ChaosEngine
metadata:
name: engine-nginx
spec:
engineState: "active"
annotationCheck: "false"
appinfo:
appns: "default"
applabel: "app=nginx"
appkind: "deployment"
chaosServiceAccount: litmus-admin
experiments:
- name: pod-api-modify-body
spec:
components:
env:
# provide the headers filters
- name: HEADERS_FILTERS
value: 'key1:value1,key2:value2'
# provide the methods filters
- name: METHODS
value: 'GET,POST'
# provide the query params filters
- name: QUERY_PARAMS
value: 'param1:value1,param2:value2'
# provide the source hosts filters
- name: SOURCE_HOSTS
value: 'host1,host2'
# provide the source ips filters
- name: SOURCE_IPS
value: 'ip1,ip2'
# provide the transaction percentage within (0,100] range
# for example, it will affect 50% of the total requests
- name: TRANSACTION_PERCENTAGE
value: '50'
# provide the connection type
- name: SERVICE_DIRECTION
value: 'ingress'
# provide the port of the targeted service
- name: TARGET_SERVICE_PORT
value: "80"
- name: RESPONSE_BODY
value: "/.+/test"
Container runtime and socket path
The CONTAINER_RUNTIME
and SOCKET_PATH
environment variable to set the container runtime and socket file path, respectively.
CONTAINER_RUNTIME
: It supportsdocker
,containerd
, andcrio
runtimes. The default value iscontainerd
.SOCKET_PATH
: It contains path of containerd socket file by default(/run/containerd/containerd.sock
). Fordocker
, specify path as/var/run/docker.sock
. Forcrio
, specify path as/var/run/crio/crio.sock
.
The following YAML snippet illustrates the use of these environment variables:
## provide the container runtime and socket file path
apiVersion: litmuschaos.io/v1alpha1
kind: ChaosEngine
metadata:
name: engine-nginx
spec:
engineState: "active"
annotationCheck: "false"
appinfo:
appns: "default"
applabel: "app=nginx"
appkind: "deployment"
chaosServiceAccount: litmus-admin
experiments:
- name: pod-api-modify-body
spec:
components:
env:
# runtime for the container
# supports docker, containerd, crio
- name: CONTAINER_RUNTIME
value: "containerd"
# path of the socket file
- name: SOCKET_PATH
value: "/run/containerd/containerd.sock"
# provide the port of the targeted service
- name: TARGET_SERVICE_PORT
value: "80"
# provide the api path filter
- name: PATH_FILTER
value: '/status'
- name: RESPONSE_BODY
value: "/.+/test"