🔑

独自のtflint pluginをリリースするためのPGP鍵セットアップ

2023/07/09に公開

tflint pluginをセキュアに配布する

terraformのリンタであるtflintはプラグイン機構を持っており、独自のpluginを自作したり第三者が開発したpluginを利用したりできる。
pluginを開発するときは、テンプレートドキュメントが整備されているので、これらを参照することで簡単に自作に取り組むことができる。

pluginを安全に配布・利用してサプライチェーン攻撃を防ぐための仕組みとしてPGP鍵による署名を利用する方法も備わっている。
しかし、PGP鍵を用いて署名する方法はGoReleaserに従うという説明だけで具体的な手順は記載されていない。
GoReleaserのドキュメントでもGoReleaserの設定については説明があるが、PGP鍵のセットアップ手順などはまとまっていなかった。

このあたり自分はわかっておらず手間取った。
また、動くようになってもきちんと理解できているか疑問なので現状を整理しておく。

GitHubリリースで公開する

pluginをビルドして配布する方法として、GitHub ActionsでビルドしてGitHub Releaseでリリースするための仕組みがテンプレートに備わっている。
このあたりはドキュメントにも Creating a GitHub Releaseとしてまとまっている。

このとき PGP鍵のセットアップに注意が必要。
GitHub Releaseにて署名付きで配布する場合、GitHub ActionsでPGP秘密鍵を指定してビルドする必要がある。
デフォルトではPGP鍵がセットアップされていないのでGitHub Actionsの実行に失敗する。

Run crazy-max/ghaction-import-gpg@v5
Error: Input required and not supplied: gpg_private_key

GitHub ActionsのSecretsに GPG_PRIVATE_KEY および PASSPHRASE を設定することで、GitHub Actionsが正常に動作して署名付きのビルド成果物がGitHub Releaseで公開されるようになる。

PGP鍵の取り扱い

PGP鍵の生成

PGP鍵の生成には、テンプレートのGitHub Actionsで利用している ghaction-import-gpg およびGitHubのドキュメントに従う。

自分が開発に利用しているUbuntu 22.04におけるgpgコンマンドのバージョンは 2.2.27 だったので --full-generate-key オプションを指定して作成する。
インタラクションにて以下のように基本的にデフォルト値の通り回答した。
パスフレーズは1passwordで適当に生成して保存した。

$ gpg --version
gpg (GnuPG) 2.2.27
libgcrypt 1.9.4
...

 gpg --full-generate-key
gpg (GnuPG) 2.2.27; Copyright (C) 2021 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Please select what kind of key you want:
   (1) RSA and RSA (default)
   (2) DSA and Elgamal
   (3) DSA (sign only)
   (4) RSA (sign only)
  (14) Existing key from card
Your selection? 1
RSA keys may be between 1024 and 4096 bits long.
What keysize do you want? (3072) 
Requested keysize is 3072 bits
Please specify how long the key should be valid.
         0 = key does not expire
      <n>  = key expires in n days
      <n>w = key expires in n weeks
      <n>m = key expires in n months
      <n>y = key expires in n years
Key is valid for? (0) 
Key does not expire at all
Is this correct? (y/N) y

GnuPG needs to construct a user ID to identify your key.

Real name: thaim
Email address: thaim24@gmail.com
Comment: 
You selected this USER-ID:
    "thaim <thaim24@gmail.com>"

Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? O
We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, utilize the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.
We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, utilize the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.
gpg: key 5FA7F02B1A8F9F4B marked as ultimately trusted
gpg: revocation certificate stored as '/home/thaim/.gnupg/openpgp-revocs.d/C221E52FA6D10FA2463E39735FA7F02B1A8F9F4B.rev'
public and secret key created and signed.

pub   rsa3072 2023-07-08 [SC]
      C221E52FA6D10FA2463E39735FA7F02B1A8F9F4B
uid                      thaim <thaim24@gmail.com>
sub   rsa3072 2023-07-08 [E]

GitHub Actionsへのセットアップ

上記出力から、生成したPGP鍵のIDは 5FA7F02B1A8F9F4B だとわかる。
このとき、このPGP鍵の公開鍵および秘密鍵は以下のコマンドで出力される。
鍵IDの指定はfingerprint (C221E52FA6D10FA2463E39735FA7F02B1A8F9F4B)を指定してもよい。

# 秘密鍵
$ gpg --armor --export-secret-key 5FA7F02B1A8F9F4B
-----BEGIN PGP PRIVATE KEY BLOCK-----

...
-----END PGP PRIVATE KEY BLOCK-----

# 公開鍵
$ gpg --armor --export 5FA7F02B1A8F9F4B
-----BEGIN PGP PUBLIC KEY BLOCK-----

...
-----END PGP PUBLIC KEY BLOCK-----

利用

以上のように署名付きでpluginの配布ができたら、 .tflint.hcl でプラグインの設定を書けばよい。

plugin "formatter" {
  enabled = true
  source  = "github.com/thaim/tflint-ruleset-formatter"
  version = "0.2.4"

  signing_key = <<-KEY
-----BEGIN PGP PUBLIC KEY BLOCK-----

...
-----END PGP PUBLIC KEY BLOCK-----
KEY
}

sourceversion を指定してばリモートからpluginを取得してくれる。
sigining_key を指定しなければ警告が、間違った内容であればエラーとなる。

# signing_keyを省略した場合
$ tflint --init
Installing `formatter` plugin...
No signing key configured. Set `signing_key` to verify that the release is signed by the plugin developer
Installed `formatter` (source: github.com/thaim/tflint-ruleset-formatter, version: 0.2.4)

# 誤ったsiging_keyを指定した場合
$ tflint --init
Installing `formatter` plugin...
Failed to install a plugin; Failed to check checksums.txt signature: openpgp: signature made by unknown entity

Discussion