# Network Identity Attestor reference

> Information and reference for Aembit Edge's Network Identity Attestor (NIA) component in virtual environments

## System requirements

To run Network Identity Attestor you must have the following:

* **Operating System**: Ubuntu 24.04 or later.
* **Root Privileges**: Execute the installation with the `root` user or equivalent privileges.

## Certificate requirements

### Attestation signing certificate

The attestation signing certificate has specific requirements that differ from standard TLS certificates:

* **Key type**: Must be an RSA key pair (ECDSA and Ed25519 aren’t supported in the initial release)
* **Key usage**: Must support digital signatures
* **CA constraint**: Must NOT be a Certificate Authority (CA) certificate
* **Chain**: Single certificate only (no chain required)
* **Common Name**: Doesn’t need to match a DNS name
* **Subject Alternative Name (SAN)**: Not required

### TLS certificate

The TLS certificate functions like a standard TLS certificate:

* **Common Name (CN)**: Required, should match the NIA hostname
* **Subject Alternative Name (SAN)**: Required
* **Chain**: Full certificate chain required (leaf certificate first, followed by intermediates)

## Environment variables

The following are environment variables associated with setting up Network Identity Attestor:

#### `TLS_PEM_PATH` Required

Default - not set

OS-Linux

Path to the TLS certificate file (PEM format) used for HTTPS connections.

You must manually provide a valid TLS certificate file on the NIA VM. The installer copies this file to a secure location; it doesn’t generate the certificate for you. After installation, you may remove the original file.

*Example*:\
`/tmp/tls.crt`

***

#### `TLS_KEY_PATH` Required

Default - not set

OS-Linux

Path to the TLS private key file (PEM format) corresponding to the certificate you set in the `TLS_PEM_PATH` variable. The Network Identity Attestor installer uses `systemd-creds` to copy and encrypt sensitive values from environment variables to a secure systemd-managed location. This ensures secrets are never stored in plain text and are only accessible to the attestor service at runtime.

*Example*:\
`/tmp/tls.key`

***

#### `AEMBIT_ATTESTATION_SIGNING_KEY_PATH` Required

Default - not set

OS-Linux

The private key used for signing attestation documents.

*Example*:\
`/tmp/signing.key`

***

#### `AEMBIT_ATTESTATION_SIGNING_CERTIFICATE_PATH` Required

Default - not set

OS-Linux

The path to the attestation signing certificate. This is the certificate corresponding to the signing key set as the value for `AEMBIT_ATTESTATION_SIGNING_KEY_PATH`.

*Example*:\
`/tmp/signing.crt`

***

#### `AEMBIT_VCENTER_URL` Required

Default - not set

OS-Linux

The URL to the vCenter server. This is the endpoint the Network Identity Attestor uses to communicate with vCenter.

*Example*:\
`https://vcenter.example.com`

***

#### `AEMBIT_VCENTER_CREDENTIALS_FILE`

Default - not set (installer prompts for credentials)

OS-Linux

The path to the vCenter credentials file. The file should contain credentials in the format `username:password`. If not provided, the installer prompts for credentials during installation. The service uses this file to authenticate with the vCenter database.

*Example*:\
`/tmp/vcenter_credentials`

***

#### `AEMBIT_VCENTER_HTTP_CACHE_EXPIRATION_SECS`

Default - `30`

OS-Linux

The number of seconds the NIA caches vCenter API responses before discarding them. Set to `0` to turn off caching (useful for debugging).

*Example*:\
`60`

***

#### `AEMBIT_VCENTER_SESSION_TIMEOUT_SECS`

Default - `1800`

OS-Linux

The number of seconds before the NIA’s vCenter API session expires and the NIA must refresh it.

*Example*:\
`3600`

***

#### `AEMBIT_VCENTER_SESSION_REFRESH_SECS`

Default - `60`

OS-Linux

The number of seconds between checks of the NIA’s vCenter API session. If 80% of the session lifetime set by `AEMBIT_VCENTER_SESSION_TIMEOUT_SECS` has elapsed, the NIA refreshes the session. After a failed refresh, the NIA retries every second until it succeeds.

*Example*:\
`120`

***

#### `AEMBIT_VCENTER_HTTP_TIMEOUT_SECS`

Default - `5`

OS-Linux

The number of seconds the NIA waits for a response from the vCenter API before timing out.

*Example*:\
`10`

***

#### `AEMBIT_LOG_LEVEL`

Default - `info`

OS-Linux

The service log level. Controls the verbosity of logs. Typical values: `debug`, `info`, `warn`, `error`.

*Example*:\
`debug`

***

#### `AEMBIT_NETID_LISTENER_IP`

Default - `0.0.0.0`

OS-Linux

Specifies the IP address that the Network Identity Attestor binds to and listen for incoming connections.

By setting this variable, you can restrict the NIA to listen only on a specific network interface. This is useful in environments with multiple Network Interface Cards (NICs). For example, VMware VMs with more than one network segment can benefit from this setting. To make Network Identity Attestor reachable from a particular subnet or network only, set this to the desired IP address assigned to the relevant NIC.

> **Operational Note**
>
> This helps ensure the attestor is only accessible from intended workload VMs or network segments. This improves security and network segmentation.

*Example*:\
`192.168.1.100`

***

#### `AEMBIT_NETID_LISTENER_PORT`

Default - `443`

OS-Linux

Specifies the TCP port that the Network Identity Attestor service listens on for incoming HTTPS connections.

Change this if you need the service to listen on a non-standard port. For example, you might want to avoid conflicts or comply with network policies.

*Example*:\
`8443`

> **Operational Note**
>
> If you change the port, update firewall rules and client configurations accordingly.

***

#### `AEMBIT_LOG_NAMESPACE`

Default - `aembit_netid_attestor`

OS-Linux

Specifies the namespace under which systemd’s `journald` logging system records logs from the Network Identity Attestor service.

By default, journald groups all logs from the Network Identity Attestor under the `aembit_netid_attestor` namespace. If you set `AEMBIT_LOG_NAMESPACE` to a custom value, journald records logs under that custom namespace instead. This is useful if you run multiple instances of the attestor on the same host. It also helps if you want to segregate logs for easier searching and analysis.

> **Operational Note**
>
> View logs for your namespace with:
>
> ```shell
> # The default namespace
> journalctl --namespace=aembit_netid_attestor
> # Your custom namespace
> journalctl --namespace=<your_namespace>
> ```

*Example*:\
`my_custom_namespace`

***

#### `AEMBIT_METRICS_ENABLED`

Default - `false`

OS-Linux

Enables the Prometheus-compatible metrics endpoint. When enabled, the Network Identity Attestor exposes metrics on a separate HTTP port (default `9099`). When off, the metrics port doesn’t listen and refuses connections.

Accepts the values `true`, `false`, `1`, `0`, `yes`, `no`.

You can also enable metrics at install time by setting this variable before running the installer. The installer bakes the value into the systemd unit configuration.

*Example*:\
`true`

***

#### `AEMBIT_METRICS_PORT`

Default - `9099`

OS-Linux

The port where the Prometheus-compatible metrics endpoint listens. This port serves plain HTTP (not HTTPS) and is separate from the main API port.

*Example*:\
`9100`

## Subcommands

The `aembit_netid_attestor` binary includes the following subcommands for credential management.

### `rotate-signing-credentials`

Rotates the attestation signing certificate and key without modifying other NIA credentials. You must restart the service after running this subcommand.

```shell
sudo aembit_netid_attestor rotate-signing-credentials \
  --signing-key-path <SIGNING_KEY_PATH> \
  --signing-cert-path <SIGNING_CERT_PATH>
```

| Option                | Required | Description                                                                                                    |
| --------------------- | -------- | -------------------------------------------------------------------------------------------------------------- |
| `--signing-key-path`  | Yes      | Path to the private key PEM file (unencrypted PKCS8 format)                                                    |
| `--signing-cert-path` | Yes      | Path to the signing certificate PEM file                                                                       |
| `--log-level`         | No       | Log level for this command’s output. Default: `info`. Values: `off`, `trace`, `debug`, `info`, `warn`, `error` |

The subcommand validates the certificate and key pair, displays certificate metadata for operator review, encrypts the new credentials using `systemd-creds`, and updates the drop-in configuration file at `/etc/systemd/system/aembit_netid_attestor.service.d/50-credentials.conf`. Rather than deleting previous credentials, the subcommand comments them out, which allows rollback without re-running it.

Both options also accept the corresponding environment variables (`AEMBIT_ATTESTATION_SIGNING_KEY_PATH` and `AEMBIT_ATTESTATION_SIGNING_CERTIFICATE_PATH`) as alternatives to the command-line flags.

For step-by-step rotation instructions, see [Rotating NIA Credentials](/user-guide/deploy-install/virtual-envs/rotate-nia-credentials).

## Health endpoint

The Network Identity Attestor exposes a `/health` endpoint for basic liveness checks.

| Property           | Value                                                                           |
| ------------------ | ------------------------------------------------------------------------------- |
| **Path**           | `/health`                                                                       |
| **Port**           | Same as main API (default `443`, configurable via `AEMBIT_NETID_LISTENER_PORT`) |
| **Protocol**       | HTTPS                                                                           |
| **Authentication** | None                                                                            |
| **Availability**   | Always enabled when the NIA service is running                                  |

The health endpoint returns a JSON response:

```json
{"status":"Healthy","version":"<build version>"}
```

When the NIA can’t communicate with the vCenter API (for example, due to an expired session or network issue), the response changes to:

```json
{"status":"Unhealthy","version":"<build version>"}
```

> **Note**
>
> The HTTP status code is always `200` regardless of health status. Check the `status` field in the JSON response body to determine whether the NIA is healthy.

For practical examples of using the health endpoint, see [Monitor Network Identity Attestor](/user-guide/deploy-install/virtual-envs/monitor-network-identity-attestor).

## Prometheus-compatible metrics

The Network Identity Attestor exposes Prometheus-compatible metrics on a separate HTTP endpoint. Metrics are off by default. To enable them, set `AEMBIT_METRICS_ENABLED=true`.

For instructions on enabling and scraping metrics, see [Monitor Network Identity Attestor](/user-guide/deploy-install/virtual-envs/monitor-network-identity-attestor).

| Property           | Value                                                   |
| ------------------ | ------------------------------------------------------- |
| **Path**           | `/metrics`                                              |
| **Port**           | Default `9099` (configurable via `AEMBIT_METRICS_PORT`) |
| **Protocol**       | HTTP                                                    |
| **Authentication** | None                                                    |
| **Format**         | Prometheus text exposition format                       |

The Network Identity Attestor exposes eight metrics, grouped by the subsystem that emits them. Each metric lists its type, labels, and example [PromQL](https://prometheus.io/docs/prometheus/latest/querying/basics/) queries.

Both histogram metrics (`vcenter_api_request_duration_seconds` and `node_lookup_duration_seconds`) use the same buckets, measured in seconds: `0.005`, `0.01`, `0.025`, `0.05`, `0.1`, `0.25`, `0.5`, `1`, `2.5`, `5`, and `10`.

### HTTP layer

#### `request_count_total`

**Counter.** Total HTTP requests handled, labeled by `endpoint`, `method`, and `status`.

```plaintext
sum(rate(request_count_total[1m]))                 # overall requests per second
sum by(endpoint) (rate(request_count_total[1m]))   # requests per second, per endpoint
sum by(status) (rate(request_count_total[1m]))     # requests per second, per status code
```

#### `request_error_count_total`

**Counter.** HTTP error responses, labeled by `endpoint`, `method`, and `status`. A failed request increments both this counter and `request_count_total`.

```plaintext
sum(rate(request_error_count_total[5m])) / sum(rate(request_count_total[5m])) * 100   # error percentage
sum by(endpoint) (rate(request_error_count_total[1m]))                                # errors per second, per endpoint
```

#### `in_flight_requests_count`

**Gauge.** HTTP requests in progress. The NIA increments this gauge when a request starts and decrements it when the request completes.

```plaintext
in_flight_requests_count   # current in-flight requests
```

### vCenter backend

#### `vcenter_api_errors_count_total`

**Counter.** vCenter API calls that returned an error. The NIA increments this counter before it records call duration, so failed calls still appear in `vcenter_api_request_duration_seconds`.

```plaintext
rate(vcenter_api_errors_count_total[5m])   # vCenter API errors per second
```

#### `vcenter_api_request_duration_seconds`

**Histogram.** vCenter API call latency, labeled by `endpoint` and `status` (`Success` or `Failure`). Exposed as `_bucket`, `_count`, and `_sum` series.

```plaintext
histogram_quantile(0.50, sum by(le) (rate(vcenter_api_request_duration_seconds_bucket{status="Success"}[5m])))   # p50 latency
histogram_quantile(0.95, sum by(le) (rate(vcenter_api_request_duration_seconds_bucket{status="Success"}[5m])))   # p95 latency
histogram_quantile(0.99, sum by(le) (rate(vcenter_api_request_duration_seconds_bucket{status="Success"}[5m])))   # p99 latency
sum(rate(vcenter_api_request_duration_seconds_count{status="Success"}[5m])) / sum(rate(vcenter_api_request_duration_seconds_count[5m])) * 100   # success percentage
sum by(endpoint) (rate(vcenter_api_request_duration_seconds_count[1m]))   # call rate, per endpoint
```

#### `vcenter_session_refresh_count_total`

**Counter.** vCenter session refresh attempts, labeled by `status` (`Success` or `Failure`). A high failure rate typically points to a credential or connectivity problem.

```plaintext
sum by(status) (rate(vcenter_session_refresh_count_total[5m]))   # refresh rate by outcome
sum(rate(vcenter_session_refresh_count_total{status="Failure"}[5m])) / sum(rate(vcenter_session_refresh_count_total[5m]))   # failure ratio
```

### Node lookup

#### `node_lookup_duration_seconds`

**Histogram.** Time to look up a VM node in the NIA’s node database, backed by vCenter. Exposed as `_bucket`, `_count`, and `_sum` series.

```plaintext
histogram_quantile(0.50, rate(node_lookup_duration_seconds_bucket[5m]))   # p50 lookup latency
histogram_quantile(0.95, rate(node_lookup_duration_seconds_bucket[5m]))   # p95 lookup latency
histogram_quantile(0.99, rate(node_lookup_duration_seconds_bucket[5m]))   # p99 lookup latency
rate(node_lookup_duration_seconds_count[1m])   # lookups per second
```

### Certificates

#### `certificate_time_to_expiry_seconds`

**Gauge.** Remaining validity of a certificate in seconds, labeled by `name`. The NIA refreshes this value hourly. A value of `0` means the certificate has expired.

```plaintext
certificate_time_to_expiry_seconds              # remaining validity for all certificates
certificate_time_to_expiry_seconds < 604800     # certificates expiring within 7 days
certificate_time_to_expiry_seconds < 2592000    # certificates expiring within 30 days
certificate_time_to_expiry_seconds / 86400      # remaining validity in days
```

### Alerting hints

The following conditions are starting points for your own Prometheus or Grafana alerting rules. Adapt the thresholds and time windows to your environment.

| Condition                       | PromQL                                                                                                               |
| ------------------------------- | -------------------------------------------------------------------------------------------------------------------- |
| Error rate over 5%              | `sum(rate(request_error_count_total[5m])) / sum(rate(request_count_total[5m])) * 100 > 5`                            |
| vCenter p99 latency over 2s     | `histogram_quantile(0.99, sum by(le) (rate(vcenter_api_request_duration_seconds_bucket{status="Success"}[5m]))) > 2` |
| Session refresh failing         | `rate(vcenter_session_refresh_count_total{status="Failure"}[5m]) > 0`                                                |
| Certificate expiry under 7 days | `certificate_time_to_expiry_seconds < 604800`                                                                        |