Plugin Signing in Marketplace
TL;DR: We have implemented a plugin-signing mechanism and are going to introduce it step by step. No actions are required, though we would appreciate it if you would review our solution.
Why do we need plugin signing?
It’s all about trust, and this mechanism will address several concerns.
- Plugin vendors want to make sure that their plugin file doesn’t change over the course of the delivery pipeline, from the package build to the plugin’s installation in our products.
- We want to have a guarantee that the plugin files in the Marketplace repository are verified and cannot be compromised or modified. Our highest priority is delivering it to end-users untouched.
- Our users trust us and may want to restrict the ability to install plugins from untrusted sources.
- In cloud products, such as TeamCity Cloud, we want to add restrictions on which plugins can be installed on our cloud.
How signing works
We have decided to follow the approach that Google uses in APK Signature Scheme v2. To do this, we had to write our own library, because Google’s tool cannot sign an archive if it’s not an APK file. The general working concept is the same, but there are some differences; for example, we use Protobuf to store all metadata according to the APK v2 format.
How the whole process is going to work
To be sure a file has not been modified, the file will be signed twice – once by the plugin author and once by JetBrains Marketplace.
- The plugin author’s sign-verify process is as follows:
- A user generates a key pair and uploads the public part to JetBrains Hub.
- A build tool signs a plugin file during the assembly process.
- The user uploads the plugin file to JetBrains Marketplace.
- JetBrains Marketplace checks if the public key is present in the JetBrains Hub user profile.
- JetBrains Marketplace verifies the signature.
The JetBrains sign-verify process is as follows:
- JetBrains CA is used as the source of truth here. Its public part will be added to the product Java TrustStore, while the private part will be used only once to generate an intermediate certificate. The private key of JetBrains CA is super-secret; in fact, we’ve already said too much.
- The intermediate certificate issues a certificate that will be used to sign plugins. This way, it will be possible to re-generate this certificate without access to JetBrains CA’s super-secret private key. The private key of the intermediate certificate is issued and kept in the AWS Certificate Manager, and no application has access to it; people’s access is also limited. So now we have an AWS-based Intermediate CA. The public part of the intermediate certificate will be added to the plugin file together with the signing certificate.
- The certificate used to sign plugins is stored securely, too. We used the AWS Key Management Service (KMS) to generate a private key, so it can never be leaked. Then we prepared a certificate request (CSR) using the AWS KMS. Then the CSR was signed by the Intermediate CA. JetBrains Marketplace uses AWS KMS as a signature provider to sign plugin files.
How we are going to introduce it
As a first step, we are going to add the signing of TeamCity plugins to JetBrains Marketplace and sign all existing TeamCity plugins. Then we are going to sign the plugins for other products, and, at the same time, we’ll work with product teams to support signatures on their side. After that, we’ll allow users to sign their plugins product by product, and sometime later bring plugin signature into effect for all plugins.