Controls mapping
This maps Nezal's features to the control frameworks a regulated buyer is audited against. It is a mapping and not a certification: Nezal is not certified against any of these and no product can be "compliant" on a customer's behalf. What a product can do is implement controls and produce evidence. What follows is exactly which ones it implements and where in the code. It also says how you demonstrate them to your own auditor.
Every row was checked against this repository rather than written from memory. A row says so wherever Nezal does part of a control and the customer does the rest — a mapping that claims more than it does is worse than none because your auditor will find the gap and then distrust the rest of the table.
Frameworks covered:
- NCA Essential Cybersecurity Controls (ECC-1:2018)
- SAMA Cyber Security Framework (v1.0)
- ISO/IEC 27001:2022 Annex A
- The Personal Data Protection Law (PDPL) as it bears on data residency
How to use this
Your auditor will ask for evidence rather than claims. Each row's Evidence column names something you can produce from a running installation: an export or a screen or a file. Produce it once during preparation and keep it with your control documentation. The audit log export is signed so it can be handed over and verified without access to the cluster.
Identity and access
| Control | NCA ECC | SAMA CSF | ISO 27001 | What Nezal does | Evidence |
|---|---|---|---|---|---|
| Identity federation | 2-2-3 | 3.3.5 | A.5.16 | Authentication is delegated to your identity provider over OIDC (authorization code with PKCE) or SAML 2.0. Nezal holds no passwords for federated users | Settings → Security shows the configured provider. GET /api/v1/auth/providers |
| Multi-factor authentication | 2-2-3 | 3.3.5 | A.5.17 | TOTP for local accounts with any free authenticator app and ten single-use recovery codes. Nothing outside the cluster is contacted. A policy can enforce it for all of them. Resetting one account makes it enrol again at its next sign-in. Federated users get whatever your IdP enforces | Settings → Security → MFA policy. The audit log records enrolment and reset |
| Password storage | 2-2-3 | 3.3.5 | A.5.17 | Argon2id (api/internal/localauth). Passwords are never logged and never in a backup in plaintext |
Source review. A backup contains only the hash |
| Role-based access | 2-2-3 | 3.3.5 | A.5.15 | Three roles — Developer and Team lead and Admin — enforced in the API and never only in the UI. The admission webhook enforces the same rules against kubectl |
Admin → Users. GET /api/v1/rbac/matrix prints the full matrix |
| Privileged session logging | 2-2-4 | 3.3.6 | A.8.15 | Every web terminal session is logged with who opened it and which pod and when and why it ended. The entry is in the hash-chained audit log and is never deleted. Sessions are not replayable: Nezal records no keystrokes or output | Admin → Terminal sessions. The audit log entry for each session |
| Privileged session limits | 2-2-4 | 3.3.6 | A.8.15 | Idle timeout (15m default) and maximum duration (4h default) per team. The reason is recorded on each closed session | Admin → Quotas. The sessions list shows why each ended |
| Session revocation | 2-2-3 | 3.3.5 | A.5.18 | Roles are re-read from the store on every request so a revoked role takes effect immediately rather than at token expiry | Remove a role and observe the next request refused |
| Brute-force protection | 2-2-3 | 3.3.5 | A.8.5 | Ten failed passwords locks one account. Sixty failures exhausts one client address across all unauthenticated endpoints. Counters survive a restart | Audit entries for lockouts. The security whitepaper |
Logging and monitoring
| Control | NCA ECC | SAMA CSF | ISO 27001 | What Nezal does | Evidence |
|---|---|---|---|---|---|
| Audit trail | 2-12-1 | 3.3.13 | A.8.15 | Every action of every user is an entry chained by SHA-256 to the previous one. The database refuses UPDATE and DELETE on the table. Recording is off on a fresh install until an administrator turns it on and turning it on or off is always written | Admin → Audit → Verify walks the chain. The audit.recording.on entry shows when recording began |
| Tamper evidence | 2-12-1 | 3.3.13 | A.8.15 | Any alteration breaks the chain and Verify reports where. Exports are signed with the installation's ed25519 key |
Export an evidence package. Verify it with the published public key |
| Log retention | 2-12-3 | 3.3.13 | A.8.15 | Entries are kept until audit.retention.days in the Helm values removes them. The default 0 keeps every entry. With audit.retention.onlyArchived only entries a signed archive already holds are removed. Each run is written to the log and the chain left still verifies |
Admin → Audit. GET /api/v1/audit/archives |
| Write-once storage | 2-12-3 | 3.3.13 | A.8.15 | Archives can be written to your own object storage. Enable object lock on the bucket and nobody — not even a Nezal administrator — can alter or delete them until retention expires | Settings → Evidence storage reports whether the bucket has object lock |
| SIEM integration | 2-12-2 | 3.3.13 | A.8.16 | Live forwarding to your SIEM over syslog (RFC 5424 over TCP or UDP) or HTTP JSON | Settings → SIEM. Entries appear in your collector |
| Monitoring | 2-12-2 | 3.3.13 | A.8.16 | Prometheus metrics with example alert rules. They cover request and error rates and latency. They also cover environments by phase and licence expiry as well as data-volume free space and a stalled audit head | /metrics. The Monitoring section of the admin guide |
Data protection and residency
| Control | NCA ECC | SAMA CSF | ISO 27001 / PDPL | What Nezal does | Evidence |
|---|---|---|---|---|---|
| Data residency | 1-1-1 and 4-1-2 | 3.3.14 | PDPL Art. 29 | Nezal runs entirely inside your cluster. It makes no outbound calls: no telemetry or update check or licence phone-home. It talks only to endpoints your administrator configured: the cluster API plus your own git server and registry and IdP and SMTP relay and SIEM. Optionally it also reaches an AI endpoint and object storage you name | NetworkPolicy egress allow-list (charts/nezal/templates/networkpolicy.yaml). make netpol-check |
| Licence verification offline | — | — | — | The licence is an ed25519-signed file verified locally against a key compiled into the binary. It works in a sealed room | An air-gapped install |
| Encryption in transit | 2-7-1 | 3.3.9 | A.8.24 | HSTS on every response when TLS is configured. The admission webhook and the bundled registry serve TLS from certificates the operator issues and renews | curl -I against the dashboard. The registry's certificate |
| Encryption at rest (backups) | 2-7-1 | 3.3.9 | A.8.24 | Database backups and audit archives are encrypted with AES-256-GCM before they are written anywhere. The key lives in a Kubernetes Secret and deliberately not inside the backup | A backup file begins NEZALENC. nezal-api verify-backup |
| Encryption at rest (volume) | 2-7-1 | 3.3.9 | A.8.24 | Yours. Nezal writes to a PersistentVolume. Encrypting it is your storage class's job | Your StorageClass configuration |
| Secrets handling | 2-7-2 | 3.3.9 | A.8.24 | Credentials live in Kubernetes Secrets and never in the database. The API never returns a stored credential. The support bundle redacts them. A test that plants known values verifies this | GET /api/v1/settings/* returns secretConfigured and never the secret |
Development and change
| Control | NCA ECC | SAMA CSF | ISO 27001 | What Nezal does | Evidence |
|---|---|---|---|---|---|
| Environment separation | 2-6-1 | 3.3.8 | A.8.31 | In shared mode each developer environment is its own namespace with its own quota and limits. In full mode every environment is a complete copy in the workspace namespace with its own NetworkPolicy. Either way one environment cannot reach another or the Nezal system or the nodes or the cloud metadata address. A full-mode environment can reach the internet | kubectl get networkpolicy. The NetworkPolicy per environment |
| Test data | 2-6-2 | 3.3.8 | A.8.33 | Yours. Nezal copies the deployment definition and not the data: persistent volume claims become empty directories in an environment and a warning says so. What a shared baseline's database contains is your decision | The warning on environment creation. The whitepaper's Known gaps |
| Secure build | 2-6-3 | 3.3.8 | A.8.28 | Builds run as unprivileged Jobs in their own namespace with no service account token and egress limited to an allow-list. No Docker daemon and no host socket anywhere | charts/nezal/templates/build-namespace.yaml |
| Vulnerability scanning | 2-10-1 | 3.3.11 | A.8.8 | Yours. Nezal does not scan images and depends on no scanner. Every built image is pushed to your registry where your own scanner can check it | Your scanner's reports for the registry |
| Change approval | 2-6-1 | 3.3.8 | A.8.32 | Every change goes through the API with its RBAC and the admission webhook and is audited. The AI agent reads only the developer's own environment and proposes every change. The developer approves it before it runs. The audit entry records both names | Audit log entries for any change |
| Backup and recovery | 2-9-1 | 3.3.10 | A.8.13 | Scheduled encrypted backups plus a documented restore procedure and a documented disaster-recovery runbook. Both are exercised by drills that run before every release | The disaster-recovery runbook. make e2e-restore and make e2e-dr |
What Nezal does not do
Stated plainly because a mapping without this section is not believed:
- It does not classify your data. PDPL obligations about what personal data you hold and why are yours. Nezal holds user identities and the audit trail of what they did.
- It does not encrypt the data volume. That is your storage class.
- It does not manage your identity provider. Password policy and account lifecycle and joiner-mover-leaver processes live in your IdP rather than here.
- It does not scan images. It depends on no scanner. Your own scanner checks the images in your registry.
- It does not sign preview images. They are built from a branch and used by one environment. They are deleted with it. The release pipeline signs what ships.
- It is not certified against any framework. No third party has assessed it. This table tells your assessor where to look.
Keeping this honest
A row that overstates what Nezal does is a bug — report it the way you would report any other. Each row was verified against the code at the time of writing. The verification is worth repeating at each release rather than assumed to hold.