Skip to content

Commit 43e1335

Browse files
committed
Added support for ssh signed commits and completed gpg signed commit work
Signed-off-by: Dustin Lactin <[email protected]>
1 parent 43f579e commit 43e1335

File tree

11 files changed

+181
-3
lines changed

11 files changed

+181
-3
lines changed

.github/actions/spelling/expect.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22
aeece
33
Artifactory
44
applicationid
5+
atlassian
6+
Bitbucket
7+
bitbucketserver
58
bacd
69
CVE
710
credref
@@ -11,7 +14,9 @@ eec
1114
fbd
1215
ffb
1316
gitlab
17+
GPG
1418
helmvalues
19+
html
1520
installationid
1621
jfrog
1722
mep

cmd/main.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ type ImageUpdaterConfig struct {
4545
GitCommitUser string
4646
GitCommitMail string
4747
GitCommitMessage *template.Template
48+
GitCommitSigningKey string
49+
GitCommitSignOff bool
4850
DisableKubeEvents bool
4951
GitCreds git.CredsStore
5052
}

cmd/run.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,8 @@ func newRunCommand() *cobra.Command {
240240
runCmd.Flags().BoolVar(&warmUpCache, "warmup-cache", true, "whether to perform a cache warm-up on startup")
241241
runCmd.Flags().StringVar(&cfg.GitCommitUser, "git-commit-user", env.GetStringVal("GIT_COMMIT_USER", "argocd-image-updater"), "Username to use for Git commits")
242242
runCmd.Flags().StringVar(&cfg.GitCommitMail, "git-commit-email", env.GetStringVal("GIT_COMMIT_EMAIL", "[email protected]"), "E-Mail address to use for Git commits")
243+
runCmd.Flags().StringVar(&cfg.GitCommitSigningKey, "git-commit-signing-key", env.GetStringVal("GIT_COMMIT_SIGNING_KEY", ""), "GnuPG key ID or path to Public SSH Key used to sign the commits")
244+
runCmd.Flags().BoolVar(&cfg.GitCommitSignOff, "git-commit-sign-off", env.GetBoolVal("GIT_COMMIT_SIGN_OFF", false), "Whether to sign-off git commits")
243245
runCmd.Flags().StringVar(&commitMessagePath, "git-commit-message-path", defaultCommitTemplatePath, "Path to a template to use for Git commit messages")
244246
runCmd.Flags().BoolVar(&cfg.DisableKubeEvents, "disable-kube-events", env.GetBoolVal("IMAGE_UPDATER_KUBE_EVENTS", false), "Disable kubernetes events")
245247

@@ -327,6 +329,8 @@ func runImageUpdater(cfg *ImageUpdaterConfig, warmUp bool) (argocd.ImageUpdaterR
327329
GitCommitUser: cfg.GitCommitUser,
328330
GitCommitEmail: cfg.GitCommitMail,
329331
GitCommitMessage: cfg.GitCommitMessage,
332+
GitCommitSigningKey: cfg.GitCommitSigningKey,
333+
GitCommitSignOff: cfg.GitCommitSignOff,
330334
DisableKubeEvents: cfg.DisableKubeEvents,
331335
GitCreds: cfg.GitCreds,
332336
}

docs/basics/update-methods.md

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,8 @@ format. To create such a secret from an existing private key, you can use
153153

154154
```bash
155155
kubectl -n argocd-image-updater create secret generic git-creds \
156-
--from-file=sshPrivateKey=~/.ssh/id_rsa
156+
--from-file=sshPrivateKey=~/.ssh/id_rsa \
157+
--from-file=sshPublicKey=~/.ssh/id_rsa.pub \
157158
```
158159

159160
### <a name="method-git-repository"></a>Specifying a repository when using a Helm repository in repoURL
@@ -247,6 +248,52 @@ as the author. You can override the author using the
247248
`git.user` and `git.email`
248249
in the `argocd-image-updater-config` ConfigMap.
249250

251+
### <a name="method-git-commit-signing"></a>Enabling commit signature verification using an SSH or GPG key
252+
Commit signing requires the repository be accessed using HTTPS or SSH with a user account.
253+
Repositories accessed using a GitHub App can not be verified when using the git command line at this time.
254+
255+
Each Git commit associated with an author's name and email address can be signed via a public SSH key or GPG key.
256+
Commit signing requires a bot account with a GPG or SSH key and the username and email address configured to match the bot account.
257+
258+
Your preferred signing key must be associated with your bot account. See provider documentation for further details:
259+
* [GitHub](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification)
260+
* [GitLab](https://docs.gitlab.com/ee/user/project/repository/signed_commits/)
261+
* [Bitbucket](https://confluence.atlassian.com/bitbucketserver/controlling-access-to-code-776639770.html)
262+
263+
Commit Sign Off can be enabled by setting `git.commit-sign-off: "true"`
264+
265+
**SSH:**
266+
267+
Both private and public keys must be mounted and accessible on the `argocd-image-updater` pod.
268+
269+
Set `git.commit-signing-key` `argocd-image-updater-config` ConfigMap to the path of your public key:
270+
271+
```yaml
272+
data:
273+
git.commit-sign-off: "true"
274+
git.commit-signing-key: /app/.ssh/id_rsa.pub
275+
```
276+
277+
The matching private key must be available in the same location.
278+
279+
Create a new SSH secret or add the public key to your existing SSH secret:
280+
```bash
281+
kubectl -n argocd-image-updater create secret generic ssh-git-creds \
282+
--from-file=sshPrivateKey=~/.ssh/id_rsa \
283+
--from-file=sshPublicKey=~/.ssh/id_rsa.pub
284+
```
285+
286+
**GPG:**
287+
288+
The GPG private key must be installed and available in the `argocd-image-updater` pod.
289+
Set `git.commit-signing-key` in the `argocd-image-updater-config` ConfigMap to the GPG key ID you want to use:
290+
291+
```yaml
292+
data:
293+
git.commit-sign-off: "true"
294+
git.commit-signing-key: 3AA5C34371567BD2
295+
```
296+
250297
### <a name="method-git-commit-message"></a>Changing the Git commit message
251298

252299
You can change the default commit message used by Argo CD Image Updater to some

ext/git/client.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ type Client interface {
8282
Add(path string) error
8383
SymRefToBranch(symRef string) (string, error)
8484
Config(username string, email string) error
85+
SigningConfig(signingkey string) error
8586
}
8687

8788
type EventHandlers struct {

ext/git/mocks/Client.go

Lines changed: 14 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

ext/git/writer.go

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package git
33
import (
44
"fmt"
55
"os/exec"
6+
"regexp"
67
"strings"
78

89
"github.com/argoproj-labs/argocd-image-updater/pkg/log"
@@ -14,7 +15,7 @@ type CommitOptions struct {
1415
CommitMessageText string
1516
// CommitMessagePath holds the path to a file to be used for the commit message (-F option)
1617
CommitMessagePath string
17-
// SigningKey holds a GnuPG key ID used to sign the commit with (-S option)
18+
// SigningKey holds a GnuPG key ID or path to Public SSH Key used to sign the commit with (-S option)
1819
SigningKey string
1920
// SignOff specifies whether to sign-off a commit (-s option)
2021
SignOff bool
@@ -33,7 +34,16 @@ func (m *nativeGitClient) Commit(pathSpec string, opts *CommitOptions) error {
3334
args = append(args, "-a")
3435
}
3536
if opts.SigningKey != "" {
36-
args = append(args, "-S", opts.SigningKey)
37+
// Check if SiginingKey is a GPG key or Public SSH Key
38+
keyCheck, err := regexp.MatchString(".*pub$", opts.SigningKey)
39+
if err != nil {
40+
return fmt.Errorf("could not validate Signing Key as GPG or Public SSH Key: %v", err)
41+
}
42+
if keyCheck {
43+
args = append(args, "-S")
44+
} else {
45+
args = append(args, "-S", opts.SigningKey)
46+
}
3747
}
3848
if opts.SignOff {
3949
args = append(args, "-s")
@@ -147,3 +157,28 @@ func (m *nativeGitClient) runCredentialedCmdWithOutput(args ...string) (string,
147157
cmd.Env = append(cmd.Env, environ...)
148158
return m.runCmdOutput(cmd, runOpts{})
149159
}
160+
161+
// SigningConfig configures commit signing for the repository
162+
func (m *nativeGitClient) SigningConfig(signingkey string) error {
163+
// Check if SiginingKey is a GPG key or Public SSH Key
164+
keyCheck, err := regexp.MatchString(".*pub$", signingkey)
165+
if err != nil {
166+
return fmt.Errorf("could not validate Signing Key as GPG or Public SSH Key: %v", err)
167+
}
168+
if keyCheck {
169+
// Setting the GPG format to ssh
170+
log.Warnf("Setting GPG Format to SSH")
171+
_, err = m.runCmd("config", "gpg.format", "ssh")
172+
if err != nil {
173+
return fmt.Errorf("could not set gpg format to ssh: %v", err)
174+
}
175+
// Setting Public SSH Key as our signing key
176+
// SSH Keys can not currently be set via cli flag
177+
_, err = m.runCmd("config", "user.signingkey", signingkey)
178+
if err != nil {
179+
return fmt.Errorf("could not set git signing key: %v", err)
180+
}
181+
}
182+
183+
return nil
184+
}

manifests/base/deployment/argocd-image-updater-deployment.yaml

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,18 @@ spec:
7777
name: argocd-image-updater-config
7878
key: git.email
7979
optional: true
80+
- name: GIT_COMMIT_SIGNING_KEY
81+
valueFrom:
82+
configMapKeyRef:
83+
key: git.commit-signing-key
84+
name: argocd-image-updater-config
85+
optional: true
86+
- name: GIT_COMMIT_SIGN_OFF
87+
valueFrom:
88+
configMapKeyRef:
89+
key: git.commit-sign-off
90+
name: argocd-image-updater-config
91+
optional: true
8092
- name: IMAGE_UPDATER_KUBE_EVENTS
8193
valueFrom:
8294
configMapKeyRef:
@@ -116,6 +128,14 @@ spec:
116128
name: ssh-config
117129
- mountPath: /tmp
118130
name: tmp
131+
- name: ssh-signing-key
132+
mountPath: /app/.ssh/id_rsa
133+
readOnly: true
134+
subPath: sshPrivateKey
135+
- name: ssh-signing-key
136+
mountPath: /app/.ssh/id_rsa.pub
137+
readOnly: true
138+
subPath: sshPublicKey
119139
serviceAccountName: argocd-image-updater
120140
volumes:
121141
- configMap:
@@ -135,5 +155,9 @@ spec:
135155
name: argocd-image-updater-ssh-config
136156
optional: true
137157
name: ssh-config
158+
- name: ssh-signing-key
159+
secret:
160+
secretName: ssh-git-creds
161+
optional: true
138162
- emptyDir: {}
139163
name: tmp

manifests/install.yaml

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,18 @@ spec:
158158
key: git.email
159159
name: argocd-image-updater-config
160160
optional: true
161+
- name: GIT_COMMIT_SIGNING_KEY
162+
valueFrom:
163+
configMapKeyRef:
164+
key: git.commit-signing-key
165+
name: argocd-image-updater-config
166+
optional: true
167+
- name: GIT_COMMIT_SIGN_OFF
168+
valueFrom:
169+
configMapKeyRef:
170+
key: git.commit-sign-off
171+
name: argocd-image-updater-config
172+
optional: true
161173
- name: IMAGE_UPDATER_KUBE_EVENTS
162174
valueFrom:
163175
configMapKeyRef:
@@ -199,6 +211,14 @@ spec:
199211
name: ssh-config
200212
- mountPath: /tmp
201213
name: tmp
214+
- mountPath: /app/.ssh/id_rsa
215+
name: ssh-signing-key
216+
readOnly: true
217+
subPath: sshPrivateKey
218+
- mountPath: /app/.ssh/id_rsa.pub
219+
name: ssh-signing-key
220+
readOnly: true
221+
subPath: sshPublicKey
202222
serviceAccountName: argocd-image-updater
203223
volumes:
204224
- configMap:
@@ -218,5 +238,9 @@ spec:
218238
name: argocd-image-updater-ssh-config
219239
optional: true
220240
name: ssh-config
241+
- name: ssh-signing-key
242+
optional: true
243+
secret:
244+
secretName: ssh-git-creds
221245
- emptyDir: {}
222246
name: tmp

pkg/argocd/git.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,14 @@ func commitChangesGit(app *v1alpha1.Application, wbc *WriteBackConfig, changeLis
169169
}
170170
}
171171

172+
// Set commit signing configuration
173+
if wbc.GitCommitSigningKey != "" {
174+
err = gitC.SigningConfig(wbc.GitCommitSigningKey)
175+
if err != nil {
176+
return err
177+
}
178+
}
179+
172180
// The branch to checkout is either a configured branch in the write-back
173181
// config, or taken from the application spec's targetRevision. If the
174182
// target revision is set to the special value HEAD, or is the empty
@@ -234,6 +242,12 @@ func commitChangesGit(app *v1alpha1.Application, wbc *WriteBackConfig, changeLis
234242
defer os.Remove(cm.Name())
235243
}
236244

245+
if wbc.GitCommitSigningKey != "" {
246+
commitOpts.SigningKey = wbc.GitCommitSigningKey
247+
}
248+
249+
commitOpts.SignOff = wbc.GitCommitSignOff
250+
237251
err = gitC.Commit("", commitOpts)
238252
if err != nil {
239253
return err

0 commit comments

Comments
 (0)