Automating Security Compliance: Surviving the Post-GDPR Audit
It has been exactly 82 days since May 25th, 2018. The GDPR deadline came and went. If you are like most sysadmins in Oslo, you probably spent that week frantically patching kernels, rewriting privacy policies, and auditing access logs until your eyes bled. The dust has settled, but let’s be honest: your infrastructure probably started drifting away from compliance about ten minutes after you deployed that "final" fix.
Manual security hardening is dead. If you are still manually editing /etc/ssh/sshd_config on production servers, you are already compromised—if not by a hacker, then by human error. In the era of the cloud, compliance must be code. If it isn't automated, it doesn't exist.
I’ve seen it happen. A team deploys a perfectly hardened CentOS 7 stack. Two weeks later, a junior dev temporarily enables password auth to debug a connection issue from a cafe in Grünerløkka. He forgets to revert it. Three months later, a botnet brute-forces the root account. Datatilsynet (The Norwegian Data Protection Authority) does not care about your intentions; they care about your negligence.
The Myth of "Set and Forget"
In a recent project for a FinTech startup in Stavanger, we faced a brutal reality check. We had strict requirements: CIS Level 2 hardening, encryption at rest, and total data sovereignty within Norway. The problem wasn't setting it up; it was keeping it that way.
We realized that treating servers as pets—giving them names and manually nursing them—was a liability. We needed to treat them like cattle, but armored cattle. This meant shifting from manual checklists to Infrastructure as Code (IaC).
Phase 1: Hardening via Ansible
Instead of running shell scripts, we standardized on Ansible. It’s agentless, which keeps our overhead low on the VPS, and it’s declarative. Here is the exact role structure we use to enforce SSH security across our fleet. This works perfectly on Ubuntu 18.04 LTS and CentOS 7.
# roles/security/tasks/ssh.yml
---
- name: Ensure SSH protocol 2 is used
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
notify: Restart SSH
- name: Disable Password Authentication
lineinfile:
path: /etc/ssh/sshd_config
regexp: '^PasswordAuthentication'
line: 'PasswordAuthentication no'
state: present
notify: Restart SSH
- name: Limit SSH Access to Specific Users
lineinfile:
path: /etc/ssh/sshd_config
regexp: '^AllowUsers'
line: 'AllowUsers deploy admin'
state: present
This is basic, but vital. By running this playbook every night, we ensure that if someone accidentally opens a hole, the system self-heals within 24 hours.
Phase 2: Continuous Auditing with OpenSCAP
Applying configs is one thing. Proving you are secure is another. For this, we use OpenSCAP. It implements the SCAP (Security Content Automation Protocol) standard, allowing us to scan against profiles like the PCI-DSS or standard CIS benchmarks.
On a CentOS 7 instance, installation is trivial:
yum install openscap-scanner scap-security-guide
Once installed, you don't guess if you are compliant. You ask the kernel. Here is how we run a scan to check for standard system vulnerabilities:
oscap xccdf eval \
--profile xccdf_org.ssgproject.content_profile_standard \
--results /var/www/html/scan-report.xml \
--report /var/www/html/scan-report.html \
/usr/share/xml/scap/ssg/content/ssg-centos7-ds.xml
This generates a readable HTML report. If you are hosting sensitive data, automating this report generation effectively creates a paper trail for auditors. It shows you are actively monitoring your security posture, a key requirement under GDPR Article 32.
Pro Tip: Don't run heavy SCAP scans during peak traffic hours. While CPU steal is rarely an issue on high-quality VPS Norway providers like CoolVDS, scanning the entire filesystem for permission bits causes significant I/O wait. Schedule this via cron for 03:00 AM.
The Infrastructure Variable: Why Hardware Matters
You can have the best Ansible roles in the world, but the underlying hardware determines your reliability. In 2018, using spinning HDDs for databases or high-traffic web servers is professional negligence. The I/O latency simply kills audit performance (like `auditd` logging) and slows down the very security tools meant to protect you.
We switched our critical workloads to CoolVDS for two specific reasons:
- NVMe Storage: Standard SSDs are fine, but NVMe allows for massive throughput. When `rsyslog` is hammering the disk with debug logs during an attack, you don't want your database to lock up. CoolVDS provides this as standard, not a premium add-on.
- Data Sovereignty: With the uncertainty surrounding the US Privacy Shield, keeping data physically in Norway is the safest legal bet. CoolVDS data centers are located locally. Your data doesn't route through a switch in Frankfurt or London; it stays within Norwegian borders, simplifying your compliance map significantly.
Configuring Auditd for High-IO Environments
If you are serious about compliance, you are running `auditd`. However, default configurations are often too noisy. Here is a balanced configuration we use to track changes to critical system files without crashing the server:
# /etc/audit/rules.d/audit.rules
# Delete all existing rules
-D
# Buffer Size
-b 8192
# Failure Mode (1=printk, 2=panic)
-f 1
# Watch critical identity files
-w /etc/group -p wa -k identity
-w /etc/passwd -p wa -k identity
-w /etc/gshadow -p wa -k identity
-w /etc/shadow -p wa -k identity
-w /etc/security/opasswd -p wa -k identity
# Monitor system calls for file truncation (potential data destruction)
-a always,exit -F arch=b64 -S truncate -S ftruncate -F exit=-EPERM -F auid>=1000 -F auid!=4294967295 -k access
Load these rules with augenrules --load. Warning: setting `-f 2` (panic) will crash your server if the audit daemon fails to write to the disk. Unless you are running a military-grade facility, stick to `-f 1`.
Network Layer Defense
Finally, compliance isn't just about disk encryption and file permissions. It is about availability. A DDoS attack that takes you offline is a security incident. We utilize the integrated DDoS protection offered by CoolVDS to filter volumetric attacks before they hit our `iptables` chains.
However, you must still harden your kernel against standard floods. Add this to your `/etc/sysctl.conf`:
# Protection against SYN flood attacks
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_max_syn_backlog = 2048
net.ipv4.tcp_synack_retries = 2
# Disable IP source routing (common in spoofing)
net.ipv4.conf.all.accept_source_route = 0
# Log Martians (packets with impossible addresses)
net.ipv4.conf.all.log_martians = 1
Apply with sysctl -p.
Conclusion
The era of the "Cowboy Admin" is over. The legal risks are too high, and the threat landscape in 2018 is too automated. Your defense must be equally automated. By combining Ansible for configuration management, OpenSCAP for verification, and hosting on robust, local infrastructure like CoolVDS, you turn compliance from a yearly nightmare into a daily routine.
Do not wait for the next letter from Datatilsynet. Audit your infrastructure today. If you need a sandbox to test these configurations without risking your production environment, spin up a KVM instance on CoolVDS. It takes less than a minute, and the low latency ensures your SSH sessions feel instant.