Aranya consists of two main subsystems which can be found in different Github repositories:
The Aranya Core library (located in aranya-core repo), which provides the fundamental building blocks for maintaining and synchronizing state, parsing and enforcing the policy, and managing cryptographic operations
The Aranya Daemon (see aranya repo), a long-running service that sets up the dependencies and runs an Aranya instance, exposes Aranya Core functionality through APIs, and manages peer communication and secure data exchange.
Together, these subsystems create a robust framework for implementing fine-grained access control and secure data sharing across distributed systems.
An overview of the components that make up an Aranya instance can be seen in Figure 1 below. The following sections will describe the individual pieces in greater detail.
Figure 1: System Architecture Overview Diagram
The Aranya Client provides an API to be integrated into user applications and submits requests to the Aranya daemon for processing. The client is currently available in Rust and C, and consists of APIs for performing or exchanging policy operations (Figure 1, Generic Actions/ Effects and Sync Transport APIs) and a set of APIs to send and receive data or compute new channel keys (Channel Transport APIs in Figure 1).
This API mirrors the default policy and can be customized to any user application. Some functionality provided by the default policy includes:
The “policy” is a pre-defined markdown file, written in a domain specific language, that contains all the business logic for devices to interact with the graph. The policy defines the set of roles/attributes and permissions which make up the authority model.
The policy document is used to configure the Policy Engine. The Policy Engine is responsible for evaluating and executing Policy decisions and interactions with the storage module according to the set of roles/attributes and permissions contained in the Policy which make up the authority model that determines which devices can execute certain operations.
See the default policy for an example of how roles, permissions and actions may be set-up.
The Aranya Daemon is a long-running executable that uses the pre-defined policy and core functionality to process actions invoked by a client. The daemon maintains state, peer syncing and generating and managing cryptographic material for the user application. Client libraries interact with the daemon through the Daemon API. The Daemon API is not intended to be a public or stable API, the client libraries are the intended APIs for applications to consume.
Aranya QUIC Channels (AQC) are high throughput, low latency network channels for exchanging data between endpoints. AQC uses a QUIC library with Pre-shared Keys (PSKs) supplied by Aranya. This approach extends authority from Aranya to the QUIC library and ensures nodes can only create channels with authorized peers.
For reusability and flexibility, the core components of Aranya have been split out into individual creates. Aranya is an implementation against these core components that provides a policy and integration against the Aranya-core crates. Several Aranya-Core components are configurable and can be swapped (or their implementation swapped): Storage, Sync, Cryptography, FFIs, and the Policy.
The Aranya Runtime connects your application to the core Aranya library and all other external components together to pass data and instructions. It provides the higher-level interfaces to configure the Policy Engine, Storage Provider, and Sync strategy to create Clients. Once the Runtime is fully configured, its general API consists of adding Clients, Graphs, issuing Actions, receiving Effects, and syncing with other Client Graphs.
A foreign function interface (FFI) gives the ability to bring more complex functionality that may otherwise be impossible to represent in the policy language. Examples of FFIs may be cryptographic functions (e.g., for signing or encrypting), Identity and access management (IDAM) functionality, or custom data structures. FFIs are custom built to fill the need of any missing functionality, the Aranya library supplies some common FFIs but the end user is completely open to write and utilize their own as FFIs are completely configurable in the Aranya runtime. FFIs are invoked on every node during policy evaluation, so FFIs must be used very carefully if acceptance of a command depends on their output. An improperly implemented FFI could cause a deadlock in the policy if attention is not paid to ensure other devices can validate a command.
The Crypto Module is used to perform all cryptographic functions without exposing sensitive material outside its domain. It implements a set of APIs that are responsible for encryption/decryption and authentication keys within the runtime. The system leverages a set of cryptographic protocols where the underlying algorithms are configurable up to NIST standard requirements for security. This component is also fully configurable and Aranya provides a default implementation.
The Crypto Engine is initialized using the Key Store. This store is configured at setup and is used to generate and store cryptographic keys securely. If using the daemon, the key store is set-up automatically. The Key Store can be configured in any way, but be aware that it will be used to hold sensitive cryptographic material. For extra security, consider using a TPM of HSM like in this example from the Aranya crypto module.
Syncing in Aranya is configured using the Sync Engine. A user can utilize the provided QUIC protocol syncer or supply their own implementation built on top of the Runtime Sync API. The QUIC syncer module provides a batteries-included implementation for syncing using the QUIC transport protocol. The Runtime Sync API provides a set of lower-level building blocks for syncing in Aranya, if a user wishes to use these APIs, however they will then need to implement their own transport layer.
The Policy VM executes the policy and connects it to the cryptographic module. It takes a compiled policy and evaluates commands to perform policy decisions, such as persisting data to the graph or factDB or returning effects.
The Aranya storage module is responsible for storing data related to executed operations that have been validated and persisted to the Graph (i.e., commands) or FactDB (facts). The Aranya runtime can use multiple different storage implementations, also known as storage providers. Aranya includes a linear file backed storage, a memory backed storage, and a linear memory storage.
Linear storage is a graph storage implementation backed by a file-like byte storage interface. This is designed to be usable across many environments with minimal assumptions on the underlying storage.
Memory storage and linear memory storage are in-memory graph storage implementations mainly used for testing, as no data is saved between each run. They can also be used in situations where data is designed to not be persisted, such as one time authentication, key exchanges, or cross team communication.