Skip to content

Hardening MicroK8s#

Original Author Sami Koivisto
Last checked by Sami Koivisto
Status Needs testing and maybe more stuff
Last Updated 13.5.2025

Proposed Prerequisites

  • Project in CSC and cPouta activated
  • Ubuntu 24.04
  • Port 80 open
  • MicroK8s installed

Hardening in general#

Hardening refers to the process of securing a system by reducing its surface of vulnerability. This involves configuring systems, applications, and networks to minimize potential attack vectors, such as disabling unnecessary services, applying security patches, enforcing strong access controls, and following security best practices. The goal of hardening is to make the system more resilient against cyberattacks by limiting the opportunities for unauthorized access or exploitation.

Kubernetes hardening#

Kubernetes hardening focuses on improving the security posture of Kubernetes clusters by applying specific configurations and best practices to protect the control plane, nodes, workloads, and network communications. This includes actions such as restricting API access, enforcing Role-Based Access Control (RBAC), securing secrets, using network policies to control traffic between pods, enabling audit logging, and applying Pod Security Standards or admission controllers. The aim is to reduce the risk of compromise within a complex containerized environment by ensuring that every component is configured with security in mind.

Five hardening steps for MicroK8s#

The first step is to install the necessary MicroK8s Addons:

microk8s enable ingress
microk8s enable cert-manager
microk8s enable rbac

# You can also install Trivy, but in my case, it installed an outdated version, and the vulnerability reports did not work properly, so I installed it using Helm instead.

microk8s enable community
microk8s enable trivy

1. Trivy Operator#

Trivy is a security scanner for vulnerabilities in container images, file systems, and Git repositories. It detects known security issues in software dependencies and configuration files.

Install trivy operator:

microk8s helm repo add aqua https://aquasecurity.github.io/helm-charts/
microk8s helm repo update

microk8s helm install trivy-operator aqua/trivy-operator \
  --namespace trivy-system \
  --create-namespace \
  --version 0.28.1

Wait a moment for the automatic scan to complete, and then you can review the vulnerability reports and config audit reports:

microk8s kubectl get vulnerabilityreports --all-namespaces -o wide
microk8s kubectl get configauditreports --all-namespaces -o wide

# For more details

microk8s kubectl describe vulnerabilityreports --all-namespaces

2. Updating Ingress#

Ingress is a Kubernetes resource that manages external access to services within a cluster, typically HTTP/HTTPS traffic. It defines rules for routing traffic to specific services based on hostnames or URLs.

Check the version of the Ingress controller:

grep TAG= /var/snap/microk8s/common/addons/core/addons/ingress/enable

If the version is a vulnerable one, go to the configuration file and change the TAG field to new version. After this, the old pods will be terminated and replaced with new ones.

sudo nano /var/snap/microk8s/common/addons/core/addons/ingress/enable
# CTRL + S and CTRL + X to save and quit

3. Using cert-manager to get certificate#

Cert-manager automates the management and issuance of TLS certificates. It helps ensure secure communication by automatically obtaining, renewing, and deploying certificates for services within the cluster.

Create a new YAML file and enter your own email address in the email field:

apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
  name: letsencrypt
spec:
  acme:
    # The ACME server URL
    server: https://acme-v02.api.letsencrypt.org/directory
    # Email address used for ACME registration
    email: #PUT YOUR EMAIL HERE
    # Name of a secret used to store the ACME account private key
    privateKeySecretRef:
      name: letsencrypt-prod
    # Enable the HTTP-01 challenge provider
    solvers:
      - http01:
          ingress:
            ingressClassName: nginx

Save and close the file. Then apply with:

microk8s kubectl apply -f <YOUR-FILE>

After that, create an Ingress YAML file and enter your own domain in the host(s) field and your own service to service name field:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: prestashop-ingress
  annotations:
    cert-manager.io/issuer: letsencrypt
spec:
  rules:
    - host: #YOUR DOMAIN
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: prestashop-service
                port:
                  number: 80
  tls:
    - hosts:
        -  #YOUR DOMAIN
      secretName: prestashop-tls

Now you can use this with PrestaShop. Apply with:

microk8s kubectl apply -f <YOUR-FILE>

Wait a moment, and the certificate ready state should change to True.

microk8s kubectl get certificate

4. NetworkPolicy between pods#

NetworkPolicy is a Kubernetes resource that controls the traffic between pods. It allows you to define rules for restricting or allowing communication based on pod selectors, namespaces, and IP addresses, enhancing cluster security.

Create new YAML file for NetworkPolicy. You can change name, apps and port.

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-prestashop-to-mysql
  namespace: default
spec:
  PodSelector:
    matchLabels:
      app: mysql
  policyTypes:
    - Ingress
  ingress:
    - from:
        - podSelector:
            matchLabels:
              app: prestashop
      ports:
        - protocol: TCP
          port: 3306

Apply with:

microk8s kubectl apply -f <YOUR-FILE>

5. RBAC#

RBAC (Role-Based Access Control) is a Kubernetes mechanism for managing access to resources. It allows you to define roles and permissions, granting users or service accounts specific access to Kubernetes resources based on their role.

Create new YAML file for RBAC. You can change names and rules. This has not been tested with PrestaShop and MySQL.

---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: rbac-tester
  namespace: default
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: pod-reader
  namespace: default
rules:
  - apiGroups: [""]
    resources: ["pods"]
    verbs: ["get", "list"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: pod-reader-binding
  namespace: default
subjects:
  - kind: ServiceAccount
    name: rbac-tester
    namespace: default
roleRef:
  kind: Role
  name: pod-reader
  apiGroup: rbac.authorization.k8s.io