Virtualization is the conceptual technology on which modern services (server applications) are built. Whether an application happens to run on a fully- or para-virtualized VM2 or is containerized—or even runs on a “bare-metal” physical server after all—most modern services are designed in isolated, replicated, disposable components on commodity hardware.3 The “twelve-factor methodology” (2011) is an influential articulation of the principles that tend to be adopted, more or less explicitly, by applications designed and deployed in this way. “Cloud-native” is a more-recent articulation and expansion of many of the same principles.
Virtualization is also the conceptual as well as literal technology on which Qubes OS’s security-by-compartmentalization desktop (client-side) environment is built. However, because most Qubes users run “normal” Linux applications (Firefox, Thunderbird, Vocal, Hypatia, etc.) most of the time, there seems to be only niche interest in considering Qubes a unique environment for designing desktop applications, not just for running them.
If virtualization has been so influential in the evolution of server-side architecture, we should wonder how it might also influence the evolution of client-side architecture—at least for specialized applications, such as the SecureDrop Workstation, that require its security properties in the first place.
Working definitions and hypotheses
A “cloud-native” (server) application consists of isolated, replicated, disposable components that talk to one another in predefined ways, especially with regard to the flow of data and the persistence of state.
A “Qubes-native” (desktop) application consists of isolated,
disposable components that talk to one another in predefined ways,
especially with regard to the flow of data and the persistence of state.
The factors are implementation patterns that follow logically from these properties of isolation, disposability, and predefinition. Where these properties apply in common to “cloud-native” and “Qubes-native” applications, both classes of applications can follow these patterns and share tools4 to help implement them—even if they have different motivations for these properties.
In the modern era, software is commonly delivered as a service: called web apps, or software-as-a-service. The twelve-factor app is a methodology for building software-as-a-service apps that:
- Use declarative formats for setup automation, to minimize time and cost for new developers joining the project;
- Have a clean contract with the underlying operating system, offering maximum portability between execution environments;
- Are suitable for deployment on modern cloud platforms, obviating the need for servers and systems administration;
- Minimize divergence between development and production, enabling continuous deployment for maximum agility;
- And can scale up without significant changes to tooling, architecture, or development practices.
The twelve-factor methodology can be applied to apps written in any programming language, and which use any combination of backing services (database, queue, memory cache, etc).
|1. Codebase||There should be exactly one codebase for a deployed service with the codebase being used for many deployments.|
|2. Dependencies||All dependencies should be declared, with no implicit reliance on system tools or libraries.|
|3. Configuration||Configuration that varies between deployments should be stored in the environment.|
|4. Backing services||All backing services are treated as attached resources and attached and detached by the execution environment.|
|5. Build, release, run||The delivery pipeline should strictly consist of build, release, run.|
|6. Processes||Applications should be deployed as one or more stateless processes with persisted data stored on a backing service.|
|7. Port binding||Self-contained services should make themselves available to other services by specified ports.|
|8. Concurrency||Concurrency is advocated by scaling individual processes.|
|9. Disposability||Fast startup and shutdown are advocated for a more robust and resilient system.|
|10. Development/ production parity||All environments should be as similar as possible.|
|11. Logs||Applications should produce logs as event streams and leave the execution environment to aggregate.|
|12. Admin processes||Any needed admin tasks should be kept in source control and packaged with the application.|
Some subsequent articulations extend this model with additional factors, for example:7
|13. API||“Define the service contract first”8; even first-party applications consume the same API as everyone else.|
|14. Telemetry||Monitor holistic service “health” over time, not just errors and exceptions.|
|15. Authentication and authorization||Authentication and access controls appropriate to every layer of the stack.|
Which factors are and are not relevant in a Qubes OS desktop environment?
|✓||The factor is relevant in Qubes OS, and the SecureDrop Workstation currently makes use of it.|
|¾||The factor is relevant in Qubes OS. The SecureDrop Workstation currently makes explicit use of it, with limitations or edge cases for future work.|
|½||The factor is relevant in Qubes OS. The SecureDrop Workstation currently makes partial or implicit use of it and could expand it.|
|¼||The factor is potentially relevant in Qubes OS, with caveats.|
|✗||The factor is not relevant in Qubes OS.|
Taking the current (→ idealized) SecureDrop Workstation as an example:
|2. Dependencies||¾—The provisioned
|3. Configuration||½—Variable configuration is injected into the
→ securedrop-workstation#853 will be unblocked by QubesOS/qubes-issues#8138.
|4. Backing services||½—See (6) “Processes” for state-oriented and (7) “Port Binding” for action-oriented backing services.|
|5. Build, release, run||✗—Not applicable. A 12-factor release involves pushing the output of a continuous-integration workflow into a continuous-deployment workflow. A Qubes-based application, like any native desktop application, will always be released by publishing an artifact for existing deployments to pull and install locally.|
|6. Processes||½—The SecureDrop Client application in the
→ These state-oriented functions could be abstracted out into other backing services to separate their concerns (and shrink their attack surfaces) further.
|7. Port binding||½—The SecureDrop Client application in the “air-gapped” (networkless)
→ We’ve considered different approaches for generalizing these action-oriented functions to make them more robust and extensible.
|8. Concurrency||¼—Potentially applicable, although concurrency on Qubes OS serves further isolation9 as much as increased performance.|
|9. Disposability||½—Disposable VMs are used to isolate “view” and “export” operations.
→ With backing stores and runtime configuration factored out, the service VMs running the SecureDrop Client and
If fully stateless and disposable, we could change our conceptual model for provisioning the Workstation from enforcing idempotent state (e.g.,
|10. Development/ production parity||✓—Pretty much!—parameterized on which Yum and Apt repositories host and guest packages are fetched from, respectively.|
|12. Admin processes||½—Via
→ Further administration depends on further work on (3) “Configuration” and (4) “Backing Services”.
|13. API||✓—The SecureDrop Server’s Journalist API is the foundation of the SecureDrop Client.|
|14. Telemetry||¼—Potentially desirable for individual VMs but not for
|15. Authentication and authorization||✓—Yes, on a comprehensive and rigorous threat-model.|
The premise of the SecureDrop Workstation project is that Qubes OS is a platform for building secure multi-VM applications. The foundation of that platform—virtualization—is originally and fundamentally server technology.
Therefore, a secure multi-VM application such as the SecureDrop Workstation isn’t straightforwardly a “desktop” or “client” application. It’s a collection of “server” services—that just so happens to have a native GUI frontend served via the Qubes GUI subsystem, rather than a Web frontend served to a Web browser.
For future work
In addition to the limitations discussed above:
Is there a Qubes-specific factor we can define, such as inter-VM policy or permissions, either (a) beyond the standard configuration factor and the supplemental authentication/authorization factor or (b) by composing multiple factors? How might this factor be related to other trends in server and network architecture, such as network ACLs and service-specific policies in cloud environments?11
- Alternatively, this might call for a generalization of the "split" service architecture exemplified by split GPG.
- Randy Bias, "The History of Pets vs Cattle and How to Use the Analogy Properly
- Freedom of the Press Foundation, "Alerting sent to admins / opt-in to SecureDrop team"
- Freedom of the Press Foundation, "Automatically send a subset of system alerts to FPF"
- Freedom of the Press Foundation, "Design of the Next-Generation SecureDrop Workstation"
- Freedom of the Press Foundation, "Configure SecureDrop-proxy via QubesDB"
- Freedom of the Press Foundation, "Journalist Interface API"
- Freedom of the Press Foundation, "Managing Clipboard Access"
- Freedom of the Press Foundation, SecureDrop Client
- Freedom of the Press Foundation, securedrop-proxy
- Freedom of the Press Foundation, "SecureDrop Workstation Architecture"
- Freedom of the Press Foundation, "Setting Up the SecureDrop Workstation"
- Freedom of the Press Foundation, "Welcome to SecureDrop's Documentation!"
- Invisible Things Lab, "Implement a way for a qube to access (some) of its features"
- Tom Grey, "5 Principles for Cloud-Native Architecture: What It is and How to Master It"
- Grace Jansen, "Beyond the 12 Factors: 15-Factor Cloud-Native Java Applications"
- Micah Lee, "Allow bulk conversion to safe PDFs"
- Domenico Luciani, "The Fifteen-Factor App"
- Qubes OS, "Architecture"
- Qubes OS, "Qrexec: Secure Communication across Domains"
- Qubes OS, "Split GPG"
- Joanna Rutkowska, "How Is Qubes OS Different from..."
- Adam Wiggins, "The Twelve-Factor App"
- Wikipedia, "Twelve-Factor App Methodology"
- Xen, "Understanding the Virtualization Spectrum"
- Michael Z., "Building Secure Appliations with Qubes OS"
16‒17 May 2023:
- Update and streamline for publication as a working paper.
- Incorporate FPF contributions.
- Convert to Markdown.
3 November 2022:
- Address FPF feedback.
26 October 2022:
- Add a footnote re: Salt.
19 October 2022:
- Clarify terminology.
13 October 2022: Second draft.
- Address “extra” factors beyond the original 12-factor model.
- Expand working definitions and hypotheses, and address the distinction between implementation patterns and motivations.
6 October 2022: First draft.
This working paper was inspired by Michael Z.’s talk on “Building Secure Applications with Qubes OS” at the 2022 Qubes OS Summit; and has been further informed by ongoing discussions within the SecureDrop and Dangerzone teams at the Freedom of the Press Foundation, where I work, and with the Qubes OS team at Invisible Things Lab. However, except where noted otherwise, the opinions and speculations expressed here are my own—as are all assumptions, limitations, and errors. ↩
Qubes's use of Salt already proves this point: Salt is first and foremost a configuration-management tool for servers. ↩
This point comes from Ro S., who observes: “If you're thinking of making a [Q]ubes-native app, one of the first things you will have to think about is which domain will be responsible for what layer, and how you will enforce that with policy.” ↩