brainstate

nais/device · source

Snapshot 0 · 2026-11-04T12:47:26Z · Go · MIT

Content fingerprintcdfa040c598845434dea1a77bd89910c1a3517d21cb3fa333d0a76d7911a191f

GitHub description at capture

naisdevice is a application suite that enables Nais developers to connect to internal resources in a secure and friendly manner.

README at capture

# Naisdevice

naisdevice is a mechanism enabling NAVs developers to connect to internal resources in a secure and friendly manner.

## Contributing

### Linux requirements

- build-essential
- ruby
- ruby-dev rubygems
- imagemagick
- fpm (ruby gem)

### Deploying client changes

Executing `mise run release-frontend` is required for deploy of new naisdevice client to be released and made available for download/install/update.

## Concept

Each resource is _protected_ by a gateway, and the developer is only granted access to the gateway if all of the following requirements are met:

- Has a valid account
- Has accepted naisdevice terms and conditions (from within the app)
- Device is [healthy](#what-is-a-healthy-device)
- Is member of the AAD access group for the gateway (e.g. to connect to team A's DB (via gateway), you must be member of team A's AAD-group)

### Key attributes

- minimal attack surface
- instantly reacting to relevant security events
- improved auditlogs: who connected when and to what
- moving away from traditional device management enables building a strong security culture through educating our users on client security instead of automatically configuring their computers

### Components

#### Apiserver

The `apiserver` component serves as the gRPC API server, responsible for handling various configurations and managing communication with other agents. Its primary functionalities include:

- Serving the gRPC API.
- Distributing configurations to the following agents:
  - [device-agent](#device-agent)
  - [gateway-agent](#gateway-agent)
  - [prometheus-agent](#prometheus-agent)
- Retrieving device health status from the `nais/kolide-event-handler`.

### Run API server locally

```Shell
# Create a sqlite database file with a mock device
go run ./hack/local-device.go
# Start apiserver
go run ./cmd/apiserver

## Run device agent with access to your local apiserver
go run ./cmd/naisdevice-agent --local-apiserver
```

## Gateway-agent

The `gateway-agent` runs on virtual machines (VMs) and interacts with the `apiserver` to receive and apply configurations. Key features of the `gateway-agent` include:

- Streaming configurations from the `apiserver`.
- Dynamic setup of:
  - WireGuard for communication from devices.
  - iptables for forwarding traffic.

## Auth-server

The `auth-server` operates in a cloud run environment and plays a crucial role in user authentication. Its functionalities include:

- Authenticating users.
- Issuing tokens to devices for secure communication.

## Enroller

The `enroller` is deployed on Cloud Run and is responsible for managing the enrollment process for both gateways and devices.

- Handling the enrollment of gateways and devices securely.

## Device-helper

The `device-helper` serves as the gRPC API for the `device-agent` and performs essential setup tasks for devices. Key functionalities include:

- Providing a gRPC API for the `device-agent`.
- Reading device serial information.
- Configuring network interfaces, routes, and WireGuard for secure communication.

## Device-agent

The `device-agent` is a crucial component responsible for managing device configurations and facilitating communication with the `apiserver`. Its main features include:

- Streaming configurations from the `apiserver`.
- Delegating configuration tasks to the `device-helper` via its gRPC API.
- Serving status updates through its gRPC API to the CLI/systray.
- Executing the authentication flow to obtain user tokens.

### Agent status file

The device-agent writes `agent-status.json` to its config directory, next to `agent-config.json`, for callers that cannot reach the gRPC socket. A sandboxed process may be allowed to read the config directory but not to open a unix socket. Everything that can use the gRPC API should use that instead.

```json
{
  "connectionState": "Connected",
  "tenant": "NAV",
  "updatedAt": "2026-09-15T21:00:00+02:00",
  "heartbeatSeconds": 30,
  "warning": "best effort, may be missing or stale, format may change, may be removed at any time, do not depend on it"
}
```

The file is written at startup before the first transition, on every state change, and every `heartbeatSeconds` in between. The agent removes it when it shuts down cleanly, but that is not guaranteed: a crash, a kill, or a lost race on the way out all leave it behind. Presence means the agent got this far, never that it is running now. That is what `updatedAt` and `heartbeatSeconds` are for:

- `updatedAt` within a few times `heartbeatSeconds`: the state as of `updatedAt`.
- `updatedAt` older than that: the agent is gone or stuck, so `connectionState` cannot be trusted.
- No file: the agent has not run, or it could not write.

This is best effort and not an interface we maintain. It can be missing or stale, the format can change, and it can be removed at any time. Do not build anything you care about on it.

## Systray

The `systray` component acts as a graphical user interface (GUI) for the `agent`, utilizing its gRPC API. It provides a convenient way for users to interact with and monitor the agent's status.

## Controlplane-cli

The `controlplane-cli` serves as an administrative command-line interface (CLI) interacting with the `apiserver` through its gRPC API. This CLI is designed for administrative tasks and configurations.

## Prometheus-agent

The `prometheus-agent` component connects to all gateways over WireGuard and configures Prometheus (deployed on the same VM) to scrape relevant metrics.

- Establishing connections to gateways using WireGuard.
- Configuring Prometheus to scrape metrics from connected gateways.

## FAQ

### How to install

See https://doc.nais.io/operate/naisdevice/how-to/install/

## Stuff we use

[Kolide](https://www.kolide.com/)

[WireGuard](https://www.wireguard.com)