A few weeks ago I configured a road warrior VPN setup. The
remote end is on a VPS running OpenBSD and OpenIKED, the VPN is
an IKEv2 VPN using x509 authentication, and the local end is
StrongSwan. I also configured an IKEv2 VPN between my VPSs. Here
are the notes for how to do so.
In all cases, to use x509 authentication, you will need to
generate a bunch of certificates and keys:
a CA certificate
a key/certificate pair for each client
Fortunately, OpenIKED provides the ikectl utility to help you do
so. Before going any further, you might find it useful to edit
/etc/ssl/ikeca.cnf to set some reasonable defaults for your
certificates.
Begin by creating and installing a CA certificate:
# ikectl ca vpn create
# ikectl ca vpn install
For simplicity, I am going to assume that the you are managing
your CA on the same host as one of the hosts that you want to
configure for the VPN. If not, see the bit about exporting
certificates at the beginning of the section on persistent
host-host VPNs.
Create and install a key/certificate pair for your server.
Suppose for example your first server is called
server1.example.org:
# ikectl ca vpn certificate server1.example.org create
# ikectl ca vpn certificate server1.example.org install
Persistent host-host VPNs
For each other server that you want to use, you need to also
create a key/certificate pair on the same host as the CA
certificate, and then copy them over to the other server.
Assuming the other server is called server2.example.org:
# ikectl ca vpn certificate server2.example.org create
# ikectl ca vpn certificate server2.example.org export
This last command will produce a tarball
server2.example.org.tgz. Copy it over to server2.example.org and
install it:
# tar -C /etc/iked -xzpvf server2.example.org.tgz
Next, it is time to configure iked. To do so, you will need to
find some information about the certificates you just generated.
On the host with the CA, run
$ cat /etc/ssl/vpn/index.txt
V 210825142056Z 01 unknown /C=US/ST=Pennsylvania/L=Pittsburgh/CN=server1.example.org/emailAddress=rak@example.org
V 210825142208Z 02 unknown /C=US/ST=Pennsylvania/L=Pittsburgh/CN=server2.example.org/emailAddress=rak@example.org
Pick one of the two hosts to play the active role (in this
case, server1.example.org). Using the information you gleaned
from index.txt, add the following to /etc/iked.conf, filling in
the srcid and dstid fields appropriately.
ikev2 'server1_server2_active' active esp from server1.example.org to server2.example.org \
local server1.example.org peer server2.example.org \
srcid '/C=US/ST=Pennsylvania/L=Pittsburgh/CN=server1.example.org/emailAddress=rak@example.org' \
dstid '/C=US/ST=Pennsylvania/L=Pittsburgh/CN=server2.example.org/emailAddress=rak@example.org'
On the other host, add the following to /etc/iked.conf
ikev2 'server2_server1_passive' passive esp from server2.example.org to server1.example.org \
local server2.example.org peer server1.example.org \
srcid '/C=US/ST=Pennsylvania/L=Pittsburgh/CN=server2.example.org/emailAddress=rak@example.org' \
dstid '/C=US/ST=Pennsylvania/L=Pittsburgh/CN=server1.example.org/emailAddress=rak@example.org'
Note that the names 'server1_server2_active' and
'server2_server1_passive' in the two stanzas do not matter and
can be omitted. Reload iked on both hosts:
# ikectl reload
If everything worked out, you should see the negotiated security
associations (SAs) in the output of
# ikectl show sa
On OpenBSD, you should also see some output on success or errors
in the file /var/log/daemon.
For a road warrior
Add the following to /etc/iked.conf on the remote end:
ikev2 'responder_x509' passive esp \
from 0.0.0.0/0 to 10.0.1.0/24 \
local server1.example.org peer any \
srcid server1.example.org \
config address 10.0.1.0/24 \
config name-server 10.0.1.1 \
tag "ROADW"
Configure or omit the address range and the name-server
configurations to suit your needs. See iked.conf(5) for details.
Reload iked:
# ikectl reload
If you are on OpenBSD and want the remote end to have an IP
address, add the following to /etc/hostname.vether0, again
configuring the address to suit your needs:
inet 10.0.1.1 255.255.255.0
Put the interface up:
# ifconfig vether0 up
Now create a client certificate for authentication. In my case,
my road-warrior client was client.example.org:
# ikectl ca vpn certificate client.example.org create
# ikectl ca vpn certificate client.example.org export
Welcome to the August 2020 report from the Reproducible Builds project.
In our monthly reports, we summarise the things that we have been up to over the past month. The motivation behind the Reproducible Builds effort is to ensure no flaws have been introduced from the original free software source code to the pre-compiled binaries we install on our systems. If you re interested in contributing to the project, please visit our main website.
This month, Jennifer Helsby launched a new reproduciblewheels.com website to address the lack of reproducibility of Python wheels.
To quote Jennifer s accompanying explanatory blog post:
One hiccup we ve encountered in SecureDrop development is that not all Python wheels can be built reproducibly. We ship multiple (Python) projects in Debian packages, with Python dependencies included in those packages as wheels. In order for our Debian packages to be reproducible, we need that wheel build process to also be reproducible
Reproducible builds at DebConf20
There were a number of talks at the recent online-only DebConf20 conference on the topic of reproducible builds.
Holger gave a talk titled Reproducing Bullseye in practice , focusing on independently verifying that the binaries distributed from ftp.debian.org are made from their claimed sources. It also served as a general update on the status of reproducible builds within Debian. The video (145 MB) and slides are available.
There were also a number of other talks that involved Reproducible Builds too. For example, the Malayalam language mini-conference had a talk titled , ? ( I want to join Debian, what should I do? ) presented by Praveen Arimbrathodiyil, the Clojure Packaging Team BoF session led by Elana Hashman, as well as Where is Salsa CI right now? that was on the topic of Salsa, the collaborative development server that Debian uses to provide the necessary tools for package maintainers, packaging teams and so on.
Jonathan Bustillos (Jathan) also gave a talk in Spanish titled Un camino verificable desde el origen hasta el binario ( A verifiable path from source to binary ). (Video, 88MB)
Development work
After many years of development work, the compiler for the Rust programming language now generates reproducible binary code. This generated some general discussion on Reddit on the topic of reproducibility in general.
Paul Spooren posted a request for comments to OpenWrt s openwrt-devel mailing list asking for clarification on when to raise the PKG_RELEASE identifier of a package. This is needed in order to successfully perform rebuilds in a reproducible builds context.
In openSUSE, Bernhard M. Wiedemann published his monthly Reproducible Builds status update.
Chris Lamb provided some comments and pointers on an upstream issue regarding the reproducibility of a Snap / SquashFS archive file. []
Debian
Holger Levsen identified that a large number of Debian .buildinfo build certificates have been tainted on the official Debian build servers, as these environments have files underneath the /usr/local/sbin directory []. He also filed against bug for debrebuild after spotting that it can fail to download packages from snapshot.debian.org [].
This month, several issues were uncovered (or assisted) due to the efforts of reproducible builds.
For instance, Debian bug #968710 was filed by Simon McVittie, which describes a problem with detached debug symbol files (required to generate a traceback) that is unlikely to have been discovered without reproducible builds. In addition, Jelmer Vernooij called attention that the new Debian Janitor tool is using the property of reproducibility (as well as diffoscope when applying archive-wide changes to Debian:
New merge proposals also include a link to the diffoscope diff between a vanilla build and the build with changes. Unfortunately these can be a bit noisy for packages that are not reproducible yet, due to the difference in build environment between the two builds. []
56 reviews of Debian packages were added, 38 were updated and 24 were removed this month adding to our knowledge about identified issues. Specifically, Chris Lamb added and categorised the nondeterministic_version_generated_by_python_param and the lessc_nondeterministic_keys toolchain issues. [][]
Holger Levsen sponsored Lukas Puehringer s upload of the python-securesystemslib pacage, which is a dependency of in-toto, a framework to secure the integrity of software supply chains. []
Lastly, Chris Lamb further refined his merge request against the debian-installer component to allow all arguments from sources.list files (such as [check-valid-until=no]) in order that we can test the reproducibility of the installer images on the Reproducible Builds own testing infrastructure and sent a ping to the team that maintains that code.
Upstream patches
The Reproducible Builds project detects, dissects and attempts to fix as many currently-unreproducible packages as possible. We endeavour to send all of our patches upstream where appropriate. This month, we wrote a large number of these patches, including:
diffoscopediffoscope is our in-depth and content-aware diff utility that can not only locate and diagnose reproducibility issues, it provides human-readable diffs of all kinds. In August, Chris Lamb made the following changes to diffoscope, including preparing and uploading versions 155, 156, 157 and 158 to Debian:
New features:
Support extracting data of PGP signed data. (#214)
Try files named .pgp against pgpdump(1) to determine whether they are Pretty Good Privacy (PGP) files. (#211)
Support multiple options for all file extension matching. []
Bug fixes:
Don t raise an exception when we encounter XML files with <!ENTITY> declarations inside the Document Type Definition (DTD), or when a DTD or entity references an external resource. (#212)
pgpdump(1) can successfully parse some binary files, so check that the parsed output contains something sensible before accepting it. []
Temporarily drop gnumeric from the Debian build-dependencies as it has been removed from the testing distribution. (#968742)
Correctly use fallback_recognises to prevent matching .xsb binary XML files.
Correct identify signed PGP files as file(1) returns data . (#211)
Logging improvements:
Emit a message when ppudump version does not match our file header. []
Don t use Python s repr(object) output in Calling external command messages. []
Include the filename in the not identified by any comparator message. []
Codebase improvements:
Bump Python requirement from 3.6 to 3.7. Most distributions are either shipping with Python 3.5 or 3.7, so supporting 3.6 is not only somewhat unnecessary but also cumbersome to test locally. []
Drop some unused imports [], drop an unnecessary dictionary comprehensions [] and some unnecessary control flow [].
Correct typo of output in a comment. []
Release process:
Move generation of debian/tests/control to an external script. []
Add some URLs for the site that will appear on PyPI.org. []
Update author and author email in setup.py for PyPI.org and similar. []
Testsuite improvements:
Update PPU tests for compatibility with Free Pascal versions 3.2.0 or greater. (#968124)
Mark that our identification test for .ppu files requires ppudump version 3.2.0 or higher. []
Add an assert_diff helper that loads and compares a fixture output. [][][][]
Misc:
Duplicate docker instructions in the Get diffoscope section of the diffoscope website. []
In addition, Mattia Rizzolo documented in setup.py that diffoscope works with Python version 3.8 [] and Frazer Clews applied some Pylint suggestions [] and removed some deprecated methods [].
Clarify & fix a few entries on the who page [][] and ensure that images do not get to large on some viewports [].
Clarify use of a pronoun re. Conservancy. []
Use View all our monthly reports over View all monthly reports . []
Move a is a suffix out of the link target on the SOURCE_DATE_EPOCH age. []
In addition, Javier Jard n added the freedesktop-sdk project [] and Kushal Das added SecureDrop project [] to our projects page. Lastly, Michael P hn added internationalisation and translation support with help from Hans-Christoph Steiner [].
Testing framework
The Reproducible Builds project operate a Jenkins-based testing framework to power tests.reproducible-builds.org. This month, Holger Levsen made the following changes:
System health checks:
Improve explanation how the status and scores are calculated. [][]
Update and condense view of detected issues. [][]
Query the canonical configuration file to determine whether a job is disabled instead of duplicating/hardcoding this. []
Detect several problems when updating the status of reporting-oriented metapackage sets. []
Detect when diffoscope is not installable [] and failures in DNS resolution [].
Mark that the u-boot Universal Boot Loader should not build architecture independent packages on the arm64 architecture anymore. []
Finally, build node maintenance was performed by Holger Levsen [], Mattia Rizzolo [][] and Vagrant Cascadian [][][][]
Mailing list
On our mailing list this month, Leo Wandersleb sent a message to the list after he was wondering how to expand his WalletScrutiny.com project (which aims to improve the security of Bitcoin wallets) from Android wallets to also monitor Linux wallets as well:
If you think you know how to spread the word about reproducibility in the context of Bitcoin wallets through WalletScrutiny, your contributions are highly welcome on this PR []
Julien Lepiller posted to the list linking to a blog post by Tavis Ormandy titled You don t need reproducible builds. Morten Linderud (foxboron) responded with a clear rebuttal that Tavis was only considering the narrow use-case of proprietary vendors and closed-source software. He additionally noted that the criticism that reproducible builds cannot prevent against backdoors being deliberately introduced into the upstream source ( bugdoors ) are decidedly (and deliberately) outside the scope of reproducible builds to begin with.
Chris Lamb included the Reproducible Builds mailing list in a wider discussion regarding a tentative proposal to include .buildinfo files in .deb packages, adding his remarks regarding requiring a custom tool in order to determine whether generated build artifacts are identical in a reproducible context. []
Jonathan Bustillos (Jathan) posted a quick email to the list requesting whether there was a list of To do tasks in Reproducible Builds.
Lastly, Chris Lamb responded at length to a query regarding the status of reproducible builds for Debian ISO or installation images. He noted that most of the technical work has been performed but there are at least four issues until they can be generally advertised as such . He pointed that the privacy-oriented Tails operation system, which is based directly on Debian, has had reproducible builds for a number of years now. []
If you are interested in contributing to the Reproducible Builds project, please visit our Contribute page on our website. However, you can get in touch with us via:
This week,last week, Last month, I attended DebConf 20 Online. It was the first DebConf to be held entirely online, but it s the 7th DebConf I ve attended from home.
My first one was DebConf7. Initially I mostly started watching the videos because I wanted to learn more about packaging. I had just figured out how to create binary packages by hand, and have read through the new maintainers guide, but a lot of it was still a mystery. By the end of DebConf7 my grasp of source packages was still a bit thin, but other than that, I ended up learning a lot more about Debian during DebConf7 than I had hoped for, and over the years, the quality of online participation for each DebConf has varied a lot.
I think having a completely online DebConf, where everyone was remote, helped raise awareness about how important it is to make the remote experience work well, and I hope that it will make people who run sessions at physical events in the future consider those who are following remotely a bit more.
During some BoF sessions, it was clear that some teams haven t talked to each other face to face in a while, and I heard at least 3 teams who said This was nice, we should do more regular video calls! . Our usual communication methods of e-mail lists and IRC serve us quite well, for the most part, but sometimes having an actual conversation with the whole team present at the same time can do wonders for dealing with many kind of issues that is just always hard to deal with in text based mediums.
There were three main languages used in this DebConf. We ve had more than one language at a DebConf before, but as far as I know it s the first time that we had multiple talks over 3 languages (English, Malayalam and Spanish).
It was also impressive how the DebConf team managed to send out DebConf t-shirts all around the world and in time before the conference! To my knowledge only 2 people didn t get theirs in time due to customs.
I already posted about the new loop that we worked on for this DebConf. It was an unintended effect that we ended up having lots of shout-outs which ended up giving this online DebConf a much more warmer, personal feel to it than if we didn t have it. I m definitely planning to keep on improving on that for the future, for online and in-person events. There were also some other new stuff from the video team during this DebConf, we ll try to co-ordinate a blog post about that once the dust settled.
Thanks to everyone for making this DebConf special, even though it was virtual!
I needed to setup a VPN in order to access my readings for class. The instructions for Linux are located: https://nyu.service-now.com/sp?id=kb_article_view&sysparm_article=KB0014932
After you download the VPN client of your choice (they recommend Cisco AnyConnect), connect to: vpn.nyu.edu.
It will ask for two passwords: your NYU username and password and a multi-factor authentication (MFA) code from Duo. Use the Duo. See below for stuff on Duo.
Hit connect and viola, you can connect to the VPN.
Duo Authentication Setup
Go to: https://start.nyu.edu and follow the instructions for MFA. They ll tell you that a smart phone is the most secure method of setting up. I am skeptical.
Install the Duo Authentication App on your phone, enter your phone number into the NYU web page (off of ) and it will send a thing to your phone to connect it.
Commentary
Okay, I have to complain at least a little bit about this. I had to guess what the VPN address was because the instructions are for NYU Shanghai. I also had to install the VPN client using the terminal. These sorts of things make it harder for people to use Linux. Boo.
So many good books, so little reading time.
Jairus Banaji A Brief History of Commercial Capitalism
(nonfiction)
Steven Brust The Baron of Magister Valley (sff)
Micaiah Johnson The Space Between Worlds (sff)
Ian McDonald Luna: New Moon (sff)
Elizabeth Moon Trading in Danger (sff)
Tamsyn Muir Harrow the Ninth (sff)
Suzanne Palmer Finder (sff)
Kit Rocha Beyond Shame (sff)
Kit Rocha Beyond Control (sff)
Kit Rocha Beyond Pain (sff)
Arundhati Roy Azadi (nonfiction)
Jeff VanderMeer Authority (sff)
Jeff VanderMeer Acceptance (sff)
K.B. Wagers Behind the Throne (sff)
Jarrett Walker Human Transit (nonfiction)
I took advantage of a few sales to get books I know I'm going to want to
read eventually for a buck or two.
This year has been a really unusual one for in-person events like conferences.
I had already planned to take this year off from travel for the most part,
attending just a handful of domestic conferences. But the pandemic has thrown
those plans into chaos; I do not plan to attend large-scale in-person events
until July 2021 at the earliest, per my employer's guidance.
I've been really sad to have turned down multiple speaking invitations this
year. To try to set expectations, I added a note to my Talks page
that indicates I will not be writing any new talks for 2020, but am happy to
join panels or reprise old talks.
And somehow, with all that background, I still ended up giving three talks at
DebConf 2020 this year. In part, I think it's because this is the first DebConf
I've been able to attend since 2017, and I was so happy to have the
opportunity! I took time off work to give myself enough space to focus on the
conference. International travel is very difficult for me, so DebConf is
generally challenging if not impossible for me to attend.
A panel a day keeps the FTP Team away?
On Thursday, August 27th, I spoke on the Leadership in Debian
panel, where I discussed some of the challenges leadership in the project must
face, including an appropriate response to the BLM movement and sustainability
for volunteer positions that require unsustainable hours (such as DPL).
On Friday, August 28th, I hosted the Debian Clojure BoF, attended by
members of the Clojure and Puppet teams. The Puppet team is working to package
the latest versions of Puppet Server/DB, which involve significant Clojure
components, and I am doing my best to help.
On Saturday, August 29th, I spoke on the Meet the Technical Committee
panel. The Committee presented a number of proposals for improving how we work
within the project. I was responsible for presenting our first proposal on
allowing folks to engage the committee privately.
Previously: v5.5.
Linux v5.6 was released back in March. Here s my quick summary of various features that caught my attention:
WireGuard
The widely used WireGuard VPN has been out-of-tree for a very long time. After 3 1/2 years since its initial upstream RFC, Ard Biesheuvel and Jason Donenfeld finished the work getting all the crypto prerequisites sorted out for the v5.5 kernel. For this release, Jason has gotten WireGuard itself landed. It was a twisty road, and I m grateful to everyone involved for sticking it out and navigating the compromises and alternative solutions.
openat2() syscall and RESOLVE_* flags
Aleksa Sarai has added a number of important path resolution scoping options to the kernel s open() handling, covering things like not walking above a specific point in a path hierarchy (RESOLVE_BENEATH), disabling the resolution of various magic links (RESOLVE_NO_MAGICLINKS) in procfs (e.g. /proc/$pid/exe) and other pseudo-filesystems, and treating a given lookup as happening relative to a different root directory (as if it were in a chroot, RESOLVE_IN_ROOT). As part of this, it became clear that there wasn t a way to correctly extend the existing openat() syscall, so he added openat2() (which is a good example of the efforts being made to codify Extensible Syscall arguments). The RESOLVE_* set of flags also cover prior behaviors like RESOLVE_NO_XDEV and RESOLVE_NO_SYMLINKS.
pidfd_getfd() syscall
In the continuing growth of the much-needed pidfd APIs, Sargun Dhillon has added the pidfd_getfd() syscall which is a way to gain access to file descriptors of a process in a race-less way (or when /proc is not mounted). Before, it wasn t always possible make sure that opening file descriptors via /proc/$pid/fd/$N was actually going to be associated with the correct PID. Much more detail about this has been written up at LWN.
openat() via io_uring
With my attack surface reduction hat on, I remain personally suspicious of the io_uring() family of APIs, but I can t deny their utility for certain kinds of workloads. Being able to pipeline reads and writes without the overhead of actually making syscalls is pretty great for performance. Jens Axboe has added the IORING_OP_OPENAT command so that existing io_urings can open files to be added on the fly to the mapping of available read/write targets of a given io_uring. While LSMs are still happily able to intercept these actions, I remain wary of the growing syscall multiplexer that io_uring is becoming. I am, of course, glad to see that it has a comprehensive (if out of tree ) test suite as part of liburing.
removal of blocking random pool
After making algorithmic changes to obviate separate entropy pools for random numbers, Andy Lutomirski removed the blocking random pool. This simplifies the kernel pRNG code significantly without compromising the userspace interfaces designed to fetch cryptographically secure random numbers. To quote Andy, This series should not break any existing programs. /dev/urandom is unchanged. /dev/random will still block just after booting, but it will block less than it used to. See LWN for more details on the history and discussion of the series.
arm64 support for on-chip RNG
Mark Brown added support for the future ARMv8.5 s RNG (SYS_RNDR_EL0), which is, from the kernel s perspective, similar to x86 s RDRAND instruction. This will provide a bootloader-independent way to add entropy to the kernel s pRNG for early boot randomness (e.g. stack canary values, memory ASLR offsets, etc). Until folks are running on ARMv8.5 systems, they can continue to depend on the bootloader for randomness (via the UEFI RNG interface) on arm64.
arm64 E0PD
Mark Brown added support for the future ARMv8.5 s E0PD feature (TCR_E0PD1), which causes all memory accesses from userspace into kernel space to fault in constant time. This is an attempt to remove any possible timing side-channel signals when probing kernel memory layout from userspace, as an alternative way to protect against Meltdown-style attacks. The expectation is that E0PD would be used instead of the more expensive Kernel Page Table Isolation (KPTI) features on arm64.
powerpc32 VMAP_STACK
Christophe Leroy added VMAP_STACK support to powerpc32, joining x86, arm64, and s390. This helps protect against the various classes of attacks that depend on exhausting the kernel stack in order to collide with neighboring kernel stacks. (Another common target, the sensitive thread_info, had already been moved away from the bottom of the stack by Christophe Leroy in Linux v5.1.)
generic Page Table dumping
Related to RISCV s work to add page table dumping (via /sys/fs/debug/kernel_page_tables), Steven Price extracted the existing implementations from multiple architectures and created a common page table dumping framework (and then refactored all the other architectures to use it). I m delighted to have this because I still remember when not having a working page table dumper for ARM delayed me for a while when trying to implement upstream kernel memory protections there. Anything that makes it easier for architectures to get their kernel memory protection working correctly makes me happy.
That s in for now; let me know if there s anything you think I missed. Next up: Linux v5.7.
The community.mysql collection from Ansible Galaxy
provides a mysql_query module to run arbitrary MySQL queries.
Unfortunately, it does not support check mode nor the --diff flag.
It is also unable to tell if there was a change. Let s write a
specific Ansible module to workaround these issues.
Code
The module has the following signature and it executes the
provided SQL statements in a single transaction. It needs a list of
the affected tables to be able to detect and show the changes.
mysql_sync:sql:DELETE FROM rules WHERE name LIKE 'CMDB:%';INSERT INTO rules (name, rule) VALUES('CMDB: check for cats', ':is(object, "CAT")'),('CMDB: check for dogs', ':is(object, "DOG")');REPLACE INTO webhooks (name, url) VALUES('OpsGenie', 'https://opsgenie/something/token'),('Slack', 'https://slack/something/token');user:monitoringpassword:Yooghah5database:monitoringtables:-rules-webhooks
Prerequisites
The module does not enforce idempotency, but it is expected you
provide appropriate SQL queries. In the above example, idempotency is
achieved because the content of the rules table is deleted and
recreated from scratch while the rows in the webhooks table are
replaced if they already exist.
You need the PyMySQL package.
Module definition
Starting from the skeleton described in the previous article, here is the module definition:
The password is marked with no_log to ensure it won t be displayed
or stored, notably when ansible-playbook runs in verbose mode. There
is no host option as the module is executed on the MySQL host.
Strong authentication using certificates is not implemented either.
This matches our goal with custom modules: only implement what you
strictly need.
Getting the current rows
The next step is to retrieve the records currently in the database.
The got dictionary is a mapping from table names to the list of rows
they contain:
got=tables=module.params['tables']connection=pymysql.connect(user=module.params['user'],password=module.params['password'],db=module.params['database'],charset='utf8mb4',cursorclass=pymysql.cursors.DictCursor)withconnection.cursor()ascursor:fortableintables:cursor.execute("SELECT * FROM ".format(table))got[table]=cursor.fetchall()
Computing the changes
Let s now build the wanted dictionary. The trick is to execute the
SQL statements in a transaction without issuing a final commit. The
changes will be invisible1 to other readers and we can
compare the final rows with the rows collected in got:
wanted=sql=module.params['sql']statements=[statement.strip()forstatementinsql.split(";\n")ifstatement.strip()]withconnection.cursor()ascursor:forstatementinstatements:try:cursor.execute(statement)exceptpymysql.OperationalErroraserr:code,message=err.argsresult['msg']="MySQL error for : ".format(statement,message)module.fail_json(**result)fortableintables:cursor.execute("SELECT * FROM ".format(table))wanted[table]=cursor.fetchall()
The first for loop executes each statement. On error, we return a
helpful message containing the faulty one. The second for loop
records the final rows of each table in wanted.
Applying changes
Back to the skeleton described in the previous article, the last step is to apply the changes if there
is a difference between got and wanted when not running with check
mode. The diff object is a bit more elaborate as it is built table
by table. This enables Ansible to display the name of each table
before the diff representation:
Applying the changes is quite trivial: just commit them! Otherwise,
they are lost when the module exits.
connection.commit()
The complete code is available on GitHub. Compared to the
mysql_query module, this one supports the check mode, signals
correctly if there is a change and displays the differences. However,
it should not be used with huge tables, as it would try to load them
in memory.
The tables need to use the InnoDB storage engine.
Moreover, MySQL does not know how to use transactions with DDL
statements: do not modify table definitions!
The cisco.iosxr collection from Ansible Galaxy
provides an iosxr_user module to manage local users,
along with their SSH keys. However, the module is quite slow, do not
display a diff for changed SSH keys, never signal change when a key is
modified, and does not delete obsolete keys. Let s write a custom
Ansible module managing only the SSH keys while fixing these issues.
How to add an SSH key to a user
Adding SSH keys to users in Cisco IOS-XR is quite undocumented. First,
you need to encode the key with the ssh-rsa key ASN.1 format,
like an OpenSSH public key, but without the base64-encoding:
Code
The module has the following signature and it installs the
specified key for each user and remove keys from retired users the
ones we do not specify.
Prerequisites
Unlike the iosxr_user module, our custom module only handles SSH
keys, one per user. Therefore, the user definitions have to already
exist in the running configuration.1 Moreover, the user defined
in ansible_user needs to be in the root-system group. The
cisco.iosxr collection must also be installed as the module relies
on its code.
When running the module, ansible_connection needs to be set to
network_cli and ansible_network_os to iosxr. These variables are
usually defined in the inventory.
Module definition
Starting from the skeleton described in the previous article, we define the module:
A common library to parse a command output is textfsm: a Python
module using a template-based state machine for parsing semi-formatted
text.
template=r"""Value Required Label (\w+)Value Required,List Data ([A-F0-9 ]+)Start ^Key label: $ Label ^Data\s+: -> GetDataGetData ^ $ Data ^$$ -> Record Start""".lstrip()re_table=textfsm.TextFSM(io.StringIO(template))got=data[0]:"".join(data[1]).replace(' ','')fordatainre_table.ParseText(out)
got is a dictionary associating key labels, considered as usernames,
with a hexadecimal representation of the public key currently
installed. It looks like this:
Comparing with the wanted keys
Let s now build the wanted dictionary using the same structure. In
module.params['keys'], we have a dictionary associating usernames
to public SSH keys in the OpenSSH format:
Applying changes
Back to the skeleton described in the previous article, the last step is to apply the changes if there
is a difference between got and wanted when not running with check
mode. The part comparing got and wanted is taken verbatim from the
skeleton module:
Let s copy the new or changed keys and attach them to their respective
users. For this purpose, we reuse the get_connection() and
copy_file() functions from
ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.iosxr.
The complete code is available on GitHub. Compared to the
iosxr_user module, this one displays a diff when
running with --diff, correctly signals a change, is faster,
3 and deletes unwanted SSH keys. However, it is unable to
create users and cannot configure passwords or multiple SSH keys.
In our environment, the Ansible playbook pushes a full
configuration, including the user definitions. Then, it
synchronizes the SSH keys.
Despite the argument provided to ssh-keygen, the format
used by Cisco is not PKCS#8. This is the ASN.1 representation of a
Subject Public Key Info structure, as defined in RFC 2459.
Moreover, PKCS#8 is a format for a private key, not a public one.
Ansible ships a lot of modules you can combine for your configuration
management needs. However, the quality of these modules may vary
widely. Sometimes, it may be quicker and more robust to write your own
module instead of shopping and assembling existing
ones.1
In my opinion, a robust module exhibits the following characteristics:
idempotency,
diff support,
check mode compatibility,
correct change signaling, and
lifecycle management.
In a nutshell, it means the module can run with --diff --check and
shows the changes it would apply. When run twice in a row, the second
run won t apply or signal changes. The last bullet point suggests the
module should be able to delete outdated objects configured during
previous runs.2
The module code should be minimal and tailored to your needs. Making
the module generic for use by other users is a non-goal. Less code
usually means less bugs and easier to understand.
I do not cover testing here. It is undeniably a good practice, but it
requires a significant effort. In my opinion, it is preferable to have
a well written module matching the above characteristics rather than a
module that is well tested but without them or a module requiring
further (untested) assembly to meet your needs.
Module skeleton
Ansible documentation contains instructions to build a module,
along with some best practices. As one of our non-goal is to
distribute it, we choose to take some shortcuts and skip some of the
boilerplate. Let s assume we build a module with the following
signature:
There are various locations you can put a module in Ansible. A common
possibility is to include it into a role. In a library/
subdirectory, create an empty __init__.py file and a
custom_module.py file with the following code:3
#!/usr/bin/pythonimportyamlfromansible.module_utils.basicimportAnsibleModuledefmain():# Define options accepted by the module. module_args=dict(user=dict(type='str',required=True),password=dict(type='str',required=True,no_log=True),data=dict(type='str',required=True),)module=AnsibleModule(argument_spec=module_args,supports_check_mode=True)result=dict(changed=False)got=wanted=# Populate both got and wanted . # [...]ifgot!=wanted:result['changed']=Trueresult['diff']=dict(before=yaml.safe_dump(got),after=yaml.safe_dump(wanted))ifmodule.check_modeornotresult['changed']:module.exit_json(**result)# Apply changes. # [...]module.exit_json(**result)if__name__=='__main__':main()
The first part, in , defines the module, with the accepted
options. Refer to the documentation on
argument_spec for more details.
The second part, in , builds the got and wanted variables. got
is the current state while wanted is the target state. For
example, if you need to modify records in a database server, got
would be the current rows while wanted would be the modified rows.
Then, we compare got and wanted. If there is a difference,
changed is switched to True and we prepare the diff object.
Ansible uses it to display the differences between the states. If we
are running in check mode or if no change is detected, we stop here.
The last part, in , applies the changes. Usually, it means
iterating over the two structures to detect the differences and create
the missing items, delete the unwanted ones and update the existing
ones.
Documentation
Ansible provides a fairly complete page on how to document a
module. I advise you to take a more minimal approach by only
documenting each option sparingly,4 skipping the examples
and only documenting return values if it needs to. I usually limit
myself to something like this:
DOCUMENTATION="""---module: custom_module.pyshort_description: Pass provided data to remote servicedescription: - Mention anything useful for your workmate. - Also mention anything you want to remember in 6 months.options: user: description: - user to identify to remote service password: description: - password for authentication to remote service data: description: - data to send to remote service"""
Error handling
If you run into an error, you can stop the execution with
module.fail_json():
module.fail_json(msg=f"remote service answered with code: message",**result)
There is no requirement to intercept all errors. Sometimes, not
swallowing an exception provides better information than replacing it
with a generic message.
Returning additional values
A module may return additional information that can be captured to be
used in another task through the register directive.
For this purpose, you can add arbitrary fields to the result
dictionary. Have a look at the documentation for common return
values. You should try to add these fields before exiting the
module when in check mode. The returned values can be documented.
Examples
Here are several examples of custom modules following the previous
skeleton. Each example highlight why a custom module was written
instead of assembling existing modules.
Syncing RIPE, ARIN and APNIC objects (not released yet)
Syncing GCP IPsec VPNs (not done yet)
Also, when using modules from Ansible Galaxy, you
introduce a dependency to a third-party. This is not something
that should be decided lightly: it may break later, it may only
meet 80% of the needs, it may add bugs.
Some declarative systems, like Terraform, exhibits
all these behaviors.
Do not worry about the shebang. It is hardcoded to
/usr/bin/python. Ansible will modify it to match the chosen
interpreter on the remote host. You can write Python 3 code if
ansible_python_interpreter evaluates to a Python 3 interpreter.
The main issue I have with this non-programmatic
approach to documentation is that it partly repeats the
information contained in argument_spec. I think an
auto-documenting structure would avoid this.
Here is my transparent report for my work on the Debian Long Term Support (LTS) and Debian Extended Long Term Support (ELTS), which extend the security support for past Debian releases, as a paid contributor.
In August, the monthly sponsored hours were split evenly among contributors depending on their max availability - I was assigned 21.75h for LTS (out of my 30 max; all done) and 14.25h for ELTS (out of my 20 max; all done).
We had a Birds of a Feathervideoconfsession at DebConf20, sadly with varying quality for participants (from very good to unusable), where we shared the first results of the LTS survey.
There were also discussions about evaluating our security reactivity, which proved surprisingly hard to estimate (neither CVE release date and criticality metrics are accurate nor easily available), and about when it is appropriate to use public naming in procedures.
Interestingly ELTS gained new supported packages, thanks to a new sponsor -- so far I'd seen the opposite, because we were close to the EOL.
As always, there were opportunities to de-dup work through mutual cooperation with the Debian Security team, and LTS/ELTS similar updates.
ELTS - Jessie
Fresh build VMs
rails/redmine: investigate issue, initially no-action as it can't be reproduced on Stretch and isn't supported in Jessie; follow-up when it's supported again
ghostscript: global triage: identify upstream fixed version, distinguish CVEs fixed within a single patch, bisect non-reproducible CVEs, reference missing commit (including at MITRE)
approved deletion of
opencc (screenshot of the github repo),
telegram-desktop (low quality)
rejected deletion of
mumble (screenshots are versioned),
audacious (keyboard mash),
apache2/hashcat/onboard/jack-keyboard/kcharselect/inxi (spam reason)
Administration
Debian:
restarted RAM eating service
Debian wiki:
unblock IP addresses,
approve accounts
Sponsors
The cython-blis/preshed/thinc/theano bugs and smart-open/python-importlib-metadata/python-pyfakefs/python-zipp/python-threadpoolctl backports were sponsored by my employer.
All other work was done on a volunteer basis.
Here is another monthly update covering what I have been doing in the free software world during August 2020 (previous month):
Filed a pull request against django-enumfield, a library that provides an enumeration-like model field for the Django web development framework. The classproperty helper has been moved to django.utils.functional in newer versions of Django. [...]
As part of my role of being the assistant Secretary of the Open Source Initiative and a board director of Software in the Public Interest, I attended their respective monthly meetings and participated in various licensing and other discussions occurring on the internet, as well as the usual internal discussions, etc.
Filed a pull request for JSON-C, a reference counting library to allow you to easily manipulate JSON objects from C in order to make the documentation build reproducibly. [...]
Reviewed and merged some changes to my django-auto-one-to-one library for Django from Dan Palmer
(which automatically creates and destroys associated model instances) to not configure signals for models that aren't installed and to honour INSTALLED_APPS during model setup. [...]
Merged a pull request from Michael K. to cleanup the codebase after dropping support for Python 2 and Django 1.x [...] in my django-slack library which provides a convenient wrapper between projects using the Django and the Slack chat platform.
Updated my django-staticfiles-dotd utility that concatenates Debian .d-style directories containing Javascript and CSS to drop unquote usage from the six compatibility library. [...]
I uploaded Lintian versions 2.86.0, 2.87.0, 2.88.0, 2.89.0, 2.90.0, 2.91.0 and 2.92.0, as well as made the following changes:
New features:
Check for StandardOutput= and StandardError= fields that use the deprecated syslog or syslog-consolesystemd facilities. (#966617)
Add support for clzip as an alternative for lzip. (#967083)
Check for User=nobody and Group=nogroup in systemd.service files. (#966623)
Update link to the detagtive web interface code as it has been moved to the lintian salsa namespace. [...]
Drop the misleading "Beta testing" from the webpage header. [...]
Misc:
Add justification for the use of the lzip dependency in a previous debian/changelog entry. (#966817)
Update the generate-tag-summary release script to reflect change of tag definition filename extension change from .desc.tag. [...]
Revert a change to the spelling-error-in-rules-requires-root tag's severity; this is not a "spelling" check in the sense that it does not use our dictionary. [...]
Drop an unused $skip_tag argument in the extract_service_file_values routine. [...]
Reproducible Builds
One of the original promises of open source software is that distributed peer review and transparency of process results in enhanced end-user security. However, whilst anyone may inspect the source code of free and open source software for malicious flaws, almost all software today is distributed as pre-compiled binaries. This allows nefarious third-parties to compromise systems by injecting malicious code into ostensibly secure software during the various compilation and distribution processes.
The motivation behind the Reproducible Builds effort is to ensure no flaws have been introduced during this compilation process by promising identical results are always generated from a given source, thus allowing multiple third-parties to come to a consensus on whether a build was compromised.
The project is proud to be a member project of the Software Freedom Conservancy. Conservancy acts as a corporate umbrella allowing projects to operate as non-profit initiatives without managing their own corporate structure. If you like the work of the Conservancy or the Reproducible Builds project, please consider becoming an official supporter.
Responded at length to a discussion about the status of the reproducibility of ISO images [...], wrote back to the maintainer of WalletScrutiny asking why Android developers appear to be "allergic" to their application not being reproducible [...] and passed on an issue about the diffoscope website being down [...]. I also added a few short remarks on a proposal to bundle .buildinfo files within .deb archives [...].
This month, I:
Filed a pull request for JSON-C, a reference counting library to allow you to easily construct JSON objects from C in order to make the documentation build reproducibly. [...]
Categorised a large number of packages and issues in the Reproducible Builds "notes" repository.
Filed a build-failure bug against the muroar package that was discovered while doing reproducibility testing. (#968189)
We operate a large and many-featured Jenkins-based testing framework that powers tests.reproducible-builds.org. This month, I updated the self-serve package rescheduler to use HTML <pre> tags when dumping any debugging data. [...]
diffoscope
I made the following changes to diffoscope, including preparing and uploading versions 155, 156, 157 and 158 to Debian:
New features:
Support extracting data of PGP signed data. (#214)
Try files named .pgp against pgpdump(1) to determine whether they are Pretty Good Privacy (PGP) files. (#211)
Support multiple options for all file extension matching. [...]
Bug fixes:
Don't raise an exception when we encounter XML files with <!ENTITY> declarations inside the Document Type Definition (DTD), or when a DTD or entity references an external resource. (#212)
pgpdump(1) can successfully parse some binary files, so check that the parsed output contains something sensible before accepting it. [...]
Temporarily drop gnumeric from the Debian build-dependies as it has been removed from the testing distribution. (#968742)
Correctly use fallback_recognises to prevent matching .xsb binary XML files.
Correct identify signed PGP files as file(1) returns "data". (#211)
Logging improvements:
Emit a message when ppudump version does not match our file header. [...]
Don't use Python's repr(object) output in "Calling external command" messages. [...]
Include the filename in the "... not identified by any comparator" message. [...]
Codebase improvements:
Bump Python requirement from 3.6 to 3.7. Most distributions are either shipping with Python 3.5 or 3.7, so supporting 3.6 is not only somewhat unnecessary but also cumbersome to test locally. [...]
Drop some unused imports [...], drop an unnecessary dictionary comprehensions [...] and some unnecessary control flow [...].
Frontdesk duties, responding to user/developer questions, reviewing others' packages, participating in mailing list discussions, attending the Debian LTS BoF at DebConf20 etc.
Issued ELA-263-1 for qtbase-opensource-src and ELA-261-1 for qt4-x11, two components of cross-platform C++ application framework. A specially-crafted XBM image file could have caused a buffer overread.
Issued ELA-268-1 to address unsafe serialisation vulnerabilities that were discovered in the PHP-based squirrelmail webmail client.
Issued DLA 2311-1 for zabbix, the PHP-based monitoring system to fix a potential cross-site scripting vulnerability via <iframe> HTML elements.
Issued DLA 2334-1 to fix a denial of service vulnerability in ruby-websocket-extensions, a library for managing long-lived HTTP 'WebSocket' connections.
Issued DLA 2345-1 for PHP 7.0 as it was discovered that there was a use-after-free vulnerability when parsing PHAR files, a method of putting entire PHP applications into a single file.
I also updated the Extended LTS website to pluralise the "Related CVEs" text in announcement emails [...] and dropped some trailing whitespace [...].
You can find out more about the project via the following video:
What is this thing?
When you first open a command-line (note that I use the terms command-line
and shell interchangably here, they re basically the same, but command-line
is the more general term, and shell is the name for the program that executes
commands for you)
you ll see something like this:
This line is called a command prompt and it tells you four pieces of information:
jaadams: The username of the user that is currently running this shell.
bg7: The name of the computer that this shell is running on, important
for when you start accessing shells on remote machines.
/tmp/thisfolder: The folder or directory that your shell is currently
running in. Like a file explorer (like Window s Explorer or Mac s Finder) a
shell always has a working directory, from which all relative paths (see
sidenote below) are resolved.
When you first opened a shell, however, you might notice that is looks more
like this:
This is a shorthand notation that the shell uses to make this output shorter
when possible. ~ stands for your home directory, usually /home/<username>.
Like C:\Users\<username>\ on Windows or /Users/<username> on Mac,
this directory is where all your files should go by default.
Thus a command prompt like this:
actually tells you that you are currently in the /home/jaadams/Downloads
directory.
Sidenote: The Unix Filesystem and Relative Paths
folders on Linux and other Unix-derived systems like MacOS are usually
called directories.
These directories are represented by paths, strings that indicate where the
directory is on the filesystem.
The one unusual part is the so-called root directory .
All files are stored in this folder or directories under it.
Its path is just / and there are no directories above it.
For example, the directory called home typically contains all user directories.
This is stored in the root directory, and each users specific data
is stored in a directory named after that user under home.
Thus, the home directory of the user jacob is typically /home/jacob,
the directory jacob under the
home directory stored in the root directory /.
If you re interested in more details about what goes in what directory,
man hier has the basics and the
Filesystem Hierarchy Standard
governs the layout of the filesystem on most Linux distributions.
You don t always have to use the full path, however.
If the path does not begin with a /, it is assumed that the path actually
begins with the path of the current directory.
So if you use a path like my/folders/here, and you re in the /home/jacob
directory, the path will be treated like /home/jacob/my/folders/here.
Each folder also contains the symbolic links .. and ..
Symbolic links are a very powerful kind of
file that is actually a reference to another file.
.. always represents the parent directory
of the current directory, so /home/jacob/.. links to /home/.
. always links to the current directory, so /home/jacob/. links to
/home/jacob.
Running commands
To run a command from the command prompt, you type its name and then
usually some arguments to tell it what to do.
For example, the echo command displays the text passed as arguments.
jacob@lovelace/home/jacob$ echo hello world
hello world
Arguments to commands are space-separated, so in the previous example hello
is the first argument and world is the second. If you need an argument to
contain spaces, you ll want to put quotes around it, echo "like so".
Certain arguments are called flags , or options (options if they take another
argument, flags otherwise) usually prefixed with a hyphen,
and they change the way a program operates.
For example, the ls command outputs the contents of a directory passed as
an argument, but if you add -l before the directory, it will give you more
details on the files in that directory.
jacob@lovelace/tmp/test$ ls /tmp/test
1 2 3 4 5 6
jacob@lovelace/tmp/test$ ls -l /tmp/test
total 0
-rw-r--r-- 1 jacob jacob 0 Aug 26 22:06 1
-rw-r--r-- 1 jacob jacob 0 Aug 26 22:06 2
-rw-r--r-- 1 jacob jacob 0 Aug 26 22:06 3
-rw-r--r-- 1 jacob jacob 0 Aug 26 22:06 4
-rw-r--r-- 1 jacob jacob 0 Aug 26 22:06 5
-rw-r--r-- 1 jacob jacob 0 Aug 26 22:06 6
jacob@lovelace/tmp/test$
Most commands take different flags to change their behavior in various ways.
File Management
cd <path>: Change the current directory of the running shell to <path>.
ls <path>: Output the contents of <path>. If no path is passed, it prints
the contents of the current directory.
touch <filename>: create an new empty file called <filename>.
Used on an existing file, it updates the file s last accessed and modified times.
Most text editors can also create a new file for you, which is probably more useful.
mkdir <directory>: Create a new folder/directory at path <directory>.
mv <src> <dest>: Move a file or directory at path <src> to <dest>.
cp <src> <dest>: Copy a file or directory at path <src> to <dest>.
rm <file>: Remove a file at path <file>.
zip -r <zipfile> <contents...>: Create a zip file <zipfile> with contents
<contents>. <contents> can be multiple arguments, and you ll usually want
to use the -r argument when including directories in your zipfile, as otherwise
only the directory will be included and not the files and directories within it.
Searching
grep <thing> <file>: Look for the string <thing> in <file>.
If no <file> is passed it searches standard input.
find <path> -name <name>: Find a file or directory called <name> somwhere
under <path>. This command is actually very powerful, but also very complex.
For example you can delete all files in a directory older than 30 days with:
find -mtime +30 -exec rm \;
locate <name>: A much easier to use command to find a file with a given
name, but it is not usually installed by default.
Outputting Files
cat <files...>: Output (concatenate) all the files passed as arguments.
head <file>: Output the beginning of <file>
tail <file>: Output the end of <file>
How to Find the Right Command
All commands (at least on sane Linux distributions like Debian or Ubuntu)
are documented with a manual page, in man section 1 (for more information on
manual sections, run man intro).
This can be accessed using man <command>
You can search for the right command using the -k flag, as in man -k <search>.
You can also view manual pages in your browser, on sites like https://manpages.debian.org
or https://linux.die.net/man.
This is not always helpful, however, because some command s descriptions are
not particularly useful, and also there are a lot of manual pages, which can
make searching for a specific one difficult. For example, finding the right
command to search inside text files is quite difficult via man (it s grep).
When you can t find what you need with man I recommend falling back to
searching the Internet. There are lots of bad Linux tutorials out there, but
here are some reputable sources I recommend:
Hosting providers like Digital Ocean or Linode: Good intro documentation, but
can sometimes be outdated
https://tldp.org: The Linux Documentation project is great, but it can also be a little
outdated sometimes.
https://stackoverflow.com: Oftentimes has great answers, but quality varies wildly
since anyone can answer.
These are certainly not the only options but they re the sources I would
recommend when available.
How to Read a Manual Page
Manual pages consist of a series of sections, each with a specific purpose.
Instead of attempting to write my own description here, I m going to borrow
the excellent one from The Linux Documentation Project
The NAME section
is the only required section. Man pages without a name section are as useful as refrigerators at the north pole. This section also has a standardized format consisting of a comma-separated list of program or function names, followed by a dash, followed by a short (usually one line) description of the functionality the program (or function, or file) is supposed to provide. By means of makewhatis(8), the name sections make it into the whatis database files. Makewhatis is the reason the name section must exist, and why it must adhere to the format I described.
(Formatting explanation cut for brevity)
The SYNOPSIS section
is intended to give a short overview on available program options. For functions this sections lists corresponding include files and the prototype so the programmer knows the type and number of arguments as well as the return type.
The DESCRIPTION section
eloquently explains why your sequence of 0s and 1s is worth anything at all. Here s where you write down all your knowledge. This is the Hall Of Fame. Win other programmers and users admiration by making this section the source of reliable and detailed information. Explain what the arguments are for, the file format, what algorithms do the dirty jobs.
The OPTIONS section
gives a description of how each option affects program behaviour. You knew that, didn t you?
The FILES section
lists files the program or function uses. For example, it lists configuration files, startup files, and files the program directly operates on.
(Cut details about installing files)
The ENVIRONMENT section
lists all environment variables that affect your program or function and tells how, of course. Most commonly the variables will hold pathnames, filenames or default options.
The DIAGNOSTICS section
should give an overview of the most common error messages from your program and how to cope with them. There s no need to explain system error error messages (from perror(3)) or fatal signals (from psignal(3)) as they can appear during execution of any program.
The BUGS section
should ideally be non-existent. If you re brave, you can describe here the limitations, known inconveniences and features that others may regard as misfeatures. If you re not so brave, rename it the TO DO section ;-)
The AUTHOR section
is nice to have in case there are gross errors in the documentation or program behaviour (Bzzt!) and you want to mail a bug report.
The SEE ALSO section
is a list of related man pages in alphabetical order. Conventionally, it is the last section.
Remote Access
One of the more powerful uses of the shell is through ssh, the secure shell.
This allows you to remotely connect to another computer and run a shell on that
machine:
The prompt changes to reflect the change in user and host,
as you can see in the example above.
This allows you to work in a shell on that machine as if it was right in front
of you.
Moving Files Between Machines
There are several ways you can move files between machines over ssh.
The first and easiest is scp, which works much like the cp command
except that paths can also take a user@host argument to move files across
computers. For example, if you wanted to move a file test.txt to your
home directory on another machine, the command would look like:
scp test.txt other@example.com:
(The home directory is the default path)
Otherwise you can move files by reversing the order of the arguments
and put a path after the colon to move files from another directory on the
remote host. For example, if you wanted to fetch the file /etc/issue.net
from example.com:
scp other@example.com:/etc/issue.net .
Another option is the sftp command, which gives you a very simple shell-like
interface in which you can cd and ls, before either puting files onto
the local machine or geting files off of it.
The final and most powerful option is rsync which syncs the contents of one
directory to another, and doesn t copy files that haven t changed. It s powerful
and complex, however, so I recommend reading the USAGE section of its man page.
Long-Running Commands
The one problem with ssh is that it will stop any command running in your
shell when you disconnect. If you want to leave something on and come back
later then this can be a problem.
This is where terminal multiplexers come in. tmux and screen both allow
you to run a shell in a safe environment where it will continue even if you
disconnect from it. You do this by running the command without any arguments,
i.e. just tmux or just screen.
In tmux you can disconnect from the current session by
pressing Ctrl+b then d, and reattach with the tmux attach command.
screen works similarly, but with Ctrl+a instead of b and screen -r to
reattach.
Command Inputs and Outputs
Arguments are not the only way to pass input to a command. They can also take
input from what s called standard input , which the shell usually connects to
your keyboard.
Output can go to two places, standard output and standard error, both of which
are directed to the screen by default.
Redirecting I/O
Note that I said above that standard input/output/error are only usually
connected to the keyboard and the terminal? This is because you can redirect
them to other places with the shell operators <, > and the very powerful .
File redirects
The operators < and > redirect the input and output of a command to a file.
For example, if you wanted a file called list.txt that contained a list of
all the files in a directory /this/one/here you could use:
ls /this/one/here > list.txt
Pipelines
The pipe character, , allows you to direct the output of one command into
the input of another. This can be very powerful.
For example, the following pipeline lists the contents of the current directory
searches for the string test , then counts the number of results.
(wc -l counts the number of lines in its input)
ls grep test wc -l
For a better, but even more contrived example, say you have a file myfile,
with a bunch of lines of potentially duplicated and unsorted data
test
test
1234
4567
1234
You can sort it and output only the unique lines with sort and uniq:
$ uniq < myfile sort
1234
1234
4567
test
Save Yourself Some Typing: Globs and Tab-Completion
Sometimes you don t want to type out the whole filename when writing out a
command. The shell can help you here by autocompleting when you press the tab
key.
If you have a whole bunch of files with the same suffix, you can refer to them
when writing arguments as *.suffix. This also works with prefixes, prefix*,
and in fact you can put a * anywhere, *middle*. The shell will expand that
* into all the files in that directory that match your criteria
(ending with a specific suffix, starting with a specific prefix, and so on)
and pass each file as a separate argument to the command.
For example, if I have a series of files called 1.txt, 2.txt, and so on
up to 9, each containing just the number for which it s named, I could use
cat to output all of them like so:
Also the ~ shorthand mentioned above that refers to your home directory
can be used when passing a path as an argument to a command.
Ifs and For loops
The files in the above example were generated with the following shell
commands:
for i in 1 2 3 4 5 6 7 8 9
do
echo $i > $i.txt
done
But I ll have to save variables, conditionals and loops for another day because
this is already too long. Needless to say the shell is a full programming
language, although a very ugly and dangerous one.
Dealing with the void during MiniDebConf Online #1
Between 28 and 31 May this year, we set out to create our first ever online MiniDebConf for Debian. Many people have been meaning to do something similar for a long time, but it just didn t work out yet. With many of us being in lock down due to COVID-19, and with the strong possibility looming that DebConf20 might have had to become an online event, we rushed towards organising the first ever Online MiniDebConf and put together some form of usable video stack for it.
I could go into all kinds of details on the above, but this post is about a bug that lead to a pretty nifty feature for DebConf20. The tool that we use to capture Jitsi calls is called Jibri (Jitsi Broadcasting Infrustructure). It had a bug (well, bug for us, but it s an upstream feature) where Jibri would hang up after 30s of complete silence, because it would assume that the call has ended and that the worker can be freed up again. This would result in the stream being ended at the end of every talk, so before the next talk, someone would have to remember to press play again in their media player or on the video player on the stream page. Hrmph.
Easy solution on the morning that the conference starts? I was testing a Debian Live image the night before in a KVM and thought that I might as well just start a Jitsi call from there and keep a steady stream of silence so that Jibri doesn t hang up.
It worked! But the black screen and silence on stream was a bit eery. Because this event was so experimental in nature, and because we were on such an incredibly tight timeline, we opted not to seek sponsors for this event, so there was no sponsors loop that we d usually stream during a DebConf event. Then I thought Ah! I could just show the schedule! .
The stream looked bright and colourful (and was even useful!) and Jitsi/Jibri didn t die. I thought my work was done. As usual, little did I know how untrue that was.
The silence was slightly disturbing after the talks, and people asked for some music. Playing music on my VM and capturing the desktop audio in to Jitsi was just a few pulseaudio settings away, so I spent two minutes finding some freely licensed tracks that sounded ok enough to just start playing on the stream. I came across mini-albums by Captive Portal and Cinema Noir, During the course of the MiniDebConf Online I even started enjoying those. Someone also pointed out that it would be really nice to have a UTC clock on the stream. I couldn t find a nice clock in a hurry so I just added a tmux clock in the meantime while we deal with the real-time torrent of issues that usually happens when organising events like this.
Speaking of issues, during our very first talk of the last day, our speaker had a power cut during the talk and abruptly dropped off. Oops! So, since I had a screenshare open from the VM to the stream, I thought I d just pop in a quick message in a text editor to let people know that we re aware of it and trying to figure out what s going on.
In the end, MiniDebConf Online worked out all right. Besides the power cut for our one speaker, and another who had a laptop that was way too under-powered to deal with video, everything worked out very well. Even the issues we had weren t show-stoppers and we managed to work around them.
DebConf20 Moves Online
For DebConf, we usually show a sponsors loop in between sessions. It s great that we give our sponsors visibility here, but in reality people see the sponsors loop and think Talk over! and then they look away. It s also completely silent and doesn t provide any additional useful information. I was wondering how I could take our lessons from MDCO#1 and integrate our new tricks with the sponsors loop. That is, add the schedule, time, some space to type announcements on the screen and also add some loopable music to it.
I used OBS before in making my videos, and like the flexibility it provides when working with scenes and sources. A scene is what you would think of as a screen or a document with its own collection of sources or elements. For example, a scene might contain sources such as a logo, clock, video, image, etc. A scene can also contain another scene. This is useful if you want to contain a banner or play some background music that is shared between scenes.
The above screenshots illustrate some basics of scenes and sources. First with just the DC20 banner, and then that used embedded in another scene.
For MDCO#1, I copied and pasted the schedule into a LibreOffice Impress slide that was displayed on the stream. Having to do this for all 7 days of DebConf, plus dealing with scheduling changes would be daunting. So, I started to look in to generating some schedule slides programmatically. Stefano then pointed me to the Happening Now page on the DebConf website, where the current schedule block is displayed. So all I would need to do in OBS was to display a web page. Nice!
Unfortunately the OBS in Debian doesn t have the ability to display web pages out of the box (we need to figure out CEF in Debian), but fortunately someone provides a pre-compiled version of the plugin called Linux Browser that works just fine. This allowed me to easily add the schedule page in its own scene.
Being able to display a web page solved another problem. I wasn t fond of having to type / manage the announcements in OBS. It would either be a bit prone to user error, and if you want to edit the text while the loop is running, you d have to disrupt the loop, go to the foreground scene, and edit the text before resuming the loop. That s a bit icky. Then I thought that we could probably just get that from a web page instead. We could host some nice html snippet in a repository in salsa, and then anyone could easily commit an MR to update the announcement.
But then I went a step further, use an etherpad! Then anyone in the orga team can quickly update the announcement and it would be instantly changed on the stream. Nice! So that small section of announcement text on the screen is actually a whole web browser with an added OBS filter to crop away all the pieces we don t want. Overkill? Sure, but it gave us a decent enough solution that worked in time for the start of DebConf. Also, being able to type directly on to the loop screen works out great especially in an emergency. Oh, and uhm the clock is also a website rendered in its own web browser :-P
So, I had the ability to make scenes, add elements and add all the minimal elements I wanted in there. Great! But now I had to figure out how to switch scenes automatically. It s probably worth mentioning that I only found some time to really dig into this right before DebConf started, so with all of this I was scrambling to find things that would work without too many bugs while also still being practical.
Now I needed the ability to switch between the scenes automatically / programmatically. I had never done this in OBS before. I know it has some API because there are Android apps that you can use to control OBS with from your phone. I discovered that it had an automatic scene switcher, but it s very basic. It can only switch based on active window, which can be useful in some cases, but since we won t have any windows open other than OBS, this tool was basically pointless.
After some quick searches, I found a plugin called Advanced Scene Switcher. This plugin can do a lot more, but has some weird UI choices, and is really meant for gamers and other types of professional streamers to help them automate their work flow and doesn t seem at all meant to be used for a continuous loop, but, it worked, and I could make it do something that will work for us during the DebConf.
I had a chicken and egg problem because I had to figure out a programming flow, but didn t really have any content to work with, or an idea of all the content that we would eventually have. I ve been toying with the idea in my mind and had some idea that we could add fun facts, postcards (an image with some text), time now in different timezones, Debian news (maybe procured by the press team), cards that contain the longer announcements that was sent to debconf-announce, perhaps a shout out or two and some photos from previous DebConfs like the group photos. I knew that I wouldn t be able to build anything substantial by the time DebConf starts, but adding content to OBS in between talks is relatively easy, so we could keep on building on it during DebConf.
Nattie provided the first shout out, and I made 2 video loops with the DC18/19 pictures and also two Did you know cards. So the flow I ended up with was: Sponsors -> Happening Now -> Random video (which would be any of those clips) -> Back to sponsors. This ended up working pretty well for quite a while. With the first batch of videos the sponsor loop would come up on average about every 2 minutes, but as much shorter clips like shout outs started to come in faster and faster, it made sense to play a few 2-3 shout-outs before going back to sponsors.
So here is a very brief guide on how I set up the sequencing in Advanced Scene Switcher.
If no condition was met, a video would play from the Random tab.
Then in the Random tab, I added the scenes that were part of the random mix. Annoyingly, you have to specify how long it should play for. If you don t, the no condition thingy is triggered and another video is selected. The time is also the length of the video minus one second, because
You can t just say that a random video should return back to a certain scene, you have to specify that in the sequence tab for each video. Why after 1 second? Because, at least in my early tests, and I didn t circle back to this, it seems like 0s can randomly either mean instantly, or never. Yes, this ended up being a bit confusing and tedious, and considering the late hours I worked on this, I m surprised that I didn t manage to screw it up completely at any point.
I also suspected that threads would eventually happen. That is, when people create video replies to other videos. We had 3 threads in total. There was a backups thread, beverage thread and an impersonation thread. The arrow in the screenshot above points to the backups thread. I know it doesn t look that complicated, but it was initially somewhat confusing to set up and make sense out of it.
For the next event, the Advanced Scene Switcher might just get some more taming, or even be replaced entirely. There are ways to drive OBS by API, and even the Advanced Scene Switcher tool can be driven externally to some degree, but I think we definitely want to replace it by the next full DebConf. We had the problem that when a talk ended, we would return to the loop in the middle of a clip, which felt very unnatural and sometimes even confusing. So Stefano helped me with a helper script that could read the socket from Vocto, which I used to write either Loop or Standby to a file, and then the scene switcher would watch that file and keep the sponsors loop ready for start while the talks play. Why not just switch to sponsors when the talk ends? Well, the little bit of delay in switching would mean that you would see a tiny bit of loop every time before switching to sponsors. This is also why we didn t have any loop for the ad-hoc track (that would have probably needed another OBS instance, we ll look more into solutions for this for the future).
Then for all the clips. There were over 50 of them. All of them edited by hand in kdenlive. I removed any hard clicks, tried to improve audibility, remove some sections at the beginning and the end that seemed extra and added some music that would reduce in volume when someone speaks. In the beginning, I had lots of fun with choosing music for the clips. Towards the end, I had to rush them through and just chose the same tune whether it made sense or not. For comparison of what a difference the music can make, compare the original and adapted version for Valhalla s clip above, or this original and adapted video from urbec. This part was a lot more fun than dealing with the video sequencer, but I also want to automate it a bit. When I can fully drive OBS from Python I ll likely instead want to show those cards and control music volume from Python (what could possibly go wrong ).
The loopy name happened when I requested an @debconf.org alias for this. I was initially just thinking about loop@debconf.org but since I wanted to make it clear that the purpose of this loop is also to have some fun, I opted for loopy instead:
I was really surprised by how people took to loopy. I hoped it would be good and that it would have somewhat positive feedback, but the positive feedback was just immense. The idea was that people typically saw it in between talks. But a few people told me they kept it playing after the last talk of the day to watch it in the background. Some asked for the music because they want to keep listening to it while working (and even for jogging!?). Some people also asked for recordings of the loop because they want to keep it for after DebConf. The shoutouts idea proved to be very popular. Overall, I m very glad that people enjoyed it and I think it s safe to say that loopy will be back for the next event.
Also throughout this experiment Loopy Loop turned into yet another DebConf mascot. We gain one about every DebConf, some by accident and some on purpose. This one was not quite on purpose. I meant to make an image for it for salsa, and started with an infinite loop symbol. That s a loop, but by just adding two more solid circles to it, it looks like googly eyes, now it s a proper loopy loop!
I like the progress we ve made on this, but there s still a long way to go, and the ideas keep heaping up. The next event is quite soon (MDCO#2 at the end of November, and it seems that 3 other MiniDebConf events may also be planned), but over the next few events there will likely be significantly better graphics/artwork, better sequencing, better flow and more layout options. I hope to gain some additional members in the team to deal with incoming requests during DebConf. It was quite hectic this time! The new OBS also has a scripting host that supports Python, so I should be able to do some nice things even within OBS without having to drive it externally (like, display a clock without starting a web browser).
The Loopy Loop Music
The two mini albums that mostly played during the first few days were just a copy and paste from the MDCO#1 music, which was:
I have much more things to say about DebConf20, but I ll keep that for another post, and hopefully we can get all the other video stuff in a post from the video team, because I think there s been some real good work done for this DebConf. Also thanks to Infomaniak who was not only a platinum sponsor for this DebConf, but they also provided us with plenty of computing power to run all the video stuff on. Thanks again!
On Saturday 29 August 2020, the annual Debian Developers
and Contributors Conference came to a close.
DebConf20 has been held online for the first time, due to the coronavirus
(COVID-19) disease pandemic.
All of the sessions have been streamed, with a variety of ways of participating:
via IRC messaging, online collaborative text documents,
and video conferencing meeting rooms.
With more than 850 attendees from 80 different countries and a
total of over 100 event talks, discussion sessions,
Birds of a Feather (BoF) gatherings and other activities,
DebConf20 was a large success.
When it became clear that DebConf20 was going to be an online-only
event, the DebConf video team spent much time over the next months to
adapt, improve, and in some cases write from scratch, technology that
would be required to make an online DebConf possible. After lessons
learned from the MiniDebConfOnline in late May, some adjustments were
made, and then eventually we came up with a setup involving Jitsi, OBS,
Voctomix, SReview, nginx, Etherpad, and a newly written web-based
frontend for voctomix as the various elements of the stack.
All components of the video infrastructure are free software, and the
whole setup is configured through their public
ansible repository.
The DebConf20 schedule included
two tracks in other languages than English: the Spanish language MiniConf,
with eight talks in two days,
and the Malayalam language MiniConf, with nine talks in three days.
Ad-hoc activities, introduced by attendees over the course of the entire conference,
have been possible too, streamed and recorded. There have also been several
team gatherings to sprint on certain Debian development areas.
Between talks, the video stream has been showing the usual sponsors on the loop, but also
some additional clips including photos from previous DebConfs, fun facts about Debian
and short shout-out videos sent by attendees to communicate with their Debian friends.
For those who were not able to participate, most of the talks and sessions are already
available through the
Debian meetings archive website,
and the remaining ones will appear in the following days.
The DebConf20 website
will remain active for archival purposes and will continue to offer
links to the presentations and videos of talks and events.
Next year, DebConf21 is planned to be held
in Haifa, Israel, in August or September.
DebConf is committed to a safe and welcome environment for all participants.
During the conference, several teams (Front Desk, Welcome team and Community team)
have been available to help so participants get their best experience
in the conference, and find solutions to any issue that may arise.
See the web page about the Code of Conduct in DebConf20 website
for more details on this.
Debian thanks the commitment of numerous sponsors
to support DebConf20, particularly our Platinum Sponsors:
Lenovo,
Infomaniak,
Google
and
Amazon Web Services (AWS).
About Debian
The Debian Project was founded in 1993 by Ian Murdock to be a truly
free community project. Since then the project has grown to be one of
the largest and most influential open source projects. Thousands of
volunteers from all over the world work together to create and
maintain Debian software. Available in 70 languages, and
supporting a huge range of computer types, Debian calls itself the
universal operating system.
About DebConf
DebConf is the Debian Project's developer conference. In addition to a
full schedule of technical, social and policy talks, DebConf provides an
opportunity for developers, contributors and other interested people to
meet in person and work together more closely. It has taken place
annually since 2000 in locations as varied as Scotland, Argentina, and
Bosnia and Herzegovina. More information about DebConf is available from
https://debconf.org/.
About Lenovo
As a global technology leader manufacturing a wide portfolio of connected products,
including smartphones, tablets, PCs and workstations as well as AR/VR devices,
smart home/office and data center solutions, Lenovo
understands how critical open systems and platforms are to a connected world.
About Infomaniak
Infomaniak is Switzerland's largest web-hosting company,
also offering backup and storage services, solutions for event organizers,
live-streaming and video on demand services.
It wholly owns its datacenters and all elements critical
to the functioning of the services and products provided by the company
(both software and hardware).
About Google
Google is one of the largest technology companies in the
world, providing a wide range of Internet-related services and products such
as online advertising technologies, search, cloud computing, software, and hardware.
Google has been supporting Debian by sponsoring DebConf for more than
ten years, and is also a Debian partner sponsoring parts
of Salsa's continuous integration infrastructure
within Google Cloud Platform.
About Amazon Web Services (AWS)
Amazon Web Services (AWS) is one of the world's
most comprehensive and broadly adopted cloud platforms,
offering over 175 fully featured services from data centers globally
(in 77 Availability Zones within 24 geographic regions).
AWS customers include the fastest-growing startups, largest enterprises
and leading government agencies.
Contact Information
For further information, please visit the DebConf20 web page at
https://debconf20.debconf.org/
or send mail to press@debian.org.
Like each month, albeit a bit later due to vacation, here comes a report about the work of paid contributors to Debian LTS.
Individual reports
In July, 249.25 work hours have been dispatched among 14 paid contributors. Their reports are available:
Abhijith PA did 18.0h (out of 14h assigned and 6h from June), and gave back 2h to the pool.
Adrian Bunk did 16.0h (out of 25.25h assigned), thus carrying over 9.25h to August.
Ben Hutchings did 5h (out of 20h assigned), and gave back the remaining 15h.
Evolution of the situation
July was our first month of Stretch LTS! Given this is our fourth LTS release
we anticipated a smooth transition and it seems everything indeed went very well.
Many thanks to the members of the Debian ftpmaster-, security, release- and publicity-
teams who helped us make this happen!
Stretch LTS begun on July 18th 2020 after the
13th and final Stretch point release. and is currently scheduled to end on
June 30th 2022.
Last month, we asked you to participate in a survey and we got 1764 submissions, which is pretty awesome.
Thank you very much for participating!. Right now we are still busy crunching the results, but we already shared some early analysis during the Debconf LTS bof this week.
The security tracker currently lists 54 packages with a known CVE and the dla-needed.txt file has 52 packages needing an update.
Thanks to our sponsors
New sponsors are in bold.
Welcome to the 29th post in the randomly repeating R recommendations series or R4 for short. Our last post #28 introduced RSPM, and just before that we also talked in #27 about binary installations on Ubuntu (which was also a T4 video). This post is joined with I aki Ucar and mainly about work we have done with his bspm package.
Background
CRAN has been a cornerstone of the success of R in recent years. As a well-maintained repository with stringent quality control, it ensures users have access to highest-quality statistical / analytical software that just works . Users on Windows and macOS also benefit from faster installation via pre-compiled binary packages.
Linux users generally install from source, which can be more tedious and, often, much slower. Those who know where to look have had access to (at least some) binaries for years as well (and one of us blogged and vlogged about this at length). Debian users get close to 1000 CRAN and BioConductor packages (and, true to Debian form, for well over a dozen hardware platforms). Michael Rutter maintains a PPA with 4600 binaries for three different Ubuntu flavors (see c2d4u4.0+). More recently, Fedora joined the party with 16000 (!!) binaries, essentially all of CRAN, via a Copr repository (see iucar/cran).
The buzz currently is however with RSPM, a new package manager by RStudio. An audacious project, it provides binaries for several Linux distributions and releases. It has already been tested in many RStudio Cloud sessions (including with some of our students) as well as some CI integrations.
RSPM cuts across and takes the breadth of CRAN across several Linux distributions, bringing installation of pre-built CRAN packages a binaries under their normal CRAN package names. Another nice touch is the integration with install.packages(): these binaries are installed in a way that is natural for R users but as binaries. It is however entirely disconnected from the system package management. This means that the installation of a package requiring an external library may succeed and still fail, as a required library simply cannot be pulled in directly by RSPM.
So what is needed is a combination. We want binaries that are aware of their system dependencies but accessible directly from R just like RSPM offers it. Enter BSPM the Bridge to System Package Manager package (also on CRAN).
The first illustration (using Ubuntu 18.04) shows RSPM on the left, and BSPM on the right, both installing the graphics package Cairo (and both using custom Rocker containers).
This fails for RSPM as no binary is present and a source build fails for the familiar lack of a -dev package. It proceeds just fine on the right under BSPM.
A second illustration shows once again RSPM on the left, and BSPM on the right (this time on Fedora), both installing the units package without a required system dependency.
The installation of units works for BSPM as the dependency libudunits is brought in, but fails under RSPM. The binary installation succeeds in both cases, but the missing dependency (the UDUNITS2 library) is brought in only by BSPM. Consequently, the package fails to load under RSPM.
Summary
To conclude, highlights of BSPM are:
direct installation of binary packages from R via R commands under their normal CRAN names (just like RSPM);
full integration with the system package manager, delivering system installations (improving upon RSPM);
full dependency resolution for R packages, including system requirements (improving upon RSPM).
This offers easy, reliable, fast installation of R packages, and we invite you to pick all three. We recommend usage with either Ubuntu with the 4.6k packages via the Rutter PPA, or Fedora via the even more complete Copr repository (which already includes a specially-tailored version of BSPM called CoprManager).
We hope this short note wets your appetite to learn more about bspm (which is itself on CRAN) and the two sets of Rocker containers shown. The rocker/r-rspm container comes in two two flavours for Ubuntu 18.04 and 20.04. Similarly, the rocker/r-bspm container comes in the same two two flavours for Ubuntu 18.04 and 20.04, as well as in a Debian testing variant.
Feedback is appreciated at the bspm or rocker issue trackers.
If you like this or other open-source work I do, you can now sponsor me at GitHub. For the first year, GitHub will match your contributions.
The DebConf 20 song - a sea shanty - to the tune of "Fathom the bowl"
Here's to DebConf 20, the brightest and best Now it's this year's orga team getting no rest We're not met in Haifa - it's all doom and gloom And I'm sat like a lifer here trapped in my room
I'm sat in my room, it's all doom and gloom And I'm sat at my keyboard here trapped in my room
Now there's IRC rooms and there's jitsi and all But no fun conversations as we meet in the hall No hugs for old friends, no shared wine and cheese Just shared indigestion as we take our ease
I'm sat in my room, it's all doom and gloom And I'm sat with three screens around me in my room
But there's people to chat to, and faces we know And new things to learn and we're all on the go Algo en espanol - there's no cause for alarm An Indic track showcasing Malayalam
I'm sat in my room, it's all doom and gloom And I'm sat with my Thinkpads and cats in my room
With webcams and buffering, with lag and delay It's as well that there's Debconf time all through the day The effects of tiredness are hard to foresee For the Debian clocks all are timezone UTC
I'm sat in my room, it's all doom and gloom And I'll sing out of tune as I'm sat in my room
There's no social drinking, there's no games of Mao Keeping social distance, we can't think quite how This year is still friendly though minus some fun We'll catch up next year when we'll all get some sun
I'm sat in my room, it's all doom and gloom I'm sat with my friends around here in my room
There's loopy@debconf and snippets and such To cheer us all up, sure, it doesn't take much For we're all one big family, though we each code alone And we sometimes switch off or just complain and moan
I'm sat in my room, it's all doom and gloom And there's space for us all in the debconf chat room
This is my first DebConf - hope it won't be my last And we'll meet up somewhere when this COVID is past To all who have done this - we deserve the credit Now if you'll excuse me - I've web pages to edit
I'm sat in my room, it's not all doom and gloom And we're met as one Debian here in my room
Introducing cryptsetup-suspend
Today, we're introducing cryptsetup-suspend, whose job is to protect the content of your harddrives while the system is sleeping.
TL;DR:
For cryptsetup-suspend to work properly, at least Linux kernel 5.6 is required
We hope that in a bright future, everything will be available out-of-the-box in Debian and it's derivatives
Before:
After:
Table of contents
What does this mean and why should you care about it?
If you don't use full-disk encryption, don't read any further. Instead, think about, what will happen if you lose your notebook on the train, a random person picks it up and browses through all your personal pictures, e-mails, and tax records. Then encrypt your system and come back.
If you believe full-disk encryption is necessary, you might know that it only works when your machine is powered off. Once you turn on the machine and decrypt your harddrive, your encryption key stays in RAM and can potentially be extracted by malicious software or physical access. Even if these attacks are non-trivial, it's enough to worry about. If an attacker is able to extract your disk encryption keys from memory, they're able to read the content of your disk in return.
Sadly, in 2020, we hardly power off our laptops anymore. The sleep mode, also known as "suspend mode", is just too convenient. Just close the lid to freeze the system state and lift it anytime later in order to continue. Well, convenience usually comes with a cost: during suspend mode, your system memory is kept powered, all your data - including your encryption keys - stays there, waiting to be extracted by a malicious person. Unfortunately, there are practical attacks to extract the data of your powered memory.
Cryptsetup-suspend expands the protection of your full-disk encryption to all those times when your computer sleeps in suspend mode. Cryptsetup-suspend utilizes the suspend feature of LUKS volumes and integrates it with your Debian system. Encryption keys are evicted from memory before suspend mode and the volumes have to be re-opened after resuming - potentially prompting for the required passphrases.
By now, we have a working prototype which we want to introduce today. We did quite some testing, both on virtualized and bare-metal Debian and Ubuntu systems, with and without graphical stack, so we dare to unseal and set free the project and ask you - the community - to test, review, criticize and give feedback.
Here's a screencast of cryptsetup-suspend in action:
State of the implementation: where are we?
If you're interested in the technical details, here's how cryptsetup-suspend works internally. It basically consists of three parts:
cryptsetup-suspend: A C program that takes a list of LUKS devices as arguments, suspends them via luksSuspend and suspends the system afterwards. Also, it tries to reserve some memory for decryption, which we'll explain below.
cryptsetup-suspend-wrapper: A shell wrapper script which works the following way:
Extract the initramfs into a ramfs
Run (systemd) pre-suspend scripts, stop udev, freeze almost all cgroups
Chroot into the ramfs and run cryptsetup-suspend
Resume initramfs devices inside chroot after resume
Resume non-initramfs devices outside chroot
Thaw groups, start udev, run (systemd) post-suspend scripts
Unmount the ramfs
A systemd unit drop-in file overriding the Exec property of systemd-suspend.service so that it invokes the script cryptsetup-suspend-wrapper.
Reusing large parts of the existing cryptsetup-initramfs implementation has some positive side-effects: Out-of-the-box, we support all LUKS block device setups that have been supported by the Debian cryptsetup packages before.
Freezing most processes/cgroups is necessary to prevent possible race-conditions and dead-locks after the system resumes. Processes will try to access data on the locked/suspended block devices eventually leading to buffer overflows and data loss.
Technical challenges and caveats
Dead-locks at suspend: In order to prevent possible dead-locks between suspending the encrypted LUKS disks and suspending the system, we have to tell the Linux kernel to notsync() before going to sleep. A corresponding patch got accepted upstream in Linux 5.6. See section What about the kernel patch? below for details.
Race conditions at resume: Likewise, there's a risk of race conditions between resuming the system and unlocking the encypted LUKS disks. We went with freezing as many processes as possible as a counter measurement. See last part of section State of the implementation: where are we? for details.
Memory management: Memory management is definitely a challenge. Unlocking disks might require a lot of memory (if key derivation function is argon2i) and the swap device most likely is locked at that time. See section All that matters to me is the memories! below for details.
systemd dependency: Our implementation depends on systemd. It uses a unit drop-in file for systemd-suspend.service for hooking into the system suspend process and depends on systemds cgroup management to freeze and thaw processes. If you're using a different init system, sorry, you're currently out of luck.
What about the kernel patch?
The problem is simple: the Linux kernel suspend implementation enforces a final filesystem sync() before the system goes to sleep in order to prevent potential data loss. While that's sensible in most scenarios, it may result in dead-locks in our situation, since the block device that holds the filesystem is already suspended. The fssync() call will block forever as it waits for the block device to finish the sync() operation. So we need a way to conditionally disable this sync() call in the Linux kernel resume function. That's what our patch does, by introducing a run-time switch at /sys/power/sync_on_suspend, but it only got accepted into the Linux kernel recently and was first released with Linux kernel 5.6.
Since release 4.3, the Linux kernel at least provides a build-time flag to disable the sync(): CONFIG_SUSPEND_SKIP_SYNC (that was called SUSPEND_SKIP_SYNC first and renamed to CONFIG_SUSPEND_SKIP_SYNC in kernel release 4.9). Enabling this flag at build-time protects you against the dead locks perfectly well. But while that works on an individual basis, it's a non-option for the distribution Linux kernel defaults. In most cases you still want the sync() to happen, except if you have user-space code that takes care of the sync() just before suspending your system - just like our cryptsetup-suspend implementation does.
So in order to properly test cryptsetup-suspend, you're strongly advised to run Linux kernel 5.6 or newer. Fortunately, Linux 5.6 is available in buster-backports thanks to the Debian Kernel Team.
All that matters to me is the memories!
One of the tricky parts is memory management. Since version 2, LUKS uses argon2i as default key derivation function. Argon2i is a memory-hard hash function and LUKS2 assigns the minimum of half of your systems memory or 1 GB to unlocking your device. While this is usually unproblematic during system boot - there's not much in the system memory anyway - it can become problematic when suspending. When cryptsetup tries to unlock a device and wants 1 GB of memory for this, but everything is already occupied by your browser and video player, there's only two options what to do:
Kill a process to free some memory
Move some of the data from memory to swap space
The first option is certainly not what you expect when suspending your system. The second option is impossible, because swap is located on your harddrive which we have locked before. Our current solution is to allocate the memory after freezing the other processes, but before locking the disks. At this time, the system can still move data to swap, but it won't be accessed anymore. We then release the memory just in time for cryptsetup to claim it again. The implementation of this is still subject to change.
What's missing: A proper user interface
As mentioned before, we consider cryptsetup-suspend usable, but it certainly still has bugs and shortcomings. The most obvious one is lack of a proper user interface. Currently, we switch over to a tty command-line interface to prompt for passphrases when unlocking the LUKS devices. It certainly would be better to replace this with a graphical user interface later, probably by using plymouth or something alike. Unfortunately, it seems rather impossible to spawn a real graphical environment for the passphrase prompt. That would imply to load the full graphical stack into the ramfs, raising the required amount of memory significantly. Lack of memory is currently our biggest concern and source of trouble.
We'd definitely appreciate to learn about your ideas how to improve the user experience here.
Let's get practical: how to use
TL;DR: On Debian Bullseye (Testing), all you need to do is to install the cryptsetup-suspend package from experimental. It's not necessary to upgrade the other cryptsetup packages. On Debian Buster, cryptsetup packages from backports are required.
First, be sure that you're running Linux kernel 5.6 or newer. For Buster systems, it's available in buster-backports.
Third, install the cryptsetup-suspend package from experimental. Beware that cryptsetup-suspend depends on cryptsetup-initramfs (>= 2:2.3.3-1~). Either you need the cryptsetup packages from testing/unstable, or the backports from buster-backports.
Now that you have the cryptsetup-suspend package installed, everything should be in place: Just send your system to sleep. It should switch to a virtual text terminal before going to sleep, ask for a passphrase to unlock your encrypted disk(s) after resume and switch back to your former working environment (most likely your graphical desktop environment) afterwards.
Security considerations
Suspending LUKS devices basically means to remove the corresponding encryption keys from system memory. This protects against all sort of attacks trying to read them from there, e.g. cold-boot attacks. But, cryptsetup-suspend only protects the encryption keys of your LUKS devices. Most likely there's more sensitive data in system memory, like all kinds of private keys (e.g. OpenPGP, OpenSSH) or documents with sensitive content.
We hope that the community will help improve this situation by providing useful pre-/post-suspend scripts. A positive example is KeepassXC, which is able to lock itself when going to suspend mode.
Related and similar projects
Systemd Homed: systemd recently got a new feature to manage home directories. It brings support for encrypting your home directory within a LUKS2 container and for suspending the LUKS2 container during system sleep. It all is limited to systemd home directories though and doesn't help with other LUKS devices.
There's several earlier luks-suspend-* implementations. Unfortunately, neither of them deal with all the Technical challenges and caveats we discovered. Still we'd like to mention some of them:
Feedback and Comments
We'd be more than happy to learn about your thoughts on cryptsetup-suspend. For specific issues, don't hesitate to open a bugreport against cryptsetup-suspend. You can also reach us via mail - see the next section for contact addresses. Last but not least, comments below the blogpost work as well.