Console Login

Automating Security Compliance: Surviving the Datatilsynet Audit with Infrastructure as Code

Automating Security Compliance: Surviving the Datatilsynet Audit with Infrastructure as Code

Most sysadmins lie. When the auditor asks if every single server has the latest kernel patch or if root login is disabled across the entire fleet, the answer is usually a confident "yes," followed by a frantic check of the inventory spreadsheets. In 2023, with the Datatilsynet (Norwegian Data Protection Authority) tightening the screws on GDPR enforcement and the Schrems II ruling making data transfers a legal minefield, relying on manual checklists is professional suicide.

Compliance isn't a PDF you sign once a year. It is a technical state of being. If you cannot prove your infrastructure's security posture via code, you are already non-compliant.

I recently inherited a chaotic infrastructure for a fintech client based in Oslo. They had data scattered across three different cloud providers, root keys circulating in Slack, and a pending audit. The solution wasn't a consulting firm; it was Compliance as Code. Here is how we automated the hardening process to meet CIS Benchmarks, strictly on Norwegian soil.

The Foundation: Isolation Matters

Before writing a single line of code, look at your virtualization. Many "cheap" VPS providers use container-based virtualization (like OpenVZ or LXC) where you share the kernel with neighbors. From a security compliance perspective, this is a nightmare. A kernel panic or a container escape vulnerability affects everyone on the node.

For strict compliance, you need KVM (Kernel-based Virtual Machine). This provides hardware-level isolation. At CoolVDS, we enforce KVM on all instances. It means your memory, CPU instructions, and kernel modules are yours. No noisy neighbors, no shared vulnerabilities. When an auditor asks about tenant isolation, "We use KVM" is the only acceptable answer.

Step 1: The Automated Hardening Pipeline

We don't manually edit /etc/ssh/sshd_config anymore. We use Ansible. This ensures that every node, from the load balancer to the database replica, adheres to the exact same standard.

Here is a production-ready Ansible task snippet that enforces SSH hardening standards compatible with CIS benchmarks. This disables empty passwords, root login, and enforces protocol 2.

- name: Harden SSH Configuration
  hosts: all
  become: yes
  tasks:
    - name: Update SSHD configuration
      lineinfile:
        path: /etc/ssh/sshd_config
        regexp: "{{ item.regexp }}"
        line: "{{ item.line }}"
        state: present
        validate: '/usr/sbin/sshd -t -f %s'
      loop:
        - { regexp: '^PermitRootLogin', line: 'PermitRootLogin no' }
        - { regexp: '^PasswordAuthentication', line: 'PasswordAuthentication no' }
        - { regexp: '^PermitEmptyPasswords', line: 'PermitEmptyPasswords no' }
        - { regexp: '^Protocol', line: 'Protocol 2' }
        - { regexp: '^MaxAuthTries', line: 'MaxAuthTries 3' }
      notify: restart sshd

  handlers:
    - name: restart sshd
      service:
        name: sshd
        state: restarted

This script does two critical things: it applies the config and validates it before restarting the service. If you break the config, SSH doesn't restart, and you don't get locked out. That is operational maturity.

Step 2: Kernel & Network Tuning

Default Linux network stacks are tuned for compatibility, not security. To prevent IP spoofing and Man-in-the-Middle attacks, we need to manipulate the sysctl settings. Doing this manually on 50 servers is impossible. Doing it via an initialization script is reliable.

Use this configuration to prevent source routing and redirect acceptance:

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

# IP Spoofing protection
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.default.rp_filter = 1

# Ignore ICMP broadcast requests
net.ipv4.icmp_echo_ignore_broadcasts = 1

# Disable source packet routing
net.ipv4.conf.all.accept_source_route = 0
net.ipv6.conf.all.accept_source_route = 0

# Disable send redirects
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.default.send_redirects = 0

Apply these immediately without rebooting using:

sysctl -p /etc/sysctl.d/99-security.conf
Pro Tip: On CoolVDS NVMe instances, tweaking vm.swappiness down to 10 often improves database performance significantly because our I/O throughput is high enough that we want to avoid swap unless absolutely necessary.

Step 3: Auditing with OpenSCAP

How do you prove to the auditor that the above settings are active? You scan. OpenSCAP is the industry standard for verifying compliance against CIS profiles.

First, install the scanner and the security guides (on RHEL/CentOS/AlmaLinux systems):

yum install openscap-scanner scap-security-guide

Now, run a scan against the "Standard" profile and generate an HTML report. This report is what you hand to the Datatilsynet auditors.

oscap xccdf eval \
  --profile xccdf_org.ssgproject.content_profile_standard \
  --results scan-results.xml \
  --report report.html \
  /usr/share/xml/scap/ssg/content/ssg-rhel9-ds.xml

If you see red on that report, you fix the Ansible playbook, run it again, and re-scan. This is the loop. Scan, Patch, Verify.

Step 4: File Integrity Monitoring (FIM)

Compliance requires knowing when a critical file changed. auditd is the Linux kernel's audit subsystem. It logs system calls. It is verbose, but necessary.

To monitor changes to the /etc/passwd file (where users are defined), add this rule:

-w /etc/passwd -p wa -k identity_changes

This command breaks down as follows:

  • -w: Watch this file.
  • -p wa: Trigger on write or attribute change.
  • -k: Key name for searching logs later.

To search for these events later:

ausearch -k identity_changes | aureport -f -i

The Data Sovereignty Factor

Technical hardening is useless if the legal framework of the data center fails. Under GDPR and Schrems II, storing personal data of Norwegian citizens on US-controlled cloud infrastructure is risky. Even with "European Regions," the US CLOUD Act can compel data access.

This is where local hosting becomes a compliance feature. CoolVDS infrastructure is physically located in Europe, often leveraging low-latency connections to NIX (Norwegian Internet Exchange). When we say your data is in Norway/Europe, it stays there. The latency benefits (often sub-10ms to Oslo) are just a bonus on top of the legal safety.

Summary

Security compliance automation reduces the "bus factor" risk. If your lead engineer leaves, the security posture shouldn't leave with them. By defining your infrastructure in Ansible and verifying it with OpenSCAP, you turn compliance into a deployable asset.

Your Checklist for Monday:

  1. Migrate off container-based VPS to KVM-based CoolVDS instances.
  2. Write an Ansible role for basic SSH hardening.
  3. Run an initial OpenSCAP scan to see how bad the baseline is.
  4. Disable root login. Seriously. Do it now.

Don't wait for the audit letter to arrive. Deploy a compliant, hardened KVM instance on CoolVDS today and secure your infrastructure before the logs start growing.