Security & Network Guide
This page is for the security reviewer signing off a Nexa deployment. Nexa is customer-managed: DataReadyAI ships container images and infrastructure-as-code, and your platform team runs it entirely inside your own cloud account against your own Snowflake or Databricks. DataReadyAI has no standing access to your environment. Everything below describes the reference architecture and calls out, honestly, what is hardened by default and what you must configure before production.
Encryption at rest
Section titled “Encryption at rest”| Store | Encryption | Key |
|---|---|---|
| Postgres (RDS) | Enabled (storage_encrypted = true) |
AWS-managed key |
| S3 raw data lake | AES256 server-side encryption |
AWS-managed key |
| S3 Terraform state | AES256, versioned, access-logged |
AWS-managed key |
| ECR images | AES256 |
AWS-managed key |
| Node EBS volumes | Provisioned via the EBS CSI driver | AWS-managed key |
| Secrets (AWS Secrets Manager, SSM SecureString) | Encrypted at rest | AWS-managed key |
Encryption in transit
Section titled “Encryption in transit”- External traffic terminates TLS at the gateway with a Let’s Encrypt certificate (see Network). Plain HTTP on
:80is redirected to HTTPS (301). - Database: an
rds.force_sslparameter can require TLS on every Postgres connection. It is off in the reference dev config — enable it in production so no client connects in cleartext. - In-cluster service-to-service traffic uses cluster DNS over the pod network. There is no service mesh / mTLS by default; if you require encrypted east-west traffic, add a mesh (or Envoy mTLS) at the cluster layer.
Data residency & what leaves the environment
Section titled “Data residency & what leaves the environment”- All Nexa infrastructure — cluster, database, object storage, secrets — is created in a single region in your cloud account. Nothing is multi-region unless you configure it.
- Your business data stays in your Snowflake/Databricks and your S3 raw data lake. Nexa’s cross-account S3 role is scoped to a single prefix (
raw/) and gated by anExternalId. - What leaves the environment: requests Nexa makes to your data platform (Snowflake/Databricks) and to any AI model endpoints you configure, plus outbound calls to the code repositories Nexa writes pipelines to (via
GITHUB_TOKEN) and to Let’s Encrypt for certificate issuance. DataReadyAI receives only what you deliberately send with a support case (see troubleshooting).
Identity & access
Section titled “Identity & access”Authentication
Section titled “Authentication”- End users authenticate to the web UI; the backend issues signed tokens (
NEXA_AUTH_JWT_SECRET,NEXA_AUTH_TOKEN_TTL_SECONDS) and can federate to your data platform’s SSO (e.g. the Databricks OAuth callback). Auth enforcement is controlled byNEXA_AUTH_ENABLED— keep ittrue. - Service-to-service calls carry a shared
NEXA_SERVICE_AUTH_TOKEN. ANEXA_SERVICE_AUTH_TOKEN_PREVIOUSslot allows zero-downtime rotation (both accepted during a rollout). - Data-platform access uses OAuth service-principal credentials (Databricks client id/secret, or the Snowflake equivalent) stored as secrets — no interactive credentials in the platform.
Authorization & RBAC
Section titled “Authorization & RBAC”- Cloud/AWS: pods get AWS permissions through EKS Pod Identity (not static keys, not IRSA). Each service has its own ServiceAccount mapped to an IAM role scoped to only the secrets it needs. Cluster add-ons (EBS CSI, Secrets Store CSI, cert-manager, ArgoCD Image Updater) each have their own least-privilege role.
- Kubernetes: one namespace per service per environment (
<service>-<env>) isolates workloads. The reference deployment relies on default namespace RBAC plus per-service ServiceAccounts; it does not ship custom app-levelRole/RoleBindingobjects, so restrict humankubectlaccess with your own cluster RBAC. - Data platform: governance (business glossary, PII tagging, change review) is enforced inside Nexa on top of your warehouse’s native grants — Nexa does not replace Snowflake/Unity Catalog permissions.
Secret storage & rotation
Section titled “Secret storage & rotation”- Secrets are held in AWS Secrets Manager and mounted into pods by the Secrets Store CSI driver, optionally synced to a Kubernetes
SecretforenvFrom. Terraform creates secret containers empty; values are populated out-of-band so they never land in Terraform state. - Deletion is protected by a recovery window (default 7 days).
- Rotation is operator-driven: update the value in Secrets Manager, reconcile the CSI-synced secret, and roll the consuming Deployments. Full steps are in the operations guide.
- The Secrets Store CSI driver’s role is broad by design (read across account secrets). If you need tighter isolation, scope it to a secret-name prefix.
Network
Section titled “Network”Nexa runs in a dedicated VPC per environment with public and private subnets. Ingress is handled by Envoy Gateway (Kubernetes Gateway API) fronted by a cloud load balancer; TLS certificates are issued and renewed by cert-manager.
Ingress & TLS
Section titled “Ingress & TLS”- The
nexa-gateway(namespaceenvoy-gateway-system) provisions a network load balancer and listens on:443(TLS terminate) and:80(redirect to HTTPS). - Certificates are Let’s Encrypt wildcards issued by cert-manager over the DNS-01 challenge (no inbound HTTP-01 needed), authenticated to the DNS provider by Pod Identity — no DNS API keys are stored. Certs auto-renew (
rotationPolicy: Always,renewBefore30 days). - Envoy
SecurityPolicyapplies a per-route IP allowlist (default-deny with explicit CIDRs) and CORS; aBackendTrafficPolicyapplies rate limiting keyed on the client IP. The web route also drops known scanner paths (/.env,/.git,/wp-, etc.) with a direct 403.
Egress
Section titled “Egress”Outbound traffic from private subnets flows through a NAT gateway. Nexa’s egress targets are your data platform, configured AI model endpoints, your Git host, container registry pulls, and Let’s Encrypt/DNS for certificates. Restrict egress to those destinations if your policy requires an allowlist.
Cloud-specific network controls
Section titled “Cloud-specific network controls”- VPC: dedicated per environment (default
10.0.0.0/16), two public and two private/24subnets across two AZs. - Load balancer: an AWS NLB provisioned by Envoy Gateway via the AWS Load Balancer Controller.
- Database SG: Postgres (5432) is reachable only from the VPC CIDR plus any explicit
rds_allowed_cidr_blocks. - NAT: a single NAT gateway by default (not per-AZ) — add per-AZ NATs for HA.
Harden before production (the reference IaC does not do these):
- The EKS API endpoint has both public and private access with no CIDR allowlist — restrict
public_access_cidrsor go private-only. - There are no VPC endpoints — add interface/gateway endpoints (S3, ECR, Secrets Manager, STS, SSM) to keep AWS API traffic off the internet.
- There is no WAF on the load balancer — attach AWS WAF if you need L7 filtering beyond the Envoy allowlist.
- RDS Multi-AZ is off and dev allows public accessibility — enable Multi-AZ and set
rds_publicly_accessible = falsefor production.
On Azure, the same architecture maps to AKS in a dedicated VNet with private/public subnets, an Azure Load Balancer (or Application Gateway) in front of Envoy Gateway, Azure Database for PostgreSQL, and secrets in Azure Key Vault via the CSI driver, with workload identity in place of Pod Identity. Apply the equivalent hardening: restrict the AKS API server (authorized IP ranges or private cluster), use Private Endpoints/Private Link for PostgreSQL, Key Vault, and the registry, and place a WAF (Application Gateway/Front Door) at the edge. Configure the concrete resource names during installation.
Compliance & hardening
Section titled “Compliance & hardening”Container-level defaults already in place: containers run with allowPrivilegeEscalation: false, all Linux capabilities dropped, and most services run as a non-root user. Audit logging is on (EKS control-plane logs and Postgres logs to CloudWatch).
Recommended before a production sign-off:
| Area | Default | Recommended action |
|---|---|---|
| Keys | AWS-managed | Use customer-managed KMS keys with rotation for RDS, S3, Secrets |
| RDS in-transit | force_ssl off (dev) |
Require TLS on every DB connection |
| RDS availability | Single-AZ, public in dev | Multi-AZ, private-only, longer backup retention |
| EKS API endpoint | Public, no allowlist | Restrict CIDRs or make the endpoint private |
| AWS API traffic | Over NAT/internet | Add VPC endpoints for S3/ECR/Secrets/STS/SSM |
| Edge filtering | Envoy IP allowlist + rate limit | Add a managed WAF |
| Cluster RBAC | Default namespace RBAC | Add least-privilege human access roles |
| East-west traffic | Cluster network, no mTLS | Add a service mesh if mTLS is required |
For the exact variable names and defaults behind these, see the configuration reference; for the topology, see the reference architecture.