Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Commit signing backend implementation #3007

Merged
merged 7 commits into from
Feb 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,33 @@ jobs:

steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11

# The default version of gpg installed on the runners is a version baked in with git
# which only contains the components needed by git and doesn't work for our test cases.
#
# This installs the latest gpg4win version, which is a variation of GnuPG built for
# Windows.
#
# There is some issue with windows PATH max length which is what all the PATH wrangling
# below is for. Please see the below link for where this fix was derived from:
# https://github.com/orgs/community/discussions/24933
- name: Setup GnuPG [windows]
if: ${{ matrix.os == 'windows-latest' }}
run: |
$env:PATH = "C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\ProgramData\chocolatey\bin"
[Environment]::SetEnvironmentVariable("Path", $env:PATH, "Machine")
choco install --yes gpg4win
echo "C:\Program Files (x86)\Gpg4win\..\GnuPG\bin" >> $env:GITHUB_PATH

# The default version of openssh on windows server is quite old (8.1) and doesn't have
# all the necessary signing/verification commands available (such as -Y find-principals)
- name: Setup ssh-agent [windows]
if: ${{ matrix.os == 'windows-latest' }}
run: |
Remove-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0
Remove-WindowsCapability -Online -Name OpenSSH.Client~~~~0.0.1.0
choco install openssh --pre

- name: Install Rust
uses: dtolnay/rust-toolchain@1482605bfc5719782e1267fd0c0cc350fe7646b8
with:
Expand Down
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### New features

* Added support for commit signing and verification. This comes with
out-of-the-box support for the following backends:
* GnuPG
* SSH

* Templates now support logical operators: `||`, `&&`, `!`

* `jj show` now accepts `-T`/`--template` option to render its output using
Expand Down
40 changes: 36 additions & 4 deletions cli/src/config-schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -366,11 +366,12 @@
"properties": {
"backend": {
"type": "string",
"description": "Which backend to use to create commit signatures"
"enum": ["gpg", "ssh"],
"description": "The backend to use for signing commits"
},
"key": {
"type": "string",
"description": "The key parameter to pass to the signing backend. Overridden by `jj sign` parameter or by the global `--sign-with` option"
"description": "The key the configured signing backend will use to to sign commits. Overridden by `jj sign` parameter or by the global `--sign-with` option"
},
"sign-all": {
"type": "boolean",
Expand All @@ -380,10 +381,41 @@
"backends": {
"type": "object",
"description": "Tables of options to pass to specific signing backends",
"properties": {},
"properties": {
"gpg": {
"type": "object",
"properties": {
"program": {
"type": "string",
"description": "Path to the gpg program to be called",
"default": "gpg"
},
"allow-expired-keys": {
"type": "boolean",
"description": "Whether to consider signatures generated with an expired key as invalid",
"default": true
}
}
},
"ssh": {
"type": "object",
"properties": {
"program": {
"type": "string",
"description": "Path to the ssh-keygen program to be called",
"default": "ssh-keygen"
},
"allowed-signers": {
"type": "boolean",
"description": "Path to an allowed signers file used for signature verification",
"default": true
}
}
}
},
"additionalProperties": true
}
}
}
}
}
}
57 changes: 57 additions & 0 deletions docs/config.md
Original file line number Diff line number Diff line change
Expand Up @@ -521,6 +521,63 @@ the conflict is done, `jj` assumes that the conflict was only partially resolved
and parses the conflict markers to get the new state of the conflict. The
conflict is considered fully resolved when there are no conflict markers left.

## Commit Signing

`jj` can be configured to sign and verify the commits it creates using either
GnuPG or SSH signing keys.

To do this you need to configure a signing backend.

### GnuPG Signing

```toml
[signing]
sign-all = true
backend = "gpg"
key = "4ED556E9729E000F"
```

By default the gpg backend will look for a `gpg` binary on your path. If you want
to change the program used or specify a path to `gpg` explicitly you can set:

```toml
signing.backends.gpg.program = "gpg2"
```

Also by default the gpg backend will ignore key expiry when verifying commit signatures.
To consider expired keys as invalid you can set:

```toml
signing.backends.gpg.allow-expired-keys = false
```

### SSH Signing

```toml
[signing]
sign-all = true
backend = "ssh"
key = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGj+J6N6SO+4P8dOZqfR1oiay2yxhhHnagH52avUqw5h"
```

By default the ssh backend will look for a `ssh-keygen` binary on your path. If you want
to change the program used or specify a path to `ssh-keygen` explicitly you can set:

```toml
signing.backends.ssh.program = "/path/to/ssh-keygen"
```

When verifying commit signatures the ssh backend needs to be provided with an allowed-signers
file containing the public keys of authors whose signatures you want to be able to verify.

You can find the format for this file in the
[ssh-keygen man page](https://man.openbsd.org/ssh-keygen#ALLOWED_SIGNERS). This can be provided
as follows:

```toml
signing.backends.ssh.allowed-signers = "/path/to/allowed-signers"
```

## Git settings

### Default remotes for `jj git fetch` and `jj git push`
Expand Down
10 changes: 9 additions & 1 deletion flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@
in
{
packages = {
jujutsu = ourRustPlatform.buildRustPackage rec {
jujutsu = ourRustPlatform.buildRustPackage {
pname = "jujutsu";
version = "unstable-${self.shortRev or "dirty"}";

Expand All @@ -82,6 +82,10 @@
installShellFiles
makeWrapper
pkg-config

# for signing tests
gnupg
openssh
] ++ linuxNativeDeps;
buildInputs = with pkgs; [
openssl zstd libgit2 libssh2
Expand Down Expand Up @@ -144,6 +148,10 @@
# In case you need to run `cargo run --bin gen-protos`
protobuf

# To run the signing tests
gnupg
openssh

# For building the documentation website
poetry
] ++ darwinDeps ++ linuxNativeDeps;
Expand Down
Loading