<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Far away to be identical</title>
    <description>Identity management chaos or a development of a fun</description>
    <link>https://vda.li/en/</link>
    <atom:link href="https://vda.li/en/fedora.xml" rel="self" type="application/rss+xml"/>
    <pubDate>Sat, 04 Apr 2026 22:10:00 +0300</pubDate>
    <lastBuildDate>Sat, 04 Apr 2026 22:10:00 +0300</lastBuildDate>
    <generator>astro-inplace-blog</generator>
    <item>
      <title>kurbu5: MIT Kerberos plugins in Rust</title>
      <description>&lt;p&gt;For a couple of years, Andreas Schneider and I have been working on a project we call the ‘local authentication hub’: an effort to use the Kerberos protocol to track authentication and authorization context for applications, regardless of whether the system they run on is enrolled into a larger organizational domain or is standalone. We aim to reuse the code and experience we got while developing Samba and FreeIPA over the past twenty years.&lt;/p&gt;
&lt;h2 id=&quot;local-authentication-hub&quot;&gt;Local authentication hub&lt;/h2&gt;
&lt;p&gt;The local authentication hub relies on a Kerberos KDC available on demand on each system. We achieved this by allowing MIT Kerberos to communicate over UNIX domain sockets. On Linux systems, systemd allows processes to be started on demand when someone connects to a UNIX domain socket, and MIT Kerberos 1.22 has support for this mode.&lt;/p&gt;
&lt;p&gt;A KDC accessible over a UNIX domain socket is not very useful in itself: it is only available within the context of a single machine (or a single container, or pod, if UNIX domain sockets are shared across multiple containers). Otherwise, it is a fully featured KDC with its own quirks. And we can start looking at what could be improved based on the enhanced context locality we have achieved. For example, a KDB driver can see host-specific network interfaces and thus be able to react to requests such as &lt;code&gt;host/&amp;lt;ip.ad.dr.ess&amp;gt;@LOCALKDC-REALM&lt;/code&gt; dynamically—something that a centrally-managed KDC would only do through statically registered service principal names (SPNs), which are a pain to update as machines move across networks.&lt;/p&gt;
&lt;p&gt;Adding support for dynamic features means new code needs to be written. MIT Kerberos is written in C, so our choices are either to continue writing in C or to integrate with whatever new language we choose. Initially, we kept the local KDC database driver written in C and decided to build the infrastructure we need in Rust. The end goal is to have most bits written in Rust.&lt;/p&gt;
&lt;p&gt;The local KDC database isn’t supposed to handle millions of principal entries, but even for millions of them, MIT Kerberos has a pretty good default database driver built on LMDB: &lt;code&gt;klmdb&lt;/code&gt;. We wanted to get out of the data store business and instead focus on higher-level logic. Thus, we made the same change I made in Samba around 2003 for virtual file system modules: we introduced support for stackable KDB drivers. This is also a part of the MIT Kerberos 1.22 release: a KDB driver implementation can ask the KDC to load a different KDB driver and choose to delegate some requests to it. The local KDC driver is using &lt;code&gt;klmdb&lt;/code&gt; for that purpose.&lt;/p&gt;
&lt;p&gt;With the database handled for us by &lt;code&gt;klmdb&lt;/code&gt;, we focused on the local KDC-specific logic. We wanted to dynamically discover user principals from the operating system so that administrators do not need to maintain separate databases for them. systemd provides a userdb API to query such information over a varlink interface (also available over a UNIX domain socket) in a structured way, using JSON format. Thus, the &lt;a href=&quot;https://gitlab.com/kirmes/kirmes&quot;&gt;Kirmes&lt;/a&gt; project was born. Kirmes is a Rust data library backed by the userdb API. It handles varlink communication through the wonderful &lt;a href=&quot;https://github.com/z-galaxy/zlink&quot;&gt;Zlink&lt;/a&gt; library and exposes both asynchronous and synchronous access to user and group information.&lt;/p&gt;
&lt;p&gt;The local KDC database driver prototype used the Kirmes C API. We demonstrated it at &lt;a href=&quot;https://archive.fosdem.org/2025/schedule/event/fosdem-2025-5618-localkdc-a-general-local-authentication-hub/&quot;&gt;FOSDEM 2025&lt;/a&gt;: a user lookup is done over varlink, and if a user is present on the system, their Kerberos key is then looked up in &lt;code&gt;klmdb&lt;/code&gt; using a specially-formatted &lt;code&gt;userdb:&amp;lt;username&amp;gt;&lt;/code&gt; principal. You still need to handle those keys somehow, but there is a way to avoid that: use RADIUS.&lt;/p&gt;
&lt;h2 id=&quot;pre-authentication&quot;&gt;Pre-authentication&lt;/h2&gt;
&lt;p&gt;A bit of historical reference. In 2012, Red Hat collaborated with MIT to introduce a &lt;a href=&quot;https://k5wiki.kerberos.org/wiki/Projects/OTPOverRADIUS&quot;&gt;KDC-side implementation&lt;/a&gt; of &lt;a href=&quot;https://datatracker.ietf.org/doc/html/rfc6560&quot;&gt;RFC 6560&lt;/a&gt; (the OTP pre-authentication mechanism; at that point implemented in a proprietary solution by the RSA corporation). This mechanism allowed the KDC to get a hint out of a KDB driver and ask a RADIUS server to authenticate the credentials provided by the Kerberos client. Unlike traditional Kerberos symmetric keys, in this case, the client is sending a plain-text credential over the Kerberos protocol, and this credential can be forwarded to the RADIUS server. The plain-text nature of the RADIUS credential requires the use of a secure communication channel, and a good part of RFC 6560 relies on Flexible Authentication Secure Tunneling (FAST, &lt;a href=&quot;https://datatracker.ietf.org/doc/html/rfc6113&quot;&gt;RFC6113&lt;/a&gt;), where a pre-existing Kerberos ticket is used to encrypt the content of that tunnel.&lt;/p&gt;
&lt;p&gt;Since ~2013, FreeIPA has used this mechanism to provide multi-factor authentication mechanisms: HOTP/TOTP tokens, RADIUS proxying to remote servers, the OAuth2 device authorization grant flow, and FIDO2 tokens. The list of mechanisms can be extended, as long as the model fits into the somewhat constrained Kerberos exchange flow. FreeIPA handles all communication from the KDC side via a local UNIX domain socket-activated daemon, &lt;code&gt;ipa-otpd&lt;/code&gt;, which performs a user principal lookup and then decides on the details of how that user will be authenticated.&lt;/p&gt;
&lt;p&gt;For the local KDC case, we used a similar approach but wrote a simplified version, &lt;code&gt;localkdc-pam-auth&lt;/code&gt;, which uses PAM to authenticate user credentials. It works well and allows for a drop-in replacement: once the local KDC is set up, users defined on the system will automatically be able to receive Kerberos tickets, with no need to change any passwords or migrate their credentials into the Kerberos KDC. All we need now is the business logic to guide the KDC to use the OTP pre-authentication mechanism so that our RADIUS ‘proxy’ (&lt;code&gt;localkdc-pam-auth&lt;/code&gt;) gets activated. This logic is implemented and will be available in the first localkdc release soon.&lt;/p&gt;
&lt;h2 id=&quot;api-bindings&quot;&gt;API bindings&lt;/h2&gt;
&lt;p&gt;But back to the KDC side. As mentioned above, our goal was to write the local KDC database driver in a modern, safe language. Interfacing Rust with the MIT Kerberos KDC means building an interface that allows aligning code on both sides. This is what this blog is actually about (sorry for the long prelude…): how to make an MIT Kerberos KDB driver in Rust.&lt;/p&gt;
&lt;p&gt;Today I published &lt;a href=&quot;https://codeberg.org/abbra/kurbu5&quot;&gt;Kurbu5&lt;/a&gt;, a project that aims to provide these API bindings to Rust. The name is a transliteration of “krb5” into Mesopotamian cuneiform phonology: Kurbu-ḫamšat-qaqqadī—“The Blessed Five-Headed One”.&lt;/p&gt;
&lt;p&gt;Creating API bindings is tedious work: there are many interfaces, each representing multiple functions and structures. MIT Kerberos has 12 interfaces which altogether expose roughly 117 methods that plugin authors implement, backed by around 70 supporting types (data structures passed into and out of those methods). It all sounds like a Tolkien tale: nine interfaces for core Kerberos functionality (checking password quality, mapping hostnames to Kerberos realms, mapping Kerberos principals to local accounts, selecting which credential cache to use, handling pre-authentication on both the client and server side, enforcing KDC policy, authorizing PKINIT certificates, and auditing events on the KDC side), the database backend interface, and two administrative interfaces. This is something that could be automated with agentic workflows—which I did to allow a parallel porting effort. The resulting agent &lt;a href=&quot;https://codeberg.org/abbra/kurbu5/src/branch/main/.agents/agents/implement-plugin.md&quot;&gt;instructions&lt;/a&gt; are useful artifacts in themselves: they show how to work when porting MIT Kerberos C code to Rust.&lt;/p&gt;
&lt;p&gt;The result is split over several Rust crates to allow targeted reuse. The bulk of the code lives in three crates. The core Kerberos plugin crate (kurbu5-rs) is the largest at around 12,600 lines. The database backend crate (kurbu5-kdb-rs) follows at 5,600 lines, and the administration crate (kurbu5-kadm5-rs) at 3,100 lines. The remaining crates—the proc-macro derives and the raw FFI sys crates—are much smaller, with the sys crates being almost trivially thin (the KDB and kadm5 ones are under 40 lines each, since they mostly just re-export bindings from the main sys crate).&lt;/p&gt;
&lt;p&gt;All crates are available on &lt;code&gt;crates.io&lt;/code&gt; and share the same MIT license as the original MIT Kerberos.&lt;/p&gt;
&lt;ul class=&quot;md-list&quot;&gt;&lt;li&gt;&lt;p&gt;&lt;a href=&quot;https://crates.io/crates/kurbu5-sys&quot;&gt;kurbu5-sys&lt;/a&gt; — Raw FFI bindings to the MIT Kerberos libkrb5 and KDB plugin API&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;a href=&quot;https://crates.io/crates/kurbu5-derive&quot;&gt;kurbu5-derive&lt;/a&gt; — Proc-macro derives for kurbu5-rs non-KDB plugin interfaces&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;a href=&quot;https://crates.io/crates/kurbu5-rs&quot;&gt;kurbu5-rs&lt;/a&gt; — Safe, idiomatic Rust API for writing MIT Kerberos non-KDB plugin modules&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;a href=&quot;https://crates.io/crates/kurbu5-kdb-sys&quot;&gt;kurbu5-kdb-sys&lt;/a&gt; — KDB plugin API re-export — thin wrapper over kurbu5-sys adding libkdb5 linkage&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;a href=&quot;https://crates.io/crates/kurbu5-kdb-derive&quot;&gt;kurbu5-kdb-derive&lt;/a&gt; — Proc-macro derive for kurbu5-kdb-rs KDB driver plugins&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;a href=&quot;https://crates.io/crates/kurbu5-kdb-rs&quot;&gt;kurbu5-kdb-rs&lt;/a&gt; — Safe, idiomatic Rust API for writing MIT Kerberos KDB driver plugins&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;a href=&quot;https://crates.io/crates/kurbu5-kadm5-sys&quot;&gt;kurbu5-kadm5-sys&lt;/a&gt; — KADM5 plugin API bindings — links libkadm5srv_mit and re-exports kurbu5-sys types&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;a href=&quot;https://crates.io/crates/kurbu5-kadm5-derive&quot;&gt;kurbu5-kadm5-derive&lt;/a&gt; — Proc-macro derives for kurbu5-kadm5-rs KADM5_AUTH and KADM5_HOOK plugin interfaces&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;a href=&quot;https://crates.io/crates/kurbu5-kadm5-rs&quot;&gt;kurbu5-kadm5-rs&lt;/a&gt; — Safe, idiomatic Rust API for writing MIT Kerberos KADM5_AUTH and KADM5_HOOK plugin modules&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;In the localkdc project, we use kurbu5 to build a KDB driver and provide our audit plugin. We also have an experimental re-implementation of the OTP pre-authentication mechanism, both client and KDC sides, that was used to test interoperability with MIT Kerberos versions. The core of the KDB driver is ~520 lines of heavily documented Rust code, mostly handling business logic.&lt;/p&gt;</description>
      <pubDate>Sat, 04 Apr 2026 22:10:00 +0300</pubDate>
      <link>https://vda.li/en/posts/2026/04/04/kurbu5/</link>
      <guid isPermaLink="true">https://vda.li/en/posts/2026/04/04/kurbu5/</guid>
      <category>rust</category>
      <category>freeipa</category>
      <category>localkdc</category>
      <category>kerberos</category>
      <category>samba</category>
      <category>fedora</category>
    </item>
    <item>
      <title>ASN.1 for legacy apps: Synta</title>
      <description>&lt;p&gt;Pretty much everything I deal with requires parsing ASN.1 encodings. ASN.1 definitions published as part of internet RFCs: certificates are encoded using DER, LDAP exchanges use BER, Kerberos packets are using DER as well. ASN.1 use is a never ending source of security issues in pretty much all applications. Having safer ASN.1 processing is important to any application developer.&lt;/p&gt;
&lt;p&gt;In FreeIPA we are using three separate ASN.1 libraries: &lt;code&gt;pyasn1&lt;/code&gt; and &lt;code&gt;x509&lt;/code&gt; (part of PyCA) for Python code, and &lt;code&gt;asn1c&lt;/code&gt; code generator for C code. In fact, we use more: LDAP server plugins also use OpenLDAP’s &lt;code&gt;lber&lt;/code&gt; library, while Kerberos KDC plugins also use internal MIT Kerberos parsers.&lt;/p&gt;
&lt;p&gt;The PyCA developers noted in their &lt;a href=&quot;https://cryptography.io/en/latest/statements/state-of-openssl/&quot;&gt;State of OpenSSL&lt;/a&gt; statement:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;[…] when pyca/cryptography migrated X.509 certificate parsing from OpenSSL to our own Rust code, we got a 10x performance improvement relative to OpenSSL 3 (n.b., some of this improvement is attributable to advantages in our own code, but much is explainable by the OpenSSL 3 regressions). Later, moving public key parsing to our own Rust code made end-to-end X.509 path validation 60% faster — just improving key loading led to a 60% end-to-end improvement, that’s how extreme the overhead of key parsing in OpenSSL was.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;That’s 16x performance improvement over the OpenSSL 3. OpenSSL did improve their performance since then but it still pays an overhead for a very flexible design to allow loading cryptographic implementations from dynamic modules (providers). Enablement for externally-provided modules is essential to allow adding new primitives and support for government-enforced standards (such as FIPS 140) where implementations have to be validated in advance and code changes cannot come without expensive and slow re-validation process.&lt;/p&gt;
&lt;p&gt;Nevertheless, in FreeIPA we focus on integrating with Linux distributions. Fedora, CentOS Stream, and RHEL enforce crypto consolidation rules, where all packaged applications must be using the same crypto primitives provided by the operating system. We can process metadata ourselves but all cryptographic operations still have to go through OpenSSL and NSS. And paying large performance costs during metadata processing would be hurting to infrastructure components such as FreeIPA.&lt;/p&gt;
&lt;p&gt;FreeIPA is a large beast. Aside from its management component, written in Python, it has more than a dozen plugins for 389-ds LDAP server, plugins for MIT Kerberos KDC, plugins for Samba, and tight integration with SSSD, all written in C. Its default certificate authority software, Dogtag PKI, is written in Java and relies on own stack of Java and C dependencies. We are using PyCA’s x509 module for certificate processing in Python code but we cannot use it and underlying ASN.1 libraries in C as those libraries aren’t exposed to C applications or intentionally limited in their functionality to PKI-related tasks.&lt;/p&gt;
&lt;p&gt;For the 2026-2028, I’m focusing on enabling FreeIPA to handle post-quantum cryptography (PQC), as a part of the &lt;a href=&quot;https://qarc.vut.cz&quot;&gt;Quantum-Resistant Cryptography in Practice (QARC)&lt;/a&gt; project. The project is funded by the European Union under the Horizon Europe framework programme (Grant Agreement No. 101225691) and supported by the European Cybersecurity Competence Centre. One of well publicized aspects of moving to PQC certificates is their sizes. The following table 5 is from &lt;a href=&quot;https://datatracker.ietf.org/doc/draft-ietf-pquip-pqc-engineers/&quot;&gt;Post-Quantum Cryptography for Engineers&lt;/a&gt; IETF draft summarizes it well:&lt;/p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;PQ Security Level&lt;/th&gt;&lt;th&gt;Algorithm&lt;/th&gt;&lt;th&gt;Public key size (bytes)&lt;/th&gt;&lt;th&gt;Private key size (bytes)&lt;/th&gt;&lt;th&gt;Signature size(bytes)&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;Traditional&lt;/td&gt;&lt;td&gt;RSA2048&lt;/td&gt;&lt;td&gt;256&lt;/td&gt;&lt;td&gt;256&lt;/td&gt;&lt;td&gt;256&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Traditional&lt;/td&gt;&lt;td&gt;ECDSA-P256&lt;/td&gt;&lt;td&gt;64&lt;/td&gt;&lt;td&gt;32&lt;/td&gt;&lt;td&gt;64&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;1&lt;/td&gt;&lt;td&gt;FN-DSA-512&lt;/td&gt;&lt;td&gt;897&lt;/td&gt;&lt;td&gt;1281&lt;/td&gt;&lt;td&gt;666&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;2&lt;/td&gt;&lt;td&gt;ML-DSA-44&lt;/td&gt;&lt;td&gt;1312&lt;/td&gt;&lt;td&gt;2560&lt;/td&gt;&lt;td&gt;2420&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;3&lt;/td&gt;&lt;td&gt;ML-DSA-65&lt;/td&gt;&lt;td&gt;1952&lt;/td&gt;&lt;td&gt;4032&lt;/td&gt;&lt;td&gt;3309&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;5&lt;/td&gt;&lt;td&gt;FN-DSA-1024&lt;/td&gt;&lt;td&gt;1793&lt;/td&gt;&lt;td&gt;2305&lt;/td&gt;&lt;td&gt;1280&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;5&lt;/td&gt;&lt;td&gt;ML-DSA-87&lt;/td&gt;&lt;td&gt;2592&lt;/td&gt;&lt;td&gt;4896&lt;/td&gt;&lt;td&gt;4627&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;Public keys for ML-DSA-65 certificates 7.6x bigger than RSA-2048 ones. You need to handle public keys in multiple situations: when performing certificates’ verification against known certificate authorities (CAs), when matching their properties for validation and identity derivation during authorization, when storing them. FreeIPA uses LDAP as a backend, so storing 7.6 times more data directly affects your scalability when number of users or machines (or Kerberos services) grow up. And since certificates are all ASN.1 encoded, I naturally wanted to establish a performance baseline to ASN.1 parsing.&lt;/p&gt;
&lt;h2 id=&quot;synta-asn1-library&quot;&gt;Synta, ASN.1 library&lt;/h2&gt;
&lt;p&gt;I started with a small task: created a Rust library, &lt;code&gt;synta&lt;/code&gt;, to decode and encode ASN.1 with the help of AI tooling. It quickly grew up to have its own ASN.1 schema parser and code generation tool. With those in place, I started generating more code, this time to process X.509 certificates, handle Kerberos packet structures, and so on. Throwing different tasks at Claude Code led to iterative improvements. Over couple months we progressed to a project with more than 60K lines of Rust code.&lt;/p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Language&lt;/th&gt;&lt;th class=&quot;right&quot;&gt;files&lt;/th&gt;&lt;th class=&quot;right&quot;&gt;blank&lt;/th&gt;&lt;th class=&quot;right&quot;&gt;comment&lt;/th&gt;&lt;th class=&quot;right&quot;&gt;code&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;Rust&lt;/td&gt;&lt;td class=&quot;right&quot;&gt;207&lt;/td&gt;&lt;td class=&quot;right&quot;&gt;9993&lt;/td&gt;&lt;td class=&quot;right&quot;&gt;17492&lt;/td&gt;&lt;td class=&quot;right&quot;&gt;67284&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Markdown&lt;/td&gt;&lt;td class=&quot;right&quot;&gt;52&lt;/td&gt;&lt;td class=&quot;right&quot;&gt;5619&lt;/td&gt;&lt;td class=&quot;right&quot;&gt;153&lt;/td&gt;&lt;td class=&quot;right&quot;&gt;18059&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Python&lt;/td&gt;&lt;td class=&quot;right&quot;&gt;41&lt;/td&gt;&lt;td class=&quot;right&quot;&gt;2383&lt;/td&gt;&lt;td class=&quot;right&quot;&gt;2742&lt;/td&gt;&lt;td class=&quot;right&quot;&gt;7679&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;C&lt;/td&gt;&lt;td class=&quot;right&quot;&gt;17&lt;/td&gt;&lt;td class=&quot;right&quot;&gt;852&lt;/td&gt;&lt;td class=&quot;right&quot;&gt;889&lt;/td&gt;&lt;td class=&quot;right&quot;&gt;4333&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Bourne Shell&lt;/td&gt;&lt;td class=&quot;right&quot;&gt;8&lt;/td&gt;&lt;td class=&quot;right&quot;&gt;319&lt;/td&gt;&lt;td class=&quot;right&quot;&gt;482&lt;/td&gt;&lt;td class=&quot;right&quot;&gt;1640&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;C/C++ Header&lt;/td&gt;&lt;td class=&quot;right&quot;&gt;4&lt;/td&gt;&lt;td class=&quot;right&quot;&gt;319&lt;/td&gt;&lt;td class=&quot;right&quot;&gt;1957&lt;/td&gt;&lt;td class=&quot;right&quot;&gt;1138&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;TOML&lt;/td&gt;&lt;td class=&quot;right&quot;&gt;20&lt;/td&gt;&lt;td class=&quot;right&quot;&gt;196&lt;/td&gt;&lt;td class=&quot;right&quot;&gt;97&lt;/td&gt;&lt;td class=&quot;right&quot;&gt;896&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;YAML&lt;/td&gt;&lt;td class=&quot;right&quot;&gt;1&lt;/td&gt;&lt;td class=&quot;right&quot;&gt;20&lt;/td&gt;&lt;td class=&quot;right&quot;&gt;46&lt;/td&gt;&lt;td class=&quot;right&quot;&gt;561&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;make&lt;/td&gt;&lt;td class=&quot;right&quot;&gt;4&lt;/td&gt;&lt;td class=&quot;right&quot;&gt;166&lt;/td&gt;&lt;td class=&quot;right&quot;&gt;256&lt;/td&gt;&lt;td class=&quot;right&quot;&gt;493&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;CMake&lt;/td&gt;&lt;td class=&quot;right&quot;&gt;3&lt;/td&gt;&lt;td class=&quot;right&quot;&gt;36&lt;/td&gt;&lt;td class=&quot;right&quot;&gt;25&lt;/td&gt;&lt;td class=&quot;right&quot;&gt;150&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;JSON&lt;/td&gt;&lt;td class=&quot;right&quot;&gt;6&lt;/td&gt;&lt;td class=&quot;right&quot;&gt;0&lt;/td&gt;&lt;td class=&quot;right&quot;&gt;0&lt;/td&gt;&lt;td class=&quot;right&quot;&gt;38&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;diff&lt;/td&gt;&lt;td class=&quot;right&quot;&gt;1&lt;/td&gt;&lt;td class=&quot;right&quot;&gt;6&lt;/td&gt;&lt;td class=&quot;right&quot;&gt;13&lt;/td&gt;&lt;td class=&quot;right&quot;&gt;29&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;SUM&lt;/strong&gt;&lt;/td&gt;&lt;td class=&quot;right&quot;&gt;&lt;strong&gt;364&lt;/strong&gt;&lt;/td&gt;&lt;td class=&quot;right&quot;&gt;&lt;strong&gt;19909&lt;/strong&gt;&lt;/td&gt;&lt;td class=&quot;right&quot;&gt;&lt;strong&gt;24152&lt;/strong&gt;&lt;/td&gt;&lt;td class=&quot;right&quot;&gt;&lt;strong&gt;102300&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;I published some of the &lt;code&gt;synta&lt;/code&gt; crates yesterday on &lt;a href=&quot;https://crates.io/users/abbra&quot;&gt;crates.io&lt;/a&gt;, the whole project is available at &lt;a href=&quot;https://codeberg.org/abbra/synta&quot;&gt;codeberg.org/abbra/synta&lt;/a&gt;. In total, there are 11 crates, though only seven are published (and &lt;code&gt;synta-python&lt;/code&gt; is also available at PyPI):&lt;/p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Crate&lt;/th&gt;&lt;th class=&quot;right&quot;&gt;Lines (src/ only)&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;synta&lt;/td&gt;&lt;td class=&quot;right&quot;&gt;10572&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;synta-derive&lt;/td&gt;&lt;td class=&quot;right&quot;&gt;2549&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;synta-codegen&lt;/td&gt;&lt;td class=&quot;right&quot;&gt;17578&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;synta-certificate&lt;/td&gt;&lt;td class=&quot;right&quot;&gt;4549&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;synta-python&lt;/td&gt;&lt;td class=&quot;right&quot;&gt;8953&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;synta-ffi&lt;/td&gt;&lt;td class=&quot;right&quot;&gt;7843&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;synta-krb5&lt;/td&gt;&lt;td class=&quot;right&quot;&gt;2765&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;synta-mtc&lt;/td&gt;&lt;td class=&quot;right&quot;&gt;7876&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;synta-tools&lt;/td&gt;&lt;td class=&quot;right&quot;&gt;707&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;synta-bench&lt;/td&gt;&lt;td class=&quot;right&quot;&gt;0&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;synta-fuzz&lt;/td&gt;&lt;td class=&quot;right&quot;&gt;3551&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;Benchmarking, fuzzer, and tools aren’t published. They only needed for development purposes.&lt;/p&gt;
&lt;h2 id=&quot;performance&quot;&gt;Performance&lt;/h2&gt;
&lt;p&gt;The numbers below were obtained on Lenovo ThinkPad P1 Gen 5, 12th Gen Intel(R) Core(TM) i7-12800H, 64 GB RAM, on Fedora 42. This is pretty much a 3-4 years old hardware.&lt;/p&gt;
&lt;p&gt;Benchmarking is what brought this project to life, let’s look at the numbers. When dealing with certificates, ASN.1 encoding can be parsed in different ways: you can visit every structure or stop at outer shells and only visit the remaining nested structures when you really need them. The former is “parse+fields” and the latter is “parse-only” in the following table that summarizes comparison between &lt;code&gt;synta&lt;/code&gt; and various Rust crates (and OpenSSL/NSS which were accessible through their Rust FFI bindings):&lt;/p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Library&lt;/th&gt;&lt;th&gt;Parse-only&lt;/th&gt;&lt;th&gt;Parse+fields&lt;/th&gt;&lt;th&gt;vs synta (parse-only)&lt;/th&gt;&lt;th&gt;vs synta (parse+fields)&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;synta&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;0.48 µs&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;1.32 µs&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;—&lt;/td&gt;&lt;td&gt;—&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;cryptography-x509&lt;/td&gt;&lt;td&gt;1.45 µs&lt;/td&gt;&lt;td&gt;1.43 µs&lt;/td&gt;&lt;td&gt;3.0× slower&lt;/td&gt;&lt;td&gt;1.1× slower&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;x509-parser&lt;/td&gt;&lt;td&gt;2.01 µs&lt;/td&gt;&lt;td&gt;1.99 µs&lt;/td&gt;&lt;td&gt;4.2× slower&lt;/td&gt;&lt;td&gt;1.5× slower&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;x509-cert&lt;/td&gt;&lt;td&gt;3.16 µs&lt;/td&gt;&lt;td&gt;3.15 µs&lt;/td&gt;&lt;td&gt;6.6× slower&lt;/td&gt;&lt;td&gt;2.4× slower&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;NSS&lt;/td&gt;&lt;td&gt;7.90 µs&lt;/td&gt;&lt;td&gt;7.99 µs&lt;/td&gt;&lt;td&gt;16× slower&lt;/td&gt;&lt;td&gt;6.1× slower&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;rust-openssl&lt;/td&gt;&lt;td&gt;15.4 µs&lt;/td&gt;&lt;td&gt;15.1 µs&lt;/td&gt;&lt;td&gt;32× slower&lt;/td&gt;&lt;td&gt;11× slower&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;ossl&lt;/td&gt;&lt;td&gt;16.1 µs&lt;/td&gt;&lt;td&gt;15.8 µs&lt;/td&gt;&lt;td&gt;33× slower&lt;/td&gt;&lt;td&gt;12× slower&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;“Parse+fields” tests access every named field: serial number, issuer/subject DNs, signature algorithm OID, signature bytes, validity period, public key algorithm OID, public key bytes, and version. The “parse+fields” speedup is the fair end-to-end comparison: &lt;code&gt;synta&lt;/code&gt;’s parse-only advantage is large because most fields are stored as zero-copy slices deferred until access, while other libraries must materialise all fields eagerly at parse time.&lt;/p&gt;
&lt;p&gt;The dominant cost in X.509 parsing is Distinguished Name traversal: a certificate’s issuer and subject each contain a SEQUENCE OF SET OF SEQUENCE with per-attribute OID lookup. &lt;code&gt;synta&lt;/code&gt; defers this entirely by storing the &lt;code&gt;Name&lt;/code&gt; as a &lt;code&gt;RawDer&amp;lt;&apos;a&amp;gt;&lt;/code&gt; — a pointer+length into the original input with no decoding. &lt;code&gt;cryptography-x509&lt;/code&gt; takes a similar deferred approach. The &lt;code&gt;nom&lt;/code&gt;-based and &lt;code&gt;RustCrypto&lt;/code&gt; libraries decode Names eagerly. &lt;code&gt;NSS&lt;/code&gt; goes further and formats them into C strings, which is the dominant fraction of its 16× parse overhead.&lt;/p&gt;
&lt;p&gt;For benchmarking I used certificates from PyCA test vectors. There are few certificates with different properties, so we parse them multiple times and then average numbers:&lt;/p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Certificate&lt;/th&gt;&lt;th&gt;synta&lt;/th&gt;&lt;th&gt;cryptography-x509&lt;/th&gt;&lt;th&gt;x509-parser&lt;/th&gt;&lt;th&gt;x509-cert&lt;/th&gt;&lt;th&gt;NSS&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;cert_00 (NoPolicies)&lt;/td&gt;&lt;td&gt;1333.7 ns&lt;/td&gt;&lt;td&gt;1386.7 ns&lt;/td&gt;&lt;td&gt;1815.9 ns&lt;/td&gt;&lt;td&gt;2990.6 ns&lt;/td&gt;&lt;td&gt;7940.3 ns&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;cert_01 (SamePolicies-1)&lt;/td&gt;&lt;td&gt;1348.8 ns&lt;/td&gt;&lt;td&gt;1441.0 ns&lt;/td&gt;&lt;td&gt;2033.4 ns&lt;/td&gt;&lt;td&gt;3174.3 ns&lt;/td&gt;&lt;td&gt;7963.8 ns&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;cert_02 (SamePolicies-2)&lt;/td&gt;&lt;td&gt;1338.6 ns&lt;/td&gt;&lt;td&gt;1440.1 ns&lt;/td&gt;&lt;td&gt;2120.1 ns&lt;/td&gt;&lt;td&gt;3205.6 ns&lt;/td&gt;&lt;td&gt;8206.8 ns&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;cert_03 (anyPolicy)&lt;/td&gt;&lt;td&gt;1362.4 ns&lt;/td&gt;&lt;td&gt;1468.3 ns&lt;/td&gt;&lt;td&gt;2006.2 ns&lt;/td&gt;&lt;td&gt;3194.5 ns&lt;/td&gt;&lt;td&gt;7902.4 ns&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;cert_04 (AnyPolicyEE)&lt;/td&gt;&lt;td&gt;1232.9 ns&lt;/td&gt;&lt;td&gt;1424.7 ns&lt;/td&gt;&lt;td&gt;1968.6 ns&lt;/td&gt;&lt;td&gt;3168.1 ns&lt;/td&gt;&lt;td&gt;7913.1 ns&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Average&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;1323 ns&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;1432 ns&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;1989 ns&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;3147 ns&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;7985 ns&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;The gap between synta (1.32 µs) and cryptography-x509 (1.43 µs) is tighter here than in parse-only (3.0×) because synta’s field access includes two &lt;code&gt;format_dn()&lt;/code&gt; calls (~800 ns combined) that cryptography-x509 does for effectively free (its offsets were computed at parse time). Synta leads by ~8% overall.&lt;/p&gt;
&lt;p&gt;Now, when parsing PQC certificates, an interesting thing happens. First, it is faster to parse ML-DSA than traditional certificates.&lt;/p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Certificate&lt;/th&gt;&lt;th&gt;synta&lt;/th&gt;&lt;th&gt;cryptography-x509&lt;/th&gt;&lt;th&gt;x509-parser&lt;/th&gt;&lt;th&gt;x509-cert&lt;/th&gt;&lt;th&gt;NSS&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;ML-DSA-44&lt;/td&gt;&lt;td&gt;1030.9 ns&lt;/td&gt;&lt;td&gt;1256.4 ns&lt;/td&gt;&lt;td&gt;1732.2 ns&lt;/td&gt;&lt;td&gt;2666.0 ns&lt;/td&gt;&lt;td&gt;7286.9 ns&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;ML-DSA-65&lt;/td&gt;&lt;td&gt;1124.9 ns&lt;/td&gt;&lt;td&gt;1237.5 ns&lt;/td&gt;&lt;td&gt;1690.5 ns&lt;/td&gt;&lt;td&gt;2664.2 ns&lt;/td&gt;&lt;td&gt;7222.1 ns&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;ML-DSA-87&lt;/td&gt;&lt;td&gt;1102.6 ns&lt;/td&gt;&lt;td&gt;1226.5 ns&lt;/td&gt;&lt;td&gt;1727.2 ns&lt;/td&gt;&lt;td&gt;2696.6 ns&lt;/td&gt;&lt;td&gt;7284.6 ns&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Average&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;1086 ns&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;1240 ns&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;1717 ns&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;2675 ns&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;7265 ns&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;&lt;code&gt;synta&lt;/code&gt;’s ML-DSA parse+fields (1.09 µs) is faster than its traditional parse+fields (1.32 µs) because ML-DSA test certificates have shorter Distinguished Names (one attribute each in issuer and subject vs multiple attributes in traditional certificates in the test above). The signature BIT STRING — which is 2,420–4,627 bytes for ML-DSA — is accessed as a zero-copy slice with no size-dependent cost.&lt;/p&gt;
&lt;h2 id=&quot;processing-ca-databases&quot;&gt;Processing CA databases&lt;/h2&gt;
&lt;p&gt;Imaging your app needs to test whether the certificate presented by a client is known to you (e.g. belongs to a trusted CAs set). A library like OpenSSL looks at the client’s certificate, extracts identifiers of the certificate issuer, looks up whether such issuer is known in the CA database. That would require looking up properties of the certificates in the database. The fast we can do that, the better.&lt;/p&gt;
&lt;p&gt;All those numbers in the previous section are for a single certificate being parsed millions of times. In a real app we often need to validate the certificate against a system-wide database of certificate authorities. The database used by Fedora and other Linux distributions comes from Firefox. It contains 180 self-signed root CA certificates for all public CAs with diverse key types (RSA 2048/4096, ECDSA P-256/P-384) and DN structures. The median cert by DER size is “Entrust.net Premium 2048 Secure Server CA” (1,070 bytes); the benchmark uses this cert for single-certificate and field-access sub-benchmarks to get stable results that are not sensitive to certificate-size outliers.&lt;/p&gt;
&lt;p&gt;Another data I tried to benchmark against is 9,898 certificates from the Common CA Database (CCADB), covering the full multi-level hierarchy used by Mozilla, Chrome, Apple, and Microsoft:&lt;/p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th class=&quot;right&quot;&gt;Depth&lt;/th&gt;&lt;th class=&quot;right&quot;&gt;Count&lt;/th&gt;&lt;th&gt;Description&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;right&quot;&gt;0&lt;/td&gt;&lt;td class=&quot;right&quot;&gt;919&lt;/td&gt;&lt;td&gt;Root CAs (self-signed)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class=&quot;right&quot;&gt;1&lt;/td&gt;&lt;td class=&quot;right&quot;&gt;6,627&lt;/td&gt;&lt;td&gt;Intermediates issued directly by roots&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class=&quot;right&quot;&gt;2&lt;/td&gt;&lt;td class=&quot;right&quot;&gt;2,212&lt;/td&gt;&lt;td&gt;Two levels deep&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class=&quot;right&quot;&gt;3&lt;/td&gt;&lt;td class=&quot;right&quot;&gt;137&lt;/td&gt;&lt;td&gt;Three levels deep&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class=&quot;right&quot;&gt;4&lt;/td&gt;&lt;td class=&quot;right&quot;&gt;3&lt;/td&gt;&lt;td&gt;Four levels deep&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;Intermediate CA certificates tend to have more complex DNs and more extensions than the root CAs in the Mozilla store. The CCADB median cert is “Bayerische SSL-CA-2014-01” (10,432 bytes). These certificates from CCADB cover past 30 years of certificate issuance on the internet.&lt;/p&gt;
&lt;p&gt;To see how those benchmarks would behave if CA roots database would be built with post quantum cryptography, I rebuilt the CCADB corpus as ML-DSA certificates. Nine CCADB certificates were skipped: OpenSSL’s &lt;code&gt;x509 -x509toreq -copy_extensions copy&lt;/code&gt; step failed to convert them to CSR form, typically because those certs use non-standard DER encodings or critical extensions that the &lt;code&gt;x509toreq&lt;/code&gt; pipeline cannot copy into a PKCS#10 request. (The failures are in OpenSSL’s cert→CSR conversion; synta parses all 9,898 original CCADB certs without error.) This leaves 9,889 of the original 9,898 certs in the synthetic database.&lt;/p&gt;
&lt;p&gt;The median cert by DER size is “TrustCor Basic Secure Site (CA1)” (6,705 bytes). ML-DSA certs range from 5,530 B to 16,866 B; the distribution is shifted left relative to the CCADB RSA/ECDSA median (10,432 B) because the smallest CCADB certs (compact root CAs with few extensions) become the new median position after ML-DSA key replacement enlarges all certs uniformly.&lt;/p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Benchmark&lt;/th&gt;&lt;th&gt;Library&lt;/th&gt;&lt;th&gt;Dataset&lt;/th&gt;&lt;th&gt;Time&lt;/th&gt;&lt;th&gt;Throughput&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;synta_parse_all&lt;/code&gt;&lt;/td&gt;&lt;td&gt;synta&lt;/td&gt;&lt;td&gt;Mozilla (180 certs)&lt;/td&gt;&lt;td&gt;&lt;strong&gt;87.8 µs&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;2.0 M/sec&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;nss_parse_all&lt;/code&gt;&lt;/td&gt;&lt;td&gt;NSS&lt;/td&gt;&lt;td&gt;Mozilla (180 certs)&lt;/td&gt;&lt;td&gt;1.577 ms&lt;/td&gt;&lt;td&gt;114 K/sec&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;openssl_parse_all&lt;/code&gt;&lt;/td&gt;&lt;td&gt;rust-openssl&lt;/td&gt;&lt;td&gt;Mozilla (180 certs)&lt;/td&gt;&lt;td&gt;3.552 ms&lt;/td&gt;&lt;td&gt;50.7 K/sec&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;ossl_parse_all&lt;/code&gt;&lt;/td&gt;&lt;td&gt;ossl&lt;/td&gt;&lt;td&gt;Mozilla (180 certs)&lt;/td&gt;&lt;td&gt;3.617 ms&lt;/td&gt;&lt;td&gt;49.8 K/sec&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;synta_parse_and_access&lt;/code&gt;&lt;/td&gt;&lt;td&gt;synta&lt;/td&gt;&lt;td&gt;Mozilla (180 certs)&lt;/td&gt;&lt;td&gt;&lt;strong&gt;261 µs&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;690 K/sec&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;synta_build_trust_chain&lt;/code&gt;&lt;/td&gt;&lt;td&gt;synta&lt;/td&gt;&lt;td&gt;Mozilla (180 certs)&lt;/td&gt;&lt;td&gt;&lt;strong&gt;11.6 µs&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;—&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;synta_parse_all&lt;/code&gt;&lt;/td&gt;&lt;td&gt;synta&lt;/td&gt;&lt;td&gt;CCADB (9,898 certs)&lt;/td&gt;&lt;td&gt;&lt;strong&gt;5.10 ms&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;1.94 M/sec&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;nss_parse_all&lt;/code&gt;&lt;/td&gt;&lt;td&gt;NSS&lt;/td&gt;&lt;td&gt;CCADB (9,898 certs)&lt;/td&gt;&lt;td&gt;106 ms&lt;/td&gt;&lt;td&gt;93 K/sec&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;openssl_parse_all&lt;/code&gt;&lt;/td&gt;&lt;td&gt;rust-openssl&lt;/td&gt;&lt;td&gt;CCADB (9,898 certs)&lt;/td&gt;&lt;td&gt;203 ms&lt;/td&gt;&lt;td&gt;48.8 K/sec&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;ossl_parse_all&lt;/code&gt;&lt;/td&gt;&lt;td&gt;ossl&lt;/td&gt;&lt;td&gt;CCADB (9,898 certs)&lt;/td&gt;&lt;td&gt;214 ms&lt;/td&gt;&lt;td&gt;46.3 K/sec&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;synta_parse_and_access&lt;/code&gt;&lt;/td&gt;&lt;td&gt;synta&lt;/td&gt;&lt;td&gt;CCADB (9,898 certs)&lt;/td&gt;&lt;td&gt;&lt;strong&gt;16.1 ms&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;615 K/sec&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;synta_parse_roots&lt;/code&gt;&lt;/td&gt;&lt;td&gt;synta&lt;/td&gt;&lt;td&gt;CCADB (919 roots)&lt;/td&gt;&lt;td&gt;&lt;strong&gt;457.7 µs&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;2.01 M/sec&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;synta_parse_intermediates&lt;/code&gt;&lt;/td&gt;&lt;td&gt;synta&lt;/td&gt;&lt;td&gt;CCADB (8,979 intermediates)&lt;/td&gt;&lt;td&gt;&lt;strong&gt;4.735 ms&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;1.90 M/sec&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;synta_build_dependency_tree&lt;/code&gt;&lt;/td&gt;&lt;td&gt;synta&lt;/td&gt;&lt;td&gt;CCADB (9,898 certs)&lt;/td&gt;&lt;td&gt;&lt;strong&gt;559 µs&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;—&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;synta_parse_all&lt;/code&gt;&lt;/td&gt;&lt;td&gt;synta&lt;/td&gt;&lt;td&gt;ML-DSA synth (9,889 certs)&lt;/td&gt;&lt;td&gt;&lt;strong&gt;5.78 ms&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;1.71 M/sec&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;nss_parse_all&lt;/code&gt;&lt;/td&gt;&lt;td&gt;NSS&lt;/td&gt;&lt;td&gt;ML-DSA synth (9,889 certs)&lt;/td&gt;&lt;td&gt;103 ms&lt;/td&gt;&lt;td&gt;96.4 K/sec&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;openssl_parse_all&lt;/code&gt;&lt;/td&gt;&lt;td&gt;rust-openssl&lt;/td&gt;&lt;td&gt;ML-DSA synth (9,889 certs)&lt;/td&gt;&lt;td&gt;239 ms&lt;/td&gt;&lt;td&gt;41.4 K/sec&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;ossl_parse_all&lt;/code&gt;&lt;/td&gt;&lt;td&gt;ossl&lt;/td&gt;&lt;td&gt;ML-DSA synth (9,889 certs)&lt;/td&gt;&lt;td&gt;256 ms&lt;/td&gt;&lt;td&gt;38.6 K/sec&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;synta_parse_and_access&lt;/code&gt;&lt;/td&gt;&lt;td&gt;synta&lt;/td&gt;&lt;td&gt;ML-DSA synth (9,889 certs)&lt;/td&gt;&lt;td&gt;&lt;strong&gt;17.5 ms&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;566 K/sec&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;synta_parse_roots&lt;/code&gt;&lt;/td&gt;&lt;td&gt;synta&lt;/td&gt;&lt;td&gt;ML-DSA synth (919 roots)&lt;/td&gt;&lt;td&gt;&lt;strong&gt;463 µs&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;1.98 M/sec&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;synta_parse_intermediates&lt;/code&gt;&lt;/td&gt;&lt;td&gt;synta&lt;/td&gt;&lt;td&gt;ML-DSA synth (8,970 ints.)&lt;/td&gt;&lt;td&gt;&lt;strong&gt;5.10 ms&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;1.76 M/sec&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;synta_build_dependency_tree&lt;/code&gt;&lt;/td&gt;&lt;td&gt;synta&lt;/td&gt;&lt;td&gt;ML-DSA synth (9,889 certs)&lt;/td&gt;&lt;td&gt;&lt;strong&gt;549 µs&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;—&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;NSS is &lt;strong&gt;18–21× slower&lt;/strong&gt; than &lt;code&gt;synta&lt;/code&gt; across all three datasets; &lt;code&gt;rust-openssl&lt;/code&gt; is &lt;strong&gt;40–41× slower&lt;/strong&gt; and &lt;code&gt;ossl&lt;/code&gt; is &lt;strong&gt;41–44× slower&lt;/strong&gt;. All three C-backed libraries successfully parse ML-DSA certificates (NSS 3.120+ and OpenSSL 3.4+ support ML-DSA natively). NSS’s absolute parse time is nearly identical across CCADB traditional certs (106 ms) and ML-DSA synthetic certs (103 ms) — confirming that NSS’s dominant cost is eager DN formatting at parse time, which depends on DN attribute count rather than the signature algorithm. The slightly lower relative slowdown for NSS on ML-DSA (18× vs 21×) is entirely because synta is slower on ML-DSA (5.78 ms vs 5.10 ms), not because NSS is faster.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;synta&lt;/code&gt;’s throughput is consistent at ~1.7–2.0 M certs/sec across all three datasets, confirming linear O(n) scaling. Parse rate is slightly lower for the ML-DSA synthetic hierarchy (1.71 M/sec) than for the CCADB traditional hierarchy (1.94 M/sec) because the larger ML-DSA SubjectPublicKeyInfo and signature BIT STRING fields add bytes to the tag+length-header scan that synta performs at parse time. The intermediates-only sub-benchmark is slightly lower than roots-only in each dataset (1.76 M/sec vs 1.98 M/sec for ML-DSA; 1.90 M/sec vs 2.01 M/sec for CCADB) because intermediate CAs tend to have more complex DNs and extension lists.&lt;/p&gt;
&lt;p&gt;Finally, individual property access for a pre-parsed certificate, single field read, no allocation unless noted:&lt;/p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Field&lt;/th&gt;&lt;th class=&quot;right&quot;&gt;Mozilla (1,070 B)&lt;/th&gt;&lt;th class=&quot;right&quot;&gt;CCADB (10,432 B)&lt;/th&gt;&lt;th class=&quot;right&quot;&gt;ML-DSA (6,705 B)&lt;/th&gt;&lt;th&gt;Notes&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;issuer_raw&lt;/code&gt; / &lt;code&gt;subject_raw&lt;/code&gt;&lt;/td&gt;&lt;td class=&quot;right&quot;&gt;4.1 / 4.1 ns&lt;/td&gt;&lt;td class=&quot;right&quot;&gt;4.2 / 4.1 ns&lt;/td&gt;&lt;td class=&quot;right&quot;&gt;4.5 / 4.4 ns&lt;/td&gt;&lt;td&gt;Zero-copy slice&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;public_key_bytes&lt;/code&gt; / &lt;code&gt;signature_bytes&lt;/code&gt;&lt;/td&gt;&lt;td class=&quot;right&quot;&gt;4.1 / 4.1 ns&lt;/td&gt;&lt;td class=&quot;right&quot;&gt;4.2 / 4.2 ns&lt;/td&gt;&lt;td class=&quot;right&quot;&gt;4.6 / 4.4 ns&lt;/td&gt;&lt;td&gt;Zero-copy slice&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;signature_algorithm&lt;/code&gt; / &lt;code&gt;public_key_algorithm&lt;/code&gt;&lt;/td&gt;&lt;td class=&quot;right&quot;&gt;5.9 / 5.4 ns&lt;/td&gt;&lt;td class=&quot;right&quot;&gt;5.9 / 5.5 ns&lt;/td&gt;&lt;td class=&quot;right&quot;&gt;6.3 / 6.4 ns&lt;/td&gt;&lt;td&gt;OID → &lt;code&gt;&amp;amp;&apos;static str&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;serial_number&lt;/code&gt;&lt;/td&gt;&lt;td class=&quot;right&quot;&gt;10.9 ns&lt;/td&gt;&lt;td class=&quot;right&quot;&gt;6.8 ns&lt;/td&gt;&lt;td class=&quot;right&quot;&gt;7.5 ns&lt;/td&gt;&lt;td&gt;Integer → i64, length-dependent&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;validity&lt;/code&gt;&lt;/td&gt;&lt;td class=&quot;right&quot;&gt;180 ns&lt;/td&gt;&lt;td class=&quot;right&quot;&gt;206 ns&lt;/td&gt;&lt;td class=&quot;right&quot;&gt;231 ns&lt;/td&gt;&lt;td&gt;Two time-string allocations&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;issuer_dn&lt;/code&gt;&lt;/td&gt;&lt;td class=&quot;right&quot;&gt;401 ns&lt;/td&gt;&lt;td class=&quot;right&quot;&gt;224 ns&lt;/td&gt;&lt;td class=&quot;right&quot;&gt;246 ns&lt;/td&gt;&lt;td&gt;&lt;code&gt;format_dn()&lt;/code&gt; → &lt;code&gt;String&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;subject_dn&lt;/code&gt;&lt;/td&gt;&lt;td class=&quot;right&quot;&gt;404 ns&lt;/td&gt;&lt;td class=&quot;right&quot;&gt;292 ns&lt;/td&gt;&lt;td class=&quot;right&quot;&gt;324 ns&lt;/td&gt;&lt;td&gt;&lt;code&gt;format_dn()&lt;/code&gt; → &lt;code&gt;String&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;Zero-copy fields (&lt;code&gt;issuer_raw&lt;/code&gt;, &lt;code&gt;subject_raw&lt;/code&gt;, &lt;code&gt;public_key_bytes&lt;/code&gt;, &lt;code&gt;signature_bytes&lt;/code&gt;) cost ~4–5 ns — the price of reading a pointer and length from a struct field. The slightly higher cost for CCADB and ML-DSA fields vs Mozilla is within measurement noise.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;identify_signature_algorithm()&lt;/code&gt; and &lt;code&gt;identify_public_key_algorithm()&lt;/code&gt; match the OID component array against a static table and return &lt;code&gt;&amp;amp;&apos;static str&lt;/code&gt; — no allocation, no string formatting. The ~5–6 ns cost is a few comparisons and a pointer return.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;serial_number&lt;/code&gt; cost depends on the integer’s byte length: the Entrust Mozilla cert carries a 16-byte serial number (parsed via &lt;code&gt;SmallVec&amp;lt;[u8; 16]&amp;gt;&lt;/code&gt;), while the CCADB and ML-DSA synthetic medians have shorter serials. At 10.9, 6.8, and 7.5 ns respectively, all are negligible.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;validity&lt;/code&gt; (~180–231 ns) allocates two strings: UTCTime and GeneralizedTime are formatted from their raw DER bytes into owned &lt;code&gt;String&lt;/code&gt;s. The two calls account for essentially all of the cost; the &lt;code&gt;YYMMDDHHMMSSZ&lt;/code&gt; to RFC 3339 formatting is the dominant work.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;format_dn()&lt;/code&gt; is the most variable field: it walks the Name DER bytes, decodes each SEQUENCE OF SET OF SEQUENCE, looks up each attribute OID by name, and formats the result into an owned &lt;code&gt;String&lt;/code&gt;. The Mozilla cert’s issuer DN is more complex (multiple attributes, longer values: 401 ns) than the CCADB median (224 ns) or the ML-DSA synthetic median (246 ns). The ML-DSA synthetic median’s subject DN (324 ns) is slightly more expensive than the CCADB median (292 ns) because a different cert occupies the median position after key replacement. &lt;code&gt;format_dn()&lt;/code&gt; cost is proportional to the DN’s attribute count and string lengths.&lt;/p&gt;
&lt;h2 id=&quot;why-c-libraries-are-slower&quot;&gt;Why C Libraries Are Slower&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;CERT_NewTempCertificate&lt;/code&gt; (NSS) and OpenSSL’s &lt;code&gt;d2i_X509&lt;/code&gt; perform significantly more work per certificate than synta:&lt;/p&gt;
&lt;ol class=&quot;md-list md-loose&quot;&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Eager DN formatting&lt;/strong&gt; — NSS formats the issuer and subject Distinguished Names into internal C strings during &lt;code&gt;CERT_NewTempCertificate&lt;/code&gt;, even when the caller never reads them. Distinguished Name formatting is the single most expensive operation in certificate parsing; doing it unconditionally at parse time accounts for roughly 80% of NSS’s total parse cost. OpenSSL decodes DN structure eagerly as well.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Arena and heap allocation&lt;/strong&gt; — each NSS certificate allocates a &lt;code&gt;PLArena&lt;/code&gt; block and copies the full DER buffer into it (&lt;code&gt;copyDER = 1&lt;/code&gt;). OpenSSL allocates from the C heap. These allocations are additional work beyond decoding.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Library state and locking&lt;/strong&gt; — NSS acquires internal locks on every &lt;code&gt;CERT_NewTempCertificate&lt;/code&gt; call to update the certificate cache, even when the resulting certificate is marked as temporary. This serialises concurrent parsing in multi-threaded applications.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;FFI boundary costs&lt;/strong&gt; — the &lt;code&gt;rust-openssl&lt;/code&gt; and &lt;code&gt;ossl&lt;/code&gt; measurements include the overhead of crossing from Rust into the C library via &lt;code&gt;extern &amp;quot;C&amp;quot;&lt;/code&gt; calls and pointer marshalling.&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;
&lt;p&gt;&lt;code&gt;synta&lt;/code&gt; defers all of (1): &lt;code&gt;issuer&lt;/code&gt; and &lt;code&gt;subject&lt;/code&gt; are stored as &lt;code&gt;RawDer&amp;lt;&apos;a&amp;gt;&lt;/code&gt; (borrowed byte spans) and decoded only when the caller calls &lt;code&gt;format_dn()&lt;/code&gt;. There is no locking, no arena, and no FFI boundary.&lt;/p&gt;
&lt;p&gt;In these tests I also found out that PyCA’s &lt;code&gt;cryptography-x509&lt;/code&gt; doesn’t have optimizations for multiple accesses to the same fields. It is typically not a problem if you are just loading a certificate and use it once. If you have to return back to it multiple times, that becomes visible and hurts your performance. So I submitted &lt;a href=&quot;https://github.com/pyca/cryptography/pull/14441&quot;&gt;a pull request&lt;/a&gt; to apply some of the optimizations I found with &lt;code&gt;synta&lt;/code&gt;. The pull request had to be split into smaller ones and few of them were already merged, so performance to access issuer, subject, and public key in certificates and to some attributes in CSRs was improved 100x. The rest waits for improvements in PyO3 to save some of memory use.&lt;/p&gt;</description>
      <pubDate>Mon, 23 Mar 2026 10:33:00 +0200</pubDate>
      <link>https://vda.li/en/posts/2026/03/23/synta/</link>
      <guid isPermaLink="true">https://vda.li/en/posts/2026/03/23/synta/</guid>
      <category>asn1</category>
      <category>rust</category>
      <category>freeipa</category>
      <category>kerberos</category>
      <category>samba</category>
      <category>fedora</category>
    </item>
    <item>
      <title>FreeIPA local tests and FOSDEM demos</title>
      <description>&lt;p&gt;&lt;a href=&quot;https://fosdem.org/2025/&quot;&gt;FOSDEM 2025&lt;/a&gt; is behind us. We ran &lt;a href=&quot;https://fosdem.org/2025/schedule/track/iam/.&quot;&gt;Identity and Access Management devroom&lt;/a&gt; at FOSDEM. At the devroom, my team did few talks and demos about FreeIPA and Kerberos. While preparing to those talks, we tried to create demonstrations that could be repeated by others as well. First, this was an attempt to help ourselves, as we need to communicate our advances to others in the teams. Then we started to look at how to show our progress to folks outside of the development groups.&lt;/p&gt;
&lt;p&gt;We iterated over our tools and finally ended up with something that is based on what we use in upstream CIs: we use podman containers to run what ends up being ephemeral VMs hosting the software. This doesn’t give ability to handle all possible scenarios. It is not a way to run actual production environments as well. Yet, it allows us a quick reuse and share:&lt;/p&gt;
&lt;ul class=&quot;md-list md-loose&quot;&gt;&lt;li&gt;&lt;p&gt;descriptive definition of the deployment configuration&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;standard tooling to provision the configuration as containers with &lt;code&gt;podman-compose&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;use of Ansible playbooks to run repeatable actions against the hosts, with inventory taken from the podman-compose integration&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;The tool, &lt;a href=&quot;https://github.com/rjeffman/ipalab-config&quot;&gt;&lt;code&gt;ipalab-config&lt;/code&gt;&lt;/a&gt;, quickly became flexible enough to be used in multiple scenarios. It powers &lt;code&gt;ansible-freeipa&lt;/code&gt;’s own upstream CI, we aim to reuse it for new FreeIPA Web UI development and for the FreeIPA workshop.&lt;/p&gt;
&lt;p&gt;For the demos at FOSDEM IAM devroom we put a separate repository that has all the scenarios and even recording files to reproduce the demos: &lt;a href=&quot;https://github.com/abbra/freeipa-local-tests/&quot;&gt;&lt;code&gt;freeipa-local-tests&lt;/code&gt;&lt;/a&gt;. You can try yourself how local authentication hub or IPA-IPA trust or IPA-IPA migration do work.&lt;/p&gt;
&lt;p&gt;This project demonstrates how complex multi-system FreeIPA deployments can be tested locally or in your CI/CD. The test environment is built with the help of &lt;a href=&quot;https://podman.io&quot;&gt;podman&lt;/a&gt; and orchestrated with &lt;a href=&quot;https://github.com/rjeffman/ipalab-config&quot;&gt;ipalab-config&lt;/a&gt; and &lt;a href=&quot;https://github.com/containers/podman-compose&quot;&gt;podman-compose&lt;/a&gt; tools. FreeIPA environment is deployed with the help of &lt;a href=&quot;https://github.com/freeipa/ansible-freeipa&quot;&gt;ansible-freeipa&lt;/a&gt;. Upstream, we run these tests in Github Actions as well.&lt;/p&gt;
&lt;h2 id=&quot;demo-labs&quot;&gt;Demo labs&lt;/h2&gt;
&lt;p&gt;Following configurations provided as ‘labs’ that can be reproduced using &lt;code&gt;ipalab-config&lt;/code&gt; tool and the configurations from this project:&lt;/p&gt;
&lt;ul class=&quot;md-list md-loose&quot;&gt;&lt;li&gt;&lt;p&gt;&lt;a href=&quot;https://github.com/abbra/freeipa-local-tests/blob/main/ipalab-config/minimal/README.md&quot;&gt;minimal deployment&lt;/a&gt;, consisting of a FreeIPA server and a FreeIPA client enrolled into it.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;a href=&quot;https://github.com/abbra/freeipa-local-tests/blob/main/ipalab-config/localkdc/README.md&quot;&gt;local KDC&lt;/a&gt;, consisting of two standalone machines, not enrolled into any domain. Each machine runs its own Kerberos KDC exposed to local applications over UNIX domain socket, with socket activation handled by systemd. See &lt;a href=&quot;https://fosdem.org/2025/schedule/event/fosdem-2025-5618-localkdc-a-general-local-authentication-hub/&quot;&gt;“localkdc - local authentication hub”&lt;/a&gt; talk at FOSDEM 2025. This is currently a work in progress.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;a href=&quot;https://github.com/abbra/freeipa-local-tests/blob/main/ipalab-config/ipa-migrate/README.md&quot;&gt;FreeIPA deployment migration&lt;/a&gt;, demonstrating how IPA data can be migrated between separate test and production deployments. See &lt;a href=&quot;https://fosdem.org/2025/schedule/event/fosdem-2025-5175-freeipa-to-freeipa-migration-current-capabilities-and-use-cases/&quot;&gt;“FreeIPA-to-FreeIPA Migration: Current Capabilities and Use Cases”&lt;/a&gt; talk at FOSDEM 2025.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;a href=&quot;https://github.com/abbra/freeipa-local-tests/blob/main/ipalab-config/ipa-trust/README.md&quot;&gt;FreeIPA trust&lt;/a&gt;, demonstrating how two separate IPA deployments can be set up to trust each other. See &lt;a href=&quot;https://fosdem.org/2025/schedule/event/fosdem-2025-5178-building-cross-domain-trust-between-freeipa-deployments/&quot;&gt;“Building Cross-Domain Trust Between FreeIPA Deployments”&lt;/a&gt; talk at FOSDEM 2025. This is currently a work in progress.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;h2 id=&quot;demo-recordings&quot;&gt;Demo recordings&lt;/h2&gt;
&lt;p&gt;Some of the demo labs have automated recording of the operations that could be performed on them. Video recording is built upon excellent &lt;a href=&quot;https://github.com/charmbracelet/vhs&quot;&gt;VHS&lt;/a&gt; tool. A pre-built version for Fedora is provided in &lt;a href=&quot;https://copr.fedorainfracloud.org/coprs/abbra/vhs/&quot;&gt;COPR abbra/vhs&lt;/a&gt;. This build also includes a fix from the upstream &lt;a href=&quot;https://github.com/charmbracelet/vhs/pull/551&quot;&gt;PR#551&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;minimal-deployment-demo&quot;&gt;Minimal deployment demo&lt;/h3&gt;
&lt;p&gt;This demo recording includes a minimal use of FreeIPA command line:&lt;/p&gt;
&lt;ul class=&quot;md-list&quot;&gt;&lt;li&gt;&lt;p&gt;an administrator logs into a client system over SSH using a password&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Kerberos ticket is obtained automatically by the SSSD&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;IPA command line tool can authenticate to IPA server using Kerberos&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;video controls preload=&quot;metadata&quot; onclick=&quot;(function(el){ if(el.paused) el.play(); else el.pause() })(this)&quot;&gt;&lt;source src=&quot;https://vda.li/en/img/2025-freeipa-local-tests/basic-demo.webm&quot; type=&quot;video/webm; codecs=&amp;quot;vp8, vorbis&amp;quot;&quot; /&gt;&lt;/video&gt;
&lt;h3 id=&quot;local-kdc-demo&quot;&gt;Local KDC demo&lt;/h3&gt;
&lt;p&gt;The local KDC demo is more evolved:&lt;/p&gt;
&lt;ul class=&quot;md-list&quot;&gt;&lt;li&gt;&lt;p&gt;a user logs into their own machine over SSH using a password&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Kerberos ticket is obtained automatically by the SSSD from the local KDC which is activated on demand&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;User then uses a Kerberos ticket to authenticate to SUDO and obtain root privileges&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;The user also uses the Kerberos ticket to authenticate to Samba server running locally&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Finally, the user authenticates with Kerberos IAKerb extension to a remotely running Samba server, removing completely a need for NTLM authentication protocol&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;video controls preload=&quot;metadata&quot; onclick=&quot;(function(el){ if(el.paused) el.play(); else el.pause() })(this)&quot;&gt;&lt;source src=&quot;https://vda.li/en/img/2025-freeipa-local-tests/localkdc-demo.webm&quot; type=&quot;video/webm; codecs=&amp;quot;vp8, vorbis&amp;quot;&quot; /&gt;&lt;/video&gt;
&lt;h3 id=&quot;ipa-to-ipa-trust-demo&quot;&gt;IPA to IPA trust demo&lt;/h3&gt;
&lt;p&gt;This is a minimalistic demo of how users and groups from one IPA environment can be resolved in the other IPA environment. There is a trust agreement established between both IPA environments, similarly how IPA can establish a forest level trust with Active Directory.&lt;/p&gt;
&lt;video controls preload=&quot;metadata&quot; onclick=&quot;(function(el){ if(el.paused) el.play(); else el.pause() })(this)&quot;&gt;&lt;source src=&quot;https://vda.li/en/img/2025-freeipa-local-tests/ipa2ipa-trust-demo.webm&quot; type=&quot;video/webm; codecs=&amp;quot;vp8, vorbis&amp;quot;&quot; /&gt;&lt;/video&gt;</description>
      <pubDate>Fri, 14 Feb 2025 13:15:00 +0200</pubDate>
      <link>https://vda.li/en/posts/2025/02/14/FreeIPA-local-tests/</link>
      <guid isPermaLink="true">https://vda.li/en/posts/2025/02/14/FreeIPA-local-tests/</guid>
      <category>freeipa</category>
      <category>kerberos</category>
      <category>iakerb</category>
      <category>localkdc</category>
      <category>samba</category>
      <category>fedora</category>
    </item>
    <item>
      <title>Local authentication hub</title>
      <description>&lt;p&gt;FOSDEM 2025 is just behind us and it was a great event. I had a chance to talk about the local authentication hub project. The talk was well received and I got a lot of questions about the project. We ran Identity and Access Management devroom for the second time in row and it was a great success. I had two talks at the IAM devroom, both were process reports on the activity we have announced at FOSDEM 2024. Now that both recordings of the both talks published, I can share articles which go into more details.&lt;/p&gt;
&lt;h2 id=&quot;local-authentication-hub&quot;&gt;Local authentication hub&lt;/h2&gt;
&lt;p&gt;Our FOSDEM talk is &lt;a href=&quot;https://fosdem.org/2025/schedule/event/fosdem-2025-5618-localkdc-a-general-local-authentication-hub/&quot;&gt;“localkdc - a general local authentication hub”&lt;/a&gt;. You can watch it and come back here for more details.&lt;/p&gt;
&lt;p&gt;But before going into details, let me provide a bit of a background. It is 2025 now and we should go almost three decades back (ugh!).&lt;/p&gt;
&lt;h3 id=&quot;history-dive&quot;&gt;History dive&lt;/h3&gt;
&lt;p&gt;Authentication on Linux systems is interwoven with the identity of the users. Once a user logged in, a process is running under a certain POSIX account identity. Many applications validate the presence of the account prior to the authentication itself. For example, the OpenSSH server does check the POSIX account and its properties and if the user was not found, will intentionally corrupt the password passed to the PAM authentication stack request. An authentication request will fail but the attempt will be recorded in the system journal.&lt;/p&gt;
&lt;p&gt;This joint operation between authentication and identification sources in Linux makes it important to maintain a coherent information state. No wonder that in corporate environments it is often handled centrally: user and group identities stored at a central server and sourced from that one by a local software, such as SSSD. In order to consume these POSIX users and groups, SSSD needs to be registered with the centralized authority or, in other words, enrolled into the domain. Domain enrollment allows not only identity and authentication of users: both the central server and the enrolled client machine can mutually authenticate each other and be sure they talk to the right authority when authenticating the user.&lt;/p&gt;
&lt;p&gt;FreeIPA provides a stable mechanism for building a centralized domain management system. Each user account has POSIX attributes associated with it and each user account is represented by the Kerberos principal. Kerberos authentication can be used to transfer the authentication state across multiple services and provides a chance for services to discover user identity information beyond POSIX. It also makes strong linking between the POSIX level identity and authentication structure possible: for example, a Kerberos service may introspect a Kerberos ticket presented by a user’s client application to see how this user was authenticated originally: with a password or some specific passwordless mechanism. Or, perhaps, that a client application performs operations on behalf of the user after claiming it was authenticated using a different (non-Kerberos) authentication.&lt;/p&gt;
&lt;p&gt;Local user accounts’ use lacks this experience. Each individual service needs to reauthenticate a user again and again. Local system login: authenticate. Elevating privileges through SUDO? Authenticate again, if not explicitly configured otherwise. Details of the user session state, like how long this particular session is active, is not checked by the applications, making it also harder to limit access. There is no information on how this user was authenticated. Finally, overall user experience between local (standalone) authentication and domain-enrolled one differs, making it harder to adjust and educate users.&lt;/p&gt;
&lt;p&gt;Local authentication is also typically password-based. This is not a bad thing in itself but depending on applications and protocols, worse choices could be made, security-wise. For example, contemporary SMB 3.11 protocol is quite secure if authenticated using Kerberos. For non-Kerberos usage, however, it is left to rely on NTLM authentication protocol which requires use of RC4 stream cipher. There are multiple attacks known to break RC4-based encryption, yet it is still used in majority of non-domain joined communications using SMB protocol simply because there was no (so far) alternative. To be correct, there was always an alternative, use of Kerberos protocol, but setting it up for individual isolated systems wasn’t practical.&lt;/p&gt;
&lt;p&gt;The Kerberos protocol assumes the use of three different parties: a client, a service, and a key distribution center (KDC). In corporate environments a KDC is part of the domain controller system, a client and a service are both domain members, computers are enrolled in the domain. The client authenticates to KDC and obtains a Kerberos ticket granting ticket (TGT). It then requests a service ticket from the KDC by presenting its TGT and then presents this service ticket to the service. The service application, on its side, is able to decrypt the service ticket presented by the client and authenticate the request.&lt;/p&gt;
&lt;p&gt;In the late 2000s Apple realised that for individual computers a number of user accounts is typically small and a KDC can be run as a service on the individual computer itself. When both the client and server are on the same computer, this works beautifully. The only problem is that when a user needs to authenticate to a different computer’s service, the client cannot reach the KDC hosted on the other computer because it is not exposed to the network directly. Luckily, MIT Kerberos folks already thought about this problem a decade prior to that: in 1997 a first idea was published for a Kerberos extension that allowed to tunnel Kerberos requests over a different application protocol. This specification became later known as “Initial and Pass Through Authentication Using Kerberos V5 and the GSS-API” (IAKerb). An initial implementation for MIT Kerberos was done in 2009/2010 while Apple introduced it in 2007 to enable remote access to your own Mac across the internet. It came in MacOS X 10.5 as a “Back to My Mac” feature and even got specified in RFC 6281, only to be retired from MacOS in 2019.&lt;/p&gt;
&lt;h3 id=&quot;modern-days&quot;&gt;Modern days&lt;/h3&gt;
&lt;p&gt;In the 2020s Microsoft continued to work on NTLM removal. In 2023 they announced that all Windows systems will have a local KDC as their local authentication source, accessible externally via selected applications through the IAKerb mechanism. By the end of 2024, we have only seen demos published by Microsoft engineers at various events but this is a promising path forward. Presence of the local KDC in Windows raises an interoperability requirement: Linux systems will have to handle access to Windows machines in a standalone environment over SMB protocol. Authentication is currently done with NTLM, it will eventually be removed, thus we need to support the IAKerb protocol extension.&lt;/p&gt;
&lt;p&gt;The NTLM removal for Linux systems requires several changes. First, the Samba server will need to learn how to accept authentication with the IAKerb protocol extension. Then, Samba client code needs to be able to establish a client connection and advertise IAKerb protocol extension. For kernel level access, the SMB filesystem driver needs to learn how to use IAKerb as well, this will also need to be implemented in the user space cifs-utils package. Finally, to be able to use the same feature in a pure Linux environment, we need to be able to deploy Kerberos KDC locally and do it in an easy manner on each machine.&lt;/p&gt;
&lt;p&gt;This is where we had an idea. If we are going to have a local KDC running on each system, maybe we should use it to handle all authentication and not just for the NTLM removal? This way we can make both the local and domain-enrolled user experience the same and provide access locally to a whole set of authentication methods we support for FreeIPA: passwords, smartcards, one-time passwords and remote RADIUS server authentication, use of FIDO2 tokens, and authentication against an external OAuth2 Identity Provider using a device authorization grant flow.&lt;/p&gt;
&lt;h3 id=&quot;how-local-a-local-kdc-should-be&quot;&gt;How “local” a local KDC should be?&lt;/h3&gt;
&lt;p&gt;On standalone systems it is often not desirable to run daemons continuously. Also, it is not desirable to expose these services to the connected network if they really don’t need to be exposed. A common approach to solve this problem is by providing a local inter-process communication (IPC) mechanism to communicate with the server components. We chose to expose a local KDC via UNIX domain sockets. A UNIX domain socket is a well-known mechanism and has known security properties. With the help of a systemd feature called socket activation, we also can start local KDC on demand, when a Kerberos client connects over the UNIX domain socket. Since on local systems actual authentication requests don’t happen often, this helps to reduce memory and CPU usage in the long run.&lt;/p&gt;
&lt;p&gt;If a local KDC is only accessible over a UNIX domain socket, remote applications could not get access to it directly. This means they would need to have help from a server application that can utilize the IAKerb mechanism to pass-through the communication between a client and the KDC. It would enable us to authenticate as a local user remotely from a different machine. Due to how the IAKerb mechanism is designed and integrated into GSS-API, this only allows password-based authentication. Anything that requires passwordless methods cannot obtain initial Kerberos authentication over IAKerb, at least at this point.&lt;/p&gt;
&lt;p&gt;Here is &lt;a href=&quot;https://youtu.be/D5vzc2Qo4k0&quot;&gt;a small demo&lt;/a&gt; on Fedora, using our &lt;code&gt;localkdc&lt;/code&gt; tool to start a local KDC, obtain a Kerberos ticket upon login. The tickets can then be used effortlessly to authenticate to local services such as SUDO or Samba. For remote access we rely on Samba support for IAKerb and authenticate with GSSAPI but local &lt;code&gt;smbclient&lt;/code&gt; uses a password first to obtain the initial ticket over IAKerb. This is purely a limitation of the current patches we have to Samba.&lt;/p&gt;
&lt;div class=&quot;embed-container&quot;&gt;
&lt;iframe width=&quot;740&quot; height=&quot;480&quot;
  src=&quot;https://www.youtube.com/embed/D5vzc2Qo4k0&quot;
  title=&quot;YouTube video player&quot; frameborder=&quot;0&quot; allow=&quot;encrypted-media; picture-in-picture; web-share&quot;
  referrerpolicy=&quot;strict-origin-when-cross-origin&quot;
  allowfullscreen&gt;&lt;/iframe&gt;
&lt;/div&gt;
&lt;p&gt;Make a pause here and think about the implications. We have an initial Kerberos ticket from the local system. The Kerberos ticket embeds details of how this authentication happened. We might have used a password to authenticate, or a smartcard. Or any other supported pre-authentication methods. We could reuse the same methods FreeIPA already provides in the centralized environment.&lt;/p&gt;
&lt;p&gt;The Kerberos ticket also can contain details about the user session, including up to date group membership. It does not currently have that in the local KDC case but we aim to fix that. This ticket can be used to authenticate to any GSS-API or Kerberos-aware service on this machine. If a remote machine accepts Kerberos, it theoretically could accept a ticket presented by a client application running on the local machine as well. Only, to do that it needs to be able to communicate with our local KDC and it couldn’t access it.&lt;/p&gt;
&lt;h3 id=&quot;trust-management&quot;&gt;Trust management&lt;/h3&gt;
&lt;p&gt;Luckily, a local KDC deployment is a full-featured Kerberos realm and thus can establish cross-realm agreements with other Kerberos realms. If two “local” KDC realms have trust agreements between each other, they can issue cross-realm Kerberos tickets which applications can present over IAKerb to the remote “local” KDC. Then a Kerberos ticket to a service running on the target system can be requested and issued by the system’s local KDC.&lt;/p&gt;
&lt;p&gt;Thus, we can achieve passwordless authentication locally on Linux systems and have the ability to establish peer to peer agreements across multiple systems, to allow authentication requests to flow and operate on commonly agreed credentials. A problem now moves to the management area: how to manage these peer to peer agreements and permissions in an easy way?&lt;/p&gt;
&lt;h3 id=&quot;systemd-usergroup-api-support&quot;&gt;Systemd User/Group API support&lt;/h3&gt;
&lt;p&gt;MIT Kerberos KDC implementation provides a flexible way to handle Kerberos principals’ information. A database backend (KDB) implementation can be dynamically loaded and replaced. This is already used by both FreeIPA and Samba AD to integrate MIT Kerberos KDC with their own database backends based on different LDAP server implementations. For a local KDC use case running a full-featured LDAP server is not required nor intended. However, it would be great if different applications could expose parts of the data needed by the KDB interfaces and cooperate together. Then a single KDB driver implementation could be used to streamline and provide uniform implementation of Kerberos-specific details in a local KDC.&lt;/p&gt;
&lt;p&gt;One of the promising interfaces to achieve that is the &lt;a href=&quot;https://systemd.io/USER_GROUP_API/&quot;&gt;User/Group record lookup API&lt;/a&gt; via varlink from systemd. Varlink allows applications to register themselves and listen on UNIX domain sockets for communication similar to D-Bus but with much less implementation overhead. The User/Group API technically also allows to merge data coming from different sources when an application inquires the information. “Technically”, because &lt;code&gt;io.systemd.Multiplexer&lt;/code&gt; API endpoint currently does not support merging non-overlapping data representing the same account from multiple sources. Once it would become possible, we could combine the data dynamically and may interact with users on demand when corresponding requsts come in. Or we can implement our own blending service.&lt;/p&gt;
&lt;p&gt;Blending data requests from multiple sources within MIT KDC needs a specialized KDB driver. We certainly don’t want this driver to duplicate the code from other drivers, so making these drivers stackable would be a good option. Support for one level of stacking has been merged to MIT Kerberos through &lt;a href=&quot;https://github.com/krb5/krb5/pull/1396&quot;&gt;a quickly processed pull request&lt;/a&gt; and will be available in the next MIT Kerberos release. This allows us to have a single KDB driver that loads other drivers specialized in storing Kerberos principals and processing additional information like &lt;a href=&quot;https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-pac/166d8064-c863-41e1-9c23-edaaa5f36962&quot;&gt;MS-PAC structure&lt;/a&gt; or applying additional authorization details.&lt;/p&gt;
&lt;h3 id=&quot;establishing-trusts&quot;&gt;Establishing trusts&lt;/h3&gt;
&lt;p&gt;If Alice and Bob are in the same network and want to exchange some files, they could do this using SMB and Samba. But that Alice can authenticate on Bob’s machine, they would need to establish a Kerberos cross realm trust. With the current tooling this is a complex task. For users we need to make this more accessible. We want to allow users to request trust on demand and validate these requests interactively. We also want to allow trust to be present for a limited timeframe, automatically expiring or manually removed.&lt;/p&gt;
&lt;p&gt;If we have a Kerberos principal lookup on demand through a curated varlink API endpoint, we also can have a user-facing service to initiate establishing the trust between two machines on demand. Imagine a user trying to access SMB share on one desktop system that triggers a pop-up to establish trust relationship with a corresponding local KDC on the remote desktop system. Both owners of the systems would be able to communicate out of band that provided information is correct and can be trusted. Once it is done, we can return back the details of the specific Kerberos principal that represents this trust relationship. We can limit lifetime of this agreement so that it would disappear automatically in one hour or a day, or a week.&lt;/p&gt;
&lt;h3 id=&quot;current-state-of-local-authentication-hub&quot;&gt;Current state of local authentication hub&lt;/h3&gt;
&lt;p&gt;We started with two individual implementation paths early in 2024:&lt;/p&gt;
&lt;ul class=&quot;md-list&quot;&gt;&lt;li&gt;&lt;p&gt;support IAKerb in MIT Kerberos and Samba&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;enable MIT Kerberos to be used locally without network exposure&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;MIT Kerberos did have support for IAKerb protocol extension for more than a decade but since Microsoft introduced some changes to the protocol, those changes needed to be integrated as well. This was completed during summer 2024, though no upstream release is available yet. MIT Kerberos typically releases new versions yearly in January so we hope to get some updates early 2025.&lt;/p&gt;
&lt;p&gt;Samba integration with IAKerb is currently under implementation. Originally, Microsoft was planning to release Windows 11 and Windows Server 2025 with IAKerb support enabled during autumn 2024. However, the Windows engineering team faced some issues and IAKerb is still not enabled in the Windows Server 2025 and Windows 11 releases. We are looking forward to getting access to Windows builds that enable IAKerb support to ensure interoperability before merging Samba changes upstream. We also need to complete the Samba implementation to properly support locally-issued Kerberos tickets and not only do acquisition of the ticket based on the password.&lt;/p&gt;
&lt;p&gt;Meanwhile, our cooperation with MIT Kerberos development team led to advancements in the local KDC support. The MIT Kerberos KDC can now be run over a UNIX domain socket. Also on systemd-enabled systems we allow socket activation, transforming local KDC into an on-demand service. We will continue our work on a dynamic database for a local KDC, to allow on-demand combination of resources from multiple authoritative local sources (Samba, FreeIPA, SSSD, local KDC, future dynamic trust application).&lt;/p&gt;
&lt;p&gt;For experiments and ease of deployments, a new configuration tool was developed, localkdc. The tool is available at &lt;a href=&quot;https://gitlab.com/cryptomilk/localkdc&quot;&gt;localkdc&lt;/a&gt; and &lt;a href=&quot;https://copr.fedorainfracloud.org/coprs/asn/localkdc&quot;&gt;COPR repository&lt;/a&gt; can be used to try the whole solution on Fedora.&lt;/p&gt;
&lt;p&gt;If you want to get that test tried in a simple setup, you might be interested in a tool that we developed initially for FreeIPA: &lt;a href=&quot;https://github.com/abbra/freeipa-local-tests/&quot;&gt;FreeIPA local tests&lt;/a&gt;. This tool allows to provision and run a complex test environment in podman containers. The video of the local KDC usage was actually generated automatically by the scripts from &lt;a href=&quot;https://github.com/abbra/freeipa-local-tests/tree/main/ipalab-config/localkdc&quot;&gt;https://github.com/abbra/freeipa-local-tests/tree/main/ipalab-config/localkdc&lt;/a&gt;.&lt;/p&gt;</description>
      <pubDate>Sun, 09 Feb 2025 13:00:00 +0200</pubDate>
      <link>https://vda.li/en/posts/2025/02/09/local-authentication-hub/</link>
      <guid isPermaLink="true">https://vda.li/en/posts/2025/02/09/local-authentication-hub/</guid>
      <category>freeipa</category>
      <category>kerberos</category>
      <category>iakerb</category>
      <category>localkdc</category>
      <category>samba</category>
      <category>fedora</category>
    </item>
    <item>
      <title>IPA-IPA trust progress report</title>
      <description>&lt;p&gt;FreeIPA and SSSD teams are working to enable IPA deployments to trust each other. This report outlines the progress we have so far.&lt;/p&gt;
&lt;h3 id=&quot;trust-across-enterprise-domains&quot;&gt;Trust across enterprise domains&lt;/h3&gt;
&lt;p&gt;FreeIPA implements an enterprise domain management: systems enrolled into domain managed centrally and access resources available through the domain controllers. These resources include information about users and groups, machines, Kerberos services and different rules that can bind them. FreeIPA supports a trust to Active Directory forest by posing as a separate Active Directory forest with a single Active Directory domain (a forest root).&lt;/p&gt;
&lt;p&gt;The approach helps to integrate with a majority of enterprise deployments. New deployments might not include Active Directory, though. Instead, they tend to be self-sufficient or integrate with externally managed data sources, often without retaining compatibility with traditional POSIX or Active Directory deployments. For example, cloud deployments might rely on OAuth2 identity providers or federate to social services.&lt;/p&gt;
&lt;p&gt;FreeIPA can also integrate with OAuth2-based identity providers by bridging authentication over to them. Users would be native IPA users; IPA policies and rules to access IPA resources would apply to them but authentication and permission to issue a Kerberos ticket to the users would be delegated to an external IdP.&lt;/p&gt;
&lt;p&gt;One useful approach is to have a single IPA environment that holds all users and groups while individual machines all placed in separate IPA deployments. These deployments would need to trust the environment where users defined. In this document we’d call such deployment an IPA-IPA trust.&lt;/p&gt;
&lt;p&gt;IPA-IPA trust would look similar to the existing trust to Active Directory. A core technology is Kerberos: each deployment is a separate Kerberos realm; a trust on Kerberos level means cross-realm ticket granting tickets (TGT) issued by the realms’ KDCs. These cross-realm TGTs allow clients from one realm to request tickets for services located in the other realm.&lt;/p&gt;
&lt;p&gt;Requesting Kerberos tickets is a base feature needed to authenticate across the trust. For proper relationship, identities of the authenticated objects (Kerberos principals and services) also need to be resolved. In POSIX environments these identities have to be associated with POSIX users to be able to store data on disk or to run processes with individual login sessions. The process requires not only authentication but also the ability to query information from a trusted domain’s domain controller.&lt;/p&gt;
&lt;p&gt;In FreeIPA deployments, user and group information from the domain controllers is retireved by SSSD. When trust to Active Directory forest created, SSSD on IPA domain controllers is able to use a special entry in the trusted domain (trusted domain object, TDO) to authenticate against trusted domain’s domain controllers. SSSD knows how LDAP schema and directory information tree (DIT) on the Active Directory side are organized and can handle user and group object mapping for us.&lt;/p&gt;
&lt;p&gt;If SSSD is able to resolve users and groups in the same way as with Active Directory trusts, this means we can reuse existing support for trusted Active Directory users and groups in IPA commands and keep the same user experience when adding HBAC or SUDO rules, managing IPA deployment, and so on. This would also mean we already would have a comprehensive test suite to validate IPA-IPA trust functionality.&lt;/p&gt;
&lt;h3 id=&quot;kerberos-trust-infrastructure&quot;&gt;Kerberos trust infrastructure&lt;/h3&gt;
&lt;p&gt;We first focused on making Kerberos infrastructure work when both realms represented by separate FreeIPA deployments. For past decade Microsoft, Samba Team, FreeIPA team, MIT Kerberos and Heimdal projects worked together to ensure there is a solid secure foundation for interoperability between non-POSIX (Active Directory) and POSIX deployments. In Active Directory world some crucial POSIX information is not available. When this information required on POSIX side, it is either synthesized or mapped onto existing objects by FreeIPA and Samba AD.&lt;/p&gt;
&lt;p&gt;Kerberos protocol originally didn’t include any means to securely tie Kerberos principals to identities. For example, one was able to create a Windows machine named &lt;code&gt;root&lt;/code&gt; in Active Directory and then use its machine account to login to a different machine as &lt;code&gt;root&lt;/code&gt; POSIX user. This attack approach not possible anymore if all sides (Kerberos KDCs of the involved realms and a target machine) use authorization data in Kerberos tickets to exchange identity details of the original Kerberos principal’s operating system object. In this case it would mean that a Kerberos principal &lt;code&gt;root&lt;/code&gt; would have its machine account information associated with the Kerberos ticket and the target machine would be able to inquire and see that the real Kerberos principal would be &lt;code&gt;host/root.some.domain&lt;/code&gt; and that this principal’s operating system object type is a machine account.&lt;/p&gt;
&lt;p&gt;The extensions also give ability to communicate group membership details and more information about the account. FreeIPA domain controllers already use these details to check and map properties of trusted Active Directory domains’ objects. For  native IPA objects we also generate this information. IPA-IPA trust can rely on these details as well.&lt;/p&gt;
&lt;p&gt;This observation allowed us to start with an experiment. Create a trusted domain object that represents a trusted IPA domain and see what does not work and needs a fix to make IPA-IPA trust a reality. We originally thought to replicate Active Directory infrastructure on IPA domain controller side so that existing &lt;code&gt;ipa trust-add --type=ad ..&lt;/code&gt; command can be used to establish trust.&lt;/p&gt;
&lt;p&gt;These changes are part of the tree I maintain at &lt;a href=&quot;https://github.com/abbra/freeipa/tree/wip-ipa-ipa-trust&quot;&gt;my github WIP tree&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;identity-information-retrieval&quot;&gt;Identity information retrieval&lt;/h3&gt;
&lt;p&gt;A part of Active Directory infrastructure that we implemented first was Global Catalog. Global Catalog is a separate, read-only, LDAP instance that contains a subset of the information about all Active Directory objects in the forest. Since FreeIPA LDAP tree uses different LDAP schema and structure than Active Directory LDAP tree, SSSD’s Active Directory identity provider cannot use normal FreeIPA LDAP tree as “yet another Active Directory domain’s LDAP tree”. We imagined that adding support for the Global Catalog (which SSSD is able to query) would make it possible to query IPA users and groups as “Active Directory” users and groups.&lt;/p&gt;
&lt;p&gt;We soon found out two issues with this approach. It is not possible to force SSSD to use Global Catalog exclusively. SSSD uses the primary LDAP tree for retrieving users’ information and only switches to Global Catalog for retrieving groups information. Adding support for Global Catalog would not help: existing Active Directory domain identity provider in SSSD would not be able to work against a trusted IPA domain anyway. A proper support for trusted IPA domain in SSSD is needed.&lt;/p&gt;
&lt;p&gt;Here we stumbled upon our next issue. SSSD implementation for IPA domain provider includes ability to handle all trusts to Active Directory domains that IPA deployment has. Trusted domains (subdomains, in SSSD speak), in theory, can come from any trust type. Since IPA has only a trust to Active Directory, SSSD implementation did not have an infrastructure to handle different types of subdomains. Instead, a single subdomain type is assumed: any subdomain discovered is an Active Directory domain. Even if we present IPA-IPA trust as an Active Directory trust, SSSD would still attempt to use Active Directory-specific LDAP schema and directory information tree arrangement when making LDAP queries. IPA users and groups from trusted domains aren’t found because LDAP server would not match that LDAP query to the IPA LDAP tree and schema.&lt;/p&gt;
&lt;p&gt;SSSD needed a complete refactoring of the subdomains’ infrastructure to allow more than one subdomain type to be present. This work is still in progress. Justin Stephenson from the SSSD team tracks his progress in &lt;a href=&quot;https://github.com/justin-stephenson/sssd/pull/69&quot;&gt;this WIP pull request&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;demo&quot;&gt;Demo&lt;/h3&gt;
&lt;p&gt;With the refactoring work currently being done by Justin, it is possible to combine two parts: Global Catalog-based FreeIPA changes from &lt;a href=&quot;https://github.com/abbra/freeipa/tree/wip-ipa-ipa-trust&quot;&gt;my WIP source tree&lt;/a&gt; and SSSD changes from &lt;a href=&quot;https://github.com/justin-stephenson/sssd/pull/69&quot;&gt;Justin’s WIP source tree&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;We have these modifications to FreeIPA and SSSD prebuilt in Fedora COPR repository &lt;code&gt;abbra/wip-ipa-trust&lt;/code&gt;. The packages there work in a specific environment where two FreeIPA deployments named &lt;code&gt;ipa1.test&lt;/code&gt; and &lt;code&gt;ipa2.test&lt;/code&gt; because we have so far no way to differentiate trusted IPA deployment from a trusted Active Directory deployment, thus SSSD hardcodes the names of the IPA domains to trust.&lt;/p&gt;
&lt;p&gt;A trust between &lt;code&gt;ipa1.test&lt;/code&gt; and &lt;code&gt;ipa2.test&lt;/code&gt; can be established using standard &lt;code&gt;ipa trust-add&lt;/code&gt; command. This approach allowed us to investigate what is working or not after the trust link is created. Both FreeIPA and SSSD teams can also work on validating that specific IPA functionality available to handle trusted Active Directory users and groups is also working with IPA-IPA trust.&lt;/p&gt;
&lt;p&gt;I recorded &lt;a href=&quot;https://youtube.com/watch/?v=z6o1tj9XUMQ&quot;&gt;a small demo&lt;/a&gt; on Fedora 40:&lt;/p&gt;
&lt;div class=&quot;embed-container&quot;&gt;
&lt;iframe width=&quot;740&quot; height=&quot;480&quot;
  src=&quot;https://www.youtube.com/embed/z6o1tj9XUMQ&quot;
  title=&quot;YouTube video player&quot; frameborder=&quot;0&quot; allow=&quot;encrypted-media; picture-in-picture; web-share&quot;
  referrerpolicy=&quot;strict-origin-when-cross-origin&quot;
  allowfullscreen&gt;&lt;/iframe&gt;
&lt;/div&gt;
&lt;p&gt;Two administrators establish trust between their environments and then allow use of resources across the trust. Since the exact details how trust is established will change, I omitted that step and show pre-created trust entries along with the ID range details. Only ‘Active Directory trust with POSIX attributes’ ID range type supported for now. It should not be a problem though because IPA deployments do provide POSIX information.&lt;/p&gt;
&lt;p&gt;To allow access to IPA API, an administrator of the trusting domain needs to create ID overrides for user from the trusted domain. Once the overrides are in place, a user from the trusted domain can issue IPA API calls. In the demo we do &lt;code&gt;ipa ping&lt;/code&gt; call and show that underlying Kerberos service tickets were requested and issued.&lt;/p&gt;
&lt;h3 id=&quot;future-work&quot;&gt;Future work&lt;/h3&gt;
&lt;p&gt;Now that we validated the approach, the road splits into two:&lt;/p&gt;
&lt;ul class=&quot;md-list&quot;&gt;&lt;li&gt;&lt;p&gt;figure out how to get trust established&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;fix remaining bugs to make ‘day two’ operations possible.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;Establishing trust is an interesting problem. Or two. For pure IPA-IPA trust we don’t need to provision the same infrastructure as with Active Directory trust: we don’t need to run Samba on each domain controller to be able to create trusted domain objects and respond to DCE RPC requests because we don’t use DCE RPC in SSSD.&lt;/p&gt;
&lt;p&gt;On top of that, FreeIPA has extensive set of passwordless authentication methods which require use of a FAST channel when obtaining an initial Kerberos TGT. When trust to Active Directory created, we first authenticate to AD DC to get a Kerberos TGT of the Active Directory’s administrator. Windows does not have support for passwordless authentication methods through Kerberos except for PKINIT (smartcards), so in most cases we deal with password authentication. If an IPA administrative account is using passwordless method to authenticate, we first have to create a FAST channel or a trusted-to-be domain controller will not even expose supported pre-authentication methods. Any existing Kerberos ticket could be used to create the FAST channel but it must be from the trusted domain and we don’t have trust yet. In our own domain we can use a machine account (on a particular machine) or an Anonymous PKINIT to create the FAST channel. For a trusted-to-be domain we have to trust the CA who issued PKINIT certificates to their KDC. And KDCs might be accessible through a HTTPS proxy (MS-KKDCP protocol). This means some kind of pre-trust exchange needed to make sure we can authenticate against their KDCs successfully.&lt;/p&gt;
&lt;p&gt;Also, we have no idea what exact pre-authentication methods will be available to the user. Practically, we only care about being able to authenticate to the trusted domain’s IPA API and then use that connection to set things up. For this it would be enough to authenticate to the trusted-to-be domain’s IPA API endpoint, save received cookies and use them. This method wouldn’t support passwordless authentication either, except an OTP method. FIDO2 and external IdP (OAuth2) authentication aren’t yet directly supported in IPA web UI and IPA API end-points.&lt;/p&gt;
&lt;p&gt;With all those complications, we look at enabling OAuth2-based authentication and authorization endpoints in IPA first. We then can use them to request a token from a trusted-to-be domain’s OAuth2 endpoint and use it to establish the trust. A remote domain controller will handle the authentication of their users and will be able to supply all required details: trusted CA chains, ID ranges, scopes for authentication/ID mapping, etc.&lt;/p&gt;
&lt;p&gt;And the OAuth2 endpoint will allow us to handle own passwordless authentication methods for IPA Web UI and applications on the enrolled systems like Cockpit which will be able to delegate to IPA for the user login.&lt;/p&gt;</description>
      <pubDate>Fri, 31 May 2024 12:30:00 +0300</pubDate>
      <link>https://vda.li/en/posts/2024/05/31/ipa-ipa-trust-progress/</link>
      <guid isPermaLink="true">https://vda.li/en/posts/2024/05/31/ipa-ipa-trust-progress/</guid>
      <category>freeipa</category>
      <category>fedora</category>
      <category>kerberos</category>
      <category>samba</category>
    </item>
    <item>
      <title>CentOS Connect 2024 report</title>
      <description>&lt;p&gt;February 1st-4th I participated in two events in Brussels: CentOS Connect and FOSDEM. FOSDEM is getting closer to its quarter a century anniversary next year. With 67 mini-conferences and another 30 events around it, it is considered one of the largest conferences in Europe, any topic included. This report is about CentOS Connect.&lt;/p&gt;
&lt;h2 id=&quot;centos-connect&quot;&gt;CentOS Connect&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://connect.centos.org&quot;&gt;CentOS Connect&lt;/a&gt; was a two-day event preceding FOSDEM. Organized by the CentOS project, it brought together contributors from multiple projects around CentOS Stream upstreams (such as Fedora Project) and downstreams (from Red Hat Enterprise Linux, AlmaLinux, Rocky Linux, and others), long-time users and community members. A lot of talks were given on both days and several special interest groups (SIGs) ran their workshops on the first day.&lt;/p&gt;
&lt;h2 id=&quot;centos-integration-sig&quot;&gt;CentOS Integration SIG&lt;/h2&gt;
&lt;p&gt;I have attended a workshop organized by the CentOS Integration SIG. The focus of this group is to define and run integration tests around CentOS Stream delivery to the public. While CentOS Stream composes are built using the messages on how RHEL next minor version is composed after being thoroughly tested by Red Hat’s quality engineering group, there is a value in testing CentOS Stream composes by other community members independently as their use cases might differ. Right now the set of tests is defined as a &lt;code&gt;t_functional&lt;/code&gt; suite maintained by the CentOS Core SIG but this suite is not enough for the complex scenarios.&lt;/p&gt;
&lt;p&gt;The Integration SIG is looking at improving the situation. Two projects were present and interested in this work: RDO (RPM-based distribution of OpenStack) and RHEL Identity Management. Both teams have to deal with coordinated package deliveries across multiple components and both need to get multi-host deployments tested. RDO can be treated as a product built on top of CentOS Stream where its own RDO deliveries are installed on top of CentOS Stream images. RHEL Identity Management (IdM), on the other hand, is a part of RHEL. It is famously known as a ‘canary in the RHEL mine’ (thanks to Stephen Gallagher’s being poetic a decade ago): if anything is broken in RHEL, chances are it will be visible in RHEL IdM testing. With RHEL IdM integration scope expanding to provide passwordless desktop login support, this becomes even more important and also requires multi-host testing.&lt;/p&gt;
&lt;p&gt;CentOS Integration SIG’s proposal to address these requirements is interesting. Since CentOS Stream compose event is independent of the tests, a proposal by Aleksandra Fedorova and Adam Samalik is to treat the compose event in a way similar to a normal development workflow. Producing CentOS Stream compose would generate a merge request of a metadata associated with it to a particular git repository. This merge request then can be reacted to by the various bots and individuals. Since CentOS Stream compose is public, it is already accessible to third-party developers to run their tests and report back the results. This way qualification of the compose promotion to CentOS Stream mirrors can be affected by all parties and will help to keep already published composes in a non-conflicting state.&lt;/p&gt;
&lt;p&gt;Since most of the projects involved already have their own continuous integration systems, adding another trigger for those would be trivial. For RHEL IdM and its upstream components (FreeIPA, SSSD, 389-ds, Dogtag PKI, etc.) it would also be possible finally to react to changes to CentOS Stream well ahead of time too. In the past this was complicated by a relative turbulence in the CentOS Stream composes early in RHEL next minor release development time when everybody updates their code and stabilization needs a lot of coordination. I am looking forward to Aleksandra’s proposal to land in the Integration SIG’s materials soon.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Update&lt;/strong&gt;: Aleksandra has published her proposal at the &lt;a href=&quot;https://discussion.fedoraproject.org/t/centos-connect-follow-up-proposal-for-the-git-interface-to-the-compose-gate/104981&quot;&gt;Fedora Discussion board&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;centos-stream-and-epel&quot;&gt;CentOS Stream and EPEL&lt;/h2&gt;
&lt;p&gt;Two talks, by Troy Dawson and Carl George, described the current state of EPEL repository and its future interactions with CentOS 10 Stream. Troy’s discussion was fun, as usual: a lot of statistics obtained from the DNF repository trackers shows that old habits are hard to get rid off and moving forward is a struggle to many users despite security and supportability challenges with older software. Both CentOS 7 and CentOS 8 Stream end of life dates are coming in 2024, adding enough pressure themselves to that.&lt;/p&gt;
&lt;p&gt;There are interesting statistics from the EPEL evolution. In August 2023 at Flock to Fedora conference Troy and Carl pointed out that 727 packagers maintained 7298 packages in EPEL 7, 489 packagers handled 4968 packages in EPEL 8, and 396 packagers were handling 5985 packages in EPEL 9. Half a year later we have 7874 packages in EPEL 7, 5108 packages in EPEL 8, and 6868 packages in EPEL 9. Pace seems to pick up EPEL 9 with upcoming end of life dates for older versions. Since soon only EPEL 9 and EPEL 10 would be actively built, there are probably more packagers that would be active in them as well.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://vda.li/en/_astro/epel-packages.BmcNSv1I_Z184lMk.webp&quot; srcset=&quot;https://vda.li/en/_astro/epel-packages.BmcNSv1I_Z1UX5vy.webp 640w, https://vda.li/en/_astro/epel-packages.BmcNSv1I_Z1mwWSK.webp 960w, https://vda.li/en/_astro/epel-packages.BmcNSv1I_Z1FKOt9.webp 1280w, https://vda.li/en/_astro/epel-packages.BmcNSv1I_ZxvFgU.webp 1920w&quot; sizes=&quot;(min-width: 992px) 70vw, 100vw&quot; width=&quot;3136&quot; height=&quot;1760&quot; alt=&quot;EPEL package statistics slide&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/p&gt;
&lt;p&gt;EPEL 10 is coming soon. It will bring a slight difference in package suffixes and overall reduction of complexity to packagers. It is great to see how close EPEL work tracks to ELN activities in Fedora. One thing worth noting is that every Fedora package maintainer is a potential EPEL maintainer as well because EPEL reuses Fedora infrastructure for package maintenance. Even if someone is not maintaining EPEL branches on their Fedora packages (I am not doing that myself – my packages are mostly in RHEL), it allows easy jump-in and collaboration. After all, if packages aren’t in RHEL but are in Fedora, their EPEL presence is just one git branch (and Fedora infrastructure ticket) away.&lt;/p&gt;
&lt;h2 id=&quot;20-years-of-centos-project&quot;&gt;20 years of CentOS project&lt;/h2&gt;
&lt;p&gt;First day of the CentOS Connect event ended with a party to celebrate 20 years of the CentOS Project. First release (“CentOS version 2”) went out on May 14th, 2004 but since CentOS Connect is the closest big event organized by the project this year, getting a lot of contributors together to celebrate this anniversary seemed appropriate. A huge cake was presented, so big that it wasn’t possible to consume it completely during the party. It was delicious (like a lot of Belgian chocolate!) and next day coffee breaks allowed me to enjoy it a lot.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://vda.li/en/_astro/centos-20y-cake.DkS5pQJv_ZgUauA.webp&quot; srcset=&quot;https://vda.li/en/_astro/centos-20y-cake.DkS5pQJv_2pQQpt.webp 640w, https://vda.li/en/_astro/centos-20y-cake.DkS5pQJv_17fgHQ.webp 960w, https://vda.li/en/_astro/centos-20y-cake.DkS5pQJv_15QDFG.webp 1280w, https://vda.li/en/_astro/centos-20y-cake.DkS5pQJv_Z2mky5W.webp 1920w&quot; sizes=&quot;(min-width: 992px) 70vw, 100vw&quot; width=&quot;4096&quot; height=&quot;2304&quot; alt=&quot;CentOS 20th anniversary cake&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;freeipa-and-centos-project-infrastructure&quot;&gt;FreeIPA and CentOS project infrastructure&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://talks.vda.li/talks/2024/CentOS-Connect-Discuss-Your-FreeIPA.pdf&quot;&gt;My own talk&lt;/a&gt; was originally planned to gather feedback from all projects which build on top of CentOS as they use a very similar infrastructure. CentOS Project infrastructure is shared with Fedora Project which is built around FreeIPA as a backend and Noggin as a user management frontend. I asked in advance for some feedback from Fedora, CentOS, AlmaLinux, and RockyLinux infrastructure teams and haven’t gotten that much which prompted my own investigation. It is not an easy job since most organizations aren’t really interested in telling the world details of their core infrastructure. Hope was that I’d be able to see real world usage and maybe take some lessons from it back to the development teams.&lt;/p&gt;
&lt;p&gt;While working on my talk, we also experienced an outage in Fedora infrastructure related to the upgrade of the FreeIPA setup used there. My team has been helping Fedora infrastructure administrators so I finally got the feedback I was looking for. That led to several fixes upstream and they have recently been backported to RHEL and CentOS Stream as well. However, the overall lack of feedback is concerning – or at least I thought so.&lt;/p&gt;
&lt;p&gt;During CentOS Connect I had the opportunity to discuss this with both AlmaLinux (Jonathan) and RockyLinux (Luis) projects’ sysadmins. “It just works” is a common response I get. Well, that’s nice to hear but what was more exciting to hear is that these projects went a bit further than we did in Fedora and CentOS Stream with their environments. Luis &lt;a href=&quot;https://talks.vda.li/talks/2024/CentOS-Connect-Discuss-Your-FreeIPA.pdf&quot;&gt;has published the whole RockyLinux infrastructure&lt;/a&gt; code responsible for FreeIPA deployment. It is based heavily on ansible-freeipa, reuses the same components we developed for Fedora Infrastructure. Rocky also runs FreeIPA tests in OpenQA instance, similarly to Fedora, and hopefully Luis would contribute more tests to cover passwordless login, already available in CentOS Stream. This would be a very welcome contribution in the light of the Integration SIG activities, helping us to test more complex scenarios community-wide. AlmaLinux infrastructure also uses ansible-freeipa but the code is not publicly available, for whatever reason. Jonathan promised to rectify this problem.&lt;/p&gt;
&lt;h2 id=&quot;hallway-tracks&quot;&gt;Hallway tracks&lt;/h2&gt;
&lt;p&gt;I had a number of discussions with people from all kinds of CentOS communities. FreeIPA sits at a unique position by providing secure infrastructure to run POSIX workloads and linking it with modern requirements to web authentication. Our effort to improve passwordless login to Linux environments with reuse of Kerberos to propagate authorization state across multiple machines helps to solve the ‘between the worlds’ problems. That is something that many academic institutions have noticed already and many talks I had in the hallways were related to it.&lt;/p&gt;</description>
      <pubDate>Tue, 13 Feb 2024 09:25:00 +0200</pubDate>
      <link>https://vda.li/en/posts/2024/02/13/CentOS-Connect-report/</link>
      <guid isPermaLink="true">https://vda.li/en/posts/2024/02/13/CentOS-Connect-report/</guid>
      <category>freeipa</category>
      <category>fedora</category>
      <category>centos</category>
    </item>
    <item>
      <title>Flock to Fedora 2023 report</title>
      <description>&lt;p&gt;On August 2nd-4th, 2023, Fedora Project ran its annual contributors conference, &lt;a href=&quot;https://flocktofedora.org&quot;&gt;Flock to Fedora&lt;/a&gt;, in Cork, Ireland. After a previous successful Flock in 2019 in Budapest, Fedora contributors did not meet in person due to rough pandemia years and had created Nest with Fedora online event instead. Nest ran for three years but online meetings aren’t a full replacement for face to face collaboration. Cork’s Flock was supposed to combine both online and offline events together.&lt;/p&gt;
&lt;p&gt;I have been attending and presenting at various Flock and Nest events over past seven years. I was looking forward to see and collaborate with many other project participants and users and get to know new people as well.&lt;/p&gt;
&lt;p&gt;My travel to Cork was unremarkable. I took a direct flight from Helsinki to Dublin and then an Aircoach bus to Cork. The ‘unremarkable’ part was really about the unexpected delays people did report over the Matrix channel. The only ‘trouble’ I had was to catch a taxi at 11pm after arrival to Cork to get to my B&amp;amp;B. The Aircoach bus from Dublin airport is very popular in summer and whatever taxi fleet is in Cork was DDoSed by the passengers.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://vda.li/en/_astro/hotel-stay.DSDxuHdm_17GAtj.webp&quot; srcset=&quot;https://vda.li/en/_astro/hotel-stay.DSDxuHdm_2aRzO.webp 640w, https://vda.li/en/_astro/hotel-stay.DSDxuHdm_DsTuz.webp 960w, https://vda.li/en/_astro/hotel-stay.DSDxuHdm_Zfrsvc.webp 1280w, https://vda.li/en/_astro/hotel-stay.DSDxuHdm_1qntn3.webp 1920w&quot; sizes=&quot;(min-width: 992px) 70vw, 100vw&quot; width=&quot;4096&quot; height=&quot;1834&quot; alt=&quot;The bed-and-breakfast and the conference hotel in Cork&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/p&gt;
&lt;p&gt;Cork is hilly. I stayed in excellent B&amp;amp;B across the road from the conference hotel. The hotel and its conference facilities are in separate buildings; the events building is up hill from the hotel. Walking is helpful, climbing harder but given we are sitting most of the time, was a welcoming ‘struggle’. Perhaps, my stay outside of the conference hotel has also helped to avoid COVID-19 which few other participants, sadly, contracted. It is hit or miss every time.&lt;/p&gt;
&lt;p&gt;Unfortunately, not everyone made to Cork. &lt;a href=&quot;https://sfconservancy.org/news/2022/jun/14/remembering-marina/&quot;&gt;Marina Zhurakhinskaya&lt;/a&gt; passed away in June 2022. &lt;a href=&quot;https://funnelfiasco.com/blog/2023/05/12/inaction-bcotton/&quot;&gt;Ben Cotton&lt;/a&gt;, Fedora Program Manager, has been let go as a part of Red Hat’s layoffs earlier this year. Both had definitely changed Fedora project dramatically, in many ways, both leading to openness and friendliness Fedora is known for. Many presenters remembered both Marina and Ben during their sessions.&lt;/p&gt;
&lt;p&gt;2023’s edition of Flock to Fedora was also the first Fedora Project’s event collocated with CentOS Connect. As a result, it brought together Red Hat Enterprise Linux distribution upstreams and downstreams together.&lt;/p&gt;
&lt;h2 id=&quot;talks&quot;&gt;Talks&lt;/h2&gt;
&lt;p&gt;In total, there were up to four parallel tracks, dedicated to different areas of a distribution development and a project’s life and spanned over three days. That, unsurprisingly, made it challenging to visit all talks and activities. It is a common trait shared by many successful events. And for those who wanted to continue discussions after a talk has ended, there is always a ‘hallway track’.&lt;/p&gt;
&lt;h3 id=&quot;state-of-fedora-2023&quot;&gt;State of Fedora 2023&lt;/h3&gt;
&lt;p&gt;The first talk was ‘State of Fedora 2023’ by the project leader, Matthew Miller. Recording is available &lt;a href=&quot;https://www.youtube.com/live/LhLEV4fi2xw?feature=share&amp;amp;t=21327&quot;&gt;here&lt;/a&gt;. I am linking to the re-take of the talk as the original streaming was off by 20 minutes and Matthew had to reprise it again.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://vda.li/en/_astro/state-of-fedora.DmiJ5x8P_R4FID.webp&quot; srcset=&quot;https://vda.li/en/_astro/state-of-fedora.DmiJ5x8P_xoBw8.webp 640w, https://vda.li/en/_astro/state-of-fedora.DmiJ5x8P_Z2wLNI7.webp 960w, https://vda.li/en/_astro/state-of-fedora.DmiJ5x8P_ZMCabe.webp 1280w, https://vda.li/en/_astro/state-of-fedora.DmiJ5x8P_Z2ehSgS.webp 1920w&quot; sizes=&quot;(min-width: 992px) 70vw, 100vw&quot; width=&quot;3136&quot; height=&quot;1404&quot; alt=&quot;State of Fedora 2023 talk&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/p&gt;
&lt;p&gt;A major announcement made during the talk was a hiring one. &lt;a href=&quot;https://communityblog.fedoraproject.org/job-posting-fedora-operations-architect/&quot;&gt;Fedora Operations Architect role&lt;/a&gt; has been introduced after a program manager role that Ben Cotton so masterfully executed was eliminated. Hopefully, this new role will be filled soon and will allow to capture the same benefits that Ben brought to Fedora. The role is a bit different, though, as it is focused on cross-project and cross-distro impact across Fedora and RHEL.&lt;/p&gt;
&lt;p&gt;Fedora contributors’ survey results were also unveiled by Matthew in the talk. In general, contributors keep trust in the project and continue their participation at the pre-pandemia levels. Recent social networking turmoil around Red Hat actions hasn’t influenced the results too much. The screenshots below are from the video stream as the talk’s slides aren’t yet available.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://vda.li/en/_astro/state-of-fedora-stats-1.BiYYlfbg_Z2ecVBA.webp&quot; srcset=&quot;https://vda.li/en/_astro/state-of-fedora-stats-1.BiYYlfbg_Z2ojKVw.webp 640w, https://vda.li/en/_astro/state-of-fedora-stats-1.BiYYlfbg_16mhK9.webp 960w, https://vda.li/en/_astro/state-of-fedora-stats-1.BiYYlfbg_1sj8Ag.webp 1280w, https://vda.li/en/_astro/state-of-fedora-stats-1.BiYYlfbg_Z2ecVBA.webp 1609w&quot; sizes=&quot;(min-width: 992px) 70vw, 100vw&quot; width=&quot;1609&quot; height=&quot;901&quot; alt=&quot;State of Fedora contributor survey results, part 1&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt; &lt;img src=&quot;https://vda.li/en/_astro/state-of-fedora-stats-2.odijOQ9__Z1xe117.webp&quot; srcset=&quot;https://vda.li/en/_astro/state-of-fedora-stats-2.odijOQ9__Z2mX9Gz.webp 640w, https://vda.li/en/_astro/state-of-fedora-stats-2.odijOQ9__17HT06.webp 960w, https://vda.li/en/_astro/state-of-fedora-stats-2.odijOQ9__29i4bJ.webp 1280w, https://vda.li/en/_astro/state-of-fedora-stats-2.odijOQ9__Z1xe117.webp 1609w&quot; sizes=&quot;(min-width: 992px) 70vw, 100vw&quot; width=&quot;1609&quot; height=&quot;901&quot; alt=&quot;State of Fedora contributor survey results, part 2&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/p&gt;
&lt;p&gt;The talk went into details on what Matthew and Fedora Council aim for Fedora Project’s future. Growing a project with thousands of contributors spread around the world and representing different cultures is hard. A lot of effort is put into making Fedora a welcoming place to everyone who is willing to work together towards a common goal.&lt;/p&gt;
&lt;h3 id=&quot;rpminspect-lessons-from-three-distributions&quot;&gt;&lt;code&gt;rpminspect&lt;/code&gt;: Lessons from three distributions&lt;/h3&gt;
&lt;p&gt;David Cantrell created and maintains a tool that helps RHEL maintainers to keep their packages sane over years of maintenance. It is run as a part of CentOS Stream merge request process, as part of Fedora gating and pull request testing, and as a gating test for RHEL.&lt;/p&gt;
&lt;p&gt;The talk itself is an excellent retrospective on what one should consider when creating a new Open Source project while working on it full time. David provided observations on how to sell the idea to your management, how to get people interested in becoming a community for your project, how to sustain development in a long run. This is one of rare gems of a ‘lone wolf’ maintainership stories that everybody needs to absorb when they start their new journey. Believe me, it is worth it.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://vda.li/en/_astro/rpminspect-1.BAwRhCt-_olY5M.webp&quot; srcset=&quot;https://vda.li/en/_astro/rpminspect-1.BAwRhCt-_1AlLNb.webp 640w, https://vda.li/en/_astro/rpminspect-1.BAwRhCt-_ZixYs7.webp 960w, https://vda.li/en/_astro/rpminspect-1.BAwRhCt-_Z2kBaED.webp 1280w, https://vda.li/en/_astro/rpminspect-1.BAwRhCt-_ZrldOL.webp 1920w&quot; sizes=&quot;(min-width: 992px) 70vw, 100vw&quot; width=&quot;3136&quot; height=&quot;1404&quot; alt=&quot;rpminspect talk&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;using-aiml-to-process-automated-test-results-from-openqa&quot;&gt;Using AI/ML to process automated test results from OpenQA&lt;/h3&gt;
&lt;p&gt;Tim Flink from Fedora QE team decided to apply AI/ML to a problem of identifying hanging or failing jobs in OpenQA. OpenQA runs full-VM tests and records screencasts of everything what is shown on a VM screen. A crash of a graphical environment is abruptly visible there as graphics would be replaced by a terminal with a Wayland’s stacktrace. What followed is an experiment on processing these screens to reliably detect a particular type of a crash.&lt;/p&gt;
&lt;p&gt;We spent some time with Tim discussing how these experiments can be applied to finding out possible issues in other system reports. Since Fedora is upstream of CentOS Stream or RHEL, it means certain issues – and their fixes – would often appear in Fedora first. If we could train a model on those issues in Fedora, can we detect automatically whether a particular fix is required in RHEL later? This is quite relevant to FreeIPA and SSSD as we do run their tests in OpenQA as a part of Fedora Server release criteria.&lt;/p&gt;
&lt;p&gt;Another possible use case is to do a reverse training. Since we do know how a potential failure could look like, we can intentionally build an OpenQA test environment that would reproduce the failure and then train a model to recognize logs from such failures in real life scenarios. For example, establishing trust to Active Directory in FreeIPA is reliant on a working DNS setup, working firewall, etc. Failure to communicate through an incomplete firewall would be reflected with timeouts in the logs which we could train to recognize. There are endless possibilities here to aid through &lt;em&gt;known errors&lt;/em&gt;…&lt;/p&gt;
&lt;h3 id=&quot;hallway-track&quot;&gt;Hallway track&lt;/h3&gt;
&lt;p&gt;On a similar note, I had discussion with Amazon’s David Duncan in the ‘hallway track’ which started from an observation that Cloud SIG would really benefit from our passwordless work: distributing VMs with pre-set passwords is not ideal, an ability to inject FIDO2 passkey information and have everything obey it at login in cloud would be great to have. Somewhere along this way, discussion switched to CoreOS-based environments and I realised my experiments with Fedora Silverblue to develop passwordless support for FreeIPA would probably be a subject to a talk that would be interesting to others as well.&lt;/p&gt;
&lt;p&gt;I am running my own Silverblue images which source SSSD and FreeIPA upstream test builds to allow me easily to switch between different potential options in one go, without messing with an installation environment. It is quite important for the integration work we do and would be crucial for end-to-end testing of upcoming GNOME changes.&lt;/p&gt;
&lt;p&gt;This also provided me an insight into what container-based environments need from FreeIPA and overall from enterprise domains to fit nicely. I should have submitted a talk about that to Flock! Well, I will do one next year, for sure. (And, TODO: file issues to track for that integration to FreeIPA upstream!)&lt;/p&gt;
&lt;p&gt;Another interesting discussion we had with Jonathan Dieter. Jonathan is a long term Fedora contributor and FreeIPA user. For past several years Jonathan works with a local Irish company that provides services around the world to test local phone numbers. They maintain an infrastructure in more than 80 countries where there might be no global cloud providers at all. To keep that infrastructure reliable, they use &lt;a href=&quot;https://www.jdieter.net/posts/2021/11/30/piv-vs-sk/&quot;&gt;FreeIPA&lt;/a&gt; (not alone, of course) and &lt;a href=&quot;https://www.jdieter.net/posts/2020/10/31/switching-to-ostree/&quot;&gt;OStree-based images&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;asahi-linux-and-fedora&quot;&gt;Asahi Linux and Fedora&lt;/h3&gt;
&lt;p&gt;It is one of the talks that I missed to attend in person as conflicts are inevitable: Mo Duffy’s Podman Desktop talk and Adam Williamson’s Fedora CI state talk were running at the same time.&lt;/p&gt;
&lt;p&gt;Asahi Linux is a project which aims to upstream support for Apple’s ARM64 architecture, best known through Apple’s M1 and M2 systems. At the Flock Asahi Linux project members &lt;a href=&quot;https://asahilinux.org/2023/08/fedora-asahi-remix/&quot;&gt;have announced&lt;/a&gt; that not only Fedora Asahi Remix will be the flagship distribution for the project, but also &lt;a href=&quot;https://discussion.fedoraproject.org/c/neighbors/asahi/92&quot;&gt;Fedora Discourse instance&lt;/a&gt; will be used to handle Asahi Linux community collaborations.&lt;/p&gt;
&lt;p&gt;Asahi’s announcement also an example of how friendly has become Fedora Project as a community over years. I am definitely looking forward to see the remix to become one of official builds of Fedora.&lt;/p&gt;
&lt;h3 id=&quot;podman-desktop-from-fedora-to-kubernetes-for-beginners&quot;&gt;Podman desktop: from Fedora to Kubernetes for beginners&lt;/h3&gt;
&lt;p&gt;Mo Duffy gave an outstanding talk about using Podman desktop to deliver workloads for non-technical people. It was a highlight of the conference, for sure. She also made few interesting points. For one, running cloud-based workloads locally to allow offline operations is nice. Mo demonstrated a &lt;a href=&quot;https://blog.linuxgrrl.com/2022/01/19/running-penpot-locally-docker-free-with-podman/&quot;&gt;Penpot instance&lt;/a&gt;, which is a design and prototyping application. Running it locally helps to maintain the same workflow while on an intercontinental flight. However, even more interesting is that this approach also allows to use a cloud software that otherwise is considered insecure. For example, running a Wordpress setup locally to benefit from its nice UI in a local browser and export static web site content to push to the actual web hosting.&lt;/p&gt;
&lt;p&gt;By lowering a barrier to use containerised applications through Podman Desktop we may hope to get more people join our community and contribute. Starting with Podman Desktop’s friendliness would allow these newcomers to discover other Fedora flavors and features. It is certainly an interesting aspect we could expand further in a way similar how this ‘F’ in Fedora got expanded in Mo’s presentation.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://vda.li/en/_astro/podmandesktop-1.CvGLGfAR_Z1o8JIC.webp&quot; srcset=&quot;https://vda.li/en/_astro/podmandesktop-1.CvGLGfAR_Z1ozPNA.webp 640w, https://vda.li/en/_astro/podmandesktop-1.CvGLGfAR_Z15QcRY.webp 960w, https://vda.li/en/_astro/podmandesktop-1.CvGLGfAR_Z2eMzB3.webp 1280w, https://vda.li/en/_astro/podmandesktop-1.CvGLGfAR_Z1DP3RY.webp 1920w&quot; sizes=&quot;(min-width: 992px) 70vw, 100vw&quot; width=&quot;2560&quot; height=&quot;1146&quot; alt=&quot;Podman Desktop talk&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;panel-upstream-collaboration--cooperation-in-the-enterprise-linux-ecosystem&quot;&gt;Panel: Upstream collaboration &amp;amp; cooperation in the Enterprise Linux ecosystem&lt;/h3&gt;
&lt;p&gt;Another conference highlight was the panel that brought representatives of Fedora, RHEL, Rocky Linux, Alma Linux, and CentOS Stream together on stage. Distributions upstream and downstream of RHEL presented their views on various development and community topics. It is worth to &lt;a href=&quot;https://www.youtube.com/watch?v=r9iy9f80nic&amp;amp;t=24804s&quot;&gt;watch the stream&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;state-of-epel&quot;&gt;State of EPEL&lt;/h3&gt;
&lt;p&gt;Trow Dawson and Carl George did present another state of EPEL. EPEL has a solid contributors’ base who keep thousands of packages available to RHEL and downstream distributions’ users. EPEL is using Fedora infrastructure and for many packages it shares maintainers with Fedora (EPEL branches are branches in Fedora dist-git for the same package, if this package is not in RHEL). So all EPEL contributors are Fedora contributors. ;)&lt;/p&gt;
&lt;p&gt;One interesting aspect in every “State of EPEL” talk is a long tail of the EPEL demographics. Much like “State of Fedora” shows demographics of Fedora releases, EPEL statistics includes details on who is running the lowest number of downstream systems:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://vda.li/en/_astro/epelstate-1.CUaaBKAn_ZPhXEp.webp&quot; srcset=&quot;https://vda.li/en/_astro/epelstate-1.CUaaBKAn_1ImL3P.webp 640w, https://vda.li/en/_astro/epelstate-1.CUaaBKAn_ZmEVYs.webp 960w, https://vda.li/en/_astro/epelstate-1.CUaaBKAn_Z28mq5A.webp 1280w, https://vda.li/en/_astro/epelstate-1.CUaaBKAn_Z2oSa0F.webp 1920w&quot; sizes=&quot;(min-width: 992px) 70vw, 100vw&quot; width=&quot;2560&quot; height=&quot;1146&quot; alt=&quot;State of EPEL talk&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;passwordless-fedora&quot;&gt;Passwordless Fedora&lt;/h3&gt;
&lt;p&gt;My talk was on the morning of the second day. People were still recovering from the night of International Candy Swap and table games so at start I had may be a couple of attendies. Eventually, we’ve got more people in the room and there were also online attendees so it wasn’t so feeling so lonely.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=GkYURkrIzx0&amp;amp;t=3226s&quot;&gt;My talk&lt;/a&gt; was similar to previous ones at FOSDEM and SambaXP. What was new is a demo from Ray Strode on how potentially a user experience could look like in GNOME for a passwordless login. Ray implemented a prototype of external identity provider login flow that Allan Day &lt;a href=&quot;https://gitlab.gnome.org/Teams/Design/os-mockups/-/issues/220&quot;&gt;has shared recently&lt;/a&gt;. This flow could be used for login through Microsoft’s Entra ID (a.k.a. Azure AD) or any OAuth2 provider supported by FreeIPA. We aren’t fully there yet but the goal is to do this work once for GNOME and reuse for various passwordless authentication approaches supported through SSSD.&lt;/p&gt;
&lt;p&gt;I also showed an &lt;a href=&quot;https://youtu.be/zK2FmP0j6tY&quot;&gt;old demo&lt;/a&gt; from my FOSDEM and Flock 2016. It shows how we integrated 2FA tokens (Yubikeys in this example) with FreeIPA to authenticate and obtain Kerberos tickets through a KDC proxy over HTTPS. These tickets then were used to login onto a VPN. This is something that is possible in Fedora and RHEL for almost a decade now.&lt;/p&gt;
&lt;h3 id=&quot;openqa-hacking&quot;&gt;OpenQA hacking&lt;/h3&gt;
&lt;p&gt;Before Flock, Adam Williamson started to work on integrating Samba AD tests into OpenQA for Fedora. It almost worked well but there were few issues Adam wasn’t able to resolve so we set down at the Flock and figured out at least few of those. The only remaining one was an apparent race condition within a test that enrolls a system to Samba AD using kickstart. SSSD, it seems, starts before networking is up and stable, and decides that it is offline. When the test tries to resolve an Active Directory user, SSSD fails to do so as it thinks to be offline.&lt;/p&gt;
&lt;p&gt;Interestingly, the same test against FreeIPA works fine. The same test done past kickstart works fine as well, for both FreeIPA and Samba AD. There is probably a need to add a waiting period to settle a network state. We saw this in past too but never found a good way to trigger a proper event for SSSD to recover.&lt;/p&gt;
&lt;h3 id=&quot;social-events&quot;&gt;Social events&lt;/h3&gt;
&lt;p&gt;I am trying to reduce candy consumption so I skipped the social events on the first day but attended the conference dinner on the second day. All social events during the Flock well organized and this one wasn’t exception either. We had interesting discussions with Fedora and Rocky folks, getting to know there is a lot of similarity in how people do their lives across the world.&lt;/p&gt;
&lt;p&gt;On Friday’s night another social event was a Ghost Tour. However, we skipped it and together with few other people went to do a bit of memorabilia road through another Mexican place and (of course!) a local bar. Life in IT and development in 90’s and early 2000’s weren’t that much different in US and Europe, really. Thanks to Spot and Amazon for covering the dinner, thanks to other folks for beer and a company.&lt;/p&gt;
&lt;p&gt;I left on Saturday at noon using the same Aircoach bus towards Dublin airport. The bus was full – make sure you have booked your seat online in advance. My flight back to Finland was uneventful as well. Overall, it was a great conference, as usual. I’d like to say thank you to all volunteers and organizers who keep Flock so wonderful and Fedora project so welcoming. Thank you!&lt;/p&gt;</description>
      <pubDate>Fri, 11 Aug 2023 13:46:00 +0300</pubDate>
      <link>https://vda.li/en/posts/2023/08/11/Flock-report/</link>
      <guid isPermaLink="true">https://vda.li/en/posts/2023/08/11/Flock-report/</guid>
      <category>freeipa</category>
      <category>fedora</category>
      <category>centos</category>
    </item>
    <item>
      <title>FreeIPA authentication improvements and Fedora Infrastructure part 2</title>
      <description>&lt;p&gt;This article continues the &lt;a href=&quot;https://vda.li/en/posts/2022/10/28/FreeIPA-Authentication-Improvements-and-Fedora-Infra/&quot;&gt;discussion&lt;/a&gt; about FreeIPA authentication improvements and how they could benefit Fedora Infrastructure.&lt;/p&gt;
&lt;p&gt;FreeIPA 4.9.10 has added support for &lt;a href=&quot;https://freeipa.readthedocs.io/en/latest/workshop/12-external-idp-support.html&quot;&gt;relaying authentication&lt;/a&gt; to OAuth2 identity providers (IdPs). Users would get their access to FreeIPA resources mediated by an external OAuth2 identity provider which supports OAuth2 device authorization grant flow (RFC 8628). This is not too dissimilar from how smart TVs connect to Youtube and other media services on your behalf. A user would be able to grant access to a scoped information to a FreeIPA OAuth2 client registered with such IdP. In order to authorize the access, the user might need to login to the IdP first and this is performed with the help of a browser running elsewhere. Most common browsers do have support for Webauthn/FIDO2 tokens, thus it is possible to build a system where a login to FreeIPA-enrolled system is authenticated by the FIDO2 token exclusively.&lt;/p&gt;
&lt;p&gt;Based on the result of the external IdP authorization grant, FreeIPA would then issue a Kerberos ticket to the user. The ticket can then be used for single sign-on across all FreeIPA services.&lt;/p&gt;
&lt;p&gt;The functionality to authenticate against an external IdP is already available in Fedora 36 versions of FreeIPA and SSSD. It is also available in RHEL 8.7 and 9.1 beta versions published in late September 2022.&lt;/p&gt;
&lt;p&gt;Relying on an external identity provider to authenticate your FreeIPA users would also mean rethinking the relationship between the IdP and the FreeIPA deployment. Typically, when people integrated FreeIPA with OAuth2 or SAML identity providers, an assumption was made that user authentication is handled by the FreeIPA servers and identity provider issues a token for a web application. Turning this situation around means FreeIPA only becomes a user data store – maybe even not the data store for the IdP itself. IdP would only need to know about the user identity from its own point of view while FreeIPA would have a POSIX identity of the same user, consumed by other applications. Whether it is visible through the IdP grants or via POSIX interfaces is more of an application implementation detail. Decoupling these details leads to a bit of duplication, of course, but allows for better flexibility. A user might come from a federated source and have their authentication handled by a different identity provider – their public service provider like Google, Github, Gitlab, or Microsoft Azure. Or Facebook and any other social media.&lt;/p&gt;
&lt;p&gt;All this, however, would mean a change to the way Fedora Accounts system and Fedora IdP, Ipsilon, interact with each other. Right now Ipsilon sources accounts information from the FreeIPA instance directly and delegates authentication to it as well (though PAM service provided by SSSD). Fedora Accounts system, in its turn, manages passwords and tokens in the FreeIPA instance. Since FreeIPA does not have support for Webauthn/FIDO2 web-based authentication yet, Ipsilon would need to manage that itself. So some user accounts would need to source their authentication details from FreeIPA and some would need to use Ipsilon’s internal source. That is a bit complicated as Ipsilon has no way to combine data sources.&lt;/p&gt;
&lt;p&gt;Ipsilon does not have any support for both OAuth2 device authorization grant flow and Webauthn/FIDO2 tokens. Even if the FreeIPA instance used by both Fedora project and CentOS project would be updated to provide external IdP authentication, the Ipsilon instance would not be able to utilize this new feature.&lt;/p&gt;
&lt;p&gt;Another alternative would be to use Keycloak (free software project upon which Red Hat Single Sign-On product is built). Keycloak 21 is adding multiple user stores support and the FreeIPA team works on &lt;a href=&quot;https://github.com/justin-stephenson/scim-keycloak-user-storage-spi&quot;&gt;a new provider&lt;/a&gt; to utilize it. This new Keycloak user store plugin supports SCIM v2 API and also needs a &lt;a href=&quot;https://github.com/freeipa/ipa-tuura&quot;&gt;new FreeIPA application&lt;/a&gt; that abstracts out access to FreeIPA resources as a SCIM v2 API. In the end, it is the same SSSD as a backend as in case of the Ipsilon IdP but with the ability to split the data store across multiple sources. Keycloak already has support for both OAuth2 device authorization grant flow and the Webauthn/FIDO2 tokens. How this all works together is shown in our &lt;a href=&quot;https://www.youtube.com/watch?v=NorXJN3tw3Q&amp;amp;list=PL0x39xti0_65yq9EuNtSLts0qm9_T-YiI&amp;amp;index=34&quot;&gt;&lt;em&gt;Nest with Fedora 2022 talk&lt;/em&gt;&lt;/a&gt;. Talk slides can be &lt;a href=&quot;https://vda.li/talks/2022/2022-Nest-With-Fedora-FreeIPA-and-OAuth2.pdf&quot;&gt;found here&lt;/a&gt; but the video includes a live demo session.&lt;/p&gt;
&lt;p&gt;On mobile devices front, both Google and Apple are gearing towards introduction of software tokens for Webauthn/FIDO2, often called ‘passkeys’ in the user-oriented marketing materials. These passkeys effectively shared across devices where a user is logged in and uses a shared password wallet. The Google Security team &lt;a href=&quot;https://security.googleblog.com/2022/10/SecurityofPasskeysintheGooglePasswordManager.html&quot;&gt;goes at length&lt;/a&gt; explaining why this is secure, although some researchers &lt;a href=&quot;https://medium.com/@arkenoi/what-is-wrong-with-apple-passkeys-1d044072c5a3&quot;&gt;aren’t convinced&lt;/a&gt; (this is more about Apple implementation, though).&lt;/p&gt;
&lt;p&gt;Consuming software tokens stored in a mobile device from a computer for authentication would need additional support from the identity providers. Neither Ipsilon nor Keycloak implement that. For native Android applications &lt;a href=&quot;https://android-developers.googleblog.com/2022/10/bringing-passkeys-to-android-and-chrome.html&quot;&gt;Google just announced&lt;/a&gt; they’ll provide an API in what remains of 2022.&lt;/p&gt;
&lt;p&gt;Finally, going outside of Fedora Project’s infrastructure, supporting Webauthn/FIDO2 to login to Linux servers and desktops in a centrally managed way is still not there.&lt;/p&gt;
&lt;p&gt;Both FreeIPA and SSSD teams are working on a more direct integration with FIDO2 tokens. Instead of relying on an OAuth2 identity provider to handle Webauthn/FIDO2 operations in the browser, SSSD is integrating with libfido2 library to make FIDO2 token’s use on the machine locally. This would replace the pam_u2f module and would allow FreeIPA to provide centralized management of the FIDO2-based passkeys. On top of that, FreeIPA will provide Kerberos integration: login with the FIDO2 token would be turned into a Kerberos ticket and single sign-on operations would be ensured across multiple services, like it is done today for traditional Kerberos pre-authentication methods. A benefit is that passwords can be completely removed for the users with direct FIDO2 token enrollment.&lt;/p&gt;
&lt;p&gt;FreeIPA-enrolled clients (Fedora 36+, RHEL 8.7/9.1 betas) already can login via external IdP as outlined above but only for the SSH or a direct console login. Login over graphical desktop is not working well: a message telling to visit an IdP page and authorize the device access does not fit into a gdm login entry which is used to show the message coming from the PAM stack. GDM is also not able to go to that URL directly as there is still no support for opening a browser instance pre-login in GNOME or any other desktop manager. We are looking at implementing this with GNOME developers similar to how a smartcard selection was added in 2017. Hopefully, this will come to one of the next Fedora versions …&lt;/p&gt;
&lt;p&gt;Notwithstanding open issues, we are pretty much close to enabling FreeIPA-enrolled Linux systems to go passwordless. It is not yet a year of passwordless Linux like not a year of Linux on the desktop but making it reality is not that far away. Perhaps I am too optimistic, though – like we were all before with Linux on the desktop.&lt;/p&gt;</description>
      <pubDate>Fri, 28 Oct 2022 09:50:00 +0300</pubDate>
      <link>https://vda.li/en/posts/2022/10/28/FreeIPA-Authentication-Improvements-and-Fedora-Infra-2/</link>
      <guid isPermaLink="true">https://vda.li/en/posts/2022/10/28/FreeIPA-Authentication-Improvements-and-Fedora-Infra-2/</guid>
      <category>freeipa</category>
      <category>fedora</category>
    </item>
  </channel>
</rss>
