Merge pull request #3452 from lumjjb/keybundles
Create CryptoConfig constructors to replace dcparameters
This commit is contained in:
		| @@ -191,10 +191,10 @@ func createGPGClient(context *cli.Context) (encryption.GPGClient, error) { | |||||||
| 	return encryption.NewGPGClient(context.String("gpg-version"), context.String("gpg-homedir")) | 	return encryption.NewGPGClient(context.String("gpg-version"), context.String("gpg-homedir")) | ||||||
| } | } | ||||||
|  |  | ||||||
| func getGPGPrivateKeys(context *cli.Context, gpgSecretKeyRingFiles [][]byte, descs []ocispec.Descriptor, mustFindKey bool, dcparameters map[string][][]byte) error { | func getGPGPrivateKeys(context *cli.Context, gpgSecretKeyRingFiles [][]byte, descs []ocispec.Descriptor, mustFindKey bool) (gpgPrivKeys [][]byte, gpgPrivKeysPwds [][]byte, err error) { | ||||||
| 	gpgClient, err := createGPGClient(context) | 	gpgClient, err := createGPGClient(context) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return err | 		return nil, nil, err | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	var gpgVault encryption.GPGVault | 	var gpgVault encryption.GPGVault | ||||||
| @@ -202,10 +202,10 @@ func getGPGPrivateKeys(context *cli.Context, gpgSecretKeyRingFiles [][]byte, des | |||||||
| 		gpgVault = encryption.NewGPGVault() | 		gpgVault = encryption.NewGPGVault() | ||||||
| 		err = gpgVault.AddSecretKeyRingDataArray(gpgSecretKeyRingFiles) | 		err = gpgVault.AddSecretKeyRingDataArray(gpgSecretKeyRingFiles) | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			return err | 			return nil, nil, err | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	return encryption.GPGGetPrivateKey(descs, gpgClient, gpgVault, mustFindKey, dcparameters) | 	return encryption.GPGGetPrivateKey(descs, gpgClient, gpgVault, mustFindKey) | ||||||
| } | } | ||||||
|  |  | ||||||
| func createLayerFilter(client *containerd.Client, ctx gocontext.Context, desc ocispec.Descriptor, layers []int32, platformList []ocispec.Platform) (imgenc.LayerFilter, error) { | func createLayerFilter(client *containerd.Client, ctx gocontext.Context, desc ocispec.Descriptor, layers []int32, platformList []ocispec.Platform) (imgenc.LayerFilter, error) { | ||||||
| @@ -359,20 +359,21 @@ func filterLayerDescriptors(alldescs []ocispec.Descriptor, layers []int32, pl [] | |||||||
| 	return layerInfos, descs | 	return layerInfos, descs | ||||||
| } | } | ||||||
|  |  | ||||||
| // CreateDcParameters creates the decryption parameter map from command line options and possibly | // CreateDecryptCryptoConfig creates the CryptoConfig object that contains the necessary | ||||||
|  | // information to perform decryption from command line options and possibly | ||||||
| // LayerInfos describing the image and helping us to query for the PGP decryption keys | // LayerInfos describing the image and helping us to query for the PGP decryption keys | ||||||
| func CreateDcParameters(context *cli.Context, descs []ocispec.Descriptor) (map[string][][]byte, error) { | func CreateDecryptCryptoConfig(context *cli.Context, descs []ocispec.Descriptor) (encconfig.CryptoConfig, error) { | ||||||
| 	dcparameters := make(map[string][][]byte) | 	ccs := []encconfig.CryptoConfig{} | ||||||
|  |  | ||||||
| 	// x509 cert is needed for PKCS7 decryption | 	// x509 cert is needed for PKCS7 decryption | ||||||
| 	_, _, x509s, err := processRecipientKeys(context.StringSlice("dec-recipient")) | 	_, _, x509s, err := processRecipientKeys(context.StringSlice("dec-recipient")) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return nil, err | 		return encconfig.CryptoConfig{}, err | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	gpgSecretKeyRingFiles, gpgSecretKeyPasswords, privKeys, privKeysPasswords, err := processPrivateKeyFiles(context.StringSlice("key")) | 	gpgSecretKeyRingFiles, gpgSecretKeyPasswords, privKeys, privKeysPasswords, err := processPrivateKeyFiles(context.StringSlice("key")) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return nil, err | 		return encconfig.CryptoConfig{}, err | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	_, err = createGPGClient(context) | 	_, err = createGPGClient(context) | ||||||
| @@ -380,26 +381,40 @@ func CreateDcParameters(context *cli.Context, descs []ocispec.Descriptor) (map[s | |||||||
| 	if gpgInstalled { | 	if gpgInstalled { | ||||||
| 		if len(gpgSecretKeyRingFiles) == 0 && len(privKeys) == 0 && descs != nil { | 		if len(gpgSecretKeyRingFiles) == 0 && len(privKeys) == 0 && descs != nil { | ||||||
| 			// Get pgp private keys from keyring only if no private key was passed | 			// Get pgp private keys from keyring only if no private key was passed | ||||||
| 			err = getGPGPrivateKeys(context, gpgSecretKeyRingFiles, descs, true, dcparameters) | 			gpgPrivKeys, gpgPrivKeyPasswords, err := getGPGPrivateKeys(context, gpgSecretKeyRingFiles, descs, true) | ||||||
| 			if err != nil { | 			if err != nil { | ||||||
| 				return nil, err | 				return encconfig.CryptoConfig{}, err | ||||||
| 			} | 			} | ||||||
| 		} else { |  | ||||||
| 			if len(gpgSecretKeyRingFiles) == 0 { |  | ||||||
| 				dcparameters["gpg-client"] = [][]byte{[]byte("1")} |  | ||||||
| 				dcparameters["gpg-client-version"] = [][]byte{[]byte(context.String("gpg-version"))} |  | ||||||
| 				dcparameters["gpg-client-homedir"] = [][]byte{[]byte(context.String("gpg-homedir"))} |  | ||||||
| 			} else { |  | ||||||
| 				dcparameters["gpg-privatekeys"] = gpgSecretKeyRingFiles |  | ||||||
| 				dcparameters["gpg-privatekeys-passwords"] = gpgSecretKeyPasswords |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 	dcparameters["privkeys"] = privKeys |  | ||||||
| 	dcparameters["privkeys-passwords"] = privKeysPasswords |  | ||||||
| 	dcparameters["x509s"] = x509s |  | ||||||
|  |  | ||||||
| 	return dcparameters, nil | 			gpgCc, err := encconfig.DecryptWithGpgPrivKeys(gpgPrivKeys, gpgPrivKeyPasswords) | ||||||
|  | 			if err != nil { | ||||||
|  | 				return encconfig.CryptoConfig{}, err | ||||||
|  | 			} | ||||||
|  | 			ccs = append(ccs, gpgCc) | ||||||
|  |  | ||||||
|  | 		} else if len(gpgSecretKeyRingFiles) > 0 { | ||||||
|  | 			gpgCc, err := encconfig.DecryptWithGpgPrivKeys(gpgSecretKeyRingFiles, gpgSecretKeyPasswords) | ||||||
|  | 			if err != nil { | ||||||
|  | 				return encconfig.CryptoConfig{}, err | ||||||
|  | 			} | ||||||
|  | 			ccs = append(ccs, gpgCc) | ||||||
|  |  | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	x509sCc, err := encconfig.DecryptWithX509s(x509s) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return encconfig.CryptoConfig{}, err | ||||||
|  | 	} | ||||||
|  | 	ccs = append(ccs, x509sCc) | ||||||
|  |  | ||||||
|  | 	privKeysCc, err := encconfig.DecryptWithPrivKeys(privKeys, privKeysPasswords) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return encconfig.CryptoConfig{}, err | ||||||
|  | 	} | ||||||
|  | 	ccs = append(ccs, privKeysCc) | ||||||
|  |  | ||||||
|  | 	return encconfig.CombineCryptoConfigs(ccs), nil | ||||||
| } | } | ||||||
|  |  | ||||||
| // parsePlatformArray parses an array of specifiers and converts them into an array of specs.Platform | // parsePlatformArray parses an array of specifiers and converts them into an array of specs.Platform | ||||||
|   | |||||||
| @@ -21,7 +21,6 @@ import ( | |||||||
|  |  | ||||||
| 	"github.com/containerd/containerd/cmd/ctr/commands" | 	"github.com/containerd/containerd/cmd/ctr/commands" | ||||||
| 	imgenc "github.com/containerd/containerd/images/encryption" | 	imgenc "github.com/containerd/containerd/images/encryption" | ||||||
| 	encconfig "github.com/containerd/containerd/pkg/encryption/config" |  | ||||||
| 	"github.com/pkg/errors" | 	"github.com/pkg/errors" | ||||||
| 	"github.com/urfave/cli" | 	"github.com/urfave/cli" | ||||||
| ) | ) | ||||||
| @@ -83,14 +82,12 @@ var decryptCommand = cli.Command{ | |||||||
| 			return nil | 			return nil | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		dcparameters, err := CreateDcParameters(context, descs) | 		cc, err := CreateDecryptCryptoConfig(context, descs) | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			return err | 			return err | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		cc := encconfig.InitDecryption(dcparameters) | 		_, err = decryptImage(client, ctx, local, newName, &cc, layers32, context.StringSlice("platform")) | ||||||
|  |  | ||||||
| 		_, err = decryptImage(client, ctx, local, newName, cc, layers32, context.StringSlice("platform")) |  | ||||||
|  |  | ||||||
| 		return err | 		return err | ||||||
| 	}, | 	}, | ||||||
|   | |||||||
| @@ -77,45 +77,21 @@ var encryptCommand = cli.Command{ | |||||||
|  |  | ||||||
| 		layers32 := commands.IntToInt32Array(context.IntSlice("layer")) | 		layers32 := commands.IntToInt32Array(context.IntSlice("layer")) | ||||||
|  |  | ||||||
| 		gpgSecretKeyRingFiles, _, privKeys, privKeysPasswords, err := processPrivateKeyFiles(context.StringSlice("key")) |  | ||||||
| 		if err != nil { |  | ||||||
| 			return err |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		gpgRecipients, pubKeys, x509s, err := processRecipientKeys(recipients) | 		gpgRecipients, pubKeys, x509s, err := processRecipientKeys(recipients) | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			return err | 			return err | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		_, _, decX509s, err := processRecipientKeys(context.StringSlice("dec-recipient")) |  | ||||||
| 		if err != nil { |  | ||||||
| 			return err |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		dcparameters := make(map[string][][]byte) |  | ||||||
| 		parameters := make(map[string][][]byte) |  | ||||||
|  |  | ||||||
| 		parameters["pubkeys"] = pubKeys |  | ||||||
| 		parameters["x509s"] = x509s |  | ||||||
|  |  | ||||||
| 		_, descs, err := getImageLayerInfos(client, ctx, local, layers32, context.StringSlice("platform")) | 		_, descs, err := getImageLayerInfos(client, ctx, local, layers32, context.StringSlice("platform")) | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			return err | 			return err | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  | 		encryptCcs := []encconfig.CryptoConfig{} | ||||||
| 		_, err = createGPGClient(context) | 		_, err = createGPGClient(context) | ||||||
| 		gpgInstalled := err == nil | 		gpgInstalled := err == nil | ||||||
| 		if len(privKeys) == 0 && gpgInstalled { |  | ||||||
| 			// Get pgp private keys from keyring only if no private key was passed |  | ||||||
| 			err = getGPGPrivateKeys(context, gpgSecretKeyRingFiles, descs, true, dcparameters) |  | ||||||
| 			if err != nil { |  | ||||||
| 				return err |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		if len(gpgRecipients) > 0 && gpgInstalled { | 		if len(gpgRecipients) > 0 && gpgInstalled { | ||||||
| 			parameters["gpg-recipients"] = gpgRecipients |  | ||||||
|  |  | ||||||
| 			gpgClient, err := createGPGClient(context) | 			gpgClient, err := createGPGClient(context) | ||||||
| 			if err != nil { | 			if err != nil { | ||||||
| 				return err | 				return err | ||||||
| @@ -126,16 +102,38 @@ var encryptCommand = cli.Command{ | |||||||
| 				return err | 				return err | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
| 			parameters["gpg-pubkeyringfile"] = [][]byte{gpgPubRingFile} | 			gpgCc, err := encconfig.EncryptWithGpg(gpgRecipients, gpgPubRingFile) | ||||||
|  | 			if err != nil { | ||||||
|  | 				return err | ||||||
|  | 			} | ||||||
|  | 			encryptCcs = append(encryptCcs, gpgCc) | ||||||
|  |  | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		dcparameters["privkeys"] = privKeys | 		// Create Encryption Crypto Config | ||||||
| 		dcparameters["privkeys-passwords"] = privKeysPasswords | 		pkcs7Cc, err := encconfig.EncryptWithPkcs7(x509s) | ||||||
| 		dcparameters["x509s"] = decX509s | 		if err != nil { | ||||||
|  | 			return err | ||||||
|  | 		} | ||||||
|  | 		encryptCcs = append(encryptCcs, pkcs7Cc) | ||||||
|  |  | ||||||
| 		cc := encconfig.InitEncryption(parameters, dcparameters) | 		jweCc, err := encconfig.EncryptWithJwe(pubKeys) | ||||||
|  | 		if err != nil { | ||||||
|  | 			return err | ||||||
|  | 		} | ||||||
|  | 		encryptCcs = append(encryptCcs, jweCc) | ||||||
|  |  | ||||||
| 		_, err = encryptImage(client, ctx, local, newName, cc, layers32, context.StringSlice("platform")) | 		cc := encconfig.CombineCryptoConfigs(encryptCcs) | ||||||
|  |  | ||||||
|  | 		// Create Decryption CryptoConfig for use in adding recipients to | ||||||
|  | 		// existing image if decryptable. | ||||||
|  | 		decryptCc, err := CreateDecryptCryptoConfig(context, descs) | ||||||
|  | 		if err != nil { | ||||||
|  | 			return err | ||||||
|  | 		} | ||||||
|  | 		cc.EncryptConfig.AttachDecryptConfig(decryptCc.DecryptConfig) | ||||||
|  |  | ||||||
|  | 		_, err = encryptImage(client, ctx, local, newName, &cc, layers32, context.StringSlice("platform")) | ||||||
|  |  | ||||||
| 		return err | 		return err | ||||||
| 	}, | 	}, | ||||||
|   | |||||||
| @@ -122,17 +122,13 @@ func TestImageEncryption(t *testing.T) { | |||||||
| 		return false | 		return false | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	dcparameters := make(map[string][][]byte) | 	cc, err := encconfig.EncryptWithJwe([][]byte{publicKey}) | ||||||
| 	parameters := make(map[string][][]byte) | 	if err != nil { | ||||||
|  | 		t.Fatal(err) | ||||||
| 	parameters["pubkeys"] = [][]byte{publicKey} | 	} | ||||||
| 	dcparameters["privkeys"] = [][]byte{privateKey} |  | ||||||
| 	dcparameters["privkeys-passwords"] = [][]byte{{}} |  | ||||||
|  |  | ||||||
| 	cc := encconfig.InitEncryption(parameters, dcparameters) |  | ||||||
|  |  | ||||||
| 	// Perform encryption of image | 	// Perform encryption of image | ||||||
| 	encSpec, modified, err := imgenc.EncryptImage(ctx, client.ContentStore(), image.Target, cc, lf) | 	encSpec, modified, err := imgenc.EncryptImage(ctx, client.ContentStore(), image.Target, &cc, lf) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		t.Fatal(err) | 		t.Fatal(err) | ||||||
| 	} | 	} | ||||||
| @@ -149,7 +145,10 @@ func TestImageEncryption(t *testing.T) { | |||||||
| 		t.Fatalf("Unable to create image: %v", err) | 		t.Fatalf("Unable to create image: %v", err) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	cc = encconfig.InitDecryption(dcparameters) | 	cc, err = encconfig.DecryptWithPrivKeys([][]byte{privateKey}, [][]byte{{}}) | ||||||
|  | 	if err != nil { | ||||||
|  | 		t.Fatal(err) | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	// Clean up function cancels lease before deleting the image so the images are | 	// Clean up function cancels lease before deleting the image so the images are | ||||||
| 	// properly deleted | 	// properly deleted | ||||||
| @@ -164,7 +163,7 @@ func TestImageEncryption(t *testing.T) { | |||||||
| 		return true | 		return true | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	decSpec, modified, err := imgenc.DecryptImage(ctx, client.ContentStore(), encSpec, cc, lf) | 	decSpec, modified, err := imgenc.DecryptImage(ctx, client.ContentStore(), encSpec, &cc, lf) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		t.Fatal(err) | 		t.Fatal(err) | ||||||
| 	} | 	} | ||||||
|   | |||||||
| @@ -421,7 +421,7 @@ func CheckAuthorization(ctx context.Context, cs content.Store, desc ocispec.Desc | |||||||
| 		return true | 		return true | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	_, _, err := cryptImage(ctx, cs, desc, cc, lf, cryptoOpUnwrapOnly) | 	_, _, err := cryptImage(ctx, cs, desc, &cc, lf, cryptoOpUnwrapOnly) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return errors.Wrapf(err, "you are not authorized to use this image") | 		return errors.Wrapf(err, "you are not authorized to use this image") | ||||||
| 	} | 	} | ||||||
|   | |||||||
| @@ -40,8 +40,8 @@ type CryptoConfig struct { | |||||||
| } | } | ||||||
|  |  | ||||||
| // InitDecryption initialized a CryptoConfig object with parameters used for decryption | // InitDecryption initialized a CryptoConfig object with parameters used for decryption | ||||||
| func InitDecryption(dcparameters map[string][][]byte) *CryptoConfig { | func InitDecryption(dcparameters map[string][][]byte) CryptoConfig { | ||||||
| 	return &CryptoConfig{ | 	return CryptoConfig{ | ||||||
| 		DecryptConfig: &DecryptConfig{ | 		DecryptConfig: &DecryptConfig{ | ||||||
| 			Parameters: dcparameters, | 			Parameters: dcparameters, | ||||||
| 		}, | 		}, | ||||||
| @@ -51,8 +51,8 @@ func InitDecryption(dcparameters map[string][][]byte) *CryptoConfig { | |||||||
| // InitEncryption initializes a CryptoConfig object with parameters used for encryption | // InitEncryption initializes a CryptoConfig object with parameters used for encryption | ||||||
| // It also takes dcparameters that may be needed for decryption when adding a recipient | // It also takes dcparameters that may be needed for decryption when adding a recipient | ||||||
| // to an already encrypted image | // to an already encrypted image | ||||||
| func InitEncryption(parameters, dcparameters map[string][][]byte) *CryptoConfig { | func InitEncryption(parameters, dcparameters map[string][][]byte) CryptoConfig { | ||||||
| 	return &CryptoConfig{ | 	return CryptoConfig{ | ||||||
| 		EncryptConfig: &EncryptConfig{ | 		EncryptConfig: &EncryptConfig{ | ||||||
| 			Parameters: parameters, | 			Parameters: parameters, | ||||||
| 			DecryptConfig: DecryptConfig{ | 			DecryptConfig: DecryptConfig{ | ||||||
| @@ -61,3 +61,54 @@ func InitEncryption(parameters, dcparameters map[string][][]byte) *CryptoConfig | |||||||
| 		}, | 		}, | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // CombineCryptoConfigs takes a CryptoConfig list and creates a single CryptoConfig | ||||||
|  | // containing the crypto configuration of all the key bundles | ||||||
|  | func CombineCryptoConfigs(ccs []CryptoConfig) CryptoConfig { | ||||||
|  | 	ecparam := map[string][][]byte{} | ||||||
|  | 	ecdcparam := map[string][][]byte{} | ||||||
|  | 	dcparam := map[string][][]byte{} | ||||||
|  |  | ||||||
|  | 	for _, cc := range ccs { | ||||||
|  | 		if ec := cc.EncryptConfig; ec != nil { | ||||||
|  | 			addToMap(ecparam, ec.Parameters) | ||||||
|  | 			addToMap(ecdcparam, ec.DecryptConfig.Parameters) | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		if dc := cc.DecryptConfig; dc != nil { | ||||||
|  | 			addToMap(dcparam, dc.Parameters) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return CryptoConfig{ | ||||||
|  | 		EncryptConfig: &EncryptConfig{ | ||||||
|  | 			Parameters: ecparam, | ||||||
|  | 			DecryptConfig: DecryptConfig{ | ||||||
|  | 				Parameters: ecdcparam, | ||||||
|  | 			}, | ||||||
|  | 		}, | ||||||
|  | 		DecryptConfig: &DecryptConfig{ | ||||||
|  | 			Parameters: dcparam, | ||||||
|  | 		}, | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // AttachDecryptConfig adds DecryptConfig to the field of EncryptConfig so that | ||||||
|  | // the decryption parameters can be used to add recipients to an existing image | ||||||
|  | // if the user is able to decrypt it. | ||||||
|  | func (ec *EncryptConfig) AttachDecryptConfig(dc *DecryptConfig) { | ||||||
|  | 	if dc != nil { | ||||||
|  | 		addToMap(ec.DecryptConfig.Parameters, dc.Parameters) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func addToMap(orig map[string][][]byte, add map[string][][]byte) { | ||||||
|  | 	for k, v := range add { | ||||||
|  | 		if ov, ok := orig[k]; ok { | ||||||
|  | 			orig[k] = append(ov, v...) | ||||||
|  | 		} else { | ||||||
|  | 			orig[k] = v | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|   | |||||||
							
								
								
									
										134
									
								
								pkg/encryption/config/constructors.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										134
									
								
								pkg/encryption/config/constructors.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,134 @@ | |||||||
|  | /* | ||||||
|  |    Copyright The containerd Authors. | ||||||
|  |  | ||||||
|  |    Licensed under the Apache License, Version 2.0 (the "License"); | ||||||
|  |    you may not use this file except in compliance with the License. | ||||||
|  |    You may obtain a copy of the License at | ||||||
|  |  | ||||||
|  |        http://www.apache.org/licenses/LICENSE-2.0 | ||||||
|  |  | ||||||
|  |    Unless required by applicable law or agreed to in writing, software | ||||||
|  |    distributed under the License is distributed on an "AS IS" BASIS, | ||||||
|  |    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||||
|  |    See the License for the specific language governing permissions and | ||||||
|  |    limitations under the License. | ||||||
|  | */ | ||||||
|  |  | ||||||
|  | package config | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"github.com/pkg/errors" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | // EncryptWithJwe returns a CryptoConfig to encrypt with jwe public keys | ||||||
|  | func EncryptWithJwe(pubKeys [][]byte) (CryptoConfig, error) { | ||||||
|  | 	dc := DecryptConfig{} | ||||||
|  | 	ep := map[string][][]byte{ | ||||||
|  | 		"pubkeys": pubKeys, | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return CryptoConfig{ | ||||||
|  | 		EncryptConfig: &EncryptConfig{ | ||||||
|  | 			Parameters:    ep, | ||||||
|  | 			DecryptConfig: dc, | ||||||
|  | 		}, | ||||||
|  | 		DecryptConfig: &dc, | ||||||
|  | 	}, nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // EncryptWithPkcs7 returns a CryptoConfig to encrypt with pkcs7 x509 certs | ||||||
|  | func EncryptWithPkcs7(x509s [][]byte) (CryptoConfig, error) { | ||||||
|  | 	dc := DecryptConfig{} | ||||||
|  |  | ||||||
|  | 	ep := map[string][][]byte{ | ||||||
|  | 		"x509s": x509s, | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return CryptoConfig{ | ||||||
|  | 		EncryptConfig: &EncryptConfig{ | ||||||
|  | 			Parameters:    ep, | ||||||
|  | 			DecryptConfig: dc, | ||||||
|  | 		}, | ||||||
|  | 		DecryptConfig: &dc, | ||||||
|  | 	}, nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // EncryptWithGpg returns a CryptoConfig to encrypt with configured gpg parameters | ||||||
|  | func EncryptWithGpg(gpgRecipients [][]byte, gpgPubRingFile []byte) (CryptoConfig, error) { | ||||||
|  | 	dc := DecryptConfig{} | ||||||
|  | 	ep := map[string][][]byte{ | ||||||
|  | 		"gpg-recipients":     gpgRecipients, | ||||||
|  | 		"gpg-pubkeyringfile": {gpgPubRingFile}, | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return CryptoConfig{ | ||||||
|  | 		EncryptConfig: &EncryptConfig{ | ||||||
|  | 			Parameters:    ep, | ||||||
|  | 			DecryptConfig: dc, | ||||||
|  | 		}, | ||||||
|  | 		DecryptConfig: &dc, | ||||||
|  | 	}, nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // DecryptWithPrivKeys returns a CryptoConfig to decrypt with configured private keys | ||||||
|  | func DecryptWithPrivKeys(privKeys [][]byte, privKeysPasswords [][]byte) (CryptoConfig, error) { | ||||||
|  | 	if len(privKeys) != len(privKeysPasswords) { | ||||||
|  | 		return CryptoConfig{}, errors.New("Length of privKeys should match length of privKeysPasswords") | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	dc := DecryptConfig{ | ||||||
|  | 		Parameters: map[string][][]byte{ | ||||||
|  | 			"privkeys":           privKeys, | ||||||
|  | 			"privkeys-passwords": privKeysPasswords, | ||||||
|  | 		}, | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	ep := map[string][][]byte{} | ||||||
|  |  | ||||||
|  | 	return CryptoConfig{ | ||||||
|  | 		EncryptConfig: &EncryptConfig{ | ||||||
|  | 			Parameters:    ep, | ||||||
|  | 			DecryptConfig: dc, | ||||||
|  | 		}, | ||||||
|  | 		DecryptConfig: &dc, | ||||||
|  | 	}, nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // DecryptWithX509s returns a CryptoConfig to decrypt with configured x509 certs | ||||||
|  | func DecryptWithX509s(x509s [][]byte) (CryptoConfig, error) { | ||||||
|  | 	dc := DecryptConfig{ | ||||||
|  | 		Parameters: map[string][][]byte{ | ||||||
|  | 			"x509s": x509s, | ||||||
|  | 		}, | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	ep := map[string][][]byte{} | ||||||
|  |  | ||||||
|  | 	return CryptoConfig{ | ||||||
|  | 		EncryptConfig: &EncryptConfig{ | ||||||
|  | 			Parameters:    ep, | ||||||
|  | 			DecryptConfig: dc, | ||||||
|  | 		}, | ||||||
|  | 		DecryptConfig: &dc, | ||||||
|  | 	}, nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // DecryptWithGpgPrivKeys returns a CryptoConfig to decrypt with configured gpg private keys | ||||||
|  | func DecryptWithGpgPrivKeys(gpgPrivKeys, gpgPrivKeysPwds [][]byte) (CryptoConfig, error) { | ||||||
|  | 	dc := DecryptConfig{ | ||||||
|  | 		Parameters: map[string][][]byte{ | ||||||
|  | 			"gpg-privatekeys":           gpgPrivKeys, | ||||||
|  | 			"gpg-privatekeys-passwords": gpgPrivKeysPwds, | ||||||
|  | 		}, | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	ep := map[string][][]byte{} | ||||||
|  |  | ||||||
|  | 	return CryptoConfig{ | ||||||
|  | 		EncryptConfig: &EncryptConfig{ | ||||||
|  | 			Parameters:    ep, | ||||||
|  | 			DecryptConfig: dc, | ||||||
|  | 		}, | ||||||
|  | 		DecryptConfig: &dc, | ||||||
|  | 	}, nil | ||||||
|  | } | ||||||
| @@ -322,7 +322,7 @@ func uint64ToStringArray(format string, in []uint64) []string { | |||||||
| // in the GPGVault or on this system and prompts for the passwords for those | // in the GPGVault or on this system and prompts for the passwords for those | ||||||
| // that are available. If we do not find a private key on the system for | // that are available. If we do not find a private key on the system for | ||||||
| // getting to the symmetric key of a layer then an error is generated. | // getting to the symmetric key of a layer then an error is generated. | ||||||
| func GPGGetPrivateKey(descs []ocispec.Descriptor, gpgClient GPGClient, gpgVault GPGVault, mustFindKey bool, dcparameters map[string][][]byte) error { | func GPGGetPrivateKey(descs []ocispec.Descriptor, gpgClient GPGClient, gpgVault GPGVault, mustFindKey bool) (gpgPrivKeys [][]byte, gpgPrivKeysPwds [][]byte, err error) { | ||||||
| 	// PrivateKeyData describes a private key | 	// PrivateKeyData describes a private key | ||||||
| 	type PrivateKeyData struct { | 	type PrivateKeyData struct { | ||||||
| 		KeyData         []byte | 		KeyData         []byte | ||||||
| @@ -338,11 +338,11 @@ func GPGGetPrivateKey(descs []ocispec.Descriptor, gpgClient GPGClient, gpgVault | |||||||
| 			} | 			} | ||||||
| 			keywrapper := GetKeyWrapper(scheme) | 			keywrapper := GetKeyWrapper(scheme) | ||||||
| 			if keywrapper == nil { | 			if keywrapper == nil { | ||||||
| 				return errors.Errorf("could not get KeyWrapper for %s\n", scheme) | 				return nil, nil, errors.Errorf("could not get KeyWrapper for %s\n", scheme) | ||||||
| 			} | 			} | ||||||
| 			keyIds, err := keywrapper.GetKeyIdsFromPacket(b64pgpPackets) | 			keyIds, err := keywrapper.GetKeyIdsFromPacket(b64pgpPackets) | ||||||
| 			if err != nil { | 			if err != nil { | ||||||
| 				return err | 				return nil, nil, err | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
| 			found := false | 			found := false | ||||||
| @@ -376,11 +376,11 @@ func GPGGetPrivateKey(descs []ocispec.Descriptor, gpgClient GPGClient, gpgVault | |||||||
| 						password, err := terminal.ReadPassword(int(os.Stdin.Fd())) | 						password, err := terminal.ReadPassword(int(os.Stdin.Fd())) | ||||||
| 						fmt.Printf("\n") | 						fmt.Printf("\n") | ||||||
| 						if err != nil { | 						if err != nil { | ||||||
| 							return err | 							return nil, nil, err | ||||||
| 						} | 						} | ||||||
| 						keydata, err := gpgClient.GetGPGPrivateKey(keyid, string(password)) | 						keydata, err := gpgClient.GetGPGPrivateKey(keyid, string(password)) | ||||||
| 						if err != nil { | 						if err != nil { | ||||||
| 							return err | 							return nil, nil, err | ||||||
| 						} | 						} | ||||||
| 						pkd = PrivateKeyData{ | 						pkd = PrivateKeyData{ | ||||||
| 							KeyData:         keydata, | 							KeyData:         keydata, | ||||||
| @@ -391,63 +391,21 @@ func GPGGetPrivateKey(descs []ocispec.Descriptor, gpgClient GPGClient, gpgVault | |||||||
| 					} | 					} | ||||||
| 					break | 					break | ||||||
| 				} else { | 				} else { | ||||||
| 					return errors.Wrapf(errdefs.ErrInvalidArgument, "no GPGVault or GPGClient passed.") | 					return nil, nil, errors.Wrapf(errdefs.ErrInvalidArgument, "no GPGVault or GPGClient passed.") | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| 			if !found && len(b64pgpPackets) > 0 && mustFindKey { | 			if !found && len(b64pgpPackets) > 0 && mustFindKey { | ||||||
| 				ids := uint64ToStringArray("0x%x", keyIds) | 				ids := uint64ToStringArray("0x%x", keyIds) | ||||||
|  |  | ||||||
| 				return errors.Wrapf(errdefs.ErrNotFound, "missing key for decryption of layer %x of %s. Need one of the following keys: %s", desc.Digest, desc.Platform, strings.Join(ids, ", ")) | 				return nil, nil, errors.Wrapf(errdefs.ErrNotFound, "missing key for decryption of layer %x of %s. Need one of the following keys: %s", desc.Digest, desc.Platform, strings.Join(ids, ", ")) | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	var ( |  | ||||||
| 		privKeys    [][]byte |  | ||||||
| 		privKeysPwd [][]byte |  | ||||||
| 	) |  | ||||||
| 	for _, pkd := range keyIDPasswordMap { | 	for _, pkd := range keyIDPasswordMap { | ||||||
| 		privKeys = append(privKeys, pkd.KeyData) | 		gpgPrivKeys = append(gpgPrivKeys, pkd.KeyData) | ||||||
| 		privKeysPwd = append(privKeysPwd, pkd.KeyDataPassword) | 		gpgPrivKeysPwds = append(gpgPrivKeysPwds, pkd.KeyDataPassword) | ||||||
| 	} |  | ||||||
| 	dcparameters["gpg-privatekeys"] = privKeys |  | ||||||
| 	dcparameters["gpg-privatekeys-passwords"] = privKeysPwd |  | ||||||
|  |  | ||||||
| 	return nil |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| // GPGSetupPrivateKeys uses the gpg specific parameters in the dcparameters map | 	return gpgPrivKeys, gpgPrivKeysPwds, nil | ||||||
| // to get the private keys needed for decryption the give layers |  | ||||||
| func GPGSetupPrivateKeys(dcparameters map[string][][]byte, descs []ocispec.Descriptor) error { |  | ||||||
| 	/* we have to find a GPG key until we also get other private keys passed */ |  | ||||||
| 	var ( |  | ||||||
| 		gpgVault   GPGVault |  | ||||||
| 		gpgClient  GPGClient |  | ||||||
| 		gpgVersion string |  | ||||||
| 		gpgHomeDir string |  | ||||||
| 		err        error |  | ||||||
| 	) |  | ||||||
| 	gpgPrivateKeys := dcparameters["gpg-privatekeys"] |  | ||||||
| 	if len(gpgPrivateKeys) > 0 { |  | ||||||
| 		gpgVault = NewGPGVault() |  | ||||||
| 		gpgVault.AddSecretKeyRingDataArray(gpgPrivateKeys) |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	haveGPGClient := dcparameters["gpg-client"] |  | ||||||
| 	if len(haveGPGClient) > 0 { |  | ||||||
| 		item := dcparameters["gpg-client-version"] |  | ||||||
| 		if len(item) == 1 { |  | ||||||
| 			gpgVersion = string(item[0]) |  | ||||||
| 		} |  | ||||||
| 		item = dcparameters["gpg-client-homedir"] |  | ||||||
| 		if len(item) == 1 { |  | ||||||
| 			gpgHomeDir = string(item[0]) |  | ||||||
| 		} |  | ||||||
| 		gpgClient, err = NewGPGClient(gpgVersion, gpgHomeDir) |  | ||||||
| 		if err != nil { |  | ||||||
| 			return err |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	return GPGGetPrivateKey(descs, gpgClient, gpgVault, false, dcparameters) |  | ||||||
| } | } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Phil Estes
					Phil Estes