Skip to content
bmwcaritPublic

About

A small polkit drop-in replacement

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

117 Commits

Folders and files

Repository files navigation

smolkit

Smolkit is a low-footprint drop-in replacement for Polkit. In particular, low-footprint means there is no JavaScript engine required.

Overview

The basic purpose of Polkit, and therefore smolkit, is to answer queries of the form "is user X allowed to perform action Y on service Z?" via D-Bus, to allow unprivileged users to perform privileged operations under certain conditions. See this example call of systemctl restart foo.service:

+-------+                 +---------+                          +---------+
| User  |                 | Systemd |                          | Smolkit |
+-------+                 +---------+                          +---------+
    |                          |                                    |
    | restart foo.service      |                                    |
    |------------------------->|                                    |
    |                          |                                    |
    |                          | is User allowed systemd-action     |
    |                          | `restart` on `foo.service`?        |
    |                          |----------------------------------->|
    |                          |                                    |
    |                          |                                    | [check rules]
    |                          |                                    |--------------
    |                          |                                    |             |
    |                          |                                    |<-------------
    |                          |                                    |
    |                          |                  allowed/denied    |
    |                          |<-----------------------------------|
    |                          |                                    |

The heart of the smolkit D-Bus API is the CheckAuthorization method. Given a subject (i.e. user), an action identifier and further data needed to describe the action (e.g. which systemd service, whether to start/stop/restart, ..), it determines whether that specific action is allowed.

There are a number of methods in Polkit's API related to registering and using authentication agents (i.e. ways of showing password prompts integrated in each desktop environment in their specific style). Smolkit doesn't support authentication agents, so we don't implement these.

Adding allow rules for smolkit

During start of smolkit, it reads its allow rules from a path supplied as argument during the boot (e.g. /etc/smolkit/rules.d). Both a singular rule file and a directory can be supplied.

Allow rules are JSON arrays containing one or more rules supplying a subject, an action-id and details. A small example would look like the following:

[
  {
    "subject": {
      "user": "sec_smolkit"
    },
    "action_id": "org.freedesktop.systemd1.manage-units",
    "details": {
      "unit": "smolkit-test-start.service",
      "verb": ["start", "stop", "restart"]
    }
  }
]

This JSON file allows the user sec_smolkit to start/stop/restart the systemd unit smolkit-test-start.service. Both unit and verb can take arrays as values.

Developer Guided Tour

The primary objective of smolkit is to work without a JavaScript engine. Instead, the rules config is basically a list of allowed values of the CheckAuthorization parameters.

The data structures representing the D-Bus side parameters of the CheckAuthorization call are currently just type aliases over the sdbus transport types. We may add separate classes for them as needed.

On the other hand there will be structures for allow rules containing subject, action ID and details as loaded from the allow rules JSON file. While the D-Bus types have specific info like a UID, the rules might have different information depending on the use case, e.g. a unix group name that is allowed.

This means there is some interpretation to be done in order to check whether a rule matches a query from D-Bus.

SDK Container

The SDK container is built from the Dockerfile. The CI creates this docker container for us. For building locally there is scripts/run-sdk-docker.sh which will rebuild the SDK container if necessary. This also offers the possibility to run any commands in the container, or just a shell if no command is given.

The build commands are collected in scripts/build.sh, so a local build can be triggered using scripts/run-sdk-docker.sh scripts/build.sh. Check the help output of scripts/build.sh for additional options like running tests or switching the compiler to Clang++.

Tests

There will be different types of tests in corresponding subfolders, e.g. tests/unit and tests/component.

There are two interfaces smolkit uses and that need to be replaced with doubles during tests: the interface to the Linux system, e.g. for looking up users and groups, and the D-Bus connection, including the services that send us requests.

The system D-Bus connection is replaced by locally started instances (see the setup code in the D-Bus interactions component test) on which we can send requests to smolkit and test the responses.

The system interface, i.e. the user lookup functions, are part of libc, and less simple to replace directly. We have added a wrapper class SystemUserLookup that allows intercepting calls in a mock class for unit tests (see e.g. the MockSystemUserLookup class in the subject unit tests).

For component tests, we exchange these libc functions with mocks during dynamic loading using the LD_PRELOAD mechanism (please refer to man 8 ld-linux for details). The implementation of this mock is very much hard coded:

  • getpwuid() only knows about user someUser with UID 9001 and returns no username for any other UID.
  • getgrnam() only knows about group someGroup (with someUser is a member of).

License

Copyright (C) 2022-2026 BMW Car IT GmbH Contact: http://www.bmw-carit.de/

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

 http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

About

A small polkit drop-in replacement

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages