IntelliJ Platform Plugin SDKのドキュメントを読んでいたところ、 Plugin Signing
というページがありました。
Plugin Signing | IntelliJ Platform Plugin SDK
そこで、自作のプラグイン Railroads にPlugin Signingしてみたときのメモを残します。
目次
環境
署名の実施
ドキュメントに従い、署名を実施してみます。
秘密鍵の生成
ドキュメントの Generate Private Key
に従い、秘密鍵を生成します。
https://plugins.jetbrains.com/docs/intellij/plugin-signing.html#generate-private-key
WSL2を開き、以下を実行します。
今回 pem ファイルは railroads_private_encrypted.pem
とします。
また、パスワードも設定しておきます。
# 実行 $ openssl genpkey\ -aes-256-cbc\ -algorithm RSA\ -out railroads_private_encrypted.pem\ -pkeyopt rsa_keygen_bits:4096 # パスワード入力 Enter PEM pass phrase: Verifying - Enter PEM pass phrase:
続いて、生成した鍵をRSA形式に変換します。
# 実行 $ openssl rsa\ -in railroads_private_encrypted.pem\ -out railroads_private.pem # パスワードを求められるので、railroads_private_encrypted.pem を生成したときのパスワードを入力 Enter pass phrase for railroads_private_encrypted.pem: # 結果 writing RSA key
最後に、 crt ファイルを生成します。
# 実行 $ openssl req\ -key railroads_private.pem\ -new\ -x509\ -days 3650\ -out railroads_2024_0406.crt # 注意書きが表示された You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter '.', the field will be left blank. # 適当な値を入力 Country Name (2 letter code) [AU]:JP State or Province Name (full name) [Some-State]:Tokyo Locality Name (eg, city) []: Organization Name (eg, company) [Internet Widgits Pty Ltd]:thinkAmi Organizational Unit Name (eg, section) []: Common Name (e.g. server FQDN or YOUR name) []:https://github.com/thinkAmi Email Address []:
IDEの環境変数に各鍵の値を設定
プラグインへの署名については
のいずれかの方法で行えば良いようです。
今回は
ということで、上記1. の方法で進めることにします。
次に、 signPlugin
タスクで実行するためには、
- build.gradle.ktsファイルにて、秘密鍵などの情報をハードコード
- build.gradle.ktsファイルにて、秘密鍵などのファイルを読み込むよう指定
- IntelliJ IDEAの環境変数に、秘密鍵などをBASE64化した値を設定
のいずれかが必要そうでした。
今回は
ということで、上記3.の方法を取ることにしました。
そこで、IntelliJ IDEAの環境変数に設定できるよう、
- railroads_2024_0406.crt
- railroads_private.pem
の2ファイルの中身をBASE64化することにします。
また、都度BASE64化するのは手間なので、
certificate
ディレクトリを作り、その中にpemやcrtを置く- 誤ってコミットしないよう、
.gitignore
にて、*.pem
と*.crt
を追加する certificate
ディレクトリに何を置くか忘れないよう、pemやcrtのサンプルファイルを追加するcertificate
ディレクトリの中にある pem や crt の中身をBASE64化するRubyスクリプトを作成する
という作業を行います。
ちなみに、Rubyスクリプト (base64encode.rb
) は以下のような感じです。
なお、BASE64化するときに改行を追加しないよう、 Base64#strict_encode64
を使っています。
https://docs.ruby-lang.org/ja/latest/class/Base64.html#M_STRICT_ENCODE64
require 'base64' file_paths = Dir.glob('*') file_paths.each do |file_path| file_name = File.basename(file_path) # Do not output Base64-encoded strings for running Ruby scripts and example files next if file_name == File.basename(__FILE__) next if File.extname(file_name) == '.example' file_data = File.read(file_path) # Do not add newlines when Base64 encoded encoded_data = Base64.strict_encode64(file_data) puts "File Name: #{file_name}" puts "Encoded Data:" puts encoded_data puts "\n\n\n" end
できたRubyスクリプトを実行し、BASE64化した値を確認します。
>ruby base64encode.rb File Name: railroads_2024_0406.crt Encoded Data: *** File Name: railroads_private.pem Encoded Data: *** File Name: railroads_private_encrypted.pem Encoded Data: ***
準備ができたので、公式ドキュメントに従い、IntelliJ IDEAで signPlugin
タスクを追加します。
https://plugins.jetbrains.com/docs/intellij/plugin-signing.html#provide-secrets-to-ide
まず、 Run > Edit configuration
から、 +
で Gradle
を選択します。
続いて、以下の設定を行います。
- Name: (任意の値)
- Run on:
Local machine
(デフォルト) - Run:
singPlugin
- Gradle project:
railroads
(デフォルト) - Environment variables は、以下の3つの値を設定
- なお、公式ドキュメントとは異なり、今回は署名するだけなので
PUBLISH_TOKEN
は設定不要
- なお、公式ドキュメントとは異なり、今回は署名するだけなので
Name | Value |
---|---|
CERTIFICATE_CHAIN | railroads_2024_0406.crt の中身をBase64エンコードしたもの(改行なし) |
PRIVATE_KEY | railroads_private.pem の中身をBase64エンコードしたもの(改行なし) |
PRIVATE_KEY_PASSWORD | OpenSSLで railroads_private_encrypted.pem を作成したときに設定したパスワード |
設定ができたので、 railroads [signPlugin]
を実行します。
すると、以下のログが出力されました。成功したようです。
... > Task :signPlugin BUILD SUCCESSFUL in 59s 17 actionable tasks: 9 executed, 8 up-to-date Configuration cache entry stored. 11:43:58: Execution finished 'signPlugin'.
また、 build/distributions/railroads-0.1.1-signed.zip
というファイルも生成されていました。
署名の検証
では、次にプラグインの署名を検証します。
検証方法としては
- Gradle で
verifyPluginSignature
タスクの実行 - CLIで検証
の2つがありました。
Gradleのタスクで検証するためにドキュメントを読んだところ、環境変数から値を読み込んだり、動的に対象のプラグインファイルを指定するのが難しそうでした。
https://plugins.jetbrains.com/docs/intellij/tools-gradle-intellij-plugin.html#tasks-verifypluginsignature
そこで今回はCLIで検証することにしました。
ドキュメントによると、CLIで検証するには CLI Tool が必要そうでした。
https://plugins.jetbrains.com/docs/intellij/plugin-signing.html#cli-tool
そこで、ドキュメントに従い、 marketplace-zip-signer-cli.jar
をダウンロードしました。
続いて、署名をしたプラグインに対してツールを実行してみましたが、何も出力されませんでした。
> C:\Users\<UserName>\.jdks\jbr-17.0.9\bin\java.exe -jar marketplace-zip-signer-cli.jar verify -in "build\distributions\railroads-0.1.1-signed.zip" -cert "certificate\railroads_2024_0406.crt"
次に、署名がないプラグインに対してツールを実行したところ、メッセージ Provided zip archive is not signed
が表示されました。
> C:\Users\<UserName>\.jdks\jbr-17.0.9\bin\java.exe -jar marketplace-zip-signer-cli.jar verify -in "build\distributions\railroads-0.1.1.zip" -cert "certificate\railroads_2024_0406.crt" Provided zip archive is not signed
念のためソースコードを見たところ、成功したときは何も出力されないのが正解のようでした。
https://github.com/JetBrains/marketplace-zip-signer/blob/1b365366563540d8b70f46578cc10c3bcd541b13/cli/src/main/kotlin/org/jetbrains/zip/signer/ZipSigningTool.kt#L90
その他資料:Busy Plugin Developers
JetBrainsがYoutubeで公開している Busy Plugin Developers #1
の21分あたりから、Pluginについてふれられていました。
Plugin Signing at JetBrains Marketplace. IntelliJ Plugins UI Testing - YouTube
ソースコード
Githubに追加しています。
https://github.com/thinkAmi/railroads
今回のプルリクはこちら。
https://github.com/thinkAmi/railroads/pull/8