Skip to content

Commit

Permalink
Merge pull request #510 from aryan9600/pgp-passphrase
Browse files Browse the repository at this point in the history
Add support for commit signing PGP key passphrases
  • Loading branch information
stefanprodan authored May 2, 2023
2 parents 0fb73e6 + cf455f2 commit f946d7f
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 14 deletions.
16 changes: 15 additions & 1 deletion docs/spec/v1beta1/imageupdateautomations.md
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,21 @@ will result in commits with the author `Fluxbot <flux@example.com>`.

The optional `signingKey` field can be used to provide a key to sign commits with. It holds a
reference to a secret, which is expected to have a file called `git.asc` containing an
ASCII-armoured PGP key.
ASCII-armoured PGP key. If the private key is protected by a password, you can specify the same
in the secret using the `passphrase` key.

```yaml
---
apiVersion: v1
kind: Secret
metadata:
name: signing-key
namespace: default
stringData:
git.asc: |
<ARMOR ENCODED PGP KEY>
passphrase: <private-key-passphrase>
```

The `messageTemplate` field is a string which will be used as a template for the commit message. If
empty, there is a default message; but you will likely want to provide your own, especially if you
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ require (
github.com/onsi/gomega v1.27.6
github.com/otiai10/copy v1.9.0
github.com/spf13/pflag v1.0.5
golang.org/x/crypto v0.7.0
k8s.io/api v0.26.3
k8s.io/apimachinery v0.26.3
k8s.io/client-go v0.26.3
Expand Down Expand Up @@ -120,6 +119,7 @@ require (
go.uber.org/atomic v1.10.0 // indirect
go.uber.org/multierr v1.8.0 // indirect
go.uber.org/zap v1.24.0 // indirect
golang.org/x/crypto v0.7.0 // indirect
golang.org/x/mod v0.9.0 // indirect
golang.org/x/net v0.8.0 // indirect
golang.org/x/oauth2 v0.6.0 // indirect
Expand Down
28 changes: 20 additions & 8 deletions internal/controllers/imageupdateautomation_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,13 +67,13 @@ import (
"github.com/fluxcd/image-automation-controller/pkg/update"
)

const originRemote = "origin"

const defaultMessageTemplate = `Update from image update automation`

const repoRefKey = ".spec.gitRepository"

const signingSecretKey = "git.asc"
const (
originRemote = "origin"
defaultMessageTemplate = `Update from image update automation`
repoRefKey = ".spec.gitRepository"
signingSecretKey = "git.asc"
signingPassphraseKey = "passphrase"
)

// TemplateData is the type of the value given to the commit message
// template.
Expand Down Expand Up @@ -590,7 +590,19 @@ func (r *ImageUpdateAutomationReconciler) getSigningEntity(ctx context.Context,
if len(entities) > 1 {
return nil, fmt.Errorf("multiple entities read from secret '%s', could not determine which signing key to use", secretName)
}
return entities[0], nil

entity := entities[0]
if entity.PrivateKey.Encrypted {
passphrase, ok := secret.Data[signingPassphraseKey]
if !ok {
return nil, fmt.Errorf("can not use passphrase protected signing key without '%s' field present in secret %s",
signingPassphraseKey, secretName)
}
if err = entity.PrivateKey.Decrypt([]byte(passphrase)); err != nil {
return nil, fmt.Errorf("could not decrypt private key of the signing key present in secret %s: %w", secretName, err)
}
}
return entity, nil
}

// --- events, metrics
Expand Down
15 changes: 11 additions & 4 deletions internal/controllers/update_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,12 @@ import (
"testing"
"time"

"github.com/ProtonMail/go-crypto/openpgp"
"github.com/ProtonMail/go-crypto/openpgp/armor"
securejoin "github.com/cyphar/filepath-securejoin"
"github.com/go-logr/logr"
. "github.com/onsi/gomega"
"github.com/otiai10/copy"
"golang.org/x/crypto/openpgp"
"golang.org/x/crypto/openpgp/armor"
corev1 "k8s.io/api/core/v1"
apimeta "k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
Expand Down Expand Up @@ -417,7 +417,7 @@ func TestImageAutomationReconciler_signedCommit(t *testing.T) {
kr := openpgp.EntityList([]*openpgp.Entity{pgpEntity})
signature := strings.NewReader(commit.PGPSignature)

_, err = openpgp.CheckArmoredDetachedSignature(kr, content, signature)
_, err = openpgp.CheckArmoredDetachedSignature(kr, content, signature, nil)
g.Expect(err).ToNot(HaveOccurred())
},
)
Expand Down Expand Up @@ -1581,6 +1581,7 @@ func createSigningKeyPair(kClient client.Client, name, namespace string) (*openp
if err != nil {
return nil, err
}

// Configure OpenPGP armor encoder.
b := bytes.NewBuffer(nil)
w, err := armor.Encode(b, openpgp.PrivateKeyType, nil)
Expand All @@ -1594,10 +1595,16 @@ func createSigningKeyPair(kClient client.Client, name, namespace string) (*openp
if err = w.Close(); err != nil {
return nil, err
}

passphrase := "abcde12345"
if err = pgpEntity.PrivateKey.Encrypt([]byte(passphrase)); err != nil {
return nil, err
}
// Create the secret containing signing key.
sec := &corev1.Secret{
Data: map[string][]byte{
"git.asc": b.Bytes(),
signingSecretKey: b.Bytes(),
signingPassphraseKey: []byte(passphrase),
},
}
sec.Name = name
Expand Down

0 comments on commit f946d7f

Please sign in to comment.