Test before release — Utilizing MicroK8s for testing production workloads

Imran Roshan
Google Cloud - Community
7 min readApr 13, 2024

Making use of Microk8s to enhance security testing on production workloads.

The lightweight Kubernetes implementation, Microk8s, which is intended for quick deployment, presents a strong option for security experts who are in charge of testing production workloads. It’s perfect for setting up isolated testing environments that closely resemble production configurations because of its simplicity of use, small resource footprint, and integrated security features. This article examines the advantages of utilizing Microk8s for security testing, as well as useful use cases and integrated tools for an all-encompassing testing approach.

Why Microk8s?

  • Quick Deployment and Teardown: Microk8s can be quickly deployed on a single machine with little configuration needed. This saves significant time and resources by enabling security teams to quickly spin up test clusters for particular scenarios and tear them down when done.
  • Resource Efficiency: Microk8s’ small footprint allows them to operate on cloud instances or laptops with less power, which lowers the infrastructure cost of security testing. This is especially advantageous for resource-constrained organizations.
  • Isolation: By establishing isolated testing environments, Microk8s prevents any security flaw in the test cluster from affecting systems that are in use. This permits comprehensive testing while guaranteeing the integrity of production environments.
  • Security Features: Role-based access control (RBAC) and network policies are two of the built-in security features of Microk8s. By utilizing these features, secure test clusters that emulate best practices for production security can be set up.
  • Flexibility: Microk8s allows workloads to be deployed using a variety of techniques, such as Helm charts, YAML manifests, and container images. Security teams can test various deployment scenarios and determine potential security risks associated with each method thanks to this flexibility.

Now I usually take my application tests in 3 major functions of SAST, DAST and IAST. Further, let’s dive deep into some tools I personally use for testing applications on Microk8s environments.

Note: These are tools of personal preference mainly chosen by understanding, ease and integration capabilities. Feel free to pick your poison.

Static Application Security Testing

For SAST let’s use Code Climate to check for any coding flaws or oopsies we might have missed out on.

Code Climate is an appealing option for SAST on Microk8s applications because it provides an easy-to-use platform with a number of features.

  • Programming Language Support: Code Climate offers support for a large number of languages, such as Java, Python, JavaScript, Ruby, and Go, which are frequently used in microservices development.
  • Detailed Reporting: It offers thorough reports that highlight vulnerabilities, indicate the degree of their severity, and include code snippets that make remediation simple.
  • Integrations: Code Climate allows for automated SAST scans following code commits by integrating easily with well-known CI/CD pipelines like Jenkins and GitLab.
  • I got no money: Code Climate provides both free and paid plans for Open Source Tools. Despite its limitations, the free plan lets you use Microk8s to get started with SAST using open-source tools.

Using a deliberately vulnerable code I’ve not written myself (Why would I? I have an image to maintain)

from flask import Flask, request

app = Flask(__name__)

@app.route("/")
def index():
# Vulnerable code: Storing user input directly in a cookie
user_input = request.args.get("name")
response = f"Hello, {user_input}!"
response.set_cookie("user", user_input)
return response

if __name__ == "__main__":
app.run(host="0.0.0.0", port=8080)

Using a GET request, this application gets the user’s name and stores it straight in a cookie. A classic example of a Cross-Site Scripting (XSS) vulnerability is this one, where malicious users could compromise other users’ sessions by injecting scripts into the name field.

Deploying the application on Microk8s the traditional way

FROM python:3.8

WORKDIR /app

COPY requirements.txt .
RUN pip install -r requirements.txt

COPY . .

CMD ["python", "vulnerable_app.py"]

Followed by running

docker build -t vulnerable-app .

Now applying a Deployment YAML to deploy our vulnerable app on Microk8s

apiVersion: apps/v1
kind: Deployment
metadata:
name: vulnerable-app
spec:
replicas: 1
selector:
matchLabels:
app: vulnerable-app
template:
metadata:
labels:
app: vulnerable-app
spec:
containers:
- name: vulnerable-app
image: <image_name>:latest
port:
- containerPort: 8080

Let’s run Bandit locally to gain a basic understanding of vulnerabilities before integrating with Code Climate. Go to your application directory by opening a terminal. Execute the subsequent command:

bandit -r vulnerable_app.py

This will analyze your Python script and identify any possible security flaws. In this instance, the insecure cookie storage should cause Bandit to detect the XSS vulnerability.

To integrate Code Climate to this we have two steps to take:

  • Connect Repository: Open your public Git repository on Code Climate and connect it to the application that is vulnerable.
  • Activate Detectors: Go to “Detectors” in the Code Climate project settings, and make sure “Bandit” is activated. For basic SAST functionality, you might need to activate your free plan.

Code Climate will automatically analyze your codebase once it has connected to your repository. The initial scan could take a while to finish. When you’re done, go to your project’s “Security” section on Code Climate.

Here, the Code Climate report ought to display the XSS vulnerability that Bandit discovered. Details regarding the vulnerability, its degree of severity, and possible corrective actions will be included in the report.

Now get up you security engineer and blame it on the developer and raise a JIRA ticket for them to fix it!!

Dynamic Application Security Testing

DAST on microk8s environments might be one of the more straightforward approaches which in some parts might be self explanatory enough. I prefer integrating DAST solutions to the CICD of your choice if you’re lazy like me but feel free to go with a more manual approach if that suits your fancy.

In this case, we shall be using ZAP on MicroK8s.

Install ZAP in your MicroK8s cluster as a container. You can use simple deployment manifests or tools like Helm. This is a simple deployment manifest example:

apiVersion: apps/v1
kind: Deployment
metadata:
name: zap
spec:
replicas: 1
selector:
matchLabels:
app: zap
template:
metadata:
labels:
app: zap
spec:
containers:
- name: zap
image: owasp/zap2docker-stable
ports:
- containerPort: 8080

ZAP provides a feature-rich API for programmatic tool interaction. Here is an example Python script that runs an automated scan using the zapv2 library:

from zapv2 import ZAPClient

# Replace with your ZAP API key and target URL
zap = ZAPClient(apikey="<your_api_key>", url="http://localhost:8080")

# Context creation (optional, can be used for grouping scans)
context_id = zap.context.new_context(name="My MicroK8s App")

# Set target URL
zap.scanner.add_target_url(context_id, "http://<your_app_url>")

# Choose scanner configs (default policy is a good starting point)
zap.scanner.scan(context_id, policy_name="Default Policy")

# Wait for scan to complete (replace with a loop and progress check)
print("Scan Running...")
time.sleep(10) # Replace with proper progress monitoring

# Retrieve scan results
scan_results = zap.core.alerts(context_id)

# Process and report results
for alert in scan_results:
print(f"Alert: {alert['pluginId']} - {alert['alert']}")

zap.core.shutdown()

Using the API key, this script connects to ZAP, sets the target application URL, defines an optional scan context, starts a scan using the default policy, and retrieves the results of the scan when it’s finished.

Feel free to customize your scans for your requirements and security gates and let it flow!

Interactive Application Security Testing

Conventional security testing techniques frequently fail in dynamic settings such as containerized applications. IAST provides a remedy by looking for vulnerabilities in applications that are currently running. A few benefits come from incorporating IAST into your MicroK8s workflow:

  • Continuous Security: By automating IAST, regular scans can be conducted to identify vulnerabilities as soon as code is deployed, thereby reducing the window of opportunity for exploitation.
  • Shift Left Security: By incorporating IAST into the development process, vulnerabilities can be found and fixed early on, sparing time and money that would otherwise be spent on post-deployment fixes.
  • Decreased False Positives: Compared to static analysis tools, IAST produces fewer false positives because it concentrates on runtime behavior.
  • Enhanced Code Coverage: IAST has the ability to examine applications in real-world settings, which may reveal vulnerabilities that static testing was unable to find.

I shall be using Aquasecurity in this case which after registration offers you with an API key to be used right away. For cloud-native environments, Aqua Security offers a full range of security solutions, including IAST capabilities. Through platform and tool integration, Aqua makes vulnerability management more efficient.

Here’s a comprehensive python script to implement Aqua to perform IAST on your MicroK8s environment.

import requests
from aqua.iaas import API

# Aqua Server details (replace with your values)
AQUA_URL = "https://your-aqua-server.io"
AQUA_API_KEY = "your_aqua_api_key"
AQUA_API_SECRET = "your_aqua_api_secret"

# MicroK8s deployment details (replace with your values)
MICROK8S_NAMESPACE = "default"
MICROK8S_DEPLOYMENT_NAME = "my-app"

def main():
# Aqua API connection
api = API(api_url=AQUA_URL, api_key=AQUA_API_KEY, api_secret=AQUA_API_SECRET)

# Get deployments within the namespace
deployments_url = f"{AQUA_URL}/api/v1/namespaces/{MICROK8S_NAMESPACE}/deployments"
response = requests.get(deployments_url, headers=api.get_headers())
deployments = response.json()

# Find the target deployment by name
target_deployment = None
for deployment in deployments:
if deployment["name"] == MICROK8S_DEPLOYMENT_NAME:
target_deployment = deployment
break

if not target_deployment:
print(f"Deployment '{MICROK8S_DEPLOYMENT_NAME}' not found in namespace '{MICROK8S_NAMESPACE}'")
return

# Initiate IAST scan
scan_url = f"{AQUA_URL}/api/v1/scans"
scan_data = {
"target": f"deployment/{MICROK8S_NAMESPACE}/{MICROK8S_DEPLOYMENT_NAME}",
"scan_type": "IAST"
}
response = requests.post(scan_url, headers=api.get_headers(), json=scan_data)

if response.status_code == 201:
scan_id = response.json()["id"]
print(f"IAST scan for deployment '{MICROK8S_DEPLOYMENT_NAME}' initiated. Scan ID: {scan_id}")
else:
print(f"Failed to initiate IAST scan: {response.text}")

if __name__ == "__main__":
main()

To Conclude

It is still critical to follow security best practices at every stage of the development process. Simple methods for local testing remain paramount and a method to integrate SAST, DAST and IAST never fails to surprise with the efficacy and reduced pressure on those stressful deployments. Go ahead, test it out!!

Connect?

--

--

Imran Roshan
Google Cloud - Community

Your security sherpa | Google Developer Expert (GCP) | Ethical Hacker | Cloud Security