Security

An overview of Prisma’s security concept: how the Zabbix root account is protected, which Zabbix API methods Prisma is allowed to call, and the cryptography, access control and network protections behind the platform.

This page explains how Prisma protects your data and your Zabbix server. The design follows a handful of common security practices. No single control is trusted on its own, every account and API surface is limited to what it actually needs, and the whole platform is written in memory-safe languages. The sections below describe the individual measures.

The Zabbix super-admin (root) account

To integrate a Zabbix server, Prisma stores one super-admin account for that server, referred to as the root account. Prisma needs it because several features perform provisioning or synchronization work that only a Zabbix administrator is allowed to do:

  • Creating and maintaining the service users and API tokens that Reporting and AI use to read data for each user group.
  • Creating and updating Zabbix user groups on your server.
  • Keeping Prisma’s copy of your users and user groups in sync.

Because the root account is powerful, its use is restricted in a few ways. End users never see it and never act as it; only the server itself uses it, and only for the operations listed above. A root session can reach only a small, fixed set of Zabbix API methods (see Permitted Zabbix API methods), so even with these credentials Prisma cannot be turned into a general purpose gateway to your Zabbix API. The credentials are also encrypted before they are stored and are never handed back to a client, as described in the next section.

The root account is configured when adding a Zabbix server. It can be a username and password pair or an API token. We recommend using an API token. A token can be revoked in Zabbix at any time without changing the account's password, and it keeps the password itself out of Prisma.

Encryption of secrets at rest

Prisma holds a number of secrets on your behalf, including the credentials for your Zabbix server. All of them are encrypted before they are written to the database. The point of this is that a copy of the database on its own is worthless. If an attacker manages to read the stored data, for example through an SQL injection flaw, a stolen backup, or direct access to the underlying storage, the encrypted fields stay unreadable, because the key needed to decrypt them is never kept in the database.

The following secrets are protected this way:

  • The Zabbix root account secret.
  • The service user secret for each user group.
  • Each user’s Zabbix API token and support token.
  • The S3 secret key used for report and AI object storage.
  • Secrets that are part of media or notification settings, such as SMTP passwords.

How it works

Sensitive fields are encrypted with AES-256-GCM, which is an authenticated cipher, and stored as binary columns in PostgreSQL. Each record is encrypted with its own key, which is derived from two parts: a master key and a random key component that is unique to each record. This key fragment is is stored alongside the record, but the master key is not. The operator supplies the master key to the services at startup, and it is never written to the database, so a database dump never contains the material needed to decrypt the secrets it holds. Because every record uses a different key, recovering one secret does not help an attacker with any of the others.

A second, separate safeguard protects the API rather than the database. Encrypted fields are masked in every response: instead of the secret, the API returns a placeholder (••••••••). A secret can be set through the API, but it can never be read back out of it.

The master key protects every stored secret. Keep it safe, provide it only through your secret management tooling, and never put it in configuration files or version control.

Permitted Zabbix API methods

Prisma can forward Zabbix API calls on your behalf, but it does not give unrestricted access to the Zabbix API. Every forwarded call is checked against an allowlist of method names. If a method is not on the list, the call is refused, even if the underlying Zabbix account would be allowed to make it.

The allowlist is split into three separate scopes, one for each way Prisma talks to Zabbix. A scope only contains the methods that it actually uses.

1. User calls

These calls run against the signed-in user’s own Zabbix session, so the user’s own Zabbix permissions apply on top of the allowlist. This scope backs the Zabbix client. It is the broadest of the three, but it is still almost entirely read-only:

Method Type
host.get Read-only
item.get Read-only
hostgroup.get Read-only
sla.get Read-only
trigger.get Read-only
problem.get Read-only
event.get Read-only
graph.get Read-only
service.get Read-only
user.get Read-only
script.get Read-only
history.get Read-only
trend.get Read-only
mediatype.get Read-only
proxy.get Read-only
template.get Read-only
usermacro.get Read-only
sla.getsli Read-only
apiinfo.version Read-only
sla.update Modifying
event.acknowledge Modifying
script.execute Modifying

2. Service user and user group calls

These calls run through a user group’s service user and are used by Reporting and AI to collect data. This scope is read-only:

Method Type
host.get Read-only
item.get Read-only
hostgroup.get Read-only
sla.get Read-only
service.get Read-only
mediatype.get Read-only
trend.get Read-only
history.get Read-only
user.get Read-only
usergroup.get Read-only

3. Root and super-admin calls

These calls use the root account for the administrative tasks described above. This is the most privileged scope, and it is also the smallest. It is limited to the user, user group and role management that Prisma actually performs:

Method Type
user.get Read-only
usergroup.get Read-only
role.get Read-only
usergroup.create Modifying
usergroup.update Modifying

Authentication and identity

Prisma has two kinds of identity. Managers are Prisma’s own administrative accounts, and users are accounts backed by an integrated Zabbix server. Signing in works in several ways:

  • Local login is used for managers and is verified against a password hash that Prisma stores. Rather than sending the password itself, the browser first runs it through PBKDF2-HMAC-SHA512 and transmits only the derived value, so the plaintext password never travels over the network.
  • LDAP login authenticates managers against a directory using an LDAP bind, with optional StartTLS at a minimum of TLS 1.2 and certificate authority verification.
  • Zabbix-backed login authenticates users against their aliased Zabbix server, and Prisma maps the Zabbix identity to a local user.
  • Headless login uses a static per-manager API token for automated access.

Password hashing

Local manager passwords are hashed twice: once on the client with PBKDF2-HMAC-SHA512 and a second time on the server with Argon2id, a memory-hard algorithm that resists side-channel and brute-force attacks, using a fresh random salt for every hash.

Sessions

Sessions are stateless JSON Web Tokens, signed with HMAC-SHA-256.

  • A token carries a fixed issuer and audience and has a limited lifetime, one hour by default. There is no long-lived refresh token. Instead, the frontend keeps the account credentials in encrypted local storage and quietly requests a new token when the current one expires, so the user stays signed in without having to log in again.
  • Verification rejects any token that is not signed with the expected HMAC method, which blocks algorithm-confusion attacks.
  • A manager can revoke all of their current sessions at once. Tokens issued before that point are then refused, even though the tokens themselves are stateless.
  • The token is sent as a bearer token in the Authorization header. In the browser it is kept in IndexedDB. The account secret stored alongside it is encrypted first, which makes it somewhat harder for someone with access to a signed-in device to extract the credentials from local storage.

Authorization: access control and multi-tenancy

Authentication decides who you are. What you are allowed to do is decided by two further layers.

Role-based access control

Every account has a role. A role is either one of the shared default roles or a custom role defined by an organization. Its access control list combines two things:

  • Permissions to create, read, update and delete each type of resource.
  • Capability flags for broad privileges that are not tied to a single resource type, such as impersonation, assigning roles, or making Zabbix and Zabbix root calls.

Roles are enforced on every model operation. Granting is subset-checked, which means a role can never hand out a permission that it does not hold itself. This prevents privilege escalation through role assignment.

Tenant isolation

Prisma is multi-tenant. Organizations are arranged in a hierarchy, and access is limited to an organization’s own subtree by row-level filtering that is applied to every query. Each request therefore answers two questions at once: whether the action is allowed at all, and which rows it may touch. The access control list answers the first, and the scope answers the second.

Transport security (TLS)

All of the externally reachable listeners can be served over TLS. This covers the gRPC, gRPC-Web, REST gateway and push endpoints. Outbound connections to PostgreSQL, Zabbix, LDAP and SMTP support TLS as well. The minimum accepted version is TLS 1.2. The only plaintext hop is the loopback connection between the REST gateway and the gRPC server, which never leaves the host.

Terminating TLS directly in Prisma is not the only option. It is equally valid to put a TLS offloading proxy in front of the services and let it handle TLS, as long as the connection between that proxy and Prisma runs over a trusted network.

Messaging security (NSQ)

Internal services talk to each other over NSQ. Prisma runs a dedicated authorization server for it. Each service authenticates with its own pre-shared secret, and every secret is limited to the specific topics and remote calls that the service uses. If one service’s secret leaks, it cannot be used to act as another service. The NSQ transport can also be secured with TLS.

SQL injection

All database access goes through GORM using parameterized queries. User-provided values are passed as bound parameters and are never concatenated into SQL statements, which is what guards against SQL injection.

Web security

In the frontend, Angular escapes interpolated values by default, which prevents most cross-site scripting on its own. The DomSanitizer is only ever used to clean content, and Angular’s built-in protection is never bypassed to inject raw HTML.

Cross-origin access is controlled by a configurable allowlist of permitted origins. Prisma sets the full set of CORS response headers for each request, covering the allowed origin, methods and headers as well as the preflight cache duration, and it only reflects an origin back to the browser when that origin is on the allowlist.

To prevent cross-site request forgery (CSRF), Prisma authenticates with a bearer token in the Authorization header instead of an ambient session cookie. Because the browser does not attach that token automatically to cross-site requests, the classic cookie-based CSRF attack does not apply.

Memory-safe implementation

The platform is written in memory-safe languages. The backend services are written in Go and are compiled as static binaries with CGO disabled for the core services. The frontend is written in TypeScript with Angular. This rules out whole categories of memory-corruption bugs. As an exception, the Prisma AI microservices link to the native TensorFlow library to run models.