1
0
mirror of https://github.com/getsops/sops.git synced 2026-02-05 12:45:21 +01:00
Files
sops/pgp/keysource.go

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

685 lines
21 KiB
Go
Raw Normal View History

2017-09-12 20:01:12 -07:00
/*
Package pgp contains an implementation of the github.com/getsops/sops/v3.MasterKey
interface that encrypts and decrypts the data key by first trying with the
github.com/ProtonMail/go-crypto/openpgp package and if that fails, by calling
the "gpg" binary.
2017-09-16 17:52:14 -07:00
*/
package pgp // import "github.com/getsops/sops/v3/pgp"
import (
"bytes"
"context"
"encoding/hex"
"errors"
"fmt"
pgp: modernize and improve, and add tests 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>
2022-05-07 01:23:24 +02:00
"io"
"os"
"os/exec"
"os/user"
pgp: modernize and improve, and add tests 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>
2022-05-07 01:23:24 +02:00
"path/filepath"
"strings"
"time"
"github.com/ProtonMail/go-crypto/openpgp"
"github.com/ProtonMail/go-crypto/openpgp/armor"
gpgagent "github.com/getsops/gopgagent"
2017-09-06 17:36:39 -07:00
"github.com/sirupsen/logrus"
"golang.org/x/term"
"github.com/getsops/sops/v3/logging"
)
pgp: modernize and improve, and add tests 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>
2022-05-07 01:23:24 +02:00
const (
// KeyTypeIdentifier is the string used to identify a PGP MasterKey.
KeyTypeIdentifier = "pgp"
pgp: modernize and improve, and add tests 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>
2022-05-07 01:23:24 +02:00
// SopsGpgExecEnv can be set as an environment variable to overwrite the
// GnuPG binary used.
SopsGpgExecEnv = "SOPS_GPG_EXEC"
)
var (
// pgpTTL is the duration after which a MasterKey requires rotation.
pgpTTL = time.Hour * 24 * 30 * 6
// defaultPubRing is the relative path to the pubring in the GnuPG
// home.
// NB: This format is no longer in use since GnuPG >=2.1, which switched
// to .kbx for new installations, and merged secring.gpg into pubring.gpg.
defaultPubRing = "pubring.gpg"
// defaultSecRing is the relative path to the secring in the GnuPG
// home.
// NB: GnuPG >= 2.1 merged this together with pubring.gpg, see
// defaultPubRing.
defaultSecRing = "secring.gpg"
)
// log is the global logger for any PGP MasterKey.
// TODO(hidde): this is not-so-nice for any implementation other than the CLI,
// as it becomes difficult to sugar the logger with data for e.g. individual
// processes.
2017-09-06 17:36:39 -07:00
var log *logrus.Logger
func init() {
2017-09-07 10:49:27 -07:00
log = logging.NewLogger("PGP")
2017-09-06 17:36:39 -07:00
}
pgp: modernize and improve, and add tests 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>
2022-05-07 01:23:24 +02:00
// MasterKey is a PGP key used to securely store SOPS' data key by
// encrypting it and decrypting it.
type MasterKey struct {
pgp: modernize and improve, and add tests 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>
2022-05-07 01:23:24 +02:00
// Fingerprint contains the fingerprint of the PGP key used to Encrypt
// or Decrypt the data key with.
Fingerprint string
// EncryptedKey contains the SOPS data key encrypted with PGP.
EncryptedKey string
pgp: modernize and improve, and add tests 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>
2022-05-07 01:23:24 +02:00
// CreationDate of the MasterKey, used to determine if the EncryptedKey
// needs rotation.
CreationDate time.Time
pgp: modernize and improve, and add tests 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>
2022-05-07 01:23:24 +02:00
// gnuPGHomeDir contains the absolute path to a GnuPG home directory.
// It can be injected by a (local) keyservice.KeyServiceServer using
// GnuPGHome.ApplyToMasterKey().
gnuPGHomeDir string
// disableOpenPGP instructs the MasterKey to skip attempting to open any
// pubRing or secRing using OpenPGP.
disableOpenPGP bool
pgp: modernize and improve, and add tests 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>
2022-05-07 01:23:24 +02:00
// pubRing contains the absolute path to a public keyring used by OpenPGP.
// When empty, defaultPubRing relative to GnuPG home is assumed.
pubRing string
// secRing contains the absolute path to a sec keyring used by OpenPGP.
// When empty, defaultSecRing relative to GnuPG home is assumed.
secRing string
}
pgp: modernize and improve, and add tests 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>
2022-05-07 01:23:24 +02:00
// NewMasterKeyFromFingerprint takes a PGP fingerprint and returns a new
// MasterKey with that fingerprint.
func NewMasterKeyFromFingerprint(fingerprint string) *MasterKey {
return &MasterKey{
Fingerprint: strings.Replace(fingerprint, " ", "", -1),
CreationDate: time.Now().UTC(),
}
}
pgp: modernize and improve, and add tests 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>
2022-05-07 01:23:24 +02:00
// MasterKeysFromFingerprintString takes a comma separated list of PGP
// fingerprints and returns a slice of new MasterKeys with those fingerprints.
func MasterKeysFromFingerprintString(fingerprint string) []*MasterKey {
var keys []*MasterKey
if fingerprint == "" {
return keys
2017-08-23 14:27:11 -07:00
}
pgp: modernize and improve, and add tests 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>
2022-05-07 01:23:24 +02:00
for _, s := range strings.Split(fingerprint, ",") {
keys = append(keys, NewMasterKeyFromFingerprint(s))
}
return keys
2017-08-23 14:27:11 -07:00
}
pgp: modernize and improve, and add tests 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>
2022-05-07 01:23:24 +02:00
// GnuPGHome is the absolute path to a GnuPG home directory.
// A new keyring can be constructed by combining the use of NewGnuPGHome() and
// Import() or ImportFile().
type GnuPGHome string
// NewGnuPGHome initializes a new GnuPGHome in a temporary directory.
// The caller is expected to handle the garbage collection of the created
// directory.
func NewGnuPGHome() (GnuPGHome, error) {
tmpDir, err := os.MkdirTemp("", "sops-gnupghome-")
if err != nil {
return "", fmt.Errorf("failed to create new GnuPG home: %w", err)
}
pgp: modernize and improve, and add tests 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>
2022-05-07 01:23:24 +02:00
return GnuPGHome(tmpDir), nil
}
// Import attempts to import the armored key bytes into the GnuPGHome keyring.
// It returns an error if the GnuPGHome does not pass Validate, or if the
// import failed.
//
// Consider using ImportContext instead.
pgp: modernize and improve, and add tests 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>
2022-05-07 01:23:24 +02:00
func (d GnuPGHome) Import(armoredKey []byte) error {
return d.ImportContext(context.Background(), armoredKey)
}
// ImportContext attempts to import the armored key bytes into the GnuPGHome keyring.
// It returns an error if the GnuPGHome does not pass Validate, or if the
// import failed.
func (d GnuPGHome) ImportContext(ctx context.Context, armoredKey []byte) error {
pgp: modernize and improve, and add tests 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>
2022-05-07 01:23:24 +02:00
if err := d.Validate(); err != nil {
return fmt.Errorf("cannot import armored key data into GnuPG keyring: %w", err)
2017-08-23 14:27:11 -07:00
}
pgp: modernize and improve, and add tests 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>
2022-05-07 01:23:24 +02:00
args := []string{"--batch", "--import"}
_, stderr, err := gpgExec(ctx, d.String(), args, bytes.NewReader(armoredKey))
2017-08-23 14:27:11 -07:00
if err != nil {
stderrStr := strings.TrimSpace(stderr.String())
errStr := err.Error()
var sb strings.Builder
sb.WriteString("failed to import armored key data into GnuPG keyring")
if len(stderrStr) > 0 {
if len(errStr) > 0 {
fmt.Fprintf(&sb, " (%s)", errStr)
}
fmt.Fprintf(&sb, ": %s", stderrStr)
} else if len(errStr) > 0 {
fmt.Fprintf(&sb, ": %s", errStr)
}
return errors.New(sb.String())
2017-08-23 14:27:11 -07:00
}
return nil
}
pgp: modernize and improve, and add tests 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>
2022-05-07 01:23:24 +02:00
// ImportFile attempts to import the armored key file into the GnuPGHome
// keyring.
// It returns an error if the GnuPGHome does not pass Validate, or if the
// import failed.
func (d GnuPGHome) ImportFile(path string) error {
b, err := os.ReadFile(path)
if err != nil {
pgp: modernize and improve, and add tests 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>
2022-05-07 01:23:24 +02:00
return fmt.Errorf("cannot read armored key data from file: %w", err)
}
return d.Import(b)
}
// Cleanup deletes the GnuPGHome if it passes Validate.
// It returns an error if the GnuPGHome does not pass Validate, or if the
// removal failed.
func (d GnuPGHome) Cleanup() error {
if err := d.Validate(); err != nil {
return err
}
return os.RemoveAll(d.String())
}
pgp: modernize and improve, and add tests 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>
2022-05-07 01:23:24 +02:00
// Validate ensures the GnuPGHome is a valid GnuPG home directory path.
// When validation fails, it returns a descriptive reason as error.
func (d GnuPGHome) Validate() error {
if d == "" {
return fmt.Errorf("empty GNUPGHOME path")
}
pgp: modernize and improve, and add tests 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>
2022-05-07 01:23:24 +02:00
if !filepath.IsAbs(d.String()) {
return fmt.Errorf("GNUPGHOME must be an absolute path")
}
pgp: modernize and improve, and add tests 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>
2022-05-07 01:23:24 +02:00
fi, err := os.Lstat(d.String())
if err != nil {
pgp: modernize and improve, and add tests 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>
2022-05-07 01:23:24 +02:00
if os.IsNotExist(err) {
return fmt.Errorf("GNUPGHOME does not exist")
}
return fmt.Errorf("cannot stat GNUPGHOME: %w", err)
}
if !fi.IsDir() {
return fmt.Errorf("GNUGPHOME is not a directory")
}
pgp: modernize and improve, and add tests 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>
2022-05-07 01:23:24 +02:00
if perm := fi.Mode().Perm(); perm != 0o700 {
return fmt.Errorf("GNUPGHOME has invalid permissions: got %#o wanted %#o", perm, 0o700)
}
return nil
}
pgp: modernize and improve, and add tests 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>
2022-05-07 01:23:24 +02:00
// String returns the GnuPGHome as a string. It does not Validate.
func (d GnuPGHome) String() string {
return string(d)
}
// ApplyToMasterKey configures the GnuPGHome on the provided key if it passes
// Validate.
func (d GnuPGHome) ApplyToMasterKey(key *MasterKey) {
if err := d.Validate(); err == nil {
key.gnuPGHomeDir = d.String()
}
pgp: modernize and improve, and add tests 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>
2022-05-07 01:23:24 +02:00
}
// DisableOpenPGP disables encrypt and decrypt operations using OpenPGP.
type DisableOpenPGP struct{}
// ApplyToMasterKey configures the provided key to not use OpenPGP.
func (d DisableOpenPGP) ApplyToMasterKey(key *MasterKey) {
key.disableOpenPGP = true
}
pgp: modernize and improve, and add tests 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>
2022-05-07 01:23:24 +02:00
// PubRing can be used to configure the absolute path to a public keyring
// used by OpenPGP.
type PubRing string
// ApplyToMasterKey configures the provided key to not use the GnuPG agent.
func (r PubRing) ApplyToMasterKey(key *MasterKey) {
key.pubRing = string(r)
}
// SecRing can be used to configure the absolute path to a sec keyring
// used by OpenPGP.
type SecRing string
// ApplyToMasterKey configures the provided key to not use the GnuPG agent.
func (r SecRing) ApplyToMasterKey(key *MasterKey) {
key.secRing = string(r)
}
// errSet is a collection of captured errors.
type errSet []error
// Error joins the errors into a "; " separated string.
func (e errSet) Error() string {
str := make([]string, len(e))
for i, err := range e {
str[i] = err.Error()
}
return strings.Join(str, "; ")
}
pgp: modernize and improve, and add tests 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>
2022-05-07 01:23:24 +02:00
// Encrypt encrypts the data key with the PGP key with the same
// fingerprint as the MasterKey.
//
// Consider using EncryptContext instead.
pgp: modernize and improve, and add tests 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>
2022-05-07 01:23:24 +02:00
func (key *MasterKey) Encrypt(dataKey []byte) error {
return key.EncryptContext(context.Background(), dataKey)
}
// EncryptContext encrypts the data key with the PGP key with the same
// fingerprint as the MasterKey.
func (key *MasterKey) EncryptContext(ctx context.Context, dataKey []byte) error {
var errs errSet
if !key.disableOpenPGP {
openpgpErr := key.encryptWithOpenPGP(dataKey)
if openpgpErr == nil {
log.WithField("fingerprint", key.Fingerprint).Info("Encryption succeeded")
return nil
}
errs = append(errs, fmt.Errorf("github.com/ProtonMail/go-crypto/openpgp error: %w", openpgpErr))
}
binaryErr := key.encryptWithGnuPG(ctx, dataKey)
pgp: modernize and improve, and add tests 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>
2022-05-07 01:23:24 +02:00
if binaryErr == nil {
log.WithField("fingerprint", key.Fingerprint).Info("Encryption succeeded")
return nil
}
errs = append(errs, fmt.Errorf("GnuPG binary error: %w", binaryErr))
log.WithField("fingerprint", key.Fingerprint).Info("Encryption failed")
return fmt.Errorf("could not encrypt data key with PGP key: %w", errs)
}
pgp: modernize and improve, and add tests 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>
2022-05-07 01:23:24 +02:00
// encryptWithOpenPGP attempts to encrypt the data key using OpenPGP with the
// PGP key that belongs to Fingerprint. It sets EncryptedDataKey, or returns
// an error.
func (key *MasterKey) encryptWithOpenPGP(dataKey []byte) error {
entity, err := key.retrievePubKey()
if err != nil {
return err
}
pgp: modernize and improve, and add tests 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>
2022-05-07 01:23:24 +02:00
encBuf := new(bytes.Buffer)
armorBuf, err := armor.Encode(encBuf, "PGP MESSAGE", nil)
if err != nil {
return err
}
pgp: modernize and improve, and add tests 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>
2022-05-07 01:23:24 +02:00
plainBuf, err := openpgp.Encrypt(armorBuf, []*openpgp.Entity{&entity}, nil, &openpgp.FileHints{IsBinary: true}, nil)
if err != nil {
return err
}
pgp: modernize and improve, and add tests 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>
2022-05-07 01:23:24 +02:00
_, err = plainBuf.Write(dataKey)
if err != nil {
return err
}
pgp: modernize and improve, and add tests 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>
2022-05-07 01:23:24 +02:00
err = plainBuf.Close()
if err != nil {
return err
}
pgp: modernize and improve, and add tests 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>
2022-05-07 01:23:24 +02:00
err = armorBuf.Close()
if err != nil {
return err
}
pgp: modernize and improve, and add tests 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>
2022-05-07 01:23:24 +02:00
b, err := io.ReadAll(encBuf)
if err != nil {
return err
}
pgp: modernize and improve, and add tests 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>
2022-05-07 01:23:24 +02:00
key.SetEncryptedDataKey(b)
return nil
}
pgp: modernize and improve, and add tests 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>
2022-05-07 01:23:24 +02:00
// encryptWithOpenPGP attempts to encrypt the data key using GnuPG with the
// PGP key that belongs to Fingerprint. It sets EncryptedDataKey, or returns
// an error.
func (key *MasterKey) encryptWithGnuPG(ctx context.Context, dataKey []byte) error {
pgp: modernize and improve, and add tests 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>
2022-05-07 01:23:24 +02:00
fingerprint := shortenFingerprint(key.Fingerprint)
args := []string{
"--no-default-recipient",
"--yes",
"--encrypt",
"-a",
"-r",
key.Fingerprint,
"--trusted-key",
fingerprint,
"--no-encrypt-to",
2017-08-23 14:27:11 -07:00
}
stdout, stderr, err := gpgExec(ctx, key.gnuPGHomeDir, args, bytes.NewReader(dataKey))
pgp: modernize and improve, and add tests 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>
2022-05-07 01:23:24 +02:00
if err != nil {
return fmt.Errorf("failed to encrypt sops data key with pgp: %s", strings.TrimSpace(stderr.String()))
2017-08-23 14:27:11 -07:00
}
pgp: modernize and improve, and add tests 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>
2022-05-07 01:23:24 +02:00
key.SetEncryptedDataKey(bytes.TrimSpace(stdout.Bytes()))
return nil
2017-08-23 14:27:11 -07:00
}
pgp: modernize and improve, and add tests 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>
2022-05-07 01:23:24 +02:00
// EncryptIfNeeded encrypts the data key with PGP only if it's needed,
// that is, if it hasn't been encrypted already.
func (key *MasterKey) EncryptIfNeeded(dataKey []byte) error {
if key.EncryptedKey == "" {
return key.Encrypt(dataKey)
}
return nil
}
pgp: modernize and improve, and add tests 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>
2022-05-07 01:23:24 +02:00
// EncryptedDataKey returns the encrypted data key this master key holds.
func (key *MasterKey) EncryptedDataKey() []byte {
return []byte(key.EncryptedKey)
}
// SetEncryptedDataKey sets the encrypted data key for this master key.
func (key *MasterKey) SetEncryptedDataKey(enc []byte) {
key.EncryptedKey = string(enc)
}
// Decrypt first attempts to obtain the data key from the EncryptedKey
// stored in the MasterKey using OpenPGP, before falling back to GnuPG.
// When both attempts fail, an error is returned.
//
// Consider using DecryptContext instead.
pgp: modernize and improve, and add tests 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>
2022-05-07 01:23:24 +02:00
func (key *MasterKey) Decrypt() ([]byte, error) {
return key.DecryptContext(context.Background())
}
// DecryptContext first attempts to obtain the data key from the EncryptedKey
// stored in the MasterKey using OpenPGP, before falling back to GnuPG.
// When both attempts fail, an error is returned.
func (key *MasterKey) DecryptContext(ctx context.Context) ([]byte, error) {
var errs errSet
if !key.disableOpenPGP {
dataKey, openpgpErr := key.decryptWithOpenPGP()
if openpgpErr == nil {
log.WithField("fingerprint", key.Fingerprint).Info("Decryption succeeded")
return dataKey, nil
}
errs = append(errs, fmt.Errorf("github.com/ProtonMail/go-crypto/openpgp error: %w", openpgpErr))
2017-08-23 14:27:11 -07:00
}
dataKey, binaryErr := key.decryptWithGnuPG(ctx)
pgp: modernize and improve, and add tests 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>
2022-05-07 01:23:24 +02:00
if binaryErr == nil {
log.WithField("fingerprint", key.Fingerprint).Info("Decryption succeeded")
return dataKey, nil
2017-08-23 14:27:11 -07:00
}
errs = append(errs, fmt.Errorf("GnuPG binary error: %w", binaryErr))
log.WithField("fingerprint", key.Fingerprint).Info("Decryption failed")
return nil, fmt.Errorf("could not decrypt data key with PGP key: %w", errs)
2017-08-23 14:27:11 -07:00
}
pgp: modernize and improve, and add tests 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>
2022-05-07 01:23:24 +02:00
// decryptWithOpenPGP attempts to obtain the data key from the EncryptedKey
// using OpenPGP and returns the result.
//
// Note: the current development of OpenPGP vs GnuPG has moved in separate
// directions. This means that e.g. GnuPG >=2.1 works with a .kbx format which
// can not be read by OpenPGP. Given the further assumptions around the
// placement of the files, and the generic fallback Decrypt uses, this raises
// the question of how widely utilized this method still is.
func (key *MasterKey) decryptWithOpenPGP() ([]byte, error) {
ring, err := key.getSecRing()
if err != nil {
pgp: modernize and improve, and add tests 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>
2022-05-07 01:23:24 +02:00
return nil, fmt.Errorf("could not load secring: %s", err)
}
block, err := armor.Decode(strings.NewReader(key.EncryptedKey))
if err != nil {
pgp: modernize and improve, and add tests 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>
2022-05-07 01:23:24 +02:00
return nil, fmt.Errorf("armor decoding failed: %s", err)
}
md, err := openpgp.ReadMessage(block.Body, ring, key.passphrasePrompt(), nil)
if err != nil {
pgp: modernize and improve, and add tests 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>
2022-05-07 01:23:24 +02:00
return nil, fmt.Errorf("reading PGP message failed: %s", err)
}
if b, err := io.ReadAll(md.UnverifiedBody); err == nil {
2016-08-23 12:49:18 -07:00
return b, nil
}
pgp: modernize and improve, and add tests 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>
2022-05-07 01:23:24 +02:00
return nil, fmt.Errorf("the key could not be decrypted with any of the PGP entries")
}
pgp: modernize and improve, and add tests 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>
2022-05-07 01:23:24 +02:00
// decryptWithGnuPG attempts to obtain the data key from the EncryptedKey using
// GnuPG and returns the result. If DisableAgent is configured on the MasterKey,
// the GnuPG agent is not enabled. When the decryption command fails, it returns
// the error from stdout.
func (key *MasterKey) decryptWithGnuPG(ctx context.Context) ([]byte, error) {
pgp: modernize and improve, and add tests 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>
2022-05-07 01:23:24 +02:00
args := []string{
"-d",
2017-08-23 14:27:11 -07:00
}
stdout, stderr, err := gpgExec(ctx, key.gnuPGHomeDir, args, strings.NewReader(key.EncryptedKey))
pgp: modernize and improve, and add tests 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>
2022-05-07 01:23:24 +02:00
if err != nil {
return nil, fmt.Errorf("failed to decrypt sops data key with pgp: %s",
strings.TrimSpace(stderr.String()))
pgp: modernize and improve, and add tests 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>
2022-05-07 01:23:24 +02:00
}
result := stdout.Bytes()
if len(result) == 0 {
// This can happen if an older GnuPG version is used to decrypt a key encrypted with a
// newer GnuPG version that used an AEAD cipher, which the old version does not support.
// Apparently some GnuPG versions drop the unspuported packets, which results in a decrypted
// data of 0 bytes, and returns nothing with exit code 0.
//
// (See https://github.com/getsops/sops/issues/896#issuecomment-2688079300 for more infos.)
return nil, fmt.Errorf("failed to decrypt sops data key with pgp: zero bytes returned")
}
return result, nil
2017-08-23 14:27:11 -07:00
}
pgp: modernize and improve, and add tests 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>
2022-05-07 01:23:24 +02:00
// NeedsRotation returns whether the data key needs to be rotated
// or not.
func (key *MasterKey) NeedsRotation() bool {
pgp: modernize and improve, and add tests 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>
2022-05-07 01:23:24 +02:00
return time.Since(key.CreationDate) > (pgpTTL)
}
pgp: modernize and improve, and add tests 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>
2022-05-07 01:23:24 +02:00
// ToString returns the string representation of the key, i.e. its
// fingerprint.
func (key *MasterKey) ToString() string {
return key.Fingerprint
}
pgp: modernize and improve, and add tests 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>
2022-05-07 01:23:24 +02:00
// ToMap converts the MasterKey into a map for serialization purposes.
func (key MasterKey) ToMap() map[string]interface{} {
out := make(map[string]interface{})
out["fp"] = key.Fingerprint
out["created_at"] = key.CreationDate.UTC().Format(time.RFC3339)
out["enc"] = key.EncryptedKey
return out
}
// TypeToIdentifier returns the string identifier for the MasterKey type.
func (key *MasterKey) TypeToIdentifier() string {
return KeyTypeIdentifier
}
pgp: modernize and improve, and add tests 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>
2022-05-07 01:23:24 +02:00
// retrievePubKey attempts to retrieve the public key from the public keyring
// by Fingerprint.
func (key *MasterKey) retrievePubKey() (openpgp.Entity, error) {
ring, err := key.getPubRing()
if err == nil {
fingerprints := fingerprintIndex(ring)
pgp: modernize and improve, and add tests 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>
2022-05-07 01:23:24 +02:00
entity, ok := fingerprints[key.Fingerprint]
if ok {
return entity, nil
}
}
pgp: modernize and improve, and add tests 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>
2022-05-07 01:23:24 +02:00
return openpgp.Entity{},
fmt.Errorf("key with fingerprint '%s' is not available "+
pgp: modernize and improve, and add tests 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>
2022-05-07 01:23:24 +02:00
"in keyring", key.Fingerprint)
}
pgp: modernize and improve, and add tests 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>
2022-05-07 01:23:24 +02:00
// getPubRing loads the public keyring from the configured path, or falls back
// to defaultPubRing relative to the GnuPG home. It returns an openpgp.EntityList
// read from the keyring, or an error.
func (key *MasterKey) getPubRing() (openpgp.EntityList, error) {
path := key.pubRing
if path == "" {
path = filepath.Join(gnuPGHome(key.gnuPGHomeDir), defaultPubRing)
pgp: modernize and improve, and add tests 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>
2022-05-07 01:23:24 +02:00
}
return loadRing(path)
}
pgp: modernize and improve, and add tests 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>
2022-05-07 01:23:24 +02:00
// getSecRing loads the sec keyring from the configured path, or falls back
// to defaultSecRing relative to the GnuPG home. It returns an openpgp.EntityList
// read from the keyring, or an error.
func (key *MasterKey) getSecRing() (openpgp.EntityList, error) {
path := key.secRing
if path == "" {
path = filepath.Join(gnuPGHome(key.gnuPGHomeDir), defaultSecRing)
pgp: modernize and improve, and add tests 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>
2022-05-07 01:23:24 +02:00
}
if _, err := os.Lstat(path); err != nil {
if !os.IsNotExist(err) {
return nil, err
}
return key.getPubRing()
}
return loadRing(path)
}
pgp: modernize and improve, and add tests 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>
2022-05-07 01:23:24 +02:00
// passphrasePrompt prompts the user for a passphrase when this is required for
// encryption or decryption.
func (key *MasterKey) passphrasePrompt() func(keys []openpgp.Key, symmetric bool) ([]byte, error) {
callCounter := 0
maxCalls := 3
return func(keys []openpgp.Key, symmetric bool) ([]byte, error) {
if callCounter >= maxCalls {
return nil, fmt.Errorf("function passphrasePrompt called too many times")
2016-08-17 10:17:36 -07:00
}
callCounter++
conn, err := gpgagent.NewConn()
if err == gpgagent.ErrNoAgent {
log.Infof("gpg-agent not found, continuing with manual passphrase " +
"input...")
fmt.Print("Enter PGP key passphrase: ")
pass, err := term.ReadPassword(int(os.Stdin.Fd()))
if err != nil {
return nil, err
}
for _, k := range keys {
k.PrivateKey.Decrypt(pass)
}
return pass, err
2016-08-17 10:17:36 -07:00
}
if err != nil {
pgp: modernize and improve, and add tests 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>
2022-05-07 01:23:24 +02:00
return nil, fmt.Errorf("could not establish connection with gpg-agent: %s", err)
}
defer func(conn *gpgagent.Conn) {
if err := conn.Close(); err != nil {
log.Errorf("failed to close connection with gpg-agent: %s", err)
}
}(conn)
for _, k := range keys {
req := gpgagent.PassphraseRequest{
CacheKey: k.PublicKey.KeyIdShortString(),
Prompt: "Passphrase",
Desc: fmt.Sprintf("Unlock key %s to decrypt sops's key", k.PublicKey.KeyIdShortString()),
}
pass, err := conn.GetPassphrase(&req)
if err != nil {
return nil, fmt.Errorf("gpg-agent passphrase request errored: %s", err)
}
k.PrivateKey.Decrypt([]byte(pass))
return []byte(pass), nil
2016-08-17 10:17:36 -07:00
}
pgp: modernize and improve, and add tests 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>
2022-05-07 01:23:24 +02:00
return nil, fmt.Errorf("no key to unlock")
}
}
2016-08-18 15:49:27 -07:00
// loadRing attempts to load the keyring from the provided path.
// Unsupported keys are ignored as long as at least a single valid key is
// found.
func loadRing(path string) (openpgp.EntityList, error) {
f, err := os.Open(path)
if err != nil {
return nil, err
}
defer f.Close()
keyring, err := openpgp.ReadKeyRing(f)
if err != nil {
return nil, err
}
return keyring, nil
}
// fingerprintIndex indexes the openpgp.Entity objects from the given ring
// by their fingerprint, and returns the result.
func fingerprintIndex(ring openpgp.EntityList) map[string]openpgp.Entity {
fps := make(map[string]openpgp.Entity)
for _, entity := range ring {
if entity != nil {
fp := strings.ToUpper(hex.EncodeToString(entity.PrimaryKey.Fingerprint[:]))
fps[fp] = *entity
}
}
return fps
}
pgp: modernize and improve, and add tests 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>
2022-05-07 01:23:24 +02:00
// gpgExec runs the provided args with the gpgBinary, while restricting it to
// homeDir when provided. Stdout and stderr can be read from the returned
// buffers. When the command fails, an error is returned.
func gpgExec(ctx context.Context, homeDir string, args []string, stdin io.Reader) (stdout bytes.Buffer, stderr bytes.Buffer, err error) {
if homeDir != "" {
args = append([]string{"--homedir", homeDir}, args...)
pgp: modernize and improve, and add tests 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>
2022-05-07 01:23:24 +02:00
}
cmd := exec.CommandContext(ctx, gpgBinary(), args...)
pgp: modernize and improve, and add tests 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>
2022-05-07 01:23:24 +02:00
cmd.Stdin = stdin
cmd.Stdout = &stdout
cmd.Stderr = &stderr
err = cmd.Run()
return
}
// gpgBinary returns the GnuPG binary which must be used.
// It allows for runtime modifications by setting the replacement binary
// via the environment variable SopsGpgExecEnv.
pgp: modernize and improve, and add tests 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>
2022-05-07 01:23:24 +02:00
func gpgBinary() string {
if envBinary := os.Getenv(SopsGpgExecEnv); envBinary != "" {
return envBinary
pgp: modernize and improve, and add tests 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>
2022-05-07 01:23:24 +02:00
}
return "gpg"
pgp: modernize and improve, and add tests 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>
2022-05-07 01:23:24 +02:00
}
// gnuPGHome determines the GnuPG home directory, and returns its path.
// In order of preference:
// 1. customPath
// 2. $GNUPGHOME
// 3. user.Current().HomeDir/.gnupg
// 4. $HOME/.gnupg
func gnuPGHome(customPath string) string {
if customPath != "" {
return customPath
}
dir := os.Getenv("GNUPGHOME")
if dir == "" {
usr, err := user.Current()
if err != nil {
return filepath.Join(os.Getenv("HOME"), ".gnupg")
}
return filepath.Join(usr.HomeDir, ".gnupg")
}
return dir
}
pgp: modernize and improve, and add tests 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>
2022-05-07 01:23:24 +02:00
// shortenFingerprint returns the short ID of the given fingerprint.
// This is mostly used for compatibility reasons, as older versions of GnuPG
pgp: modernize and improve, and add tests 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>
2022-05-07 01:23:24 +02:00
// do not always like long IDs.
func shortenFingerprint(fingerprint string) string {
offset := len(fingerprint) - 16
// If the fingerprint ends with '!', we must include '!' in the ID *and* the
// 16 hex digits before it. See https://github.com/getsops/sops/issues/1365.
if strings.HasSuffix(fingerprint, "!") {
offset -= 1
}
if offset > 0 {
pgp: modernize and improve, and add tests 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>
2022-05-07 01:23:24 +02:00
fingerprint = fingerprint[offset:]
}
return fingerprint
2016-08-18 15:49:27 -07:00
}