northstar-runtime 0.8.1

Northstar is an container runtime for Linux targetting embedded systems
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
# Northstar

![CI Status](https://img.shields.io/github/actions/workflow/status/esrlabs/northstar/ci.yml?branch=main)
[![Docs](https://img.shields.io/badge/docs-passing-brightgreen)](https://docs.rs/crate/northstar-runtime/latest)
![License](https://img.shields.io/github/license/esrlabs/northstar)
![Issues](https://img.shields.io/github/issues/esrlabs/northstar)
![Top Language](https://img.shields.io/github/languages/top/esrlabs/northstar)

Northstar is an embedded container runtime prototype for Linux.

![Demo](./doc/northstar.gif)

## Table of content

- [Northstar]#northstar
  - [Table of content]#table-of-content
  - [About]#about
    - [Containers]#containers
    - [Processes]#processes
    - [Comparison]#comparison
  - [Quickstart]#quickstart
  - [Configuration]#configuration
    - [Repositories]#repositories
  - [Console]#console
  - [Debugging]#debugging
  - [cargo-npk]#cargo-npk
  - [Integration tests]#integration-tests
  - [Integration]#integration
  - [Container launch sequence]#container-launch-sequence
  - [Manifest Format]#manifest-format
    - [Mounts]#mounts
    - [Seccomp]#seccomp
    - [Capabilities]#capabilities
  - [Roadmap]#roadmap
  - [Questions and Help]#questions-and-help
  - [Contributing]#contributing
  - [License]#license
  - [Contact]#contact
  - [Acknowledgements]#acknowledgements

## About

Northstar is an open source embedded container runtime optimized for speed and
resource usage. Northstar combines several standard Linux process isolation and
sandboxing features to gain a medium level of isolation between
containers/processes. The Northstar runtime consists out of two parts: The
container handling and process spawning. To build the most efficient and robust
solution, Northstar is completely developed in Rust, a language designed to
afford the performance of C/C++ without their footguns.

The [Northstar - Embedded Container
Runtime](doc/Northstar%20-%20Embedded%20Container%20Runtime.pdf) whitepaper
describes the motivation and initial concepts and ideas of Northstar.

Security is a strong concern and hard to achieve. Northstar uses tons of OS
interfaces with room for mistakes security and stability wise. This
[report](doc/Cure53%20ESR-01-report.pdf) describes the results of a security
assessment of the Northstar Embedded Linux Container Runtime. Carried out by
[Cure53](https://cure53.de) in August 2022, the project included a penetration
test and a dedicated audit of the source code. Outcome and actions take are
documented in the projects [issue
tracker](https://github.com/esrlabs/northstar/issues?q=label%3Aaudit_0822+)
label
[audit_0822](https://github.com/esrlabs/northstar/issues?q=label%3Aaudit_0822+).

### Containers

<!-- markdown-link-check-disable -->
Northstar containers are called `NPK`. The NPK format is heavily inspired by the
[Android APEX](https://source.android.com/devices/tech/ota/apex) technology. A
Northstar container contains:
<!-- markdown-link-check-enable -->

* Root filesystem in a [Squashfs]https://github.com/plougher/squashfs-tools
  file system image (optionally compressed)
* Northstar manifest with process configuration and container meta information

Northstar containers can be created with the Northstar utility
[sextant](northstar-sextant/README.md) or the [cargo-npk](cargo-npk) subcommand.

### Processes

Started Northstar containers are Linux processes. The attributes and environment
for a spawned container is described in a container manifest which is included
in a NPK. The container manifest allows to configure the following Linux
subsystems and features:

* Arguments passed to the containers init
* Environment variables set in the container context
* User and group id
* Mount namespace
* PID namespace
* IPC namespace
* UTS namespace
* Cgroups memory (optional)
* CGroups CPU (optional)
* Additional bind mounts (optional)
* Capabilities (optional)
* Stdout/stderr handling (optional)
* Seccomp configuration (optional)

### Comparison

* Northstar containers are not portable and are tailored to a known system (uid/gid/mounts...)
* **TODO**

## Quickstart

Northstar is written in [Rust](https://www.rust-lang.org). The minimum supported
Rust version (MSRV) is *1.65.0*. Rust is best installed and managed by the rustup
tool. Rust has a 6-week rapid release process and supports a great number of
platforms, so there are many builds of Rust available at any time. rustup
manages these builds in a consistent way on every platform that Rust supports,
enabling installation of Rust from the beta and nightly release channels as well
as support for additional cross-compilation targets.

Building Northstar is limited to Linux systems and runs on Linux systems **only**!
The Northstar build generates bindings for various system libraries and uses the
`mksquashfs` command line tool for NPK creation.

Install build dependencies on Debian based distributions by running

```sh
sudo apt-get install build-essential libclang1 squashfs-tools
```

The `squashfs-tools` package is required in version **4.1** or higher. The
recommended version is `Squashfs-tools 4.5.1 released (17th March 2022)`.

Northstar comes with a set of [examples](./examples) that demonstrate most of
the Northstar features. Building the example binaries and packing its
corresponding NPKs is done via:

```sh
./examples/build.sh
```

Building and starting the [example runtime main](./northstar/src/main.rs) is
triggered by a

```sh
cargo run --bin northstar
```

The Northstar workspace configuration configures a cargo
[runner](.cargo/runner.x86_64-unknown-linux-gnu) that invokes the runtimes
example main binary with super user rights.

Use the [northstar-nstar](./northstar-nstar) utility to inspect and modify the
runtimes state e.g.

```sh
cargo build --release --bin northstar-nstar
...
./target/release/northstar-nstar --help
...
> ./target/release/northstar-nstar -j start hello-world
{"Response":{"Err":{"StartContainerStarted":{"name":"hello-world","version":"0.0.1"}}}}
> ./target/release/northstar-nstar -j kill hello-world
{"Response":{"Ok":null}}
```

`northstar-nstar` is developement tool and not considered for any production
usecase. See [console](./doc/console.md) for details why.

## Configuration

The example executable `northstar` reads a configuration file that represents
[northstar_runtime::config::Config](https://docs.rs/northstar-runtime/latest/northstar_runtime/runtime/config/index.html).
 Example with comments [here](northstar.toml).

### Repositories

A repository is an entity that is able to store NPK's at runtime. Repositories
are configured at initialization time of the runtime. The repository
configuration cannot be changed at runtime. Each configured repository has a
unique identifier. Currently two types of repositories exists: `fs` and `mem`.

The `fs` type repositories are backed by file system storage. The configured
directory (`dir`) is used to store NPK's. If this directory is read only, no
additional install requests can be performed at runtime. If a `fs` repository
configuration contains a `key` field, the repository is treated as "verified".
The configured key is used to verify the signature of the containers manifest
and it's verity root hash. When the container is mounted, the verity root hash
is used to configure a device mapper verity devices that is mounted instead of
the contained Squashfs image.

Repositories without a `key` are treated as trustful sources. No signature
checks are performed. The root filesystem is mounted *without* verity. A
possibly present verity root hash with in the NPK is ignored. Trusted
repositories should be verified and read only file systems.

Set the `mount_on_start` flag of a `fs` repository to `true` to make the runtime
mount *all* containers present at startup. The mount operations are done in
parallel.

The `mem` type repositories use
[memfd](https://man7.org/linux/man-pages/man2/memfd_create.2.html) for their
storage. No data is persistently stored during an installation of a container.
Obviously it's not possible to have NPK's preinstalled in a `mem` repository at
runtime startup. The `mem` repositories are mainly used for testing.

## Console

Northstar uses **JSON** to encode the messages shared with clients. The messages
are newline delimited. This is a common approach that facilitates clients being
implemented in any programming language.  However, Northstar as a library,
provides a convenient
[Client](https://docs.rs/northstar-client/latest/northstar_client/struct.Client.html)
type that can be used for a simpler client implementation using **Rust**.

Details about the Northstar console are [here](doc/console.md). A good starting
point is to run the `northstar-nstar` tool with the `-j` flag that. This
instructs `northstar-nstar` to display the raw json payload exchanged with the
runtime.

Details about the model used as json payload are found
[here](https://docs.rs/northstar-runtime/latest/northstar_runtime/api/model/index.html).

## Debugging

Debugging containers can be hard. Most useful information can be obtained by
configuring various debug commands that are spawned with the container e.g `strace`.
Check the `debug` section of the [runtime configuration](northstar.toml) for examples.

## cargo-npk

The [cargo-npk](cargo-npk) subcommand is a `cargo` subcommand for building npks
from Rust binary crates. The manifest can be either fully specified (target
specific) in the cargo manifest or linked:

```toml
[package.metadata.npk]
# Default manifest
manifest = "manifest.yaml"
```

See e.g the [hello-world](examples/hello-world/Cargo.toml) for a full example:

```sh
cargo npk pack --target aarch64-unknown-linux-gnu --release --manifest-path examples/hello-world/Cargo.toml
ls target/aarch64-unknown-linux-gnu/release/hello-world-0.0.1.npk 
  target/aarch64-unknown-linux-gnu/release/hello-world-0.0.1.npk
```

## Integration tests

Integration tests start a runtime instance and assert on log output of
container of notification sent from the runtime. The testsuite is invoked by the
Rust test system:

```sh
./examples/build.sh
cargo test -p northstar-tests
```

and are executed by the project
[CI](https://github.com/esrlabs/northstar/actions). Check the
[northstar-tests](./northstar-tests/) crate for details. The Northstar projects
recommends [nextest](https://nexte.st) 🙂.

## Integration

Notes about integrating Northstar into an embedded Linux system can be found [here](./doc/integration.md).

## Container launch sequence

<br/><img src="doc/container-startup.png" class="inline" width=600/>

## Manifest Format

The manifest format is described [here](https://docs.rs/northstar-runtime/latest/northstar_runtime/npk/manifest/struct.Manifest.html).

### Mounts

The options of a mount entry in the manifest are optional. To apply one of the
mount options `rw`, `noexec`, `nosuid`, `nodev` or `rec` it must be explicitly set.

The default for a `bind` and `tmpfs` mount is *read only*. Mounts that are `rw` are
usually hard to handle from an integration point of view (SELinux and
permissions). Nevertheless - here's the example how to mount the host systems
`/tmp` directory to `/tmp`. The bind mount is *not* remounted `ro`. Note that
`ro` bind mounts require two mount operations.

```yaml
/tmp:
  type: bind
  host: /tmp
  options: rw, nosuid, noexec
```

Resource containers *cannot* be mounted `rw`. The filesystem of resource
containers is squashfs which is not writeable. Resource containers can be
mounted without the `noexec` flag in order to provide binaries.

Example resource mount with the executable flag set but `nodev` and `nosuid`
set (optional):

```yaml
/bin/java:
  type: resource
  name: java13
  version:
  dir: /
  options: nodev, nosuid
```

Example `tmpfs` mount. `tmpfs` mounts are never `ro` ;-):

```yaml
/tmpfs:
  type: tmpfs
  size: 20M
```

Mounts of type `persist` are support from the runtime for containers. The runtime
takes care to mount a *read* and *writeable* directory into the containers fs. The
directory is dedicated to this container. The directory is not shared with other
containers.

```yaml
/data:
  type: persist
```

To provide a `minimal` `/dev` file system to the container, add a mount entry of
type `dev`.

```yaml
/dev:
  type: dev
```

to the manifest. The `/dev` is populated with *only*:

* `full`
* `null`
* `random`
* `tty`
* `urandom`
* `zero`

If the container binary needs more devices, bind mount the host systems `/dev`.

### Seccomp

Northstar supports
[Seccomp](https://www.kernel.org/doc/Documentation/prctl/seccomp_filter.txt)
to filter syscalls of containers.
The easiest way to add seccomp to a container is to add the `default` profile
to the container's manifest:

```yaml
seccomp:
  profile:
    default
```

The `default` profile is similar to
[Docker's default profile](https://docs.docker.com/engine/security/seccomp/).

More specific seccomp rules that target filter syscalls are possible.
For example, the following manifest entry allows the `default` profile as well
as the
[delete_module](https://man7.org/linux/man-pages/man2/delete_module.2.html)
syscall, if its second argument equals `1` or matches the mask `0x06`.

```yaml
seccomp:
  profile:
    default
  allow:
    delete_module: !args
      index: 1
      values: [
          1,
      ]
      mask: 0x06
```

The complete format of the seccomp manifest entry is described
[here](https://docs.rs/northstar-runtime/latest/northstar_runtime/seccomp/struct.Seccomp.html).

If seccomp is defined in the manifest and the container attempts to access a
syscall that is not on the list of allowed calls the process is terminated
immediately.

### Capabilities

Every capability assigned to a container in the manifests `capabilities` field,
instructs the runtime to *not* drop this capability *after* forking a container.
Please note that the capabilities listed in the `capabilities` field is raised
in the [ambient](https://man7.org/linux/man-pages/man7/capabilities.7.html) set.

With a an empty capability set in the manifest *all* capabilities in *all* sets
are dropped upon container launch.

Example capability setting in a manifest:

```yaml
capabilities: [ CAP_NET_RAW, CAP_NET_ADMIN ]
```

## Roadmap

See the [open issues](https://github.com/esrlabs/northstar/issues) for a list of
proposed features and known issues.

## Questions and Help

Ask us questions about anything related to Northstar! To add your question,
[create an issue](https://github.com/esrlabs/northstar/issues) in this
repository.

Just a few guidelines to remember before you ask a question:

* Ensure your question hasn't already been answered. If it has been answered but
  the answer does not satisfy you, feel free to comment in the issue and we
  will re-open it.
* Use a succinct title and description. Add as *much* information as possible e.g
  manifests, npks, applications...
* If your question has already been asked and answered adequately, please add a
  thumbs-up (or the emoji of your choice!) to the issue. This helps us in identifying
  common problems that people usually face.
* Lastly, be civil, polite and patient. :)

## Contributing

Contributions are what make the open source community such an amazing place to
learn, inspire, and create. Any contributions you make are **greatly
appreciated**.

1. Fork the Project
2. Create your Feature Branch (`git checkout -b feature/AmazingFeature`)
3. Commit your Changes (`git commit -m 'Add some AmazingFeature'`)
4. Push to the Branch (`git push origin feature/AmazingFeature`)
5. Open a Pull Request

## License

Distributed under the Apache 2.0 License. See [LICENSE](LICENSE.txt) for more information.

## Contact

Project Link: [https://github.com/esrlabs/northstar](https://github.com/esrlabs/northstar)

## Acknowledgements

* [The Rust Community]https://users.rust-lang.org for providing
  [crates]./northstar/Cargo.toml that form the foundation of Northstar
<!-- markdown-link-check-disable-next-line -->
* [The Android Open Source Project]https://source.android.com for the APEX inspiration
* [youki]https://github.com/containers/youki for solving similar problems
* [The manpage project]https://man7.org/linux/man-pages/dir_section_2.html
  for documenting the weird world of system calls