Console Login

Automating Compliance: A CTO’s Guide to CIS Benchmarks and GDPR in a Post-Schrems II World

Automating Compliance: A CTO’s Guide to CIS Benchmarks and GDPR in a Post-Schrems II World

It is July 2022. If your engineering team is still manually editing /etc/ssh/sshd_config on production servers, you are not just inefficient—you are a liability. In the wake of the Schrems II ruling and the aggressive stance taken by Datatilsynet (The Norwegian Data Protection Authority), the "security through obscurity" mindset is dead. You need audit trails. You need reproducible infrastructure. You need to prove that your data hasn't left the EEA.

As a CTO, my job isn't to chase the latest JavaScript framework. It's to ensure the company survives a ransomware attack or a compliance audit. We don't harden servers because it's fun. We do it to reduce the blast radius when—not if—something goes wrong. This guide covers how to automate this process using Infrastructure as Code (IaC) principles, specifically targeting the CIS (Center for Internet Security) Benchmarks on Ubuntu 22.04 LTS instances running on local Norwegian infrastructure.

The Myth of the "Secure" Default Image

No OS image is secure by default. Not even the minimal ones. When you spin up a VPS, regardless of the provider, it is optimized for compatibility, not security. Services you don't need are running. Ports are open. Legacy protocols are enabled. If you deploy a standard LAMP stack without hardening, automated bots will brute-force your SSH within minutes.

To fix this at scale, we stop treating servers like pets. We use Ansible. Below is the difference between a junior admin's approach and a senior architect's approach.

1. Base Hardening with Ansible

Instead of running shell scripts, we define the desired state. Here is a production-ready Ansible playbook snippet that enforces basic SSH hardening rules required by most compliance frameworks (PCI-DSS, SOC2).

---
- name: Harden SSH Configuration
  hosts: web_servers
  become: yes
  tasks:
    - name: Ensure SSH protocol 2 is set
      lineinfile:
        path: /etc/ssh/sshd_config
        regexp: '^Protocol'
        line: 'Protocol 2'
        state: present

    - name: Disable Root Login
      lineinfile:
        path: /etc/ssh/sshd_config
        regexp: '^PermitRootLogin'
        line: 'PermitRootLogin no'
        state: present

    - name: Disable Password Authentication
      lineinfile:
        path: /etc/ssh/sshd_config
        regexp: '^PasswordAuthentication'
        line: 'PasswordAuthentication no'
        state: present

    - name: Ensure SSH MaxAuthTries is set to 3
      lineinfile:
        path: /etc/ssh/sshd_config
        regexp: '^MaxAuthTries'
        line: 'MaxAuthTries 3'
        state: present
      notify: Restart SSH

  handlers:
    - name: Restart SSH
      service:
        name: sshd
        state: restarted

This ensures that every time we deploy a new node on CoolVDS, it lands with root login disabled and keys enforced. Consistency is the bedrock of security.

Pro Tip: Always validate your configuration syntax before restarting the service. In your CI/CD pipeline, run sshd -t to prevent locking yourself out of a thousand servers simultaneously.

Network Stack Hardening

Beyond SSH, the kernel itself needs tuning. For high-performance web serving, we often tune sysctl for throughput, but for security, we tune to prevent spoofing and flooding. Specifically, disabling IP forwarding (unless you are a router) and ignoring ICMP broadcasts are mandatory for passing a CIS Level 1 audit.

Apply these settings via a file in /etc/sysctl.d/99-security.conf:

net.ipv4.conf.all.accept_redirects = 0
net.ipv6.conf.all.accept_redirects = 0
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.all.accept_source_route = 0
net.ipv4.tcp_syncookies = 1
kernel.randomize_va_space = 2

To apply this immediately without rebooting, run:

sysctl -p /etc/sysctl.d/99-security.conf

Automated Auditing with OpenSCAP

You have hardened the server. Great. How do you prove it? Taking screenshots of config files is not a strategy. We use OpenSCAP (Security Content Automation Protocol) to scan our systems against standard profiles.

In 2022, the scap-security-guide package covers Ubuntu 20.04 and 22.04. Here is how you install the tooling:

apt-get install libopenscap8 scap-security-guide -y

Running a CIS Compliance Scan

The following bash script automates the scanning process. It identifies the correct profile for Ubuntu and generates an HTML report that you can hand directly to your auditor.

#!/bin/bash

# Define variables
PROFILE="xccdf_org.ssgproject.content_profile_cis_level1_server"
CONTENT="/usr/share/xml/scap/ssg/content/ssg-ubuntu2204-ds.xml"
REPORT_DIR="/var/www/html/security-reports"
DATE=$(date +%F)
HOSTNAME=$(hostname)

# Ensure report directory exists
mkdir -p $REPORT_DIR

# Run the evaluation
echo "Starting OpenSCAP scan for $HOSTNAME..."
oscap xccdf eval \
  --profile $PROFILE \
  --results $REPORT_DIR/$HOSTNAME-$DATE.xml \
  --report $REPORT_DIR/$HOSTNAME-$DATE.html \
  $CONTENT

# Check exit status
if [ $? -eq 0 ]; then
    echo "Scan Compliant."
elif [ $? -eq 1 ]; then
    echo "Scan Error."
else
    echo "Scan Non-Compliant. Check report at $REPORT_DIR/$HOSTNAME-$DATE.html"
fi

When running this on CoolVDS NVMe instances, the I/O intense nature of scanning thousands of files completes rapidly. On legacy spinning rust VPS, this scan can cause iowait spikes that degrade application performance. High IOPS isn't just for databases; it's for maintenance tasks too.

The "Schrems II" Reality Check

Technical hardening is useless if you fail legal compliance. Since the Schrems II ruling in 2020, relying on the US-EU Privacy Shield is illegal. Transferring personal data to US-owned hyperscalers (AWS, Azure, GCP) creates a complex risk assessment requirement regarding the US CLOUD Act.

This is where infrastructure choice becomes a compliance tool. By utilizing CoolVDS, your data resides physically in Oslo, on hardware owned by a Norwegian entity. There is no murky data transfer. Your data sovereignty is absolute. This simplifies your GDPR Article 30 records immensely.

Continuous Monitoring with Auditd

Compliance is not a one-time event. It is a state. We use the Linux Audit daemon (auditd) to watch critical files for changes. If /etc/passwd changes at 3 AM on a Sunday, I want to know.

Here is a robust audit.rules configuration block to catch unauthorized file access:

# Delete all existing rules
-D

# Set buffer size
-b 8192

# Failure mode (1=printk, 2=panic). We choose printk.
-f 1

# Monitor /etc/passwd
-w /etc/passwd -p wa -k identity
-w /etc/group -p wa -k identity
-w /etc/shadow -p wa -k identity
-w /etc/gshadow -p wa -k identity
-w /etc/security/opasswd -p wa -k identity

# Monitor system calls for file truncation or deletion
-a always,exit -F arch=b64 -S unlink -S unlinkat -S rename -S renameat -F auid>=1000 -F auid!=4294967295 -k delete
-a always,exit -F arch=b32 -S unlink -S unlinkat -S rename -S renameat -F auid>=1000 -F auid!=4294967295 -k delete

# Make the configuration immutable (requires reboot to change)
-e 2

Load these rules with:

augenrules --load

Conclusion

Compliance automation reduces the TCO of your infrastructure. It moves security from a bottleneck to a standard feature of your deployment pipeline. By combining Ansible for consistency, OpenSCAP for verification, and local Norwegian hosting for data sovereignty, you build a fortress that is both performant and legal.

Do not wait for the audit letter to arrive. Start hardening today. If you need a sandbox to test these playbooks without risking production, spin up a high-performance CoolVDS instance. With our KVM virtualization, you get the kernel-level isolation needed for accurate security testing.