How to encrypt with GPG in CI
There is a rather unpleasant problem: if you ever tried to encrypt message (or file) with gpg in a CI/CD pipeline, you get a rather annoying error:
gpg: 123456789ABCDEF: There is no assurance this key belongs to the named usergpg: cannot open '/dev/tty': No such device or address
In CI/CD environment there is a rather low chance to understand what’s going on.
If you have /dev/tty
(which you don’t have in CI/CD), you can read the rest of the message, which explain the problem a bit more:
sub rsa4096/123456789ABCDEF 2022-22-22 Some One <some@example.com>
Primary key fingerprint: 0102 0304 0506 0708 090A 0B0C
Subkey fingerprint: 0D0E 0F10 1112 1314 1516 1718It is NOT certain that the key belongs to the person named
in the user ID. If you *really* know what you are doing,
you may answer the next question with yes.Use this key anyway? (y/N)
Yes, GPG is paranoid about keys and do not want to encrypt with random key. The proper way to solve this problem on desktop is to mark key as trusted via pgp trust database.
The problem is that CI/CD is not a desktop and pipeline finishes as soon as job done, so there is no special ‘trust’ there.
Stackoverflow is full of rather non-satisfying answers proposing different way of adding keys into trusted database, etc.
I found a better way. We can control trust model of gpg. The one we want is either ‘tofu’ or ‘always’:
echo test | gpg --encrypt --armor --yes --encrypt-to -r 123456789ABCDEF --trust-model always-----BEGIN PGP MESSAGE-----
...
Success.
You may wonder where I got a public key to encrypt to into CI/CD. The most simple way is to import it, or use existing (known to CI via secrets) key.
For GH Actions I used this: crazy-max/ghaction-import-gpg@v4