Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

pgp: modernize and improve, and add tests #1054

Merged
merged 4 commits into from
May 31, 2022
Merged

pgp: modernize and improve, and add tests #1054

merged 4 commits into from
May 31, 2022

Conversation

hiddeco
Copy link
Member

@hiddeco hiddeco commented May 6, 2022

This replaces the current PGP keysource implementation with a modernized
version the Flux project has been using.

It includes utilities to configure the MasterKey via other means than
environment variables, to allow SDK users to have extensive control
over what things are decrypted with. This can for example be combined
with an own keyserver implementation.

To be able to contribute it back upstream while keeping it backwards
compatible with SOPS, a couple of changes have been made compared to
Flux:

  • Instead of removing the enabling of the agent while making use of
    GnuPG, it can now be disabled.
  • Support for OpenPGP has been added back. Note however my comments
    on this in-code, as I am not quite sure to what extend it is used
    at the moment, as it will not work on most setups (GnuPG <2.1 was
    released in 2017.)
  • The absolute paths to the pub and sec keyrings can now be configured
    by SDK users. This would add more reason to keep OpenPGP around, if
    they are able to produce the keyring files themselves via other means
    than GnuPG.
  • When a sec keyring is not detected, the pub keyring is loaded instead. This
    to account for GnuPG >=2.1 merging the sec keyring into pub keyring.
  • Support for fetching keys from servers has been removed. This can be
    added back if we need to keep it around for a little longer.

The Flux version of this has compatibility tests with current SOPS:

@hiddeco
Copy link
Member Author

hiddeco commented May 7, 2022

@ajvb please have a look. As you can see, introduction of configuration of the MasterKey could already be introduced. But I am happy to discuss other options. I made some other notes in-code, it would be great to have your opinion on this.

If I can get a sense of the general direction we wanted to head at, the other implementations could follow quickly. Thanks ✨

@hwine
Copy link

hwine commented May 13, 2022

@hiddeco can you describe what changes this makes for the user after this is merged? e.g.

  • configuration of local pgp/gpg setup to work with SOPS
  • any changes to making a new public key available for SOPS to use

Actually, I'm not really sure I know the answers for the current version 😞 my guesses:

  • if gpg is in path, you're okay
  • can only use public keys in local gpg keystore (which implies they must have a user id)

@hiddeco
Copy link
Member Author

hiddeco commented May 13, 2022

The PGP look-up via a server is no longer possible, so the key is indeed expected to exist in the user their key ring. However, this can be re-added. Our implementation does not require it, so I did not include it while writing it based on SOPS' own.

Besides this, it changes very little for a CLI user:

  • GnuPG binary is detected according to same logic, including the ability to overwrite the absolute path of the binary using SOPS_GPG_EXEC.
  • Instead of failing on the lack of a secring.gpg, it now attempts to open pubring.gpg instead before falling back to shelling out to GnuPG. This is added behavior to cover for users who have their secring.gpg merged into pubring.gpg due to GnuPG >=2.1 changes.

The strength in this PR is mostly in the fact that:

  • It has test coverage of way more test cases, and revised and restructured code.
  • It provides a rich set of utilities to work with SOPS as a SDK, to for example decrypt SOPS encrypted files users provide to you. Using these utilities, you could write your own key service server implementation to serve decryption requests with a set of specific secrets.

You can see an example of the latter here. As we are running decryption operations for multiple tenants in the same process, we can't rely on the decrypt.Decrypt of SOPS itself, which utilizes runtime environment variables which are not shared between tenants.

Implementing this would help us (and potentially quite some others) in not having to write their forked key service implementations to control the decryption process using a local server.

@hwine
Copy link

hwine commented May 16, 2022

Thanks for the clarification! So no change to user experience beyond enforcing the previously announced deprecation.

Copy link
Contributor

@ajvb ajvb left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Left a few comments but this is looking great to me!

pgp/keysource.go Show resolved Hide resolved
pgp/keysource.go Show resolved Hide resolved
pgp/keysource.go Show resolved Hide resolved
pgp/keysource_test.go Outdated Show resolved Hide resolved
This replaces the current PGP keysource implementation with a modernized
version the Flux project has been using[1].

It includes utilites to configure the MasterKey via other means than
environment variables, to allow SDK users to have extensive control
over what things are decrypted with. This can for example be combined
with an own keyserver implementation.

To be able to contribute it back upstream while keeping it backwards
compatible with SOPS, a couple of changes have been made compared to
Flux:
- Instead of removing the enabling of the agent while making use of
  GnuPG, it can now be disabled.
- Support for OpenPGP has been added back. Note however my comments
  on this in-code, as I am not quite sure to what extend it is used
  at the moment, as it will not work on most setups (GnuPG <2.1 was
  released in 2017.)
- The absolute paths to the pub and sec keyrings can now be configured
  by SDK users. This would add more reason to keep OpenPGP around, if
  they are able to produce the keyring files themselves via other means
  than GnuPG.
- When a sec keyring is not detected, a lookup for the pub keyring is
  made and loaded instead if found. This to account for GnuPG >=2.1
  merging the sec keyring into pub keyring.
- Support for fetching keys from servers has been removed. This can be
  added back if we need to keep it around for a little longer.

This has extensive test coverage for GnuPG, but would need coverage for
the re-added OpenPGP implementation before it can be deemed ready.

[1]: https://github.com/fluxcd/kustomize-controller/tree/ffdda3f3da75aa39a5b5c29997c2654b6a2f1f89/internal/sops/pgp

Signed-off-by: Hidde Beydals <hello@hidde.co>
Signed-off-by: Hidde Beydals <hello@hidde.co>
Signed-off-by: Hidde Beydals <hello@hidde.co>
@hiddeco hiddeco marked this pull request as ready for review May 26, 2022 09:02
// SopsGpgExecEnv to the absolute path of the replacement binary.
func gpgBinary() string {
binary := "gpg"
if envBinary := os.Getenv(SopsGpgExecEnv); envBinary != "" && filepath.IsAbs(envBinary) {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ajvb did a last comparison round, and we introduced this stricter behavior on the environment variable to ensure nothing magical is injected. Any concerns this may break things for people?

@hiddeco
Copy link
Member Author

hiddeco commented May 26, 2022

This has now tests added for OpenPGP as well, plus some coverage around the fallback behavior, etc. If there are no other concerns, it should be OK to merge.

@hiddeco hiddeco requested a review from ajvb May 27, 2022 21:45
Signed-off-by: Hidde Beydals <hello@hidde.co>
Copy link
Contributor

@ajvb ajvb left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Exciting! Merging in here shortly. I'll do some additional functional testing prior to our next release.

@ajvb ajvb merged commit 0014114 into getsops:develop May 31, 2022
@hiddeco hiddeco deleted the pgp-keysource-imprv branch June 1, 2022 06:29
@hiddeco hiddeco added this to the v3.8.0 milestone Jul 4, 2023
@james-callahan
Copy link

@hiddeco looks like this added --no-default-keyring and --homedir which unfortunately broke usage with qubes split gpg (https://www.qubes-os.org/doc/split-gpg/ / https://github.com/QubesOS/qubes-app-linux-split-gpg)

Will try and followup with them; but I think you'll have a few people coming in with various confusing error messages.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants