TrunionOverhaul

From MozillaWiki
Jump to: navigation, search

Abstract

Wherein I propose a significant restructuring of the key management and signing logic within the trunion signing service to improve maintainability and therefore, hopefully, bus factor.

Background

The core of the receipt, FirefoxOS privileged apps, and addons signing functionality is a web service project named trunion. It was originally a simple service written by Mike Hanson in the labs to manage signing FirefoxOS receipts for in-app payments. Due to unexpected time constraints in the original project schedule, this code was shoehorned into something that could run in a production environment in a very short time frame. After the usual bumps in the deployment road the service was running in AMO dev, stage, and prod. Since in-app payment receipts use the (at the time) immature JWT and JWK specifications, there are some distinct inconsistencies and possibly even incompatibilities with this code and the final JW* specifications.

Roughly a year later, there developed a need for a service to sign Firefox OS privileged apps. Since a service along those lines already existed, some middlin' modifications were made to trunion's source to support the XPI signing that this method required. In order to minimize the modifications, some slightly unsavoury techniques were used that resulted in working(and apparently solid in production) code that is less easily maintained than it should be.

18 months after that, a request for signing addons on AMO was requested. Since this uses the same method of signing(XPI igning) that the FirefoxOS privileged apps use, the changes needed were almost exclusively in ephemeral key management. For more information see the addon signing docs. This also used perhaps ungainly techniques to minimize the amount of code changed.

There is also a fourth signing method for APK app signing that isn't currently done in trunion but should probably be included in any restructuring or rewrite. This fourth method is not taken into consideration for the remainder of this document deliberately. NEEDS URL.

Problem

Code

Due to the significant differences in the methods of signing as well as key and certificate management(format, storage, and generation) used by all three signing methods overloading the existing methods in a single class has become unwieldy. Until the addon signing additions all signing operations occurred in one Python module. With the addon changes one additional file was added to separate ephemeral key management. This overloading and inline extension of the single class's methods has led to some fairly ugly spaghetti code.

There is also a separate repository for the client code that is needed by the Marketplace workers to verify a receipt signature chain. This was moved so that the zamboni project wouldn't have to include a Pyramid app and cause dependency tree issues.

Operational

Secondly, the service itself is a Pyramid app. When I was first given the task of "productionizing" the existing code from Labs I was unaware that the Marketplace/AMO group was a Django shop. As a result this particular service is a bit of an ugly duckling in its stack. Considering the sensitivity of the information at hand, that is probably a Bad Idea.

The configuration file is also a complete disaster. I can not apologize sufficiently for its nastiness.

Proposal

My proposal is pretty straightforward:

  1. gut trunion of everything except crypt.py and ephemeral.py
  2. pull the signing-clients logic back into the trunion package
  3. write a Django service using the existing trunion web service logic as a template. This is only necessary for the receipt signing input validation

Code restructuring

Trunion's crypto.py is currently a single class, a singleton of that class, and some module level functions to operate using that singleton. This is insufficient to its task at this point.

In order to make the code more manageable I propose separating the functions of the existing Keystore class:

  • A new Credentials base class(or just an interface) that is only responsible for the loading and/or generation of keys and certificates
    • A flat group of Credentials subclasses that each implement a particular format or access technique
      • For receipt signing, a subclass that will load JW* keys and certificates
      • For FirefoxOS privileged app signing, a subclass that will load standard PEM formatted keys and certificates
      • For addon signing, a subclass that will generate a new ephemeral key and certificate request on demand and get that request certified by a purpose specific certificate authority
  • A new SigningStyle base class(or interface) that performs a particular type of signing using a given Credentials object
    • A flat group of SigningStyle subclasses that each implement a method of signing
      • For receipt signing, our particular brand of JW* signatures
      • For FirefoxOS privileged apps and addons, XPI signing

Additional work

No particular order:

  • signing-clients needs to be brought up to date in a big way
  • a class hierarchy that manages accessing different types of HSMs may be necessary. i.e. none(for testing), chil(for stage/prod), and maybe SoftHSM(for dev).
  • a revisit of receipt signing in general
  • possibly replacing our tilde separated receipt format (for key separation) with a more standard way of attaching a key to a JSON Web Token. The Persona/FxA work may have some leads on how to do this.

Bugs

Tracking bug: 1118050

No results.

0 Total; 0 Open (0%); 0 Resolved (0%); 0 Verified (0%);