Skip to content

Commit 7ff2343

Browse files
authored
Merge pull request containerd#3452 from lumjjb/keybundles
Create CryptoConfig constructors to replace dcparameters
2 parents 2190c0e + 3d1fa69 commit 7ff2343

File tree

8 files changed

+279
-127
lines changed

8 files changed

+279
-127
lines changed

cmd/ctr/commands/images/crypt_utils.go

Lines changed: 38 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -191,21 +191,21 @@ func createGPGClient(context *cli.Context) (encryption.GPGClient, error) {
191191
return encryption.NewGPGClient(context.String("gpg-version"), context.String("gpg-homedir"))
192192
}
193193

194-
func getGPGPrivateKeys(context *cli.Context, gpgSecretKeyRingFiles [][]byte, descs []ocispec.Descriptor, mustFindKey bool, dcparameters map[string][][]byte) error {
194+
func getGPGPrivateKeys(context *cli.Context, gpgSecretKeyRingFiles [][]byte, descs []ocispec.Descriptor, mustFindKey bool) (gpgPrivKeys [][]byte, gpgPrivKeysPwds [][]byte, err error) {
195195
gpgClient, err := createGPGClient(context)
196196
if err != nil {
197-
return err
197+
return nil, nil, err
198198
}
199199

200200
var gpgVault encryption.GPGVault
201201
if len(gpgSecretKeyRingFiles) > 0 {
202202
gpgVault = encryption.NewGPGVault()
203203
err = gpgVault.AddSecretKeyRingDataArray(gpgSecretKeyRingFiles)
204204
if err != nil {
205-
return err
205+
return nil, nil, err
206206
}
207207
}
208-
return encryption.GPGGetPrivateKey(descs, gpgClient, gpgVault, mustFindKey, dcparameters)
208+
return encryption.GPGGetPrivateKey(descs, gpgClient, gpgVault, mustFindKey)
209209
}
210210

211211
func createLayerFilter(client *containerd.Client, ctx gocontext.Context, desc ocispec.Descriptor, layers []int32, platformList []ocispec.Platform) (imgenc.LayerFilter, error) {
@@ -359,47 +359,62 @@ func filterLayerDescriptors(alldescs []ocispec.Descriptor, layers []int32, pl []
359359
return layerInfos, descs
360360
}
361361

362-
// CreateDcParameters creates the decryption parameter map from command line options and possibly
362+
// CreateDecryptCryptoConfig creates the CryptoConfig object that contains the necessary
363+
// information to perform decryption from command line options and possibly
363364
// LayerInfos describing the image and helping us to query for the PGP decryption keys
364-
func CreateDcParameters(context *cli.Context, descs []ocispec.Descriptor) (map[string][][]byte, error) {
365-
dcparameters := make(map[string][][]byte)
365+
func CreateDecryptCryptoConfig(context *cli.Context, descs []ocispec.Descriptor) (encconfig.CryptoConfig, error) {
366+
ccs := []encconfig.CryptoConfig{}
366367

367368
// x509 cert is needed for PKCS7 decryption
368369
_, _, x509s, err := processRecipientKeys(context.StringSlice("dec-recipient"))
369370
if err != nil {
370-
return nil, err
371+
return encconfig.CryptoConfig{}, err
371372
}
372373

373374
gpgSecretKeyRingFiles, gpgSecretKeyPasswords, privKeys, privKeysPasswords, err := processPrivateKeyFiles(context.StringSlice("key"))
374375
if err != nil {
375-
return nil, err
376+
return encconfig.CryptoConfig{}, err
376377
}
377378

378379
_, err = createGPGClient(context)
379380
gpgInstalled := err == nil
380381
if gpgInstalled {
381382
if len(gpgSecretKeyRingFiles) == 0 && len(privKeys) == 0 && descs != nil {
382383
// Get pgp private keys from keyring only if no private key was passed
383-
err = getGPGPrivateKeys(context, gpgSecretKeyRingFiles, descs, true, dcparameters)
384+
gpgPrivKeys, gpgPrivKeyPasswords, err := getGPGPrivateKeys(context, gpgSecretKeyRingFiles, descs, true)
384385
if err != nil {
385-
return nil, err
386+
return encconfig.CryptoConfig{}, err
386387
}
387-
} else {
388-
if len(gpgSecretKeyRingFiles) == 0 {
389-
dcparameters["gpg-client"] = [][]byte{[]byte("1")}
390-
dcparameters["gpg-client-version"] = [][]byte{[]byte(context.String("gpg-version"))}
391-
dcparameters["gpg-client-homedir"] = [][]byte{[]byte(context.String("gpg-homedir"))}
392-
} else {
393-
dcparameters["gpg-privatekeys"] = gpgSecretKeyRingFiles
394-
dcparameters["gpg-privatekeys-passwords"] = gpgSecretKeyPasswords
388+
389+
gpgCc, err := encconfig.DecryptWithGpgPrivKeys(gpgPrivKeys, gpgPrivKeyPasswords)
390+
if err != nil {
391+
return encconfig.CryptoConfig{}, err
392+
}
393+
ccs = append(ccs, gpgCc)
394+
395+
} else if len(gpgSecretKeyRingFiles) > 0 {
396+
gpgCc, err := encconfig.DecryptWithGpgPrivKeys(gpgSecretKeyRingFiles, gpgSecretKeyPasswords)
397+
if err != nil {
398+
return encconfig.CryptoConfig{}, err
395399
}
400+
ccs = append(ccs, gpgCc)
401+
396402
}
397403
}
398-
dcparameters["privkeys"] = privKeys
399-
dcparameters["privkeys-passwords"] = privKeysPasswords
400-
dcparameters["x509s"] = x509s
401404

402-
return dcparameters, nil
405+
x509sCc, err := encconfig.DecryptWithX509s(x509s)
406+
if err != nil {
407+
return encconfig.CryptoConfig{}, err
408+
}
409+
ccs = append(ccs, x509sCc)
410+
411+
privKeysCc, err := encconfig.DecryptWithPrivKeys(privKeys, privKeysPasswords)
412+
if err != nil {
413+
return encconfig.CryptoConfig{}, err
414+
}
415+
ccs = append(ccs, privKeysCc)
416+
417+
return encconfig.CombineCryptoConfigs(ccs), nil
403418
}
404419

405420
// parsePlatformArray parses an array of specifiers and converts them into an array of specs.Platform

cmd/ctr/commands/images/decrypt.go

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ import (
2121

2222
"github.com/containerd/containerd/cmd/ctr/commands"
2323
imgenc "github.com/containerd/containerd/images/encryption"
24-
encconfig "github.com/containerd/containerd/pkg/encryption/config"
2524
"github.com/pkg/errors"
2625
"github.com/urfave/cli"
2726
)
@@ -83,14 +82,12 @@ var decryptCommand = cli.Command{
8382
return nil
8483
}
8584

86-
dcparameters, err := CreateDcParameters(context, descs)
85+
cc, err := CreateDecryptCryptoConfig(context, descs)
8786
if err != nil {
8887
return err
8988
}
9089

91-
cc := encconfig.InitDecryption(dcparameters)
92-
93-
_, err = decryptImage(client, ctx, local, newName, cc, layers32, context.StringSlice("platform"))
90+
_, err = decryptImage(client, ctx, local, newName, &cc, layers32, context.StringSlice("platform"))
9491

9592
return err
9693
},

cmd/ctr/commands/images/encrypt.go

Lines changed: 29 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -77,45 +77,21 @@ var encryptCommand = cli.Command{
7777

7878
layers32 := commands.IntToInt32Array(context.IntSlice("layer"))
7979

80-
gpgSecretKeyRingFiles, _, privKeys, privKeysPasswords, err := processPrivateKeyFiles(context.StringSlice("key"))
81-
if err != nil {
82-
return err
83-
}
84-
8580
gpgRecipients, pubKeys, x509s, err := processRecipientKeys(recipients)
8681
if err != nil {
8782
return err
8883
}
8984

90-
_, _, decX509s, err := processRecipientKeys(context.StringSlice("dec-recipient"))
91-
if err != nil {
92-
return err
93-
}
94-
95-
dcparameters := make(map[string][][]byte)
96-
parameters := make(map[string][][]byte)
97-
98-
parameters["pubkeys"] = pubKeys
99-
parameters["x509s"] = x509s
100-
10185
_, descs, err := getImageLayerInfos(client, ctx, local, layers32, context.StringSlice("platform"))
10286
if err != nil {
10387
return err
10488
}
10589

90+
encryptCcs := []encconfig.CryptoConfig{}
10691
_, err = createGPGClient(context)
10792
gpgInstalled := err == nil
108-
if len(privKeys) == 0 && gpgInstalled {
109-
// Get pgp private keys from keyring only if no private key was passed
110-
err = getGPGPrivateKeys(context, gpgSecretKeyRingFiles, descs, true, dcparameters)
111-
if err != nil {
112-
return err
113-
}
114-
}
11593

11694
if len(gpgRecipients) > 0 && gpgInstalled {
117-
parameters["gpg-recipients"] = gpgRecipients
118-
11995
gpgClient, err := createGPGClient(context)
12096
if err != nil {
12197
return err
@@ -126,16 +102,38 @@ var encryptCommand = cli.Command{
126102
return err
127103
}
128104

129-
parameters["gpg-pubkeyringfile"] = [][]byte{gpgPubRingFile}
105+
gpgCc, err := encconfig.EncryptWithGpg(gpgRecipients, gpgPubRingFile)
106+
if err != nil {
107+
return err
108+
}
109+
encryptCcs = append(encryptCcs, gpgCc)
110+
130111
}
131112

132-
dcparameters["privkeys"] = privKeys
133-
dcparameters["privkeys-passwords"] = privKeysPasswords
134-
dcparameters["x509s"] = decX509s
113+
// Create Encryption Crypto Config
114+
pkcs7Cc, err := encconfig.EncryptWithPkcs7(x509s)
115+
if err != nil {
116+
return err
117+
}
118+
encryptCcs = append(encryptCcs, pkcs7Cc)
135119

136-
cc := encconfig.InitEncryption(parameters, dcparameters)
120+
jweCc, err := encconfig.EncryptWithJwe(pubKeys)
121+
if err != nil {
122+
return err
123+
}
124+
encryptCcs = append(encryptCcs, jweCc)
125+
126+
cc := encconfig.CombineCryptoConfigs(encryptCcs)
127+
128+
// Create Decryption CryptoConfig for use in adding recipients to
129+
// existing image if decryptable.
130+
decryptCc, err := CreateDecryptCryptoConfig(context, descs)
131+
if err != nil {
132+
return err
133+
}
134+
cc.EncryptConfig.AttachDecryptConfig(decryptCc.DecryptConfig)
137135

138-
_, err = encryptImage(client, ctx, local, newName, cc, layers32, context.StringSlice("platform"))
136+
_, err = encryptImage(client, ctx, local, newName, &cc, layers32, context.StringSlice("platform"))
139137

140138
return err
141139
},

image_enc_test.go

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -122,17 +122,13 @@ func TestImageEncryption(t *testing.T) {
122122
return false
123123
}
124124

125-
dcparameters := make(map[string][][]byte)
126-
parameters := make(map[string][][]byte)
127-
128-
parameters["pubkeys"] = [][]byte{publicKey}
129-
dcparameters["privkeys"] = [][]byte{privateKey}
130-
dcparameters["privkeys-passwords"] = [][]byte{{}}
131-
132-
cc := encconfig.InitEncryption(parameters, dcparameters)
125+
cc, err := encconfig.EncryptWithJwe([][]byte{publicKey})
126+
if err != nil {
127+
t.Fatal(err)
128+
}
133129

134130
// Perform encryption of image
135-
encSpec, modified, err := imgenc.EncryptImage(ctx, client.ContentStore(), image.Target, cc, lf)
131+
encSpec, modified, err := imgenc.EncryptImage(ctx, client.ContentStore(), image.Target, &cc, lf)
136132
if err != nil {
137133
t.Fatal(err)
138134
}
@@ -149,7 +145,10 @@ func TestImageEncryption(t *testing.T) {
149145
t.Fatalf("Unable to create image: %v", err)
150146
}
151147

152-
cc = encconfig.InitDecryption(dcparameters)
148+
cc, err = encconfig.DecryptWithPrivKeys([][]byte{privateKey}, [][]byte{{}})
149+
if err != nil {
150+
t.Fatal(err)
151+
}
153152

154153
// Clean up function cancels lease before deleting the image so the images are
155154
// properly deleted
@@ -164,7 +163,7 @@ func TestImageEncryption(t *testing.T) {
164163
return true
165164
}
166165

167-
decSpec, modified, err := imgenc.DecryptImage(ctx, client.ContentStore(), encSpec, cc, lf)
166+
decSpec, modified, err := imgenc.DecryptImage(ctx, client.ContentStore(), encSpec, &cc, lf)
168167
if err != nil {
169168
t.Fatal(err)
170169
}

images/encryption/encryption.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -421,7 +421,7 @@ func CheckAuthorization(ctx context.Context, cs content.Store, desc ocispec.Desc
421421
return true
422422
}
423423

424-
_, _, err := cryptImage(ctx, cs, desc, cc, lf, cryptoOpUnwrapOnly)
424+
_, _, err := cryptImage(ctx, cs, desc, &cc, lf, cryptoOpUnwrapOnly)
425425
if err != nil {
426426
return errors.Wrapf(err, "you are not authorized to use this image")
427427
}

pkg/encryption/config/config.go

Lines changed: 55 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,8 @@ type CryptoConfig struct {
4040
}
4141

4242
// InitDecryption initialized a CryptoConfig object with parameters used for decryption
43-
func InitDecryption(dcparameters map[string][][]byte) *CryptoConfig {
44-
return &CryptoConfig{
43+
func InitDecryption(dcparameters map[string][][]byte) CryptoConfig {
44+
return CryptoConfig{
4545
DecryptConfig: &DecryptConfig{
4646
Parameters: dcparameters,
4747
},
@@ -51,8 +51,8 @@ func InitDecryption(dcparameters map[string][][]byte) *CryptoConfig {
5151
// InitEncryption initializes a CryptoConfig object with parameters used for encryption
5252
// It also takes dcparameters that may be needed for decryption when adding a recipient
5353
// to an already encrypted image
54-
func InitEncryption(parameters, dcparameters map[string][][]byte) *CryptoConfig {
55-
return &CryptoConfig{
54+
func InitEncryption(parameters, dcparameters map[string][][]byte) CryptoConfig {
55+
return CryptoConfig{
5656
EncryptConfig: &EncryptConfig{
5757
Parameters: parameters,
5858
DecryptConfig: DecryptConfig{
@@ -61,3 +61,54 @@ func InitEncryption(parameters, dcparameters map[string][][]byte) *CryptoConfig
6161
},
6262
}
6363
}
64+
65+
// CombineCryptoConfigs takes a CryptoConfig list and creates a single CryptoConfig
66+
// containing the crypto configuration of all the key bundles
67+
func CombineCryptoConfigs(ccs []CryptoConfig) CryptoConfig {
68+
ecparam := map[string][][]byte{}
69+
ecdcparam := map[string][][]byte{}
70+
dcparam := map[string][][]byte{}
71+
72+
for _, cc := range ccs {
73+
if ec := cc.EncryptConfig; ec != nil {
74+
addToMap(ecparam, ec.Parameters)
75+
addToMap(ecdcparam, ec.DecryptConfig.Parameters)
76+
}
77+
78+
if dc := cc.DecryptConfig; dc != nil {
79+
addToMap(dcparam, dc.Parameters)
80+
}
81+
}
82+
83+
return CryptoConfig{
84+
EncryptConfig: &EncryptConfig{
85+
Parameters: ecparam,
86+
DecryptConfig: DecryptConfig{
87+
Parameters: ecdcparam,
88+
},
89+
},
90+
DecryptConfig: &DecryptConfig{
91+
Parameters: dcparam,
92+
},
93+
}
94+
95+
}
96+
97+
// AttachDecryptConfig adds DecryptConfig to the field of EncryptConfig so that
98+
// the decryption parameters can be used to add recipients to an existing image
99+
// if the user is able to decrypt it.
100+
func (ec *EncryptConfig) AttachDecryptConfig(dc *DecryptConfig) {
101+
if dc != nil {
102+
addToMap(ec.DecryptConfig.Parameters, dc.Parameters)
103+
}
104+
}
105+
106+
func addToMap(orig map[string][][]byte, add map[string][][]byte) {
107+
for k, v := range add {
108+
if ov, ok := orig[k]; ok {
109+
orig[k] = append(ov, v...)
110+
} else {
111+
orig[k] = v
112+
}
113+
}
114+
}

0 commit comments

Comments
 (0)