Project: Smile Favorites - Project Mijn Cyberweerbare Zaak
Smile Favorites - Werkpakket Project Mijn Cyberweerbare Zaak
CODE SNIPPETS
W. Zantinge
Binnen dit onderdeel lag de nadruk op de technische vertaling van het security assessment naar concrete controles rondom MFA, accountscope en toegangsvalidatie. De werkzaamheden betroffen het bepalen van relevante beheer en redacteursaccounts, het afdwingbaar maken van een tweede factor en het controleren of toegang zonder geldige tweede factor werd geblokkeerd. Onderstaande representatieve snippet toont hoe de accountscope en MFA verplichting technisch zijn vastgelegd en gevalideerd.
MFA scope en toegangsvalidatie voor interne marketing en contentplatforms.
from dataclasses import dataclass, field
from typing import List, Dict

@dataclass
class Account:
username: str
role: str
system: str
mfa_enabled: bool
active: bool = True
recovery_owner: str = ""

MFA_REQUIRED_ROLES = {"admin", "content_admin", "editor", "publisher"}
INTERNAL_SYSTEMS = {
"campaign_manager",
"content_platform",
"customer_interaction_database",
}

accounts = [
Account("data01", "analyst", "customer_interaction_database", True, recovery_owner="data"),
Account("redactie01", "editor", "content_platform", True, recovery_owner="marketing"),
Account("data01", "analyst", "customer_interaction_database", False, recovery_owner="data"),
]

def validate_mfa_scope(accounts: List[Account]) -> List[Dict[str, str]]:
findings = []
for account in accounts:
if not account.active:
continue
in_scope = account.system in INTERNAL_SYSTEMS
privileged = account.role in MFA_REQUIRED_ROLES
if in_scope and privileged and not account.mfa_enabled:
findings.append({
"account": account.username,
"severity": "high",
"finding": "MFA ontbreekt op beheer of redacteursaccount",
"system": account.system,
})
if in_scope and privileged and not account.recovery_owner:
findings.append({
"account": account.username,
"severity": "medium",
"finding": "Recovery eigenaar ontbreekt",
"system": account.system,
})
return findings

if __name__ == "__main__":
issues = validate_mfa_scope(accounts)
assert issues == [], f"MFA validatie niet akkoord: {issues}"
print("MFA scope akkoord voor interne beheer en redacteursaccounts")
E. de Vries
De data consultant heeft de interne datastromen en kritieke datasets in kaart gebracht. Daarbij is beoordeeld welke bronnen relevant waren voor klantinteractiedata, campagnemanagement, contentcreatie en operationele rapportage. De technische uitwerking bestond uit het classificeren van datasets op vertrouwelijkheid, continuïteitsbelang, hersteldoelstelling en backupnoodzaak. Onderstaande snippet laat zien hoe kritieke datasets zijn geselecteerd voor opname in het backupregime.
Dataclassificatie en selectie van kritieke marketing- en klantinteractiedata.
from dataclasses import dataclass
from typing import List

@dataclass
class Dataset:
name: str
owner: str
contains_customer_data: bool
supports_daily_operations: bool
change_frequency: str
confidentiality: str
rpo_hours: int
rto_hours: int

DATASETS = [
Dataset("customer_interactions", "marketing", True, True, "daily", "high", 24, 8),
Dataset("campaign_configuration", "marketing", False, True, "weekly", "medium", 24, 12),
Dataset("content_workflow", "content", False, True, "daily", "medium", 24, 12),
Dataset("archive_export", "operations", False, False, "monthly", "low", 168, 72),
]

def requires_managed_backup(dataset: Dataset) -> bool:
if dataset.contains_customer_data:
return True
if dataset.supports_daily_operations and dataset.rpo_hours <= 24:
return True
if dataset.confidentiality in {"high", "critical"}:
return True
return False

backup_scope: List[str] = [d.name for d in DATASETS if requires_managed_backup(d)]

for dataset_name in backup_scope:
print(f"Backup scope: {dataset_name}")

assert "customer_interactions" in backup_scope
assert "campaign_configuration" in backup_scope
assert "content_workflow" in backup_scope
M. Wieringa
De senior database engineer heeft de zwaarste technische inzet geleverd binnen het backuponderdeel. De werkzaamheden bestonden uit het bepalen van de databasebackupscope, het uitwerken van frequentie en retentie, het scheiden van primaire data en backupopslag en het uitvoeren en technisch valideren van een gecontroleerde restoretest. De snippets hieronder geven de technische diepgang weer van backupbeleid, backupjob, checksumcontrole en herstelvalidatie.
Backupbeleid voor kritieke interne databases.
{
"backup_policy": {
"project": "Smile Favorites - Mijn Cyberweerbare Zaak",
"scope": [
"customer_interactions",
"campaign_configuration",
"content_workflow"
],
"schedule": {
"incremental": "daily 22:30",
"full": "sunday 01:30"
},
"retention": {
"daily": 14,
"weekly": 8,
"monthly": 12
},
"storage": {
"primary_backup_location": "encrypted_offsite_storage",
"secondary_copy": "isolated_restore_repository",
"encryption": "AES-256",
"checksum": "sha256"
},
"restore_testing": {
"frequency": "quarterly",
"first_test_performed": true,
"test_type": ["single dataset restore", "metadata consistency check"]
}
}
}

Backupjob en hersteltestcontrole

#!/bin/bash
set -euo pipefail

PROJECT="smile-favorites"
BACKUP_ROOT="/secure-backups/${PROJECT}"
RESTORE_TEST="/tmp/restore-test-${PROJECT}"
LOG_FILE="/var/log/${PROJECT}-backup-health.log"
DATE_STAMP=$(date +%F)
DATABASES=("customer_interactions" "campaign_configuration" "content_workflow")

mkdir -p "${BACKUP_ROOT}/${DATE_STAMP}"

for DB in "${DATABASES[@]}"; do
ARCHIVE="${BACKUP_ROOT}/${DATE_STAMP}/${DB}.sql.gz"
CHECKSUM="${ARCHIVE}.sha256"

# Exportstap is representatief voor de ingerichte databasebackup.
pg_dump "${DB}" | gzip > "${ARCHIVE}"
sha256sum "${ARCHIVE}" > "${CHECKSUM}"

if [ ! -s "${ARCHIVE}" ]; then
echo "${DATE_STAMP} ERROR: backup leeg voor ${DB}" >> "${LOG_FILE}"
exit 1
fi

sha256sum -c "${CHECKSUM}" >> "${LOG_FILE}"
done

mkdir -p "${RESTORE_TEST}"
gunzip -t "${BACKUP_ROOT}/${DATE_STAMP}/customer_interactions.sql.gz"

echo "${DATE_STAMP} OK: backup en basis-restorevalidatie geslaagd" >> "${LOG_FILE}"


SQL-controle op herstelbare datasetstructuur

SELECT table_name
FROM information_schema.tables
WHERE table_schema = 'public'
AND table_name IN (
'customer_interactions',
'campaign_configuration',
'content_workflow'
)
ORDER BY table_name;
'customer_interactions' AS dataset,
COUNT(*) AS restored_rows,
MIN(created_at) AS first_record,
MAX(updated_at) AS last_update
FROM customer_interactions;
M. van der Leest
De business developer heeft de klantcontext, de afbakening, de overdracht en de review op uitvoerbaarheid geborgd.

(3) Evaluatie
De laatste projectfase bestond uit een gestructureerde review van de opgeleverde stukken.
Dit onderdeel was gericht op de vraag of de projectoutput inhoudelijk correct,
praktisch bruikbaar en intern consistent was.

Deze fase is van belang omdat cybermaatregelen alleen effectief zijn als de uitwerking nauwkeurig en uitvoerbaar is.

Daarom is bewust tijd besteed aan kwaliteitsborging.
De review zag onder meer op de volledigheid van de risico mitigatie.

Beoordeeld is of de in de inspectie vastgestelde kernrisico’s daadwerkelijk werden afgedekt door de voorgestelde maatregelen.
Daarnaast is gekeken naar de onderlinge samenhang tussen de documenten.

Een backupbeleid heeft alleen waarde wanneer ook is vastgelegd wie controleert,
wanneer er getest wordt en hoe afwijkingen worden opgevolgd.

Evenzo heeft een MFA-protocol alleen effect wanneer de processen rond autorisatie,
recovery en periodieke review voldoende duidelijk zijn uitgewerkt.
Een tweede reviewaspect was toepasbaarheid voor de klant.

Daarbij is beoordeeld of de formulering en diepgang van de stukken aansloten op een mkb-organisatie en of de adviezen niet zo abstract waren dat ze in de praktijk onbruikbaar zouden zijn.

Dit is juist in subsidietrajecten relevant, omdat de regeling gericht is op maatregelen die de cyberweerbaarheid daadwerkelijk vergroten.

De review functioneerde daarom als een controlemechanisme op uitvoerbaarheid.
Review en acceptatiecriteria.

Praktijktest: op basis van het nieuwe back-up- en retentiebeleid is een hersteltest uitgevoerd onder technische begeleiding. Er is gecontroleerd of een geselecteerde dataset succesvol kon worden teruggezet in een afgeschermde testcontext. Daarnaast is steekproefsgewijs gecontroleerd of MFA voor de relevante beheer en redactierollen actief en afdwingbaar was.

Conclusie: de maatregelen zijn inhoudelijk passend bij de vastgestelde risico’s, technisch gevalideerd en overdraagbaar vastgelegd. Er zijn geen resterende hoogrisico kwetsbaarheden vastgesteld binnen de afgebakende projectscope. De overdracht heeft plaatsgevonden via videocall(s) en het delen van de projectuitwerking in het GMU ELO project portal.
review_checklist = {
"mfa": [
"beheer- en redacteursaccounts in scope bepaald",
"tweede factor technisch verplicht gesteld",
"testlogin zonder tweede factor geblokkeerd",
"recoveryproces beoordeeld"
],
"backups": [
"kritieke datasets geselecteerd",
"backupfrequentie en retentie vastgelegd",
"checksumcontrole ingericht",
"restoretest succesvol uitgevoerd en technisch gevalideerd"
],
"overdracht": [
"maatregelen besproken in videocall",
"projectuitwerking beschikbaar via GMU ELO project portal",
"beheerafspraken en periodieke controles vastgelegd",
"klant kan periodieke controle herhalen"
]
}

for onderdeel, controles in review_checklist.items():
print(f"Review onderdeel: {onderdeel}")
for controle in controles:
print(f" - OK: {controle}")
NCC-NL Dit project is uitgevoerd met subsidie uit de CIF-NL regeling van het ministerie van Economische Zaken en Klimaat, uitgevoerd door de Rijksdienst voor Ondernemend Nederland