Giter Site home page Giter Site logo

gonzalo-bulnes / qubes-mgmt-salt-user Goto Github PK

View Code? Open in Web Editor NEW
6.0 3.0 3.0 225 KB

:ice_cube: A collection of user Salt formulas for Qubes OS.

Home Page: https://docs.gonzalobulnes.com/configuration_management.html

SaltStack 15.54% Shell 0.29% Makefile 64.71% Jinja 15.84% Python 3.62%
qubes-os saltstack rpm-packages salt

qubes-mgmt-salt-user's Introduction

User Salt Formulas for Qubes OS

A collection of user Salt formulas for Qubes OS.

Overview

This repository contains a collection of Salt formulas that I use in Qubes OS, along with the tooling necessary to create RPM packages in order to get those Salt formulas into dom0 in a reasonably secure fashion.

See RPM packaging in the context of Qubes OS for more information about why RPM packages may be a good way to copy files into dom0.

See also the References section in this README, bear in mind that your cirumstances and mine could be different, and use own judgement.

Usage

Prerequisites

Enable the Salt user directories if you haven't already. This allows to install Salt formulas without mixing them with the base formulas that are maintained by the Qubes OS team.

# dom0

sudo qubesctl top.enable qubes.user-dirs

Then apply the state to ensure the directories are present:

# dom0

sudo qubesctl state.apply

Installation

This repository contains multiple formulas and it is not required to use them all. For each of them, similar installation and usage instructions apply: please refer to their respective READMEs for details.

Useful commands

Enabling a formula

In Qubes OS, Salt states are applied by qubesctl. No state will be applied by qubesctl unless its top files have been enabled.

In qubesctl/Salt context, the directories are separated by a . and the .top extension is omitted. Multiple top files can be enabled all at once:

# dom0

sudo qubesctl top.enable split-ssh.client split-ssh.policy split-ssh.vault

At any time, you can list all the enabled formulas:

# dom0

sudo qubesctl top.enabled
# local
#     ----------
#     user:
#         - /srv/salt/_tops/user/split-ssh.vault.top
#         - /srv/salt/_tops/user/split-ssh.client.top
#         - /srv/salt/_tops/user/split-ssh.policy.top
#     base:
#         - /srv/salt/_tops/base/topd.top
#         - /srv/salt/_tops/base/qubes.user-dirs.top

Applying the state

If you've got time to spare, the enabled states can be applied at once across all qubes:

# dom0

sudo qubesctl --all state.apply

Each state targets one or more qubes, and if you know which qubes you're modifying you can save some time by targetting them specifically.

# dom0

sudo qubesctl --targets=debian-11,ssh-client,ssh-vault state.apply

Note that dom0 is always implicitly targetted by qubesctl (and appears in the output as local). If you know it doesn't need to be updated, you can skip dom0:

# dom0

sudo qubesctl --skip-dom0 --targets=debian-11,ssh-client,ssh-vault state.apply

Development

Pre-requisites

Platform

I personally build the packages on the target platform, because Qubes OS templates make that easy, and it makes sense to me to do it. For now I'll assume you do the same.

For Qubes OS R4.1, that means a Fedora 32 qube. That qube can be completely offline, and it can be disposable.

Tito and rpm-sign

Tito is in charge of building the RPM packages. Make sure it is installed:

# fedora-32

sudo dnf install tito

The entire point of building our own packages is being able to sign them. To do that, rpm-sign must be installed.

# fedora-32

sudo dnf install rpm-sign

Using RPM with Split-GPG

If you use Split-GPG on Qubes OS, some configuration is needed to ensure that RPM tooling can sign the packages. That can be done adding the following to the ~/.rpmmarcos file of the qube where you'll build the packages. (Of course, that qube also needs allow the use of Split GPG.)

# ~/.rpmmacros

# ...

# Use split-GPG. The options are adjusted below.
%__gpg /usr/bin/qubes-gpg-client-wrapper

# Your signing key name would be different:
%_gpg_name Package Signing Key

# Based on the default command defined in /usr/lib/rpm/macros
# Removed the options: --no-armor --no-verbose --no-secmem-warning because qubes-gpg-client-wrapper doesn't support them
# Separated the option -o from -sb because qubes-gpg-client-wrapper was getting confused
%__gpg_sign_cmd                 %{__gpg} \
        gpg \
        %{?_gpg_digest_algo:--digest-algo %{_gpg_digest_algo}} \
        %{?_gpg_sign_cmd_extra_args:%{_gpg_sign_cmd_extra_args}} \
        -u "%{_gpg_name}" -sb -o %{__signature_filename} %{__plaintext_filename}
# ...

Note: you'll export the name of the GPG key as GPG_NAME later on. Both need to match!

Building packages

In order to build packages for a given formula (e.g. the split-SSH formula):

  1. Set the formula version number and the package release number:

    # The name of the Salt formula
    export FORMULA=split-ssh
    
    # The version of the formula (sources)
    export VERSION=0.8.0
    
    # The release of the RPM package
    export RELEASE=4
    
    make release
  2. Commit the changes, create a Git tag for Tito, and a signed tag for sources verification purposes:

    # This uses all the environment variables defined above.
    
    # The GPG key to verify the sources and sign the RPM packages
    export GPG_NAME="Key ID"
    
    # The commit message can be whatever you want
    git commit -m "Release ${FORMULA}-${VERSION}-${RELEASE}"
    
    # This tag is required to build the packages with Tito
    git tag qubes-mgmt-salt-user-${FORMULA}-${VERSION}-${RELEASE}
    
    # Any signed tag would do
    git stag
  3. Build the packages:

    # This uses all the environment variables defined above.
    
    make packages
  4. The packages will be created in /tmp/tito:

    tree /tmp/tito
    
    # /tmp/tito/
    # ├── noarch
    # │   └── qubes-mgmt-salt-user-split-ssh-0.8.0-4.fc32.noarch.rpm
    # ├── qubes-mgmt-salt-user-split-ssh-0.8.0-4.fc32.src.rpm
    # ├── qubes-mgmt-salt-user-split-ssh-0.8.0.tar.gz
    # └── qubes-mgmt-salt-user-split-ssh-0.8.0.tar.gz.asc
  5. Unset the environment variables:

    unset FORMULA
    unset VERSION
    unset RELEASE
    unset GPG_NAME

Publishing packages

See 🌳 qubes-packages, a template repository of RPM packages for Qubes OS. That project contains instructions and code to create your own RPM repository and manage it on untrusted infrastructure.

References

Contributions

Contributions are welcome! Please refer to the contribution guidelines to get started.

Please note that this project is released with a Contributor Code of Conduct. By participating in this project you agree to abide by its terms.

License

REUSE Compliance

This project complies with the REUSE initiative recommendations. All files include licensing information, have a companion .license file, or are listed in .reuse/dep5.

qubes-mgmt-salt-user's People

Contributors

gonzalo-bulnes avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

qubes-mgmt-salt-user's Issues

Reproducible RPM builds?

The source tarball produced by Tito is the same every build—as far as I can tell.

The source RPM and the RPM packages, however are not. By that I mean that two packages built at different times (to pick an obvious difference) will be different.

  • That's expected for signed packages, since the signature is timestamped.
  • However, once the signature stripped (rpmsign --delsign <package>), the RPM packages are still different.

To do

  • Attach an diffoscope report to illustrate the differences at play
  • document the build environment (Can a buildinfo file be created for a Fedora-based environment? Is that the right tool to look at?)
  • ideally also identify which aspects of the environment are actually relevant to reproducible RPM packages

Maybe useful references

The selected top file merging strategy should be deterministic

After enabling the user environment (via user directories), applying the state causes the following warning:

[WARNING ] top_file_merging_strategy is set to 'merge' and multiple top files were found. Merging order is not deterministic, it may be desirable to either set top_file_merging_strategy to 'same' or use the 'env_order' configuration parameter to specify the merging order.

I haven't yet looked up where the top_file_merging_strategy can be configured, but it certainly should be deterministic.

Testing of qvm-tags-in-pillar under R4.2 is needed!

Opening this issue as a placeholder for @ben-grande's sake. I'll add details (including the full error message) when I've time to investigate further, but help is welcome!

The default Salt configuration in R4.2 doesn't seem to allow qvm-tags-in-pillar and qvm-features-in-pillar to work.

I'm not sure what changed since R4.1, but the pillar extensions are consistently reported as "not found" in my early testing.

If anyone was able to confirm this, that would be a great first step towards documenting and troubleshooting the issue so that it can be fixed either upstream if the change of behaviour wasn't intentional, or here if adjustments to those two states are needed.

The validation of the Salt formulas rendering still happens in dom0

While packaging the split-GPG formula I made several mistakes involving Jinja syntax errors (or Jinja usage errors resulting in invalid YAML, which are similar). See #11

Currently, the rendering of the Jinja templates (both in the state and the pillar) happens in dom0 because qubesctl/Salt is not available in the other qubes.

Considering that the purpose of packaging the Salt formulas as RPM packages is to allow development outside dom0 while avoiding copying into dom0, I think that ensuring such validation can be performed in the development qubes before packaging would be great.

References

Packages: qvm-tags-in-pillar and qvm-features-in-pillar

I think both can be released at the same time, since they're so similar.

Depends on #16

I would still build two separate packages because QVM Features and QVM Tags currently have different uses, so the implications of exposing them to the Salt pillar are slightly different.

A few files need to be added before a release can be created. And I'm happy to help at any step in the process (including before if the process doesn't quite make sense!)

QVM Features in Pillar:

  • (Package-level) README.md
  • (Package-level) Makefile template
  • RPM Specification file template

QVM Tags in Pillar:

  • (Package-level) README.md
  • (Package-level) Makefile template
  • RPM Specification file template

The other files will be generated during the release process. (Docs for the release process in the main README.)

Observations

README, Makefile template

The README and Makefiles template are mostly generic, with the exception of the configuration details that are specific to each package. If I did a good job, those shouldn't be too difficult to identify and set. The files in the Split SSH or Split GPG packages can be used as an example.

RPM spec file

The RPM Spec template is the core of the packaging work. Besides some package metadata, that's the file that defines which files were created when installing the package, so they can, for example, be removed when the package is uninstalled.

Most of the tasks can be delegated to the formula Makefile, but files still need to be listed. Again, the spec files of the Split SSH or Split GPG packages are a good reference. (Gladly, the workarounds related to the user Salt pillar won't be necessary anymore once targetting can be performed using QVM features and QVM tags! 🎉)

Note on change logs

The RPM spec file contains a change log. That shoild list changes relevant to packaging. And the formula change log should list the changes relevant to the formula itself and its functionality.

Note on numbers!

The VERSION is the version number of the formula. It should follow the semantic versioning convention.

The RELEASE number allows to account for changes in packaging. It is a sequential number that is only there to allow the same version of the formula to be packaged more than once, e.g. to correct a packaging mistake or add an improvement (and for new packages to replace old ones in package managers). Start at 1 and increase if needed.

After a change in version number, the release number can be reset at 1 because the version number change will already hint the package managers to do the right thing.

Let me know if there is anything else you'd like me to explain! If this explanation seems good, I'll add it as documentation.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.