Security hardening

The security settings of the reference root, and what to tighten for production.

This page lists what the reference root already does, and the settings to review before production.

What the root already does#

  • One service account per role. role_service_accounts names one account for each role, and there is no shared account. Each role trusts only the roles that call it: the root grants run.invoker call by call, and the services also check the caller's identity token against their list of trusted accounts.
  • Secrets in Secret Manager. The core module creates the database password and the signing keys as Secret Manager secrets. The backend's account reads them; tool credentials, such as the Sifflet and Castor tokens, live there too. Never put a secret in a tfvars file or in role_extra_env_vars. Use role_extra_secret_volumes instead.
  • The database. Connections must be encrypted (ssl_mode = ENCRYPTED_ONLY), IAM database authentication is on, and no network is authorised: every connection goes through the Cloud SQL connector or a private IP.
  • The image. It runs as a non-root user (nistor, uid 10001), starts from a base image pinned by digest, and checks itself at build time (nistor dist verify --installed). The build refuses third-party packages under a denied licence.
  • Startup checks. A backend on Cloud Run refuses to start without BOOTSTRAP_ADMIN_EMAIL. In test and prod it also refuses to start without AUTO_REGISTER_EMAIL_DOMAINS. See Identity and access.

Review before production#

Setting Default Production
trust_iap_header_fallback true false, once the backend logs show verified IAP assertions on all browser traffic
auto_register_email_domains empty Your organisation's domains only
cloud_sql_public_ip_enabled true false where possible. This needs db_private_network, and the services connect over the VPC (db_connect_via_private_ip, vpc_network, vpc_subnetwork)
vpc_egress ALL_TRAFFIC Keep it, or PRIVATE_RANGES_ONLY if outbound calls to tool APIs must not go through the VPC
IAP access — Grant roles/iap.httpsResourceAccessor to groups, not to individuals
ci_cd_service_account_email empty The install pipeline's account. It gets read-only health access, not administrator rights
backend_extra_trusted_service_accounts empty Keep it empty in production. Every account listed there is trusted like a role

Network#

The backend's Cloud Run ingress is INGRESS_TRAFFIC_ALL, so that the web shell's server and CI jobs in other projects can reach it. What protects it is IAM: only the accounts granted run.invoker can call it, and the backend checks their identity tokens. Do not grant run.invoker on any service to allUsers or allAuthenticatedUsers.

Encryption keys#

Cloud SQL, Cloud Storage and Secret Manager use Google-managed encryption keys. The reference root has no input for customer-managed encryption keys (CMEK) in 1.0.

Edit this page on GitLab

↑ ↓ to moveEnter to openEsc to close