Skip to content

Commit df380c9

Browse files
committedOct 23, 2021
Merge branch 'fs/ssh-signing' into jch
Use ssh public crypto for object and push-cert signing. * fs/ssh-signing: ssh signing: test that gpg fails for unknown keys ssh signing: tests for logs, tags & push certs ssh signing: duplicate t7510 tests for commits ssh signing: verify signatures using ssh-keygen ssh signing: provide a textual signing_key_id ssh signing: retrieve a default key from ssh-agent ssh signing: add ssh key format and signing code ssh signing: add test prereqs ssh signing: preliminary refactoring and clean-up
2 parents b5ce01e + 1bfb57f commit df380c9

15 files changed

+1341
-66
lines changed
 

‎Documentation/config/gpg.txt

+43-2
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,13 @@ gpg.program::
1111

1212
gpg.format::
1313
Specifies which key format to use when signing with `--gpg-sign`.
14-
Default is "openpgp" and another possible value is "x509".
14+
Default is "openpgp". Other possible values are "x509", "ssh".
1515

1616
gpg.<format>.program::
1717
Use this to customize the program used for the signing format you
1818
chose. (see `gpg.program` and `gpg.format`) `gpg.program` can still
1919
be used as a legacy synonym for `gpg.openpgp.program`. The default
20-
value for `gpg.x509.program` is "gpgsm".
20+
value for `gpg.x509.program` is "gpgsm" and `gpg.ssh.program` is "ssh-keygen".
2121

2222
gpg.minTrustLevel::
2323
Specifies a minimum trust level for signature verification. If
@@ -33,3 +33,44 @@ gpg.minTrustLevel::
3333
* `marginal`
3434
* `fully`
3535
* `ultimate`
36+
37+
gpg.ssh.defaultKeyCommand:
38+
This command that will be run when user.signingkey is not set and a ssh
39+
signature is requested. On successful exit a valid ssh public key is
40+
expected in the first line of its output. To automatically use the first
41+
available key from your ssh-agent set this to "ssh-add -L".
42+
43+
gpg.ssh.allowedSignersFile::
44+
A file containing ssh public keys which you are willing to trust.
45+
The file consists of one or more lines of principals followed by an ssh
46+
public key.
47+
e.g.: user1@example.com,user2@example.com ssh-rsa AAAAX1...
48+
See ssh-keygen(1) "ALLOWED SIGNERS" for details.
49+
The principal is only used to identify the key and is available when
50+
verifying a signature.
51+
+
52+
SSH has no concept of trust levels like gpg does. To be able to differentiate
53+
between valid signatures and trusted signatures the trust level of a signature
54+
verification is set to `fully` when the public key is present in the allowedSignersFile.
55+
Therefore to only mark fully trusted keys as verified set gpg.minTrustLevel to `fully`.
56+
Otherwise valid but untrusted signatures will still verify but show no principal
57+
name of the signer.
58+
+
59+
This file can be set to a location outside of the repository and every developer
60+
maintains their own trust store. A central repository server could generate this
61+
file automatically from ssh keys with push access to verify the code against.
62+
In a corporate setting this file is probably generated at a global location
63+
from automation that already handles developer ssh keys.
64+
+
65+
A repository that only allows signed commits can store the file
66+
in the repository itself using a path relative to the top-level of the working tree.
67+
This way only committers with an already valid key can add or change keys in the keyring.
68+
+
69+
Using a SSH CA key with the cert-authority option
70+
(see ssh-keygen(1) "CERTIFICATES") is also valid.
71+
72+
gpg.ssh.revocationFile::
73+
Either a SSH KRL or a list of revoked public keys (without the principal prefix).
74+
See ssh-keygen(1) for details.
75+
If a public key is found in this file then it will always be treated
76+
as having trust level "never" and signatures will show as invalid.

‎Documentation/config/user.txt

+7
Original file line numberDiff line numberDiff line change
@@ -36,3 +36,10 @@ user.signingKey::
3636
commit, you can override the default selection with this variable.
3737
This option is passed unchanged to gpg's --local-user parameter,
3838
so you may specify a key using any method that gpg supports.
39+
If gpg.format is set to "ssh" this can contain the literal ssh public
40+
key (e.g.: "ssh-rsa XXXXXX identifier") or a file which contains it and
41+
corresponds to the private key used for signing. The private key
42+
needs to be available via ssh-agent. Alternatively it can be set to
43+
a file containing a private key directly. If not set git will call
44+
gpg.ssh.defaultKeyCommand (e.g.: "ssh-add -L") and try to use the first
45+
key available.

‎builtin/receive-pack.c

+4
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,10 @@ static int receive_pack_config(const char *var, const char *value, void *cb)
132132
{
133133
int status = parse_hide_refs_config(var, value, "receive");
134134

135+
if (status)
136+
return status;
137+
138+
status = git_gpg_config(var, value, NULL);
135139
if (status)
136140
return status;
137141

‎fmt-merge-msg.c

+3-3
Original file line numberDiff line numberDiff line change
@@ -528,11 +528,11 @@ static void fmt_merge_msg_sigs(struct strbuf *out)
528528
buf = payload.buf;
529529
len = payload.len;
530530
if (check_signature(payload.buf, payload.len, sig.buf,
531-
sig.len, &sigc) &&
532-
!sigc.gpg_output)
531+
sig.len, &sigc) &&
532+
!sigc.output)
533533
strbuf_addstr(&sig, "gpg verification failed.\n");
534534
else
535-
strbuf_addstr(&sig, sigc.gpg_output);
535+
strbuf_addstr(&sig, sigc.output);
536536
}
537537
signature_check_clear(&sigc);
538538

0 commit comments

Comments
 (0)